diff --git a/.github/workflows/lint-go.yml b/.github/workflows/lint-go.yml index c6bd3e5bb..e901160ec 100644 --- a/.github/workflows/lint-go.yml +++ b/.github/workflows/lint-go.yml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v4 with: - go-version: '1.21.4' + go-version: "1.21.4" cache: false - name: golangci-lint uses: golangci/golangci-lint-action@v3.6.0 @@ -28,7 +28,7 @@ jobs: # Require: The version of golangci-lint to use. # When `install-mode` is `binary` (default) the value can be v1.2 or v1.2.3 or `latest` to use the latest version. # When `install-mode` is `goinstall` the value can be v1.2.3, `latest`, or the hash of a commit. - version: v1.56.2 + version: v1.62.2 # Optional: working directory, useful for monorepos # working-directory: somedir diff --git a/.golangci.yml b/.golangci.yml index 3af894222..fd168cf9a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,10 +1,43 @@ +run: + tests: true + linters: # Enable specific linter # https://golangci-lint.run/usage/linters/#enabled-by-default enable: - gofumpt - - goimports + - gci + - testifylint + - errcheck + - thelper linters-settings: - goimports: - local-prefixes: github.com/CosmWasm/wasmvm + gci: + # Section configuration to compare against. + # Section names are case-insensitive and may contain parameters in (). + # The default order of sections is `standard > default > custom > blank > dot > alias > localmodule`, + # If `custom-order` is `true`, it follows the order of `sections` option. + # Default: ["standard", "default"] + sections: + - standard # Standard section: captures all standard packages. + - default # Default section: contains all imports that could not be matched to another section type. + - prefix(github.com/cosmos/cosmos-sdk) # Custom section: groups all imports with the specified Prefix. + - prefix(github.com/cosmos/ibc-go) + - blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled. + - dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled. + - alias # Alias section: contains all alias imports. This section is not present unless explicitly enabled. + - localmodule # Local module section: contains all local packages. This section is not present unless explicitly enabled. + # Skip generated files. + # Default: true + skip-generated: false + # Enable custom order of sections. + # If `true`, make the section order the same as the order of `sections`. + # Default: false + custom-order: true + # Drops lexical ordering for custom sections. + # Default: false + no-lex-order: true + +issues: + max-issues-per-linter: 0 + max-same-issues: 0 diff --git a/ibc_test.go b/ibc_test.go index 2da754d14..4992ee50b 100644 --- a/ibc_test.go +++ b/ibc_test.go @@ -76,6 +76,7 @@ type AcknowledgeDispatch struct { } func toBytes(t *testing.T, v interface{}) []byte { + t.Helper() bz, err := json.Marshal(v) require.NoError(t, err) return bz @@ -109,7 +110,7 @@ func TestIBCHandshake(t *testing.T) { require.NoError(t, err) assert.NotNil(t, i.Ok) iResponse := i.Ok - require.Equal(t, 0, len(iResponse.Messages)) + require.Empty(t, iResponse.Messages) // channel open gasMeter2 := api.NewMockGasMeter(TESTING_GAS_LIMIT) @@ -132,7 +133,7 @@ func TestIBCHandshake(t *testing.T) { require.NoError(t, err) require.NotNil(t, conn.Ok) connResponse := conn.Ok - require.Equal(t, 1, len(connResponse.Messages)) + require.Len(t, connResponse.Messages, 1) // check for the expected custom event expected_events := []types.Event{{ @@ -200,7 +201,7 @@ func TestIBCPacketDispatch(t *testing.T) { require.NoError(t, err) require.NotNil(t, conn.Ok) connResponse := conn.Ok - require.Equal(t, 1, len(connResponse.Messages)) + require.Len(t, connResponse.Messages, 1) id := connResponse.Messages[0].ID // mock reflect init callback (to store address) @@ -237,7 +238,7 @@ func TestIBCPacketDispatch(t *testing.T) { var accounts ListAccountsResponse err = json.Unmarshal(qResponse, &accounts) require.NoError(t, err) - require.Equal(t, 1, len(accounts.Accounts)) + require.Len(t, accounts.Accounts, 1) require.Equal(t, CHANNEL_ID, accounts.Accounts[0].ChannelID) require.Equal(t, REFLECT_ADDR, accounts.Accounts[0].Account) @@ -332,7 +333,7 @@ func TestIBCMsgGetChannel(t *testing.T) { require.Equal(t, msg1.GetChannel(), msg4.GetChannel()) require.Equal(t, msg1.GetChannel(), msg5.GetChannel()) require.Equal(t, msg1.GetChannel(), msg6.GetChannel()) - require.Equal(t, msg1.GetChannel().Endpoint.ChannelID, CHANNEL_ID) + require.Equal(t, CHANNEL_ID, msg1.GetChannel().Endpoint.ChannelID) } func TestIBCMsgGetCounterVersion(t *testing.T) { diff --git a/internal/api/iterator_test.go b/internal/api/iterator_test.go index 0c81db775..a543124cd 100644 --- a/internal/api/iterator_test.go +++ b/internal/api/iterator_test.go @@ -6,7 +6,6 @@ import ( "sync" "testing" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/CosmWasm/wasmvm/v2/internal/api/testdb" @@ -25,6 +24,7 @@ func (q queueData) Store(meter MockGasMeter) types.KVStore { } func setupQueueContractWithData(t *testing.T, cache Cache, values ...int) queueData { + t.Helper() checksum := createQueueContract(t, cache) gasMeter1 := NewMockGasMeter(TESTING_GAS_LIMIT) @@ -59,6 +59,7 @@ func setupQueueContractWithData(t *testing.T, cache Cache, values ...int) queueD } func setupQueueContract(t *testing.T, cache Cache) queueData { + t.Helper() return setupQueueContractWithData(t, cache, 17, 22) } @@ -202,14 +203,14 @@ func TestQueueIteratorSimple(t *testing.T) { err = json.Unmarshal(data, &reduced) require.NoError(t, err) require.Equal(t, "", reduced.Err) - require.Equal(t, `{"counters":[[17,22],[22,0]]}`, string(reduced.Ok)) + require.JSONEq(t, `{"counters":[[17,22],[22,0]]}`, string(reduced.Ok)) } func TestQueueIteratorRaces(t *testing.T) { cache, cleanup := withCache(t) defer cleanup() - assert.Equal(t, 0, len(iteratorFrames)) + require.Empty(t, iteratorFrames) contract1 := setupQueueContractWithData(t, cache, 17, 22) contract2 := setupQueueContractWithData(t, cache, 1, 19, 6, 35, 8) @@ -217,6 +218,7 @@ func TestQueueIteratorRaces(t *testing.T) { env := MockEnvBin(t) reduceQuery := func(t *testing.T, setup queueData, expected string) { + t.Helper() checksum, querier, api := setup.checksum, setup.querier, setup.api gasMeter := NewMockGasMeter(TESTING_GAS_LIMIT) igasMeter := types.GasMeter(gasMeter) @@ -256,7 +258,7 @@ func TestQueueIteratorRaces(t *testing.T) { wg.Wait() // when they finish, we should have removed all frames - assert.Equal(t, 0, len(iteratorFrames)) + require.Empty(t, iteratorFrames) } func TestQueueIteratorLimit(t *testing.T) { diff --git a/internal/api/lib_test.go b/internal/api/lib_test.go index 90c55a8c2..e9809bde5 100644 --- a/internal/api/lib_test.go +++ b/internal/api/lib_test.go @@ -26,6 +26,9 @@ const ( TESTING_CACHE_SIZE = 100 // MiB ) +// Add mutex for thread safety +var testMutex sync.Mutex + var TESTING_CAPABILITIES = []string{"staking", "stargate", "iterator", "cosmwasm_1_1", "cosmwasm_1_2", "cosmwasm_1_3"} func TestInitAndReleaseCache(t *testing.T) { @@ -191,9 +194,10 @@ func TestInitCacheEmptyCapabilities(t *testing.T) { ReleaseCache(cache) } -func withCache(t testing.TB) (Cache, func()) { +func withCache(tb testing.TB) (Cache, func()) { + tb.Helper() tmpdir, err := os.MkdirTemp("", "wasmvm-testing") - require.NoError(t, err) + require.NoError(tb, err) config := types.VMConfig{ Cache: types.CacheOptions{ BaseDir: tmpdir, @@ -203,7 +207,7 @@ func withCache(t testing.TB) (Cache, func()) { }, } cache, err := InitCache(config) - require.NoError(t, err) + require.NoError(tb, err) cleanup := func() { os.RemoveAll(tmpdir) @@ -363,7 +367,7 @@ func TestGetMetrics(t *testing.T) { // GetMetrics 1 metrics, err := GetMetrics(cache) require.NoError(t, err) - assert.Equal(t, &types.Metrics{}, metrics) + require.Equal(t, &types.Metrics{}, metrics) // Store contract wasm, err := os.ReadFile("../../testdata/hackatom.wasm") @@ -374,7 +378,7 @@ func TestGetMetrics(t *testing.T) { // GetMetrics 2 metrics, err = GetMetrics(cache) require.NoError(t, err) - assert.Equal(t, &types.Metrics{}, metrics) + require.Equal(t, &types.Metrics{}, metrics) // Instantiate 1 gasMeter := NewMockGasMeter(TESTING_GAS_LIMIT) @@ -390,7 +394,7 @@ func TestGetMetrics(t *testing.T) { // GetMetrics 3 metrics, err = GetMetrics(cache) - assert.NoError(t, err) + require.NoError(t, err) require.Equal(t, uint32(0), metrics.HitsMemoryCache) require.Equal(t, uint32(1), metrics.HitsFsCache) require.Equal(t, uint64(1), metrics.ElementsMemoryCache) @@ -403,7 +407,7 @@ func TestGetMetrics(t *testing.T) { // GetMetrics 4 metrics, err = GetMetrics(cache) - assert.NoError(t, err) + require.NoError(t, err) require.Equal(t, uint32(1), metrics.HitsMemoryCache) require.Equal(t, uint32(1), metrics.HitsFsCache) require.Equal(t, uint64(1), metrics.ElementsMemoryCache) @@ -415,7 +419,7 @@ func TestGetMetrics(t *testing.T) { // GetMetrics 5 metrics, err = GetMetrics(cache) - assert.NoError(t, err) + require.NoError(t, err) require.Equal(t, uint32(1), metrics.HitsMemoryCache) require.Equal(t, uint32(2), metrics.HitsFsCache) require.Equal(t, uint64(1), metrics.ElementsPinnedMemoryCache) @@ -430,7 +434,7 @@ func TestGetMetrics(t *testing.T) { // GetMetrics 6 metrics, err = GetMetrics(cache) - assert.NoError(t, err) + require.NoError(t, err) require.Equal(t, uint32(1), metrics.HitsPinnedMemoryCache) require.Equal(t, uint32(1), metrics.HitsMemoryCache) require.Equal(t, uint32(2), metrics.HitsFsCache) @@ -445,7 +449,7 @@ func TestGetMetrics(t *testing.T) { // GetMetrics 7 metrics, err = GetMetrics(cache) - assert.NoError(t, err) + require.NoError(t, err) require.Equal(t, uint32(1), metrics.HitsPinnedMemoryCache) require.Equal(t, uint32(1), metrics.HitsMemoryCache) require.Equal(t, uint32(2), metrics.HitsFsCache) @@ -461,7 +465,7 @@ func TestGetMetrics(t *testing.T) { // GetMetrics 8 metrics, err = GetMetrics(cache) - assert.NoError(t, err) + require.NoError(t, err) require.Equal(t, uint32(1), metrics.HitsPinnedMemoryCache) require.Equal(t, uint32(2), metrics.HitsMemoryCache) require.Equal(t, uint32(2), metrics.HitsFsCache) @@ -478,7 +482,7 @@ func TestGetPinnedMetrics(t *testing.T) { // GetMetrics 1 metrics, err := GetPinnedMetrics(cache) require.NoError(t, err) - assert.Equal(t, &types.PinnedMetrics{PerModule: make([]types.PerModuleEntry, 0)}, metrics) + require.Equal(t, &types.PinnedMetrics{PerModule: make([]types.PerModuleEntry, 0)}, metrics) // Store contract 1 wasm, err := os.ReadFile("../../testdata/hackatom.wasm") @@ -514,15 +518,15 @@ func TestGetPinnedMetrics(t *testing.T) { // GetMetrics 2 metrics, err = GetPinnedMetrics(cache) require.NoError(t, err) - assert.Equal(t, 2, len(metrics.PerModule)) + require.Len(t, metrics.PerModule, 2) hackatomMetrics := findMetrics(metrics.PerModule, checksum) cyberpunkMetrics := findMetrics(metrics.PerModule, cyberpunkChecksum) - assert.Equal(t, uint32(0), hackatomMetrics.Hits) - assert.NotEqual(t, uint32(0), hackatomMetrics.Size) - assert.Equal(t, uint32(0), cyberpunkMetrics.Hits) - assert.NotEqual(t, uint32(0), cyberpunkMetrics.Size) + require.Equal(t, uint32(0), hackatomMetrics.Hits) + require.NotEqual(t, uint32(0), hackatomMetrics.Size) + require.Equal(t, uint32(0), cyberpunkMetrics.Hits) + require.NotEqual(t, uint32(0), cyberpunkMetrics.Size) // Instantiate 1 gasMeter := NewMockGasMeter(TESTING_GAS_LIMIT) @@ -539,15 +543,15 @@ func TestGetPinnedMetrics(t *testing.T) { // GetMetrics 3 metrics, err = GetPinnedMetrics(cache) require.NoError(t, err) - assert.Equal(t, 2, len(metrics.PerModule)) + require.Len(t, metrics.PerModule, 2) hackatomMetrics = findMetrics(metrics.PerModule, checksum) cyberpunkMetrics = findMetrics(metrics.PerModule, cyberpunkChecksum) - assert.Equal(t, uint32(1), hackatomMetrics.Hits) - assert.NotEqual(t, uint32(0), hackatomMetrics.Size) - assert.Equal(t, uint32(0), cyberpunkMetrics.Hits) - assert.NotEqual(t, uint32(0), cyberpunkMetrics.Size) + require.Equal(t, uint32(1), hackatomMetrics.Hits) + require.NotEqual(t, uint32(0), hackatomMetrics.Size) + require.Equal(t, uint32(0), cyberpunkMetrics.Hits) + require.NotEqual(t, uint32(0), cyberpunkMetrics.Size) } func TestInstantiate(t *testing.T) { @@ -573,13 +577,13 @@ func TestInstantiate(t *testing.T) { res, cost, err := Instantiate(cache, checksum, env, info, msg, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) require.NoError(t, err) requireOkResponse(t, res, 0) - assert.Equal(t, uint64(0xb1fe27), cost.UsedInternally) + require.Equal(t, uint64(0xb1fe27), cost.UsedInternally) var result types.ContractResult err = json.Unmarshal(res, &result) require.NoError(t, err) require.Equal(t, "", result.Err) - require.Equal(t, 0, len(result.Ok.Messages)) + require.Empty(t, result.Ok.Messages) } func TestExecute(t *testing.T) { @@ -604,7 +608,7 @@ func TestExecute(t *testing.T) { diff := time.Since(start) require.NoError(t, err) requireOkResponse(t, res, 0) - assert.Equal(t, uint64(0xb1fe27), cost.UsedInternally) + require.Equal(t, uint64(0xb1fe27), cost.UsedInternally) t.Logf("Time (%d gas): %s\n", cost.UsedInternally, diff) // execute with the same store @@ -617,7 +621,7 @@ func TestExecute(t *testing.T) { res, cost, err = Execute(cache, checksum, env, info, []byte(`{"release":{}}`), &igasMeter2, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) diff = time.Since(start) require.NoError(t, err) - assert.Equal(t, uint64(0x1416da5), cost.UsedInternally) + require.Equal(t, uint64(0x1416da5), cost.UsedInternally) t.Logf("Time (%d gas): %s\n", cost.UsedInternally, diff) // make sure it read the balance properly and we got 250 atoms @@ -625,25 +629,24 @@ func TestExecute(t *testing.T) { err = json.Unmarshal(res, &result) require.NoError(t, err) require.Equal(t, "", result.Err) - require.Equal(t, 1, len(result.Ok.Messages)) - + require.Len(t, result.Ok.Messages, 1) // Ensure we got our custom event - assert.Equal(t, len(result.Ok.Events), 1) + require.Len(t, result.Ok.Events, 1) ev := result.Ok.Events[0] - assert.Equal(t, ev.Type, "hackatom") - assert.Equal(t, len(ev.Attributes), 1) - assert.Equal(t, ev.Attributes[0].Key, "action") - assert.Equal(t, ev.Attributes[0].Value, "release") + require.Equal(t, "hackatom", ev.Type) + require.Len(t, ev.Attributes, 1) + require.Equal(t, "action", ev.Attributes[0].Key) + require.Equal(t, "release", ev.Attributes[0].Value) dispatch := result.Ok.Messages[0].Msg require.NotNil(t, dispatch.Bank, "%#v", dispatch) require.NotNil(t, dispatch.Bank.Send, "%#v", dispatch) send := dispatch.Bank.Send - assert.Equal(t, "bob", send.ToAddress) - assert.Equal(t, balance, send.Amount) + require.Equal(t, "bob", send.ToAddress) + require.Equal(t, balance, send.Amount) // check the data is properly formatted expectedData := []byte{0xF0, 0x0B, 0xAA} - assert.Equal(t, expectedData, result.Ok.Data) + require.Equal(t, expectedData, result.Ok.Data) } func TestExecutePanic(t *testing.T) { @@ -725,7 +728,7 @@ func TestExecuteCpuLoop(t *testing.T) { diff := time.Since(start) require.NoError(t, err) requireOkResponse(t, res, 0) - assert.Equal(t, uint64(0x79f527), cost.UsedInternally) + require.Equal(t, uint64(0x79f527), cost.UsedInternally) t.Logf("Time (%d gas): %s\n", cost.UsedInternally, diff) // execute a cpu loop @@ -738,7 +741,7 @@ func TestExecuteCpuLoop(t *testing.T) { _, cost, err = Execute(cache, checksum, env, info, []byte(`{"cpu_loop":{}}`), &igasMeter2, store, api, &querier, maxGas, TESTING_PRINT_DEBUG) diff = time.Since(start) require.Error(t, err) - assert.Equal(t, cost.UsedInternally, maxGas) + require.Equal(t, cost.UsedInternally, maxGas) t.Logf("CPULoop Time (%d gas): %s\n", cost.UsedInternally, diff) } @@ -807,7 +810,9 @@ func BenchmarkContractCall(b *testing.B) { gasMeter2 := NewMockGasMeter(TESTING_GAS_LIMIT) igasMeter2 := types.GasMeter(gasMeter2) store.SetGasMeter(gasMeter2) + testMutex.Lock() info = MockInfoBin(b, "fred") + testMutex.Unlock() msg := []byte(`{"allocate_large_memory":{"pages":0}}`) // replace with noop once we have it res, _, err = Execute(cache, checksum, env, info, msg, &igasMeter2, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) require.NoError(b, err) @@ -841,22 +846,31 @@ func Benchmark100ConcurrentContractCalls(b *testing.B) { b.ResetTimer() for n := 0; n < b.N; n++ { var wg sync.WaitGroup + errChan := make(chan error, callCount) + resChan := make(chan []byte, callCount) wg.Add(callCount) + info = mockInfoBinNoAssert("fred") for i := 0; i < callCount; i++ { go func() { + defer wg.Done() gasMeter2 := NewMockGasMeter(TESTING_GAS_LIMIT) igasMeter2 := types.GasMeter(gasMeter2) store.SetGasMeter(gasMeter2) - info = MockInfoBin(b, "fred") msg := []byte(`{"allocate_large_memory":{"pages":0}}`) // replace with noop once we have it res, _, err = Execute(cache, checksum, env, info, msg, &igasMeter2, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) - require.NoError(b, err) - requireOkResponse(b, res, 0) - - wg.Done() + errChan <- err + resChan <- res }() } wg.Wait() + close(errChan) + close(resChan) + + // Now check results in the main test goroutine + for i := 0; i < callCount; i++ { + require.NoError(b, <-errChan) + requireOkResponse(b, <-resChan, 0) + } } } @@ -919,7 +933,7 @@ func TestMigrate(t *testing.T) { err = json.Unmarshal(data, &qResult) require.NoError(t, err) require.Equal(t, "", qResult.Err) - require.Equal(t, string(qResult.Ok), `{"verifier":"fred"}`) + require.JSONEq(t, `{"verifier":"fred"}`, string(qResult.Ok)) // migrate to a new verifier - alice // we use the same code blob as we are testing hackatom self-migration @@ -933,7 +947,7 @@ func TestMigrate(t *testing.T) { err = json.Unmarshal(data, &qResult2) require.NoError(t, err) require.Equal(t, "", qResult2.Err) - require.Equal(t, `{"verifier":"alice"}`, string(qResult2.Ok)) + require.JSONEq(t, `{"verifier":"alice"}`, string(qResult2.Ok)) } func TestMultipleInstances(t *testing.T) { @@ -974,18 +988,18 @@ func TestMultipleInstances(t *testing.T) { // succeed to execute store1 with fred resp = exec(t, cache, checksum, "fred", store1, api, querier, 0x140e8ad) require.Equal(t, "", resp.Err) - require.Equal(t, 1, len(resp.Ok.Messages)) + require.Len(t, resp.Ok.Messages, 1) attributes := resp.Ok.Attributes - require.Equal(t, 2, len(attributes)) + require.Len(t, attributes, 2) require.Equal(t, "destination", attributes[1].Key) require.Equal(t, "bob", attributes[1].Value) // succeed to execute store2 with mary resp = exec(t, cache, checksum, "mary", store2, api, querier, 0x1412b29) require.Equal(t, "", resp.Err) - require.Equal(t, 1, len(resp.Ok.Messages)) + require.Len(t, resp.Ok.Messages, 1) attributes = resp.Ok.Attributes - require.Equal(t, 2, len(attributes)) + require.Len(t, attributes, 2) require.Equal(t, "destination", attributes[1].Key) require.Equal(t, "sue", attributes[1].Value) } @@ -1024,7 +1038,7 @@ func TestSudo(t *testing.T) { err = json.Unmarshal(res, &result) require.NoError(t, err) require.Equal(t, "", result.Err) - require.Equal(t, 1, len(result.Ok.Messages)) + require.Len(t, result.Ok.Messages, 1) dispatch := result.Ok.Messages[0].Msg require.NotNil(t, dispatch.Bank, "%#v", dispatch) require.NotNil(t, dispatch.Bank.Send, "%#v", dispatch) @@ -1079,7 +1093,7 @@ func TestDispatchSubmessage(t *testing.T) { err = json.Unmarshal(res, &result) require.NoError(t, err) require.Equal(t, "", result.Err) - require.Equal(t, 1, len(result.Ok.Messages)) + require.Len(t, result.Ok.Messages, 1) dispatch := result.Ok.Messages[0] assert.Equal(t, id, dispatch.ID) assert.Equal(t, payload.Msg, dispatch.Msg) @@ -1156,15 +1170,17 @@ func TestReplyAndQuery(t *testing.T) { require.Equal(t, events, val.Events) } -func requireOkResponse(t testing.TB, res []byte, expectedMsgs int) { +func requireOkResponse(tb testing.TB, res []byte, expectedMsgs int) { + tb.Helper() var result types.ContractResult err := json.Unmarshal(res, &result) - require.NoError(t, err) - require.Equal(t, "", result.Err) - require.Equal(t, expectedMsgs, len(result.Ok.Messages)) + require.NoError(tb, err) + require.Equal(tb, "", result.Err) + require.Len(tb, result.Ok.Messages, expectedMsgs) } func requireQueryError(t *testing.T, res []byte) { + t.Helper() var result types.QueryResult err := json.Unmarshal(res, &result) require.NoError(t, err) @@ -1173,6 +1189,7 @@ func requireQueryError(t *testing.T, res []byte) { } func requireQueryOk(t *testing.T, res []byte) []byte { + t.Helper() var result types.QueryResult err := json.Unmarshal(res, &result) require.NoError(t, err) @@ -1181,36 +1198,43 @@ func requireQueryOk(t *testing.T, res []byte) []byte { return result.Ok } -func createHackatomContract(t testing.TB, cache Cache) []byte { - return createContract(t, cache, "../../testdata/hackatom.wasm") +func createHackatomContract(tb testing.TB, cache Cache) []byte { + tb.Helper() + return createContract(tb, cache, "../../testdata/hackatom.wasm") } -func createCyberpunkContract(t testing.TB, cache Cache) []byte { - return createContract(t, cache, "../../testdata/cyberpunk.wasm") +func createCyberpunkContract(tb testing.TB, cache Cache) []byte { + tb.Helper() + return createContract(tb, cache, "../../testdata/cyberpunk.wasm") } -func createQueueContract(t testing.TB, cache Cache) []byte { - return createContract(t, cache, "../../testdata/queue.wasm") +func createQueueContract(tb testing.TB, cache Cache) []byte { + tb.Helper() + return createContract(tb, cache, "../../testdata/queue.wasm") } -func createReflectContract(t testing.TB, cache Cache) []byte { - return createContract(t, cache, "../../testdata/reflect.wasm") +func createReflectContract(tb testing.TB, cache Cache) []byte { + tb.Helper() + return createContract(tb, cache, "../../testdata/reflect.wasm") } -func createFloaty2(t testing.TB, cache Cache) []byte { - return createContract(t, cache, "../../testdata/floaty_2.0.wasm") +func createFloaty2(tb testing.TB, cache Cache) []byte { + tb.Helper() + return createContract(tb, cache, "../../testdata/floaty_2.0.wasm") } -func createContract(t testing.TB, cache Cache, wasmFile string) []byte { +func createContract(tb testing.TB, cache Cache, wasmFile string) []byte { + tb.Helper() wasm, err := os.ReadFile(wasmFile) - require.NoError(t, err) + require.NoError(tb, err) checksum, err := StoreCode(cache, wasm, true) - require.NoError(t, err) + require.NoError(tb, err) return checksum } // exec runs the handle tx with the given signer func exec(t *testing.T, cache Cache, checksum []byte, signer types.HumanAddress, store types.KVStore, api *types.GoAPI, querier Querier, gasExpected uint64) types.ContractResult { + t.Helper() gasMeter := NewMockGasMeter(TESTING_GAS_LIMIT) igasMeter := types.GasMeter(gasMeter) env := MockEnvBin(t) @@ -1265,7 +1289,7 @@ func TestQuery(t *testing.T) { err = json.Unmarshal(data, &qResult) require.NoError(t, err) require.Equal(t, "", qResult.Err) - require.Equal(t, string(qResult.Ok), `{"verifier":"fred"}`) + require.JSONEq(t, `{"verifier":"fred"}`, string(qResult.Ok)) } func TestHackatomQuerier(t *testing.T) { @@ -1308,10 +1332,6 @@ func TestCustomReflectQuerier(t *testing.T) { // https://github.com/CosmWasm/cosmwasm/blob/v0.11.0-alpha3/contracts/reflect/src/msg.rs#L18-L28 } - type CapitalizedResponse struct { - Text string `json:"text"` - } - cache, cleanup := withCache(t) defer cleanup() checksum := createReflectContract(t, cache) @@ -1350,6 +1370,10 @@ func TestCustomReflectQuerier(t *testing.T) { require.Equal(t, "SMALL FRYS :)", response.Text) } +type CapitalizedResponse struct { + Text string `json:"text"` +} + // TestFloats is a port of the float_instrs_are_deterministic test in cosmwasm-vm func TestFloats(t *testing.T) { type Value struct { @@ -1394,12 +1418,12 @@ func TestFloats(t *testing.T) { var qResult types.QueryResult err = json.Unmarshal(data, &qResult) require.NoError(t, err) - require.Equal(t, "", qResult.Err) + require.Empty(t, qResult.Err) var instructions []string err = json.Unmarshal(qResult.Ok, &instructions) require.NoError(t, err) // little sanity check - require.Equal(t, 70, len(instructions)) + require.Len(t, instructions, 70) hasher := sha256.New() const RUNS_PER_INSTRUCTION = 150 @@ -1411,7 +1435,7 @@ func TestFloats(t *testing.T) { require.NoError(t, err) err = json.Unmarshal(data, &qResult) require.NoError(t, err) - require.Equal(t, "", qResult.Err) + require.Empty(t, qResult.Err) var args []Value err = json.Unmarshal(qResult.Ok, &args) require.NoError(t, err) @@ -1426,13 +1450,13 @@ func TestFloats(t *testing.T) { data, _, err = Query(cache, checksum, env, []byte(msg), &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) var result string if err != nil { - assert.ErrorContains(t, err, "Error calling the VM: Error executing Wasm: ") + require.Error(t, err) // remove the prefix to make the error message the same as in the cosmwasm-vm test result = strings.Replace(err.Error(), "Error calling the VM: Error executing Wasm: ", "", 1) } else { err = json.Unmarshal(data, &qResult) require.NoError(t, err) - require.Equal(t, "", qResult.Err) + require.Empty(t, qResult.Err) var response Value err = json.Unmarshal(qResult.Ok, &response) require.NoError(t, err) @@ -1446,3 +1470,16 @@ func TestFloats(t *testing.T) { hash := hasher.Sum(nil) require.Equal(t, "95f70fa6451176ab04a9594417a047a1e4d8e2ff809609b8f81099496bee2393", hex.EncodeToString(hash)) } + +// mockInfoBinNoAssert creates the message binary without using testify assertions +func mockInfoBinNoAssert(sender types.HumanAddress) []byte { + info := types.MessageInfo{ + Sender: sender, + Funds: types.Array[types.Coin]{}, + } + res, err := json.Marshal(info) + if err != nil { + panic(err) + } + return res +} diff --git a/internal/api/mocks.go b/internal/api/mocks.go index ac8500dd8..7f8547308 100644 --- a/internal/api/mocks.go +++ b/internal/api/mocks.go @@ -35,9 +35,10 @@ func MockEnv() types.Env { } } -func MockEnvBin(t testing.TB) []byte { +func MockEnvBin(tb testing.TB) []byte { + tb.Helper() bin, err := json.Marshal(MockEnv()) - require.NoError(t, err) + require.NoError(tb, err) return bin } @@ -55,9 +56,10 @@ func MockInfoWithFunds(sender types.HumanAddress) types.MessageInfo { }}) } -func MockInfoBin(t testing.TB, sender types.HumanAddress) []byte { +func MockInfoBin(tb testing.TB, sender types.HumanAddress) []byte { + tb.Helper() bin, err := json.Marshal(MockInfoWithFunds(sender)) - require.NoError(t, err) + require.NoError(tb, err) return bin } @@ -391,13 +393,13 @@ func TestMockApi(t *testing.T) { human := "foobar" canon, cost, err := MockCanonicalizeAddress(human) require.NoError(t, err) - assert.Equal(t, CanonicalLength, len(canon)) - assert.Equal(t, CostCanonical, cost) + require.Len(t, canon, CanonicalLength) + require.Equal(t, CostCanonical, cost) recover, cost, err := MockHumanizeAddress(canon) require.NoError(t, err) - assert.Equal(t, recover, human) - assert.Equal(t, CostHuman, cost) + require.Equal(t, recover, human) + require.Equal(t, CostHuman, cost) } /**** MockQuerier ****/ @@ -639,7 +641,7 @@ func TestReflectCustomQuerier(t *testing.T) { var resp CustomResponse err = json.Unmarshal(bz, &resp) require.NoError(t, err) - assert.Equal(t, resp.Msg, "PONG") + assert.Equal(t, "PONG", resp.Msg) // try capital msg2, err := json.Marshal(CustomQuery{Capitalized: &CapitalizedQuery{Text: "small."}}) @@ -649,5 +651,5 @@ func TestReflectCustomQuerier(t *testing.T) { var resp2 CustomResponse err = json.Unmarshal(bz, &resp2) require.NoError(t, err) - assert.Equal(t, resp2.Msg, "SMALL.") + assert.Equal(t, "SMALL.", resp2.Msg) } diff --git a/internal/api/version_test.go b/internal/api/version_test.go index 038b1de13..3e809b83f 100644 --- a/internal/api/version_test.go +++ b/internal/api/version_test.go @@ -1,7 +1,6 @@ package api import ( - "regexp" "testing" "github.com/stretchr/testify/require" @@ -10,5 +9,5 @@ import ( func TestLibwasmvmVersion(t *testing.T) { version, err := LibwasmvmVersion() require.NoError(t, err) - require.Regexp(t, regexp.MustCompile(`^([0-9]+)\.([0-9]+)\.([0-9]+)(-[a-z0-9.]+)?$`), version) + require.Regexp(t, `^([0-9]+)\.([0-9]+)\.([0-9]+)(-[a-z0-9.]+)?$`, version) } diff --git a/lib_libwasmvm_test.go b/lib_libwasmvm_test.go index 4c25f69a0..344ce614f 100644 --- a/lib_libwasmvm_test.go +++ b/lib_libwasmvm_test.go @@ -31,6 +31,7 @@ const ( ) func withVM(t *testing.T) *VM { + t.Helper() tmpdir, err := os.MkdirTemp("", "wasmvm-testing") require.NoError(t, err) vm, err := NewVM(tmpdir, TESTING_CAPABILITIES, TESTING_MEMORY_LIMIT, TESTING_PRINT_DEBUG, TESTING_CACHE_SIZE) @@ -44,6 +45,7 @@ func withVM(t *testing.T) *VM { } func createTestContract(t *testing.T, vm *VM, path string) Checksum { + t.Helper() wasm, err := os.ReadFile(path) require.NoError(t, err) checksum, _, err := vm.StoreCode(wasm, TESTING_GAS_LIMIT) @@ -128,10 +130,9 @@ func TestSimulateStoreCode(t *testing.T) { if spec.err != "" { assert.ErrorContains(t, err, spec.err) } else { - assert.NoError(t, err) - + require.NoError(t, err) _, err = vm.GetCode(checksum) - assert.ErrorContains(t, err, "Error opening Wasm file for reading") + require.ErrorContains(t, err, "Error opening Wasm file for reading") } }) } @@ -187,7 +188,7 @@ func TestHappyPath(t *testing.T) { require.NoError(t, err) require.NotNil(t, i.Ok) ires := i.Ok - require.Equal(t, 0, len(ires.Messages)) + require.Empty(t, ires.Messages) // execute gasMeter2 := api.NewMockGasMeter(TESTING_GAS_LIMIT) @@ -198,7 +199,7 @@ func TestHappyPath(t *testing.T) { require.NoError(t, err) require.NotNil(t, h.Ok) hres := h.Ok - require.Equal(t, 1, len(hres.Messages)) + require.Len(t, hres.Messages, 1) // make sure it read the balance properly and we got 250 atoms dispatch := hres.Messages[0].Msg @@ -231,7 +232,7 @@ func TestEnv(t *testing.T) { require.NoError(t, err) require.NotNil(t, i.Ok) ires := i.Ok - require.Equal(t, 0, len(ires.Messages)) + require.Empty(t, ires.Messages) // Execute mirror env without Transaction env = types.Env{ @@ -311,11 +312,11 @@ func TestGetMetrics(t *testing.T) { require.NoError(t, err) require.NotNil(t, i.Ok) ires := i.Ok - require.Equal(t, 0, len(ires.Messages)) + require.Empty(t, ires.Messages) // GetMetrics 3 metrics, err = vm.GetMetrics() - assert.NoError(t, err) + require.NoError(t, err) require.Equal(t, uint32(0), metrics.HitsMemoryCache) require.Equal(t, uint32(1), metrics.HitsFsCache) require.Equal(t, uint64(1), metrics.ElementsMemoryCache) @@ -328,11 +329,11 @@ func TestGetMetrics(t *testing.T) { require.NoError(t, err) require.NotNil(t, i.Ok) ires = i.Ok - require.Equal(t, 0, len(ires.Messages)) + require.Empty(t, ires.Messages) // GetMetrics 4 metrics, err = vm.GetMetrics() - assert.NoError(t, err) + require.NoError(t, err) require.Equal(t, uint32(1), metrics.HitsMemoryCache) require.Equal(t, uint32(1), metrics.HitsFsCache) require.Equal(t, uint64(1), metrics.ElementsMemoryCache) @@ -344,7 +345,7 @@ func TestGetMetrics(t *testing.T) { // GetMetrics 5 metrics, err = vm.GetMetrics() - assert.NoError(t, err) + require.NoError(t, err) require.Equal(t, uint32(1), metrics.HitsMemoryCache) require.Equal(t, uint32(2), metrics.HitsFsCache) require.Equal(t, uint64(1), metrics.ElementsPinnedMemoryCache) @@ -358,11 +359,11 @@ func TestGetMetrics(t *testing.T) { require.NoError(t, err) require.NotNil(t, i.Ok) ires = i.Ok - require.Equal(t, 0, len(ires.Messages)) + require.Empty(t, ires.Messages) // GetMetrics 6 metrics, err = vm.GetMetrics() - assert.NoError(t, err) + require.NoError(t, err) require.Equal(t, uint32(1), metrics.HitsPinnedMemoryCache) require.Equal(t, uint32(1), metrics.HitsMemoryCache) require.Equal(t, uint32(2), metrics.HitsFsCache) @@ -377,7 +378,7 @@ func TestGetMetrics(t *testing.T) { // GetMetrics 7 metrics, err = vm.GetMetrics() - assert.NoError(t, err) + require.NoError(t, err) require.Equal(t, uint32(1), metrics.HitsPinnedMemoryCache) require.Equal(t, uint32(1), metrics.HitsMemoryCache) require.Equal(t, uint32(2), metrics.HitsFsCache) @@ -392,11 +393,11 @@ func TestGetMetrics(t *testing.T) { require.NoError(t, err) require.NotNil(t, i.Ok) ires = i.Ok - require.Equal(t, 0, len(ires.Messages)) + require.Empty(t, ires.Messages) // GetMetrics 8 metrics, err = vm.GetMetrics() - assert.NoError(t, err) + require.NoError(t, err) require.Equal(t, uint32(1), metrics.HitsPinnedMemoryCache) require.Equal(t, uint32(2), metrics.HitsMemoryCache) require.Equal(t, uint32(2), metrics.HitsFsCache) diff --git a/types/env_test.go b/types/env_test.go index 4bae5038a..d4ea14ad4 100644 --- a/types/env_test.go +++ b/types/env_test.go @@ -60,7 +60,7 @@ func TestBlockInfoSerialization(t *testing.T) { } bz, err := json.Marshal(block) require.NoError(t, err) - assert.Equal(t, `{"height":123,"time":"1578939743987654321","chain_id":"foobar"}`, string(bz)) + assert.JSONEq(t, `{"height":123,"time":"1578939743987654321","chain_id":"foobar"}`, string(bz)) block = BlockInfo{ Height: 0, @@ -69,7 +69,7 @@ func TestBlockInfoSerialization(t *testing.T) { } bz, err = json.Marshal(block) require.NoError(t, err) - assert.Equal(t, `{"height":0,"time":"0","chain_id":""}`, string(bz)) + assert.JSONEq(t, `{"height":0,"time":"0","chain_id":""}`, string(bz)) } func TestBlockInfoDeserialization(t *testing.T) { diff --git a/types/ibc_test.go b/types/ibc_test.go index 8c17b558d..a4d32f4ff 100644 --- a/types/ibc_test.go +++ b/types/ibc_test.go @@ -19,7 +19,7 @@ func TestIbcTimeoutSerialization(t *testing.T) { } bz, err := json.Marshal(timeout) require.NoError(t, err) - assert.Equal(t, `{"block":{"revision":17,"height":42},"timestamp":"1578939743987654321"}`, string(bz)) + assert.JSONEq(t, `{"block":{"revision":17,"height":42},"timestamp":"1578939743987654321"}`, string(bz)) // Null block timeout = IBCTimeout{ @@ -28,7 +28,7 @@ func TestIbcTimeoutSerialization(t *testing.T) { } bz, err = json.Marshal(timeout) require.NoError(t, err) - assert.Equal(t, `{"block":null,"timestamp":"1578939743987654321"}`, string(bz)) + assert.JSONEq(t, `{"block":null,"timestamp":"1578939743987654321"}`, string(bz)) // Null timestamp // This should be `"timestamp":null`, but we are lacking this feature: https://github.com/golang/go/issues/37711 @@ -42,7 +42,7 @@ func TestIbcTimeoutSerialization(t *testing.T) { } bz, err = json.Marshal(timeout) require.NoError(t, err) - assert.Equal(t, `{"block":{"revision":17,"height":42}}`, string(bz)) + assert.JSONEq(t, `{"block":{"revision":17,"height":42}}`, string(bz)) } func TestIbcTimeoutDeserialization(t *testing.T) { diff --git a/types/msg_test.go b/types/msg_test.go index f56915928..fa0c7061b 100644 --- a/types/msg_test.go +++ b/types/msg_test.go @@ -25,7 +25,7 @@ func TestWasmMsgInstantiateSerialization(t *testing.T) { require.Equal(t, "", msg.Instantiate.Admin) require.Equal(t, uint64(7897), msg.Instantiate.CodeID) - require.Equal(t, []byte(`{"claim":{}}`), msg.Instantiate.Msg) + require.JSONEq(t, `{"claim":{}}`, string(msg.Instantiate.Msg)) require.Equal(t, Array[Coin]{ {"stones", "321"}, }, msg.Instantiate.Funds) @@ -46,7 +46,7 @@ func TestWasmMsgInstantiateSerialization(t *testing.T) { require.Equal(t, "king", msg.Instantiate.Admin) require.Equal(t, uint64(7897), msg.Instantiate.CodeID) - require.Equal(t, []byte(`{"claim":{}}`), msg.Instantiate.Msg) + require.JSONEq(t, `{"claim":{}}`, string(msg.Instantiate.Msg)) require.Equal(t, Array[Coin]{}, msg.Instantiate.Funds) require.Equal(t, "my instance", msg.Instantiate.Label) } @@ -67,7 +67,7 @@ func TestWasmMsgInstantiate2Serialization(t *testing.T) { require.Equal(t, "", msg.Instantiate2.Admin) require.Equal(t, uint64(7897), msg.Instantiate2.CodeID) - require.Equal(t, []byte(`{"claim":{}}`), msg.Instantiate2.Msg) + require.JSONEq(t, `{"claim":{}}`, string(msg.Instantiate2.Msg)) require.Equal(t, Array[Coin]{ {"stones", "321"}, }, msg.Instantiate2.Funds) diff --git a/types/queries_test.go b/types/queries_test.go index 8dd52dc8d..bff855235 100644 --- a/types/queries_test.go +++ b/types/queries_test.go @@ -12,7 +12,7 @@ func TestDelegationWithEmptyArray(t *testing.T) { var del Array[Delegation] bz, err := json.Marshal(&del) require.NoError(t, err) - assert.Equal(t, string(bz), `[]`) + assert.Equal(t, `[]`, string(bz)) var redel Array[Delegation] err = json.Unmarshal(bz, &redel) @@ -39,7 +39,7 @@ func TestValidatorWithEmptyArray(t *testing.T) { var val Array[Validator] bz, err := json.Marshal(&val) require.NoError(t, err) - assert.Equal(t, string(bz), `[]`) + assert.Equal(t, `[]`, string(bz)) var reval Array[Validator] err = json.Unmarshal(bz, &reval) @@ -165,11 +165,11 @@ func TestDistributionQuerySerialization(t *testing.T) { var query DistributionQuery err = json.Unmarshal(document, &query) require.NoError(t, err) - require.Equal(t, query, DistributionQuery{ + require.Equal(t, DistributionQuery{ DelegatorWithdrawAddress: &DelegatorWithdrawAddressQuery{ DelegatorAddress: "jane", }, - }) + }, query) // Serialization res := DelegatorWithdrawAddressResponse{ @@ -177,7 +177,7 @@ func TestDistributionQuerySerialization(t *testing.T) { } serialized, err := json.Marshal(res) require.NoError(t, err) - require.Equal(t, string(serialized), `{"withdraw_address":"jane"}`) + require.JSONEq(t, `{"withdraw_address":"jane"}`, string(serialized)) } func TestCodeInfoResponseSerialization(t *testing.T) { @@ -200,5 +200,5 @@ func TestCodeInfoResponseSerialization(t *testing.T) { } serialized, err := json.Marshal(&myRes) require.NoError(t, err) - require.Equal(t, `{"code_id":0,"creator":"sam","checksum":"ea4140c2d8ff498997f074cbe4f5236e52bc3176c61d1af6938aeb2f2e7b0e6d"}`, string(serialized)) + require.JSONEq(t, `{"code_id":0,"creator":"sam","checksum":"ea4140c2d8ff498997f074cbe4f5236e52bc3176c61d1af6938aeb2f2e7b0e6d"}`, string(serialized)) } diff --git a/types/submessages_test.go b/types/submessages_test.go index 5f3ec18a2..54d97e13b 100644 --- a/types/submessages_test.go +++ b/types/submessages_test.go @@ -37,7 +37,7 @@ func TestReplySerialization(t *testing.T) { } serialized, err := json.Marshal(&reply1) require.NoError(t, err) - require.Equal(t, `{"gas_used":4312324,"id":75,"result":{"ok":{"events":[{"type":"hi","attributes":[{"key":"si","value":"claro"}]}],"data":"PwCqXKs=","msg_responses":[{"type_url":"/cosmos.bank.v1beta1.MsgSendResponse","value":""}]}},"payload":"cGF5bG9hZA=="}`, string(serialized)) + require.JSONEq(t, `{"gas_used":4312324,"id":75,"result":{"ok":{"events":[{"type":"hi","attributes":[{"key":"si","value":"claro"}]}],"data":"PwCqXKs=","msg_responses":[{"type_url":"/cosmos.bank.v1beta1.MsgSendResponse","value":""}]}},"payload":"cGF5bG9hZA=="}`, string(serialized)) withoutPayload := Reply{ GasUsed: 4312324, @@ -48,14 +48,14 @@ func TestReplySerialization(t *testing.T) { } serialized2, err := json.Marshal(&withoutPayload) require.NoError(t, err) - require.Equal(t, `{"gas_used":4312324,"id":75,"result":{"error":"some error"}}`, string(serialized2)) + require.JSONEq(t, `{"gas_used":4312324,"id":75,"result":{"error":"some error"}}`, string(serialized2)) } func TestSubMsgResponseSerialization(t *testing.T) { response := SubMsgResponse{} document, err := json.Marshal(response) require.NoError(t, err) - require.Equal(t, `{"events":[],"msg_responses":[]}`, string(document)) + require.JSONEq(t, `{"events":[],"msg_responses":[]}`, string(document)) // we really only care about marshal, but let's test unmarshal too document2 := []byte(`{}`) diff --git a/types/systemerror_test.go b/types/systemerror_test.go index 5f45c7404..cfc0cafae 100644 --- a/types/systemerror_test.go +++ b/types/systemerror_test.go @@ -27,7 +27,7 @@ func TestSystemErrorNoSuchContractSerialization(t *testing.T) { } serialized, err := json.Marshal(&mySE) require.NoError(t, err) - require.Equal(t, `{"no_such_contract":{"addr":"404"}}`, string(serialized)) + require.JSONEq(t, `{"no_such_contract":{"addr":"404"}}`, string(serialized)) } func TestSystemErrorNoSuchCodeSerialization(t *testing.T) { @@ -50,5 +50,5 @@ func TestSystemErrorNoSuchCodeSerialization(t *testing.T) { } serialized, err := json.Marshal(&mySE) require.NoError(t, err) - require.Equal(t, `{"no_such_code":{"code_id":321}}`, string(serialized)) + require.JSONEq(t, `{"no_such_code":{"code_id":321}}`, string(serialized)) }