Skip to content

Commit d1da52e

Browse files
authored
Test: Use NearZeros to make simple Equal() tests (algorand#6458)
1 parent 9ab4e78 commit d1da52e

File tree

3 files changed

+66
-7
lines changed

3 files changed

+66
-7
lines changed

data/basics/testing/nearzero.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package testing
1818

1919
import (
2020
"reflect"
21+
"slices"
2122
"testing"
2223
"time"
2324
)
@@ -35,7 +36,7 @@ func NearZeros(t *testing.T, sample any) []any {
3536
if typ.Kind() != reflect.Struct {
3637
t.Fatalf("NearZeros: sample must be a struct, got %s", typ.Kind())
3738
}
38-
paths := CollectPaths(typ, []int{})
39+
paths := collectPaths(typ, nil, nil)
3940
var results []any
4041
for _, path := range paths {
4142
inst := makeInstanceWithNonZeroField(typ, path)
@@ -45,14 +46,22 @@ func NearZeros(t *testing.T, sample any) []any {
4546
}
4647

4748
// CollectPaths walks over the struct type (recursively) and returns a slice of
48-
// index paths. Each path points to exactly one (exported) sub-field.
49+
// index paths. Each path points to exactly one (exported) sub-field. If the
50+
// type supplied is recursive, the path terminates at the recursion point.
4951
func CollectPaths(typ reflect.Type, prefix []int) [][]int {
52+
return collectPaths(typ, prefix, []reflect.Type{})
53+
}
54+
55+
// collectPaths walks over the struct type (recursively) and returns a slice of
56+
// index paths. Each path points to exactly one (exported) sub-field.
57+
// It tracks types in the current path to avoid infinite loops on recursive types.
58+
func collectPaths(typ reflect.Type, prefix []int, pathStack []reflect.Type) [][]int {
5059
var paths [][]int
5160

5261
switch typ.Kind() {
5362
case reflect.Ptr, reflect.Slice, reflect.Array:
5463
// Look through container to the element
55-
return CollectPaths(typ.Elem(), prefix)
64+
return collectPaths(typ.Elem(), prefix, pathStack)
5665

5766
case reflect.Map:
5867
// Record as a leaf because we will just make a single entry in the map
@@ -64,13 +73,23 @@ func CollectPaths(typ reflect.Type, prefix []int) [][]int {
6473
return [][]int{prefix}
6574
}
6675

76+
// Check if this type is already in the path stack (cycle detection)
77+
if slices.Contains(pathStack, typ) {
78+
// We've encountered a cycle, treat this as a leaf
79+
return [][]int{prefix}
80+
}
81+
82+
// Add this type to the path stack
83+
// Clone to avoid sharing the underlying array across branches
84+
newStack := append(slices.Clone(pathStack), typ)
85+
6786
for i := 0; i < typ.NumField(); i++ {
6887
field := typ.Field(i)
6988
if !field.IsExported() {
7089
continue
7190
}
7291
newPath := append(append([]int(nil), prefix...), i)
73-
subPaths := CollectPaths(field.Type, newPath)
92+
subPaths := collectPaths(field.Type, newPath, newStack)
7493

7594
// If recursion yielded deeper paths, use them
7695
if len(subPaths) > 0 {

data/transactions/teal.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,18 @@ func (ed EvalDelta) Equal(o EvalDelta) bool {
5858
return false
5959
}
6060

61-
// GlobalDeltas must be equal
6261
if !ed.GlobalDelta.Equal(o.GlobalDelta) {
6362
return false
6463
}
6564

66-
// Logs must be equal
65+
if !slices.Equal(ed.SharedAccts, o.SharedAccts) {
66+
return false
67+
}
68+
6769
if !slices.Equal(ed.Logs, o.Logs) {
6870
return false
6971
}
7072

71-
// InnerTxns must be equal
7273
if len(ed.InnerTxns) != len(o.InnerTxns) {
7374
return false
7475
}

data/transactions/transaction_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ package transactions
1919
import (
2020
"testing"
2121

22+
"github.com/stretchr/testify/assert"
2223
"github.com/stretchr/testify/require"
2324

2425
"github.com/algorand/go-algorand/config"
2526
"github.com/algorand/go-algorand/crypto"
2627
"github.com/algorand/go-algorand/data/basics"
28+
basics_testing "github.com/algorand/go-algorand/data/basics/testing"
2729
"github.com/algorand/go-algorand/protocol"
2830
"github.com/algorand/go-algorand/test/partitiontest"
2931
)
@@ -76,6 +78,7 @@ func TestTransactionHash(t *testing.T) {
7678

7779
func TestTransactionIDChanges(t *testing.T) {
7880
partitiontest.PartitionTest(t)
81+
t.Parallel()
7982

8083
txn := Transaction{
8184
Type: "pay",
@@ -115,3 +118,39 @@ func TestTransactionIDChanges(t *testing.T) {
115118
t.Errorf("txid does not depend on lastvalid")
116119
}
117120
}
121+
122+
func TestApplyDataEquality(t *testing.T) {
123+
partitiontest.PartitionTest(t)
124+
t.Parallel()
125+
126+
var empty ApplyData
127+
for _, nz := range basics_testing.NearZeros(t, ApplyData{}) {
128+
ad := nz.(ApplyData)
129+
assert.False(t, ad.Equal(empty), "Equal() seems to be disregarding something %+v", ad)
130+
}
131+
132+
}
133+
134+
func TestEvalDataEquality(t *testing.T) {
135+
partitiontest.PartitionTest(t)
136+
t.Parallel()
137+
138+
var empty EvalDelta
139+
for _, nz := range basics_testing.NearZeros(t, EvalDelta{}) {
140+
ed := nz.(EvalDelta)
141+
assert.False(t, ed.Equal(empty), "Equal() seems to be disregarding something %+v", ed)
142+
}
143+
144+
}
145+
146+
func TestLogicSigEquality(t *testing.T) {
147+
partitiontest.PartitionTest(t)
148+
t.Parallel()
149+
150+
var empty LogicSig
151+
for _, nz := range basics_testing.NearZeros(t, LogicSig{}) {
152+
ls := nz.(LogicSig)
153+
assert.False(t, ls.Equal(&empty), "Equal() seems to be disregarding something %+v", ls)
154+
}
155+
156+
}

0 commit comments

Comments
 (0)