diff --git a/.github/golangci.yml b/.github/golangci.yml index 992398956b1..53141a3143d 100644 --- a/.github/golangci.yml +++ b/.github/golangci.yml @@ -1,9 +1,20 @@ run: - timeout: 5m + concurrency: 8 + timeout: 10m + issue-exit-code: 1 tests: true skip-dirs-use-default: true + modules-download-mode: readonly + allow-parallel-runners: false + go: "" + +output: + uniq-by-line: false + path-prefix: "" + sort-results: true linters: + fast: false disable-all: true enable: - whitespace # Tool for detection of leading and trailing whitespace @@ -21,12 +32,11 @@ linters: - gofmt # Whether the code was gofmt-ed - goimports # Unused imports - goconst # Repeated strings that could be replaced by a constant - #- forcetypeassert # Finds forced type assertions - dogsled # Checks assignments with too many blank identifiers (e.g. x, , , _, := f()) - #- dupl # Code clone detection - errname # Checks that sentinel errors are prefixed with the Err and error types are suffixed with the Error - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13 - gofumpt # Stricter gofmt + - unused # Checks Go code for unused constants, variables, functions and types linters-settings: gofmt: @@ -42,9 +52,20 @@ linters-settings: checks: [ "all", "-ST1022", "-ST1003" ] errorlint: asserts: false + gocritic: + enabled-tags: + - diagnostic + - experimental + - opinionated + - performance + - style issues: whole-files: true + max-issues-per-linter: 0 + max-same-issues: 0 + new: false + fix: false exclude-rules: - path: _test\.go linters: diff --git a/.github/workflows/contribs.yml b/.github/workflows/contribs.yml new file mode 100644 index 00000000000..939ac670710 --- /dev/null +++ b/.github/workflows/contribs.yml @@ -0,0 +1,35 @@ +name: contribs + +on: + push: + branches: [ "master" ] + pull_request: + paths: + - "contribs/**" + - ".github/workflows/contribs.yml" + - "gnovm/**.go" + - "gno.land/**.go" + - "tm2/**.go" + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + install: + strategy: + fail-fast: false + matrix: + goversion: # two latest versions + - "1.21.x" + program: + - "gnomd" + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.goversion }} + - run: make install ${{ matrix.program }} + working-directory: contribs diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index b17c66d8e5a..f69a27d15b6 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -73,3 +73,22 @@ jobs: - run: go run ./gnovm/cmd/gno lint --verbose ./examples/gno.land/r/gnoland - run: go run ./gnovm/cmd/gno lint --verbose ./examples/gno.land/r/system # TODO: track coverage + mod-tidy: + strategy: + fail-fast: false + matrix: + go-version: [ "1.21.x" ] + # unittests: TODO: matrix with contracts + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.go-version }} + - uses: actions/checkout@v4 + - run: | + GNO_CMD="$(pwd)/gnovm/cmd/gno" + # Find all directories containing gno.mod file + find ./examples -name "gno.mod" -execdir go run "$GNO_CMD" mod tidy \; + # Check if there are changes after running gno mod tidy + git diff --exit-code || (echo "Some gno.mod files are not tidy, please run 'make tidy'." && exit 1) diff --git a/.github/workflows/gnoland.yml b/.github/workflows/gnoland.yml index 95cb5fa8ce0..d305bed2dcd 100644 --- a/.github/workflows/gnoland.yml +++ b/.github/workflows/gnoland.yml @@ -60,9 +60,7 @@ jobs: - _test.gnoland - _test.gnokey - _test.pkgs - # XXX: test broken, should be rewritten to run an inmemory localnode - # Re-add to makefile when fixed. Tracked here: https://github.com/gnolang/gno/issues/1222 - #- _test.gnoweb + - _test.gnoweb runs-on: ubuntu-latest timeout-minutes: 15 steps: @@ -78,7 +76,7 @@ jobs: export LOG_DIR="${{ runner.temp }}/logs/test-${{ matrix.goversion }}-gnoland" make ${{ matrix.args }} - name: Upload Test Log - if: always() + if: always() uses: actions/upload-artifact@v3 with: name: logs-test-gnoland-go${{ matrix.goversion }} @@ -101,7 +99,7 @@ jobs: uses: codecov/codecov-action@v3 with: directory: ${{ runner.temp }}/coverage - token: ${{ secrets.CODECOV_TOKEN }} + token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: ${{ github.repository == 'gnolang/gno' }} docker-integration: diff --git a/.github/workflows/gnovm.yml b/.github/workflows/gnovm.yml index 71b03b5ca05..5fa68ac305a 100644 --- a/.github/workflows/gnovm.yml +++ b/.github/workflows/gnovm.yml @@ -67,6 +67,8 @@ jobs: - _test.gnolang.other runs-on: ubuntu-latest timeout-minutes: 15 + env: + COVERAGE_DIR: "/tmp/coverage" steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v4 @@ -74,28 +76,59 @@ jobs: go-version: ${{ matrix.goversion }} - name: test working-directory: gnovm + env: + TXTARCOVERDIR: ${{ env.COVERAGE_DIR }} run: | + mkdir -p $COVERAGE_DIR + + # Setup testing environements variables export GOPATH=$HOME/go - export GOTEST_FLAGS="-v -p 1 -timeout=30m -coverprofile=coverage.out -covermode=atomic" + export GOTEST_FLAGS="-v -p 1 -timeout=30m -covermode=atomic -test.gocoverdir=$COVERAGE_DIR" + + # Run target test make ${{ matrix.args }} - uses: actions/upload-artifact@v3 if: ${{ runner.os == 'Linux' && matrix.goversion == '1.21.x' }} with: name: ${{runner.os}}-coverage-gnovm-${{ matrix.args}}-${{matrix.goversion}} - path: ./gnovm/coverage.out + path: ${{ env.COVERAGE_DIR }} upload-coverage: needs: test runs-on: ubuntu-latest + env: + COVERAGE_DATA: /tmp/coverage/coverage-raw + COVERAGE_OUTPUT: /tmp/coverage/coverage-out + COVERAGE_PROFILE: /tmp/coverage/coverage.txt steps: - - name: Download all previous coverage artifacts + - run: mkdir -p $COVERAGE_DATA $COVERAGE_OUTPUT + - name: Download all previous coverage data artifacts uses: actions/download-artifact@v3 with: - path: ${{ runner.temp }}/coverage + path: ${{ env.COVERAGE_DATA }} + - uses: actions/setup-go@v4 + with: + go-version: "1.21.x" + - name: Merge coverages + working-directory: ${{ env.COVERAGE_DATA }} + run: | + # Create coverage directory list separate by comma + export COVERAGE_DIRS="$(ls | tr '\n' ',' | sed s/,$//)" + + # Merge all coverage data directories from previous tests + go tool covdata merge -v 1 -i="$COVERAGE_DIRS" -o $COVERAGE_OUTPUT + + # Print coverage percent for debug purpose if needed + echo 'coverage results:' + go tool covdata percent -i=$COVERAGE_OUTPUT + + # Generate coverage profile + go tool covdata textfmt -v 1 -i=$COVERAGE_OUTPUT -o $COVERAGE_PROFILE + - name: Upload combined coverage to Codecov uses: codecov/codecov-action@v3 with: - directory: ${{ runner.temp }}/coverage + files: ${{ env.COVERAGE_PROFILE }} token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: ${{ github.repository == 'gnolang/gno' }} diff --git a/.github/workflows/misc.yml b/.github/workflows/misc.yml index a7c20d61ffd..f72a97c95b3 100644 --- a/.github/workflows/misc.yml +++ b/.github/workflows/misc.yml @@ -71,8 +71,9 @@ jobs: - name: Check go.mods run: | - sums="$(sha256sum go.mod misc/devdeps/go.mod)" - for path in . ./misc/devdeps; do + gomods=$(find . -type f -name go.mod) + sums="$(sha256sum ${gomods})" + for path in $(dirname $(gomods)); do env -C $path go mod tidy -v || exit 1 done echo "$sums" | sha256sum -c diff --git a/.github/workflows/tm2.yml b/.github/workflows/tm2.yml index 7b78ccb1e0f..d5c6d9ddda6 100644 --- a/.github/workflows/tm2.yml +++ b/.github/workflows/tm2.yml @@ -55,7 +55,7 @@ jobs: - _test.pkg.bft - _test.pkg.others runs-on: ubuntu-latest - timeout-minutes: 15 + timeout-minutes: 21 steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v4 @@ -65,7 +65,7 @@ jobs: working-directory: tm2 run: | export GOPATH=$HOME/go - export GOTEST_FLAGS="-v -p 1 -timeout=30m -coverprofile=coverage.out -covermode=atomic" + export GOTEST_FLAGS="-v -p 1 -timeout=20m -coverprofile=coverage.out -covermode=atomic" make ${{ matrix.args }} touch coverage.out - uses: actions/upload-artifact@v3 diff --git a/contribs/Makefile b/contribs/Makefile new file mode 100644 index 00000000000..b816987b733 --- /dev/null +++ b/contribs/Makefile @@ -0,0 +1,30 @@ +.PHONY: help +help: + @echo "Available make commands:" + @cat Makefile | grep '^[a-z][^:]*:' | cut -d: -f1 | sort | sed 's/^/ /' + +.PHONY: install +install: install.gnomd + +install.gnomd:; cd gnomd && go install . + +.PHONY: clean +clean: + rm -rf build + +######################################## +# Dev tools +rundep=go run -modfile ../misc/devdeps/go.mod + +.PHONY: fmt +GOFMT_FLAGS ?= -w +fmt: + $(rundep) mvdan.cc/gofumpt $(GOFMT_FLAGS) . + +######################################## +# Test suite +GOTEST_FLAGS ?= -v -p 1 -timeout=30m + +.PHONY: test +test: + @echo "nothing to do." diff --git a/contribs/README.md b/contribs/README.md new file mode 100644 index 00000000000..c481af0f4aa --- /dev/null +++ b/contribs/README.md @@ -0,0 +1,17 @@ +# Gno Contribs + +This directory houses additional commands and tools designed to enhance your Gno experience. +These tools can range from simple wrappers for `gno`, `gnoland`, and `gnokey` to complete applications. +Some may be Go binaries with their own `go.mod` files, allowing the use of specialized libraries, +while others may be shell scripts or programs written in different languages. + +## Contributing Guidelines + +If you'd like to contribute a tool to Gno Contribs, please follow these guidelines: + +1. **Naming**: Choose a clear and concise name for your tool, starting with one of the prefixes: `gno`, `gnoland`, or `gnokey`, + followed by a short descriptive word or abbreviation. + This naming convention helps users identify the purpose of the tool easily. + +2. **User-Friendly**: Ensure that your tool is user-friendly and follows a similar style to other Gno tools, + providing a consistent experience for users. diff --git a/contribs/gnokeykc/README.md b/contribs/gnokeykc/README.md new file mode 100644 index 00000000000..5d508b4b221 --- /dev/null +++ b/contribs/gnokeykc/README.md @@ -0,0 +1,16 @@ +# `gnokeykc` + +`gnokeykc` is a Go-based CLI tool that enhances [`gnokey`](../../gno.land/cmd/gnokey) by integrating with your system's keychain. It adds `gnokey kc ...` subcommands to set and unset passwords in the keychain, allowing Gnokey to fetch passwords directly from the keychain instead of prompting for terminal input. + +## Usage + + gnokey kc -h + +## Terminal Alias + +For ease of use, set up a terminal alias to replace `gnokey` with `gnokeykc`: + + echo "alias gnokey='gnokeykc'" >> ~/.bashrc && source ~/.bashrc + +Now, `gnokey` commands will use `gnokeykc`, fetching passwords from the keychain. + diff --git a/contribs/gnokeykc/go.mod b/contribs/gnokeykc/go.mod new file mode 100644 index 00000000000..fca27e7455a --- /dev/null +++ b/contribs/gnokeykc/go.mod @@ -0,0 +1,54 @@ +module github.com/gnolang/gno/contribs/gnokeykc + +go 1.20 + +replace github.com/gnolang/gno => ../.. + +require ( + github.com/gnolang/gno v0.0.0-00010101000000-000000000000 + github.com/zalando/go-keyring v0.2.3 +) + +require ( + github.com/alessio/shellescape v1.4.1 // indirect + github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c // indirect + github.com/btcsuite/btcd/btcutil v1.0.0 // indirect + github.com/cespare/xxhash v1.1.0 // indirect + github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cockroachdb/apd v1.1.0 // indirect + github.com/danieljoos/wincred v1.2.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgraph-io/badger/v3 v3.2103.4 // indirect + github.com/dgraph-io/ristretto v0.1.1 // indirect + github.com/dustin/go-humanize v1.0.0 // indirect + github.com/gnolang/goleveldb v0.0.9 // indirect + github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect + github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/flatbuffers v1.12.1 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/klauspost/compress v1.12.3 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/linxGnu/grocksdb v1.8.4 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect + github.com/peterbourgon/ff/v3 v3.4.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/rs/cors v1.10.1 // indirect + github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect + go.etcd.io/bbolt v1.3.7 // indirect + go.opencensus.io v0.22.5 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/term v0.13.0 // indirect + golang.org/x/tools v0.13.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect +) diff --git a/contribs/gnokeykc/go.sum b/contribs/gnokeykc/go.sum new file mode 100644 index 00000000000..9ab29663ae6 --- /dev/null +++ b/contribs/gnokeykc/go.sum @@ -0,0 +1,237 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0= +github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c h1:lnAMg3ra/Gw4AkRMxrxYs8nrprWsHowg8H9zaYsJOo4= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd/btcutil v1.0.0 h1:dB36qRTOucIh6NUe40UCieOS+axPhP6VNyRtYkTUKKk= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/danieljoos/wincred v1.2.0 h1:ozqKHaLK0W/ii4KVbbvluM91W2H3Sh0BncbUNPS7jLE= +github.com/danieljoos/wincred v1.2.0/go.mod h1:FzQLLMKBFdvu+osBrnFODiv32YGwCfx0SkRa/eYHgec= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgraph-io/badger/v3 v3.2103.4 h1:WE1B07YNTTJTtG9xjBcSW2wn0RJLyiV99h959RKZqM4= +github.com/dgraph-io/badger/v3 v3.2103.4/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw= +github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= +github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/gnolang/goleveldb v0.0.9 h1:Q7rGko9oXMKtQA+Apeeed5a3sjba/mcDhzJGoTVLCKE= +github.com/gnolang/goleveldb v0.0.9/go.mod h1:Dz6p9bmpy/FBESTgduiThZt5mToVDipcHGzj/zUOo8E= +github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 h1:GKvsK3oLWG9B1GL7WP/VqwM6C92j5tIvB844oggL9Lk= +github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216/go.mod h1:xJhtEL7ahjM1WJipt89gel8tHzfIl/LyMY+lCYh38d8= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw= +github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jaekwon/testify v1.6.1 h1:4AtAJcR9GzXN5W4DdY7ie74iCPiJV1JJUJL90t2ZUyw= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= +github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU= +github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= +github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= +github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/linxGnu/grocksdb v1.8.4 h1:ZMsBpPpJNtRLHiKKp0mI7gW+NT4s7UgfD5xHxx1jVRo= +github.com/linxGnu/grocksdb v1.8.4/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc= +github.com/peterbourgon/ff/v3 v3.4.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= +github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/zalando/go-keyring v0.2.3 h1:v9CUu9phlABObO4LPWycf+zwMG7nlbb3t/B5wa97yms= +github.com/zalando/go-keyring v0.2.3/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk= +go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= +go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/contribs/gnokeykc/kc.go b/contribs/gnokeykc/kc.go new file mode 100644 index 00000000000..f91dc8ba4dd --- /dev/null +++ b/contribs/gnokeykc/kc.go @@ -0,0 +1,94 @@ +package main + +import ( + "context" + "flag" + "fmt" + + "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/zalando/go-keyring" +) + +const ( + kcService = "gnokey" + kcName = "encryption" +) + +func newKcCmd(io commands.IO) *commands.Command { + cmd := commands.NewCommand( + commands.Metadata{ + Name: "kc", + ShortUsage: "kc ", + ShortHelp: "Manage OS keychain", + }, + commands.NewEmptyConfig(), + commands.HelpExec, + ) + cmd.AddSubCommands( + newKcSetCmd(io), + newKcUnsetCmd(io), + ) + return cmd +} + +func newKcSetCmd(io commands.IO) *commands.Command { + return commands.NewCommand( + commands.Metadata{ + Name: "set", + ShortUsage: "set", + ShortHelp: "set encryption password in OS keychain", + }, + commands.NewEmptyConfig(), + func(_ context.Context, args []string) error { + return execKcSet(args, io) + }, + ) +} + +func execKcSet(args []string, io commands.IO) error { + if len(args) != 0 { + return flag.ErrHelp + } + + insecurePasswordStdin := false // XXX: cfg.rootCfg.InsecurePasswordStdin + password, err := io.GetPassword("Enter password.", insecurePasswordStdin) + if err != nil { + return fmt.Errorf("cannot read password: %w", err) + } + + err = keyring.Set(kcService, kcName, password) + if err != nil { + return fmt.Errorf("cannot set password is OS keychain") + } + + io.Printfln("Successfully added password for key.") + return nil +} + +func newKcUnsetCmd(io commands.IO) *commands.Command { + return commands.NewCommand( + commands.Metadata{ + Name: "unset", + ShortUsage: "unset", + ShortHelp: "unset password in OS keychain", + }, + commands.NewEmptyConfig(), + func(_ context.Context, args []string) error { + return execKcUnset(args, io) + }, + ) +} + +func execKcUnset(args []string, io commands.IO) error { + if len(args) != 0 { + return flag.ErrHelp + } + + err := keyring.Delete(kcService, kcName) + if err != nil { + return fmt.Errorf("cannot unset password from OS keychain") + } + + io.Printfln("Successfully unset password") + return nil +} diff --git a/contribs/gnokeykc/main.go b/contribs/gnokeykc/main.go new file mode 100644 index 00000000000..8060f8cb1e3 --- /dev/null +++ b/contribs/gnokeykc/main.go @@ -0,0 +1,32 @@ +package main + +import ( + "context" + "fmt" + "os" + + "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/gnolang/gno/tm2/pkg/crypto/keys/client" + "github.com/zalando/go-keyring" +) + +func main() { + stdio := commands.NewDefaultIO() + wrappedio := &wrappedIO{IO: stdio} + cmd := client.NewRootCmd(wrappedio) + cmd.AddSubCommands(newKcCmd(stdio)) + + if err := cmd.ParseAndRun(context.Background(), os.Args[1:]); err != nil { + _, _ = fmt.Fprintf(os.Stderr, "%+v\n", err) + + os.Exit(1) + } +} + +type wrappedIO struct { + commands.IO +} + +func (io *wrappedIO) GetPassword(prompt string, insecure bool) (string, error) { + return keyring.Get(kcService, kcName) +} diff --git a/contribs/gnomd/go.mod b/contribs/gnomd/go.mod new file mode 100644 index 00000000000..b631040ce94 --- /dev/null +++ b/contribs/gnomd/go.mod @@ -0,0 +1,25 @@ +module github.com/gnolang/gno/contribs/gnomd + +go 1.20 + +require github.com/MichaelMure/go-term-markdown v0.1.4 + +require ( + github.com/MichaelMure/go-term-text v0.3.1 // indirect + github.com/alecthomas/chroma v0.7.1 // indirect + github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect + github.com/disintegration/imaging v1.6.2 // indirect + github.com/dlclark/regexp2 v1.1.6 // indirect + github.com/eliukblau/pixterm/pkg/ansimage v0.0.0-20191210081756-9fb6cf8c2f75 // indirect + github.com/fatih/color v1.9.0 // indirect + github.com/gomarkdown/markdown v0.0.0-20191123064959-2c17d62f5098 // indirect + github.com/kyokomi/emoji/v2 v2.2.8 // indirect + github.com/lucasb-eyer/go-colorful v1.0.3 // indirect + github.com/mattn/go-colorable v0.1.4 // indirect + github.com/mattn/go-isatty v0.0.11 // indirect + github.com/mattn/go-runewidth v0.0.12 // indirect + github.com/rivo/uniseg v0.1.0 // indirect + golang.org/x/image v0.0.0-20191206065243-da761ea9ff43 // indirect + golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 // indirect + golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect +) diff --git a/contribs/gnomd/go.sum b/contribs/gnomd/go.sum new file mode 100644 index 00000000000..b4ad4f5c9bf --- /dev/null +++ b/contribs/gnomd/go.sum @@ -0,0 +1,70 @@ +github.com/MichaelMure/go-term-markdown v0.1.4 h1:Ir3kBXDUtOX7dEv0EaQV8CNPpH+T7AfTh0eniMOtNcs= +github.com/MichaelMure/go-term-markdown v0.1.4/go.mod h1:EhcA3+pKYnlUsxYKBJ5Sn1cTQmmBMjeNlpV8nRb+JxA= +github.com/MichaelMure/go-term-text v0.3.1 h1:Kw9kZanyZWiCHOYu9v/8pWEgDQ6UVN9/ix2Vd2zzWf0= +github.com/MichaelMure/go-term-text v0.3.1/go.mod h1:QgVjAEDUnRMlzpS6ky5CGblux7ebeiLnuy9dAaFZu8o= +github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U= +github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI= +github.com/alecthomas/chroma v0.7.1 h1:G1i02OhUbRi2nJxcNkwJaY/J1gHXj9tt72qN6ZouLFQ= +github.com/alecthomas/chroma v0.7.1/go.mod h1:gHw09mkX1Qp80JlYbmN9L3+4R5o6DJJ3GRShh+AICNc= +github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo= +github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0= +github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI= +github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY= +github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ= +github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ= +github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= +github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= +github.com/dlclark/regexp2 v1.1.6 h1:CqB4MjHw0MFCDj+PHHjiESmHX+N7t0tJzKvC6M97BRg= +github.com/dlclark/regexp2 v1.1.6/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/eliukblau/pixterm/pkg/ansimage v0.0.0-20191210081756-9fb6cf8c2f75 h1:vbix8DDQ/rfatfFr/8cf/sJfIL69i4BcZfjrVOxsMqk= +github.com/eliukblau/pixterm/pkg/ansimage v0.0.0-20191210081756-9fb6cf8c2f75/go.mod h1:0gZuvTO1ikSA5LtTI6E13LEOdWQNjIo5MTQOvrV0eFg= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/gomarkdown/markdown v0.0.0-20191123064959-2c17d62f5098 h1:Qxs3bNRWe8GTcKMxYOSXm0jx6j0de8XUtb/fsP3GZ0I= +github.com/gomarkdown/markdown v0.0.0-20191123064959-2c17d62f5098/go.mod h1:aii0r/K0ZnHv7G0KF7xy1v0A7s2Ljrb5byB7MO5p6TU= +github.com/kyokomi/emoji/v2 v2.2.8 h1:jcofPxjHWEkJtkIbcLHvZhxKgCPl6C7MyjTrD4KDqUE= +github.com/kyokomi/emoji/v2 v2.2.8/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE= +github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac= +github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-runewidth v0.0.12 h1:Y41i/hVW3Pgwr8gV+J23B9YEY0zxjptBuCWEaxmAOow= +github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY= +github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/dl v0.0.0-20190829154251-82a15e2f2ead/go.mod h1:IUMfjQLJQd4UTqG1Z90tenwKoCX93Gn3MAQJMOSBsDQ= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20191206065243-da761ea9ff43 h1:gQ6GUSD102fPgli+Yb4cR/cGaHF7tNBt+GYoRCpGC7s= +golang.org/x/image v0.0.0-20191206065243-da761ea9ff43/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/contribs/gnomd/main.go b/contribs/gnomd/main.go new file mode 100644 index 00000000000..2d3b7266af5 --- /dev/null +++ b/contribs/gnomd/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "fmt" + "io/ioutil" + "os" + + markdown "github.com/MichaelMure/go-term-markdown" +) + +func main() { + // If no arguments are provided, read from stdin + if len(os.Args) <= 1 { + fileContent, err := ioutil.ReadAll(os.Stdin) + checkErr(err) + renderMarkdown("stdin.gno", fileContent) + } + + // Iterate through command-line arguments (file paths) + for _, filePath := range os.Args[1:] { + fileContent, err := ioutil.ReadFile(filePath) + checkErr(err) + renderMarkdown(filePath, fileContent) + } +} + +func renderMarkdown(filePath string, fileContent []byte) { + fmt.Printf("-- %s --\n", filePath) + + result := markdown.Render(string(fileContent), 80, 6) + fmt.Println(string(result)) +} + +func checkErr(err error) { + if err != nil { + panic(err) + } +} diff --git a/examples/Makefile b/examples/Makefile index f20072d9df2..9b628e01ce5 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -37,3 +37,7 @@ clean: GOFMT_FLAGS ?= -w fmt: go run -modfile ../misc/devdeps/go.mod mvdan.cc/gofumpt $(GOFMT_FLAGS) `find . -name "*.gno"` + +.PHONY: tidy +tidy: + find . -name "gno.mod" -execdir go run github.com/gnolang/gno/gnovm/cmd/gno mod tidy \; diff --git a/examples/gno.land/p/demo/acl/gno.mod b/examples/gno.land/p/demo/acl/gno.mod index 2aabe3a5645..176cde637bd 100644 --- a/examples/gno.land/p/demo/acl/gno.mod +++ b/examples/gno.land/p/demo/acl/gno.mod @@ -1,6 +1,6 @@ module gno.land/p/demo/acl require ( - "gno.land/p/demo/avl" v0.0.0-latest - "gno.land/p/demo/testutils" v0.0.0-latest + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/testutils v0.0.0-latest ) diff --git a/examples/gno.land/p/demo/blog/gno.mod b/examples/gno.land/p/demo/blog/gno.mod index c8437af1732..65f58e7a0f6 100644 --- a/examples/gno.land/p/demo/blog/gno.mod +++ b/examples/gno.land/p/demo/blog/gno.mod @@ -1,7 +1,7 @@ module gno.land/p/demo/blog require ( - "gno.land/p/demo/avl" v0.0.0-latest - "gno.land/p/demo/ufmt" v0.0.0-latest - "gno.land/p/demo/mux" v0.0.0-latest + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/mux v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest ) diff --git a/examples/gno.land/p/demo/dom/gno.mod b/examples/gno.land/p/demo/dom/gno.mod index e7d0e5a9e75..83ca827cf66 100644 --- a/examples/gno.land/p/demo/dom/gno.mod +++ b/examples/gno.land/p/demo/dom/gno.mod @@ -1,5 +1,3 @@ module gno.land/p/demo/dom -require ( - "gno.land/p/demo/avl" v0.0.0-latest -) +require gno.land/p/demo/avl v0.0.0-latest diff --git a/examples/gno.land/p/demo/flow/gno.mod b/examples/gno.land/p/demo/flow/gno.mod index 4a4d4fb4d82..5adddbfe021 100644 --- a/examples/gno.land/p/demo/flow/gno.mod +++ b/examples/gno.land/p/demo/flow/gno.mod @@ -1 +1 @@ -module "gno.land/p/demo/flow" +module gno.land/p/demo/flow diff --git a/examples/gno.land/p/demo/gnode/gno.mod b/examples/gno.land/p/demo/gnode/gno.mod index e922821f7fd..a93c2051830 100644 --- a/examples/gno.land/p/demo/gnode/gno.mod +++ b/examples/gno.land/p/demo/gnode/gno.mod @@ -1 +1 @@ -module "gno.land/p/demo/gnode" +module gno.land/p/demo/gnode diff --git a/examples/gno.land/p/demo/grc/exts/vault/gno.mod b/examples/gno.land/p/demo/grc/exts/vault/gno.mod index 8b4d4524366..2720bf09d95 100644 --- a/examples/gno.land/p/demo/grc/exts/vault/gno.mod +++ b/examples/gno.land/p/demo/grc/exts/vault/gno.mod @@ -1,6 +1,6 @@ module gno.land/p/demo/grc/exts/vault require ( - "gno.land/p/demo/avl" v0.0.0-latest - "gno.land/p/demo/grc/grc20" v0.0.0-latest + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/grc/grc20 v0.0.0-latest ) diff --git a/examples/gno.land/p/demo/grc/grc1155/gno.mod b/examples/gno.land/p/demo/grc/grc1155/gno.mod index 33a8e55be71..0b2b85d8e86 100644 --- a/examples/gno.land/p/demo/grc/grc1155/gno.mod +++ b/examples/gno.land/p/demo/grc/grc1155/gno.mod @@ -1,7 +1,7 @@ module gno.land/p/demo/grc/grc1155 require ( - "gno.land/p/demo/avl" v0.0.0-latest - "gno.land/r/demo/users" v0.0.0-latest - "gno.land/p/demo/ufmt" v0.0.0-latest + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/r/demo/users v0.0.0-latest ) diff --git a/examples/gno.land/p/demo/grc/grc20/gno.mod b/examples/gno.land/p/demo/grc/grc20/gno.mod index 5e6e13f834c..fd80766a956 100644 --- a/examples/gno.land/p/demo/grc/grc20/gno.mod +++ b/examples/gno.land/p/demo/grc/grc20/gno.mod @@ -1,7 +1,7 @@ module gno.land/p/demo/grc/grc20 require ( - "gno.land/p/demo/avl" v0.0.0-latest - "gno.land/p/demo/ufmt" v0.0.0-latest - "gno.land/p/demo/grc/exts" v0.0.0-latest + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/grc/exts v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest ) diff --git a/examples/gno.land/p/demo/grc/grc721/gno.mod b/examples/gno.land/p/demo/grc/grc721/gno.mod index 229fc3f739c..ea8c9c9e52e 100644 --- a/examples/gno.land/p/demo/grc/grc721/gno.mod +++ b/examples/gno.land/p/demo/grc/grc721/gno.mod @@ -1,7 +1,7 @@ module gno.land/p/demo/grc/grc721 require ( - "gno.land/p/demo/avl" v0.0.0-latest - "gno.land/r/demo/users" v0.0.0-latest - "gno.land/p/demo/ufmt" v0.0.0-latest + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/r/demo/users v0.0.0-latest ) diff --git a/examples/gno.land/p/demo/grc/grc777/gno.mod b/examples/gno.land/p/demo/grc/grc777/gno.mod index 2fddce3f8f8..9fbf2f2b7cd 100644 --- a/examples/gno.land/p/demo/grc/grc777/gno.mod +++ b/examples/gno.land/p/demo/grc/grc777/gno.mod @@ -1,5 +1,3 @@ module gno.land/p/demo/grc/grc777 -require ( - "gno.land/p/demo/grc/exts" v0.0.0-latest -) +require gno.land/p/demo/grc/exts v0.0.0-latest diff --git a/examples/gno.land/p/demo/groups/gno.mod b/examples/gno.land/p/demo/groups/gno.mod index b52ad8b05b1..0e9f7cf2a7c 100644 --- a/examples/gno.land/p/demo/groups/gno.mod +++ b/examples/gno.land/p/demo/groups/gno.mod @@ -1,7 +1,6 @@ module gno.land/p/demo/groups require ( - "gno.land/r/demo/boards" v0.0.0-latest - "gno.land/p/demo/maths" v0.0.0-latest - "gno.land/p/demo/testutils" v0.0.0-latest + gno.land/p/demo/maths v0.0.0-latest + gno.land/r/demo/boards v0.0.0-latest ) diff --git a/examples/gno.land/p/demo/math_eval/int32/gno.mod b/examples/gno.land/p/demo/math_eval/int32/gno.mod index 9a1e634447c..de57497a699 100644 --- a/examples/gno.land/p/demo/math_eval/int32/gno.mod +++ b/examples/gno.land/p/demo/math_eval/int32/gno.mod @@ -1,5 +1,3 @@ module gno.land/p/demo/math_eval/int32 -require ( - "gno.land/p/demo/ufmt" v0.0.0-latest -) +require gno.land/p/demo/ufmt v0.0.0-latest diff --git a/examples/gno.land/p/demo/microblog/gno.mod b/examples/gno.land/p/demo/microblog/gno.mod index fe19b89f777..5964679efa6 100644 --- a/examples/gno.land/p/demo/microblog/gno.mod +++ b/examples/gno.land/p/demo/microblog/gno.mod @@ -1,7 +1,8 @@ module gno.land/p/demo/microblog require ( - "gno.land/p/demo/avl" v0.0.0-latest - "gno.land/p/demo/ufmt" v0.0.0-latest - "gno.land/r/demo/users" v0.0.0-latest + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/testutils v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/r/demo/users v0.0.0-latest ) diff --git a/examples/gno.land/p/demo/mux/gno.mod b/examples/gno.land/p/demo/mux/gno.mod index 13e4736bea8..972a531e14c 100644 --- a/examples/gno.land/p/demo/mux/gno.mod +++ b/examples/gno.land/p/demo/mux/gno.mod @@ -1 +1 @@ -module "gno.land/p/demo/mux" +module gno.land/p/demo/mux diff --git a/examples/gno.land/p/demo/pausable/gno.mod b/examples/gno.land/p/demo/pausable/gno.mod new file mode 100644 index 00000000000..08c7a4f7e5f --- /dev/null +++ b/examples/gno.land/p/demo/pausable/gno.mod @@ -0,0 +1,3 @@ +module gno.land/p/demo/pausable + +require gno.land/p/demo/ownable v0.0.0-latest diff --git a/examples/gno.land/p/demo/pausable/pausable.gno b/examples/gno.land/p/demo/pausable/pausable.gno new file mode 100644 index 00000000000..eae3456ba61 --- /dev/null +++ b/examples/gno.land/p/demo/pausable/pausable.gno @@ -0,0 +1,49 @@ +package pausable + +import "gno.land/p/demo/ownable" + +type Pausable struct { + *ownable.Ownable + paused bool +} + +// New returns a new Pausable struct with non-paused state as default +func New() *Pausable { + return &Pausable{ + Ownable: ownable.New(), + paused: false, + } +} + +// NewFromOwnable is the same as New, but with a pre-existing top-level ownable +func NewFromOwnable(ownable *ownable.Ownable) *Pausable { + return &Pausable{ + Ownable: ownable, + paused: false, + } +} + +// IsPaused checks if Pausable is paused +func (p Pausable) IsPaused() bool { + return p.paused +} + +// Pause sets the state of Pausable to true, meaning all pausable functions are paused +func (p *Pausable) Pause() error { + if err := p.CallerIsOwner(); err != nil { + return err + } + + p.paused = true + return nil +} + +// Unpause sets the state of Pausable to false, meaning all pausable functions are resumed +func (p *Pausable) Unpause() error { + if err := p.CallerIsOwner(); err != nil { + return err + } + + p.paused = false + return nil +} diff --git a/examples/gno.land/p/demo/pausable/pausable_test.gno b/examples/gno.land/p/demo/pausable/pausable_test.gno new file mode 100644 index 00000000000..cc95c457573 --- /dev/null +++ b/examples/gno.land/p/demo/pausable/pausable_test.gno @@ -0,0 +1,77 @@ +package pausable + +import ( + "std" + "testing" + + "gno.land/p/demo/ownable" +) + +var ( + firstCaller = std.Address("g1l9aypkr8xfvs82zeux486ddzec88ty69lue9de") + secondCaller = std.Address("g127jydsh6cms3lrtdenydxsckh23a8d6emqcvfa") +) + +func TestNew(t *testing.T) { + std.TestSetOrigCaller(firstCaller) + + result := New() + + if result.paused != false { + t.Fatalf("Expected result to be unpaused, got %t\n", result.paused) + } + + if result.Owner() != firstCaller { + t.Fatalf("Expected %s, got %s\n", firstCaller, result.Owner()) + } +} + +func TestNewFromOwnable(t *testing.T) { + std.TestSetOrigCaller(firstCaller) + o := ownable.New() + + std.TestSetOrigCaller(secondCaller) + result := NewFromOwnable(o) + + if result.Owner() != firstCaller { + t.Fatalf("Expected %s, got %s\n", firstCaller, result.Owner()) + } +} + +func TestSetUnpaused(t *testing.T) { + std.TestSetOrigCaller(firstCaller) + + result := New() + result.Unpause() + + if result.IsPaused() { + t.Fatalf("Expected result to be unpaused, got %t\n", result.IsPaused()) + } +} + +func TestSetPaused(t *testing.T) { + std.TestSetOrigCaller(firstCaller) + + result := New() + result.Pause() + + if !result.IsPaused() { + t.Fatalf("Expected result to be paused, got %t\n", result.IsPaused()) + } +} + +func TestIsPaused(t *testing.T) { + std.TestSetOrigCaller(firstCaller) + + result := New() + + if result.IsPaused() { + t.Fatalf("Expected result to be unpaused, got %t\n", result.IsPaused()) + } + + result.Pause() + + if !result.IsPaused() { + t.Fatalf("Expected result to be paused, got %t\n", result.IsPaused()) + } +} diff --git a/examples/gno.land/p/demo/rand/gno.mod b/examples/gno.land/p/demo/rand/gno.mod index 66082ea873e..098af152648 100644 --- a/examples/gno.land/p/demo/rand/gno.mod +++ b/examples/gno.land/p/demo/rand/gno.mod @@ -1,3 +1,3 @@ // Draft -module gno.land/p/demo/rand +module gno.land/p/demo/rand diff --git a/examples/gno.land/p/demo/svg/gno.mod b/examples/gno.land/p/demo/svg/gno.mod index adb2acf1350..0af7ba0636d 100644 --- a/examples/gno.land/p/demo/svg/gno.mod +++ b/examples/gno.land/p/demo/svg/gno.mod @@ -1,5 +1,3 @@ module gno.land/p/demo/svg -require ( - "gno.land/p/demo/ufmt" v0.0.0-latest -) +require gno.land/p/demo/ufmt v0.0.0-latest diff --git a/examples/gno.land/p/demo/tests/gno.mod b/examples/gno.land/p/demo/tests/gno.mod index 229c2f62d9c..5d80e106567 100644 --- a/examples/gno.land/p/demo/tests/gno.mod +++ b/examples/gno.land/p/demo/tests/gno.mod @@ -1,6 +1,6 @@ module gno.land/p/demo/tests require ( - "gno.land/p/demo/tests/subtests" v0.0.0-latest - "gno.land/r/demo/tests" v0.0.0-latest + gno.land/p/demo/tests/subtests v0.0.0-latest + gno.land/r/demo/tests v0.0.0-latest ) diff --git a/examples/gno.land/p/demo/tests/subtests/gno.mod b/examples/gno.land/p/demo/tests/subtests/gno.mod index 26ec7c4879a..c8333722809 100644 --- a/examples/gno.land/p/demo/tests/subtests/gno.mod +++ b/examples/gno.land/p/demo/tests/subtests/gno.mod @@ -1,4 +1,4 @@ module gno.land/p/demo/tests/subtests -// TODO: this file should not exist. +// TODO: this file should not exist. // This is a temporary workaround. Until https://github.com/gnolang/gno/issues/852 diff --git a/examples/gno.land/p/demo/ui/gno.mod b/examples/gno.land/p/demo/ui/gno.mod index e71ee2d1ab1..41f5cb78d83 100644 --- a/examples/gno.land/p/demo/ui/gno.mod +++ b/examples/gno.land/p/demo/ui/gno.mod @@ -1 +1 @@ -module "gno.land/p/demo/ui" +module gno.land/p/demo/ui diff --git a/examples/gno.land/r/demo/art/gnoface/gno.mod b/examples/gno.land/r/demo/art/gnoface/gno.mod index 33d644206d6..bc17ee9df3b 100644 --- a/examples/gno.land/r/demo/art/gnoface/gno.mod +++ b/examples/gno.land/r/demo/art/gnoface/gno.mod @@ -1,6 +1,6 @@ module gno.land/r/demo/art/gnoface require ( - "gno.land/p/demo/rand" v0.0.0-latest - "gno.land/p/demo/ufmt" v0.0.0-latest + gno.land/p/demo/rand v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/art/millipede/gno.mod b/examples/gno.land/r/demo/art/millipede/gno.mod index 10e3d2f1474..346e3a1673c 100644 --- a/examples/gno.land/r/demo/art/millipede/gno.mod +++ b/examples/gno.land/r/demo/art/millipede/gno.mod @@ -1,5 +1,3 @@ module gno.land/r/demo/art/millipede -require ( - "gno.land/p/demo/ufmt" v0.0.0-latest -) +require gno.land/p/demo/ufmt v0.0.0-latest diff --git a/examples/gno.land/r/demo/boards/gno.mod b/examples/gno.land/r/demo/boards/gno.mod index 882d97fec83..434ad019883 100644 --- a/examples/gno.land/r/demo/boards/gno.mod +++ b/examples/gno.land/r/demo/boards/gno.mod @@ -1,6 +1,6 @@ module gno.land/r/demo/boards require ( - "gno.land/p/demo/avl" v0.0.0-latest - "gno.land/r/demo/users" v0.0.0-latest + gno.land/p/demo/avl v0.0.0-latest + gno.land/r/demo/users v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/foo1155/gno.mod b/examples/gno.land/r/demo/foo1155/gno.mod index 07c05ff5ef3..6fdf18a1658 100644 --- a/examples/gno.land/r/demo/foo1155/gno.mod +++ b/examples/gno.land/r/demo/foo1155/gno.mod @@ -1,7 +1,7 @@ module gno.land/r/demo/foo1155 require ( - "gno.land/p/demo/ufmt" v0.0.0-latest - "gno.land/p/demo/grc/grc1155" v0.0.0-latest - "gno.land/r/demo/users" v0.0.0-latest + gno.land/p/demo/grc/grc1155 v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/r/demo/users v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/foo20/gno.mod b/examples/gno.land/r/demo/foo20/gno.mod index 1dbe9e01e4f..516690ee66c 100644 --- a/examples/gno.land/r/demo/foo20/gno.mod +++ b/examples/gno.land/r/demo/foo20/gno.mod @@ -1,7 +1,7 @@ module gno.land/r/demo/foo20 require ( - "gno.land/p/demo/ufmt" v0.0.0-latest - "gno.land/p/demo/grc/grc20" v0.0.0-latest - "gno.land/r/demo/users" v0.0.0-latest + gno.land/p/demo/grc/grc20 v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/r/demo/users v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/foo721/gno.mod b/examples/gno.land/r/demo/foo721/gno.mod index b34ffd2b3fe..46c19e6ae55 100644 --- a/examples/gno.land/r/demo/foo721/gno.mod +++ b/examples/gno.land/r/demo/foo721/gno.mod @@ -1,7 +1,7 @@ module gno.land/r/demo/foo721 require ( - "gno.land/p/demo/ufmt" v0.0.0-latest - "gno.land/p/demo/grc/grc721" v0.0.0-latest - "gno.land/r/demo/users" v0.0.0-latest + gno.land/p/demo/grc/grc721 v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/r/demo/users v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/groups/gno.mod b/examples/gno.land/r/demo/groups/gno.mod index d97acbecc7a..fc6756e13e2 100644 --- a/examples/gno.land/r/demo/groups/gno.mod +++ b/examples/gno.land/r/demo/groups/gno.mod @@ -1,6 +1,6 @@ module gno.land/r/demo/groups require ( - "gno.land/p/demo/avl" v0.0.0-latest - "gno.land/r/demo/users" v0.0.0-latest + gno.land/p/demo/avl v0.0.0-latest + gno.land/r/demo/users v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/keystore/gno.mod b/examples/gno.land/r/demo/keystore/gno.mod index 88d59c9ccd6..af0b907c259 100644 --- a/examples/gno.land/r/demo/keystore/gno.mod +++ b/examples/gno.land/r/demo/keystore/gno.mod @@ -1,6 +1,7 @@ module gno.land/r/demo/keystore require ( - "gno.land/p/demo/ufmt" v0.0.0-latest - "gno.land/p/demo/avl" v0.0.0-latest + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/testutils v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/math_eval/gno.mod b/examples/gno.land/r/demo/math_eval/gno.mod index 69d4e8c459b..0e3fcfe6e9b 100644 --- a/examples/gno.land/r/demo/math_eval/gno.mod +++ b/examples/gno.land/r/demo/math_eval/gno.mod @@ -1,6 +1,6 @@ module gno.land/r/demo/math_eval require ( - "gno.land/p/demo/ufmt" v0.0.0-latest - "gno.land/p/demo/math_eval/int32" v0.0.0-latest + gno.land/p/demo/math_eval/int32 v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/microblog/gno.mod b/examples/gno.land/r/demo/microblog/gno.mod index 3d79a38d5fd..f496b1008ce 100644 --- a/examples/gno.land/r/demo/microblog/gno.mod +++ b/examples/gno.land/r/demo/microblog/gno.mod @@ -1,6 +1,6 @@ module gno.land/r/demo/microblog require ( - "gno.land/p/demo/microblog" v0.0.0-latest - "gno.land/r/demo/users" v0.0.0-latest + gno.land/p/demo/microblog v0.0.0-latest + gno.land/r/demo/users v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/nft/gno.mod b/examples/gno.land/r/demo/nft/gno.mod index 2fefdbd1907..89e0055be51 100644 --- a/examples/gno.land/r/demo/nft/gno.mod +++ b/examples/gno.land/r/demo/nft/gno.mod @@ -1,6 +1,6 @@ module gno.land/r/demo/nft require ( - "gno.land/p/demo/avl" v0.0.0-latest - "gno.land/p/demo/grc/grc721" v0.0.0-latest + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/grc/grc721 v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/releases_example/gno.mod b/examples/gno.land/r/demo/releases_example/gno.mod index 85bcd07f232..22f640fe797 100644 --- a/examples/gno.land/r/demo/releases_example/gno.mod +++ b/examples/gno.land/r/demo/releases_example/gno.mod @@ -1,5 +1,3 @@ module gno.land/r/demo/releases_example -require ( - "gno.land/p/demo/releases" v0.0.0-latest -) +require gno.land/p/demo/releases v0.0.0-latest diff --git a/examples/gno.land/r/demo/tests/gno.mod b/examples/gno.land/r/demo/tests/gno.mod index 23dd3760157..9c5162f848e 100644 --- a/examples/gno.land/r/demo/tests/gno.mod +++ b/examples/gno.land/r/demo/tests/gno.mod @@ -1,6 +1,6 @@ module gno.land/r/demo/tests require ( - "gno.land/p/demo/testutils" v0.0.0-latest - "gno.land/r/demo/tests/subtests" v0.0.0-latest + gno.land/p/demo/testutils v0.0.0-latest + gno.land/r/demo/tests/subtests v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/tests/subtests/gno.mod b/examples/gno.land/r/demo/tests/subtests/gno.mod index 80db73b4c15..9f466ff77b9 100644 --- a/examples/gno.land/r/demo/tests/subtests/gno.mod +++ b/examples/gno.land/r/demo/tests/subtests/gno.mod @@ -1,4 +1,4 @@ module gno.land/r/demo/tests/subtests -// TODO: this file should not exist. +// TODO: this file should not exist. // This is a temporary workaround. Until https://github.com/gnolang/gno/issues/852 diff --git a/examples/gno.land/r/demo/tests_foo/gno.mod b/examples/gno.land/r/demo/tests_foo/gno.mod index b19d8a21de1..226271ae4b0 100644 --- a/examples/gno.land/r/demo/tests_foo/gno.mod +++ b/examples/gno.land/r/demo/tests_foo/gno.mod @@ -1,5 +1,3 @@ module gno.land/r/demo/tests_foo -require ( - "gno.land/r/demo/tests" v0.0.0-latest -) +require gno.land/r/demo/tests v0.0.0-latest diff --git a/examples/gno.land/r/demo/types/gno.mod b/examples/gno.land/r/demo/types/gno.mod index 5709668ef2a..0e86e5d5676 100644 --- a/examples/gno.land/r/demo/types/gno.mod +++ b/examples/gno.land/r/demo/types/gno.mod @@ -1,5 +1,3 @@ module gno.land/r/demo/types -require ( - "gno.land/p/demo/avl" v0.0.0-latest -) +require gno.land/p/demo/avl v0.0.0-latest diff --git a/examples/gno.land/r/demo/ui/gno.mod b/examples/gno.land/r/demo/ui/gno.mod index 597c0f388a4..42be8cec3f0 100644 --- a/examples/gno.land/r/demo/ui/gno.mod +++ b/examples/gno.land/r/demo/ui/gno.mod @@ -1,5 +1,3 @@ module gno.land/r/demo/ui -require ( - "gno.land/p/demo/ui" v0.0.0-latest -) +require gno.land/p/demo/ui v0.0.0-latest diff --git a/examples/gno.land/r/demo/users/gno.mod b/examples/gno.land/r/demo/users/gno.mod index 055b5816871..edd20eb2721 100644 --- a/examples/gno.land/r/demo/users/gno.mod +++ b/examples/gno.land/r/demo/users/gno.mod @@ -1,6 +1,3 @@ module gno.land/r/demo/users -require ( - "gno.land/p/demo/avl" v0.0.0-latest - "gno.land/p/demo/testutils" v0.0.0-latest -) +require gno.land/p/demo/avl v0.0.0-latest diff --git a/examples/gno.land/r/gnoland/blog/gno.mod b/examples/gno.land/r/gnoland/blog/gno.mod index a8b4f3ceaa9..1d64238cdc8 100644 --- a/examples/gno.land/r/gnoland/blog/gno.mod +++ b/examples/gno.land/r/gnoland/blog/gno.mod @@ -1,6 +1,6 @@ module gno.land/r/gnoland/blog require ( - "gno.land/p/demo/avl" v0.0.0-latest - "gno.land/p/demo/blog" v0.0.0-latest + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/blog v0.0.0-latest ) diff --git a/examples/gno.land/r/gnoland/faucet/gno.mod b/examples/gno.land/r/gnoland/faucet/gno.mod index 75e85df326b..693b0e795cf 100644 --- a/examples/gno.land/r/gnoland/faucet/gno.mod +++ b/examples/gno.land/r/gnoland/faucet/gno.mod @@ -1,7 +1,7 @@ module gno.land/r/gnoland/faucet require ( - "gno.land/p/demo/avl" v0.0.0-latest - "gno.land/p/demo/testutils" v0.0.0-latest - "gno.land/p/demo/ufmt" v0.0.0-latest + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/testutils v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest ) diff --git a/examples/gno.land/r/gnoland/home/gno.mod b/examples/gno.land/r/gnoland/home/gno.mod index 9192b4364d0..2864958930c 100644 --- a/examples/gno.land/r/gnoland/home/gno.mod +++ b/examples/gno.land/r/gnoland/home/gno.mod @@ -1,8 +1,7 @@ module gno.land/r/gnoland/home require ( - "gno.land/r/gnoland/blog" v0.0.0-latest - "gno.land/p/demo/ufmt" v0.0.0-latest - "gno.land/p/demo/avl" v0.0.0-latest - "gno.land/p/demo/ui" v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/p/demo/ui v0.0.0-latest + gno.land/r/gnoland/blog v0.0.0-latest ) diff --git a/examples/gno.land/r/gnoland/pages/gno.mod b/examples/gno.land/r/gnoland/pages/gno.mod index 0f5c4076509..31e9ad2c85b 100644 --- a/examples/gno.land/r/gnoland/pages/gno.mod +++ b/examples/gno.land/r/gnoland/pages/gno.mod @@ -1,6 +1,6 @@ module gno.land/r/gnoland/pages require ( - "gno.land/p/demo/avl" v0.0.0-latest - "gno.land/p/demo/blog" v0.0.0-latest + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/blog v0.0.0-latest ) diff --git a/examples/gno.land/r/manfred/present/gno.mod b/examples/gno.land/r/manfred/present/gno.mod index 9d1ab5b0e56..5d50447e0e0 100644 --- a/examples/gno.land/r/manfred/present/gno.mod +++ b/examples/gno.land/r/manfred/present/gno.mod @@ -1,6 +1,6 @@ module gno.land/r/manfred/present require ( - "gno.land/p/demo/avl" v0.0.0-latest - "gno.land/p/demo/blog" v0.0.0-latest + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/blog v0.0.0-latest ) diff --git a/examples/gno.land/r/system/names/gno.mod b/examples/gno.land/r/system/names/gno.mod index 31c456f90e0..cd4fd0aae4a 100644 --- a/examples/gno.land/r/system/names/gno.mod +++ b/examples/gno.land/r/system/names/gno.mod @@ -1,5 +1,3 @@ module gno.land/r/system/names -require ( - "gno.land/p/demo/avl" v0.0.0-latest -) +require gno.land/p/demo/avl v0.0.0-latest diff --git a/examples/gno.land/r/x/manfred_outfmt/gno.mod b/examples/gno.land/r/x/manfred_outfmt/gno.mod index eef8ec5956e..e6f705c46b9 100644 --- a/examples/gno.land/r/x/manfred_outfmt/gno.mod +++ b/examples/gno.land/r/x/manfred_outfmt/gno.mod @@ -1,6 +1,6 @@ module gno.land/r/x/manfred_outfmt require ( - "gno.land/p/demo/rand" v0.0.0-latest - "gno.land/p/demo/ufmt" v0.0.0-latest + gno.land/p/demo/rand v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest ) diff --git a/gno.land/Makefile b/gno.land/Makefile index 22b9ec24650..29c192e9987 100644 --- a/gno.land/Makefile +++ b/gno.land/Makefile @@ -48,9 +48,7 @@ fmt: ######################################## # Test suite .PHONY: test -test: _test.gnoland _test.gnokey _test.pkgs -# XXX: _test.gnoweb is currently disabled. If fixed, re-enable here and in CI. -# https://github.com/gnolang/gno/issues/1222 +test: _test.gnoland _test.gnoweb _test.gnokey _test.pkgs GOTEST_FLAGS ?= -v -p 1 -timeout=30m diff --git a/gno.land/cmd/genesis/balances.go b/gno.land/cmd/genesis/balances.go index bb6cd8b532c..0e81f280f33 100644 --- a/gno.land/cmd/genesis/balances.go +++ b/gno.land/cmd/genesis/balances.go @@ -11,7 +11,7 @@ type balancesCfg struct { } // newBalancesCmd creates the genesis balances subcommand -func newBalancesCmd(io *commands.IO) *commands.Command { +func newBalancesCmd(io commands.IO) *commands.Command { cfg := &balancesCfg{} cmd := commands.NewCommand( diff --git a/gno.land/cmd/genesis/balances_add.go b/gno.land/cmd/genesis/balances_add.go index 276e48690a8..d1e88efcc6b 100644 --- a/gno.land/cmd/genesis/balances_add.go +++ b/gno.land/cmd/genesis/balances_add.go @@ -8,32 +8,22 @@ import ( "fmt" "io" "os" - "regexp" - "strconv" "strings" "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" - "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/sdk/bank" "github.com/gnolang/gno/tm2/pkg/std" _ "github.com/gnolang/gno/gno.land/pkg/sdk/vm" ) -var ( - balanceRegex = regexp.MustCompile(`^(\w+)=(\d+)ugnot$`) - amountRegex = regexp.MustCompile(`^(\d+)ugnot$`) -) - var ( errNoBalanceSource = errors.New("at least one balance source must be set") errBalanceParsingAborted = errors.New("balance parsing aborted") - errInvalidBalanceFormat = errors.New("invalid balance format encountered") errInvalidAddress = errors.New("invalid address encountered") - errInvalidAmount = errors.New("invalid amount encountered") ) type balancesAddCfg struct { @@ -45,7 +35,7 @@ type balancesAddCfg struct { } // newBalancesAddCmd creates the genesis balances add subcommand -func newBalancesAddCmd(rootCfg *balancesCfg, io *commands.IO) *commands.Command { +func newBalancesAddCmd(rootCfg *balancesCfg, io commands.IO) *commands.Command { cfg := &balancesAddCfg{ rootCfg: rootCfg, } @@ -85,7 +75,7 @@ func (c *balancesAddCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execBalancesAdd(ctx context.Context, cfg *balancesAddCfg, io *commands.IO) error { +func execBalancesAdd(ctx context.Context, cfg *balancesAddCfg, io commands.IO) error { // Load the genesis genesis, loadErr := types.GenesisDocFromFile(cfg.rootCfg.genesisPath) if loadErr != nil { @@ -152,7 +142,7 @@ func execBalancesAdd(ctx context.Context, cfg *balancesAddCfg, io *commands.IO) // Construct the initial genesis balance sheet state := genesis.AppState.(gnoland.GnoGenesisState) - genesisBalances, err := extractGenesisBalances(state) + genesisBalances, err := mapGenesisBalancesFromState(state) if err != nil { return err } @@ -190,12 +180,11 @@ func getBalancesFromEntries(entries []string) (accountBalances, error) { balances := make(accountBalances) for _, entry := range entries { - accountBalance, err := getBalanceFromEntry(entry) - if err != nil { - return nil, fmt.Errorf("unable to extract balance data, %w", err) + var balance gnoland.Balance + if err := balance.Parse(entry); err != nil { + return nil, fmt.Errorf("unable to parse balance entry: %w", err) } - - balances[accountBalance.address] = accountBalance.amount + balances[balance.Address] = balance } return balances, nil @@ -220,12 +209,12 @@ func getBalancesFromSheet(sheet io.Reader) (accountBalances, error) { continue } - accountBalance, err := getBalanceFromEntry(entry) - if err != nil { + var balance gnoland.Balance + if err := balance.Parse(entry); err != nil { return nil, fmt.Errorf("unable to extract balance data, %w", err) } - balances[accountBalance.address] = accountBalance.amount + balances[balance.Address] = balance } if err := scanner.Err(); err != nil { @@ -243,7 +232,7 @@ func getBalancesFromSheet(sheet io.Reader) (accountBalances, error) { // and construct a balance sheet based off of this information func getBalancesFromTransactions( ctx context.Context, - io *commands.IO, + io commands.IO, reader io.Reader, ) (accountBalances, error) { balances := make(accountBalances) @@ -262,21 +251,19 @@ func getBalancesFromTransactions( if err := amino.UnmarshalJSON(line, &tx); err != nil { io.ErrPrintfln( - "invalid amino JSON encountered: %s", + "invalid amino JSON encountered: %q", string(line), ) continue } - feeAmount, err := getAmountFromEntry(tx.Fee.GasFee.String()) - if err != nil { + feeAmount := std.NewCoins(tx.Fee.GasFee) + if feeAmount.AmountOf("ugnot") <= 0 { io.ErrPrintfln( - "invalid gas fee amount encountered: %s", + "invalid gas fee amount encountered: %q", tx.Fee.GasFee.String(), ) - - continue } for _, msg := range tx.Msgs { @@ -286,13 +273,12 @@ func getBalancesFromTransactions( msgSend := msg.(bank.MsgSend) - sendAmount, err := getAmountFromEntry(msgSend.Amount.String()) - if err != nil { + sendAmount := msgSend.Amount + if sendAmount.AmountOf("ugnot") <= 0 { io.ErrPrintfln( "invalid send amount encountered: %s", msgSend.Amount.String(), ) - continue } @@ -304,27 +290,35 @@ func getBalancesFromTransactions( // causes an accounts balance to go < 0. In these cases, // we initialize the account (it is present in the balance sheet), but // with the balance of 0 - from := balances[msgSend.FromAddress] - to := balances[msgSend.ToAddress] - to += sendAmount + from := balances[msgSend.FromAddress].Amount + to := balances[msgSend.ToAddress].Amount + + to = to.Add(sendAmount) - if from < sendAmount || from < feeAmount { + if from.IsAllLT(sendAmount) || from.IsAllLT(feeAmount) { // Account cannot cover send amount / fee // (see message above) - from = 0 + from = std.NewCoins(std.NewCoin("ugnot", 0)) } - if from > sendAmount { - from -= sendAmount + if from.IsAllGT(sendAmount) { + from = from.Sub(sendAmount) } - if from > feeAmount { - from -= feeAmount + if from.IsAllGT(feeAmount) { + from = from.Sub(feeAmount) } - balances[msgSend.FromAddress] = from - balances[msgSend.ToAddress] = to + // Set new balance + balances[msgSend.FromAddress] = gnoland.Balance{ + Address: msgSend.FromAddress, + Amount: from, + } + balances[msgSend.ToAddress] = gnoland.Balance{ + Address: msgSend.ToAddress, + Amount: to, + } } } } @@ -340,65 +334,14 @@ func getBalancesFromTransactions( return balances, nil } -// getAmountFromEntry -func getAmountFromEntry(entry string) (int64, error) { - matches := amountRegex.FindStringSubmatch(entry) - - // Check if there is a match - if len(matches) != 2 { - return 0, fmt.Errorf( - "invalid amount, %s", - entry, - ) - } - - amount, err := strconv.ParseInt(matches[1], 10, 64) - if err != nil { - return 0, fmt.Errorf("invalid amount, %s", matches[1]) - } - - return amount, nil -} - -// getBalanceFromEntry extracts the account balance information -// from a single line in the form of:
=ugnot -func getBalanceFromEntry(entry string) (*accountBalance, error) { - matches := balanceRegex.FindStringSubmatch(entry) - if len(matches) != 3 { - return nil, fmt.Errorf("%w, %s", errInvalidBalanceFormat, entry) - } - - // Validate the address - address, err := crypto.AddressFromString(matches[1]) - if err != nil { - return nil, fmt.Errorf("%w, %w", errInvalidAddress, err) - } - - // Validate the amount - amount, err := strconv.ParseInt(matches[2], 10, 64) - if err != nil { - return nil, fmt.Errorf("%w, %w", errInvalidAmount, err) - } - - return &accountBalance{ - address: address, - amount: amount, - }, nil -} - -// extractGenesisBalances extracts the initial account balances from the +// mapGenesisBalancesFromState extracts the initial account balances from the // genesis app state -func extractGenesisBalances(state gnoland.GnoGenesisState) (accountBalances, error) { +func mapGenesisBalancesFromState(state gnoland.GnoGenesisState) (accountBalances, error) { // Construct the initial genesis balance sheet genesisBalances := make(accountBalances) - for _, entry := range state.Balances { - accountBalance, err := getBalanceFromEntry(entry) - if err != nil { - return nil, fmt.Errorf("invalid genesis balance entry, %w", err) - } - - genesisBalances[accountBalance.address] = accountBalance.amount + for _, balance := range state.Balances { + genesisBalances[balance.Address] = balance } return genesisBalances, nil diff --git a/gno.land/cmd/genesis/balances_add_test.go b/gno.land/cmd/genesis/balances_add_test.go index f986ee85274..73e2fe148a2 100644 --- a/gno.land/cmd/genesis/balances_add_test.go +++ b/gno.land/cmd/genesis/balances_add_test.go @@ -98,7 +98,7 @@ func TestGenesis_Balances_Add(t *testing.T) { tempGenesis.Name(), } - amount := int64(10) + amount := std.NewCoins(std.NewCoin("ugnot", 10)) for _, dummyKey := range dummyKeys { args = append(args, "--single") @@ -107,7 +107,7 @@ func TestGenesis_Balances_Add(t *testing.T) { fmt.Sprintf( "%s=%dugnot", dummyKey.Address().String(), - amount, + amount.AmountOf("ugnot"), ), ) } @@ -127,16 +127,13 @@ func TestGenesis_Balances_Add(t *testing.T) { require.Equal(t, len(dummyKeys), len(state.Balances)) - for _, entry := range state.Balances { - accountBalance, err := getBalanceFromEntry(entry) - require.NoError(t, err) - + for _, balance := range state.Balances { // Find the appropriate key // (the genesis is saved with randomized balance order) found := false for _, dummyKey := range dummyKeys { - if dummyKey.Address().String() == accountBalance.address.String() { - assert.Equal(t, amount, accountBalance.amount) + if dummyKey.Address().String() == balance.Address.String() { + assert.Equal(t, amount, balance.Amount) found = true break @@ -144,7 +141,7 @@ func TestGenesis_Balances_Add(t *testing.T) { } if !found { - t.Fatalf("unexpected entry with address %s found", accountBalance.address.String()) + t.Fatalf("unexpected entry with address %s found", balance.Address.String()) } } }) @@ -159,7 +156,7 @@ func TestGenesis_Balances_Add(t *testing.T) { require.NoError(t, genesis.SaveAs(tempGenesis.Name())) dummyKeys := getDummyKeys(t, 10) - amount := int64(10) + amount := std.NewCoins(std.NewCoin("ugnot", 10)) balances := make([]string, len(dummyKeys)) @@ -170,7 +167,7 @@ func TestGenesis_Balances_Add(t *testing.T) { balances[index] = fmt.Sprintf( "%s=%dugnot", key.Address().String(), - amount, + amount.AmountOf("ugnot"), ) } @@ -207,16 +204,13 @@ func TestGenesis_Balances_Add(t *testing.T) { require.Equal(t, len(dummyKeys), len(state.Balances)) - for _, entry := range state.Balances { - accountBalance, err := getBalanceFromEntry(entry) - require.NoError(t, err) - + for _, balance := range state.Balances { // Find the appropriate key // (the genesis is saved with randomized balance order) found := false for _, dummyKey := range dummyKeys { - if dummyKey.Address().String() == accountBalance.address.String() { - assert.Equal(t, amount, accountBalance.amount) + if dummyKey.Address().String() == balance.Address.String() { + assert.Equal(t, amount, balance.Amount) found = true break @@ -224,7 +218,7 @@ func TestGenesis_Balances_Add(t *testing.T) { } if !found { - t.Fatalf("unexpected entry with address %s found", accountBalance.address.String()) + t.Fatalf("unexpected entry with address %s found", balance.Address.String()) } } }) @@ -240,8 +234,8 @@ func TestGenesis_Balances_Add(t *testing.T) { var ( dummyKeys = getDummyKeys(t, 10) - amount = int64(10) - amountCoins = std.NewCoins(std.NewCoin("ugnot", amount)) + amount = std.NewCoins(std.NewCoin("ugnot", 10)) + amountCoins = std.NewCoins(std.NewCoin("ugnot", 10)) gasFee = std.NewCoin("ugnot", 1000000) txs = make([]std.Tx, 0) ) @@ -309,10 +303,7 @@ func TestGenesis_Balances_Add(t *testing.T) { require.Equal(t, len(dummyKeys), len(state.Balances)) - for _, entry := range state.Balances { - accountBalance, err := getBalanceFromEntry(entry) - require.NoError(t, err) - + for _, balance := range state.Balances { // Find the appropriate key // (the genesis is saved with randomized balance order) found := false @@ -321,11 +312,11 @@ func TestGenesis_Balances_Add(t *testing.T) { if index == 0 { // the first address should // have a balance of 0 - checkAmount = 0 + checkAmount = std.NewCoins(std.NewCoin("ugnot", 0)) } - if dummyKey.Address().String() == accountBalance.address.String() { - assert.Equal(t, checkAmount, accountBalance.amount) + if dummyKey.Address().String() == balance.Address.String() { + assert.True(t, balance.Amount.IsEqual(checkAmount)) found = true break @@ -333,7 +324,7 @@ func TestGenesis_Balances_Add(t *testing.T) { } if !found { - t.Fatalf("unexpected entry with address %s found", accountBalance.address.String()) + t.Fatalf("unexpected entry with address %s found", balance.Address.String()) } } }) @@ -349,12 +340,11 @@ func TestGenesis_Balances_Add(t *testing.T) { genesis := getDefaultGenesis() state := gnoland.GnoGenesisState{ // Set an initial balance value - Balances: []string{ - fmt.Sprintf( - "%s=%dugnot", - dummyKeys[0].Address().String(), - 100, - ), + Balances: []gnoland.Balance{ + { + Address: dummyKeys[0].Address(), + Amount: std.NewCoins(std.NewCoin("ugnot", 100)), + }, }, } genesis.AppState = state @@ -369,7 +359,7 @@ func TestGenesis_Balances_Add(t *testing.T) { tempGenesis.Name(), } - amount := int64(10) + amount := std.NewCoins(std.NewCoin("ugnot", 10)) for _, dummyKey := range dummyKeys { args = append(args, "--single") @@ -378,7 +368,7 @@ func TestGenesis_Balances_Add(t *testing.T) { fmt.Sprintf( "%s=%dugnot", dummyKey.Address().String(), - amount, + amount.AmountOf("ugnot"), ), ) } @@ -398,16 +388,13 @@ func TestGenesis_Balances_Add(t *testing.T) { require.Equal(t, len(dummyKeys), len(state.Balances)) - for _, entry := range state.Balances { - accountBalance, err := getBalanceFromEntry(entry) - require.NoError(t, err) - + for _, balance := range state.Balances { // Find the appropriate key // (the genesis is saved with randomized balance order) found := false for _, dummyKey := range dummyKeys { - if dummyKey.Address().String() == accountBalance.address.String() { - assert.Equal(t, amount, accountBalance.amount) + if dummyKey.Address().String() == balance.Address.String() { + assert.Equal(t, amount, balance.Amount) found = true break @@ -415,7 +402,7 @@ func TestGenesis_Balances_Add(t *testing.T) { } if !found { - t.Fatalf("unexpected entry with address %s found", accountBalance.address.String()) + t.Fatalf("unexpected entry with address %s found", balance.Address.String()) } } }) @@ -429,7 +416,7 @@ func TestBalances_GetBalancesFromEntries(t *testing.T) { // Generate dummy keys dummyKeys := getDummyKeys(t, 2) - amount := int64(10) + amount := std.NewCoins(std.NewCoin("ugnot", 10)) balances := make([]string, len(dummyKeys)) @@ -437,7 +424,7 @@ func TestBalances_GetBalancesFromEntries(t *testing.T) { balances[index] = fmt.Sprintf( "%s=%dugnot", key.Address().String(), - amount, + amount.AmountOf("ugnot"), ) } @@ -447,7 +434,7 @@ func TestBalances_GetBalancesFromEntries(t *testing.T) { // Validate the balance map assert.Len(t, balanceMap, len(dummyKeys)) for _, key := range dummyKeys { - assert.Equal(t, amount, balanceMap[key.Address()]) + assert.Equal(t, amount, balanceMap[key.Address()].Amount) } }) @@ -461,7 +448,7 @@ func TestBalances_GetBalancesFromEntries(t *testing.T) { balanceMap, err := getBalancesFromEntries(balances) assert.Nil(t, balanceMap) - assert.ErrorContains(t, err, errInvalidBalanceFormat.Error()) + assert.ErrorContains(t, err, "malformed entry") }) t.Run("malformed balance, invalid address", func(t *testing.T) { @@ -474,7 +461,7 @@ func TestBalances_GetBalancesFromEntries(t *testing.T) { balanceMap, err := getBalancesFromEntries(balances) assert.Nil(t, balanceMap) - assert.ErrorContains(t, err, errInvalidAddress.Error()) + assert.ErrorContains(t, err, "invalid address") }) t.Run("malformed balance, invalid amount", func(t *testing.T) { @@ -493,7 +480,7 @@ func TestBalances_GetBalancesFromEntries(t *testing.T) { balanceMap, err := getBalancesFromEntries(balances) assert.Nil(t, balanceMap) - assert.ErrorContains(t, err, errInvalidAmount.Error()) + assert.ErrorContains(t, err, "invalid amount") }) } @@ -505,7 +492,7 @@ func TestBalances_GetBalancesFromSheet(t *testing.T) { // Generate dummy keys dummyKeys := getDummyKeys(t, 2) - amount := int64(10) + amount := std.NewCoins(std.NewCoin("ugnot", 10)) balances := make([]string, len(dummyKeys)) @@ -513,7 +500,7 @@ func TestBalances_GetBalancesFromSheet(t *testing.T) { balances[index] = fmt.Sprintf( "%s=%dugnot", key.Address().String(), - amount, + amount.AmountOf("ugnot"), ) } @@ -524,7 +511,7 @@ func TestBalances_GetBalancesFromSheet(t *testing.T) { // Validate the balance map assert.Len(t, balanceMap, len(dummyKeys)) for _, key := range dummyKeys { - assert.Equal(t, amount, balanceMap[key.Address()]) + assert.Equal(t, amount, balanceMap[key.Address()].Amount) } }) @@ -546,7 +533,7 @@ func TestBalances_GetBalancesFromSheet(t *testing.T) { balanceMap, err := getBalancesFromSheet(reader) assert.Nil(t, balanceMap) - assert.ErrorContains(t, err, errInvalidAmount.Error()) + assert.ErrorContains(t, err, "invalid amount") }) } @@ -558,8 +545,8 @@ func TestBalances_GetBalancesFromTransactions(t *testing.T) { var ( dummyKeys = getDummyKeys(t, 10) - amount = int64(10) - amountCoins = std.NewCoins(std.NewCoin("ugnot", amount)) + amount = std.NewCoins(std.NewCoin("ugnot", 10)) + amountCoins = std.NewCoins(std.NewCoin("ugnot", 10)) gasFee = std.NewCoin("ugnot", 1000000) txs = make([]std.Tx, 0) ) @@ -605,10 +592,10 @@ func TestBalances_GetBalancesFromTransactions(t *testing.T) { // Validate the balance map assert.Len(t, balanceMap, len(dummyKeys)) for _, key := range dummyKeys[1:] { - assert.Equal(t, amount, balanceMap[key.Address()]) + assert.Equal(t, amount, balanceMap[key.Address()].Amount) } - assert.Equal(t, int64(0), balanceMap[sender.Address()]) + assert.Equal(t, std.Coins{}, balanceMap[sender.Address()].Amount) }) t.Run("malformed transaction, invalid fee amount", func(t *testing.T) { @@ -616,8 +603,7 @@ func TestBalances_GetBalancesFromTransactions(t *testing.T) { var ( dummyKeys = getDummyKeys(t, 10) - amount = int64(10) - amountCoins = std.NewCoins(std.NewCoin("ugnot", amount)) + amountCoins = std.NewCoins(std.NewCoin("ugnot", 10)) gasFee = std.NewCoin("gnos", 1) // invalid fee txs = make([]std.Tx, 0) ) @@ -669,8 +655,7 @@ func TestBalances_GetBalancesFromTransactions(t *testing.T) { var ( dummyKeys = getDummyKeys(t, 10) - amount = int64(10) - amountCoins = std.NewCoins(std.NewCoin("gnogno", amount)) // invalid send amount + amountCoins = std.NewCoins(std.NewCoin("gnogno", 10)) // invalid send amount gasFee = std.NewCoin("ugnot", 1) txs = make([]std.Tx, 0) ) diff --git a/gno.land/cmd/genesis/balances_export.go b/gno.land/cmd/genesis/balances_export.go index fd5ade26663..c07f250afeb 100644 --- a/gno.land/cmd/genesis/balances_export.go +++ b/gno.land/cmd/genesis/balances_export.go @@ -11,7 +11,7 @@ import ( ) // newBalancesExportCmd creates the genesis balances export subcommand -func newBalancesExportCmd(balancesCfg *balancesCfg, io *commands.IO) *commands.Command { +func newBalancesExportCmd(balancesCfg *balancesCfg, io commands.IO) *commands.Command { return commands.NewCommand( commands.Metadata{ Name: "export", @@ -26,7 +26,7 @@ func newBalancesExportCmd(balancesCfg *balancesCfg, io *commands.IO) *commands.C ) } -func execBalancesExport(cfg *balancesCfg, io *commands.IO, args []string) error { +func execBalancesExport(cfg *balancesCfg, io commands.IO, args []string) error { // Load the genesis genesis, loadErr := types.GenesisDocFromFile(cfg.genesisPath) if loadErr != nil { diff --git a/gno.land/cmd/genesis/balances_export_test.go b/gno.land/cmd/genesis/balances_export_test.go index 33e4f7bc800..d7441fd438f 100644 --- a/gno.land/cmd/genesis/balances_export_test.go +++ b/gno.land/cmd/genesis/balances_export_test.go @@ -3,31 +3,30 @@ package main import ( "bufio" "context" - "fmt" "testing" "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/testutils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -// getDummyBalanceLines generates dummy balance lines -func getDummyBalanceLines(t *testing.T, count int) []string { +// getDummyBalances generates dummy balance lines +func getDummyBalances(t *testing.T, count int) []gnoland.Balance { t.Helper() dummyKeys := getDummyKeys(t, count) - amount := int64(10) + amount := std.NewCoins(std.NewCoin("ugnot", 10)) - balances := make([]string, len(dummyKeys)) + balances := make([]gnoland.Balance, len(dummyKeys)) for index, key := range dummyKeys { - balances[index] = fmt.Sprintf( - "%s=%dugnot", - key.Address().String(), - amount, - ) + balances[index] = gnoland.Balance{ + Address: key.Address(), + Amount: amount, + } } return balances @@ -85,7 +84,7 @@ func TestGenesis_Balances_Export(t *testing.T) { genesis := getDefaultGenesis() genesis.AppState = gnoland.GnoGenesisState{ - Balances: getDummyBalanceLines(t, 1), + Balances: getDummyBalances(t, 1), } require.NoError(t, genesis.SaveAs(tempGenesis.Name())) @@ -107,7 +106,7 @@ func TestGenesis_Balances_Export(t *testing.T) { t.Parallel() // Generate dummy balances - balances := getDummyBalanceLines(t, 10) + balances := getDummyBalances(t, 10) tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) @@ -139,9 +138,13 @@ func TestGenesis_Balances_Export(t *testing.T) { // Validate the transactions were written down scanner := bufio.NewScanner(outputFile) - outputBalances := make([]string, 0) + outputBalances := make([]gnoland.Balance, 0) for scanner.Scan() { - outputBalances = append(outputBalances, scanner.Text()) + var balance gnoland.Balance + err := balance.Parse(scanner.Text()) + require.NoError(t, err) + + outputBalances = append(outputBalances, balance) } require.NoError(t, scanner.Err()) diff --git a/gno.land/cmd/genesis/balances_remove.go b/gno.land/cmd/genesis/balances_remove.go index f7e9092dc3b..a752bbda4fd 100644 --- a/gno.land/cmd/genesis/balances_remove.go +++ b/gno.land/cmd/genesis/balances_remove.go @@ -24,7 +24,7 @@ type balancesRemoveCfg struct { } // newBalancesRemoveCmd creates the genesis balances remove subcommand -func newBalancesRemoveCmd(rootCfg *balancesCfg, io *commands.IO) *commands.Command { +func newBalancesRemoveCmd(rootCfg *balancesCfg, io commands.IO) *commands.Command { cfg := &balancesRemoveCfg{ rootCfg: rootCfg, } @@ -51,7 +51,7 @@ func (c *balancesRemoveCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execBalancesRemove(cfg *balancesRemoveCfg, io *commands.IO) error { +func execBalancesRemove(cfg *balancesRemoveCfg, io commands.IO) error { // Load the genesis genesis, loadErr := types.GenesisDocFromFile(cfg.rootCfg.genesisPath) if loadErr != nil { @@ -71,7 +71,7 @@ func execBalancesRemove(cfg *balancesRemoveCfg, io *commands.IO) error { // Construct the initial genesis balance sheet state := genesis.AppState.(gnoland.GnoGenesisState) - genesisBalances, err := extractGenesisBalances(state) + genesisBalances, err := mapGenesisBalancesFromState(state) if err != nil { return err } diff --git a/gno.land/cmd/genesis/balances_remove_test.go b/gno.land/cmd/genesis/balances_remove_test.go index 29179c43604..b9d10d0db08 100644 --- a/gno.land/cmd/genesis/balances_remove_test.go +++ b/gno.land/cmd/genesis/balances_remove_test.go @@ -2,12 +2,12 @@ package main import ( "context" - "fmt" "testing" "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/testutils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -70,12 +70,11 @@ func TestGenesis_Balances_Remove(t *testing.T) { genesis := getDefaultGenesis() state := gnoland.GnoGenesisState{ // Set an initial balance value - Balances: []string{ - fmt.Sprintf( - "%s=%dugnot", - dummyKey.Address().String(), - 100, - ), + Balances: []gnoland.Balance{ + { + Address: dummyKey.Address(), + Amount: std.NewCoins(std.NewCoin("ugnot", 100)), + }, }, } genesis.AppState = state @@ -118,7 +117,7 @@ func TestGenesis_Balances_Remove(t *testing.T) { genesis := getDefaultGenesis() state := gnoland.GnoGenesisState{ - Balances: []string{}, // Empty initial balance + Balances: []gnoland.Balance{}, // Empty initial balance } genesis.AppState = state require.NoError(t, genesis.SaveAs(tempGenesis.Name())) diff --git a/gno.land/cmd/genesis/generate.go b/gno.land/cmd/genesis/generate.go index 93f8553f9e7..684f8441874 100644 --- a/gno.land/cmd/genesis/generate.go +++ b/gno.land/cmd/genesis/generate.go @@ -23,7 +23,7 @@ type generateCfg struct { } // newGenerateCmd creates the genesis generate subcommand -func newGenerateCmd(io *commands.IO) *commands.Command { +func newGenerateCmd(io commands.IO) *commands.Command { cfg := &generateCfg{} return commands.NewCommand( @@ -91,7 +91,7 @@ func (c *generateCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execGenerate(cfg *generateCfg, io *commands.IO) error { +func execGenerate(cfg *generateCfg, io commands.IO) error { // Start with the default configuration genesis := getDefaultGenesis() diff --git a/gno.land/cmd/genesis/main.go b/gno.land/cmd/genesis/main.go index c0b043b456a..507d004e8ed 100644 --- a/gno.land/cmd/genesis/main.go +++ b/gno.land/cmd/genesis/main.go @@ -20,7 +20,7 @@ func main() { } } -func newRootCmd(io *commands.IO) *commands.Command { +func newRootCmd(io commands.IO) *commands.Command { cmd := commands.NewCommand( commands.Metadata{ ShortUsage: " [flags] [...]", diff --git a/gno.land/cmd/genesis/txs.go b/gno.land/cmd/genesis/txs.go index a7be307c4be..a292a9c01de 100644 --- a/gno.land/cmd/genesis/txs.go +++ b/gno.land/cmd/genesis/txs.go @@ -11,7 +11,7 @@ type txsCfg struct { } // newTxsCmd creates the genesis txs subcommand -func newTxsCmd(io *commands.IO) *commands.Command { +func newTxsCmd(io commands.IO) *commands.Command { cfg := &txsCfg{} cmd := commands.NewCommand( diff --git a/gno.land/cmd/genesis/txs_add.go b/gno.land/cmd/genesis/txs_add.go index 027cedae0bd..e356badc4aa 100644 --- a/gno.land/cmd/genesis/txs_add.go +++ b/gno.land/cmd/genesis/txs_add.go @@ -22,7 +22,7 @@ var ( ) // newTxsAddCmd creates the genesis txs add subcommand -func newTxsAddCmd(txsCfg *txsCfg, io *commands.IO) *commands.Command { +func newTxsAddCmd(txsCfg *txsCfg, io commands.IO) *commands.Command { return commands.NewCommand( commands.Metadata{ Name: "add", @@ -40,7 +40,7 @@ func newTxsAddCmd(txsCfg *txsCfg, io *commands.IO) *commands.Command { func execTxsAdd( ctx context.Context, cfg *txsCfg, - io *commands.IO, + io commands.IO, args []string, ) error { // Load the genesis diff --git a/gno.land/cmd/genesis/txs_export.go b/gno.land/cmd/genesis/txs_export.go index 170166e8a37..b06660d87d4 100644 --- a/gno.land/cmd/genesis/txs_export.go +++ b/gno.land/cmd/genesis/txs_export.go @@ -15,7 +15,7 @@ import ( var errNoOutputFile = errors.New("no output file path specified") // newTxsExportCmd creates the genesis txs export subcommand -func newTxsExportCmd(txsCfg *txsCfg, io *commands.IO) *commands.Command { +func newTxsExportCmd(txsCfg *txsCfg, io commands.IO) *commands.Command { return commands.NewCommand( commands.Metadata{ Name: "export", @@ -30,7 +30,7 @@ func newTxsExportCmd(txsCfg *txsCfg, io *commands.IO) *commands.Command { ) } -func execTxsExport(cfg *txsCfg, io *commands.IO, args []string) error { +func execTxsExport(cfg *txsCfg, io commands.IO, args []string) error { // Load the genesis genesis, loadErr := types.GenesisDocFromFile(cfg.genesisPath) if loadErr != nil { diff --git a/gno.land/cmd/genesis/txs_remove.go b/gno.land/cmd/genesis/txs_remove.go index 2aef44fe1e5..7893ad50cac 100644 --- a/gno.land/cmd/genesis/txs_remove.go +++ b/gno.land/cmd/genesis/txs_remove.go @@ -20,7 +20,7 @@ var ( ) // newTxsRemoveCmd creates the genesis txs remove subcommand -func newTxsRemoveCmd(txsCfg *txsCfg, io *commands.IO) *commands.Command { +func newTxsRemoveCmd(txsCfg *txsCfg, io commands.IO) *commands.Command { return commands.NewCommand( commands.Metadata{ Name: "remove", @@ -35,7 +35,7 @@ func newTxsRemoveCmd(txsCfg *txsCfg, io *commands.IO) *commands.Command { ) } -func execTxsRemove(cfg *txsCfg, io *commands.IO, args []string) error { +func execTxsRemove(cfg *txsCfg, io commands.IO, args []string) error { // Load the genesis genesis, loadErr := types.GenesisDocFromFile(cfg.genesisPath) if loadErr != nil { diff --git a/gno.land/cmd/genesis/types.go b/gno.land/cmd/genesis/types.go index 208eaddb6da..dba39ea8ec1 100644 --- a/gno.land/cmd/genesis/types.go +++ b/gno.land/cmd/genesis/types.go @@ -1,8 +1,7 @@ package main import ( - "fmt" - + "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/std" ) @@ -39,23 +38,14 @@ func (i *txStore) leftMerge(b txStore) error { return nil } -type ( - accountBalances map[types.Address]int64 // address -> balance (ugnot) - accountBalance struct { - address types.Address - amount int64 - } -) +type accountBalances map[types.Address]gnoland.Balance // address -> balance (ugnot) // toList linearizes the account balances map -func (a accountBalances) toList() []string { - balances := make([]string, 0, len(a)) +func (a accountBalances) toList() []gnoland.Balance { + balances := make([]gnoland.Balance, 0, len(a)) - for address, balance := range a { - balances = append( - balances, - fmt.Sprintf("%s=%dugnot", address, balance), - ) + for _, balance := range a { + balances = append(balances, balance) } return balances diff --git a/gno.land/cmd/genesis/validator.go b/gno.land/cmd/genesis/validator.go index a1fee07d070..bf858a7732e 100644 --- a/gno.land/cmd/genesis/validator.go +++ b/gno.land/cmd/genesis/validator.go @@ -13,7 +13,7 @@ type validatorCfg struct { } // newValidatorCmd creates the genesis validator subcommand -func newValidatorCmd(io *commands.IO) *commands.Command { +func newValidatorCmd(io commands.IO) *commands.Command { cfg := &validatorCfg{ commonCfg: commonCfg{}, } diff --git a/gno.land/cmd/genesis/validator_add.go b/gno.land/cmd/genesis/validator_add.go index 603bfa90caa..502b572effb 100644 --- a/gno.land/cmd/genesis/validator_add.go +++ b/gno.land/cmd/genesis/validator_add.go @@ -28,7 +28,7 @@ type validatorAddCfg struct { } // newValidatorAddCmd creates the genesis validator add subcommand -func newValidatorAddCmd(validatorCfg *validatorCfg, io *commands.IO) *commands.Command { +func newValidatorAddCmd(validatorCfg *validatorCfg, io commands.IO) *commands.Command { cfg := &validatorAddCfg{ rootCfg: validatorCfg, } @@ -69,7 +69,7 @@ func (c *validatorAddCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execValidatorAdd(cfg *validatorAddCfg, io *commands.IO) error { +func execValidatorAdd(cfg *validatorAddCfg, io commands.IO) error { // Load the genesis genesis, loadErr := types.GenesisDocFromFile(cfg.rootCfg.genesisPath) if loadErr != nil { diff --git a/gno.land/cmd/genesis/validator_remove.go b/gno.land/cmd/genesis/validator_remove.go index f769b53b0e1..960d891239b 100644 --- a/gno.land/cmd/genesis/validator_remove.go +++ b/gno.land/cmd/genesis/validator_remove.go @@ -13,7 +13,7 @@ import ( var errValidatorNotPresent = errors.New("validator not present in genesis.json") // newValidatorRemoveCmd creates the genesis validator remove subcommand -func newValidatorRemoveCmd(rootCfg *validatorCfg, io *commands.IO) *commands.Command { +func newValidatorRemoveCmd(rootCfg *validatorCfg, io commands.IO) *commands.Command { return commands.NewCommand( commands.Metadata{ Name: "remove", @@ -27,7 +27,7 @@ func newValidatorRemoveCmd(rootCfg *validatorCfg, io *commands.IO) *commands.Com ) } -func execValidatorRemove(cfg *validatorCfg, io *commands.IO) error { +func execValidatorRemove(cfg *validatorCfg, io commands.IO) error { // Load the genesis genesis, loadErr := types.GenesisDocFromFile(cfg.genesisPath) if loadErr != nil { diff --git a/gno.land/cmd/genesis/verify.go b/gno.land/cmd/genesis/verify.go index ba51f5801f6..260a9eb734d 100644 --- a/gno.land/cmd/genesis/verify.go +++ b/gno.land/cmd/genesis/verify.go @@ -9,7 +9,6 @@ import ( "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" - "github.com/gnolang/gno/tm2/pkg/std" ) var errInvalidGenesisState = errors.New("invalid genesis state type") @@ -19,7 +18,7 @@ type verifyCfg struct { } // newVerifyCmd creates the genesis verify subcommand -func newVerifyCmd(io *commands.IO) *commands.Command { +func newVerifyCmd(io commands.IO) *commands.Command { cfg := &verifyCfg{} return commands.NewCommand( @@ -40,7 +39,7 @@ func (c *verifyCfg) RegisterFlags(fs *flag.FlagSet) { c.commonCfg.RegisterFlags(fs) } -func execVerify(cfg *verifyCfg, io *commands.IO) error { +func execVerify(cfg *verifyCfg, io commands.IO) error { // Load the genesis genesis, loadErr := types.GenesisDocFromFile(cfg.genesisPath) if loadErr != nil { @@ -68,8 +67,8 @@ func execVerify(cfg *verifyCfg, io *commands.IO) error { // Validate the initial balances for _, balance := range state.Balances { - if _, parseErr := std.ParseCoins(balance); parseErr != nil { - return fmt.Errorf("invalid balance %s, %w", balance, parseErr) + if err := balance.Verify(); err != nil { + return fmt.Errorf("invalid balance: %w", err) } } } diff --git a/gno.land/cmd/genesis/verify_test.go b/gno.land/cmd/genesis/verify_test.go index fcc5305b9d0..8388949898b 100644 --- a/gno.land/cmd/genesis/verify_test.go +++ b/gno.land/cmd/genesis/verify_test.go @@ -44,7 +44,7 @@ func TestGenesis_Verify(t *testing.T) { g := getValidTestGenesis() g.AppState = gnoland.GnoGenesisState{ - Balances: []string{}, + Balances: []gnoland.Balance{}, Txs: []std.Tx{ {}, }, @@ -74,8 +74,8 @@ func TestGenesis_Verify(t *testing.T) { g := getValidTestGenesis() g.AppState = gnoland.GnoGenesisState{ - Balances: []string{ - "dummybalance", + Balances: []gnoland.Balance{ + {}, }, Txs: []std.Tx{}, } @@ -103,7 +103,7 @@ func TestGenesis_Verify(t *testing.T) { g := getValidTestGenesis() g.AppState = gnoland.GnoGenesisState{ - Balances: []string{}, + Balances: []gnoland.Balance{}, Txs: []std.Tx{}, } diff --git a/gno.land/cmd/gnofaucet/serve.go b/gno.land/cmd/gnofaucet/serve.go index 3fe0966592c..e00406a6e80 100644 --- a/gno.land/cmd/gnofaucet/serve.go +++ b/gno.land/cmd/gnofaucet/serve.go @@ -152,7 +152,7 @@ func (c *config) RegisterFlags(fs *flag.FlagSet) { ) } -func execServe(cfg *config, args []string, io *commands.IO) error { +func execServe(cfg *config, args []string, io commands.IO) error { if len(args) != 1 { return flag.ErrHelp } @@ -345,7 +345,7 @@ func execServe(cfg *config, args []string, io *commands.IO) error { func sendAmountTo( cfg *config, cli rpcclient.Client, - io *commands.IO, + io commands.IO, name, pass string, toAddr crypto.Address, diff --git a/gno.land/cmd/gnoland/integration_test.go b/gno.land/cmd/gnoland/integration_test.go index 78c8e94fa09..37451df9704 100644 --- a/gno.land/cmd/gnoland/integration_test.go +++ b/gno.land/cmd/gnoland/integration_test.go @@ -4,9 +4,8 @@ import ( "testing" "github.com/gnolang/gno/gno.land/pkg/integration" - "github.com/rogpeppe/go-internal/testscript" ) func TestTestdata(t *testing.T) { - testscript.Run(t, integration.SetupGnolandTestScript(t, "testdata")) + integration.RunGnolandTestscripts(t, "testdata") } diff --git a/gno.land/cmd/gnoland/root.go b/gno.land/cmd/gnoland/root.go index cf2a6252478..dfb595347c0 100644 --- a/gno.land/cmd/gnoland/root.go +++ b/gno.land/cmd/gnoland/root.go @@ -11,8 +11,7 @@ import ( ) func main() { - io := commands.NewDefaultIO() - cmd := newRootCmd(io) + cmd := newRootCmd(commands.NewDefaultIO()) if err := cmd.ParseAndRun(context.Background(), os.Args[1:]); err != nil { _, _ = fmt.Fprintf(os.Stderr, "%+v\n", err) @@ -20,7 +19,7 @@ func main() { } } -func newRootCmd(io *commands.IO) *commands.Command { +func newRootCmd(io commands.IO) *commands.Command { cmd := commands.NewCommand( commands.Metadata{ ShortUsage: " [flags] [...]", diff --git a/gno.land/cmd/gnoland/start.go b/gno.land/cmd/gnoland/start.go index a42e1df1bf0..77d6eb4ed51 100644 --- a/gno.land/cmd/gnoland/start.go +++ b/gno.land/cmd/gnoland/start.go @@ -1,21 +1,15 @@ package main import ( - "bufio" "context" "errors" "flag" "fmt" - "os" "path/filepath" "strings" "time" "github.com/gnolang/gno/gno.land/pkg/gnoland" - vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm" - gno "github.com/gnolang/gno/gnovm/pkg/gnolang" - "github.com/gnolang/gno/gnovm/pkg/gnomod" - "github.com/gnolang/gno/tm2/pkg/amino" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" "github.com/gnolang/gno/tm2/pkg/bft/config" "github.com/gnolang/gno/tm2/pkg/bft/node" @@ -32,13 +26,14 @@ import ( ) type startCfg struct { + gnoRootDir string skipFailingGenesisTxs bool skipStart bool genesisBalancesFile string genesisTxsFile string chainID string genesisRemote string - rootDir string + dataDir string genesisMaxVMCycles int64 config string @@ -47,7 +42,7 @@ type startCfg struct { nodeConfigPath string } -func newStartCmd(io *commands.IO) *commands.Command { +func newStartCmd(io commands.IO) *commands.Command { cfg := &startCfg{} return commands.NewCommand( @@ -64,6 +59,10 @@ func newStartCmd(io *commands.IO) *commands.Command { } func (c *startCfg) RegisterFlags(fs *flag.FlagSet) { + gnoroot := gnoland.MustGuessGnoRootDir() + defaultGenesisBalancesFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_balances.txt") + defaultGenesisTxsFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_txs.txt") + fs.BoolVar( &c.skipFailingGenesisTxs, "skip-failing-genesis-txs", @@ -81,14 +80,14 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) { fs.StringVar( &c.genesisBalancesFile, "genesis-balances-file", - "./genesis/genesis_balances.txt", + defaultGenesisBalancesFile, "initial distribution file", ) fs.StringVar( &c.genesisTxsFile, "genesis-txs-file", - "./genesis/genesis_txs.txt", + defaultGenesisTxsFile, "initial txs to replay", ) @@ -100,8 +99,16 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) { ) fs.StringVar( - &c.rootDir, - "root-dir", + &c.gnoRootDir, + "gnoroot-dir", + gnoroot, + "the root directory of the gno repository", + ) + + // XXX: Use home directory for this + fs.StringVar( + &c.dataDir, + "data-dir", "testdir", "directory for config and data", ) @@ -156,11 +163,19 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) { "", fmt.Sprintf("path for the file tx event store (required if event store is '%s')", file.EventStoreType), ) + + // XXX(deprecated): use data-dir instead + fs.StringVar( + &c.dataDir, + "root-dir", + "testdir", + "deprecated: use data-dir instead - directory for config and data", + ) } -func execStart(c *startCfg, io *commands.IO) error { - logger := log.NewTMLogger(log.NewSyncWriter(io.Out)) - rootDir := c.rootDir +func execStart(c *startCfg, io commands.IO) error { + logger := log.NewTMLogger(log.NewSyncWriter(io.Out())) + dataDir := c.dataDir var ( cfg *config.Config @@ -174,39 +189,28 @@ func execStart(c *startCfg, io *commands.IO) error { cfg, loadCfgErr = config.LoadConfigFile(c.nodeConfigPath) } else { // Load the default node configuration - cfg, loadCfgErr = config.LoadOrMakeConfigWithOptions(rootDir, nil) + cfg, loadCfgErr = config.LoadOrMakeConfigWithOptions(dataDir, nil) } if loadCfgErr != nil { return fmt.Errorf("unable to load node configuration, %w", loadCfgErr) } - // create priv validator first. - // need it to generate genesis.json - newPrivValKey := cfg.PrivValidatorKeyFile() - newPrivValState := cfg.PrivValidatorStateFile() - priv := privval.LoadOrGenFilePV(newPrivValKey, newPrivValState) - - // write genesis file if missing. - genesisFilePath := filepath.Join(rootDir, cfg.Genesis) - - genesisTxs, genesisTxsErr := loadGenesisTxs(c.genesisTxsFile, c.chainID, c.genesisRemote) - if genesisTxsErr != nil { - return fmt.Errorf("unable to load genesis txs, %w", genesisTxsErr) - } + // Write genesis file if missing. + genesisFilePath := filepath.Join(dataDir, cfg.Genesis) if !osm.FileExists(genesisFilePath) { - genDoc, err := makeGenesisDoc( - priv.GetPubKey(), - c.chainID, - c.genesisBalancesFile, - genesisTxs, - ) - if err != nil { - return fmt.Errorf("unable to generate genesis.json, %w", err) + // Create priv validator first. + // Need it to generate genesis.json + newPrivValKey := cfg.PrivValidatorKeyFile() + newPrivValState := cfg.PrivValidatorStateFile() + priv := privval.LoadOrGenFilePV(newPrivValKey, newPrivValState) + pk := priv.GetPubKey() + + // Generate genesis.json file + if err := generateGenesisFile(genesisFilePath, pk, c); err != nil { + return fmt.Errorf("unable to generate genesis file: %w", err) } - - writeGenesisFile(genDoc, genesisFilePath) } // Initialize the indexer config @@ -214,15 +218,13 @@ func execStart(c *startCfg, io *commands.IO) error { if err != nil { return fmt.Errorf("unable to parse indexer config, %w", err) } - cfg.TxEventStore = txEventStoreCfg - // create application and node. - gnoApp, err := gnoland.NewApp(rootDir, c.skipFailingGenesisTxs, logger, c.genesisMaxVMCycles) + // Create application and node. + gnoApp, err := gnoland.NewApp(dataDir, c.skipFailingGenesisTxs, logger, c.genesisMaxVMCycles) if err != nil { return fmt.Errorf("error in creating new app: %w", err) } - cfg.LocalApp = gnoApp gnoNode, err := node.DefaultNewNode(cfg, logger) @@ -230,11 +232,10 @@ func execStart(c *startCfg, io *commands.IO) error { return fmt.Errorf("error in creating node: %w", err) } - fmt.Fprintln(io.Err, "Node created.") + fmt.Fprintln(io.Err(), "Node created.") if c.skipStart { - fmt.Fprintln(io.Err, "'--skip-start' is set. Exiting.") - + io.ErrPrintln("'--skip-start' is set. Exiting.") return nil } @@ -242,215 +243,96 @@ func execStart(c *startCfg, io *commands.IO) error { return fmt.Errorf("error in start node: %w", err) } - // run forever osm.TrapSignal(func() { if gnoNode.IsRunning() { _ = gnoNode.Stop() } }) - select {} // run forever + // Run forever + select {} } -// getTxEventStoreConfig constructs an event store config from provided user options -func getTxEventStoreConfig(c *startCfg) (*eventstorecfg.Config, error) { - var cfg *eventstorecfg.Config - - switch c.txEventStoreType { - case file.EventStoreType: - if c.txEventStorePath == "" { - return nil, errors.New("unspecified file transaction indexer path") - } - - // Fill out the configuration - cfg = &eventstorecfg.Config{ - EventStoreType: file.EventStoreType, - Params: map[string]any{ - file.Path: c.txEventStorePath, - }, - } - default: - cfg = eventstorecfg.DefaultEventStoreConfig() - } - - return cfg, nil -} - -// Makes a local test genesis doc with local privValidator. -func makeGenesisDoc( - pvPub crypto.PubKey, - chainID string, - genesisBalancesFile string, - genesisTxs []std.Tx, -) (*bft.GenesisDoc, error) { +func generateGenesisFile(genesisFile string, pk crypto.PubKey, c *startCfg) error { gen := &bft.GenesisDoc{} - gen.GenesisTime = time.Now() - gen.ChainID = chainID + gen.ChainID = c.chainID gen.ConsensusParams = abci.ConsensusParams{ Block: &abci.BlockParams{ // TODO: update limits. - MaxTxBytes: 1000000, // 1MB, - MaxDataBytes: 2000000, // 2MB, - MaxGas: 10000000, // 10M gas - TimeIotaMS: 100, // 100ms + MaxTxBytes: 1_000_000, // 1MB, + MaxDataBytes: 2_000_000, // 2MB, + MaxGas: 10_0000_00, // 10M gas + TimeIotaMS: 100, // 100ms }, } + gen.Validators = []bft.GenesisValidator{ { - Address: pvPub.Address(), - PubKey: pvPub, + Address: pk.Address(), + PubKey: pk, Power: 10, Name: "testvalidator", }, } - // Load distribution. - balances, err := loadGenesisBalances(genesisBalancesFile) + // Load balances files + balances, err := gnoland.LoadGenesisBalancesFile(c.genesisBalancesFile) if err != nil { - return nil, fmt.Errorf("unable to load genesis balances, %w", err) + return fmt.Errorf("unable to load genesis balances file %q: %w", c.genesisBalancesFile, err) } - // Load initial packages from examples. + // Load examples folder + examplesDir := filepath.Join(c.gnoRootDir, "examples") test1 := crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") - txs := []std.Tx{} - - // List initial packages to load from examples. - pkgs, err := gnomod.ListPkgs(filepath.Join("..", "examples")) + defaultFee := std.NewFee(50000, std.MustParseCoin("1000000ugnot")) + pkgsTxs, err := gnoland.LoadPackagesFromDir(examplesDir, test1, defaultFee, nil) if err != nil { - panic(fmt.Errorf("listing gno packages: %w", err)) + return fmt.Errorf("unable to load examples folder: %w", err) } - // Sort packages by dependencies. - sortedPkgs, err := pkgs.Sort() + // Load Genesis TXs + genesisTxs, err := gnoland.LoadGenesisTxsFile(c.genesisTxsFile, c.chainID, c.genesisRemote) if err != nil { - panic(fmt.Errorf("sorting packages: %w", err)) + return fmt.Errorf("unable to load genesis txs file: %w", err) } - // Filter out draft packages. - nonDraftPkgs := sortedPkgs.GetNonDraftPkgs() - - for _, pkg := range nonDraftPkgs { - // open files in directory as MemPackage. - memPkg := gno.ReadMemPackage(pkg.Dir, pkg.Name) - - var tx std.Tx - tx.Msgs = []std.Msg{ - vmm.MsgAddPackage{ - Creator: test1, - Package: memPkg, - Deposit: nil, - }, - } - tx.Fee = std.NewFee(50000, std.MustParseCoin("1000000ugnot")) - tx.Signatures = make([]std.Signature, len(tx.GetSigners())) - txs = append(txs, tx) - } + genesisTxs = append(pkgsTxs, genesisTxs...) - // load genesis txs from file. - txs = append(txs, genesisTxs...) - - // construct genesis AppState. + // Construct genesis AppState. gen.AppState = gnoland.GnoGenesisState{ Balances: balances, - Txs: txs, - } - return gen, nil -} - -func writeGenesisFile(gen *bft.GenesisDoc, filePath string) { - err := gen.SaveAs(filePath) - if err != nil { - panic(err) - } -} - -func loadGenesisTxs( - path string, - chainID string, - genesisRemote string, -) ([]std.Tx, error) { - txs := make([]std.Tx, 0) - - if !osm.FileExists(path) { - // No initial transactions - return txs, nil - } - - txsFile, openErr := os.Open(path) - if openErr != nil { - return nil, fmt.Errorf("unable to open genesis txs file, %w", openErr) - } - - scanner := bufio.NewScanner(txsFile) - - for scanner.Scan() { - txLine := scanner.Text() - - if txLine == "" { - continue // skip empty line - } - - // patch the TX - txLine = strings.ReplaceAll(txLine, "%%CHAINID%%", chainID) - txLine = strings.ReplaceAll(txLine, "%%REMOTE%%", genesisRemote) - - var tx std.Tx - - if unmarshalErr := amino.UnmarshalJSON([]byte(txLine), &tx); unmarshalErr != nil { - return nil, fmt.Errorf("unable to amino unmarshal tx, %w", unmarshalErr) - } - - txs = append(txs, tx) + Txs: genesisTxs, } - if scanErr := scanner.Err(); scanErr != nil { - return nil, fmt.Errorf("error encountered while scanning, %w", scanErr) + // Write genesis state + if err := gen.SaveAs(genesisFile); err != nil { + return fmt.Errorf("unable to write genesis file %q: %w", genesisFile, err) } - return txs, nil + return nil } -func loadGenesisBalances(path string) ([]string, error) { - // each balance is in the form: g1xxxxxxxxxxxxxxxx=100000ugnot - balances := make([]string, 0) - - if !osm.FileExists(path) { - // No initial balances - return balances, nil - } - - balancesFile, openErr := os.Open(path) - if openErr != nil { - return nil, fmt.Errorf("unable to open genesis balances file, %w", openErr) - } - - scanner := bufio.NewScanner(balancesFile) - - for scanner.Scan() { - line := scanner.Text() - - line = strings.TrimSpace(line) - - // remove comments. - line = strings.Split(line, "#")[0] - line = strings.TrimSpace(line) +// getTxEventStoreConfig constructs an event store config from provided user options +func getTxEventStoreConfig(c *startCfg) (*eventstorecfg.Config, error) { + var cfg *eventstorecfg.Config - // skip empty lines. - if line == "" { - continue + switch c.txEventStoreType { + case file.EventStoreType: + if c.txEventStorePath == "" { + return nil, errors.New("unspecified file transaction indexer path") } - if len(strings.Split(line, "=")) != 2 { - return nil, fmt.Errorf("invalid genesis_balance line: %s", line) + // Fill out the configuration + cfg = &eventstorecfg.Config{ + EventStoreType: file.EventStoreType, + Params: map[string]any{ + file.Path: c.txEventStorePath, + }, } - - balances = append(balances, line) - } - - if scanErr := scanner.Err(); scanErr != nil { - return nil, fmt.Errorf("error encountered while scanning, %w", scanErr) + default: + cfg = eventstorecfg.DefaultEventStoreConfig() } - return balances, nil + return cfg, nil } diff --git a/gno.land/cmd/gnoland/start_test.go b/gno.land/cmd/gnoland/start_test.go index 27ef2f572ea..6606d88ba2e 100644 --- a/gno.land/cmd/gnoland/start_test.go +++ b/gno.land/cmd/gnoland/start_test.go @@ -13,6 +13,8 @@ import ( ) func TestStartInitialize(t *testing.T) { + t.Parallel() + cases := []struct { args []string }{ @@ -23,8 +25,11 @@ func TestStartInitialize(t *testing.T) { os.Chdir(filepath.Join("..", "..")) // go to repo's root dir for _, tc := range cases { + tc := tc name := strings.Join(tc.args, " ") t.Run(name, func(t *testing.T) { + t.Parallel() + mockOut := bytes.NewBufferString("") mockErr := bytes.NewBufferString("") io := commands.NewTestIO() diff --git a/gno.land/cmd/gnoland/testdata/addpkg.txtar b/gno.land/cmd/gnoland/testdata/addpkg.txtar index 5e871b058ac..5f1ee0caf49 100644 --- a/gno.land/cmd/gnoland/testdata/addpkg.txtar +++ b/gno.land/cmd/gnoland/testdata/addpkg.txtar @@ -10,7 +10,11 @@ gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/foobar/bar -gas-fee 10000 gnokey maketx call -pkgpath gno.land/r/foobar/bar -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -args '' -broadcast -chainid=tendermint_test test1 ## compare render -cmp stdout stdout.golden +stdout '("hello from foo" string)' +stdout 'OK!' +stdout 'GAS WANTED: 2000000' +stdout 'GAS USED: [0-9]+' + -- bar.gno -- package bar @@ -19,8 +23,3 @@ func Render(path string) string { return "hello from foo" } --- stdout.golden -- -("hello from foo" string) -OK! -GAS WANTED: 2000000 -GAS USED: 69163 \ No newline at end of file diff --git a/gno.land/cmd/gnoland/testdata/import.txtar b/gno.land/cmd/gnoland/testdata/import.txtar new file mode 100644 index 00000000000..3ad070654cf --- /dev/null +++ b/gno.land/cmd/gnoland/testdata/import.txtar @@ -0,0 +1,27 @@ +# test that the example packages directory is loaded and usable. + +## start a new node +gnoland start + +gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/importtest -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +stdout OK! + +## execute Render +gnokey maketx call -pkgpath gno.land/r/importtest -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -args '' -broadcast -chainid=tendermint_test test1 +stdout '("92054" string)' +stdout OK! + +-- gno.mod -- +module gno.land/r/importtest + +-- import.gno -- +package importtest + +import ( + "gno.land/p/demo/ufmt" +) + +func Render(_ string) string { + return ufmt.Sprintf("%d", 92054) +} + diff --git a/gno.land/cmd/gnoweb/main.go b/gno.land/cmd/gnoweb/main.go index 0d9398cb8e2..b080e0b403d 100644 --- a/gno.land/cmd/gnoweb/main.go +++ b/gno.land/cmd/gnoweb/main.go @@ -486,11 +486,11 @@ func writeError(w http.ResponseWriter, err error) { // XXX: writeError should return an error page template. w.WriteHeader(500) - details := errors.Unwrap(err).Error() - main := err.Error() + fmt.Println("main", err.Error()) - fmt.Println("main", main) - fmt.Println("details", details) + if details := errors.Unwrap(err); details != nil { + fmt.Println("details", details.Error()) + } w.Write([]byte(err.Error())) } diff --git a/gno.land/cmd/gnoweb/main_test.go b/gno.land/cmd/gnoweb/main_test.go index 974d3f987b7..61650563405 100644 --- a/gno.land/cmd/gnoweb/main_test.go +++ b/gno.land/cmd/gnoweb/main_test.go @@ -4,10 +4,12 @@ import ( "fmt" "net/http" "net/http/httptest" - "os" "strings" "testing" + "github.com/gnolang/gno/gno.land/pkg/gnoland" + "github.com/gnolang/gno/gno.land/pkg/integration" + "github.com/gnolang/gno/tm2/pkg/log" "github.com/gotuna/gotuna/test/assert" ) @@ -41,20 +43,17 @@ func TestRoutes(t *testing.T) { {"/blog", found, "/r/gnoland/blog"}, {"/404-not-found", notFound, "/404-not-found"}, } - if wd, err := os.Getwd(); err == nil { - if strings.HasSuffix(wd, "cmd/gnoweb") { - os.Chdir("../..") - } - } else { - panic("os.Getwd() -> err: " + err.Error()) - } - // configure default values - flags.RemoteAddr = "127.0.0.1:26657" - flags.HelpRemote = "127.0.0.1:26657" + config, _ := integration.TestingNodeConfig(t, gnoland.MustGuessGnoRootDir()) + node, remoteAddr := integration.TestingInMemoryNode(t, log.NewNopLogger(), config) + defer node.Stop() + + // set the `remoteAddr` of the client to the listening address of the + // node, which is randomly assigned. + flags.RemoteAddr = remoteAddr flags.HelpChainID = "dev" flags.CaptchaSite = "" - flags.ViewsDir = "./cmd/gnoweb/views" + flags.ViewsDir = "../../cmd/gnoweb/views" flags.WithAnalytics = false app := makeApp() @@ -93,27 +92,34 @@ func TestAnalytics(t *testing.T) { "/404-not-found", } + config, _ := integration.TestingNodeConfig(t, gnoland.MustGuessGnoRootDir()) + node, remoteAddr := integration.TestingInMemoryNode(t, log.NewNopLogger(), config) + defer node.Stop() + + flags.ViewsDir = "../../cmd/gnoweb/views" t.Run("with", func(t *testing.T) { for _, route := range routes { t.Run(route, func(t *testing.T) { + flags.RemoteAddr = remoteAddr flags.WithAnalytics = true app := makeApp() request := httptest.NewRequest(http.MethodGet, route, nil) response := httptest.NewRecorder() app.Router.ServeHTTP(response, request) - assert.Contains(t, response.Body.String(), "simpleanalytics") + assert.Contains(t, response.Body.String(), "sa.gno.services") }) } }) t.Run("without", func(t *testing.T) { for _, route := range routes { t.Run(route, func(t *testing.T) { + flags.RemoteAddr = remoteAddr flags.WithAnalytics = false app := makeApp() request := httptest.NewRequest(http.MethodGet, route, nil) response := httptest.NewRecorder() app.Router.ServeHTTP(response, request) - assert.Equal(t, strings.Contains(response.Body.String(), "simpleanalytics"), false) + assert.Equal(t, strings.Contains(response.Body.String(), "sa.gno.services"), false) }) } }) diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go index 3585f99d7de..0610cd4a93f 100644 --- a/gno.land/pkg/gnoland/app.go +++ b/gno.land/pkg/gnoland/app.go @@ -1,16 +1,17 @@ package gnoland import ( + "errors" "fmt" "os" "os/exec" "path/filepath" + "runtime" "strings" "github.com/gnolang/gno/gno.land/pkg/sdk/vm" "github.com/gnolang/gno/tm2/pkg/amino" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" - "github.com/gnolang/gno/tm2/pkg/crypto" dbm "github.com/gnolang/gno/tm2/pkg/db" "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/sdk" @@ -36,7 +37,7 @@ func NewAppOptions() *AppOptions { return &AppOptions{ Logger: log.NewNopLogger(), DB: dbm.NewMemDB(), - GnoRootDir: GuessGnoRootDir(), + GnoRootDir: MustGuessGnoRootDir(), } } @@ -73,6 +74,8 @@ func NewAppWithOptions(cfg *AppOptions) (abci.Application, error) { // Construct keepers. acctKpr := auth.NewAccountKeeper(mainKey, ProtoGnoAccount) bankKpr := bank.NewBankKeeper(acctKpr) + + // XXX: Embed this ? stdlibsDir := filepath.Join(cfg.GnoRootDir, "gnovm", "stdlibs") vmKpr := vm.NewVMKeeper(baseKey, mainKey, acctKpr, bankKpr, stdlibsDir, cfg.MaxCycles) @@ -142,10 +145,9 @@ func InitChainer(baseApp *sdk.BaseApp, acctKpr auth.AccountKeeperI, bankKpr bank genState := req.AppState.(GnoGenesisState) // Parse and set genesis state balances. for _, bal := range genState.Balances { - addr, coins := parseBalance(bal) - acc := acctKpr.NewAccountWithAddress(ctx, addr) + acc := acctKpr.NewAccountWithAddress(ctx, bal.Address) acctKpr.SetAccount(ctx, acc) - err := bankKpr.SetCoins(ctx, addr, coins) + err := bankKpr.SetCoins(ctx, bal.Address, bal.Amount) if err != nil { panic(err) } @@ -172,22 +174,6 @@ func InitChainer(baseApp *sdk.BaseApp, acctKpr auth.AccountKeeperI, bankKpr bank } } -func parseBalance(bal string) (crypto.Address, std.Coins) { - parts := strings.Split(bal, "=") - if len(parts) != 2 { - panic(fmt.Sprintf("invalid balance string %s", bal)) - } - addr, err := crypto.AddressFromBech32(parts[0]) - if err != nil { - panic(fmt.Sprintf("invalid balance addr %s (%v)", bal, err)) - } - coins, err := std.ParseCoins(parts[1]) - if err != nil { - panic(fmt.Sprintf("invalid balance coins %s (%v)", bal, err)) - } - return addr, coins -} - // XXX not used yet. func EndBlocker(vmk vm.VMKeeperI) func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { return func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { @@ -195,24 +181,44 @@ func EndBlocker(vmk vm.VMKeeperI) func(ctx sdk.Context, req abci.RequestEndBlock } } -func GuessGnoRootDir() string { - var rootdir string +// XXX: all the method bellow should be removed in favor of +// https://github.com/gnolang/gno/pull/1233 +func MustGuessGnoRootDir() string { + root, err := GuessGnoRootDir() + if err != nil { + panic(err) + } + + return root +} +func GuessGnoRootDir() (string, error) { // First try to get the root directory from the GNOROOT environment variable. - if rootdir = os.Getenv("GNOROOT"); rootdir != "" { - return filepath.Clean(rootdir) + if rootdir := os.Getenv("GNOROOT"); rootdir != "" { + return filepath.Clean(rootdir), nil } + // Try to guess GNOROOT using the nearest go.mod. if gobin, err := exec.LookPath("go"); err == nil { // If GNOROOT is not set, try to guess the root directory using the `go list` command. cmd := exec.Command(gobin, "list", "-m", "-mod=mod", "-f", "{{.Dir}}", "github.com/gnolang/gno") out, err := cmd.CombinedOutput() - if err != nil { - panic(fmt.Errorf("invalid gno directory %q: %w", rootdir, err)) + if err == nil { + return strings.TrimSpace(string(out)), nil } + } - return strings.TrimSpace(string(out)) + // Try to guess GNOROOT using caller stack. + if _, filename, _, ok := runtime.Caller(1); ok && filepath.IsAbs(filename) { + if currentDir := filepath.Dir(filename); currentDir != "" { + // Gno root directory relative from `app.go` path: + // gno/ .. /gno.land/ .. /pkg/ .. /gnoland/app.go + rootdir, err := filepath.Abs(filepath.Join(currentDir, "..", "..", "..")) + if err == nil { + return rootdir, nil + } + } } - panic("no go binary available, unable to determine gno root-dir path") + return "", errors.New("unable to guess gno's root-directory") } diff --git a/gno.land/pkg/gnoland/genesis.go b/gno.land/pkg/gnoland/genesis.go new file mode 100644 index 00000000000..e809103469d --- /dev/null +++ b/gno.land/pkg/gnoland/genesis.go @@ -0,0 +1,126 @@ +package gnoland + +import ( + "errors" + "fmt" + "strings" + + vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm" + gno "github.com/gnolang/gno/gnovm/pkg/gnolang" + "github.com/gnolang/gno/gnovm/pkg/gnomod" + "github.com/gnolang/gno/tm2/pkg/amino" + bft "github.com/gnolang/gno/tm2/pkg/bft/types" + "github.com/gnolang/gno/tm2/pkg/crypto" + osm "github.com/gnolang/gno/tm2/pkg/os" + "github.com/gnolang/gno/tm2/pkg/std" +) + +// LoadGenesisBalancesFile loads genesis balances from the provided file path. +func LoadGenesisBalancesFile(path string) ([]Balance, error) { + // each balance is in the form: g1xxxxxxxxxxxxxxxx=100000ugnot + content := osm.MustReadFile(path) + lines := strings.Split(string(content), "\n") + + balances := make([]Balance, 0, len(lines)) + for _, line := range lines { + line = strings.TrimSpace(line) + + // remove comments. + line = strings.Split(line, "#")[0] + line = strings.TrimSpace(line) + + // skip empty lines. + if line == "" { + continue + } + + parts := strings.Split(line, "=") //
= + if len(parts) != 2 { + return nil, errors.New("invalid genesis_balance line: " + line) + } + + addr, err := crypto.AddressFromBech32(parts[0]) + if err != nil { + return nil, fmt.Errorf("invalid balance addr %s: %w", parts[0], err) + } + + coins, err := std.ParseCoins(parts[1]) + if err != nil { + return nil, fmt.Errorf("invalid balance coins %s: %w", parts[1], err) + } + + balances = append(balances, Balance{ + Address: addr, + Amount: coins, + }) + } + + return balances, nil +} + +// LoadGenesisTxsFile loads genesis transactions from the provided file path. +// XXX: Improve the way we generate and load this file +func LoadGenesisTxsFile(path string, chainID string, genesisRemote string) ([]std.Tx, error) { + txs := []std.Tx{} + txsBz := osm.MustReadFile(path) + txsLines := strings.Split(string(txsBz), "\n") + for _, txLine := range txsLines { + if txLine == "" { + continue // Skip empty line. + } + + // Patch the TX. + txLine = strings.ReplaceAll(txLine, "%%CHAINID%%", chainID) + txLine = strings.ReplaceAll(txLine, "%%REMOTE%%", genesisRemote) + + var tx std.Tx + if err := amino.UnmarshalJSON([]byte(txLine), &tx); err != nil { + return nil, fmt.Errorf("unable to Unmarshall txs file: %w", err) + } + + txs = append(txs, tx) + } + + return txs, nil +} + +// LoadPackagesFromDir loads gno packages from a directory. +// It creates and returns a list of transactions based on these packages. +func LoadPackagesFromDir(dir string, creator bft.Address, fee std.Fee, deposit std.Coins) ([]std.Tx, error) { + // list all packages from target path + pkgs, err := gnomod.ListPkgs(dir) + if err != nil { + return nil, fmt.Errorf("listing gno packages: %w", err) + } + + // Sort packages by dependencies. + sortedPkgs, err := pkgs.Sort() + if err != nil { + return nil, fmt.Errorf("sorting packages: %w", err) + } + + // Filter out draft packages. + nonDraftPkgs := sortedPkgs.GetNonDraftPkgs() + txs := []std.Tx{} + for _, pkg := range nonDraftPkgs { + // Open files in directory as MemPackage. + memPkg := gno.ReadMemPackage(pkg.Dir, pkg.Name) + + // Create transaction + tx := std.Tx{ + Fee: fee, + Msgs: []std.Msg{ + vmm.MsgAddPackage{ + Creator: creator, + Package: memPkg, + Deposit: deposit, + }, + }, + } + + tx.Signatures = make([]std.Signature, len(tx.GetSigners())) + txs = append(txs, tx) + } + + return txs, nil +} diff --git a/gno.land/pkg/gnoland/node_inmemory.go b/gno.land/pkg/gnoland/node_inmemory.go new file mode 100644 index 00000000000..0edef304281 --- /dev/null +++ b/gno.land/pkg/gnoland/node_inmemory.go @@ -0,0 +1,147 @@ +package gnoland + +import ( + "fmt" + "time" + + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + tmcfg "github.com/gnolang/gno/tm2/pkg/bft/config" + "github.com/gnolang/gno/tm2/pkg/bft/node" + "github.com/gnolang/gno/tm2/pkg/bft/proxy" + bft "github.com/gnolang/gno/tm2/pkg/bft/types" + "github.com/gnolang/gno/tm2/pkg/crypto" + "github.com/gnolang/gno/tm2/pkg/crypto/ed25519" + "github.com/gnolang/gno/tm2/pkg/db" + "github.com/gnolang/gno/tm2/pkg/log" + "github.com/gnolang/gno/tm2/pkg/p2p" + "github.com/gnolang/gno/tm2/pkg/std" +) + +type InMemoryNodeConfig struct { + PrivValidator bft.PrivValidator // identity of the validator + Genesis *bft.GenesisDoc + TMConfig *tmcfg.Config + SkipFailingGenesisTxs bool + GenesisMaxVMCycles int64 +} + +// NewMockedPrivValidator generate a new key +func NewMockedPrivValidator() bft.PrivValidator { + return bft.NewMockPVWithParams(ed25519.GenPrivKey(), false, false) +} + +// NewInMemoryNodeConfig creates a default configuration for an in-memory node. +func NewDefaultGenesisConfig(pk crypto.PubKey, chainid string) *bft.GenesisDoc { + return &bft.GenesisDoc{ + GenesisTime: time.Now(), + ChainID: chainid, + ConsensusParams: abci.ConsensusParams{ + Block: &abci.BlockParams{ + MaxTxBytes: 1_000_000, // 1MB, + MaxDataBytes: 2_000_000, // 2MB, + MaxGas: 10_0000_000, // 10M gas + TimeIotaMS: 100, // 100ms + }, + }, + AppState: &GnoGenesisState{ + Balances: []Balance{}, + Txs: []std.Tx{}, + }, + } +} + +func NewDefaultTMConfig(rootdir string) *tmcfg.Config { + return tmcfg.DefaultConfig().SetRootDir(rootdir) +} + +// NewInMemoryNodeConfig creates a default configuration for an in-memory node. +func NewDefaultInMemoryNodeConfig(rootdir string) *InMemoryNodeConfig { + tm := NewDefaultTMConfig(rootdir) + + // Create Mocked Identity + pv := NewMockedPrivValidator() + genesis := NewDefaultGenesisConfig(pv.GetPubKey(), tm.ChainID()) + + // Add self as validator + self := pv.GetPubKey() + genesis.Validators = []bft.GenesisValidator{ + { + Address: self.Address(), + PubKey: self, + Power: 10, + Name: "self", + }, + } + + return &InMemoryNodeConfig{ + PrivValidator: pv, + TMConfig: tm, + Genesis: genesis, + GenesisMaxVMCycles: 10_000_000, + } +} + +func (cfg *InMemoryNodeConfig) validate() error { + if cfg.PrivValidator == nil { + return fmt.Errorf("`PrivValidator` is required but not provided") + } + + if cfg.TMConfig == nil { + return fmt.Errorf("`TMConfig` is required but not provided") + } + + if cfg.TMConfig.RootDir == "" { + return fmt.Errorf("`TMConfig.RootDir` is required to locate `stdlibs` directory") + } + + return nil +} + +// NewInMemoryNode creates an in-memory gnoland node. In this mode, the node does not +// persist any data and uses an in-memory database. The `InMemoryNodeConfig.TMConfig.RootDir` +// should point to the correct gno repository to load the stdlibs. +func NewInMemoryNode(logger log.Logger, cfg *InMemoryNodeConfig) (*node.Node, error) { + if err := cfg.validate(); err != nil { + return nil, fmt.Errorf("validate config error: %w", err) + } + + // Initialize the application with the provided options + gnoApp, err := NewAppWithOptions(&AppOptions{ + Logger: logger, + GnoRootDir: cfg.TMConfig.RootDir, + SkipFailingGenesisTxs: cfg.SkipFailingGenesisTxs, + MaxCycles: cfg.GenesisMaxVMCycles, + DB: db.NewMemDB(), + }) + if err != nil { + return nil, fmt.Errorf("error initializing new app: %w", err) + } + + cfg.TMConfig.LocalApp = gnoApp + + // Setup app client creator + appClientCreator := proxy.DefaultClientCreator( + cfg.TMConfig.LocalApp, + cfg.TMConfig.ProxyApp, + cfg.TMConfig.ABCI, + cfg.TMConfig.DBDir(), + ) + + // Create genesis factory + genProvider := func() (*bft.GenesisDoc, error) { return cfg.Genesis, nil } + + dbProvider := func(*node.DBContext) (db.DB, error) { return db.NewMemDB(), nil } + + // generate p2p node identity + // XXX: do we need to configur + nodekey := &p2p.NodeKey{PrivKey: ed25519.GenPrivKey()} + + // Create and return the in-memory node instance + return node.NewNode(cfg.TMConfig, + cfg.PrivValidator, nodekey, + appClientCreator, + genProvider, + dbProvider, + logger, + ) +} diff --git a/gno.land/pkg/gnoland/types.go b/gno.land/pkg/gnoland/types.go index 1c762366ae9..5d68064c9c5 100644 --- a/gno.land/pkg/gnoland/types.go +++ b/gno.land/pkg/gnoland/types.go @@ -1,9 +1,20 @@ package gnoland import ( + "errors" + "fmt" + "strings" + + bft "github.com/gnolang/gno/tm2/pkg/bft/types" + "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/std" ) +var ( + ErrBalanceEmptyAddress = errors.New("balance address is empty") + ErrBalanceEmptyAmount = errors.New("balance amount is empty") +) + type GnoAccount struct { std.BaseAccount } @@ -13,6 +24,56 @@ func ProtoGnoAccount() std.Account { } type GnoGenesisState struct { - Balances []string `json:"balances"` - Txs []std.Tx `json:"txs"` + Balances []Balance `json:"balances"` + Txs []std.Tx `json:"txs"` +} + +type Balance struct { + Address bft.Address + Amount std.Coins +} + +func (b *Balance) Verify() error { + if b.Address.IsZero() { + return ErrBalanceEmptyAddress + } + + if b.Amount.Len() == 0 { + return ErrBalanceEmptyAmount + } + + return nil +} + +func (b *Balance) Parse(entry string) error { + parts := strings.Split(strings.TrimSpace(entry), "=") //
= + if len(parts) != 2 { + return fmt.Errorf("malformed entry: %q", entry) + } + + var err error + + b.Address, err = crypto.AddressFromBech32(parts[0]) + if err != nil { + return fmt.Errorf("invalid address %q: %w", parts[0], err) + } + + b.Amount, err = std.ParseCoins(parts[1]) + if err != nil { + return fmt.Errorf("invalid amount %q: %w", parts[1], err) + } + + return nil +} + +func (b *Balance) UnmarshalAmino(rep string) error { + return b.Parse(rep) +} + +func (b Balance) MarshalAmino() (string, error) { + return b.String(), nil +} + +func (b Balance) String() string { + return fmt.Sprintf("%s=%s", b.Address.String(), b.Amount.String()) } diff --git a/gno.land/pkg/gnoland/types_test.go b/gno.land/pkg/gnoland/types_test.go new file mode 100644 index 00000000000..97222d0cdfd --- /dev/null +++ b/gno.land/pkg/gnoland/types_test.go @@ -0,0 +1,98 @@ +package gnoland + +import ( + "fmt" + "testing" + + "github.com/gnolang/gno/tm2/pkg/amino" + bft "github.com/gnolang/gno/tm2/pkg/bft/types" + "github.com/gnolang/gno/tm2/pkg/crypto" + "github.com/gnolang/gno/tm2/pkg/std" + "github.com/jaekwon/testify/assert" + "github.com/jaekwon/testify/require" +) + +func TestBalance_Verify(t *testing.T) { + validAddress := crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + emptyAmount := std.Coins{} + nonEmptyAmount := std.NewCoins(std.NewCoin("test", 100)) + + tests := []struct { + name string + balance Balance + expectErr bool + }{ + {"empty amount", Balance{Address: validAddress, Amount: emptyAmount}, true}, + {"empty address", Balance{Address: bft.Address{}, Amount: nonEmptyAmount}, true}, + {"valid balance", Balance{Address: validAddress, Amount: nonEmptyAmount}, false}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.balance.Verify() + if tc.expectErr { + assert.Error(t, err, fmt.Sprintf("TestVerifyBalance: %s", tc.name)) + } else { + assert.NoError(t, err, fmt.Sprintf("TestVerifyBalance: %s", tc.name)) + } + }) + } +} + +func TestBalance_Parse(t *testing.T) { + validAddress := crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + validBalance := Balance{Address: validAddress, Amount: std.NewCoins(std.NewCoin("test", 100))} + + tests := []struct { + name string + entry string + expected Balance + expectErr bool + }{ + {"valid entry", "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5=100test", validBalance, false}, + {"invalid address", "invalid=100test", Balance{}, true}, + {"incomplete entry", "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", Balance{}, true}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + balance := Balance{} + err := balance.Parse(tc.entry) + if tc.expectErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tc.expected, balance) + } + }) + } +} + +func TestBalance_AminoUnmarshalJSON(t *testing.T) { + expected := Balance{ + Address: crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"), + Amount: std.MustParseCoins("100ugnot"), + } + value := fmt.Sprintf("[%q]", expected.String()) + + var balances []Balance + err := amino.UnmarshalJSON([]byte(value), &balances) + require.NoError(t, err) + require.Len(t, balances, 1, "there should be one balance after unmarshaling") + + balance := balances[0] + require.Equal(t, expected.Address, balance.Address) + require.True(t, expected.Amount.IsEqual(balance.Amount)) +} + +func TestBalance_AminoMarshalJSON(t *testing.T) { + expected := Balance{ + Address: crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"), + Amount: std.MustParseCoins("100ugnot"), + } + expectedJSON := fmt.Sprintf("[%q]", expected.String()) + + balancesJSON, err := amino.MarshalJSON([]Balance{expected}) + require.NoError(t, err) + require.JSONEq(t, expectedJSON, string(balancesJSON)) +} diff --git a/gno.land/pkg/integration/gnoland.go b/gno.land/pkg/integration/gnoland.go deleted file mode 100644 index 318d76eea86..00000000000 --- a/gno.land/pkg/integration/gnoland.go +++ /dev/null @@ -1,334 +0,0 @@ -package integration - -import ( - "flag" - "fmt" - "path/filepath" - "strings" - "testing" - "time" - - "github.com/gnolang/gno/gno.land/pkg/gnoland" - vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm" - gno "github.com/gnolang/gno/gnovm/pkg/gnolang" - "github.com/gnolang/gno/gnovm/pkg/gnomod" - "github.com/gnolang/gno/tm2/pkg/amino" - abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" - "github.com/gnolang/gno/tm2/pkg/bft/config" - "github.com/gnolang/gno/tm2/pkg/bft/node" - "github.com/gnolang/gno/tm2/pkg/bft/privval" - bft "github.com/gnolang/gno/tm2/pkg/bft/types" - "github.com/gnolang/gno/tm2/pkg/crypto" - "github.com/gnolang/gno/tm2/pkg/db" - "github.com/gnolang/gno/tm2/pkg/log" - osm "github.com/gnolang/gno/tm2/pkg/os" - "github.com/gnolang/gno/tm2/pkg/std" - "github.com/rogpeppe/go-internal/testscript" -) - -type IntegrationConfig struct { - SkipFailingGenesisTxs bool - SkipStart bool - GenesisBalancesFile string - GenesisTxsFile string - ChainID string - GenesisRemote string - RootDir string - GenesisMaxVMCycles int64 - Config string -} - -// NOTE: This is a copy of gnoland actual flags. -// XXX: A lot this make no sense for integration. -func (c *IntegrationConfig) RegisterFlags(fs *flag.FlagSet) { - fs.BoolVar( - &c.SkipFailingGenesisTxs, - "skip-failing-genesis-txs", - false, - "don't panic when replaying invalid genesis txs", - ) - fs.BoolVar( - &c.SkipStart, - "skip-start", - false, - "quit after initialization, don't start the node", - ) - - fs.StringVar( - &c.GenesisBalancesFile, - "genesis-balances-file", - "./genesis/genesis_balances.txt", - "initial distribution file", - ) - - fs.StringVar( - &c.GenesisTxsFile, - "genesis-txs-file", - "./genesis/genesis_txs.txt", - "initial txs to replay", - ) - - fs.StringVar( - &c.ChainID, - "chainid", - "dev", - "the ID of the chain", - ) - - fs.StringVar( - &c.RootDir, - "root-dir", - "testdir", - "directory for config and data", - ) - - fs.StringVar( - &c.GenesisRemote, - "genesis-remote", - "localhost:26657", - "replacement for '%%REMOTE%%' in genesis", - ) - - fs.Int64Var( - &c.GenesisMaxVMCycles, - "genesis-max-vm-cycles", - 10_000_000, - "set maximum allowed vm cycles per operation. Zero means no limit.", - ) -} - -func execTestingGnoland(t *testing.T, logger log.Logger, gnoDataDir, gnoRootDir string, args []string) (*node.Node, error) { - t.Helper() - - // Setup start config. - icfg := &IntegrationConfig{} - { - fs := flag.NewFlagSet("start", flag.ExitOnError) - icfg.RegisterFlags(fs) - - // Override default value for flags. - fs.VisitAll(func(f *flag.Flag) { - switch f.Name { - case "root-dir": - f.DefValue = gnoDataDir - case "chainid": - f.DefValue = "tendermint_test" - case "genesis-balances-file": - f.DefValue = filepath.Join(gnoRootDir, "gno.land", "genesis", "genesis_balances.txt") - case "genesis-txs-file": - f.DefValue = filepath.Join(gnoRootDir, "gno.land", "genesis", "genesis_txs.txt") - default: - return - } - - f.Value.Set(f.DefValue) - }) - - if err := fs.Parse(args); err != nil { - return nil, fmt.Errorf("unable to parse flags: %w", err) - } - } - - // Setup testing config. - cfg := config.TestConfig().SetRootDir(gnoDataDir) - { - cfg.EnsureDirs() - cfg.RPC.ListenAddress = "tcp://127.0.0.1:0" - cfg.P2P.ListenAddress = "tcp://127.0.0.1:0" - } - - // Prepare genesis. - if err := setupTestingGenesis(gnoDataDir, cfg, icfg, gnoRootDir); err != nil { - return nil, err - } - - // Create application and node. - return createAppAndNode(cfg, logger, gnoRootDir, icfg) -} - -func setupTestingGenesis(gnoDataDir string, cfg *config.Config, icfg *IntegrationConfig, gnoRootDir string) error { - newPrivValKey := cfg.PrivValidatorKeyFile() - newPrivValState := cfg.PrivValidatorStateFile() - priv := privval.LoadOrGenFilePV(newPrivValKey, newPrivValState) - - genesisFilePath := filepath.Join(gnoDataDir, cfg.Genesis) - genesisDirPath := filepath.Dir(genesisFilePath) - if err := osm.EnsureDir(genesisDirPath, 0o700); err != nil { - return fmt.Errorf("unable to ensure directory %q: %w", genesisDirPath, err) - } - - genesisTxs := loadGenesisTxs(icfg.GenesisTxsFile, icfg.ChainID, icfg.GenesisRemote) - pvPub := priv.GetPubKey() - - gen := &bft.GenesisDoc{ - GenesisTime: time.Now(), - ChainID: icfg.ChainID, - ConsensusParams: abci.ConsensusParams{ - Block: &abci.BlockParams{ - // TODO: update limits. - MaxTxBytes: 1000000, // 1MB, - MaxDataBytes: 2000000, // 2MB, - MaxGas: 10000000, // 10M gas - TimeIotaMS: 100, // 100ms - }, - }, - Validators: []bft.GenesisValidator{ - { - Address: pvPub.Address(), - PubKey: pvPub, - Power: 10, - Name: "testvalidator", - }, - }, - } - - // Load distribution. - balances := loadGenesisBalances(icfg.GenesisBalancesFile) - - // Load initial packages from examples. - // XXX: We should be able to config this. - test1 := crypto.MustAddressFromString(test1Addr) - txs := []std.Tx{} - - // List initial packages to load from examples. - // println(filepath.Join(gnoRootDir, "examples")) - pkgs, err := gnomod.ListPkgs(filepath.Join(gnoRootDir, "examples")) - if err != nil { - return fmt.Errorf("listing gno packages: %w", err) - } - - // Sort packages by dependencies. - sortedPkgs, err := pkgs.Sort() - if err != nil { - return fmt.Errorf("sorting packages: %w", err) - } - - // Filter out draft packages. - nonDraftPkgs := sortedPkgs.GetNonDraftPkgs() - - for _, pkg := range nonDraftPkgs { - // Open files in directory as MemPackage. - memPkg := gno.ReadMemPackage(pkg.Dir, pkg.Name) - - var tx std.Tx - tx.Msgs = []std.Msg{ - vmm.MsgAddPackage{ - Creator: test1, - Package: memPkg, - Deposit: nil, - }, - } - - // XXX: Add fee flag ? - // Or maybe reduce fee to the minimum ? - tx.Fee = std.NewFee(50000, std.MustParseCoin("1000000ugnot")) - tx.Signatures = make([]std.Signature, len(tx.GetSigners())) - txs = append(txs, tx) - } - - // Load genesis txs from file. - txs = append(txs, genesisTxs...) - - // Construct genesis AppState. - gen.AppState = gnoland.GnoGenesisState{ - Balances: balances, - Txs: txs, - } - - writeGenesisFile(gen, genesisFilePath) - - return nil -} - -func createAppAndNode(cfg *config.Config, logger log.Logger, gnoRootDir string, icfg *IntegrationConfig) (*node.Node, error) { - gnoApp, err := gnoland.NewAppWithOptions(&gnoland.AppOptions{ - Logger: logger, - GnoRootDir: gnoRootDir, - SkipFailingGenesisTxs: icfg.SkipFailingGenesisTxs, - MaxCycles: icfg.GenesisMaxVMCycles, - DB: db.NewMemDB(), - }) - if err != nil { - return nil, fmt.Errorf("error in creating new app: %w", err) - } - - cfg.LocalApp = gnoApp - node, err := node.DefaultNewNode(cfg, logger) - if err != nil { - return nil, fmt.Errorf("error in creating node: %w", err) - } - - return node, node.Start() -} - -func tsValidateError(ts *testscript.TestScript, cmd string, neg bool, err error) { - if err != nil { - fmt.Fprintf(ts.Stderr(), "%q error: %v\n", cmd, err) - if !neg { - ts.Fatalf("unexpected %q command failure: %s", cmd, err) - } - } else { - if neg { - ts.Fatalf("unexpected %s command success", cmd) - } - } -} - -func loadGenesisTxs( - path string, - chainID string, - genesisRemote string, -) []std.Tx { - txs := []std.Tx{} - txsBz := osm.MustReadFile(path) - txsLines := strings.Split(string(txsBz), "\n") - for _, txLine := range txsLines { - if txLine == "" { - continue // Skip empty line. - } - - // Patch the TX. - txLine = strings.ReplaceAll(txLine, "%%CHAINID%%", chainID) - txLine = strings.ReplaceAll(txLine, "%%REMOTE%%", genesisRemote) - - var tx std.Tx - amino.MustUnmarshalJSON([]byte(txLine), &tx) - txs = append(txs, tx) - } - - return txs -} - -func loadGenesisBalances(path string) []string { - // Each balance is in the form: g1xxxxxxxxxxxxxxxx=100000ugnot. - balances := []string{} - content := osm.MustReadFile(path) - lines := strings.Split(string(content), "\n") - for _, line := range lines { - line = strings.TrimSpace(line) - - // Remove comments. - line = strings.Split(line, "#")[0] - line = strings.TrimSpace(line) - - // Skip empty lines. - if line == "" { - continue - } - - parts := strings.Split(line, "=") - if len(parts) != 2 { - panic("invalid genesis_balance line: " + line) - } - - balances = append(balances, line) - } - return balances -} - -func writeGenesisFile(gen *bft.GenesisDoc, filePath string) { - err := gen.SaveAs(filePath) - if err != nil { - panic(err) - } -} diff --git a/gno.land/pkg/integration/integration_test.go b/gno.land/pkg/integration/integration_test.go index 3c22a190d64..f88707f2b90 100644 --- a/gno.land/pkg/integration/integration_test.go +++ b/gno.land/pkg/integration/integration_test.go @@ -2,10 +2,10 @@ package integration import ( "testing" - - "github.com/rogpeppe/go-internal/testscript" ) func TestTestdata(t *testing.T) { - testscript.Run(t, SetupGnolandTestScript(t, "testdata")) + t.Parallel() + + RunGnolandTestscripts(t, "testdata") } diff --git a/gno.land/pkg/integration/testing.go b/gno.land/pkg/integration/testing.go new file mode 100644 index 00000000000..7803e213da1 --- /dev/null +++ b/gno.land/pkg/integration/testing.go @@ -0,0 +1,39 @@ +package integration + +import ( + "errors" + + "github.com/jaekwon/testify/assert" + "github.com/jaekwon/testify/require" + "github.com/rogpeppe/go-internal/testscript" +) + +// This error is from testscript.Fatalf and is needed to correctly +// handle the FailNow method. +// see: https://github.com/rogpeppe/go-internal/blob/32ae33786eccde1672d4ba373c80e1bc282bfbf6/testscript/testscript.go#L799-L812 +var errFailNow = errors.New("fail now!") //nolint:stylecheck + +var ( + _ require.TestingT = (*testingTS)(nil) + _ assert.TestingT = (*testingTS)(nil) +) + +type TestingTS = require.TestingT + +type testingTS struct { + *testscript.TestScript +} + +func TSTestingT(ts *testscript.TestScript) TestingTS { + return &testingTS{ts} +} + +func (t *testingTS) Errorf(format string, args ...interface{}) { + defer recover() // we can ignore recover result, we just want to catch it up + t.Fatalf(format, args...) +} + +func (t *testingTS) FailNow() { + // unfortunately we can't access underlying `t.t.FailNow` method + panic(errFailNow) +} diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go index f0a696ddd85..b10686b0105 100644 --- a/gno.land/pkg/integration/testing_integration.go +++ b/gno.land/pkg/integration/testing_integration.go @@ -8,60 +8,67 @@ import ( "path/filepath" "strconv" "strings" - "sync" "testing" - "time" "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/tm2/pkg/bft/node" - "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/crypto/keys" "github.com/gnolang/gno/tm2/pkg/crypto/keys/client" - "github.com/gnolang/gno/tm2/pkg/events" "github.com/gnolang/gno/tm2/pkg/log" "github.com/rogpeppe/go-internal/testscript" ) -// XXX: This should be centralize somewhere. -const ( - test1Addr = "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5" - test1Seed = "source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast" -) +type tSeqShim struct{ *testing.T } + +// noop Parallel method allow us to run test sequentially +func (tSeqShim) Parallel() {} + +func (t tSeqShim) Run(name string, f func(testscript.T)) { + t.T.Run(name, func(t *testing.T) { + f(tSeqShim{t}) + }) +} + +func (t tSeqShim) Verbose() bool { + return testing.Verbose() +} + +// RunGnolandTestscripts sets up and runs txtar integration tests for gnoland nodes. +// It prepares an in-memory gnoland node and initializes the necessary environment and custom commands. +// The function adapts the test setup for use with the testscript package, enabling +// the execution of gnoland and gnokey commands within txtar scripts. +// +// Refer to package documentation in doc.go for more information on commands and example txtar scripts. +func RunGnolandTestscripts(t *testing.T, txtarDir string) { + t.Helper() + + p := setupGnolandTestScript(t, txtarDir) + if deadline, ok := t.Deadline(); ok && p.Deadline.IsZero() { + p.Deadline = deadline + } + + testscript.RunT(tSeqShim{t}, p) +} type testNode struct { *node.Node - logger log.Logger nGnoKeyExec uint // Counter for execution of gnokey. } -// SetupGnolandTestScript prepares the test environment to execute txtar tests -// using a partial InMemory gnoland node. It initializes key storage, sets up the gnoland node, -// and provides custom commands like "gnoland" and "gnokey" for txtar script execution. -// -// The function returns testscript.Params which contain the test setup and command -// executions to be used with the testscript package. -// -// For a detailed explanation of the commands and their behaviors, as well as -// example txtar scripts, refer to the package documentation in doc.go. -func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { +func setupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { t.Helper() tmpdir := t.TempDir() // `gnoRootDir` should point to the local location of the gno repository. // It serves as the gno equivalent of GOROOT. - gnoRootDir := gnoland.GuessGnoRootDir() + gnoRootDir := gnoland.MustGuessGnoRootDir() // `gnoHomeDir` should be the local directory where gnokey stores keys. gnoHomeDir := filepath.Join(tmpdir, "gno") - // `gnoDataDir` should refer to the local location where the gnoland node - // stores its configuration and data. - gnoDataDir := filepath.Join(tmpdir, "data") - // Testscripts run concurrently by default, so we need to be prepared for that. - var muNodes sync.Mutex nodes := map[string]*testNode{} updateScripts, _ := strconv.ParseBool(os.Getenv("UPDATE_SCRIPTS")) @@ -76,10 +83,35 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { return err } - // XXX: Add a command to add custom account. - kb.CreateAccount("test1", test1Seed, "", "", 0, 0) - env.Setenv("USER_SEED_test1", test1Seed) - env.Setenv("USER_ADDR_test1", test1Addr) + // create sessions ID + var sid string + { + works := env.Getenv("WORK") + sum := crc32.ChecksumIEEE([]byte(works)) + sid = strconv.FormatUint(uint64(sum), 16) + env.Setenv("SID", sid) + } + + // setup logger + var logger log.Logger + { + logger = log.NewNopLogger() + if persistWorkDir || os.Getenv("LOG_DIR") != "" { + logname := fmt.Sprintf("gnoland-%s.log", sid) + logger, err = getTestingLogger(env, logname) + if err != nil { + return fmt.Errorf("unable to setup logger: %w", err) + } + } + + env.Values["_logger"] = logger + } + + // Setup "test1" default account + kb.CreateAccount(DefaultAccount_Name, DefaultAccount_Seed, "", "", 0, 0) + + env.Setenv("USER_SEED_"+DefaultAccount_Name, DefaultAccount_Seed) + env.Setenv("USER_ADDR_"+DefaultAccount_Name, DefaultAccount_Address) env.Setenv("GNOROOT", gnoRootDir) env.Setenv("GNOHOME", gnoHomeDir) @@ -88,15 +120,13 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { }, Cmds: map[string]func(ts *testscript.TestScript, neg bool, args []string){ "gnoland": func(ts *testscript.TestScript, neg bool, args []string) { - muNodes.Lock() - defer muNodes.Unlock() - if len(args) == 0 { tsValidateError(ts, "gnoland", neg, fmt.Errorf("syntax: gnoland [start|stop]")) return } - sid := getSessionID(ts) + logger := ts.Value("_logger").(log.Logger) // grab logger + sid := ts.Getenv("SID") // grab session id var cmd string cmd, args = args[0], args[1:] @@ -109,63 +139,20 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { break } - logger := log.NewNopLogger() - if persistWorkDir || os.Getenv("LOG_DIR") != "" { - logname := fmt.Sprintf("gnoland-%s.log", sid) - logger = getTestingLogger(ts, logname) - } + // Warp up `ts` so we can pass it to other testing method + t := TSTestingT(ts) - dataDir := filepath.Join(gnoDataDir, sid) - var node *node.Node - if node, err = execTestingGnoland(t, logger, dataDir, gnoRootDir, args); err == nil { - nodes[sid] = &testNode{ - Node: node, - logger: logger, - } - ts.Defer(func() { - muNodes.Lock() - defer muNodes.Unlock() - - if n := nodes[sid]; n != nil { - if err := n.Stop(); err != nil { - panic(fmt.Errorf("node %q was unable to stop: %w", sid, err)) - } - } - }) - - // Get listen address environment. - // It should have been updated with the right port on start. - laddr := node.Config().RPC.ListenAddress - - // Add default environements. - ts.Setenv("RPC_ADDR", laddr) - ts.Setenv("GNODATA", gnoDataDir) - - const listenerID = "testing_listener" - - // Wait for first block by waiting for `EventNewBlock` event. - nb := make(chan struct{}, 1) - node.EventSwitch().AddListener(listenerID, func(ev events.Event) { - if _, ok := ev.(types.EventNewBlock); ok { - select { - case nb <- struct{}{}: - default: - } - } - }) - - if node.BlockStore().Height() == 0 { - select { - case <-nb: // ok - case <-time.After(time.Second * 6): - ts.Fatalf("timeout while waiting for the node to start") - } - } - - node.EventSwitch().RemoveListener(listenerID) - - fmt.Fprintln(ts.Stdout(), "node started successfully") - } + // Generate config and node + cfg, _ := TestingNodeConfig(t, gnoRootDir) + n, remoteAddr := TestingInMemoryNode(t, logger, cfg) + + // Register cleanup + nodes[sid] = &testNode{Node: n} + + // Add default environements + ts.Setenv("RPC_ADDR", remoteAddr) + + fmt.Fprintln(ts.Stdout(), "node started successfully") case "stop": n, ok := nodes[sid] if !ok { @@ -176,9 +163,8 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { if err = n.Stop(); err == nil { delete(nodes, sid) - // Unset gnoland environements. + // Unset gnoland environements ts.Setenv("RPC_ADDR", "") - ts.Setenv("GNODATA", "") fmt.Fprintln(ts.Stdout(), "node stopped successfully") } default: @@ -188,12 +174,10 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { tsValidateError(ts, "gnoland "+cmd, neg, err) }, "gnokey": func(ts *testscript.TestScript, neg bool, args []string) { - muNodes.Lock() - defer muNodes.Unlock() + logger := ts.Value("_logger").(log.Logger) // grab logger + sid := ts.Getenv("SID") // grab session id - sid := getSessionID(ts) - - // Setup IO command. + // Setup IO command io := commands.NewTestIO() io.SetOut(commands.WriteNopCloser(ts.Stdout())) io.SetErr(commands.WriteNopCloser(ts.Stderr())) @@ -212,9 +196,10 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { n.nGnoKeyExec++ headerlog := fmt.Sprintf("%.02d!EXEC_GNOKEY", n.nGnoKeyExec) + // Log the command inside gnoland logger, so we can better scope errors. - n.logger.Info(headerlog, strings.Join(args, " ")) - defer n.logger.Info(headerlog, "END") + logger.Info(headerlog, strings.Join(args, " ")) + defer logger.Info(headerlog, "END") } // Inject default argument, if duplicate @@ -230,35 +215,30 @@ func SetupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { } } -func getSessionID(ts *testscript.TestScript) string { - works := ts.Getenv("WORK") - sum := crc32.ChecksumIEEE([]byte(works)) - return strconv.FormatUint(uint64(sum), 16) -} - -func getTestingLogger(ts *testscript.TestScript, logname string) log.Logger { +func getTestingLogger(env *testscript.Env, logname string) (log.Logger, error) { var path string + if logdir := os.Getenv("LOG_DIR"); logdir != "" { if err := os.MkdirAll(logdir, 0o755); err != nil { - ts.Fatalf("unable to make log directory %q", logdir) + return nil, fmt.Errorf("unable to make log directory %q", logdir) } var err error if path, err = filepath.Abs(filepath.Join(logdir, logname)); err != nil { - ts.Fatalf("uanble to get absolute path of logdir %q", logdir) + return nil, fmt.Errorf("uanble to get absolute path of logdir %q", logdir) } - } else if workdir := ts.Getenv("WORK"); workdir != "" { + } else if workdir := env.Getenv("WORK"); workdir != "" { path = filepath.Join(workdir, logname) } else { - return log.NewNopLogger() + return log.NewNopLogger(), nil } f, err := os.Create(path) if err != nil { - ts.Fatalf("unable to create log file %q: %s", path, err.Error()) + return nil, fmt.Errorf("unable to create log file %q: %w", path, err) } - ts.Defer(func() { + env.Defer(func() { if err := f.Close(); err != nil { panic(fmt.Errorf("unable to close log file %q: %w", path, err)) } @@ -274,9 +254,22 @@ func getTestingLogger(ts *testscript.TestScript, logname string) log.Logger { logger.SetLevel(log.LevelInfo) case "": default: - ts.Fatalf("invalid log level %q", level) + return nil, fmt.Errorf("invalid log level %q", level) } - ts.Logf("starting logger: %q", path) - return logger + env.T().Log("starting logger: %q", path) + return logger, nil +} + +func tsValidateError(ts *testscript.TestScript, cmd string, neg bool, err error) { + if err != nil { + fmt.Fprintf(ts.Stderr(), "%q error: %v\n", cmd, err) + if !neg { + ts.Fatalf("unexpected %q command failure: %s", cmd, err) + } + } else { + if neg { + ts.Fatalf("unexpected %q command success", cmd) + } + } } diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go new file mode 100644 index 00000000000..1ca7e11eb63 --- /dev/null +++ b/gno.land/pkg/integration/testing_node.go @@ -0,0 +1,184 @@ +package integration + +import ( + "path/filepath" + "sync" + "time" + + "github.com/gnolang/gno/gno.land/pkg/gnoland" + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + tmcfg "github.com/gnolang/gno/tm2/pkg/bft/config" + "github.com/gnolang/gno/tm2/pkg/bft/node" + bft "github.com/gnolang/gno/tm2/pkg/bft/types" + "github.com/gnolang/gno/tm2/pkg/crypto" + "github.com/gnolang/gno/tm2/pkg/events" + "github.com/gnolang/gno/tm2/pkg/log" + "github.com/gnolang/gno/tm2/pkg/std" + "github.com/jaekwon/testify/require" +) + +const ( + DefaultAccount_Name = "test1" + DefaultAccount_Address = "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5" + DefaultAccount_Seed = "source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast" +) + +// TestingInMemoryNode initializes and starts an in-memory node for testing. +// It returns the node instance and its RPC remote address. +func TestingInMemoryNode(t TestingTS, logger log.Logger, config *gnoland.InMemoryNodeConfig) (*node.Node, string) { + node, err := gnoland.NewInMemoryNode(logger, config) + require.NoError(t, err) + + err = node.Start() + require.NoError(t, err) + + select { + case <-waitForNodeReadiness(node): + case <-time.After(time.Second * 6): + require.FailNow(t, "timeout while waiting for the node to start") + } + + return node, node.Config().RPC.ListenAddress +} + +// TestingNodeConfig constructs an in-memory node configuration +// with default packages and genesis transactions already loaded. +// It will return the default creator address of the loaded packages. +func TestingNodeConfig(t TestingTS, gnoroot string) (*gnoland.InMemoryNodeConfig, bft.Address) { + cfg := TestingMinimalNodeConfig(t, gnoroot) + + creator := crypto.MustAddressFromString(DefaultAccount_Address) // test1 + + balances := LoadDefaultGenesisBalanceFile(t, gnoroot) + txs := []std.Tx{} + txs = append(txs, LoadDefaultPackages(t, creator, gnoroot)...) + txs = append(txs, LoadDefaultGenesisTXsFile(t, cfg.Genesis.ChainID, gnoroot)...) + + cfg.Genesis.AppState = gnoland.GnoGenesisState{ + Balances: balances, + Txs: txs, + } + + return cfg, creator +} + +// TestingMinimalNodeConfig constructs the default minimal in-memory node configuration for testing. +func TestingMinimalNodeConfig(t TestingTS, gnoroot string) *gnoland.InMemoryNodeConfig { + tmconfig := DefaultTestingTMConfig(gnoroot) + + // Create Mocked Identity + pv := gnoland.NewMockedPrivValidator() + + // Generate genesis config + genesis := DefaultTestingGenesisConfig(t, gnoroot, pv.GetPubKey(), tmconfig) + + return &gnoland.InMemoryNodeConfig{ + PrivValidator: pv, + Genesis: genesis, + TMConfig: tmconfig, + } +} + +func DefaultTestingGenesisConfig(t TestingTS, gnoroot string, self crypto.PubKey, tmconfig *tmcfg.Config) *bft.GenesisDoc { + return &bft.GenesisDoc{ + GenesisTime: time.Now(), + ChainID: tmconfig.ChainID(), + ConsensusParams: abci.ConsensusParams{ + Block: &abci.BlockParams{ + MaxTxBytes: 1_000_000, // 1MB, + MaxDataBytes: 2_000_000, // 2MB, + MaxGas: 10_0000_000, // 10M gas + TimeIotaMS: 100, // 100ms + }, + }, + Validators: []bft.GenesisValidator{ + { + Address: self.Address(), + PubKey: self, + Power: 10, + Name: "self", + }, + }, + AppState: gnoland.GnoGenesisState{ + Balances: []gnoland.Balance{ + { + Address: crypto.MustAddressFromString(DefaultAccount_Address), + Amount: std.MustParseCoins("10000000000000ugnot"), + }, + }, + Txs: []std.Tx{}, + }, + } +} + +// LoadDefaultPackages loads the default packages for testing using a given creator address and gnoroot directory. +func LoadDefaultPackages(t TestingTS, creator bft.Address, gnoroot string) []std.Tx { + examplesDir := filepath.Join(gnoroot, "examples") + + defaultFee := std.NewFee(50000, std.MustParseCoin("1000000ugnot")) + defaultCreator := crypto.MustAddressFromString(DefaultAccount_Address) // test1 + txs, err := gnoland.LoadPackagesFromDir(examplesDir, defaultCreator, defaultFee, nil) + require.NoError(t, err) + + return txs +} + +// LoadDefaultGenesisBalanceFile loads the default genesis balance file for testing. +func LoadDefaultGenesisBalanceFile(t TestingTS, gnoroot string) []gnoland.Balance { + balanceFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_balances.txt") + + genesisBalances, err := gnoland.LoadGenesisBalancesFile(balanceFile) + require.NoError(t, err) + + return genesisBalances +} + +// LoadDefaultGenesisTXsFile loads the default genesis transactions file for testing. +func LoadDefaultGenesisTXsFile(t TestingTS, chainid string, gnoroot string) []std.Tx { + txsFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_txs.txt") + + // NOTE: We dont care about giving a correct address here, as it's only for display + // XXX: Do we care loading this TXs for testing ? + genesisTXs, err := gnoland.LoadGenesisTxsFile(txsFile, chainid, "https://127.0.0.1:26657") + require.NoError(t, err) + + return genesisTXs +} + +// DefaultTestingTMConfig constructs the default Tendermint configuration for testing. +func DefaultTestingTMConfig(gnoroot string) *tmcfg.Config { + const defaultListner = "tcp://127.0.0.1:0" + + tmconfig := tmcfg.TestConfig().SetRootDir(gnoroot) + tmconfig.Consensus.CreateEmptyBlocks = true + tmconfig.Consensus.CreateEmptyBlocksInterval = time.Duration(0) + tmconfig.RPC.ListenAddress = defaultListner + tmconfig.P2P.ListenAddress = defaultListner + return tmconfig +} + +// waitForNodeReadiness waits until the node is ready, signaling via the EventNewBlock event. +// XXX: This should be replace by https://github.com/gnolang/gno/pull/1216 +func waitForNodeReadiness(n *node.Node) <-chan struct{} { + const listenerID = "first_block_listener" + + var once sync.Once + + nb := make(chan struct{}) + ready := func() { + close(nb) + n.EventSwitch().RemoveListener(listenerID) + } + + n.EventSwitch().AddListener(listenerID, func(ev events.Event) { + if _, ok := ev.(bft.EventNewBlock); ok { + once.Do(ready) + } + }) + + if n.BlockStore().Height() > 0 { + once.Do(ready) + } + + return nb +} diff --git a/gnovm/Makefile b/gnovm/Makefile index 5fcacf94f62..34e94f88633 100644 --- a/gnovm/Makefile +++ b/gnovm/Makefile @@ -46,15 +46,15 @@ _test.pkg: .PHONY: _test.gnolang _test.gnolang: _test.gnolang.native _test.gnolang.stdlibs _test.gnolang.realm _test.gnolang.pkg0 _test.gnolang.pkg1 _test.gnolang.pkg2 _test.gnolang.other -_test.gnolang.other:; go test $(GOTEST_FLAGS) tests/*.go -run "(TestFileStr|TestSelectors)" -_test.gnolang.realm:; go test $(GOTEST_FLAGS) tests/*.go -run "TestFiles/^zrealm" -_test.gnolang.pkg0:; go test $(GOTEST_FLAGS) tests/*.go -run "TestPackages/(bufio|crypto|encoding|errors|internal|io|math|sort|std|stdshim|strconv|strings|testing|unicode)" -_test.gnolang.pkg1:; go test $(GOTEST_FLAGS) tests/*.go -run "TestPackages/regexp" -_test.gnolang.pkg2:; go test $(GOTEST_FLAGS) tests/*.go -run "TestPackages/bytes" -_test.gnolang.native:; go test $(GOTEST_FLAGS) tests/*.go -test.short -run "TestFilesNative/" -_test.gnolang.stdlibs:; go test $(GOTEST_FLAGS) tests/*.go -test.short -run 'TestFiles$$/' -_test.gnolang.native.sync:; go test $(GOTEST_FLAGS) tests/*.go -test.short -run "TestFilesNative/" --update-golden-tests -_test.gnolang.stdlibs.sync:; go test $(GOTEST_FLAGS) tests/*.go -test.short -run 'TestFiles$$/' --update-golden-tests +_test.gnolang.other:; go test tests/*.go -run "(TestFileStr|TestSelectors)" $(GOTEST_FLAGS) +_test.gnolang.realm:; go test tests/*.go -run "TestFiles/^zrealm" $(GOTEST_FLAGS) +_test.gnolang.pkg0:; go test tests/*.go -run "TestPackages/(bufio|crypto|encoding|errors|internal|io|math|sort|std|stdshim|strconv|strings|testing|unicode)" $(GOTEST_FLAGS) +_test.gnolang.pkg1:; go test tests/*.go -run "TestPackages/regexp" $(GOTEST_FLAGS) +_test.gnolang.pkg2:; go test tests/*.go -run "TestPackages/bytes" $(GOTEST_FLAGS) +_test.gnolang.native:; go test tests/*.go -test.short -run "TestFilesNative/" $(GOTEST_FLAGS) +_test.gnolang.stdlibs:; go test tests/*.go -test.short -run 'TestFiles$$/' $(GOTEST_FLAGS) +_test.gnolang.native.sync:; go test tests/*.go -test.short -run "TestFilesNative/" --update-golden-tests $(GOTEST_FLAGS) +_test.gnolang.stdlibs.sync:; go test tests/*.go -test.short -run 'TestFiles$$/' --update-golden-tests $(GOTEST_FLAGS) ######################################## # Code gen diff --git a/gnovm/cmd/gno/build.go b/gnovm/cmd/gno/build.go index b80711586e4..7396d17fd8f 100644 --- a/gnovm/cmd/gno/build.go +++ b/gnovm/cmd/gno/build.go @@ -20,7 +20,7 @@ var defaultBuildOptions = &buildCfg{ goBinary: "go", } -func newBuildCmd(io *commands.IO) *commands.Command { +func newBuildCmd(io commands.IO) *commands.Command { cfg := &buildCfg{} return commands.NewCommand( @@ -52,7 +52,7 @@ func (c *buildCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execBuild(cfg *buildCfg, args []string, io *commands.IO) error { +func execBuild(cfg *buildCfg, args []string, io commands.IO) error { if len(args) < 1 { return flag.ErrHelp } diff --git a/gnovm/cmd/gno/build_test.go b/gnovm/cmd/gno/build_test.go index 5bb03ef0d35..81aed7d1c79 100644 --- a/gnovm/cmd/gno/build_test.go +++ b/gnovm/cmd/gno/build_test.go @@ -3,9 +3,23 @@ package main import ( "testing" + "github.com/gnolang/gno/gnovm/pkg/integration" "github.com/rogpeppe/go-internal/testscript" + "github.com/stretchr/testify/require" ) -func TestBuild(t *testing.T) { - testscript.Run(t, setupTestScript(t, "testdata/gno_build")) +func Test_ScriptsBuild(t *testing.T) { + p := testscript.Params{ + Dir: "testdata/gno_build", + } + + if coverdir, ok := integration.ResolveCoverageDir(); ok { + err := integration.SetupTestscriptsCoverage(&p, coverdir) + require.NoError(t, err) + } + + err := integration.SetupGno(&p, t.TempDir()) + require.NoError(t, err) + + testscript.Run(t, p) } diff --git a/gnovm/cmd/gno/clean.go b/gnovm/cmd/gno/clean.go index 999cc5f1f53..dad5332c4fa 100644 --- a/gnovm/cmd/gno/clean.go +++ b/gnovm/cmd/gno/clean.go @@ -20,7 +20,7 @@ type cleanCfg struct { modCache bool // clean -modcache flag } -func newCleanCmd(io *commands.IO) *commands.Command { +func newCleanCmd(io commands.IO) *commands.Command { cfg := &cleanCfg{} return commands.NewCommand( @@ -59,7 +59,7 @@ func (c *cleanCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execClean(cfg *cleanCfg, args []string, io *commands.IO) error { +func execClean(cfg *cleanCfg, args []string, io commands.IO) error { if len(args) > 0 { return flag.ErrHelp } @@ -96,7 +96,7 @@ func execClean(cfg *cleanCfg, args []string, io *commands.IO) error { } // clean removes generated files from a directory. -func clean(dir string, cfg *cleanCfg, io *commands.IO) error { +func clean(dir string, cfg *cleanCfg, io commands.IO) error { return filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error { if err != nil { return err diff --git a/gnovm/cmd/gno/doc.go b/gnovm/cmd/gno/doc.go index 0de49470c2a..4617c31741e 100644 --- a/gnovm/cmd/gno/doc.go +++ b/gnovm/cmd/gno/doc.go @@ -22,7 +22,7 @@ type docCfg struct { rootDir string } -func newDocCmd(io *commands.IO) *commands.Command { +func newDocCmd(io commands.IO) *commands.Command { c := &docCfg{} return commands.NewCommand( commands.Metadata{ @@ -74,7 +74,7 @@ func (c *docCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execDoc(cfg *docCfg, args []string, io *commands.IO) error { +func execDoc(cfg *docCfg, args []string, io commands.IO) error { // guess opts.RootDir if cfg.rootDir == "" { cfg.rootDir = guessRootDir() @@ -112,7 +112,7 @@ func execDoc(cfg *docCfg, args []string, io *commands.IO) error { io.Printfln("warning: error parsing some candidate packages:\n%v", err) } return res.WriteDocumentation( - io.Out, + io.Out(), &doc.WriteDocumentationOptions{ ShowAll: cfg.all, Source: cfg.src, diff --git a/gnovm/cmd/gno/lint.go b/gnovm/cmd/gno/lint.go index 7acd9877770..ad223afa3b0 100644 --- a/gnovm/cmd/gno/lint.go +++ b/gnovm/cmd/gno/lint.go @@ -19,7 +19,7 @@ type lintCfg struct { // auto-fix: apply suggested fixes automatically. } -func newLintCmd(io *commands.IO) *commands.Command { +func newLintCmd(io commands.IO) *commands.Command { cfg := &lintCfg{} return commands.NewCommand( @@ -41,7 +41,7 @@ func (c *lintCfg) RegisterFlags(fs *flag.FlagSet) { fs.IntVar(&c.setExitStatus, "set-exit-status", 1, "set exit status to 1 if any issues are found") } -func execLint(cfg *lintCfg, args []string, io *commands.IO) error { +func execLint(cfg *lintCfg, args []string, io commands.IO) error { if len(args) < 1 { return flag.ErrHelp } @@ -62,12 +62,12 @@ func execLint(cfg *lintCfg, args []string, io *commands.IO) error { hasError := false addIssue := func(issue lintIssue) { hasError = true - fmt.Fprint(io.Err, issue.String()+"\n") + fmt.Fprint(io.Err(), issue.String()+"\n") } for _, pkgPath := range pkgPaths { if verbose { - fmt.Fprintf(io.Err, "Linting %q...\n", pkgPath) + fmt.Fprintf(io.Err(), "Linting %q...\n", pkgPath) } // 'gno.mod' exists? diff --git a/gnovm/cmd/gno/main.go b/gnovm/cmd/gno/main.go index 433db703b90..c84aa52fc86 100644 --- a/gnovm/cmd/gno/main.go +++ b/gnovm/cmd/gno/main.go @@ -18,7 +18,7 @@ func main() { } } -func newGnocliCmd(io *commands.IO) *commands.Command { +func newGnocliCmd(io commands.IO) *commands.Command { cmd := commands.NewCommand( commands.Metadata{ ShortUsage: " [flags] [...]", diff --git a/gnovm/cmd/gno/main_test.go b/gnovm/cmd/gno/main_test.go index 8d19a50e814..371cdf913e8 100644 --- a/gnovm/cmd/gno/main_test.go +++ b/gnovm/cmd/gno/main_test.go @@ -5,12 +5,10 @@ import ( "context" "fmt" "os" - "os/exec" "path/filepath" "strings" "testing" - "github.com/rogpeppe/go-internal/testscript" "github.com/stretchr/testify/require" "github.com/gnolang/gno/tm2/pkg/commands" @@ -144,45 +142,3 @@ func testMainCaseRun(t *testing.T, tc []testMainCase) { }) } } - -func setupTestScript(t *testing.T, txtarDir string) testscript.Params { - t.Helper() - // Get root location of github.com/gnolang/gno - goModPath, err := exec.Command("go", "env", "GOMOD").CombinedOutput() - require.NoError(t, err) - rootDir := filepath.Dir(string(goModPath)) - // Build a fresh gno binary in a temp directory - gnoBin := filepath.Join(t.TempDir(), "gno") - err = exec.Command("go", "build", "-o", gnoBin, filepath.Join(rootDir, "gnovm", "cmd", "gno")).Run() - require.NoError(t, err) - // Define script params - return testscript.Params{ - Setup: func(env *testscript.Env) error { - env.Vars = append(env.Vars, - "GNOROOT="+rootDir, // thx PR 1014 :) - // by default, $HOME=/no-home, but we need an existing $HOME directory - // because some commands needs to access $HOME/.cache/go-build - "HOME="+t.TempDir(), - ) - return nil - }, - Cmds: map[string]func(ts *testscript.TestScript, neg bool, args []string){ - // add a custom "gno" command so txtar files can easily execute "gno" - // without knowing where is the binary or how it is executed. - "gno": func(ts *testscript.TestScript, neg bool, args []string) { - err := ts.Exec(gnoBin, args...) - if err != nil { - ts.Logf("[%v]\n", err) - if !neg { - ts.Fatalf("unexpected gno command failure") - } - } else { - if neg { - ts.Fatalf("unexpected gno command success") - } - } - }, - }, - Dir: txtarDir, - } -} diff --git a/gnovm/cmd/gno/mod.go b/gnovm/cmd/gno/mod.go index 267b7d99237..da8db3ed68a 100644 --- a/gnovm/cmd/gno/mod.go +++ b/gnovm/cmd/gno/mod.go @@ -4,8 +4,12 @@ import ( "context" "flag" "fmt" + "go/parser" + "go/token" "os" "path/filepath" + "sort" + "strings" "github.com/gnolang/gno/gnovm/pkg/gnomod" "github.com/gnolang/gno/tm2/pkg/commands" @@ -17,7 +21,7 @@ type modDownloadCfg struct { verbose bool } -func newModCmd(io *commands.IO) *commands.Command { +func newModCmd(io commands.IO) *commands.Command { cmd := commands.NewCommand( commands.Metadata{ Name: "mod", @@ -31,12 +35,13 @@ func newModCmd(io *commands.IO) *commands.Command { cmd.AddSubCommands( newModDownloadCmd(io), newModInitCmd(), + newModTidy(io), ) return cmd } -func newModDownloadCmd(io *commands.IO) *commands.Command { +func newModDownloadCmd(io commands.IO) *commands.Command { cfg := &modDownloadCfg{} return commands.NewCommand( @@ -66,6 +71,20 @@ func newModInitCmd() *commands.Command { ) } +func newModTidy(io commands.IO) *commands.Command { + return commands.NewCommand( + commands.Metadata{ + Name: "tidy", + ShortUsage: "tidy", + ShortHelp: "Add missing and remove unused modules", + }, + commands.NewEmptyConfig(), + func(_ context.Context, args []string) error { + return execModTidy(args, io) + }, + ) +} + func (c *modDownloadCfg) RegisterFlags(fs *flag.FlagSet) { fs.StringVar( &c.remote, @@ -82,7 +101,7 @@ func (c *modDownloadCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execModDownload(cfg *modDownloadCfg, args []string, io *commands.IO) error { +func execModDownload(cfg *modDownloadCfg, args []string, io commands.IO) error { if len(args) > 0 { return flag.ErrHelp } @@ -152,3 +171,89 @@ func execModInit(args []string) error { return nil } + +func execModTidy(args []string, io commands.IO) error { + if len(args) > 0 { + return flag.ErrHelp + } + + wd, err := os.Getwd() + if err != nil { + return err + } + fname := filepath.Join(wd, "gno.mod") + gm, err := gnomod.ParseGnoMod(fname) + if err != nil { + return err + } + + // Drop all existing requires + for _, r := range gm.Require { + gm.DropRequire(r.Mod.Path) + } + + imports, err := getGnoImports(wd) + if err != nil { + return err + } + for _, im := range imports { + // skip if importpath is modulepath + if im == gm.Module.Mod.Path { + continue + } + gm.AddRequire(im, "v0.0.0-latest") + } + + gm.Write(fname) + return nil +} + +// getGnoImports returns the list of gno imports from a given path. +// Note: It ignores subdirs. Since right now we are still deciding on +// how to handle subdirs. +// See: +// - https://github.com/gnolang/gno/issues/1024 +// - https://github.com/gnolang/gno/issues/852 +// +// TODO: move this to better location. +func getGnoImports(path string) ([]string, error) { + entries, err := os.ReadDir(path) + if err != nil { + return nil, err + } + + allImports := make([]string, 0) + seen := make(map[string]struct{}) + for _, e := range entries { + filename := e.Name() + if ext := filepath.Ext(filename); ext != ".gno" { + continue + } + if strings.HasSuffix(filename, "_filetest.gno") { + continue + } + data, err := os.ReadFile(filepath.Join(path, filename)) + if err != nil { + return nil, err + } + fs := token.NewFileSet() + f, err := parser.ParseFile(fs, filename, data, parser.ImportsOnly) + if err != nil { + return nil, err + } + for _, imp := range f.Imports { + importPath := strings.TrimPrefix(strings.TrimSuffix(imp.Path.Value, `"`), `"`) + if !strings.HasPrefix(importPath, "gno.land/") { + continue + } + if _, ok := seen[importPath]; ok { + continue + } + allImports = append(allImports, importPath) + seen[importPath] = struct{}{} + } + } + sort.Strings(allImports) + + return allImports, nil +} diff --git a/gnovm/cmd/gno/mod_test.go b/gnovm/cmd/gno/mod_test.go index fdae3d12c7a..bbf106c8960 100644 --- a/gnovm/cmd/gno/mod_test.go +++ b/gnovm/cmd/gno/mod_test.go @@ -1,6 +1,13 @@ package main -import "testing" +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) func TestModApp(t *testing.T) { tc := []testMainCase{ @@ -9,7 +16,7 @@ func TestModApp(t *testing.T) { errShouldBe: "flag: help requested", }, - // test gno.mod download + // test `gno mod download` { args: []string{"mod", "download"}, testDir: "../../tests/integ/empty-dir", @@ -73,7 +80,7 @@ func TestModApp(t *testing.T) { errShouldContain: "fetch: writepackage: querychain", }, - // test gno.mod init with no module name + // test `gno mod init` with no module name { args: []string{"mod", "init"}, testDir: "../../tests/integ/valid1", @@ -110,7 +117,7 @@ func TestModApp(t *testing.T) { errShouldBe: "create gno.mod file: gno.mod file already exists", }, - // test gno.mod init with module name + // test `gno mod init` with module name { args: []string{"mod", "init", "gno.land/p/demo/foo"}, testDir: "../../tests/integ/empty-dir", @@ -137,6 +144,164 @@ func TestModApp(t *testing.T) { simulateExternalRepo: true, errShouldBe: "create gno.mod file: gno.mod file already exists", }, + + // test `gno mod tidy` with module name + { + args: []string{"mod", "tidy", "arg1"}, + testDir: "../../tests/integ/minimalist-gnomod", + simulateExternalRepo: true, + errShouldContain: "flag: help requested", + }, + { + args: []string{"mod", "tidy"}, + testDir: "../../tests/integ/empty-dir", + simulateExternalRepo: true, + errShouldContain: "could not read gno.mod file", + }, + { + args: []string{"mod", "tidy"}, + testDir: "../../tests/integ/invalid-module-version1", + simulateExternalRepo: true, + errShouldContain: "error parsing gno.mod file at", + }, + { + args: []string{"mod", "tidy"}, + testDir: "../../tests/integ/minimalist-gnomod", + simulateExternalRepo: true, + }, + { + args: []string{"mod", "tidy"}, + testDir: "../../tests/integ/require-remote-module", + simulateExternalRepo: true, + }, + { + args: []string{"mod", "tidy"}, + testDir: "../../tests/integ/valid2", + simulateExternalRepo: true, + }, + { + args: []string{"mod", "tidy"}, + testDir: "../../tests/integ/invalid-gno-file", + simulateExternalRepo: true, + errShouldContain: "expected 'package', found packag", + }, } testMainCaseRun(t, tc) } + +func TestGetGnoImports(t *testing.T) { + workingDir, err := os.Getwd() + require.NoError(t, err) + + // create external dir + tmpDir, cleanUpFn := createTmpDir(t) + defer cleanUpFn() + + // cd to tmp directory + os.Chdir(tmpDir) + defer os.Chdir(workingDir) + + files := []struct { + name, data string + }{ + { + name: "file1.gno", + data: ` + package tmp + + import ( + "std" + + "gno.land/p/demo/pkg1" + ) + `, + }, + { + name: "file2.gno", + data: ` + package tmp + + import ( + "gno.land/p/demo/pkg1" + "gno.land/p/demo/pkg2" + ) + `, + }, + { + name: "file1_test.gno", + data: ` + package tmp + + import ( + "testing" + + "gno.land/p/demo/testpkg" + ) + `, + }, + { + name: "z_0_filetest.gno", + data: ` + package main + + import ( + "gno.land/p/demo/filetestpkg" + ) + `, + }, + + // subpkg files + { + name: filepath.Join("subtmp", "file1.gno"), + data: ` + package subtmp + + import ( + "std" + + "gno.land/p/demo/subpkg1" + ) + `, + }, + { + name: filepath.Join("subtmp", "file2.gno"), + data: ` + package subtmp + + import ( + "gno.land/p/demo/subpkg1" + "gno.land/p/demo/subpkg2" + ) + `, + }, + } + + // Expected list of imports + // - ignore subdirs + // - ignore duplicate + // - ignore *_filetest.gno + // - should be sorted + expected := []string{ + "gno.land/p/demo/pkg1", + "gno.land/p/demo/pkg2", + "gno.land/p/demo/testpkg", + } + + // Create subpkg dir + err = os.Mkdir("subtmp", 0o700) + require.NoError(t, err) + + // Create files + for _, f := range files { + err = os.WriteFile(f.name, []byte(f.data), 0o644) + require.NoError(t, err) + } + + imports, err := getGnoImports(tmpDir) + require.NoError(t, err) + + require.Equal(t, len(expected), len(imports)) + for i := range imports { + assert.Equal(t, expected[i], imports[i]) + } +} diff --git a/gnovm/cmd/gno/precompile.go b/gnovm/cmd/gno/precompile.go index 7e895109706..4a4528001a2 100644 --- a/gnovm/cmd/gno/precompile.go +++ b/gnovm/cmd/gno/precompile.go @@ -47,7 +47,7 @@ func (p *precompileOptions) markAsPrecompiled(pkg importPath) { p.precompiled[pkg] = struct{}{} } -func newPrecompileCmd(io *commands.IO) *commands.Command { +func newPrecompileCmd(io commands.IO) *commands.Command { cfg := &precompileCfg{} return commands.NewCommand( @@ -107,7 +107,7 @@ func (c *precompileCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execPrecompile(cfg *precompileCfg, args []string, io *commands.IO) error { +func execPrecompile(cfg *precompileCfg, args []string, io commands.IO) error { if len(args) < 1 { return flag.ErrHelp } diff --git a/gnovm/cmd/gno/repl.go b/gnovm/cmd/gno/repl.go index 1acb96c3cb9..0a9d4934ce3 100644 --- a/gnovm/cmd/gno/repl.go +++ b/gnovm/cmd/gno/repl.go @@ -2,10 +2,11 @@ package main import ( "bufio" - "bytes" "context" + "errors" "flag" "fmt" + "go/scanner" "os" "strings" @@ -88,10 +89,10 @@ func execRepl(cfg *replCfg, args []string) error { // gno> import "gno.land/p/demo/avl" // import the p/demo/avl package // gno> func a() string { return "a" } // declare a new function named a // gno> /src // print current generated source -// gno> /editor // enter in editor mode to add several lines +// gno> /editor // enter in multi-line mode, end with ';' // gno> /reset // remove all previously inserted code // gno> println(a()) // print the result of calling a() -// gno> /exit +// gno> /exit // alternative to `) } @@ -99,30 +100,59 @@ func execRepl(cfg *replCfg, args []string) error { } func runRepl(cfg *replCfg) error { - // init repl state r := repl.NewRepl() if cfg.initialCommand != "" { handleInput(r, cfg.initialCommand) } - var multiline bool - for { - fmt.Fprint(os.Stdout, "gno> ") + fmt.Fprint(os.Stdout, "gno> ") - input, err := getInput(multiline) - if err != nil { - return err + inEdit := false + prev := "" + liner := bufio.NewScanner(os.Stdin) + + for liner.Scan() { + line := liner.Text() + + if l := strings.TrimSpace(line); l == ";" { + line, inEdit = "", false + } else if l == "/editor" { + line, inEdit = "", true + fmt.Fprintln(os.Stdout, "// enter a single ';' to quit and commit") + } + if prev != "" { + line = prev + "\n" + line + prev = "" + } + if inEdit { + fmt.Fprint(os.Stdout, "... ") + prev = line + continue } - multiline = handleInput(r, input) + if err := handleInput(r, line); err != nil { + var goScanError scanner.ErrorList + if errors.As(err, &goScanError) { + // We assune that a Go scanner error indicates an incomplete Go statement. + // Append next line and retry. + prev = line + } else { + fmt.Fprintln(os.Stderr, err) + } + } + + if prev == "" { + fmt.Fprint(os.Stdout, "gno> ") + } else { + fmt.Fprint(os.Stdout, "... ") + } } + return nil } -// handleInput reads the input string and parses it depending if it -// is a specific command, or source code. It returns true if the following -// input is expected to be on more than one line. -func handleInput(r *repl.Repl, input string) bool { +// handleInput executes specific "/" commands, or evaluates input as Gno source code. +func handleInput(r *repl.Repl, input string) error { switch strings.TrimSpace(input) { case "/reset": r.Reset() @@ -130,49 +160,14 @@ func handleInput(r *repl.Repl, input string) bool { fmt.Fprintln(os.Stdout, r.Src()) case "/exit": os.Exit(0) - case "/editor": - fmt.Fprintln(os.Stdout, "// Entering editor mode (^D to finish)") - return true case "": - // avoid to increase the repl execution counter if sending empty content - fmt.Fprintln(os.Stdout, "") - return false + // Avoid to increase the repl execution counter if no input. default: out, err := r.Process(input) if err != nil { - fmt.Fprintln(os.Stderr, err) + return err } fmt.Fprintln(os.Stdout, out) } - - return false -} - -const ( - inputBreaker = "^D" - nl = "\n" -) - -func getInput(ml bool) (string, error) { - s := bufio.NewScanner(os.Stdin) - var mlOut bytes.Buffer - for s.Scan() { - line := s.Text() - if !ml { - return line, nil - } - - if line == inputBreaker { - break - } - - mlOut.WriteString(line) - mlOut.WriteString(nl) - } - - if err := s.Err(); err != nil { - return "", err - } - - return mlOut.String(), nil + return nil } diff --git a/gnovm/cmd/gno/run.go b/gnovm/cmd/gno/run.go index 2c8d8c77350..d37c86df502 100644 --- a/gnovm/cmd/gno/run.go +++ b/gnovm/cmd/gno/run.go @@ -20,7 +20,7 @@ type runCfg struct { expr string } -func newRunCmd(io *commands.IO) *commands.Command { +func newRunCmd(io commands.IO) *commands.Command { cfg := &runCfg{} return commands.NewCommand( @@ -59,7 +59,7 @@ func (c *runCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execRun(cfg *runCfg, args []string, io *commands.IO) error { +func execRun(cfg *runCfg, args []string, io commands.IO) error { if len(args) == 0 { return flag.ErrHelp } @@ -68,9 +68,9 @@ func execRun(cfg *runCfg, args []string, io *commands.IO) error { cfg.rootDir = guessRootDir() } - stdin := io.In - stdout := io.Out - stderr := io.Err + stdin := io.In() + stdout := io.Out() + stderr := io.Err() // init store and machine testStore := tests.TestStore(cfg.rootDir, diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index d4b8dbb5486..af7984a2ebe 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -37,7 +37,7 @@ type testCfg struct { withNativeFallback bool } -func newTestCmd(io *commands.IO) *commands.Command { +func newTestCmd(io commands.IO) *commands.Command { cfg := &testCfg{} return commands.NewCommand( @@ -157,7 +157,7 @@ func (c *testCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execTest(cfg *testCfg, args []string, io *commands.IO) error { +func execTest(cfg *testCfg, args []string, io commands.IO) error { if len(args) < 1 { return flag.ErrHelp } @@ -279,7 +279,7 @@ func gnoTestPkg( unittestFiles, filetestFiles []string, cfg *testCfg, - io *commands.IO, + io commands.IO, ) error { var ( verbose = cfg.verbose @@ -287,9 +287,9 @@ func gnoTestPkg( runFlag = cfg.run printRuntimeMetrics = cfg.printRuntimeMetrics - stdin = io.In - stdout = io.Out - stderr = io.Err + stdin = io.In() + stdout = io.Out() + stderr = io.Err() errs error ) @@ -436,7 +436,7 @@ func runTestFiles( verbose bool, printRuntimeMetrics bool, runFlag string, - io *commands.IO, + io commands.IO, ) error { var errs error diff --git a/gnovm/cmd/gno/test_test.go b/gnovm/cmd/gno/test_test.go index f5b069a5f03..b1dcfb21d29 100644 --- a/gnovm/cmd/gno/test_test.go +++ b/gnovm/cmd/gno/test_test.go @@ -3,9 +3,23 @@ package main import ( "testing" + "github.com/gnolang/gno/gnovm/pkg/integration" "github.com/rogpeppe/go-internal/testscript" + "github.com/stretchr/testify/require" ) -func TestTest(t *testing.T) { - testscript.Run(t, setupTestScript(t, "testdata/gno_test")) +func Test_ScriptsTest(t *testing.T) { + p := testscript.Params{ + Dir: "testdata/gno_test", + } + + if coverdir, ok := integration.ResolveCoverageDir(); ok { + err := integration.SetupTestscriptsCoverage(&p, coverdir) + require.NoError(t, err) + } + + err := integration.SetupGno(&p, t.TempDir()) + require.NoError(t, err) + + testscript.Run(t, p) } diff --git a/gnovm/docs/go-gno-compatibility.md b/gnovm/docs/go-gno-compatibility.md index a39cec533f4..6ff433c056f 100644 --- a/gnovm/docs/go-gno-compatibility.md +++ b/gnovm/docs/go-gno-compatibility.md @@ -1,11 +1,7 @@ # Go<>Gno compatibility -**WIP: does not reflect the current state yet.** - ## Native keywords -Legend: full, partial, missing, TBD. - | keyword | support | |-------------|------------------------| | break | full | @@ -32,22 +28,27 @@ Legend: full, partial, missing, TBD. | type | full | | var | full | +Generics are currently not implemented. + ## Native types | type | usage | persistency | |-----------------------------------------------|------------------------|------------------------------------------------------------| | `bool` | full | full | | `byte` | full | full | -| `float32`, `float64` | full | full | | `int`, `int8`, `int16`, `int32`, `int64` | full | full | | `uint`, `uint8`, `uint16`, `uint32`, `uint64` | full | full | +| `float32`, `float64` | full | full | +| `complex64`, `complex128` | missing (TBD) | missing | +| `uintptr`, `unsafe.Pointer` | missing | missing | | `string` | full | full | | `rune` | full | full | | `interface{}` | full | full | -| `[]T` (slices) | full | full* | -| `map[T1]T2` | full | full* | +| `[]T` (slices) | full | full\* | +| `[N]T` (arrays) | full | full\* | +| `map[T1]T2` | full | full\* | | `func (T1...) T2...` | full | full (needs more tests) | -| `*T` (pointers) | full | full* | +| `*T` (pointers) | full | full\* | | `chan T` (channels) | missing (after launch) | missing (after launch) | **\*:** depends on `T`/`T1`/`T2` @@ -62,286 +63,221 @@ Additional native types: ## Stdlibs - +Legend: + +* `nondet`: the standard library in question would require non-deterministic + behaviour to implement as in Go, such as cryptographical randomness or + os/network access. The library may still be implemented at one point, with a + different API. +* `gospec`: the standard library is very Go-specific -- for instance, it is used + for debugging information or for parsing/build Go source code. A Gno version + may exist at one point, likely with a different package name or semantics. +* `gnics`: the standard library requires generics. +* `test`: the standard library is currently available for use exclusively in + test contexts, and may have limited functionality. +* `cmd`: the Go standard library is a command -- a direct equivalent in Gno + would not be useful. +* `tbd`: whether to include the standard library or not is still up for + discussion. +* `todo`: the standard libary is to be added, and + [contributions are welcome.](https://github.com/gnolang/gno/issues/1267) +* `part`: the standard library is partially implemented in Gno, and contributions are + welcome to add the missing functionality. +* `full`: the standard library is fully implemented in Gno. + + | package | status | |---------------------------------------------|----------| -| archive/tar | TBD | -| archive/zip | TBD | -| arena | TBD | -| bufio | TBD | -| builtin | TBD | -| bytes | TBD | -| cmd/addr2line | TBD | -| cmd/api | TBD | -| cmd/api/testdata/src/issue21181/dep | TBD | -| cmd/api/testdata/src/issue21181/indirect | TBD | -| cmd/api/testdata/src/issue21181/p | TBD | -| cmd/api/testdata/src/pkg/p1 | TBD | -| cmd/api/testdata/src/pkg/p2 | TBD | -| cmd/api/testdata/src/pkg/p3 | TBD | -| cmd/api/testdata/src/pkg/p4 | TBD | -| cmd/asm | TBD | -| cmd/buildid | TBD | -| cmd/cgo | TBD | -| cmd/compile | TBD | -| cmd/covdata | TBD | -| cmd/covdata/testdata | TBD | -| cmd/cover | TBD | -| cmd/cover/testdata | TBD | -| cmd/cover/testdata/html | TBD | -| cmd/cover/testdata/pkgcfg/a | TBD | -| cmd/cover/testdata/pkgcfg/b | TBD | -| cmd/cover/testdata/pkgcfg/main | TBD | -| cmd/dist | TBD | -| cmd/distpack | TBD | -| cmd/doc | TBD | -| cmd/doc/testdata | TBD | -| cmd/doc/testdata/merge | TBD | -| cmd/doc/testdata/nested | TBD | -| cmd/doc/testdata/nested/empty | TBD | -| cmd/doc/testdata/nested/nested | TBD | -| cmd/fix | TBD | -| cmd/go | TBD | -| cmd/gofmt | TBD | -| cmd/go/testdata | TBD | -| cmd/link | TBD | -| cmd/link/testdata/pe-binutils | TBD | -| cmd/link/testdata/pe-llvm | TBD | -| cmd/link/testdata/testBuildFortvOS | TBD | -| cmd/link/testdata/testHashedSyms | TBD | -| cmd/link/testdata/testIndexMismatch | TBD | -| cmd/link/testdata/testRO | TBD | -| cmd/nm | TBD | -| cmd/objdump | TBD | -| cmd/objdump/testdata | TBD | -| cmd/objdump/testdata/testfilenum | TBD | -| cmd/pack | TBD | -| cmd/pprof | TBD | -| cmd/pprof/testdata | TBD | -| cmd/test2json | TBD | -| cmd/trace | TBD | -| cmd/vet | TBD | -| cmd/vet/testdata/asm | TBD | -| cmd/vet/testdata/assign | TBD | -| cmd/vet/testdata/atomic | TBD | -| cmd/vet/testdata/bool | TBD | -| cmd/vet/testdata/buildtag | TBD | -| cmd/vet/testdata/cgo | TBD | -| cmd/vet/testdata/composite | TBD | -| cmd/vet/testdata/copylock | TBD | -| cmd/vet/testdata/deadcode | TBD | -| cmd/vet/testdata/directive | TBD | -| cmd/vet/testdata/httpresponse | TBD | -| cmd/vet/testdata/lostcancel | TBD | -| cmd/vet/testdata/method | TBD | -| cmd/vet/testdata/nilfunc | TBD | -| cmd/vet/testdata/print | TBD | -| cmd/vet/testdata/rangeloop | TBD | -| cmd/vet/testdata/shift | TBD | -| cmd/vet/testdata/structtag | TBD | -| cmd/vet/testdata/tagtest | TBD | -| cmd/vet/testdata/testingpkg | TBD | -| cmd/vet/testdata/unmarshal | TBD | -| cmd/vet/testdata/unsafeptr | TBD | -| cmd/vet/testdata/unused | TBD | -| compress/bzip2 | TBD | -| compress/flate | TBD | -| compress/gzip | TBD | -| compress/lzw | TBD | -| compress/zlib | TBD | -| container/heap | TBD | -| container/list | TBD | -| container/ring | TBD | -| context | TBD | -| crypto | TBD | -| crypto/aes | TBD | -| crypto/boring | TBD | -| crypto/cipher | TBD | -| crypto/des | TBD | -| crypto/dsa | TBD | -| crypto/ecdh | TBD | -| crypto/ecdsa | TBD | -| crypto/ed25519 | TBD | -| crypto/elliptic | TBD | -| crypto/hmac | TBD | -| crypto/md5 | TBD | -| crypto/rand | TBD | -| crypto/rc4 | TBD | -| crypto/rsa | TBD | -| crypto/sha1 | TBD | -| crypto/sha256 | TBD | -| crypto/sha512 | TBD | -| crypto/subtle | TBD | -| crypto/tls | TBD | -| crypto/tls/fipsonly | TBD | -| crypto/x509 | TBD | -| crypto/x509/pkix | TBD | -| database/sql | TBD | -| database/sql/driver | TBD | -| debug/buildinfo | TBD | -| debug/dwarf | TBD | -| debug/elf | TBD | -| debug/gosym | TBD | -| debug/gosym/testdata | TBD | -| debug/macho | TBD | -| debug/pe | TBD | -| debug/plan9obj | TBD | -| embed | TBD | -| encoding | TBD | -| encoding/ascii85 | TBD | -| encoding/asn1 | TBD | -| encoding/base32 | TBD | -| encoding/base64 | TBD | -| encoding/binary | partial | -| encoding/csv | TBD | -| encoding/gob | TBD | -| encoding/hex | TBD | -| encoding/json | TBD | -| encoding/pem | TBD | -| encoding/xml | TBD | -| errors | TBD | -| expvar | TBD | -| flag | TBD | -| fmt | TBD | -| go/ast | TBD | -| go/build | TBD | -| go/build/constraint | TBD | -| go/build/testdata/alltags | TBD | -| go/build/testdata/cgo_disabled | TBD | -| go/build/testdata/directives | TBD | -| go/build/testdata/doc | TBD | -| go/build/testdata/multi | TBD | -| go/build/testdata/non_source_tags | TBD | -| go/build/testdata/other | TBD | -| go/build/testdata/other/file | TBD | -| go/constant | TBD | -| go/doc | TBD | -| go/doc/comment | TBD | -| go/doc/testdata | TBD | -| go/doc/testdata/examples | TBD | -| go/doc/testdata/pkgdoc | TBD | -| go/format | TBD | -| go/importer | TBD | -| go/parser | TBD | -| go/parser/testdata/goversion | TBD | -| go/parser/testdata/issue42951 | TBD | -| go/parser/testdata/issue42951/not_a_file.go | TBD | -| go/printer | TBD | -| go/printer/testdata | TBD | -| go/scanner | TBD | -| go/token | TBD | -| go/types | TBD | -| go/types/testdata | TBD | -| go/types/testdata/local | TBD | -| hash | partial | -| hash/adler32 | full | -| hash/crc32 | TBD | -| hash/crc64 | TBD | -| hash/fnv | TBD | -| hash/maphash | TBD | -| html | TBD | -| html/template | TBD | -| image | TBD | -| image/color | TBD | -| image/color/palette | TBD | -| image/draw | TBD | -| image/gif | TBD | -| image/jpeg | TBD | -| image/png | TBD | -| index/suffixarray | TBD | -| io | TBD | -| io/fs | TBD | -| io/ioutil | TBD | -| log | TBD | -| log/internal | TBD | -| log/slog | TBD | -| log/slog/internal | TBD | -| log/syslog | TBD | -| maps | TBD | -| math | partial | -| math/big | TBD | -| math/bits | TBD | -| math/cmplx | TBD | -| math/rand | TBD | -| mime | TBD | -| mime/multipart | TBD | -| mime/quotedprintable | TBD | -| net | TBD | -| net/http | TBD | -| net/http/cgi | TBD | -| net/http/cookiejar | TBD | -| net/http/fcgi | TBD | -| net/http/httptest | TBD | -| net/http/httptrace | TBD | -| net/http/httputil | TBD | -| net/http/internal | TBD | -| net/http/pprof | TBD | -| net/mail | TBD | -| net/netip | TBD | -| net/rpc | TBD | -| net/rpc/jsonrpc | TBD | -| net/smtp | TBD | -| net/textproto | TBD | -| net/url | full | -| os | TBD | -| os/exec | TBD | -| os/signal | TBD | -| os/user | TBD | -| path | full | -| path/filepath | TBD | -| plugin | TBD | -| reflect | TBD | -| regexp | TBD | -| regexp/syntax | TBD | -| runtime | TBD | -| runtime/asan | TBD | -| runtime/cgo | TBD | -| runtime/coverage | TBD | -| runtime/coverage/testdata | TBD | -| runtime/coverage/testdata/issue56006 | TBD | -| runtime/debug | TBD | -| runtime/metrics | TBD | -| runtime/msan | TBD | -| runtime/pprof | TBD | -| runtime/pprof/testdata/mappingtest | TBD | -| runtime/race | TBD | -| runtime/race/testdata | TBD | -| runtime/testdata/testexithooks | TBD | -| runtime/testdata/testfaketime | TBD | -| runtime/testdata/testprog | TBD | -| runtime/testdata/testprogcgo | TBD | -| runtime/testdata/testprogcgo/windows | TBD | -| runtime/testdata/testprognet | TBD | -| runtime/testdata/testwinlib | TBD | -| runtime/testdata/testwinlibsignal | TBD | -| runtime/testdata/testwinlibthrow | TBD | -| runtime/testdata/testwinsignal | TBD | -| runtime/trace | TBD | -| slices | TBD | -| sort | TBD | -| strconv | TBD | -| strings | TBD | -| sync | TBD | -| sync/atomic | TBD | -| syscall | TBD | -| syscall/js | TBD | -| testing | TBD | -| testing/fstest | TBD | -| testing/iotest | TBD | -| testing/quick | TBD | -| text/scanner | TBD | -| text/tabwriter | TBD | -| text/template | TBD | -| text/template/parse | TBD | -| time | TBD | -| time/tzdata | TBD | -| unicode | TBD | -| unicode/utf16 | TBD | -| unicode/utf8 | TBD | -| unsafe | TBD | - +| archive/tar | `tbd` | +| archive/zip | `tbd` | +| arena | `improb` | +| bufio | `full` | +| builtin | `full`[^1] | +| bytes | `full` | +| cmd/\* | `cmd` | +| compress/bzip2 | `tbd` | +| compress/flate | `tbd` | +| compress/gzip | `tbd` | +| compress/lzw | `tbd` | +| compress/zlib | `tbd` | +| container/heap | `tbd` | +| container/list | `tbd` | +| container/ring | `tbd` | +| context | `tbd` | +| crypto | `todo` | +| crypto/aes | `todo` | +| crypto/boring | `tbd` | +| crypto/cipher | `part` | +| crypto/des | `tbd` | +| crypto/dsa | `tbd` | +| crypto/ecdh | `tbd` | +| crypto/ecdsa | `tbd` | +| crypto/ed25519 | `tbd` | +| crypto/elliptic | `tbd` | +| crypto/hmac | `todo` | +| crypto/md5 | `test`[^2] | +| crypto/rand | `nondet` | +| crypto/rc4 | `tbd` | +| crypto/rsa | `tbd` | +| crypto/sha1 | `test`[^2] | +| crypto/sha256 | `part`[^3] | +| crypto/sha512 | `tbd` | +| crypto/subtle | `tbd` | +| crypto/tls | `nondet` | +| crypto/tls/fipsonly | `nondet` | +| crypto/x509 | `tbd` | +| crypto/x509/pkix | `tbd` | +| database/sql | `nondet` | +| database/sql/driver | `nondet` | +| debug/buildinfo | `gospec` | +| debug/dwarf | `gospec` | +| debug/elf | `gospec` | +| debug/gosym | `gospec` | +| debug/macho | `gospec` | +| debug/pe | `gospec` | +| debug/plan9obj | `gospec` | +| embed | `tbd` | +| encoding | `full` | +| encoding/ascii85 | `todo` | +| encoding/asn1 | `todo` | +| encoding/base32 | `todo` | +| encoding/base64 | `full` | +| encoding/binary | `part` | +| encoding/csv | `todo` | +| encoding/gob | `tbd` | +| encoding/hex | `full` | +| encoding/json | `todo` | +| encoding/pem | `todo` | +| encoding/xml | `todo` | +| errors | `part` | +| expvar | `tbd` | +| flag | `nondet` | +| fmt | `test`[^4] | +| go/ast | `gospec` | +| go/build | `gospec` | +| go/build/constraint | `gospec` | +| go/constant | `gospec` | +| go/doc | `gospec` | +| go/doc/comment | `gospec` | +| go/format | `gospec` | +| go/importer | `gospec` | +| go/parser | `gospec` | +| go/printer | `gospec` | +| go/scanner | `gospec` | +| go/token | `gospec` | +| go/types | `gospec` | +| hash | `full` | +| hash/adler32 | `full` | +| hash/crc32 | `todo` | +| hash/crc64 | `todo` | +| hash/fnv | `todo` | +| hash/maphash | `todo` | +| html | `todo` | +| html/template | `todo` | +| image | `tbd` | +| image/color | `tbd` | +| image/color/palette | `tbd` | +| image/draw | `tbd` | +| image/gif | `tbd` | +| image/jpeg | `tbd` | +| image/png | `tbd` | +| index/suffixarray | `tbd` | +| io | `full` | +| io/fs | `tbd` | +| io/ioutil | removed[^5] | +| log | `tbd` | +| log/slog | `tbd` | +| log/syslog | `nondet` | +| maps | `gnics` | +| math | `part` | +| math/big | `tbd` | +| math/bits | `todo` | +| math/cmplx | `tbd` | +| math/rand | `todo` | +| mime | `tbd` | +| mime/multipart | `tbd` | +| mime/quotedprintable | `tbd` | +| net | `nondet` | +| net/http | `nondet` | +| net/http/cgi | `nondet` | +| net/http/cookiejar | `nondet` | +| net/http/fcgi | `nondet` | +| net/http/httptest | `nondet` | +| net/http/httptrace | `nondet` | +| net/http/httputil | `nondet` | +| net/http/internal | `nondet` | +| net/http/pprof | `nondet` | +| net/mail | `nondet` | +| net/netip | `nondet` | +| net/rpc | `nondet` | +| net/rpc/jsonrpc | `nondet` | +| net/smtp | `nondet` | +| net/textproto | `nondet` | +| net/url | `full` | +| os | `nondet` | +| os/exec | `nondet` | +| os/signal | `nondet` | +| os/user | `nondet` | +| path | `full` | +| path/filepath | `nondet` | +| plugin | `nondet` | +| reflect | `todo` | +| regexp | `full` | +| regexp/syntax | `full` | +| runtime | `gospec` | +| runtime/asan | `gospec` | +| runtime/cgo | `gospec` | +| runtime/coverage | `gospec` | +| runtime/debug | `gospec` | +| runtime/metrics | `gospec` | +| runtime/msan | `gospec` | +| runtime/pprof | `gospec` | +| runtime/race | `gospec` | +| runtime/trace | `gospec` | +| slices | `gnics` | +| sort | `part`[^6] | +| strconv | `part` | +| strings | `full` | +| sync | `tbd` | +| sync/atomic | `tbd` | +| syscall | `nondet` | +| syscall/js | `nondet` | +| testing | `part` | +| testing/fstest | `tbd` | +| testing/iotest | `tbd` | +| testing/quick | `tbd` | +| text/scanner | `todo` | +| text/tabwriter | `todo` | +| text/template | `todo` | +| text/template/parse | `todo` | +| time | `full`[^7] | +| time/tzdata | `tbd` | +| unicode | `full` | +| unicode/utf16 | `tbd` | +| unicode/utf8 | `full` | +| unsafe | `nondet` | +[^1]: `builtin` is a "fake" package that exists to document the behaviour of + some builtin functions. The "fake" package does not currently exist in Gno, + but [all functions up to Go 1.17 exist](https://pkg.go.dev/builtin@go1.17), + except for those relating to complex or channel types. +[^2]: `crypto/sha1` and `crypto/md5` implement "deprecated" hashing + algorithms, widely considered unsafe for cryptographic hashing. Decision on + whether to include these as part of the official standard libraries is still + pending. +[^3]: `crypto/sha256` is currently only implemented for `Sum256`, which should + still cover a majority of use cases. A full implementation is welcome. +[^4]: like many other encoding packages, `fmt` depends on `reflect` to be added. + For now, package `gno.land/p/demo/ufmt` may do what you need. In test + functions, `fmt` works. +[^5]: `io/ioutil` [is deprecated in Go.](https://pkg.go.dev/io/ioutil) + Its functionality has been moved to packages `os` and `io`. The functions + which have been moved in `io` are implemented in that package. +[^6]: `sort` has the notable omission of `sort.Slice`. You'll need to write a + bit of boilerplate, but you can use `sort.Interface` + `sort.Sort`! +[^7]: `time.Now` returns the block time rather than the system time, for + determinism. Concurrent functionality (such as `time.Ticker`) is not implemented. ## Tooling (`gno` binary) @@ -353,15 +289,16 @@ Additional native types: | go doc | gno doc | limited compatibility; see https://github.com/gnolang/gno/issues/522 | | go env | | | | go fix | | | -| go fmt | | | +| go fmt | | gofmt (& similar tools, like gofumpt) works on gno code. | | go generate | | | -| go get | | | -| go help | | | +| go get | | see `gno mod download`. | +| go help | gno $cmd --help | ie. `gno doc --help` | | go install | | | | go list | | | -| go mod | | | -| + go mod download | gno mod download | same behavior | +| go mod | gno mod | | | + go mod init | gno mod init | same behavior | +| + go mod download | gno mod download | same behavior | +| + go mod tidy | gno mod tidy | same behavior | | | gno precompile | | | go work | | | | | gno repl | | diff --git a/gnovm/pkg/doc/dirs.go b/gnovm/pkg/doc/dirs.go index 21216828ce4..19d312f6826 100644 --- a/gnovm/pkg/doc/dirs.go +++ b/gnovm/pkg/doc/dirs.go @@ -5,7 +5,6 @@ package doc import ( - "fmt" "log" "os" "path" @@ -52,7 +51,7 @@ func newDirs(dirs []string, modDirs []string) *bfsDirs { } for _, mdir := range modDirs { - gm, err := parseGnoMod(filepath.Join(mdir, "gno.mod")) + gm, err := gnomod.ParseGnoMod(filepath.Join(mdir, "gno.mod")) if err != nil { log.Printf("%v", err) continue @@ -68,34 +67,6 @@ func newDirs(dirs []string, modDirs []string) *bfsDirs { return d } -// tries to parse gno mod file given the filename, using Parse and Validate from -// the gnomod package -// -// TODO(tb): replace by `gnomod.ParseAt` ? The key difference is the latter -// looks for gno.mod in parent directories, while this function doesn't. -func parseGnoMod(fname string) (*gnomod.File, error) { - file, err := os.Stat(fname) - if err != nil { - return nil, fmt.Errorf("could not read gno.mod file: %w", err) - } - if file.IsDir() { - return nil, fmt.Errorf("invalid gno.mod at %q: is a directory", fname) - } - - b, err := os.ReadFile(fname) - if err != nil { - return nil, fmt.Errorf("could not read gno.mod file: %w", err) - } - gm, err := gnomod.Parse(fname, b) - if err != nil { - return nil, fmt.Errorf("error parsing gno.mod file at %q: %w", fname, err) - } - if err := gm.Validate(); err != nil { - return nil, fmt.Errorf("error validating gno.mod file at %q: %w", fname, err) - } - return gm, nil -} - func getGnoModDirs(gm *gnomod.File) []bfsDir { // cmd/go makes use of the go list command, we don't have that here. diff --git a/gnovm/pkg/gnolang/alloc_test.go b/gnovm/pkg/gnolang/alloc_test.go index e3b9f1cb069..dbb3903f862 100644 --- a/gnovm/pkg/gnolang/alloc_test.go +++ b/gnovm/pkg/gnolang/alloc_test.go @@ -6,6 +6,8 @@ import ( ) func TestAllocSizes(t *testing.T) { + t.Parallel() + // go elemental println("_allocPointer", unsafe.Sizeof(&StructValue{})) println("_allocSlice", unsafe.Sizeof([]byte("12345678901234567890123456789012345678901234567890"))) diff --git a/gnovm/pkg/gnolang/gno_test.go b/gnovm/pkg/gnolang/gno_test.go index 5ed5971c836..37b590b1c4c 100644 --- a/gnovm/pkg/gnolang/gno_test.go +++ b/gnovm/pkg/gnolang/gno_test.go @@ -13,6 +13,8 @@ import ( // run empty main(). func TestRunEmptyMain(t *testing.T) { + t.Parallel() + m := NewMachine("test", nil) main := FuncD("main", nil, nil, nil) m.RunDeclaration(main) @@ -21,6 +23,8 @@ func TestRunEmptyMain(t *testing.T) { // run main() with a for loop. func TestRunLoopyMain(t *testing.T) { + t.Parallel() + m := NewMachine("test", nil) c := `package test func main() { @@ -36,6 +40,8 @@ func main() { } func TestEval(t *testing.T) { + t.Parallel() + m := NewMachine("test", nil) c := `package test func next(i int) int { @@ -64,6 +70,8 @@ func assertOutput(t *testing.T, input string, output string) { } func TestRunMakeStruct(t *testing.T) { + t.Parallel() + assertOutput(t, `package test type Outfit struct { Scarf string @@ -90,6 +98,8 @@ func main() { } func TestRunReturnStruct(t *testing.T) { + t.Parallel() + assertOutput(t, `package test type MyStruct struct { FieldA string @@ -160,6 +170,8 @@ type Struct1 struct { } func TestModifyTypeAsserted(t *testing.T) { + t.Parallel() + x := Struct1{1, 1} var v interface{} = x x2 := v.(Struct1) @@ -176,6 +188,8 @@ type Interface1 interface { } func TestTypeConversion(t *testing.T) { + t.Parallel() + x := 1 var v interface{} = x if _, ok := v.(Interface1); ok { @@ -193,6 +207,8 @@ func TestTypeConversion(t *testing.T) { } func TestSomething(t *testing.T) { + t.Parallel() + type Foo struct { X interface{} } @@ -210,6 +226,8 @@ func TestSomething(t *testing.T) { // XXX is there a way to test in Go as well as Gno? func TestDeferOrder(t *testing.T) { + t.Parallel() + a := func() func(int, int) int { fmt.Println("a constructed") return func(x int, y int) int { @@ -238,6 +256,8 @@ func TestDeferOrder(t *testing.T) { // XXX is there a way to test in Go as well as Gno? func TestCallOrder(t *testing.T) { + t.Parallel() + a := func() func(int, int) int { fmt.Println("a constructed") return func(x int, y int) int { @@ -264,6 +284,8 @@ func TestCallOrder(t *testing.T) { // XXX is there a way to test in Go as well as Gno? func TestBinaryShortCircuit(t *testing.T) { + t.Parallel() + tr := func() bool { fmt.Println("t called") return true @@ -281,6 +303,8 @@ func TestBinaryShortCircuit(t *testing.T) { // XXX is there a way to test in Go as well as Gno? func TestSwitchDefine(t *testing.T) { + t.Parallel() + var x interface{} = 1 switch y := x.(type) { case int: @@ -292,6 +316,8 @@ func TestSwitchDefine(t *testing.T) { // XXX is there a way to test in Go as well as Gno? func TestBinaryCircuit(t *testing.T) { + t.Parallel() + tr := func() bool { fmt.Println("tr() called") return true @@ -316,6 +342,8 @@ func TestBinaryCircuit(t *testing.T) { } func TestMultiAssignment(t *testing.T) { + t.Parallel() + buf := make([]int, 4) ref := func(i int) *int { fmt.Printf("ref(%v) called\n", i) @@ -342,6 +370,8 @@ func TestMultiAssignment(t *testing.T) { // XXX is there a way to test in Go as well as Gno? func TestCallLHS(t *testing.T) { + t.Parallel() + x := 1 xptr := func() *int { return &x @@ -352,6 +382,8 @@ func TestCallLHS(t *testing.T) { // XXX is there a way to test in Go as well as Gno? func TestCallFieldLHS(t *testing.T) { + t.Parallel() + type str struct { X int } diff --git a/gnovm/pkg/gnolang/go2gno_test.go b/gnovm/pkg/gnolang/go2gno_test.go index 6a1413a07e1..d5b94c618b0 100644 --- a/gnovm/pkg/gnolang/go2gno_test.go +++ b/gnovm/pkg/gnolang/go2gno_test.go @@ -8,6 +8,8 @@ import ( ) func TestParseForLoop(t *testing.T) { + t.Parallel() + gocode := `package main func main(){ for i:=0; i<10; i++ { diff --git a/gnovm/pkg/gnolang/gonative_test.go b/gnovm/pkg/gnolang/gonative_test.go index b9b659aae99..e348ffe9c22 100644 --- a/gnovm/pkg/gnolang/gonative_test.go +++ b/gnovm/pkg/gnolang/gonative_test.go @@ -98,6 +98,8 @@ D: } func TestGoNativeDefine3(t *testing.T) { + t.Parallel() + // Create package foo and define Foo. out := new(bytes.Buffer) pkg := NewPackageNode("foo", "test.foo", nil) @@ -135,6 +137,8 @@ D: } func TestCrypto(t *testing.T) { + t.Parallel() + addr := crypto.Address{} store := gonativeTestStore() tv := Go2GnoValue(nilAllocator, store, reflect.ValueOf(addr)) diff --git a/gnovm/pkg/gnolang/helpers.go b/gnovm/pkg/gnolang/helpers.go index c16ea795ea3..4810a67304a 100644 --- a/gnovm/pkg/gnolang/helpers.go +++ b/gnovm/pkg/gnolang/helpers.go @@ -440,18 +440,6 @@ var ( precs = [][]string{prec1, prec2, prec3, prec4, prec5} ) -// 0 for prec1... -1 if no match. -func lowestMatch(op string) int { - for i, prec := range precs { - for _, op2 := range prec { - if op == op2 { - return i - } - } - } - return -1 -} - func Ss(b ...Stmt) []Stmt { return b } diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 46308fb3a02..2a9e0b51a97 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -4,7 +4,6 @@ import ( "fmt" "go/parser" "go/token" - "io/ioutil" "os" "path/filepath" "reflect" @@ -1095,7 +1094,7 @@ func PackageNameFromFileBody(name, body string) Name { // NOTE: panics if package name is invalid. func ReadMemPackage(dir string, pkgPath string) *std.MemPackage { - files, err := ioutil.ReadDir(dir) + files, err := os.ReadDir(dir) if err != nil { panic(err) } diff --git a/gnovm/pkg/gnolang/op_call.go b/gnovm/pkg/gnolang/op_call.go index f43a593c50e..8d652667111 100644 --- a/gnovm/pkg/gnolang/op_call.go +++ b/gnovm/pkg/gnolang/op_call.go @@ -154,7 +154,11 @@ func (m *Machine) doOpCall() { } // TODO: some more pt <> pv.Type // reconciliations/conversions necessary. - b.Values[i] = pv + + // Make a copy so that a reference to the arguemnt isn't used + // in cases where the non-primitive value type is represented + // as a pointer, *StructValue, for example. + b.Values[i] = pv.Copy(m.Alloc) } } diff --git a/gnovm/pkg/gnolang/package_test.go b/gnovm/pkg/gnolang/package_test.go index 47efd736bac..f219ba9b23f 100644 --- a/gnovm/pkg/gnolang/package_test.go +++ b/gnovm/pkg/gnolang/package_test.go @@ -12,6 +12,8 @@ import ( // Tries to reproduce the bug #1036 on all registered types func TestAminoJSONRegisteredTypes(t *testing.T) { + t.Parallel() + for _, typ := range Package.Types { // Instantiate registered type x := reflect.New(typ.Type).Interface() diff --git a/gnovm/pkg/gnolang/precompile.go b/gnovm/pkg/gnolang/precompile.go index f7a10d5589a..c3116f25800 100644 --- a/gnovm/pkg/gnolang/precompile.go +++ b/gnovm/pkg/gnolang/precompile.go @@ -7,7 +7,6 @@ import ( "go/format" "go/parser" "go/token" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -112,7 +111,7 @@ func GetPrecompileFilenameAndTags(gnoFilePath string) (targetFilename, tags stri func PrecompileAndCheckMempkg(mempkg *std.MemPackage) error { gofmt := "gofmt" - tmpDir, err := ioutil.TempDir("", mempkg.Name) + tmpDir, err := os.MkdirTemp("", mempkg.Name) if err != nil { return err } diff --git a/gnovm/pkg/gnolang/precompile_test.go b/gnovm/pkg/gnolang/precompile_test.go index 3d50353505f..e2cb5e92d86 100644 --- a/gnovm/pkg/gnolang/precompile_test.go +++ b/gnovm/pkg/gnolang/precompile_test.go @@ -12,6 +12,8 @@ import ( ) func TestPrecompile(t *testing.T) { + t.Parallel() + cases := []struct { name string source string @@ -56,6 +58,8 @@ func TestPrecompile(t *testing.T) { for _, c := range cases { c := c // scopelint t.Run(c.name, func(t *testing.T) { + t.Parallel() + // parse gno fset := token.NewFileSet() f, err := parser.ParseFile(fset, "foo.go", c.source, parser.ParseComments) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index e02a158fcf1..1a1edc41222 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -3338,23 +3338,6 @@ func elideCompositeExpr(vx *Expr, vt Type) { } } -// returns true of x is exactly `nil`. -func isNilExpr(x Expr) bool { - if nx, ok := x.(*NameExpr); ok { - return nx.Name == nilStr - } - return false -} - -func isNilComparableKind(k Kind) bool { - switch k { - case SliceKind, MapKind, FuncKind: - return true - default: - return false - } -} - // returns number of args, or if arg is a call result, // the number of results of the return tuple type. func countNumArgs(store Store, last BlockNode, n *CallExpr) (numArgs int) { @@ -3374,13 +3357,6 @@ func countNumArgs(store Store, last BlockNode, n *CallExpr) (numArgs int) { } } -func mergeNames(a, b []Name) []Name { - c := make([]Name, len(a)+len(b)) - copy(c, a) - copy(c[len(a):], b) - return c -} - // This is to be run *after* preprocessing is done, // to determine the order of var decl execution // (which may include functions which may refer to package vars). diff --git a/gnovm/pkg/gnolang/scanner.go b/gnovm/pkg/gnolang/scanner.go index 87695c0f346..f0b3f34c9ad 100644 --- a/gnovm/pkg/gnolang/scanner.go +++ b/gnovm/pkg/gnolang/scanner.go @@ -192,21 +192,3 @@ func (ss *scanner) advanceEscapeSequence() bool { return ss.done() } } - -// pops the next monoid term. -// The result is a string enclosed in balanced parentheses, -// brackets, or quotes; or what comes before such things. -// scanner doesn't understand operators, so a polynomial -// expression could be a single monoid as far as this scanner -// is concerned. TODO Chop functions should maybe use this. -func (ss *scanner) popMonoid() string { - startOut := ss.out() - start := ss.idx - for !ss.advance() { - if ss.out() != startOut { - end := ss.idx - return string(ss.rnz[start:end]) - } - } - panic("no monoid") -} diff --git a/gnovm/pkg/gnolang/store.go b/gnovm/pkg/gnolang/store.go index d3628edf216..24aff4936f3 100644 --- a/gnovm/pkg/gnolang/store.go +++ b/gnovm/pkg/gnolang/store.go @@ -11,8 +11,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/store" ) -const iavlCacheSize = 1024 * 1024 // TODO increase and parameterize. - // return nil if package doesn't exist. type PackageGetter func(pkgPath string) (*PackageNode, *PackageValue) @@ -626,7 +624,7 @@ func (ds *defaultStore) Flush() { // XXX } -//---------------------------------------- +// ---------------------------------------- // StoreOp type StoreOpType uint8 @@ -723,7 +721,7 @@ func (ds *defaultStore) Print() { } } -//---------------------------------------- +// ---------------------------------------- // backend keys func backendObjectKey(oid ObjectID) string { @@ -755,7 +753,7 @@ func backendPackagePathKey(path string) string { return fmt.Sprintf("pkg:" + path) } -//---------------------------------------- +// ---------------------------------------- // builtin types and packages func InitStoreCaches(store Store) { diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index c3e439e9427..6aed71fcf9b 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -879,7 +879,6 @@ type InterfaceType struct { } // General empty interface. -var gEmptyInterfaceType *InterfaceType = &InterfaceType{} func (it *InterfaceType) IsEmptyInterface() bool { return len(it.Methods) == 0 diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index 3de74ac0130..3bdd3332e08 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -500,7 +500,15 @@ func (sv *StructValue) Copy(alloc *Allocator) *StructValue { } */ fields := alloc.NewStructFields(len(sv.Fields)) - copy(fields, sv.Fields) + + // Each field needs to be copied individually to ensure that + // value fields are copied as such, even though they may be represented + // as pointers. A good example of this would be a struct that has + // a field that is an array. The value array is represented as a pointer. + for i, field := range sv.Fields { + fields[i] = field.Copy(alloc) + } + return alloc.NewStruct(fields) } diff --git a/gnovm/pkg/gnolang/values_conversions_test.go b/gnovm/pkg/gnolang/values_conversions_test.go index b9ac9e68d68..e92496c1ac2 100644 --- a/gnovm/pkg/gnolang/values_conversions_test.go +++ b/gnovm/pkg/gnolang/values_conversions_test.go @@ -9,6 +9,8 @@ import ( ) func TestConvertUntypedBigdecToFloat(t *testing.T) { + t.Parallel() + dst := &TypedValue{} dec, err := apd.New(-math.MaxInt64, -4).SetFloat64(math.SmallestNonzeroFloat64 / 2) diff --git a/gnovm/pkg/gnomod/file_test.go b/gnovm/pkg/gnomod/file_test.go index 7acea3a6096..0012960eb4f 100644 --- a/gnovm/pkg/gnomod/file_test.go +++ b/gnovm/pkg/gnomod/file_test.go @@ -20,11 +20,30 @@ func TestFetchDeps(t *testing.T) { for _, tc := range []struct { desc string modFile File + errorShouldContain string requirements []string stdOutContains []string cachedStdOutContains []string }{ { + desc: "not_exists", + modFile: File{ + Module: &modfile.Module{ + Mod: module.Version{ + Path: "testFetchDeps", + }, + }, + Require: []*modfile.Require{ + { + Mod: module.Version{ + Path: "gno.land/p/demo/does_not_exists", + Version: "v0.0.0", + }, + }, + }, + }, + errorShouldContain: "querychain (gno.land/p/demo/does_not_exists)", + }, { desc: "fetch_gno.land/p/demo/avl", modFile: File{ Module: &modfile.Module{ @@ -89,29 +108,34 @@ func TestFetchDeps(t *testing.T) { defer cleanUpFn() // Fetching dependencies - tc.modFile.FetchDeps(dirPath, testRemote, true) + err := tc.modFile.FetchDeps(dirPath, testRemote, true) + if tc.errorShouldContain != "" { + require.ErrorContains(t, err, tc.errorShouldContain) + } else { + require.Nil(t, err) - // Read dir - entries, err := os.ReadDir(filepath.Join(dirPath, "gno.land", "p", "demo")) - require.Nil(t, err) + // Read dir + entries, err := os.ReadDir(filepath.Join(dirPath, "gno.land", "p", "demo")) + require.Nil(t, err) - // Check dir entries - assert.Equal(t, len(tc.requirements), len(entries)) - for _, e := range entries { - assert.Contains(t, tc.requirements, e.Name()) - } + // Check dir entries + assert.Equal(t, len(tc.requirements), len(entries)) + for _, e := range entries { + assert.Contains(t, tc.requirements, e.Name()) + } - // Check logs - for _, c := range tc.stdOutContains { - assert.Contains(t, buf.String(), c) - } + // Check logs + for _, c := range tc.stdOutContains { + assert.Contains(t, buf.String(), c) + } - buf.Reset() + buf.Reset() - // Try fetching again. Should be cached - tc.modFile.FetchDeps(dirPath, testRemote, true) - for _, c := range tc.cachedStdOutContains { - assert.Contains(t, buf.String(), c) + // Try fetching again. Should be cached + tc.modFile.FetchDeps(dirPath, testRemote, true) + for _, c := range tc.cachedStdOutContains { + assert.Contains(t, buf.String(), c) + } } }) } diff --git a/gnovm/pkg/gnomod/gnomod.go b/gnovm/pkg/gnomod/gnomod.go index 7bb51d6558a..3c224bafb87 100644 --- a/gnovm/pkg/gnomod/gnomod.go +++ b/gnovm/pkg/gnomod/gnomod.go @@ -3,7 +3,6 @@ package gnomod import ( "errors" "fmt" - "io/ioutil" "os" "path/filepath" "strings" @@ -172,9 +171,9 @@ func CreateGnoModFile(rootDir, modPath string) error { if modPath == "" { // Check .gno files for package name // and use it as modPath - files, err := ioutil.ReadDir(rootDir) + files, err := os.ReadDir(rootDir) if err != nil { - fmt.Errorf("read dir %q: %w", rootDir, err) + return fmt.Errorf("read dir %q: %w", rootDir, err) } var pkgName gnolang.Name diff --git a/gnovm/pkg/gnomod/parse.go b/gnovm/pkg/gnomod/parse.go index 5bda3c31f70..a6314d5729f 100644 --- a/gnovm/pkg/gnomod/parse.go +++ b/gnovm/pkg/gnomod/parse.go @@ -42,6 +42,34 @@ func ParseAt(dir string) (*File, error) { return gm, nil } +// tries to parse gno mod file given the filename, using Parse and Validate from +// the gnomod package +// +// TODO(tb): replace by `gnomod.ParseAt` ? The key difference is the latter +// looks for gno.mod in parent directories, while this function doesn't. +func ParseGnoMod(fname string) (*File, error) { + file, err := os.Stat(fname) + if err != nil { + return nil, fmt.Errorf("could not read gno.mod file: %w", err) + } + if file.IsDir() { + return nil, fmt.Errorf("invalid gno.mod at %q: is a directory", fname) + } + + b, err := os.ReadFile(fname) + if err != nil { + return nil, fmt.Errorf("could not read gno.mod file: %w", err) + } + gm, err := Parse(fname, b) + if err != nil { + return nil, fmt.Errorf("error parsing gno.mod file at %q: %w", fname, err) + } + if err := gm.Validate(); err != nil { + return nil, fmt.Errorf("error validating gno.mod file at %q: %w", fname, err) + } + return gm, nil +} + // Parse parses and returns a gno.mod file. // // - file is the name of the file, used in positions and errors. diff --git a/gnovm/pkg/gnomod/parse_test.go b/gnovm/pkg/gnomod/parse_test.go index 934531e69c7..61aaa83482b 100644 --- a/gnovm/pkg/gnomod/parse_test.go +++ b/gnovm/pkg/gnomod/parse_test.go @@ -1,9 +1,12 @@ package gnomod import ( + "path/filepath" "testing" + "github.com/gnolang/gno/tm2/pkg/testutils" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestModuleDeprecated(t *testing.T) { @@ -167,3 +170,57 @@ func TestParseDraft(t *testing.T) { }) } } + +func TestParseGnoMod(t *testing.T) { + pkgDir := "bar" + for _, tc := range []struct { + desc, modData, modPath, errShouldContain string + }{ + { + desc: "file not exists", + modData: `module foo`, + modPath: filepath.Join(pkgDir, "mod.gno"), + errShouldContain: "could not read gno.mod file:", + }, + { + desc: "file path is dir", + modData: `module foo`, + modPath: pkgDir, + errShouldContain: "is a directory", + }, + { + desc: "valid gno.mod file", + modData: `module foo`, + modPath: filepath.Join(pkgDir, "gno.mod"), + }, + { + desc: "error parsing gno.mod", + modData: `module foo v0.0.0`, + modPath: filepath.Join(pkgDir, "gno.mod"), + errShouldContain: "error parsing gno.mod file at", + }, + { + desc: "error validating gno.mod", + modData: `require bar v0.0.0`, + modPath: filepath.Join(pkgDir, "gno.mod"), + errShouldContain: "error validating gno.mod file at", + }, + } { + t.Run(tc.desc, func(t *testing.T) { + // Create test dir + tempDir, cleanUpFn := testutils.NewTestCaseDir(t) + require.NotNil(t, tempDir) + defer cleanUpFn() + + // Create gno package + createGnoModPkg(t, tempDir, pkgDir, tc.modData) + + _, err := ParseGnoMod(filepath.Join(tempDir, tc.modPath)) + if tc.errShouldContain != "" { + assert.ErrorContains(t, err, tc.errShouldContain) + } else { + assert.NoError(t, err) + } + }) + } +} diff --git a/gnovm/pkg/gnomod/read.go b/gnovm/pkg/gnomod/read.go index 9bbed3c4651..e279d66344d 100644 --- a/gnovm/pkg/gnomod/read.go +++ b/gnovm/pkg/gnomod/read.go @@ -774,7 +774,7 @@ func parseReplace(filename string, line *modfile.Line, verb string, args []strin if strings.Contains(ns, "@") { return nil, errorf("replacement module must match format 'path version', not 'path@version'") } - return nil, errorf("replacement module without version must be directory path (rooted or starting with ./ or ../)") + return nil, errorf("replacement module without version must be directory path (rooted or starting with . or ..)") } if filepath.Separator == '/' && strings.Contains(ns, `\`) { return nil, errorf("replacement directory appears to be Windows path (on a non-windows system)") diff --git a/gnovm/pkg/integration/coverage.go b/gnovm/pkg/integration/coverage.go new file mode 100644 index 00000000000..017f5f9de88 --- /dev/null +++ b/gnovm/pkg/integration/coverage.go @@ -0,0 +1,68 @@ +package integration + +import ( + "flag" + "fmt" + "os" + "path/filepath" + + "github.com/rogpeppe/go-internal/testscript" +) + +var coverageEnv struct { + coverdir string +} + +func init() { + flag.StringVar(&coverageEnv.coverdir, + "txtarcoverdir", "", "write testscripts coverage intermediate files to this directory") +} + +// ResolveCoverageDir attempts to resolve the coverage directory from the 'TXTARCOVERDIR' +// environment variable first, and if not set, from the 'test.txtarcoverdir' flag. +// It returns the resolved directory and a boolean indicating if the resolution was successful. +func ResolveCoverageDir() (string, bool) { + // Attempt to resolve the cover directory from the environment variable or flag + coverdir := os.Getenv("TXTARCOVERDIR") + if coverdir == "" { + coverdir = coverageEnv.coverdir + } + + return coverdir, coverdir != "" +} + +// SetupTestscriptsCoverage sets up the given testscripts environment for coverage. +// It will mostly override `GOCOVERDIR` with the target cover directory +func SetupTestscriptsCoverage(p *testscript.Params, coverdir string) error { + // Check if the given coverage directory exist + info, err := os.Stat(coverdir) + if err != nil { + return fmt.Errorf("output directory %q inaccessible: %w", coverdir, err) + } else if !info.IsDir() { + return fmt.Errorf("output %q not a directory", coverdir) + } + + // We need to have an absolute path here, because current directory + // context will change while executing testscripts. + if !filepath.IsAbs(coverdir) { + var err error + if coverdir, err = filepath.Abs(coverdir); err != nil { + return fmt.Errorf("unable to determine absolute path of %q: %w", coverdir, err) + } + } + + // Backup the original setup function + origSetup := p.Setup + p.Setup = func(env *testscript.Env) error { + if origSetup != nil { + // Call previous setup first + origSetup(env) + } + + // Override `GOCOVEDIR` directory for sub-execution + env.Setenv("GOCOVERDIR", coverdir) + return nil + } + + return nil +} diff --git a/gnovm/pkg/integration/gno.go b/gnovm/pkg/integration/gno.go new file mode 100644 index 00000000000..56e18bbb5db --- /dev/null +++ b/gnovm/pkg/integration/gno.go @@ -0,0 +1,108 @@ +package integration + +import ( + "errors" + "fmt" + "os" + "os/exec" + "path/filepath" + "testing" + + osm "github.com/gnolang/gno/tm2/pkg/os" + "github.com/rogpeppe/go-internal/testscript" +) + +// SetupGno prepares the given testscript environment for tests that utilize the gno command. +// If the `gno` binary doesn't exist, it's built using the `go build` command into the specified buildDir. +// The function also include the `gno` command into `p.Cmds` to and wrap environment into p.Setup +// to correctly set up the environment variables needed for the `gno` command. +func SetupGno(p *testscript.Params, buildDir string) error { + // Try to fetch `GNOROOT` from the environment variables + gnoroot := os.Getenv("GNOROOT") + if gnoroot == "" { + // If `GNOROOT` isn't set, determine the root directory of github.com/gnolang/gno + goModPath, err := exec.Command("go", "env", "GOMOD").CombinedOutput() + if err != nil { + return fmt.Errorf("unable to determine gno root directory") + } + + gnoroot = filepath.Dir(string(goModPath)) + } + + if !osm.DirExists(buildDir) { + return fmt.Errorf("%q does not exist or is not a directory", buildDir) + } + + // Determine the path to the gno binary within the build directory + gnoBin := filepath.Join(buildDir, "gno") + if _, err := os.Stat(gnoBin); err != nil { + if !errors.Is(err, os.ErrNotExist) { + // Handle other potential errors from os.Stat + return err + } + + // Build a fresh gno binary in a temp directory + gnoArgsBuilder := []string{"build", "-o", gnoBin} + + // Forward `-covermode` settings if set + if coverMode := testing.CoverMode(); coverMode != "" { + gnoArgsBuilder = append(gnoArgsBuilder, "-covermode", coverMode) + } + + // Append the path to the gno command source + gnoArgsBuilder = append(gnoArgsBuilder, filepath.Join(gnoroot, "gnovm", "cmd", "gno")) + + if err = exec.Command("go", gnoArgsBuilder...).Run(); err != nil { + return fmt.Errorf("unable to build gno binary: %w", err) + } + } + + // Store the original setup scripts for potential wrapping + origSetup := p.Setup + p.Setup = func(env *testscript.Env) error { + // If there's an original setup, execute it + if origSetup != nil { + if err := origSetup(env); err != nil { + return err + } + } + + // Set the GNOROOT environment variable + env.Setenv("GNOROOT", gnoroot) + + // Create a temporary home directory because certain commands require access to $HOME/.cache/go-build + home, err := os.MkdirTemp("", "gno") + if err != nil { + return fmt.Errorf("unable to create temporary home directory: %w", err) + } + env.Setenv("HOME", home) + + // Cleanup home folder + env.Defer(func() { os.RemoveAll(home) }) + + return nil + } + + // Initialize cmds map if needed + if p.Cmds == nil { + p.Cmds = make(map[string]func(ts *testscript.TestScript, neg bool, args []string)) + } + + // Register the gno command for testscripts + p.Cmds["gno"] = func(ts *testscript.TestScript, neg bool, args []string) { + err := ts.Exec(gnoBin, args...) + if err != nil { + ts.Logf("gno command error: %v", err) + } + + commandSucceeded := (err == nil) + successExpected := !neg + + // Compare the command's success status with the expected outcome. + if commandSucceeded != successExpected { + ts.Fatalf("unexpected gno command outcome (err=%t expected=%t)", commandSucceeded, successExpected) + } + } + + return nil +} diff --git a/gnovm/pkg/repl/repl.go b/gnovm/pkg/repl/repl.go index 0f60b948f39..c7786cf08b0 100644 --- a/gnovm/pkg/repl/repl.go +++ b/gnovm/pkg/repl/repl.go @@ -161,7 +161,7 @@ func (r *Repl) Process(input string) (out string, err error) { return r.handleExpression(exp) } - return "", fmt.Errorf("error parsing code:\n\t- as expression (error: %q)\n\t- as declarations (error: %q)", expErr.Error(), declErr.Error()) + return "", fmt.Errorf("error parsing code:\n\t- as expression: %w\n\t- as declarations: %w", expErr, declErr) } func (r *Repl) handleExpression(e *ast.File) (string, error) { diff --git a/gnovm/pkg/repl/repl_test.go b/gnovm/pkg/repl/repl_test.go index 3c4d1f7c6c6..09c350dd49a 100644 --- a/gnovm/pkg/repl/repl_test.go +++ b/gnovm/pkg/repl/repl_test.go @@ -199,6 +199,8 @@ func TestRepl(t *testing.T) { } func TestReplOpts(t *testing.T) { + t.Parallel() + require := require.New(t) r := NewRepl(WithStd(nil, nil, nil), WithStore(nil)) @@ -212,6 +214,8 @@ func TestReplOpts(t *testing.T) { } func TestReplReset(t *testing.T) { + t.Parallel() + require := require.New(t) r := NewRepl() diff --git a/gnovm/stdlibs/io/export_test.gno b/gnovm/stdlibs/io/export_test.gno index fa3e8e76f61..6204ffc4591 100644 --- a/gnovm/stdlibs/io/export_test.gno +++ b/gnovm/stdlibs/io/export_test.gno @@ -5,4 +5,8 @@ package io // exported for test -var ErrInvalidWrite = errInvalidWrite +var ( + ErrInvalidWrite = errInvalidWrite + ErrWhence = errWhence + ErrOffset = errOffset +) diff --git a/gnovm/stdlibs/io/io.gno b/gnovm/stdlibs/io/io.gno index 54caf32cb95..6ee52cfe293 100644 --- a/gnovm/stdlibs/io/io.gno +++ b/gnovm/stdlibs/io/io.gno @@ -16,6 +16,8 @@ import ( "errors" ) +// TODO: implement rest of io package after sync package added. + // Seek whence values. const ( SeekStart = 0 // seek relative to the origin of the file @@ -477,6 +479,15 @@ func (l *LimitedReader) Read(p []byte) (n int, err error) { // NewSectionReader returns a SectionReader that reads from r // starting at offset off and stops with EOF after n bytes. func NewSectionReader(r ReaderAt, off int64, n int64) *SectionReader { + var remaining int64 + const maxInt64 = 1<<63 - 1 + if off <= maxInt64-n { + remaining = n + off + } else { + // Overflow, with no way to return error. + // Assume we can read up to an offset of `1<<63 - 1` bytes in this case. + remaining = maxInt64 + } return &SectionReader{r, off, off, off + n} } @@ -543,6 +554,53 @@ func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err error) { // Size returns the size of the section in bytes. func (s *SectionReader) Size() int64 { return s.limit - s.base } +// An OffsetWriter maps writers at offset base to offset base + off in the underlying writer. +type OffsetWriter struct { + w WriterAt + base int64 // the original offset + off int64 // the current offset +} + +// NewOffsetWriter returns a new OffsetWriter that writes to w starting at offset off. +func NewOffsetWriter(w WriterAt, off int64) *OffsetWriter { + return &OffsetWriter{w: w, off: off} +} + +func (o *OffsetWriter) Write(p []byte) (n int, err error) { + // n, err = o.w.WriterAt(p, o.off) + wa := o.w + n, err = wa.WriteAt(p, o.off) + o.off += int64(n) + return +} + +func (o *OffsetWriter) WriteAt(p []byte, off int64) (n int, err error) { + if off < 0 { + return 0, errOffset + } + + off += o.base + return o.w.WriteAt(p, off) +} + +func (o *OffsetWriter) Seek(offset int64, whence int) (int64, error) { + switch whence { + default: + return 0, errWhence + case SeekStart: + offset += o.base + case SeekCurrent: + offset += o.off + } + + if offset < o.base { + return 0, errOffset + } + + o.off = offset + return offset - o.base, nil +} + // TeeReader returns a Reader that writes to w what it reads from r. // All reads from r performed through it are matched with // corresponding writes to w. There is no internal buffering - @@ -614,7 +672,12 @@ func (discard) ReadFrom(r Reader) (n int64, err error) { // NopCloser returns a ReadCloser with a no-op Close method wrapping // the provided Reader r. +// If r implements WriterTo, the returned ReadCloser will implement WriterTo +// by forwarding calls to r. func NopCloser(r Reader) ReadCloser { + if _, ok := r.(WriterTo); ok { + return nopCloserWriterTo{r} + } return nopCloser{r} } @@ -624,6 +687,16 @@ type nopCloser struct { func (nopCloser) Close() error { return nil } +type nopCloserWriterTo struct { + Reader +} + +func (nopCloserWriterTo) Close() error { return nil } + +func (c nopCloserWriterTo) WriteTo(w Writer) (n int64, err error) { + return c.Reader.(WriterTo).WriteTo(w) +} + // ReadAll reads from r until an error or EOF and returns the data it read. // A successful call returns err == nil, not err == EOF. Because ReadAll is // defined to read from src until EOF, it does not treat an EOF from Read @@ -643,5 +716,9 @@ func ReadAll(r Reader) ([]byte, error) { } return b, err } + if len(b) == cap(b) { + // Add more capacity (let append pick how much). + b = append(b, 0)[:len(b)] + } } } diff --git a/gnovm/stdlibs/io/io_test.gno b/gnovm/stdlibs/io/io_test.gno index a97f6b8c075..613b7d13e35 100644 --- a/gnovm/stdlibs/io/io_test.gno +++ b/gnovm/stdlibs/io/io_test.gno @@ -1,14 +1,15 @@ +package io_test + // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package io_test - import ( "bytes" "errors" "fmt" "io" + "os" "strings" "testing" ) @@ -459,3 +460,84 @@ func TestCopyLargeWriter(t *testing.T) { t.Errorf("Copy error: got %v, want %v", err, want) } } + +func TestNopCloserWriterToForwarding(t *testing.T) { + for _, tc := range [...]struct { + Name string + r io.Reader + }{ + {"not a WriterTo", io.Reader(nil)}, + {"a WriterTo", struct { + io.Reader + io.WriterTo + }{}}, + } { + nc := io.NopCloser(tc.r) + + _, expected := tc.r.(io.WriterTo) + _, got := nc.(io.WriterTo) + if expected != got { + t.Errorf("NopCloser incorrectly forwards WriterTo for %s, got %t want %t", tc.Name, got, expected) + } + } +} + +// XXX os.CreateTemp is not available for now +// func TestOffsetWriter_Seek(t *testing.T) { +// tmpfilename := "TestOffsetWriter_Seek" +// tmpfile, err := os.CreateTemp(t.TempDir(), tmpfilename) +// if err != nil || tmpfile == nil { +// t.Fatalf("CreateTemp(%s) failed: %v", tmpfilename, err) +// } +// defer tmpfile.Close() +// w := NewOffsetWriter(tmpfile, 0) + +// // Should throw error errWhence if whence is not valid +// t.Run("errWhence", func(t *testing.T) { +// for _, whence := range []int{-3, -2, -1, 3, 4, 5} { +// var offset int64 = 0 +// gotOff, gotErr := w.Seek(offset, whence) +// if gotOff != 0 || gotErr != ErrWhence { +// t.Errorf("For whence %d, offset %d, OffsetWriter.Seek got: (%d, %v), want: (%d, %v)", +// whence, offset, gotOff, gotErr, 0, ErrWhence) +// } +// } +// }) + +// // Should throw error errOffset if offset is negative +// t.Run("errOffset", func(t *testing.T) { +// for _, whence := range []int{SeekStart, SeekCurrent} { +// for offset := int64(-3); offset < 0; offset++ { +// gotOff, gotErr := w.Seek(offset, whence) +// if gotOff != 0 || gotErr != ErrOffset { +// t.Errorf("For whence %d, offset %d, OffsetWriter.Seek got: (%d, %v), want: (%d, %v)", +// whence, offset, gotOff, gotErr, 0, ErrOffset) +// } +// } +// } +// }) + +// // Normal tests +// t.Run("normal", func(t *testing.T) { +// tests := []struct { +// offset int64 +// whence int +// returnOff int64 +// }{ +// // keep in order +// {whence: SeekStart, offset: 1, returnOff: 1}, +// {whence: SeekStart, offset: 2, returnOff: 2}, +// {whence: SeekStart, offset: 3, returnOff: 3}, +// {whence: SeekCurrent, offset: 1, returnOff: 4}, +// {whence: SeekCurrent, offset: 2, returnOff: 6}, +// {whence: SeekCurrent, offset: 3, returnOff: 9}, +// } +// for idx, tt := range tests { +// gotOff, gotErr := w.Seek(tt.offset, tt.whence) +// if gotOff != tt.returnOff || gotErr != nil { +// t.Errorf("%d:: For whence %d, offset %d, OffsetWriter.Seek got: (%d, %v), want: (%d, )", +// idx+1, tt.whence, tt.offset, gotOff, gotErr, tt.returnOff) +// } +// } +// }) +// } diff --git a/gnovm/stdlibs/io/ioutil/ioutil.gno b/gnovm/stdlibs/io/ioutil/ioutil.gno deleted file mode 100644 index 935031c0511..00000000000 --- a/gnovm/stdlibs/io/ioutil/ioutil.gno +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package ioutil implements some I/O utility functions. -// -// As of Go 1.16, the same functionality is now provided -// by package io or package os, and those implementations -// should be preferred in new code. -// See the specific function documentation for details. -package ioutil - -import ( - "io" -) - -// ReadAll reads from r until an error or EOF and returns the data it read. -// A successful call returns err == nil, not err == EOF. Because ReadAll is -// defined to read from src until EOF, it does not treat an EOF from Read -// as an error to be reported. -// -// As of Go 1.16, this function simply calls io.ReadAll. -func ReadAll(r io.Reader) ([]byte, error) { - return io.ReadAll(r) -} - -/* XXX os and os/fs removed. -// ReadFile reads the file named by filename and returns the contents. -// A successful call returns err == nil, not err == EOF. Because ReadFile -// reads the whole file, it does not treat an EOF from Read as an error -// to be reported. -// -// As of Go 1.16, this function simply calls os.ReadFile. -func ReadFile(filename string) ([]byte, error) { - return os.ReadFile(filename) -} - -// WriteFile writes data to a file named by filename. -// If the file does not exist, WriteFile creates it with permissions perm -// (before umask); otherwise WriteFile truncates it before writing, without changing permissions. -// -// As of Go 1.16, this function simply calls os.WriteFile. -func WriteFile(filename string, data []byte, perm fs.FileMode) error { - return os.WriteFile(filename, data, perm) -} - -// ReadDir reads the directory named by dirname and returns -// a list of fs.FileInfo for the directory's contents, -// sorted by filename. If an error occurs reading the directory, -// ReadDir returns no directory entries along with the error. -// -// As of Go 1.16, os.ReadDir is a more efficient and correct choice: -// it returns a list of fs.DirEntry instead of fs.FileInfo, -// and it returns partial results in the case of an error -// midway through reading a directory. -func ReadDir(dirname string) ([]fs.FileInfo, error) { - f, err := os.Open(dirname) - if err != nil { - return nil, err - } - list, err := f.Readdir(-1) - f.Close() - if err != nil { - return nil, err - } - sort.Slice(list, func(i, j int) bool { return list[i].Name() < list[j].Name() }) - return list, nil -} -*/ - -// NopCloser returns a ReadCloser with a no-op Close method wrapping -// the provided Reader r. -// -// As of Go 1.16, this function simply calls io.NopCloser. -func NopCloser(r io.Reader) io.ReadCloser { - return io.NopCloser(r) -} - -// Discard is an io.Writer on which all Write calls succeed -// without doing anything. -// -// As of Go 1.16, this value is simply io.Discard. -var Discard io.Writer = io.Discard diff --git a/gnovm/stdlibs/io/multi_test.gno b/gnovm/stdlibs/io/multi_test.gno index ee800b3ec24..31345279318 100644 --- a/gnovm/stdlibs/io/multi_test.gno +++ b/gnovm/stdlibs/io/multi_test.gno @@ -1,9 +1,9 @@ +package io_test + // Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package io_test - import ( "bytes" "crypto/sha1" diff --git a/gnovm/stdlibs/stdlibs.go b/gnovm/stdlibs/stdlibs.go index fb230a0cf86..8931266eb9a 100644 --- a/gnovm/stdlibs/stdlibs.go +++ b/gnovm/stdlibs/stdlibs.go @@ -581,13 +581,3 @@ func typedByteArray(ln int, bz *gno.ArrayValue) gno.TypedValue { tv := gno.TypedValue{T: &gno.ArrayType{Len: ln, Elt: gno.Uint8Type}, V: bz} return tv } - -func typedByteSlice(bz *gno.SliceValue) gno.TypedValue { - tv := gno.TypedValue{T: &gno.SliceType{Elt: gno.Uint8Type}, V: bz} - return tv -} - -func typedNil(t gno.Type) gno.TypedValue { - tv := gno.TypedValue{T: t, V: nil} - return tv -} diff --git a/gnovm/tests/backup/cli1.gno b/gnovm/tests/backup/cli1.gno index 8eb9e8c40d7..843eb461ac2 100644 --- a/gnovm/tests/backup/cli1.gno +++ b/gnovm/tests/backup/cli1.gno @@ -2,7 +2,7 @@ package main import ( "fmt" - "io/ioutil" + "io" "log" "net" "net/http" @@ -13,7 +13,7 @@ func client(uri string) { if err != nil { log.Fatal(err) } - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } diff --git a/gnovm/tests/backup/cli2.gno b/gnovm/tests/backup/cli2.gno index a9e8e53be3a..0be01d2f1a9 100644 --- a/gnovm/tests/backup/cli2.gno +++ b/gnovm/tests/backup/cli2.gno @@ -2,7 +2,7 @@ package main import ( "fmt" - "io/ioutil" + "io" "log" "net" "net/http" @@ -21,7 +21,7 @@ func client(uri string) { if err != nil { log.Fatal(err) } - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } diff --git a/gnovm/tests/backup/cli3.gno b/gnovm/tests/backup/cli3.gno index 1c696d4bc4c..50b11b9e4c3 100644 --- a/gnovm/tests/backup/cli3.gno +++ b/gnovm/tests/backup/cli3.gno @@ -2,7 +2,7 @@ package main import ( "fmt" - "io/ioutil" + "io" "log" "net/http" "net/http/httptest" @@ -13,7 +13,7 @@ func client(uri string) { if err != nil { log.Fatal(err) } - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } diff --git a/gnovm/tests/backup/cli4.gno b/gnovm/tests/backup/cli4.gno index 147b63c3e6e..aab6405917c 100644 --- a/gnovm/tests/backup/cli4.gno +++ b/gnovm/tests/backup/cli4.gno @@ -2,7 +2,7 @@ package main import ( "fmt" - "io/ioutil" + "io" "log" "net/http" "net/http/httptest" @@ -40,7 +40,7 @@ func client(uri string) { if err != nil { log.Fatal(err) } - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } diff --git a/gnovm/tests/backup/cli5.gno b/gnovm/tests/backup/cli5.gno index a2e1787c996..6b536841a6d 100644 --- a/gnovm/tests/backup/cli5.gno +++ b/gnovm/tests/backup/cli5.gno @@ -2,7 +2,7 @@ package main import ( "fmt" - "io/ioutil" + "io" "log" "net/http" "net/http/httptest" @@ -40,7 +40,7 @@ func client(uri string) { if err != nil { log.Fatal(err) } - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } diff --git a/gnovm/tests/backup/cli6.gno b/gnovm/tests/backup/cli6.gno index 89ae9f8b98d..e97da82736e 100644 --- a/gnovm/tests/backup/cli6.gno +++ b/gnovm/tests/backup/cli6.gno @@ -2,7 +2,7 @@ package main import ( "fmt" - "io/ioutil" + "io" "log" "net/http" "net/http/httptest" @@ -41,7 +41,7 @@ func client(uri string) { if err != nil { log.Fatal(err) } - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } diff --git a/gnovm/tests/backup/file_access.gno b/gnovm/tests/backup/file_access.gno index 6d750c44a36..e81cc6a0bee 100644 --- a/gnovm/tests/backup/file_access.gno +++ b/gnovm/tests/backup/file_access.gno @@ -2,12 +2,11 @@ package main import ( "fmt" - "io/ioutil" - "os" + "io" ) func main() { - file, err := ioutil.TempFile("", "yeagibench") + file, err := io.TempFile("", "yeagibench") if err != nil { panic(err) } diff --git a/gnovm/tests/backup/ioutil.gno b/gnovm/tests/backup/ioutil.gno deleted file mode 100644 index eae22b6ea5a..00000000000 --- a/gnovm/tests/backup/ioutil.gno +++ /dev/null @@ -1,16 +0,0 @@ -package main - -import ( - "fmt" - "os" -) - -func main() { - _, err := os.ReadFile("__NotExisting__") - if err != nil { - fmt.Println(err.Error()) - } -} - -// Output: -// open __NotExisting__: no such file or directory diff --git a/gnovm/tests/backup/issue-558.gno b/gnovm/tests/backup/issue-558.gno index d36bb4e18a7..e99566f7634 100644 --- a/gnovm/tests/backup/issue-558.gno +++ b/gnovm/tests/backup/issue-558.gno @@ -4,7 +4,7 @@ import ( "errors" "fmt" "io" - "io/ioutil" + "io" "log" "strings" ) @@ -37,7 +37,7 @@ type pipe struct { func newReadAutoCloser(r io.Reader) readAutoCloser { if _, ok := r.(io.Closer); !ok { - return readAutoCloser{ioutil.NopCloser(r)} + return readAutoCloser{io.NopCloser(r)} } return readAutoCloser{r.(io.ReadCloser)} } @@ -45,7 +45,7 @@ func newReadAutoCloser(r io.Reader) readAutoCloser { func main() { p := &pipe{} p.Reader = newReadAutoCloser(strings.NewReader("test")) - b, err := ioutil.ReadAll(p.Reader) + b, err := io.ReadAll(p.Reader) if err != nil { log.Fatal(err) } diff --git a/gnovm/tests/files/ioutil0.gno b/gnovm/tests/files/io2.gno similarity index 88% rename from gnovm/tests/files/ioutil0.gno rename to gnovm/tests/files/io2.gno index 800d237be22..24655f5040c 100644 --- a/gnovm/tests/files/ioutil0.gno +++ b/gnovm/tests/files/io2.gno @@ -2,7 +2,7 @@ package main import ( "fmt" - "io/ioutil" + "io" "log" "strings" ) @@ -10,7 +10,7 @@ import ( func main() { r := strings.NewReader("Go is a general-purpose language designed with systems programming in mind.") - b, err := ioutil.ReadAll(r) + b, err := io.ReadAll(r) if err != nil { log.Fatal(err) } diff --git a/gnovm/tests/files/issue-1096.gno b/gnovm/tests/files/issue-1096.gno new file mode 100644 index 00000000000..b0593913401 --- /dev/null +++ b/gnovm/tests/files/issue-1096.gno @@ -0,0 +1,87 @@ +package main + +import "fmt" + +type X struct { + Array [8]int + Test bool +} + +type Y [8]int + +func main() { + x := X{} + x.Array[1] = 888 + println(x.Array[1]) + println(x.Array[2]) + println(x.Test) + + x.manip() + println(x.Array[1]) + println(x.Array[2]) + println(x.Test) + + println("-----") + + y := Y{} + y[1] = 888 + println(y[1]) + println(y[2]) + + y.manip() + println(y[1]) + println(y[2]) + println("-----") + + x = X{} + println(x.Array[1]) + println(x.Array[2]) + println(x.Test) + + x.Array[1] = 888 + println(x.Array[1]) + println(x.Array[2]) + println(x.Test) + + manip(x) + println(x.Array[1]) + println(x.Array[2]) + println(x.Test) +} + +func (x X) manip() { + x.Array[2] = 999 + x.Test = true +} + +func manip(x X) { + x.Array[2] = 999 + x.Test = true +} + +func (y Y) manip() { + y[2] = 111 +} + +// Output: +// 888 +// 0 +// false +// 888 +// 0 +// false +// ----- +// 888 +// 0 +// 888 +// 0 +// ----- +// 0 +// 0 +// false +// 888 +// 0 +// false +// 888 +// 0 +// false diff --git a/gnovm/tests/files/issue-558b.gno b/gnovm/tests/files/issue-558b.gno index 686c73b5c88..55eba88c985 100644 --- a/gnovm/tests/files/issue-558b.gno +++ b/gnovm/tests/files/issue-558b.gno @@ -3,7 +3,7 @@ package main import ( "fmt" "io" - "io/ioutil" + "io" "log" "strings" ) @@ -36,7 +36,7 @@ type pipe struct { func newReadAutoCloser(r io.Reader) readAutoCloser { if _, ok := r.(io.Closer); !ok { - return readAutoCloser{ioutil.NopCloser(r)} + return readAutoCloser{io.NopCloser(r)} } return readAutoCloser{r.(io.ReadCloser)} } diff --git a/gnovm/tests/imports.go b/gnovm/tests/imports.go index fc2820ce00e..0741d0b466a 100644 --- a/gnovm/tests/imports.go +++ b/gnovm/tests/imports.go @@ -20,7 +20,6 @@ import ( "image" "image/color" "io" - "io/ioutil" "log" "math" "math/big" @@ -356,16 +355,13 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri case "io": pkg := gno.NewPackageNode("io", pkgPath, nil) pkg.DefineGoNativeValue("EOF", io.EOF) + pkg.DefineGoNativeValue("NopCloser", io.NopCloser) pkg.DefineGoNativeValue("ReadFull", io.ReadFull) + pkg.DefineGoNativeValue("ReadAll", io.ReadAll) pkg.DefineGoNativeType(reflect.TypeOf((*io.ReadCloser)(nil)).Elem()) pkg.DefineGoNativeType(reflect.TypeOf((*io.Closer)(nil)).Elem()) pkg.DefineGoNativeType(reflect.TypeOf((*io.Reader)(nil)).Elem()) return pkg, pkg.NewPackage() - case "io/ioutil": - pkg := gno.NewPackageNode("ioutil", pkgPath, nil) - pkg.DefineGoNativeValue("NopCloser", ioutil.NopCloser) - pkg.DefineGoNativeValue("ReadAll", ioutil.ReadAll) - return pkg, pkg.NewPackage() case "log": pkg := gno.NewPackageNode("log", pkgPath, nil) pkg.DefineGoNativeValue("Fatal", log.Fatal) diff --git a/gnovm/tests/integ/invalid-gno-file/gno.mod b/gnovm/tests/integ/invalid-gno-file/gno.mod new file mode 100644 index 00000000000..060e28b9dc4 --- /dev/null +++ b/gnovm/tests/integ/invalid-gno-file/gno.mod @@ -0,0 +1 @@ +module test diff --git a/gnovm/tests/integ/invalid-gno-file/invalid.gno b/gnovm/tests/integ/invalid-gno-file/invalid.gno new file mode 100644 index 00000000000..1e4ff406ada --- /dev/null +++ b/gnovm/tests/integ/invalid-gno-file/invalid.gno @@ -0,0 +1 @@ +packag invalid diff --git a/gnovm/tests/integ/valid2/gno.mod b/gnovm/tests/integ/valid2/gno.mod new file mode 100644 index 00000000000..98a5a0dacc1 --- /dev/null +++ b/gnovm/tests/integ/valid2/gno.mod @@ -0,0 +1,3 @@ +module gno.land/p/integ/valid + +require gno.land/p/demo/avl v0.0.0-latest diff --git a/gnovm/tests/integ/valid2/valid.gno b/gnovm/tests/integ/valid2/valid.gno new file mode 100644 index 00000000000..4de283f5d87 --- /dev/null +++ b/gnovm/tests/integ/valid2/valid.gno @@ -0,0 +1,11 @@ +package valid + +import ( + "gno.land/p/demo/avl" +) + +const Foo = "foo" + +func DoNothing(t *avl.Tree) { + // noop +} diff --git a/gnovm/tests/integ/valid2/valid_test.gno b/gnovm/tests/integ/valid2/valid_test.gno new file mode 100644 index 00000000000..2394da5c5ae --- /dev/null +++ b/gnovm/tests/integ/valid2/valid_test.gno @@ -0,0 +1,11 @@ +package valid + +import ( + "testing" + + "gno.land/p/integ/valid" +) + +func TestAlwaysValid(t *testing.T) { + _ = valid.Foo +} diff --git a/gnovm/tests/integ/valid2/z_0_filetest.gno b/gnovm/tests/integ/valid2/z_0_filetest.gno new file mode 100644 index 00000000000..06ab7d0f9a3 --- /dev/null +++ b/gnovm/tests/integ/valid2/z_0_filetest.gno @@ -0,0 +1 @@ +package main diff --git a/gnovm/tests/selector_test.go b/gnovm/tests/selector_test.go index 4d6e9c587b0..1f0b400555b 100644 --- a/gnovm/tests/selector_test.go +++ b/gnovm/tests/selector_test.go @@ -52,6 +52,8 @@ func _printValue(x interface{}) { } func TestSelectors(t *testing.T) { + t.Parallel() + x0 := struct{ F0 int }{1} _printValue(x0.F0) // *ST.F0 // F:0 diff --git a/go.mod b/go.mod index 5cc274f82b4..f8b1ecf669b 100644 --- a/go.mod +++ b/go.mod @@ -15,8 +15,8 @@ require ( github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 github.com/golang/protobuf v1.5.3 github.com/google/gofuzz v1.2.0 - github.com/gorilla/mux v1.8.0 - github.com/gorilla/websocket v1.5.0 + github.com/gorilla/mux v1.8.1 + github.com/gorilla/websocket v1.5.1 github.com/gotuna/gotuna v0.6.0 github.com/jaekwon/testify v1.6.1 github.com/jmhodges/levigo v1.0.0 @@ -30,10 +30,10 @@ require ( github.com/rs/cors v1.10.1 github.com/stretchr/testify v1.8.4 github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c - go.etcd.io/bbolt v1.3.7 + go.etcd.io/bbolt v1.3.8 go.uber.org/multierr v1.9.0 golang.org/x/crypto v0.14.0 - golang.org/x/mod v0.13.0 + golang.org/x/mod v0.14.0 golang.org/x/net v0.17.0 golang.org/x/term v0.13.0 golang.org/x/tools v0.13.0 diff --git a/go.sum b/go.sum index 0be3496a422..b9ab94d490c 100644 --- a/go.sum +++ b/go.sum @@ -85,14 +85,15 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/gorilla/csrf v1.7.0/go.mod h1:+a/4tCmqhG6/w4oafeAZ9pEa3/NZOWYVbD9fV0FwIQA= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/gotuna/gotuna v0.6.0 h1:N1lQKXEi/lwRp8u3sccTYLhzOffA4QasExz/1M5Riws= github.com/gotuna/gotuna v0.6.0/go.mod h1:F/ecRt29ChB6Ycy1AFIBpBiMNK0j7Heq+gFbLWquhjc= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= @@ -177,8 +178,8 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1: github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= -go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= +go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= @@ -201,8 +202,8 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= diff --git a/misc/docker-integration/integration_test.go b/misc/docker-integration/integration_test.go index 6ae0ea1d36e..1142709cc16 100644 --- a/misc/docker-integration/integration_test.go +++ b/misc/docker-integration/integration_test.go @@ -29,6 +29,8 @@ const ( ) func TestDockerIntegration(t *testing.T) { + t.Parallel() + tmpdir, err := os.MkdirTemp(os.TempDir(), "*-gnoland-integration") require.NoError(t, err) diff --git a/misc/list-gnophers/main.sh b/misc/list-gnophers/main.sh index beb90d4c767..0b230e97948 100755 --- a/misc/list-gnophers/main.sh +++ b/misc/list-gnophers/main.sh @@ -1,12 +1,13 @@ #!/bin/sh main() { + cd "$(dirname "$0")" cd ../.. + fname="$(mktemp --tmpdir gno_file_commits.XXXXXXXXXX.csv)" for file in $(list_gno_files); do extract_file_metadata $file - done > gno_file_commits.csv - echo - cat gno_file_commits.csv | sort_by_date | unique_by_author + done > "$fname" + cat "$fname" | sort_by_date | unique_by_author } list_gno_files() { diff --git a/misc/logos/buffer.go b/misc/logos/buffer.go index 90665f79bfd..81e8d1abc75 100644 --- a/misc/logos/buffer.go +++ b/misc/logos/buffer.go @@ -7,7 +7,7 @@ import ( "github.com/gdamore/tcell/v2" ) -//---------------------------------------- +// ---------------------------------------- // Buffer // A Buffer is a buffer area in which to draw. @@ -82,7 +82,7 @@ func (bb *Buffer) DrawToScreen(s tcell.Screen) { } } -//---------------------------------------- +// ---------------------------------------- // Cell // A terminal character cell. @@ -131,10 +131,6 @@ var gDefaultSpaceTStyle = tcell.StyleDefault. Dim(true). Background(tcell.ColorGray) -var gDefaultTStyle = gDefaultStyle.GetTStyle(). - Foreground(gDefaultForeground). - Background(gDefaultBackground) - // This is where a bit of dynamic logic is performed, // namely where the attr is used to derive the final style. func (cc *Cell) GetTCellContent() (mainc rune, combc []rune, tstyle tcell.Style) { @@ -161,7 +157,7 @@ func (cc *Cell) GetTCellContent() (mainc rune, combc []rune, tstyle tcell.Style) return } -//---------------------------------------- +// ---------------------------------------- // View // analogy: "Buffer:View :: array:slice". @@ -205,7 +201,7 @@ func (bs View) GetCell(x, y int) *Cell { ) } -//---------------------------------------- +// ---------------------------------------- // BufferedView // A view onto an element. diff --git a/misc/logos/cmd/logos.go b/misc/logos/cmd/logos.go index 228895f852d..3a374fecba2 100644 --- a/misc/logos/cmd/logos.go +++ b/misc/logos/cmd/logos.go @@ -10,11 +10,6 @@ import ( "github.com/gnolang/gno/misc/logos" ) -var ( - row = 0 - style = tcell.StyleDefault -) - func main() { encoding.Register() diff --git a/misc/logos/debug.go b/misc/logos/debug.go deleted file mode 100644 index 8b2a4692bf4..00000000000 --- a/misc/logos/debug.go +++ /dev/null @@ -1,26 +0,0 @@ -package logos - -import ( - "fmt" -) - -// NOTE: the golang compiler doesn't seem to be intelligent -// enough to remove steps when const debug is True, -// so it is still faster to first check the truth value -// before calling debug.Println or debug.Printf. - -const debug debugging = false // or flip - -type debugging bool - -func (d debugging) Println(args ...interface{}) { - if d { - fmt.Println(append([]interface{}{"DEBUG:"}, args...)...) - } -} - -func (d debugging) Printf(format string, args ...interface{}) { - if d { - fmt.Printf("DEBUG: "+format, args...) - } -} diff --git a/misc/logos/types.go b/misc/logos/types.go index 944f02515d3..96e983992eb 100644 --- a/misc/logos/types.go +++ b/misc/logos/types.go @@ -7,7 +7,7 @@ import ( "github.com/gdamore/tcell/v2" ) -//---------------------------------------- +// ---------------------------------------- // Page // A Page has renderable Elem(ents). @@ -389,7 +389,7 @@ func (pg *Page) DecCursor(isVertical bool) { } } -//---------------------------------------- +// ---------------------------------------- // TextElem type TextElem struct { @@ -474,8 +474,6 @@ func (tel *TextElem) Render() (updated bool) { return true } -var ctr = 0 - func (tel *TextElem) Draw(offset Coord, view View) { minX, maxX, minY, maxY := computeIntersection(tel.Size, offset, view.Bounds) for y := minY; y < maxY; y++ { @@ -494,7 +492,7 @@ func (tel *TextElem) ProcessEventKey(ev *EventKey) bool { return false // TODO: clipboard. } -//---------------------------------------- +// ---------------------------------------- // misc. type Color = tcell.Color @@ -728,7 +726,7 @@ func (tt *Attrs) Merge(ot *Attrs) { tt.Other = ot.Other // TODO merge by key. } -//---------------------------------------- +// ---------------------------------------- // AttrFlags // NOTE: AttrFlags are merged with a simple or-assign op. @@ -752,7 +750,7 @@ type KVPair struct { Value interface{} } -//---------------------------------------- +// ---------------------------------------- // computeIntersection() // els: element size @@ -812,7 +810,7 @@ func computeIntersection(els Size, elo Coord, vws Size) (minX, maxX, minY, maxY return } -//---------------------------------------- +// ---------------------------------------- // Misc simple types type Padding struct { diff --git a/misc/logos/unicode.go b/misc/logos/unicode.go index 3bdb46cd88b..924edecc2c5 100644 --- a/misc/logos/unicode.go +++ b/misc/logos/unicode.go @@ -4,7 +4,7 @@ func isCombining(r rune) bool { return inTable(r, combining) } -//---------------------------------------- +// ---------------------------------------- // from https://github.com/mattn/go-runewidth // runewidth doesn't expose whether a character is combining or not. // TODO might as well fork both runewidth and tcell. @@ -62,15 +62,6 @@ type interval struct { type table []interval -func inTables(r rune, ts ...table) bool { - for _, t := range ts { - if inTable(r, t) { - return true - } - } - return false -} - func inTable(r rune, t table) bool { if r < t[0].first { return false diff --git a/tm2/pkg/amino/amino_test.go b/tm2/pkg/amino/amino_test.go index a06601a43da..d7dd0dc5b98 100644 --- a/tm2/pkg/amino/amino_test.go +++ b/tm2/pkg/amino/amino_test.go @@ -10,6 +10,8 @@ import ( ) func TestMarshal(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() type SimpleStruct struct { @@ -35,6 +37,8 @@ func TestMarshal(t *testing.T) { } func TestUnmarshalReader(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() type SimpleStruct struct { @@ -65,6 +69,8 @@ type stringWrapper struct { } func TestUnmarshalReaderSize(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() s1 := stringWrapper{"foo"} @@ -82,6 +88,8 @@ func TestUnmarshalReaderSize(t *testing.T) { } func TestUnmarshalReaderSizeLimit(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() s1 := stringWrapper{"foo"} @@ -101,6 +109,8 @@ func TestUnmarshalReaderSizeLimit(t *testing.T) { } func TestUnmarshalReaderTooLong(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() type SimpleStruct struct { @@ -125,6 +135,8 @@ func TestUnmarshalReaderTooLong(t *testing.T) { } func TestUnmarshalBufferedWritesReads(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() buf := bytes.NewBuffer(nil) @@ -155,6 +167,8 @@ func TestUnmarshalBufferedWritesReads(t *testing.T) { } func TestBoolPointers(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() type SimpleStruct struct { BoolPtrTrue *bool diff --git a/tm2/pkg/amino/binary_decode.go b/tm2/pkg/amino/binary_decode.go index 8ac4161cede..333994d60b0 100644 --- a/tm2/pkg/amino/binary_decode.go +++ b/tm2/pkg/amino/binary_decode.go @@ -12,14 +12,6 @@ const bdOptionByte = 0x01 // ---------------------------------------- // cdc.decodeReflectBinary -var ErrOverflowInt = errors.New("encoded integer value overflows int(32)") - -const ( - // architecture dependent int limits: - maxInt = int(^uint(0) >> 1) - minInt = -maxInt - 1 -) - // This is the main entrypoint for decoding all types from binary form. This // function calls decodeReflectBinary*, and generally those functions should // only call this one, for overrides all happen here. diff --git a/tm2/pkg/amino/binary_encode_test.go b/tm2/pkg/amino/binary_encode_test.go index 8208bb74c67..a775a911cf6 100644 --- a/tm2/pkg/amino/binary_encode_test.go +++ b/tm2/pkg/amino/binary_encode_test.go @@ -8,6 +8,8 @@ import ( ) func TestEncodeFieldNumberAndTyp3_1(t *testing.T) { + t.Parallel() + buf := new(bytes.Buffer) err := encodeFieldNumberAndTyp3(buf, 1, Typ3ByteLength) assert.Nil(t, err) @@ -15,6 +17,8 @@ func TestEncodeFieldNumberAndTyp3_1(t *testing.T) { } func TestEncodeFieldNumberAndTyp3_2(t *testing.T) { + t.Parallel() + buf := new(bytes.Buffer) err := encodeFieldNumberAndTyp3(buf, 2, Typ3ByteLength) assert.Nil(t, err) diff --git a/tm2/pkg/amino/binary_test.go b/tm2/pkg/amino/binary_test.go index 8516ac2e1fa..e50427afeef 100644 --- a/tm2/pkg/amino/binary_test.go +++ b/tm2/pkg/amino/binary_test.go @@ -12,6 +12,8 @@ import ( ) func TestNilSliceEmptySlice(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() type TestStruct struct { @@ -59,6 +61,8 @@ func TestNilSliceEmptySlice(t *testing.T) { } func TestNewFieldBackwardsCompatibility(t *testing.T) { + t.Parallel() + type V1 struct { String string String2 string @@ -109,6 +113,8 @@ func TestNewFieldBackwardsCompatibility(t *testing.T) { } func TestWriteEmpty(t *testing.T) { + t.Parallel() + type Inner struct { Val int } @@ -136,6 +142,8 @@ func TestWriteEmpty(t *testing.T) { } func TestForceWriteEmpty(t *testing.T) { + t.Parallel() + type InnerWriteEmpty struct { // sth. that isn't zero-len if default, e.g. fixed32: ValIn int32 `amino:"write_empty" binary:"fixed32"` @@ -158,6 +166,8 @@ func TestForceWriteEmpty(t *testing.T) { } func TestStructSlice(t *testing.T) { + t.Parallel() + type Foo struct { A uint B uint @@ -182,6 +192,8 @@ func TestStructSlice(t *testing.T) { } func TestStructPointerSlice1(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() type Foo struct { @@ -220,6 +232,8 @@ func TestStructPointerSlice1(t *testing.T) { // Like TestStructPointerSlice2, but without nil_elements field tag. func TestStructPointerSlice2(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() type Foo struct { @@ -251,6 +265,8 @@ func TestStructPointerSlice2(t *testing.T) { } func TestBasicTypes(t *testing.T) { + t.Parallel() + // we explicitly disallow type definitions like the following: type byteAlias []byte @@ -268,6 +284,8 @@ func TestBasicTypes(t *testing.T) { } func TestUnmarshalMapBinary(t *testing.T) { + t.Parallel() + obj := new(map[string]int) cdc := amino.NewCodec() @@ -291,6 +309,8 @@ func TestUnmarshalMapBinary(t *testing.T) { } func TestUnmarshalFuncBinary(t *testing.T) { + t.Parallel() + obj := func() {} cdc := amino.NewCodec() // Binary doesn't support decoding to a func... @@ -316,6 +336,8 @@ func TestUnmarshalFuncBinary(t *testing.T) { } func TestDuration(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() d0 := time.Duration(0) bz := cdc.MustMarshal(d0) diff --git a/tm2/pkg/amino/byteslice_test.go b/tm2/pkg/amino/byteslice_test.go index 310b294a8b7..80faca8e4e9 100644 --- a/tm2/pkg/amino/byteslice_test.go +++ b/tm2/pkg/amino/byteslice_test.go @@ -6,6 +6,8 @@ import ( ) func TestReadByteSliceEquality(t *testing.T) { + t.Parallel() + var encoded []byte var err error cdc := NewCodec() diff --git a/tm2/pkg/amino/codec_test.go b/tm2/pkg/amino/codec_test.go index 7e025f73271..9368d4ef40e 100644 --- a/tm2/pkg/amino/codec_test.go +++ b/tm2/pkg/amino/codec_test.go @@ -29,6 +29,8 @@ func newSimpleStruct() SimpleStruct { } func TestMarshalUnmarshalPointer0(t *testing.T) { + t.Parallel() + s := newSimpleStruct() cdc := amino.NewCodec() b, err := cdc.MarshalSized(s) // no indirection @@ -41,6 +43,8 @@ func TestMarshalUnmarshalPointer0(t *testing.T) { } func TestMarshalUnmarshalPointer1(t *testing.T) { + t.Parallel() + s := newSimpleStruct() cdc := amino.NewCodec() b, err := cdc.MarshalSized(&s) // extra indirection @@ -53,6 +57,8 @@ func TestMarshalUnmarshalPointer1(t *testing.T) { } func TestMarshalUnmarshalPointer2(t *testing.T) { + t.Parallel() + s := newSimpleStruct() ptr := &s cdc := amino.NewCodec() @@ -63,6 +69,8 @@ func TestMarshalUnmarshalPointer2(t *testing.T) { } func TestMarshalUnmarshalPointer3(t *testing.T) { + t.Parallel() + s := newSimpleStruct() cdc := amino.NewCodec() b, err := cdc.MarshalSized(s) // no indirection @@ -75,6 +83,8 @@ func TestMarshalUnmarshalPointer3(t *testing.T) { } func TestDecodeVarint8(t *testing.T) { + t.Parallel() + // DecodeVarint8 uses binary.Varint so we need to make // sure that all the values out of the range of [-128, 127] // return an error. @@ -122,6 +132,8 @@ func TestDecodeVarint8(t *testing.T) { } func TestDecodeVarint16(t *testing.T) { + t.Parallel() + // DecodeVarint16 uses binary.Varint so we need to make // sure that all the values out of the range of [-32768, 32767] // return an error. @@ -170,6 +182,8 @@ func TestDecodeVarint16(t *testing.T) { } func TestEncodeDecodeString(t *testing.T) { + t.Parallel() + s := "🔌🎉⛵︎♠️⎍" bs := []byte(s) di := len(bs) * 3 / 4 @@ -214,8 +228,7 @@ func TestEncodeDecodeString(t *testing.T) { } func TestCodecSeal(t *testing.T) { - type Foo interface{} - type Bar interface{} + t.Parallel() cdc := amino.NewCodec() cdc.Seal() diff --git a/tm2/pkg/amino/deep_copy_test.go b/tm2/pkg/amino/deep_copy_test.go index 55aff4c6a60..f2a793bfca1 100644 --- a/tm2/pkg/amino/deep_copy_test.go +++ b/tm2/pkg/amino/deep_copy_test.go @@ -15,6 +15,8 @@ func (dcf *DCFoo1) MarshalAmino() (string, error) { return dcf.a, nil } func (dcf *DCFoo1) UnmarshalAmino(s string) error { dcf.a = s; return nil } func TestDeepCopyFoo1(t *testing.T) { + t.Parallel() + dcf1 := newDCFoo1("foobar") dcf2 := amino.DeepCopy(dcf1).(*DCFoo1) assert.Equal(t, "foobar", dcf2.a) @@ -27,6 +29,8 @@ func (dcf DCFoo2) MarshalAmino() (string, error) { return dcf.a, nil } // non-p func (dcf *DCFoo2) UnmarshalAmino(s string) error { dcf.a = s; return nil } func TestDeepCopyFoo2(t *testing.T) { + t.Parallel() + dcf1 := newDCFoo2("foobar") dcf2 := amino.DeepCopy(dcf1).(*DCFoo2) assert.Equal(t, "foobar", dcf2.a) @@ -39,6 +43,8 @@ func (dcf DCFoo3) MarshalAmino() (string, error) { return dcf.a, nil } func (dcf *DCFoo3) UnmarshalAmino(s []byte) error { dcf.a = string(s); return nil } // mismatch type func TestDeepCopyFoo3(t *testing.T) { + t.Parallel() + dcf1 := newDCFoo3("foobar") dcf2 := amino.DeepCopy(dcf1).(*DCFoo3) assert.Equal(t, "", dcf2.a) @@ -52,6 +58,8 @@ func (dcf DCFoo4) MarshalAmino() (string, error) { return dcf.a, nil } func (dcf *DCFoo4) UnmarshalAmino(s string) error { dcf.a = s; return nil } // mismatch type func TestDeepCopyFoo4(t *testing.T) { + t.Parallel() + dcf1 := newDCFoo4("foobar") dcf2 := amino.DeepCopy(dcf1).(*DCFoo4) assert.Equal(t, "good", dcf2.a) @@ -65,6 +73,8 @@ func (dcf DCFoo5) MarshalAmino() (string, error) { return dcf.a, nil } func (dcf *DCFoo5) UnmarshalAmino(s string) error { dcf.a = s; return nil } // mismatch type func TestDeepCopyFoo5(t *testing.T) { + t.Parallel() + dcf1 := newDCFoo5("foobar") dcf2 := amino.DeepCopy(dcf1).(*DCFoo5) assert.Equal(t, "good", dcf2.a) @@ -76,6 +86,8 @@ func newDCFoo6(a string) *DCFoo6 { return &DCFoo6{a: a} } func (dcf *DCFoo6) DeepCopy() DCFoo6 { return DCFoo6{"good"} } func TestDeepCopyFoo6(t *testing.T) { + t.Parallel() + dcf1 := newDCFoo6("foobar") dcf2 := amino.DeepCopy(dcf1).(*DCFoo6) assert.Equal(t, "good", dcf2.a) @@ -87,6 +99,8 @@ func newDCFoo7(a string) *DCFoo7 { return &DCFoo7{a: a} } func (dcf DCFoo7) DeepCopy() *DCFoo7 { return &DCFoo7{"good"} } func TestDeepCopyFoo7(t *testing.T) { + t.Parallel() + dcf1 := newDCFoo7("foobar") dcf2 := amino.DeepCopy(dcf1).(*DCFoo7) assert.Equal(t, "good", dcf2.a) @@ -99,6 +113,8 @@ func (dcf DCFoo8) MarshalAmino() (string, error) { return "", errors.New("uh oh func (dcf *DCFoo8) UnmarshalAmino(s string) error { dcf.a = s; return nil } func TestDeepCopyFoo8(t *testing.T) { + t.Parallel() + dcf1 := newDCFoo8("foobar") assert.Panics(t, func() { amino.DeepCopy(dcf1) }) } @@ -110,6 +126,8 @@ func (dcf DCFoo9) MarshalAmino() (string, error) { return dcf.a, nil } func (dcf *DCFoo9) UnmarshalAmino(s string) error { return errors.New("uh oh") } // error func TestDeepCopyFoo9(t *testing.T) { + t.Parallel() + dcf1 := newDCFoo9("foobar") assert.Panics(t, func() { amino.DeepCopy(dcf1) }) } @@ -119,12 +137,16 @@ type DCInterface1 struct { } func TestDeepCopyInterface1(t *testing.T) { + t.Parallel() + dci1 := DCInterface1{Foo: nil} dci2 := amino.DeepCopy(dci1).(DCInterface1) assert.Nil(t, dci2.Foo) } func TestDeepCopyInterface2(t *testing.T) { + t.Parallel() + dci1 := DCInterface1{Foo: "foo"} dci2 := amino.DeepCopy(dci1).(DCInterface1) assert.Equal(t, "foo", dci2.Foo) diff --git a/tm2/pkg/amino/encoder_test.go b/tm2/pkg/amino/encoder_test.go index 5c8afc4833d..02ece6fd667 100644 --- a/tm2/pkg/amino/encoder_test.go +++ b/tm2/pkg/amino/encoder_test.go @@ -7,6 +7,8 @@ import ( ) func TestUvarintSize(t *testing.T) { + t.Parallel() + testCases := []struct { name string u uint64 @@ -22,7 +24,10 @@ func TestUvarintSize(t *testing.T) { {"64 bits", 1 << 63, 10}, } for i, tc := range testCases { + tc := tc t.Run(tc.name, func(t *testing.T) { + t.Parallel() + require.Equal(t, tc.want, UvarintSize(tc.u), "#%d", i) //nolint:scopelint }) } diff --git a/tm2/pkg/amino/gengo/gengo_test.go b/tm2/pkg/amino/gengo/gengo_test.go index 88b25d9acdd..404b1c77c23 100644 --- a/tm2/pkg/amino/gengo/gengo_test.go +++ b/tm2/pkg/amino/gengo/gengo_test.go @@ -15,6 +15,8 @@ type SampleStruct struct { } func TestBasic(t *testing.T) { + t.Parallel() + p := press.NewPress() fmt.Println(p) ss := SampleStruct{"cat", "dog"} diff --git a/tm2/pkg/amino/genproto/bindings.go b/tm2/pkg/amino/genproto/bindings.go index 458d8b14578..5d587870a7d 100644 --- a/tm2/pkg/amino/genproto/bindings.go +++ b/tm2/pkg/amino/genproto/bindings.go @@ -105,7 +105,7 @@ func generateMethodsForType(imports *ast.GenDecl, scope *ast.Scope, pkg *amino.P } dpbote_ := pbote_[1:] - ////////////////// + // ----------- // ToPBMessage() { scope2 := ast.NewScope(scope) @@ -127,7 +127,7 @@ func generateMethodsForType(imports *ast.GenDecl, scope *ast.Scope, pkg *amino.P )) } - ////////////////// + // ----------- // EmptyPBMessage() // Use to create the pbm to proto.Unmarshal to before FromPBMessage. { @@ -148,7 +148,7 @@ func generateMethodsForType(imports *ast.GenDecl, scope *ast.Scope, pkg *amino.P )) } - ////////////////// + // ----------- // FromPBMessage() { scope2 := ast.NewScope(scope) @@ -169,7 +169,7 @@ func generateMethodsForType(imports *ast.GenDecl, scope *ast.Scope, pkg *amino.P )) } - ////////////////// + // ----------- // TypeUrl() { methods = append(methods, _func("GetTypeURL", @@ -182,7 +182,7 @@ func generateMethodsForType(imports *ast.GenDecl, scope *ast.Scope, pkg *amino.P )) } - ////////////////// + // ----------- // Is*ReprEmpty() { rinfo := info.ReprType @@ -965,7 +965,7 @@ func isReprEmptyStmts(rootPkg *amino.Package, isRoot bool, imports *ast.GenDecl, return b } -//---------------------------------------- +// ---------------------------------------- // other.... // Splits a Go expression into left and right parts. @@ -1013,7 +1013,7 @@ func chopRight(expr string) (left string, tok rune, right string) { return } -//---------------------------------------- +// ---------------------------------------- // AST Construction (Expr) func _i(name string) *ast.Ident { @@ -1023,14 +1023,6 @@ func _i(name string) *ast.Ident { return &ast.Ident{Name: name} } -func _iOrNil(name string) *ast.Ident { - if name == "" { - return nil - } else { - return _i(name) - } -} - // recvTypeName is empty if there are no receivers. // recvTypeName cannot contain any dots. func _func(name string, recvRef string, recvTypeName string, params *ast.FieldList, results *ast.FieldList, b *ast.BlockStmt) *ast.FuncDecl { @@ -1344,29 +1336,6 @@ func _x(expr string, args ...interface{}) ast.Expr { // 3 == != < <= > >= // 2 && // 1 || -var sp = " " - -var ( - prec5 = strings.Split("* / % << >> & &^", sp) - prec4 = strings.Split("+ - | ^", sp) - prec3 = strings.Split("== != < <= > >=", sp) - prec2 = strings.Split("&&", sp) - prec1 = strings.Split("||", sp) - precs = [][]string{prec1, prec2, prec3, prec4, prec5} -) - -// 0 for prec1... -1 if no match. -func lowestMatch(op string) int { - for i, prec := range precs { - for _, op2 := range prec { - if op == op2 { - return i - } - } - } - return -1 -} - func _kv(k, v interface{}) *ast.KeyValueExpr { var kx, vx ast.Expr if ks, ok := k.(string); ok { @@ -1391,10 +1360,6 @@ func _block(b ...ast.Stmt) *ast.BlockStmt { } } -func _xs(exprs ...ast.Expr) []ast.Expr { - return exprs -} - // Usage: _a(lhs1, lhs2, ..., ":=", rhs1, rhs2, ...) // Token can be ":=", "=", "+=", etc. // Other strings are automatically parsed as _x(arg). @@ -1470,13 +1435,6 @@ func _call(fn ast.Expr, args ...ast.Expr) *ast.CallExpr { } } -func _ta(x ast.Expr, t ast.Expr) *ast.TypeAssertExpr { - return &ast.TypeAssertExpr{ - X: x, - Type: t, - } -} - func _sel(x ast.Expr, sel string) *ast.SelectorExpr { return &ast.SelectorExpr{ X: x, @@ -1532,7 +1490,7 @@ func _sl(x ast.Expr) *ast.ArrayType { } } -//---------------------------------------- +// ---------------------------------------- // AST Construction (Stmt) func _if(cond ast.Expr, b ...ast.Stmt) *ast.IfStmt { @@ -1564,34 +1522,6 @@ func _return(results ...ast.Expr) *ast.ReturnStmt { } } -func _continue(label string) *ast.BranchStmt { - return &ast.BranchStmt{ - Tok: token.CONTINUE, - Label: _i(label), - } -} - -func _break(label string) *ast.BranchStmt { - return &ast.BranchStmt{ - Tok: token.BREAK, - Label: _i(label), - } -} - -func _goto(label string) *ast.BranchStmt { - return &ast.BranchStmt{ - Tok: token.GOTO, - Label: _i(label), - } -} - -func _fallthrough(label string) *ast.BranchStmt { - return &ast.BranchStmt{ - Tok: token.FALLTHROUGH, - Label: _i(label), - } -} - // even/odd args are paired, // name1, path1, name2, path2, etc. func _imports(nameAndPaths ...string) *ast.GenDecl { @@ -1618,15 +1548,6 @@ func _for(init ast.Stmt, cond ast.Expr, post ast.Stmt, b ...ast.Stmt) *ast.ForSt } } -func _loop(b ...ast.Stmt) *ast.ForStmt { - return _for(nil, nil, nil, b...) -} - -func _once(b ...ast.Stmt) *ast.ForStmt { - b = append(b, _break("")) - return _for(nil, nil, nil, b...) -} - func _len(x ast.Expr) *ast.CallExpr { return _call(_i("len"), x) } @@ -1766,7 +1687,7 @@ func _aop(op string) token.Token { } } -//---------------------------------------- +// ---------------------------------------- // AST Compile-Time func _ctif(cond bool, then_, else_ ast.Stmt) ast.Stmt { @@ -1779,7 +1700,7 @@ func _ctif(cond bool, then_, else_ ast.Stmt) ast.Stmt { } } -//---------------------------------------- +// ---------------------------------------- // AST query and manipulation. func importPathForName(name string, imports *ast.GenDecl) (path string, exists bool) { @@ -1800,24 +1721,6 @@ func importPathForName(name string, imports *ast.GenDecl) (path string, exists b return "", false } -func importNameForPath(path string, imports *ast.GenDecl) (name string, exists bool) { - if imports.Tok != token.IMPORT { - panic("unexpected ast.GenDecl token " + imports.Tok.String()) - } - for _, spec := range imports.Specs { - if ispec, ok := spec.(*ast.ImportSpec); ok { - specPath, err := strconv.Unquote(ispec.Path.Value) - if err != nil { - panic("malformed path " + ispec.Path.Value) - } - if specPath == path { - return ispec.Name.Name, true - } - } - } - return "", false -} - func rootScope(scope *ast.Scope) *ast.Scope { for scope.Outer != nil { scope = scope.Outer diff --git a/tm2/pkg/amino/genproto/bindings_test.go b/tm2/pkg/amino/genproto/bindings_test.go index 295c388def3..d1911d43542 100644 --- a/tm2/pkg/amino/genproto/bindings_test.go +++ b/tm2/pkg/amino/genproto/bindings_test.go @@ -11,6 +11,8 @@ import ( ) func TestGenerateProtoBindings(t *testing.T) { + t.Parallel() + file, err := GenerateProtoBindingsForTypes(tests.Package, tests.Package.ReflectTypes()...) assert.NoError(t, err) t.Logf("%v", file) diff --git a/tm2/pkg/amino/genproto/example/main.go b/tm2/pkg/amino/genproto/example/main.go index 24132305893..6e4023b596d 100644 --- a/tm2/pkg/amino/genproto/example/main.go +++ b/tm2/pkg/amino/genproto/example/main.go @@ -11,16 +11,12 @@ import ( // amino type StructA struct { - fieldA int - fieldB int FieldC int FieldD uint32 } // amino type StructB struct { - fieldA int - fieldB int FieldC int FieldD uint32 FieldE submodule.StructSM diff --git a/tm2/pkg/amino/genproto/genproto.go b/tm2/pkg/amino/genproto/genproto.go index 8af73b2690a..4f7154e058c 100644 --- a/tm2/pkg/amino/genproto/genproto.go +++ b/tm2/pkg/amino/genproto/genproto.go @@ -6,7 +6,6 @@ import ( "bytes" "errors" "fmt" - "io/ioutil" "os" "os/exec" "path" @@ -120,7 +119,6 @@ func (p3c *P3Context) GetP3ImportPath(p3type P3Type, implicit bool) string { func (p3c *P3Context) GenerateProto3MessagePartial(p3doc *P3Doc, rt reflect.Type) (p3msg P3Message) { if p3doc.PackageName == "" { panic(fmt.Sprintf("cannot generate message partials in the root package \"\".")) - return } if rt.Kind() == reflect.Ptr { panic("pointers not yet supported. if you meant pointer-preferred (for decoding), pass in rt.Elem()") @@ -220,7 +218,6 @@ func (p3c *P3Context) GenerateProto3MessagePartial(p3doc *P3Doc, rt reflect.Type func (p3c *P3Context) GenerateProto3ListPartial(p3doc *P3Doc, nl NList) (p3msg P3Message) { if p3doc.PackageName == "" { panic(fmt.Sprintf("cannot generate message partials in the root package \"\".")) - return } ep3 := nl.ElemP3Type() @@ -496,7 +493,7 @@ func RunProtoc(pkg *amino.Package, protosDir string) { } } // First generate output to a temp dir. - tempDir, err := ioutil.TempDir("", "amino-genproto") + tempDir, err := os.MkdirTemp("", "amino-genproto") if err != nil { return } diff --git a/tm2/pkg/amino/genproto/genproto_test.go b/tm2/pkg/amino/genproto/genproto_test.go index 20a45361519..2a52741c901 100644 --- a/tm2/pkg/amino/genproto/genproto_test.go +++ b/tm2/pkg/amino/genproto/genproto_test.go @@ -9,6 +9,8 @@ import ( ) func TestBasic(t *testing.T) { + t.Parallel() + p3c := NewP3Context() p3c.RegisterPackage(sm1.Package) p3doc := P3Doc{PackageName: "test"} diff --git a/tm2/pkg/amino/genproto/scanner.go b/tm2/pkg/amino/genproto/scanner.go deleted file mode 100644 index 6c5f770ab48..00000000000 --- a/tm2/pkg/amino/genproto/scanner.go +++ /dev/null @@ -1,192 +0,0 @@ -package genproto - -import "fmt" - -type runestate int - -const ( - runestateCode runestate = 0 - runestateRune runestate = 1 - runestateStringQuote runestate = 2 - runestateStringBacktick runestate = 3 -) - -type scanner struct { - str string - rnz []rune - idx int - runestate - curly int - round int - square int -} - -// returns a new scanner. -func newScanner(str string) *scanner { - rnz := make([]rune, 0, len(str)) - for _, r := range str { - rnz = append(rnz, r) - } - return &scanner{ - str: str, - runestate: runestateCode, - rnz: rnz, - } -} - -// Peeks the next n runes and returns a string. returns a shorter string if -// there are less than n runes left. -func (ss *scanner) peek(n int) string { - if ss.idx+n > len(ss.rnz) { - return string(ss.rnz[ss.idx:len(ss.rnz)]) - } - return string(ss.rnz[ss.idx : ss.idx+n]) -} - -// Advance a single rune, e.g. by incrementing ss.curly if ss.rnz[ss.idx] is -// '{' before advancing. If ss.runestate is runestateRune or runestateQuote, -// advances escape sequences to completion so ss.idx may increment more than -// one. Returns true if done. -func (ss *scanner) advance() bool { - rn := ss.rnz[ss.idx] // just panic if out of scope, caller error. - switch ss.runestate { - case runestateCode: - switch rn { - case '}': - ss.curly-- - if ss.curly < 0 { - panic("mismatched curly: " + ss.str) - } - case ')': - ss.round-- - if ss.round < 0 { - panic("mismatched round: " + ss.str) - } - case ']': - ss.square-- - if ss.square < 0 { - panic("mismatched square: " + ss.str) - } - case '{': - ss.curly++ - case '(': - ss.round++ - case '[': - ss.square++ - case '\'': - ss.runestate = runestateRune - case '"': - ss.runestate = runestateStringQuote - case '`': - ss.runestate = runestateStringBacktick - } - case runestateRune: - switch rn { - case '\\': - return ss.advanceEscapeSequence() - case '\'': - ss.runestate = runestateCode - } - case runestateStringQuote: - switch rn { - case '\\': - return ss.advanceEscapeSequence() - case '"': - ss.runestate = runestateCode - } - case runestateStringBacktick: - switch rn { - case '`': - ss.runestate = runestateCode - } - } - ss.idx++ - return ss.done() -} - -// returns true if no runes left to advance. -func (ss *scanner) done() bool { - return ss.idx == len(ss.rnz) -} - -// returns true if outside the scope of any -// parentheses, brackets, strings, or rune literals. -func (ss *scanner) out() bool { - return ss.runestate == runestateCode && - ss.curly == int(0) && - ss.round == int(0) && - ss.square == int(0) -} - -func isOctal(r rune) bool { - switch r { - case '0', '1', '2', '3', '4', '5', '6', '7': - return true - default: - return false - } -} - -func isHex(r rune) bool { - switch r { - case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f', - 'A', 'B', 'C', 'D', 'E', 'F': - return true - default: - return false - } -} - -// Advances runes, while checking that each passes `check`. if error, panics -// with info including `back` runes back. -func (ss *scanner) eatRunes(back int, eat int, check func(rune) bool) { - for i := 0; i < eat; i++ { - if ss.idx+i == len(ss.rnz) { - panic(fmt.Sprintf("eof while parsing: %s", - string(ss.rnz[ss.idx-back:]))) - } - if !check(ss.rnz[ss.idx+i]) { - panic(fmt.Sprintf("invalid character while parsing: %s", - string(ss.rnz[ss.idx-back:ss.idx+i+1]))) - } - ss.idx++ - } -} - -// increments ss.idx until escape sequence is complete. returns true if done. -func (ss *scanner) advanceEscapeSequence() bool { - rn1 := ss.rnz[ss.idx] - if rn1 != '\\' { - panic("should not happen") - } - if ss.idx == len(ss.rnz)-1 { - panic("eof while parsing escape sequence") - } - rn2 := ss.rnz[ss.idx+1] - switch rn2 { - case 'x': - ss.idx += 2 - ss.eatRunes(2, 2, isHex) - return ss.done() - case 'u': - ss.idx += 2 - ss.eatRunes(2, 4, isHex) - return ss.done() - case 'U': - ss.idx += 2 - ss.eatRunes(2, 8, isHex) - return ss.done() - case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '\'', '"': - ss.idx += 2 - return ss.done() - default: - ss.idx += 1 - if isOctal(rn2) { - ss.eatRunes(1, 3, isOctal) - } else { - panic("invalid escape sequence") - } - return ss.done() - } -} diff --git a/tm2/pkg/amino/genproto/types_test.go b/tm2/pkg/amino/genproto/types_test.go index 8b7398ab184..4e57427e809 100644 --- a/tm2/pkg/amino/genproto/types_test.go +++ b/tm2/pkg/amino/genproto/types_test.go @@ -7,6 +7,8 @@ import ( ) func TestPrintP3Types(t *testing.T) { + t.Parallel() + doc := P3Doc{ Comment: "doc comment", Messages: []P3Message{ diff --git a/tm2/pkg/amino/json_test.go b/tm2/pkg/amino/json_test.go index 81118080d89..e3f7d413fcb 100644 --- a/tm2/pkg/amino/json_test.go +++ b/tm2/pkg/amino/json_test.go @@ -29,6 +29,8 @@ func registerTransports(cdc *amino.Codec) { } func TestMarshalJSON(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() registerTransports(cdc) cases := []struct { @@ -130,6 +132,8 @@ func TestMarshalJSON(t *testing.T) { } func TestMarshalJSONTime(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() registerTransports(cdc) @@ -180,6 +184,8 @@ type innerFP struct { // We don't support maps. func TestUnmarshalMap(t *testing.T) { + t.Parallel() + jsonBytes := []byte("dontcare") obj := new(map[string]int) cdc := amino.NewCodec() @@ -198,6 +204,8 @@ func TestUnmarshalMap(t *testing.T) { } func TestUnmarshalFunc(t *testing.T) { + t.Parallel() + jsonBytes := []byte(`"dontcare"`) obj := func() {} cdc := amino.NewCodec() @@ -218,6 +226,8 @@ func TestUnmarshalFunc(t *testing.T) { } func TestUnmarshalJSON(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() registerTransports(cdc) cases := []struct { @@ -310,6 +320,8 @@ func TestUnmarshalJSON(t *testing.T) { } func TestJSONCodecRoundTrip(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() registerTransports(cdc) type allInclusive struct { @@ -480,6 +492,8 @@ func interfacePtr(v interface{}) *interface{} { // Test to ensure that Amino codec's time encoding/decoding roundtrip // produces the same result as the standard library json's. func TestAminoJSONTimeEncodeDecodeRoundTrip(t *testing.T) { + t.Parallel() + loc, err := time.LoadLocation("America/Los_Angeles") require.NoError(t, err) din := time.Date(2008, 9, 15, 14, 13, 12, 11109876, loc).Round(time.Millisecond).UTC() @@ -503,6 +517,8 @@ func TestAminoJSONTimeEncodeDecodeRoundTrip(t *testing.T) { } func TestMarshalJSONIndent(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() registerTransports(cdc) obj := Transport{Vehicle: Car("Tesla")} diff --git a/tm2/pkg/amino/libs/press/press_test.go b/tm2/pkg/amino/libs/press/press_test.go index 3978e5a5f52..e05042f4556 100644 --- a/tm2/pkg/amino/libs/press/press_test.go +++ b/tm2/pkg/amino/libs/press/press_test.go @@ -7,11 +7,15 @@ import ( ) func TestEmpty(t *testing.T) { + t.Parallel() + p := NewPress() assert.Equal(t, p.Print(), "") } func TestBasic(t *testing.T) { + t.Parallel() + p := NewPress() p.P("this ") p.P("is ") @@ -20,6 +24,8 @@ func TestBasic(t *testing.T) { } func TestBasicLn(t *testing.T) { + t.Parallel() + p := NewPress() p.P("this ") p.P("is ") @@ -28,6 +34,8 @@ func TestBasicLn(t *testing.T) { } func TestNewlineStr(t *testing.T) { + t.Parallel() + p := NewPress().SetNewlineStr("\r\n") p.P("this ") p.P("is ") @@ -38,6 +46,8 @@ func TestNewlineStr(t *testing.T) { } func TestIndent(t *testing.T) { + t.Parallel() + p := NewPress() p.P("first line ") p.Pl("{").I(func(p *Press) { @@ -51,6 +61,8 @@ func TestIndent(t *testing.T) { } func TestIndent2(t *testing.T) { + t.Parallel() + p := NewPress() p.P("first line ") p.Pl("{").I(func(p *Press) { @@ -66,6 +78,8 @@ func TestIndent2(t *testing.T) { } func TestIndent3(t *testing.T) { + t.Parallel() + p := NewPress() p.P("first line ") p.Pl("{").I(func(p *Press) { @@ -78,6 +92,8 @@ func TestIndent3(t *testing.T) { } func TestIndentLn(t *testing.T) { + t.Parallel() + p := NewPress() p.P("first line ") p.Pl("{").I(func(p *Press) { @@ -92,6 +108,8 @@ func TestIndentLn(t *testing.T) { } func TestNestedIndent(t *testing.T) { + t.Parallel() + p := NewPress() p.P("first line ") p.Pl("{").I(func(p *Press) { diff --git a/tm2/pkg/amino/pkg/pkg_test.go b/tm2/pkg/amino/pkg/pkg_test.go index 2be0b0cefe3..1be87e88f4e 100644 --- a/tm2/pkg/amino/pkg/pkg_test.go +++ b/tm2/pkg/amino/pkg/pkg_test.go @@ -14,6 +14,8 @@ type Foo struct { } func TestNewPackage(t *testing.T) { + t.Parallel() + // This should panic, as slashes in p3pkg is not allowed. assert.Panics(t, func() { NewPackage("foobar.com/some/path", "some/path", "").WithTypes(Foo{}) @@ -39,6 +41,8 @@ func TestNewPackage(t *testing.T) { } func TestFullNameForType(t *testing.T) { + t.Parallel() + // The Go package depends on how this test is invoked. // Sometimes it is "github.com/gnolang/gno/tm2/pkg/amino/packagepkg_test". // Sometimes it is "command-line-arguments" @@ -55,6 +59,8 @@ func TestFullNameForType(t *testing.T) { // If the struct wasn't registered, you can't get a name or type_url for it. func TestFullNameForUnexpectedType(t *testing.T) { + t.Parallel() + gopkg := reflect.TypeOf(Foo{}).PkgPath() pkg := NewPackage(gopkg, "some.path", "") diff --git a/tm2/pkg/amino/reflect.go b/tm2/pkg/amino/reflect.go index bc4fa57e626..01402a320d2 100644 --- a/tm2/pkg/amino/reflect.go +++ b/tm2/pkg/amino/reflect.go @@ -1,26 +1,21 @@ package amino import ( - "encoding/json" "fmt" "reflect" "unicode" ) -//---------------------------------------- +// ---------------------------------------- // Constants -var ( - jsonMarshalerType = reflect.TypeOf(new(json.Marshaler)).Elem() - jsonUnmarshalerType = reflect.TypeOf(new(json.Unmarshaler)).Elem() - errorType = reflect.TypeOf(new(error)).Elem() -) +var errorType = reflect.TypeOf(new(error)).Elem() -//---------------------------------------- +// ---------------------------------------- // encode: see binary-encode.go and json-encode.go // decode: see binary-decode.go and json-decode.go -//---------------------------------------- +// ---------------------------------------- // Misc. // CONTRACT: by the time this is called, len(bz) >= _n @@ -182,18 +177,6 @@ func constructConcreteType(cinfo *TypeInfo) (crv, irvSet reflect.Value) { return } -// Like constructConcreteType(), but if pointer preferred, returns a nil one. -// We like nil pointers for efficiency. -func constructConcreteTypeNilPreferred(cinfo *TypeInfo) (crv reflect.Value) { - // Construct new concrete type. - if cinfo.PointerPreferred { - crv = reflect.Zero(cinfo.PtrToType) - } else { - crv = reflect.New(cinfo.Type).Elem() - } - return -} - func toReprObject(rv reflect.Value) (rrv reflect.Value, err error) { var mwrm reflect.Value if rv.CanAddr() { @@ -269,12 +252,6 @@ func unmarshalAminoReprType(rm reflect.Method) (rrt reflect.Type) { return } -func toPBMessage(cdc *Codec, rv reflect.Value) (pbrv reflect.Value) { - rm := rv.MethodByName("ToPBMessage") - pbrv = rm.Call([]reflect.Value{reflect.ValueOf(cdc)})[0] - return -} - // NOTE: do not change this definition. // It is also defined for genproto. func isListType(rt reflect.Type) bool { diff --git a/tm2/pkg/amino/reflect_test.go b/tm2/pkg/amino/reflect_test.go index c5c7b6b5c83..9adfa0b35d0 100644 --- a/tm2/pkg/amino/reflect_test.go +++ b/tm2/pkg/amino/reflect_test.go @@ -18,44 +18,70 @@ import ( "github.com/gnolang/gno/tm2/pkg/amino/tests" ) -//------------------------------------- +// ------------------------------------- // Non-interface Google fuzz tests func TestCodecStruct(t *testing.T) { + t.Parallel() + for _, ptr := range tests.StructTypes { t.Logf("case %v", reflect.TypeOf(ptr)) rt := getTypeFromPointer(ptr) name := rt.Name() - t.Run(name+":binary", func(t *testing.T) { _testCodec(t, rt, "binary") }) - t.Run(name+":json", func(t *testing.T) { _testCodec(t, rt, "json") }) + t.Run(name+":binary", func(t *testing.T) { + t.Parallel() + _testCodec(t, rt, "binary") + }) + t.Run(name+":json", func(t *testing.T) { + t.Parallel() + _testCodec(t, rt, "json") + }) } } func TestCodecDef(t *testing.T) { + t.Parallel() + for _, ptr := range tests.DefTypes { t.Logf("case %v", reflect.TypeOf(ptr)) rt := getTypeFromPointer(ptr) name := rt.Name() - t.Run(name+":binary", func(t *testing.T) { _testCodec(t, rt, "binary") }) - t.Run(name+":json", func(t *testing.T) { _testCodec(t, rt, "json") }) + t.Run(name+":binary", func(t *testing.T) { + t.Parallel() + _testCodec(t, rt, "binary") + }) + t.Run(name+":json", func(t *testing.T) { + t.Parallel() + _testCodec(t, rt, "json") + }) } } func TestDeepCopyStruct(t *testing.T) { + t.Parallel() + for _, ptr := range tests.StructTypes { t.Logf("case %v", reflect.TypeOf(ptr)) rt := getTypeFromPointer(ptr) name := rt.Name() - t.Run(name+":deepcopy", func(t *testing.T) { _testDeepCopy(t, rt) }) + t.Run(name+":deepcopy", func(t *testing.T) { + t.Parallel() + _testDeepCopy(t, rt) + }) } } func TestDeepCopyDef(t *testing.T) { + t.Parallel() + for _, ptr := range tests.DefTypes { t.Logf("case %v", reflect.TypeOf(ptr)) rt := getTypeFromPointer(ptr) name := rt.Name() - t.Run(name+":deepcopy", func(t *testing.T) { _testDeepCopy(t, rt) }) + t.Run(name+":deepcopy", func(t *testing.T) { + t.Parallel() + _testDeepCopy(t, rt) + }) } } @@ -190,10 +216,12 @@ func _testDeepCopy(t *testing.T, rt reflect.Type) { } } -//---------------------------------------- +// ---------------------------------------- // Register/interface tests func TestCodecMashalFailsOnUnregisteredConcrete(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() bz, err := cdc.Marshal(struct{ tests.Interface1 }{tests.Concrete1{}}) @@ -202,6 +230,8 @@ func TestCodecMashalFailsOnUnregisteredConcrete(t *testing.T) { } func TestCodecMarshalPassesOnRegistered(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() cdc.RegisterTypeFrom(reflect.TypeOf(tests.Concrete1{}), tests.Package) @@ -218,6 +248,8 @@ func TestCodecMarshalPassesOnRegistered(t *testing.T) { } func TestCodecRegisterAndMarshalMultipleConcrete(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() cdc.RegisterTypeFrom(reflect.TypeOf(tests.Concrete1{}), tests.Package) cdc.RegisterTypeFrom(reflect.TypeOf(tests.Concrete2{}), tests.Package) @@ -251,6 +283,8 @@ func TestCodecRegisterAndMarshalMultipleConcrete(t *testing.T) { // Serialize and deserialize a registered typedef. func TestCodecRoundtripNonNilRegisteredTypeDef(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() cdc.RegisterTypeFrom(reflect.TypeOf(tests.ConcreteTypeDef{}), tests.Package) @@ -322,6 +356,8 @@ func TestCodecRoundtripNonNilRegisteredTypeDef(t *testing.T) { // Exactly like TestCodecRoundtripNonNilRegisteredTypeDef but with struct // around the value instead of a type def. func TestCodecRoundtripNonNilRegisteredWrappedValue(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() cdc.RegisterTypeFrom(reflect.TypeOf(tests.ConcreteWrappedBytes{}), tests.Package) @@ -351,6 +387,8 @@ func TestCodecRoundtripNonNilRegisteredWrappedValue(t *testing.T) { // MarshalAny(msg) and Marshal(&msg) are the same. func TestCodecMarshalAny(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() cdc.RegisterTypeFrom(reflect.TypeOf(tests.ConcreteWrappedBytes{}), tests.Package) @@ -368,6 +406,8 @@ func TestCodecMarshalAny(t *testing.T) { // Like TestCodecRoundtripNonNilRegisteredTypeDef, but JSON. func TestCodecJSONRoundtripNonNilRegisteredTypeDef(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() cdc.RegisterTypeFrom(reflect.TypeOf(tests.ConcreteTypeDef{}), tests.Package) @@ -388,6 +428,8 @@ func TestCodecJSONRoundtripNonNilRegisteredTypeDef(t *testing.T) { // Like TestCodecRoundtripNonNilRegisteredTypeDef, but serialize the concrete value directly. func TestCodecRoundtripMarshalOnConcreteNonNilRegisteredTypeDef(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() cdc.RegisterTypeFrom(reflect.TypeOf(tests.ConcreteTypeDef{}), tests.Package) @@ -418,6 +460,8 @@ func TestCodecRoundtripMarshalOnConcreteNonNilRegisteredTypeDef(t *testing.T) { // Like TestCodecRoundtripNonNilRegisteredTypeDef but read into concrete var. func TestCodecRoundtripUnmarshalOnConcreteNonNilRegisteredTypeDef(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() cdc.RegisterTypeFrom(reflect.TypeOf(tests.ConcreteTypeDef{}), tests.Package) @@ -437,6 +481,8 @@ func TestCodecRoundtripUnmarshalOnConcreteNonNilRegisteredTypeDef(t *testing.T) } func TestCodecBinaryStructFieldNilInterface(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() cdc.RegisterTypeFrom(reflect.TypeOf(tests.InterfaceFieldsStruct{}), tests.Package) @@ -451,7 +497,7 @@ func TestCodecBinaryStructFieldNilInterface(t *testing.T) { require.Equal(t, i2, i1, "i1 and i2 should be the same after decoding") } -//---------------------------------------- +// ---------------------------------------- // Misc. func spw(o interface{}) string { @@ -613,7 +659,7 @@ func getTypeFromPointer(ptr interface{}) reflect.Type { return rt.Elem() } -//---------------------------------------- +// ---------------------------------------- // From https://github.com/google/gofuzz/blob/master/fuzz.go // (Apache2.0 License) diff --git a/tm2/pkg/amino/repr_test.go b/tm2/pkg/amino/repr_test.go index 5fb31515fb6..4be50b5d93d 100644 --- a/tm2/pkg/amino/repr_test.go +++ b/tm2/pkg/amino/repr_test.go @@ -55,6 +55,8 @@ var ( ) func TestMarshalAminoBinary(t *testing.T) { + t.Parallel() + cdc := NewCodec() cdc.RegisterPackage(testPackage) @@ -78,6 +80,8 @@ func TestMarshalAminoBinary(t *testing.T) { } func TestMarshalAminoJSON(t *testing.T) { + t.Parallel() + cdc := NewCodec() cdc.RegisterPackage(testPackage) diff --git a/tm2/pkg/amino/tests/common.go b/tm2/pkg/amino/tests/common.go index b7213a56efc..1abf3aaf601 100644 --- a/tm2/pkg/amino/tests/common.go +++ b/tm2/pkg/amino/tests/common.go @@ -32,8 +32,6 @@ type PrimitivesStruct struct { Time time.Time Duration time.Duration Empty EmptyStruct - - unexposed int8 } type ShortArraysStruct struct { diff --git a/tm2/pkg/amino/tests/proto3/proto3_compat_test.go b/tm2/pkg/amino/tests/proto3/proto3_compat_test.go index bd2a51825da..8f9e04fc35c 100644 --- a/tm2/pkg/amino/tests/proto3/proto3_compat_test.go +++ b/tm2/pkg/amino/tests/proto3/proto3_compat_test.go @@ -36,6 +36,8 @@ func init() { } func TestFixed32Roundtrip(t *testing.T) { + t.Parallel() + // amino fixed32 (int32) <-> protbuf fixed32 (uint32) type testi32 struct { Int32 int32 `binary:"fixed32"` @@ -61,6 +63,8 @@ func TestFixed32Roundtrip(t *testing.T) { } func TestVarintZigzagRoundtrip(t *testing.T) { + t.Parallel() + t.Skip("zigzag encoding isn't default anymore for (unsigned) ints") // amino varint (int) <-> protobuf zigzag32 (int32 in go sint32 in proto file) type testInt32Varint struct { @@ -85,6 +89,8 @@ func TestVarintZigzagRoundtrip(t *testing.T) { } func TestFixedU64Roundtrip(t *testing.T) { + t.Parallel() + type testFixed64Uint struct { Int64 uint64 `binary:"fixed64"` } @@ -111,6 +117,8 @@ func TestFixedU64Roundtrip(t *testing.T) { } func TestMultidimensionalSlices(t *testing.T) { + t.Parallel() + s := [][]int8{ {1, 2}, {3, 4, 5}, @@ -121,6 +129,8 @@ func TestMultidimensionalSlices(t *testing.T) { } func TestMultidimensionalArrays(t *testing.T) { + t.Parallel() + arr := [2][2]int8{ {1, 2}, {3, 4}, @@ -131,6 +141,8 @@ func TestMultidimensionalArrays(t *testing.T) { } func TestMultidimensionalByteArraysAndSlices(t *testing.T) { + t.Parallel() + arr := [2][2]byte{ {1, 2}, {3, 4}, @@ -157,6 +169,8 @@ func TestMultidimensionalByteArraysAndSlices(t *testing.T) { } func TestProto3CompatPtrsRoundtrip(t *testing.T) { + t.Parallel() + s := p3.SomeStruct{} ab, err := cdc.Marshal(s) @@ -214,6 +228,8 @@ type goAminoGotTime struct { } func TestProto3CompatEmptyTimestamp(t *testing.T) { + t.Parallel() + empty := p3.ProtoGotTime{} // protobuf also marshals to empty bytes here: pb, err := proto.Marshal(&empty) @@ -235,6 +251,8 @@ func TestProto3CompatEmptyTimestamp(t *testing.T) { } func TestProto3CompatTimestampNow(t *testing.T) { + t.Parallel() + // test with current time: now := time.Now() ptts, err := ptypes.TimestampProto(now) @@ -267,6 +285,8 @@ func TestProto3CompatTimestampNow(t *testing.T) { } func TestProto3EpochTime(t *testing.T) { + t.Parallel() + pbRes := p3.ProtoGotTime{} // amino encode epoch (1970) and decode using proto; expect the resulting time to be epoch again: ab, err := cdc.Marshal(goAminoGotTime{T: &epoch}) @@ -279,6 +299,8 @@ func TestProto3EpochTime(t *testing.T) { } func TestProtoNegativeSeconds(t *testing.T) { + t.Parallel() + pbRes := p3.ProtoGotTime{} // test with negative seconds (0001-01-01 -> seconds = -62135596800, nanos = 0): ntm, err := time.Parse("2006-01-02 15:04:05 +0000 UTC", "0001-01-01 00:00:00 +0000 UTC") @@ -296,6 +318,8 @@ func TestProtoNegativeSeconds(t *testing.T) { } func TestIntVarintCompat(t *testing.T) { + t.Parallel() + tcs := []struct { val32 int32 val64 int64 @@ -382,6 +406,8 @@ func TestIntVarintCompat(t *testing.T) { // See if encoding of type def types matches the proto3 encoding func TestTypeDefCompatibility(t *testing.T) { + t.Parallel() + pNow := ptypes.TimestampNow() now, err := ptypes.Timestamp(pNow) require.NoError(t, err) diff --git a/tm2/pkg/amino/time2_test.go b/tm2/pkg/amino/time2_test.go index c40e2fc660e..b8d73f37d55 100644 --- a/tm2/pkg/amino/time2_test.go +++ b/tm2/pkg/amino/time2_test.go @@ -18,6 +18,8 @@ type testTime struct { } func TestDecodeSkippedFieldsInTime(t *testing.T) { + t.Parallel() + tm, err := time.Parse("2006-01-02 15:04:05 +0000 UTC", "1970-01-01 00:00:00 +0000 UTC") assert.NoError(t, err) @@ -62,6 +64,8 @@ func TestDecodeSkippedFieldsInTime(t *testing.T) { } func TestMinMaxTimeEncode(t *testing.T) { + t.Parallel() + tMin, err := time.Parse("2006-01-02 15:04:05 +0000 UTC", "0001-01-01 00:00:00 +0000 UTC") assert.NoError(t, err) tm := testTime{tMin} diff --git a/tm2/pkg/amino/wellknown_test.go b/tm2/pkg/amino/wellknown_test.go index 3b91ffc77a5..345466bd285 100644 --- a/tm2/pkg/amino/wellknown_test.go +++ b/tm2/pkg/amino/wellknown_test.go @@ -9,6 +9,8 @@ import ( ) func TestAnyWellKnownNative(t *testing.T) { + t.Parallel() + cdc := amino.NewCodec() s1 := tests.InterfaceFieldsStruct{ diff --git a/tm2/pkg/async/async_test.go b/tm2/pkg/async/async_test.go index f82e32312f0..255ce6b8d51 100644 --- a/tm2/pkg/async/async_test.go +++ b/tm2/pkg/async/async_test.go @@ -12,6 +12,8 @@ import ( ) func TestParallel(t *testing.T) { + t.Parallel() + // Create tasks. counter := new(int32) tasks := make([]Task, 100*1000) @@ -52,6 +54,8 @@ func TestParallel(t *testing.T) { } func TestParallelAbort(t *testing.T) { + t.Parallel() + flow1 := make(chan struct{}, 1) flow2 := make(chan struct{}, 1) flow3 := make(chan struct{}, 1) // Cap must be > 0 to prevent blocking. @@ -103,6 +107,8 @@ func TestParallelAbort(t *testing.T) { } func TestParallelRecover(t *testing.T) { + t.Parallel() + // Create tasks. tasks := []Task{ func(i int) (res interface{}, err error, abort bool) { @@ -155,7 +161,7 @@ func waitTimeout(t *testing.T, taskResultCh TaskResultCh, taskName string) { } else { assert.Fail(t, "TaskResultCh unexpectedly returned for %v", taskName) } - case <-time.After(1 * time.Second): // TODO use deterministic time? + case <-time.After(200 * time.Millisecond): // TODO use deterministic time? // Good! } } diff --git a/tm2/pkg/autofile/autofile_test.go b/tm2/pkg/autofile/autofile_test.go index d50bdca3ce0..d631e0ed265 100644 --- a/tm2/pkg/autofile/autofile_test.go +++ b/tm2/pkg/autofile/autofile_test.go @@ -1,7 +1,6 @@ package autofile import ( - "io/ioutil" "os" "syscall" "testing" @@ -14,7 +13,7 @@ import ( func TestSIGHUP(t *testing.T) { // First, create an AutoFile writing to a tempfile dir - file, err := ioutil.TempFile("", "sighup_test") + file, err := os.CreateTemp("", "sighup_test") require.NoError(t, err) err = file.Close() require.NoError(t, err) @@ -60,7 +59,7 @@ func TestSIGHUP(t *testing.T) { // // Manually modify file permissions, close, and reopen using autofile: // // We expect the file permissions to be changed back to the intended perms. // func TestOpenAutoFilePerms(t *testing.T) { -// file, err := ioutil.TempFile("", "permission_test") +// file, err := os.CreateTemp("", "permission_test") // require.NoError(t, err) // err = file.Close() // require.NoError(t, err) @@ -86,7 +85,7 @@ func TestSIGHUP(t *testing.T) { func TestAutoFileSize(t *testing.T) { // First, create an AutoFile writing to a tempfile dir - f, err := ioutil.TempFile("", "sighup_test") + f, err := os.CreateTemp("", "sighup_test") require.NoError(t, err) err = f.Close() require.NoError(t, err) diff --git a/tm2/pkg/autofile/group_test.go b/tm2/pkg/autofile/group_test.go index 6face4630d1..1bf79894b93 100644 --- a/tm2/pkg/autofile/group_test.go +++ b/tm2/pkg/autofile/group_test.go @@ -47,6 +47,8 @@ func assertGroupInfo(t *testing.T, gInfo GroupInfo, minIndex, maxIndex int, tota } func TestCheckHeadSizeLimit(t *testing.T) { + t.Parallel() + g := createTestGroupWithHeadSizeLimit(t, 1000*1000) // At first, there are no files. @@ -93,6 +95,8 @@ func TestCheckHeadSizeLimit(t *testing.T) { } func TestRotateFile(t *testing.T) { + t.Parallel() + g := createTestGroupWithHeadSizeLimit(t, 0) g.WriteLine("Line 1") g.WriteLine("Line 2") @@ -123,6 +127,8 @@ func TestRotateFile(t *testing.T) { } func TestWrite(t *testing.T) { + t.Parallel() + g := createTestGroupWithHeadSizeLimit(t, 0) written := []byte("Medusa") @@ -144,6 +150,8 @@ func TestWrite(t *testing.T) { // test that Read reads the required amount of bytes from all the files in the // group and returns no error if n == size of the given slice. func TestGroupReaderRead(t *testing.T) { + t.Parallel() + g := createTestGroupWithHeadSizeLimit(t, 0) professor := []byte("Professor Monster") @@ -173,6 +181,8 @@ func TestGroupReaderRead(t *testing.T) { // test that Read returns an error if number of bytes read < size of // the given slice. Subsequent call should return 0, io.EOF. func TestGroupReaderRead2(t *testing.T) { + t.Parallel() + g := createTestGroupWithHeadSizeLimit(t, 0) professor := []byte("Professor Monster") @@ -204,6 +214,8 @@ func TestGroupReaderRead2(t *testing.T) { } func TestMinIndex(t *testing.T) { + t.Parallel() + g := createTestGroupWithHeadSizeLimit(t, 0) assert.Zero(t, g.MinIndex(), "MinIndex should be zero at the beginning") @@ -213,6 +225,8 @@ func TestMinIndex(t *testing.T) { } func TestMaxIndex(t *testing.T) { + t.Parallel() + g := createTestGroupWithHeadSizeLimit(t, 0) assert.Zero(t, g.MaxIndex(), "MaxIndex should be zero at the beginning") diff --git a/tm2/pkg/bech32/bech32_test.go b/tm2/pkg/bech32/bech32_test.go index 557507cef57..361a18116ab 100644 --- a/tm2/pkg/bech32/bech32_test.go +++ b/tm2/pkg/bech32/bech32_test.go @@ -12,6 +12,8 @@ import ( ) func TestEncodeAndDecode(t *testing.T) { + t.Parallel() + sum := sha256.Sum256([]byte("hello world\n")) bech, err := bech32.ConvertAndEncode("shasum", sum[:]) @@ -39,6 +41,8 @@ var ( ) func TestEncode(t *testing.T) { + t.Parallel() + bz, err := hex.DecodeString(pubkeyBytes) assert.NoError(t, err) @@ -49,6 +53,8 @@ func TestEncode(t *testing.T) { } func TestDecode(t *testing.T) { + t.Parallel() + hrp, b1, err := bech32.Decode(pubkeyBech32) assert.NoError(t, err) diff --git a/tm2/pkg/bft/abci/client/client.go b/tm2/pkg/bft/abci/client/client.go index b3d5a945839..f9f21f08fdb 100644 --- a/tm2/pkg/bft/abci/client/client.go +++ b/tm2/pkg/bft/abci/client/client.go @@ -7,11 +7,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/service" ) -const ( - dialRetryIntervalSeconds = 3 - echoRetryIntervalSeconds = 1 -) - // Client defines an interface for an ABCI client. // All `Async` methods return a `ReqRes` object. // All `Sync` methods return the appropriate protobuf ResponseXxx struct and an error. @@ -48,11 +43,11 @@ type Client interface { EndBlockSync(abci.RequestEndBlock) (abci.ResponseEndBlock, error) } -//---------------------------------------- +// ---------------------------------------- type Callback func(abci.Request, abci.Response) -//---------------------------------------- +// ---------------------------------------- type ReqRes struct { abci.Request diff --git a/tm2/pkg/bft/blockchain/pool_test.go b/tm2/pkg/bft/blockchain/pool_test.go index 79205bff5ce..39c17d8428f 100644 --- a/tm2/pkg/bft/blockchain/pool_test.go +++ b/tm2/pkg/bft/blockchain/pool_test.go @@ -72,6 +72,8 @@ func makePeers(numPeers int, minHeight, maxHeight int64) testPeers { } func TestBlockPoolBasic(t *testing.T) { + t.Parallel() + start := int64(42) peers := makePeers(10, start+1, 1000) errorsCh := make(chan peerError, 1000) @@ -128,6 +130,8 @@ func TestBlockPoolBasic(t *testing.T) { } func TestBlockPoolTimeout(t *testing.T) { + t.Parallel() + start := int64(42) peers := makePeers(10, start+1, 1000) errorsCh := make(chan peerError, 1000) @@ -187,6 +191,8 @@ func TestBlockPoolTimeout(t *testing.T) { } func TestBlockPoolRemovePeer(t *testing.T) { + t.Parallel() + peers := make(testPeers, 10) for i := 0; i < 10; i++ { peerID := p2p.ID(fmt.Sprintf("%d", i+1)) diff --git a/tm2/pkg/bft/blockchain/reactor_test.go b/tm2/pkg/bft/blockchain/reactor_test.go index f4265e0f78d..fef640b0f82 100644 --- a/tm2/pkg/bft/blockchain/reactor_test.go +++ b/tm2/pkg/bft/blockchain/reactor_test.go @@ -115,6 +115,8 @@ func newBlockchainReactor(logger log.Logger, genDoc *types.GenesisDoc, privVals } func TestNoBlockResponse(t *testing.T) { + t.Parallel() + config = cfg.ResetTestRoot("blockchain_reactor_test") defer os.RemoveAll(config.RootDir) genDoc, privVals := randGenesisDoc(1, false, 30) @@ -174,6 +176,8 @@ func TestNoBlockResponse(t *testing.T) { // Alternatively we could actually dial a TCP conn but // that seems extreme. func TestFlappyBadBlockStopsPeer(t *testing.T) { + t.Parallel() + testutils.FilterStability(t, testutils.Flappy) config = cfg.ResetTestRoot("blockchain_reactor_test") @@ -245,6 +249,8 @@ func TestFlappyBadBlockStopsPeer(t *testing.T) { } func TestBcBlockRequestMessageValidateBasic(t *testing.T) { + t.Parallel() + testCases := []struct { testName string requestHeight int64 @@ -258,6 +264,8 @@ func TestBcBlockRequestMessageValidateBasic(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + request := bcBlockRequestMessage{Height: tc.requestHeight} assert.Equal(t, tc.expectErr, request.ValidateBasic() != nil, "Validate Basic had an unexpected result") }) @@ -265,6 +273,8 @@ func TestBcBlockRequestMessageValidateBasic(t *testing.T) { } func TestBcNoBlockResponseMessageValidateBasic(t *testing.T) { + t.Parallel() + testCases := []struct { testName string nonResponseHeight int64 @@ -278,6 +288,8 @@ func TestBcNoBlockResponseMessageValidateBasic(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + nonResponse := bcNoBlockResponseMessage{Height: tc.nonResponseHeight} assert.Equal(t, tc.expectErr, nonResponse.ValidateBasic() != nil, "Validate Basic had an unexpected result") }) @@ -285,6 +297,8 @@ func TestBcNoBlockResponseMessageValidateBasic(t *testing.T) { } func TestBcStatusRequestMessageValidateBasic(t *testing.T) { + t.Parallel() + testCases := []struct { testName string requestHeight int64 @@ -298,6 +312,8 @@ func TestBcStatusRequestMessageValidateBasic(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + request := bcStatusRequestMessage{Height: tc.requestHeight} assert.Equal(t, tc.expectErr, request.ValidateBasic() != nil, "Validate Basic had an unexpected result") }) @@ -305,6 +321,8 @@ func TestBcStatusRequestMessageValidateBasic(t *testing.T) { } func TestBcStatusResponseMessageValidateBasic(t *testing.T) { + t.Parallel() + testCases := []struct { testName string responseHeight int64 @@ -318,13 +336,15 @@ func TestBcStatusResponseMessageValidateBasic(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + response := bcStatusResponseMessage{Height: tc.responseHeight} assert.Equal(t, tc.expectErr, response.ValidateBasic() != nil, "Validate Basic had an unexpected result") }) } } -//---------------------------------------------- +// ---------------------------------------------- // utility funcs func makeTxs(height int64) (txs []types.Tx) { diff --git a/tm2/pkg/bft/config/toml.go b/tm2/pkg/bft/config/toml.go index fdaa1295342..1599bc78968 100644 --- a/tm2/pkg/bft/config/toml.go +++ b/tm2/pkg/bft/config/toml.go @@ -3,7 +3,6 @@ package config import ( "bytes" "fmt" - "io/ioutil" "os" "path/filepath" "text/template" @@ -308,7 +307,7 @@ func ResetTestRoot(testName string) *Config { func ResetTestRootWithChainID(testName string, chainID string) *Config { // create a unique, concurrency-safe test directory under os.TempDir() - rootDir, err := ioutil.TempDir("", fmt.Sprintf("%s-%s_", chainID, testName)) + rootDir, err := os.MkdirTemp("", fmt.Sprintf("%s-%s_", chainID, testName)) if err != nil { panic(err) } diff --git a/tm2/pkg/bft/config/toml_test.go b/tm2/pkg/bft/config/toml_test.go index da6a720ecd4..d1d70155cb8 100644 --- a/tm2/pkg/bft/config/toml_test.go +++ b/tm2/pkg/bft/config/toml_test.go @@ -22,6 +22,8 @@ func ensureFiles(t *testing.T, rootDir string, files ...string) { } func TestEnsureRoot(t *testing.T) { + t.Parallel() + require := require.New(t) // setup temp dir for test @@ -46,6 +48,8 @@ func TestEnsureRoot(t *testing.T) { } func TestEnsureTestRoot(t *testing.T) { + t.Parallel() + require := require.New(t) testName := "ensureTestRoot" diff --git a/tm2/pkg/bft/consensus/common_test.go b/tm2/pkg/bft/consensus/common_test.go index 7424305c00a..ba19881aace 100644 --- a/tm2/pkg/bft/consensus/common_test.go +++ b/tm2/pkg/bft/consensus/common_test.go @@ -3,7 +3,6 @@ package consensus import ( "bytes" "fmt" - "io/ioutil" "os" "path" "path/filepath" @@ -30,7 +29,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/events" "github.com/gnolang/gno/tm2/pkg/log" osm "github.com/gnolang/gno/tm2/pkg/os" - "github.com/gnolang/gno/tm2/pkg/p2p" ) const ( @@ -662,11 +660,11 @@ func randConsensusNetWithPeers(nValidators, nPeers int, testName string, tickerF if i < nValidators { privVal = privVals[i] } else { - tempKeyFile, err := ioutil.TempFile("", "priv_validator_key_") + tempKeyFile, err := os.CreateTemp("", "priv_validator_key_") if err != nil { panic(err) } - tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") + tempStateFile, err := os.CreateTemp("", "priv_validator_state_") if err != nil { panic(err) } @@ -702,15 +700,6 @@ func randConsensusNetWithPeers(nValidators, nPeers int, testName string, tickerF } } -func getSwitchIndex(switches []*p2p.Switch, peer p2p.Peer) int { - for i, s := range switches { - if peer.NodeInfo().ID() == s.NodeInfo().ID() { - return i - } - } - panic("didnt find peer in switches") -} - // ------------------------------------------------------------------------------- // genesis @@ -795,7 +784,7 @@ func newCounter() abci.Application { } func newPersistentKVStore() abci.Application { - dir, err := ioutil.TempDir("", "persistent-kvstore") + dir, err := os.MkdirTemp("", "persistent-kvstore") if err != nil { panic(err) } diff --git a/tm2/pkg/bft/consensus/mempool_test.go b/tm2/pkg/bft/consensus/mempool_test.go index b9c04cabbed..85914262903 100644 --- a/tm2/pkg/bft/consensus/mempool_test.go +++ b/tm2/pkg/bft/consensus/mempool_test.go @@ -24,6 +24,8 @@ func assertMempool(txn txNotifier) mempl.Mempool { } func TestMempoolNoProgressUntilTxsAvailable(t *testing.T) { + t.Parallel() + config := ResetConfig("consensus_mempool_no_progress_until_txs_available") defer os.RemoveAll(config.RootDir) config.Consensus.CreateEmptyBlocks = false @@ -71,6 +73,8 @@ func TestMempoolProgressAfterCreateEmptyBlocksInterval(t *testing.T) { } func TestMempoolProgressInHigherRound(t *testing.T) { + t.Parallel() + config := ResetConfig("consensus_mempool_progress_in_higher_round") defer os.RemoveAll(config.RootDir) config.Consensus.CreateEmptyBlocks = false @@ -138,6 +142,8 @@ func deliverTxsRange(cs *ConsensusState, start, end int) { } func TestMempoolTxConcurrentWithCommit(t *testing.T) { + t.Parallel() + state, privVals := randGenesisState(1, false, 10) blockDB := dbm.NewMemDB() app := NewCounterApplication() @@ -169,6 +175,8 @@ func TestMempoolTxConcurrentWithCommit(t *testing.T) { } func TestMempoolRmBadTx(t *testing.T) { + t.Parallel() + state, privVals := randGenesisState(1, false, 10) app := NewCounterApplication() blockDB := dbm.NewMemDB() diff --git a/tm2/pkg/bft/consensus/reactor_test.go b/tm2/pkg/bft/consensus/reactor_test.go index 2194d4d007d..db084b61395 100644 --- a/tm2/pkg/bft/consensus/reactor_test.go +++ b/tm2/pkg/bft/consensus/reactor_test.go @@ -86,6 +86,8 @@ func stopConsensusNet(logger log.Logger, reactors []*ConsensusReactor, eventSwit // Ensure a testnet makes blocks func TestReactorBasic(t *testing.T) { + t.Parallel() + N := 4 css, cleanup := randConsensusNet(N, "consensus_reactor_test", newMockTickerFunc(true), newCounter) defer cleanup() @@ -101,6 +103,8 @@ func TestReactorBasic(t *testing.T) { // Ensure a testnet makes blocks when there are txs func TestReactorCreatesBlockWhenEmptyBlocksFalse(t *testing.T) { + t.Parallel() + N := 4 css, cleanup := randConsensusNet(N, "consensus_reactor_test", newMockTickerFunc(true), newCounter, func(c *cfg.Config) { @@ -122,6 +126,8 @@ func TestReactorCreatesBlockWhenEmptyBlocksFalse(t *testing.T) { } func TestReactorReceiveDoesNotPanicIfAddPeerHasntBeenCalledYet(t *testing.T) { + t.Parallel() + N := 1 css, cleanup := randConsensusNet(N, "consensus_reactor_test", newMockTickerFunc(true), newCounter) defer cleanup() @@ -144,6 +150,8 @@ func TestReactorReceiveDoesNotPanicIfAddPeerHasntBeenCalledYet(t *testing.T) { } func TestReactorReceivePanicsIfInitPeerHasntBeenCalledYet(t *testing.T) { + t.Parallel() + N := 1 css, cleanup := randConsensusNet(N, "consensus_reactor_test", newMockTickerFunc(true), newCounter) defer cleanup() @@ -166,6 +174,8 @@ func TestReactorReceivePanicsIfInitPeerHasntBeenCalledYet(t *testing.T) { // Test we record stats about votes and block parts from other peers. func TestFlappyReactorRecordsVotesAndBlockParts(t *testing.T) { + t.Parallel() + testutils.FilterStability(t, testutils.Flappy) N := 4 @@ -192,6 +202,8 @@ func TestFlappyReactorRecordsVotesAndBlockParts(t *testing.T) { // ensure we can make blocks despite cycling a validator set func TestReactorVotingPowerChange(t *testing.T) { + t.Parallel() + nVals := 4 logger := log.TestingLogger() css, cleanup := randConsensusNet(nVals, "consensus_voting_power_changes_test", newMockTickerFunc(true), newPersistentKVStore) @@ -254,6 +266,8 @@ func TestReactorVotingPowerChange(t *testing.T) { } func TestReactorValidatorSetChanges(t *testing.T) { + t.Parallel() + nPeers := 7 nVals := 4 css, _, _, cleanup := randConsensusNetWithPeers(nVals, nPeers, "consensus_val_set_changes_test", newMockTickerFunc(true), newPersistentKVStoreWithPath) @@ -350,6 +364,8 @@ func TestReactorValidatorSetChanges(t *testing.T) { // Check we can make blocks with skip_timeout_commit=false func TestReactorWithTimeoutCommit(t *testing.T) { + t.Parallel() + N := 4 css, cleanup := randConsensusNet(N, "consensus_reactor_with_timeout_commit_test", newMockTickerFunc(false), newCounter) defer cleanup() @@ -510,6 +526,8 @@ func timeoutWaitGroup(t *testing.T, n int, f func(int), css []*ConsensusState) { // Ensure basic validation of structs is functioning func TestNewRoundStepMessageValidateBasic(t *testing.T) { + t.Parallel() + testCases := []struct { testName string messageHeight int64 @@ -529,6 +547,8 @@ func TestNewRoundStepMessageValidateBasic(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + message := NewRoundStepMessage{ Height: tc.messageHeight, Round: tc.messageRound, @@ -542,6 +562,8 @@ func TestNewRoundStepMessageValidateBasic(t *testing.T) { } func TestNewValidBlockMessageValidateBasic(t *testing.T) { + t.Parallel() + testCases := []struct { malleateFn func(*NewValidBlockMessage) expErr string @@ -569,6 +591,8 @@ func TestNewValidBlockMessageValidateBasic(t *testing.T) { for i, tc := range testCases { tc := tc t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) { + t.Parallel() + msg := &NewValidBlockMessage{ Height: 1, Round: 0, @@ -588,6 +612,8 @@ func TestNewValidBlockMessageValidateBasic(t *testing.T) { } func TestProposalPOLMessageValidateBasic(t *testing.T) { + t.Parallel() + testCases := []struct { malleateFn func(*ProposalPOLMessage) expErr string @@ -605,6 +631,8 @@ func TestProposalPOLMessageValidateBasic(t *testing.T) { for i, tc := range testCases { tc := tc t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) { + t.Parallel() + msg := &ProposalPOLMessage{ Height: 1, ProposalPOLRound: 1, @@ -621,6 +649,8 @@ func TestProposalPOLMessageValidateBasic(t *testing.T) { } func TestBlockPartMessageValidateBasic(t *testing.T) { + t.Parallel() + testPart := new(types.Part) testPart.Proof.LeafHash = tmhash.Sum([]byte("leaf")) testCases := []struct { @@ -638,6 +668,8 @@ func TestBlockPartMessageValidateBasic(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + message := BlockPartMessage{ Height: tc.messageHeight, Round: tc.messageRound, @@ -655,6 +687,8 @@ func TestBlockPartMessageValidateBasic(t *testing.T) { } func TestHasVoteMessageValidateBasic(t *testing.T) { + t.Parallel() + const ( validSignedMsgType types.SignedMsgType = 0x01 invalidSignedMsgType types.SignedMsgType = 0x03 @@ -678,6 +712,8 @@ func TestHasVoteMessageValidateBasic(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + message := HasVoteMessage{ Height: tc.messageHeight, Round: tc.messageRound, @@ -691,6 +727,8 @@ func TestHasVoteMessageValidateBasic(t *testing.T) { } func TestVoteSetMaj23MessageValidateBasic(t *testing.T) { + t.Parallel() + const ( validSignedMsgType types.SignedMsgType = 0x01 invalidSignedMsgType types.SignedMsgType = 0x03 @@ -723,6 +761,8 @@ func TestVoteSetMaj23MessageValidateBasic(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + message := VoteSetMaj23Message{ Height: tc.messageHeight, Round: tc.messageRound, @@ -736,6 +776,8 @@ func TestVoteSetMaj23MessageValidateBasic(t *testing.T) { } func TestVoteSetBitsMessageValidateBasic(t *testing.T) { + t.Parallel() + testCases := []struct { //nolint: maligned malleateFn func(*VoteSetBitsMessage) expErr string @@ -762,6 +804,8 @@ func TestVoteSetBitsMessageValidateBasic(t *testing.T) { for i, tc := range testCases { tc := tc t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) { + t.Parallel() + msg := &VoteSetBitsMessage{ Height: 1, Round: 0, diff --git a/tm2/pkg/bft/consensus/replay.go b/tm2/pkg/bft/consensus/replay.go index 16b4ba3fa87..b228c1b63e4 100644 --- a/tm2/pkg/bft/consensus/replay.go +++ b/tm2/pkg/bft/consensus/replay.go @@ -4,7 +4,6 @@ import ( "bytes" "errors" "fmt" - "hash/crc32" "io" "reflect" "time" @@ -21,8 +20,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/log" ) -var crc32c = crc32.MakeTable(crc32.Castagnoli) - // Functionality to replay blocks and messages on recovery from a crash. // There are two general failure scenarios: // diff --git a/tm2/pkg/bft/consensus/replay_test.go b/tm2/pkg/bft/consensus/replay_test.go index 3174207ef8d..d43a06f40c2 100644 --- a/tm2/pkg/bft/consensus/replay_test.go +++ b/tm2/pkg/bft/consensus/replay_test.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "os" "path/filepath" "runtime" @@ -124,6 +123,8 @@ func sendTxs(ctx context.Context, cs *ConsensusState) { // TestWALCrash uses crashing WAL to test we can recover from any WAL failure. func TestWALCrash(t *testing.T) { + t.Parallel() + testCases := []struct { name string initFn func(dbm.DB, *ConsensusState, context.Context) @@ -147,6 +148,8 @@ func TestWALCrash(t *testing.T) { tc := tc consensusReplayConfig := ResetConfig(fmt.Sprintf("%s_%d", t.Name(), i)) t.Run(tc.name, func(t *testing.T) { + t.Parallel() + crashWALandCheckLiveness(t, consensusReplayConfig, tc.initFn, tc.lastBlockHeight) }) } @@ -507,6 +510,8 @@ func makeTestSim(t *testing.T, name string) (sim testSim) { // Sync from scratch func TestHandshakeReplayAll(t *testing.T) { + t.Parallel() + for _, m := range modes { testHandshakeReplay(t, config, 0, m, nil) } @@ -519,6 +524,8 @@ func TestHandshakeReplayAll(t *testing.T) { // Sync many, not from scratch func TestHandshakeReplaySome(t *testing.T) { + t.Parallel() + for _, m := range modes { testHandshakeReplay(t, config, 1, m, nil) } @@ -531,6 +538,8 @@ func TestHandshakeReplaySome(t *testing.T) { // Sync from lagging by one func TestHandshakeReplayOne(t *testing.T) { + t.Parallel() + for _, m := range modes { testHandshakeReplay(t, config, numBlocks-1, m, nil) } @@ -543,6 +552,8 @@ func TestHandshakeReplayOne(t *testing.T) { // Sync from caught up func TestFlappyHandshakeReplayNone(t *testing.T) { + t.Parallel() + testutils.FilterStability(t, testutils.Flappy) for _, m := range modes { @@ -557,6 +568,8 @@ func TestFlappyHandshakeReplayNone(t *testing.T) { // Test mockProxyApp should not panic when app return ABCIResponses with some empty ResponseDeliverTx func TestMockProxyApp(t *testing.T) { + t.Parallel() + logger := log.TestingLogger() validTxs, invalidTxs := 0, 0 txIndex := 0 @@ -604,7 +617,7 @@ func TestMockProxyApp(t *testing.T) { } func tempWALWithData(data []byte) string { - walFile, err := ioutil.TempFile("", "wal") + walFile, err := os.CreateTemp("", "wal") if err != nil { panic(fmt.Sprintf("failed to create temp WAL file: %v", err)) } @@ -811,6 +824,8 @@ func buildTMStateFromChain(config *cfg.Config, stateDB dbm.DB, state sm.State, c } func TestHandshakePanicsIfAppReturnsWrongAppHash(t *testing.T) { + t.Parallel() + // 1. Initialize tendermint and commit 3 blocks with the following app hashes: // - 0x01 // - 0x02 @@ -1090,6 +1105,8 @@ func (bs *mockBlockStore) LoadSeenCommit(height int64) *types.Commit { // Test handshake/init chain func TestHandshakeUpdatesValidators(t *testing.T) { + t.Parallel() + val, _ := types.RandValidator(true, 10) vals := types.NewValidatorSet([]*types.Validator{val}) app := &initChainApp{vals: vals.ABCIValidatorUpdates()} diff --git a/tm2/pkg/bft/consensus/state_test.go b/tm2/pkg/bft/consensus/state_test.go index 1587fa03057..35877837ab3 100644 --- a/tm2/pkg/bft/consensus/state_test.go +++ b/tm2/pkg/bft/consensus/state_test.go @@ -59,10 +59,12 @@ x * TestHalt1 - if we see +2/3 precommits after timing out into new round, we sh */ -//---------------------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------------------- // ProposeSuite func TestStateProposerSelection0(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(4) height, round := cs1.Height, cs1.Round @@ -103,6 +105,8 @@ func TestStateProposerSelection0(t *testing.T) { // Now let's do it all again, but starting from round 2 instead of 0 func TestStateProposerSelection2(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(4) // test needs more work for more than 3 validators height := cs1.Height newRoundCh := subscribe(cs1.evsw, cstypes.EventNewRound{}) @@ -138,6 +142,8 @@ func TestStateProposerSelection2(t *testing.T) { // a non-validator should timeout into the prevote round func TestStateEnterProposeNoPrivValidator(t *testing.T) { + t.Parallel() + cs, _ := randConsensusState(1) cs.SetPrivValidator(nil) height, round := cs.Height, cs.Round @@ -161,6 +167,8 @@ func TestStateEnterProposeNoPrivValidator(t *testing.T) { // a validator should not timeout of the prevote round (TODO: unless the block is really big!) func TestStateEnterProposeYesPrivValidator(t *testing.T) { + t.Parallel() + cs, _ := randConsensusState(1) height, round := cs.Height, cs.Round @@ -197,6 +205,8 @@ func TestStateEnterProposeYesPrivValidator(t *testing.T) { } func TestStateBadProposal(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(2) height, round := cs1.Height, cs1.Round vs2 := vss[1] @@ -255,11 +265,13 @@ func TestStateBadProposal(t *testing.T) { signAddVotes(cs1, types.PrecommitType, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2) } -//---------------------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------------------- // FullRoundSuite // propose, prevote, and precommit a block func TestStateFullRound1(t *testing.T) { + t.Parallel() + cs, vss := randConsensusState(1) height, round := cs.Height, cs.Round @@ -292,6 +304,8 @@ func TestStateFullRound1(t *testing.T) { // nil is proposed, so prevote and precommit nil func TestStateFullRoundNil(t *testing.T) { + t.Parallel() + cs, vss := randConsensusState(1) height, round := cs.Height, cs.Round cs.decideProposal = func(height int64, round int) { @@ -316,6 +330,8 @@ func TestStateFullRoundNil(t *testing.T) { // run through propose, prevote, precommit commit with two validators // where the first validator has to wait for votes from the second func TestStateFullRound2(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(2) vs2 := vss[1] height, round := cs1.Height, cs1.Round @@ -354,12 +370,14 @@ func TestStateFullRound2(t *testing.T) { ensureNewBlock(newBlockCh, height) } -//------------------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------------------ // LockSuite // two validators, 4 rounds. // two vals take turns proposing. val1 locks on first one, precommits nil on everything else func TestStateLockNoPOL(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(2) vs2 := vss[1] height, round := cs1.Height, cs1.Round @@ -409,7 +427,7 @@ func TestStateLockNoPOL(t *testing.T) { // but with invalid args. then we enterPrecommitWait, and the timeout to new round ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) - /// + // ----------- round++ // moving to the next round ensureNewRound(newRoundCh, height, round) @@ -532,6 +550,8 @@ func TestStateLockNoPOL(t *testing.T) { // 4 vals, one precommits, other 3 polka at next round, so we unlock and precomit the polka func TestStateLockPOLRelock(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(4) vs2, vs3, vs4 := vss[1], vss[2], vss[3] height, round := cs1.Height, cs1.Round @@ -627,6 +647,8 @@ func TestStateLockPOLRelock(t *testing.T) { // 4 vals, one precommits, other 3 polka at next round, so we unlock and precomit the polka func TestStateLockPOLUnlock(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(4) vs2, vs3, vs4 := vss[1], vss[2], vss[3] height, round := cs1.Height, cs1.Round @@ -727,6 +749,8 @@ func TestStateLockPOLUnlock(t *testing.T) { // then a polka at round 2 that we lock on // then we see the polka from round 1 but shouldn't unlock func TestStateLockPOLSafety1(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(4) vs2, vs3, vs4 := vss[1], vss[2], vss[3] height, round := cs1.Height, cs1.Round @@ -848,6 +872,8 @@ func TestStateLockPOLSafety1(t *testing.T) { // What we want: // dont see P0, lock on P1 at R1, dont unlock using P0 at R2 func TestStateLockPOLSafety2(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(4) vs2, vs3, vs4 := vss[1], vss[2], vss[3] height, round := cs1.Height, cs1.Round @@ -943,6 +969,8 @@ func TestStateLockPOLSafety2(t *testing.T) { // What we want: // P0 proposes B0 at R3. func TestProposeValidBlock(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(4) vs2, vs3, vs4 := vss[1], vss[2], vss[3] height, round := cs1.Height, cs1.Round @@ -1038,6 +1066,8 @@ func TestProposeValidBlock(t *testing.T) { // What we want: // P0 miss to lock B but set valid block to B after receiving delayed prevote. func TestSetValidBlockOnDelayedPrevote(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(4) vs2, vs3, vs4 := vss[1], vss[2], vss[3] height, round := cs1.Height, cs1.Round @@ -1102,6 +1132,8 @@ func TestSetValidBlockOnDelayedPrevote(t *testing.T) { // P0 miss to lock B as Proposal Block is missing, but set valid block to B after // receiving delayed Block Proposal. func TestSetValidBlockOnDelayedProposal(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(4) vs2, vs3, vs4 := vss[1], vss[2], vss[3] height, round := cs1.Height, cs1.Round @@ -1160,6 +1192,8 @@ func TestSetValidBlockOnDelayedProposal(t *testing.T) { // What we want: // P0 waits for timeoutPrecommit before starting next round func TestWaitingTimeoutOnNilPolka(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(4) vs2, vs3, vs4 := vss[1], vss[2], vss[3] height, round := cs1.Height, cs1.Round @@ -1185,6 +1219,8 @@ func TestWaitingTimeoutOnNilPolka(t *testing.T) { // What we want: // P0 waits for timeoutPropose in the next round before entering prevote func TestWaitingTimeoutProposeOnNewRound(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(4) vs2, vs3, vs4 := vss[1], vss[2], vss[3] height, round := cs1.Height, cs1.Round @@ -1223,6 +1259,8 @@ func TestWaitingTimeoutProposeOnNewRound(t *testing.T) { // What we want: // P0 jump to higher round, precommit and start precommit wait func TestRoundSkipOnNilPolkaFromHigherRound(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(4) vs2, vs3, vs4 := vss[1], vss[2], vss[3] height, round := cs1.Height, cs1.Round @@ -1261,6 +1299,8 @@ func TestRoundSkipOnNilPolkaFromHigherRound(t *testing.T) { // What we want: // P0 wait for timeoutPropose to expire before sending prevote. func TestWaitTimeoutProposeOnNilPolkaForTheCurrentRound(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(4) vs2, vs3, vs4 := vss[1], vss[2], vss[3] height, round := cs1.Height, 1 @@ -1290,6 +1330,8 @@ func TestWaitTimeoutProposeOnNilPolkaForTheCurrentRound(t *testing.T) { // What we want: // P0 emit NewValidBlock event upon receiving 2/3+ Precommit for B but hasn't received block B yet func TestEmitNewValidBlockEventOnCommitWithoutBlock(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(4) vs2, vs3, vs4 := vss[1], vss[2], vss[3] height, round := cs1.Height, 1 @@ -1327,6 +1369,8 @@ func TestEmitNewValidBlockEventOnCommitWithoutBlock(t *testing.T) { // P0 receives 2/3+ Precommit for B for round 0, while being in round 1. It emits NewValidBlock event. // After receiving block, it executes block and moves to the next height. func TestCommitFromPreviousRound(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(4) vs2, vs3, vs4 := vss[1], vss[2], vss[3] height, round := cs1.Height, 1 @@ -1439,6 +1483,8 @@ func TestStartNextHeightCorrectly(t *testing.T) { } func TestFlappyResetTimeoutPrecommitUponNewHeight(t *testing.T) { + t.Parallel() + testutils.FilterStability(t, testutils.Flappy) config.Consensus.SkipTimeoutCommit = false @@ -1496,12 +1542,14 @@ func TestFlappyResetTimeoutPrecommitUponNewHeight(t *testing.T) { assert.False(t, rs.TriggeredTimeoutPrecommit, "triggeredTimeoutPrecommit should be false at the beginning of each height") } -//------------------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------------------ // SlashingSuite // TODO: Slashing /* func TestStateSlashingPrevotes(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(2) vs2 := vss[1] @@ -1537,6 +1585,8 @@ func TestStateSlashingPrevotes(t *testing.T) { } func TestStateSlashingPrecommits(t *testing.T) { + t.Parallel() + cs1, vss := randConsensusState(2) vs2 := vss[1] @@ -1573,15 +1623,17 @@ func TestStateSlashingPrecommits(t *testing.T) { } */ -//------------------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------------------ // CatchupSuite -//------------------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------------------ // HaltSuite // 4 vals. // we receive a final precommit after going into next round, but others might have gone to commit already! func TestFlappyStateHalt1(t *testing.T) { + t.Parallel() + testutils.FilterStability(t, testutils.Flappy) cs1, vss := randConsensusState(4) vs2, vs3, vs4 := vss[1], vss[2], vss[3] @@ -1652,6 +1704,8 @@ func TestFlappyStateHalt1(t *testing.T) { } func TestStateOutputsBlockPartsStats(t *testing.T) { + t.Parallel() + // create dummy peer cs, _ := randConsensusState(1) peer := p2pmock.NewPeer(nil) @@ -1694,6 +1748,8 @@ func TestStateOutputsBlockPartsStats(t *testing.T) { } func TestStateOutputVoteStats(t *testing.T) { + t.Parallel() + cs, vss := randConsensusState(2) // create dummy peer peer := p2pmock.NewPeer(nil) diff --git a/tm2/pkg/bft/consensus/types/height_vote_set_test.go b/tm2/pkg/bft/consensus/types/height_vote_set_test.go index 86dc4ee84f6..4c315585daa 100644 --- a/tm2/pkg/bft/consensus/types/height_vote_set_test.go +++ b/tm2/pkg/bft/consensus/types/height_vote_set_test.go @@ -21,6 +21,8 @@ func TestMain(m *testing.M) { } func TestPeerCatchupRounds(t *testing.T) { + t.Parallel() + valSet, privVals := types.RandValidatorSet(10, 1) hvs := NewHeightVoteSet(config.ChainID(), 1, valSet) diff --git a/tm2/pkg/bft/consensus/wal_generator.go b/tm2/pkg/bft/consensus/wal_generator.go index dff1cca1446..7893c544c7f 100644 --- a/tm2/pkg/bft/consensus/wal_generator.go +++ b/tm2/pkg/bft/consensus/wal_generator.go @@ -40,7 +40,7 @@ func WALGenerateNBlocks(t *testing.T, wr io.Writer, numBlocks int) (err error) { logger := log.TestingLogger().With("wal_generator", "wal_generator") logger.Info("generating WAL (last height msg excluded)", "numBlocks", numBlocks) - ///////////////////////////////////////////////////////////////////////////// + // ----------- // COPY PASTE FROM node.go WITH A FEW MODIFICATIONS // NOTE: we can't import node package because of circular dependency. // NOTE: we don't do handshake so need to set state.Version.Consensus.App directly. @@ -83,7 +83,7 @@ func WALGenerateNBlocks(t *testing.T, wr io.Writer, numBlocks int) (err error) { consensusState.SetPrivValidator(privValidator) } // END OF COPY PASTE - ///////////////////////////////////////////////////////////////////////////// + // ----------- // set consensus wal to buffered WAL, which will write all incoming msgs to buffer numBlocksWritten := make(chan struct{}) diff --git a/tm2/pkg/bft/consensus/wal_test.go b/tm2/pkg/bft/consensus/wal_test.go index 1b271fb73c7..55c9be03508 100644 --- a/tm2/pkg/bft/consensus/wal_test.go +++ b/tm2/pkg/bft/consensus/wal_test.go @@ -13,10 +13,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/log" ) -const ( - walTestFlushInterval = time.Duration(100) * time.Millisecond -) - // ---------------------------------------- // copied over from wal/wal_test.go @@ -53,8 +49,9 @@ func makeTempWAL(t *testing.T, walChunkSize int64) (wal walm.WAL) { // ---------------------------------------- func TestWALTruncate(t *testing.T) { - const maxTestMsgSize = 1024 * 1024 // 1MB - const walChunkSize = 409610 // 4KB + t.Parallel() + + const walChunkSize = 409610 // 4KB wal := makeTempWAL(t, walChunkSize) wal.SetLogger(log.TestingLogger()) diff --git a/tm2/pkg/bft/mempool/cache_test.go b/tm2/pkg/bft/mempool/cache_test.go index 5f76d6875ea..2d523db37ae 100644 --- a/tm2/pkg/bft/mempool/cache_test.go +++ b/tm2/pkg/bft/mempool/cache_test.go @@ -13,6 +13,8 @@ import ( ) func TestCacheRemove(t *testing.T) { + t.Parallel() + cache := newMapTxCache(100) numTxs := 10 txs := make([][]byte, numTxs) @@ -35,6 +37,8 @@ func TestCacheRemove(t *testing.T) { } func TestCacheAfterUpdate(t *testing.T) { + t.Parallel() + app := kvstore.NewKVStoreApplication() cc := proxy.NewLocalClientCreator(app) mempool, cleanup := newMempoolWithApp(cc) diff --git a/tm2/pkg/bft/mempool/reactor_test.go b/tm2/pkg/bft/mempool/reactor_test.go index c3b77fb46df..154cb1a7132 100644 --- a/tm2/pkg/bft/mempool/reactor_test.go +++ b/tm2/pkg/bft/mempool/reactor_test.go @@ -140,6 +140,8 @@ const ( ) func TestReactorBroadcastTxMessage(t *testing.T) { + t.Parallel() + mconfig := memcfg.TestMempoolConfig() pconfig := p2pcfg.TestP2PConfig() const N = 4 @@ -162,6 +164,8 @@ func TestReactorBroadcastTxMessage(t *testing.T) { } func TestReactorNoBroadcastToSender(t *testing.T) { + t.Parallel() + mconfig := memcfg.TestMempoolConfig() pconfig := p2pcfg.TestP2PConfig() const N = 2 @@ -179,6 +183,8 @@ func TestReactorNoBroadcastToSender(t *testing.T) { } func TestFlappyBroadcastTxForPeerStopsWhenPeerStops(t *testing.T) { + t.Parallel() + testutils.FilterStability(t, testutils.Flappy) if testing.Short() { @@ -205,6 +211,8 @@ func TestFlappyBroadcastTxForPeerStopsWhenPeerStops(t *testing.T) { } func TestFlappyBroadcastTxForPeerStopsWhenReactorStops(t *testing.T) { + t.Parallel() + testutils.FilterStability(t, testutils.Flappy) if testing.Short() { @@ -227,6 +235,8 @@ func TestFlappyBroadcastTxForPeerStopsWhenReactorStops(t *testing.T) { } func TestMempoolIDsBasic(t *testing.T) { + t.Parallel() + ids := newMempoolIDs() peer := mock.NewPeer(net.IP{127, 0, 0, 1}) @@ -241,6 +251,8 @@ func TestMempoolIDsBasic(t *testing.T) { } func TestMempoolIDsPanicsIfNodeRequestsOvermaxActiveIDs(t *testing.T) { + t.Parallel() + if testing.Short() { return } diff --git a/tm2/pkg/bft/node/node.go b/tm2/pkg/bft/node/node.go index bdeb5061540..9d6143e7af3 100644 --- a/tm2/pkg/bft/node/node.go +++ b/tm2/pkg/bft/node/node.go @@ -665,7 +665,6 @@ func (n *Node) ConfigureRPC() { rpccore.SetPubKey(pubKey) rpccore.SetGenesisDoc(n.genesisDoc) rpccore.SetProxyAppQuery(n.proxyApp.Query()) - rpccore.SetTxEventStore(n.txEventStore) rpccore.SetConsensusReactor(n.consensusReactor) rpccore.SetLogger(n.Logger.With("module", "rpc")) rpccore.SetEventSwitch(n.evsw) diff --git a/tm2/pkg/bft/privval/file_test.go b/tm2/pkg/bft/privval/file_test.go index 306db4177e5..a798a7ddc64 100644 --- a/tm2/pkg/bft/privval/file_test.go +++ b/tm2/pkg/bft/privval/file_test.go @@ -3,7 +3,6 @@ package privval import ( "encoding/base64" "fmt" - "io/ioutil" "os" "testing" "time" @@ -18,11 +17,13 @@ import ( ) func TestGenLoadValidator(t *testing.T) { + t.Parallel() + assert := assert.New(t) - tempKeyFile, err := ioutil.TempFile("", "priv_validator_key_") + tempKeyFile, err := os.CreateTemp("", "priv_validator_key_") require.Nil(t, err) - tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") + tempStateFile, err := os.CreateTemp("", "priv_validator_state_") require.Nil(t, err) privVal := GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) @@ -38,9 +39,11 @@ func TestGenLoadValidator(t *testing.T) { } func TestResetValidator(t *testing.T) { - tempKeyFile, err := ioutil.TempFile("", "priv_validator_key_") + t.Parallel() + + tempKeyFile, err := os.CreateTemp("", "priv_validator_key_") require.Nil(t, err) - tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") + tempStateFile, err := os.CreateTemp("", "priv_validator_state_") require.Nil(t, err) privVal := GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) @@ -66,11 +69,13 @@ func TestResetValidator(t *testing.T) { } func TestLoadOrGenValidator(t *testing.T) { + t.Parallel() + assert := assert.New(t) - tempKeyFile, err := ioutil.TempFile("", "priv_validator_key_") + tempKeyFile, err := os.CreateTemp("", "priv_validator_key_") require.Nil(t, err) - tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") + tempStateFile, err := os.CreateTemp("", "priv_validator_state_") require.Nil(t, err) tempKeyFilePath := tempKeyFile.Name() @@ -89,6 +94,8 @@ func TestLoadOrGenValidator(t *testing.T) { } func TestUnmarshalValidatorState(t *testing.T) { + t.Parallel() + assert, require := assert.New(t), require.New(t) // create some fixed values @@ -114,6 +121,8 @@ func TestUnmarshalValidatorState(t *testing.T) { } func TestUnmarshalValidatorKey(t *testing.T) { + t.Parallel() + assert, require := assert.New(t), require.New(t) // create some fixed values @@ -158,11 +167,13 @@ func TestUnmarshalValidatorKey(t *testing.T) { } func TestSignVote(t *testing.T) { + t.Parallel() + assert := assert.New(t) - tempKeyFile, err := ioutil.TempFile("", "priv_validator_key_") + tempKeyFile, err := os.CreateTemp("", "priv_validator_key_") require.Nil(t, err) - tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") + tempStateFile, err := os.CreateTemp("", "priv_validator_state_") require.Nil(t, err) privVal := GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) @@ -204,11 +215,13 @@ func TestSignVote(t *testing.T) { } func TestSignProposal(t *testing.T) { + t.Parallel() + assert := assert.New(t) - tempKeyFile, err := ioutil.TempFile("", "priv_validator_key_") + tempKeyFile, err := os.CreateTemp("", "priv_validator_key_") require.Nil(t, err) - tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") + tempStateFile, err := os.CreateTemp("", "priv_validator_state_") require.Nil(t, err) privVal := GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) @@ -248,9 +261,11 @@ func TestSignProposal(t *testing.T) { } func TestDifferByTimestamp(t *testing.T) { - tempKeyFile, err := ioutil.TempFile("", "priv_validator_key_") + t.Parallel() + + tempKeyFile, err := os.CreateTemp("", "priv_validator_key_") require.Nil(t, err) - tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") + tempStateFile, err := os.CreateTemp("", "priv_validator_state_") require.Nil(t, err) privVal := GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) diff --git a/tm2/pkg/bft/privval/signer_client_test.go b/tm2/pkg/bft/privval/signer_client_test.go index 1ba6b2e08d5..a896547aec3 100644 --- a/tm2/pkg/bft/privval/signer_client_test.go +++ b/tm2/pkg/bft/privval/signer_client_test.go @@ -53,6 +53,8 @@ func getSignerTestCases(t *testing.T) []signerTestCase { } func TestSignerClose(t *testing.T) { + t.Parallel() + for _, tc := range getSignerTestCases(t) { err := tc.signerClient.Close() assert.NoError(t, err) @@ -63,6 +65,8 @@ func TestSignerClose(t *testing.T) { } func TestSignerPing(t *testing.T) { + t.Parallel() + for _, tc := range getSignerTestCases(t) { defer tc.signerServer.Stop() defer tc.signerClient.Close() @@ -73,6 +77,8 @@ func TestSignerPing(t *testing.T) { } func TestSignerGetPubKey(t *testing.T) { + t.Parallel() + for _, tc := range getSignerTestCases(t) { defer tc.signerServer.Stop() defer tc.signerClient.Close() @@ -90,6 +96,8 @@ func TestSignerGetPubKey(t *testing.T) { } func TestSignerProposal(t *testing.T) { + t.Parallel() + for _, tc := range getSignerTestCases(t) { ts := time.Now() want := &types.Proposal{Timestamp: ts} @@ -106,6 +114,8 @@ func TestSignerProposal(t *testing.T) { } func TestSignerVote(t *testing.T) { + t.Parallel() + for _, tc := range getSignerTestCases(t) { ts := time.Now() want := &types.Vote{Timestamp: ts, Type: types.PrecommitType} @@ -122,6 +132,8 @@ func TestSignerVote(t *testing.T) { } func TestSignerVoteResetDeadline(t *testing.T) { + t.Parallel() + for _, tc := range getSignerTestCases(t) { ts := time.Now() want := &types.Vote{Timestamp: ts, Type: types.PrecommitType} @@ -148,6 +160,8 @@ func TestSignerVoteResetDeadline(t *testing.T) { } func TestFlappySignerVoteKeepAlive(t *testing.T) { + t.Parallel() + testutils.FilterStability(t, testutils.Flappy) for _, tc := range getSignerTestCases(t) { @@ -175,6 +189,8 @@ func TestFlappySignerVoteKeepAlive(t *testing.T) { } func TestSignerSignProposalErrors(t *testing.T) { + t.Parallel() + for _, tc := range getSignerTestCases(t) { // Replace service with a mock that always fails tc.signerServer.privVal = types.NewErroringMockPV() @@ -197,6 +213,8 @@ func TestSignerSignProposalErrors(t *testing.T) { } func TestSignerSignVoteErrors(t *testing.T) { + t.Parallel() + for _, tc := range getSignerTestCases(t) { ts := time.Now() vote := &types.Vote{Timestamp: ts, Type: types.PrecommitType} @@ -243,6 +261,8 @@ func brokenHandler(privVal types.PrivValidator, request SignerMessage, chainID s } func TestSignerUnexpectedResponse(t *testing.T) { + t.Parallel() + for _, tc := range getSignerTestCases(t) { tc.signerServer.privVal = types.NewMockPV() tc.mockPV = types.NewMockPV() diff --git a/tm2/pkg/bft/privval/signer_listener_endpoint_test.go b/tm2/pkg/bft/privval/signer_listener_endpoint_test.go index 8e5b1613454..16640583364 100644 --- a/tm2/pkg/bft/privval/signer_listener_endpoint_test.go +++ b/tm2/pkg/bft/privval/signer_listener_endpoint_test.go @@ -32,6 +32,8 @@ type dialerTestCase struct { // SignerDialerEndpoint.dialer() call inside SignerDialerEndpoint.acceptNewConnection() to return // successfully immediately, putting an instant stop to any retry attempts. func TestSignerRemoteRetryTCPOnly(t *testing.T) { + t.Parallel() + var ( attemptCh = make(chan int) retries = 10 @@ -83,6 +85,8 @@ func TestSignerRemoteRetryTCPOnly(t *testing.T) { } func TestRetryConnToRemoteSigner(t *testing.T) { + t.Parallel() + for _, tc := range getDialerTestCases(t) { var ( logger = log.TestingLogger() @@ -130,7 +134,7 @@ func TestRetryConnToRemoteSigner(t *testing.T) { } } -// ///////////////////////////////// +// ----------- func newSignerListenerEndpoint(logger log.Logger, ln net.Listener, timeoutReadWrite time.Duration) *SignerListenerEndpoint { var listener net.Listener diff --git a/tm2/pkg/bft/privval/socket_dialers_test.go b/tm2/pkg/bft/privval/socket_dialers_test.go index 150b9218575..a2f2cf9743b 100644 --- a/tm2/pkg/bft/privval/socket_dialers_test.go +++ b/tm2/pkg/bft/privval/socket_dialers_test.go @@ -40,6 +40,8 @@ func getDialerTestCases(t *testing.T) []dialerTestCase { } func TestIsConnTimeoutForFundamentalTimeouts(t *testing.T) { + t.Parallel() + // Generate a networking timeout tcpAddr := "127.0.0.1:34985" dialer := DialTCPFn(tcpAddr, time.Millisecond, ed25519.GenPrivKey()) @@ -49,6 +51,8 @@ func TestIsConnTimeoutForFundamentalTimeouts(t *testing.T) { } func TestIsConnTimeoutForWrappedConnTimeouts(t *testing.T) { + t.Parallel() + tcpAddr := "127.0.0.1:34985" dialer := DialTCPFn(tcpAddr, time.Millisecond, ed25519.GenPrivKey()) _, err := dialer() diff --git a/tm2/pkg/bft/privval/socket_listeners_test.go b/tm2/pkg/bft/privval/socket_listeners_test.go index a3630903197..f43ec6e1636 100644 --- a/tm2/pkg/bft/privval/socket_listeners_test.go +++ b/tm2/pkg/bft/privval/socket_listeners_test.go @@ -1,7 +1,6 @@ package privval import ( - "io/ioutil" "net" "os" "testing" @@ -29,7 +28,7 @@ type listenerTestCase struct { // testUnixAddr will attempt to obtain a platform-independent temporary file // name for a Unix socket func testUnixAddr() (string, error) { - f, err := ioutil.TempFile("", "tendermint-privval-test-*") + f, err := os.CreateTemp("", "tendermint-privval-test-*") if err != nil { return "", err } @@ -89,6 +88,8 @@ func listenerTestCases(t *testing.T, timeoutAccept, timeoutReadWrite time.Durati } func TestListenerTimeoutAccept(t *testing.T) { + t.Parallel() + for _, tc := range listenerTestCases(t, time.Millisecond, time.Second) { _, err := tc.listener.Accept() opErr, ok := err.(*net.OpError) @@ -103,6 +104,8 @@ func TestListenerTimeoutAccept(t *testing.T) { } func TestListenerTimeoutReadWrite(t *testing.T) { + t.Parallel() + const ( // This needs to be long enough s.t. the Accept will definitely succeed: timeoutAccept = time.Second diff --git a/tm2/pkg/bft/privval/utils_test.go b/tm2/pkg/bft/privval/utils_test.go index 6e5562e4cbd..63ee6a6076a 100644 --- a/tm2/pkg/bft/privval/utils_test.go +++ b/tm2/pkg/bft/privval/utils_test.go @@ -9,6 +9,8 @@ import ( ) func TestIsConnTimeoutForNonTimeoutErrors(t *testing.T) { + t.Parallel() + assert.False(t, IsConnTimeout(errors.Wrap(ErrDialRetryMax, "max retries exceeded"))) assert.False(t, IsConnTimeout(errors.New("completely irrelevant error"))) } diff --git a/tm2/pkg/bft/rpc/client/helpers_test.go b/tm2/pkg/bft/rpc/client/helpers_test.go index a58ed5adfd6..4d0b54c2358 100644 --- a/tm2/pkg/bft/rpc/client/helpers_test.go +++ b/tm2/pkg/bft/rpc/client/helpers_test.go @@ -15,6 +15,8 @@ import ( ) func TestWaitForHeight(t *testing.T) { + t.Parallel() + assert, require := assert.New(t), require.New(t) // test with error result - immediate failure diff --git a/tm2/pkg/bft/rpc/client/main_test.go b/tm2/pkg/bft/rpc/client/main_test.go index 58dd9538412..759104a3029 100644 --- a/tm2/pkg/bft/rpc/client/main_test.go +++ b/tm2/pkg/bft/rpc/client/main_test.go @@ -1,7 +1,6 @@ package client_test import ( - "io/ioutil" "os" "testing" @@ -14,7 +13,7 @@ var node *nm.Node func TestMain(m *testing.M) { // start a tendermint node (and kvstore) in the background to test against - dir, err := ioutil.TempDir("/tmp", "rpc-client-test") + dir, err := os.MkdirTemp("/tmp", "rpc-client-test") if err != nil { panic(err) } diff --git a/tm2/pkg/bft/rpc/client/rpc_test.go b/tm2/pkg/bft/rpc/client/rpc_test.go index 7b649e1dda8..e09ae8d4466 100644 --- a/tm2/pkg/bft/rpc/client/rpc_test.go +++ b/tm2/pkg/bft/rpc/client/rpc_test.go @@ -35,6 +35,8 @@ func GetClients() []client.Client { } func TestNilCustomHTTPClient(t *testing.T) { + t.Parallel() + require.Panics(t, func() { client.NewHTTPWithClient("http://example.com", "/websocket", nil) }) @@ -44,6 +46,8 @@ func TestNilCustomHTTPClient(t *testing.T) { } func TestCustomHTTPClient(t *testing.T) { + t.Parallel() + remote := rpctest.GetConfig().RPC.ListenAddress c := client.NewHTTPWithClient(remote, "/websocket", http.DefaultClient) status, err := c.Status() @@ -52,6 +56,8 @@ func TestCustomHTTPClient(t *testing.T) { } func TestCorsEnabled(t *testing.T) { + t.Parallel() + origin := rpctest.GetConfig().RPC.CORSAllowedOrigins[0] remote := strings.Replace(rpctest.GetConfig().RPC.ListenAddress, "tcp", "http", -1) @@ -68,6 +74,8 @@ func TestCorsEnabled(t *testing.T) { // Make sure status is correct (we connect properly) func TestStatus(t *testing.T) { + t.Parallel() + for i, c := range GetClients() { moniker := rpctest.GetConfig().Moniker status, err := c.Status() @@ -78,6 +86,8 @@ func TestStatus(t *testing.T) { // Make sure info is correct (we connect properly) func TestInfo(t *testing.T) { + t.Parallel() + for i, c := range GetClients() { // status, err := c.Status() // require.Nil(t, err, "%+v", err) @@ -90,6 +100,8 @@ func TestInfo(t *testing.T) { } func TestNetInfo(t *testing.T) { + t.Parallel() + for i, c := range GetClients() { nc, ok := c.(client.NetworkClient) require.True(t, ok, "%d", i) @@ -101,6 +113,8 @@ func TestNetInfo(t *testing.T) { } func TestDumpConsensusState(t *testing.T) { + t.Parallel() + for i, c := range GetClients() { // FIXME: fix server so it doesn't panic on invalid input nc, ok := c.(client.NetworkClient) @@ -113,6 +127,8 @@ func TestDumpConsensusState(t *testing.T) { } func TestConsensusState(t *testing.T) { + t.Parallel() + for i, c := range GetClients() { // FIXME: fix server so it doesn't panic on invalid input nc, ok := c.(client.NetworkClient) @@ -124,6 +140,8 @@ func TestConsensusState(t *testing.T) { } func TestHealth(t *testing.T) { + t.Parallel() + for i, c := range GetClients() { nc, ok := c.(client.NetworkClient) require.True(t, ok, "%d", i) @@ -133,6 +151,8 @@ func TestHealth(t *testing.T) { } func TestGenesisAndValidators(t *testing.T) { + t.Parallel() + for i, c := range GetClients() { // make sure this is the right genesis file gen, err := c.Genesis() @@ -173,6 +193,8 @@ func TestABCIQuery(t *testing.T) { // Make some app checks func TestAppCalls(t *testing.T) { + t.Parallel() + assert, require := assert.New(t), require.New(t) for i, c := range GetClients() { // get an offset of height to avoid racing and guessing @@ -265,6 +287,8 @@ func TestAppCalls(t *testing.T) { } func TestBroadcastTxSync(t *testing.T) { + t.Parallel() + require := require.New(t) // TODO (melekes): use mempool which is set on RPC rather than getting it from node @@ -344,6 +368,8 @@ func TestNumUnconfirmedTxs(t *testing.T) { /* func TestTx(t *testing.T) { + t.Parallel() + // first we broadcast a tx c := getHTTPClient() _, _, tx := MakeTxKV() @@ -398,6 +424,8 @@ func TestTx(t *testing.T) { } func TestTxSearch(t *testing.T) { + t.Parallel() + // first we broadcast a tx c := getHTTPClient() _, _, tx := MakeTxKV() @@ -519,6 +547,8 @@ func testBatchedJSONRPCCalls(t *testing.T, c *client.HTTP) { } func TestBatchedJSONRPCCallsCancellation(t *testing.T) { + t.Parallel() + c := getHTTPClient() _, _, tx1 := MakeTxKV() _, _, tx2 := MakeTxKV() @@ -537,6 +567,8 @@ func TestBatchedJSONRPCCallsCancellation(t *testing.T) { } func TestSendingEmptyJSONRPCRequestBatch(t *testing.T) { + t.Parallel() + c := getHTTPClient() batch := c.NewBatch() _, err := batch.Send() @@ -544,6 +576,8 @@ func TestSendingEmptyJSONRPCRequestBatch(t *testing.T) { } func TestClearingEmptyJSONRPCRequestBatch(t *testing.T) { + t.Parallel() + c := getHTTPClient() batch := c.NewBatch() require.Zero(t, batch.Clear(), "clearing an empty batch of JSON RPC requests should result in a 0 result") diff --git a/tm2/pkg/bft/rpc/core/blocks_test.go b/tm2/pkg/bft/rpc/core/blocks_test.go index a4d689ffd23..0fcd40f6d14 100644 --- a/tm2/pkg/bft/rpc/core/blocks_test.go +++ b/tm2/pkg/bft/rpc/core/blocks_test.go @@ -8,6 +8,8 @@ import ( ) func TestBlockchainInfo(t *testing.T) { + t.Parallel() + cases := []struct { min, max int64 height int64 diff --git a/tm2/pkg/bft/rpc/core/net_test.go b/tm2/pkg/bft/rpc/core/net_test.go index 42bf79fcce1..c3a8830cb1b 100644 --- a/tm2/pkg/bft/rpc/core/net_test.go +++ b/tm2/pkg/bft/rpc/core/net_test.go @@ -13,6 +13,8 @@ import ( ) func TestUnsafeDialSeeds(t *testing.T) { + t.Parallel() + sw := p2p.MakeSwitch(p2pcfg.DefaultP2PConfig(), 1, "testing", "123.123.123", func(n int, sw *p2p.Switch) *p2p.Switch { return sw }) err := sw.Start() @@ -43,6 +45,8 @@ func TestUnsafeDialSeeds(t *testing.T) { } func TestUnsafeDialPeers(t *testing.T) { + t.Parallel() + sw := p2p.MakeSwitch(p2pcfg.DefaultP2PConfig(), 1, "testing", "123.123.123", func(n int, sw *p2p.Switch) *p2p.Switch { return sw }) err := sw.Start() diff --git a/tm2/pkg/bft/rpc/core/pipe.go b/tm2/pkg/bft/rpc/core/pipe.go index a8b102d9ab7..abfdc300d31 100644 --- a/tm2/pkg/bft/rpc/core/pipe.go +++ b/tm2/pkg/bft/rpc/core/pipe.go @@ -10,7 +10,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/bft/proxy" cfg "github.com/gnolang/gno/tm2/pkg/bft/rpc/config" sm "github.com/gnolang/gno/tm2/pkg/bft/state" - "github.com/gnolang/gno/tm2/pkg/bft/state/eventstore" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/crypto" dbm "github.com/gnolang/gno/tm2/pkg/db" @@ -68,7 +67,6 @@ var ( // objects pubKey crypto.PubKey genDoc *types.GenesisDoc // cache the genesis structure - txEventStore eventstore.TxEventStore consensusReactor *consensus.ConsensusReactor evsw events.EventSwitch gTxDispatcher *txDispatcher @@ -115,10 +113,6 @@ func SetProxyAppQuery(appConn proxy.AppConnQuery) { proxyAppQuery = appConn } -func SetTxEventStore(indexer eventstore.TxEventStore) { - txEventStore = indexer -} - func SetConsensusReactor(conR *consensus.ConsensusReactor) { consensusReactor = conR } @@ -169,12 +163,3 @@ func validatePerPage(perPage int) int { } return perPage } - -func validateSkipCount(page, perPage int) int { - skipCount := (page - 1) * perPage - if skipCount < 0 { - return 0 - } - - return skipCount -} diff --git a/tm2/pkg/bft/rpc/core/pipe_test.go b/tm2/pkg/bft/rpc/core/pipe_test.go index 3147f600734..6136f66c9d8 100644 --- a/tm2/pkg/bft/rpc/core/pipe_test.go +++ b/tm2/pkg/bft/rpc/core/pipe_test.go @@ -8,6 +8,8 @@ import ( ) func TestPaginationPage(t *testing.T) { + t.Parallel() + cases := []struct { totalCount int perPage int @@ -51,6 +53,8 @@ func TestPaginationPage(t *testing.T) { } func TestPaginationPerPage(t *testing.T) { + t.Parallel() + cases := []struct { totalCount int perPage int diff --git a/tm2/pkg/bft/rpc/core/types/responses_test.go b/tm2/pkg/bft/rpc/core/types/responses_test.go index d309a6b63a1..268a8d25c34 100644 --- a/tm2/pkg/bft/rpc/core/types/responses_test.go +++ b/tm2/pkg/bft/rpc/core/types/responses_test.go @@ -9,6 +9,8 @@ import ( ) func TestStatusIndexer(t *testing.T) { + t.Parallel() + var status *ResultStatus assert.False(t, status.TxIndexEnabled()) diff --git a/tm2/pkg/bft/rpc/lib/client/args_test.go b/tm2/pkg/bft/rpc/lib/client/args_test.go index 8f44939f0aa..2a7e749f094 100644 --- a/tm2/pkg/bft/rpc/lib/client/args_test.go +++ b/tm2/pkg/bft/rpc/lib/client/args_test.go @@ -15,6 +15,8 @@ type Foo struct { } func TestArgToJSON(t *testing.T) { + t.Parallel() + assert := assert.New(t) require := require.New(t) diff --git a/tm2/pkg/bft/rpc/lib/client/http_client.go b/tm2/pkg/bft/rpc/lib/client/http_client.go index 5a9da9ec052..c02d029f27a 100644 --- a/tm2/pkg/bft/rpc/lib/client/http_client.go +++ b/tm2/pkg/bft/rpc/lib/client/http_client.go @@ -4,7 +4,7 @@ import ( "bytes" "encoding/json" "fmt" - "io/ioutil" + "io" "net" "net/http" "net/url" @@ -201,7 +201,7 @@ func (c *JSONRPCClient) Call(method string, params map[string]interface{}, resul return nil, errors.New("server at '%s' returned %s", c.address, httpResponse.Status) } - responseBytes, err := ioutil.ReadAll(httpResponse.Body) + responseBytes, err := io.ReadAll(httpResponse.Body) if err != nil { return nil, err } @@ -238,7 +238,7 @@ func (c *JSONRPCClient) sendBatch(requests []*jsonRPCBufferedRequest) ([]interfa return nil, errors.New("server at '%s' returned %s", c.address, httpResponse.Status) } - responseBytes, err := ioutil.ReadAll(httpResponse.Body) + responseBytes, err := io.ReadAll(httpResponse.Body) if err != nil { return nil, err } @@ -332,7 +332,7 @@ func (c *URIClient) Call(method string, params map[string]interface{}, result in return nil, errors.New("server at '%s' returned %s", c.address, resp.Status) } - responseBytes, err := ioutil.ReadAll(resp.Body) + responseBytes, err := io.ReadAll(resp.Body) if err != nil { return nil, err } diff --git a/tm2/pkg/bft/rpc/lib/client/http_client_test.go b/tm2/pkg/bft/rpc/lib/client/http_client_test.go index 9546a0c1d72..460f5b9947b 100644 --- a/tm2/pkg/bft/rpc/lib/client/http_client_test.go +++ b/tm2/pkg/bft/rpc/lib/client/http_client_test.go @@ -7,6 +7,8 @@ import ( ) func Test_parseRemoteAddr(t *testing.T) { + t.Parallel() + tt := []struct { remoteAddr string network, s, errContains string @@ -32,6 +34,8 @@ func Test_parseRemoteAddr(t *testing.T) { // and other protocols are left intact from parseRemoteAddr() func Test_makeHTTPDialer(t *testing.T) { + t.Parallel() + dl := makeHTTPDialer("https://.") _, err := dl("hello", "world") if assert.NotNil(t, err) { @@ -42,6 +46,8 @@ func Test_makeHTTPDialer(t *testing.T) { } func Test_makeHTTPDialer_noConvert(t *testing.T) { + t.Parallel() + dl := makeHTTPDialer("udp://.") _, err := dl("hello", "world") if assert.NotNil(t, err) { diff --git a/tm2/pkg/bft/rpc/lib/client/integration_test.go b/tm2/pkg/bft/rpc/lib/client/integration_test.go index 486540a989f..f3c705ecf98 100644 --- a/tm2/pkg/bft/rpc/lib/client/integration_test.go +++ b/tm2/pkg/bft/rpc/lib/client/integration_test.go @@ -19,6 +19,8 @@ import ( ) func TestWSClientReconnectWithJitter(t *testing.T) { + t.Parallel() + n := 8 maxReconnectAttempts := 3 // Max wait time is ceil(1+0.999) + ceil(2+0.999) + ceil(4+0.999) + ceil(...) = 2 + 3 + 5 = 10s + ... diff --git a/tm2/pkg/bft/rpc/lib/client/ws_client.go b/tm2/pkg/bft/rpc/lib/client/ws_client.go index 040437d11ff..4e159a3e3dc 100644 --- a/tm2/pkg/bft/rpc/lib/client/ws_client.go +++ b/tm2/pkg/bft/rpc/lib/client/ws_client.go @@ -226,7 +226,7 @@ func (c *WSClient) CallWithArrayParams(ctx context.Context, method string, param return c.Send(ctx, request) } -/////////////////////////////////////////////////////////////////////////////// +// ----------- // Private methods func (c *WSClient) dial() error { diff --git a/tm2/pkg/bft/rpc/lib/client/ws_client_test.go b/tm2/pkg/bft/rpc/lib/client/ws_client_test.go index b3a495f25b2..47c3a50ee63 100644 --- a/tm2/pkg/bft/rpc/lib/client/ws_client_test.go +++ b/tm2/pkg/bft/rpc/lib/client/ws_client_test.go @@ -58,6 +58,8 @@ func (h *myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } func TestWSClientReconnectsAfterReadFailure(t *testing.T) { + t.Parallel() + var wg sync.WaitGroup // start server @@ -91,6 +93,8 @@ func TestWSClientReconnectsAfterReadFailure(t *testing.T) { } func TestWSClientReconnectsAfterWriteFailure(t *testing.T) { + t.Parallel() + var wg sync.WaitGroup // start server @@ -121,6 +125,8 @@ func TestWSClientReconnectsAfterWriteFailure(t *testing.T) { } func TestWSClientReconnectFailure(t *testing.T) { + t.Parallel() + // start server h := &myHandler{} s := httptest.NewServer(h) @@ -172,6 +178,8 @@ func TestWSClientReconnectFailure(t *testing.T) { } func TestNotBlockingOnStop(t *testing.T) { + t.Parallel() + timeout := 2 * time.Second s := httptest.NewServer(&myHandler{}) c := startClient(t, s.Listener.Addr()) diff --git a/tm2/pkg/bft/rpc/lib/rpc_test.go b/tm2/pkg/bft/rpc/lib/rpc_test.go index 2c1aebaae14..a299417187a 100644 --- a/tm2/pkg/bft/rpc/lib/rpc_test.go +++ b/tm2/pkg/bft/rpc/lib/rpc_test.go @@ -280,6 +280,8 @@ func testWithWSClient(t *testing.T, cl *client.WSClient) { // ------------- func TestServersAndClientsBasic(t *testing.T) { + t.Parallel() + serverAddrs := [...]string{tcpAddr, unixAddr} for _, addr := range serverAddrs { cl1 := client.NewURIClient(addr) @@ -309,6 +311,8 @@ func TestServersAndClientsBasic(t *testing.T) { } func TestHexStringArg(t *testing.T) { + t.Parallel() + cl := client.NewURIClient(tcpAddr) // should NOT be handled as hex val := "0xabc" @@ -318,6 +322,8 @@ func TestHexStringArg(t *testing.T) { } func TestQuotedStringArg(t *testing.T) { + t.Parallel() + cl := client.NewURIClient(tcpAddr) // should NOT be unquoted val := "\"abc\"" @@ -327,6 +333,8 @@ func TestQuotedStringArg(t *testing.T) { } func TestWSNewWSRPCFunc(t *testing.T) { + t.Parallel() + cl := client.NewWSClient(tcpAddr, websocketEndpoint) cl.SetLogger(log.TestingLogger()) err := cl.Start() @@ -352,6 +360,8 @@ func TestWSNewWSRPCFunc(t *testing.T) { } func TestWSHandlesArrayParams(t *testing.T) { + t.Parallel() + cl := client.NewWSClient(tcpAddr, websocketEndpoint) cl.SetLogger(log.TestingLogger()) err := cl.Start() @@ -377,6 +387,8 @@ func TestWSHandlesArrayParams(t *testing.T) { // TestWSClientPingPong checks that a client & server exchange pings // & pongs so connection stays alive. func TestWSClientPingPong(t *testing.T) { + t.Parallel() + cl := client.NewWSClient(tcpAddr, websocketEndpoint) cl.SetLogger(log.TestingLogger()) err := cl.Start() diff --git a/tm2/pkg/bft/rpc/lib/server/handlers.go b/tm2/pkg/bft/rpc/lib/server/handlers.go index aa3fadd4d18..40543e5f465 100644 --- a/tm2/pkg/bft/rpc/lib/server/handlers.go +++ b/tm2/pkg/bft/rpc/lib/server/handlers.go @@ -6,7 +6,7 @@ import ( "encoding/hex" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "reflect" "runtime/debug" @@ -101,7 +101,7 @@ func funcReturnTypes(f interface{}) []reflect.Type { // jsonrpc calls grab the given method's function info and runs reflect.Call func makeJSONRPCHandler(funcMap map[string]*RPCFunc, logger log.Logger) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - b, err := ioutil.ReadAll(r.Body) + b, err := io.ReadAll(r.Body) if err != nil { WriteRPCResponseHTTP(w, types.RPCInvalidRequestError(types.JSONRPCStringID(""), errors.Wrap(err, "error reading request body"))) return diff --git a/tm2/pkg/bft/rpc/lib/server/handlers_test.go b/tm2/pkg/bft/rpc/lib/server/handlers_test.go index 8bf2cc0f7f1..e09a8a7cf96 100644 --- a/tm2/pkg/bft/rpc/lib/server/handlers_test.go +++ b/tm2/pkg/bft/rpc/lib/server/handlers_test.go @@ -3,7 +3,7 @@ package rpcserver_test import ( "bytes" "encoding/json" - "io/ioutil" + "io" "net/http" "net/http/httptest" "strings" @@ -18,11 +18,11 @@ import ( "github.com/gnolang/gno/tm2/pkg/log" ) -////////////////////////////////////////////////////////////////////////////// +// ----------- // HTTP REST API // TODO -////////////////////////////////////////////////////////////////////////////// +// ----------- // JSON-RPC over HTTP func testMux() *http.ServeMux { @@ -43,6 +43,8 @@ func statusOK(code int) bool { return code >= 200 && code <= 299 } // do not crash our RPC handlers. // See Issue https://github.com/gnolang/gno/tm2/pkg/bft/issues/708. func TestRPCParams(t *testing.T) { + t.Parallel() + mux := testMux() tests := []struct { payload string @@ -70,7 +72,7 @@ func TestRPCParams(t *testing.T) { res := rec.Result() // Always expecting back a JSONRPCResponse assert.True(t, statusOK(res.StatusCode), "#%d: should always return 2XX", i) - blob, err := ioutil.ReadAll(res.Body) + blob, err := io.ReadAll(res.Body) if err != nil { t.Errorf("#%d: err reading body: %v", i, err) continue @@ -91,6 +93,8 @@ func TestRPCParams(t *testing.T) { } func TestJSONRPCID(t *testing.T) { + t.Parallel() + mux := testMux() tests := []struct { payload string @@ -118,7 +122,7 @@ func TestJSONRPCID(t *testing.T) { res := rec.Result() // Always expecting back a JSONRPCResponse assert.True(t, statusOK(res.StatusCode), "#%d: should always return 2XX", i) - blob, err := ioutil.ReadAll(res.Body) + blob, err := io.ReadAll(res.Body) if err != nil { t.Errorf("#%d: err reading body: %v", i, err) continue @@ -138,6 +142,8 @@ func TestJSONRPCID(t *testing.T) { } func TestRPCNotification(t *testing.T) { + t.Parallel() + mux := testMux() body := strings.NewReader(`{"jsonrpc": "2.0", "id": ""}`) req, _ := http.NewRequest("POST", "http://localhost/", body) @@ -147,12 +153,14 @@ func TestRPCNotification(t *testing.T) { // Always expecting back a JSONRPCResponse require.True(t, statusOK(res.StatusCode), "should always return 2XX") - blob, err := ioutil.ReadAll(res.Body) + blob, err := io.ReadAll(res.Body) require.Nil(t, err, "reading from the body should not give back an error") require.Equal(t, len(blob), 0, "a notification SHOULD NOT be responded to by the server") } func TestRPCNotificationInBatch(t *testing.T) { + t.Parallel() + mux := testMux() tests := []struct { payload string @@ -182,7 +190,7 @@ func TestRPCNotificationInBatch(t *testing.T) { res := rec.Result() // Always expecting back a JSONRPCResponse assert.True(t, statusOK(res.StatusCode), "#%d: should always return 2XX", i) - blob, err := ioutil.ReadAll(res.Body) + blob, err := io.ReadAll(res.Body) if err != nil { t.Errorf("#%d: err reading body: %v", i, err) continue @@ -219,6 +227,8 @@ func TestRPCNotificationInBatch(t *testing.T) { } func TestUnknownRPCPath(t *testing.T) { + t.Parallel() + mux := testMux() req, _ := http.NewRequest("GET", "http://localhost/unknownrpcpath", nil) rec := httptest.NewRecorder() @@ -229,10 +239,12 @@ func TestUnknownRPCPath(t *testing.T) { require.Equal(t, http.StatusNotFound, res.StatusCode, "should always return 404") } -////////////////////////////////////////////////////////////////////////////// +// ----------- // JSON-RPC over WEBSOCKETS func TestWebsocketManagerHandler(t *testing.T) { + t.Parallel() + s := newWSServer() defer s.Close() diff --git a/tm2/pkg/bft/rpc/lib/server/http_server_test.go b/tm2/pkg/bft/rpc/lib/server/http_server_test.go index 6753a339981..5ab8d2890ae 100644 --- a/tm2/pkg/bft/rpc/lib/server/http_server_test.go +++ b/tm2/pkg/bft/rpc/lib/server/http_server_test.go @@ -5,7 +5,6 @@ import ( "crypto/tls" "fmt" "io" - "io/ioutil" "net" "net/http" "net/http/httptest" @@ -22,6 +21,8 @@ import ( ) func TestMaxOpenConnections(t *testing.T) { + t.Parallel() + const max = 5 // max simultaneous connections // Start the server. @@ -58,7 +59,7 @@ func TestMaxOpenConnections(t *testing.T) { return } defer r.Body.Close() - io.Copy(ioutil.Discard, r.Body) + io.Copy(io.Discard, r.Body) }() } wg.Wait() @@ -71,6 +72,8 @@ func TestMaxOpenConnections(t *testing.T) { } func TestStartHTTPAndTLSServer(t *testing.T) { + t.Parallel() + ln, err := net.Listen("tcp", "localhost:0") require.NoError(t, err) defer ln.Close() @@ -91,12 +94,14 @@ func TestStartHTTPAndTLSServer(t *testing.T) { defer res.Body.Close() assert.Equal(t, http.StatusOK, res.StatusCode) - body, err := ioutil.ReadAll(res.Body) + body, err := io.ReadAll(res.Body) require.NoError(t, err) assert.Equal(t, []byte("some body"), body) } func TestRecoverAndLogHandler(t *testing.T) { + t.Parallel() + tests := []struct { name string panicArg any @@ -164,6 +169,8 @@ func TestRecoverAndLogHandler(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() + var ( req, _ = http.NewRequest(http.MethodGet, "", nil) resp = httptest.NewRecorder() diff --git a/tm2/pkg/bft/rpc/lib/server/parse_test.go b/tm2/pkg/bft/rpc/lib/server/parse_test.go index a28dd255f23..aece3f20f3a 100644 --- a/tm2/pkg/bft/rpc/lib/server/parse_test.go +++ b/tm2/pkg/bft/rpc/lib/server/parse_test.go @@ -13,6 +13,8 @@ import ( ) func TestParseJSONMap(t *testing.T) { + t.Parallel() + input := []byte(`{"value":"1234","height":22}`) // naive is float,string @@ -101,6 +103,8 @@ func TestParseJSONMap(t *testing.T) { } func TestParseJSONArray(t *testing.T) { + t.Parallel() + input := []byte(`["1234",22]`) // naive is float,string @@ -134,6 +138,8 @@ func TestParseJSONArray(t *testing.T) { } func TestParseJSONRPC(t *testing.T) { + t.Parallel() + demo := func(ctx *types.Context, height int, name string) {} call := NewRPCFunc(demo, "height,name") @@ -170,6 +176,8 @@ func TestParseJSONRPC(t *testing.T) { } func TestParseURI(t *testing.T) { + t.Parallel() + demo := func(ctx *types.Context, height int, name string) {} call := NewRPCFunc(demo, "height,name") diff --git a/tm2/pkg/bft/rpc/lib/types/types_test.go b/tm2/pkg/bft/rpc/lib/types/types_test.go index e047c69bd77..55ee8ed3945 100644 --- a/tm2/pkg/bft/rpc/lib/types/types_test.go +++ b/tm2/pkg/bft/rpc/lib/types/types_test.go @@ -31,6 +31,8 @@ var responseTests = []responseTest{ } func TestResponses(t *testing.T) { + t.Parallel() + assert := assert.New(t) for _, tt := range responseTests { jsonid := tt.id @@ -52,6 +54,8 @@ func TestResponses(t *testing.T) { } func TestUnmarshallResponses(t *testing.T) { + t.Parallel() + assert := assert.New(t) for _, tt := range responseTests { response := &RPCResponse{} @@ -66,6 +70,8 @@ func TestUnmarshallResponses(t *testing.T) { } func TestRPCError(t *testing.T) { + t.Parallel() + assert.Equal(t, "RPC error 12 - Badness: One worse than a code 11", fmt.Sprintf("%v", &RPCError{ Code: 12, diff --git a/tm2/pkg/bft/state/execution_test.go b/tm2/pkg/bft/state/execution_test.go index 849c87d3359..25217ffccbe 100644 --- a/tm2/pkg/bft/state/execution_test.go +++ b/tm2/pkg/bft/state/execution_test.go @@ -29,6 +29,8 @@ var ( ) func TestApplyBlock(t *testing.T) { + t.Parallel() + cc := proxy.NewLocalClientCreator(kvstore.NewKVStoreApplication()) proxyApp := proxy.NewAppConns(cc) err := proxyApp.Start() @@ -53,6 +55,8 @@ func TestApplyBlock(t *testing.T) { // TestBeginBlockValidators ensures we send absent validators list. func TestBeginBlockValidators(t *testing.T) { + t.Parallel() + app := &testApp{} cc := proxy.NewLocalClientCreator(app) proxyApp := proxy.NewAppConns(cc) @@ -104,6 +108,8 @@ func TestBeginBlockValidators(t *testing.T) { } func TestValidateValidatorUpdates(t *testing.T) { + t.Parallel() + pubkey1 := ed25519.GenPrivKey().PubKey() pubkey2 := ed25519.GenPrivKey().PubKey() @@ -164,6 +170,8 @@ func TestValidateValidatorUpdates(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { + t.Parallel() + err := sm.ValidateValidatorUpdates(tc.abciUpdates, tc.validatorParams) if tc.shouldErr { assert.Error(t, err) @@ -175,6 +183,8 @@ func TestValidateValidatorUpdates(t *testing.T) { } func TestUpdateValidators(t *testing.T) { + t.Parallel() + pubkey1 := ed25519.GenPrivKey().PubKey() val1 := types.NewValidator(pubkey1, 10) pubkey2 := ed25519.GenPrivKey().PubKey() @@ -230,6 +240,8 @@ func TestUpdateValidators(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { + t.Parallel() + err := tc.currentSet.UpdateWithABCIValidatorUpdates(tc.abciUpdates) if tc.shouldErr { assert.Error(t, err) @@ -250,6 +262,8 @@ func TestUpdateValidators(t *testing.T) { // TestEndBlockValidatorUpdates ensures we update validator set and send an event. func TestEndBlockValidatorUpdates(t *testing.T) { + t.Parallel() + app := &testApp{} cc := proxy.NewLocalClientCreator(app) proxyApp := proxy.NewAppConns(cc) @@ -316,6 +330,8 @@ LOOP: // TestEndBlockValidatorUpdatesResultingInEmptySet checks that processing validator updates that // would result in empty set causes no panic, an error is raised and NextValidators is not updated func TestEndBlockValidatorUpdatesResultingInEmptySet(t *testing.T) { + t.Parallel() + app := &testApp{} cc := proxy.NewLocalClientCreator(app) proxyApp := proxy.NewAppConns(cc) diff --git a/tm2/pkg/bft/state/helpers_test.go b/tm2/pkg/bft/state/helpers_test.go index 219baaf0f55..ca4175185a9 100644 --- a/tm2/pkg/bft/state/helpers_test.go +++ b/tm2/pkg/bft/state/helpers_test.go @@ -8,7 +8,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/bft/proxy" sm "github.com/gnolang/gno/tm2/pkg/bft/state" "github.com/gnolang/gno/tm2/pkg/bft/types" - tmtime "github.com/gnolang/gno/tm2/pkg/bft/types/time" "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/crypto/ed25519" dbm "github.com/gnolang/gno/tm2/pkg/db" @@ -190,24 +189,7 @@ func makeHeaderPartsResponsesParams(state sm.State, params abci.ConsensusParams) return block.Header, types.BlockID{Hash: block.Hash(), PartsHeader: types.PartSetHeader{}}, abciResponses } -func randomGenesisDoc() *types.GenesisDoc { - pubkey := ed25519.GenPrivKey().PubKey() - return &types.GenesisDoc{ - GenesisTime: tmtime.Now(), - ChainID: "abc", - Validators: []types.GenesisValidator{ - { - Address: pubkey.Address(), - PubKey: pubkey, - Power: 10, - Name: "myval", - }, - }, - ConsensusParams: types.DefaultConsensusParams(), - } -} - -//---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- type testApp struct { abci.BaseApplication diff --git a/tm2/pkg/bft/state/state_test.go b/tm2/pkg/bft/state/state_test.go index a48f4f0a3e4..d19b8526d98 100644 --- a/tm2/pkg/bft/state/state_test.go +++ b/tm2/pkg/bft/state/state_test.go @@ -42,6 +42,8 @@ func setupTestCase(t *testing.T) (func(t *testing.T), dbm.DB, sm.State) { // TestStateCopy tests the correct copying behaviour of State. func TestStateCopy(t *testing.T) { + t.Parallel() + t.Helper() tearDown, _, state := setupTestCase(t) @@ -62,6 +64,8 @@ func TestStateCopy(t *testing.T) { // TestMakeGenesisStateNilValidators tests state's consistency when genesis file's validators field is nil. func TestMakeGenesisStateNilValidators(t *testing.T) { + t.Parallel() + doc := types.GenesisDoc{ ChainID: "dummy", Validators: nil, @@ -75,6 +79,8 @@ func TestMakeGenesisStateNilValidators(t *testing.T) { // TestStateSaveLoad tests saving and loading State from a db. func TestStateSaveLoad(t *testing.T) { + t.Parallel() + tearDown, stateDB, state := setupTestCase(t) defer tearDown(t) //nolint: vetshadow @@ -91,6 +97,8 @@ func TestStateSaveLoad(t *testing.T) { // TestABCIResponsesSaveLoad tests saving and loading ABCIResponses. func TestABCIResponsesSaveLoad1(t *testing.T) { + t.Parallel() + tearDown, stateDB, state := setupTestCase(t) defer tearDown(t) //nolint: vetshadow @@ -129,6 +137,8 @@ func TestABCIResponsesSaveLoad1(t *testing.T) { // TestResultsSaveLoad tests saving and loading ABCI results. func TestABCIResponsesSaveLoad2(t *testing.T) { + t.Parallel() + tearDown, stateDB, _ := setupTestCase(t) defer tearDown(t) //nolint: vetshadow @@ -223,6 +233,8 @@ func TestABCIResponsesSaveLoad2(t *testing.T) { // TestValidatorSimpleSaveLoad tests saving and loading validators. func TestValidatorSimpleSaveLoad(t *testing.T) { + t.Parallel() + tearDown, stateDB, state := setupTestCase(t) defer tearDown(t) //nolint: vetshadow @@ -256,6 +268,8 @@ func TestValidatorSimpleSaveLoad(t *testing.T) { // TestValidatorChangesSaveLoad tests saving and loading a validator set with changes. func TestOneValidatorChangesSaveLoad(t *testing.T) { + t.Parallel() + tearDown, stateDB, state := setupTestCase(t) defer tearDown(t) @@ -309,6 +323,8 @@ func TestOneValidatorChangesSaveLoad(t *testing.T) { } func TestProposerFrequency(t *testing.T) { + t.Parallel() + // some explicit test cases testCases := []struct { powers []int64 @@ -432,6 +448,8 @@ func testProposerFreq(t *testing.T, caseNum int, valSet *types.ValidatorSet) { // TestProposerPriorityDoesNotGetResetToZero assert that we preserve accum when calling updateState // see https://github.com/tendermint/classic/issues/2718 func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) { + t.Parallel() + tearDown, _, state := setupTestCase(t) defer tearDown(t) val1VotingPower := int64(10) @@ -534,6 +552,8 @@ func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) { } func TestProposerPriorityProposerAlternates(t *testing.T) { + t.Parallel() + // Regression test that would fail if the inner workings of // IncrementProposerPriority change. // Additionally, make sure that same power validators alternate if both @@ -670,6 +690,8 @@ func TestProposerPriorityProposerAlternates(t *testing.T) { } func TestLargeGenesisValidator(t *testing.T) { + t.Parallel() + tearDown, _, state := setupTestCase(t) defer tearDown(t) @@ -822,6 +844,8 @@ func TestLargeGenesisValidator(t *testing.T) { } func TestStoreLoadValidatorsIncrementsProposerPriority(t *testing.T) { + t.Parallel() + const valSetSize = 2 tearDown, stateDB, state := setupTestCase(t) defer tearDown(t) @@ -845,6 +869,8 @@ func TestStoreLoadValidatorsIncrementsProposerPriority(t *testing.T) { // TestValidatorChangesSaveLoad tests saving and loading a validator set with // changes. func TestManyValidatorChangesSaveLoad(t *testing.T) { + t.Parallel() + const valSetSize = 7 tearDown, stateDB, state := setupTestCase(t) defer tearDown(t) @@ -890,6 +916,8 @@ func TestManyValidatorChangesSaveLoad(t *testing.T) { } func TestStateMakeBlock(t *testing.T) { + t.Parallel() + tearDown, _, state := setupTestCase(t) defer tearDown(t) @@ -905,6 +933,8 @@ func TestStateMakeBlock(t *testing.T) { // TestConsensusParamsChangesSaveLoad tests saving and loading consensus params // with changes. func TestConsensusParamsChangesSaveLoad(t *testing.T) { + t.Parallel() + tearDown, stateDB, state := setupTestCase(t) defer tearDown(t) @@ -964,6 +994,8 @@ func TestConsensusParamsChangesSaveLoad(t *testing.T) { } func TestApplyUpdates(t *testing.T) { + t.Parallel() + initParams := makeConsensusParams(1, 2, 3, 3, 4) cases := [...]struct { diff --git a/tm2/pkg/bft/state/store_test.go b/tm2/pkg/bft/state/store_test.go index 79282e6a311..ed3b8e63311 100644 --- a/tm2/pkg/bft/state/store_test.go +++ b/tm2/pkg/bft/state/store_test.go @@ -15,6 +15,8 @@ import ( ) func TestStoreLoadValidators(t *testing.T) { + t.Parallel() + stateDB := dbm.NewMemDB() val, _ := types.RandValidator(true, 10) vals := types.NewValidatorSet([]*types.Validator{val}) diff --git a/tm2/pkg/bft/state/validation_test.go b/tm2/pkg/bft/state/validation_test.go index 94aafe92694..c1941381de7 100644 --- a/tm2/pkg/bft/state/validation_test.go +++ b/tm2/pkg/bft/state/validation_test.go @@ -19,6 +19,8 @@ import ( const validationTestsStopHeight int64 = 10 func TestValidateBlockHeader(t *testing.T) { + t.Parallel() + proxyApp := newTestApp() require.NoError(t, proxyApp.Start()) defer proxyApp.Stop() @@ -80,6 +82,8 @@ func TestValidateBlockHeader(t *testing.T) { } func TestValidateBlockCommit(t *testing.T) { + t.Parallel() + proxyApp := newTestApp() require.NoError(t, proxyApp.Start()) defer proxyApp.Stop() diff --git a/tm2/pkg/bft/store/store_test.go b/tm2/pkg/bft/store/store_test.go index 1dc0bda833c..fce566903c3 100644 --- a/tm2/pkg/bft/store/store_test.go +++ b/tm2/pkg/bft/store/store_test.go @@ -58,6 +58,8 @@ func makeStateAndBlockStore(logger log.Logger) (sm.State, *BlockStore, cleanupFu } func TestLoadBlockStoreStateJSON(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() bsj := &BlockStoreStateJSON{Height: 1000} @@ -69,6 +71,8 @@ func TestLoadBlockStoreStateJSON(t *testing.T) { } func TestNewBlockStore(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() db.Set(blockStoreKey, []byte(`{"height": "10000"}`)) bs := NewBlockStore(db) @@ -129,6 +133,8 @@ func TestMain(m *testing.M) { // TODO: This test should be simplified ... func TestBlockStoreSaveLoadBlock(t *testing.T) { + t.Parallel() + state, bs, cleanup := makeStateAndBlockStore(log.NewTMLogger(new(bytes.Buffer))) defer cleanup() require.Equal(t, bs.Height(), int64(0), "initially the height should be zero") @@ -325,6 +331,8 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) { } func TestLoadBlockPart(t *testing.T) { + t.Parallel() + bs, db := freshBlockStore() height, index := int64(10), 1 loadPart := func() (interface{}, error) { @@ -354,6 +362,8 @@ func TestLoadBlockPart(t *testing.T) { } func TestLoadBlockMeta(t *testing.T) { + t.Parallel() + bs, db := freshBlockStore() height := int64(10) loadMeta := func() (interface{}, error) { @@ -384,6 +394,8 @@ func TestLoadBlockMeta(t *testing.T) { } func TestBlockFetchAtHeight(t *testing.T) { + t.Parallel() + state, bs, cleanup := makeStateAndBlockStore(log.NewTMLogger(new(bytes.Buffer))) defer cleanup() require.Equal(t, bs.Height(), int64(0), "initially the height should be zero") diff --git a/tm2/pkg/bft/types/block_test.go b/tm2/pkg/bft/types/block_test.go index 5b49e0c392e..3963378436b 100644 --- a/tm2/pkg/bft/types/block_test.go +++ b/tm2/pkg/bft/types/block_test.go @@ -21,6 +21,8 @@ import ( ) func TestBlockValidateBasic(t *testing.T) { + t.Parallel() + require.Error(t, (*Block)(nil).ValidateBasic()) txs := []Tx{Tx("foo"), Tx("bar")} @@ -57,6 +59,8 @@ func TestBlockValidateBasic(t *testing.T) { tc := tc i := i t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + block := MakeBlock(h, txs, commit) block.ProposerAddress = valSet.GetProposer().Address tc.malleateBlock(block) @@ -67,11 +71,15 @@ func TestBlockValidateBasic(t *testing.T) { } func TestBlockHash(t *testing.T) { + t.Parallel() + assert.Nil(t, (*Block)(nil).Hash()) assert.Nil(t, MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil).Hash()) } func TestBlockMakePartSet(t *testing.T) { + t.Parallel() + assert.Nil(t, (*Block)(nil).MakePartSet(2)) partSet := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil).MakePartSet(1024) @@ -80,6 +88,8 @@ func TestBlockMakePartSet(t *testing.T) { } func TestBlockHashesTo(t *testing.T) { + t.Parallel() + assert.False(t, (*Block)(nil).HashesTo(nil)) lastID := makeBlockIDRandom() @@ -96,6 +106,8 @@ func TestBlockHashesTo(t *testing.T) { } func TestBlockSize(t *testing.T) { + t.Parallel() + size := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil).Size() if size <= 0 { t.Fatal("Size of the block is zero or negative") @@ -103,6 +115,8 @@ func TestBlockSize(t *testing.T) { } func TestBlockString(t *testing.T) { + t.Parallel() + assert.Equal(t, "nil-Block", (*Block)(nil).String()) assert.Equal(t, "nil-Block", (*Block)(nil).StringIndented("")) assert.Equal(t, "nil-Block", (*Block)(nil).StringShort()) @@ -135,16 +149,22 @@ func makeBlockID(hash []byte, partSetSize int, partSetHash []byte) BlockID { var nilBytes []byte func TestNilHeaderHashDoesntCrash(t *testing.T) { + t.Parallel() + assert.Equal(t, (*Header)(nil).Hash(), nilBytes) assert.Equal(t, (new(Header)).Hash(), nilBytes) } func TestNilDataHashDoesntCrash(t *testing.T) { + t.Parallel() + assert.Equal(t, (*Data)(nil).Hash(), nilBytes) assert.Equal(t, new(Data).Hash(), nilBytes) } func TestCommit(t *testing.T) { + t.Parallel() + lastID := makeBlockIDRandom() h := int64(3) voteSet, _, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1) @@ -166,6 +186,8 @@ func TestCommit(t *testing.T) { } func TestCommitValidateBasic(t *testing.T) { + t.Parallel() + testCases := []struct { testName string malleateCommit func(*Commit) @@ -181,6 +203,8 @@ func TestCommitValidateBasic(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + com := randCommit() tc.malleateCommit(com) assert.Equal(t, tc.expectErr, com.ValidateBasic() != nil, "Validate Basic had an unexpected result") @@ -189,6 +213,8 @@ func TestCommitValidateBasic(t *testing.T) { } func TestHeaderByteSize(t *testing.T) { + t.Parallel() + // Construct a UTF-8 string of MaxChainIDLen length using the supplementary // characters. // Each supplementary character takes 4 bytes. @@ -239,6 +265,8 @@ func randCommit() *Commit { } func TestCommitToVoteSet(t *testing.T) { + t.Parallel() + lastID := makeBlockIDRandom() h := int64(3) @@ -263,6 +291,8 @@ func TestCommitToVoteSet(t *testing.T) { } func TestCommitToVoteSetWithVotesForAnotherBlockOrNilBlock(t *testing.T) { + t.Parallel() + blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash")) blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash")) blockID3 := makeBlockID([]byte("blockhash3"), 10000, []byte("partshash")) @@ -320,6 +350,8 @@ func TestCommitToVoteSetWithVotesForAnotherBlockOrNilBlock(t *testing.T) { } func TestSignedHeaderValidateBasic(t *testing.T) { + t.Parallel() + commit := randCommit() chainID := "𠜎" timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC) @@ -360,6 +392,8 @@ func TestSignedHeaderValidateBasic(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + sh := SignedHeader{ Header: tc.shHeader, Commit: tc.shCommit, @@ -370,6 +404,8 @@ func TestSignedHeaderValidateBasic(t *testing.T) { } func TestBlockIDValidateBasic(t *testing.T) { + t.Parallel() + validBlockID := BlockID{ Hash: []byte{}, PartsHeader: PartSetHeader{ @@ -400,6 +436,8 @@ func TestBlockIDValidateBasic(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + blockID := BlockID{ Hash: tc.blockIDHash, PartsHeader: tc.blockIDPartsHeader, diff --git a/tm2/pkg/bft/types/evidence_test.go b/tm2/pkg/bft/types/evidence_test.go index 4efc61f8be7..5c43c547b74 100644 --- a/tm2/pkg/bft/types/evidence_test.go +++ b/tm2/pkg/bft/types/evidence_test.go @@ -37,6 +37,8 @@ func makeVote(val PrivValidator, chainID string, valIndex int, height int64, rou } func TestEvidence(t *testing.T) { + t.Parallel() + val := NewMockPV() val2 := NewMockPV() @@ -83,6 +85,8 @@ func TestEvidence(t *testing.T) { } func TestDuplicatedVoteEvidence(t *testing.T) { + t.Parallel() + ev := randomDuplicatedVoteEvidence() assert.True(t, ev.Equal(ev)) @@ -90,6 +94,8 @@ func TestDuplicatedVoteEvidence(t *testing.T) { } func TestEvidenceList(t *testing.T) { + t.Parallel() + ev := randomDuplicatedVoteEvidence() evl := EvidenceList([]Evidence{ev}) @@ -99,6 +105,8 @@ func TestEvidenceList(t *testing.T) { } func TestEvidenceByteSize(t *testing.T) { + t.Parallel() + val := NewMockPV() blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt64, tmhash.Sum([]byte("partshash"))) blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt64, tmhash.Sum([]byte("partshash"))) @@ -127,6 +135,8 @@ func randomDuplicatedVoteEvidence() *DuplicateVoteEvidence { } func TestDuplicateVoteEvidenceValidation(t *testing.T) { + t.Parallel() + val := NewMockPV() blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt64, tmhash.Sum([]byte("partshash"))) blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt64, tmhash.Sum([]byte("partshash"))) @@ -151,6 +161,8 @@ func TestDuplicateVoteEvidenceValidation(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + ev := &DuplicateVoteEvidence{ PubKey: secp256k1.GenPrivKey().PubKey(), VoteA: makeVote(val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0x02, blockID), @@ -163,11 +175,15 @@ func TestDuplicateVoteEvidenceValidation(t *testing.T) { } func TestMockGoodEvidenceValidateBasic(t *testing.T) { + t.Parallel() + goodEvidence := NewMockGoodEvidence(int64(1), 1, crypto.AddressFromPreimage([]byte{1})) assert.Nil(t, goodEvidence.ValidateBasic()) } func TestMockBadEvidenceValidateBasic(t *testing.T) { + t.Parallel() + badEvidence := MockBadEvidence{MockGoodEvidence: NewMockGoodEvidence(int64(1), 1, crypto.AddressFromPreimage([]byte{1}))} assert.Nil(t, badEvidence.ValidateBasic()) } diff --git a/tm2/pkg/bft/types/genesis_test.go b/tm2/pkg/bft/types/genesis_test.go index a8816bed2e7..24c69c6a28e 100644 --- a/tm2/pkg/bft/types/genesis_test.go +++ b/tm2/pkg/bft/types/genesis_test.go @@ -1,7 +1,6 @@ package types import ( - "io/ioutil" "os" "testing" "time" @@ -15,6 +14,8 @@ import ( ) func TestGenesisBad(t *testing.T) { + t.Parallel() + // test some bad ones from raw json testCases := [][]byte{ {}, // empty @@ -38,6 +39,8 @@ func TestGenesisBad(t *testing.T) { } func TestGenesisGood(t *testing.T) { + t.Parallel() + // test a good one by raw json genDocBytes := []byte(`{"genesis_time":"0001-01-01T00:00:00Z","chain_id":"test-chain-QDKdJr","consensus_params":null,"validators":[{"pub_key":{"@type":"/tm.PubKeyEd25519","value":"AT/+aaL1eB0477Mud9JMm8Sh8BIvOYlPGC9KkIUmFaE="},"power":"10","name":""}],"app_hash":"","app_state":{"@type":"/tm.MockAppState","account_owner":"Bob"}}`) _, err := GenesisDocFromJSON(genDocBytes) @@ -88,7 +91,9 @@ func TestGenesisGood(t *testing.T) { } func TestGenesisSaveAs(t *testing.T) { - tmpfile, err := ioutil.TempFile("", "genesis") + t.Parallel() + + tmpfile, err := os.CreateTemp("", "genesis") require.NoError(t, err) defer os.Remove(tmpfile.Name()) @@ -115,6 +120,8 @@ func TestGenesisSaveAs(t *testing.T) { } func TestGenesisValidatorHash(t *testing.T) { + t.Parallel() + genDoc := randomGenesisDoc() assert.NotEmpty(t, genDoc.ValidatorHash()) } diff --git a/tm2/pkg/bft/types/params_test.go b/tm2/pkg/bft/types/params_test.go index cb5f3244e8d..141a67b903c 100644 --- a/tm2/pkg/bft/types/params_test.go +++ b/tm2/pkg/bft/types/params_test.go @@ -16,6 +16,8 @@ var ( ) func TestConsensusParamsValidation(t *testing.T) { + t.Parallel() + testCases := []struct { params abci.ConsensusParams valid bool @@ -63,6 +65,8 @@ func makeParams( } func TestConsensusParamsHash(t *testing.T) { + t.Parallel() + params := []abci.ConsensusParams{ makeParams(4, 1024, 2, 10, valEd25519), makeParams(1, 1024, 4, 10, valEd25519), @@ -90,6 +94,8 @@ func TestConsensusParamsHash(t *testing.T) { } func TestConsensusParamsUpdate(t *testing.T) { + t.Parallel() + testCases := []struct { params abci.ConsensusParams updates abci.ConsensusParams diff --git a/tm2/pkg/bft/types/part_set_test.go b/tm2/pkg/bft/types/part_set_test.go index 2e05daed849..13ebb2f0bba 100644 --- a/tm2/pkg/bft/types/part_set_test.go +++ b/tm2/pkg/bft/types/part_set_test.go @@ -1,7 +1,7 @@ package types import ( - "io/ioutil" + "io" "testing" "github.com/stretchr/testify/assert" @@ -16,6 +16,8 @@ const ( ) func TestBasicPartSet(t *testing.T) { + t.Parallel() + // Construct random data of size partSize * 100 data := random.RandBytes(testPartSize * 100) partSet := NewPartSetFromData(data, testPartSize) @@ -54,13 +56,15 @@ func TestBasicPartSet(t *testing.T) { // Reconstruct data, assert that they are equal. data2Reader := partSet2.GetReader() - data2, err := ioutil.ReadAll(data2Reader) + data2, err := io.ReadAll(data2Reader) require.NoError(t, err) assert.Equal(t, data, data2) } func TestWrongProof(t *testing.T) { + t.Parallel() + // Construct random data of size partSize * 100 data := random.RandBytes(testPartSize * 100) partSet := NewPartSetFromData(data, testPartSize) @@ -86,6 +90,8 @@ func TestWrongProof(t *testing.T) { } func TestPartSetHeaderValidateBasic(t *testing.T) { + t.Parallel() + testCases := []struct { testName string malleatePartSetHeader func(*PartSetHeader) @@ -98,6 +104,8 @@ func TestPartSetHeaderValidateBasic(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + data := random.RandBytes(testPartSize * 100) ps := NewPartSetFromData(data, testPartSize) psHeader := ps.Header() @@ -108,6 +116,8 @@ func TestPartSetHeaderValidateBasic(t *testing.T) { } func TestPartValidateBasic(t *testing.T) { + t.Parallel() + testCases := []struct { testName string malleatePart func(*Part) @@ -128,6 +138,8 @@ func TestPartValidateBasic(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + data := random.RandBytes(testPartSize * 100) ps := NewPartSetFromData(data, testPartSize) part := ps.GetPart(0) diff --git a/tm2/pkg/bft/types/proposal_test.go b/tm2/pkg/bft/types/proposal_test.go index ebda33298d1..0692e9bdd6f 100644 --- a/tm2/pkg/bft/types/proposal_test.go +++ b/tm2/pkg/bft/types/proposal_test.go @@ -29,6 +29,8 @@ func init() { } func TestProposalSignable(t *testing.T) { + t.Parallel() + chainID := "test_chain_id" signBytes := testProposal.SignBytes(chainID) @@ -38,6 +40,8 @@ func TestProposalSignable(t *testing.T) { } func TestProposalString(t *testing.T) { + t.Parallel() + str := testProposal.String() expected := `Proposal{12345/23456 (010203:111:626C6F636B70, -1) 000000000000 @ 2018-02-11T07:09:22.765Z}` if str != expected { @@ -46,6 +50,8 @@ func TestProposalString(t *testing.T) { } func TestProposalVerifySignature(t *testing.T) { + t.Parallel() + privVal := NewMockPV() pubKey := privVal.GetPubKey() @@ -104,6 +110,8 @@ func BenchmarkProposalVerifySignature(b *testing.B) { } func TestProposalValidateBasic(t *testing.T) { + t.Parallel() + privVal := NewMockPV() testCases := []struct { testName string @@ -130,6 +138,8 @@ func TestProposalValidateBasic(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + prop := NewProposal( 4, 2, 2, blockID) diff --git a/tm2/pkg/bft/types/results_test.go b/tm2/pkg/bft/types/results_test.go index 6db7044f6ad..6b375413ac6 100644 --- a/tm2/pkg/bft/types/results_test.go +++ b/tm2/pkg/bft/types/results_test.go @@ -10,6 +10,8 @@ import ( ) func TestABCIResults(t *testing.T) { + t.Parallel() + a := ABCIResult{Error: nil, Data: nil} b := ABCIResult{Error: nil, Data: []byte{}} c := ABCIResult{Error: nil, Data: []byte("one")} @@ -46,6 +48,8 @@ func TestABCIResults(t *testing.T) { } func TestABCIResultsBytes(t *testing.T) { + t.Parallel() + results := NewResults([]abci.ResponseDeliverTx{ {ResponseBase: abci.ResponseBase{Error: nil, Data: []byte{}}}, {ResponseBase: abci.ResponseBase{Error: nil, Data: []byte("one")}}, diff --git a/tm2/pkg/bft/types/time/time_test.go b/tm2/pkg/bft/types/time/time_test.go index 1b1a30e5058..bf53e313fef 100644 --- a/tm2/pkg/bft/types/time/time_test.go +++ b/tm2/pkg/bft/types/time/time_test.go @@ -8,6 +8,8 @@ import ( ) func TestWeightedMedian(t *testing.T) { + t.Parallel() + m := make([]*WeightedTime, 3) t1 := Now() diff --git a/tm2/pkg/bft/types/tx_test.go b/tm2/pkg/bft/types/tx_test.go index 1470fab024d..375783f874f 100644 --- a/tm2/pkg/bft/types/tx_test.go +++ b/tm2/pkg/bft/types/tx_test.go @@ -25,6 +25,8 @@ func randInt(low, high int) int { } func TestTxIndex(t *testing.T) { + t.Parallel() + for i := 0; i < 20; i++ { txs := makeTxs(15, 60) for j := 0; j < len(txs); j++ { @@ -38,6 +40,8 @@ func TestTxIndex(t *testing.T) { } func TestTxIndexByHash(t *testing.T) { + t.Parallel() + for i := 0; i < 20; i++ { txs := makeTxs(15, 60) for j := 0; j < len(txs); j++ { @@ -51,6 +55,8 @@ func TestTxIndexByHash(t *testing.T) { } func TestValidTxProof(t *testing.T) { + t.Parallel() + cases := []struct { txs Txs }{ @@ -90,6 +96,8 @@ func TestValidTxProof(t *testing.T) { } func TestTxProofUnchangable(t *testing.T) { + t.Parallel() + // run the other test a bunch... for i := 0; i < 40; i++ { testTxProofUnchangable(t) diff --git a/tm2/pkg/bft/types/validator_set.go b/tm2/pkg/bft/types/validator_set.go index 617ceecaae5..80ed994ca39 100644 --- a/tm2/pkg/bft/types/validator_set.go +++ b/tm2/pkg/bft/types/validator_set.go @@ -758,7 +758,7 @@ func (vals *ValidatorSet) VerifyFutureCommit(newSet *ValidatorSet, chainID strin return nil } -//----------------- +// ----------------- // ErrTooMuchChange func IsErrTooMuchChange(err error) bool { @@ -775,7 +775,7 @@ func (e tooMuchChangeError) Error() string { return fmt.Sprintf("Invalid commit -- insufficient old voting power: got %v, needed %v", e.got, e.needed) } -//---------------- +// ---------------- func (vals *ValidatorSet) String() string { return vals.StringIndented("") @@ -802,7 +802,7 @@ func (vals *ValidatorSet) StringIndented(indent string) string { indent) } -//------------------------------------- +// ------------------------------------- // Implements sort for sorting validators by address. // Sort validators by address. @@ -822,7 +822,7 @@ func (valz ValidatorsByAddress) Swap(i, j int) { valz[j] = it } -//---------------------------------------- +// ---------------------------------------- // for testing // RandValidatorSet returns a randomized validator set, useful for testing. @@ -841,7 +841,7 @@ func RandValidatorSet(numValidators int, votingPower int64) (*ValidatorSet, []Pr return vals, privValidators } -/////////////////////////////////////////////////////////////////////////////// +// ----------- // safe addition/subtraction func safeAdd(a, b int64) (int64, bool) { diff --git a/tm2/pkg/bft/types/validator_set_test.go b/tm2/pkg/bft/types/validator_set_test.go index a2c38026ed8..0fafb6fca9e 100644 --- a/tm2/pkg/bft/types/validator_set_test.go +++ b/tm2/pkg/bft/types/validator_set_test.go @@ -20,6 +20,8 @@ import ( ) func TestValidatorSetBasic(t *testing.T) { + t.Parallel() + // empty or nil validator lists are allowed, // but attempting to IncrementProposerPriority on them will panic. vset := NewValidatorSet([]*Validator{}) @@ -76,6 +78,8 @@ func TestValidatorSetBasic(t *testing.T) { } func TestCopy(t *testing.T) { + t.Parallel() + vset := randValidatorSet(10) vsetHash := vset.Hash() if len(vsetHash) == 0 { @@ -92,6 +96,8 @@ func TestCopy(t *testing.T) { // Test that IncrementProposerPriority requires positive times. func TestIncrementProposerPriorityPositiveTimes(t *testing.T) { + t.Parallel() + vset := NewValidatorSet([]*Validator{ newValidator([]byte("foo"), 1000), newValidator([]byte("bar"), 300), @@ -122,9 +128,11 @@ func BenchmarkValidatorSetCopy(b *testing.B) { } } -//------------------------------------------------------------------- +// ------------------------------------------------------------------- func TestProposerSelection1(t *testing.T) { + t.Parallel() + vset := NewValidatorSet([]*Validator{ newValidator([]byte("foo"), 1000), newValidator([]byte("bar"), 300), @@ -143,6 +151,8 @@ func TestProposerSelection1(t *testing.T) { } func TestProposerSelection2(t *testing.T) { + t.Parallel() + addr0 := []byte{1} addr1 := []byte{2} addr2 := []byte{3} @@ -217,6 +227,8 @@ func TestProposerSelection2(t *testing.T) { } func TestProposerSelection3(t *testing.T) { + t.Parallel() + vset := NewValidatorSet([]*Validator{ newValidator([]byte("a"), 1), newValidator([]byte("b"), 1), @@ -321,9 +333,11 @@ func (vals *ValidatorSet) fromBytes(b []byte) { } } -//------------------------------------------------------------------- +// ------------------------------------------------------------------- func TestValidatorSetTotalVotingPowerPanicsOnOverflow(t *testing.T) { + t.Parallel() + // NewValidatorSet calls IncrementProposerPriority which calls TotalVotingPower() // which should panic on overflows: shouldPanic := func() { @@ -338,6 +352,8 @@ func TestValidatorSetTotalVotingPowerPanicsOnOverflow(t *testing.T) { } func TestAvgProposerPriority(t *testing.T) { + t.Parallel() + // Create Validator set without calling IncrementProposerPriority: tcs := []struct { vs ValidatorSet @@ -356,6 +372,8 @@ func TestAvgProposerPriority(t *testing.T) { } func TestAveragingInIncrementProposerPriority(t *testing.T) { + t.Parallel() + // Test that the averaging works as expected inside of IncrementProposerPriority. // Each validator comes with zero voting power which simplifies reasoning about // the expected ProposerPriority. @@ -408,6 +426,8 @@ func TestAveragingInIncrementProposerPriority(t *testing.T) { } func TestAveragingInIncrementProposerPriorityWithVotingPower(t *testing.T) { + t.Parallel() + // Other than TestAveragingInIncrementProposerPriority this is a more complete test showing // how each ProposerPriority changes in relation to the validator's voting power respectively. // average is zero in each round: @@ -558,6 +578,8 @@ func TestAveragingInIncrementProposerPriorityWithVotingPower(t *testing.T) { } func TestSafeAdd(t *testing.T) { + t.Parallel() + f := func(a, b int64) bool { c, overflow := safeAdd(a, b) return overflow || (!overflow && c == a+b) @@ -568,21 +590,27 @@ func TestSafeAdd(t *testing.T) { } func TestSafeAddClip(t *testing.T) { + t.Parallel() + assert.EqualValues(t, math.MaxInt64, safeAddClip(math.MaxInt64, 10)) assert.EqualValues(t, math.MaxInt64, safeAddClip(math.MaxInt64, math.MaxInt64)) assert.EqualValues(t, math.MinInt64, safeAddClip(math.MinInt64, -10)) } func TestSafeSubClip(t *testing.T) { + t.Parallel() + assert.EqualValues(t, math.MinInt64, safeSubClip(math.MinInt64, 10)) assert.EqualValues(t, 0, safeSubClip(math.MinInt64, math.MinInt64)) assert.EqualValues(t, math.MinInt64, safeSubClip(math.MinInt64, math.MaxInt64)) assert.EqualValues(t, math.MaxInt64, safeSubClip(math.MaxInt64, -10)) } -//------------------------------------------------------------------- +// ------------------------------------------------------------------- func TestValidatorSetVerifyCommit(t *testing.T) { + t.Parallel() + privKey := mock.GenPrivKey() pubKey := privKey.PubKey() v1 := NewValidator(pubKey, 1000) @@ -635,6 +663,8 @@ func TestValidatorSetVerifyCommit(t *testing.T) { } func TestEmptySet(t *testing.T) { + t.Parallel() + var valList []*Validator valSet := NewValidatorSet(valList) assert.Panics(t, func() { valSet.IncrementProposerPriority(1) }) @@ -661,6 +691,8 @@ func TestEmptySet(t *testing.T) { } func TestUpdatesForNewValidatorSet(t *testing.T) { + t.Parallel() + v1 := newValidator([]byte("v1"), 100) v2 := newValidator([]byte("v2"), 100) valList := []*Validator{v1, v2} @@ -793,6 +825,8 @@ func executeValSetErrTestCase(t *testing.T, idx int, tt valSetErrTestCase) { } func TestValSetUpdatesDuplicateEntries(t *testing.T) { + t.Parallel() + testCases := []valSetErrTestCase{ // Duplicate entries in changes { // first entry is duplicated change @@ -850,6 +884,8 @@ func TestValSetUpdatesDuplicateEntries(t *testing.T) { } func TestValSetUpdatesOverflows(t *testing.T) { + t.Parallel() + maxVP := MaxTotalVotingPower testCases := []valSetErrTestCase{ { // single update leading to overflow @@ -884,6 +920,8 @@ func TestValSetUpdatesOverflows(t *testing.T) { } func TestValSetUpdatesOtherErrors(t *testing.T) { + t.Parallel() + testCases := []valSetErrTestCase{ { // update with negative voting power testValSet(2, 10), @@ -909,6 +947,8 @@ func TestValSetUpdatesOtherErrors(t *testing.T) { } func TestValSetUpdatesBasicTestsExecute(t *testing.T) { + t.Parallel() + valSetUpdatesBasicTests := []struct { startVals []testVal updateVals []testVal @@ -970,6 +1010,8 @@ func TestValSetUpdatesBasicTestsExecute(t *testing.T) { // Test that different permutations of an update give the same result. func TestValSetUpdatesOrderIndependenceTestsExecute(t *testing.T) { + t.Parallel() + // startVals - initial validators to create the set with // updateVals - a sequence of updates to be applied to the set. // updateVals is shuffled a number of times during testing to check for same resulting validator set. @@ -1031,6 +1073,8 @@ func TestValSetUpdatesOrderIndependenceTestsExecute(t *testing.T) { // This tests the private function validator_set.go:applyUpdates() function, used only for additions and changes. // Should perform a proper merge of updatedVals and startVals func TestValSetApplyUpdatesTestsExecute(t *testing.T) { + t.Parallel() + valSetUpdatesBasicTests := []struct { startVals []testVal updateVals []testVal @@ -1174,6 +1218,8 @@ func applyChangesToValSet(t *testing.T, valSet *ValidatorSet, valsLists ...[]tes } func TestValSetUpdatePriorityOrderTests(t *testing.T) { + t.Parallel() + const nMaxElections = 5000 testCases := []testVSetCfg{ diff --git a/tm2/pkg/bft/types/vote_set_test.go b/tm2/pkg/bft/types/vote_set_test.go index e3199f83edc..ca5639f2406 100644 --- a/tm2/pkg/bft/types/vote_set_test.go +++ b/tm2/pkg/bft/types/vote_set_test.go @@ -61,6 +61,8 @@ func withBlockPartsHeader(vote *Vote, blockPartsHeader PartSetHeader) *Vote { } func TestAddVote(t *testing.T) { + t.Parallel() + height, round := int64(1), 0 voteSet, _, privValidators := randVoteSet(height, round, PrevoteType, 10, 1) val0 := privValidators[0] @@ -106,6 +108,8 @@ func TestAddVote(t *testing.T) { } func Test2_3Majority(t *testing.T) { + t.Parallel() + height, round := int64(1), 0 voteSet, _, privValidators := randVoteSet(height, round, PrevoteType, 10, 1) @@ -162,6 +166,8 @@ func Test2_3Majority(t *testing.T) { } func Test2_3MajorityRedux(t *testing.T) { + t.Parallel() + height, round := int64(1), 0 voteSet, _, privValidators := randVoteSet(height, round, PrevoteType, 100, 1) @@ -267,6 +273,8 @@ func Test2_3MajorityRedux(t *testing.T) { } func TestBadVotes(t *testing.T) { + t.Parallel() + height, round := int64(1), 0 voteSet, _, privValidators := randVoteSet(height, round, PrevoteType, 10, 1) @@ -332,6 +340,8 @@ func TestBadVotes(t *testing.T) { } func TestConflicts(t *testing.T) { + t.Parallel() + height, round := int64(1), 0 voteSet, _, privValidators := randVoteSet(height, round, PrevoteType, 4, 1) blockHash1 := random.RandBytes(32) @@ -465,6 +475,8 @@ func TestConflicts(t *testing.T) { } func TestMakeCommit(t *testing.T) { + t.Parallel() + height, round := int64(1), 0 voteSet, _, privValidators := randVoteSet(height, round, PrecommitType, 10, 1) blockHash, blockPartsHeader := crypto.CRandBytes(32), PartSetHeader{123, crypto.CRandBytes(32)} diff --git a/tm2/pkg/bft/types/vote_test.go b/tm2/pkg/bft/types/vote_test.go index 1028694ebc5..8b34e474fbd 100644 --- a/tm2/pkg/bft/types/vote_test.go +++ b/tm2/pkg/bft/types/vote_test.go @@ -50,6 +50,8 @@ func exampleVote(t byte) *Vote { // This test will fail and can be removed once CommitSig contains only sigs and // timestamps. func TestVoteEncoding(t *testing.T) { + t.Parallel() + vote := examplePrecommit() commitSig := vote.CommitSig() bz1 := amino.MustMarshal(vote) @@ -58,6 +60,8 @@ func TestVoteEncoding(t *testing.T) { } func TestVoteSignable(t *testing.T) { + t.Parallel() + vote := examplePrecommit() signBytes := vote.SignBytes("test_chain_id") @@ -68,6 +72,8 @@ func TestVoteSignable(t *testing.T) { } func TestVoteSignBytesTestVectors(t *testing.T) { + t.Parallel() + tests := []struct { chainID string vote *Vote @@ -147,6 +153,8 @@ func TestVoteSignBytesTestVectors(t *testing.T) { } func TestVoteProposalNotEq(t *testing.T) { + t.Parallel() + cv := CanonicalizeVote("", &Vote{Height: 1, Round: 1}) p := CanonicalizeProposal("", &Proposal{Height: 1, Round: 1}) vb, err := amino.MarshalSized(cv) @@ -157,6 +165,8 @@ func TestVoteProposalNotEq(t *testing.T) { } func TestVoteVerifySignature(t *testing.T) { + t.Parallel() + privVal := NewMockPV() pubkey := privVal.GetPubKey() @@ -186,6 +196,8 @@ func TestVoteVerifySignature(t *testing.T) { } func TestIsVoteTypeValid(t *testing.T) { + t.Parallel() + tc := []struct { name string in SignedMsgType @@ -199,6 +211,8 @@ func TestIsVoteTypeValid(t *testing.T) { for _, tt := range tc { tt := tt t.Run(tt.name, func(st *testing.T) { + st.Parallel() + if rs := IsVoteTypeValid(tt.in); rs != tt.out { t.Errorf("Got unexpected Vote type. Expected:\n%v\nGot:\n%v", rs, tt.out) } @@ -207,6 +221,8 @@ func TestIsVoteTypeValid(t *testing.T) { } func TestVoteVerify(t *testing.T) { + t.Parallel() + privVal := NewMockPV() pubkey := privVal.GetPubKey() @@ -225,6 +241,8 @@ func TestVoteVerify(t *testing.T) { } func TestMaxVoteBytes(t *testing.T) { + t.Parallel() + // time is varint encoded so need to pick the max. // year int, month Month, day, hour, min, sec, nsec int, loc *Location timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC) @@ -256,6 +274,8 @@ func TestMaxVoteBytes(t *testing.T) { } func TestVoteString(t *testing.T) { + t.Parallel() + str := examplePrecommit().String() expected := `Vote{56789:6AF1F4111082 12345/02/2(Precommit) 8B01023386C3 000000000000 @ 2017-12-25T03:00:01.234Z}` if str != expected { @@ -270,6 +290,8 @@ func TestVoteString(t *testing.T) { } func TestVoteValidateBasic(t *testing.T) { + t.Parallel() + privVal := NewMockPV() testCases := []struct { @@ -289,6 +311,8 @@ func TestVoteValidateBasic(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + vote := examplePrecommit() err := privVal.SignVote("test_chain_id", vote) require.NoError(t, err) diff --git a/tm2/pkg/bft/wal/wal.go b/tm2/pkg/bft/wal/wal.go index b66a34df222..a4a14d638dd 100644 --- a/tm2/pkg/bft/wal/wal.go +++ b/tm2/pkg/bft/wal/wal.go @@ -436,7 +436,7 @@ OUTER_LOOP: return nil, false, nil } -// ///////////////////////////////////////////////////////////////////////////// +// ----------- // A WALWriter writes custom-encoded WAL messages to an output stream. // Each binary WAL entry is length encoded, then crc encoded, @@ -512,7 +512,7 @@ func (enc *WALWriter) WriteMeta(meta MetaMessage) error { return err } -// ///////////////////////////////////////////////////////////////////////////// +// ----------- // IsDataCorruptionError returns true if data has been corrupted inside WAL. func IsDataCorruptionError(err error) bool { diff --git a/tm2/pkg/bft/wal/wal_test.go b/tm2/pkg/bft/wal/wal_test.go index 4cb94766389..322ee82bc2b 100644 --- a/tm2/pkg/bft/wal/wal_test.go +++ b/tm2/pkg/bft/wal/wal_test.go @@ -29,7 +29,7 @@ type TestMessage struct { func (TestMessage) AssertWALMessage() {} -var testPackage = amino.RegisterPackage(amino.NewPackage( +var _ = amino.RegisterPackage(amino.NewPackage( "github.com/gnolang/gno/tm2/pkg/bft/wal", "wal", amino.GetCallersDirname(), @@ -39,6 +39,8 @@ var testPackage = amino.RegisterPackage(amino.NewPackage( )) func TestWALWriterReader(t *testing.T) { + t.Parallel() + now := tmtime.Now() msgs := []TimedWALMessage{ {Time: now, Msg: TestMessage{Duration: time.Second, Height: 1, Round: 1}}, @@ -96,6 +98,8 @@ func makeTempWAL(t *testing.T, maxMsgSize int64, walChunkSize int64) (wal *baseW } func TestWALWrite(t *testing.T) { + t.Parallel() + // Create WAL const walChunkSize = 100000 wal := makeTempWAL(t, maxTestMsgSize, walChunkSize) @@ -119,6 +123,8 @@ func TestWALWrite(t *testing.T) { } func TestWALSearchForHeight(t *testing.T) { + t.Parallel() + // Create WAL const numHeight, numRounds, dataSize = 100, 10000, 10 const walChunkSize = 100000 @@ -161,6 +167,8 @@ func TestWALSearchForHeight(t *testing.T) { } func TestWALPeriodicSync(t *testing.T) { + t.Parallel() + // Create WAL const numHeight, numRounds, dataSize = 100, 10000, 10 const walChunkSize = 100000 diff --git a/tm2/pkg/bitarray/bit_array_test.go b/tm2/pkg/bitarray/bit_array_test.go index a70de110790..614d56d22cc 100644 --- a/tm2/pkg/bitarray/bit_array_test.go +++ b/tm2/pkg/bitarray/bit_array_test.go @@ -28,6 +28,8 @@ func randBitArray(bits int) (*BitArray, []byte) { } func TestAnd(t *testing.T) { + t.Parallel() + bA1, _ := randBitArray(51) bA2, _ := randBitArray(31) bA3 := bA1.And(bA2) @@ -52,6 +54,8 @@ func TestAnd(t *testing.T) { } func TestOr(t *testing.T) { + t.Parallel() + bA1, _ := randBitArray(51) bA2, _ := randBitArray(31) bA3 := bA1.Or(bA2) @@ -76,6 +80,8 @@ func TestOr(t *testing.T) { } func TestSub(t *testing.T) { + t.Parallel() + testCases := []struct { initBA string subtractingBA string @@ -107,6 +113,8 @@ func TestSub(t *testing.T) { } func TestPickRandom(t *testing.T) { + t.Parallel() + empty16Bits := "________________" empty64Bits := empty16Bits + empty16Bits + empty16Bits + empty16Bits testCases := []struct { @@ -134,6 +142,8 @@ func TestPickRandom(t *testing.T) { } func TestBytes(t *testing.T) { + t.Parallel() + bA := NewBitArray(4) bA.SetIndex(0, true) check := func(bA *BitArray, bz []byte) { @@ -163,6 +173,8 @@ func TestBytes(t *testing.T) { } func TestEmptyFull(t *testing.T) { + t.Parallel() + ns := []int{47, 123} for _, n := range ns { bA := NewBitArray(n) @@ -179,6 +191,8 @@ func TestEmptyFull(t *testing.T) { } func TestUpdateNeverPanics(t *testing.T) { + t.Parallel() + newRandBitArray := func(n int) *BitArray { ba, _ := randBitArray(n) return ba @@ -201,6 +215,8 @@ func TestUpdateNeverPanics(t *testing.T) { } func TestNewBitArrayNeverCrashesOnNegatives(t *testing.T) { + t.Parallel() + bitList := []int{-127, -128, -1 << 31} for _, bits := range bitList { _ = NewBitArray(bits) @@ -208,6 +224,8 @@ func TestNewBitArrayNeverCrashesOnNegatives(t *testing.T) { } func TestJSONMarshalUnmarshal(t *testing.T) { + t.Parallel() + bA1 := NewBitArray(0) bA2 := NewBitArray(1) @@ -233,6 +251,8 @@ func TestJSONMarshalUnmarshal(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.bA.String(), func(t *testing.T) { + t.Parallel() + bz, err := json.Marshal(tc.bA) require.NoError(t, err) diff --git a/tm2/pkg/clist/clist_test.go b/tm2/pkg/clist/clist_test.go index 496966d2d61..2cef3ef847f 100644 --- a/tm2/pkg/clist/clist_test.go +++ b/tm2/pkg/clist/clist_test.go @@ -2,8 +2,6 @@ package clist import ( "fmt" - "runtime" - "sync/atomic" "testing" "time" @@ -12,6 +10,8 @@ import ( ) func TestPanicOnMaxLength(t *testing.T) { + t.Parallel() + maxLength := 1000 l := newWithMax(maxLength) @@ -24,6 +24,8 @@ func TestPanicOnMaxLength(t *testing.T) { } func TestSmall(t *testing.T) { + t.Parallel() + l := New() el1 := l.PushBack(1) el2 := l.PushBack(2) @@ -64,110 +66,9 @@ func TestSmall(t *testing.T) { } } -// This test is quite hacky because it relies on SetFinalizer -// which isn't guaranteed to run at all. -// -//nolint:unused,deadcode -func _TestGCFifo(t *testing.T) { - t.Helper() - - if runtime.GOARCH != "amd64" { - t.Skipf("Skipping on non-amd64 machine") - } - - const numElements = 1000000 - l := New() - gcCount := new(uint64) - - // SetFinalizer doesn't work well with circular structures, - // so we construct a trivial non-circular structure to - // track. - type value struct { - Int int - } - done := make(chan struct{}) - - for i := 0; i < numElements; i++ { - v := new(value) - v.Int = i - l.PushBack(v) - runtime.SetFinalizer(v, func(v *value) { - atomic.AddUint64(gcCount, 1) - }) - } - - for el := l.Front(); el != nil; { - l.Remove(el) - // oldEl := el - el = el.Next() - // oldEl.DetachPrev() - // oldEl.DetachNext() - } - - runtime.GC() - time.Sleep(time.Second * 3) - runtime.GC() - time.Sleep(time.Second * 3) - _ = done - - if *gcCount != numElements { - t.Errorf("Expected gcCount to be %v, got %v", numElements, - *gcCount) - } -} - -// This test is quite hacky because it relies on SetFinalizer -// which isn't guaranteed to run at all. -// -//nolint:unused,deadcode -func _TestGCRandom(t *testing.T) { - t.Helper() - - if runtime.GOARCH != "amd64" { - t.Skipf("Skipping on non-amd64 machine") - } - - const numElements = 1000000 - l := New() - gcCount := 0 - - // SetFinalizer doesn't work well with circular structures, - // so we construct a trivial non-circular structure to - // track. - type value struct { - Int int - } - - for i := 0; i < numElements; i++ { - v := new(value) - v.Int = i - l.PushBack(v) - runtime.SetFinalizer(v, func(v *value) { - gcCount++ - }) - } - - els := make([]*CElement, 0, numElements) - for el := l.Front(); el != nil; el = el.Next() { - els = append(els, el) - } - - for _, i := range random.RandPerm(numElements) { - el := els[i] - l.Remove(el) - _ = el.Next() - } - - runtime.GC() - time.Sleep(time.Second * 3) - - if gcCount != numElements { - t.Errorf("Expected gcCount to be %v, got %v", numElements, - gcCount) - } -} - func TestScanRightDeleteRandom(t *testing.T) { + t.Parallel() + const numElements = 1000 const numTimes = 100 const numScanners = 10 @@ -239,6 +140,8 @@ func TestScanRightDeleteRandom(t *testing.T) { } func TestWaitChan(t *testing.T) { + t.Parallel() + l := New() ch := l.WaitChan() diff --git a/tm2/pkg/cmap/cmap_test.go b/tm2/pkg/cmap/cmap_test.go index e0fc5a5dc4e..d9051ea18d6 100644 --- a/tm2/pkg/cmap/cmap_test.go +++ b/tm2/pkg/cmap/cmap_test.go @@ -9,6 +9,8 @@ import ( ) func TestIterateKeysWithValues(t *testing.T) { + t.Parallel() + cmap := NewCMap() for i := 1; i <= 10; i++ { @@ -39,6 +41,8 @@ func TestIterateKeysWithValues(t *testing.T) { } func TestContains(t *testing.T) { + t.Parallel() + cmap := NewCMap() cmap.Set("key1", "value1") diff --git a/tm2/pkg/commands/commands_test.go b/tm2/pkg/commands/commands_test.go index 96802b9d720..4879e667cf5 100644 --- a/tm2/pkg/commands/commands_test.go +++ b/tm2/pkg/commands/commands_test.go @@ -26,6 +26,8 @@ func (c *mockConfig) RegisterFlags(fs *flag.FlagSet) { } func TestCommandParseAndRun(t *testing.T) { + t.Parallel() + type flags struct { b bool s string @@ -215,7 +217,10 @@ func TestCommandParseAndRun(t *testing.T) { }, } for _, tt := range tests { + tt := tt t.Run(tt.name, func(t *testing.T) { + t.Parallel() + var ( invokedCmd string args []string @@ -416,9 +421,7 @@ func TestCommand_AddSubCommands(t *testing.T) { // Forked from peterbourgon/ff/ffcli func TestHelpUsage(t *testing.T) { - fs, _ := fftest.Pair() - var buf bytes.Buffer - fs.SetOutput(&buf) + t.Parallel() tests := []struct { name string @@ -432,7 +435,6 @@ func TestHelpUsage(t *testing.T) { shortUsage: "TestHelpUsage [flags] ", shortHelp: "Some short help", longHelp: "Some long help.", - flagSet: fs, }, expectedOutput: strings.TrimSpace(` USAGE @@ -455,7 +457,6 @@ FLAGS name: "TestHelpUsage", shortUsage: "TestHelpUsage [flags] ", shortHelp: "Some short help", - flagSet: fs, }, expectedOutput: strings.TrimSpace(` USAGE @@ -477,7 +478,6 @@ FLAGS command: &Command{ name: "TestHelpUsage", shortUsage: "TestHelpUsage [flags] ", - flagSet: fs, }, expectedOutput: strings.TrimSpace(` USAGE @@ -494,8 +494,15 @@ FLAGS }, } for _, tt := range tests { + tt := tt t.Run(tt.name, func(t *testing.T) { - buf.Reset() + t.Parallel() + + fs, _ := fftest.Pair() + var buf bytes.Buffer + fs.SetOutput(&buf) + + tt.command.flagSet = fs err := tt.command.ParseAndRun(context.Background(), []string{"-h"}) @@ -507,6 +514,8 @@ FLAGS // Forked from peterbourgon/ff/ffcli func TestNestedOutput(t *testing.T) { + t.Parallel() + var ( rootHelpOutput = "USAGE\n \n\nSUBCOMMANDS\n foo\n\n" fooHelpOutput = "USAGE\n foo\n\nSUBCOMMANDS\n bar\n\n" @@ -572,6 +581,8 @@ func TestNestedOutput(t *testing.T) { }, } { t.Run(testcase.name, func(t *testing.T) { + t.Parallel() + var ( rootfs = flag.NewFlagSet("root", flag.ContinueOnError) foofs = flag.NewFlagSet("foo", flag.ContinueOnError) diff --git a/tm2/pkg/commands/io.go b/tm2/pkg/commands/io.go index b23455e4602..fc0d3378a88 100644 --- a/tm2/pkg/commands/io.go +++ b/tm2/pkg/commands/io.go @@ -9,21 +9,42 @@ import ( // IO holds settable command // input, output and error buffers -type IO struct { - In io.Reader +type IO interface { + // getters + In() io.Reader + Out() io.WriteCloser + Err() io.WriteCloser + + // setters and helpers + SetIn(in io.Reader) + SetOut(out io.WriteCloser) + SetErr(err io.WriteCloser) + Println(args ...interface{}) + Printf(format string, args ...interface{}) + Printfln(format string, args ...interface{}) + ErrPrintln(args ...interface{}) + ErrPrintfln(format string, args ...interface{}) + GetCheckPassword(prompts [2]string, insecure bool) (string, error) + GetConfirmation(prompt string) (bool, error) + GetPassword(prompt string, insecure bool) (string, error) + GetString(prompt string) (string, error) +} + +type IOImpl struct { + in io.Reader inBuf *bufio.Reader - Out io.WriteCloser + out io.WriteCloser outBuf *bufio.Writer - Err io.WriteCloser + err io.WriteCloser errBuf *bufio.Writer } // NewDefaultIO returns a default command io // that utilizes standard input / output / error -func NewDefaultIO() *IO { - c := &IO{} +func NewDefaultIO() IO { + c := &IOImpl{} c.SetIn(os.Stdin) c.SetOut(os.Stdout) @@ -34,17 +55,21 @@ func NewDefaultIO() *IO { // NewTestIO returns a test command io // that only sets standard input (to avoid panics) -func NewTestIO() *IO { - c := &IO{} +func NewTestIO() IO { + c := &IOImpl{} c.SetIn(os.Stdin) return c } +func (io *IOImpl) In() io.Reader { return io.in } +func (io *IOImpl) Out() io.WriteCloser { return io.out } +func (io *IOImpl) Err() io.WriteCloser { return io.err } + // SetIn sets the input reader for the command io -func (io *IO) SetIn(in io.Reader) { - io.In = in - if inbuf, ok := io.In.(*bufio.Reader); ok { +func (io *IOImpl) SetIn(in io.Reader) { + io.in = in + if inbuf, ok := io.in.(*bufio.Reader); ok { io.inBuf = inbuf return @@ -54,19 +79,19 @@ func (io *IO) SetIn(in io.Reader) { } // SetOut sets the output writer for the command io -func (io *IO) SetOut(out io.WriteCloser) { - io.Out = out - io.outBuf = bufio.NewWriter(io.Out) +func (io *IOImpl) SetOut(out io.WriteCloser) { + io.out = out + io.outBuf = bufio.NewWriter(io.out) } // SetErr sets the error writer for the command io -func (io *IO) SetErr(err io.WriteCloser) { - io.Err = err - io.errBuf = bufio.NewWriter(io.Err) +func (io *IOImpl) SetErr(err io.WriteCloser) { + io.err = err + io.errBuf = bufio.NewWriter(io.err) } // Println prints a line terminated by a newline -func (io *IO) Println(args ...interface{}) { +func (io *IOImpl) Println(args ...interface{}) { if io.outBuf == nil { return } @@ -76,7 +101,7 @@ func (io *IO) Println(args ...interface{}) { } // Printf prints a formatted string without trailing newline -func (io *IO) Printf(format string, args ...interface{}) { +func (io *IOImpl) Printf(format string, args ...interface{}) { if io.outBuf == nil { return } @@ -86,7 +111,7 @@ func (io *IO) Printf(format string, args ...interface{}) { } // Printfln prints a formatted string terminated by a newline -func (io *IO) Printfln(format string, args ...interface{}) { +func (io *IOImpl) Printfln(format string, args ...interface{}) { if io.outBuf == nil { return } @@ -97,7 +122,7 @@ func (io *IO) Printfln(format string, args ...interface{}) { // ErrPrintln prints a line terminated by a newline to // cmd.Err(Buf) -func (io *IO) ErrPrintln(args ...interface{}) { +func (io *IOImpl) ErrPrintln(args ...interface{}) { if io.errBuf == nil { return } @@ -107,7 +132,7 @@ func (io *IO) ErrPrintln(args ...interface{}) { } // ErrPrintfln prints a formatted string terminated by a newline to cmd.Err(Buf) -func (io *IO) ErrPrintfln(format string, args ...interface{}) { +func (io *IOImpl) ErrPrintfln(format string, args ...interface{}) { if io.errBuf == nil { return } diff --git a/tm2/pkg/commands/utils.go b/tm2/pkg/commands/utils.go index c7ce19e8138..90b6fa12b64 100644 --- a/tm2/pkg/commands/utils.go +++ b/tm2/pkg/commands/utils.go @@ -9,7 +9,7 @@ import ( ) // GetPassword fetches the password using the provided prompt, if any -func (io *IO) GetPassword( +func (io *IOImpl) GetPassword( prompt string, insecure bool, ) (string, error) { @@ -27,7 +27,7 @@ func (io *IO) GetPassword( } // readLine reads a new line from standard input -func (io *IO) readLine() (string, error) { +func (io *IOImpl) readLine() (string, error) { input, err := io.inBuf.ReadString('\n') if err != nil { return "", err @@ -52,7 +52,7 @@ func readPassword() (string, error) { // GetConfirmation will request user give the confirmation from stdin. // "y", "Y", "yes", "YES", and "Yes" all count as confirmations. // If the input is not recognized, it returns false and a nil error. -func (io *IO) GetConfirmation(prompt string) (bool, error) { +func (io *IOImpl) GetConfirmation(prompt string) (bool, error) { // On stderr so it isn't part of bash output. io.ErrPrintfln("%s [y/n]:", prompt) @@ -78,7 +78,7 @@ func (io *IO) GetConfirmation(prompt string) (bool, error) { // match (for creating a new password). // It enforces the password length. Only parses password once if // input is piped in. -func (io *IO) GetCheckPassword( +func (io *IOImpl) GetCheckPassword( prompts [2]string, insecure bool, ) (string, error) { @@ -100,7 +100,7 @@ func (io *IO) GetCheckPassword( } // GetString simply returns the trimmed string output of a given reader. -func (io *IO) GetString(prompt string) (string, error) { +func (io *IOImpl) GetString(prompt string) (string, error) { if prompt != "" { // On stderr so it isn't part of bash output. io.ErrPrintln(prompt) diff --git a/tm2/pkg/crypto/bcrypt/bcrypt_test.go b/tm2/pkg/crypto/bcrypt/bcrypt_test.go index 96634260d65..92b296bfe52 100644 --- a/tm2/pkg/crypto/bcrypt/bcrypt_test.go +++ b/tm2/pkg/crypto/bcrypt/bcrypt_test.go @@ -12,6 +12,8 @@ import ( ) func TestBcryptingIsEasy(t *testing.T) { + t.Parallel() + pass := []byte("mypassword") salt := []byte("1234567890123456") hp, err := GenerateFromPassword(salt, pass, 0) @@ -31,6 +33,8 @@ func TestBcryptingIsEasy(t *testing.T) { } func TestBcryptingIsCorrect(t *testing.T) { + t.Parallel() + pass := []byte("allmine") salt := []byte("XajjQvNhvvRt5GSeFk1xFe") expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga") @@ -56,6 +60,8 @@ func TestBcryptingIsCorrect(t *testing.T) { } func TestVeryShortPasswords(t *testing.T) { + t.Parallel() + key := []byte("k") salt := []byte("XajjQvNhvvRt5GSeFk1xFe") _, err := bcrypt(key, 10, salt) @@ -65,6 +71,8 @@ func TestVeryShortPasswords(t *testing.T) { } func TestTooLongPasswordsWork(t *testing.T) { + t.Parallel() + salt := []byte("XajjQvNhvvRt5GSeFk1xFe") // One byte over the usual 56 byte limit that blowfish has tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456") @@ -92,6 +100,8 @@ var invalidTests = []InvalidHashTest{ } func TestInvalidHashErrors(t *testing.T) { + t.Parallel() + check := func(name string, expected, err error) { if err == nil { t.Errorf("%s: Should have returned an error", name) @@ -109,6 +119,8 @@ func TestInvalidHashErrors(t *testing.T) { } func TestUnpaddedBase64Encoding(t *testing.T) { + t.Parallel() + original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30} encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe") @@ -129,6 +141,8 @@ func TestUnpaddedBase64Encoding(t *testing.T) { } func TestCost(t *testing.T) { + t.Parallel() + suffix := "XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C" for _, vers := range []string{"2a", "2"} { for _, cost := range []int{4, 10} { @@ -151,6 +165,8 @@ func TestCost(t *testing.T) { } func TestCostValidationInHash(t *testing.T) { + t.Parallel() + if testing.Short() { return } @@ -185,6 +201,8 @@ func TestCostValidationInHash(t *testing.T) { } func TestCostReturnsWithLeadingZeroes(t *testing.T) { + t.Parallel() + salt := []byte("1234567890123456") hp, _ := newFromPassword(salt, []byte("abcdefgh"), 7) cost := hp.Hash()[4:7] @@ -196,6 +214,8 @@ func TestCostReturnsWithLeadingZeroes(t *testing.T) { } func TestMinorNotRequired(t *testing.T) { + t.Parallel() + noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga") h, err := newFromHash(noMinorHash) if err != nil { @@ -233,6 +253,8 @@ func BenchmarkDefaultCost(b *testing.B) { // See Issue https://github.com/golang/go/issues/20425. func TestNoSideEffectsFromCompare(t *testing.T) { + t.Parallel() + source := []byte("passw0rd123456") password := source[:len(source)-6] token := source[len(source)-6:] diff --git a/tm2/pkg/crypto/bech32_test.go b/tm2/pkg/crypto/bech32_test.go index 13bdaa8e816..f5bc3e9ed7c 100644 --- a/tm2/pkg/crypto/bech32_test.go +++ b/tm2/pkg/crypto/bech32_test.go @@ -21,6 +21,8 @@ var invalidStrs = []string{ } func TestEmptyAddresses(t *testing.T) { + t.Parallel() + require.Equal(t, (crypto.Address{}).String(), "g1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqluuxe") addr := crypto.AddressFromBytes(make([]byte, 20)) @@ -47,6 +49,8 @@ func testMarshal(t *testing.T, addr crypto.Address, marshal func(orig interface{ } func TestRandBech32AddrConsistency(t *testing.T) { + t.Parallel() + var pub ed25519.PubKeyEd25519 for i := 0; i < 1000; i++ { diff --git a/tm2/pkg/crypto/bip39/bip39_test.go b/tm2/pkg/crypto/bip39/bip39_test.go index cbe15be6c3f..7854db76f53 100644 --- a/tm2/pkg/crypto/bip39/bip39_test.go +++ b/tm2/pkg/crypto/bip39/bip39_test.go @@ -14,6 +14,8 @@ type Vector struct { } func TestBip39(t *testing.T) { + t.Parallel() + for _, vector := range testVectors() { entropy, err := hex.DecodeString(vector.entropy) assert.NoError(t, err) @@ -31,6 +33,8 @@ func TestBip39(t *testing.T) { } func TestIsMnemonicValid(t *testing.T) { + t.Parallel() + for _, vector := range badMnemonicSentences() { assert.Equal(t, IsMnemonicValid(vector.mnemonic), false) } @@ -41,6 +45,8 @@ func TestIsMnemonicValid(t *testing.T) { } func TestInvalidMnemonicFails(t *testing.T) { + t.Parallel() + for _, vector := range badMnemonicSentences() { _, err := MnemonicToByteArray(vector.mnemonic) assert.NotNil(t, err) @@ -48,6 +54,8 @@ func TestInvalidMnemonicFails(t *testing.T) { } func TestValidateEntropyWithChecksumBitSize(t *testing.T) { + t.Parallel() + // Good tests. for i := 1; i <= (12*32 + 12); i++ { err := validateEntropyWithChecksumBitSize(i) @@ -74,6 +82,8 @@ func TestValidateEntropyWithChecksumBitSize(t *testing.T) { } func TestNewEntropy(t *testing.T) { + t.Parallel() + // Good tests. for i := 128; i <= 256; i += 32 { _, err := NewEntropy(i) diff --git a/tm2/pkg/crypto/ed25519/ed25519_test.go b/tm2/pkg/crypto/ed25519/ed25519_test.go index c07b7ae2298..fdf269018c0 100644 --- a/tm2/pkg/crypto/ed25519/ed25519_test.go +++ b/tm2/pkg/crypto/ed25519/ed25519_test.go @@ -10,6 +10,8 @@ import ( ) func TestSignAndValidateEd25519(t *testing.T) { + t.Parallel() + privKey := ed25519.GenPrivKey() pubKey := privKey.PubKey() diff --git a/tm2/pkg/crypto/hd/fundraiser_test.go b/tm2/pkg/crypto/hd/fundraiser_test.go index dabfd670c37..884425c6c39 100644 --- a/tm2/pkg/crypto/hd/fundraiser_test.go +++ b/tm2/pkg/crypto/hd/fundraiser_test.go @@ -43,6 +43,8 @@ func initFundraiserTestVectors(t *testing.T) []addrData { } func TestFundraiserCompatibility(t *testing.T) { + t.Parallel() + hdToAddrTable := initFundraiserTestVectors(t) for i, d := range hdToAddrTable { diff --git a/tm2/pkg/crypto/hd/hdpath_test.go b/tm2/pkg/crypto/hd/hdpath_test.go index 1e66a9fba2c..31e806b2b1a 100644 --- a/tm2/pkg/crypto/hd/hdpath_test.go +++ b/tm2/pkg/crypto/hd/hdpath_test.go @@ -34,6 +34,8 @@ const ( ) func TestStringifyFundraiserPathParams(t *testing.T) { + t.Parallel() + path := NewFundraiserParams(4, testCoinType, 22) require.Equal(t, "44'/118'/4'/0/22", path.String()) @@ -45,6 +47,8 @@ func TestStringifyFundraiserPathParams(t *testing.T) { } func TestPathToArray(t *testing.T) { + t.Parallel() + path := NewParams(44, 118, 1, false, 4) require.Equal(t, "[44 118 1 0 4]", fmt.Sprintf("%v", path.DerivationPath())) @@ -53,6 +57,8 @@ func TestPathToArray(t *testing.T) { } func TestParamsFromPath(t *testing.T) { + t.Parallel() + goodCases := []struct { params *BIP44Params path string diff --git a/tm2/pkg/crypto/keys/client/add.go b/tm2/pkg/crypto/keys/client/add.go index c90dfc9f803..71dc6f03090 100644 --- a/tm2/pkg/crypto/keys/client/add.go +++ b/tm2/pkg/crypto/keys/client/add.go @@ -29,7 +29,7 @@ type addCfg struct { index uint64 } -func newAddCmd(rootCfg *baseCfg, io *commands.IO) *commands.Command { +func newAddCmd(rootCfg *baseCfg, io commands.IO) *commands.Command { cfg := &addCfg{ rootCfg: rootCfg, } @@ -131,7 +131,7 @@ input output - armor encrypted private key (saved to file) */ -func execAdd(cfg *addCfg, args []string, io *commands.IO) error { +func execAdd(cfg *addCfg, args []string, io commands.IO) error { var ( kb keys.Keybase err error @@ -156,8 +156,7 @@ func execAdd(cfg *addCfg, args []string, io *commands.IO) error { return err } - _, err = kb.GetByName(name) - if err == nil { + if has, err := kb.HasByName(name); err == nil && has { // account exists, ask for user confirmation response, err2 := io.GetConfirmation(fmt.Sprintf("Override the existing name %s", name)) if err2 != nil { @@ -280,7 +279,7 @@ func execAdd(cfg *addCfg, args []string, io *commands.IO) error { return printCreate(info, showMnemonic, mnemonic, io) } -func printCreate(info keys.Info, showMnemonic bool, mnemonic string, io *commands.IO) error { +func printCreate(info keys.Info, showMnemonic bool, mnemonic string, io commands.IO) error { io.Println("") printNewInfo(info, io) @@ -296,7 +295,7 @@ It is the only way to recover your account if you ever forget your password. return nil } -func printNewInfo(info keys.Info, io *commands.IO) { +func printNewInfo(info keys.Info, io commands.IO) { keyname := info.GetName() keytype := info.GetType() keypub := info.GetPubKey() diff --git a/tm2/pkg/crypto/keys/client/addpkg.go b/tm2/pkg/crypto/keys/client/addpkg.go index 3de9a6de546..5bbd3f08ad0 100644 --- a/tm2/pkg/crypto/keys/client/addpkg.go +++ b/tm2/pkg/crypto/keys/client/addpkg.go @@ -24,7 +24,7 @@ type addPkgCfg struct { deposit string } -func newAddPkgCmd(rootCfg *makeTxCfg, io *commands.IO) *commands.Command { +func newAddPkgCmd(rootCfg *makeTxCfg, io commands.IO) *commands.Command { cfg := &addPkgCfg{ rootCfg: rootCfg, } @@ -65,7 +65,7 @@ func (c *addPkgCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execAddPkg(cfg *addPkgCfg, args []string, io *commands.IO) error { +func execAddPkg(cfg *addPkgCfg, args []string, io commands.IO) error { if cfg.pkgPath == "" { return errors.New("pkgpath not specified") } @@ -142,7 +142,7 @@ func signAndBroadcast( cfg *makeTxCfg, args []string, tx std.Tx, - io *commands.IO, + io commands.IO, ) error { baseopts := cfg.rootCfg txopts := cfg diff --git a/tm2/pkg/crypto/keys/client/broadcast.go b/tm2/pkg/crypto/keys/client/broadcast.go index f1d448495a6..9c05f2c43b3 100644 --- a/tm2/pkg/crypto/keys/client/broadcast.go +++ b/tm2/pkg/crypto/keys/client/broadcast.go @@ -23,7 +23,7 @@ type broadcastCfg struct { tx *std.Tx } -func newBroadcastCmd(rootCfg *baseCfg, io *commands.IO) *commands.Command { +func newBroadcastCmd(rootCfg *baseCfg, io commands.IO) *commands.Command { cfg := &broadcastCfg{ rootCfg: rootCfg, } @@ -50,7 +50,7 @@ func (c *broadcastCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execBroadcast(cfg *broadcastCfg, args []string, io *commands.IO) error { +func execBroadcast(cfg *broadcastCfg, args []string, io commands.IO) error { if len(args) != 1 { return flag.ErrHelp } diff --git a/tm2/pkg/crypto/keys/client/call.go b/tm2/pkg/crypto/keys/client/call.go index 29fe9739a36..6f9c9d52f5f 100644 --- a/tm2/pkg/crypto/keys/client/call.go +++ b/tm2/pkg/crypto/keys/client/call.go @@ -22,7 +22,7 @@ type callCfg struct { args commands.StringArr } -func newCallCmd(rootCfg *makeTxCfg, io *commands.IO) *commands.Command { +func newCallCmd(rootCfg *makeTxCfg, io commands.IO) *commands.Command { cfg := &callCfg{ rootCfg: rootCfg, } @@ -69,7 +69,7 @@ func (c *callCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execCall(cfg *callCfg, args []string, io *commands.IO) error { +func execCall(cfg *callCfg, args []string, io commands.IO) error { if cfg.pkgPath == "" { return errors.New("pkgpath not specified") } diff --git a/tm2/pkg/crypto/keys/client/delete.go b/tm2/pkg/crypto/keys/client/delete.go index e22ac30988c..cf65b8fc60a 100644 --- a/tm2/pkg/crypto/keys/client/delete.go +++ b/tm2/pkg/crypto/keys/client/delete.go @@ -16,7 +16,7 @@ type deleteCfg struct { force bool } -func newDeleteCmd(rootCfg *baseCfg, io *commands.IO) *commands.Command { +func newDeleteCmd(rootCfg *baseCfg, io commands.IO) *commands.Command { cfg := &deleteCfg{ rootCfg: rootCfg, } @@ -50,7 +50,7 @@ func (c *deleteCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execDelete(cfg *deleteCfg, args []string, io *commands.IO) error { +func execDelete(cfg *deleteCfg, args []string, io commands.IO) error { if len(args) != 1 { return flag.ErrHelp } @@ -101,7 +101,7 @@ func execDelete(cfg *deleteCfg, args []string, io *commands.IO) error { return nil } -func confirmDeletion(io *commands.IO) error { +func confirmDeletion(io commands.IO) error { answer, err := io.GetConfirmation("Key reference will be deleted. Continue?") if err != nil { return err diff --git a/tm2/pkg/crypto/keys/client/export.go b/tm2/pkg/crypto/keys/client/export.go index 6eff8aa97b3..c3921c31fd7 100644 --- a/tm2/pkg/crypto/keys/client/export.go +++ b/tm2/pkg/crypto/keys/client/export.go @@ -18,7 +18,7 @@ type exportCfg struct { unsafe bool } -func newExportCmd(rootCfg *baseCfg, io *commands.IO) *commands.Command { +func newExportCmd(rootCfg *baseCfg, io commands.IO) *commands.Command { cfg := &exportCfg{ rootCfg: rootCfg, } @@ -59,7 +59,7 @@ func (c *exportCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execExport(cfg *exportCfg, io *commands.IO) error { +func execExport(cfg *exportCfg, io commands.IO) error { // Create a new instance of the key-base kb, err := keys.NewKeyBaseFromDir(cfg.rootCfg.Home) if err != nil { diff --git a/tm2/pkg/crypto/keys/client/export_test.go b/tm2/pkg/crypto/keys/client/export_test.go index 7ddbeede993..0f4c5311dfa 100644 --- a/tm2/pkg/crypto/keys/client/export_test.go +++ b/tm2/pkg/crypto/keys/client/export_test.go @@ -64,11 +64,9 @@ func addRandomKeyToKeybase( } type testCmdKeyOptsBase struct { - kbHome string - keyName string - decryptPassword string - encryptPassword string - unsafe bool + kbHome string + keyName string + unsafe bool } type testExportKeyOpts struct { diff --git a/tm2/pkg/crypto/keys/client/generate.go b/tm2/pkg/crypto/keys/client/generate.go index d209bd70bd3..04a0ea8947f 100644 --- a/tm2/pkg/crypto/keys/client/generate.go +++ b/tm2/pkg/crypto/keys/client/generate.go @@ -16,7 +16,7 @@ type generateCfg struct { customEntropy bool } -func newGenerateCmd(rootCfg *baseCfg, io *commands.IO) *commands.Command { +func newGenerateCmd(rootCfg *baseCfg, io commands.IO) *commands.Command { cfg := &generateCfg{ rootCfg: rootCfg, } @@ -43,7 +43,7 @@ func (c *generateCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execGenerate(cfg *generateCfg, args []string, io *commands.IO) error { +func execGenerate(cfg *generateCfg, args []string, io commands.IO) error { customEntropy := cfg.customEntropy if len(args) != 0 { diff --git a/tm2/pkg/crypto/keys/client/import.go b/tm2/pkg/crypto/keys/client/import.go index e1d8af55861..e4f20ff6402 100644 --- a/tm2/pkg/crypto/keys/client/import.go +++ b/tm2/pkg/crypto/keys/client/import.go @@ -18,7 +18,7 @@ type importCfg struct { unsafe bool } -func newImportCmd(rootCfg *baseCfg, io *commands.IO) *commands.Command { +func newImportCmd(rootCfg *baseCfg, io commands.IO) *commands.Command { cfg := &importCfg{ rootCfg: rootCfg, } @@ -59,7 +59,7 @@ func (c *importCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execImport(cfg *importCfg, io *commands.IO) error { +func execImport(cfg *importCfg, io commands.IO) error { // Create a new instance of the key-base kb, err := keys.NewKeyBaseFromDir(cfg.rootCfg.Home) if err != nil { diff --git a/tm2/pkg/crypto/keys/client/list.go b/tm2/pkg/crypto/keys/client/list.go index cb86feb2395..bdee6b3bbe9 100644 --- a/tm2/pkg/crypto/keys/client/list.go +++ b/tm2/pkg/crypto/keys/client/list.go @@ -8,7 +8,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/crypto/keys" ) -func newListCmd(rootCfg *baseCfg, io *commands.IO) *commands.Command { +func newListCmd(rootCfg *baseCfg, io commands.IO) *commands.Command { return commands.NewCommand( commands.Metadata{ Name: "list", @@ -22,7 +22,7 @@ func newListCmd(rootCfg *baseCfg, io *commands.IO) *commands.Command { ) } -func execList(cfg *baseCfg, args []string, io *commands.IO) error { +func execList(cfg *baseCfg, args []string, io commands.IO) error { if len(args) != 0 { return flag.ErrHelp } @@ -40,7 +40,7 @@ func execList(cfg *baseCfg, args []string, io *commands.IO) error { return err } -func printInfos(infos []keys.Info, io *commands.IO) { +func printInfos(infos []keys.Info, io commands.IO) { for i, info := range infos { keyname := info.GetName() keytype := info.GetType() diff --git a/tm2/pkg/crypto/keys/client/maketx.go b/tm2/pkg/crypto/keys/client/maketx.go index 36214a5a983..e3fe89b930d 100644 --- a/tm2/pkg/crypto/keys/client/maketx.go +++ b/tm2/pkg/crypto/keys/client/maketx.go @@ -17,7 +17,7 @@ type makeTxCfg struct { chainID string } -func newMakeTxCmd(rootCfg *baseCfg, io *commands.IO) *commands.Command { +func newMakeTxCmd(rootCfg *baseCfg, io commands.IO) *commands.Command { cfg := &makeTxCfg{ rootCfg: rootCfg, } diff --git a/tm2/pkg/crypto/keys/client/query.go b/tm2/pkg/crypto/keys/client/query.go index 8cc5757aba7..746048e772c 100644 --- a/tm2/pkg/crypto/keys/client/query.go +++ b/tm2/pkg/crypto/keys/client/query.go @@ -21,7 +21,7 @@ type queryCfg struct { path string } -func newQueryCmd(rootCfg *baseCfg, io *commands.IO) *commands.Command { +func newQueryCmd(rootCfg *baseCfg, io commands.IO) *commands.Command { cfg := &queryCfg{ rootCfg: rootCfg, } @@ -62,7 +62,7 @@ func (c *queryCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execQuery(cfg *queryCfg, args []string, io *commands.IO) error { +func execQuery(cfg *queryCfg, args []string, io commands.IO) error { if len(args) != 1 { return flag.ErrHelp } diff --git a/tm2/pkg/crypto/keys/client/root.go b/tm2/pkg/crypto/keys/client/root.go index 550dd408b77..61fd7d077b5 100644 --- a/tm2/pkg/crypto/keys/client/root.go +++ b/tm2/pkg/crypto/keys/client/root.go @@ -18,7 +18,7 @@ type baseCfg struct { BaseOptions } -func NewRootCmd(io *commands.IO) *commands.Command { +func NewRootCmd(io commands.IO) *commands.Command { cfg := &baseCfg{} cmd := commands.NewCommand( diff --git a/tm2/pkg/crypto/keys/client/send.go b/tm2/pkg/crypto/keys/client/send.go index 6d19ffcb393..a5098aea08c 100644 --- a/tm2/pkg/crypto/keys/client/send.go +++ b/tm2/pkg/crypto/keys/client/send.go @@ -21,7 +21,7 @@ type sendCfg struct { to string } -func newSendCmd(rootCfg *makeTxCfg, io *commands.IO) *commands.Command { +func newSendCmd(rootCfg *makeTxCfg, io commands.IO) *commands.Command { cfg := &sendCfg{ rootCfg: rootCfg, } @@ -55,7 +55,7 @@ func (c *sendCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execSend(cfg *sendCfg, args []string, io *commands.IO) error { +func execSend(cfg *sendCfg, args []string, io commands.IO) error { if len(args) != 1 { return flag.ErrHelp } diff --git a/tm2/pkg/crypto/keys/client/sign.go b/tm2/pkg/crypto/keys/client/sign.go index 761e0d7a563..f8fcc02fdde 100644 --- a/tm2/pkg/crypto/keys/client/sign.go +++ b/tm2/pkg/crypto/keys/client/sign.go @@ -28,7 +28,7 @@ type signCfg struct { pass string } -func newSignCmd(rootCfg *baseCfg, io *commands.IO) *commands.Command { +func newSignCmd(rootCfg *baseCfg, io commands.IO) *commands.Command { cfg := &signCfg{ rootCfg: rootCfg, } @@ -83,7 +83,7 @@ func (c *signCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execSign(cfg *signCfg, args []string, io *commands.IO) error { +func execSign(cfg *signCfg, args []string, io commands.IO) error { var err error if len(args) != 1 { diff --git a/tm2/pkg/crypto/keys/client/verify.go b/tm2/pkg/crypto/keys/client/verify.go index bb486c1a8fa..fff2fcd852f 100644 --- a/tm2/pkg/crypto/keys/client/verify.go +++ b/tm2/pkg/crypto/keys/client/verify.go @@ -16,7 +16,7 @@ type verifyCfg struct { docPath string } -func newVerifyCmd(rootCfg *baseCfg, io *commands.IO) *commands.Command { +func newVerifyCmd(rootCfg *baseCfg, io commands.IO) *commands.Command { cfg := &verifyCfg{ rootCfg: rootCfg, } @@ -43,7 +43,7 @@ func (c *verifyCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execVerify(cfg *verifyCfg, args []string, io *commands.IO) error { +func execVerify(cfg *verifyCfg, args []string, io commands.IO) error { var ( kb keys.Keybase err error diff --git a/tm2/pkg/crypto/keys/keybase.go b/tm2/pkg/crypto/keys/keybase.go index 16b3631d188..31b0012c433 100644 --- a/tm2/pkg/crypto/keys/keybase.go +++ b/tm2/pkg/crypto/keys/keybase.go @@ -46,14 +46,6 @@ const ( infoSuffix = "info" ) -const ( - // used for deriving seed from mnemonic - DefaultBIP39Passphrase = "" - - // bits of entropy to draw when creating a mnemonic - defaultEntropySize = 256 -) - var ( // ErrUnsupportedSigningAlgo is raised when the caller tries to use a // different signing scheme than secp256k1. @@ -168,14 +160,32 @@ func (kb dbKeybase) List() ([]Info, error) { return res, nil } +// HasByNameOrAddress checks if a key with the name or bech32 string address is in the keybase. +func (kb dbKeybase) HasByNameOrAddress(nameOrBech32 string) (bool, error) { + address, err := crypto.AddressFromBech32(nameOrBech32) + if err != nil { + return kb.HasByName(nameOrBech32) + } + return kb.HasByAddress(address) +} + +// HasByName checks if a key with the name is in the keybase. +func (kb dbKeybase) HasByName(name string) (bool, error) { + return kb.db.Has(infoKey(name)), nil +} + +// HasByAddress checks if a key with the address is in the keybase. +func (kb dbKeybase) HasByAddress(address crypto.Address) (bool, error) { + return kb.db.Has(addrKey(address)), nil +} + // Get returns the public information about one key. func (kb dbKeybase) GetByNameOrAddress(nameOrBech32 string) (Info, error) { addr, err := crypto.AddressFromBech32(nameOrBech32) if err != nil { return kb.GetByName(nameOrBech32) - } else { - return kb.GetByAddress(addr) } + return kb.GetByAddress(addr) } func (kb dbKeybase) GetByName(name string) (Info, error) { @@ -189,7 +199,7 @@ func (kb dbKeybase) GetByName(name string) (Info, error) { func (kb dbKeybase) GetByAddress(address crypto.Address) (Info, error) { ik := kb.db.Get(addrKey(address)) if len(ik) == 0 { - return nil, fmt.Errorf("key with address %s not found", address) + return nil, keyerror.NewErrKeyNotFound(fmt.Sprintf("key with address %s not found", address)) } bs := kb.db.Get(ik) return readInfo(bs) diff --git a/tm2/pkg/crypto/keys/keybase_test.go b/tm2/pkg/crypto/keys/keybase_test.go index 987a271881b..d7660ac38f1 100644 --- a/tm2/pkg/crypto/keys/keybase_test.go +++ b/tm2/pkg/crypto/keys/keybase_test.go @@ -9,9 +9,12 @@ import ( "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/crypto/ed25519" + "github.com/gnolang/gno/tm2/pkg/crypto/keys/keyerror" ) func TestCreateAccountInvalidMnemonic(t *testing.T) { + t.Parallel() + kb := NewInMemory() _, err := kb.CreateAccount( "some_account", @@ -22,6 +25,8 @@ func TestCreateAccountInvalidMnemonic(t *testing.T) { } func TestCreateLedgerUnsupportedAlgo(t *testing.T) { + t.Parallel() + kb := NewInMemory() _, err := kb.CreateLedger("some_account", Ed25519, "cosmos", 0, 1) assert.Error(t, err) @@ -29,6 +34,8 @@ func TestCreateLedgerUnsupportedAlgo(t *testing.T) { } func TestCreateLedger(t *testing.T) { + t.Parallel() + kb := NewInMemory() // test_cover and test_unit will result in different answers @@ -65,6 +72,8 @@ func TestCreateLedger(t *testing.T) { // TestKeyManagement makes sure we can manipulate these keys well func TestKeyManagement(t *testing.T) { + t.Parallel() + // make the storage with reasonable defaults cstore := NewInMemory() @@ -80,8 +89,9 @@ func TestKeyManagement(t *testing.T) { assert.Empty(t, l) // create some keys - _, err = cstore.GetByName(n1) - require.Error(t, err) + has, err := cstore.HasByName(n1) + require.NoError(t, err) + require.False(t, has) i, err := cstore.CreateAccount(n1, mn1, bip39Passphrase, p1, 0, 0) require.NoError(t, err) require.Equal(t, n1, i.GetName()) @@ -91,14 +101,21 @@ func TestKeyManagement(t *testing.T) { // we can get these keys i2, err := cstore.GetByName(n2) require.NoError(t, err) - _, err = cstore.GetByName(n3) - require.NotNil(t, err) - _, err = cstore.GetByAddress(toAddr(i2)) + has, err = cstore.HasByName(n3) + require.NoError(t, err) + require.False(t, has) + has, err = cstore.HasByAddress(toAddr(i2)) + require.NoError(t, err) + require.True(t, has) + // Also check with HasByNameOrAddress + has, err = cstore.HasByNameOrAddress(crypto.AddressToBech32(toAddr(i2))) require.NoError(t, err) + require.True(t, has) addr, err := crypto.AddressFromBech32("g1frtkxv37nq7arvyz5p0mtjqq7hwuvd4dnt892p") require.NoError(t, err) _, err = cstore.GetByAddress(addr) require.NotNil(t, err) + require.True(t, keyerror.IsErrKeyNotFound(err)) // list shows them in order keyS, err := cstore.List() @@ -117,8 +134,9 @@ func TestKeyManagement(t *testing.T) { keyS, err = cstore.List() require.NoError(t, err) require.Equal(t, 1, len(keyS)) - _, err = cstore.GetByName(n1) - require.Error(t, err) + has, err = cstore.HasByName(n1) + require.NoError(t, err) + require.False(t, has) // create an offline key o1 := "offline" @@ -147,6 +165,8 @@ func TestKeyManagement(t *testing.T) { // TestSignVerify does some detailed checks on how we sign and validate // signatures func TestSignVerify(t *testing.T) { + t.Parallel() + cstore := NewInMemory() n1, n2, n3 := "some dude", "a dudette", "dude-ish" @@ -233,6 +253,8 @@ func assertPassword(t *testing.T, cstore Keybase, name, pass, badpass string) { // TestExportImport tests exporting and importing func TestExportImport(t *testing.T) { + t.Parallel() + // make the storage with reasonable defaults cstore := NewInMemory() @@ -263,6 +285,8 @@ func TestExportImport(t *testing.T) { } func TestExportImportPubKey(t *testing.T) { + t.Parallel() + // make the storage with reasonable defaults cstore := NewInMemory() @@ -304,6 +328,8 @@ func TestExportImportPubKey(t *testing.T) { // TestAdvancedKeyManagement verifies update, import, export functionality func TestAdvancedKeyManagement(t *testing.T) { + t.Parallel() + // make the storage with reasonable defaults cstore := NewInMemory() @@ -352,6 +378,8 @@ func TestAdvancedKeyManagement(t *testing.T) { // TestSeedPhrase verifies restoring from a seed phrase func TestSeedPhrase(t *testing.T) { + t.Parallel() + // make the storage with reasonable defaults cstore := NewInMemory() @@ -368,8 +396,9 @@ func TestSeedPhrase(t *testing.T) { // now, let us delete this key err = cstore.Delete(n1, p1, false) require.Nil(t, err, "%+v", err) - _, err = cstore.GetByName(n1) - require.NotNil(t, err) + has, err := cstore.HasByName(n1) + require.NoError(t, err) + require.False(t, has) } func ExampleNew() { diff --git a/tm2/pkg/crypto/keys/lazy_keybase.go b/tm2/pkg/crypto/keys/lazy_keybase.go index f7f9e229980..62e88d9a8e2 100644 --- a/tm2/pkg/crypto/keys/lazy_keybase.go +++ b/tm2/pkg/crypto/keys/lazy_keybase.go @@ -37,6 +37,36 @@ func (lkb lazyKeybase) List() ([]Info, error) { return NewDBKeybase(db).List() } +func (lkb lazyKeybase) HasByNameOrAddress(nameOrBech32 string) (bool, error) { + db, err := db.NewDB(lkb.name, dbBackend, lkb.dir) + if err != nil { + return false, err + } + defer db.Close() + + return NewDBKeybase(db).HasByNameOrAddress(nameOrBech32) +} + +func (lkb lazyKeybase) HasByName(name string) (bool, error) { + db, err := db.NewDB(lkb.name, dbBackend, lkb.dir) + if err != nil { + return false, err + } + defer db.Close() + + return NewDBKeybase(db).HasByName(name) +} + +func (lkb lazyKeybase) HasByAddress(address crypto.Address) (bool, error) { + db, err := db.NewDB(lkb.name, dbBackend, lkb.dir) + if err != nil { + return false, err + } + defer db.Close() + + return NewDBKeybase(db).HasByAddress(address) +} + func (lkb lazyKeybase) GetByNameOrAddress(nameOrBech32 string) (Info, error) { db, err := db.NewDB(lkb.name, dbBackend, lkb.dir) if err != nil { diff --git a/tm2/pkg/crypto/keys/types.go b/tm2/pkg/crypto/keys/types.go index bba3a917b69..c5d33023a0a 100644 --- a/tm2/pkg/crypto/keys/types.go +++ b/tm2/pkg/crypto/keys/types.go @@ -13,6 +13,9 @@ import ( type Keybase interface { // CRUD on the keystore List() ([]Info, error) + HasByNameOrAddress(nameOrBech32 string) (bool, error) + HasByName(name string) (bool, error) + HasByAddress(address crypto.Address) (bool, error) GetByNameOrAddress(nameOrBech32 string) (Info, error) GetByName(name string) (Info, error) GetByAddress(address crypto.Address) (Info, error) diff --git a/tm2/pkg/crypto/keys/types_test.go b/tm2/pkg/crypto/keys/types_test.go index a0591819a88..2a2dd2c82f6 100644 --- a/tm2/pkg/crypto/keys/types_test.go +++ b/tm2/pkg/crypto/keys/types_test.go @@ -11,6 +11,8 @@ import ( ) func Test_writeReadLedgerInfo(t *testing.T) { + t.Parallel() + var tmpKey secp256k1.PubKeySecp256k1 bz, _ := hex.DecodeString("035AD6810A47F073553FF30D2FCC7E0D3B1C0B74B61A1AAA2582344037151E143A") copy(tmpKey[:], bz) diff --git a/tm2/pkg/crypto/merkle/proof_key_path_test.go b/tm2/pkg/crypto/merkle/proof_key_path_test.go index 22e3e21ca3d..669e8c5630c 100644 --- a/tm2/pkg/crypto/merkle/proof_key_path_test.go +++ b/tm2/pkg/crypto/merkle/proof_key_path_test.go @@ -10,6 +10,8 @@ import ( ) func TestKeyPath(t *testing.T) { + t.Parallel() + var path KeyPath keys := make([][]byte, 10) alphanum := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/tm2/pkg/crypto/merkle/proof_test.go b/tm2/pkg/crypto/merkle/proof_test.go index 676e281ac60..0424ea351dd 100644 --- a/tm2/pkg/crypto/merkle/proof_test.go +++ b/tm2/pkg/crypto/merkle/proof_test.go @@ -26,19 +26,6 @@ func NewDominoOp(key, input, output string) DominoOp { } } -//nolint:unused -func DominoOpDecoder(pop ProofOp) (ProofOperator, error) { - if pop.Type != ProofOpDomino { - panic("unexpected proof op type") - } - var op DominoOp // a bit strange as we'll discard this, but it works. - err := amino.UnmarshalSized(pop.Data, &op) - if err != nil { - return nil, errors.Wrap(err, "decoding ProofOp.Data into SimpleValueOp") - } - return NewDominoOp(string(pop.Key), op.Input, op.Output), nil -} - func (dop DominoOp) ProofOp() ProofOp { bz := amino.MustMarshalSized(dop) return ProofOp{ @@ -63,9 +50,11 @@ func (dop DominoOp) GetKey() []byte { return []byte(dop.key) } -//---------------------------------------- +// ---------------------------------------- func TestProofOperators(t *testing.T) { + t.Parallel() + var err error // ProofRuntime setup diff --git a/tm2/pkg/crypto/merkle/rfc6962_test.go b/tm2/pkg/crypto/merkle/rfc6962_test.go index 917b09015b0..57f72cea311 100644 --- a/tm2/pkg/crypto/merkle/rfc6962_test.go +++ b/tm2/pkg/crypto/merkle/rfc6962_test.go @@ -24,6 +24,8 @@ import ( ) func TestRFC6962Hasher(t *testing.T) { + t.Parallel() + _, leafHashTrail := trailsFromByteSlices([][]byte{[]byte("L123456")}) leafHash := leafHashTrail.Hash _, leafHashTrail = trailsFromByteSlices([][]byte{{}}) @@ -58,6 +60,8 @@ func TestRFC6962Hasher(t *testing.T) { } { tc := tc t.Run(tc.desc, func(t *testing.T) { + t.Parallel() + wantBytes, err := hex.DecodeString(tc.want) if err != nil { t.Fatalf("hex.DecodeString(%x): %v", tc.want, err) @@ -70,6 +74,8 @@ func TestRFC6962Hasher(t *testing.T) { } func TestRFC6962HasherCollisions(t *testing.T) { + t.Parallel() + // Check that different leaves have different hashes. leaf1, leaf2 := []byte("Hello"), []byte("World") _, leafHashTrail := trailsFromByteSlices([][]byte{leaf1}) diff --git a/tm2/pkg/crypto/merkle/simple_map_test.go b/tm2/pkg/crypto/merkle/simple_map_test.go index 366d9f39099..6df8e0b967e 100644 --- a/tm2/pkg/crypto/merkle/simple_map_test.go +++ b/tm2/pkg/crypto/merkle/simple_map_test.go @@ -8,6 +8,8 @@ import ( ) func TestSimpleMap(t *testing.T) { + t.Parallel() + tests := []struct { keys []string values []string // each string gets converted to []byte in test diff --git a/tm2/pkg/crypto/merkle/simple_proof_test.go b/tm2/pkg/crypto/merkle/simple_proof_test.go index 1a517905b5e..88677e3fb0e 100644 --- a/tm2/pkg/crypto/merkle/simple_proof_test.go +++ b/tm2/pkg/crypto/merkle/simple_proof_test.go @@ -7,6 +7,8 @@ import ( ) func TestSimpleProofValidateBasic(t *testing.T) { + t.Parallel() + testCases := []struct { testName string malleateProof func(*SimpleProof) @@ -23,6 +25,8 @@ func TestSimpleProofValidateBasic(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + _, proofs := SimpleProofsFromByteSlices([][]byte{ []byte("apple"), []byte("watermelon"), diff --git a/tm2/pkg/crypto/merkle/simple_tree_test.go b/tm2/pkg/crypto/merkle/simple_tree_test.go index 8690bae6ac3..209df75b1b5 100644 --- a/tm2/pkg/crypto/merkle/simple_tree_test.go +++ b/tm2/pkg/crypto/merkle/simple_tree_test.go @@ -17,6 +17,8 @@ func (tI testItem) Hash() []byte { } func TestSimpleProof(t *testing.T) { + t.Parallel() + total := 100 items := make([][]byte, total) @@ -69,6 +71,8 @@ func TestSimpleProof(t *testing.T) { } func TestSimpleHashAlternatives(t *testing.T) { + t.Parallel() + total := 100 items := make([][]byte, total) @@ -104,6 +108,8 @@ func BenchmarkSimpleHashAlternatives(b *testing.B) { } func Test_getSplitPoint(t *testing.T) { + t.Parallel() + tests := []struct { length int want int diff --git a/tm2/pkg/crypto/mock/mock_test.go b/tm2/pkg/crypto/mock/mock_test.go index 2e5f1d776bd..3d7ac571faa 100644 --- a/tm2/pkg/crypto/mock/mock_test.go +++ b/tm2/pkg/crypto/mock/mock_test.go @@ -10,6 +10,8 @@ import ( ) func TestSignAndValidateMock(t *testing.T) { + t.Parallel() + privKey := mock.PrivKeyMock([]byte{0x01}) pubKey := privKey.PubKey() diff --git a/tm2/pkg/crypto/multisig/bitarray/compact_bit_array_test.go b/tm2/pkg/crypto/multisig/bitarray/compact_bit_array_test.go index ecbfb64005d..c41e8e3c87b 100644 --- a/tm2/pkg/crypto/multisig/bitarray/compact_bit_array_test.go +++ b/tm2/pkg/crypto/multisig/bitarray/compact_bit_array_test.go @@ -28,6 +28,8 @@ func randCompactBitArray(bits int) (*CompactBitArray, []byte) { } func TestNewBitArrayNeverCrashesOnNegatives(t *testing.T) { + t.Parallel() + bitList := []int{-127, -128, -1 << 31} for _, bits := range bitList { bA := NewCompactBitArray(bits) @@ -36,6 +38,8 @@ func TestNewBitArrayNeverCrashesOnNegatives(t *testing.T) { } func TestJSONMarshalUnmarshal(t *testing.T) { + t.Parallel() + bA1 := NewCompactBitArray(0) bA2 := NewCompactBitArray(1) @@ -73,6 +77,8 @@ func TestJSONMarshalUnmarshal(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.bA.String(), func(t *testing.T) { + t.Parallel() + bz, err := json.Marshal(tc.bA) require.NoError(t, err) @@ -96,6 +102,8 @@ func TestJSONMarshalUnmarshal(t *testing.T) { } func TestCompactMarshalUnmarshal(t *testing.T) { + t.Parallel() + bA1 := NewCompactBitArray(0) bA2 := NewCompactBitArray(1) @@ -133,6 +141,8 @@ func TestCompactMarshalUnmarshal(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.bA.String(), func(t *testing.T) { + t.Parallel() + bz := tc.bA.CompactMarshal() assert.Equal(t, tc.marshalledBA, bz) @@ -153,6 +163,8 @@ func TestCompactMarshalUnmarshal(t *testing.T) { } func TestCompactBitArrayNumOfTrueBitsBefore(t *testing.T) { + t.Parallel() + testCases := []struct { marshalledBA string bAIndex []int @@ -169,6 +181,8 @@ func TestCompactBitArrayNumOfTrueBitsBefore(t *testing.T) { tc := tc tcIndex := tcIndex t.Run(tc.marshalledBA, func(t *testing.T) { + t.Parallel() + var bA *CompactBitArray err := json.Unmarshal([]byte(tc.marshalledBA), &bA) require.NoError(t, err) @@ -181,6 +195,8 @@ func TestCompactBitArrayNumOfTrueBitsBefore(t *testing.T) { } func TestCompactBitArrayGetSetIndex(t *testing.T) { + t.Parallel() + r := rand.New(rand.NewSource(100)) numTests := 10 numBitsPerArr := 100 diff --git a/tm2/pkg/crypto/multisig/threshold_pubkey_test.go b/tm2/pkg/crypto/multisig/threshold_pubkey_test.go index 9195344f423..548e8df0a82 100644 --- a/tm2/pkg/crypto/multisig/threshold_pubkey_test.go +++ b/tm2/pkg/crypto/multisig/threshold_pubkey_test.go @@ -15,6 +15,8 @@ import ( // This tests multisig functionality, but it expects the first k signatures to be valid // TODO: Adapt it to give more flexibility about first k signatures being valid func TestThresholdMultisigValidCases(t *testing.T) { + t.Parallel() + pkSet1, sigSet1 := generatePubKeysAndSignatures(5, []byte{1, 2, 3, 4}) cases := []struct { msg []byte @@ -105,6 +107,8 @@ func TestThresholdMultisigValidCases(t *testing.T) { // TODO: Fully replace this test with table driven tests func TestThresholdMultisigDuplicateSignatures(t *testing.T) { + t.Parallel() + msg := []byte{1, 2, 3, 4, 5} pubkeys, sigs := generatePubKeysAndSignatures(5, msg) multisigKey := NewPubKeyMultisigThreshold(2, pubkeys) @@ -118,6 +122,8 @@ func TestThresholdMultisigDuplicateSignatures(t *testing.T) { // TODO: Fully replace this test with table driven tests func TestMultiSigPubKeyEquality(t *testing.T) { + t.Parallel() + msg := []byte{1, 2, 3, 4} pubkeys, _ := generatePubKeysAndSignatures(5, msg) multisigKey := NewPubKeyMultisigThreshold(2, pubkeys) @@ -135,6 +141,8 @@ func TestMultiSigPubKeyEquality(t *testing.T) { } func TestAddress(t *testing.T) { + t.Parallel() + msg := []byte{1, 2, 3, 4} pubkeys, _ := generatePubKeysAndSignatures(5, msg) multisigKey := NewPubKeyMultisigThreshold(2, pubkeys) @@ -142,6 +150,8 @@ func TestAddress(t *testing.T) { } func TestPubKeyMultisigThresholdAminoToIface(t *testing.T) { + t.Parallel() + msg := []byte{1, 2, 3, 4} pubkeys, _ := generatePubKeysAndSignatures(5, msg) multisigKey := NewPubKeyMultisigThreshold(2, pubkeys) diff --git a/tm2/pkg/crypto/random_test.go b/tm2/pkg/crypto/random_test.go index aab505cb61c..dd405c06859 100644 --- a/tm2/pkg/crypto/random_test.go +++ b/tm2/pkg/crypto/random_test.go @@ -11,6 +11,8 @@ import ( // the purpose of this test is primarily to ensure that the randomness // generation won't error. func TestRandomConsistency(t *testing.T) { + t.Parallel() + x1 := crypto.CRandBytes(256) x2 := crypto.CRandBytes(256) x3 := crypto.CRandBytes(256) diff --git a/tm2/pkg/crypto/secp256k1/secp256k1_cgo_test.go b/tm2/pkg/crypto/secp256k1/secp256k1_cgo_test.go index e5b584707e5..d0070ad9bbe 100644 --- a/tm2/pkg/crypto/secp256k1/secp256k1_cgo_test.go +++ b/tm2/pkg/crypto/secp256k1/secp256k1_cgo_test.go @@ -10,6 +10,8 @@ import ( ) func TestPrivKeySecp256k1SignVerify(t *testing.T) { + t.Parallel() + msg := []byte("A.1.2 ECC Key Pair Generation by Testing Candidates") priv := GenPrivKey() tests := []struct { @@ -23,6 +25,8 @@ func TestPrivKeySecp256k1SignVerify(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() + got, err := tt.privKey.Sign(msg) if tt.wantSignErr { require.Error(t, err) diff --git a/tm2/pkg/crypto/secp256k1/secp256k1_internal_test.go b/tm2/pkg/crypto/secp256k1/secp256k1_internal_test.go index d680d24f6a9..d80bea83dba 100644 --- a/tm2/pkg/crypto/secp256k1/secp256k1_internal_test.go +++ b/tm2/pkg/crypto/secp256k1/secp256k1_internal_test.go @@ -11,6 +11,8 @@ import ( ) func Test_genPrivKey(t *testing.T) { + t.Parallel() + empty := make([]byte, 32) oneB := big.NewInt(1).Bytes() onePadded := make([]byte, 32) @@ -30,6 +32,8 @@ func Test_genPrivKey(t *testing.T) { for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { + t.Parallel() + if tt.shouldPanic { require.Panics(t, func() { genPrivKey(bytes.NewReader(tt.notSoRand)) diff --git a/tm2/pkg/crypto/secp256k1/secp256k1_nocgo_test.go b/tm2/pkg/crypto/secp256k1/secp256k1_nocgo_test.go index e75d5377670..aeaca9df47f 100644 --- a/tm2/pkg/crypto/secp256k1/secp256k1_nocgo_test.go +++ b/tm2/pkg/crypto/secp256k1/secp256k1_nocgo_test.go @@ -13,6 +13,8 @@ import ( // non-canonical signatures fail. // Note: run with CGO_ENABLED=0 or go test -tags !cgo. func TestSignatureVerificationAndRejectUpperS(t *testing.T) { + t.Parallel() + msg := []byte("We have lingered long enough on the shores of the cosmic ocean.") for i := 0; i < 500; i++ { priv := GenPrivKey() diff --git a/tm2/pkg/crypto/secp256k1/secp256k1_test.go b/tm2/pkg/crypto/secp256k1/secp256k1_test.go index 86aa058f95a..e04f622fdbb 100644 --- a/tm2/pkg/crypto/secp256k1/secp256k1_test.go +++ b/tm2/pkg/crypto/secp256k1/secp256k1_test.go @@ -30,6 +30,8 @@ var secpDataTable = []keyData{ } func TestPubKeySecp256k1Address(t *testing.T) { + t.Parallel() + for _, d := range secpDataTable { privB, _ := hex.DecodeString(d.priv) pubB, _ := hex.DecodeString(d.pub) @@ -50,6 +52,8 @@ func TestPubKeySecp256k1Address(t *testing.T) { } func TestSignAndValidateSecp256k1(t *testing.T) { + t.Parallel() + privKey := secp256k1.GenPrivKey() pubKey := privKey.PubKey() @@ -68,6 +72,8 @@ func TestSignAndValidateSecp256k1(t *testing.T) { // This test is intended to justify the removal of calls to the underlying library // in creating the privkey. func TestSecp256k1LoadPrivkeyAndSerializeIsIdentity(t *testing.T) { + t.Parallel() + numberOfTests := 256 for i := 0; i < numberOfTests; i++ { // Seed the test case with some random bytes @@ -87,6 +93,8 @@ func TestSecp256k1LoadPrivkeyAndSerializeIsIdentity(t *testing.T) { } func TestGenPrivKeySecp256k1(t *testing.T) { + t.Parallel() + // curve oder N N := underlyingSecp256k1.S256().N tests := []struct { @@ -102,6 +110,8 @@ func TestGenPrivKeySecp256k1(t *testing.T) { for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { + t.Parallel() + gotPrivKey := secp256k1.GenPrivKeySecp256k1(tt.secret) require.NotNil(t, gotPrivKey) // interpret as a big.Int and make sure it is a valid field element: diff --git a/tm2/pkg/crypto/tmhash/hash_test.go b/tm2/pkg/crypto/tmhash/hash_test.go index 4a129bb86ac..c69d86653b1 100644 --- a/tm2/pkg/crypto/tmhash/hash_test.go +++ b/tm2/pkg/crypto/tmhash/hash_test.go @@ -9,6 +9,8 @@ import ( ) func TestHash(t *testing.T) { + t.Parallel() + testVector := []byte("abc") hasher := tmhash.New() hasher.Write(testVector) @@ -25,6 +27,8 @@ func TestHash(t *testing.T) { } func TestHashTruncated(t *testing.T) { + t.Parallel() + testVector := []byte("abc") hasher := tmhash.NewTruncated() hasher.Write(testVector) diff --git a/tm2/pkg/crypto/util.go b/tm2/pkg/crypto/util.go deleted file mode 100644 index f017557f09b..00000000000 --- a/tm2/pkg/crypto/util.go +++ /dev/null @@ -1,7 +0,0 @@ -package crypto - -func cp(bz []byte) (ret []byte) { - ret = make([]byte, len(bz)) - copy(ret, bz) - return ret -} diff --git a/tm2/pkg/crypto/xchacha20poly1305/vector_test.go b/tm2/pkg/crypto/xchacha20poly1305/vector_test.go index 3001217f41e..7ed186de19d 100644 --- a/tm2/pkg/crypto/xchacha20poly1305/vector_test.go +++ b/tm2/pkg/crypto/xchacha20poly1305/vector_test.go @@ -19,6 +19,8 @@ func fromHex(bits string) []byte { } func TestHChaCha20(t *testing.T) { + t.Parallel() + for i, v := range hChaCha20Vectors { var key [32]byte var nonce [16]byte @@ -63,6 +65,8 @@ var hChaCha20Vectors = []struct { } func TestVectors(t *testing.T) { + t.Parallel() + for i, v := range vectors { if len(v.plaintext) == 0 { v.plaintext = make([]byte, len(v.ciphertext)) diff --git a/tm2/pkg/crypto/xchacha20poly1305/xchachapoly_test.go b/tm2/pkg/crypto/xchacha20poly1305/xchachapoly_test.go index 5b92a7607e7..ea7b0bee1a4 100644 --- a/tm2/pkg/crypto/xchacha20poly1305/xchachapoly_test.go +++ b/tm2/pkg/crypto/xchacha20poly1305/xchachapoly_test.go @@ -14,6 +14,8 @@ import ( // Use of this source code is governed by a BSD-style // license that can be found at the bottom of this file. func TestRandom(t *testing.T) { + t.Parallel() + // Some random tests to verify Open(Seal) == Plaintext for i := 0; i < 256; i++ { var nonce [24]byte diff --git a/tm2/pkg/crypto/xsalsa20symmetric/symmetric_test.go b/tm2/pkg/crypto/xsalsa20symmetric/symmetric_test.go index dea965a4356..7460add5185 100644 --- a/tm2/pkg/crypto/xsalsa20symmetric/symmetric_test.go +++ b/tm2/pkg/crypto/xsalsa20symmetric/symmetric_test.go @@ -11,6 +11,8 @@ import ( ) func TestSimple(t *testing.T) { + t.Parallel() + plaintext := []byte("sometext") secret := []byte("somesecretoflengththirtytwo===32") ciphertext := EncryptSymmetric(plaintext, secret) @@ -21,6 +23,8 @@ func TestSimple(t *testing.T) { } func TestSimpleWithKDF(t *testing.T) { + t.Parallel() + salt := []byte("1234567890123456") plaintext := []byte("sometext") secretPass := []byte("somesecret") diff --git a/tm2/pkg/db/backend_test.go b/tm2/pkg/db/backend_test.go index b6cd3f026aa..fd03629fd58 100644 --- a/tm2/pkg/db/backend_test.go +++ b/tm2/pkg/db/backend_test.go @@ -41,8 +41,12 @@ func testBackendGetSetDelete(t *testing.T, backend BackendType) { } func TestBackendsGetSetDelete(t *testing.T) { + t.Parallel() + for dbType := range backends { t.Run(string(dbType), func(t *testing.T) { + t.Parallel() + testBackendGetSetDelete(t, dbType) }) } @@ -59,6 +63,8 @@ func withDB(t *testing.T, creator dbCreator, fn func(DB)) { } func TestBackendsNilKeys(t *testing.T) { + t.Parallel() + // Test all backends. for dbType, creator := range backends { withDB(t, creator, func(db DB) { @@ -137,6 +143,8 @@ func TestBackendsNilKeys(t *testing.T) { } func TestGoLevelDBBackend(t *testing.T) { + t.Parallel() + name := fmt.Sprintf("test_%x", randStr(12)) db, err := NewDB(name, GoLevelDBBackend, t.TempDir()) require.NoError(t, err) @@ -146,9 +154,11 @@ func TestGoLevelDBBackend(t *testing.T) { } func TestDBIterator(t *testing.T) { + t.Parallel() + for dbType := range backends { t.Run(fmt.Sprintf("%v", dbType), func(t *testing.T) { - t.Helper() + t.Parallel() testDBIterator(t, dbType) }) diff --git a/tm2/pkg/db/boltdb_test.go b/tm2/pkg/db/boltdb_test.go index 031023f275a..57091fb53a2 100644 --- a/tm2/pkg/db/boltdb_test.go +++ b/tm2/pkg/db/boltdb_test.go @@ -10,6 +10,8 @@ import ( ) func TestBoltDBNewBoltDB(t *testing.T) { + t.Parallel() + name := fmt.Sprintf("test_%x", randStr(12)) db, err := NewBoltDB(name, t.TempDir()) diff --git a/tm2/pkg/db/c_level_db_test.go b/tm2/pkg/db/c_level_db_test.go index 2bdffd14a83..7044ea0f4de 100644 --- a/tm2/pkg/db/c_level_db_test.go +++ b/tm2/pkg/db/c_level_db_test.go @@ -88,6 +88,8 @@ func bytes2Int64(buf []byte) int64 { */ func TestCLevelDBBackend(t *testing.T) { + t.Parallel() + name := fmt.Sprintf("test_%x", randStr(12)) // Can't use "" (current directory) or "./" here because levigo.Open returns: // "Error initializing DB: IO error: test_XXX.db: Invalid argument" @@ -99,6 +101,8 @@ func TestCLevelDBBackend(t *testing.T) { } func TestCLevelDBStats(t *testing.T) { + t.Parallel() + name := fmt.Sprintf("test_%x", randStr(12)) db, err := NewDB(name, CLevelDBBackend, t.TempDir()) require.NoError(t, err) diff --git a/tm2/pkg/db/db_test.go b/tm2/pkg/db/db_test.go index 3634fb4bf03..62231645613 100644 --- a/tm2/pkg/db/db_test.go +++ b/tm2/pkg/db/db_test.go @@ -8,8 +8,12 @@ import ( ) func TestDBIteratorSingleKey(t *testing.T) { + t.Parallel() + for backend := range backends { t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) { + t.Parallel() + db := newTempDB(t, backend) db.SetSync(bz("1"), bz("value_1")) @@ -27,8 +31,12 @@ func TestDBIteratorSingleKey(t *testing.T) { } func TestDBIteratorTwoKeys(t *testing.T) { + t.Parallel() + for backend := range backends { t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) { + t.Parallel() + db := newTempDB(t, backend) db.SetSync(bz("1"), bz("value_1")) @@ -54,8 +62,12 @@ func TestDBIteratorTwoKeys(t *testing.T) { } func TestDBIteratorMany(t *testing.T) { + t.Parallel() + for backend := range backends { t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) { + t.Parallel() + db := newTempDB(t, backend) keys := make([][]byte, 100) @@ -78,8 +90,12 @@ func TestDBIteratorMany(t *testing.T) { } func TestDBIteratorEmpty(t *testing.T) { + t.Parallel() + for backend := range backends { t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) { + t.Parallel() + db := newTempDB(t, backend) itr := db.Iterator(nil, nil) @@ -90,8 +106,12 @@ func TestDBIteratorEmpty(t *testing.T) { } func TestDBIteratorEmptyBeginAfter(t *testing.T) { + t.Parallel() + for backend := range backends { t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) { + t.Parallel() + db := newTempDB(t, backend) itr := db.Iterator(bz("1"), nil) @@ -102,8 +122,12 @@ func TestDBIteratorEmptyBeginAfter(t *testing.T) { } func TestDBIteratorNonemptyBeginAfter(t *testing.T) { + t.Parallel() + for backend := range backends { t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) { + t.Parallel() + db := newTempDB(t, backend) db.SetSync(bz("1"), bz("value_1")) @@ -115,6 +139,8 @@ func TestDBIteratorNonemptyBeginAfter(t *testing.T) { } func TestDBBatchWrite(t *testing.T) { + t.Parallel() + testCases := []struct { modify func(batch Batch) calls map[string]int diff --git a/tm2/pkg/db/fsdb.go b/tm2/pkg/db/fsdb.go index aa8cea83889..e11cd6d4ce5 100644 --- a/tm2/pkg/db/fsdb.go +++ b/tm2/pkg/db/fsdb.go @@ -2,7 +2,7 @@ package db import ( "fmt" - "io/ioutil" + "io" "net/url" "os" "path/filepath" @@ -189,7 +189,7 @@ func read(path string) ([]byte, error) { } defer f.Close() - d, err := ioutil.ReadAll(f) + d, err := io.ReadAll(f) if err != nil { return nil, err } diff --git a/tm2/pkg/db/go_level_db_test.go b/tm2/pkg/db/go_level_db_test.go index a85bb6e8713..677b8d86c08 100644 --- a/tm2/pkg/db/go_level_db_test.go +++ b/tm2/pkg/db/go_level_db_test.go @@ -9,6 +9,8 @@ import ( ) func TestGoLevelDBNewGoLevelDB(t *testing.T) { + t.Parallel() + dir := t.TempDir() name := fmt.Sprintf("test_%x", randStr(12)) diff --git a/tm2/pkg/db/gorocks_db_test.go b/tm2/pkg/db/gorocks_db_test.go index 9d1b10cef34..d4792424f39 100644 --- a/tm2/pkg/db/gorocks_db_test.go +++ b/tm2/pkg/db/gorocks_db_test.go @@ -10,6 +10,8 @@ import ( ) func TestGoRocksDBBackend(t *testing.T) { + t.Parallel() + name := fmt.Sprintf("test_%x", randStr(12)) db := NewDB(name, GoRocksDBBackend, t.TempDir()) @@ -18,6 +20,8 @@ func TestGoRocksDBBackend(t *testing.T) { } func TestGoRocksDBStats(t *testing.T) { + t.Parallel() + name := fmt.Sprintf("test_%x", randStr(12)) db := NewDB(name, GoRocksDBBackend, t.TempDir()) diff --git a/tm2/pkg/db/grocks_db_test.go b/tm2/pkg/db/grocks_db_test.go index 60592bc8d82..10b33026128 100644 --- a/tm2/pkg/db/grocks_db_test.go +++ b/tm2/pkg/db/grocks_db_test.go @@ -10,6 +10,8 @@ import ( ) func TestGRocksDBBackend(t *testing.T) { + t.Parallel() + name := fmt.Sprintf("test_%x", randStr(12)) db := NewDB(name, GRocksDBBackend, t.TempDir()) @@ -18,6 +20,8 @@ func TestGRocksDBBackend(t *testing.T) { } func TestGRocksDBStats(t *testing.T) { + t.Parallel() + name := fmt.Sprintf("test_%x", randStr(12)) db := NewDB(name, GRocksDBBackend, t.TempDir()) diff --git a/tm2/pkg/db/prefix_db_test.go b/tm2/pkg/db/prefix_db_test.go index e3e37c7d12c..0948cce98a5 100644 --- a/tm2/pkg/db/prefix_db_test.go +++ b/tm2/pkg/db/prefix_db_test.go @@ -18,6 +18,8 @@ func mockDBWithStuff() DB { } func TestPrefixDBSimple(t *testing.T) { + t.Parallel() + db := mockDBWithStuff() pdb := NewPrefixDB(db, bz("key")) @@ -36,6 +38,8 @@ func TestPrefixDBSimple(t *testing.T) { } func TestPrefixDBIterator1(t *testing.T) { + t.Parallel() + db := mockDBWithStuff() pdb := NewPrefixDB(db, bz("key")) @@ -54,6 +58,8 @@ func TestPrefixDBIterator1(t *testing.T) { } func TestPrefixDBIterator2(t *testing.T) { + t.Parallel() + db := mockDBWithStuff() pdb := NewPrefixDB(db, bz("key")) @@ -64,6 +70,8 @@ func TestPrefixDBIterator2(t *testing.T) { } func TestPrefixDBIterator3(t *testing.T) { + t.Parallel() + db := mockDBWithStuff() pdb := NewPrefixDB(db, bz("key")) @@ -82,6 +90,8 @@ func TestPrefixDBIterator3(t *testing.T) { } func TestPrefixDBIterator4(t *testing.T) { + t.Parallel() + db := mockDBWithStuff() pdb := NewPrefixDB(db, bz("key")) @@ -92,6 +102,8 @@ func TestPrefixDBIterator4(t *testing.T) { } func TestPrefixDBReverseIterator1(t *testing.T) { + t.Parallel() + db := mockDBWithStuff() pdb := NewPrefixDB(db, bz("key")) @@ -110,6 +122,8 @@ func TestPrefixDBReverseIterator1(t *testing.T) { } func TestPrefixDBReverseIterator2(t *testing.T) { + t.Parallel() + db := mockDBWithStuff() pdb := NewPrefixDB(db, bz("key")) @@ -128,6 +142,8 @@ func TestPrefixDBReverseIterator2(t *testing.T) { } func TestPrefixDBReverseIterator3(t *testing.T) { + t.Parallel() + db := mockDBWithStuff() pdb := NewPrefixDB(db, bz("key")) @@ -138,6 +154,8 @@ func TestPrefixDBReverseIterator3(t *testing.T) { } func TestPrefixDBReverseIterator4(t *testing.T) { + t.Parallel() + db := mockDBWithStuff() pdb := NewPrefixDB(db, bz("key")) @@ -148,6 +166,8 @@ func TestPrefixDBReverseIterator4(t *testing.T) { } func TestPrefixDBReverseIterator5(t *testing.T) { + t.Parallel() + db := mockDBWithStuff() pdb := NewPrefixDB(db, bz("key")) @@ -164,6 +184,8 @@ func TestPrefixDBReverseIterator5(t *testing.T) { } func TestPrefixDBReverseIterator6(t *testing.T) { + t.Parallel() + db := mockDBWithStuff() pdb := NewPrefixDB(db, bz("key")) @@ -178,6 +200,8 @@ func TestPrefixDBReverseIterator6(t *testing.T) { } func TestPrefixDBReverseIterator7(t *testing.T) { + t.Parallel() + db := mockDBWithStuff() pdb := NewPrefixDB(db, bz("key")) diff --git a/tm2/pkg/db/util_test.go b/tm2/pkg/db/util_test.go index adf52123290..f66fddde64e 100644 --- a/tm2/pkg/db/util_test.go +++ b/tm2/pkg/db/util_test.go @@ -7,8 +7,12 @@ import ( // Empty iterator for empty db. func TestPrefixIteratorNoMatchNil(t *testing.T) { + t.Parallel() + for backend := range backends { t.Run(fmt.Sprintf("Prefix w/ backend %s", backend), func(t *testing.T) { + t.Parallel() + db := newTempDB(t, backend) itr := IteratePrefix(db, []byte("2")) @@ -19,6 +23,8 @@ func TestPrefixIteratorNoMatchNil(t *testing.T) { // Empty iterator for db populated after iterator created. func TestPrefixIteratorNoMatch1(t *testing.T) { + t.Parallel() + for backend := range backends { if backend == BoltDBBackend { t.Log("bolt does not support concurrent writes while iterating") @@ -26,6 +32,8 @@ func TestPrefixIteratorNoMatch1(t *testing.T) { } t.Run(fmt.Sprintf("Prefix w/ backend %s", backend), func(t *testing.T) { + t.Parallel() + db := newTempDB(t, backend) itr := IteratePrefix(db, []byte("2")) db.SetSync(bz("1"), bz("value_1")) @@ -37,8 +45,12 @@ func TestPrefixIteratorNoMatch1(t *testing.T) { // Empty iterator for prefix starting after db entry. func TestPrefixIteratorNoMatch2(t *testing.T) { + t.Parallel() + for backend := range backends { t.Run(fmt.Sprintf("Prefix w/ backend %s", backend), func(t *testing.T) { + t.Parallel() + db := newTempDB(t, backend) db.SetSync(bz("3"), bz("value_3")) itr := IteratePrefix(db, []byte("4")) @@ -50,8 +62,12 @@ func TestPrefixIteratorNoMatch2(t *testing.T) { // Iterator with single val for db with single val, starting from that val. func TestPrefixIteratorMatch1(t *testing.T) { + t.Parallel() + for backend := range backends { t.Run(fmt.Sprintf("Prefix w/ backend %s", backend), func(t *testing.T) { + t.Parallel() + db := newTempDB(t, backend) db.SetSync(bz("2"), bz("value_2")) itr := IteratePrefix(db, bz("2")) @@ -68,8 +84,12 @@ func TestPrefixIteratorMatch1(t *testing.T) { // Iterator with prefix iterates over everything with same prefix. func TestPrefixIteratorMatches1N(t *testing.T) { + t.Parallel() + for backend := range backends { t.Run(fmt.Sprintf("Prefix w/ backend %s", backend), func(t *testing.T) { + t.Parallel() + db := newTempDB(t, backend) // prefixed diff --git a/tm2/pkg/errors/errors_test.go b/tm2/pkg/errors/errors_test.go index ddd2539738f..21115c21862 100644 --- a/tm2/pkg/errors/errors_test.go +++ b/tm2/pkg/errors/errors_test.go @@ -9,6 +9,8 @@ import ( ) func TestErrorPanic(t *testing.T) { + t.Parallel() + type pnk struct { msg string } @@ -31,6 +33,8 @@ func TestErrorPanic(t *testing.T) { } func TestWrapSomething(t *testing.T) { + t.Parallel() + err := Wrap("something", "formatter%v%v", 0, 1) assert.Equal(t, "something", err.Data()) @@ -40,6 +44,8 @@ func TestWrapSomething(t *testing.T) { } func TestWrapNothing(t *testing.T) { + t.Parallel() + err := Wrap(nil, "formatter%v%v", 0, 1) assert.Equal(t, @@ -51,6 +57,8 @@ func TestWrapNothing(t *testing.T) { } func TestErrorNew(t *testing.T) { + t.Parallel() + err := New("formatter%v%v", 0, 1) assert.Equal(t, @@ -62,6 +70,8 @@ func TestErrorNew(t *testing.T) { } func TestErrorNewWithDetails(t *testing.T) { + t.Parallel() + err := New("formatter%v%v", 0, 1) err.Trace(0, "trace %v", 1) err.Trace(0, "trace %v", 2) @@ -71,6 +81,8 @@ func TestErrorNewWithDetails(t *testing.T) { } func TestErrorNewWithStacktrace(t *testing.T) { + t.Parallel() + err := New("formatter%v%v", 0, 1).Stacktrace() assert.Equal(t, @@ -82,6 +94,8 @@ func TestErrorNewWithStacktrace(t *testing.T) { } func TestErrorNewWithTrace(t *testing.T) { + t.Parallel() + err := New("formatter%v%v", 0, 1) err.Trace(0, "trace %v", 1) err.Trace(0, "trace %v", 2) @@ -100,6 +114,8 @@ func TestErrorNewWithTrace(t *testing.T) { } func TestWrapError(t *testing.T) { + t.Parallel() + var err1 error = New("my message") var err2 error = Wrap(err1, "another message") assert.Equal(t, err1, err2) diff --git a/tm2/pkg/events/events_test.go b/tm2/pkg/events/events_test.go index f3b4aa2fd82..5232364b1c8 100644 --- a/tm2/pkg/events/events_test.go +++ b/tm2/pkg/events/events_test.go @@ -35,6 +35,8 @@ func TestAddListenerFireOnce(t *testing.T) { // TestAddListenerFireMany sets up an EventSwitch, subscribes a single // listener, and sends a thousand integers. func TestAddListenerFireMany(t *testing.T) { + t.Parallel() + evsw := NewEventSwitch() err := evsw.Start() require.NoError(t, err) @@ -62,6 +64,8 @@ func TestAddListenerFireMany(t *testing.T) { // TestAddListeners sets up an EventSwitch, subscribes three // listeners, and sends a thousand integers for each. func TestAddListeners(t *testing.T) { + t.Parallel() + evsw := NewEventSwitch() err := evsw.Start() require.NoError(t, err) @@ -100,6 +104,8 @@ func TestAddListeners(t *testing.T) { } func TestAddAndRemoveListenerConcurrency(t *testing.T) { + t.Parallel() + var ( stopInputEvent = false roundCount = 2000 @@ -145,6 +151,8 @@ func TestAddAndRemoveListenerConcurrency(t *testing.T) { } func TestAddAndRemoveListener(t *testing.T) { + t.Parallel() + evsw := NewEventSwitch() err := evsw.Start() require.NoError(t, err) @@ -192,6 +200,8 @@ func TestAddAndRemoveListener(t *testing.T) { // TestRemoveListener does basic tests on adding and removing func TestRemoveListener(t *testing.T) { + t.Parallel() + evsw := NewEventSwitch() err := evsw.Start() require.NoError(t, err) @@ -241,6 +251,8 @@ func TestRemoveListener(t *testing.T) { // NOTE: it is important to run this test with race conditions tracking on, // `go test -race`, to examine for possible race conditions. func TestRemoveListenersAsync(t *testing.T) { + t.Parallel() + evsw := NewEventSwitch() err := evsw.Start() require.NoError(t, err) diff --git a/tm2/pkg/events/store.go b/tm2/pkg/events/store.go index bea4626394e..1891fd17ac6 100644 --- a/tm2/pkg/events/store.go +++ b/tm2/pkg/events/store.go @@ -1,33 +1,12 @@ package events -import ( - "fmt" - - auto "github.com/gnolang/gno/tm2/pkg/autofile" -) - // StoreStream stores events to disk but is also listenaable. type StoreStream interface { Eventable SetHeight(height int64) // to demarcate height in WAL for replay. } -type storeStream struct { - afile *auto.AutoFile - buf []byte - height int64 -} - -func (ss *storeStream) SetHeight(height int64) { - if ss.height < height { - // write new height - ss.height = height - } else /* if height <= ss.height */ { - panic(fmt.Sprintf("invalid SetHeight height value. current %v, got %v", ss.height, height)) - } -} - -//---------------------------------------- +// ---------------------------------------- // move to own file // FilterStream is listenable and lets you filter. diff --git a/tm2/pkg/flow/io_test.go b/tm2/pkg/flow/io_test.go index 196c7c65d9a..d023d32c347 100644 --- a/tm2/pkg/flow/io_test.go +++ b/tm2/pkg/flow/io_test.go @@ -32,6 +32,8 @@ func nextStatus(m *Monitor) Status { } func TestReader(t *testing.T) { + t.Parallel() + in := make([]byte, 100) for i := range in { in[i] = byte(i) @@ -101,6 +103,8 @@ func TestReader(t *testing.T) { } func TestWriter(t *testing.T) { + t.Parallel() + b := make([]byte, 100) for i := range b { b[i] = byte(i) diff --git a/tm2/pkg/iavl/basic_test.go b/tm2/pkg/iavl/basic_test.go index ab46792aee4..f684209a682 100644 --- a/tm2/pkg/iavl/basic_test.go +++ b/tm2/pkg/iavl/basic_test.go @@ -13,6 +13,8 @@ import ( ) func TestBasic(t *testing.T) { + t.Parallel() + tree := NewMutableTree(db.NewMemDB(), 0) up := tree.Set([]byte("1"), []byte("one")) if up { @@ -103,6 +105,8 @@ func TestBasic(t *testing.T) { } func TestUnit(t *testing.T) { + t.Parallel() + expectHash := func(tree *ImmutableTree, hashCount int64) { // ensure number of new hash calculations is as expected. hash, count := tree.hashWithCount() @@ -184,6 +188,8 @@ func TestUnit(t *testing.T) { } func TestRemove(t *testing.T) { + t.Parallel() + size := 10000 keyLen, dataLen := 16, 40 @@ -214,6 +220,8 @@ func TestRemove(t *testing.T) { } func TestIntegration(t *testing.T) { + t.Parallel() + type record struct { key string value string @@ -279,6 +287,8 @@ func TestIntegration(t *testing.T) { } func TestIterateRange(t *testing.T) { + t.Parallel() + type record struct { key string value string @@ -363,6 +373,8 @@ func TestIterateRange(t *testing.T) { } func TestPersistence(t *testing.T) { + t.Parallel() + db := db.NewMemDB() // Create some random key value pairs @@ -390,6 +402,8 @@ func TestPersistence(t *testing.T) { } func TestProof(t *testing.T) { + t.Parallel() + // Construct some random tree db := db.NewMemDB() tree := NewMutableTree(db, 100) @@ -420,6 +434,8 @@ func TestProof(t *testing.T) { } func TestTreeProof(t *testing.T) { + t.Parallel() + db := db.NewMemDB() tree := NewMutableTree(db, 100) assert.Equal(t, tree.Hash(), []byte(nil)) diff --git a/tm2/pkg/iavl/benchmarks/bench_test.go b/tm2/pkg/iavl/benchmarks/bench_test.go index de6a573020e..77ad77eed28 100644 --- a/tm2/pkg/iavl/benchmarks/bench_test.go +++ b/tm2/pkg/iavl/benchmarks/bench_test.go @@ -75,19 +75,6 @@ func runKnownQueries(b *testing.B, t *iavl.MutableTree, keys [][]byte) { } } -func runInsert(b *testing.B, t *iavl.MutableTree, keyLen, dataLen, blockSize int) *iavl.MutableTree { - b.Helper() - - for i := 1; i <= b.N; i++ { - t.Set(randBytes(keyLen), randBytes(dataLen)) - if i%blockSize == 0 { - t.Hash() - t.SaveVersion() - } - } - return t -} - func runUpdate(b *testing.B, t *iavl.MutableTree, dataLen, blockSize int, keys [][]byte) *iavl.MutableTree { b.Helper() @@ -102,23 +89,6 @@ func runUpdate(b *testing.B, t *iavl.MutableTree, dataLen, blockSize int, keys [ return t } -func runDelete(b *testing.B, t *iavl.MutableTree, blockSize int, keys [][]byte) *iavl.MutableTree { - b.Helper() - - var key []byte - l := int32(len(keys)) - for i := 1; i <= b.N; i++ { - key = keys[rand.Int31n(l)] - // key = randBytes(16) - // TODO: test if removed, use more keys (from insert) - t.Remove(key) - if i%blockSize == 0 { - commitTree(b, t) - } - } - return t -} - // runBlock measures time for an entire block, not just one tx func runBlock(b *testing.B, t *iavl.MutableTree, keyLen, dataLen, blockSize int, keys [][]byte) *iavl.MutableTree { b.Helper() diff --git a/tm2/pkg/iavl/common/random_test.go b/tm2/pkg/iavl/common/random_test.go index 6ed73ab898c..4c1ee8024e0 100644 --- a/tm2/pkg/iavl/common/random_test.go +++ b/tm2/pkg/iavl/common/random_test.go @@ -11,12 +11,16 @@ import ( ) func TestRandStr(t *testing.T) { + t.Parallel() + l := 243 s := RandStr(l) assert.Equal(t, l, len(s)) } func TestRandBytes(t *testing.T) { + t.Parallel() + l := 243 b := RandBytes(l) assert.Equal(t, l, len(b)) diff --git a/tm2/pkg/iavl/node.go b/tm2/pkg/iavl/node.go index f2a944afc6a..ee522016f0c 100644 --- a/tm2/pkg/iavl/node.go +++ b/tm2/pkg/iavl/node.go @@ -371,10 +371,6 @@ func (node *Node) traverse(t *ImmutableTree, ascending bool, cb func(*Node) bool }) } -func (node *Node) traverseWithDepth(t *ImmutableTree, ascending bool, cb func(*Node, uint8) bool) bool { - return node.traverseInRange(t, nil, nil, ascending, false, 0, cb) -} - func (node *Node) traverseInRange(t *ImmutableTree, start, end []byte, ascending bool, inclusive bool, depth uint8, cb func(*Node, uint8) bool) bool { afterStart := start == nil || bytes.Compare(start, node.key) < 0 startOrAfter := start == nil || bytes.Compare(start, node.key) <= 0 diff --git a/tm2/pkg/iavl/nodedb.go b/tm2/pkg/iavl/nodedb.go index 3e59b3480e9..e1998d8cc1d 100644 --- a/tm2/pkg/iavl/nodedb.go +++ b/tm2/pkg/iavl/nodedb.go @@ -385,7 +385,7 @@ func (ndb *nodeDB) saveRoot(hash []byte, version int64) error { return nil } -////////////////// Utility and test functions ///////////////////////////////// +// ----------- Utility and test functions // ----------- func (ndb *nodeDB) leafNodes() []*Node { leaves := []*Node{} diff --git a/tm2/pkg/iavl/proof_forgery_test.go b/tm2/pkg/iavl/proof_forgery_test.go index a742ad40fcc..028675f7c48 100644 --- a/tm2/pkg/iavl/proof_forgery_test.go +++ b/tm2/pkg/iavl/proof_forgery_test.go @@ -14,6 +14,8 @@ import ( ) func TestProofForgery(t *testing.T) { + t.Parallel() + source := rand.NewSource(0) r := rand.New(source) cacheSize := 0 diff --git a/tm2/pkg/iavl/proof_path.go b/tm2/pkg/iavl/proof_path.go index f66fcf3c48c..a5ac14bc4e7 100644 --- a/tm2/pkg/iavl/proof_path.go +++ b/tm2/pkg/iavl/proof_path.go @@ -1,11 +1,8 @@ package iavl import ( - "bytes" "fmt" "strings" - - "github.com/gnolang/gno/tm2/pkg/errors" ) // pathWithLeaf is a path to a leaf node and the leaf node itself. @@ -28,14 +25,6 @@ func (pwl pathWithLeaf) StringIndented(indent string) string { indent) } -// `verify` checks that the leaf node's hash + the inner nodes merkle-izes to -// the given root. If it returns an error, it means the leafHash or the -// PathToLeaf is incorrect. -func (pwl pathWithLeaf) verify(root []byte) error { - leafHash := pwl.Leaf.Hash() - return pwl.Path.verify(leafHash, root) -} - // `computeRootHash` computes the root hash with leaf node. // Does not verify the root hash. func (pwl pathWithLeaf) computeRootHash() []byte { @@ -73,21 +62,6 @@ func (pl PathToLeaf) stringIndented(indent string) string { indent) } -// `verify` checks that the leaf node's hash + the inner nodes merkle-izes to -// the given root. If it returns an error, it means the leafHash or the -// PathToLeaf is incorrect. -func (pl PathToLeaf) verify(leafHash []byte, root []byte) error { - hash := leafHash - for i := len(pl) - 1; i >= 0; i-- { - pin := pl[i] - hash = pin.Hash(hash) - } - if !bytes.Equal(root, hash) { - return errors.Wrap(ErrInvalidProof, "") - } - return nil -} - // `computeRootHash` computes the root hash assuming some leaf hash. // Does not verify the root hash. func (pl PathToLeaf) computeRootHash(leafHash []byte) []byte { @@ -117,37 +91,6 @@ func (pl PathToLeaf) isRightmost() bool { return true } -func (pl PathToLeaf) isEmpty() bool { - return pl == nil || len(pl) == 0 -} - -func (pl PathToLeaf) dropRoot() PathToLeaf { - if pl.isEmpty() { - return pl - } - return pl[:len(pl)-1] -} - -func (pl PathToLeaf) hasCommonRoot(pl2 PathToLeaf) bool { - if pl.isEmpty() || pl2.isEmpty() { - return false - } - leftEnd := pl[len(pl)-1] - rightEnd := pl2[len(pl2)-1] - - return bytes.Equal(leftEnd.Left, rightEnd.Left) && - bytes.Equal(leftEnd.Right, rightEnd.Right) -} - -func (pl PathToLeaf) isLeftAdjacentTo(pl2 PathToLeaf) bool { - for pl.hasCommonRoot(pl2) { - pl, pl2 = pl.dropRoot(), pl2.dropRoot() - } - pl, pl2 = pl.dropRoot(), pl2.dropRoot() - - return pl.isRightmost() && pl2.isLeftmost() -} - // returns -1 if invalid. func (pl PathToLeaf) Index() (idx int64) { for i, node := range pl { diff --git a/tm2/pkg/iavl/proof_range.go b/tm2/pkg/iavl/proof_range.go index 799fb65cebb..ea6bce24fc0 100644 --- a/tm2/pkg/iavl/proof_range.go +++ b/tm2/pkg/iavl/proof_range.go @@ -299,7 +299,7 @@ func (proof *RangeProof) _computeRootHash() (rootHash []byte, treeEnd bool, err return rootHash, treeEnd, nil } -/////////////////////////////////////////////////////////////////////////////// +// ----------- // keyStart is inclusive and keyEnd is exclusive. // If keyStart or keyEnd don't exist, the leaf before keyStart @@ -442,7 +442,7 @@ func (t *ImmutableTree) getRangeProof(keyStart, keyEnd []byte, limit int) (proof }, keys, values, nil } -//---------------------------------------- +// ---------------------------------------- // GetWithProof gets the value under the key if it exists, or returns nil. // A proof of existence or absence is returned alongside the value. diff --git a/tm2/pkg/iavl/proof_test.go b/tm2/pkg/iavl/proof_test.go index f67ea45b00a..ad4d85d1cd5 100644 --- a/tm2/pkg/iavl/proof_test.go +++ b/tm2/pkg/iavl/proof_test.go @@ -15,6 +15,8 @@ import ( ) func TestTreeGetWithProof(t *testing.T) { + t.Parallel() + tree := NewMutableTree(db.NewMemDB(), 0) require := require.New(t) for _, ikey := range []byte{0x11, 0x32, 0x50, 0x72, 0x99} { @@ -49,6 +51,8 @@ func TestTreeGetWithProof(t *testing.T) { } func TestTreeKeyExistsProof(t *testing.T) { + t.Parallel() + tree := NewMutableTree(db.NewMemDB(), 0) root := tree.WorkingHash() @@ -115,6 +119,8 @@ func TestTreeKeyExistsProof(t *testing.T) { } func TestTreeKeyInRangeProofs(t *testing.T) { + t.Parallel() + tree := NewMutableTree(db.NewMemDB(), 0) require := require.New(t) keys := []byte{0x0a, 0x11, 0x2e, 0x32, 0x50, 0x72, 0x99, 0xa1, 0xe4, 0xf7} // 10 total. diff --git a/tm2/pkg/iavl/tree_dotgraph_test.go b/tm2/pkg/iavl/tree_dotgraph_test.go index 29be03ca241..3c0233f51fa 100644 --- a/tm2/pkg/iavl/tree_dotgraph_test.go +++ b/tm2/pkg/iavl/tree_dotgraph_test.go @@ -1,13 +1,15 @@ package iavl import ( - "io/ioutil" + "io" "testing" db "github.com/gnolang/gno/tm2/pkg/db" ) func TestWriteDOTGraph(t *testing.T) { + t.Parallel() + tree := NewMutableTree(db.NewMemDB(), 0) for _, ikey := range []byte{ 0x0a, 0x11, 0x2e, 0x32, 0x50, 0x72, 0x99, 0xa1, 0xe4, 0xf7, @@ -15,5 +17,5 @@ func TestWriteDOTGraph(t *testing.T) { key := []byte{ikey} tree.Set(key, key) } - WriteDOTGraph(ioutil.Discard, tree.ImmutableTree, []PathToLeaf{}) + WriteDOTGraph(io.Discard, tree.ImmutableTree, []PathToLeaf{}) } diff --git a/tm2/pkg/iavl/tree_fuzz_test.go b/tm2/pkg/iavl/tree_fuzz_test.go index 7ea9bb50389..64e20d944a2 100644 --- a/tm2/pkg/iavl/tree_fuzz_test.go +++ b/tm2/pkg/iavl/tree_fuzz_test.go @@ -105,6 +105,8 @@ func genRandomProgram(size int) *program { // Generate many programs and run them. func TestMutableTreeFuzz(t *testing.T) { + t.Parallel() + maxIterations := testFuzzIterations progsPerIteration := 100000 iterations := 0 diff --git a/tm2/pkg/iavl/tree_test.go b/tm2/pkg/iavl/tree_test.go index 56a00ee2424..ba5bbe3e5ef 100644 --- a/tm2/pkg/iavl/tree_test.go +++ b/tm2/pkg/iavl/tree_test.go @@ -51,6 +51,8 @@ func getTestDB() (db.DB, func()) { } func TestVersionedRandomTree(t *testing.T) { + t.Parallel() + require := require.New(t) d, closeDB := getTestDB() @@ -105,6 +107,8 @@ func TestVersionedRandomTree(t *testing.T) { } func TestVersionedRandomTreeSmallKeys(t *testing.T) { + t.Parallel() + require := require.New(t) d, closeDB := getTestDB() defer closeDB() @@ -146,6 +150,8 @@ func TestVersionedRandomTreeSmallKeys(t *testing.T) { } func TestVersionedRandomTreeSmallKeysRandomDeletes(t *testing.T) { + t.Parallel() + require := require.New(t) d, closeDB := getTestDB() defer closeDB() @@ -187,6 +193,8 @@ func TestVersionedRandomTreeSmallKeysRandomDeletes(t *testing.T) { } func TestVersionedTreeSpecial1(t *testing.T) { + t.Parallel() + tree := NewMutableTree(db.NewMemDB(), 100) tree.Set([]byte("C"), []byte("so43QQFN")) @@ -209,6 +217,8 @@ func TestVersionedTreeSpecial1(t *testing.T) { } func TestVersionedRandomTreeSpecial2(t *testing.T) { + t.Parallel() + require := require.New(t) tree := NewMutableTree(db.NewMemDB(), 100) @@ -225,6 +235,8 @@ func TestVersionedRandomTreeSpecial2(t *testing.T) { } func TestVersionedEmptyTree(t *testing.T) { + t.Parallel() + require := require.New(t) d, closeDB := getTestDB() defer closeDB() @@ -281,6 +293,8 @@ func TestVersionedEmptyTree(t *testing.T) { } func TestVersionedTree(t *testing.T) { + t.Parallel() + require := require.New(t) d, closeDB := getTestDB() defer closeDB() @@ -468,6 +482,8 @@ func TestVersionedTree(t *testing.T) { } func TestVersionedTreeVersionDeletingEfficiency(t *testing.T) { + t.Parallel() + d, closeDB := getTestDB() defer closeDB() @@ -512,6 +528,8 @@ func TestVersionedTreeVersionDeletingEfficiency(t *testing.T) { } func TestVersionedTreeOrphanDeleting(t *testing.T) { + t.Parallel() + mdb := db.NewMemDB() tree := NewMutableTree(mdb, 0) @@ -550,6 +568,8 @@ func TestVersionedTreeOrphanDeleting(t *testing.T) { } func TestVersionedTreeSpecialCase(t *testing.T) { + t.Parallel() + require := require.New(t) tree := NewMutableTree(db.NewMemDB(), 100) @@ -571,6 +591,8 @@ func TestVersionedTreeSpecialCase(t *testing.T) { } func TestVersionedTreeSpecialCase2(t *testing.T) { + t.Parallel() + require := require.New(t) d := db.NewMemDB() @@ -598,6 +620,8 @@ func TestVersionedTreeSpecialCase2(t *testing.T) { } func TestVersionedTreeSpecialCase3(t *testing.T) { + t.Parallel() + require := require.New(t) tree := NewMutableTree(db.NewMemDB(), 0) @@ -626,6 +650,8 @@ func TestVersionedTreeSpecialCase3(t *testing.T) { } func TestVersionedTreeSaveAndLoad(t *testing.T) { + t.Parallel() + require := require.New(t) d := db.NewMemDB() tree := NewMutableTree(d, 0) @@ -677,6 +703,8 @@ func TestVersionedTreeSaveAndLoad(t *testing.T) { } func TestVersionedTreeErrors(t *testing.T) { + t.Parallel() + require := require.New(t) tree := NewMutableTree(db.NewMemDB(), 100) @@ -706,6 +734,8 @@ func TestVersionedTreeErrors(t *testing.T) { } func TestVersionedCheckpoints(t *testing.T) { + t.Parallel() + require := require.New(t) d, closeDB := getTestDB() defer closeDB() @@ -762,6 +792,8 @@ func TestVersionedCheckpoints(t *testing.T) { } func TestVersionedCheckpointsSpecialCase(t *testing.T) { + t.Parallel() + require := require.New(t) tree := NewMutableTree(db.NewMemDB(), 0) key := []byte("k") @@ -788,6 +820,8 @@ func TestVersionedCheckpointsSpecialCase(t *testing.T) { } func TestVersionedCheckpointsSpecialCase2(t *testing.T) { + t.Parallel() + tree := NewMutableTree(db.NewMemDB(), 0) tree.Set([]byte("U"), []byte("XamDUtiJ")) @@ -808,6 +842,8 @@ func TestVersionedCheckpointsSpecialCase2(t *testing.T) { } func TestVersionedCheckpointsSpecialCase3(t *testing.T) { + t.Parallel() + tree := NewMutableTree(db.NewMemDB(), 0) tree.Set([]byte("n"), []byte("2wUCUs8q")) @@ -828,6 +864,8 @@ func TestVersionedCheckpointsSpecialCase3(t *testing.T) { } func TestVersionedCheckpointsSpecialCase4(t *testing.T) { + t.Parallel() + tree := NewMutableTree(db.NewMemDB(), 0) tree.Set([]byte("U"), []byte("XamDUtiJ")) @@ -860,6 +898,8 @@ func TestVersionedCheckpointsSpecialCase4(t *testing.T) { } func TestVersionedCheckpointsSpecialCase5(t *testing.T) { + t.Parallel() + tree := NewMutableTree(db.NewMemDB(), 0) tree.Set([]byte("R"), []byte("ygZlIzeW")) @@ -877,6 +917,8 @@ func TestVersionedCheckpointsSpecialCase5(t *testing.T) { } func TestVersionedCheckpointsSpecialCase6(t *testing.T) { + t.Parallel() + tree := NewMutableTree(db.NewMemDB(), 0) tree.Set([]byte("Y"), []byte("MW79JQeV")) @@ -909,6 +951,8 @@ func TestVersionedCheckpointsSpecialCase6(t *testing.T) { } func TestVersionedCheckpointsSpecialCase7(t *testing.T) { + t.Parallel() + tree := NewMutableTree(db.NewMemDB(), 100) tree.Set([]byte("n"), []byte("OtqD3nyn")) @@ -942,6 +986,8 @@ func TestVersionedCheckpointsSpecialCase7(t *testing.T) { } func TestVersionedTreeEfficiency(t *testing.T) { + t.Parallel() + require := require.New(t) tree := NewMutableTree(db.NewMemDB(), 0) versions := 20 @@ -977,6 +1023,8 @@ func TestVersionedTreeEfficiency(t *testing.T) { } func TestVersionedTreeProofs(t *testing.T) { + t.Parallel() + require := require.New(t) tree := NewMutableTree(db.NewMemDB(), 0) @@ -1047,6 +1095,8 @@ func TestVersionedTreeProofs(t *testing.T) { } func TestOrphans(t *testing.T) { + t.Parallel() + // If you create a sequence of saved versions // Then randomly delete versions other than the first and last until only those two remain // Any remaining orphan nodes should be constrained to just the first version @@ -1079,6 +1129,8 @@ func TestOrphans(t *testing.T) { } func TestVersionedTreeHash(t *testing.T) { + t.Parallel() + require := require.New(t) tree := NewMutableTree(db.NewMemDB(), 0) @@ -1101,6 +1153,8 @@ func TestVersionedTreeHash(t *testing.T) { } func TestNilValueSemantics(t *testing.T) { + t.Parallel() + require := require.New(t) tree := NewMutableTree(db.NewMemDB(), 0) @@ -1110,6 +1164,8 @@ func TestNilValueSemantics(t *testing.T) { } func TestCopyValueSemantics(t *testing.T) { + t.Parallel() + require := require.New(t) tree := NewMutableTree(db.NewMemDB(), 0) @@ -1127,6 +1183,8 @@ func TestCopyValueSemantics(t *testing.T) { } func TestRollback(t *testing.T) { + t.Parallel() + require := require.New(t) tree := NewMutableTree(db.NewMemDB(), 0) @@ -1156,6 +1214,8 @@ func TestRollback(t *testing.T) { } func TestLazyLoadVersion(t *testing.T) { + t.Parallel() + mdb := db.NewMemDB() tree := NewMutableTree(mdb, 0) maxVersions := 10 @@ -1194,6 +1254,8 @@ func TestLazyLoadVersion(t *testing.T) { } func TestOverwrite(t *testing.T) { + t.Parallel() + require := require.New(t) mdb := db.NewMemDB() @@ -1226,6 +1288,8 @@ func TestOverwrite(t *testing.T) { } func TestLoadVersionForOverwriting(t *testing.T) { + t.Parallel() + require := require.New(t) mdb := db.NewMemDB() @@ -1290,7 +1354,7 @@ func TestLoadVersionForOverwriting(t *testing.T) { require.NoError(err, "SaveVersion should not fail.") } -//////////////////////////// BENCHMARKS /////////////////////////////////////// +// ----------- BENCHMARKS // ----------- func BenchmarkTreeLoadAndDelete(b *testing.B) { if testing.Short() { diff --git a/tm2/pkg/log/tm_logger_test.go b/tm2/pkg/log/tm_logger_test.go index a6d56bb8feb..43ca98eb0f9 100644 --- a/tm2/pkg/log/tm_logger_test.go +++ b/tm2/pkg/log/tm_logger_test.go @@ -2,7 +2,7 @@ package log_test import ( "bytes" - "io/ioutil" + "io" "strings" "testing" @@ -10,6 +10,8 @@ import ( ) func TestLoggerLogsItsErrors(t *testing.T) { + t.Parallel() + var buf bytes.Buffer logger := log.NewTMLogger(&buf) @@ -21,11 +23,11 @@ func TestLoggerLogsItsErrors(t *testing.T) { } func BenchmarkTMLoggerSimple(b *testing.B) { - benchmarkRunner(b, log.NewTMLogger(ioutil.Discard), baseInfoMessage) + benchmarkRunner(b, log.NewTMLogger(io.Discard), baseInfoMessage) } func BenchmarkTMLoggerContextual(b *testing.B) { - benchmarkRunner(b, log.NewTMLogger(ioutil.Discard), withInfoMessage) + benchmarkRunner(b, log.NewTMLogger(io.Discard), withInfoMessage) } func benchmarkRunner(b *testing.B, logger log.Logger, f func(log.Logger)) { diff --git a/tm2/pkg/os/net_test.go b/tm2/pkg/os/net_test.go index 258ee28bb28..8cbba60aef2 100644 --- a/tm2/pkg/os/net_test.go +++ b/tm2/pkg/os/net_test.go @@ -7,6 +7,8 @@ import ( ) func TestProtocolAndAddress(t *testing.T) { + t.Parallel() + cases := []struct { fullAddr string proto string diff --git a/tm2/pkg/os/tempfile_test.go b/tm2/pkg/os/tempfile_test.go index 12d6abb27cb..ec294d58e30 100644 --- a/tm2/pkg/os/tempfile_test.go +++ b/tm2/pkg/os/tempfile_test.go @@ -5,7 +5,6 @@ package os import ( "bytes" "fmt" - "io/ioutil" "os" "testing" @@ -21,7 +20,7 @@ func TestWriteFileAtomic(t *testing.T) { perm os.FileMode = 0o600 ) - f, err := ioutil.TempFile("/tmp", "write-atomic-test-") + f, err := os.CreateTemp("/tmp", "write-atomic-test-") if err != nil { t.Fatal(err) } diff --git a/tm2/pkg/p2p/config/config.go b/tm2/pkg/p2p/config/config.go index 855c0fd9844..830f84ad137 100644 --- a/tm2/pkg/p2p/config/config.go +++ b/tm2/pkg/p2p/config/config.go @@ -6,7 +6,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/errors" ) -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // P2PConfig const ( @@ -16,8 +16,6 @@ const ( FuzzModeDelay ) -var defaultConfigDir = "config" // duplicate across module configs? - // P2PConfig defines the configuration options for the Tendermint peer-to-peer networking layer type P2PConfig struct { RootDir string `toml:"home"` diff --git a/tm2/pkg/p2p/conn/connection_test.go b/tm2/pkg/p2p/conn/connection_test.go index 6974dd97e56..68f7fbc0841 100644 --- a/tm2/pkg/p2p/conn/connection_test.go +++ b/tm2/pkg/p2p/conn/connection_test.go @@ -37,6 +37,8 @@ func createMConnectionWithCallbacks(conn net.Conn, onReceive func(chID byte, msg } func TestMConnectionSendFlushStop(t *testing.T) { + t.Parallel() + server, client := NetPipe() defer server.Close() //nolint: errcheck defer client.Close() //nolint: errcheck @@ -82,6 +84,8 @@ func TestMConnectionSendFlushStop(t *testing.T) { } func TestMConnectionSend(t *testing.T) { + t.Parallel() + server, client := NetPipe() defer server.Close() //nolint: errcheck defer client.Close() //nolint: errcheck @@ -113,6 +117,8 @@ func TestMConnectionSend(t *testing.T) { } func TestMConnectionReceive(t *testing.T) { + t.Parallel() + server, client := NetPipe() defer server.Close() //nolint: errcheck defer client.Close() //nolint: errcheck @@ -149,6 +155,8 @@ func TestMConnectionReceive(t *testing.T) { } func TestMConnectionStatus(t *testing.T) { + t.Parallel() + server, client := NetPipe() defer server.Close() //nolint: errcheck defer client.Close() //nolint: errcheck @@ -164,6 +172,8 @@ func TestMConnectionStatus(t *testing.T) { } func TestMConnectionPongTimeoutResultsInError(t *testing.T) { + t.Parallel() + server, client := net.Pipe() defer server.Close() defer client.Close() @@ -203,6 +213,8 @@ func TestMConnectionPongTimeoutResultsInError(t *testing.T) { } func TestMConnectionMultiplePongsInTheBeginning(t *testing.T) { + t.Parallel() + server, client := net.Pipe() defer server.Close() defer client.Close() @@ -256,6 +268,8 @@ func TestMConnectionMultiplePongsInTheBeginning(t *testing.T) { } func TestMConnectionMultiplePings(t *testing.T) { + t.Parallel() + server, client := net.Pipe() defer server.Close() defer client.Close() @@ -293,6 +307,8 @@ func TestMConnectionMultiplePings(t *testing.T) { } func TestMConnectionPingPongs(t *testing.T) { + t.Parallel() + // check that we are not leaking any go-routines defer leaktest.CheckTimeout(t, 10*time.Second)() @@ -348,6 +364,8 @@ func TestMConnectionPingPongs(t *testing.T) { } func TestMConnectionStopsAndReturnsError(t *testing.T) { + t.Parallel() + server, client := NetPipe() defer server.Close() //nolint: errcheck defer client.Close() //nolint: errcheck @@ -422,6 +440,8 @@ func expectSend(ch chan struct{}) bool { } func TestMConnectionReadErrorBadEncoding(t *testing.T) { + t.Parallel() + chOnErr := make(chan struct{}) mconnClient, mconnServer := newClientAndServerConnsForReadErrors(t, chOnErr) defer mconnClient.Stop() @@ -440,6 +460,8 @@ func TestMConnectionReadErrorBadEncoding(t *testing.T) { } func TestMConnectionReadErrorUnknownChannel(t *testing.T) { + t.Parallel() + chOnErr := make(chan struct{}) mconnClient, mconnServer := newClientAndServerConnsForReadErrors(t, chOnErr) defer mconnClient.Stop() @@ -457,6 +479,8 @@ func TestMConnectionReadErrorUnknownChannel(t *testing.T) { } func TestMConnectionReadErrorLongMessage(t *testing.T) { + t.Parallel() + chOnErr := make(chan struct{}) chOnRcv := make(chan struct{}) @@ -499,6 +523,8 @@ func TestMConnectionReadErrorLongMessage(t *testing.T) { } func TestMConnectionReadErrorUnknownMsgType(t *testing.T) { + t.Parallel() + chOnErr := make(chan struct{}) mconnClient, mconnServer := newClientAndServerConnsForReadErrors(t, chOnErr) defer mconnClient.Stop() @@ -513,6 +539,8 @@ func TestMConnectionReadErrorUnknownMsgType(t *testing.T) { } func TestMConnectionTrySend(t *testing.T) { + t.Parallel() + server, client := NetPipe() defer server.Close() defer client.Close() diff --git a/tm2/pkg/p2p/conn/secret_connection_test.go b/tm2/pkg/p2p/conn/secret_connection_test.go index a2560af34eb..b238297ae5e 100644 --- a/tm2/pkg/p2p/conn/secret_connection_test.go +++ b/tm2/pkg/p2p/conn/secret_connection_test.go @@ -98,6 +98,8 @@ func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection } func TestSecretConnectionHandshake(t *testing.T) { + t.Parallel() + fooSecConn, barSecConn := makeSecretConnPair(t) if err := fooSecConn.Close(); err != nil { t.Error(err) @@ -110,6 +112,8 @@ func TestSecretConnectionHandshake(t *testing.T) { // Test that shareEphPubKey rejects lower order public keys based on an // (incomplete) blacklist. func TestShareLowOrderPubkey(t *testing.T) { + t.Parallel() + fooConn, barConn := makeKVStoreConnPair() defer fooConn.Close() defer barConn.Close() @@ -141,6 +145,8 @@ func TestShareLowOrderPubkey(t *testing.T) { // Test that additionally that the Diffie-Hellman shared secret is non-zero. // The shared secret would be zero for lower order pub-keys (but tested against the blacklist only). func TestComputeDHFailsOnLowOrder(t *testing.T) { + t.Parallel() + _, locPrivKey := genEphKeys() for _, remLowOrderPubKey := range blacklist { remLowOrderPubKey := remLowOrderPubKey @@ -153,6 +159,8 @@ func TestComputeDHFailsOnLowOrder(t *testing.T) { } func TestConcurrentWrite(t *testing.T) { + t.Parallel() + fooSecConn, barSecConn := makeSecretConnPair(t) fooWriteText := random.RandStr(dataMaxSize) @@ -175,6 +183,8 @@ func TestConcurrentWrite(t *testing.T) { } func TestConcurrentRead(t *testing.T) { + t.Parallel() + fooSecConn, barSecConn := makeSecretConnPair(t) fooWriteText := random.RandStr(dataMaxSize) n := 100 @@ -221,6 +231,8 @@ func readLots(t *testing.T, wg *sync.WaitGroup, conn net.Conn, n int) { } func TestSecretConnectionReadWrite(t *testing.T) { + t.Parallel() + fooConn, barConn := makeKVStoreConnPair() fooWrites, barWrites := []string{}, []string{} fooReads, barReads := []string{}, []string{} @@ -341,6 +353,8 @@ func TestSecretConnectionReadWrite(t *testing.T) { var update = flag.Bool("update", false, "update .golden files") func TestDeriveSecretsAndChallengeGolden(t *testing.T) { + t.Parallel() + goldenFilepath := filepath.Join("testdata", t.Name()+".golden") if *update { t.Logf("Updating golden test vector file %s", goldenFilepath) @@ -386,6 +400,8 @@ func (pk privKeyWithNilPubKey) PubKey() crypto.PubKey { return nil } func (pk privKeyWithNilPubKey) Equals(pk2 crypto.PrivKey) bool { return pk.orig.Equals(pk2) } func TestNilPubkey(t *testing.T) { + t.Parallel() + fooConn, barConn := makeKVStoreConnPair() fooPrvKey := ed25519.GenPrivKey() barPrvKey := privKeyWithNilPubKey{ed25519.GenPrivKey()} @@ -404,6 +420,8 @@ func TestNilPubkey(t *testing.T) { } func TestNonEd25519Pubkey(t *testing.T) { + t.Parallel() + fooConn, barConn := makeKVStoreConnPair() fooPrvKey := ed25519.GenPrivKey() barPrvKey := secp256k1.GenPrivKey() diff --git a/tm2/pkg/p2p/key_test.go b/tm2/pkg/p2p/key_test.go index 8046f58eb25..4f67cc0a5da 100644 --- a/tm2/pkg/p2p/key_test.go +++ b/tm2/pkg/p2p/key_test.go @@ -11,6 +11,8 @@ import ( ) func TestLoadOrGenNodeKey(t *testing.T) { + t.Parallel() + filePath := filepath.Join(os.TempDir(), random.RandStr(12)+"_peer_id.json") nodeKey, err := LoadOrGenNodeKey(filePath) @@ -22,13 +24,15 @@ func TestLoadOrGenNodeKey(t *testing.T) { assert.Equal(t, nodeKey, nodeKey2) } -//---------------------------------------------------------- +// ---------------------------------------------------------- func padBytes(bz []byte, targetBytes int) []byte { return append(bz, bytes.Repeat([]byte{0xFF}, targetBytes-len(bz))...) } func TestPoWTarget(t *testing.T) { + t.Parallel() + targetBytes := 20 cases := []struct { difficulty uint diff --git a/tm2/pkg/p2p/netaddress_test.go b/tm2/pkg/p2p/netaddress_test.go index a5dc3fca375..413d020c153 100644 --- a/tm2/pkg/p2p/netaddress_test.go +++ b/tm2/pkg/p2p/netaddress_test.go @@ -11,6 +11,8 @@ import ( ) func TestAddress2ID(t *testing.T) { + t.Parallel() + idbz, _ := hex.DecodeString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef") id := crypto.AddressFromBytes(idbz).ID() assert.Equal(t, crypto.ID("g1m6kmam774klwlh4dhmhaatd7al02m0h0jwnyc6"), id) @@ -21,6 +23,8 @@ func TestAddress2ID(t *testing.T) { } func TestNewNetAddress(t *testing.T) { + t.Parallel() + tcpAddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:8080") require.Nil(t, err) @@ -41,6 +45,8 @@ func TestNewNetAddress(t *testing.T) { } func TestNewNetAddressFromString(t *testing.T) { + t.Parallel() + testCases := []struct { name string addr string @@ -85,6 +91,8 @@ func TestNewNetAddressFromString(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { + t.Parallel() + addr, err := NewNetAddressFromString(tc.addr) if tc.correct { if assert.Nil(t, err, tc.addr) { @@ -98,6 +106,8 @@ func TestNewNetAddressFromString(t *testing.T) { } func TestNewNetAddressFromStrings(t *testing.T) { + t.Parallel() + addrs, errs := NewNetAddressFromStrings([]string{ "127.0.0.1:8080", "g1m6kmam774klwlh4dhmhaatd7al02m0h0jwnyc6@127.0.0.1:8080", @@ -108,11 +118,15 @@ func TestNewNetAddressFromStrings(t *testing.T) { } func TestNewNetAddressFromIPPort(t *testing.T) { + t.Parallel() + addr := NewNetAddressFromIPPort("", net.ParseIP("127.0.0.1"), 8080) assert.Equal(t, "127.0.0.1:8080", addr.String()) } func TestNetAddressProperties(t *testing.T) { + t.Parallel() + // TODO add more test cases testCases := []struct { addr string @@ -140,6 +154,8 @@ func TestNetAddressProperties(t *testing.T) { } func TestNetAddressReachabilityTo(t *testing.T) { + t.Parallel() + // TODO add more test cases testCases := []struct { addr string diff --git a/tm2/pkg/p2p/node_info_test.go b/tm2/pkg/p2p/node_info_test.go index ea97239643f..58f1dab8854 100644 --- a/tm2/pkg/p2p/node_info_test.go +++ b/tm2/pkg/p2p/node_info_test.go @@ -11,6 +11,8 @@ import ( ) func TestNodeInfoValidate(t *testing.T) { + t.Parallel() + // empty fails ni := NodeInfo{} assert.Error(t, ni.Validate()) @@ -86,6 +88,8 @@ func TestNodeInfoValidate(t *testing.T) { } func TestNodeInfoCompatible(t *testing.T) { + t.Parallel() + nodeKey1 := NodeKey{PrivKey: ed25519.GenPrivKey()} nodeKey2 := NodeKey{PrivKey: ed25519.GenPrivKey()} name := "testing" diff --git a/tm2/pkg/p2p/peer_test.go b/tm2/pkg/p2p/peer_test.go index 070d783d2af..8841e34cc83 100644 --- a/tm2/pkg/p2p/peer_test.go +++ b/tm2/pkg/p2p/peer_test.go @@ -19,6 +19,8 @@ import ( ) func TestPeerBasic(t *testing.T) { + t.Parallel() + assert, require := assert.New(t), require.New(t) // simulate remote peer @@ -43,6 +45,8 @@ func TestPeerBasic(t *testing.T) { } func TestPeerSend(t *testing.T) { + t.Parallel() + assert, require := assert.New(t), require.New(t) config := cfg diff --git a/tm2/pkg/p2p/switch.go b/tm2/pkg/p2p/switch.go index 1f693544d5a..368de659fb1 100644 --- a/tm2/pkg/p2p/switch.go +++ b/tm2/pkg/p2p/switch.go @@ -387,10 +387,6 @@ func (sw *Switch) reconnectToPeer(addr *NetAddress) { // --------------------------------------------------------------------- // Dialing -type privateAddr interface { - PrivateAddr() bool -} - // DialPeersAsync dials a list of peers asynchronously in random order. // Used to dial peers from config on startup or from unsafe-RPC (trusted sources). // It ignores NetAddressLookupError. However, if there are other errors, first diff --git a/tm2/pkg/p2p/switch_test.go b/tm2/pkg/p2p/switch_test.go index a0d4853493b..9e82e20bca1 100644 --- a/tm2/pkg/p2p/switch_test.go +++ b/tm2/pkg/p2p/switch_test.go @@ -105,6 +105,8 @@ func initSwitchFunc(i int, sw *Switch) *Switch { } func TestSwitches(t *testing.T) { + t.Parallel() + s1, s2 := MakeSwitchPair(t, initSwitchFunc) defer s1.Stop() defer s2.Stop() @@ -152,6 +154,8 @@ func assertMsgReceivedWithTimeout(t *testing.T, msgBytes []byte, channel byte, r } func TestSwitchFiltersOutItself(t *testing.T) { + t.Parallel() + s1 := MakeSwitch(cfg, 1, "127.0.0.1", "123.123.123", initSwitchFunc) // simulate s1 having a public IP by creating a remote peer with the same ID @@ -176,6 +180,8 @@ func TestSwitchFiltersOutItself(t *testing.T) { } func TestSwitchPeerFilter(t *testing.T) { + t.Parallel() + var ( filters = []PeerFilterFunc{ func(_ IPeerSet, _ Peer) error { return nil }, @@ -219,6 +225,8 @@ func TestSwitchPeerFilter(t *testing.T) { } func TestSwitchPeerFilterTimeout(t *testing.T) { + t.Parallel() + var ( filters = []PeerFilterFunc{ func(_ IPeerSet, _ Peer) error { @@ -260,6 +268,8 @@ func TestSwitchPeerFilterTimeout(t *testing.T) { } func TestSwitchPeerFilterDuplicate(t *testing.T) { + t.Parallel() + sw := MakeSwitch(cfg, 1, "testing", "123.123.123", initSwitchFunc) sw.Start() defer sw.Stop() @@ -303,6 +313,8 @@ func assertNoPeersAfterTimeout(t *testing.T, sw *Switch, timeout time.Duration) } func TestSwitchStopsNonPersistentPeerOnError(t *testing.T) { + t.Parallel() + assert, require := assert.New(t), require.New(t) sw := MakeSwitch(cfg, 1, "testing", "123.123.123", initSwitchFunc) @@ -338,6 +350,8 @@ func TestSwitchStopsNonPersistentPeerOnError(t *testing.T) { } func TestSwitchStopPeerForError(t *testing.T) { + t.Parallel() + // make two connected switches sw1, sw2 := MakeSwitchPair(t, func(i int, sw *Switch) *Switch { return initSwitchFunc(i, sw) @@ -360,6 +374,8 @@ func TestSwitchStopPeerForError(t *testing.T) { } func TestSwitchReconnectsToOutboundPersistentPeer(t *testing.T) { + t.Parallel() + sw := MakeSwitch(cfg, 1, "testing", "123.123.123", initSwitchFunc) err := sw.Start() require.NoError(t, err) @@ -405,6 +421,8 @@ func TestSwitchReconnectsToOutboundPersistentPeer(t *testing.T) { } func TestSwitchReconnectsToInboundPersistentPeer(t *testing.T) { + t.Parallel() + sw := MakeSwitch(cfg, 1, "testing", "123.123.123", initSwitchFunc) err := sw.Start() require.NoError(t, err) @@ -430,6 +448,8 @@ func TestSwitchReconnectsToInboundPersistentPeer(t *testing.T) { } func TestSwitchDialPeersAsync(t *testing.T) { + t.Parallel() + if testing.Short() { return } @@ -460,6 +480,8 @@ func waitUntilSwitchHasAtLeastNPeers(sw *Switch, n int) { } func TestSwitchFullConnectivity(t *testing.T) { + t.Parallel() + switches := MakeConnectedSwitches(cfg, 3, initSwitchFunc, Connect2Switches) defer func() { for _, sw := range switches { @@ -475,6 +497,8 @@ func TestSwitchFullConnectivity(t *testing.T) { } func TestSwitchAcceptRoutine(t *testing.T) { + t.Parallel() + cfg.MaxNumInboundPeers = 5 // make switch @@ -547,6 +571,8 @@ func (errorTransport) Cleanup(Peer) { } func TestSwitchAcceptRoutineErrorCases(t *testing.T) { + t.Parallel() + sw := NewSwitch(cfg, errorTransport{FilterTimeoutError{}}) assert.NotPanics(t, func() { err := sw.Start() @@ -599,6 +625,8 @@ func (r *mockReactor) InitCalledBeforeRemoveFinished() bool { // see stopAndRemovePeer func TestFlappySwitchInitPeerIsNotCalledBeforeRemovePeer(t *testing.T) { + t.Parallel() + testutils.FilterStability(t, testutils.Flappy) // make reactor diff --git a/tm2/pkg/p2p/transport_test.go b/tm2/pkg/p2p/transport_test.go index 49ab9ac52e3..63b1c26e666 100644 --- a/tm2/pkg/p2p/transport_test.go +++ b/tm2/pkg/p2p/transport_test.go @@ -33,6 +33,8 @@ func newMultiplexTransport( } func TestTransportMultiplexConnFilter(t *testing.T) { + t.Parallel() + mt := newMultiplexTransport( emptyNodeInfo(), NodeKey{ @@ -87,6 +89,8 @@ func TestTransportMultiplexConnFilter(t *testing.T) { } func TestTransportMultiplexConnFilterTimeout(t *testing.T) { + t.Parallel() + mt := newMultiplexTransport( emptyNodeInfo(), NodeKey{ @@ -137,6 +141,8 @@ func TestTransportMultiplexConnFilterTimeout(t *testing.T) { } func TestTransportMultiplexAcceptMultiple(t *testing.T) { + t.Parallel() + mt := testSetupMultiplexTransport(t) laddr := NewNetAddress(mt.nodeKey.ID(), mt.listener.Addr()) @@ -212,6 +218,8 @@ func testDialer(dialAddr NetAddress, errc chan error) { } func TestFlappyTransportMultiplexAcceptNonBlocking(t *testing.T) { + t.Parallel() + testutils.FilterStability(t, testutils.Flappy) mt := testSetupMultiplexTransport(t) @@ -298,6 +306,8 @@ func TestFlappyTransportMultiplexAcceptNonBlocking(t *testing.T) { } func TestTransportMultiplexValidateNodeInfo(t *testing.T) { + t.Parallel() + mt := testSetupMultiplexTransport(t) errc := make(chan error) @@ -339,6 +349,8 @@ func TestTransportMultiplexValidateNodeInfo(t *testing.T) { } func TestTransportMultiplexRejectMismatchID(t *testing.T) { + t.Parallel() + mt := testSetupMultiplexTransport(t) errc := make(chan error) @@ -378,6 +390,8 @@ func TestTransportMultiplexRejectMismatchID(t *testing.T) { } func TestTransportMultiplexDialRejectWrongID(t *testing.T) { + t.Parallel() + mt := testSetupMultiplexTransport(t) var ( @@ -407,6 +421,8 @@ func TestTransportMultiplexDialRejectWrongID(t *testing.T) { } func TestTransportMultiplexRejectIncompatible(t *testing.T) { + t.Parallel() + mt := testSetupMultiplexTransport(t) errc := make(chan error) @@ -443,6 +459,8 @@ func TestTransportMultiplexRejectIncompatible(t *testing.T) { } func TestTransportMultiplexRejectSelf(t *testing.T) { + t.Parallel() + mt := testSetupMultiplexTransport(t) errc := make(chan error) @@ -482,6 +500,8 @@ func TestTransportMultiplexRejectSelf(t *testing.T) { } func TestTransportConnDuplicateIPFilter(t *testing.T) { + t.Parallel() + filter := ConnDuplicateIPFilter() if err := filter(nil, &testTransportConn{}, nil); err != nil { @@ -507,6 +527,8 @@ func TestTransportConnDuplicateIPFilter(t *testing.T) { } func TestTransportHandshake(t *testing.T) { + t.Parallel() + ln, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatal(err) diff --git a/tm2/pkg/p2p/upnp/upnp.go b/tm2/pkg/p2p/upnp/upnp.go index 40f2067e232..cd47ac35553 100644 --- a/tm2/pkg/p2p/upnp/upnp.go +++ b/tm2/pkg/p2p/upnp/upnp.go @@ -10,7 +10,7 @@ import ( "encoding/xml" "errors" "fmt" - "io/ioutil" + "io" "net" "net/http" "strconv" @@ -306,7 +306,7 @@ func (n *upnpNAT) getExternalIPAddress() (info statusInfo, err error) { return } var envelope Envelope - data, err := ioutil.ReadAll(response.Body) + data, err := io.ReadAll(response.Body) if err != nil { return } @@ -363,7 +363,7 @@ func (n *upnpNAT) AddPortMapping(protocol string, externalPort, internalPort int // TODO: check response to see if the port was forwarded // log.Println(message, response) // JAE: - // body, err := ioutil.ReadAll(response.Body) + // body, err := io.ReadAll(response.Body) // fmt.Println(string(body), err) mappedExternalPort = externalPort _ = response diff --git a/tm2/pkg/random/random_test.go b/tm2/pkg/random/random_test.go index e2d45533626..71e05e95e16 100644 --- a/tm2/pkg/random/random_test.go +++ b/tm2/pkg/random/random_test.go @@ -15,18 +15,24 @@ import ( ) func TestRandStr(t *testing.T) { + t.Parallel() + l := 243 s := RandStr(l) assert.Equal(t, l, len(s)) } func TestRandBytes(t *testing.T) { + t.Parallel() + l := 243 b := RandBytes(l) assert.Equal(t, l, len(b)) } func TestRandIntn(t *testing.T) { + t.Parallel() + n := 243 for i := 0; i < 100; i++ { x := RandIntn(n) @@ -76,6 +82,8 @@ func testThemAll() string { } func TestRngConcurrencySafety(t *testing.T) { + t.Parallel() + var wg sync.WaitGroup for i := 0; i < 100; i++ { wg.Add(1) diff --git a/tm2/pkg/sdk/auth/ante_test.go b/tm2/pkg/sdk/auth/ante_test.go index 2dc3ec08176..9c15cca18a2 100644 --- a/tm2/pkg/sdk/auth/ante_test.go +++ b/tm2/pkg/sdk/auth/ante_test.go @@ -59,6 +59,8 @@ func defaultAnteOptions() AnteOptions { // Test various error cases in the AnteHandler control flow. func TestAnteHandlerSigErrors(t *testing.T) { + t.Parallel() + // setup env := setupTestEnv() ctx := env.ctx @@ -107,6 +109,8 @@ func TestAnteHandlerSigErrors(t *testing.T) { // Test logic around account number checking with one signer and many signers. func TestAnteHandlerAccountNumbers(t *testing.T) { + t.Parallel() + // setup env := setupTestEnv() anteHandler := NewAnteHandler(env.acck, env.bank, DefaultSigVerificationGasConsumer, defaultAnteOptions()) @@ -164,6 +168,8 @@ func TestAnteHandlerAccountNumbers(t *testing.T) { // Test logic around account number checking with many signers when BlockHeight is 0. func TestAnteHandlerAccountNumbersAtBlockHeightZero(t *testing.T) { + t.Parallel() + // setup env := setupTestEnv() anteHandler := NewAnteHandler(env.acck, env.bank, DefaultSigVerificationGasConsumer, defaultAnteOptions()) @@ -223,6 +229,8 @@ func TestAnteHandlerAccountNumbersAtBlockHeightZero(t *testing.T) { // Test logic around sequence checking with one signer and many signers. func TestAnteHandlerSequences(t *testing.T) { + t.Parallel() + // setup env := setupTestEnv() anteHandler := NewAnteHandler(env.acck, env.bank, DefaultSigVerificationGasConsumer, defaultAnteOptions()) @@ -300,6 +308,8 @@ func TestAnteHandlerSequences(t *testing.T) { // Test logic around fee deduction. func TestAnteHandlerFees(t *testing.T) { + t.Parallel() + // setup env := setupTestEnv() ctx := env.ctx @@ -341,6 +351,8 @@ func TestAnteHandlerFees(t *testing.T) { // Test logic around memo gas consumption. func TestAnteHandlerMemoGas(t *testing.T) { + t.Parallel() + // setup env := setupTestEnv() anteHandler := NewAnteHandler(env.acck, env.bank, DefaultSigVerificationGasConsumer, defaultAnteOptions()) @@ -381,6 +393,8 @@ func TestAnteHandlerMemoGas(t *testing.T) { } func TestAnteHandlerMultiSigner(t *testing.T) { + t.Parallel() + // setup env := setupTestEnv() anteHandler := NewAnteHandler(env.acck, env.bank, DefaultSigVerificationGasConsumer, defaultAnteOptions()) @@ -431,6 +445,8 @@ func TestAnteHandlerMultiSigner(t *testing.T) { } func TestAnteHandlerBadSignBytes(t *testing.T) { + t.Parallel() + // setup env := setupTestEnv() anteHandler := NewAnteHandler(env.acck, env.bank, DefaultSigVerificationGasConsumer, defaultAnteOptions()) @@ -508,6 +524,8 @@ func TestAnteHandlerBadSignBytes(t *testing.T) { } func TestAnteHandlerSetPubKey(t *testing.T) { + t.Parallel() + // setup env := setupTestEnv() anteHandler := NewAnteHandler(env.acck, env.bank, DefaultSigVerificationGasConsumer, defaultAnteOptions()) @@ -560,6 +578,8 @@ func TestAnteHandlerSetPubKey(t *testing.T) { } func TestProcessPubKey(t *testing.T) { + t.Parallel() + env := setupTestEnv() ctx := env.ctx @@ -588,7 +608,10 @@ func TestProcessPubKey(t *testing.T) { {"pubkey doesn't match addr, simulate on", args{acc1, std.Signature{PubKey: priv2.PubKey()}, true}, false}, } for _, tt := range tests { + tt := tt t.Run(tt.name, func(t *testing.T) { + t.Parallel() + _, err := ProcessPubKey(tt.args.acc, tt.args.sig, tt.args.simulate) require.Equal(t, tt.wantErr, !err.IsOK()) }) @@ -596,6 +619,8 @@ func TestProcessPubKey(t *testing.T) { } func TestConsumeSignatureVerificationGas(t *testing.T) { + t.Parallel() + params := DefaultParams() msg := []byte{1, 2, 3, 4} @@ -625,7 +650,10 @@ func TestConsumeSignatureVerificationGas(t *testing.T) { {"unknown key", args{store.NewInfiniteGasMeter(), nil, nil, params}, 0, true}, } for _, tt := range tests { + tt := tt t.Run(tt.name, func(t *testing.T) { + t.Parallel() + res := DefaultSigVerificationGasConsumer(tt.args.meter, tt.args.sig, tt.args.pubkey, tt.args.params) if tt.shouldErr { @@ -671,6 +699,8 @@ func expectedGasCostByKeys(pubkeys []crypto.PubKey) int64 { } func TestCountSubkeys(t *testing.T) { + t.Parallel() + genPubKeys := func(n int) []crypto.PubKey { var ret []crypto.PubKey for i := 0; i < n; i++ { @@ -698,13 +728,18 @@ func TestCountSubkeys(t *testing.T) { {"multi level multikey", args{multiLevelMultiKey}, 11}, } for _, tt := range tests { - t.Run(tt.name, func(T *testing.T) { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + require.Equal(t, tt.want, std.CountSubKeys(tt.args.pub)) }) } } func TestAnteHandlerSigLimitExceeded(t *testing.T) { + t.Parallel() + // setup env := setupTestEnv() anteHandler := NewAnteHandler(env.acck, env.bank, DefaultSigVerificationGasConsumer, defaultAnteOptions()) @@ -742,6 +777,8 @@ func TestAnteHandlerSigLimitExceeded(t *testing.T) { } func TestEnsureSufficientMempoolFees(t *testing.T) { + t.Parallel() + // setup env := setupTestEnv() ctx := env.ctx.WithMinGasPrices( @@ -775,6 +812,8 @@ func TestEnsureSufficientMempoolFees(t *testing.T) { // Test custom SignatureVerificationGasConsumer func TestCustomSignatureVerificationGasConsumer(t *testing.T) { + t.Parallel() + // setup env := setupTestEnv() // setup an ante handler that only accepts PubKeyEd25519 diff --git a/tm2/pkg/sdk/auth/keeper_test.go b/tm2/pkg/sdk/auth/keeper_test.go index 3af74cf4a4c..d40d96cdb4b 100644 --- a/tm2/pkg/sdk/auth/keeper_test.go +++ b/tm2/pkg/sdk/auth/keeper_test.go @@ -9,6 +9,8 @@ import ( ) func TestAccountMapperGetSet(t *testing.T) { + t.Parallel() + env := setupTestEnv() addr := crypto.AddressFromPreimage([]byte("some-address")) @@ -38,6 +40,8 @@ func TestAccountMapperGetSet(t *testing.T) { } func TestAccountMapperRemoveAccount(t *testing.T) { + t.Parallel() + env := setupTestEnv() addr1 := crypto.AddressFromPreimage([]byte("addr1")) addr2 := crypto.AddressFromPreimage([]byte("addr2")) diff --git a/tm2/pkg/sdk/auth/test_common.go b/tm2/pkg/sdk/auth/test_common.go index a51c8576bad..ee4153184a4 100644 --- a/tm2/pkg/sdk/auth/test_common.go +++ b/tm2/pkg/sdk/auth/test_common.go @@ -19,33 +19,6 @@ type testEnv struct { bank BankKeeperI } -// moduleAccount defines an account for modules that holds coins on a pool -type moduleAccount struct { - *std.BaseAccount - name string `json:"name" yaml:"name"` // name of the module - permissions []string `json:"permissions" yaml"permissions"` // permissions of module account -} - -// HasPermission returns whether or not the module account has permission. -func (ma moduleAccount) HasPermission(permission string) bool { - for _, perm := range ma.permissions { - if perm == permission { - return true - } - } - return false -} - -// GetName returns the the name of the holder's module -func (ma moduleAccount) GetName() string { - return ma.name -} - -// GetPermissions returns permissions granted to the module account -func (ma moduleAccount) GetPermissions() []string { - return ma.permissions -} - func setupTestEnv() testEnv { db := dbm.NewMemDB() diff --git a/tm2/pkg/sdk/bank/handler_test.go b/tm2/pkg/sdk/bank/handler_test.go index fef4810c027..85fc68fc304 100644 --- a/tm2/pkg/sdk/bank/handler_test.go +++ b/tm2/pkg/sdk/bank/handler_test.go @@ -16,6 +16,8 @@ import ( ) func TestInvalidMsg(t *testing.T) { + t.Parallel() + h := NewHandler(BankKeeper{}) res := h.Process(sdk.NewContext(sdk.RunTxModeDeliver, nil, &bft.Header{ChainID: "test-chain"}, nil), tu.NewTestMsg()) require.False(t, res.IsOK()) @@ -23,6 +25,8 @@ func TestInvalidMsg(t *testing.T) { } func TestBalances(t *testing.T) { + t.Parallel() + env := setupTestEnv() h := NewHandler(env.bank) _, _, addr := tu.KeyTestPubAddr() @@ -51,6 +55,8 @@ func TestBalances(t *testing.T) { } func TestQuerierRouteNotFound(t *testing.T) { + t.Parallel() + env := setupTestEnv() h := NewHandler(env.bank) req := abci.RequestQuery{ diff --git a/tm2/pkg/sdk/bank/keeper_test.go b/tm2/pkg/sdk/bank/keeper_test.go index d4e230330d5..59b4c12689c 100644 --- a/tm2/pkg/sdk/bank/keeper_test.go +++ b/tm2/pkg/sdk/bank/keeper_test.go @@ -11,6 +11,8 @@ import ( ) func TestKeeper(t *testing.T) { + t.Parallel() + env := setupTestEnv() ctx := env.ctx @@ -88,6 +90,8 @@ func TestKeeper(t *testing.T) { } func TestBankKeeper(t *testing.T) { + t.Parallel() + env := setupTestEnv() ctx := env.ctx @@ -134,6 +138,8 @@ func TestBankKeeper(t *testing.T) { } func TestViewKeeper(t *testing.T) { + t.Parallel() + env := setupTestEnv() ctx := env.ctx view := NewViewKeeper(env.acck) diff --git a/tm2/pkg/sdk/baseapp_test.go b/tm2/pkg/sdk/baseapp_test.go index 2d130583885..f6c2038569a 100644 --- a/tm2/pkg/sdk/baseapp_test.go +++ b/tm2/pkg/sdk/baseapp_test.go @@ -80,6 +80,8 @@ func setupBaseApp(t *testing.T, options ...func(*BaseApp)) *BaseApp { } func TestMountStores(t *testing.T) { + t.Parallel() + app := setupBaseApp(t) // check both stores @@ -92,6 +94,8 @@ func TestMountStores(t *testing.T) { // Test that we can make commits and then reload old versions. // Test that LoadLatestVersion actually does. func TestLoadVersion(t *testing.T) { + t.Parallel() + pruningOpt := SetPruningOptions(store.PruneSyncable) name := t.Name() db := dbm.NewMemDB() @@ -139,6 +143,8 @@ func TestLoadVersion(t *testing.T) { } func TestAppVersionSetterGetter(t *testing.T) { + t.Parallel() + pruningOpt := SetPruningOptions(store.PruneSyncable) name := t.Name() db := dbm.NewMemDB() @@ -158,6 +164,8 @@ func TestAppVersionSetterGetter(t *testing.T) { } func TestLoadVersionInvalid(t *testing.T) { + t.Parallel() + pruningOpt := SetPruningOptions(store.PruneSyncable) name := t.Name() db := dbm.NewMemDB() @@ -198,6 +206,8 @@ func testLoadVersionHelper(t *testing.T, app *BaseApp, expectedHeight int64, exp } func TestOptionFunction(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() bap := newBaseApp("starting name", db, testChangeNameHelper("new name")) require.Equal(t, bap.name, "new name", "BaseApp should have had name changed via option function") @@ -211,6 +221,8 @@ func testChangeNameHelper(name string) func(*BaseApp) { // Test that Info returns the latest committed state. func TestInfo(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() app := newBaseApp(t.Name(), db) @@ -229,6 +241,8 @@ func TestInfo(t *testing.T) { } func TestBaseAppOptionSeal(t *testing.T) { + t.Parallel() + app := setupBaseApp(t) require.Panics(t, func() { @@ -258,6 +272,8 @@ func TestBaseAppOptionSeal(t *testing.T) { } func TestSetMinGasPrices(t *testing.T) { + t.Parallel() + minGasPrices, err := ParseGasPrices("5000stake/10gas") require.Nil(t, err) db := dbm.NewMemDB() @@ -266,6 +282,8 @@ func TestSetMinGasPrices(t *testing.T) { } func TestInitChainer(t *testing.T) { + t.Parallel() + name := t.Name() // keep the db and logger ourselves so // we can reload the same app later @@ -444,10 +462,6 @@ func (mch msgCounterHandler) Query(ctx Context, req abci.RequestQuery) abci.Resp panic("should not happen") } -func i2b(i int64) []byte { - return []byte{byte(i)} -} - func getIntFromStore(store store.Store, key []byte) int64 { bz := store.Get(key) if len(bz) == 0 { @@ -477,7 +491,7 @@ func incrementingCounter(t *testing.T, store store.Store, counterKey []byte, cou return } -//--------------------------------------------------------------------- +// --------------------------------------------------------------------- // Tx processing - CheckTx, DeliverTx, SimulateTx. // These tests use the serialized tx as input, while most others will use the // Check(), Deliver(), Simulate() methods directly. @@ -487,6 +501,8 @@ func incrementingCounter(t *testing.T, store store.Store, counterKey []byte, cou // on the store within a block, and that the CheckTx state // gets reset to the latest committed state during Commit func TestCheckTx(t *testing.T) { + t.Parallel() + // This ante handler reads the key and checks that the value matches the current counter. // This ensures changes to the kvstore persist across successive CheckTx. counterKey := []byte("counter-key") @@ -530,6 +546,8 @@ func TestCheckTx(t *testing.T) { // Test that successive DeliverTx can see each others' effects // on the store, both within and across blocks. func TestDeliverTx(t *testing.T) { + t.Parallel() + // test increments in the ante anteKey := []byte("ante-key") anteOpt := func(bapp *BaseApp) { bapp.SetAnteHandler(anteHandlerTxTest(t, mainKey, anteKey)) } @@ -566,14 +584,10 @@ func TestDeliverTx(t *testing.T) { } } -// Number of messages doesn't matter to CheckTx. -func TestMultiMsgCheckTx(t *testing.T) { - // TODO: ensure we get the same results - // with one message or many -} - // One call to DeliverTx should process all the messages, in order. func TestMultiMsgDeliverTx(t *testing.T) { + t.Parallel() + // increment the tx counter anteKey := []byte("ante-key") anteOpt := func(bapp *BaseApp) { bapp.SetAnteHandler(anteHandlerTxTest(t, mainKey, anteKey)) } @@ -633,17 +647,12 @@ func TestMultiMsgDeliverTx(t *testing.T) { require.Equal(t, int64(2), msgCounter2) } -// Interleave calls to Check and Deliver and ensure -// that there is no cross-talk. Check sees results of the previous Check calls -// and Deliver sees that of the previous Deliver calls, but they don't see eachother. -func TestConcurrentCheckDeliver(t *testing.T) { - // TODO -} - // Simulate a transaction that uses gas to compute the gas. // Simulate() and Query(".app/simulate", txBytes) should give // the same results. func TestSimulateTx(t *testing.T) { + t.Parallel() + gasConsumed := int64(5) anteOpt := func(bapp *BaseApp) { @@ -704,6 +713,8 @@ func TestSimulateTx(t *testing.T) { } func TestRunInvalidTransaction(t *testing.T) { + t.Parallel() + anteOpt := func(bapp *BaseApp) { bapp.SetAnteHandler(func(ctx Context, tx Tx, simulate bool) (newCtx Context, res Result, abort bool) { newCtx = ctx @@ -779,6 +790,8 @@ func TestRunInvalidTransaction(t *testing.T) { // Test that transactions exceeding gas limits fail func TestTxGasLimits(t *testing.T) { + t.Parallel() + gasGranted := int64(10) anteOpt := func(bapp *BaseApp) { bapp.SetAnteHandler(func(ctx Context, tx Tx, simulate bool) (newCtx Context, res Result, abort bool) { @@ -853,6 +866,8 @@ func TestTxGasLimits(t *testing.T) { // Test that transactions exceeding gas limits fail func TestMaxBlockGasLimits(t *testing.T) { + t.Parallel() + gasGranted := int64(10) anteOpt := func(bapp *BaseApp) { bapp.SetAnteHandler(func(ctx Context, tx Tx, simulate bool) (newCtx Context, res Result, abort bool) { @@ -942,6 +957,8 @@ func TestMaxBlockGasLimits(t *testing.T) { } func TestBaseAppAnteHandler(t *testing.T) { + t.Parallel() + anteKey := []byte("ante-key") anteOpt := func(bapp *BaseApp) { bapp.SetAnteHandler(anteHandlerTxTest(t, mainKey, anteKey)) @@ -1011,6 +1028,8 @@ func TestBaseAppAnteHandler(t *testing.T) { } func TestGasConsumptionBadTx(t *testing.T) { + t.Parallel() + gasWanted := int64(5) anteOpt := func(bapp *BaseApp) { bapp.SetAnteHandler(func(ctx Context, tx Tx, simulate bool) (newCtx Context, res Result, abort bool) { @@ -1074,6 +1093,8 @@ func TestGasConsumptionBadTx(t *testing.T) { // Test that we can only query from the latest committed state. func TestQuery(t *testing.T) { + t.Parallel() + key, value := []byte("hello"), []byte("goodbye") anteOpt := func(bapp *BaseApp) { bapp.SetAnteHandler(func(ctx Context, tx Tx, simulate bool) (newCtx Context, res Result, abort bool) { diff --git a/tm2/pkg/service/service_test.go b/tm2/pkg/service/service_test.go index b3817d6f60a..adf14e0c539 100644 --- a/tm2/pkg/service/service_test.go +++ b/tm2/pkg/service/service_test.go @@ -16,6 +16,8 @@ func (testService) OnReset() error { } func TestBaseServiceWait(t *testing.T) { + t.Parallel() + ts := &testService{} ts.BaseService = *NewBaseService(nil, "TestService", ts) ts.Start() @@ -37,6 +39,8 @@ func TestBaseServiceWait(t *testing.T) { } func TestBaseServiceReset(t *testing.T) { + t.Parallel() + ts := &testService{} ts.BaseService = *NewBaseService(nil, "TestService", ts) ts.Start() diff --git a/tm2/pkg/std/coin.go b/tm2/pkg/std/coin.go index d5eb9bb1da0..75063320ad3 100644 --- a/tm2/pkg/std/coin.go +++ b/tm2/pkg/std/coin.go @@ -619,11 +619,9 @@ var ( // Denominations can be 3 ~ 16 characters long. reDnmString = `[a-z][a-z0-9]{2,15}` reAmt = `[[:digit:]]+` - reDecAmt = `[[:digit:]]*\.[[:digit:]]+` reSpc = `[[:space:]]*` reDnm = regexp.MustCompile(fmt.Sprintf(`^%s$`, reDnmString)) reCoin = regexp.MustCompile(fmt.Sprintf(`^(%s)%s(%s)$`, reAmt, reSpc, reDnmString)) - reDecCoin = regexp.MustCompile(fmt.Sprintf(`^(%s)%s(%s)$`, reDecAmt, reSpc, reDnmString)) ) func validateDenom(denom string) error { diff --git a/tm2/pkg/std/coin_test.go b/tm2/pkg/std/coin_test.go index 923781ed412..8d9a9359b61 100644 --- a/tm2/pkg/std/coin_test.go +++ b/tm2/pkg/std/coin_test.go @@ -18,12 +18,16 @@ var ( // Coin tests func TestCoin(t *testing.T) { + t.Parallel() + require.Panics(t, func() { NewCoin(testDenom1, -1) }) require.Panics(t, func() { NewCoin(strings.ToUpper(testDenom1), 10) }) require.Equal(t, int64(5), NewCoin(testDenom1, 5).Amount) } func TestIsEqualCoin(t *testing.T) { + t.Parallel() + cases := []struct { inputOne Coin inputTwo Coin @@ -46,6 +50,8 @@ func TestIsEqualCoin(t *testing.T) { } func TestCoinIsValid(t *testing.T) { + t.Parallel() + cases := []struct { coin Coin expectPass bool @@ -66,6 +72,8 @@ func TestCoinIsValid(t *testing.T) { } func TestAddCoin(t *testing.T) { + t.Parallel() + cases := []struct { inputOne Coin inputTwo Coin @@ -88,6 +96,8 @@ func TestAddCoin(t *testing.T) { } func TestSubCoin(t *testing.T) { + t.Parallel() + cases := []struct { inputOne Coin inputTwo Coin @@ -120,6 +130,8 @@ func TestSubCoin(t *testing.T) { } func TestIsGTECoin(t *testing.T) { + t.Parallel() + cases := []struct { inputOne Coin inputTwo Coin @@ -142,6 +154,8 @@ func TestIsGTECoin(t *testing.T) { } func TestIsLTCoin(t *testing.T) { + t.Parallel() + cases := []struct { inputOne Coin inputTwo Coin @@ -167,6 +181,8 @@ func TestIsLTCoin(t *testing.T) { } func TestCoinIsZero(t *testing.T) { + t.Parallel() + coin := NewCoin(testDenom1, 0) res := coin.IsZero() require.True(t, res) @@ -180,6 +196,8 @@ func TestCoinIsZero(t *testing.T) { // Coins tests func TestIsZeroCoins(t *testing.T) { + t.Parallel() + cases := []struct { inputOne Coins expected bool @@ -198,6 +216,8 @@ func TestIsZeroCoins(t *testing.T) { } func TestEqualCoins(t *testing.T) { + t.Parallel() + cases := []struct { inputOne Coins inputTwo Coins @@ -224,6 +244,8 @@ func TestEqualCoins(t *testing.T) { } func TestAddCoins(t *testing.T) { + t.Parallel() + zero := int64(0) one := int64(1) two := int64(2) @@ -248,6 +270,8 @@ func TestAddCoins(t *testing.T) { } func TestSubCoins(t *testing.T) { + t.Parallel() + zero := int64(0) one := int64(1) two := int64(2) @@ -277,6 +301,8 @@ func TestSubCoins(t *testing.T) { } func TestCoins(t *testing.T) { + t.Parallel() + good := Coins{ {"gas", int64(1)}, {"mineral", int64(1)}, @@ -339,6 +365,8 @@ func TestCoins(t *testing.T) { } func TestCoinsGT(t *testing.T) { + t.Parallel() + one := int64(1) two := int64(2) @@ -351,6 +379,8 @@ func TestCoinsGT(t *testing.T) { } func TestCoinsLT(t *testing.T) { + t.Parallel() + one := int64(1) two := int64(2) @@ -366,6 +396,8 @@ func TestCoinsLT(t *testing.T) { } func TestCoinsLTE(t *testing.T) { + t.Parallel() + one := int64(1) two := int64(2) @@ -381,6 +413,8 @@ func TestCoinsLTE(t *testing.T) { } func TestParse(t *testing.T) { + t.Parallel() + one := int64(1) cases := []struct { @@ -413,6 +447,8 @@ func TestParse(t *testing.T) { } func TestSortCoins(t *testing.T) { + t.Parallel() + good := Coins{ NewCoin("gas", 1), NewCoin("mineral", 1), @@ -462,6 +498,8 @@ func TestSortCoins(t *testing.T) { } func TestAmountOf(t *testing.T) { + t.Parallel() + case0 := Coins{} case1 := Coins{ NewCoin("gold", 0), @@ -504,6 +542,8 @@ func TestAmountOf(t *testing.T) { } func TestCoinsIsAnyGTE(t *testing.T) { + t.Parallel() + one := int64(1) two := int64(2) @@ -524,6 +564,8 @@ func TestCoinsIsAnyGTE(t *testing.T) { } func TestCoinsIsAllGT(t *testing.T) { + t.Parallel() + one := int64(1) two := int64(2) @@ -544,6 +586,8 @@ func TestCoinsIsAllGT(t *testing.T) { } func TestCoinsIsAllGTE(t *testing.T) { + t.Parallel() + one := int64(1) two := int64(2) @@ -566,6 +610,8 @@ func TestCoinsIsAllGTE(t *testing.T) { } func TestNewCoins(t *testing.T) { + t.Parallel() + tenatom := NewCoin("atom", 10) tenbtc := NewCoin("btc", 10) zeroeth := NewCoin("eth", 0) @@ -582,7 +628,10 @@ func TestNewCoins(t *testing.T) { {"panic on dups", []Coin{tenatom, tenatom}, Coins{}, true}, } for _, tt := range tests { + tt := tt t.Run(tt.name, func(t *testing.T) { + t.Parallel() + if tt.wantPanic { require.Panics(t, func() { NewCoins(tt.coins...) }) return @@ -594,6 +643,8 @@ func TestNewCoins(t *testing.T) { } func TestCoinsIsAnyGT(t *testing.T) { + t.Parallel() + twoAtom := NewCoin("atom", 2) fiveAtom := NewCoin("atom", 5) threeEth := NewCoin("eth", 3) @@ -613,6 +664,8 @@ func TestCoinsIsAnyGT(t *testing.T) { } func TestFindDup(t *testing.T) { + t.Parallel() + abc := NewCoin("abc", 10) def := NewCoin("def", 10) ghi := NewCoin("ghi", 10) @@ -632,7 +685,10 @@ func TestFindDup(t *testing.T) { {"dup after first position", args{Coins{abc, def, def}}, 2}, } for _, tt := range tests { + tt := tt t.Run(tt.name, func(t *testing.T) { + t.Parallel() + if got := findDup(tt.args.coins); got != tt.want { t.Errorf("findDup() = %v, want %v", got, tt.want) } @@ -641,6 +697,8 @@ func TestFindDup(t *testing.T) { } func TestMarshalJSONCoins(t *testing.T) { + t.Parallel() + testCases := []struct { name string input Coins @@ -652,7 +710,11 @@ func TestMarshalJSONCoins(t *testing.T) { } for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + bz, err := amino.MarshalJSON(tc.input) require.NoError(t, err) require.Equal(t, tc.strOutput, string(bz)) diff --git a/tm2/pkg/std/kvpair_test.go b/tm2/pkg/std/kvpair_test.go index d030da48053..5edf750e6dd 100644 --- a/tm2/pkg/std/kvpair_test.go +++ b/tm2/pkg/std/kvpair_test.go @@ -7,6 +7,8 @@ import ( ) func TestKVPairs(t *testing.T) { + t.Parallel() + kvs := KVPairs{ {Key: []byte("k2"), Value: []byte("")}, {Key: []byte("k1"), Value: []byte("2")}, @@ -32,6 +34,8 @@ func TestKVPairs(t *testing.T) { } func TestKI64Pairs(t *testing.T) { + t.Parallel() + kvs := KI64Pairs{ {Key: []byte("k2"), Value: 0}, {Key: []byte("k1"), Value: 2}, diff --git a/tm2/pkg/store/cache/store_test.go b/tm2/pkg/store/cache/store_test.go index 5daf83fcb61..adf122fc637 100644 --- a/tm2/pkg/store/cache/store_test.go +++ b/tm2/pkg/store/cache/store_test.go @@ -22,6 +22,8 @@ func keyFmt(i int) []byte { return bz(fmt.Sprintf("key%0.8d", i)) } func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) } func TestCacheStore(t *testing.T) { + t.Parallel() + mem := dbadapter.Store{dbm.NewMemDB()} st := cache.New(mem) @@ -65,12 +67,16 @@ func TestCacheStore(t *testing.T) { } func TestCacheStoreNoNilSet(t *testing.T) { + t.Parallel() + mem := dbadapter.Store{dbm.NewMemDB()} st := cache.New(mem) require.Panics(t, func() { st.Set([]byte("key"), nil) }, "setting a nil value should panic") } func TestCacheStoreNested(t *testing.T) { + t.Parallel() + mem := dbadapter.Store{dbm.NewMemDB()} st := cache.New(mem) @@ -100,6 +106,8 @@ func TestCacheStoreNested(t *testing.T) { } func TestCacheKVIteratorBounds(t *testing.T) { + t.Parallel() + st := newCacheStore() // set some items @@ -151,6 +159,8 @@ func TestCacheKVIteratorBounds(t *testing.T) { } func TestCacheKVReverseIteratorBounds(t *testing.T) { + t.Parallel() + st := newCacheStore() // set some items @@ -195,6 +205,8 @@ func TestCacheKVReverseIteratorBounds(t *testing.T) { } func TestCacheKVMergeIteratorBasics(t *testing.T) { + t.Parallel() + st := newCacheStore() // set and delete an item in the cache, iterator should be empty @@ -243,6 +255,8 @@ func TestCacheKVMergeIteratorBasics(t *testing.T) { } func TestCacheKVMergeIteratorDeleteLast(t *testing.T) { + t.Parallel() + st := newCacheStore() // set some items and write them @@ -269,6 +283,8 @@ func TestCacheKVMergeIteratorDeleteLast(t *testing.T) { } func TestCacheKVMergeIteratorDeletes(t *testing.T) { + t.Parallel() + st := newCacheStore() truth := dbm.NewMemDB() @@ -303,6 +319,8 @@ func TestCacheKVMergeIteratorDeletes(t *testing.T) { } func TestCacheKVMergeIteratorChunks(t *testing.T) { + t.Parallel() + st := newCacheStore() // Use the truth to check values on the merge iterator @@ -334,6 +352,8 @@ func TestCacheKVMergeIteratorChunks(t *testing.T) { } func TestCacheKVMergeIteratorRandom(t *testing.T) { + t.Parallel() + st := newCacheStore() truth := dbm.NewMemDB() diff --git a/tm2/pkg/store/gas/store_test.go b/tm2/pkg/store/gas/store_test.go index 70f1fc8ea7f..54729abf2ed 100644 --- a/tm2/pkg/store/gas/store_test.go +++ b/tm2/pkg/store/gas/store_test.go @@ -13,18 +13,14 @@ import ( "github.com/stretchr/testify/require" ) -func newGasKVStore() types.Store { - meter := types.NewGasMeter(10000) - mem := dbadapter.Store{dbm.NewMemDB()} - return gas.New(mem, meter, types.DefaultGasConfig()) -} - func bz(s string) []byte { return []byte(s) } func keyFmt(i int) []byte { return bz(fmt.Sprintf("key%0.8d", i)) } func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) } func TestGasKVStoreBasic(t *testing.T) { + t.Parallel() + mem := dbadapter.Store{dbm.NewMemDB()} meter := types.NewGasMeter(10000) st := gas.New(mem, meter, types.DefaultGasConfig()) @@ -37,6 +33,8 @@ func TestGasKVStoreBasic(t *testing.T) { } func TestGasKVStoreIterator(t *testing.T) { + t.Parallel() + mem := dbadapter.Store{dbm.NewMemDB()} meter := types.NewGasMeter(10000) st := gas.New(mem, meter, types.DefaultGasConfig()) @@ -61,6 +59,8 @@ func TestGasKVStoreIterator(t *testing.T) { } func TestGasKVStoreOutOfGasSet(t *testing.T) { + t.Parallel() + mem := dbadapter.Store{dbm.NewMemDB()} meter := types.NewGasMeter(0) st := gas.New(mem, meter, types.DefaultGasConfig()) @@ -68,6 +68,8 @@ func TestGasKVStoreOutOfGasSet(t *testing.T) { } func TestGasKVStoreOutOfGasIterator(t *testing.T) { + t.Parallel() + mem := dbadapter.Store{dbm.NewMemDB()} meter := types.NewGasMeter(20000) st := gas.New(mem, meter, types.DefaultGasConfig()) diff --git a/tm2/pkg/store/iavl/store_test.go b/tm2/pkg/store/iavl/store_test.go index 83afae91860..a29dbab096a 100644 --- a/tm2/pkg/store/iavl/store_test.go +++ b/tm2/pkg/store/iavl/store_test.go @@ -49,6 +49,8 @@ func newAlohaTree(t *testing.T, db dbm.DB) (*iavl.MutableTree, types.CommitID) { } func TestGetImmutable(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() tree, cID := newAlohaTree(t, db) store := UnsafeNewStore(tree, storeOptions(10, 10)) @@ -79,6 +81,8 @@ func TestGetImmutable(t *testing.T) { } func TestTestGetImmutableIterator(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() tree, cID := newAlohaTree(t, db) store := UnsafeNewStore(tree, storeOptions(10, 10)) @@ -102,6 +106,8 @@ func TestTestGetImmutableIterator(t *testing.T) { } func TestIAVLStoreGetSetHasDelete(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() tree, _ := newAlohaTree(t, db) iavlStore := UnsafeNewStore(tree, storeOptions(numRecent, storeEvery)) @@ -127,6 +133,8 @@ func TestIAVLStoreGetSetHasDelete(t *testing.T) { } func TestIAVLStoreNoNilSet(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() tree, _ := newAlohaTree(t, db) iavlStore := UnsafeNewStore(tree, storeOptions(numRecent, storeEvery)) @@ -134,6 +142,8 @@ func TestIAVLStoreNoNilSet(t *testing.T) { } func TestIAVLIterator(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() tree, _ := newAlohaTree(t, db) iavlStore := UnsafeNewStore(tree, storeOptions(numRecent, storeEvery)) @@ -207,6 +217,8 @@ func TestIAVLIterator(t *testing.T) { } func TestIAVLReverseIterator(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() tree := iavl.NewMutableTree(db, cacheSize) iavlStore := UnsafeNewStore(tree, storeOptions(numRecent, storeEvery)) @@ -240,6 +252,8 @@ func TestIAVLReverseIterator(t *testing.T) { } func TestIAVLPrefixIterator(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() tree := iavl.NewMutableTree(db, cacheSize) iavlStore := UnsafeNewStore(tree, storeOptions(numRecent, storeEvery)) @@ -302,6 +316,8 @@ func TestIAVLPrefixIterator(t *testing.T) { } func TestIAVLReversePrefixIterator(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() tree := iavl.NewMutableTree(db, cacheSize) iavlStore := UnsafeNewStore(tree, storeOptions(numRecent, storeEvery)) @@ -368,6 +384,8 @@ func nextVersion(iavl *Store) { } func TestIAVLDefaultPruning(t *testing.T) { + t.Parallel() + // Expected stored / deleted version numbers for: // numRecent = 5, storeEvery = 3 states := []pruneState{ @@ -392,6 +410,8 @@ func TestIAVLDefaultPruning(t *testing.T) { } func TestIAVLAlternativePruning(t *testing.T) { + t.Parallel() + // Expected stored / deleted version numbers for: // numRecent = 3, storeEvery = 5 states := []pruneState{ @@ -442,6 +462,8 @@ func testPruning(t *testing.T, numRecent int64, storeEvery int64, states []prune } func TestIAVLNoPrune(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() tree := iavl.NewMutableTree(db, cacheSize) iavlStore := UnsafeNewStore(tree, storeOptions(numRecent, int64(1))) @@ -457,6 +479,8 @@ func TestIAVLNoPrune(t *testing.T) { } func TestIAVLPruneEverything(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() tree := iavl.NewMutableTree(db, cacheSize) iavlStore := UnsafeNewStore(tree, storeOptions(int64(0), int64(0))) @@ -475,6 +499,8 @@ func TestIAVLPruneEverything(t *testing.T) { } func TestIAVLStoreQuery(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() tree := iavl.NewMutableTree(db, cacheSize) iavlStore := UnsafeNewStore(tree, storeOptions(numRecent, storeEvery)) diff --git a/tm2/pkg/store/prefix/store_test.go b/tm2/pkg/store/prefix/store_test.go index 70f0eae05c8..6f70c5bd16f 100644 --- a/tm2/pkg/store/prefix/store_test.go +++ b/tm2/pkg/store/prefix/store_test.go @@ -88,6 +88,8 @@ func testPrefixStore(t *testing.T, baseStore types.Store, prefix []byte) { } func TestIAVLStorePrefix(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() tree := tiavl.NewMutableTree(db, cacheSize) iavlStore := iavl.UnsafeNewStore(tree, types.StoreOptions{ @@ -101,6 +103,8 @@ func TestIAVLStorePrefix(t *testing.T) { } func TestPrefixStoreNoNilSet(t *testing.T) { + t.Parallel() + meter := types.NewGasMeter(100000000) mem := dbadapter.Store{dbm.NewMemDB()} gasStore := gas.New(mem, meter, types.DefaultGasConfig()) @@ -108,6 +112,8 @@ func TestPrefixStoreNoNilSet(t *testing.T) { } func TestPrefixStoreIterate(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() baseStore := dbadapter.Store{db} prefix := []byte("test") @@ -135,6 +141,8 @@ func incFirstByte(bz []byte) { } func TestCloneAppend(t *testing.T) { + t.Parallel() + kvps := genRandomKVPairs() for _, kvp := range kvps { bz := cloneAppend(kvp.key, kvp.value) @@ -154,6 +162,8 @@ func TestCloneAppend(t *testing.T) { } func TestPrefixStoreIteratorEdgeCase(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() baseStore := dbadapter.Store{db} @@ -184,6 +194,8 @@ func TestPrefixStoreIteratorEdgeCase(t *testing.T) { } func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() baseStore := dbadapter.Store{db} @@ -323,6 +335,8 @@ func checkNextPanics(t *testing.T, itr types.Iterator) { } func TestPrefixDBSimple(t *testing.T) { + t.Parallel() + store := mockStoreWithStuff() pstore := New(store, bz("key")) @@ -341,6 +355,8 @@ func TestPrefixDBSimple(t *testing.T) { } func TestPrefixDBIterator1(t *testing.T) { + t.Parallel() + store := mockStoreWithStuff() pstore := New(store, bz("key")) @@ -359,6 +375,8 @@ func TestPrefixDBIterator1(t *testing.T) { } func TestPrefixDBIterator2(t *testing.T) { + t.Parallel() + store := mockStoreWithStuff() pstore := New(store, bz("key")) @@ -369,6 +387,8 @@ func TestPrefixDBIterator2(t *testing.T) { } func TestPrefixDBIterator3(t *testing.T) { + t.Parallel() + store := mockStoreWithStuff() pstore := New(store, bz("key")) @@ -387,6 +407,8 @@ func TestPrefixDBIterator3(t *testing.T) { } func TestPrefixDBIterator4(t *testing.T) { + t.Parallel() + store := mockStoreWithStuff() pstore := New(store, bz("key")) @@ -397,6 +419,8 @@ func TestPrefixDBIterator4(t *testing.T) { } func TestPrefixDBReverseIterator1(t *testing.T) { + t.Parallel() + store := mockStoreWithStuff() pstore := New(store, bz("key")) @@ -415,6 +439,8 @@ func TestPrefixDBReverseIterator1(t *testing.T) { } func TestPrefixDBReverseIterator2(t *testing.T) { + t.Parallel() + store := mockStoreWithStuff() pstore := New(store, bz("key")) @@ -433,6 +459,8 @@ func TestPrefixDBReverseIterator2(t *testing.T) { } func TestPrefixDBReverseIterator3(t *testing.T) { + t.Parallel() + store := mockStoreWithStuff() pstore := New(store, bz("key")) @@ -443,6 +471,8 @@ func TestPrefixDBReverseIterator3(t *testing.T) { } func TestPrefixDBReverseIterator4(t *testing.T) { + t.Parallel() + store := mockStoreWithStuff() pstore := New(store, bz("key")) diff --git a/tm2/pkg/store/rootmulti/dbadapter.go b/tm2/pkg/store/rootmulti/dbadapter.go deleted file mode 100644 index 254d139a608..00000000000 --- a/tm2/pkg/store/rootmulti/dbadapter.go +++ /dev/null @@ -1,33 +0,0 @@ -package rootmulti - -import ( - "github.com/gnolang/gno/tm2/pkg/store/dbadapter" - "github.com/gnolang/gno/tm2/pkg/store/types" -) - -var commithash = []byte("FAKE_HASH") - -//---------------------------------------- -// commitDBStoreWrapper should only be used for simulation/debugging, -// as it doesn't compute any commit hash, and it cannot load older state. - -// Wrapper type for dbm.Db with implementation of KVStore -type commitDBStoreAdapter struct { - dbadapter.Store -} - -func (cdsa commitDBStoreAdapter) Commit() types.CommitID { - return types.CommitID{ - Version: -1, - Hash: commithash, - } -} - -func (cdsa commitDBStoreAdapter) LastCommitID() types.CommitID { - return types.CommitID{ - Version: -1, - Hash: commithash, - } -} - -func (cdsa commitDBStoreAdapter) SetPruning(_ types.PruningOptions) {} diff --git a/tm2/pkg/store/rootmulti/proof_test.go b/tm2/pkg/store/rootmulti/proof_test.go index 565ea59face..c79cbb07bd5 100644 --- a/tm2/pkg/store/rootmulti/proof_test.go +++ b/tm2/pkg/store/rootmulti/proof_test.go @@ -13,6 +13,8 @@ import ( ) func TestVerifyIAVLStoreQueryProof(t *testing.T) { + t.Parallel() + // Create main tree for testing. db := dbm.NewMemDB() opts := types.StoreOptions{ @@ -58,6 +60,8 @@ func TestVerifyIAVLStoreQueryProof(t *testing.T) { } func TestVerifyMultiStoreQueryProof(t *testing.T) { + t.Parallel() + // Create main tree for testing. db := dbm.NewMemDB() store := NewMultiStore(db) @@ -113,6 +117,8 @@ func TestVerifyMultiStoreQueryProof(t *testing.T) { } func TestVerifyMultiStoreQueryProofEmptyStore(t *testing.T) { + t.Parallel() + // Create main tree for testing. db := dbm.NewMemDB() store := NewMultiStore(db) @@ -142,6 +148,8 @@ func TestVerifyMultiStoreQueryProofEmptyStore(t *testing.T) { } func TestVerifyMultiStoreQueryProofAbsence(t *testing.T) { + t.Parallel() + // Create main tree for testing. db := dbm.NewMemDB() store := NewMultiStore(db) diff --git a/tm2/pkg/store/rootmulti/store_test.go b/tm2/pkg/store/rootmulti/store_test.go index e660f80c6bb..e6a04ee5ded 100644 --- a/tm2/pkg/store/rootmulti/store_test.go +++ b/tm2/pkg/store/rootmulti/store_test.go @@ -15,6 +15,8 @@ import ( ) func TestStoreType(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() store := NewMultiStore(db) store.MountStoreWithDB( @@ -22,6 +24,8 @@ func TestStoreType(t *testing.T) { } func TestStoreMount(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() store := NewMultiStore(db) @@ -37,6 +41,8 @@ func TestStoreMount(t *testing.T) { } func TestCacheMultiStoreWithVersion(t *testing.T) { + t.Parallel() + var db dbm.DB = dbm.NewMemDB() ms := newMultiStoreWithMounts(db) err := ms.LoadLatestVersion() @@ -74,6 +80,8 @@ func TestCacheMultiStoreWithVersion(t *testing.T) { } func TestHashStableWithEmptyCommit(t *testing.T) { + t.Parallel() + var db dbm.DB = dbm.NewMemDB() ms := newMultiStoreWithMounts(db) err := ms.LoadLatestVersion() @@ -98,6 +106,8 @@ func TestHashStableWithEmptyCommit(t *testing.T) { } func TestMultistoreCommitLoad(t *testing.T) { + t.Parallel() + var db dbm.DB = dbm.NewMemDB() store := newMultiStoreWithMounts(db) err := store.LoadLatestVersion() @@ -158,6 +168,8 @@ func TestMultistoreCommitLoad(t *testing.T) { } func TestParsePath(t *testing.T) { + t.Parallel() + _, _, err := parsePath("foo") require.Error(t, err) @@ -178,6 +190,8 @@ func TestParsePath(t *testing.T) { } func TestMultiStoreQuery(t *testing.T) { + t.Parallel() + db := dbm.NewMemDB() multi := newMultiStoreWithMounts(db) err := multi.LoadLatestVersion() diff --git a/tm2/pkg/store/types/gas_test.go b/tm2/pkg/store/types/gas_test.go index 7fef09227c5..410ba0b7e92 100644 --- a/tm2/pkg/store/types/gas_test.go +++ b/tm2/pkg/store/types/gas_test.go @@ -9,6 +9,8 @@ import ( ) func TestGasMeter(t *testing.T) { + t.Parallel() + cases := []struct { limit Gas usage []Gas @@ -46,6 +48,8 @@ func TestGasMeter(t *testing.T) { } func TestAddUint64Overflow(t *testing.T) { + t.Parallel() + testCases := []struct { a, b int64 result int64 diff --git a/tm2/pkg/strings/string_test.go b/tm2/pkg/strings/string_test.go index 1ec7b0d56be..55deac00b1f 100644 --- a/tm2/pkg/strings/string_test.go +++ b/tm2/pkg/strings/string_test.go @@ -9,6 +9,8 @@ import ( ) func TestStringInSlice(t *testing.T) { + t.Parallel() + assert.True(t, StringInSlice("a", []string{"a", "b", "c"})) assert.False(t, StringInSlice("d", []string{"a", "b", "c"})) assert.True(t, StringInSlice("", []string{""})) @@ -16,6 +18,8 @@ func TestStringInSlice(t *testing.T) { } func TestIsASCIIText(t *testing.T) { + t.Parallel() + notASCIIText := []string{ "", "\xC2", "\xC2\xA2", "\xFF", "\x80", "\xF0", "\n", "\t", } @@ -31,6 +35,8 @@ func TestIsASCIIText(t *testing.T) { } func TestASCIITrim(t *testing.T) { + t.Parallel() + assert.Equal(t, ASCIITrim(" "), "") assert.Equal(t, ASCIITrim(" a"), "a") assert.Equal(t, ASCIITrim("a "), "a") @@ -39,6 +45,8 @@ func TestASCIITrim(t *testing.T) { } func TestStringSliceEqual(t *testing.T) { + t.Parallel() + tests := []struct { a []string b []string diff --git a/tm2/pkg/timer/throttle_timer_test.go b/tm2/pkg/timer/throttle_timer_test.go index 2bee1dc0125..fb82fe39ff6 100644 --- a/tm2/pkg/timer/throttle_timer_test.go +++ b/tm2/pkg/timer/throttle_timer_test.go @@ -36,6 +36,8 @@ func (c *thCounter) Read() { } func TestThrottle(test *testing.T) { + test.Parallel() + assert := asrt.New(test) ms := 100