github.com/zhongdalu/gf@v1.0.0/g/test/gtest/gtest.go (about)

     1  // Copyright 2018 gf Author(https://github.com/zhongdalu/gf). 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/zhongdalu/gf.
     6  
     7  // Package gtest provides convenient test utilities for unit testing.
     8  package gtest
     9  
    10  import (
    11  	"fmt"
    12  	"os"
    13  	"reflect"
    14  	"testing"
    15  
    16  	"github.com/zhongdalu/gf/g/internal/debug"
    17  
    18  	"github.com/zhongdalu/gf/g/util/gconv"
    19  )
    20  
    21  const (
    22  	gPATH_FILTER_KEY = "/g/test/gtest/gtest"
    23  )
    24  
    25  // Case creates an unit test case.
    26  // The parameter <t> is the pointer to testing.T of stdlib (*testing.T).
    27  // The parameter <f> is the callback function for unit test case.
    28  func Case(t *testing.T, f func()) {
    29  	defer func() {
    30  		if err := recover(); err != nil {
    31  			fmt.Fprintf(os.Stderr, "%v\n%s", err, debug.StackWithFilter(gPATH_FILTER_KEY))
    32  			t.Fail()
    33  		}
    34  	}()
    35  	f()
    36  }
    37  
    38  // Assert checks <value> and <expect> EQUAL.
    39  func Assert(value, expect interface{}) {
    40  	rvExpect := reflect.ValueOf(expect)
    41  	if 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  	strValue := gconv.String(value)
    51  	strExpect := gconv.String(expect)
    52  	if strValue != strExpect {
    53  		panic(fmt.Sprintf(`[ASSERT] EXPECT %v == %v`, strValue, strExpect))
    54  	}
    55  }
    56  
    57  // AssertEQ checks <value> and <expect> EQUAL, including their TYPES.
    58  func AssertEQ(value, expect interface{}) {
    59  	// Value assert.
    60  	rvExpect := reflect.ValueOf(expect)
    61  	if isNil(value) {
    62  		value = nil
    63  	}
    64  	if rvExpect.Kind() == reflect.Map {
    65  		if err := compareMap(value, expect); err != nil {
    66  			panic(err)
    67  		}
    68  		return
    69  	}
    70  	strValue := gconv.String(value)
    71  	strExpect := gconv.String(expect)
    72  	if strValue != strExpect {
    73  		panic(fmt.Sprintf(`[ASSERT] EXPECT %v == %v`, strValue, strExpect))
    74  	}
    75  	// Type assert.
    76  	t1 := reflect.TypeOf(value)
    77  	t2 := reflect.TypeOf(expect)
    78  	if t1 != t2 {
    79  		panic(fmt.Sprintf(`[ASSERT] EXPECT TYPE %v[%v] == %v[%v]`, strValue, t1, strExpect, t2))
    80  	}
    81  }
    82  
    83  // AssertNE checks <value> and <expect> NOT EQUAL.
    84  func AssertNE(value, expect interface{}) {
    85  	rvExpect := reflect.ValueOf(expect)
    86  	if isNil(value) {
    87  		value = nil
    88  	}
    89  	if rvExpect.Kind() == reflect.Map {
    90  		if err := compareMap(value, expect); err == nil {
    91  			panic(fmt.Sprintf(`[ASSERT] EXPECT %v != %v`, value, expect))
    92  		}
    93  		return
    94  	}
    95  	strValue := gconv.String(value)
    96  	strExpect := gconv.String(expect)
    97  	if strValue == strExpect {
    98  		panic(fmt.Sprintf(`[ASSERT] EXPECT %v != %v`, strValue, strExpect))
    99  	}
   100  }
   101  
   102  // AssertGT checks <value> is GREATER THAN <expect>.
   103  // Notice that, only string, integer and float types can be compared by AssertGT,
   104  // others are invalid.
   105  func AssertGT(value, expect interface{}) {
   106  	passed := false
   107  	switch reflect.ValueOf(expect).Kind() {
   108  	case reflect.String:
   109  		passed = gconv.String(value) > gconv.String(expect)
   110  
   111  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   112  		passed = gconv.Int(value) > gconv.Int(expect)
   113  
   114  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   115  		passed = gconv.Uint(value) > gconv.Uint(expect)
   116  
   117  	case reflect.Float32, reflect.Float64:
   118  		passed = gconv.Float64(value) > gconv.Float64(expect)
   119  	}
   120  	if !passed {
   121  		panic(fmt.Sprintf(`[ASSERT] EXPECT %v > %v`, value, expect))
   122  	}
   123  }
   124  
   125  // Deprecated.
   126  // See AssertGE.
   127  func AssertGTE(value, expect interface{}) {
   128  	AssertGE(value, expect)
   129  }
   130  
   131  // AssertGE checks <value> is GREATER OR EQUAL THAN <expect>.
   132  // Notice that, only string, integer and float types can be compared by AssertGTE,
   133  // others are invalid.
   134  func AssertGE(value, expect interface{}) {
   135  	passed := false
   136  	switch reflect.ValueOf(expect).Kind() {
   137  	case reflect.String:
   138  		passed = gconv.String(value) >= gconv.String(expect)
   139  
   140  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   141  		passed = gconv.Int(value) >= gconv.Int(expect)
   142  
   143  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   144  		passed = gconv.Uint(value) >= gconv.Uint(expect)
   145  
   146  	case reflect.Float32, reflect.Float64:
   147  		passed = gconv.Float64(value) >= gconv.Float64(expect)
   148  	}
   149  	if !passed {
   150  		panic(fmt.Sprintf(`[ASSERT] EXPECT %v >= %v`, value, expect))
   151  	}
   152  }
   153  
   154  // AssertLT checks <value> is LESS EQUAL THAN <expect>.
   155  // Notice that, only string, integer and float types can be compared by AssertLT,
   156  // others are invalid.
   157  func AssertLT(value, expect interface{}) {
   158  	passed := false
   159  	switch reflect.ValueOf(expect).Kind() {
   160  	case reflect.String:
   161  		passed = gconv.String(value) < gconv.String(expect)
   162  
   163  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   164  		passed = gconv.Int(value) < gconv.Int(expect)
   165  
   166  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   167  		passed = gconv.Uint(value) < gconv.Uint(expect)
   168  
   169  	case reflect.Float32, reflect.Float64:
   170  		passed = gconv.Float64(value) < gconv.Float64(expect)
   171  	}
   172  	if !passed {
   173  		panic(fmt.Sprintf(`[ASSERT] EXPECT %v < %v`, value, expect))
   174  	}
   175  }
   176  
   177  // Deprecated.
   178  // See AssertLE.
   179  func AssertLTE(value, expect interface{}) {
   180  	AssertLE(value, expect)
   181  }
   182  
   183  // AssertLE checks <value> is LESS OR EQUAL THAN <expect>.
   184  // Notice that, only string, integer and float types can be compared by AssertLTE,
   185  // others are invalid.
   186  func AssertLE(value, expect interface{}) {
   187  	passed := false
   188  	switch reflect.ValueOf(expect).Kind() {
   189  	case reflect.String:
   190  		passed = gconv.String(value) <= gconv.String(expect)
   191  
   192  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   193  		passed = gconv.Int(value) <= gconv.Int(expect)
   194  
   195  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   196  		passed = gconv.Uint(value) <= gconv.Uint(expect)
   197  
   198  	case reflect.Float32, reflect.Float64:
   199  		passed = gconv.Float64(value) <= gconv.Float64(expect)
   200  	}
   201  	if !passed {
   202  		panic(fmt.Sprintf(`[ASSERT] EXPECT %v <= %v`, value, expect))
   203  	}
   204  }
   205  
   206  // AssertIN checks <value> is IN <expect>.
   207  // The <expect> should be a slice,
   208  // but the <value> can be a slice or a basic type variable.
   209  // TODO map support.
   210  func AssertIN(value, expect interface{}) {
   211  	passed := true
   212  	switch reflect.ValueOf(expect).Kind() {
   213  	case reflect.Slice, reflect.Array:
   214  		expectSlice := gconv.Interfaces(expect)
   215  		for _, v1 := range gconv.Interfaces(value) {
   216  			result := false
   217  			for _, v2 := range expectSlice {
   218  				if v1 == v2 {
   219  					result = true
   220  					break
   221  				}
   222  			}
   223  			if !result {
   224  				passed = false
   225  				break
   226  			}
   227  		}
   228  	}
   229  	if !passed {
   230  		panic(fmt.Sprintf(`[ASSERT] EXPECT %v IN %v`, value, expect))
   231  	}
   232  }
   233  
   234  // AssertNI checks <value> is NOT IN <expect>.
   235  // The <expect> should be a slice,
   236  // but the <value> can be a slice or a basic type variable.
   237  // TODO map support.
   238  func AssertNI(value, expect interface{}) {
   239  	passed := true
   240  	switch reflect.ValueOf(expect).Kind() {
   241  	case reflect.Slice, reflect.Array:
   242  		for _, v1 := range gconv.Interfaces(value) {
   243  			result := true
   244  			for _, v2 := range gconv.Interfaces(expect) {
   245  				if v1 == v2 {
   246  					result = false
   247  					break
   248  				}
   249  			}
   250  			if !result {
   251  				passed = false
   252  				break
   253  			}
   254  		}
   255  	}
   256  	if !passed {
   257  		panic(fmt.Sprintf(`[ASSERT] EXPECT %v NOT IN %v`, value, expect))
   258  	}
   259  }
   260  
   261  // Error panics with given <message>.
   262  func Error(message ...interface{}) {
   263  	panic(fmt.Sprintf("[ERROR] %s", fmt.Sprint(message...)))
   264  }
   265  
   266  // Fatal prints <message> to stderr and exit the process.
   267  func Fatal(message ...interface{}) {
   268  	fmt.Fprintf(os.Stderr, "[FATAL] %s\n%s", fmt.Sprint(message...), debug.StackWithFilter(gPATH_FILTER_KEY))
   269  	os.Exit(1)
   270  }
   271  
   272  // compareMap compares two maps, returns nil if they are equal, or else returns error.
   273  func compareMap(value, expect interface{}) error {
   274  	rvValue := reflect.ValueOf(value)
   275  	rvExpect := reflect.ValueOf(expect)
   276  	if isNil(value) {
   277  		value = nil
   278  	}
   279  	if rvExpect.Kind() == reflect.Map {
   280  		if rvValue.Kind() == reflect.Map {
   281  			if rvExpect.Len() == rvValue.Len() {
   282  				// Turn two interface maps to the same type for comparison.
   283  				// Direct use of rvValue.MapIndex(key).Interface() will panic
   284  				// when the key types are inconsistent.
   285  				mValue := make(map[string]string)
   286  				mExpect := make(map[string]string)
   287  				ksValue := rvValue.MapKeys()
   288  				ksExpect := rvExpect.MapKeys()
   289  				for _, key := range ksValue {
   290  					mValue[gconv.String(key.Interface())] = gconv.String(rvValue.MapIndex(key).Interface())
   291  				}
   292  				for _, key := range ksExpect {
   293  					mExpect[gconv.String(key.Interface())] = gconv.String(rvExpect.MapIndex(key).Interface())
   294  				}
   295  				for k, v := range mExpect {
   296  					if v != mValue[k] {
   297  						return fmt.Errorf(`[ASSERT] EXPECT VALUE map["%v"]:%v == map["%v"]:%v`+
   298  							"\nGIVEN : %v\nEXPECT: %v", k, mValue[k], k, v, mValue, mExpect)
   299  					}
   300  				}
   301  			} else {
   302  				return fmt.Errorf(`[ASSERT] EXPECT MAP LENGTH %d == %d`, rvValue.Len(), rvExpect.Len())
   303  			}
   304  		} else {
   305  			return fmt.Errorf(`[ASSERT] EXPECT VALUE TO BE A MAP`)
   306  		}
   307  	}
   308  	return nil
   309  }
   310  
   311  // isNil checks whether <value> is nil.
   312  func isNil(value interface{}) bool {
   313  	rv := reflect.ValueOf(value)
   314  	switch rv.Kind() {
   315  	case reflect.Slice, reflect.Array, reflect.Map, reflect.Ptr, reflect.Func:
   316  		return rv.IsNil()
   317  	default:
   318  		return value == nil
   319  	}
   320  }