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  }