diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8db8dde..41a231c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -81,22 +81,3 @@ jobs: run: ./script/bootstrap - name: Lint run: ./script/lint - - thirdparty: - strategy: - matrix: - go-version: [1.15.x, 1.16.x] - platform: [ubuntu-latest] - runs-on: ${{ matrix.platform }} - steps: - - name: Install Go - uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 - with: - go-version: ${{ matrix.go-version }} - - name: Checkout code - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 - with: - persist-credentials: false - - name: Run Third-Party Tests - working-directory: ./tests/thirdparty - run: go test -pkgs packages.json diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml new file mode 100644 index 0000000..1e75781 --- /dev/null +++ b/.github/workflows/packages.yml @@ -0,0 +1,558 @@ +# Code generated by make_workflow.go. DO NOT EDIT. + +name: packages +permissions: + contents: read +on: + push: + branches: + - master + pull_request: + +jobs: + zeebo-xxh3: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 + with: + go-version: 1.17.x + - name: Checkout avo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + path: avo + persist-credentials: false + - name: Checkout zeebo/xxh3 + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + repository: zeebo/xxh3 + ref: v1.0.0-rc1 + path: xxh3 + persist-credentials: false + - name: Avo Module Replacement + working-directory: xxh3/avo + run: | + go mod edit -modfile=go.mod -require=github.com/mmcloughlin/avo@v0.0.0-00010101000000-000000000000 + go mod edit -modfile=go.mod -replace=github.com/mmcloughlin/avo=${{ github.workspace }}/avo + go mod tidy -modfile=go.mod + - name: Generate + working-directory: xxh3/avo + run: | + go run . -avx -out ../accum_vector_avx_amd64.s + go run . -sse -out ../accum_vector_sse_amd64.s + - name: Diff + working-directory: xxh3 + run: git diff + - name: Test + working-directory: xxh3 + run: go test ./... + dgryski-go-sip13: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 + with: + go-version: 1.17.x + - name: Checkout avo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + path: avo + persist-credentials: false + - name: Checkout dgryski/go-sip13 + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + repository: dgryski/go-sip13 + ref: 62edffca92457b3a66125c686137cc5f0fe81672 + path: go-sip13 + persist-credentials: false + - name: Setup Root Module + working-directory: go-sip13 + run: go mod init github.com/dgryski/go-sip13 + - name: Setup Generator Module + working-directory: go-sip13/_avo + run: | + sed -i.bak '/+build ignore/d' asm.go + go mod init github.com/dgryski/go-sip13/_avo + - name: Avo Module Replacement + working-directory: go-sip13/_avo + run: | + go mod edit -modfile=go.mod -require=github.com/mmcloughlin/avo@v0.0.0-00010101000000-000000000000 + go mod edit -modfile=go.mod -replace=github.com/mmcloughlin/avo=${{ github.workspace }}/avo + go mod tidy -modfile=go.mod + - name: Generate + working-directory: go-sip13/_avo + run: | + go mod edit -modfile=go.mod -require=github.com/dgryski/go-sip13@v0.0.0-00010101000000-000000000000 + go mod edit -modfile=go.mod -replace=github.com/dgryski/go-sip13=../ + go run . -out ../sip13_amd64.s + - name: Diff + working-directory: go-sip13 + run: git diff + - name: Test + working-directory: go-sip13 + run: go test ./... + phoreproject-bls: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 + with: + go-version: 1.17.x + - name: Checkout avo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + path: avo + persist-credentials: false + - name: Checkout phoreproject/bls + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + repository: phoreproject/bls + ref: a88a5ae26844d7293359422888d7c7f69f43c845 + path: bls + persist-credentials: false + - name: Setup + working-directory: bls/asm + run: | + sed -i.bak '/+build ignore/d' asm.go + go mod init github.com/phoreproject/bls/asm + - name: Avo Module Replacement + working-directory: bls/asm + run: | + go mod edit -modfile=go.mod -require=github.com/mmcloughlin/avo@v0.0.0-00010101000000-000000000000 + go mod edit -modfile=go.mod -replace=github.com/mmcloughlin/avo=${{ github.workspace }}/avo + go mod tidy -modfile=go.mod + - name: Generate + working-directory: bls/asm + run: | + go mod edit -modfile=go.mod -require=github.com/phoreproject/bls@v0.0.0-00010101000000-000000000000 + go mod edit -modfile=go.mod -replace=github.com/phoreproject/bls=../ + go mod download + go run . -out ../primitivefuncs_amd64.s + - name: Diff + working-directory: bls + run: git diff + - name: Test + working-directory: bls + run: go test ./... + minio-md5-simd: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 + with: + go-version: 1.17.x + - name: Checkout avo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + path: avo + persist-credentials: false + - name: Checkout minio/md5-simd + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + repository: minio/md5-simd + ref: 30ad8af83f6868c2a30c615f3edf1a9366bf3f89 + path: md5-simd + persist-credentials: false + - name: Avo Module Replacement + working-directory: md5-simd/_gen + run: | + go mod edit -modfile=go.mod -require=github.com/mmcloughlin/avo@v0.0.0-00010101000000-000000000000 + go mod edit -modfile=go.mod -replace=github.com/mmcloughlin/avo=${{ github.workspace }}/avo + go mod tidy -modfile=go.mod + - name: Generate + working-directory: md5-simd/_gen + run: go run gen.go -out ../md5block_amd64.s -stubs ../md5block_amd64.go -pkg md5simd + - name: Diff + working-directory: md5-simd + run: git diff + - name: Test + working-directory: md5-simd + run: go test ./... + zeebo-blake3: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 + with: + go-version: 1.17.x + - name: Checkout avo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + path: avo + persist-credentials: false + - name: Checkout zeebo/blake3 + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + repository: zeebo/blake3 + ref: 25dba572f0e78ec108f0dd79c9c15288f542d7d9 + path: blake3 + persist-credentials: false + - name: Avo Module Replacement + working-directory: blake3/avo + run: | + go mod edit -modfile=go.mod -require=github.com/mmcloughlin/avo@v0.0.0-00010101000000-000000000000 + go mod edit -modfile=go.mod -replace=github.com/mmcloughlin/avo=${{ github.workspace }}/avo + go mod tidy -modfile=go.mod + - name: Generate + working-directory: blake3/avo + run: | + go run ./avx2 -out ../avx2/impl.s + go run ./sse41 -out ../sse41/impl.s + - name: Diff + working-directory: blake3 + run: git diff + - name: Test + working-directory: blake3 + run: go test ./... + klauspost-reedsolomon: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 + with: + go-version: 1.17.x + - name: Checkout avo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + path: avo + persist-credentials: false + - name: Checkout klauspost/reedsolomon + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + repository: klauspost/reedsolomon + ref: 922778284547557265cff0f903ab5f4c27e40ae9 + path: reedsolomon + persist-credentials: false + - name: Avo Module Replacement + working-directory: reedsolomon/_gen + run: | + go mod edit -modfile=go.mod -require=github.com/mmcloughlin/avo@v0.0.0-00010101000000-000000000000 + go mod edit -modfile=go.mod -replace=github.com/mmcloughlin/avo=${{ github.workspace }}/avo + go mod tidy -modfile=go.mod + - name: Generate + working-directory: reedsolomon/_gen + run: go run gen.go -out ../galois_gen_amd64.s -stubs ../galois_gen_amd64.go -pkg reedsolomon + - name: Diff + working-directory: reedsolomon + run: git diff + - name: Test + working-directory: reedsolomon + run: go test ./... + orisano-wyhash: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 + with: + go-version: 1.17.x + - name: Checkout avo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + path: avo + persist-credentials: false + - name: Checkout orisano/wyhash + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + repository: orisano/wyhash + ref: 32a3f7f6ba4797e2d87dab2969cc9dd63d39cce9 + path: wyhash + persist-credentials: false + - name: Setup Generator Module + working-directory: wyhash/avo + run: go mod init github.com/orisano/wyhash/avo + - name: Avo Module Replacement + working-directory: wyhash/avo + run: | + go mod edit -modfile=go.mod -require=github.com/mmcloughlin/avo@v0.0.0-00010101000000-000000000000 + go mod edit -modfile=go.mod -replace=github.com/mmcloughlin/avo=${{ github.workspace }}/avo + go mod tidy -modfile=go.mod + - name: Generate + working-directory: wyhash/avo + run: go run gen.go -out ../blocks_amd64.s -stubs ../blocks_amd64.go -pkg wyhash + - name: Diff + working-directory: wyhash + run: git diff + - name: Test + working-directory: wyhash + run: go test ./... + klauspost-compress-s2: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 + with: + go-version: 1.17.x + - name: Checkout avo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + path: avo + persist-credentials: false + - name: Checkout klauspost/compress + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + repository: klauspost/compress + ref: 2adf487b3e02f95ce7efd6e4953fda0ae7ecd080 + path: compress + persist-credentials: false + - name: Avo Module Replacement + working-directory: compress/s2/_generate + run: | + go mod edit -modfile=go.mod -require=github.com/mmcloughlin/avo@v0.0.0-00010101000000-000000000000 + go mod edit -modfile=go.mod -replace=github.com/mmcloughlin/avo=${{ github.workspace }}/avo + go mod tidy -modfile=go.mod + - name: Generate + working-directory: compress/s2/_generate + run: go run gen.go -out ../encodeblock_amd64.s -stubs ../encodeblock_amd64.go -pkg s2 + - name: Diff + working-directory: compress/s2 + run: git diff + - name: Test + working-directory: compress/s2 + run: go test ./... + dgryski-go-bloomindex: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 + with: + go-version: 1.17.x + - name: Checkout avo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + path: avo + persist-credentials: false + - name: Checkout dgryski/go-bloomindex + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + repository: dgryski/go-bloomindex + ref: 0902316dce158c154b958ee5cfc706c62af29a42 + path: go-bloomindex + persist-credentials: false + - name: Setup Root Module + working-directory: go-bloomindex + run: | + go mod init github.com/dgryski/go-bloomindex + go get github.com/dgryski/go-bits@v0.0.0-20180113010104-bd8a69a71dc2 + - name: Create Generator Module + working-directory: go-bloomindex + run: | + mkdir avo + git mv asm.go avo + - name: Setup Generator Module + working-directory: go-bloomindex/avo + run: | + sed -i.bak '/+build ignore/d' asm.go + go mod init github.com/dgryski/go-bloomindex/avo + - name: Avo Module Replacement + working-directory: go-bloomindex/avo + run: | + go mod edit -modfile=go.mod -require=github.com/mmcloughlin/avo@v0.0.0-00010101000000-000000000000 + go mod edit -modfile=go.mod -replace=github.com/mmcloughlin/avo=${{ github.workspace }}/avo + go mod tidy -modfile=go.mod + - name: Generate + working-directory: go-bloomindex/avo + run: go run asm.go -out ../query_amd64.s + - name: Diff + working-directory: go-bloomindex + run: git diff + - name: Test + working-directory: go-bloomindex + run: go test ./... + dgryski-go-marvin32: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 + with: + go-version: 1.17.x + - name: Checkout avo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + path: avo + persist-credentials: false + - name: Checkout dgryski/go-marvin32 + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + repository: dgryski/go-marvin32 + ref: 7d18f4c6ea7c24b29d1c7a670f8ae40b0812f2e3 + path: go-marvin32 + persist-credentials: false + - name: Setup Root Module + working-directory: go-marvin32 + run: go mod init github.com/dgryski/go-marvin32 + - name: Create Generator Module + working-directory: go-marvin32 + run: | + mkdir avo + git mv asm.go avo + - name: Setup Generator Module + working-directory: go-marvin32/avo + run: | + sed -i.bak '/+build ignore/d' asm.go + go mod init github.com/dgryski/go-marvin32/avo + - name: Avo Module Replacement + working-directory: go-marvin32/avo + run: | + go mod edit -modfile=go.mod -require=github.com/mmcloughlin/avo@v0.0.0-00010101000000-000000000000 + go mod edit -modfile=go.mod -replace=github.com/mmcloughlin/avo=${{ github.workspace }}/avo + go mod tidy -modfile=go.mod + - name: Generate + working-directory: go-marvin32/avo + run: | + go mod edit -modfile=go.mod -require=github.com/dgryski/go-marvin32@v0.0.0-00010101000000-000000000000 + go mod edit -modfile=go.mod -replace=github.com/dgryski/go-marvin32=../ + go run asm.go -out ../marvin_amd64.s + - name: Diff + working-directory: go-marvin32 + run: git diff + - name: Test + working-directory: go-marvin32 + run: go test ./... + dgryski-go-speck: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 + with: + go-version: 1.17.x + - name: Checkout avo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + path: avo + persist-credentials: false + - name: Checkout dgryski/go-speck + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + repository: dgryski/go-speck + ref: 5b36d4c08d8840c352a153bf37281434ad550ec0 + path: go-speck + persist-credentials: false + - name: Setup Root Module + working-directory: go-speck + run: | + go mod init github.com/dgryski/go-speck + go get github.com/dgryski/go-skipjack@v0.0.0-20150401095227-f3a984a142ab + - name: Create Generator Module + working-directory: go-speck + run: | + mkdir avo + git mv asm.go avo + - name: Setup Generator Module + working-directory: go-speck/avo + run: | + sed -i.bak '/+build ignore/d' asm.go + go mod init github.com/dgryski/go-speck/avo + - name: Avo Module Replacement + working-directory: go-speck/avo + run: | + go mod edit -modfile=go.mod -require=github.com/mmcloughlin/avo@v0.0.0-00010101000000-000000000000 + go mod edit -modfile=go.mod -replace=github.com/mmcloughlin/avo=${{ github.workspace }}/avo + go mod tidy -modfile=go.mod + - name: Generate + working-directory: go-speck/avo + run: | + go mod edit -modfile=go.mod -require=github.com/dgryski/go-speck@v0.0.0-00010101000000-000000000000 + go mod edit -modfile=go.mod -replace=github.com/dgryski/go-speck=../ + go run asm.go -out ../speck_amd64.s + - name: Diff + working-directory: go-speck + run: git diff + - name: Test + working-directory: go-speck + run: go test ./... + dgryski-go-chaskey: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 + with: + go-version: 1.17.x + - name: Checkout avo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + path: avo + persist-credentials: false + - name: Checkout dgryski/go-chaskey + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + repository: dgryski/go-chaskey + ref: ba454392bc5ab6daae103e15147185f8f4a27dcc + path: go-chaskey + persist-credentials: false + - name: Setup Root Module + working-directory: go-chaskey + run: | + go mod init github.com/dgryski/go-chaskey + go get github.com/dchest/siphash@v1.2.2 + - name: Create Generator Module + working-directory: go-chaskey + run: | + mkdir avo + git mv asm.go avo + - name: Setup Generator Module + working-directory: go-chaskey/avo + run: | + sed -i.bak '/+build ignore/d' asm.go + go mod init github.com/dgryski/go-chaskey/avo + - name: Avo Module Replacement + working-directory: go-chaskey/avo + run: | + go mod edit -modfile=go.mod -require=github.com/mmcloughlin/avo@v0.0.0-00010101000000-000000000000 + go mod edit -modfile=go.mod -replace=github.com/mmcloughlin/avo=${{ github.workspace }}/avo + go mod tidy -modfile=go.mod + - name: Generate + working-directory: go-chaskey/avo + run: | + go mod edit -modfile=go.mod -require=github.com/dgryski/go-chaskey@v0.0.0-00010101000000-000000000000 + go mod edit -modfile=go.mod -replace=github.com/dgryski/go-chaskey=../ + go run asm.go -out ../core_amd64.s + - name: Diff + working-directory: go-chaskey + run: git diff + - name: Test + working-directory: go-chaskey + run: go test ./... + lukechampine-us-merkle-blake2b: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 + with: + go-version: 1.17.x + - name: Checkout avo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + path: avo + persist-credentials: false + - name: Checkout lukechampine/us + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + repository: lukechampine/us + ref: dff56a80f83653cb14eeeb57ba6ba3c3e942c412 + path: us + persist-credentials: false + - name: Create Generator Module + working-directory: us/merkle/blake2b + run: | + mkdir avo + git mv gen.go avo + - name: Setup Generator Module + working-directory: us/merkle/blake2b/avo + run: | + sed -i.bak '/+build ignore/d' gen.go + go mod init github.com/lukechampine/us/merkle/blake2b/avo + - name: Avo Module Replacement + working-directory: us/merkle/blake2b/avo + run: | + go mod edit -modfile=go.mod -require=github.com/mmcloughlin/avo@v0.0.0-00010101000000-000000000000 + go mod edit -modfile=go.mod -replace=github.com/mmcloughlin/avo=${{ github.workspace }}/avo + go mod tidy -modfile=go.mod + - name: Generate + working-directory: us/merkle/blake2b/avo + run: go run gen.go -out ../blake2b_amd64.s + - name: Diff + working-directory: us/merkle/blake2b + run: git diff + - name: Test + working-directory: us/merkle/blake2b + run: go test ./... diff --git a/.github/workflows/thirdparty.yml b/.github/workflows/thirdparty.yml new file mode 100644 index 0000000..2e773c3 --- /dev/null +++ b/.github/workflows/thirdparty.yml @@ -0,0 +1,34 @@ +name: thirdparty + +permissions: + contents: read + +on: + push: + branches: + - master + paths: + - "tests/thirdparty/**" + pull_request: + paths: + - "tests/thirdparty/**" + +jobs: + test: + strategy: + matrix: + go-version: [1.17.x] + platform: [ubuntu-latest] + runs-on: ${{ matrix.platform }} + steps: + - name: Install Go + uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 + with: + go-version: ${{ matrix.go-version }} + - name: Checkout code + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + persist-credentials: false + - name: Run Third-Party Tests + working-directory: tests/thirdparty + run: go test -pkgs packages.json diff --git a/internal/prnt/printer.go b/internal/prnt/printer.go index 410895c..904d1b2 100644 --- a/internal/prnt/printer.go +++ b/internal/prnt/printer.go @@ -13,8 +13,11 @@ import ( // any errors to be stored so they can be checked at the end, rather than having // error checks obscuring the code generation. type Generator struct { - buf bytes.Buffer - err error + buf bytes.Buffer + level int // current indentation level + indent string // indentation string + pending bool // if there's a pending indentation + err error // saved error from printing } // Raw provides direct access to the underlying output stream. @@ -22,11 +25,38 @@ func (g *Generator) Raw() io.Writer { return &g.buf } +// SetIndentString sets the string used for one level of indentation. Use +// Indent() and Dedent() to control indent level. +func (g *Generator) SetIndentString(indent string) { + g.indent = indent +} + +// Indent increments the indent level. +func (g *Generator) Indent() { + g.level++ +} + +// Dedent decrements the indent level. +func (g *Generator) Dedent() { + g.level-- +} + +// Linef prints formatted output terminated with a new line. +func (g *Generator) Linef(format string, args ...interface{}) { + g.Printf(format, args...) + g.NL() +} + // Printf prints to the internal buffer. func (g *Generator) Printf(format string, args ...interface{}) { if g.err != nil { return } + if g.pending { + indent := strings.Repeat(g.indent, g.level) + format = indent + format + g.pending = false + } _, err := fmt.Fprintf(&g.buf, format, args...) g.AddError(err) } @@ -34,6 +64,7 @@ func (g *Generator) Printf(format string, args ...interface{}) { // NL prints a new line. func (g *Generator) NL() { g.Printf("\n") + g.pending = true } // Comment writes comment lines prefixed with "// ". diff --git a/tests/thirdparty/config.go b/tests/thirdparty/config.go index d857a32..1e7d0a5 100644 --- a/tests/thirdparty/config.go +++ b/tests/thirdparty/config.go @@ -3,51 +3,226 @@ package thirdparty import ( "encoding/json" + "errors" + "fmt" "io" "os" + "path" "path/filepath" + "strings" ) -// Package defines an integration test based on a third-party package using avo. -type Package struct { - ImportPath string `json:"import_path"` // package import path - Version string `json:"version"` // git sha, tag or branch - Generate [][]string `json:"generate"` // generate commands to run - Dir string `json:"dir"` // working directory for generate commands - Test string `json:"test"` // test path relative to repo root (if empty defaults to ./...) +// GithubRepository specifies a repository on github. +type GithubRepository struct { + Owner string `json:"owner"` + Name string `json:"name"` } -// Name returns the package name. -func (p Package) Name() string { - return filepath.Base(p.ImportPath) +func (r GithubRepository) String() string { + return path.Join(r.Owner, r.Name) } // CloneURL returns the git clone URL. -func (p Package) CloneURL() string { - return "https://" + p.ImportPath + ".git" +func (r GithubRepository) CloneURL() string { + return fmt.Sprintf("https://github.com/%s.git", r) } -// TestPath returns the paths to run "go test" on, relative to the repository root. -func (p Package) TestPath() string { - if p.Test == "" { - return "./..." +// Step represents a set of commands to run as part of the testing plan for a +// third-party package. +type Step struct { + Name string `json:"name"` + WorkingDirectory string `json:"dir"` + Commands []string `json:"commands"` +} + +// Validate step parameters. +func (s *Step) Validate() error { + if s.Name == "" { + return errors.New("missing name") } - return p.Test + if len(s.Commands) == 0 { + return errors.New("missing commands") + } + return nil +} + +// Package defines an integration test based on a third-party package using avo. +type Package struct { + // Repository the package belongs to. At the moment, all packages are + // available on github. + Repository GithubRepository `json:"repository"` + + // Version as a git sha, tag or branch. + Version string `json:"version"` + + // Sub-package within the repository under test. All file path references + // will be relative to this directory. If empty the root of the repository + // is used. + SubPackage string `json:"pkg"` + + // Path to the module file for the avo generator package. This is necessary + // so the integration test can insert replace directives to point at the avo + // version under test. + Module string `json:"module"` + + // Setup steps. These run prior to the insertion of avo replace directives, + // therefore should be used if it's necessary to initialize new go modules + // within the repository. + Setup []*Step `json:"setup"` + + // Steps to run the avo code generator. + Generate []*Step `json:"generate"` // generate commands to run + + // Test steps. If empty, defaults to "go test ./...". + Test []*Step `json:"test"` +} + +// ID returns an identifier for the package. +func (p *Package) ID() string { + pkgpath := path.Join(p.Repository.String(), p.SubPackage) + return strings.ReplaceAll(pkgpath, "/", "-") +} + +// setdefaults fills in missing parameters to help make the input package +// descriptions less verbose. +func (p *Package) setdefaults() { + for _, stage := range []struct { + Steps []*Step + DefaultName string + }{ + {p.Setup, "Setup"}, + {p.Generate, "Generate"}, + {p.Test, "Test"}, + } { + if len(stage.Steps) == 1 && stage.Steps[0].Name == "" { + stage.Steps[0].Name = stage.DefaultName + } + } +} + +// Validate package definition. +func (p *Package) Validate() error { + if p.Version == "" { + return errors.New("missing version") + } + if p.Module == "" { + return errors.New("missing module") + } + if len(p.Generate) == 0 { + return errors.New("no generate commands") + } + + stages := map[string][]*Step{ + "setup": p.Setup, + "generate": p.Generate, + "test": p.Test, + } + for name, steps := range stages { + for _, s := range steps { + if err := s.Validate(); err != nil { + return fmt.Errorf("%s step: %w", name, err) + } + } + } + + return nil +} + +// Context specifies execution environment parameters for a third-party test. +type Context struct { + // Path to the avo version under test. + AvoDirectory string + + // Path to the checked out third-party repository. + RepositoryDirectory string +} + +// Steps generates the list of steps required to execute the integration test +// for this package. Context specifies execution environment parameters. +func (p *Package) Steps(c *Context) []*Step { + var steps []*Step + + // Optional setup. + steps = append(steps, p.Setup...) + + // Replace avo dependency. + const invalid = "v0.0.0-00010101000000-000000000000" + moddir := filepath.Dir(p.Module) + modfile := filepath.Base(p.Module) + steps = append(steps, &Step{ + Name: "Avo Module Replacement", + WorkingDirectory: moddir, + Commands: []string{ + "go mod edit -modfile=" + modfile + " -require=github.com/mmcloughlin/avo@" + invalid, + "go mod edit -modfile=" + modfile + " -replace=github.com/mmcloughlin/avo=" + c.AvoDirectory, + "go mod tidy -modfile=" + modfile, + }, + }) + + // Run generation. + steps = append(steps, p.Generate...) + + // Display changes. + steps = append(steps, &Step{ + Name: "Diff", + Commands: []string{"git diff"}, + }) + + // Tests. + if len(p.Test) > 0 { + steps = append(steps, p.Test...) + } else { + steps = append(steps, &Step{ + Name: "Test", + Commands: []string{ + "go test ./...", + }, + }) + } + + // Prepend sub-directory to every step. + if p.SubPackage != "" { + for _, s := range steps { + s.WorkingDirectory = filepath.Join(p.SubPackage, s.WorkingDirectory) + } + } + + return steps +} + +// Packages is a collection of third-party integration tests. +type Packages []*Package + +func (p Packages) setdefaults() { + for _, pkg := range p { + pkg.setdefaults() + } +} + +// Validate the package collection. +func (p Packages) Validate() error { + for _, pkg := range p { + if err := pkg.Validate(); err != nil { + return fmt.Errorf("package %s: %w", pkg.ID(), err) + } + } + return nil } // LoadPackages loads a list of package configurations from JSON format. -func LoadPackages(r io.Reader) ([]Package, error) { - var pkgs []Package +func LoadPackages(r io.Reader) (Packages, error) { + var pkgs Packages d := json.NewDecoder(r) d.DisallowUnknownFields() if err := d.Decode(&pkgs); err != nil { return nil, err } + pkgs.setdefaults() return pkgs, nil } // LoadPackagesFile loads a list of package configurations from a JSON file. -func LoadPackagesFile(filename string) ([]Package, error) { +func LoadPackagesFile(filename string) (Packages, error) { f, err := os.Open(filename) if err != nil { return nil, err diff --git a/tests/thirdparty/config_test.go b/tests/thirdparty/config_test.go index 88bd8a8..81cc399 100644 --- a/tests/thirdparty/config_test.go +++ b/tests/thirdparty/config_test.go @@ -5,33 +5,85 @@ import ( "testing" ) -func TestPackageName(t *testing.T) { - p := Package{ImportPath: "github.com/username/repo"} - if p.Name() != "repo" { - t.Fail() +func TestValidateErrors(t *testing.T) { + cases := []struct { + Name string + Item interface{ Validate() error } + ErrorSubstring string + }{ + { + Name: "step_missing_name", + Item: &Step{}, + ErrorSubstring: "missing name", + }, + { + Name: "step_missing_commands", + Item: &Step{ + Name: "Setup", + }, + ErrorSubstring: "missing commands", + }, + { + Name: "package_missing_version", + Item: &Package{ + Repository: GithubRepository{Owner: "octocat", Name: "hello-world"}, + }, + ErrorSubstring: "missing version", + }, + { + Name: "package_missing_module", + Item: &Package{ + Repository: GithubRepository{Owner: "octocat", Name: "hello-world"}, + Version: "v1.0.1", + }, + ErrorSubstring: "missing module", + }, + { + Name: "package_no_generate_commands", + Item: &Package{ + Repository: GithubRepository{Owner: "octocat", Name: "hello-world"}, + Version: "v1.0.1", + Module: "avo/go.mod", + }, + ErrorSubstring: "no generate commands", + }, + { + Name: "package_invalid_generate_commands", + Item: &Package{ + Repository: GithubRepository{Owner: "octocat", Name: "hello-world"}, + Version: "v1.0.1", + Module: "avo/go.mod", + Generate: []*Step{ + {}, + }, + }, + ErrorSubstring: "generate step: missing name", + }, + { + Name: "packages_invalid_package", + Item: Packages{ + { + Repository: GithubRepository{Owner: "octocat", Name: "hello-world"}, + }, + }, + ErrorSubstring: "missing version", + }, + } + for _, c := range cases { + c := c // scopelint + t.Run(c.Name, func(t *testing.T) { + err := c.Item.Validate() + if err == nil { + t.Fatal("expected error; got nil") + } + if !strings.Contains(err.Error(), c.ErrorSubstring) { + t.Fatalf("expected error message to contain %q; got %q", c.ErrorSubstring, err) + } + }) } } -func TestPackageCloneURL(t *testing.T) { - p := Package{ImportPath: "github.com/username/repo"} - if p.CloneURL() != "https://github.com/username/repo.git" { - t.Fail() - } -} - -func TestPackagesTestPath(t *testing.T) { - p := Package{} - if p.TestPath() != "./..." { - t.Fail() - } - - p.Test = "./sub" - if p.TestPath() != "./sub" { - t.Fail() - } -} - -func TestLoadPackages(t *testing.T) { +func TestLoadPackagesBad(t *testing.T) { r := strings.NewReader(`[{"unknown_field": "value"}]`) _, err := LoadPackages(r) if err == nil { @@ -39,19 +91,6 @@ func TestLoadPackages(t *testing.T) { } } -func TestLoadPackagesFile(t *testing.T) { - pkgs, err := LoadPackagesFile("packages.json") - if err != nil { - t.Fatal(err) - } - for _, pkg := range pkgs { - t.Log(pkg.ImportPath) - } - if len(pkgs) == 0 { - t.Fatal("no packages loaded") - } -} - func TestLoadPackagesFileNotExist(t *testing.T) { pkgs, err := LoadPackagesFile("does_not_exist") if pkgs != nil { @@ -61,3 +100,37 @@ func TestLoadPackagesFileNotExist(t *testing.T) { t.Fatal("expected non-nil error") } } + +func TestPackagesFileValid(t *testing.T) { + pkgs, err := LoadPackagesFile("packages.json") + if err != nil { + t.Fatal(err) + } + for _, pkg := range pkgs { + t.Logf("read: %s", pkg.ID()) + } + if len(pkgs) == 0 { + t.Fatal("no packages loaded") + } + if err := pkgs.Validate(); err != nil { + t.Fatal(err) + } +} + +func TestPackagesFileStepsValid(t *testing.T) { + pkgs, err := LoadPackagesFile("packages.json") + if err != nil { + t.Fatal(err) + } + c := &Context{ + AvoDirectory: "avo", + RepositoryDirectory: "repo", + } + for _, pkg := range pkgs { + for _, s := range pkg.Steps(c) { + if err := s.Validate(); err != nil { + t.Errorf("package %s: %s", pkg.ID(), err) + } + } + } +} diff --git a/tests/thirdparty/make_workflow.go b/tests/thirdparty/make_workflow.go new file mode 100644 index 0000000..f46f019 --- /dev/null +++ b/tests/thirdparty/make_workflow.go @@ -0,0 +1,148 @@ +//go:build ignore +// +build ignore + +package main + +import ( + "flag" + "log" + "os" + "path" + "path/filepath" + "runtime" + + "github.com/mmcloughlin/avo/internal/prnt" + "github.com/mmcloughlin/avo/tests/thirdparty" +) + +var ( + pkgsfilename = flag.String("pkgs", "", "packages configuration") + output = flag.String("output", "", "path to output file (default stdout)") +) + +func main() { + if err := mainerr(); err != nil { + log.Fatal(err) + } +} + +func mainerr() error { + flag.Parse() + + // Read packages. + pkgs, err := thirdparty.LoadPackagesFile(*pkgsfilename) + if err != nil { + return err + } + + if err := pkgs.Validate(); err != nil { + return err + } + + // Determine output. + w := os.Stdout + if *output != "" { + f, err := os.Create(*output) + if err != nil { + return err + } + defer f.Close() + w = f + } + + // Generate workflow file. + b, err := GenerateWorkflow(pkgs) + if err != nil { + return err + } + + // Write output. + if _, err := w.Write(b); err != nil { + return err + } + + return nil +} + +func GenerateWorkflow(pkgs thirdparty.Packages) ([]byte, error) { + g := &prnt.Generator{} + g.SetIndentString(" ") + + _, self, _, _ := runtime.Caller(0) + g.Linef("# Code generated by %s. DO NOT EDIT.", filepath.Base(self)) + g.NL() + + // Header. + g.Linef("name: packages") + + g.Linef("permissions:") + g.Linef(" contents: read") + + g.Linef("on:") + g.Linef(" push:") + g.Linef(" branches:") + g.Linef(" - master") + g.Linef(" pull_request:") + + // One job per package. + g.NL() + g.Linef("jobs:") + g.Indent() + for _, pkg := range pkgs { + g.Linef("%s:", pkg.ID()) + g.Indent() + + g.Linef("runs-on: ubuntu-latest") + g.Linef("steps:") + g.Indent() + + // Install Go. + g.Linef("- name: Install Go") + g.Linef(" uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3") + g.Linef(" with:") + g.Linef(" go-version: 1.17.x") + + // Checkout avo. + avodir := "avo" + g.Linef("- name: Checkout avo") + g.Linef(" uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4") + g.Linef(" with:") + g.Linef(" path: %s", avodir) + g.Linef(" persist-credentials: false") + + // Checkout the third-party package. + pkgdir := pkg.Repository.Name + g.Linef("- name: Checkout %s", pkg.Repository) + g.Linef(" uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4") + g.Linef(" with:") + g.Linef(" repository: %s", pkg.Repository) + g.Linef(" ref: %s", pkg.Version) + g.Linef(" path: %s", pkgdir) + g.Linef(" persist-credentials: false") + + // Build steps. + c := &thirdparty.Context{ + AvoDirectory: path.Join("${{ github.workspace }}", avodir), + RepositoryDirectory: path.Join("${{ github.workspace }}", pkgdir), + } + + for _, step := range pkg.Steps(c) { + g.Linef("- name: %s", step.Name) + g.Linef(" working-directory: %s", path.Join(pkgdir, step.WorkingDirectory)) + if len(step.Commands) == 1 { + g.Linef(" run: %s", step.Commands[0]) + } else { + g.Linef(" run: |") + for _, cmd := range step.Commands { + g.Linef(" %s", cmd) + } + } + } + + g.Dedent() + g.Dedent() + } + g.Dedent() + + return g.Result() +} diff --git a/tests/thirdparty/packages.json b/tests/thirdparty/packages.json index 19e6b3c..5f3e19f 100644 --- a/tests/thirdparty/packages.json +++ b/tests/thirdparty/packages.json @@ -1,234 +1,371 @@ [ { - "import_path": "github.com/zeebo/xxh3", - "version": "65f423c10688c362d2a2ce6987b665c72ee7bddd", - "dir": "avo", + "repository": { + "owner": "zeebo", + "name": "xxh3" + }, + "version": "v1.0.0-rc1", + "module": "avo/go.mod", "generate": [ - [ - "go", - "run", - "-mod=mod", - ".", - "-avx", - "-out", - "../vector_avx_amd64.s" - ], - [ - "go", - "run", - ".", - "-sse", - "-out", - "../vector_sse_amd64.s" - ] + { + "dir": "avo", + "commands": [ + "go run . -avx -out ../accum_vector_avx_amd64.s", + "go run . -sse -out ../accum_vector_sse_amd64.s" + ] + } ] }, { - "import_path": "github.com/dgryski/go-sip13", - "version": "25c5027a8c7bfa6dab4b577e53e5c9068f6e2152", - "generate": [ - [ - "go", - "run", - "-mod=mod", - "_avo/asm.go", - "-out", - "sip13_amd64.s" - ] - ] - }, - { - "import_path": "github.com/orisano/wyhash", - "version": "32a3f7f6ba4797e2d87dab2969cc9dd63d39cce9", - "generate": [ - [ - "go", - "run", - "-mod=mod", - "avo/gen.go", - "-out", - "blocks_amd64.s", - "-stubs", - "blocks_amd64.go" - ] - ] - }, - { - "import_path": "github.com/dgryski/go-bloomindex", - "version": "0902316dce158c154b958ee5cfc706c62af29a42", - "generate": [ - [ - "go", - "run", - "asm.go", - "-out", - "query_amd64.s" - ] - ] - }, - { - "import_path": "github.com/dgryski/go-marvin32", - "version": "7d18f4c6ea7c24b29d1c7a670f8ae40b0812f2e3", - "generate": [ - [ - "go", - "run", - "-mod=mod", - "asm.go", - "-out", - "marvin_amd64.s" - ] - ] - }, - { - "import_path": "github.com/dgryski/go-speck", - "version": "5b36d4c08d8840c352a153bf37281434ad550ec0", - "generate": [ - [ - "go", - "run", - "asm.go", - "-out", - "speck_amd64.s" - ] - ] - }, - { - "import_path": "github.com/dgryski/go-chaskey", - "version": "ba454392bc5ab6daae103e15147185f8f4a27dcc", - "generate": [ - [ - "go", - "run", - "asm.go", - "-out", - "core_amd64.s" - ] - ] - }, - { - "import_path": "github.com/mkevac/gopherconrussia2019", - "version": "235b8b0156a20b4e078b88462e669730f99caeb1", - "dir": "simplesimd", - "generate": [ - [ - "go", - "run", - "asm.go", - "-out", - "simd.s", - "-stubs", - "stub.go" - ] - ] - }, - { - "import_path": "github.com/phoreproject/bls", - "version": "9d5f85bf4a9badf491a1b9b27fb3344b489bd2c4", - "generate": [ - [ - "go", - "run", - "-mod=mod", - "asm/asm.go", - "-out", - "primitivefuncs_amd64.s" - ] - ] - }, - { - "import_path": "github.com/klauspost/compress", - "version": "2adf487b3e02f95ce7efd6e4953fda0ae7ecd080", - "dir": "s2/_generate", - "generate": [ - [ - "go", - "run", - "-mod=mod", - "gen.go", - "-out", - "../encodeblock_amd64.s", - "-stubs", - "../encodeblock_amd64.go", - "-pkg", - "s2" - ] + "repository": { + "owner": "dgryski", + "name": "go-sip13" + }, + "version": "62edffca92457b3a66125c686137cc5f0fe81672", + "module": "_avo/go.mod", + "setup": [ + { + "name": "Setup Root Module", + "commands": [ + "go mod init github.com/dgryski/go-sip13" + ] + }, + { + "name": "Setup Generator Module", + "dir": "_avo", + "commands": [ + "sed -i.bak '/+build ignore/d' asm.go", + "go mod init github.com/dgryski/go-sip13/_avo" + ] + } ], - "test": "./s2" - }, - { - "import_path": "github.com/klauspost/reedsolomon", - "version": "922778284547557265cff0f903ab5f4c27e40ae9", - "dir": "_gen", "generate": [ - [ - "go", - "run", - "-mod=mod", - "gen.go", - "-out", - "../galois_gen_amd64.s", - "-stubs", - "../galois_gen_amd64.go", - "-pkg", - "reedsolomon" - ] + { + "dir": "_avo", + "commands": [ + "go mod edit -modfile=go.mod -require=github.com/dgryski/go-sip13@v0.0.0-00010101000000-000000000000", + "go mod edit -modfile=go.mod -replace=github.com/dgryski/go-sip13=../", + "go run . -out ../sip13_amd64.s" + ] + } ] }, { - "import_path": "github.com/minio/md5-simd", + "repository": { + "owner": "phoreproject", + "name": "bls" + }, + "version": "a88a5ae26844d7293359422888d7c7f69f43c845", + "module": "asm/go.mod", + "setup": [ + { + "dir": "asm", + "commands": [ + "sed -i.bak '/+build ignore/d' asm.go", + "go mod init github.com/phoreproject/bls/asm" + ] + } + ], + "generate": [ + { + "dir": "asm", + "commands": [ + "go mod edit -modfile=go.mod -require=github.com/phoreproject/bls@v0.0.0-00010101000000-000000000000", + "go mod edit -modfile=go.mod -replace=github.com/phoreproject/bls=../", + "go mod download", + "go run . -out ../primitivefuncs_amd64.s" + ] + } + ] + }, + { + "repository": { + "owner": "minio", + "name": "md5-simd" + }, "version": "30ad8af83f6868c2a30c615f3edf1a9366bf3f89", - "dir": "_gen", + "module": "_gen/go.mod", "generate": [ - [ - "go", - "run", - "-mod=mod", - "gen.go", - "-out", - "../md5block_amd64.s", - "-stubs", - "../md5block_amd64.go", - "-pkg", - "md5simd" - ] + { + "dir": "_gen", + "commands": [ + "go run gen.go -out ../md5block_amd64.s -stubs ../md5block_amd64.go -pkg md5simd" + ] + } ] }, { - "import_path": "github.com/zeebo/blake3", + "repository": { + "owner": "zeebo", + "name": "blake3" + }, "version": "25dba572f0e78ec108f0dd79c9c15288f542d7d9", - "dir": "avo", + "module": "avo/go.mod", "generate": [ - [ - "go", - "run", - "-mod=mod", - "./avx2", - "-out", - "../avx2/impl.s" - ], - [ - "go", - "run", - "./sse41", - "-out", - "../sse41/impl.s" - ] + { + "dir": "avo", + "commands": [ + "go run ./avx2 -out ../avx2/impl.s", + "go run ./sse41 -out ../sse41/impl.s" + ] + } ] }, { - "import_path": "github.com/lukechampine/us", - "version": "dff56a80f83653cb14eeeb57ba6ba3c3e942c412", - "dir": "merkle/blake2b", + "repository": { + "owner": "klauspost", + "name": "reedsolomon" + }, + "version": "922778284547557265cff0f903ab5f4c27e40ae9", + "module": "_gen/go.mod", "generate": [ - [ - "go", - "run", - "gen.go", - "-out", - "blake2b_amd64.s" - ] + { + "dir": "_gen", + "commands": [ + "go run gen.go -out ../galois_gen_amd64.s -stubs ../galois_gen_amd64.go -pkg reedsolomon" + ] + } + ] + }, + { + "repository": { + "owner": "orisano", + "name": "wyhash" + }, + "version": "32a3f7f6ba4797e2d87dab2969cc9dd63d39cce9", + "module": "avo/go.mod", + "setup": [ + { + "name": "Setup Generator Module", + "dir": "avo", + "commands": [ + "go mod init github.com/orisano/wyhash/avo" + ] + } ], - "test": "./merkle/..." + "generate": [ + { + "dir": "avo", + "commands": [ + "go run gen.go -out ../blocks_amd64.s -stubs ../blocks_amd64.go -pkg wyhash" + ] + } + ] + }, + { + "repository": { + "owner": "klauspost", + "name": "compress" + }, + "version": "2adf487b3e02f95ce7efd6e4953fda0ae7ecd080", + "pkg": "s2", + "module": "_generate/go.mod", + "generate": [ + { + "dir": "_generate", + "commands": [ + "go run gen.go -out ../encodeblock_amd64.s -stubs ../encodeblock_amd64.go -pkg s2" + ] + } + ] + }, + { + "repository": { + "owner": "dgryski", + "name": "go-bloomindex" + }, + "version": "0902316dce158c154b958ee5cfc706c62af29a42", + "module": "avo/go.mod", + "setup": [ + { + "name": "Setup Root Module", + "commands": [ + "go mod init github.com/dgryski/go-bloomindex", + "go get github.com/dgryski/go-bits@v0.0.0-20180113010104-bd8a69a71dc2" + ] + }, + { + "name": "Create Generator Module", + "commands": [ + "mkdir avo", + "git mv asm.go avo" + ] + }, + { + "name": "Setup Generator Module", + "dir": "avo", + "commands": [ + "sed -i.bak '/+build ignore/d' asm.go", + "go mod init github.com/dgryski/go-bloomindex/avo" + ] + } + ], + "generate": [ + { + "dir": "avo", + "commands": [ + "go run asm.go -out ../query_amd64.s" + ] + } + ] + }, + { + "repository": { + "owner": "dgryski", + "name": "go-marvin32" + }, + "version": "7d18f4c6ea7c24b29d1c7a670f8ae40b0812f2e3", + "module": "avo/go.mod", + "setup": [ + { + "name": "Setup Root Module", + "commands": [ + "go mod init github.com/dgryski/go-marvin32" + ] + }, + { + "name": "Create Generator Module", + "commands": [ + "mkdir avo", + "git mv asm.go avo" + ] + }, + { + "name": "Setup Generator Module", + "dir": "avo", + "commands": [ + "sed -i.bak '/+build ignore/d' asm.go", + "go mod init github.com/dgryski/go-marvin32/avo" + ] + } + ], + "generate": [ + { + "dir": "avo", + "commands": [ + "go mod edit -modfile=go.mod -require=github.com/dgryski/go-marvin32@v0.0.0-00010101000000-000000000000", + "go mod edit -modfile=go.mod -replace=github.com/dgryski/go-marvin32=../", + "go run asm.go -out ../marvin_amd64.s" + ] + } + ] + }, + { + "repository": { + "owner": "dgryski", + "name": "go-speck" + }, + "version": "5b36d4c08d8840c352a153bf37281434ad550ec0", + "module": "avo/go.mod", + "setup": [ + { + "name": "Setup Root Module", + "commands": [ + "go mod init github.com/dgryski/go-speck", + "go get github.com/dgryski/go-skipjack@v0.0.0-20150401095227-f3a984a142ab" + ] + }, + { + "name": "Create Generator Module", + "commands": [ + "mkdir avo", + "git mv asm.go avo" + ] + }, + { + "name": "Setup Generator Module", + "dir": "avo", + "commands": [ + "sed -i.bak '/+build ignore/d' asm.go", + "go mod init github.com/dgryski/go-speck/avo" + ] + } + ], + "generate": [ + { + "dir": "avo", + "commands": [ + "go mod edit -modfile=go.mod -require=github.com/dgryski/go-speck@v0.0.0-00010101000000-000000000000", + "go mod edit -modfile=go.mod -replace=github.com/dgryski/go-speck=../", + "go run asm.go -out ../speck_amd64.s" + ] + } + ] + }, + { + "repository": { + "owner": "dgryski", + "name": "go-chaskey" + }, + "version": "ba454392bc5ab6daae103e15147185f8f4a27dcc", + "module": "avo/go.mod", + "setup": [ + { + "name": "Setup Root Module", + "commands": [ + "go mod init github.com/dgryski/go-chaskey", + "go get github.com/dchest/siphash@v1.2.2" + ] + }, + { + "name": "Create Generator Module", + "commands": [ + "mkdir avo", + "git mv asm.go avo" + ] + }, + { + "name": "Setup Generator Module", + "dir": "avo", + "commands": [ + "sed -i.bak '/+build ignore/d' asm.go", + "go mod init github.com/dgryski/go-chaskey/avo" + ] + } + ], + "generate": [ + { + "dir": "avo", + "commands": [ + "go mod edit -modfile=go.mod -require=github.com/dgryski/go-chaskey@v0.0.0-00010101000000-000000000000", + "go mod edit -modfile=go.mod -replace=github.com/dgryski/go-chaskey=../", + "go run asm.go -out ../core_amd64.s" + ] + } + ] + }, + { + "repository": { + "owner": "lukechampine", + "name": "us" + }, + "version": "dff56a80f83653cb14eeeb57ba6ba3c3e942c412", + "pkg": "merkle/blake2b", + "module": "avo/go.mod", + "setup": [ + { + "name": "Create Generator Module", + "commands": [ + "mkdir avo", + "git mv gen.go avo" + ] + }, + { + "name": "Setup Generator Module", + "dir": "avo", + "commands": [ + "sed -i.bak '/+build ignore/d' gen.go", + "go mod init github.com/lukechampine/us/merkle/blake2b/avo" + ] + } + ], + "generate": [ + { + "dir": "avo", + "commands": [ + "go run gen.go -out ../blake2b_amd64.s" + ] + } + ] } ] diff --git a/tests/thirdparty/packages_test.go b/tests/thirdparty/packages_test.go index 25dabb3..3f43419 100644 --- a/tests/thirdparty/packages_test.go +++ b/tests/thirdparty/packages_test.go @@ -2,7 +2,6 @@ package thirdparty import ( "flag" - "os" "os/exec" "path/filepath" "runtime" @@ -11,6 +10,8 @@ import ( "github.com/mmcloughlin/avo/internal/test" ) +//go:generate go run make_workflow.go -pkgs packages.json -output ../../.github/workflows/packages.yml + // Custom flags. var ( pkgsfilename = flag.String("pkgs", "", "packages configuration") @@ -33,7 +34,7 @@ func TestPackages(t *testing.T) { for _, pkg := range pkgs { pkg := pkg // scopelint - t.Run(pkg.Name(), func(t *testing.T) { + t.Run(pkg.ID(), func(t *testing.T) { dir, clean := test.TempDir(t) if !*preserve { defer clean() @@ -54,57 +55,36 @@ func TestPackages(t *testing.T) { // PackageTest executes an integration test based on a given third-party package. type PackageTest struct { *testing.T - Package + *Package WorkDir string // working directory for the test Latest bool // use latest version of the package repopath string // path the repo is cloned to - cwd string // working directory to execute commands in } // Run the test. func (t *PackageTest) Run() { t.checkout() - t.modinit() - t.replaceavo() - t.diff() - t.generate() - t.diff() - t.test() + t.steps() } // checkout the code at the specified version. func (t *PackageTest) checkout() { // Clone repo. dst := filepath.Join(t.WorkDir, t.Name()) - t.git("clone", "--quiet", t.CloneURL(), dst) + test.Exec(t.T, "git", "clone", "--quiet", t.Repository.CloneURL(), dst) t.repopath = dst - t.cd(t.repopath) // Checkout specific version. if t.Latest { t.Log("using latest version") return } - t.git("-C", t.repopath, "checkout", "--quiet", t.Version) + test.Exec(t.T, "git", "-C", t.repopath, "checkout", "--quiet", t.Version) } -// modinit initializes the repo as a go module if it isn't one already. -func (t *PackageTest) modinit() { - // Check if module path already exists. - gomod := filepath.Join(t.repopath, "go.mod") - if _, err := os.Stat(gomod); err == nil { - t.Logf("already a module") - return - } - - // Initialize the module. - t.gotool("mod", "init", t.ImportPath) -} - -// replaceavo points all avo dependencies to the local version. -func (t *PackageTest) replaceavo() { +func (t *PackageTest) steps() { // Determine the path to avo. _, self, _, ok := runtime.Caller(1) if !ok { @@ -112,64 +92,17 @@ func (t *PackageTest) replaceavo() { } avodir := filepath.Join(filepath.Dir(self), "..", "..") - // Edit all go.mod files in the repo. - err := filepath.Walk(t.repopath, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err + // Run steps. + c := &Context{ + AvoDirectory: avodir, + RepositoryDirectory: t.repopath, + } + + for _, s := range t.Steps(c) { + for _, command := range s.Commands { + cmd := exec.Command("sh", "-c", command) + cmd.Dir = filepath.Join(t.repopath, s.WorkingDirectory) + test.ExecCommand(t.T, cmd) } - dir, base := filepath.Split(path) - if base != "go.mod" { - return nil - } - t.cd(dir) - t.gotool("mod", "tidy") - t.gotool("get", "github.com/mmcloughlin/avo") - t.gotool("mod", "edit", "-replace=github.com/mmcloughlin/avo="+avodir) - t.gotool("mod", "download") - return nil - }) - if err != nil { - t.Fatal(err) - } - - t.cd(t.repopath) -} - -// generate runs generate commands. -func (t *PackageTest) generate() { - if len(t.Generate) == 0 { - t.Fatal("no commands specified") - } - for _, args := range t.Generate { - cmd := exec.Command(args[0], args[1:]...) - cmd.Dir = filepath.Join(t.repopath, t.Dir) - test.ExecCommand(t.T, cmd) } } - -// diff runs git diff on the repository. -func (t *PackageTest) diff() { - t.git("-C", t.repopath, "diff") -} - -// test runs go test. -func (t *PackageTest) test() { - t.gotool("test", t.TestPath()) -} - -// git runs a git command. -func (t *PackageTest) git(arg ...string) { - test.Exec(t.T, "git", arg...) -} - -// gotool runs a go command. -func (t *PackageTest) gotool(arg ...string) { - cmd := exec.Command(test.GoTool(), arg...) - cmd.Dir = t.cwd - test.ExecCommand(t.T, cmd) -} - -// cd sets the working directory. -func (t *PackageTest) cd(dir string) { - t.cwd = dir -}