github.com/go-spring/spring-base@v1.1.3/assert/assert.go (about)

     1  /*
     2   * Copyright 2012-2019 the original author or authors.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *      https://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  //go:generate mockgen -build_flags="-mod=mod" -package=assert -source=assert.go -destination=assert_mock.go
    18  
    19  // Package assert provides some useful assertion methods.
    20  package assert
    21  
    22  import (
    23  	"fmt"
    24  	"reflect"
    25  	"regexp"
    26  	"strings"
    27  
    28  	"github.com/go-spring/spring-base/json"
    29  )
    30  
    31  // T is the minimum interface of *testing.T.
    32  type T interface {
    33  	Helper()
    34  	Error(args ...interface{})
    35  }
    36  
    37  func fail(t T, str string, msg ...string) {
    38  	t.Helper()
    39  	args := append([]string{str}, msg...)
    40  	t.Error(strings.Join(args, "; "))
    41  }
    42  
    43  // True assertion failed when got is false.
    44  func True(t T, got bool, msg ...string) {
    45  	t.Helper()
    46  	if !got {
    47  		fail(t, "got false but expect true", msg...)
    48  	}
    49  }
    50  
    51  // False assertion failed when got is true.
    52  func False(t T, got bool, msg ...string) {
    53  	t.Helper()
    54  	if got {
    55  		fail(t, "got true but expect false", msg...)
    56  	}
    57  }
    58  
    59  // isNil reports v is nil, but will not panic.
    60  func isNil(v reflect.Value) bool {
    61  	switch v.Kind() {
    62  	case reflect.Chan,
    63  		reflect.Func,
    64  		reflect.Interface,
    65  		reflect.Map,
    66  		reflect.Ptr,
    67  		reflect.Slice,
    68  		reflect.UnsafePointer:
    69  		return v.IsNil()
    70  	}
    71  	return !v.IsValid()
    72  }
    73  
    74  // Nil assertion failed when got is not nil.
    75  func Nil(t T, got interface{}, msg ...string) {
    76  	t.Helper()
    77  	// Why can't we use got==nil to judge?Because if
    78  	// a := (*int)(nil)        // %T == *int
    79  	// b := (interface{})(nil) // %T == <nil>
    80  	// then a==b is false, because they are different types.
    81  	if !isNil(reflect.ValueOf(got)) {
    82  		str := fmt.Sprintf("got (%T) %v but expect nil", got, got)
    83  		fail(t, str, msg...)
    84  	}
    85  }
    86  
    87  // NotNil assertion failed when got is nil.
    88  func NotNil(t T, got interface{}, msg ...string) {
    89  	t.Helper()
    90  	if isNil(reflect.ValueOf(got)) {
    91  		fail(t, "got nil but expect not nil", msg...)
    92  	}
    93  }
    94  
    95  // Equal assertion failed when got and expect are not `deeply equal`.
    96  func Equal(t T, got interface{}, expect interface{}, msg ...string) {
    97  	t.Helper()
    98  	if !reflect.DeepEqual(got, expect) {
    99  		str := fmt.Sprintf("got (%T) %v but expect (%T) %v", got, got, expect, expect)
   100  		fail(t, str, msg...)
   101  	}
   102  }
   103  
   104  // NotEqual assertion failed when got and expect are `deeply equal`.
   105  func NotEqual(t T, got interface{}, expect interface{}, msg ...string) {
   106  	t.Helper()
   107  	if reflect.DeepEqual(got, expect) {
   108  		str := fmt.Sprintf("got (%T) %v but expect not (%T) %v", got, got, expect, expect)
   109  		fail(t, str, msg...)
   110  	}
   111  }
   112  
   113  // JsonEqual assertion failed when got and expect are not `json equal`.
   114  func JsonEqual(t T, got string, expect string, msg ...string) {
   115  	t.Helper()
   116  	var gotJson interface{}
   117  	if err := json.Unmarshal([]byte(got), &gotJson); err != nil {
   118  		fail(t, err.Error(), msg...)
   119  		return
   120  	}
   121  	var expectJson interface{}
   122  	if err := json.Unmarshal([]byte(expect), &expectJson); err != nil {
   123  		fail(t, err.Error(), msg...)
   124  		return
   125  	}
   126  	if !reflect.DeepEqual(gotJson, expectJson) {
   127  		str := fmt.Sprintf("got (%T) %v but expect (%T) %v", got, got, expect, expect)
   128  		fail(t, str, msg...)
   129  	}
   130  }
   131  
   132  // Same assertion failed when got and expect are not same.
   133  func Same(t T, got interface{}, expect interface{}, msg ...string) {
   134  	t.Helper()
   135  	if got != expect {
   136  		str := fmt.Sprintf("got (%T) %v but expect (%T) %v", got, got, expect, expect)
   137  		fail(t, str, msg...)
   138  	}
   139  }
   140  
   141  // NotSame assertion failed when got and expect are same.
   142  func NotSame(t T, got interface{}, expect interface{}, msg ...string) {
   143  	t.Helper()
   144  	if got == expect {
   145  		str := fmt.Sprintf("expect not (%T) %v", expect, expect)
   146  		fail(t, str, msg...)
   147  	}
   148  }
   149  
   150  // Panic assertion failed when fn doesn't panic or not match expr expression.
   151  func Panic(t T, fn func(), expr string, msg ...string) {
   152  	t.Helper()
   153  	str := recovery(fn)
   154  	if str == "<<SUCCESS>>" {
   155  		fail(t, "did not panic", msg...)
   156  	} else {
   157  		matches(t, str, expr, msg...)
   158  	}
   159  }
   160  
   161  func recovery(fn func()) (str string) {
   162  	defer func() {
   163  		if r := recover(); r != nil {
   164  			str = fmt.Sprint(r)
   165  		}
   166  	}()
   167  	fn()
   168  	return "<<SUCCESS>>"
   169  }
   170  
   171  // Matches assertion failed when got doesn't match expr expression.
   172  func Matches(t T, got string, expr string, msg ...string) {
   173  	t.Helper()
   174  	matches(t, got, expr, msg...)
   175  }
   176  
   177  // Error assertion failed when got `error` doesn't match expr expression.
   178  func Error(t T, got error, expr string, msg ...string) {
   179  	t.Helper()
   180  	if got == nil {
   181  		fail(t, "expect not nil error", msg...)
   182  		return
   183  	}
   184  	matches(t, got.Error(), expr, msg...)
   185  }
   186  
   187  func matches(t T, got string, expr string, msg ...string) {
   188  	t.Helper()
   189  	if ok, err := regexp.MatchString(expr, got); err != nil {
   190  		fail(t, "invalid pattern", msg...)
   191  	} else if !ok {
   192  		str := fmt.Sprintf("got %q which does not match %q", got, expr)
   193  		fail(t, str, msg...)
   194  	}
   195  }
   196  
   197  // TypeOf assertion failed when got and expect are not same type.
   198  func TypeOf(t T, got interface{}, expect interface{}, msg ...string) {
   199  	t.Helper()
   200  
   201  	e1 := reflect.TypeOf(got)
   202  	e2 := reflect.TypeOf(expect)
   203  	if e2.Kind() == reflect.Ptr && e2.Elem().Kind() == reflect.Interface {
   204  		e2 = e2.Elem()
   205  	}
   206  
   207  	if !e1.AssignableTo(e2) {
   208  		str := fmt.Sprintf("got type (%s) but expect type (%s)", e1, e2)
   209  		fail(t, str, msg...)
   210  	}
   211  }
   212  
   213  // Implements assertion failed when got doesn't implement expect.
   214  func Implements(t T, got interface{}, expect interface{}, msg ...string) {
   215  	t.Helper()
   216  
   217  	e1 := reflect.TypeOf(got)
   218  	e2 := reflect.TypeOf(expect)
   219  	if e2.Kind() == reflect.Ptr {
   220  		if e2.Elem().Kind() == reflect.Interface {
   221  			e2 = e2.Elem()
   222  		} else {
   223  			fail(t, "expect should be interface", msg...)
   224  			return
   225  		}
   226  	}
   227  
   228  	if !e1.Implements(e2) {
   229  		str := fmt.Sprintf("got type (%s) but expect type (%s)", e1, e2)
   230  		fail(t, str, msg...)
   231  	}
   232  }