github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/common/rpc/errors_test.go (about)

     1  package rpc
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"github.com/hashicorp/go-multierror"
     9  	"github.com/stretchr/testify/assert"
    10  	"google.golang.org/grpc/codes"
    11  	"google.golang.org/grpc/status"
    12  
    13  	"github.com/onflow/flow-go/storage"
    14  )
    15  
    16  func TestConvertError(t *testing.T) {
    17  	defaultCode := codes.Internal
    18  	t.Run("no error", func(t *testing.T) {
    19  		err := ConvertError(nil, "", defaultCode)
    20  		assert.NoError(t, err)
    21  	})
    22  
    23  	t.Run("preset status code", func(t *testing.T) {
    24  		err := ConvertError(status.Error(codes.Unavailable, "Unavailable"), "", defaultCode)
    25  		assert.Equal(t, codes.Unavailable, status.Code(err))
    26  
    27  		err = ConvertError(status.Error(codes.OutOfRange, "OutOfRange"), "", defaultCode)
    28  		assert.Equal(t, codes.OutOfRange, status.Code(err))
    29  
    30  		err = ConvertError(status.Error(codes.Internal, "Internal"), "", defaultCode)
    31  		assert.Equal(t, codes.Internal, status.Code(err))
    32  	})
    33  
    34  	t.Run("multierror", func(t *testing.T) {
    35  		var errors *multierror.Error
    36  		errors = multierror.Append(errors, status.Error(codes.NotFound, "not found"))
    37  		errors = multierror.Append(errors, fmt.Errorf("not a grpc status code"))
    38  		errors = multierror.Append(errors, status.Error(codes.NotFound, "not found"))
    39  
    40  		err := ConvertError(errors, "some prefix", defaultCode)
    41  		assert.Equal(t, defaultCode, status.Code(err))
    42  		assert.ErrorContains(t, err, "some prefix: ")
    43  	})
    44  
    45  	t.Run("derived code", func(t *testing.T) {
    46  		err := ConvertError(context.Canceled, "", defaultCode)
    47  		assert.Equal(t, codes.Canceled, status.Code(err))
    48  
    49  		err = ConvertError(context.DeadlineExceeded, "some prefix", defaultCode)
    50  		assert.Equal(t, codes.DeadlineExceeded, status.Code(err))
    51  		assert.ErrorContains(t, err, "some prefix: ")
    52  	})
    53  
    54  	t.Run("unhandled code", func(t *testing.T) {
    55  		err := ConvertError(storage.ErrNotFound, "", defaultCode)
    56  		assert.Equal(t, codes.Internal, status.Code(err))
    57  
    58  		err = ConvertError(status.Error(codes.Unknown, "Unknown"), "", defaultCode)
    59  		assert.Equal(t, codes.Internal, status.Code(err))
    60  
    61  		err = ConvertError(status.Error(codes.Internal, "Internal"), "", defaultCode)
    62  		assert.Equal(t, codes.Internal, status.Code(err))
    63  
    64  		err = ConvertError(fmt.Errorf("unhandled error"), "", defaultCode)
    65  		assert.Equal(t, codes.Internal, status.Code(err))
    66  
    67  		err = ConvertError(fmt.Errorf("unhandled error"), "some prefix", defaultCode)
    68  		assert.Equal(t, defaultCode, status.Code(err))
    69  		assert.ErrorContains(t, err, "some prefix: ")
    70  	})
    71  }
    72  
    73  func TestConvertMultiError(t *testing.T) {
    74  	defaultCode := codes.Internal
    75  	t.Run("single error", func(t *testing.T) {
    76  		var errors *multierror.Error
    77  		errors = multierror.Append(errors, status.Error(codes.NotFound, "not found"))
    78  
    79  		err := ConvertMultiError(errors, "", defaultCode)
    80  		assert.Equal(t, codes.NotFound, status.Code(err))
    81  	})
    82  
    83  	t.Run("same code", func(t *testing.T) {
    84  		var errors *multierror.Error
    85  		errors = multierror.Append(errors, status.Error(codes.NotFound, "not found"))
    86  		errors = multierror.Append(errors, status.Error(codes.NotFound, "not found"))
    87  		errors = multierror.Append(errors, status.Error(codes.NotFound, "not found"))
    88  
    89  		err := ConvertMultiError(errors, "", defaultCode)
    90  		assert.Equal(t, codes.NotFound, status.Code(err))
    91  	})
    92  
    93  	t.Run("same codes - unavailable ignored", func(t *testing.T) {
    94  		var errors *multierror.Error
    95  		errors = multierror.Append(errors, status.Error(codes.NotFound, "not found"))
    96  		errors = multierror.Append(errors, status.Error(codes.Unavailable, "unavailable"))
    97  		errors = multierror.Append(errors, status.Error(codes.Unavailable, "unavailable"))
    98  
    99  		err := ConvertMultiError(errors, "", defaultCode)
   100  		assert.Equal(t, codes.NotFound, status.Code(err))
   101  	})
   102  
   103  	t.Run("same codes - deadline exceeded ignored", func(t *testing.T) {
   104  		var errors *multierror.Error
   105  		errors = multierror.Append(errors, status.Error(codes.DeadlineExceeded, "deadline exceeded"))
   106  		errors = multierror.Append(errors, status.Error(codes.NotFound, "not found"))
   107  		errors = multierror.Append(errors, status.Error(codes.NotFound, "not found"))
   108  
   109  		err := ConvertMultiError(errors, "", defaultCode)
   110  		assert.Equal(t, codes.NotFound, status.Code(err))
   111  	})
   112  
   113  	t.Run("all different codes", func(t *testing.T) {
   114  		var errors *multierror.Error
   115  		errors = multierror.Append(errors, status.Error(codes.NotFound, "not found"))
   116  		errors = multierror.Append(errors, status.Error(codes.Internal, "internal"))
   117  		errors = multierror.Append(errors, status.Error(codes.InvalidArgument, "invalid arg"))
   118  
   119  		err := ConvertMultiError(errors, "", defaultCode)
   120  		assert.Equal(t, defaultCode, status.Code(err))
   121  	})
   122  
   123  	t.Run("non-grpc errors", func(t *testing.T) {
   124  		var errors *multierror.Error
   125  		errors = multierror.Append(errors, status.Error(codes.NotFound, "not found"))
   126  		errors = multierror.Append(errors, fmt.Errorf("not a grpc status code"))
   127  		errors = multierror.Append(errors, status.Error(codes.NotFound, "not found"))
   128  
   129  		err := ConvertMultiError(errors, "some prefix", defaultCode)
   130  		assert.Equal(t, defaultCode, status.Code(err))
   131  		assert.ErrorContains(t, err, "some prefix: ")
   132  	})
   133  }