github.com/blend/go-sdk@v1.20240719.1/ex/is_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 func TestIs(t *testing.T) { 19 stdLibErr := errors.New("sentinel") 20 multi := Multi{New("not test class"), Class("test class")} 21 testCases := []struct { 22 Name string 23 Err error 24 Cause error 25 Expected bool 26 }{ 27 { 28 Name: "True for equal classes", 29 Err: Class("test class"), 30 Cause: Class("test class"), 31 Expected: true, 32 }, 33 { 34 Name: "True for comparing ex against class", 35 Err: New("test class"), 36 Cause: Class("test class"), 37 Expected: true, 38 }, 39 { 40 Name: "True for comparing ex against ex with equal class", 41 Err: New("test class"), 42 Cause: New("test class"), 43 Expected: true, 44 }, 45 { 46 Name: "True for comparing ex against ex with equal sentinel errors", 47 Err: New(stdLibErr), 48 Cause: stdLibErr, 49 Expected: true, 50 }, 51 { 52 Name: "True for comparing ex with wrapped sentinel error against sentinel error", 53 Err: New(fmt.Errorf("outer err: %w", stdLibErr)), 54 Cause: stdLibErr, 55 Expected: true, 56 }, 57 { 58 Name: "True for comparing a ClassProvider against sentinel error", 59 Err: classProvider{ErrClass: stdLibErr}, 60 Cause: stdLibErr, 61 Expected: true, 62 }, 63 { 64 Name: "True for comparing a ClassProvider that implements Unwrap() against sentinel error", 65 Err: wrappingClassProvider{error: stdLibErr, ErrClass: New("another class")}, 66 Cause: stdLibErr, 67 Expected: true, 68 }, 69 { 70 Name: "False for comparing multi ex against multi (due to Go slice comparison limitation)", 71 Err: Multi([]error{New("not test class"), Class("test class")}), 72 Cause: Multi([]error{New("not test class"), Class("test class")}), 73 Expected: false, 74 }, 75 { 76 Name: "False for identity comparison of multi ex (due to Go slice comparison limitation)", 77 Err: multi, 78 Cause: multi, 79 Expected: false, 80 }, 81 { 82 Name: "True for comparing multi ex against class", 83 Err: func() error { 84 var err error = Multi{Class("test class")} 85 for i := 0; i < 50; i++ { 86 err = Multi{New(err), New("not test class")} 87 } 88 return err 89 }(), 90 Cause: Class("test class"), 91 Expected: true, 92 }, 93 { 94 Name: "True for comparing multi ex (created via ex.Append()) against class", 95 Err: func() error { 96 var err error 97 for i := 0; i < 50; i++ { 98 err = Append(err, New("not test class")) 99 } 100 return Append(err, Class("test class")) 101 }(), 102 Cause: Class("test class"), 103 Expected: true, 104 }, 105 { 106 Name: "False for comparing a ClassProvider without Unwrap() against sentinel error", 107 Err: classProvider{error: stdLibErr, ErrClass: New("another class")}, 108 Cause: stdLibErr, 109 Expected: false, 110 }, 111 { 112 Name: "False for comparing multi ex against different multi #1", 113 Err: Multi([]error{New("not test class"), Class("test class"), Class("?? class")}), 114 Cause: Multi([]error{New("not test class"), Class("test class")}), 115 Expected: false, 116 }, 117 { 118 Name: "False for comparing multi ex against different multi #2", 119 Err: Multi([]error{New("not test class"), Class("test class")}), 120 Cause: Multi([]error{New("test class"), Class("not test class")}), 121 Expected: false, 122 }, 123 { 124 Name: "False for comparing multi ex (created via ex.Append()) against class", 125 Err: func() error { 126 var err error 127 for i := 0; i < 50; i++ { 128 err = Append(err, New("not test class")) 129 } 130 return Append(err, Class("test class")) 131 }(), 132 Cause: Class("neither"), 133 Expected: false, 134 }, 135 { 136 Name: "False for different classes", 137 Err: Class("not test class"), 138 Cause: New("test class"), 139 Expected: false, 140 }, 141 { 142 Name: "False for ex with different classes", 143 Err: New("test class"), 144 Cause: New("not test class"), 145 Expected: false, 146 }, 147 { 148 Name: "False for ex comparison against nil", 149 Err: New("test class"), 150 Cause: nil, 151 Expected: false, 152 }, 153 { 154 Name: "True for wrapped sentinel error", 155 Err: fmt.Errorf("outer err: %w", stdLibErr), 156 Cause: stdLibErr, 157 Expected: true, 158 }, 159 { 160 Name: "True for identity comparison of native error", 161 Err: stdLibErr, 162 Cause: stdLibErr, 163 Expected: true, 164 }, 165 { 166 Name: "False for comparison between two different instances of the same native error", 167 Err: stdLibErr, 168 Cause: errors.New("sentinel"), 169 Expected: false, 170 }, 171 { 172 Name: "False for nil comparisons", 173 Err: nil, 174 Cause: nil, 175 Expected: false, 176 }, 177 { 178 Name: "False for nil error against class", 179 Err: nil, 180 Cause: Class("test class"), 181 Expected: false, 182 }, 183 } 184 185 for _, tc := range testCases { 186 tc := tc 187 t.Run(tc.Name, func(t *testing.T) { 188 t.Parallel() 189 its := assert.New(t) 190 its.Equal(tc.Expected, Is(tc.Err, tc.Cause)) 191 }) 192 } 193 } 194 195 type wrappingClassProvider classProvider // classProvider is declared in util_test.go 196 197 // Unwrap implements the error interface. 198 func (wcp wrappingClassProvider) Unwrap() error { 199 return wcp.error 200 }