From 9404e321a39833f97dfb6a802663d60ff9f037ab Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Sun, 22 Dec 2024 19:09:14 +0700 Subject: [PATCH 01/19] testifylint execpt for the MockInfoBin --- .golangci.yml | 12 ++-- ibc_test.go | 6 +- internal/api/iterator_test.go | 7 +-- internal/api/lib_test.go | 112 ++++++++++++++++++---------------- internal/api/mocks.go | 12 ++-- internal/api/version_test.go | 3 +- lib_libwasmvm_test.go | 26 ++++---- types/env_test.go | 4 +- types/ibc_test.go | 6 +- types/msg_test.go | 6 +- types/queries_test.go | 12 ++-- types/submessages_test.go | 6 +- types/systemerror_test.go | 4 +- 13 files changed, 111 insertions(+), 105 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 3af894222..8ba457557 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,10 +1,14 @@ +run: + tests: true + linters: # Enable specific linter # https://golangci-lint.run/usage/linters/#enabled-by-default enable: - gofumpt - - goimports + - gci + - testifylint -linters-settings: - goimports: - local-prefixes: github.com/CosmWasm/wasmvm +issues: + max-issues-per-linter: 0 + max-same-issues: 0 diff --git a/ibc_test.go b/ibc_test.go index 2da754d14..4e2a7cf42 100644 --- a/ibc_test.go +++ b/ibc_test.go @@ -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{{ @@ -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/iterator_test.go b/internal/api/iterator_test.go index 0c81db775..bcf2b6290 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" @@ -202,14 +201,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) @@ -256,7 +255,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..706690202 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) { @@ -363,7 +366,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 +377,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 +393,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 +406,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 +418,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,11 +433,11 @@ 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) - require.Equal(t, uint64(1), metrics.ElementsPinnedMemoryCache) + require.Equal(t, uint64(0), 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) @@ -445,7 +448,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 +464,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 +481,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 +517,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 +542,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 +576,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 +607,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 +620,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 +628,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 +727,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 +740,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 +809,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) @@ -919,7 +923,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 +937,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 +978,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 +1028,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 +1083,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,12 +1160,12 @@ 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) { 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) { @@ -1265,7 +1269,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) { @@ -1394,12 +1398,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 +1415,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 +1430,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) diff --git a/internal/api/mocks.go b/internal/api/mocks.go index ac8500dd8..ba64aaabc 100644 --- a/internal/api/mocks.go +++ b/internal/api/mocks.go @@ -391,13 +391,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 +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 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..7d56eabac 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,11 +311,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 +328,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 +344,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 +358,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 +377,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 +392,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)) } From 3eb0c979047b839172f4f575331c9ee25d01cf92 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Sun, 22 Dec 2024 19:26:03 +0700 Subject: [PATCH 02/19] gci'd --- ibc_test.go | 5 ++--- internal/api/api_test.go | 3 +-- internal/api/iterator_test.go | 3 +-- internal/api/lib.go | 3 +-- internal/api/lib_test.go | 3 +-- internal/api/mocks.go | 5 ++--- lib_libwasmvm_test.go | 5 ++--- lib_test.go | 3 +-- 8 files changed, 11 insertions(+), 19 deletions(-) diff --git a/ibc_test.go b/ibc_test.go index 4e2a7cf42..3260d5e53 100644 --- a/ibc_test.go +++ b/ibc_test.go @@ -7,11 +7,10 @@ import ( "os" "testing" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/CosmWasm/wasmvm/v2/internal/api" "github.com/CosmWasm/wasmvm/v2/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const IBC_TEST_CONTRACT = "./testdata/ibc_reflect.wasm" diff --git a/internal/api/api_test.go b/internal/api/api_test.go index 1d8109857..7b6c6eec1 100644 --- a/internal/api/api_test.go +++ b/internal/api/api_test.go @@ -5,9 +5,8 @@ import ( "os" "testing" - "github.com/stretchr/testify/require" - "github.com/CosmWasm/wasmvm/v2/types" + "github.com/stretchr/testify/require" ) func TestValidateAddressFailure(t *testing.T) { diff --git a/internal/api/iterator_test.go b/internal/api/iterator_test.go index bcf2b6290..d5912338e 100644 --- a/internal/api/iterator_test.go +++ b/internal/api/iterator_test.go @@ -6,10 +6,9 @@ import ( "sync" "testing" - "github.com/stretchr/testify/require" - "github.com/CosmWasm/wasmvm/v2/internal/api/testdb" "github.com/CosmWasm/wasmvm/v2/types" + "github.com/stretchr/testify/require" ) type queueData struct { diff --git a/internal/api/lib.go b/internal/api/lib.go index 2b71adc1c..73a922930 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -13,9 +13,8 @@ import ( "strings" "syscall" - "golang.org/x/sys/unix" - "github.com/CosmWasm/wasmvm/v2/types" + "golang.org/x/sys/unix" ) // Value types diff --git a/internal/api/lib_test.go b/internal/api/lib_test.go index 706690202..ccb0b7c02 100644 --- a/internal/api/lib_test.go +++ b/internal/api/lib_test.go @@ -13,10 +13,9 @@ import ( "testing" "time" + "github.com/CosmWasm/wasmvm/v2/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - - "github.com/CosmWasm/wasmvm/v2/types" ) const ( diff --git a/internal/api/mocks.go b/internal/api/mocks.go index ba64aaabc..c7043f208 100644 --- a/internal/api/mocks.go +++ b/internal/api/mocks.go @@ -8,11 +8,10 @@ import ( "strings" "testing" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/CosmWasm/wasmvm/v2/internal/api/testdb" "github.com/CosmWasm/wasmvm/v2/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) /** helper constructors **/ diff --git a/lib_libwasmvm_test.go b/lib_libwasmvm_test.go index 7d56eabac..02abce36f 100644 --- a/lib_libwasmvm_test.go +++ b/lib_libwasmvm_test.go @@ -9,11 +9,10 @@ import ( "os" "testing" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/CosmWasm/wasmvm/v2/internal/api" "github.com/CosmWasm/wasmvm/v2/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const ( diff --git a/lib_test.go b/lib_test.go index 35094e7df..54b2d3293 100644 --- a/lib_test.go +++ b/lib_test.go @@ -3,9 +3,8 @@ package cosmwasm import ( "testing" - "github.com/stretchr/testify/require" - "github.com/CosmWasm/wasmvm/v2/types" + "github.com/stretchr/testify/require" ) func TestCreateChecksum(t *testing.T) { From 64e241eb37022b27d0f5d729cf761e2d011285de Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Sun, 22 Dec 2024 19:30:33 +0700 Subject: [PATCH 03/19] continue test cleanup --- ibc_test.go | 4 ++-- lib_libwasmvm_test.go | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/ibc_test.go b/ibc_test.go index 3260d5e53..d095871aa 100644 --- a/ibc_test.go +++ b/ibc_test.go @@ -108,7 +108,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) @@ -199,7 +199,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) diff --git a/lib_libwasmvm_test.go b/lib_libwasmvm_test.go index 02abce36f..8633f7036 100644 --- a/lib_libwasmvm_test.go +++ b/lib_libwasmvm_test.go @@ -127,10 +127,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") } }) } From 675f892664417aff323568d8499d03dd9cacd32c Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Sun, 22 Dec 2024 19:33:56 +0700 Subject: [PATCH 04/19] gci is much better than goimports --- .golangci.yml | 27 +++++++++++++++++++++++++++ ibc_test.go | 5 +++-- internal/api/api_test.go | 3 ++- internal/api/iterator_test.go | 3 ++- internal/api/lib.go | 3 ++- internal/api/lib_test.go | 3 ++- internal/api/mocks.go | 5 +++-- lib_libwasmvm_test.go | 5 +++-- lib_test.go | 3 ++- 9 files changed, 46 insertions(+), 11 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 8ba457557..a1be8e233 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -9,6 +9,33 @@ linters: - gci - testifylint +linters-settings: + 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 d095871aa..76987c9cc 100644 --- a/ibc_test.go +++ b/ibc_test.go @@ -7,10 +7,11 @@ import ( "os" "testing" - "github.com/CosmWasm/wasmvm/v2/internal/api" - "github.com/CosmWasm/wasmvm/v2/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/CosmWasm/wasmvm/v2/internal/api" + "github.com/CosmWasm/wasmvm/v2/types" ) const IBC_TEST_CONTRACT = "./testdata/ibc_reflect.wasm" diff --git a/internal/api/api_test.go b/internal/api/api_test.go index 7b6c6eec1..1d8109857 100644 --- a/internal/api/api_test.go +++ b/internal/api/api_test.go @@ -5,8 +5,9 @@ import ( "os" "testing" - "github.com/CosmWasm/wasmvm/v2/types" "github.com/stretchr/testify/require" + + "github.com/CosmWasm/wasmvm/v2/types" ) func TestValidateAddressFailure(t *testing.T) { diff --git a/internal/api/iterator_test.go b/internal/api/iterator_test.go index d5912338e..bcf2b6290 100644 --- a/internal/api/iterator_test.go +++ b/internal/api/iterator_test.go @@ -6,9 +6,10 @@ import ( "sync" "testing" + "github.com/stretchr/testify/require" + "github.com/CosmWasm/wasmvm/v2/internal/api/testdb" "github.com/CosmWasm/wasmvm/v2/types" - "github.com/stretchr/testify/require" ) type queueData struct { diff --git a/internal/api/lib.go b/internal/api/lib.go index 73a922930..2b71adc1c 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -13,8 +13,9 @@ import ( "strings" "syscall" - "github.com/CosmWasm/wasmvm/v2/types" "golang.org/x/sys/unix" + + "github.com/CosmWasm/wasmvm/v2/types" ) // Value types diff --git a/internal/api/lib_test.go b/internal/api/lib_test.go index ccb0b7c02..706690202 100644 --- a/internal/api/lib_test.go +++ b/internal/api/lib_test.go @@ -13,9 +13,10 @@ import ( "testing" "time" - "github.com/CosmWasm/wasmvm/v2/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/CosmWasm/wasmvm/v2/types" ) const ( diff --git a/internal/api/mocks.go b/internal/api/mocks.go index c7043f208..ba64aaabc 100644 --- a/internal/api/mocks.go +++ b/internal/api/mocks.go @@ -8,10 +8,11 @@ import ( "strings" "testing" - "github.com/CosmWasm/wasmvm/v2/internal/api/testdb" - "github.com/CosmWasm/wasmvm/v2/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/CosmWasm/wasmvm/v2/internal/api/testdb" + "github.com/CosmWasm/wasmvm/v2/types" ) /** helper constructors **/ diff --git a/lib_libwasmvm_test.go b/lib_libwasmvm_test.go index 8633f7036..15b587fec 100644 --- a/lib_libwasmvm_test.go +++ b/lib_libwasmvm_test.go @@ -9,10 +9,11 @@ import ( "os" "testing" - "github.com/CosmWasm/wasmvm/v2/internal/api" - "github.com/CosmWasm/wasmvm/v2/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/CosmWasm/wasmvm/v2/internal/api" + "github.com/CosmWasm/wasmvm/v2/types" ) const ( diff --git a/lib_test.go b/lib_test.go index 54b2d3293..35094e7df 100644 --- a/lib_test.go +++ b/lib_test.go @@ -3,8 +3,9 @@ package cosmwasm import ( "testing" - "github.com/CosmWasm/wasmvm/v2/types" "github.com/stretchr/testify/require" + + "github.com/CosmWasm/wasmvm/v2/types" ) func TestCreateChecksum(t *testing.T) { From 1921179466c5e26f93905a7f23ea14c323356e71 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Sun, 22 Dec 2024 19:34:54 +0700 Subject: [PATCH 05/19] use latest linter --- .github/workflows/lint-go.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From f8005f89c8238c1273744316b9c999db23450f47 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Sun, 22 Dec 2024 19:41:17 +0700 Subject: [PATCH 06/19] resolve issues with goroutine --- internal/api/lib_test.go | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/internal/api/lib_test.go b/internal/api/lib_test.go index 706690202..1727cbfae 100644 --- a/internal/api/lib_test.go +++ b/internal/api/lib_test.go @@ -845,22 +845,33 @@ 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) + testMutex.Lock() + info = MockInfoBin(b, "fred") + testMutex.Unlock() 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) + } } } @@ -1312,10 +1323,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) @@ -1354,6 +1361,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 { From 445f165fcb0e812646d845a3ad7bb63579c904c1 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Sun, 22 Dec 2024 19:51:58 +0700 Subject: [PATCH 07/19] enable errcheck and thelper linters --- .golangci.yml | 2 ++ ibc_test.go | 1 + internal/api/iterator_test.go | 3 ++ internal/api/lib_test.go | 60 ++++++++++++++++++++++++----------- internal/api/mocks.go | 10 +++--- lib_libwasmvm_test.go | 2 ++ 6 files changed, 55 insertions(+), 23 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index a1be8e233..fd168cf9a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -8,6 +8,8 @@ linters: - gofumpt - gci - testifylint + - errcheck + - thelper linters-settings: gci: diff --git a/ibc_test.go b/ibc_test.go index 76987c9cc..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 diff --git a/internal/api/iterator_test.go b/internal/api/iterator_test.go index bcf2b6290..a543124cd 100644 --- a/internal/api/iterator_test.go +++ b/internal/api/iterator_test.go @@ -24,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) @@ -58,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) } @@ -216,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) diff --git a/internal/api/lib_test.go b/internal/api/lib_test.go index 1727cbfae..ed760c9fc 100644 --- a/internal/api/lib_test.go +++ b/internal/api/lib_test.go @@ -194,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, @@ -206,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) @@ -848,9 +849,7 @@ func Benchmark100ConcurrentContractCalls(b *testing.B) { errChan := make(chan error, callCount) resChan := make(chan []byte, callCount) wg.Add(callCount) - testMutex.Lock() - info = MockInfoBin(b, "fred") - testMutex.Unlock() + info = mockInfoBinNoAssert("fred") for i := 0; i < callCount; i++ { go func() { defer wg.Done() @@ -1172,6 +1171,7 @@ func TestReplyAndQuery(t *testing.T) { } func requireOkResponse(tb testing.TB, res []byte, expectedMsgs int) { + tb.Helper() var result types.ContractResult err := json.Unmarshal(res, &result) require.NoError(tb, err) @@ -1180,6 +1180,7 @@ func requireOkResponse(tb testing.TB, res []byte, expectedMsgs int) { } func requireQueryError(t *testing.T, res []byte) { + t.Helper() var result types.QueryResult err := json.Unmarshal(res, &result) require.NoError(t, err) @@ -1188,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) @@ -1196,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) @@ -1461,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 ba64aaabc..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 } diff --git a/lib_libwasmvm_test.go b/lib_libwasmvm_test.go index 15b587fec..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) From fdaf809691ea6417e46d484453083de44ac75db5 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Sun, 22 Dec 2024 20:03:38 +0700 Subject: [PATCH 08/19] enable additional linters --- .github/workflows/lint-go.yml | 2 +- .golangci.yml | 47 +++++++++++++++++++++++++++++++---- cmd/demo/main.go | 2 +- go.mod | 2 +- ibc_test.go | 2 +- internal/api/iterator.go | 6 ++--- internal/api/lib_test.go | 8 +++--- internal/api/mocks.go | 8 +++--- internal/api/testdb/memdb.go | 2 +- lib.go | 10 ++++---- lib_libwasmvm.go | 22 ++++++++-------- types/ibc.go | 10 ++++---- types/msg.go | 6 ++--- types/queries.go | 24 +++++++++--------- types/submessages.go | 2 +- types/systemerror.go | 2 +- types/types.go | 18 +++++++------- 17 files changed, 105 insertions(+), 68 deletions(-) diff --git a/.github/workflows/lint-go.yml b/.github/workflows/lint-go.yml index e901160ec..3893e0165 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.23" cache: false - name: golangci-lint uses: golangci/golangci-lint-action@v3.6.0 diff --git a/.golangci.yml b/.golangci.yml index fd168cf9a..132c69402 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,15 +1,36 @@ run: tests: true + timeout: 5m + skip-dirs: + - vendor/ + - third_party/ linters: # Enable specific linter # https://golangci-lint.run/usage/linters/#enabled-by-default enable: - - gofumpt - - gci - - testifylint - - errcheck - - thelper + - errcheck # Detect unchecked errors + - gosimple # Simplify code + - govet # Reports suspicious constructs + - ineffassign # Detect unused assignments + - staticcheck # Go static analysis + - typecheck # Go type checker + - unused # Detect unused constants, variables, functions and types + + # Additional recommended linters + - gocritic # A more opinionated linter + - gosec # Security checker + - misspell # Find commonly misspelled words + - revive # a metalinter with more checks + - bodyclose # Check HTTP response bodies are closed + - dupl # Code clone detector + - goconst # Find repeated strings that could be constants + - gocyclo # Check function complexity + - godot # Check comment endings + - gocognit # Check cognitive complexity + - whitespace # Check trailing whitespace + - thelper # Detect test helpers not using t.Helper() + - tparallel # Detect incorrect usage of t.Parallel() linters-settings: gci: @@ -37,7 +58,23 @@ linters-settings: # Drops lexical ordering for custom sections. # Default: false no-lex-order: true + gocyclo: + min-complexity: 15 + gocognit: + min-complexity: 20 + dupl: + threshold: 100 + goconst: + min-len: 3 + min-occurrences: 3 + revive: + rules: + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#var-naming + - name: var-naming + severity: warning + disabled: true issues: + exclude-use-default: false max-issues-per-linter: 0 max-same-issues: 0 diff --git a/cmd/demo/main.go b/cmd/demo/main.go index 58286e782..8afbfe650 100644 --- a/cmd/demo/main.go +++ b/cmd/demo/main.go @@ -16,7 +16,7 @@ const ( var SUPPORTED_CAPABILITIES = []string{"staking"} -// This is just a demo to ensure we can compile a static go binary +// This is just a demo to ensure we can compile a static go binary. func main() { file := os.Args[1] diff --git a/go.mod b/go.mod index b8a003356..16083455d 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/CosmWasm/wasmvm/v2 -go 1.21 +go 1.23 require ( github.com/google/btree v1.0.0 diff --git a/ibc_test.go b/ibc_test.go index 4992ee50b..f47b5cc75 100644 --- a/ibc_test.go +++ b/ibc_test.go @@ -70,7 +70,7 @@ type AccountInfo struct { ChannelID string `json:"channel_id"` } -// We just check if an error is returned or not +// We just check if an error is returned or not. type AcknowledgeDispatch struct { Err string `json:"error"` } diff --git a/internal/api/iterator.go b/internal/api/iterator.go index c9a768b40..0b3c9cf7b 100644 --- a/internal/api/iterator.go +++ b/internal/api/iterator.go @@ -8,7 +8,7 @@ import ( "github.com/CosmWasm/wasmvm/v2/types" ) -// frame stores all Iterators for one contract call +// frame stores all Iterators for one contract call. type frame []types.Iterator // iteratorFrames contains one frame for each contract call, indexed by contract call ID. @@ -17,7 +17,7 @@ var ( iteratorFramesMutex sync.Mutex ) -// this is a global counter for creating call IDs +// this is a global counter for creating call IDs. var ( latestCallID uint64 latestCallIDMutex sync.Mutex @@ -44,7 +44,7 @@ func removeFrame(callID uint64) frame { return remove } -// endCall is called at the end of a contract call to remove one item the iteratorFrames +// endCall is called at the end of a contract call to remove one item the iteratorFrames. func endCall(callID uint64) { // we pull removeFrame in another function so we don't hold the mutex while cleaning up the removed frame remove := removeFrame(callID) diff --git a/internal/api/lib_test.go b/internal/api/lib_test.go index ed760c9fc..7e2e48868 100644 --- a/internal/api/lib_test.go +++ b/internal/api/lib_test.go @@ -26,7 +26,7 @@ const ( TESTING_CACHE_SIZE = 100 // MiB ) -// Add mutex for thread safety +// 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"} @@ -1232,7 +1232,7 @@ func createContract(tb testing.TB, cache Cache, wasmFile string) []byte { return checksum } -// exec runs the handle tx with the given signer +// 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) @@ -1374,7 +1374,7 @@ type CapitalizedResponse struct { Text string `json:"text"` } -// TestFloats is a port of the float_instrs_are_deterministic test in cosmwasm-vm +// TestFloats is a port of the float_instrs_are_deterministic test in cosmwasm-vm. func TestFloats(t *testing.T) { type Value struct { U32 *uint32 `json:"u32,omitempty"` @@ -1471,7 +1471,7 @@ func TestFloats(t *testing.T) { require.Equal(t, "95f70fa6451176ab04a9594417a047a1e4d8e2ff809609b8f81099496bee2393", hex.EncodeToString(hash)) } -// mockInfoBinNoAssert creates the message binary without using testify assertions +// mockInfoBinNoAssert creates the message binary without using testify assertions. func mockInfoBinNoAssert(sender types.HumanAddress) []byte { info := types.MessageInfo{ Sender: sender, diff --git a/internal/api/mocks.go b/internal/api/mocks.go index 7f8547308..b8a249ac0 100644 --- a/internal/api/mocks.go +++ b/internal/api/mocks.go @@ -248,7 +248,7 @@ func (g *mockGasMeter) ConsumeGas(amount types.Gas, descriptor string) { // Note: these gas prices are all in *wasmer gas* and (sdk gas * 100) // // We making simple values and non-clear multiples so it is easy to see their impact in test output -// Also note we do not charge for each read on an iterator (out of simplicity and not needed for tests) +// Also note we do not charge for each read on an iterator (out of simplicity and not needed for tests). const ( GetPrice uint64 = 99000 SetPrice uint64 = 187000 @@ -502,7 +502,7 @@ func (q NoCustom) Query(request json.RawMessage) ([]byte, error) { return nil, types.UnsupportedRequest{Kind: "custom"} } -// ReflectCustom fulfills the requirements for testing `reflect` contract +// ReflectCustom fulfills the requirements for testing `reflect` contract. type ReflectCustom struct{} var _ CustomQuerier = ReflectCustom{} @@ -516,7 +516,7 @@ type CapitalizedQuery struct { Text string `json:"text"` } -// CustomResponse is the response for all `CustomQuery`s +// CustomResponse is the response for all `CustomQuery`s. type CustomResponse struct { Msg string `json:"msg"` } @@ -538,7 +538,7 @@ func (q ReflectCustom) Query(request json.RawMessage) ([]byte, error) { return json.Marshal(resp) } -//************ test code for mocks *************************// +// ************ test code for mocks *************************// func TestBankQuerierAllBalances(t *testing.T) { addr := "foobar" diff --git a/internal/api/testdb/memdb.go b/internal/api/testdb/memdb.go index 5e667ced7..212d506ea 100644 --- a/internal/api/testdb/memdb.go +++ b/internal/api/testdb/memdb.go @@ -13,7 +13,7 @@ const ( bTreeDegree = 32 ) -// item is a btree.Item with byte slices as keys and values +// item is a btree.Item with byte slices as keys and values. type item struct { key []byte value []byte diff --git a/lib.go b/lib.go index 458af0740..a9b90d946 100644 --- a/lib.go +++ b/lib.go @@ -14,19 +14,19 @@ import ( // Checksum represents a hash of the Wasm bytecode that serves as an ID. Must be generated from this library. type Checksum = types.Checksum -// WasmCode is an alias for raw bytes of the wasm compiled code +// WasmCode is an alias for raw bytes of the wasm compiled code. type WasmCode []byte -// KVStore is a reference to some sub-kvstore that is valid for one instance of a code +// KVStore is a reference to some sub-kvstore that is valid for one instance of a code. type KVStore = types.KVStore -// GoAPI is a reference to some "precompiles", go callbacks +// GoAPI is a reference to some "precompiles", go callbacks. type GoAPI = types.GoAPI -// Querier lets us make read-only queries on other modules +// Querier lets us make read-only queries on other modules. type Querier = types.Querier -// GasMeter is a read-only version of the sdk gas meter +// GasMeter is a read-only version of the sdk gas meter. type GasMeter = types.GasMeter // LibwasmvmVersion returns the version of the loaded library diff --git a/lib_libwasmvm.go b/lib_libwasmvm.go index 3f66b71ea..ad300f558 100644 --- a/lib_libwasmvm.go +++ b/lib_libwasmvm.go @@ -128,7 +128,7 @@ func (vm *VM) Unpin(checksum Checksum) error { // Returns a report of static analysis of the wasm contract (uncompiled). // This contract must have been stored in the cache previously (via Create). -// Only info currently returned is if it exposes all ibc entry points, but this may grow later +// Only info currently returned is if it exposes all ibc entry points, but this may grow later. func (vm *VM) AnalyzeCode(checksum Checksum) (*types.AnalysisReport, error) { return api.AnalyzeCode(vm.cache, checksum) } @@ -190,7 +190,7 @@ func (vm *VM) Instantiate( // (That is a detail for the external, sdk-facing, side). // // The caller is responsible for passing the correct `store` (which must have been initialized exactly once), -// and setting the env with relevant info on this instance (address, balance, etc) +// and setting the env with relevant info on this instance (address, balance, etc). func (vm *VM) Execute( checksum Checksum, env types.Env, @@ -226,7 +226,7 @@ func (vm *VM) Execute( // Query allows a client to execute a contract-specific query. If the result is not empty, it should be // valid json-encoded data to return to the client. -// The meaning of path and data can be determined by the code. Path is the suffix of the abci.QueryRequest.Path +// The meaning of path and data can be determined by the code. Path is the suffix of the abci.QueryRequest.Path. func (vm *VM) Query( checksum Checksum, env types.Env, @@ -370,7 +370,7 @@ func (vm *VM) Sudo( // Reply allows the native Go wasm modules to make a privileged call to return the result // of executing a SubMsg. // -// These work much like Sudo (same scenario) but focuses on one specific case (and one message type) +// These work much like Sudo (same scenario) but focuses on one specific case (and one message type). func (vm *VM) Reply( checksum Checksum, env types.Env, @@ -404,7 +404,7 @@ func (vm *VM) Reply( } // IBCChannelOpen is available on IBC-enabled contracts and is a hook to call into -// during the handshake pahse +// during the handshake pahse. func (vm *VM) IBCChannelOpen( checksum Checksum, env types.Env, @@ -438,7 +438,7 @@ func (vm *VM) IBCChannelOpen( } // IBCChannelConnect is available on IBC-enabled contracts and is a hook to call into -// during the handshake pahse +// during the handshake pahse. func (vm *VM) IBCChannelConnect( checksum Checksum, env types.Env, @@ -472,7 +472,7 @@ func (vm *VM) IBCChannelConnect( } // IBCChannelClose is available on IBC-enabled contracts and is a hook to call into -// at the end of the channel lifetime +// at the end of the channel lifetime. func (vm *VM) IBCChannelClose( checksum Checksum, env types.Env, @@ -506,7 +506,7 @@ func (vm *VM) IBCChannelClose( } // IBCPacketReceive is available on IBC-enabled contracts and is called when an incoming -// packet is received on a channel belonging to this contract +// packet is received on a channel belonging to this contract. func (vm *VM) IBCPacketReceive( checksum Checksum, env types.Env, @@ -541,7 +541,7 @@ func (vm *VM) IBCPacketReceive( // IBCPacketAck is available on IBC-enabled contracts and is called when an // the response for an outgoing packet (previously sent by this contract) -// is received +// is received. func (vm *VM) IBCPacketAck( checksum Checksum, env types.Env, @@ -576,7 +576,7 @@ func (vm *VM) IBCPacketAck( // IBCPacketTimeout is available on IBC-enabled contracts and is called when an // outgoing packet (previously sent by this contract) will provably never be executed. -// Usually handled like ack returning an error +// Usually handled like ack returning an error. func (vm *VM) IBCPacketTimeout( checksum Checksum, env types.Env, @@ -693,7 +693,7 @@ type hasSubMessages interface { } // make sure the types implement the interface -// cannot put these next to the types, as the interface is private +// cannot put these next to the types, as the interface is private. var ( _ hasSubMessages = (*types.IBCBasicResult)(nil) _ hasSubMessages = (*types.IBCReceiveResult)(nil) diff --git a/types/ibc.go b/types/ibc.go index 0b9df4956..6ff29a5a2 100644 --- a/types/ibc.go +++ b/types/ibc.go @@ -194,7 +194,7 @@ type IBCDestinationCallbackMsg struct { // Auto-gen code: https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/x/ibc/core/04-channel/types/channel.pb.go#L70-L101 type IBCOrder = string -// These are the only two valid values for IbcOrder +// These are the only two valid values for IbcOrder. const ( Unordered = "ORDER_UNORDERED" Ordered = "ORDER_ORDERED" @@ -203,7 +203,7 @@ const ( // IBCTimeoutBlock Height is a monotonically increasing data type // that can be compared against another Height for the purposes of updating and // freezing clients. -// Ordering is (revision_number, timeout_height) +// Ordering is (revision_number, timeout_height). type IBCTimeoutBlock struct { // the version that the client is currently on // (eg. after resetting the chain this could increment 1 as height drops to 0) @@ -246,7 +246,7 @@ type IBCChannelOpenResult struct { Err string `json:"error,omitempty"` } -// IBC3ChannelOpenResponse is version negotiation data for the handshake +// IBC3ChannelOpenResponse is version negotiation data for the handshake. type IBC3ChannelOpenResponse struct { Version string `json:"version"` } @@ -257,7 +257,7 @@ type IBC3ChannelOpenResponse struct { // // Callbacks that have return values (like ibc_receive_packet) // or that cannot redispatch messages (like ibc_channel_open) -// will use other Response types +// will use other Response types. type IBCBasicResult struct { Ok *IBCBasicResponse `json:"ok,omitempty"` Err string `json:"error,omitempty"` @@ -291,7 +291,7 @@ type IBCBasicResponse struct { // // Callbacks that have return values (like receive_packet) // or that cannot redispatch messages (like the handshake callbacks) -// will use other Response types +// will use other Response types. type IBCReceiveResult struct { Ok *IBCReceiveResponse `json:"ok,omitempty"` Err string `json:"error,omitempty"` diff --git a/types/msg.go b/types/msg.go index 60a6e8751..677f96ab4 100644 --- a/types/msg.go +++ b/types/msg.go @@ -43,7 +43,7 @@ type Event struct { Attributes Array[EventAttribute] `json:"attributes"` } -// EventAttribute +// EventAttribute. type EventAttribute struct { Key string `json:"key"` Value string `json:"value"` @@ -107,7 +107,7 @@ type BankMsg struct { } // SendMsg contains instructions for a Cosmos-SDK/SendMsg -// It has a fixed interface here and should be converted into the proper SDK format before dispatching +// It has a fixed interface here and should be converted into the proper SDK format before dispatching. type SendMsg struct { ToAddress string `json:"to_address"` Amount Array[Coin] `json:"amount"` @@ -328,7 +328,7 @@ type WithdrawDelegatorRewardMsg struct { } // FundCommunityPoolMsg is translated to a [MsgFundCommunityPool](https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/proto/cosmos/distribution/v1beta1/tx.proto#LL69C1-L76C2). -// `depositor` is automatically filled with the current contract's address +// `depositor` is automatically filled with the current contract's address. type FundCommunityPoolMsg struct { // Amount is the list of coins to be send to the community pool Amount Array[Coin] `json:"amount"` diff --git a/types/queries.go b/types/queries.go index 42a8aa853..80c1b9117 100644 --- a/types/queries.go +++ b/types/queries.go @@ -16,7 +16,7 @@ type queryResultImpl struct { } // A custom serializer that allows us to map QueryResult instances to the Rust -// enum `ContractResult` +// enum `ContractResult`. func (q QueryResult) MarshalJSON() ([]byte, error) { // In case both Ok and Err are empty, this is interpreted and serialized // as an Ok case with no data because errors must not be empty. @@ -52,7 +52,7 @@ type Querier interface { GasConsumed() uint64 } -// this is a thin wrapper around the desired Go API to give us types closer to Rust FFI +// this is a thin wrapper around the desired Go API to give us types closer to Rust FFI. func RustQuery(querier Querier, binRequest []byte, gasLimit uint64) QuerierResult { var request QueryRequest err := json.Unmarshal(binRequest, &request) @@ -70,7 +70,7 @@ func RustQuery(querier Querier, binRequest []byte, gasLimit uint64) QuerierResul return ToQuerierResult(bz, err) } -// This is a 2-level result +// This is a 2-level result. type QuerierResult struct { Ok *QueryResult `json:"ok,omitempty"` Err *SystemError `json:"error,omitempty"` @@ -122,7 +122,7 @@ type SupplyQuery struct { Denom string `json:"denom"` } -// SupplyResponse is the expected response to SupplyQuery +// SupplyResponse is the expected response to SupplyQuery. type SupplyResponse struct { Amount Coin `json:"amount"` } @@ -132,7 +132,7 @@ type BalanceQuery struct { Denom string `json:"denom"` } -// BalanceResponse is the expected response to BalanceQuery +// BalanceResponse is the expected response to BalanceQuery. type BalanceResponse struct { Amount Coin `json:"amount"` } @@ -141,7 +141,7 @@ type AllBalancesQuery struct { Address string `json:"address"` } -// AllBalancesResponse is the expected response to AllBalancesQuery +// AllBalancesResponse is the expected response to AllBalancesQuery. type AllBalancesResponse struct { Amount Array[Coin] `json:"amount"` } @@ -226,7 +226,7 @@ type StakingQuery struct { type AllValidatorsQuery struct{} -// AllValidatorsResponse is the expected response to AllValidatorsQuery +// AllValidatorsResponse is the expected response to AllValidatorsQuery. type AllValidatorsResponse struct { Validators Array[Validator] `json:"validators"` } @@ -236,7 +236,7 @@ type ValidatorQuery struct { Address string `json:"address"` } -// ValidatorResponse is the expected response to ValidatorQuery +// ValidatorResponse is the expected response to ValidatorQuery. type ValidatorResponse struct { Validator *Validator `json:"validator"` // serializes to `null` when unset which matches Rust's Option::None serialization } @@ -260,7 +260,7 @@ type DelegationQuery struct { Validator string `json:"validator"` } -// AllDelegationsResponse is the expected response to AllDelegationsQuery +// AllDelegationsResponse is the expected response to AllDelegationsQuery. type AllDelegationsResponse struct { Delegations Array[Delegation] `json:"delegations"` } @@ -324,7 +324,7 @@ type DelegatorValidatorsResponse struct { Validators []string `json:"validators"` } -// DelegationResponse is the expected response to Array[Delegation]Query +// DelegationResponse is the expected response to Array[Delegation]Query. type DelegationResponse struct { Delegation *FullDelegation `json:"delegation,omitempty"` } @@ -375,14 +375,14 @@ type WasmQuery struct { CodeInfo *CodeInfoQuery `json:"code_info,omitempty"` } -// SmartQuery response is raw bytes ([]byte) +// SmartQuery response is raw bytes ([]byte). type SmartQuery struct { // Bech32 encoded sdk.AccAddress of the contract ContractAddr string `json:"contract_addr"` Msg []byte `json:"msg"` } -// RawQuery response is raw bytes ([]byte) +// RawQuery response is raw bytes ([]byte). type RawQuery struct { // Bech32 encoded sdk.AccAddress of the contract ContractAddr string `json:"contract_addr"` diff --git a/types/submessages.go b/types/submessages.go index b0cb81747..ce74f4dca 100644 --- a/types/submessages.go +++ b/types/submessages.go @@ -53,7 +53,7 @@ func (s *replyOn) UnmarshalJSON(b []byte) error { } // SubMsg wraps a CosmosMsg with some metadata for handling replies (ID) and optionally -// limiting the gas usage (GasLimit) +// limiting the gas usage (GasLimit). type SubMsg struct { // An arbitrary ID chosen by the contract. // This is typically used to match `Reply`s in the `reply` entry point to the submessage. diff --git a/types/systemerror.go b/types/systemerror.go index c7ca32029..33cca47a3 100644 --- a/types/systemerror.go +++ b/types/systemerror.go @@ -139,7 +139,7 @@ func ToSystemError(err error) *SystemError { } } -// check if an interface is nil (even if it has type info) +// check if an interface is nil (even if it has type info). func isNil(i interface{}) bool { if i == nil { return true diff --git a/types/types.go b/types/types.go index df7582eb4..5df368fd9 100644 --- a/types/types.go +++ b/types/types.go @@ -8,7 +8,7 @@ import ( "github.com/shamaton/msgpack/v2" ) -// Uint64 is a wrapper for uint64, but it is marshalled to and from JSON as a string +// Uint64 is a wrapper for uint64, but it is marshalled to and from JSON as a string. type Uint64 uint64 func (u Uint64) MarshalJSON() ([]byte, error) { @@ -28,7 +28,7 @@ func (u *Uint64) UnmarshalJSON(data []byte) error { return nil } -// Int64 is a wrapper for int64, but it is marshalled to and from JSON as a string +// Int64 is a wrapper for int64, but it is marshalled to and from JSON as a string. type Int64 int64 func (i Int64) MarshalJSON() ([]byte, error) { @@ -51,10 +51,10 @@ func (i *Int64) UnmarshalJSON(data []byte) error { // HumanAddress is a printable (typically bech32 encoded) address string. Just use it as a label for developers. type HumanAddress = string -// CanonicalAddress uses standard base64 encoding, just use it as a label for developers +// CanonicalAddress uses standard base64 encoding, just use it as a label for developers. type CanonicalAddress = []byte -// Coin is a string representation of the sdk.Coin type (more portable than sdk.Int) +// Coin is a string representation of the sdk.Coin type (more portable than sdk.Int). type Coin struct { Denom string `json:"denom"` // type, eg. "ATOM" Amount string `json:"amount"` // string encoding of decimal value, eg. "12.3456" @@ -67,7 +67,7 @@ func NewCoin(amount uint64, denom string) Coin { } } -// Replicating the cosmos-sdk bank module Metadata type +// Replicating the cosmos-sdk bank module Metadata type. type DenomMetadata struct { Description string `json:"description"` // DenomUnits represents the list of DenomUnits for a given coin @@ -97,7 +97,7 @@ type DenomMetadata struct { URIHash string `json:"uri_hash"` } -// Replicating the cosmos-sdk bank module DenomUnit type +// Replicating the cosmos-sdk bank module DenomUnit type. type DenomUnit struct { // Denom represents the string name of the given denom unit (e.g uatom). Denom string `json:"denom"` @@ -128,7 +128,7 @@ type DecCoin struct { Denom string `json:"denom"` } -// Simplified version of the cosmos-sdk PageRequest type +// Simplified version of the cosmos-sdk PageRequest type. type PageRequest struct { // Key is a value returned in PageResponse.next_key to begin // querying the next page most efficiently. Only one of offset or key @@ -233,7 +233,7 @@ type MigrateInfo struct { OldMigrateVersion *uint64 `json:"old_migrate_version"` } -// MarshalJSON ensures that we get "[]" for nil arrays +// MarshalJSON ensures that we get "[]" for nil arrays. func (a Array[C]) MarshalJSON() ([]byte, error) { if len(a) == 0 { return []byte("[]"), nil @@ -242,7 +242,7 @@ func (a Array[C]) MarshalJSON() ([]byte, error) { return json.Marshal(raw) } -// UnmarshalJSON ensures that we get an empty slice for "[]" and "null" +// UnmarshalJSON ensures that we get an empty slice for "[]" and "null". func (a *Array[C]) UnmarshalJSON(data []byte) error { var raw []C if err := json.Unmarshal(data, &raw); err != nil { From bd565b44fbe28919bf0219efb415c2924f861bab Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Mon, 23 Dec 2024 02:04:07 +0700 Subject: [PATCH 09/19] correct typo from adjusting tests. --- internal/api/lib_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/api/lib_test.go b/internal/api/lib_test.go index 1727cbfae..3939fda7a 100644 --- a/internal/api/lib_test.go +++ b/internal/api/lib_test.go @@ -437,7 +437,7 @@ func TestGetMetrics(t *testing.T) { 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.ElementsPinnedMemoryCache) require.Equal(t, uint64(1), metrics.ElementsMemoryCache) require.InEpsilon(t, 3700000, metrics.SizePinnedMemoryCache, 0.25) require.InEpsilon(t, 3700000, metrics.SizeMemoryCache, 0.25) From 71b2d1eeec72c11441b3c0eff1b21cad07a69668 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Mon, 23 Dec 2024 02:16:05 +0700 Subject: [PATCH 10/19] adjust golang version in circleci --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d376d482c..6e1b0c6f5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -186,7 +186,7 @@ jobs: # Build types and cosmwam package without cgo wasmvm_no_cgo: docker: - - image: cimg/go:1.21.4 + - image: cimg/go:1.23.4 steps: - checkout - run: From f3713991f58ea935c0e10e7b2e5596155c067b96 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Mon, 23 Dec 2024 02:18:47 +0700 Subject: [PATCH 11/19] bump go... --- .circleci/config.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6e1b0c6f5..df5af5842 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -168,7 +168,7 @@ jobs: format-go: docker: - - image: cimg/go:1.21.4 + - image: cimg/go:1.23.4 steps: - run: name: Install gofumpt @@ -205,7 +205,7 @@ jobs: # Build types and cosmwasm with libwasmvm linking disabled nolink_libwasmvm: docker: - - image: cimg/go:1.21.4 + - image: cimg/go:1.23.4 steps: - checkout - run: @@ -223,7 +223,7 @@ jobs: tidy-go: docker: - - image: cimg/go:1.21.4 + - image: cimg/go:1.23.4 steps: - checkout - run: @@ -241,7 +241,7 @@ jobs: format-scripts: docker: - - image: cimg/go:1.21.4 + - image: cimg/go:1.23.4 steps: - run: name: Install shfmt @@ -298,7 +298,7 @@ jobs: # Test the Go project and run benchmarks wasmvm_test: docker: - - image: cimg/go:1.21.4 + - image: cimg/go:1.23.4 environment: GORACE: "halt_on_error=1" BUILD_VERSION: $(echo ${CIRCLE_SHA1} | cut -c 1-10) From cbde7172c6ce2ae8131cd20851adfaa11a17e504 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Mon, 23 Dec 2024 02:21:19 +0700 Subject: [PATCH 12/19] remove dupl --- .golangci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index 132c69402..139768e7a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -23,7 +23,6 @@ linters: - misspell # Find commonly misspelled words - revive # a metalinter with more checks - bodyclose # Check HTTP response bodies are closed - - dupl # Code clone detector - goconst # Find repeated strings that could be constants - gocyclo # Check function complexity - godot # Check comment endings From 08ea4c474357b746b15a60d442592b6a4d1eceb9 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Fri, 3 Jan 2025 01:20:19 +0700 Subject: [PATCH 13/19] lint main.go --- .golangci.yml | 2 +- cmd/demo/main.go | 66 ++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 139768e7a..18cc6fd4b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -24,7 +24,7 @@ linters: - revive # a metalinter with more checks - bodyclose # Check HTTP response bodies are closed - goconst # Find repeated strings that could be constants - - gocyclo # Check function complexity +# - gocyclo # Check function complexity - godot # Check comment endings - gocognit # Check cognitive complexity - whitespace # Check trailing whitespace diff --git a/cmd/demo/main.go b/cmd/demo/main.go index 8afbfe650..d54e0a94a 100644 --- a/cmd/demo/main.go +++ b/cmd/demo/main.go @@ -4,53 +4,91 @@ import ( "fmt" "math" "os" + "path/filepath" + "strings" wasmvm "github.com/CosmWasm/wasmvm/v2" ) +// PrintDebug enables debug printing when true const ( - PRINT_DEBUG = true - MEMORY_LIMIT = 32 // MiB - CACHE_SIZE = 100 // MiB + PrintDebug = true + // MemoryLimit defines the memory limit in MiB + MemoryLimit = 32 + // CacheSize defines the cache size in MiB + CacheSize = 100 ) -var SUPPORTED_CAPABILITIES = []string{"staking"} +// SupportedCapabilities defines the list of supported staking capabilities +var SupportedCapabilities = []string{"staking"} -// This is just a demo to ensure we can compile a static go binary. +// exitCode tracks the code that the program will exit with +var exitCode = 0 + +// main is the entry point for the demo application that tests wasmvm functionality func main() { + defer func() { + os.Exit(exitCode) + }() + + if len(os.Args) < 2 { + fmt.Println("Usage: demo ") + exitCode = 1 + return + } + file := os.Args[1] if file == "version" { libwasmvmVersion, err := wasmvm.LibwasmvmVersion() if err != nil { - panic(err) + fmt.Printf("Error getting libwasmvm version: %v\n", err) + exitCode = 1 + return } fmt.Printf("libwasmvm: %s\n", libwasmvmVersion) return } fmt.Printf("Running %s...\n", file) - bz, err := os.ReadFile(file) + + // Validate file path + cleanPath := filepath.Clean(file) + if filepath.IsAbs(cleanPath) || strings.Contains(cleanPath, "..") { + fmt.Println("Error: invalid file path") + exitCode = 1 + return + } + + bz, err := os.ReadFile(cleanPath) if err != nil { - panic(err) + fmt.Printf("Error reading file: %v\n", err) + exitCode = 1 + return } fmt.Println("Loaded!") - err = os.MkdirAll("tmp", 0o755) + err = os.MkdirAll("tmp", 0o750) if err != nil { - panic(err) + fmt.Printf("Error creating tmp directory: %v\n", err) + exitCode = 1 + return } - vm, err := wasmvm.NewVM("tmp", SUPPORTED_CAPABILITIES, MEMORY_LIMIT, PRINT_DEBUG, CACHE_SIZE) + vm, err := wasmvm.NewVM("tmp", SupportedCapabilities, MemoryLimit, PrintDebug, CacheSize) if err != nil { - panic(err) + fmt.Printf("Error creating VM: %v\n", err) + exitCode = 1 + return } + defer vm.Cleanup() checksum, _, err := vm.StoreCode(bz, math.MaxUint64) if err != nil { - panic(err) + fmt.Printf("Error storing code: %v\n", err) + exitCode = 1 + return } fmt.Printf("Stored code with checksum: %X\n", checksum) - vm.Cleanup() fmt.Println("finished") } From 7a812f550e177b75ae2846194254db2753b7753d Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Fri, 3 Jan 2025 01:44:09 +0700 Subject: [PATCH 14/19] lints... --- cmd/demo/main.go | 12 ++++---- internal/api/callbacks.go | 22 +++++--------- internal/api/iterator.go | 7 ++++- internal/api/lib.go | 8 ++--- internal/api/lib_test.go | 60 ++++++++++++++++++++++++++++--------- internal/api/memory.go | 22 +++++++------- internal/api/memory_test.go | 14 +++++---- internal/api/mocks.go | 18 ++++++----- 8 files changed, 101 insertions(+), 62 deletions(-) diff --git a/cmd/demo/main.go b/cmd/demo/main.go index d54e0a94a..4d05413d0 100644 --- a/cmd/demo/main.go +++ b/cmd/demo/main.go @@ -10,22 +10,22 @@ import ( wasmvm "github.com/CosmWasm/wasmvm/v2" ) -// PrintDebug enables debug printing when true +// PrintDebug enables debug printing when true. const ( PrintDebug = true - // MemoryLimit defines the memory limit in MiB + // MemoryLimit defines the memory limit in MiB. MemoryLimit = 32 - // CacheSize defines the cache size in MiB + // CacheSize defines the cache size in MiB. CacheSize = 100 ) -// SupportedCapabilities defines the list of supported staking capabilities +// SupportedCapabilities defines the list of supported staking capabilities. var SupportedCapabilities = []string{"staking"} -// exitCode tracks the code that the program will exit with +// exitCode tracks the code that the program will exit with. var exitCode = 0 -// main is the entry point for the demo application that tests wasmvm functionality +// main is the entry point for the demo application that tests wasmvm functionality. func main() { defer func() { os.Exit(exitCode) diff --git a/internal/api/callbacks.go b/internal/api/callbacks.go index 702c8faf7..043898383 100644 --- a/internal/api/callbacks.go +++ b/internal/api/callbacks.go @@ -158,7 +158,7 @@ func cGet(ptr *C.db_t, gasMeter *C.gas_meter_t, usedGas *cu64, key C.U8SliceView return C.GoError_BadArgument } // errOut is unused and we don't check `is_none` because of https://github.com/CosmWasm/wasmvm/issues/536 - if !(*val).is_none { + if !val.is_none { panic("Got a non-none UnmanagedVector we're about to override. This is a bug because someone has to drop the old one.") } @@ -231,7 +231,7 @@ func cScan(ptr *C.db_t, gasMeter *C.gas_meter_t, usedGas *cu64, start C.U8SliceV // we received an invalid pointer return C.GoError_BadArgument } - if !(*errOut).is_none { + if !errOut.is_none { panic("Got a non-none UnmanagedVector we're about to override. This is a bug because someone has to drop the old one.") } @@ -272,19 +272,13 @@ func cScan(ptr *C.db_t, gasMeter *C.gas_meter_t, usedGas *cu64, start C.U8SliceV //export cNext func cNext(ref C.IteratorReference, gasMeter *C.gas_meter_t, usedGas *cu64, key *C.UnmanagedVector, val *C.UnmanagedVector, errOut *C.UnmanagedVector) (ret C.GoError) { - // typical usage of iterator - // for ; itr.Valid(); itr.Next() { - // k, v := itr.Key(); itr.Value() - // ... - // } - defer recoverPanic(&ret) if ref.call_id == 0 || gasMeter == nil || usedGas == nil || key == nil || val == nil || errOut == nil { // we received an invalid pointer return C.GoError_BadArgument } // errOut is unused and we don't check `is_none` because of https://github.com/CosmWasm/wasmvm/issues/536 - if !(*key).is_none || !(*val).is_none { + if !key.is_none || !val.is_none { panic("Got a non-none UnmanagedVector we're about to override. This is a bug because someone has to drop the old one.") } @@ -336,7 +330,7 @@ func nextPart(ref C.IteratorReference, gasMeter *C.gas_meter_t, usedGas *cu64, o return C.GoError_BadArgument } // errOut is unused and we don't check `is_none` because of https://github.com/CosmWasm/wasmvm/issues/536 - if !(*output).is_none { + if !output.is_none { panic("Got a non-none UnmanagedVector we're about to override. This is a bug because someone has to drop the old one.") } @@ -384,7 +378,7 @@ func cHumanizeAddress(ptr *C.api_t, src C.U8SliceView, dest *C.UnmanagedVector, if dest == nil || errOut == nil { return C.GoError_BadArgument } - if !(*dest).is_none || !(*errOut).is_none { + if !dest.is_none || !errOut.is_none { panic("Got a non-none UnmanagedVector we're about to override. This is a bug because someone has to drop the old one.") } @@ -412,7 +406,7 @@ func cCanonicalizeAddress(ptr *C.api_t, src C.U8SliceView, dest *C.UnmanagedVect if dest == nil || errOut == nil { return C.GoError_BadArgument } - if !(*dest).is_none || !(*errOut).is_none { + if !dest.is_none || !errOut.is_none { panic("Got a non-none UnmanagedVector we're about to override. This is a bug because someone has to drop the old one.") } @@ -439,7 +433,7 @@ func cValidateAddress(ptr *C.api_t, src C.U8SliceView, errOut *C.UnmanagedVector if errOut == nil { return C.GoError_BadArgument } - if !(*errOut).is_none { + if !errOut.is_none { panic("Got a non-none UnmanagedVector we're about to override. This is a bug because someone has to drop the old one.") } @@ -479,7 +473,7 @@ func cQueryExternal(ptr *C.querier_t, gasLimit cu64, usedGas *cu64, request C.U8 // we received an invalid pointer return C.GoError_BadArgument } - if !(*result).is_none || !(*errOut).is_none { + if !result.is_none || !errOut.is_none { panic("Got a non-none UnmanagedVector we're about to override. This is a bug because someone has to drop the old one.") } diff --git a/internal/api/iterator.go b/internal/api/iterator.go index 0b3c9cf7b..74539c2a0 100644 --- a/internal/api/iterator.go +++ b/internal/api/iterator.go @@ -3,6 +3,7 @@ package api import ( "fmt" "math" + "os" "sync" "github.com/CosmWasm/wasmvm/v2/types" @@ -50,7 +51,11 @@ func endCall(callID uint64) { remove := removeFrame(callID) // free all iterators in the frame when we release it for _, iter := range remove { - iter.Close() + if err := iter.Close(); err != nil { + // In this cleanup code, we can't do much with the error + // Log it to stderr since that's better than silently ignoring it + fmt.Fprintf(os.Stderr, "failed to close iterator: %v\n", err) + } } } diff --git a/internal/api/lib.go b/internal/api/lib.go index 2b71adc1c..8f0f7c811 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -44,7 +44,7 @@ type Cache struct { type Querier = types.Querier func InitCache(config types.VMConfig) (Cache, error) { - // libwasmvm would create this directory too but we need it earlier for the lockfile + // libwasmvm would create this directory too but we need it earlier for the lockfile. err := os.MkdirAll(config.Cache.BaseDir, 0o755) if err != nil { return Cache{}, fmt.Errorf("Could not create base directory") @@ -83,7 +83,7 @@ func InitCache(config types.VMConfig) (Cache, error) { func ReleaseCache(cache Cache) { C.release_cache(cache.ptr) - cache.lockfile.Close() // Also releases the file lock + cache.lockfile.Close() // Also releases the file lock. } func StoreCode(cache Cache, wasm []byte, persist bool) ([]byte, error) { @@ -331,7 +331,7 @@ func Migrate( errmsg := uninitializedUnmanagedVector() res, err := C.migrate(cache.ptr, cs, e, m, db, a, q, cu64(gasLimit), cbool(printDebug), &gasReport, &errmsg) - if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { + if err != nil && err.(syscall.Errno) != 0 { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, convertGasReport(gasReport), errorWithMessage(err, errmsg) } @@ -376,7 +376,7 @@ func MigrateWithInfo( errmsg := uninitializedUnmanagedVector() res, err := C.migrate_with_info(cache.ptr, cs, e, m, i, db, a, q, cu64(gasLimit), cbool(printDebug), &gasReport, &errmsg) - if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success { + if err != nil && err.(syscall.Errno) != 0 { // Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0. return nil, convertGasReport(gasReport), errorWithMessage(err, errmsg) } diff --git a/internal/api/lib_test.go b/internal/api/lib_test.go index e2dd1e8c9..ae129b545 100644 --- a/internal/api/lib_test.go +++ b/internal/api/lib_test.go @@ -34,7 +34,11 @@ var TESTING_CAPABILITIES = []string{"staking", "stargate", "iterator", "cosmwasm func TestInitAndReleaseCache(t *testing.T) { tmpdir, err := os.MkdirTemp("", "wasmvm-testing") require.NoError(t, err) - defer os.RemoveAll(tmpdir) + defer func() { + if err := os.RemoveAll(tmpdir); err != nil { + t.Errorf("failed to remove temp dir: %v", err) + } + }() config := types.VMConfig{ Cache: types.CacheOptions{ @@ -54,7 +58,11 @@ func TestInitAndReleaseCache(t *testing.T) { func TestInitCacheWorksForNonExistentDir(t *testing.T) { tmpdir, err := os.MkdirTemp("", "wasmvm-testing") require.NoError(t, err) - defer os.RemoveAll(tmpdir) + defer func() { + if err := os.RemoveAll(tmpdir); err != nil { + t.Errorf("failed to remove temp dir: %v", err) + } + }() createMe := filepath.Join(tmpdir, "does-not-yet-exist") config := types.VMConfig{ @@ -90,7 +98,11 @@ func TestInitCacheErrorsForBrokenDir(t *testing.T) { func TestInitLockingPreventsConcurrentAccess(t *testing.T) { tmpdir, err := os.MkdirTemp("", "wasmvm-testing") require.NoError(t, err) - defer os.RemoveAll(tmpdir) + defer func() { + if err := os.RemoveAll(tmpdir); err != nil { + t.Errorf("failed to remove temp dir: %v", err) + } + }() config1 := types.VMConfig{ Cache: types.CacheOptions{ @@ -137,9 +149,21 @@ 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) + defer func() { + if err := os.RemoveAll(tmpdir1); err != nil { + t.Errorf("failed to remove temp dir: %v", err) + } + }() + defer func() { + if err := os.RemoveAll(tmpdir2); err != nil { + t.Errorf("failed to remove temp dir: %v", err) + } + }() + defer func() { + if err := os.RemoveAll(tmpdir3); err != nil { + t.Errorf("failed to remove temp dir: %v", err) + } + }() config1 := types.VMConfig{ Cache: types.CacheOptions{ @@ -180,7 +204,11 @@ func TestInitLockingAllowsMultipleInstancesInDifferentDirs(t *testing.T) { func TestInitCacheEmptyCapabilities(t *testing.T) { tmpdir, err := os.MkdirTemp("", "wasmvm-testing") require.NoError(t, err) - defer os.RemoveAll(tmpdir) + defer func() { + if err := os.RemoveAll(tmpdir); err != nil { + t.Errorf("failed to remove temp dir: %v", err) + } + }() config := types.VMConfig{ Cache: types.CacheOptions{ BaseDir: tmpdir, @@ -210,7 +238,9 @@ func withCache(tb testing.TB) (Cache, func()) { require.NoError(tb, err) cleanup := func() { - os.RemoveAll(tmpdir) + if err := os.RemoveAll(tmpdir); err != nil { + tb.Errorf("failed to remove temp dir: %v", err) + } ReleaseCache(cache) } return cache, cleanup @@ -781,7 +811,7 @@ func TestExecuteStorageLoop(t *testing.T) { // the "sdk gas" * GasMultiplier + the wasm cost should equal the maxGas (or be very close) totalCost := gasReport.UsedInternally + gasMeter2.GasConsumed() - require.Equal(t, int64(maxGas), int64(totalCost)) + require.Equal(t, uint64(maxGas), totalCost) } func BenchmarkContractCall(b *testing.B) { @@ -1225,6 +1255,7 @@ func createFloaty2(tb testing.TB, cache Cache) []byte { func createContract(tb testing.TB, cache Cache, wasmFile string) []byte { tb.Helper() + // #nosec G304 - used for test files only wasm, err := os.ReadFile(wasmFile) require.NoError(tb, err) checksum, err := StoreCode(cache, wasm, true) @@ -1385,15 +1416,16 @@ func TestFloats(t *testing.T) { // 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 "" } diff --git a/internal/api/memory.go b/internal/api/memory.go index f2fb06d73..953296fae 100644 --- a/internal/api/memory.go +++ b/internal/api/memory.go @@ -46,15 +46,16 @@ func uninitializedUnmanagedVector() C.UnmanagedVector { } func newUnmanagedVector(data []byte) C.UnmanagedVector { - if data == nil { + switch { + case data == nil: return C.new_unmanaged_vector(cbool(true), cu8_ptr(nil), cusize(0)) - } else if len(data) == 0 { + case len(data) == 0: // in Go, accessing the 0-th element of an empty array triggers a panic. That is why in the case // of an empty `[]byte` we can't get the internal heap pointer to the underlying array as we do // below with `&data[0]`. // https://play.golang.org/p/xvDY3g9OqUk return C.new_unmanaged_vector(cbool(false), cu8_ptr(nil), cusize(0)) - } else { + default: // This will allocate a proper vector with content and return a description of it return C.new_unmanaged_vector(cbool(false), cu8_ptr(unsafe.Pointer(&data[0])), cusize(len(data))) } @@ -62,14 +63,15 @@ func newUnmanagedVector(data []byte) C.UnmanagedVector { func copyAndDestroyUnmanagedVector(v C.UnmanagedVector) []byte { var out []byte - if v.is_none { + switch { + case bool(v.is_none): out = nil - } else if v.cap == cusize(0) { + case v.cap == cusize(0): // There is no allocation we can copy out = []byte{} - } else { - // C.GoBytes create a copy (https://stackoverflow.com/a/40950744/2013738) - out = C.GoBytes(unsafe.Pointer(v.ptr), cint(v.len)) + default: + // C.GoBytes accepts C types directly, avoiding unsafe integer conversions + out = C.GoBytes(unsafe.Pointer(v.ptr), C.int(v.len)) } C.destroy_unmanaged_vector(v) return out @@ -92,7 +94,7 @@ func copyU8Slice(view C.U8SliceView) []byte { // In this case, we don't want to look into the ptr return []byte{} } - // C.GoBytes create a copy (https://stackoverflow.com/a/40950744/2013738) - res := C.GoBytes(unsafe.Pointer(view.ptr), cint(view.len)) + // C.GoBytes accepts C types directly, avoiding unsafe integer conversions + res := C.GoBytes(unsafe.Pointer(view.ptr), C.int(view.len)) return res } diff --git a/internal/api/memory_test.go b/internal/api/memory_test.go index 397faf50c..749809f9d 100644 --- a/internal/api/memory_test.go +++ b/internal/api/memory_test.go @@ -28,8 +28,8 @@ func TestCreateAndDestroyUnmanagedVector(t *testing.T) { 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.Equal(t, uint64(3), uint64(unmanaged.len)) + require.GreaterOrEqual(t, uint64(3), uint64(unmanaged.cap)) // Rust implementation decides this copy := copyAndDestroyUnmanagedVector(unmanaged) require.Equal(t, original, copy) } @@ -39,8 +39,8 @@ func TestCreateAndDestroyUnmanagedVector(t *testing.T) { 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.Equal(t, uint64(0), uint64(unmanaged.len)) + require.GreaterOrEqual(t, uint64(0), uint64(unmanaged.cap)) // Rust implementation decides this copy := copyAndDestroyUnmanagedVector(unmanaged) require.Equal(t, original, copy) } @@ -63,14 +63,16 @@ func TestCreateAndDestroyUnmanagedVector(t *testing.T) { func TestCopyDestroyUnmanagedVector(t *testing.T) { { // ptr, cap and len broken. Do not access those values when is_none is true - invalid_ptr := unsafe.Pointer(uintptr(42)) + base := unsafe.Pointer(&struct{ x byte }{}) //nolint:gosec + invalid_ptr := unsafe.Add(base, 42) uv := constructUnmanagedVector(cbool(true), cu8_ptr(invalid_ptr), cusize(0xBB), cusize(0xAA)) copy := copyAndDestroyUnmanagedVector(uv) require.Nil(t, copy) } { // Capacity is 0, so no allocation happened. Do not access the pointer. - invalid_ptr := unsafe.Pointer(uintptr(42)) + base := unsafe.Pointer(&struct{ x byte }{}) //nolint:gosec + invalid_ptr := unsafe.Add(base, 42) uv := constructUnmanagedVector(cbool(false), cu8_ptr(invalid_ptr), 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 b8a249ac0..4ed17c727 100644 --- a/internal/api/mocks.go +++ b/internal/api/mocks.go @@ -15,6 +15,10 @@ import ( "github.com/CosmWasm/wasmvm/v2/types" ) +const ( + testAddress = "foobar" +) + /** helper constructors **/ const MOCK_CONTRACT_ADDR = "contract" @@ -24,7 +28,7 @@ func MockEnv() types.Env { Block: types.BlockInfo{ Height: 123, Time: 1578939743_987654321, - ChainID: "foobar", + ChainID: testAddress, }, Transaction: &types.TransactionInfo{ Index: 4, @@ -390,15 +394,14 @@ func NewMockAPI() *types.GoAPI { } func TestMockApi(t *testing.T) { - human := "foobar" - canon, cost, err := MockCanonicalizeAddress(human) + canon, cost, err := MockCanonicalizeAddress(testAddress) require.NoError(t, err) require.Len(t, canon, CanonicalLength) require.Equal(t, CostCanonical, cost) recover, cost, err := MockHumanizeAddress(canon) require.NoError(t, err) - require.Equal(t, recover, human) + require.Equal(t, recover, testAddress) require.Equal(t, CostHuman, cost) } @@ -528,11 +531,12 @@ func (q ReflectCustom) Query(request json.RawMessage) ([]byte, error) { return nil, err } var resp CustomResponse - if query.Ping != nil { + switch { + case query.Ping != nil: resp.Msg = "PONG" - } else if query.Capitalized != nil { + case query.Capitalized != nil: resp.Msg = strings.ToUpper(query.Capitalized.Text) - } else { + default: return nil, errors.New("Unsupported query") } return json.Marshal(resp) From 65039a53378f2aae139e08c25b60656e947d0194 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Fri, 3 Jan 2025 01:50:17 +0700 Subject: [PATCH 15/19] complete --- .golangci.yml | 6 +++++- internal/api/lib.go | 5 ++++- lib_libwasmvm_test.go | 5 ++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 18cc6fd4b..a90d1a3f7 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -24,7 +24,7 @@ linters: - revive # a metalinter with more checks - bodyclose # Check HTTP response bodies are closed - goconst # Find repeated strings that could be constants -# - gocyclo # Check function complexity + # - gocyclo # Check function complexity - godot # Check comment endings - gocognit # Check cognitive complexity - whitespace # Check trailing whitespace @@ -57,6 +57,10 @@ linters-settings: # Drops lexical ordering for custom sections. # Default: false no-lex-order: true + gocritic: + # Enable all gocritic checks. + disabled-checks: + - dupSubExpr gocyclo: min-complexity: 15 gocognit: diff --git a/internal/api/lib.go b/internal/api/lib.go index 8f0f7c811..3531f8164 100644 --- a/internal/api/lib.go +++ b/internal/api/lib.go @@ -83,7 +83,10 @@ func InitCache(config types.VMConfig) (Cache, error) { func ReleaseCache(cache Cache) { C.release_cache(cache.ptr) - cache.lockfile.Close() // Also releases the file lock. + if err := cache.lockfile.Close(); err != nil { + // Just log the error since this is cleanup code + fmt.Printf("failed to close lockfile: %v\n", err) + } // Also releases the file lock. } func StoreCode(cache Cache, wasm []byte, persist bool) ([]byte, error) { diff --git a/lib_libwasmvm_test.go b/lib_libwasmvm_test.go index 344ce614f..c4c77c728 100644 --- a/lib_libwasmvm_test.go +++ b/lib_libwasmvm_test.go @@ -39,13 +39,16 @@ func withVM(t *testing.T) *VM { t.Cleanup(func() { vm.Cleanup() - os.RemoveAll(tmpdir) + if err := os.RemoveAll(tmpdir); err != nil { + t.Fatal(err) + } }) return vm } func createTestContract(t *testing.T, vm *VM, path string) Checksum { t.Helper() + //#nosec G304 -- This is test code using hardcoded test files wasm, err := os.ReadFile(path) require.NoError(t, err) checksum, _, err := vm.StoreCode(wasm, TESTING_GAS_LIMIT) From a06cd0d2621cd97b7159a44af37dac55c9d383cc Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Fri, 17 Jan 2025 18:13:15 +0700 Subject: [PATCH 16/19] remove mutext lock in lib_test.go --- internal/api/lib_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/api/lib_test.go b/internal/api/lib_test.go index ae129b545..be982f60f 100644 --- a/internal/api/lib_test.go +++ b/internal/api/lib_test.go @@ -840,9 +840,7 @@ 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) From 1118f26c7322b988877782629545ed8c4df3c288 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Fri, 17 Jan 2025 18:14:57 +0700 Subject: [PATCH 17/19] remove unused variable --- internal/api/lib_test.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/internal/api/lib_test.go b/internal/api/lib_test.go index be982f60f..0e8854cf7 100644 --- a/internal/api/lib_test.go +++ b/internal/api/lib_test.go @@ -26,9 +26,6 @@ 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) { From d6c14e665f7c729482f7741911f60a1530f08c7c Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Fri, 17 Jan 2025 18:26:50 +0700 Subject: [PATCH 18/19] restore comments --- internal/api/memory.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/api/memory.go b/internal/api/memory.go index 953296fae..7b426d911 100644 --- a/internal/api/memory.go +++ b/internal/api/memory.go @@ -70,7 +70,7 @@ func copyAndDestroyUnmanagedVector(v C.UnmanagedVector) []byte { // There is no allocation we can copy out = []byte{} default: - // C.GoBytes accepts C types directly, avoiding unsafe integer conversions + // C.GoBytes create a copy (https://stackoverflow.com/a/40950744/2013738) out = C.GoBytes(unsafe.Pointer(v.ptr), C.int(v.len)) } C.destroy_unmanaged_vector(v) @@ -94,7 +94,7 @@ func copyU8Slice(view C.U8SliceView) []byte { // In this case, we don't want to look into the ptr return []byte{} } - // C.GoBytes accepts C types directly, avoiding unsafe integer conversions + // C.GoBytes create a copy (https://stackoverflow.com/a/40950744/2013738) res := C.GoBytes(unsafe.Pointer(view.ptr), C.int(view.len)) return res } From d9438025f429d9ca7d081e67328996f4360089d2 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Fri, 17 Jan 2025 18:30:24 +0700 Subject: [PATCH 19/19] fix lint in .golangci.yml --- .golangci.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index a90d1a3f7..895be36c7 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,14 +1,12 @@ run: tests: true timeout: 5m - skip-dirs: - - vendor/ - - third_party/ linters: # Enable specific linter # https://golangci-lint.run/usage/linters/#enabled-by-default enable: + - copyloopvar # Detect copy loops - errcheck # Detect unchecked errors - gosimple # Simplify code - govet # Reports suspicious constructs @@ -81,3 +79,6 @@ issues: exclude-use-default: false max-issues-per-linter: 0 max-same-issues: 0 + exclude-dirs: + - vendor/ + - third_party/