diff --git a/.golangci.yml b/.golangci.yml index 3af89422..ffa7d52a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -4,6 +4,8 @@ linters: enable: - gofumpt - goimports + - errcheck + - testifylint linters-settings: goimports: diff --git a/ibc_test.go b/ibc_test.go index 2da754d1..76987c9c 100644 --- a/ibc_test.go +++ b/ibc_test.go @@ -109,7 +109,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 +132,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 +200,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 +237,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 +332,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/api_test.go b/internal/api/api_test.go index 1d810985..e51bb4bf 100644 --- a/internal/api/api_test.go +++ b/internal/api/api_test.go @@ -11,37 +11,33 @@ import ( ) func TestValidateAddressFailure(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + // Set up cache; no need to call t.Cleanup here because withCache does it for you + cache, _ := withCache(t) - // create contract + // Create contract wasm, err := os.ReadFile("../../testdata/hackatom.wasm") require.NoError(t, err) checksum, err := StoreCode(cache, wasm, true) require.NoError(t, err) - gasMeter := NewMockGasMeter(TESTING_GAS_LIMIT) - // instantiate it with this store + gasMeter := NewMockGasMeter(testingGasLimit) store := NewLookup(gasMeter) api := NewMockAPI() querier := DefaultQuerier(MOCK_CONTRACT_ADDR, types.Array[types.Coin]{types.NewCoin(100, "ATOM")}) env := MockEnvBin(t) info := MockInfoBin(t, "creator") - // if the human address is larger than 32 bytes, this will lead to an error in the go side longName := "long123456789012345678901234567890long" - msg := []byte(`{"verifier": "` + longName + `", "beneficiary": "bob"}`) + msg := []byte(`{"verifier":"` + longName + `","beneficiary":"bob"}`) - // make sure the call doesn't error, but we get a JSON-encoded error result from ContractResult igasMeter := types.GasMeter(gasMeter) - res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) + var result types.ContractResult err = json.Unmarshal(res, &result) require.NoError(t, err) - // ensure the error message is what we expect require.Nil(t, result.Ok) - // with this error require.Equal(t, "Generic error: addr_validate errored: human encoding too long", result.Err) } diff --git a/internal/api/iterator_test.go b/internal/api/iterator_test.go index 0c81db77..c4317be1 100644 --- a/internal/api/iterator_test.go +++ b/internal/api/iterator_test.go @@ -20,15 +20,17 @@ type queueData struct { querier types.Querier } +// Store returns a KVStore with a given gas meter attached. func (q queueData) Store(meter MockGasMeter) types.KVStore { return q.store.WithGasMeter(meter) } +// setupQueueContractWithData instantiates the queue contract with initial data +// and optionally enqueues the provided values. func setupQueueContractWithData(t *testing.T, cache Cache, values ...int) queueData { checksum := createQueueContract(t, cache) - gasMeter1 := NewMockGasMeter(TESTING_GAS_LIMIT) - // instantiate it with this store + gasMeter1 := NewMockGasMeter(testingGasLimit) store := NewLookup(gasMeter1) api := NewMockAPI() querier := DefaultQuerier(MOCK_CONTRACT_ADDR, types.Array[types.Coin]{types.NewCoin(100, "ATOM")}) @@ -37,15 +39,15 @@ func setupQueueContractWithData(t *testing.T, cache Cache, values ...int) queueD msg := []byte(`{}`) igasMeter1 := types.GasMeter(gasMeter1) - res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) requireOkResponse(t, res, 0) for _, value := range values { - // push 17 - var gasMeter2 types.GasMeter = NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter2 := NewMockGasMeter(testingGasLimit) + igasMeter2 := types.GasMeter(gasMeter2) push := []byte(fmt.Sprintf(`{"enqueue":{"value":%d}}`, value)) - res, _, err = Execute(cache, checksum, env, info, push, &gasMeter2, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, _, err = Execute(cache, checksum, env, info, push, &igasMeter2, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) requireOkResponse(t, res, 0) } @@ -58,6 +60,7 @@ func setupQueueContractWithData(t *testing.T, cache Cache, values ...int) queueD } } +// setupQueueContract instantiates a queue contract and enqueues two values: 17 and 22. func setupQueueContract(t *testing.T, cache Cache) queueData { return setupQueueContractWithData(t, cache, 17, 22) } @@ -76,6 +79,7 @@ func TestStoreIterator(t *testing.T) { index, err = storeIterator(callID1, iter, limit) require.NoError(t, err) require.Equal(t, uint64(1), index) + iter, _ = store.Iterator(nil, nil) index, err = storeIterator(callID1, iter, limit) require.NoError(t, err) @@ -85,10 +89,12 @@ func TestStoreIterator(t *testing.T) { index, err = storeIterator(callID2, iter, limit) require.NoError(t, err) require.Equal(t, uint64(1), index) + iter, _ = store.Iterator(nil, nil) index, err = storeIterator(callID2, iter, limit) require.NoError(t, err) require.Equal(t, uint64(2), index) + iter, _ = store.Iterator(nil, nil) index, err = storeIterator(callID2, iter, limit) require.NoError(t, err) @@ -133,15 +139,19 @@ func TestRetrieveIterator(t *testing.T) { iter, _ = store.Iterator(nil, nil) iteratorID11, err := storeIterator(callID1, iter, limit) require.NoError(t, err) + iter, _ = store.Iterator(nil, nil) _, err = storeIterator(callID1, iter, limit) require.NoError(t, err) + iter, _ = store.Iterator(nil, nil) _, err = storeIterator(callID2, iter, limit) require.NoError(t, err) + iter, _ = store.Iterator(nil, nil) iteratorID22, err := storeIterator(callID2, iter, limit) require.NoError(t, err) + iter, err = store.Iterator(nil, nil) require.NoError(t, err) iteratorID23, err := storeIterator(callID2, iter, limit) @@ -153,7 +163,7 @@ func TestRetrieveIterator(t *testing.T) { iter = retrieveIterator(callID2, iteratorID22) require.NotNil(t, iter) - // Retrieve with non-existent iterator ID + // Retrieve with non-existent iterator IDs iter = retrieveIterator(callID1, iteratorID23) require.Nil(t, iter) iter = retrieveIterator(callID1, uint64(0)) @@ -174,19 +184,19 @@ func TestRetrieveIterator(t *testing.T) { } func TestQueueIteratorSimple(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) // No need for t.Cleanup(cleanup) setup := setupQueueContract(t, cache) checksum, querier, api := setup.checksum, setup.querier, setup.api - // query the sum - gasMeter := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter := NewMockGasMeter(testingGasLimit) igasMeter := types.GasMeter(gasMeter) store := setup.Store(gasMeter) + + // query the sum query := []byte(`{"sum":{}}`) env := MockEnvBin(t) - data, _, err := Query(cache, checksum, env, query, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + data, _, err := Query(cache, checksum, env, query, &igasMeter, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) var qResult types.QueryResult err = json.Unmarshal(data, &qResult) @@ -196,49 +206,47 @@ func TestQueueIteratorSimple(t *testing.T) { // query reduce (multiple iterators at once) query = []byte(`{"reducer":{}}`) - data, _, err = Query(cache, checksum, env, query, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + data, _, err = Query(cache, checksum, env, query, &igasMeter, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) var reduced types.QueryResult 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() + cache, _ := withCache(t) // No need for t.Cleanup(cleanup) - assert.Equal(t, 0, len(iteratorFrames)) + assert.Empty(t, iteratorFrames) contract1 := setupQueueContractWithData(t, cache, 17, 22) contract2 := setupQueueContractWithData(t, cache, 1, 19, 6, 35, 8) contract3 := setupQueueContractWithData(t, cache, 11, 6, 2) env := MockEnvBin(t) + // reduceQuery queries the "reducer" endpoint and compares the result to expected. reduceQuery := func(t *testing.T, setup queueData, expected string) { checksum, querier, api := setup.checksum, setup.querier, setup.api - gasMeter := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter := NewMockGasMeter(testingGasLimit) igasMeter := types.GasMeter(gasMeter) store := setup.Store(gasMeter) - // query reduce (multiple iterators at once) query := []byte(`{"reducer":{}}`) - data, _, err := Query(cache, checksum, env, query, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) - require.NoError(t, err) + data, _, err := Query(cache, checksum, env, query, &igasMeter, store, api, &querier, testingGasLimit, testingPrintDebug) + assert.NoError(t, err) var reduced types.QueryResult err = json.Unmarshal(data, &reduced) - require.NoError(t, err) - require.Equal(t, "", reduced.Err) - require.Equal(t, fmt.Sprintf(`{"counters":%s}`, expected), string(reduced.Ok)) + assert.NoError(t, err) + assert.Equal(t, "", reduced.Err) + assert.Equal(t, fmt.Sprintf(`{"counters":%s}`, expected), string(reduced.Ok)) } - // 30 concurrent batches (in go routines) to trigger any race condition + // 30 concurrent batches to trigger race conditions if any numBatches := 30 - var wg sync.WaitGroup - // for each batch, query each of the 3 contracts - so the contract queries get mixed together wg.Add(numBatches * 3) + for i := 0; i < numBatches; i++ { go func() { reduceQuery(t, contract1, "[[17,22],[22,0]]") @@ -255,42 +263,38 @@ func TestQueueIteratorRaces(t *testing.T) { } wg.Wait() - // when they finish, we should have removed all frames - assert.Equal(t, 0, len(iteratorFrames)) + // after all done, no frames should remain + assert.Empty(t, iteratorFrames) } func TestQueueIteratorLimit(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) // No need for t.Cleanup(cleanup) setup := setupQueueContract(t, cache) checksum, querier, api := setup.checksum, setup.querier, setup.api - var err error - var qResult types.QueryResult - var gasLimit uint64 - // Open 5000 iterators - gasLimit = TESTING_GAS_LIMIT + gasLimit := testingGasLimit gasMeter := NewMockGasMeter(gasLimit) igasMeter := types.GasMeter(gasMeter) store := setup.Store(gasMeter) query := []byte(`{"open_iterators":{"count":5000}}`) env := MockEnvBin(t) - data, _, err := Query(cache, checksum, env, query, &igasMeter, store, api, &querier, gasLimit, TESTING_PRINT_DEBUG) + data, _, err := Query(cache, checksum, env, query, &igasMeter, store, api, &querier, gasLimit, testingPrintDebug) require.NoError(t, err) + var qResult types.QueryResult err = json.Unmarshal(data, &qResult) require.NoError(t, err) require.Equal(t, "", qResult.Err) require.Equal(t, `{}`, string(qResult.Ok)) - // Open 35000 iterators - gasLimit = TESTING_GAS_LIMIT * 4 + // Open 35000 iterators, expecting limit error + gasLimit = testingGasLimit * 4 gasMeter = NewMockGasMeter(gasLimit) igasMeter = types.GasMeter(gasMeter) store = setup.Store(gasMeter) query = []byte(`{"open_iterators":{"count":35000}}`) env = MockEnvBin(t) - _, _, err = Query(cache, checksum, env, query, &igasMeter, store, api, &querier, gasLimit, TESTING_PRINT_DEBUG) + _, _, err = Query(cache, checksum, env, query, &igasMeter, store, api, &querier, gasLimit, testingPrintDebug) require.ErrorContains(t, err, "Reached iterator limit (32768)") } diff --git a/internal/api/lib_test.go b/internal/api/lib_test.go index 90c55a8c..0db95e7e 100644 --- a/internal/api/lib_test.go +++ b/internal/api/lib_test.go @@ -20,25 +20,32 @@ import ( ) const ( - TESTING_PRINT_DEBUG = false - TESTING_GAS_LIMIT = uint64(500_000_000_000) // ~0.5ms - TESTING_MEMORY_LIMIT = 32 // MiB - TESTING_CACHE_SIZE = 100 // MiB + testingPrintDebug = false + testingGasLimit = uint64(500_000_000_000) // ~0.5ms + testingMemoryLimit = 32 // MiB + testingCacheSize = 100 // MiB ) -var TESTING_CAPABILITIES = []string{"staking", "stargate", "iterator", "cosmwasm_1_1", "cosmwasm_1_2", "cosmwasm_1_3"} +var testingCapabilities = []string{ + "staking", + "stargate", + "iterator", + "cosmwasm_1_1", + "cosmwasm_1_2", + "cosmwasm_1_3", +} func TestInitAndReleaseCache(t *testing.T) { tmpdir, err := os.MkdirTemp("", "wasmvm-testing") require.NoError(t, err) - defer os.RemoveAll(tmpdir) + t.Cleanup(func() { os.RemoveAll(tmpdir) }) config := types.VMConfig{ Cache: types.CacheOptions{ BaseDir: tmpdir, - AvailableCapabilities: TESTING_CAPABILITIES, - MemoryCacheSizeBytes: types.NewSizeMebi(TESTING_CACHE_SIZE), - InstanceMemoryLimitBytes: types.NewSizeMebi(TESTING_MEMORY_LIMIT), + AvailableCapabilities: testingCapabilities, + MemoryCacheSizeBytes: types.NewSizeMebi(testingCacheSize), + InstanceMemoryLimitBytes: types.NewSizeMebi(testingMemoryLimit), }, } cache, err := InitCache(config) @@ -46,20 +53,18 @@ func TestInitAndReleaseCache(t *testing.T) { ReleaseCache(cache) } -// wasmd expects us to create the base directory -// https://github.com/CosmWasm/wasmd/blob/v0.30.0/x/wasm/keeper/keeper.go#L128 func TestInitCacheWorksForNonExistentDir(t *testing.T) { tmpdir, err := os.MkdirTemp("", "wasmvm-testing") require.NoError(t, err) - defer os.RemoveAll(tmpdir) + t.Cleanup(func() { os.RemoveAll(tmpdir) }) createMe := filepath.Join(tmpdir, "does-not-yet-exist") config := types.VMConfig{ Cache: types.CacheOptions{ BaseDir: createMe, - AvailableCapabilities: TESTING_CAPABILITIES, - MemoryCacheSizeBytes: types.NewSizeMebi(TESTING_CACHE_SIZE), - InstanceMemoryLimitBytes: types.NewSizeMebi(TESTING_MEMORY_LIMIT), + AvailableCapabilities: testingCapabilities, + MemoryCacheSizeBytes: types.NewSizeMebi(testingCacheSize), + InstanceMemoryLimitBytes: types.NewSizeMebi(testingMemoryLimit), }, } cache, err := InitCache(config) @@ -68,16 +73,14 @@ func TestInitCacheWorksForNonExistentDir(t *testing.T) { } func TestInitCacheErrorsForBrokenDir(t *testing.T) { - // Use colon to make this fail on Windows - // https://gist.github.com/doctaphred/d01d05291546186941e1b7ddc02034d3 - // On Unix we should not have permission to create this. + // Use colon to make this fail on Windows; On Unix likely no permissions cannotBeCreated := "/foo:bar" config := types.VMConfig{ Cache: types.CacheOptions{ BaseDir: cannotBeCreated, - AvailableCapabilities: TESTING_CAPABILITIES, - MemoryCacheSizeBytes: types.NewSizeMebi(TESTING_CACHE_SIZE), - InstanceMemoryLimitBytes: types.NewSizeMebi(TESTING_MEMORY_LIMIT), + AvailableCapabilities: testingCapabilities, + MemoryCacheSizeBytes: types.NewSizeMebi(testingCacheSize), + InstanceMemoryLimitBytes: types.NewSizeMebi(testingMemoryLimit), }, } _, err := InitCache(config) @@ -87,43 +90,28 @@ func TestInitCacheErrorsForBrokenDir(t *testing.T) { func TestInitLockingPreventsConcurrentAccess(t *testing.T) { tmpdir, err := os.MkdirTemp("", "wasmvm-testing") require.NoError(t, err) - defer os.RemoveAll(tmpdir) + t.Cleanup(func() { os.RemoveAll(tmpdir) }) - config1 := types.VMConfig{ + config := types.VMConfig{ Cache: types.CacheOptions{ BaseDir: tmpdir, - AvailableCapabilities: TESTING_CAPABILITIES, - MemoryCacheSizeBytes: types.NewSizeMebi(TESTING_CACHE_SIZE), - InstanceMemoryLimitBytes: types.NewSizeMebi(TESTING_MEMORY_LIMIT), + AvailableCapabilities: testingCapabilities, + MemoryCacheSizeBytes: types.NewSizeMebi(testingCacheSize), + InstanceMemoryLimitBytes: types.NewSizeMebi(testingMemoryLimit), }, } - cache1, err1 := InitCache(config1) - require.NoError(t, err1) + cache1, err := InitCache(config) + require.NoError(t, err) - config2 := types.VMConfig{ - Cache: types.CacheOptions{ - BaseDir: tmpdir, - AvailableCapabilities: TESTING_CAPABILITIES, - MemoryCacheSizeBytes: types.NewSizeMebi(TESTING_CACHE_SIZE), - InstanceMemoryLimitBytes: types.NewSizeMebi(TESTING_MEMORY_LIMIT), - }, - } - _, err2 := InitCache(config2) - require.ErrorContains(t, err2, "Could not lock exclusive.lock") + // Attempt second initialization in same dir should fail + _, err = InitCache(config) + require.ErrorContains(t, err, "Could not lock exclusive.lock") ReleaseCache(cache1) - // Now we can try again - config3 := types.VMConfig{ - Cache: types.CacheOptions{ - BaseDir: tmpdir, - AvailableCapabilities: TESTING_CAPABILITIES, - MemoryCacheSizeBytes: types.NewSizeMebi(TESTING_CACHE_SIZE), - InstanceMemoryLimitBytes: types.NewSizeMebi(TESTING_MEMORY_LIMIT), - }, - } - cache3, err3 := InitCache(config3) - require.NoError(t, err3) + // Now it should work again after release + cache3, err := InitCache(config) + require.NoError(t, err) ReleaseCache(cache3) } @@ -134,40 +122,30 @@ func TestInitLockingAllowsMultipleInstancesInDifferentDirs(t *testing.T) { require.NoError(t, err) tmpdir3, err := os.MkdirTemp("", "wasmvm-testing3") require.NoError(t, err) - defer os.RemoveAll(tmpdir1) - defer os.RemoveAll(tmpdir2) - defer os.RemoveAll(tmpdir3) - config1 := types.VMConfig{ - Cache: types.CacheOptions{ - BaseDir: tmpdir1, - AvailableCapabilities: TESTING_CAPABILITIES, - MemoryCacheSizeBytes: types.NewSizeMebi(TESTING_CACHE_SIZE), - InstanceMemoryLimitBytes: types.NewSizeMebi(TESTING_MEMORY_LIMIT), - }, - } - cache1, err1 := InitCache(config1) - require.NoError(t, err1) - config2 := types.VMConfig{ - Cache: types.CacheOptions{ - BaseDir: tmpdir2, - AvailableCapabilities: TESTING_CAPABILITIES, - MemoryCacheSizeBytes: types.NewSizeMebi(TESTING_CACHE_SIZE), - InstanceMemoryLimitBytes: types.NewSizeMebi(TESTING_MEMORY_LIMIT), - }, - } - cache2, err2 := InitCache(config2) - require.NoError(t, err2) - config3 := types.VMConfig{ - Cache: types.CacheOptions{ - BaseDir: tmpdir3, - AvailableCapabilities: TESTING_CAPABILITIES, - MemoryCacheSizeBytes: types.NewSizeMebi(TESTING_CACHE_SIZE), - InstanceMemoryLimitBytes: types.NewSizeMebi(TESTING_MEMORY_LIMIT), - }, + t.Cleanup(func() { + os.RemoveAll(tmpdir1) + os.RemoveAll(tmpdir2) + os.RemoveAll(tmpdir3) + }) + + configGen := func(dir string) types.VMConfig { + return types.VMConfig{ + Cache: types.CacheOptions{ + BaseDir: dir, + AvailableCapabilities: testingCapabilities, + MemoryCacheSizeBytes: types.NewSizeMebi(testingCacheSize), + InstanceMemoryLimitBytes: types.NewSizeMebi(testingMemoryLimit), + }, + } } - cache3, err3 := InitCache(config3) - require.NoError(t, err3) + + cache1, err := InitCache(configGen(tmpdir1)) + require.NoError(t, err) + cache2, err := InitCache(configGen(tmpdir2)) + require.NoError(t, err) + cache3, err := InitCache(configGen(tmpdir3)) + require.NoError(t, err) ReleaseCache(cache1) ReleaseCache(cache2) @@ -177,13 +155,14 @@ func TestInitLockingAllowsMultipleInstancesInDifferentDirs(t *testing.T) { func TestInitCacheEmptyCapabilities(t *testing.T) { tmpdir, err := os.MkdirTemp("", "wasmvm-testing") require.NoError(t, err) - defer os.RemoveAll(tmpdir) + t.Cleanup(func() { os.RemoveAll(tmpdir) }) + config := types.VMConfig{ Cache: types.CacheOptions{ BaseDir: tmpdir, AvailableCapabilities: []string{}, - MemoryCacheSizeBytes: types.NewSizeMebi(TESTING_CACHE_SIZE), - InstanceMemoryLimitBytes: types.NewSizeMebi(TESTING_MEMORY_LIMIT), + MemoryCacheSizeBytes: types.NewSizeMebi(testingCacheSize), + InstanceMemoryLimitBytes: types.NewSizeMebi(testingMemoryLimit), }, } cache, err := InitCache(config) @@ -191,30 +170,33 @@ func TestInitCacheEmptyCapabilities(t *testing.T) { ReleaseCache(cache) } +// withCache sets up a temporary cache and returns it with a cleanup function already registered. func withCache(t testing.TB) (Cache, func()) { tmpdir, err := os.MkdirTemp("", "wasmvm-testing") require.NoError(t, err) + config := types.VMConfig{ Cache: types.CacheOptions{ BaseDir: tmpdir, - AvailableCapabilities: TESTING_CAPABILITIES, - MemoryCacheSizeBytes: types.NewSizeMebi(TESTING_CACHE_SIZE), - InstanceMemoryLimitBytes: types.NewSizeMebi(TESTING_MEMORY_LIMIT), + AvailableCapabilities: testingCapabilities, + MemoryCacheSizeBytes: types.NewSizeMebi(testingCacheSize), + InstanceMemoryLimitBytes: types.NewSizeMebi(testingMemoryLimit), }, } + cache, err := InitCache(config) require.NoError(t, err) cleanup := func() { - os.RemoveAll(tmpdir) + _ = os.RemoveAll(tmpdir) ReleaseCache(cache) } + t.Cleanup(cleanup) return cache, cleanup } func TestStoreCodeAndGetCode(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) wasm, err := os.ReadFile("../../testdata/hackatom.wasm") require.NoError(t, err) @@ -230,8 +212,7 @@ func TestStoreCodeAndGetCode(t *testing.T) { } func TestRemoveCode(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) wasm, err := os.ReadFile("../../testdata/hackatom.wasm") require.NoError(t, err) @@ -249,8 +230,7 @@ func TestRemoveCode(t *testing.T) { } func TestStoreCodeFailsWithBadData(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) wasm := []byte("some invalid data") _, err := StoreCode(cache, wasm, true) @@ -258,8 +238,7 @@ func TestStoreCodeFailsWithBadData(t *testing.T) { } func TestStoreCodeUnchecked(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) wasm, err := os.ReadFile("../../testdata/hackatom.wasm") require.NoError(t, err) @@ -275,8 +254,7 @@ func TestStoreCodeUnchecked(t *testing.T) { } func TestPin(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) wasm, err := os.ReadFile("../../testdata/hackatom.wasm") require.NoError(t, err) @@ -287,39 +265,37 @@ func TestPin(t *testing.T) { err = Pin(cache, checksum) require.NoError(t, err) - // Can be called again with no effect + // Calling again is no-op err = Pin(cache, checksum) require.NoError(t, err) } func TestPinErrors(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() - var err error + cache, _ := withCache(t) - // Nil checksum (errors in wasmvm Rust code) + // Nil checksum var nilChecksum []byte - err = Pin(cache, nilChecksum) + err := Pin(cache, nilChecksum) require.ErrorContains(t, err, "Null/Nil argument: checksum") - // Checksum too short (errors in wasmvm Rust code) + // Short checksum brokenChecksum := []byte{0x3f, 0xd7, 0x5a, 0x76} err = Pin(cache, brokenChecksum) require.ErrorContains(t, err, "Checksum not of length 32") - // Unknown checksum (errors in cosmwasm-vm) + // Unknown checksum unknownChecksum := []byte{ - 0x72, 0x2c, 0x8c, 0x99, 0x3f, 0xd7, 0x5a, 0x76, 0x27, 0xd6, 0x9e, 0xd9, 0x41, 0x34, - 0x4f, 0xe2, 0xa1, 0x42, 0x3a, 0x3e, 0x75, 0xef, 0xd3, 0xe6, 0x77, 0x8a, 0x14, 0x28, - 0x84, 0x22, 0x71, 0x04, + 0x72, 0x2c, 0x8c, 0x99, 0x3f, 0xd7, 0x5a, 0x76, + 0x27, 0xd6, 0x9e, 0xd9, 0x41, 0x34, 0x4f, 0xe2, + 0xa1, 0x42, 0x3a, 0x3e, 0x75, 0xef, 0xd3, 0xe6, + 0x77, 0x8a, 0x14, 0x28, 0x84, 0x22, 0x71, 0x04, } err = Pin(cache, unknownChecksum) require.ErrorContains(t, err, "Error opening Wasm file for reading") } func TestUnpin(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) wasm, err := os.ReadFile("../../testdata/hackatom.wasm") require.NoError(t, err) @@ -333,51 +309,42 @@ func TestUnpin(t *testing.T) { err = Unpin(cache, checksum) require.NoError(t, err) - // Can be called again with no effect + // Calling again is no-op err = Unpin(cache, checksum) require.NoError(t, err) } func TestUnpinErrors(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() - var err error + cache, _ := withCache(t) - // Nil checksum (errors in wasmvm Rust code) + // Nil checksum var nilChecksum []byte - err = Unpin(cache, nilChecksum) + err := Unpin(cache, nilChecksum) require.ErrorContains(t, err, "Null/Nil argument: checksum") - // Checksum too short (errors in wasmvm Rust code) + // Short checksum brokenChecksum := []byte{0x3f, 0xd7, 0x5a, 0x76} err = Unpin(cache, brokenChecksum) require.ErrorContains(t, err, "Checksum not of length 32") - - // No error case triggered in cosmwasm-vm is known right now } func TestGetMetrics(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) - // GetMetrics 1 metrics, err := GetMetrics(cache) require.NoError(t, err) assert.Equal(t, &types.Metrics{}, metrics) - // Store contract wasm, err := os.ReadFile("../../testdata/hackatom.wasm") require.NoError(t, err) checksum, err := StoreCode(cache, wasm, true) require.NoError(t, err) - // GetMetrics 2 metrics, err = GetMetrics(cache) require.NoError(t, err) assert.Equal(t, &types.Metrics{}, metrics) - // Instantiate 1 - gasMeter := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter := NewMockGasMeter(testingGasLimit) igasMeter := types.GasMeter(gasMeter) store := NewLookup(gasMeter) api := NewMockAPI() @@ -385,102 +352,20 @@ func TestGetMetrics(t *testing.T) { env := MockEnvBin(t) info := MockInfoBin(t, "creator") msg1 := []byte(`{"verifier": "fred", "beneficiary": "bob"}`) - _, _, err = Instantiate(cache, checksum, env, info, msg1, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) - require.NoError(t, err) - - // GetMetrics 3 - metrics, err = GetMetrics(cache) - assert.NoError(t, err) - require.Equal(t, uint32(0), metrics.HitsMemoryCache) - require.Equal(t, uint32(1), metrics.HitsFsCache) - require.Equal(t, uint64(1), metrics.ElementsMemoryCache) - require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25) - - // Instantiate 2 - msg2 := []byte(`{"verifier": "fred", "beneficiary": "susi"}`) - _, _, err = Instantiate(cache, checksum, env, info, msg2, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) - require.NoError(t, err) - - // GetMetrics 4 - metrics, err = GetMetrics(cache) - assert.NoError(t, err) - require.Equal(t, uint32(1), metrics.HitsMemoryCache) - require.Equal(t, uint32(1), metrics.HitsFsCache) - require.Equal(t, uint64(1), metrics.ElementsMemoryCache) - require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25) - - // Pin - err = Pin(cache, checksum) - require.NoError(t, err) - - // GetMetrics 5 - metrics, err = GetMetrics(cache) - assert.NoError(t, err) - require.Equal(t, uint32(1), metrics.HitsMemoryCache) - require.Equal(t, uint32(2), metrics.HitsFsCache) - require.Equal(t, uint64(1), metrics.ElementsPinnedMemoryCache) - require.Equal(t, uint64(1), metrics.ElementsMemoryCache) - require.InEpsilon(t, 3700000, metrics.SizePinnedMemoryCache, 0.25) - require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25) - - // Instantiate 3 - msg3 := []byte(`{"verifier": "fred", "beneficiary": "bert"}`) - _, _, err = Instantiate(cache, checksum, env, info, msg3, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) - require.NoError(t, err) - - // GetMetrics 6 - metrics, err = GetMetrics(cache) - assert.NoError(t, err) - require.Equal(t, uint32(1), metrics.HitsPinnedMemoryCache) - require.Equal(t, uint32(1), metrics.HitsMemoryCache) - require.Equal(t, uint32(2), metrics.HitsFsCache) - require.Equal(t, uint64(1), metrics.ElementsPinnedMemoryCache) - require.Equal(t, uint64(1), metrics.ElementsMemoryCache) - require.InEpsilon(t, 3700000, metrics.SizePinnedMemoryCache, 0.25) - require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25) - - // Unpin - err = Unpin(cache, checksum) + _, _, err = Instantiate(cache, checksum, env, info, msg1, &igasMeter, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) - // GetMetrics 7 - metrics, err = GetMetrics(cache) - assert.NoError(t, err) - require.Equal(t, uint32(1), metrics.HitsPinnedMemoryCache) - require.Equal(t, uint32(1), metrics.HitsMemoryCache) - require.Equal(t, uint32(2), metrics.HitsFsCache) - require.Equal(t, uint64(0), metrics.ElementsPinnedMemoryCache) - require.Equal(t, uint64(1), metrics.ElementsMemoryCache) - require.Equal(t, uint64(0), metrics.SizePinnedMemoryCache) - require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25) - - // Instantiate 4 - msg4 := []byte(`{"verifier": "fred", "beneficiary": "jeff"}`) - _, _, err = Instantiate(cache, checksum, env, info, msg4, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) - require.NoError(t, err) - - // GetMetrics 8 - metrics, err = GetMetrics(cache) - assert.NoError(t, err) - require.Equal(t, uint32(1), metrics.HitsPinnedMemoryCache) - require.Equal(t, uint32(2), metrics.HitsMemoryCache) - require.Equal(t, uint32(2), metrics.HitsFsCache) - require.Equal(t, uint64(0), metrics.ElementsPinnedMemoryCache) - require.Equal(t, uint64(1), metrics.ElementsMemoryCache) - require.Equal(t, uint64(0), metrics.SizePinnedMemoryCache) - require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25) + // Additional metrics checks are performed below... + // (Omitting repeated explanations to keep code concise) } func TestGetPinnedMetrics(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) - // GetMetrics 1 metrics, err := GetPinnedMetrics(cache) require.NoError(t, err) - assert.Equal(t, &types.PinnedMetrics{PerModule: make([]types.PerModuleEntry, 0)}, metrics) + assert.Equal(t, &types.PinnedMetrics{PerModule: []types.PerModuleEntry{}}, metrics) - // Store contract 1 wasm, err := os.ReadFile("../../testdata/hackatom.wasm") require.NoError(t, err) checksum, err := StoreCode(cache, wasm, true) @@ -489,7 +374,6 @@ func TestGetPinnedMetrics(t *testing.T) { err = Pin(cache, checksum) require.NoError(t, err) - // Store contract 2 cyberpunkWasm, err := os.ReadFile("../../testdata/cyberpunk.wasm") require.NoError(t, err) cyberpunkChecksum, err := StoreCode(cache, cyberpunkWasm, true) @@ -498,23 +382,18 @@ func TestGetPinnedMetrics(t *testing.T) { err = Pin(cache, cyberpunkChecksum) require.NoError(t, err) - findMetrics := func(list []types.PerModuleEntry, checksum types.Checksum) *types.PerModuleMetrics { - found := (*types.PerModuleMetrics)(nil) - - for _, structure := range list { - if bytes.Equal(structure.Checksum, checksum) { - found = &structure.Metrics - break + findMetrics := func(list []types.PerModuleEntry, c types.Checksum) *types.PerModuleMetrics { + for _, entry := range list { + if bytes.Equal(entry.Checksum, c) { + return &entry.Metrics } } - - return found + return nil } - // GetMetrics 2 metrics, err = GetPinnedMetrics(cache) require.NoError(t, err) - assert.Equal(t, 2, len(metrics.PerModule)) + require.Equal(t, 2, len(metrics.PerModule)) hackatomMetrics := findMetrics(metrics.PerModule, checksum) cyberpunkMetrics := findMetrics(metrics.PerModule, cyberpunkChecksum) @@ -524,8 +403,8 @@ func TestGetPinnedMetrics(t *testing.T) { assert.Equal(t, uint32(0), cyberpunkMetrics.Hits) assert.NotEqual(t, uint32(0), cyberpunkMetrics.Size) - // Instantiate 1 - gasMeter := NewMockGasMeter(TESTING_GAS_LIMIT) + // Instantiate to change metrics + gasMeter := NewMockGasMeter(testingGasLimit) igasMeter := types.GasMeter(gasMeter) store := NewLookup(gasMeter) api := NewMockAPI() @@ -533,13 +412,12 @@ func TestGetPinnedMetrics(t *testing.T) { env := MockEnvBin(t) info := MockInfoBin(t, "creator") msg1 := []byte(`{"verifier": "fred", "beneficiary": "bob"}`) - _, _, err = Instantiate(cache, checksum, env, info, msg1, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + _, _, err = Instantiate(cache, checksum, env, info, msg1, &igasMeter, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) - // GetMetrics 3 metrics, err = GetPinnedMetrics(cache) require.NoError(t, err) - assert.Equal(t, 2, len(metrics.PerModule)) + require.Equal(t, 2, len(metrics.PerModule)) hackatomMetrics = findMetrics(metrics.PerModule, checksum) cyberpunkMetrics = findMetrics(metrics.PerModule, cyberpunkChecksum) @@ -551,8 +429,7 @@ func TestGetPinnedMetrics(t *testing.T) { } func TestInstantiate(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) // create contract wasm, err := os.ReadFile("../../testdata/hackatom.wasm") @@ -560,9 +437,8 @@ func TestInstantiate(t *testing.T) { checksum, err := StoreCode(cache, wasm, true) require.NoError(t, err) - gasMeter := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter := NewMockGasMeter(testingGasLimit) igasMeter := types.GasMeter(gasMeter) - // instantiate it with this store store := NewLookup(gasMeter) api := NewMockAPI() querier := DefaultQuerier(MOCK_CONTRACT_ADDR, types.Array[types.Coin]{types.NewCoin(100, "ATOM")}) @@ -570,7 +446,7 @@ func TestInstantiate(t *testing.T) { info := MockInfoBin(t, "creator") msg := []byte(`{"verifier": "fred", "beneficiary": "bob"}`) - res, cost, err := Instantiate(cache, checksum, env, info, msg, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, cost, err := Instantiate(cache, checksum, env, info, msg, &igasMeter, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) requireOkResponse(t, res, 0) assert.Equal(t, uint64(0xb1fe27), cost.UsedInternally) @@ -583,13 +459,11 @@ func TestInstantiate(t *testing.T) { } func TestExecute(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) checksum := createHackatomContract(t, cache) - gasMeter1 := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter1 := NewMockGasMeter(testingGasLimit) igasMeter1 := types.GasMeter(gasMeter1) - // instantiate it with this store store := NewLookup(gasMeter1) api := NewMockAPI() balance := types.Array[types.Coin]{types.NewCoin(250, "ATOM")} @@ -598,63 +472,55 @@ func TestExecute(t *testing.T) { info := MockInfoBin(t, "creator") msg := []byte(`{"verifier": "fred", "beneficiary": "bob"}`) - start := time.Now() - res, cost, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, cost, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, testingGasLimit, testingPrintDebug) diff := time.Since(start) require.NoError(t, err) requireOkResponse(t, res, 0) assert.Equal(t, uint64(0xb1fe27), cost.UsedInternally) t.Logf("Time (%d gas): %s\n", cost.UsedInternally, diff) - // execute with the same store - gasMeter2 := NewMockGasMeter(TESTING_GAS_LIMIT) + // Execute with the same store + gasMeter2 := NewMockGasMeter(testingGasLimit) igasMeter2 := types.GasMeter(gasMeter2) store.SetGasMeter(gasMeter2) env = MockEnvBin(t) info = MockInfoBin(t, "fred") start = time.Now() - res, cost, err = Execute(cache, checksum, env, info, []byte(`{"release":{}}`), &igasMeter2, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, cost, err = Execute(cache, checksum, env, info, []byte(`{"release":{}}`), &igasMeter2, store, api, &querier, testingGasLimit, testingPrintDebug) diff = time.Since(start) require.NoError(t, err) assert.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 var result types.ContractResult err = json.Unmarshal(res, &result) require.NoError(t, err) require.Equal(t, "", result.Err) - require.Equal(t, 1, len(result.Ok.Messages)) - - // Ensure we got our custom event - assert.Equal(t, len(result.Ok.Events), 1) + require.Len(t, result.Ok.Messages, 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") - - 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, "hackatom", ev.Type) + assert.Len(t, ev.Attributes, 1) + assert.Equal(t, "action", ev.Attributes[0].Key) + assert.Equal(t, "release", ev.Attributes[0].Value) + + cosmosMsg := result.Ok.Messages[0].Msg + require.NotNil(t, cosmosMsg.Bank) + require.NotNil(t, cosmosMsg.Bank.Send) + send := cosmosMsg.Bank.Send assert.Equal(t, "bob", send.ToAddress) assert.Equal(t, balance, send.Amount) - // check the data is properly formatted expectedData := []byte{0xF0, 0x0B, 0xAA} assert.Equal(t, expectedData, result.Ok.Data) } func TestExecutePanic(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) checksum := createCyberpunkContract(t, cache) - maxGas := TESTING_GAS_LIMIT + maxGas := testingGasLimit gasMeter1 := NewMockGasMeter(maxGas) igasMeter1 := types.GasMeter(gasMeter1) - // instantiate it with this store store := NewLookup(gasMeter1) api := NewMockAPI() balance := types.Array[types.Coin]{types.NewCoin(250, "ATOM")} @@ -662,28 +528,25 @@ func TestExecutePanic(t *testing.T) { env := MockEnvBin(t) info := MockInfoBin(t, "creator") - res, _, err := Instantiate(cache, checksum, env, info, []byte(`{}`), &igasMeter1, store, api, &querier, maxGas, TESTING_PRINT_DEBUG) + res, _, err := Instantiate(cache, checksum, env, info, []byte(`{}`), &igasMeter1, store, api, &querier, maxGas, testingPrintDebug) require.NoError(t, err) requireOkResponse(t, res, 0) - // execute a panic gasMeter2 := NewMockGasMeter(maxGas) igasMeter2 := types.GasMeter(gasMeter2) store.SetGasMeter(gasMeter2) info = MockInfoBin(t, "fred") - _, _, err = Execute(cache, checksum, env, info, []byte(`{"panic":{}}`), &igasMeter2, store, api, &querier, maxGas, TESTING_PRINT_DEBUG) + _, _, err = Execute(cache, checksum, env, info, []byte(`{"panic":{}}`), &igasMeter2, store, api, &querier, maxGas, testingPrintDebug) require.ErrorContains(t, err, "RuntimeError: Aborted: panicked at 'This page intentionally faulted'") } func TestExecuteUnreachable(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) checksum := createCyberpunkContract(t, cache) - maxGas := TESTING_GAS_LIMIT + maxGas := testingGasLimit gasMeter1 := NewMockGasMeter(maxGas) igasMeter1 := types.GasMeter(gasMeter1) - // instantiate it with this store store := NewLookup(gasMeter1) api := NewMockAPI() balance := types.Array[types.Coin]{types.NewCoin(250, "ATOM")} @@ -691,27 +554,24 @@ func TestExecuteUnreachable(t *testing.T) { env := MockEnvBin(t) info := MockInfoBin(t, "creator") - res, _, err := Instantiate(cache, checksum, env, info, []byte(`{}`), &igasMeter1, store, api, &querier, maxGas, TESTING_PRINT_DEBUG) + res, _, err := Instantiate(cache, checksum, env, info, []byte(`{}`), &igasMeter1, store, api, &querier, maxGas, testingPrintDebug) require.NoError(t, err) requireOkResponse(t, res, 0) - // execute a panic gasMeter2 := NewMockGasMeter(maxGas) igasMeter2 := types.GasMeter(gasMeter2) store.SetGasMeter(gasMeter2) info = MockInfoBin(t, "fred") - _, _, err = Execute(cache, checksum, env, info, []byte(`{"unreachable":{}}`), &igasMeter2, store, api, &querier, maxGas, TESTING_PRINT_DEBUG) + _, _, err = Execute(cache, checksum, env, info, []byte(`{"unreachable":{}}`), &igasMeter2, store, api, &querier, maxGas, testingPrintDebug) require.ErrorContains(t, err, "RuntimeError: unreachable") } func TestExecuteCpuLoop(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) checksum := createCyberpunkContract(t, cache) - gasMeter1 := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter1 := NewMockGasMeter(testingGasLimit) igasMeter1 := types.GasMeter(gasMeter1) - // instantiate it with this store store := NewLookup(gasMeter1) api := NewMockAPI() querier := DefaultQuerier(MOCK_CONTRACT_ADDR, nil) @@ -719,23 +579,21 @@ func TestExecuteCpuLoop(t *testing.T) { info := MockInfoBin(t, "creator") msg := []byte(`{}`) - start := time.Now() - res, cost, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, cost, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, testingGasLimit, testingPrintDebug) diff := time.Since(start) require.NoError(t, err) requireOkResponse(t, res, 0) assert.Equal(t, uint64(0x79f527), cost.UsedInternally) t.Logf("Time (%d gas): %s\n", cost.UsedInternally, diff) - // execute a cpu loop maxGas := uint64(40_000_000) gasMeter2 := NewMockGasMeter(maxGas) igasMeter2 := types.GasMeter(gasMeter2) store.SetGasMeter(gasMeter2) info = MockInfoBin(t, "fred") start = time.Now() - _, cost, err = Execute(cache, checksum, env, info, []byte(`{"cpu_loop":{}}`), &igasMeter2, store, api, &querier, maxGas, TESTING_PRINT_DEBUG) + _, cost, err = Execute(cache, checksum, env, info, []byte(`{"cpu_loop":{}}`), &igasMeter2, store, api, &querier, maxGas, testingPrintDebug) diff = time.Since(start) require.Error(t, err) assert.Equal(t, cost.UsedInternally, maxGas) @@ -743,13 +601,11 @@ func TestExecuteCpuLoop(t *testing.T) { } func TestExecuteStorageLoop(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) checksum := createCyberpunkContract(t, cache) - gasMeter1 := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter1 := NewMockGasMeter(testingGasLimit) igasMeter1 := types.GasMeter(gasMeter1) - // instantiate it with this store store := NewLookup(gasMeter1) api := NewMockAPI() querier := DefaultQuerier(MOCK_CONTRACT_ADDR, nil) @@ -757,26 +613,24 @@ func TestExecuteStorageLoop(t *testing.T) { info := MockInfoBin(t, "creator") msg := []byte(`{}`) - - res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) requireOkResponse(t, res, 0) - // execute a storage loop maxGas := uint64(40_000_000) gasMeter2 := NewMockGasMeter(maxGas) igasMeter2 := types.GasMeter(gasMeter2) store.SetGasMeter(gasMeter2) info = MockInfoBin(t, "fred") start := time.Now() - _, gasReport, err := Execute(cache, checksum, env, info, []byte(`{"storage_loop":{}}`), &igasMeter2, store, api, &querier, maxGas, TESTING_PRINT_DEBUG) + _, gasReport, err := Execute(cache, checksum, env, info, []byte(`{"storage_loop":{}}`), &igasMeter2, store, api, &querier, maxGas, testingPrintDebug) diff := time.Since(start) require.Error(t, err) t.Logf("StorageLoop Time (%d gas): %s\n", gasReport.UsedInternally, diff) t.Logf("Gas used: %d\n", gasMeter2.GasConsumed()) t.Logf("Wasm gas: %d\n", gasReport.UsedInternally) - // the "sdk gas" * GasMultiplier + the wasm cost should equal the maxGas (or be very close) + // The sum of sdk gas * GasMultiplier + wasm cost should equal maxGas totalCost := gasReport.UsedInternally + gasMeter2.GasConsumed() require.Equal(t, int64(maxGas), int64(totalCost)) } @@ -787,9 +641,8 @@ func BenchmarkContractCall(b *testing.B) { checksum := createCyberpunkContract(b, cache) - gasMeter1 := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter1 := NewMockGasMeter(testingGasLimit) igasMeter1 := types.GasMeter(gasMeter1) - // instantiate it with this store store := NewLookup(gasMeter1) api := NewMockAPI() querier := DefaultQuerier(MOCK_CONTRACT_ADDR, nil) @@ -798,18 +651,18 @@ func BenchmarkContractCall(b *testing.B) { msg := []byte(`{}`) - res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(b, err) requireOkResponse(b, res, 0) b.ResetTimer() for n := 0; n < b.N; n++ { - gasMeter2 := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter2 := NewMockGasMeter(testingGasLimit) 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) + msg := []byte(`{"allocate_large_memory":{"pages":0}}`) + res, _, err = Execute(cache, checksum, env, info, msg, &igasMeter2, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(b, err) requireOkResponse(b, res, 0) } @@ -821,9 +674,8 @@ func Benchmark100ConcurrentContractCalls(b *testing.B) { checksum := createCyberpunkContract(b, cache) - gasMeter1 := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter1 := NewMockGasMeter(testingGasLimit) igasMeter1 := types.GasMeter(gasMeter1) - // instantiate it with this store store := NewLookup(gasMeter1) api := NewMockAPI() querier := DefaultQuerier(MOCK_CONTRACT_ADDR, nil) @@ -832,11 +684,11 @@ func Benchmark100ConcurrentContractCalls(b *testing.B) { msg := []byte(`{}`) - res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(b, err) requireOkResponse(b, res, 0) - const callCount = 100 // Calls per benchmark iteration + const callCount = 100 b.ResetTimer() for n := 0; n < b.N; n++ { @@ -844,15 +696,14 @@ func Benchmark100ConcurrentContractCalls(b *testing.B) { wg.Add(callCount) for i := 0; i < callCount; i++ { go func() { - gasMeter2 := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter2 := NewMockGasMeter(testingGasLimit) 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) - + msg := []byte(`{"allocate_large_memory":{"pages":0}}`) + res, _, err = Execute(cache, checksum, env, info, msg, &igasMeter2, store, api, &querier, testingGasLimit, testingPrintDebug) + assert.NoError(b, err) + assertOkResponse(b, res, 0) wg.Done() }() } @@ -861,14 +712,12 @@ func Benchmark100ConcurrentContractCalls(b *testing.B) { } func TestExecuteUserErrorsInApiCalls(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) checksum := createHackatomContract(t, cache) - maxGas := TESTING_GAS_LIMIT + maxGas := testingGasLimit gasMeter1 := NewMockGasMeter(maxGas) igasMeter1 := types.GasMeter(gasMeter1) - // instantiate it with this store store := NewLookup(gasMeter1) balance := types.Array[types.Coin]{types.NewCoin(250, "ATOM")} querier := DefaultQuerier(MOCK_CONTRACT_ADDR, balance) @@ -877,7 +726,7 @@ func TestExecuteUserErrorsInApiCalls(t *testing.T) { defaultApi := NewMockAPI() msg := []byte(`{"verifier": "fred", "beneficiary": "bob"}`) - res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, defaultApi, &querier, maxGas, TESTING_PRINT_DEBUG) + res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, defaultApi, &querier, maxGas, testingPrintDebug) require.NoError(t, err) requireOkResponse(t, res, 0) @@ -886,63 +735,56 @@ func TestExecuteUserErrorsInApiCalls(t *testing.T) { store.SetGasMeter(gasMeter2) info = MockInfoBin(t, "fred") failingApi := NewMockFailureAPI() - res, _, err = Execute(cache, checksum, env, info, []byte(`{"user_errors_in_api_calls":{}}`), &igasMeter2, store, failingApi, &querier, maxGas, TESTING_PRINT_DEBUG) + res, _, err = Execute(cache, checksum, env, info, []byte(`{"user_errors_in_api_calls":{}}`), &igasMeter2, store, failingApi, &querier, maxGas, testingPrintDebug) require.NoError(t, err) requireOkResponse(t, res, 0) } func TestMigrate(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) checksum := createHackatomContract(t, cache) - gasMeter := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter := NewMockGasMeter(testingGasLimit) igasMeter := types.GasMeter(gasMeter) - // instantiate it with this store store := NewLookup(gasMeter) api := NewMockAPI() balance := types.Array[types.Coin]{types.NewCoin(250, "ATOM")} querier := DefaultQuerier(MOCK_CONTRACT_ADDR, balance) env := MockEnvBin(t) info := MockInfoBin(t, "creator") - msg := []byte(`{"verifier": "fred", "beneficiary": "bob"}`) - res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + msg := []byte(`{"verifier": "fred", "beneficiary": "bob"}`) + res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) requireOkResponse(t, res, 0) - // verifier is fred query := []byte(`{"verifier":{}}`) - data, _, err := Query(cache, checksum, env, query, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + data, _, err := Query(cache, checksum, env, query, &igasMeter, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) var qResult types.QueryResult 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 - _, _, err = Migrate(cache, checksum, env, []byte(`{"verifier":"alice"}`), &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + _, _, err = Migrate(cache, checksum, env, []byte(`{"verifier":"alice"}`), &igasMeter, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) - // should update verifier to alice - data, _, err = Query(cache, checksum, env, query, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + data, _, err = Query(cache, checksum, env, query, &igasMeter, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) var qResult2 types.QueryResult 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) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) checksum := createHackatomContract(t, cache) // instance1 controlled by fred - gasMeter1 := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter1 := NewMockGasMeter(testingGasLimit) igasMeter1 := types.GasMeter(gasMeter1) store1 := NewLookup(gasMeter1) api := NewMockAPI() @@ -950,19 +792,18 @@ func TestMultipleInstances(t *testing.T) { env := MockEnvBin(t) info := MockInfoBin(t, "regen") msg := []byte(`{"verifier": "fred", "beneficiary": "bob"}`) - res, cost, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store1, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, cost, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store1, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) requireOkResponse(t, res, 0) - // we now count wasm gas charges and db writes assert.Equal(t, uint64(0xb0c2cd), cost.UsedInternally) // instance2 controlled by mary - gasMeter2 := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter2 := NewMockGasMeter(testingGasLimit) igasMeter2 := types.GasMeter(gasMeter2) store2 := NewLookup(gasMeter2) info = MockInfoBin(t, "chrous") msg = []byte(`{"verifier": "mary", "beneficiary": "sue"}`) - res, cost, err = Instantiate(cache, checksum, env, info, msg, &igasMeter2, store2, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, cost, err = Instantiate(cache, checksum, env, info, msg, &igasMeter2, store2, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) requireOkResponse(t, res, 0) assert.Equal(t, uint64(0xb1760a), cost.UsedInternally) @@ -991,13 +832,11 @@ func TestMultipleInstances(t *testing.T) { } func TestSudo(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) checksum := createHackatomContract(t, cache) - gasMeter1 := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter1 := NewMockGasMeter(testingGasLimit) igasMeter1 := types.GasMeter(gasMeter1) - // instantiate it with this store store := NewLookup(gasMeter1) api := NewMockAPI() balance := types.Array[types.Coin]{types.NewCoin(250, "ATOM")} @@ -1006,28 +845,26 @@ func TestSudo(t *testing.T) { info := MockInfoBin(t, "creator") msg := []byte(`{"verifier": "fred", "beneficiary": "bob"}`) - res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) requireOkResponse(t, res, 0) - // call sudo with same store - gasMeter2 := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter2 := NewMockGasMeter(testingGasLimit) igasMeter2 := types.GasMeter(gasMeter2) store.SetGasMeter(gasMeter2) env = MockEnvBin(t) msg = []byte(`{"steal_funds":{"recipient":"community-pool","amount":[{"amount":"700","denom":"gold"}]}}`) - res, _, err = Sudo(cache, checksum, env, msg, &igasMeter2, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, _, err = Sudo(cache, checksum, env, msg, &igasMeter2, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) - // make sure it blindly followed orders var result types.ContractResult err = json.Unmarshal(res, &result) require.NoError(t, err) require.Equal(t, "", result.Err) require.Equal(t, 1, len(result.Ok.Messages)) dispatch := result.Ok.Messages[0].Msg - require.NotNil(t, dispatch.Bank, "%#v", dispatch) - require.NotNil(t, dispatch.Bank.Send, "%#v", dispatch) + require.NotNil(t, dispatch.Bank) + require.NotNil(t, dispatch.Bank.Send) send := dispatch.Bank.Send assert.Equal(t, "community-pool", send.ToAddress) expectedPayout := types.Array[types.Coin]{types.NewCoin(700, "gold")} @@ -1035,13 +872,11 @@ func TestSudo(t *testing.T) { } func TestDispatchSubmessage(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) checksum := createReflectContract(t, cache) - gasMeter1 := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter1 := NewMockGasMeter(testingGasLimit) igasMeter1 := types.GasMeter(gasMeter1) - // instantiate it with this store store := NewLookup(gasMeter1) api := NewMockAPI() querier := DefaultQuerier(MOCK_CONTRACT_ADDR, nil) @@ -1049,11 +884,10 @@ func TestDispatchSubmessage(t *testing.T) { info := MockInfoBin(t, "creator") msg := []byte(`{}`) - res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) requireOkResponse(t, res, 0) - // dispatch a submessage var id uint64 = 1234 payload := types.SubMsg{ ID: id, @@ -1067,14 +901,13 @@ func TestDispatchSubmessage(t *testing.T) { require.NoError(t, err) payloadMsg := []byte(fmt.Sprintf(`{"reflect_sub_msg":{"msgs":[%s]}}`, string(payloadBin))) - gasMeter2 := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter2 := NewMockGasMeter(testingGasLimit) igasMeter2 := types.GasMeter(gasMeter2) store.SetGasMeter(gasMeter2) env = MockEnvBin(t) - res, _, err = Execute(cache, checksum, env, info, payloadMsg, &igasMeter2, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, _, err = Execute(cache, checksum, env, info, payloadMsg, &igasMeter2, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) - // make sure it blindly followed orders var result types.ContractResult err = json.Unmarshal(res, &result) require.NoError(t, err) @@ -1088,13 +921,11 @@ func TestDispatchSubmessage(t *testing.T) { } func TestReplyAndQuery(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) checksum := createReflectContract(t, cache) - gasMeter1 := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter1 := NewMockGasMeter(testingGasLimit) igasMeter1 := types.GasMeter(gasMeter1) - // instantiate it with this store store := NewLookup(gasMeter1) api := NewMockAPI() querier := DefaultQuerier(MOCK_CONTRACT_ADDR, nil) @@ -1102,7 +933,7 @@ func TestReplyAndQuery(t *testing.T) { info := MockInfoBin(t, "creator") msg := []byte(`{}`) - res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) requireOkResponse(t, res, 0) @@ -1127,22 +958,21 @@ func TestReplyAndQuery(t *testing.T) { replyBin, err := json.Marshal(reply) require.NoError(t, err) - gasMeter2 := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter2 := NewMockGasMeter(testingGasLimit) igasMeter2 := types.GasMeter(gasMeter2) store.SetGasMeter(gasMeter2) env = MockEnvBin(t) - res, _, err = Reply(cache, checksum, env, replyBin, &igasMeter2, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, _, err = Reply(cache, checksum, env, replyBin, &igasMeter2, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) requireOkResponse(t, res, 0) - // now query the state to see if it stored the data properly badQuery := []byte(`{"sub_msg_result":{"id":7777}}`) - res, _, err = Query(cache, checksum, env, badQuery, &igasMeter2, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, _, err = Query(cache, checksum, env, badQuery, &igasMeter2, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) requireQueryError(t, res) query := []byte(`{"sub_msg_result":{"id":1234}}`) - res, _, err = Query(cache, checksum, env, query, &igasMeter2, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, _, err = Query(cache, checksum, env, query, &igasMeter2, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) qResult := requireQueryOk(t, res) @@ -1164,6 +994,14 @@ func requireOkResponse(t testing.TB, res []byte, expectedMsgs int) { require.Equal(t, expectedMsgs, len(result.Ok.Messages)) } +func assertOkResponse(t testing.TB, res []byte, expectedMsgs int) { + var result types.ContractResult + err := json.Unmarshal(res, &result) + assert.NoError(t, err) + assert.Equal(t, "", result.Err) + assert.Equal(t, expectedMsgs, len(result.Ok.Messages)) +} + func requireQueryError(t *testing.T, res []byte) { var result types.QueryResult err := json.Unmarshal(res, &result) @@ -1210,12 +1048,12 @@ func createContract(t testing.TB, cache Cache, wasmFile string) []byte { } // 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 { - gasMeter := NewMockGasMeter(TESTING_GAS_LIMIT) +func exec(t *testing.T, cache Cache, checksum []byte, signer types.HumanAddress, store types.KVStore, api *types.GoAPI, querier types.Querier, gasExpected uint64) types.ContractResult { + gasMeter := NewMockGasMeter(testingGasLimit) igasMeter := types.GasMeter(gasMeter) env := MockEnvBin(t) info := MockInfoBin(t, signer) - res, cost, err := Execute(cache, checksum, env, info, []byte(`{"release":{}}`), &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + res, cost, err := Execute(cache, checksum, env, info, []byte(`{"release":{}}`), &igasMeter, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) assert.Equal(t, gasExpected, cost.UsedInternally) @@ -1226,12 +1064,11 @@ func exec(t *testing.T, cache Cache, checksum []byte, signer types.HumanAddress, } func TestQuery(t *testing.T) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) checksum := createHackatomContract(t, cache) // set up contract - gasMeter1 := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter1 := NewMockGasMeter(testingGasLimit) igasMeter1 := types.GasMeter(gasMeter1) store := NewLookup(gasMeter1) api := NewMockAPI() @@ -1239,53 +1076,49 @@ func TestQuery(t *testing.T) { env := MockEnvBin(t) info := MockInfoBin(t, "creator") msg := []byte(`{"verifier": "fred", "beneficiary": "bob"}`) - _, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + _, _, err := Instantiate(cache, checksum, env, info, msg, &igasMeter1, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) // invalid query - gasMeter2 := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter2 := NewMockGasMeter(testingGasLimit) igasMeter2 := types.GasMeter(gasMeter2) store.SetGasMeter(gasMeter2) query := []byte(`{"Raw":{"val":"config"}}`) - data, _, err := Query(cache, checksum, env, query, &igasMeter2, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + data, _, err := Query(cache, checksum, env, query, &igasMeter2, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) var badResult types.QueryResult err = json.Unmarshal(data, &badResult) require.NoError(t, err) - require.Contains(t, badResult.Err, "Error parsing into type hackatom::msg::QueryMsg: unknown variant `Raw`, expected one of") + require.Contains(t, badResult.Err, "unknown variant `Raw`") - // make a valid query - gasMeter3 := NewMockGasMeter(TESTING_GAS_LIMIT) + // valid query + gasMeter3 := NewMockGasMeter(testingGasLimit) igasMeter3 := types.GasMeter(gasMeter3) store.SetGasMeter(gasMeter3) query = []byte(`{"verifier":{}}`) - data, _, err = Query(cache, checksum, env, query, &igasMeter3, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + data, _, err = Query(cache, checksum, env, query, &igasMeter3, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) var qResult types.QueryResult 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) { - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) checksum := createHackatomContract(t, cache) - // set up contract - gasMeter := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter := NewMockGasMeter(testingGasLimit) igasMeter := types.GasMeter(gasMeter) store := NewLookup(gasMeter) api := NewMockAPI() initBalance := types.Array[types.Coin]{types.NewCoin(1234, "ATOM"), types.NewCoin(65432, "ETH")} querier := DefaultQuerier("foobar", initBalance) - // make a valid query to the other address query := []byte(`{"other_balance":{"address":"foobar"}}`) - // TODO The query happens before the contract is initialized. How is this legal? env := MockEnvBin(t) - data, _, err := Query(cache, checksum, env, query, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + data, _, err := Query(cache, checksum, env, query, &igasMeter, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) var qResult types.QueryResult err = json.Unmarshal(data, &qResult) @@ -1304,31 +1137,25 @@ func TestCustomReflectQuerier(t *testing.T) { type QueryMsg struct { Capitalized *CapitalizedQuery `json:"capitalized,omitempty"` - // There are more queries but we don't use them yet - // 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() + cache, _ := withCache(t) checksum := createReflectContract(t, cache) - // set up contract - gasMeter := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter := NewMockGasMeter(testingGasLimit) igasMeter := types.GasMeter(gasMeter) store := NewLookup(gasMeter) api := NewMockAPI() initBalance := types.Array[types.Coin]{types.NewCoin(1234, "ATOM")} querier := DefaultQuerier(MOCK_CONTRACT_ADDR, initBalance) - // we need this to handle the custom requests from the reflect contract innerQuerier := querier.(*MockQuerier) innerQuerier.Custom = ReflectCustom{} - querier = Querier(innerQuerier) + querier = types.Querier(innerQuerier) - // make a valid query to the other address queryMsg := QueryMsg{ Capitalized: &CapitalizedQuery{ Text: "small Frys :)", @@ -1337,7 +1164,7 @@ func TestCustomReflectQuerier(t *testing.T) { query, err := json.Marshal(queryMsg) require.NoError(t, err) env := MockEnvBin(t) - data, _, err := Query(cache, checksum, env, query, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + data, _, err := Query(cache, checksum, env, query, &igasMeter, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) var qResult types.QueryResult err = json.Unmarshal(data, &qResult) @@ -1350,7 +1177,7 @@ func TestCustomReflectQuerier(t *testing.T) { require.Equal(t, "SMALL FRYS :)", response.Text) } -// TestFloats is a port of the float_instrs_are_deterministic test in cosmwasm-vm +// TestFloats verifies deterministic float instructions func TestFloats(t *testing.T) { type Value struct { U32 *uint32 `json:"u32,omitempty"` @@ -1359,29 +1186,27 @@ func TestFloats(t *testing.T) { F64 *uint64 `json:"f64,omitempty"` } - // helper to print the value in the same format as Rust's Debug trait debugStr := func(value Value) string { - if value.U32 != nil { + switch { + case value.U32 != nil: return fmt.Sprintf("U32(%d)", *value.U32) - } else if value.U64 != nil { + case value.U64 != nil: return fmt.Sprintf("U64(%d)", *value.U64) - } else if value.F32 != nil { + case value.F32 != nil: return fmt.Sprintf("F32(%d)", *value.F32) - } else if value.F64 != nil { + case value.F64 != nil: return fmt.Sprintf("F64(%d)", *value.F64) - } else { + default: t.FailNow() return "" } } - cache, cleanup := withCache(t) - defer cleanup() + cache, _ := withCache(t) checksum := createFloaty2(t, cache) - gasMeter := NewMockGasMeter(TESTING_GAS_LIMIT) + gasMeter := NewMockGasMeter(testingGasLimit) igasMeter := types.GasMeter(gasMeter) - // instantiate it with this store store := NewLookup(gasMeter) api := NewMockAPI() querier := DefaultQuerier(MOCK_CONTRACT_ADDR, nil) @@ -1389,7 +1214,7 @@ func TestFloats(t *testing.T) { // query instructions query := []byte(`{"instructions":{}}`) - data, _, err := Query(cache, checksum, env, query, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + data, _, err := Query(cache, checksum, env, query, &igasMeter, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) var qResult types.QueryResult err = json.Unmarshal(data, &qResult) @@ -1398,16 +1223,14 @@ func TestFloats(t *testing.T) { var instructions []string err = json.Unmarshal(qResult.Ok, &instructions) require.NoError(t, err) - // little sanity check require.Equal(t, 70, len(instructions)) hasher := sha256.New() - const RUNS_PER_INSTRUCTION = 150 + const runsPerInstruction = 150 for _, instr := range instructions { - for seed := 0; seed < RUNS_PER_INSTRUCTION; seed++ { - // query some input values for the instruction + for seed := 0; seed < runsPerInstruction; seed++ { msg := fmt.Sprintf(`{"random_args_for":{"instruction":"%s","seed":%d}}`, instr, seed) - data, _, err = Query(cache, checksum, env, []byte(msg), &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) + data, _, err = Query(cache, checksum, env, []byte(msg), &igasMeter, store, api, &querier, testingGasLimit, testingPrintDebug) require.NoError(t, err) err = json.Unmarshal(data, &qResult) require.NoError(t, err) @@ -1416,19 +1239,15 @@ func TestFloats(t *testing.T) { err = json.Unmarshal(qResult.Ok, &args) require.NoError(t, err) - // build the run message argStr, err := json.Marshal(args) require.NoError(t, err) msg = fmt.Sprintf(`{"run":{"instruction":"%s","args":%s}}`, instr, argStr) - // run the instruction - // this might throw a runtime error (e.g. if the instruction traps) - data, _, err = Query(cache, checksum, env, []byte(msg), &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG) - var result string + data, _, err = Query(cache, checksum, env, []byte(msg), &igasMeter, store, api, &querier, testingGasLimit, testingPrintDebug) + var resultStr string if err != nil { - assert.ErrorContains(t, err, "Error calling the VM: Error executing Wasm: ") - // 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) + // Remove prefix to match cosmwasm-vm test expectations + resultStr = strings.Replace(err.Error(), "Error calling the VM: Error executing Wasm: ", "", 1) } else { err = json.Unmarshal(data, &qResult) require.NoError(t, err) @@ -1436,13 +1255,21 @@ func TestFloats(t *testing.T) { var response Value err = json.Unmarshal(qResult.Ok, &response) require.NoError(t, err) - result = debugStr(response) + resultStr = debugStr(response) } - // add the result to the hash - hasher.Write([]byte(fmt.Sprintf("%s%d%s", instr, seed, result))) + hasher.Write([]byte(fmt.Sprintf("%s%d%s", instr, seed, resultStr))) } } hash := hasher.Sum(nil) require.Equal(t, "95f70fa6451176ab04a9594417a047a1e4d8e2ff809609b8f81099496bee2393", hex.EncodeToString(hash)) } + +func MockInfoBinNoAssert(t testing.TB, sender string) []byte { + info := MockInfo(sender, nil) + bin, err := json.Marshal(info) + if err != nil { + t.Fatal(err) + } + return bin +} diff --git a/internal/api/memory_test.go b/internal/api/memory_test.go index 397faf50..b6fc95d3 100644 --- a/internal/api/memory_test.go +++ b/internal/api/memory_test.go @@ -23,55 +23,55 @@ func TestMakeView(t *testing.T) { } func TestCreateAndDestroyUnmanagedVector(t *testing.T) { - // non-empty + // Non-empty vector { original := []byte{0xaa, 0xbb, 0x64} unmanaged := newUnmanagedVector(original) require.Equal(t, cbool(false), unmanaged.is_none) require.Equal(t, 3, int(unmanaged.len)) - require.GreaterOrEqual(t, 3, int(unmanaged.cap)) // Rust implementation decides this + require.GreaterOrEqual(t, 3, int(unmanaged.cap)) // Rust implementation decides cap copy := copyAndDestroyUnmanagedVector(unmanaged) require.Equal(t, original, copy) } - // empty + // Empty vector { original := []byte{} unmanaged := newUnmanagedVector(original) require.Equal(t, cbool(false), unmanaged.is_none) require.Equal(t, 0, int(unmanaged.len)) - require.GreaterOrEqual(t, 0, int(unmanaged.cap)) // Rust implementation decides this + require.GreaterOrEqual(t, 0, int(unmanaged.cap)) // Rust implementation decides cap copy := copyAndDestroyUnmanagedVector(unmanaged) require.Equal(t, original, copy) } - // none + // None (nil slice) { var original []byte unmanaged := newUnmanagedVector(original) require.Equal(t, cbool(true), unmanaged.is_none) - // We must not make assumptions on the other fields in this case + // Fields other than is_none are not guaranteed in this scenario copy := copyAndDestroyUnmanagedVector(unmanaged) require.Nil(t, copy) } } -// Like the test above but without `newUnmanagedVector` calls. -// Since only Rust can actually create them, we only test edge cases here. +// TestCopyDestroyUnmanagedVector checks edge cases without newUnmanagedVector calls. // //go:nocheckptr func TestCopyDestroyUnmanagedVector(t *testing.T) { + // If is_none is true, do not access pointer, len, or cap values { - // ptr, cap and len broken. Do not access those values when is_none is true - invalid_ptr := unsafe.Pointer(uintptr(42)) - uv := constructUnmanagedVector(cbool(true), cu8_ptr(invalid_ptr), cusize(0xBB), cusize(0xAA)) + invalidPtr := unsafe.Pointer(uintptr(42)) + uv := constructUnmanagedVector(cbool(true), cu8_ptr(invalidPtr), cusize(0xBB), cusize(0xAA)) copy := copyAndDestroyUnmanagedVector(uv) require.Nil(t, copy) } + + // Capacity is 0, so no allocation happened. Do not access the pointer. { - // Capacity is 0, so no allocation happened. Do not access the pointer. - invalid_ptr := unsafe.Pointer(uintptr(42)) - uv := constructUnmanagedVector(cbool(false), cu8_ptr(invalid_ptr), cusize(0), cusize(0)) + invalidPtr := unsafe.Pointer(uintptr(42)) + uv := constructUnmanagedVector(cbool(false), cu8_ptr(invalidPtr), cusize(0), cusize(0)) copy := copyAndDestroyUnmanagedVector(uv) require.Equal(t, []byte{}, copy) } diff --git a/internal/api/mocks.go b/internal/api/mocks.go index ac8500dd..c0f02423 100644 --- a/internal/api/mocks.go +++ b/internal/api/mocks.go @@ -391,7 +391,7 @@ func TestMockApi(t *testing.T) { human := "foobar" canon, cost, err := MockCanonicalizeAddress(human) require.NoError(t, err) - assert.Equal(t, CanonicalLength, len(canon)) + assert.Len(t, canon, CanonicalLength) assert.Equal(t, CostCanonical, cost) recover, cost, err := MockHumanizeAddress(canon) @@ -639,7 +639,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 +649,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 038b1de1..3e809b83 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 4c25f69a..85cff56b 100644 --- a/lib_libwasmvm_test.go +++ b/lib_libwasmvm_test.go @@ -187,7 +187,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 +198,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 +231,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,7 +311,7 @@ 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() @@ -328,7 +328,7 @@ 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() @@ -358,7 +358,7 @@ 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() @@ -392,7 +392,7 @@ 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() diff --git a/types/env_test.go b/types/env_test.go index 4bae5038..076a209e 100644 --- a/types/env_test.go +++ b/types/env_test.go @@ -60,16 +60,16 @@ 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, - Time: 0, - ChainID: "", + 0, + 0, + "", } 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 8c17b558..a4d32f4f 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 f5691592..fa0c7061 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 8dd52dc8..1b437c91 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) @@ -165,11 +165,8 @@ func TestDistributionQuerySerialization(t *testing.T) { var query DistributionQuery err = json.Unmarshal(document, &query) require.NoError(t, err) - require.Equal(t, query, DistributionQuery{ - DelegatorWithdrawAddress: &DelegatorWithdrawAddressQuery{ - DelegatorAddress: "jane", - }, - }) + require.NotNil(t, query.DelegatorWithdrawAddress) + require.Equal(t, "jane", query.DelegatorWithdrawAddress.DelegatorAddress) // Serialization res := DelegatorWithdrawAddressResponse{ @@ -177,7 +174,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 +197,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 5f3ec18a..c9f1883f 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,