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  }