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