diff --git a/crypto/onetimesig_test.go b/crypto/onetimesig_test.go
index d9eec123d3..96a412f7ea 100644
--- a/crypto/onetimesig_test.go
+++ b/crypto/onetimesig_test.go
@@ -20,6 +20,7 @@ import (
"fmt"
"testing"
+ "github.com/algorand/go-algorand/data/basics/testing/roundtrip"
"github.com/algorand/go-algorand/test/partitiontest"
)
@@ -140,6 +141,17 @@ func testOneTimeSignVerifyNewStyle(t *testing.T, c *OneTimeSignatureSecrets, c2
}
}
+func TestHeartbeatProofRoundTrip(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ toOTS := func(h HeartbeatProof) OneTimeSignature { return h.ToOneTimeSignature() }
+ toProof := func(ots OneTimeSignature) HeartbeatProof { return ots.ToHeartbeatProof() }
+
+ // Test with an empty proof as example, NearZeros will test each field
+ var emptyProof HeartbeatProof
+ roundtrip.Check(t, emptyProof, toOTS, toProof)
+}
+
func BenchmarkOneTimeSigBatchVerification(b *testing.B) {
for _, enabled := range []bool{false, true} {
b.Run(fmt.Sprintf("batch=%v", enabled), func(b *testing.B) {
diff --git a/daemon/algod/api/server/v2/account_test.go b/daemon/algod/api/server/v2/account_test.go
index e58990ada0..7ca873b5b0 100644
--- a/daemon/algod/api/server/v2/account_test.go
+++ b/daemon/algod/api/server/v2/account_test.go
@@ -25,11 +25,31 @@ import (
"github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated/model"
"github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/data/basics/testing/roundtrip"
ledgertesting "github.com/algorand/go-algorand/ledger/testing"
"github.com/algorand/go-algorand/protocol"
"github.com/algorand/go-algorand/test/partitiontest"
)
+// makeAccountConverters creates conversion functions for round-trip testing between
+// basics.AccountData and model.Account.
+func makeAccountConverters(t *testing.T, addrStr string, round basics.Round, proto *config.ConsensusParams, withoutRewards basics.MicroAlgos) (
+ toModel func(basics.AccountData) model.Account,
+ toBasics func(model.Account) basics.AccountData,
+) {
+ toModel = func(ad basics.AccountData) model.Account {
+ converted, err := AccountDataToAccount(addrStr, &ad, round, proto, withoutRewards)
+ require.NoError(t, err)
+ return converted
+ }
+ toBasics = func(acc model.Account) basics.AccountData {
+ converted, err := AccountToAccountData(&acc)
+ require.NoError(t, err)
+ return converted
+ }
+ return toModel, toBasics
+}
+
func TestAccount(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
@@ -106,8 +126,9 @@ func TestAccount(t *testing.T) {
b := a.WithUpdatedRewards(proto.RewardUnit, 100)
addr := basics.Address{}.String()
- conv, err := AccountDataToAccount(addr, &b, round, &proto, a.MicroAlgos)
- require.NoError(t, err)
+ toModel, toBasics := makeAccountConverters(t, addr, round, &proto, a.MicroAlgos)
+
+ conv := toModel(b)
require.Equal(t, addr, conv.Address)
require.Equal(t, b.MicroAlgos.Raw, conv.Amount)
require.Equal(t, a.MicroAlgos.Raw, conv.AmountWithoutPendingRewards)
@@ -145,6 +166,21 @@ func TestAccount(t *testing.T) {
verifyCreatedApp(0, appIdx1, appParams1)
verifyCreatedApp(1, appIdx2, appParams2)
+ appRoundTrip := func(idx basics.AppIndex, params basics.AppParams) {
+ roundtrip.Check(t, params,
+ func(ap basics.AppParams) model.Application {
+ return AppParamsToApplication(addr, idx, &ap)
+ },
+ func(app model.Application) basics.AppParams {
+ converted, err := ApplicationParamsToAppParams(&app.Params)
+ require.NoError(t, err)
+ return converted
+ })
+ }
+
+ appRoundTrip(appIdx1, appParams1)
+ appRoundTrip(appIdx2, appParams2)
+
makeTKV := func(k string, v interface{}) model.TealKeyValue {
value := model.TealValue{}
switch v.(type) {
@@ -198,8 +234,8 @@ func TestAccount(t *testing.T) {
verifyCreatedAsset(0, assetIdx1, assetParams1)
verifyCreatedAsset(1, assetIdx2, assetParams2)
- c, err := AccountToAccountData(&conv)
- require.NoError(t, err)
+ // Verify round-trip conversion works for the manually constructed account
+ c := toBasics(toModel(b))
require.Equal(t, b, c)
t.Run("IsDeterministic", func(t *testing.T) {
@@ -223,11 +259,92 @@ func TestAccountRandomRoundTrip(t *testing.T) {
for addr, acct := range accts {
round := basics.Round(2)
proto := config.Consensus[protocol.ConsensusFuture]
- conv, err := AccountDataToAccount(addr.String(), &acct, round, &proto, acct.MicroAlgos)
- require.NoError(t, err)
- c, err := AccountToAccountData(&conv)
- require.NoError(t, err)
+ toModel, toBasics := makeAccountConverters(t, addr.String(), round, &proto, acct.MicroAlgos)
+ // Test the randomly-generated account round-trips correctly
+ c := toBasics(toModel(acct))
require.Equal(t, acct, c)
}
}
}
+
+func TestConvertTealKeyValueRoundTrip(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ t.Run("nil input", func(t *testing.T) {
+ require.Nil(t, convertTKVToGenerated(nil))
+ result, err := convertGeneratedTKV(nil)
+ require.NoError(t, err)
+ require.Nil(t, result)
+ })
+
+ t.Run("empty map treated as nil", func(t *testing.T) {
+ empty := basics.TealKeyValue{}
+ require.Nil(t, convertTKVToGenerated(&empty))
+ result, err := convertGeneratedTKV(convertTKVToGenerated(&empty))
+ require.NoError(t, err)
+ require.Nil(t, result)
+ })
+
+ t.Run("round-trip non-empty map", func(t *testing.T) {
+ kv := basics.TealKeyValue{
+ "alpha": {Type: basics.TealUintType, Uint: 17},
+ "beta": {Type: basics.TealBytesType, Bytes: "\x00\x01binary"},
+ }
+
+ toGenerated := func(val basics.TealKeyValue) *model.TealKeyValueStore {
+ return convertTKVToGenerated(&val)
+ }
+ toBasics := func(store *model.TealKeyValueStore) basics.TealKeyValue {
+ converted, err := convertGeneratedTKV(store)
+ require.NoError(t, err)
+ return converted
+ }
+
+ // Test the manually constructed map round-trips correctly
+ result := toBasics(toGenerated(kv))
+ require.Equal(t, kv, result)
+ })
+}
+
+func TestAppLocalStateRoundTrip(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ appIdx := basics.AppIndex(42)
+ cases := map[string]basics.AppLocalState{
+ "empty kv": {
+ Schema: basics.StateSchema{NumUint: 1, NumByteSlice: 0},
+ KeyValue: nil,
+ },
+ "mixed kv": {
+ Schema: basics.StateSchema{NumUint: 2, NumByteSlice: 3},
+ KeyValue: basics.TealKeyValue{
+ "counter": {Type: basics.TealUintType, Uint: 99},
+ "note": {Type: basics.TealBytesType, Bytes: "hello world"},
+ },
+ },
+ }
+
+ for name, state := range cases {
+ t.Run(name, func(t *testing.T) {
+ modelState := AppLocalState(state, appIdx)
+ modelStates := []model.ApplicationLocalState{modelState}
+
+ acc := model.Account{
+ Status: basics.Offline.String(),
+ Amount: 0,
+ AppsLocalState: &modelStates,
+ }
+
+ ad, err := AccountToAccountData(&acc)
+ require.NoError(t, err)
+
+ require.NotNil(t, ad.AppLocalStates)
+ got, ok := ad.AppLocalStates[appIdx]
+ require.True(t, ok)
+ require.Equal(t, state.Schema, got.Schema)
+ require.Equal(t, state.KeyValue, got.KeyValue)
+ })
+ }
+}
diff --git a/daemon/algod/api/server/v2/dryrun_test.go b/daemon/algod/api/server/v2/dryrun_test.go
index 8bd7addc92..de5d15c826 100644
--- a/daemon/algod/api/server/v2/dryrun_test.go
+++ b/daemon/algod/api/server/v2/dryrun_test.go
@@ -1087,6 +1087,32 @@ func TestStateDeltaToStateDelta(t *testing.T) {
gsd := globalDeltaToStateDelta(sd)
require.Equal(t, 3, len(gsd))
+ decode := func(msd model.StateDelta) basics.StateDelta {
+ if len(msd) == 0 {
+ return nil
+ }
+ result := make(basics.StateDelta, len(msd))
+ for _, kv := range msd {
+ keyBytes, err := base64.StdEncoding.DecodeString(kv.Key)
+ require.NoError(t, err)
+ vd := basics.ValueDelta{Action: basics.DeltaAction(kv.Value.Action)}
+ if kv.Value.Bytes != nil {
+ decoded, err := base64.StdEncoding.DecodeString(*kv.Value.Bytes)
+ require.NoError(t, err)
+ vd.Bytes = string(decoded)
+ }
+ if kv.Value.Uint != nil {
+ vd.Uint = *kv.Value.Uint
+ }
+ result[string(keyBytes)] = vd
+ }
+ return result
+ }
+
+ // Test the manually constructed StateDelta round-trips correctly
+ result := decode(globalDeltaToStateDelta(sd))
+ require.Equal(t, sd, result)
+
var keys []string
// test with a loop because sd is a map and iteration order is random
for _, item := range gsd {
diff --git a/data/basics/teal_test.go b/data/basics/teal_test.go
index 50b0501e49..792913d231 100644
--- a/data/basics/teal_test.go
+++ b/data/basics/teal_test.go
@@ -20,10 +20,36 @@ import (
"testing"
"github.com/stretchr/testify/require"
+ "pgregory.net/rapid"
"github.com/algorand/go-algorand/test/partitiontest"
)
+// genTealValue generates a valid TealValue with proper Type/field correspondence.
+func genTealValue() *rapid.Generator[TealValue] {
+ return rapid.Custom(func(t *rapid.T) TealValue {
+ tealType := rapid.OneOf(rapid.Just(TealUintType), rapid.Just(TealBytesType)).Draw(t, "type")
+
+ if tealType == TealUintType {
+ return TealValue{Type: TealUintType, Uint: rapid.Uint64().Draw(t, "uint")}
+ }
+ return TealValue{Type: TealBytesType, Bytes: rapid.String().Draw(t, "bytes")}
+ })
+}
+
+// genValueDelta generates a valid ValueDelta with proper Action/field correspondence.
+// Note: DeleteAction is excluded as it doesn't round-trip to TealValue.
+func genValueDelta() *rapid.Generator[ValueDelta] {
+ return rapid.Custom(func(t *rapid.T) ValueDelta {
+ action := rapid.OneOf(rapid.Just(SetUintAction), rapid.Just(SetBytesAction)).Draw(t, "action")
+
+ if action == SetUintAction {
+ return ValueDelta{Action: SetUintAction, Uint: rapid.Uint64().Draw(t, "uint")}
+ }
+ return ValueDelta{Action: SetBytesAction, Bytes: rapid.String().Draw(t, "bytes")}
+ })
+}
+
func TestStateDeltaEqual(t *testing.T) {
partitiontest.PartitionTest(t)
@@ -60,3 +86,45 @@ func TestStateDeltaEqual(t *testing.T) {
d2 = StateDelta{"test": {Action: SetBytesAction, Bytes: "val1"}}
a.False(d1.Equal(d2))
}
+
+func TestTealValueRoundTrip(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ // Test with a simple example value
+ example := TealValue{Type: TealUintType, Uint: 17}
+
+ // TealValue has constraints (Type determines valid fields), so test the specific example
+ toVD := func(tv TealValue) ValueDelta { return tv.ToValueDelta() }
+ toTV := func(vd ValueDelta) TealValue {
+ tv, ok := vd.ToTealValue()
+ require.True(t, ok)
+ return tv
+ }
+ result := toTV(toVD(example))
+ require.Equal(t, example, result)
+}
+
+func TestValueDeltaRoundTrip(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ // Test with a simple example value
+ example := ValueDelta{Action: SetUintAction, Uint: 42}
+
+ // ValueDelta has constraints (Action determines valid fields), so test the specific example
+ toTV := func(vd ValueDelta) TealValue {
+ tv, ok := vd.ToTealValue()
+ require.True(t, ok)
+ return tv
+ }
+ toVD := func(tv TealValue) ValueDelta { return tv.ToValueDelta() }
+ result := toVD(toTV(example))
+ require.Equal(t, example, result)
+}
+
+func TestValueDeltaDeleteDoesNotRoundTrip(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ vd := ValueDelta{Action: DeleteAction}
+ _, ok := vd.ToTealValue()
+ require.False(t, ok)
+}
diff --git a/data/basics/testing/copiers.go b/data/basics/testing/copiers.go
deleted file mode 100644
index e2df453e6e..0000000000
--- a/data/basics/testing/copiers.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
-// This file is part of go-algorand
-//
-// go-algorand is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// go-algorand is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with go-algorand. If not, see .
-
-package testing
-
-import (
- "reflect"
- "testing"
-)
-
-// RoundTrip checks that converting an A -> B -> A gives the original value.
-// Returns true if equal, false otherwise.
-func RoundTrip[A any, B any](t *testing.T, a A, toB func(A) B, toA func(B) A) bool {
- b := toB(a)
- a2 := toA(b)
- return reflect.DeepEqual(a, a2)
-}
diff --git a/data/basics/testing/nearzero.go b/data/basics/testing/roundtrip/nearzero.go
similarity index 99%
rename from data/basics/testing/nearzero.go
rename to data/basics/testing/roundtrip/nearzero.go
index 0482797e94..0607172c70 100644
--- a/data/basics/testing/nearzero.go
+++ b/data/basics/testing/roundtrip/nearzero.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with go-algorand. If not, see .
-package testing
+package roundtrip
import (
"reflect"
diff --git a/data/basics/testing/nearzero_test.go b/data/basics/testing/roundtrip/nearzero_test.go
similarity index 99%
rename from data/basics/testing/nearzero_test.go
rename to data/basics/testing/roundtrip/nearzero_test.go
index f1aaf32058..b8c71f1ad0 100644
--- a/data/basics/testing/nearzero_test.go
+++ b/data/basics/testing/roundtrip/nearzero_test.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with go-algorand. If not, see .
-package testing
+package roundtrip
import (
"testing"
diff --git a/data/basics/testing/roundtrip/roundtrip.go b/data/basics/testing/roundtrip/roundtrip.go
new file mode 100644
index 0000000000..c1ccd7e15e
--- /dev/null
+++ b/data/basics/testing/roundtrip/roundtrip.go
@@ -0,0 +1,54 @@
+// Copyright (C) 2019-2025 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see .
+
+package roundtrip
+
+import (
+ "reflect"
+ "testing"
+)
+
+// Check verifies that converting from A -> B -> A yields the original value.
+// It tests the provided example value, then tests all NearZeros variants (setting one field at a time).
+// NearZeros is tested first because failures clearly identify which field is problematic.
+func Check[A any, B any](t *testing.T, example A, toB func(A) B, toA func(B) A) {
+ t.Helper()
+
+ // Test the provided example
+ if !checkOne(t, example, toB, toA) {
+ t.Fatalf("Round-trip failed for provided example: %+v", example)
+ }
+
+ // Test NearZeros (one test per field) - comprehensive and deterministic
+ // This comes first because failures clearly show which field is the problem
+ nearZeroValues := NearZeros(t, example)
+ for i, nzA := range nearZeroValues {
+ if !checkOne(t, nzA, toB, toA) {
+ t.Fatalf("Round-trip failed for NearZero variant %d: %+v", i, nzA)
+ }
+ }
+}
+
+func checkOne[A any, B any](t *testing.T, a A, toB func(A) B, toA func(B) A) bool {
+ t.Helper()
+ b := toB(a)
+ a2 := toA(b)
+ if !reflect.DeepEqual(a, a2) {
+ t.Logf("Round-trip mismatch:\n Original: %+v\n After: %+v", a, a2)
+ return false
+ }
+ return true
+}
diff --git a/data/transactions/application_test.go b/data/transactions/application_test.go
index 223c7a4ae8..d48105ce97 100644
--- a/data/transactions/application_test.go
+++ b/data/transactions/application_test.go
@@ -27,7 +27,7 @@ import (
"github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/data/basics"
- basics_testing "github.com/algorand/go-algorand/data/basics/testing"
+ "github.com/algorand/go-algorand/data/basics/testing/roundtrip"
"github.com/algorand/go-algorand/protocol"
"github.com/algorand/go-algorand/test/partitiontest"
)
@@ -37,7 +37,7 @@ func TestResourceRefEmpty(t *testing.T) {
t.Parallel()
assert.True(t, ResourceRef{}.Empty())
- for _, rr := range basics_testing.NearZeros(t, ResourceRef{}) {
+ for _, rr := range roundtrip.NearZeros(t, ResourceRef{}) {
assert.False(t, rr.Empty(), "Empty is disregarding a non-zero field in %+v", rr)
}
}
@@ -51,7 +51,7 @@ func TestApplicationCallFieldsEmpty(t *testing.T) {
ac := ApplicationCallTxnFields{}
a.True(ac.Empty())
- for _, fields := range basics_testing.NearZeros(t, ac) {
+ for _, fields := range roundtrip.NearZeros(t, ac) {
a.False(fields.Empty(), "Empty is disregarding a non-zero field in %+v", fields)
}
}
diff --git a/data/transactions/transaction_test.go b/data/transactions/transaction_test.go
index 1d9f04d5f0..f214ca16df 100644
--- a/data/transactions/transaction_test.go
+++ b/data/transactions/transaction_test.go
@@ -25,7 +25,7 @@ import (
"github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/data/basics"
- basics_testing "github.com/algorand/go-algorand/data/basics/testing"
+ "github.com/algorand/go-algorand/data/basics/testing/roundtrip"
"github.com/algorand/go-algorand/protocol"
"github.com/algorand/go-algorand/test/partitiontest"
)
@@ -124,7 +124,7 @@ func TestApplyDataEquality(t *testing.T) {
t.Parallel()
var empty ApplyData
- for _, ad := range basics_testing.NearZeros(t, ApplyData{}) {
+ for _, ad := range roundtrip.NearZeros(t, ApplyData{}) {
assert.False(t, ad.Equal(empty), "Equal() seems to be disregarding something %+v", ad)
}
@@ -135,7 +135,7 @@ func TestEvalDataEquality(t *testing.T) {
t.Parallel()
var empty EvalDelta
- for _, ed := range basics_testing.NearZeros(t, EvalDelta{}) {
+ for _, ed := range roundtrip.NearZeros(t, EvalDelta{}) {
assert.False(t, ed.Equal(empty), "Equal() seems to be disregarding something %+v", ed)
}
@@ -146,7 +146,7 @@ func TestLogicSigEquality(t *testing.T) {
t.Parallel()
var empty LogicSig
- for _, ls := range basics_testing.NearZeros(t, LogicSig{}) {
+ for _, ls := range roundtrip.NearZeros(t, LogicSig{}) {
assert.False(t, ls.Equal(&empty), "Equal() seems to be disregarding something %+v", ls)
}
diff --git a/ledger/store/trackerdb/data_test.go b/ledger/store/trackerdb/data_test.go
index 4524169b89..471be82ecf 100644
--- a/ledger/store/trackerdb/data_test.go
+++ b/ledger/store/trackerdb/data_test.go
@@ -26,7 +26,7 @@ import (
"github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/data/basics"
- basics_testing "github.com/algorand/go-algorand/data/basics/testing"
+ "github.com/algorand/go-algorand/data/basics/testing/roundtrip"
"github.com/algorand/go-algorand/ledger/ledgercore"
ledgertesting "github.com/algorand/go-algorand/ledger/testing"
"github.com/algorand/go-algorand/protocol"
@@ -1291,9 +1291,8 @@ func TestCopyFunctions(t *testing.T) {
rdToAsset := func(rd ResourcesData) basics.AssetParams {
return rd.GetAssetParams()
}
- for _, nz := range basics_testing.NearZeros(t, basics.AssetParams{}) {
- assert.True(t, basics_testing.RoundTrip(t, nz, assetToRD, rdToAsset), nz)
- }
+ // roundtrip.Check automatically tests the example plus NearZeros variants
+ roundtrip.Check(t, basics.AssetParams{}, assetToRD, rdToAsset)
// Asset holdings are copied into and out of ResourceData losslessly
holdingToRD := func(ap basics.AssetHolding) ResourcesData {
@@ -1304,9 +1303,7 @@ func TestCopyFunctions(t *testing.T) {
rdToHolding := func(rd ResourcesData) basics.AssetHolding {
return rd.GetAssetHolding()
}
- for _, nz := range basics_testing.NearZeros(t, basics.AssetHolding{}) {
- assert.True(t, basics_testing.RoundTrip(t, nz, holdingToRD, rdToHolding), nz)
- }
+ roundtrip.Check(t, basics.AssetHolding{}, holdingToRD, rdToHolding)
// AppParams are copied into and out of ResourceData losslessly
apToRD := func(ap basics.AppParams) ResourcesData {
@@ -1317,9 +1314,7 @@ func TestCopyFunctions(t *testing.T) {
rdToAP := func(rd ResourcesData) basics.AppParams {
return rd.GetAppParams()
}
- for _, nz := range basics_testing.NearZeros(t, basics.AppParams{}) {
- assert.True(t, basics_testing.RoundTrip(t, nz, apToRD, rdToAP), nz)
- }
+ roundtrip.Check(t, basics.AppParams{}, apToRD, rdToAP)
// AppLocalStates are copied into and out of ResourceData losslessly
localsToRD := func(ap basics.AppLocalState) ResourcesData {
@@ -1330,9 +1325,7 @@ func TestCopyFunctions(t *testing.T) {
rdToLocals := func(rd ResourcesData) basics.AppLocalState {
return rd.GetAppLocalState()
}
- for _, nz := range basics_testing.NearZeros(t, basics.AppLocalState{}) {
- assert.True(t, basics_testing.RoundTrip(t, nz, localsToRD, rdToLocals), nz)
- }
+ roundtrip.Check(t, basics.AppLocalState{}, localsToRD, rdToLocals)
}
@@ -1340,7 +1333,7 @@ func TestIsEmptyAppFields(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
- for _, nz := range basics_testing.NearZeros(t, basics.AppParams{}) {
+ for _, nz := range roundtrip.NearZeros(t, basics.AppParams{}) {
var rd ResourcesData
rd.SetAppParams(nz, false)
assert.False(t, rd.IsEmptyAppFields(), nz)
diff --git a/network/msgOfInterest_test.go b/network/msgOfInterest_test.go
index c596781d64..94cbcb904f 100644
--- a/network/msgOfInterest_test.go
+++ b/network/msgOfInterest_test.go
@@ -17,6 +17,7 @@
package network
import (
+ "maps"
"testing"
"github.com/stretchr/testify/require"
@@ -70,3 +71,22 @@ func TestMarshallMessageOfInterest(t *testing.T) {
require.Equal(t, tags[protocol.AgreementVoteTag], true)
require.Equal(t, 1, len(tags))
}
+
+func TestDefaultSendMessageTagsMarshalRoundTrip(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ cloned := maps.Clone(defaultSendMessageTags)
+
+ toBytes := func(tags map[protocol.Tag]bool) []byte {
+ return marshallMessageOfInterestMap(tags)
+ }
+ toTags := func(data []byte) map[protocol.Tag]bool {
+ tags, err := unmarshallMessageOfInterest(data)
+ require.NoError(t, err)
+ return tags
+ }
+
+ // Test that default messages of interest round-trip correctly
+ result := toTags(toBytes(cloned))
+ require.Equal(t, cloned, result, "default messages of interest should round-trip")
+}