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  }