github.com/blend/go-sdk@v1.20240719.1/ex/as_test.go (about) 1 /* 2 3 Copyright (c) 2024 - Present. Blend Labs, Inc. All rights reserved 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file. 5 6 */ 7 8 package ex 9 10 import ( 11 "errors" 12 "fmt" 13 "testing" 14 15 "github.com/blend/go-sdk/assert" 16 ) 17 18 type customError struct { 19 err error 20 } 21 22 func (e *customError) Unwrap() error { 23 return e.err 24 } 25 26 func (e *customError) Error() string { 27 return e.err.Error() 28 } 29 30 func TestAs(t *testing.T) { 31 // base sentinel errors to check against 32 baseSentinel := &Ex{Class: Class("sentinel")} 33 baseSentinelAlt := &Ex{Class: Class("sentinel alt")} 34 35 exSentinelErr := New("sentinel") 36 stdLibSentinelErr := errors.New("sentinel") 37 nonPointerExErr := Ex{Class: Class("sentinel")} 38 customErrWrappingEx := customError{err: exSentinelErr} 39 customErrWrappingstdLibErr := customError{err: stdLibSentinelErr} 40 customDeepWrappedErr := customError{ 41 err: fmt.Errorf( 42 "Top of deep error: %w", 43 fmt.Errorf( 44 "Level 1 of deep error: %w", 45 &customError{err: New(exSentinelErr)}, 46 ), 47 ), 48 } 49 50 // Note: Multi's Unwrap method converts all errors in the error chain to *ex.Ex. 51 multiErrorWithStdLibFirst := Append(stdLibSentinelErr, baseSentinelAlt) 52 multiErrorWithAltFirst := Append(baseSentinelAlt, exSentinelErr) 53 multiErrorWithSentinelFirst := Append(exSentinelErr, baseSentinelAlt) 54 55 tests := []struct { 56 name string 57 candidate error 58 expectedEx *Ex 59 }{ 60 { 61 name: "stdlib error is not Ex pointer", 62 candidate: stdLibSentinelErr, 63 expectedEx: nil, 64 }, 65 { 66 name: "error from New is Ex pointer", 67 candidate: exSentinelErr, 68 expectedEx: baseSentinel, 69 }, 70 { 71 name: "non pointer Ex is resolved to Ex pointer", 72 candidate: &nonPointerExErr, 73 expectedEx: baseSentinel, 74 }, 75 { 76 name: "Handles custom errors that wrap Ex pointer", 77 candidate: &customErrWrappingEx, 78 expectedEx: baseSentinel, 79 }, 80 { 81 name: "wrapped stdlib error is no Ex pointer", 82 candidate: &customErrWrappingstdLibErr, 83 expectedEx: nil, 84 }, 85 { 86 name: "deeply nested Ex pointer is extracted", 87 candidate: &customDeepWrappedErr, 88 expectedEx: baseSentinel, 89 }, 90 { 91 name: "Returns first Ex in Multi error chain", 92 candidate: multiErrorWithAltFirst, 93 expectedEx: baseSentinelAlt, 94 }, 95 { 96 name: "Returns first Ex in Multi error chain alt", 97 candidate: multiErrorWithSentinelFirst, 98 expectedEx: baseSentinel, 99 }, 100 { 101 name: "Returns first error as Ex in Multi error chain", 102 candidate: multiErrorWithStdLibFirst, 103 expectedEx: baseSentinel, 104 }, 105 } 106 107 for _, test := range tests { 108 test := test 109 t.Run(test.name, func(t *testing.T) { 110 t.Parallel() 111 its := assert.New(t) 112 maybeEx := As(test.candidate) 113 if test.expectedEx == nil { 114 its.Nil(maybeEx) 115 return 116 } 117 its.NotNil(maybeEx) 118 its.Equal(test.expectedEx.Error(), maybeEx.Error()) 119 }) 120 } 121 }