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  }