github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/errors/errors_collector_test.go (about)

     1  package errors
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/require"
     8  )
     9  
    10  func TestErrorsCollector(t *testing.T) {
    11  	t.Run("basic collection", func(t *testing.T) {
    12  		collector := ErrorsCollector{}
    13  
    14  		// Collecting nil is ok
    15  		require.False(t, collector.Collect(nil).CollectedFailure())
    16  		require.False(t, collector.CollectedError())
    17  		require.Nil(t, collector.ErrorOrNil())
    18  
    19  		// Collected non-fatal errors
    20  		err1 := NewOperationNotSupportedError("op1")
    21  		require.False(
    22  			t,
    23  			collector.Collect(fmt.Errorf("error wrapped: %w", err1)).
    24  				CollectedFailure())
    25  
    26  		require.True(t, collector.CollectedError())
    27  		err := collector.ErrorOrNil()
    28  		require.NotNil(t, err)
    29  		require.ErrorContains(t, err, "op1")
    30  		require.False(t, IsFailure(err))
    31  
    32  		require.True(t, IsOperationNotSupportedError(err))
    33  		found := Find(err, ErrCodeOperationNotSupportedError)
    34  		require.Equal(t, err1, found)
    35  
    36  		nonFatal, fatal := SplitErrorTypes(err)
    37  		require.Nil(t, fatal)
    38  		require.NotNil(t, nonFatal)
    39  		require.Equal(t, ErrCodeOperationNotSupportedError, nonFatal.Code())
    40  
    41  		err2 := NewInvalidArgumentErrorf("bad arg")
    42  		require.False(t, collector.Collect(err2).CollectedFailure())
    43  
    44  		require.True(t, collector.CollectedError())
    45  		err = collector.ErrorOrNil()
    46  		require.NotNil(t, err)
    47  		require.ErrorContains(t, err, "error wrapped")
    48  		require.ErrorContains(t, err, "op1")
    49  		require.ErrorContains(t, err, "bad arg")
    50  		require.False(t, IsFailure(err))
    51  
    52  		require.True(t, IsOperationNotSupportedError(err))
    53  		found = Find(err, ErrCodeOperationNotSupportedError)
    54  		require.Equal(t, err1, found)
    55  
    56  		require.True(t, IsInvalidArgumentError(err))
    57  		found = Find(err, ErrCodeInvalidArgumentError)
    58  		require.Equal(t, err2, found)
    59  
    60  		nonFatal, fatal = SplitErrorTypes(err)
    61  		require.Nil(t, fatal)
    62  		require.NotNil(t, nonFatal)
    63  		require.Equal(t, ErrCodeOperationNotSupportedError, nonFatal.Code())
    64  
    65  		// Collected fatal error
    66  		require.True(
    67  			t,
    68  			collector.Collect(
    69  				fmt.Errorf(
    70  					"failure wrapped: %w",
    71  					NewLedgerFailure(fmt.Errorf("fatal1"))),
    72  			).CollectedFailure())
    73  
    74  		require.True(t, collector.CollectedError())
    75  		err = collector.ErrorOrNil()
    76  		require.NotNil(t, err)
    77  		require.ErrorContains(t, err, "error wrapped")
    78  		require.ErrorContains(t, err, "op1")
    79  		require.ErrorContains(t, err, "bad arg")
    80  		require.ErrorContains(t, err, "failure wrapped")
    81  		require.ErrorContains(t, err, "fatal1")
    82  		require.True(t, IsFailure(err))
    83  
    84  		// Note: when a fatal error is collected, the non-fatal errors are no
    85  		// longer accessible.
    86  		require.False(t, IsOperationNotSupportedError(err))
    87  		require.False(t, IsInvalidArgumentError(err))
    88  		require.True(t, IsLedgerFailure(err))
    89  
    90  		nonFatal, fatal = SplitErrorTypes(err)
    91  		require.Nil(t, nonFatal)
    92  		require.NotNil(t, fatal)
    93  		require.Equal(t, FailureCodeLedgerFailure, fatal.Code())
    94  
    95  		// Collecting a non-fatal error after a fatal error should still be
    96  		// fatal
    97  		require.True(
    98  			t,
    99  			collector.Collect(
   100  				NewOperationNotSupportedError("op3"),
   101  			).CollectedFailure())
   102  
   103  		require.True(t, collector.CollectedError())
   104  		err = collector.ErrorOrNil()
   105  		require.NotNil(t, err)
   106  		require.ErrorContains(t, err, "error wrapped")
   107  		require.ErrorContains(t, err, "op1")
   108  		require.ErrorContains(t, err, "bad arg")
   109  		require.ErrorContains(t, err, "op3")
   110  		require.ErrorContains(t, err, "failure wrapped")
   111  		require.ErrorContains(t, err, "fatal1")
   112  		require.True(t, IsFailure(err))
   113  
   114  		nonFatal, fatal = SplitErrorTypes(err)
   115  		require.Nil(t, nonFatal)
   116  		require.NotNil(t, fatal)
   117  		require.Equal(t, FailureCodeLedgerFailure, fatal.Code())
   118  
   119  		// Collected multiple fatal errors (This should never happen, but just
   120  		// in case)
   121  		require.True(
   122  			t,
   123  			collector.Collect(fmt.Errorf("fatal2")).CollectedFailure())
   124  
   125  		require.True(t, collector.CollectedError())
   126  		err = collector.ErrorOrNil()
   127  		require.NotNil(t, err)
   128  		require.ErrorContains(t, err, "error wrapped")
   129  		require.ErrorContains(t, err, "op1")
   130  		require.ErrorContains(t, err, "bad arg")
   131  		require.ErrorContains(t, err, "op3")
   132  		require.ErrorContains(t, err, "failure wrapped")
   133  		require.ErrorContains(t, err, "fatal1")
   134  		require.ErrorContains(t, err, "fatal2")
   135  		require.True(t, IsFailure(err))
   136  
   137  		nonFatal, fatal = SplitErrorTypes(err)
   138  		require.Nil(t, nonFatal)
   139  		require.NotNil(t, fatal)
   140  		require.Equal(t, FailureCodeLedgerFailure, fatal.Code())
   141  	})
   142  
   143  	t.Run("failure only", func(t *testing.T) {
   144  		collector := ErrorsCollector{}
   145  
   146  		require.True(
   147  			t,
   148  			collector.Collect(fmt.Errorf("fatal1")).CollectedFailure())
   149  
   150  		require.True(t, collector.CollectedError())
   151  		err := collector.ErrorOrNil()
   152  		require.NotNil(t, err)
   153  		require.ErrorContains(t, err, "fatal1")
   154  		require.True(t, IsFailure(err))
   155  
   156  		nonFatal, fatal := SplitErrorTypes(err)
   157  		require.Nil(t, nonFatal)
   158  		require.NotNil(t, fatal)
   159  		require.Equal(t, FailureCodeUnknownFailure, fatal.Code())
   160  	})
   161  }