From 8ff8e3b751f177d6184f74acbec36c93735a694e Mon Sep 17 00:00:00 2001 From: Michael McLoughlin Date: Wed, 15 Sep 2021 23:25:51 -0700 Subject: [PATCH] tests/thirdparty: fix and run as github workflow (#198) As part of fixing failing third-party tests, this PR significantly rearchitects their specification and execution. Third-party tests are now specified in a much more flexible format allowing more customization on a per-package level. In addition, third-party tests are now used to auto-generate a Github Actions workflow to perform the tests in parallel. This not only gives faster feedback on PRs, but will also allow us to more quickly narrow down on which packages are failing. An additional workflow also confirms that local execution of third-party tests is consistent with the Github Actions version. This workflow only runs when tests/thirdparty itself is changed. --- .github/workflows/ci.yml | 19 - .github/workflows/packages.yml | 558 ++++++++++++++++++++++++++++++ .github/workflows/thirdparty.yml | 34 ++ internal/prnt/printer.go | 35 +- tests/thirdparty/config.go | 215 ++++++++++-- tests/thirdparty/config_test.go | 147 ++++++-- tests/thirdparty/make_workflow.go | 148 ++++++++ tests/thirdparty/packages.json | 555 ++++++++++++++++++----------- tests/thirdparty/packages_test.go | 105 +----- 9 files changed, 1443 insertions(+), 373 deletions(-) create mode 100644 .github/workflows/packages.yml create mode 100644 .github/workflows/thirdparty.yml create mode 100644 tests/thirdparty/make_workflow.go 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 -}