github.com/wangyougui/gf/v2@v2.6.5/test/gtest/gtest_util.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/wangyougui/gf. 6 7 package gtest 8 9 import ( 10 "fmt" 11 "os" 12 "path/filepath" 13 "reflect" 14 "testing" 15 16 "github.com/wangyougui/gf/v2/debug/gdebug" 17 "github.com/wangyougui/gf/v2/internal/empty" 18 "github.com/wangyougui/gf/v2/util/gconv" 19 ) 20 21 const ( 22 pathFilterKey = "/test/gtest/gtest" 23 ) 24 25 // C creates a unit testing case. 26 // The parameter `t` is the pointer to testing.T of stdlib (*testing.T). 27 // The parameter `f` is the closure function for unit testing case. 28 func C(t *testing.T, f func(t *T)) { 29 defer func() { 30 if err := recover(); err != nil { 31 _, _ = fmt.Fprintf(os.Stderr, "%v\n%s", err, gdebug.StackWithFilter([]string{pathFilterKey})) 32 t.Fail() 33 } 34 }() 35 f(&T{t}) 36 } 37 38 // Assert checks `value` and `expect` EQUAL. 39 func Assert(value, expect interface{}) { 40 rvExpect := reflect.ValueOf(expect) 41 if empty.IsNil(value) { 42 value = nil 43 } 44 if rvExpect.Kind() == reflect.Map { 45 if err := compareMap(value, expect); err != nil { 46 panic(err) 47 } 48 return 49 } 50 var ( 51 strValue = gconv.String(value) 52 strExpect = gconv.String(expect) 53 ) 54 if strValue != strExpect { 55 panic(fmt.Sprintf(`[ASSERT] EXPECT %v == %v`, strValue, strExpect)) 56 } 57 } 58 59 // AssertEQ checks `value` and `expect` EQUAL, including their TYPES. 60 func AssertEQ(value, expect interface{}) { 61 // Value assert. 62 rvExpect := reflect.ValueOf(expect) 63 if empty.IsNil(value) { 64 value = nil 65 } 66 if rvExpect.Kind() == reflect.Map { 67 if err := compareMap(value, expect); err != nil { 68 panic(err) 69 } 70 return 71 } 72 strValue := gconv.String(value) 73 strExpect := gconv.String(expect) 74 if strValue != strExpect { 75 panic(fmt.Sprintf(`[ASSERT] EXPECT %v == %v`, strValue, strExpect)) 76 } 77 // Type assert. 78 t1 := reflect.TypeOf(value) 79 t2 := reflect.TypeOf(expect) 80 if t1 != t2 { 81 panic(fmt.Sprintf(`[ASSERT] EXPECT TYPE %v[%v] == %v[%v]`, strValue, t1, strExpect, t2)) 82 } 83 } 84 85 // AssertNE checks `value` and `expect` NOT EQUAL. 86 func AssertNE(value, expect interface{}) { 87 rvExpect := reflect.ValueOf(expect) 88 if empty.IsNil(value) { 89 value = nil 90 } 91 if rvExpect.Kind() == reflect.Map { 92 if err := compareMap(value, expect); err == nil { 93 panic(fmt.Sprintf(`[ASSERT] EXPECT %v != %v`, value, expect)) 94 } 95 return 96 } 97 var ( 98 strValue = gconv.String(value) 99 strExpect = gconv.String(expect) 100 ) 101 if strValue == strExpect { 102 panic(fmt.Sprintf(`[ASSERT] EXPECT %v != %v`, strValue, strExpect)) 103 } 104 } 105 106 // AssertNQ checks `value` and `expect` NOT EQUAL, including their TYPES. 107 func AssertNQ(value, expect interface{}) { 108 // Type assert. 109 t1 := reflect.TypeOf(value) 110 t2 := reflect.TypeOf(expect) 111 if t1 == t2 { 112 panic( 113 fmt.Sprintf( 114 `[ASSERT] EXPECT TYPE %v[%v] != %v[%v]`, 115 gconv.String(value), t1, gconv.String(expect), t2, 116 ), 117 ) 118 } 119 // Value assert. 120 AssertNE(value, expect) 121 } 122 123 // AssertGT checks `value` is GREATER THAN `expect`. 124 // Notice that, only string, integer and float types can be compared by AssertGT, 125 // others are invalid. 126 func AssertGT(value, expect interface{}) { 127 passed := false 128 switch reflect.ValueOf(expect).Kind() { 129 case reflect.String: 130 passed = gconv.String(value) > gconv.String(expect) 131 132 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 133 passed = gconv.Int(value) > gconv.Int(expect) 134 135 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 136 passed = gconv.Uint(value) > gconv.Uint(expect) 137 138 case reflect.Float32, reflect.Float64: 139 passed = gconv.Float64(value) > gconv.Float64(expect) 140 } 141 if !passed { 142 panic(fmt.Sprintf(`[ASSERT] EXPECT %v > %v`, value, expect)) 143 } 144 } 145 146 // AssertGE checks `value` is GREATER OR EQUAL THAN `expect`. 147 // Notice that, only string, integer and float types can be compared by AssertGTE, 148 // others are invalid. 149 func AssertGE(value, expect interface{}) { 150 passed := false 151 switch reflect.ValueOf(expect).Kind() { 152 case reflect.String: 153 passed = gconv.String(value) >= gconv.String(expect) 154 155 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 156 passed = gconv.Int64(value) >= gconv.Int64(expect) 157 158 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 159 passed = gconv.Uint64(value) >= gconv.Uint64(expect) 160 161 case reflect.Float32, reflect.Float64: 162 passed = gconv.Float64(value) >= gconv.Float64(expect) 163 } 164 if !passed { 165 panic(fmt.Sprintf( 166 `[ASSERT] EXPECT %v(%v) >= %v(%v)`, 167 value, reflect.ValueOf(value).Kind(), 168 expect, reflect.ValueOf(expect).Kind(), 169 )) 170 } 171 } 172 173 // AssertLT checks `value` is LESS EQUAL THAN `expect`. 174 // Notice that, only string, integer and float types can be compared by AssertLT, 175 // others are invalid. 176 func AssertLT(value, expect interface{}) { 177 passed := false 178 switch reflect.ValueOf(expect).Kind() { 179 case reflect.String: 180 passed = gconv.String(value) < gconv.String(expect) 181 182 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 183 passed = gconv.Int(value) < gconv.Int(expect) 184 185 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 186 passed = gconv.Uint(value) < gconv.Uint(expect) 187 188 case reflect.Float32, reflect.Float64: 189 passed = gconv.Float64(value) < gconv.Float64(expect) 190 } 191 if !passed { 192 panic(fmt.Sprintf(`[ASSERT] EXPECT %v < %v`, value, expect)) 193 } 194 } 195 196 // AssertLE checks `value` is LESS OR EQUAL THAN `expect`. 197 // Notice that, only string, integer and float types can be compared by AssertLTE, 198 // others are invalid. 199 func AssertLE(value, expect interface{}) { 200 passed := false 201 switch reflect.ValueOf(expect).Kind() { 202 case reflect.String: 203 passed = gconv.String(value) <= gconv.String(expect) 204 205 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 206 passed = gconv.Int(value) <= gconv.Int(expect) 207 208 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 209 passed = gconv.Uint(value) <= gconv.Uint(expect) 210 211 case reflect.Float32, reflect.Float64: 212 passed = gconv.Float64(value) <= gconv.Float64(expect) 213 } 214 if !passed { 215 panic(fmt.Sprintf(`[ASSERT] EXPECT %v <= %v`, value, expect)) 216 } 217 } 218 219 // AssertIN checks `value` is IN `expect`. 220 // The `expect` should be a slice, 221 // but the `value` can be a slice or a basic type variable. 222 // TODO map support. 223 // TODO: gconv.Strings(0) is not [0] 224 func AssertIN(value, expect interface{}) { 225 var ( 226 passed = true 227 expectKind = reflect.ValueOf(expect).Kind() 228 ) 229 switch expectKind { 230 case reflect.Slice, reflect.Array: 231 expectSlice := gconv.Strings(expect) 232 for _, v1 := range gconv.Strings(value) { 233 result := false 234 for _, v2 := range expectSlice { 235 if v1 == v2 { 236 result = true 237 break 238 } 239 } 240 if !result { 241 passed = false 242 break 243 } 244 } 245 default: 246 panic(fmt.Sprintf(`[ASSERT] INVALID EXPECT VALUE TYPE: %v`, expectKind)) 247 } 248 if !passed { 249 panic(fmt.Sprintf(`[ASSERT] EXPECT %v IN %v`, value, expect)) 250 } 251 } 252 253 // AssertNI checks `value` is NOT IN `expect`. 254 // The `expect` should be a slice, 255 // but the `value` can be a slice or a basic type variable. 256 // TODO map support. 257 func AssertNI(value, expect interface{}) { 258 var ( 259 passed = true 260 expectKind = reflect.ValueOf(expect).Kind() 261 ) 262 switch expectKind { 263 case reflect.Slice, reflect.Array: 264 for _, v1 := range gconv.Strings(value) { 265 result := true 266 for _, v2 := range gconv.Strings(expect) { 267 if v1 == v2 { 268 result = false 269 break 270 } 271 } 272 if !result { 273 passed = false 274 break 275 } 276 } 277 default: 278 panic(fmt.Sprintf(`[ASSERT] INVALID EXPECT VALUE TYPE: %v`, expectKind)) 279 } 280 if !passed { 281 panic(fmt.Sprintf(`[ASSERT] EXPECT %v NOT IN %v`, value, expect)) 282 } 283 } 284 285 // Error panics with given `message`. 286 func Error(message ...interface{}) { 287 panic(fmt.Sprintf("[ERROR] %s", fmt.Sprint(message...))) 288 } 289 290 // Fatal prints `message` to stderr and exit the process. 291 func Fatal(message ...interface{}) { 292 _, _ = fmt.Fprintf( 293 os.Stderr, "[FATAL] %s\n%s", fmt.Sprint(message...), 294 gdebug.StackWithFilter([]string{pathFilterKey}), 295 ) 296 os.Exit(1) 297 } 298 299 // compareMap compares two maps, returns nil if they are equal, or else returns error. 300 func compareMap(value, expect interface{}) error { 301 var ( 302 rvValue = reflect.ValueOf(value) 303 rvExpect = reflect.ValueOf(expect) 304 ) 305 if rvExpect.Kind() == reflect.Map { 306 if rvValue.Kind() == reflect.Map { 307 if rvExpect.Len() == rvValue.Len() { 308 // Turn two interface maps to the same type for comparison. 309 // Direct use of rvValue.MapIndex(key).Interface() will panic 310 // when the key types are inconsistent. 311 mValue := make(map[string]string) 312 mExpect := make(map[string]string) 313 ksValue := rvValue.MapKeys() 314 ksExpect := rvExpect.MapKeys() 315 for _, key := range ksValue { 316 mValue[gconv.String(key.Interface())] = gconv.String(rvValue.MapIndex(key).Interface()) 317 } 318 for _, key := range ksExpect { 319 mExpect[gconv.String(key.Interface())] = gconv.String(rvExpect.MapIndex(key).Interface()) 320 } 321 for k, v := range mExpect { 322 if v != mValue[k] { 323 return fmt.Errorf(`[ASSERT] EXPECT VALUE map["%v"]:%v == map["%v"]:%v`+ 324 "\nGIVEN : %v\nEXPECT: %v", k, mValue[k], k, v, mValue, mExpect) 325 } 326 } 327 } else { 328 return fmt.Errorf(`[ASSERT] EXPECT MAP LENGTH %d == %d`, rvValue.Len(), rvExpect.Len()) 329 } 330 } else { 331 return fmt.Errorf(`[ASSERT] EXPECT VALUE TO BE A MAP, BUT GIVEN "%s"`, rvValue.Kind()) 332 } 333 } 334 return nil 335 } 336 337 // AssertNil asserts `value` is nil. 338 func AssertNil(value interface{}) { 339 if empty.IsNil(value) { 340 return 341 } 342 if err, ok := value.(error); ok { 343 panic(fmt.Sprintf(`%+v`, err)) 344 } 345 Assert(value, nil) 346 } 347 348 // DataPath retrieves and returns the testdata path of current package, 349 // which is used for unit testing cases only. 350 // The optional parameter `names` specifies the sub-folders/sub-files, 351 // which will be joined with current system separator and returned with the path. 352 func DataPath(names ...string) string { 353 _, path, _ := gdebug.CallerWithFilter([]string{pathFilterKey}) 354 path = filepath.Dir(path) + string(filepath.Separator) + "testdata" 355 for _, name := range names { 356 path += string(filepath.Separator) + name 357 } 358 return path 359 } 360 361 // DataContent retrieves and returns the file content for specified testdata path of current package 362 func DataContent(names ...string) string { 363 path := DataPath(names...) 364 if path != "" { 365 data, err := os.ReadFile(path) 366 if err == nil { 367 return string(data) 368 } 369 } 370 return "" 371 }