github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/access/rpc/backend/script_comparer_test.go (about) 1 package backend 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/rs/zerolog" 8 "github.com/stretchr/testify/assert" 9 "google.golang.org/grpc/codes" 10 "google.golang.org/grpc/status" 11 12 "github.com/onflow/flow-go/module/metrics" 13 "github.com/onflow/flow-go/storage" 14 "github.com/onflow/flow-go/utils/unittest" 15 ) 16 17 func TestCompare(t *testing.T) { 18 m := metrics.NewNoopCollector() 19 logger := zerolog.Nop() 20 21 result1 := []byte("result1") 22 result2 := []byte("result2") 23 24 error1 := status.Error(codes.InvalidArgument, "error1") 25 error2 := status.Error(codes.InvalidArgument, "error2") 26 27 outOfRange := status.Error(codes.OutOfRange, "out of range") 28 29 testcases := []struct { 30 name string 31 execResult *scriptResult 32 localResult *scriptResult 33 expected bool 34 }{ 35 { 36 name: "results match", 37 execResult: newScriptResult(result1, 0, nil), 38 localResult: newScriptResult(result1, 0, nil), 39 expected: true, 40 }, 41 { 42 name: "results do not match", 43 execResult: newScriptResult(result1, 0, nil), 44 localResult: newScriptResult(result2, 0, nil), 45 expected: false, 46 }, 47 { 48 name: "en returns result, local returns error", 49 execResult: newScriptResult(result1, 0, nil), 50 localResult: newScriptResult(nil, 0, error1), 51 expected: false, 52 }, 53 { 54 name: "en returns error, local returns result", 55 execResult: newScriptResult(nil, 0, error1), 56 localResult: newScriptResult(result1, 0, nil), 57 expected: false, 58 }, 59 { 60 // demonstrate this works by passing the same result since the OOR check happens first 61 // if the check failed, this should return true 62 name: "local returns out of range", 63 execResult: newScriptResult(result1, 0, nil), 64 localResult: newScriptResult(result1, 0, outOfRange), 65 expected: false, 66 }, 67 { 68 name: "both return same error", 69 execResult: newScriptResult(nil, 0, error1), 70 localResult: newScriptResult(nil, 0, error1), 71 expected: true, 72 }, 73 { 74 name: "both return different errors", 75 execResult: newScriptResult(nil, 0, error1), 76 localResult: newScriptResult(nil, 0, error2), 77 expected: false, 78 }, 79 } 80 81 request := newScriptExecutionRequest(unittest.IdentifierFixture(), 1, []byte("script"), [][]byte{}) 82 comparer := newScriptResultComparison(logger, m, request) 83 84 for _, tc := range testcases { 85 t.Run(tc.name, func(t *testing.T) { 86 actual := comparer.compare(tc.execResult, tc.localResult) 87 assert.Equalf(t, tc.expected, actual, "expected %v, got %v", tc.expected, actual) 88 }) 89 } 90 } 91 92 func TestCompareErrors(t *testing.T) { 93 testcases := []struct { 94 name string 95 execErr error 96 localErr error 97 expected bool 98 }{ 99 { 100 name: "both nil", 101 execErr: nil, 102 localErr: nil, 103 expected: true, 104 }, 105 { 106 name: "same error", 107 execErr: storage.ErrNotFound, 108 localErr: storage.ErrNotFound, 109 expected: true, 110 }, 111 { 112 name: "same error message", 113 execErr: fmt.Errorf("same error message"), 114 localErr: fmt.Errorf("same error message"), 115 expected: true, 116 }, 117 { 118 name: "same error code", 119 execErr: status.Error(codes.InvalidArgument, "some message"), 120 localErr: status.Error(codes.InvalidArgument, "some message"), 121 expected: true, 122 }, 123 { 124 name: "different error code", 125 execErr: status.Error(codes.Canceled, "some message"), 126 localErr: status.Error(codes.DeadlineExceeded, "some message"), 127 expected: false, 128 }, 129 { 130 name: "same error code, different message", 131 execErr: status.Error(codes.InvalidArgument, "some message"), 132 localErr: status.Error(codes.InvalidArgument, "different message"), 133 expected: false, 134 }, 135 { 136 name: "same error, different prefix", 137 execErr: status.Errorf(codes.InvalidArgument, "original: %s: some message", executeErrorPrefix), 138 localErr: status.Errorf(codes.InvalidArgument, "anything: %s: some message", executeErrorPrefix), 139 expected: true, 140 }, 141 { 142 name: "different error, different prefix", 143 execErr: status.Errorf(codes.InvalidArgument, "original: %s: some message", executeErrorPrefix), 144 localErr: status.Errorf(codes.InvalidArgument, "anything: %s: another message", executeErrorPrefix), 145 expected: false, 146 }, 147 { 148 name: "truncated error, match", 149 execErr: status.Errorf(codes.InvalidArgument, "original: %s: this is the original message", executeErrorPrefix), 150 localErr: status.Errorf(codes.InvalidArgument, "anything: %s: this is ... message", executeErrorPrefix), 151 expected: true, 152 }, 153 { 154 name: "truncated error, do not match", 155 execErr: status.Errorf(codes.InvalidArgument, "original: %s: this is the original message", executeErrorPrefix), 156 localErr: status.Errorf(codes.InvalidArgument, "anything: %s: this is ... a different message", executeErrorPrefix), 157 expected: false, 158 }, 159 } 160 161 for _, tc := range testcases { 162 t.Run(tc.name, func(t *testing.T) { 163 actual := compareErrors(tc.execErr, tc.localErr) 164 assert.Equalf(t, tc.expected, actual, "expected %v, got %v", tc.expected, actual) 165 }) 166 } 167 }