github.com/avfs/avfs@v0.33.1-0.20240303173310-c6ba67c33eb7/test/test_error.go (about) 1 // 2 // Copyright 2023 The AVFS authors 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 package test 18 19 import ( 20 "io/fs" 21 "os" 22 "reflect" 23 "regexp" 24 "runtime" 25 "slices" 26 "testing" 27 28 "github.com/avfs/avfs" 29 ) 30 31 // assertError stores the current fs.PathError or the os.LinkError test data. 32 type assertError struct { 33 tb testing.TB 34 err error 35 wantOsTypes []avfs.OSType 36 wantGoVersions []string 37 wantOps []string 38 wantPath string 39 wantOld string 40 wantNew string 41 wantErrs []error 42 IsLinkError bool 43 } 44 45 // AssertPathError checks an error of type fs.PathError. 46 func AssertPathError(tb testing.TB, err error) *assertError { 47 return &assertError{tb: tb, err: err, IsLinkError: false} 48 } 49 50 // AssertLinkError checks an error of type os.LinkError. 51 func AssertLinkError(tb testing.TB, err error) *assertError { 52 return &assertError{tb: tb, err: err, IsLinkError: true} 53 } 54 55 // Test runs the test. 56 func (ae *assertError) Test() *assertError { 57 tb := ae.tb 58 tb.Helper() 59 60 if len(ae.wantOsTypes) != 0 && !slices.Contains(ae.wantOsTypes, avfs.CurrentOSType()) { 61 return ae 62 } 63 64 if len(ae.wantGoVersions) != 0 { 65 re := regexp.MustCompile(`go\d+\.\d+`) 66 version := re.FindString(runtime.Version()) 67 68 if !slices.Contains(ae.wantGoVersions, version) { 69 return ae 70 } 71 } 72 73 if len(ae.wantErrs) == 0 { 74 if ae.err != nil { 75 tb.Errorf("want error to be nil got %v", ae.err) 76 } 77 78 return ae 79 } 80 81 if ae.IsLinkError { 82 return ae.testLinkError() 83 } 84 85 return ae.testPathError() 86 } 87 88 func (ae *assertError) testLinkError() *assertError { 89 tb := ae.tb 90 91 e, ok := ae.err.(*os.LinkError) 92 if !ok { 93 tb.Errorf("want error type to be *os.LinkError, got %v : %v", reflect.TypeOf(ae.err), ae.err) 94 95 return ae 96 } 97 98 if len(ae.wantOps) != 0 && !slices.Contains(ae.wantOps, e.Op) { 99 tb.Errorf("want Op to be %s, got %s", ae.wantOps, e.Op) 100 } 101 102 if ae.wantOld != "" && ae.wantOld != e.Old { 103 tb.Errorf("want Old to be %s, got %s", ae.wantOld, e.Old) 104 } 105 106 if ae.wantNew != "" && ae.wantNew != e.New { 107 tb.Errorf("want New to be %s, got %s", ae.wantNew, e.New) 108 } 109 110 te := reflect.ValueOf(e.Err) 111 foundOk := false 112 113 for _, wantErr := range ae.wantErrs { 114 we := reflect.ValueOf(wantErr) 115 if (te.CanUint() && we.CanUint() && te.Uint() == we.Uint()) || (e.Err.Error() == wantErr.Error()) { 116 foundOk = true 117 118 break 119 } 120 } 121 122 if !foundOk { 123 tb.Errorf("want error to be %s, got %s", ae.wantErrs, e.Err.Error()) 124 } 125 126 return ae 127 } 128 129 func (ae *assertError) testPathError() *assertError { 130 tb := ae.tb 131 132 e, ok := ae.err.(*fs.PathError) 133 if !ok { 134 tb.Errorf("want error type to be *fs.PathError, got %v : %v", reflect.TypeOf(ae.err), ae.err) 135 136 return ae 137 } 138 139 if len(ae.wantOps) != 0 && !slices.Contains(ae.wantOps, e.Op) { 140 tb.Errorf("want Op to be %s, got %s", ae.wantOps, e.Op) 141 } 142 143 if ae.wantPath != "" && ae.wantPath != e.Path { 144 tb.Errorf("want Path to be %s, got %s", ae.wantPath, e.Path) 145 } 146 147 te := reflect.ValueOf(e.Err) 148 foundOk := false 149 150 for _, wantErr := range ae.wantErrs { 151 we := reflect.ValueOf(wantErr) 152 if (te.CanUint() && we.CanUint() && te.Uint() == we.Uint()) || (e.Err.Error() == wantErr.Error()) { 153 foundOk = true 154 155 break 156 } 157 } 158 159 if !foundOk { 160 tb.Errorf("want error to be %s, got %s", ae.wantErrs, e.Err.Error()) 161 } 162 163 return ae 164 } 165 166 // GoVersion sets the expected Go version. 167 func (ae *assertError) GoVersion(goVersions ...string) *assertError { 168 ae.wantGoVersions = goVersions 169 170 return ae 171 } 172 173 // New sets the expected new path. 174 func (ae *assertError) New(wantNew string) *assertError { 175 ae.wantNew = wantNew 176 177 return ae 178 } 179 180 // NoError set the expected error to nil. 181 func (ae *assertError) NoError() *assertError { 182 ae.wantErrs = nil 183 184 return ae 185 } 186 187 // Old sets the expected old path. 188 func (ae *assertError) Old(WantOld string) *assertError { 189 ae.wantOld = WantOld 190 191 return ae 192 } 193 194 // Op sets the expected Op. 195 func (ae *assertError) Op(ops ...string) *assertError { 196 ae.wantOps = ops 197 198 return ae 199 } 200 201 // OpLstat sets the expected Lstat Op for the current OS. 202 func (ae *assertError) OpLstat() *assertError { 203 switch avfs.CurrentOSType() { 204 case avfs.OsWindows: 205 return ae.Op("CreateFile") 206 default: 207 return ae.Op("lstat") 208 } 209 } 210 211 // OpStat sets the expected Stat Op for the current OS. 212 func (ae *assertError) OpStat() *assertError { 213 switch avfs.CurrentOSType() { 214 case avfs.OsWindows: 215 return ae.Op("CreateFile") 216 default: 217 return ae.Op("stat") 218 } 219 } 220 221 // OSType sets at least one expected OSType. 222 func (ae *assertError) OSType(ost ...avfs.OSType) *assertError { 223 ae.wantOsTypes = ost 224 225 return ae 226 } 227 228 // Path sets the expected path. 229 func (ae *assertError) Path(path string) *assertError { 230 ae.wantPath = path 231 232 return ae 233 } 234 235 // Err sets the expected error. 236 func (ae *assertError) Err(wantErr ...error) *assertError { 237 ae.wantErrs = wantErr 238 239 return ae 240 } 241 242 // ErrPermDenied sets the expected permission error for the current OS. 243 func (ae *assertError) ErrPermDenied() *assertError { 244 switch avfs.CurrentOSType() { 245 case avfs.OsWindows: 246 ae.Err(avfs.ErrWinAccessDenied) 247 default: 248 ae.Err(avfs.ErrPermDenied) 249 } 250 251 return ae 252 }