github.com/gogf/gf@v1.16.9/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 "io/ioutil" 12 "os" 13 "path/filepath" 14 "reflect" 15 "testing" 16 17 "github.com/gogf/gf/debug/gdebug" 18 "github.com/gogf/gf/internal/empty" 19 "github.com/gogf/gf/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 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(os.Stderr, "[FATAL] %s\n%s", fmt.Sprint(message...), gdebug.StackWithFilter([]string{pathFilterKey})) 293 os.Exit(1) 294 } 295 296 // compareMap compares two maps, returns nil if they are equal, or else returns error. 297 func compareMap(value, expect interface{}) error { 298 var ( 299 rvValue = reflect.ValueOf(value) 300 rvExpect = reflect.ValueOf(expect) 301 ) 302 if empty.IsNil(value) { 303 value = nil 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 AssertNE(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 := ioutil.ReadFile(path) 366 if err == nil { 367 return string(data) 368 } 369 } 370 return "" 371 }