go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/sdk/errutil/multi_test.go (about) 1 /* 2 3 Copyright (c) 2023 - Present. Will Charczuk. All rights reserved. 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository. 5 6 */ 7 8 package errutil 9 10 import ( 11 "errors" 12 "fmt" 13 "testing" 14 ) 15 16 func TestError_Impl(t *testing.T) { 17 var _ error = (*Multi)(nil) 18 } 19 20 func TestErrorError_default(t *testing.T) { 21 expected := `2 errors occurred: 22 * foo 23 * bar 24 25 ` 26 27 errors := []error{ 28 errors.New("foo"), 29 errors.New("bar"), 30 } 31 32 multi := Multi(errors) 33 if multi.Error() != expected { 34 t.Fatalf("bad: %s", multi.Error()) 35 } 36 } 37 38 func Test_Multi_WrappedErrors(t *testing.T) { 39 errors := []error{ 40 errors.New("foo"), 41 errors.New("bar"), 42 } 43 44 multi := Multi(errors) 45 wrapped := multi.WrappedErrors() 46 for x := 0; x < len(errors); x++ { 47 if wrapped[x].Error() != errors[x].Error() { 48 t.Fatalf("bad: %s vs. %s", wrapped[x], errors[x]) 49 } 50 } 51 52 multi = nil 53 if err := multi.WrappedErrors(); err != nil { 54 t.Fatalf("bad: %#v", multi) 55 } 56 } 57 58 func TestErrorUnwrap(t *testing.T) { 59 t.Run("with errors", func(t *testing.T) { 60 err := Multi([]error{ 61 errors.New("foo"), 62 errors.New("bar"), 63 errors.New("baz"), 64 }) 65 66 var current error = err 67 for i := 0; i < len(err); i++ { 68 current = errors.Unwrap(current) 69 if !errors.Is(current, err[i]) { 70 t.Fatal("should be next value") 71 } 72 } 73 74 if errors.Unwrap(current) != nil { 75 t.Fatal("should be nil at the end") 76 } 77 }) 78 79 t.Run("with no errors", func(t *testing.T) { 80 err := Multi{} 81 if errors.Unwrap(err) != nil { 82 t.Fatal("should be nil") 83 } 84 }) 85 86 t.Run("with nil multierror", func(t *testing.T) { 87 var err Multi 88 if errors.Unwrap(err) != nil { 89 t.Fatal("should be nil") 90 } 91 }) 92 } 93 94 func TestErrorIs(t *testing.T) { 95 errBar := errors.New("bar") 96 97 t.Run("with errBar", func(t *testing.T) { 98 err := Multi([]error{ 99 errors.New("foo"), 100 errBar, 101 errors.New("baz"), 102 }) 103 104 if !errors.Is(err, errBar) { 105 t.Fatal("should be true") 106 } 107 }) 108 109 t.Run("with errBar wrapped by fmt.Errorf", func(t *testing.T) { 110 err := Multi([]error{ 111 errors.New("foo"), 112 fmt.Errorf("errorf: %w", errBar), 113 errors.New("baz"), 114 }) 115 116 if !errors.Is(err, errBar) { 117 t.Fatal("should be true") 118 } 119 }) 120 121 t.Run("without errBar", func(t *testing.T) { 122 err := Multi([]error{ 123 errors.New("foo"), 124 errors.New("baz"), 125 }) 126 127 if errors.Is(err, errBar) { 128 t.Fatal("should be false") 129 } 130 }) 131 } 132 133 func TestErrorAs(t *testing.T) { 134 match := &nestedError{} 135 136 t.Run("with the value", func(t *testing.T) { 137 err := Multi([]error{ 138 errors.New("foo"), 139 match, 140 errors.New("baz"), 141 }) 142 143 var target *nestedError 144 if !errors.As(err, &target) { 145 t.Fatal("should be true") 146 } 147 if target == nil { 148 t.Fatal("target should not be nil") 149 } 150 }) 151 152 t.Run("with the value wrapped by fmt.Errorf", func(t *testing.T) { 153 err := Multi([]error{ 154 errors.New("foo"), 155 fmt.Errorf("errorf: %w", match), 156 errors.New("baz"), 157 }) 158 159 var target *nestedError 160 if !errors.As(err, &target) { 161 t.Fatal("should be true") 162 } 163 if target == nil { 164 t.Fatal("target should not be nil") 165 } 166 }) 167 168 t.Run("without the value", func(t *testing.T) { 169 err := Multi([]error{ 170 errors.New("foo"), 171 errors.New("baz"), 172 }) 173 174 var target *nestedError 175 if errors.As(err, &target) { 176 t.Fatal("should be false") 177 } 178 if target != nil { 179 t.Fatal("target should be nil") 180 } 181 }) 182 } 183 184 // nestedError implements error and is used for tests. 185 type nestedError struct{} 186 187 func (*nestedError) Error() string { return "" }