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 }