├── .envrc
├── .github
└── images
│ └── bmc-button.png
├── .gitignore
├── .gitmodules
├── LICENSE
├── Makefile
├── README.md
├── assertion_compare.go
├── assertion_format.go
├── assertion_order.go
├── assertions.go
├── codegen.sh
├── doc.go
├── errors.go
├── extra.go
├── flake.lock
├── flake.nix
├── go.mod
├── go.sum
├── http_assertions.go
├── prod_assertion_compare.go
├── prod_assertion_format.go
├── prod_assertion_order.go
├── prod_assertions.go
├── prod_errors.go
├── prod_extra.go
├── prod_http_assertions.go
└── tests
└── assertions_test.go
/.envrc:
--------------------------------------------------------------------------------
1 | use flake
2 |
--------------------------------------------------------------------------------
/.github/images/bmc-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/negrel/assert/dcf77153b52ead32375afd500bd546a951d38a48/.github/images/bmc-button.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .direnv/
2 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "testify"]
2 | path = testify
3 | url = https://github.com/stretchr/testify.git
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Alexandre Negrel
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: codegen
2 | codegen:
3 | ./codegen.sh
4 |
5 | .PHONY: clear
6 | clear:
7 | rm -f ./*assertion*.go ./prod_*
8 |
9 | .PHONY: lint
10 | lint:
11 | shellcheck ./codegen.sh
12 |
13 | .PHONY: test
14 | test:
15 | go test -tags assert -v ./...
16 |
17 | .PHONY: bench
18 | bench: bench/assert bench/noassert
19 |
20 | .PHONY: bench/noassert
21 | bench/noassert:
22 | @echo "ASSERTIONS DISABLED"
23 | go test -bench=. -run=^$$ -v ./...
24 |
25 | .PHONY: bench/assert
26 | bench/assert:
27 | @echo "ASSERTIONS ENABLED"
28 | go test -bench=. -run=^$$ -tags assert -v ./...
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | # `assert` - Zero cost debug assertions.
15 |
16 | This package provides zero cost debug assertions to your Go programs. It is based
17 | on the excellent [`github.com/stretchr/testify/assert`](https://github.com/stretchr/testify)
18 | package and provide the same API (minus `t testing.T` parameter).
19 |
20 | ## Why?
21 |
22 | This is a complete rewrite of [`debuggo`](https://github.com/negrel/debuggo) that aims
23 | to be up to date and more maintainable.
24 |
25 | It aims to provide the same API as [`github.com/stretchr/testify/assert`](https://github.com/stretchr/testify).
26 | * Prints friendly, easy to read failure descriptions
27 | * Allows for very readable code
28 | * Optionally annotate each assertion with a message
29 | * No performance impact on production build (see benchmarks)
30 |
31 | Debug assertions main use is to assert invariant that can't be encoded in the
32 | type systems. For example, a method that should be called only when mutex is
33 | locked:
34 |
35 | ```go
36 | package mypkg
37 |
38 | import (
39 | "sync"
40 | "github.com/negrel/assert"
41 | )
42 |
43 | type myType struct {
44 | mu sync.Mutex
45 | // other fields...
46 | }
47 |
48 | // doWork perform internal work. Caller must hold mutex while calling this
49 | // function.
50 | func (mt *myType) doWork(k string) {
51 | assert.Locked(&mt.mu) // panic if assertions are enabled and mutex isn't locked
52 |
53 | // Do work...
54 | }
55 | ```
56 |
57 | ## How does it works?
58 |
59 | [Read my blog post](https://www.negrel.dev/blog/zero-cost-debug-assertions-in-go/)
60 | about to understand how `assert` works and why it is designed that way.
61 |
62 | ## Getting started
63 |
64 | Here is our example program:
65 |
66 | ```go
67 | package main
68 |
69 | import (
70 | "github.com/negrel/assert"
71 | )
72 |
73 | func main() {
74 | assert.True(false)
75 | println("Hello world!")
76 | }
77 | ```
78 |
79 | A simple `go run .` will simply print `Hello world!` as all `assert` functions
80 | are removed by the compiler.
81 |
82 | Now, if we compile and run it with assertions enabled `go run -tags assert .`,
83 | it will output something like:
84 |
85 | ```
86 | panic:
87 | Error Trace: /home/anegrel/code/go/assert/example/main.go:8
88 | /usr/share/go/src/runtime/proc.go:267
89 | /usr/share/go/src/runtime/asm_amd64.s:1650
90 | Error: Should be true
91 |
92 |
93 | goroutine 1 [running]:
94 | github.com/negrel/assert.Fail({0x568dc2, 0xe}, {0x0, 0x0, 0x0})
95 | /home/anegrel/code/go/assert/assertions.go:349 +0x168
96 | github.com/negrel/assert.True(...)
97 | /home/anegrel/code/go/assert/assertions.go:754
98 | main.main()
99 | /home/anegrel/code/go/assert/example/main.go:8 +0x27
100 | exit status 2
101 | ```
102 |
103 | Note that most `go` subcommands (build, run, test, ...) supports `-tags` flag.
104 | You may want to set `GOFLAGS` environment variable to `-tags assert` make it
105 | permanent and avoid specifying it on each command.
106 |
107 | ## Benchmarks
108 |
109 | As we've seen previously, assertions are hidden behind a compilation flag. If
110 | the flag is absent, all assertions functions will be empty/noop function that
111 | the compiler will optimize.
112 |
113 | **WITH** `-tags assert`:
114 |
115 | ```
116 | goos: linux
117 | goarch: amd64
118 | pkg: github.com/negrel/assert/tests
119 | cpu: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
120 | BenchmarkSliceIndexWithoutBoundCheckAssertions
121 | BenchmarkSliceIndexWithoutBoundCheckAssertions-8 728439501 1.407 ns/op
122 | BenchmarkSliceIndexWithBoundCheckAssertions
123 | BenchmarkSliceIndexWithBoundCheckAssertions-8 27423670 40.80 ns/op
124 | PASS
125 | ok github.com/negrel/assert/tests 3.338s
126 | ```
127 |
128 | **WITHOUT** `-tags assert`:
129 |
130 | ```
131 | goos: linux
132 | goarch: amd64
133 | pkg: github.com/negrel/assert/tests
134 | cpu: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
135 | BenchmarkSliceIndexWithoutBoundCheckAssertions
136 | BenchmarkSliceIndexWithoutBoundCheckAssertions-8 772181695 1.399 ns/op
137 | BenchmarkSliceIndexWithBoundCheckAssertions
138 | BenchmarkSliceIndexWithBoundCheckAssertions-8 802181890 1.412 ns/op
139 | PASS
140 | ok github.com/negrel/assert/tests 2.531s
141 | ```
142 |
143 | However, keep in mind that `assert` may slightly increase binary size (~100 KiB)
144 | as it imports `net/http` and `reflect`.
145 |
146 | ## Contributing
147 |
148 | If you want to contribute to `assert` to add a feature or improve the code contact
149 | me at [negrel.dev@protonmail.com](mailto:negrel.dev@protonmail.com), open an
150 | [issue](https://github.com/negrel/assert/issues) or make a
151 | [pull request](https://github.com/negrel/assert/pulls).
152 |
153 | ## :stars: Show your support
154 |
155 | Please give a :star: if this project helped you!
156 |
157 | [](https://www.buymeacoffee.com/negrel)
158 |
159 | ## :scroll: License
160 |
161 | MIT © [Alexandre Negrel](https://www.negrel.dev/)
162 |
--------------------------------------------------------------------------------
/assertion_compare.go:
--------------------------------------------------------------------------------
1 | //go:build assert
2 |
3 | package assert
4 |
5 | import (
6 | "bytes"
7 | "fmt"
8 | "reflect"
9 | "time"
10 | )
11 |
12 | // Deprecated: CompareType has only ever been for internal use and has accidentally been published since v1.6.0. Do not use it.
13 | type CompareType = compareResult
14 |
15 | type compareResult int
16 |
17 | const (
18 | compareLess compareResult = iota - 1
19 | compareEqual
20 | compareGreater
21 | )
22 |
23 | var (
24 | intType = reflect.TypeOf(int(1))
25 | int8Type = reflect.TypeOf(int8(1))
26 | int16Type = reflect.TypeOf(int16(1))
27 | int32Type = reflect.TypeOf(int32(1))
28 | int64Type = reflect.TypeOf(int64(1))
29 |
30 | uintType = reflect.TypeOf(uint(1))
31 | uint8Type = reflect.TypeOf(uint8(1))
32 | uint16Type = reflect.TypeOf(uint16(1))
33 | uint32Type = reflect.TypeOf(uint32(1))
34 | uint64Type = reflect.TypeOf(uint64(1))
35 |
36 | uintptrType = reflect.TypeOf(uintptr(1))
37 |
38 | float32Type = reflect.TypeOf(float32(1))
39 | float64Type = reflect.TypeOf(float64(1))
40 |
41 | stringType = reflect.TypeOf("")
42 |
43 | timeType = reflect.TypeOf(time.Time{})
44 | bytesType = reflect.TypeOf([]byte{})
45 | )
46 |
47 | func compare(obj1, obj2 interface{}, kind reflect.Kind) (compareResult, bool) {
48 | obj1Value := reflect.ValueOf(obj1)
49 | obj2Value := reflect.ValueOf(obj2)
50 |
51 | // throughout this switch we try and avoid calling .Convert() if possible,
52 | // as this has a pretty big performance impact
53 | switch kind {
54 | case reflect.Int:
55 | {
56 | intobj1, ok := obj1.(int)
57 | if !ok {
58 | intobj1 = obj1Value.Convert(intType).Interface().(int)
59 | }
60 | intobj2, ok := obj2.(int)
61 | if !ok {
62 | intobj2 = obj2Value.Convert(intType).Interface().(int)
63 | }
64 | if intobj1 > intobj2 {
65 | return compareGreater, true
66 | }
67 | if intobj1 == intobj2 {
68 | return compareEqual, true
69 | }
70 | if intobj1 < intobj2 {
71 | return compareLess, true
72 | }
73 | }
74 | case reflect.Int8:
75 | {
76 | int8obj1, ok := obj1.(int8)
77 | if !ok {
78 | int8obj1 = obj1Value.Convert(int8Type).Interface().(int8)
79 | }
80 | int8obj2, ok := obj2.(int8)
81 | if !ok {
82 | int8obj2 = obj2Value.Convert(int8Type).Interface().(int8)
83 | }
84 | if int8obj1 > int8obj2 {
85 | return compareGreater, true
86 | }
87 | if int8obj1 == int8obj2 {
88 | return compareEqual, true
89 | }
90 | if int8obj1 < int8obj2 {
91 | return compareLess, true
92 | }
93 | }
94 | case reflect.Int16:
95 | {
96 | int16obj1, ok := obj1.(int16)
97 | if !ok {
98 | int16obj1 = obj1Value.Convert(int16Type).Interface().(int16)
99 | }
100 | int16obj2, ok := obj2.(int16)
101 | if !ok {
102 | int16obj2 = obj2Value.Convert(int16Type).Interface().(int16)
103 | }
104 | if int16obj1 > int16obj2 {
105 | return compareGreater, true
106 | }
107 | if int16obj1 == int16obj2 {
108 | return compareEqual, true
109 | }
110 | if int16obj1 < int16obj2 {
111 | return compareLess, true
112 | }
113 | }
114 | case reflect.Int32:
115 | {
116 | int32obj1, ok := obj1.(int32)
117 | if !ok {
118 | int32obj1 = obj1Value.Convert(int32Type).Interface().(int32)
119 | }
120 | int32obj2, ok := obj2.(int32)
121 | if !ok {
122 | int32obj2 = obj2Value.Convert(int32Type).Interface().(int32)
123 | }
124 | if int32obj1 > int32obj2 {
125 | return compareGreater, true
126 | }
127 | if int32obj1 == int32obj2 {
128 | return compareEqual, true
129 | }
130 | if int32obj1 < int32obj2 {
131 | return compareLess, true
132 | }
133 | }
134 | case reflect.Int64:
135 | {
136 | int64obj1, ok := obj1.(int64)
137 | if !ok {
138 | int64obj1 = obj1Value.Convert(int64Type).Interface().(int64)
139 | }
140 | int64obj2, ok := obj2.(int64)
141 | if !ok {
142 | int64obj2 = obj2Value.Convert(int64Type).Interface().(int64)
143 | }
144 | if int64obj1 > int64obj2 {
145 | return compareGreater, true
146 | }
147 | if int64obj1 == int64obj2 {
148 | return compareEqual, true
149 | }
150 | if int64obj1 < int64obj2 {
151 | return compareLess, true
152 | }
153 | }
154 | case reflect.Uint:
155 | {
156 | uintobj1, ok := obj1.(uint)
157 | if !ok {
158 | uintobj1 = obj1Value.Convert(uintType).Interface().(uint)
159 | }
160 | uintobj2, ok := obj2.(uint)
161 | if !ok {
162 | uintobj2 = obj2Value.Convert(uintType).Interface().(uint)
163 | }
164 | if uintobj1 > uintobj2 {
165 | return compareGreater, true
166 | }
167 | if uintobj1 == uintobj2 {
168 | return compareEqual, true
169 | }
170 | if uintobj1 < uintobj2 {
171 | return compareLess, true
172 | }
173 | }
174 | case reflect.Uint8:
175 | {
176 | uint8obj1, ok := obj1.(uint8)
177 | if !ok {
178 | uint8obj1 = obj1Value.Convert(uint8Type).Interface().(uint8)
179 | }
180 | uint8obj2, ok := obj2.(uint8)
181 | if !ok {
182 | uint8obj2 = obj2Value.Convert(uint8Type).Interface().(uint8)
183 | }
184 | if uint8obj1 > uint8obj2 {
185 | return compareGreater, true
186 | }
187 | if uint8obj1 == uint8obj2 {
188 | return compareEqual, true
189 | }
190 | if uint8obj1 < uint8obj2 {
191 | return compareLess, true
192 | }
193 | }
194 | case reflect.Uint16:
195 | {
196 | uint16obj1, ok := obj1.(uint16)
197 | if !ok {
198 | uint16obj1 = obj1Value.Convert(uint16Type).Interface().(uint16)
199 | }
200 | uint16obj2, ok := obj2.(uint16)
201 | if !ok {
202 | uint16obj2 = obj2Value.Convert(uint16Type).Interface().(uint16)
203 | }
204 | if uint16obj1 > uint16obj2 {
205 | return compareGreater, true
206 | }
207 | if uint16obj1 == uint16obj2 {
208 | return compareEqual, true
209 | }
210 | if uint16obj1 < uint16obj2 {
211 | return compareLess, true
212 | }
213 | }
214 | case reflect.Uint32:
215 | {
216 | uint32obj1, ok := obj1.(uint32)
217 | if !ok {
218 | uint32obj1 = obj1Value.Convert(uint32Type).Interface().(uint32)
219 | }
220 | uint32obj2, ok := obj2.(uint32)
221 | if !ok {
222 | uint32obj2 = obj2Value.Convert(uint32Type).Interface().(uint32)
223 | }
224 | if uint32obj1 > uint32obj2 {
225 | return compareGreater, true
226 | }
227 | if uint32obj1 == uint32obj2 {
228 | return compareEqual, true
229 | }
230 | if uint32obj1 < uint32obj2 {
231 | return compareLess, true
232 | }
233 | }
234 | case reflect.Uint64:
235 | {
236 | uint64obj1, ok := obj1.(uint64)
237 | if !ok {
238 | uint64obj1 = obj1Value.Convert(uint64Type).Interface().(uint64)
239 | }
240 | uint64obj2, ok := obj2.(uint64)
241 | if !ok {
242 | uint64obj2 = obj2Value.Convert(uint64Type).Interface().(uint64)
243 | }
244 | if uint64obj1 > uint64obj2 {
245 | return compareGreater, true
246 | }
247 | if uint64obj1 == uint64obj2 {
248 | return compareEqual, true
249 | }
250 | if uint64obj1 < uint64obj2 {
251 | return compareLess, true
252 | }
253 | }
254 | case reflect.Float32:
255 | {
256 | float32obj1, ok := obj1.(float32)
257 | if !ok {
258 | float32obj1 = obj1Value.Convert(float32Type).Interface().(float32)
259 | }
260 | float32obj2, ok := obj2.(float32)
261 | if !ok {
262 | float32obj2 = obj2Value.Convert(float32Type).Interface().(float32)
263 | }
264 | if float32obj1 > float32obj2 {
265 | return compareGreater, true
266 | }
267 | if float32obj1 == float32obj2 {
268 | return compareEqual, true
269 | }
270 | if float32obj1 < float32obj2 {
271 | return compareLess, true
272 | }
273 | }
274 | case reflect.Float64:
275 | {
276 | float64obj1, ok := obj1.(float64)
277 | if !ok {
278 | float64obj1 = obj1Value.Convert(float64Type).Interface().(float64)
279 | }
280 | float64obj2, ok := obj2.(float64)
281 | if !ok {
282 | float64obj2 = obj2Value.Convert(float64Type).Interface().(float64)
283 | }
284 | if float64obj1 > float64obj2 {
285 | return compareGreater, true
286 | }
287 | if float64obj1 == float64obj2 {
288 | return compareEqual, true
289 | }
290 | if float64obj1 < float64obj2 {
291 | return compareLess, true
292 | }
293 | }
294 | case reflect.String:
295 | {
296 | stringobj1, ok := obj1.(string)
297 | if !ok {
298 | stringobj1 = obj1Value.Convert(stringType).Interface().(string)
299 | }
300 | stringobj2, ok := obj2.(string)
301 | if !ok {
302 | stringobj2 = obj2Value.Convert(stringType).Interface().(string)
303 | }
304 | if stringobj1 > stringobj2 {
305 | return compareGreater, true
306 | }
307 | if stringobj1 == stringobj2 {
308 | return compareEqual, true
309 | }
310 | if stringobj1 < stringobj2 {
311 | return compareLess, true
312 | }
313 | }
314 | // Check for known struct types we can check for compare results.
315 | case reflect.Struct:
316 | {
317 | // All structs enter here. We're not interested in most types.
318 | if !obj1Value.CanConvert(timeType) {
319 | break
320 | }
321 |
322 | // time.Time can be compared!
323 | timeObj1, ok := obj1.(time.Time)
324 | if !ok {
325 | timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time)
326 | }
327 |
328 | timeObj2, ok := obj2.(time.Time)
329 | if !ok {
330 | timeObj2 = obj2Value.Convert(timeType).Interface().(time.Time)
331 | }
332 |
333 | if timeObj1.Before(timeObj2) {
334 | return compareLess, true
335 | }
336 | if timeObj1.Equal(timeObj2) {
337 | return compareEqual, true
338 | }
339 | return compareGreater, true
340 | }
341 | case reflect.Slice:
342 | {
343 | // We only care about the []byte type.
344 | if !obj1Value.CanConvert(bytesType) {
345 | break
346 | }
347 |
348 | // []byte can be compared!
349 | bytesObj1, ok := obj1.([]byte)
350 | if !ok {
351 | bytesObj1 = obj1Value.Convert(bytesType).Interface().([]byte)
352 |
353 | }
354 | bytesObj2, ok := obj2.([]byte)
355 | if !ok {
356 | bytesObj2 = obj2Value.Convert(bytesType).Interface().([]byte)
357 | }
358 |
359 | return compareResult(bytes.Compare(bytesObj1, bytesObj2)), true
360 | }
361 | case reflect.Uintptr:
362 | {
363 | uintptrObj1, ok := obj1.(uintptr)
364 | if !ok {
365 | uintptrObj1 = obj1Value.Convert(uintptrType).Interface().(uintptr)
366 | }
367 | uintptrObj2, ok := obj2.(uintptr)
368 | if !ok {
369 | uintptrObj2 = obj2Value.Convert(uintptrType).Interface().(uintptr)
370 | }
371 | if uintptrObj1 > uintptrObj2 {
372 | return compareGreater, true
373 | }
374 | if uintptrObj1 == uintptrObj2 {
375 | return compareEqual, true
376 | }
377 | if uintptrObj1 < uintptrObj2 {
378 | return compareLess, true
379 | }
380 | }
381 | }
382 |
383 | return compareEqual, false
384 | }
385 |
386 | // Greater asserts that the first element is greater than the second
387 | //
388 | // assert.Greater(2, 1)
389 | // assert.Greater(float64(2), float64(1))
390 | // assert.Greater("b", "a")
391 | func Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
392 | return compareTwoValues(e1, e2, []compareResult{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
393 | }
394 |
395 | // GreaterOrEqual asserts that the first element is greater than or equal to the second
396 | //
397 | // assert.GreaterOrEqual(2, 1)
398 | // assert.GreaterOrEqual(2, 2)
399 | // assert.GreaterOrEqual("b", "a")
400 | // assert.GreaterOrEqual("b", "b")
401 | func GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
402 | return compareTwoValues(e1, e2, []compareResult{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
403 | }
404 |
405 | // Less asserts that the first element is less than the second
406 | //
407 | // assert.Less(1, 2)
408 | // assert.Less(float64(1), float64(2))
409 | // assert.Less("a", "b")
410 | func Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
411 | return compareTwoValues(e1, e2, []compareResult{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
412 | }
413 |
414 | // LessOrEqual asserts that the first element is less than or equal to the second
415 | //
416 | // assert.LessOrEqual(1, 2)
417 | // assert.LessOrEqual(2, 2)
418 | // assert.LessOrEqual("a", "b")
419 | // assert.LessOrEqual("b", "b")
420 | func LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
421 | return compareTwoValues(e1, e2, []compareResult{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
422 | }
423 |
424 | // Positive asserts that the specified element is positive
425 | //
426 | // assert.Positive(1)
427 | // assert.Positive(1.23)
428 | func Positive(e interface{}, msgAndArgs ...interface{}) bool {
429 | zero := reflect.Zero(reflect.TypeOf(e))
430 | return compareTwoValues(e, zero.Interface(), []compareResult{compareGreater}, "\"%v\" is not positive", msgAndArgs...)
431 | }
432 |
433 | // Negative asserts that the specified element is negative
434 | //
435 | // assert.Negative(-1)
436 | // assert.Negative(-1.23)
437 | func Negative(e interface{}, msgAndArgs ...interface{}) bool {
438 | zero := reflect.Zero(reflect.TypeOf(e))
439 | return compareTwoValues(e, zero.Interface(), []compareResult{compareLess}, "\"%v\" is not negative", msgAndArgs...)
440 | }
441 |
442 | func compareTwoValues(e1 interface{}, e2 interface{}, allowedComparesResults []compareResult, failMessage string, msgAndArgs ...interface{}) bool {
443 |
444 | e1Kind := reflect.ValueOf(e1).Kind()
445 | e2Kind := reflect.ValueOf(e2).Kind()
446 | if e1Kind != e2Kind {
447 | return Fail("Elements should be the same type", msgAndArgs...)
448 | }
449 |
450 | compareResult, isComparable := compare(e1, e2, e1Kind)
451 | if !isComparable {
452 | return Fail(fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
453 | }
454 |
455 | if !containsValue(allowedComparesResults, compareResult) {
456 | return Fail(fmt.Sprintf(failMessage, e1, e2), msgAndArgs...)
457 | }
458 |
459 | return true
460 | }
461 |
462 | func containsValue(values []compareResult, value compareResult) bool {
463 | for _, v := range values {
464 | if v == value {
465 | return true
466 | }
467 | }
468 |
469 | return false
470 | }
471 |
--------------------------------------------------------------------------------
/assertion_format.go:
--------------------------------------------------------------------------------
1 | //go:build assert
2 |
3 | // Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT.
4 |
5 | package assert
6 |
7 | import (
8 | http "net/http"
9 | url "net/url"
10 | time "time"
11 | )
12 |
13 | // Conditionf uses a Comparison to assert a complex condition.
14 | func Conditionf(comp Comparison, msg string, args ...interface{}) bool {
15 | return Condition(comp, append([]interface{}{msg}, args...)...)
16 | }
17 |
18 | // Containsf asserts that the specified string, list(array, slice...) or map contains the
19 | // specified substring or element.
20 | //
21 | // assert.Containsf("Hello World", "World", "error message %s", "formatted")
22 | // assert.Containsf(["Hello", "World"], "World", "error message %s", "formatted")
23 | // assert.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted")
24 | func Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool {
25 | return Contains(s, contains, append([]interface{}{msg}, args...)...)
26 | }
27 |
28 | // DirExistsf checks whether a directory exists in the given path. It also fails
29 | // if the path is a file rather a directory or there is an error checking whether it exists.
30 | func DirExistsf(path string, msg string, args ...interface{}) bool {
31 | return DirExists(path, append([]interface{}{msg}, args...)...)
32 | }
33 |
34 | // ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified
35 | // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
36 | // the number of appearances of each of them in both lists should match.
37 | //
38 | // assert.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
39 | func ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
40 | return ElementsMatch(listA, listB, append([]interface{}{msg}, args...)...)
41 | }
42 |
43 | // Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
44 | // a slice or a channel with len == 0.
45 | //
46 | // assert.Emptyf(obj, "error message %s", "formatted")
47 | func Emptyf(object interface{}, msg string, args ...interface{}) bool {
48 | return Empty(object, append([]interface{}{msg}, args...)...)
49 | }
50 |
51 | // Equalf asserts that two objects are equal.
52 | //
53 | // assert.Equalf(123, 123, "error message %s", "formatted")
54 | //
55 | // Pointer variable equality is determined based on the equality of the
56 | // referenced values (as opposed to the memory addresses). Function equality
57 | // cannot be determined and will always fail.
58 | func Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
59 | return Equal(expected, actual, append([]interface{}{msg}, args...)...)
60 | }
61 |
62 | // EqualErrorf asserts that a function returned an error (i.e. not `nil`)
63 | // and that it is equal to the provided error.
64 | //
65 | // actualObj, err := SomeFunction()
66 | // assert.EqualErrorf(err, expectedErrorString, "error message %s", "formatted")
67 | func EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool {
68 | return EqualError(theError, errString, append([]interface{}{msg}, args...)...)
69 | }
70 |
71 | // EqualExportedValuesf asserts that the types of two objects are equal and their public
72 | // fields are also equal. This is useful for comparing structs that have private fields
73 | // that could potentially differ.
74 | //
75 | // type S struct {
76 | // Exported int
77 | // notExported int
78 | // }
79 | // assert.EqualExportedValuesf(S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
80 | // assert.EqualExportedValuesf(S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
81 | func EqualExportedValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
82 | return EqualExportedValues(expected, actual, append([]interface{}{msg}, args...)...)
83 | }
84 |
85 | // EqualValuesf asserts that two objects are equal or convertible to the larger
86 | // type and equal.
87 | //
88 | // assert.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
89 | func EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
90 | return EqualValues(expected, actual, append([]interface{}{msg}, args...)...)
91 | }
92 |
93 | // Errorf asserts that a function returned an error (i.e. not `nil`).
94 | //
95 | // actualObj, err := SomeFunction()
96 | // if assert.Errorf(err, "error message %s", "formatted") {
97 | // assert.Equal(expectedErrorf, err)
98 | // }
99 | func Errorf(err error, msg string, args ...interface{}) bool {
100 | return Error(err, append([]interface{}{msg}, args...)...)
101 | }
102 |
103 | // ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
104 | // This is a wrapper for errors.As.
105 | func ErrorAsf(err error, target interface{}, msg string, args ...interface{}) bool {
106 | return ErrorAs(err, target, append([]interface{}{msg}, args...)...)
107 | }
108 |
109 | // ErrorContainsf asserts that a function returned an error (i.e. not `nil`)
110 | // and that the error contains the specified substring.
111 | //
112 | // actualObj, err := SomeFunction()
113 | // assert.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted")
114 | func ErrorContainsf(theError error, contains string, msg string, args ...interface{}) bool {
115 | return ErrorContains(theError, contains, append([]interface{}{msg}, args...)...)
116 | }
117 |
118 | // ErrorIsf asserts that at least one of the errors in err's chain matches target.
119 | // This is a wrapper for errors.Is.
120 | func ErrorIsf(err error, target error, msg string, args ...interface{}) bool {
121 | return ErrorIs(err, target, append([]interface{}{msg}, args...)...)
122 | }
123 |
124 | // Eventuallyf asserts that given condition will be met in waitFor time,
125 | // periodically checking target function each tick.
126 | //
127 | // assert.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
128 | func Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
129 | return Eventually(condition, waitFor, tick, append([]interface{}{msg}, args...)...)
130 | }
131 |
132 | // EventuallyWithTf asserts that given condition will be met in waitFor time,
133 | // periodically checking target function each tick. In contrast to Eventually,
134 | // it supplies a CollectT to the condition function, so that the condition
135 | // function can use the CollectT to call other assertions.
136 | // The condition is considered "met" if no errors are raised in a tick.
137 | // The supplied CollectT collects all errors from one tick (if there are any).
138 | // If the condition is not met before waitFor, the collected errors of
139 | // the last tick are copied to t.
140 | //
141 | // externalValue := false
142 | // go func() {
143 | // time.Sleep(8*time.Second)
144 | // externalValue = true
145 | // }()
146 | // assert.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") {
147 | // // add assertions as needed; any assertion failure will fail the current tick
148 | // assert.True(c, externalValue, "expected 'externalValue' to be true")
149 | // }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
150 | func EventuallyWithTf(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
151 | return EventuallyWithT(condition, waitFor, tick, append([]interface{}{msg}, args...)...)
152 | }
153 |
154 | // Exactlyf asserts that two objects are equal in value and type.
155 | //
156 | // assert.Exactlyf(int32(123), int64(123), "error message %s", "formatted")
157 | func Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
158 | return Exactly(expected, actual, append([]interface{}{msg}, args...)...)
159 | }
160 |
161 | // Failf reports a failure through
162 | func Failf(failureMessage string, msg string, args ...interface{}) bool {
163 | return Fail(failureMessage, append([]interface{}{msg}, args...)...)
164 | }
165 |
166 | // FailNowf fails test
167 | func FailNowf(failureMessage string, msg string, args ...interface{}) bool {
168 | return FailNow(failureMessage, append([]interface{}{msg}, args...)...)
169 | }
170 |
171 | // Falsef asserts that the specified value is false.
172 | //
173 | // assert.Falsef(myBool, "error message %s", "formatted")
174 | func Falsef(value bool, msg string, args ...interface{}) bool {
175 | return False(value, append([]interface{}{msg}, args...)...)
176 | }
177 |
178 | // FileExistsf checks whether a file exists in the given path. It also fails if
179 | // the path points to a directory or there is an error when trying to check the file.
180 | func FileExistsf(path string, msg string, args ...interface{}) bool {
181 | return FileExists(path, append([]interface{}{msg}, args...)...)
182 | }
183 |
184 | // Greaterf asserts that the first element is greater than the second
185 | //
186 | // assert.Greaterf(2, 1, "error message %s", "formatted")
187 | // assert.Greaterf(float64(2), float64(1), "error message %s", "formatted")
188 | // assert.Greaterf("b", "a", "error message %s", "formatted")
189 | func Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
190 | return Greater(e1, e2, append([]interface{}{msg}, args...)...)
191 | }
192 |
193 | // GreaterOrEqualf asserts that the first element is greater than or equal to the second
194 | //
195 | // assert.GreaterOrEqualf(2, 1, "error message %s", "formatted")
196 | // assert.GreaterOrEqualf(2, 2, "error message %s", "formatted")
197 | // assert.GreaterOrEqualf("b", "a", "error message %s", "formatted")
198 | // assert.GreaterOrEqualf("b", "b", "error message %s", "formatted")
199 | func GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
200 | return GreaterOrEqual(e1, e2, append([]interface{}{msg}, args...)...)
201 | }
202 |
203 | // HTTPBodyContainsf asserts that a specified handler returns a
204 | // body that contains a string.
205 | //
206 | // assert.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
207 | //
208 | // Returns whether the assertion was successful (true) or not (false).
209 | func HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
210 | return HTTPBodyContains(handler, method, url, values, str, append([]interface{}{msg}, args...)...)
211 | }
212 |
213 | // HTTPBodyNotContainsf asserts that a specified handler returns a
214 | // body that does not contain a string.
215 | //
216 | // assert.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
217 | //
218 | // Returns whether the assertion was successful (true) or not (false).
219 | func HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
220 | return HTTPBodyNotContains(handler, method, url, values, str, append([]interface{}{msg}, args...)...)
221 | }
222 |
223 | // HTTPErrorf asserts that a specified handler returns an error status code.
224 | //
225 | // assert.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
226 | //
227 | // Returns whether the assertion was successful (true) or not (false).
228 | func HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
229 | return HTTPError(handler, method, url, values, append([]interface{}{msg}, args...)...)
230 | }
231 |
232 | // HTTPRedirectf asserts that a specified handler returns a redirect status code.
233 | //
234 | // assert.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
235 | //
236 | // Returns whether the assertion was successful (true) or not (false).
237 | func HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
238 | return HTTPRedirect(handler, method, url, values, append([]interface{}{msg}, args...)...)
239 | }
240 |
241 | // HTTPStatusCodef asserts that a specified handler returns a specified status code.
242 | //
243 | // assert.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
244 | //
245 | // Returns whether the assertion was successful (true) or not (false).
246 | func HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool {
247 | return HTTPStatusCode(handler, method, url, values, statuscode, append([]interface{}{msg}, args...)...)
248 | }
249 |
250 | // HTTPSuccessf asserts that a specified handler returns a success status code.
251 | //
252 | // assert.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
253 | //
254 | // Returns whether the assertion was successful (true) or not (false).
255 | func HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
256 | return HTTPSuccess(handler, method, url, values, append([]interface{}{msg}, args...)...)
257 | }
258 |
259 | // Implementsf asserts that an object is implemented by the specified interface.
260 | //
261 | // assert.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
262 | func Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
263 | return Implements(interfaceObject, object, append([]interface{}{msg}, args...)...)
264 | }
265 |
266 | // InDeltaf asserts that the two numerals are within delta of each other.
267 | //
268 | // assert.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted")
269 | func InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
270 | return InDelta(expected, actual, delta, append([]interface{}{msg}, args...)...)
271 | }
272 |
273 | // InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
274 | func InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
275 | return InDeltaMapValues(expected, actual, delta, append([]interface{}{msg}, args...)...)
276 | }
277 |
278 | // InDeltaSlicef is the same as InDelta, except it compares two slices.
279 | func InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
280 | return InDeltaSlice(expected, actual, delta, append([]interface{}{msg}, args...)...)
281 | }
282 |
283 | // InEpsilonf asserts that expected and actual have a relative error less than epsilon
284 | func InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
285 | return InEpsilon(expected, actual, epsilon, append([]interface{}{msg}, args...)...)
286 | }
287 |
288 | // InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
289 | func InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
290 | return InEpsilonSlice(expected, actual, epsilon, append([]interface{}{msg}, args...)...)
291 | }
292 |
293 | // IsDecreasingf asserts that the collection is decreasing
294 | //
295 | // assert.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted")
296 | // assert.IsDecreasingf([]float{2, 1}, "error message %s", "formatted")
297 | // assert.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted")
298 | func IsDecreasingf(object interface{}, msg string, args ...interface{}) bool {
299 | return IsDecreasing(object, append([]interface{}{msg}, args...)...)
300 | }
301 |
302 | // IsIncreasingf asserts that the collection is increasing
303 | //
304 | // assert.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted")
305 | // assert.IsIncreasingf([]float{1, 2}, "error message %s", "formatted")
306 | // assert.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted")
307 | func IsIncreasingf(object interface{}, msg string, args ...interface{}) bool {
308 | return IsIncreasing(object, append([]interface{}{msg}, args...)...)
309 | }
310 |
311 | // IsNonDecreasingf asserts that the collection is not decreasing
312 | //
313 | // assert.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted")
314 | // assert.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted")
315 | // assert.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted")
316 | func IsNonDecreasingf(object interface{}, msg string, args ...interface{}) bool {
317 | return IsNonDecreasing(object, append([]interface{}{msg}, args...)...)
318 | }
319 |
320 | // IsNonIncreasingf asserts that the collection is not increasing
321 | //
322 | // assert.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted")
323 | // assert.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted")
324 | // assert.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted")
325 | func IsNonIncreasingf(object interface{}, msg string, args ...interface{}) bool {
326 | return IsNonIncreasing(object, append([]interface{}{msg}, args...)...)
327 | }
328 |
329 | // IsTypef asserts that the specified objects are of the same type.
330 | func IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
331 | return IsType(expectedType, object, append([]interface{}{msg}, args...)...)
332 | }
333 |
334 | // JSONEqf asserts that two JSON strings are equivalent.
335 | //
336 | // assert.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
337 | func JSONEqf(expected string, actual string, msg string, args ...interface{}) bool {
338 | return JSONEq(expected, actual, append([]interface{}{msg}, args...)...)
339 | }
340 |
341 | // Lenf asserts that the specified object has specific length.
342 | // Lenf also fails if the object has a type that len() not accept.
343 | //
344 | // assert.Lenf(mySlice, 3, "error message %s", "formatted")
345 | func Lenf(object interface{}, length int, msg string, args ...interface{}) bool {
346 | return Len(object, length, append([]interface{}{msg}, args...)...)
347 | }
348 |
349 | // Lessf asserts that the first element is less than the second
350 | //
351 | // assert.Lessf(1, 2, "error message %s", "formatted")
352 | // assert.Lessf(float64(1), float64(2), "error message %s", "formatted")
353 | // assert.Lessf("a", "b", "error message %s", "formatted")
354 | func Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
355 | return Less(e1, e2, append([]interface{}{msg}, args...)...)
356 | }
357 |
358 | // LessOrEqualf asserts that the first element is less than or equal to the second
359 | //
360 | // assert.LessOrEqualf(1, 2, "error message %s", "formatted")
361 | // assert.LessOrEqualf(2, 2, "error message %s", "formatted")
362 | // assert.LessOrEqualf("a", "b", "error message %s", "formatted")
363 | // assert.LessOrEqualf("b", "b", "error message %s", "formatted")
364 | func LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
365 | return LessOrEqual(e1, e2, append([]interface{}{msg}, args...)...)
366 | }
367 |
368 | // Negativef asserts that the specified element is negative
369 | //
370 | // assert.Negativef(-1, "error message %s", "formatted")
371 | // assert.Negativef(-1.23, "error message %s", "formatted")
372 | func Negativef(e interface{}, msg string, args ...interface{}) bool {
373 | return Negative(e, append([]interface{}{msg}, args...)...)
374 | }
375 |
376 | // Neverf asserts that the given condition doesn't satisfy in waitFor time,
377 | // periodically checking the target function each tick.
378 | //
379 | // assert.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
380 | func Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
381 | return Never(condition, waitFor, tick, append([]interface{}{msg}, args...)...)
382 | }
383 |
384 | // Nilf asserts that the specified object is nil.
385 | //
386 | // assert.Nilf(err, "error message %s", "formatted")
387 | func Nilf(object interface{}, msg string, args ...interface{}) bool {
388 | return Nil(object, append([]interface{}{msg}, args...)...)
389 | }
390 |
391 | // NoDirExistsf checks whether a directory does not exist in the given path.
392 | // It fails if the path points to an existing _directory_ only.
393 | func NoDirExistsf(path string, msg string, args ...interface{}) bool {
394 | return NoDirExists(path, append([]interface{}{msg}, args...)...)
395 | }
396 |
397 | // NoErrorf asserts that a function returned no error (i.e. `nil`).
398 | //
399 | // actualObj, err := SomeFunction()
400 | // if assert.NoErrorf(err, "error message %s", "formatted") {
401 | // assert.Equal(expectedObj, actualObj)
402 | // }
403 | func NoErrorf(err error, msg string, args ...interface{}) bool {
404 | return NoError(err, append([]interface{}{msg}, args...)...)
405 | }
406 |
407 | // NoFileExistsf checks whether a file does not exist in a given path. It fails
408 | // if the path points to an existing _file_ only.
409 | func NoFileExistsf(path string, msg string, args ...interface{}) bool {
410 | return NoFileExists(path, append([]interface{}{msg}, args...)...)
411 | }
412 |
413 | // NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
414 | // specified substring or element.
415 | //
416 | // assert.NotContainsf("Hello World", "Earth", "error message %s", "formatted")
417 | // assert.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted")
418 | // assert.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted")
419 | func NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool {
420 | return NotContains(s, contains, append([]interface{}{msg}, args...)...)
421 | }
422 |
423 | // NotElementsMatchf asserts that the specified listA(array, slice...) is NOT equal to specified
424 | // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
425 | // the number of appearances of each of them in both lists should not match.
426 | // This is an inverse of ElementsMatch.
427 | //
428 | // assert.NotElementsMatchf([1, 1, 2, 3], [1, 1, 2, 3], "error message %s", "formatted") -> false
429 | //
430 | // assert.NotElementsMatchf([1, 1, 2, 3], [1, 2, 3], "error message %s", "formatted") -> true
431 | //
432 | // assert.NotElementsMatchf([1, 2, 3], [1, 2, 4], "error message %s", "formatted") -> true
433 | func NotElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
434 | return NotElementsMatch(listA, listB, append([]interface{}{msg}, args...)...)
435 | }
436 |
437 | // NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
438 | // a slice or a channel with len == 0.
439 | //
440 | // if assert.NotEmptyf(obj, "error message %s", "formatted") {
441 | // assert.Equal("two", obj[1])
442 | // }
443 | func NotEmptyf(object interface{}, msg string, args ...interface{}) bool {
444 | return NotEmpty(object, append([]interface{}{msg}, args...)...)
445 | }
446 |
447 | // NotEqualf asserts that the specified values are NOT equal.
448 | //
449 | // assert.NotEqualf(obj1, obj2, "error message %s", "formatted")
450 | //
451 | // Pointer variable equality is determined based on the equality of the
452 | // referenced values (as opposed to the memory addresses).
453 | func NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
454 | return NotEqual(expected, actual, append([]interface{}{msg}, args...)...)
455 | }
456 |
457 | // NotEqualValuesf asserts that two objects are not equal even when converted to the same type
458 | //
459 | // assert.NotEqualValuesf(obj1, obj2, "error message %s", "formatted")
460 | func NotEqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
461 | return NotEqualValues(expected, actual, append([]interface{}{msg}, args...)...)
462 | }
463 |
464 | // NotErrorAsf asserts that none of the errors in err's chain matches target,
465 | // but if so, sets target to that error value.
466 | func NotErrorAsf(err error, target interface{}, msg string, args ...interface{}) bool {
467 | return NotErrorAs(err, target, append([]interface{}{msg}, args...)...)
468 | }
469 |
470 | // NotErrorIsf asserts that none of the errors in err's chain matches target.
471 | // This is a wrapper for errors.Is.
472 | func NotErrorIsf(err error, target error, msg string, args ...interface{}) bool {
473 | return NotErrorIs(err, target, append([]interface{}{msg}, args...)...)
474 | }
475 |
476 | // NotImplementsf asserts that an object does not implement the specified interface.
477 | //
478 | // assert.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
479 | func NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
480 | return NotImplements(interfaceObject, object, append([]interface{}{msg}, args...)...)
481 | }
482 |
483 | // NotNilf asserts that the specified object is not nil.
484 | //
485 | // assert.NotNilf(err, "error message %s", "formatted")
486 | func NotNilf(object interface{}, msg string, args ...interface{}) bool {
487 | return NotNil(object, append([]interface{}{msg}, args...)...)
488 | }
489 |
490 | // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
491 | //
492 | // assert.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted")
493 | func NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool {
494 | return NotPanics(f, append([]interface{}{msg}, args...)...)
495 | }
496 |
497 | // NotRegexpf asserts that a specified regexp does not match a string.
498 | //
499 | // assert.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted")
500 | // assert.NotRegexpf("^start", "it's not starting", "error message %s", "formatted")
501 | func NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
502 | return NotRegexp(rx, str, append([]interface{}{msg}, args...)...)
503 | }
504 |
505 | // NotSamef asserts that two pointers do not reference the same object.
506 | //
507 | // assert.NotSamef(ptr1, ptr2, "error message %s", "formatted")
508 | //
509 | // Both arguments must be pointer variables. Pointer variable sameness is
510 | // determined based on the equality of both type and value.
511 | func NotSamef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
512 | return NotSame(expected, actual, append([]interface{}{msg}, args...)...)
513 | }
514 |
515 | // NotSubsetf asserts that the specified list(array, slice...) or map does NOT
516 | // contain all elements given in the specified subset list(array, slice...) or
517 | // map.
518 | //
519 | // assert.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted")
520 | // assert.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
521 | func NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
522 | return NotSubset(list, subset, append([]interface{}{msg}, args...)...)
523 | }
524 |
525 | // NotZerof asserts that i is not the zero value for its type.
526 | func NotZerof(i interface{}, msg string, args ...interface{}) bool {
527 | return NotZero(i, append([]interface{}{msg}, args...)...)
528 | }
529 |
530 | // Panicsf asserts that the code inside the specified PanicTestFunc panics.
531 | //
532 | // assert.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted")
533 | func Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool {
534 | return Panics(f, append([]interface{}{msg}, args...)...)
535 | }
536 |
537 | // PanicsWithErrorf asserts that the code inside the specified PanicTestFunc
538 | // panics, and that the recovered panic value is an error that satisfies the
539 | // EqualError comparison.
540 | //
541 | // assert.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
542 | func PanicsWithErrorf(errString string, f PanicTestFunc, msg string, args ...interface{}) bool {
543 | return PanicsWithError(errString, f, append([]interface{}{msg}, args...)...)
544 | }
545 |
546 | // PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
547 | // the recovered panic value equals the expected panic value.
548 | //
549 | // assert.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
550 | func PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
551 | return PanicsWithValue(expected, f, append([]interface{}{msg}, args...)...)
552 | }
553 |
554 | // Positivef asserts that the specified element is positive
555 | //
556 | // assert.Positivef(1, "error message %s", "formatted")
557 | // assert.Positivef(1.23, "error message %s", "formatted")
558 | func Positivef(e interface{}, msg string, args ...interface{}) bool {
559 | return Positive(e, append([]interface{}{msg}, args...)...)
560 | }
561 |
562 | // Regexpf asserts that a specified regexp matches a string.
563 | //
564 | // assert.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted")
565 | // assert.Regexpf("start...$", "it's not starting", "error message %s", "formatted")
566 | func Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
567 | return Regexp(rx, str, append([]interface{}{msg}, args...)...)
568 | }
569 |
570 | // Samef asserts that two pointers reference the same object.
571 | //
572 | // assert.Samef(ptr1, ptr2, "error message %s", "formatted")
573 | //
574 | // Both arguments must be pointer variables. Pointer variable sameness is
575 | // determined based on the equality of both type and value.
576 | func Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
577 | return Same(expected, actual, append([]interface{}{msg}, args...)...)
578 | }
579 |
580 | // Subsetf asserts that the specified list(array, slice...) or map contains all
581 | // elements given in the specified subset list(array, slice...) or map.
582 | //
583 | // assert.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted")
584 | // assert.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
585 | func Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
586 | return Subset(list, subset, append([]interface{}{msg}, args...)...)
587 | }
588 |
589 | // Truef asserts that the specified value is true.
590 | //
591 | // assert.Truef(myBool, "error message %s", "formatted")
592 | func Truef(value bool, msg string, args ...interface{}) bool {
593 | return True(value, append([]interface{}{msg}, args...)...)
594 | }
595 |
596 | // WithinDurationf asserts that the two times are within duration delta of each other.
597 | //
598 | // assert.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
599 | func WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
600 | return WithinDuration(expected, actual, delta, append([]interface{}{msg}, args...)...)
601 | }
602 |
603 | // WithinRangef asserts that a time is within a time range (inclusive).
604 | //
605 | // assert.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
606 | func WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool {
607 | return WithinRange(actual, start, end, append([]interface{}{msg}, args...)...)
608 | }
609 |
610 | // YAMLEqf asserts that two YAML strings are equivalent.
611 |
612 | // Zerof asserts that i is the zero value for its type.
613 | func Zerof(i interface{}, msg string, args ...interface{}) bool {
614 | return Zero(i, append([]interface{}{msg}, args...)...)
615 | }
616 |
--------------------------------------------------------------------------------
/assertion_order.go:
--------------------------------------------------------------------------------
1 | //go:build assert
2 |
3 | package assert
4 |
5 | import (
6 | "fmt"
7 | "reflect"
8 | )
9 |
10 | // isOrdered checks that collection contains orderable elements.
11 | func isOrdered(object interface{}, allowedComparesResults []compareResult, failMessage string, msgAndArgs ...interface{}) bool {
12 | objKind := reflect.TypeOf(object).Kind()
13 | if objKind != reflect.Slice && objKind != reflect.Array {
14 | return false
15 | }
16 |
17 | objValue := reflect.ValueOf(object)
18 | objLen := objValue.Len()
19 |
20 | if objLen <= 1 {
21 | return true
22 | }
23 |
24 | value := objValue.Index(0)
25 | valueInterface := value.Interface()
26 | firstValueKind := value.Kind()
27 |
28 | for i := 1; i < objLen; i++ {
29 | prevValue := value
30 | prevValueInterface := valueInterface
31 |
32 | value = objValue.Index(i)
33 | valueInterface = value.Interface()
34 |
35 | compareResult, isComparable := compare(prevValueInterface, valueInterface, firstValueKind)
36 |
37 | if !isComparable {
38 | return Fail(fmt.Sprintf("Can not compare type \"%s\" and \"%s\"", reflect.TypeOf(value), reflect.TypeOf(prevValue)), msgAndArgs...)
39 | }
40 |
41 | if !containsValue(allowedComparesResults, compareResult) {
42 | return Fail(fmt.Sprintf(failMessage, prevValue, value), msgAndArgs...)
43 | }
44 | }
45 |
46 | return true
47 | }
48 |
49 | // IsIncreasing asserts that the collection is increasing
50 | //
51 | // assert.IsIncreasing([]int{1, 2, 3})
52 | // assert.IsIncreasing([]float{1, 2})
53 | // assert.IsIncreasing([]string{"a", "b"})
54 | func IsIncreasing(object interface{}, msgAndArgs ...interface{}) bool {
55 | return isOrdered(object, []compareResult{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
56 | }
57 |
58 | // IsNonIncreasing asserts that the collection is not increasing
59 | //
60 | // assert.IsNonIncreasing([]int{2, 1, 1})
61 | // assert.IsNonIncreasing([]float{2, 1})
62 | // assert.IsNonIncreasing([]string{"b", "a"})
63 | func IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) bool {
64 | return isOrdered(object, []compareResult{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
65 | }
66 |
67 | // IsDecreasing asserts that the collection is decreasing
68 | //
69 | // assert.IsDecreasing([]int{2, 1, 0})
70 | // assert.IsDecreasing([]float{2, 1})
71 | // assert.IsDecreasing([]string{"b", "a"})
72 | func IsDecreasing(object interface{}, msgAndArgs ...interface{}) bool {
73 | return isOrdered(object, []compareResult{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
74 | }
75 |
76 | // IsNonDecreasing asserts that the collection is not decreasing
77 | //
78 | // assert.IsNonDecreasing([]int{1, 1, 2})
79 | // assert.IsNonDecreasing([]float{1, 2})
80 | // assert.IsNonDecreasing([]string{"a", "b"})
81 | func IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) bool {
82 | return isOrdered(object, []compareResult{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
83 | }
84 |
--------------------------------------------------------------------------------
/assertions.go:
--------------------------------------------------------------------------------
1 | //go:build assert
2 |
3 | package assert
4 |
5 | import (
6 | "bufio"
7 | "bytes"
8 | "encoding/json"
9 | "errors"
10 | "fmt"
11 | "math"
12 | "os"
13 | "reflect"
14 | "regexp"
15 | "runtime"
16 | "runtime/debug"
17 | "strings"
18 | "time"
19 | "unicode"
20 | "unicode/utf8"
21 |
22 | "github.com/davecgh/go-spew/spew"
23 | "github.com/pmezard/go-difflib/difflib"
24 | // Wrapper around gopkg.in/yaml.v3
25 | )
26 |
27 | //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl"
28 |
29 | // TestingT is an interface wrapper around *testing.T
30 | type TestingT interface {
31 | Errorf(format string, args ...interface{})
32 | }
33 |
34 | // ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful
35 | // for table driven tests.
36 | type ComparisonAssertionFunc func(interface{}, interface{}, ...interface{}) bool
37 |
38 | // ValueAssertionFunc is a common function prototype when validating a single value. Can be useful
39 | // for table driven tests.
40 | type ValueAssertionFunc func(interface{}, ...interface{}) bool
41 |
42 | // BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful
43 | // for table driven tests.
44 | type BoolAssertionFunc func(bool, ...interface{}) bool
45 |
46 | // ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful
47 | // for table driven tests.
48 | type ErrorAssertionFunc func(error, ...interface{}) bool
49 |
50 | // PanicAssertionFunc is a common function prototype when validating a panic value. Can be useful
51 | // for table driven tests.
52 | type PanicAssertionFunc = func(f PanicTestFunc, msgAndArgs ...interface{}) bool
53 |
54 | // Comparison is a custom function that returns true on success and false on failure
55 | type Comparison func() (success bool)
56 |
57 | /*
58 | Helper functions
59 | */
60 |
61 | // ObjectsAreEqual determines if two objects are considered equal.
62 | //
63 | // This function does no assertion of any kind.
64 | func ObjectsAreEqual(expected, actual interface{}) bool {
65 | if expected == nil || actual == nil {
66 | return expected == actual
67 | }
68 |
69 | exp, ok := expected.([]byte)
70 | if !ok {
71 | return reflect.DeepEqual(expected, actual)
72 | }
73 |
74 | act, ok := actual.([]byte)
75 | if !ok {
76 | return false
77 | }
78 | if exp == nil || act == nil {
79 | return exp == nil && act == nil
80 | }
81 | return bytes.Equal(exp, act)
82 | }
83 |
84 | // copyExportedFields iterates downward through nested data structures and creates a copy
85 | // that only contains the exported struct fields.
86 | func copyExportedFields(expected interface{}) interface{} {
87 | if isNil(expected) {
88 | return expected
89 | }
90 |
91 | expectedType := reflect.TypeOf(expected)
92 | expectedKind := expectedType.Kind()
93 | expectedValue := reflect.ValueOf(expected)
94 |
95 | switch expectedKind {
96 | case reflect.Struct:
97 | result := reflect.New(expectedType).Elem()
98 | for i := 0; i < expectedType.NumField(); i++ {
99 | field := expectedType.Field(i)
100 | isExported := field.IsExported()
101 | if isExported {
102 | fieldValue := expectedValue.Field(i)
103 | if isNil(fieldValue) || isNil(fieldValue.Interface()) {
104 | continue
105 | }
106 | newValue := copyExportedFields(fieldValue.Interface())
107 | result.Field(i).Set(reflect.ValueOf(newValue))
108 | }
109 | }
110 | return result.Interface()
111 |
112 | case reflect.Ptr:
113 | result := reflect.New(expectedType.Elem())
114 | unexportedRemoved := copyExportedFields(expectedValue.Elem().Interface())
115 | result.Elem().Set(reflect.ValueOf(unexportedRemoved))
116 | return result.Interface()
117 |
118 | case reflect.Array, reflect.Slice:
119 | var result reflect.Value
120 | if expectedKind == reflect.Array {
121 | result = reflect.New(reflect.ArrayOf(expectedValue.Len(), expectedType.Elem())).Elem()
122 | } else {
123 | result = reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len())
124 | }
125 | for i := 0; i < expectedValue.Len(); i++ {
126 | index := expectedValue.Index(i)
127 | if isNil(index) {
128 | continue
129 | }
130 | unexportedRemoved := copyExportedFields(index.Interface())
131 | result.Index(i).Set(reflect.ValueOf(unexportedRemoved))
132 | }
133 | return result.Interface()
134 |
135 | case reflect.Map:
136 | result := reflect.MakeMap(expectedType)
137 | for _, k := range expectedValue.MapKeys() {
138 | index := expectedValue.MapIndex(k)
139 | unexportedRemoved := copyExportedFields(index.Interface())
140 | result.SetMapIndex(k, reflect.ValueOf(unexportedRemoved))
141 | }
142 | return result.Interface()
143 |
144 | default:
145 | return expected
146 | }
147 | }
148 |
149 | // ObjectsExportedFieldsAreEqual determines if the exported (public) fields of two objects are
150 | // considered equal. This comparison of only exported fields is applied recursively to nested data
151 | // structures.
152 | //
153 | // This function does no assertion of any kind.
154 | //
155 | // Deprecated: Use [EqualExportedValues] instead.
156 | func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool {
157 | expectedCleaned := copyExportedFields(expected)
158 | actualCleaned := copyExportedFields(actual)
159 | return ObjectsAreEqualValues(expectedCleaned, actualCleaned)
160 | }
161 |
162 | // ObjectsAreEqualValues gets whether two objects are equal, or if their
163 | // values are equal.
164 | func ObjectsAreEqualValues(expected, actual interface{}) bool {
165 | if ObjectsAreEqual(expected, actual) {
166 | return true
167 | }
168 |
169 | expectedValue := reflect.ValueOf(expected)
170 | actualValue := reflect.ValueOf(actual)
171 | if !expectedValue.IsValid() || !actualValue.IsValid() {
172 | return false
173 | }
174 |
175 | expectedType := expectedValue.Type()
176 | actualType := actualValue.Type()
177 | if !expectedType.ConvertibleTo(actualType) {
178 | return false
179 | }
180 |
181 | if !isNumericType(expectedType) || !isNumericType(actualType) {
182 | // Attempt comparison after type conversion
183 | return reflect.DeepEqual(
184 | expectedValue.Convert(actualType).Interface(), actual,
185 | )
186 | }
187 |
188 | // If BOTH values are numeric, there are chances of false positives due
189 | // to overflow or underflow. So, we need to make sure to always convert
190 | // the smaller type to a larger type before comparing.
191 | if expectedType.Size() >= actualType.Size() {
192 | return actualValue.Convert(expectedType).Interface() == expected
193 | }
194 |
195 | return expectedValue.Convert(actualType).Interface() == actual
196 | }
197 |
198 | // isNumericType returns true if the type is one of:
199 | // int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64,
200 | // float32, float64, complex64, complex128
201 | func isNumericType(t reflect.Type) bool {
202 | return t.Kind() >= reflect.Int && t.Kind() <= reflect.Complex128
203 | }
204 |
205 | /* CallerInfo is necessary because the assert functions use the testing object
206 | internally, causing it to print the file:line of the assert method, rather than where
207 | the problem actually occurred in calling code.*/
208 |
209 | // CallerInfo returns an array of strings containing the file and line number
210 | // of each stack frame leading from the current test to the assert call that
211 | // failed.
212 | func CallerInfo() []string {
213 |
214 | var pc uintptr
215 | var ok bool
216 | var file string
217 | var line int
218 | var name string
219 |
220 | callers := []string{}
221 | for i := 0; ; i++ {
222 | pc, file, line, ok = runtime.Caller(i)
223 | if !ok {
224 | // The breaks below failed to terminate the loop, and we ran off the
225 | // end of the call stack.
226 | break
227 | }
228 |
229 | // This is a huge edge case, but it will panic if this is the case, see #180
230 | if file == "" {
231 | break
232 | }
233 |
234 | f := runtime.FuncForPC(pc)
235 | if f == nil {
236 | break
237 | }
238 | name = f.Name()
239 |
240 | // testing.tRunner is the standard library function that calls
241 | // tests. Subtests are called directly by tRunner, without going through
242 | // the Test/Benchmark/Example function that contains the t.Run calls, so
243 | // with subtests we should break when we hit tRunner, without adding it
244 | // to the list of callers.
245 | if name == "testing.tRunner" {
246 | break
247 | }
248 |
249 | parts := strings.Split(file, "/")
250 | if len(parts) > 1 {
251 | filename := parts[len(parts)-1]
252 | dir := parts[len(parts)-2]
253 | if (dir != "assert" && dir != "mock" && dir != "require") || filename == "mock_test.go" {
254 | callers = append(callers, fmt.Sprintf("%s:%d", file, line))
255 | }
256 | }
257 |
258 | // Drop the package
259 | segments := strings.Split(name, ".")
260 | name = segments[len(segments)-1]
261 | if isTest(name, "Test") ||
262 | isTest(name, "Benchmark") ||
263 | isTest(name, "Example") {
264 | break
265 | }
266 | }
267 |
268 | return callers
269 | }
270 |
271 | // Stolen from the `go test` tool.
272 | // isTest tells whether name looks like a test (or benchmark, according to prefix).
273 | // It is a Test (say) if there is a character after Test that is not a lower-case letter.
274 | // We don't want TesticularCancer.
275 | func isTest(name, prefix string) bool {
276 | if !strings.HasPrefix(name, prefix) {
277 | return false
278 | }
279 | if len(name) == len(prefix) { // "Test" is ok
280 | return true
281 | }
282 | r, _ := utf8.DecodeRuneInString(name[len(prefix):])
283 | return !unicode.IsLower(r)
284 | }
285 |
286 | func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
287 | if len(msgAndArgs) == 0 || msgAndArgs == nil {
288 | return ""
289 | }
290 | if len(msgAndArgs) == 1 {
291 | msg := msgAndArgs[0]
292 | if msgAsStr, ok := msg.(string); ok {
293 | return msgAsStr
294 | }
295 | return fmt.Sprintf("%+v", msg)
296 | }
297 | if len(msgAndArgs) > 1 {
298 | return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
299 | }
300 | return ""
301 | }
302 |
303 | // Aligns the provided message so that all lines after the first line start at the same location as the first line.
304 | // Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab).
305 | // The longestLabelLen parameter specifies the length of the longest label in the output (required because this is the
306 | // basis on which the alignment occurs).
307 | func indentMessageLines(message string, longestLabelLen int) string {
308 | outBuf := new(bytes.Buffer)
309 |
310 | for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ {
311 | // no need to align first line because it starts at the correct location (after the label)
312 | if i != 0 {
313 | // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab
314 | outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t")
315 | }
316 | outBuf.WriteString(scanner.Text())
317 | }
318 |
319 | return outBuf.String()
320 | }
321 |
322 | type failNower interface {
323 | FailNow()
324 | }
325 |
326 | // FailNow fails test
327 | func FailNow(failureMessage string, msgAndArgs ...interface{}) bool {
328 | Fail(failureMessage, msgAndArgs...)
329 |
330 | // We cannot extend TestingT with FailNow() and
331 | // maintain backwards compatibility, so we fallback
332 | // to panicking when FailNow is not available in
333 | // TestingT.
334 | // See issue #263
335 |
336 | return false
337 | }
338 |
339 | // Fail reports a failure through
340 | func Fail(failureMessage string, msgAndArgs ...interface{}) bool {
341 | content := []labeledContent{
342 | {"Error Trace", strings.Join(CallerInfo(), "\n\t\t\t")},
343 | {"Error", failureMessage},
344 | }
345 |
346 | // Add test name if the Go version supports it
347 |
348 | message := messageFromMsgAndArgs(msgAndArgs...)
349 | if len(message) > 0 {
350 | content = append(content, labeledContent{"Messages", message})
351 | }
352 |
353 | panic(fmt.Errorf("\n%s", ""+labeledOutput(content...)))
354 |
355 | return false
356 | }
357 |
358 | type labeledContent struct {
359 | label string
360 | content string
361 | }
362 |
363 | // labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner:
364 | //
365 | // \t{{label}}:{{align_spaces}}\t{{content}}\n
366 | //
367 | // The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label.
368 | // If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this
369 | // alignment is achieved, "\t{{content}}\n" is added for the output.
370 | //
371 | // If the content of the labeledOutput contains line breaks, the subsequent lines are aligned so that they start at the same location as the first line.
372 | func labeledOutput(content ...labeledContent) string {
373 | longestLabel := 0
374 | for _, v := range content {
375 | if len(v.label) > longestLabel {
376 | longestLabel = len(v.label)
377 | }
378 | }
379 | var output string
380 | for _, v := range content {
381 | output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n"
382 | }
383 | return output
384 | }
385 |
386 | // Implements asserts that an object is implemented by the specified interface.
387 | //
388 | // assert.Implements((*MyInterface)(nil), new(MyObject))
389 | func Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
390 | interfaceType := reflect.TypeOf(interfaceObject).Elem()
391 |
392 | if object == nil {
393 | return Fail(fmt.Sprintf("Cannot check if nil implements %v", interfaceType), msgAndArgs...)
394 | }
395 | if !reflect.TypeOf(object).Implements(interfaceType) {
396 | return Fail(fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...)
397 | }
398 |
399 | return true
400 | }
401 |
402 | // NotImplements asserts that an object does not implement the specified interface.
403 | //
404 | // assert.NotImplements((*MyInterface)(nil), new(MyObject))
405 | func NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
406 | interfaceType := reflect.TypeOf(interfaceObject).Elem()
407 |
408 | if object == nil {
409 | return Fail(fmt.Sprintf("Cannot check if nil does not implement %v", interfaceType), msgAndArgs...)
410 | }
411 | if reflect.TypeOf(object).Implements(interfaceType) {
412 | return Fail(fmt.Sprintf("%T implements %v", object, interfaceType), msgAndArgs...)
413 | }
414 |
415 | return true
416 | }
417 |
418 | // IsType asserts that the specified objects are of the same type.
419 | func IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
420 |
421 | if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) {
422 | return Fail(fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...)
423 | }
424 |
425 | return true
426 | }
427 |
428 | // Equal asserts that two objects are equal.
429 | //
430 | // assert.Equal(123, 123)
431 | //
432 | // Pointer variable equality is determined based on the equality of the
433 | // referenced values (as opposed to the memory addresses). Function equality
434 | // cannot be determined and will always fail.
435 | func Equal(expected, actual interface{}, msgAndArgs ...interface{}) bool {
436 | if err := validateEqualArgs(expected, actual); err != nil {
437 | return Fail(fmt.Sprintf("Invalid operation: %#v == %#v (%s)",
438 | expected, actual, err), msgAndArgs...)
439 | }
440 |
441 | if !ObjectsAreEqual(expected, actual) {
442 | diff := diff(expected, actual)
443 | expected, actual = formatUnequalValues(expected, actual)
444 | return Fail(fmt.Sprintf("Not equal: \n"+
445 | "expected: %s\n"+
446 | "actual : %s%s", expected, actual, diff), msgAndArgs...)
447 | }
448 |
449 | return true
450 |
451 | }
452 |
453 | // validateEqualArgs checks whether provided arguments can be safely used in the
454 | // Equal/NotEqual functions.
455 | func validateEqualArgs(expected, actual interface{}) error {
456 | if expected == nil && actual == nil {
457 | return nil
458 | }
459 |
460 | if isFunction(expected) || isFunction(actual) {
461 | return errors.New("cannot take func type as argument")
462 | }
463 | return nil
464 | }
465 |
466 | // Same asserts that two pointers reference the same object.
467 | //
468 | // assert.Same(ptr1, ptr2)
469 | //
470 | // Both arguments must be pointer variables. Pointer variable sameness is
471 | // determined based on the equality of both type and value.
472 | func Same(expected, actual interface{}, msgAndArgs ...interface{}) bool {
473 |
474 | same, ok := samePointers(expected, actual)
475 | if !ok {
476 | return Fail("Both arguments must be pointers", msgAndArgs...)
477 | }
478 |
479 | if !same {
480 | // both are pointers but not the same type & pointing to the same address
481 | return Fail(fmt.Sprintf("Not same: \n"+
482 | "expected: %p %#v\n"+
483 | "actual : %p %#v", expected, expected, actual, actual), msgAndArgs...)
484 | }
485 |
486 | return true
487 | }
488 |
489 | // NotSame asserts that two pointers do not reference the same object.
490 | //
491 | // assert.NotSame(ptr1, ptr2)
492 | //
493 | // Both arguments must be pointer variables. Pointer variable sameness is
494 | // determined based on the equality of both type and value.
495 | func NotSame(expected, actual interface{}, msgAndArgs ...interface{}) bool {
496 |
497 | same, ok := samePointers(expected, actual)
498 | if !ok {
499 | //fails when the arguments are not pointers
500 | return !(Fail("Both arguments must be pointers", msgAndArgs...))
501 | }
502 |
503 | if same {
504 | return Fail(fmt.Sprintf(
505 | "Expected and actual point to the same object: %p %#v",
506 | expected, expected), msgAndArgs...)
507 | }
508 | return true
509 | }
510 |
511 | // samePointers checks if two generic interface objects are pointers of the same
512 | // type pointing to the same object. It returns two values: same indicating if
513 | // they are the same type and point to the same object, and ok indicating that
514 | // both inputs are pointers.
515 | func samePointers(first, second interface{}) (same bool, ok bool) {
516 | firstPtr, secondPtr := reflect.ValueOf(first), reflect.ValueOf(second)
517 | if firstPtr.Kind() != reflect.Ptr || secondPtr.Kind() != reflect.Ptr {
518 | return false, false //not both are pointers
519 | }
520 |
521 | firstType, secondType := reflect.TypeOf(first), reflect.TypeOf(second)
522 | if firstType != secondType {
523 | return false, true // both are pointers, but of different types
524 | }
525 |
526 | // compare pointer addresses
527 | return first == second, true
528 | }
529 |
530 | // formatUnequalValues takes two values of arbitrary types and returns string
531 | // representations appropriate to be presented to the user.
532 | //
533 | // If the values are not of like type, the returned strings will be prefixed
534 | // with the type name, and the value will be enclosed in parentheses similar
535 | // to a type conversion in the Go grammar.
536 | func formatUnequalValues(expected, actual interface{}) (e string, a string) {
537 | if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
538 | return fmt.Sprintf("%T(%s)", expected, truncatingFormat(expected)),
539 | fmt.Sprintf("%T(%s)", actual, truncatingFormat(actual))
540 | }
541 | switch expected.(type) {
542 | case time.Duration:
543 | return fmt.Sprintf("%v", expected), fmt.Sprintf("%v", actual)
544 | }
545 | return truncatingFormat(expected), truncatingFormat(actual)
546 | }
547 |
548 | // truncatingFormat formats the data and truncates it if it's too long.
549 | //
550 | // This helps keep formatted error messages lines from exceeding the
551 | // bufio.MaxScanTokenSize max line length that the go testing framework imposes.
552 | func truncatingFormat(data interface{}) string {
553 | value := fmt.Sprintf("%#v", data)
554 | max := bufio.MaxScanTokenSize - 100 // Give us some space the type info too if needed.
555 | if len(value) > max {
556 | value = value[0:max] + "<... truncated>"
557 | }
558 | return value
559 | }
560 |
561 | // EqualValues asserts that two objects are equal or convertible to the larger
562 | // type and equal.
563 | //
564 | // assert.EqualValues(uint32(123), int32(123))
565 | func EqualValues(expected, actual interface{}, msgAndArgs ...interface{}) bool {
566 |
567 | if !ObjectsAreEqualValues(expected, actual) {
568 | diff := diff(expected, actual)
569 | expected, actual = formatUnequalValues(expected, actual)
570 | return Fail(fmt.Sprintf("Not equal: \n"+
571 | "expected: %s\n"+
572 | "actual : %s%s", expected, actual, diff), msgAndArgs...)
573 | }
574 |
575 | return true
576 |
577 | }
578 |
579 | // EqualExportedValues asserts that the types of two objects are equal and their public
580 | // fields are also equal. This is useful for comparing structs that have private fields
581 | // that could potentially differ.
582 | //
583 | // type S struct {
584 | // Exported int
585 | // notExported int
586 | // }
587 | // assert.EqualExportedValues(S{1, 2}, S{1, 3}) => true
588 | // assert.EqualExportedValues(S{1, 2}, S{2, 3}) => false
589 | func EqualExportedValues(expected, actual interface{}, msgAndArgs ...interface{}) bool {
590 |
591 | aType := reflect.TypeOf(expected)
592 | bType := reflect.TypeOf(actual)
593 |
594 | if aType != bType {
595 | return Fail(fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...)
596 | }
597 |
598 | expected = copyExportedFields(expected)
599 | actual = copyExportedFields(actual)
600 |
601 | if !ObjectsAreEqualValues(expected, actual) {
602 | diff := diff(expected, actual)
603 | expected, actual = formatUnequalValues(expected, actual)
604 | return Fail(fmt.Sprintf("Not equal (comparing only exported fields): \n"+
605 | "expected: %s\n"+
606 | "actual : %s%s", expected, actual, diff), msgAndArgs...)
607 | }
608 |
609 | return true
610 | }
611 |
612 | // Exactly asserts that two objects are equal in value and type.
613 | //
614 | // assert.Exactly(int32(123), int64(123))
615 | func Exactly(expected, actual interface{}, msgAndArgs ...interface{}) bool {
616 |
617 | aType := reflect.TypeOf(expected)
618 | bType := reflect.TypeOf(actual)
619 |
620 | if aType != bType {
621 | return Fail(fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...)
622 | }
623 |
624 | return Equal(expected, actual, msgAndArgs...)
625 |
626 | }
627 |
628 | // NotNil asserts that the specified object is not nil.
629 | //
630 | // assert.NotNil(err)
631 | func NotNil(object interface{}, msgAndArgs ...interface{}) bool {
632 | if !isNil(object) {
633 | return true
634 | }
635 | return Fail("Expected value not to be nil.", msgAndArgs...)
636 | }
637 |
638 | // isNil checks if a specified object is nil or not, without Failing.
639 | func isNil(object interface{}) bool {
640 | if object == nil {
641 | return true
642 | }
643 |
644 | value := reflect.ValueOf(object)
645 | switch value.Kind() {
646 | case
647 | reflect.Chan, reflect.Func,
648 | reflect.Interface, reflect.Map,
649 | reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
650 |
651 | return value.IsNil()
652 | }
653 |
654 | return false
655 | }
656 |
657 | // Nil asserts that the specified object is nil.
658 | //
659 | // assert.Nil(err)
660 | func Nil(object interface{}, msgAndArgs ...interface{}) bool {
661 | if isNil(object) {
662 | return true
663 | }
664 | return Fail(fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
665 | }
666 |
667 | // isEmpty gets whether the specified object is considered empty or not.
668 | func isEmpty(object interface{}) bool {
669 |
670 | // get nil case out of the way
671 | if object == nil {
672 | return true
673 | }
674 |
675 | objValue := reflect.ValueOf(object)
676 |
677 | switch objValue.Kind() {
678 | // collection types are empty when they have no element
679 | case reflect.Chan, reflect.Map, reflect.Slice:
680 | return objValue.Len() == 0
681 | // pointers are empty if nil or if the value they point to is empty
682 | case reflect.Ptr:
683 | if objValue.IsNil() {
684 | return true
685 | }
686 | deref := objValue.Elem().Interface()
687 | return isEmpty(deref)
688 | // for all other types, compare against the zero value
689 | // array types are empty when they match their zero-initialized state
690 | default:
691 | zero := reflect.Zero(objValue.Type())
692 | return reflect.DeepEqual(object, zero.Interface())
693 | }
694 | }
695 |
696 | // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
697 | // a slice or a channel with len == 0.
698 | //
699 | // assert.Empty(obj)
700 | func Empty(object interface{}, msgAndArgs ...interface{}) bool {
701 | pass := isEmpty(object)
702 | if !pass {
703 | Fail(fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...)
704 | }
705 |
706 | return pass
707 |
708 | }
709 |
710 | // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
711 | // a slice or a channel with len == 0.
712 | //
713 | // if assert.NotEmpty(obj) {
714 | // assert.Equal("two", obj[1])
715 | // }
716 | func NotEmpty(object interface{}, msgAndArgs ...interface{}) bool {
717 | pass := !isEmpty(object)
718 | if !pass {
719 | Fail(fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...)
720 | }
721 |
722 | return pass
723 |
724 | }
725 |
726 | // getLen tries to get the length of an object.
727 | // It returns (0, false) if impossible.
728 | func getLen(x interface{}) (length int, ok bool) {
729 | v := reflect.ValueOf(x)
730 | defer func() {
731 | ok = recover() == nil
732 | }()
733 | return v.Len(), true
734 | }
735 |
736 | // Len asserts that the specified object has specific length.
737 | // Len also fails if the object has a type that len() not accept.
738 | //
739 | // assert.Len(mySlice, 3)
740 | func Len(object interface{}, length int, msgAndArgs ...interface{}) bool {
741 | l, ok := getLen(object)
742 | if !ok {
743 | return Fail(fmt.Sprintf("\"%v\" could not be applied builtin len()", object), msgAndArgs...)
744 | }
745 |
746 | if l != length {
747 | return Fail(fmt.Sprintf("\"%v\" should have %d item(s), but has %d", object, length, l), msgAndArgs...)
748 | }
749 | return true
750 | }
751 |
752 | // True asserts that the specified value is true.
753 | //
754 | // assert.True(myBool)
755 | func True(value bool, msgAndArgs ...interface{}) bool {
756 | if !value {
757 | return Fail("Should be true", msgAndArgs...)
758 | }
759 |
760 | return true
761 |
762 | }
763 |
764 | // False asserts that the specified value is false.
765 | //
766 | // assert.False(myBool)
767 | func False(value bool, msgAndArgs ...interface{}) bool {
768 | if value {
769 | return Fail("Should be false", msgAndArgs...)
770 | }
771 |
772 | return true
773 |
774 | }
775 |
776 | // NotEqual asserts that the specified values are NOT equal.
777 | //
778 | // assert.NotEqual(obj1, obj2)
779 | //
780 | // Pointer variable equality is determined based on the equality of the
781 | // referenced values (as opposed to the memory addresses).
782 | func NotEqual(expected, actual interface{}, msgAndArgs ...interface{}) bool {
783 | if err := validateEqualArgs(expected, actual); err != nil {
784 | return Fail(fmt.Sprintf("Invalid operation: %#v != %#v (%s)",
785 | expected, actual, err), msgAndArgs...)
786 | }
787 |
788 | if ObjectsAreEqual(expected, actual) {
789 | return Fail(fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
790 | }
791 |
792 | return true
793 |
794 | }
795 |
796 | // NotEqualValues asserts that two objects are not equal even when converted to the same type
797 | //
798 | // assert.NotEqualValues(obj1, obj2)
799 | func NotEqualValues(expected, actual interface{}, msgAndArgs ...interface{}) bool {
800 |
801 | if ObjectsAreEqualValues(expected, actual) {
802 | return Fail(fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
803 | }
804 |
805 | return true
806 | }
807 |
808 | // containsElement try loop over the list check if the list includes the element.
809 | // return (false, false) if impossible.
810 | // return (true, false) if element was not found.
811 | // return (true, true) if element was found.
812 | func containsElement(list interface{}, element interface{}) (ok, found bool) {
813 |
814 | listValue := reflect.ValueOf(list)
815 | listType := reflect.TypeOf(list)
816 | if listType == nil {
817 | return false, false
818 | }
819 | listKind := listType.Kind()
820 | defer func() {
821 | if e := recover(); e != nil {
822 | ok = false
823 | found = false
824 | }
825 | }()
826 |
827 | if listKind == reflect.String {
828 | elementValue := reflect.ValueOf(element)
829 | return true, strings.Contains(listValue.String(), elementValue.String())
830 | }
831 |
832 | if listKind == reflect.Map {
833 | mapKeys := listValue.MapKeys()
834 | for i := 0; i < len(mapKeys); i++ {
835 | if ObjectsAreEqual(mapKeys[i].Interface(), element) {
836 | return true, true
837 | }
838 | }
839 | return true, false
840 | }
841 |
842 | for i := 0; i < listValue.Len(); i++ {
843 | if ObjectsAreEqual(listValue.Index(i).Interface(), element) {
844 | return true, true
845 | }
846 | }
847 | return true, false
848 |
849 | }
850 |
851 | // Contains asserts that the specified string, list(array, slice...) or map contains the
852 | // specified substring or element.
853 | //
854 | // assert.Contains("Hello World", "World")
855 | // assert.Contains(["Hello", "World"], "World")
856 | // assert.Contains({"Hello": "World"}, "Hello")
857 | func Contains(s, contains interface{}, msgAndArgs ...interface{}) bool {
858 |
859 | ok, found := containsElement(s, contains)
860 | if !ok {
861 | return Fail(fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...)
862 | }
863 | if !found {
864 | return Fail(fmt.Sprintf("%#v does not contain %#v", s, contains), msgAndArgs...)
865 | }
866 |
867 | return true
868 |
869 | }
870 |
871 | // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
872 | // specified substring or element.
873 | //
874 | // assert.NotContains("Hello World", "Earth")
875 | // assert.NotContains(["Hello", "World"], "Earth")
876 | // assert.NotContains({"Hello": "World"}, "Earth")
877 | func NotContains(s, contains interface{}, msgAndArgs ...interface{}) bool {
878 |
879 | ok, found := containsElement(s, contains)
880 | if !ok {
881 | return Fail(fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...)
882 | }
883 | if found {
884 | return Fail(fmt.Sprintf("%#v should not contain %#v", s, contains), msgAndArgs...)
885 | }
886 |
887 | return true
888 |
889 | }
890 |
891 | // Subset asserts that the specified list(array, slice...) or map contains all
892 | // elements given in the specified subset list(array, slice...) or map.
893 | //
894 | // assert.Subset([1, 2, 3], [1, 2])
895 | // assert.Subset({"x": 1, "y": 2}, {"x": 1})
896 | func Subset(list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
897 | if subset == nil {
898 | return true // we consider nil to be equal to the nil set
899 | }
900 |
901 | listKind := reflect.TypeOf(list).Kind()
902 | if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map {
903 | return Fail(fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
904 | }
905 |
906 | subsetKind := reflect.TypeOf(subset).Kind()
907 | if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map {
908 | return Fail(fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
909 | }
910 |
911 | if subsetKind == reflect.Map && listKind == reflect.Map {
912 | subsetMap := reflect.ValueOf(subset)
913 | actualMap := reflect.ValueOf(list)
914 |
915 | for _, k := range subsetMap.MapKeys() {
916 | ev := subsetMap.MapIndex(k)
917 | av := actualMap.MapIndex(k)
918 |
919 | if !av.IsValid() {
920 | return Fail(fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...)
921 | }
922 | if !ObjectsAreEqual(ev.Interface(), av.Interface()) {
923 | return Fail(fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...)
924 | }
925 | }
926 |
927 | return true
928 | }
929 |
930 | subsetList := reflect.ValueOf(subset)
931 | for i := 0; i < subsetList.Len(); i++ {
932 | element := subsetList.Index(i).Interface()
933 | ok, found := containsElement(list, element)
934 | if !ok {
935 | return Fail(fmt.Sprintf("%#v could not be applied builtin len()", list), msgAndArgs...)
936 | }
937 | if !found {
938 | return Fail(fmt.Sprintf("%#v does not contain %#v", list, element), msgAndArgs...)
939 | }
940 | }
941 |
942 | return true
943 | }
944 |
945 | // NotSubset asserts that the specified list(array, slice...) or map does NOT
946 | // contain all elements given in the specified subset list(array, slice...) or
947 | // map.
948 | //
949 | // assert.NotSubset([1, 3, 4], [1, 2])
950 | // assert.NotSubset({"x": 1, "y": 2}, {"z": 3})
951 | func NotSubset(list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
952 | if subset == nil {
953 | return Fail("nil is the empty set which is a subset of every set", msgAndArgs...)
954 | }
955 |
956 | listKind := reflect.TypeOf(list).Kind()
957 | if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map {
958 | return Fail(fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
959 | }
960 |
961 | subsetKind := reflect.TypeOf(subset).Kind()
962 | if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map {
963 | return Fail(fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
964 | }
965 |
966 | if subsetKind == reflect.Map && listKind == reflect.Map {
967 | subsetMap := reflect.ValueOf(subset)
968 | actualMap := reflect.ValueOf(list)
969 |
970 | for _, k := range subsetMap.MapKeys() {
971 | ev := subsetMap.MapIndex(k)
972 | av := actualMap.MapIndex(k)
973 |
974 | if !av.IsValid() {
975 | return true
976 | }
977 | if !ObjectsAreEqual(ev.Interface(), av.Interface()) {
978 | return true
979 | }
980 | }
981 |
982 | return Fail(fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
983 | }
984 |
985 | subsetList := reflect.ValueOf(subset)
986 | for i := 0; i < subsetList.Len(); i++ {
987 | element := subsetList.Index(i).Interface()
988 | ok, found := containsElement(list, element)
989 | if !ok {
990 | return Fail(fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)
991 | }
992 | if !found {
993 | return true
994 | }
995 | }
996 |
997 | return Fail(fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
998 | }
999 |
1000 | // ElementsMatch asserts that the specified listA(array, slice...) is equal to specified
1001 | // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
1002 | // the number of appearances of each of them in both lists should match.
1003 | //
1004 | // assert.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2])
1005 | func ElementsMatch(listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) {
1006 | if isEmpty(listA) && isEmpty(listB) {
1007 | return true
1008 | }
1009 |
1010 | if !isList(listA, msgAndArgs...) || !isList(listB, msgAndArgs...) {
1011 | return false
1012 | }
1013 |
1014 | extraA, extraB := diffLists(listA, listB)
1015 |
1016 | if len(extraA) == 0 && len(extraB) == 0 {
1017 | return true
1018 | }
1019 |
1020 | return Fail(formatListDiff(listA, listB, extraA, extraB), msgAndArgs...)
1021 | }
1022 |
1023 | // isList checks that the provided value is array or slice.
1024 | func isList(list interface{}, msgAndArgs ...interface{}) (ok bool) {
1025 | kind := reflect.TypeOf(list).Kind()
1026 | if kind != reflect.Array && kind != reflect.Slice {
1027 | return Fail(fmt.Sprintf("%q has an unsupported type %s, expecting array or slice", list, kind),
1028 | msgAndArgs...)
1029 | }
1030 | return true
1031 | }
1032 |
1033 | // diffLists diffs two arrays/slices and returns slices of elements that are only in A and only in B.
1034 | // If some element is present multiple times, each instance is counted separately (e.g. if something is 2x in A and
1035 | // 5x in B, it will be 0x in extraA and 3x in extraB). The order of items in both lists is ignored.
1036 | func diffLists(listA, listB interface{}) (extraA, extraB []interface{}) {
1037 | aValue := reflect.ValueOf(listA)
1038 | bValue := reflect.ValueOf(listB)
1039 |
1040 | aLen := aValue.Len()
1041 | bLen := bValue.Len()
1042 |
1043 | // Mark indexes in bValue that we already used
1044 | visited := make([]bool, bLen)
1045 | for i := 0; i < aLen; i++ {
1046 | element := aValue.Index(i).Interface()
1047 | found := false
1048 | for j := 0; j < bLen; j++ {
1049 | if visited[j] {
1050 | continue
1051 | }
1052 | if ObjectsAreEqual(bValue.Index(j).Interface(), element) {
1053 | visited[j] = true
1054 | found = true
1055 | break
1056 | }
1057 | }
1058 | if !found {
1059 | extraA = append(extraA, element)
1060 | }
1061 | }
1062 |
1063 | for j := 0; j < bLen; j++ {
1064 | if visited[j] {
1065 | continue
1066 | }
1067 | extraB = append(extraB, bValue.Index(j).Interface())
1068 | }
1069 |
1070 | return
1071 | }
1072 |
1073 | func formatListDiff(listA, listB interface{}, extraA, extraB []interface{}) string {
1074 | var msg bytes.Buffer
1075 |
1076 | msg.WriteString("elements differ")
1077 | if len(extraA) > 0 {
1078 | msg.WriteString("\n\nextra elements in list A:\n")
1079 | msg.WriteString(spewConfig.Sdump(extraA))
1080 | }
1081 | if len(extraB) > 0 {
1082 | msg.WriteString("\n\nextra elements in list B:\n")
1083 | msg.WriteString(spewConfig.Sdump(extraB))
1084 | }
1085 | msg.WriteString("\n\nlistA:\n")
1086 | msg.WriteString(spewConfig.Sdump(listA))
1087 | msg.WriteString("\n\nlistB:\n")
1088 | msg.WriteString(spewConfig.Sdump(listB))
1089 |
1090 | return msg.String()
1091 | }
1092 |
1093 | // NotElementsMatch asserts that the specified listA(array, slice...) is NOT equal to specified
1094 | // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
1095 | // the number of appearances of each of them in both lists should not match.
1096 | // This is an inverse of ElementsMatch.
1097 | //
1098 | // assert.NotElementsMatch([1, 1, 2, 3], [1, 1, 2, 3]) -> false
1099 | //
1100 | // assert.NotElementsMatch([1, 1, 2, 3], [1, 2, 3]) -> true
1101 | //
1102 | // assert.NotElementsMatch([1, 2, 3], [1, 2, 4]) -> true
1103 | func NotElementsMatch(listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) {
1104 | if isEmpty(listA) && isEmpty(listB) {
1105 | return Fail("listA and listB contain the same elements", msgAndArgs)
1106 | }
1107 |
1108 | if !isList(listA, msgAndArgs...) {
1109 | return Fail("listA is not a list type", msgAndArgs...)
1110 | }
1111 | if !isList(listB, msgAndArgs...) {
1112 | return Fail("listB is not a list type", msgAndArgs...)
1113 | }
1114 |
1115 | extraA, extraB := diffLists(listA, listB)
1116 | if len(extraA) == 0 && len(extraB) == 0 {
1117 | return Fail("listA and listB contain the same elements", msgAndArgs)
1118 | }
1119 |
1120 | return true
1121 | }
1122 |
1123 | // Condition uses a Comparison to assert a complex condition.
1124 | func Condition(comp Comparison, msgAndArgs ...interface{}) bool {
1125 | result := comp()
1126 | if !result {
1127 | Fail("Condition failed!", msgAndArgs...)
1128 | }
1129 | return result
1130 | }
1131 |
1132 | // PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics
1133 | // methods, and represents a simple func that takes no arguments, and returns nothing.
1134 | type PanicTestFunc func()
1135 |
1136 | // didPanic returns true if the function passed to it panics. Otherwise, it returns false.
1137 | func didPanic(f PanicTestFunc) (didPanic bool, message interface{}, stack string) {
1138 | didPanic = true
1139 |
1140 | defer func() {
1141 | message = recover()
1142 | if didPanic {
1143 | stack = string(debug.Stack())
1144 | }
1145 | }()
1146 |
1147 | // call the target function
1148 | f()
1149 | didPanic = false
1150 |
1151 | return
1152 | }
1153 |
1154 | // Panics asserts that the code inside the specified PanicTestFunc panics.
1155 | //
1156 | // assert.Panics(func(){ GoCrazy() })
1157 | func Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
1158 |
1159 | if funcDidPanic, panicValue, _ := didPanic(f); !funcDidPanic {
1160 | return Fail(fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
1161 | }
1162 |
1163 | return true
1164 | }
1165 |
1166 | // PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
1167 | // the recovered panic value equals the expected panic value.
1168 | //
1169 | // assert.PanicsWithValue("crazy error", func(){ GoCrazy() })
1170 | func PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool {
1171 |
1172 | funcDidPanic, panicValue, panickedStack := didPanic(f)
1173 | if !funcDidPanic {
1174 | return Fail(fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
1175 | }
1176 | if panicValue != expected {
1177 | return Fail(fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, expected, panicValue, panickedStack), msgAndArgs...)
1178 | }
1179 |
1180 | return true
1181 | }
1182 |
1183 | // PanicsWithError asserts that the code inside the specified PanicTestFunc
1184 | // panics, and that the recovered panic value is an error that satisfies the
1185 | // EqualError comparison.
1186 | //
1187 | // assert.PanicsWithError("crazy error", func(){ GoCrazy() })
1188 | func PanicsWithError(errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool {
1189 |
1190 | funcDidPanic, panicValue, panickedStack := didPanic(f)
1191 | if !funcDidPanic {
1192 | return Fail(fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
1193 | }
1194 | panicErr, ok := panicValue.(error)
1195 | if !ok || panicErr.Error() != errString {
1196 | return Fail(fmt.Sprintf("func %#v should panic with error message:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, errString, panicValue, panickedStack), msgAndArgs...)
1197 | }
1198 |
1199 | return true
1200 | }
1201 |
1202 | // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
1203 | //
1204 | // assert.NotPanics(func(){ RemainCalm() })
1205 | func NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
1206 |
1207 | if funcDidPanic, panicValue, panickedStack := didPanic(f); funcDidPanic {
1208 | return Fail(fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v\n\tPanic stack:\t%s", f, panicValue, panickedStack), msgAndArgs...)
1209 | }
1210 |
1211 | return true
1212 | }
1213 |
1214 | // WithinDuration asserts that the two times are within duration delta of each other.
1215 | //
1216 | // assert.WithinDuration(time.Now(), time.Now(), 10*time.Second)
1217 | func WithinDuration(expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
1218 |
1219 | dt := expected.Sub(actual)
1220 | if dt < -delta || dt > delta {
1221 | return Fail(fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
1222 | }
1223 |
1224 | return true
1225 | }
1226 |
1227 | // WithinRange asserts that a time is within a time range (inclusive).
1228 | //
1229 | // assert.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second))
1230 | func WithinRange(actual, start, end time.Time, msgAndArgs ...interface{}) bool {
1231 |
1232 | if end.Before(start) {
1233 | return Fail("Start should be before end", msgAndArgs...)
1234 | }
1235 |
1236 | if actual.Before(start) {
1237 | return Fail(fmt.Sprintf("Time %v expected to be in time range %v to %v, but is before the range", actual, start, end), msgAndArgs...)
1238 | } else if actual.After(end) {
1239 | return Fail(fmt.Sprintf("Time %v expected to be in time range %v to %v, but is after the range", actual, start, end), msgAndArgs...)
1240 | }
1241 |
1242 | return true
1243 | }
1244 |
1245 | func toFloat(x interface{}) (float64, bool) {
1246 | var xf float64
1247 | xok := true
1248 |
1249 | switch xn := x.(type) {
1250 | case uint:
1251 | xf = float64(xn)
1252 | case uint8:
1253 | xf = float64(xn)
1254 | case uint16:
1255 | xf = float64(xn)
1256 | case uint32:
1257 | xf = float64(xn)
1258 | case uint64:
1259 | xf = float64(xn)
1260 | case int:
1261 | xf = float64(xn)
1262 | case int8:
1263 | xf = float64(xn)
1264 | case int16:
1265 | xf = float64(xn)
1266 | case int32:
1267 | xf = float64(xn)
1268 | case int64:
1269 | xf = float64(xn)
1270 | case float32:
1271 | xf = float64(xn)
1272 | case float64:
1273 | xf = xn
1274 | case time.Duration:
1275 | xf = float64(xn)
1276 | default:
1277 | xok = false
1278 | }
1279 |
1280 | return xf, xok
1281 | }
1282 |
1283 | // InDelta asserts that the two numerals are within delta of each other.
1284 | //
1285 | // assert.InDelta(math.Pi, 22/7.0, 0.01)
1286 | func InDelta(expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
1287 |
1288 | af, aok := toFloat(expected)
1289 | bf, bok := toFloat(actual)
1290 |
1291 | if !aok || !bok {
1292 | return Fail("Parameters must be numerical", msgAndArgs...)
1293 | }
1294 |
1295 | if math.IsNaN(af) && math.IsNaN(bf) {
1296 | return true
1297 | }
1298 |
1299 | if math.IsNaN(af) {
1300 | return Fail("Expected must not be NaN", msgAndArgs...)
1301 | }
1302 |
1303 | if math.IsNaN(bf) {
1304 | return Fail(fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...)
1305 | }
1306 |
1307 | dt := af - bf
1308 | if dt < -delta || dt > delta {
1309 | return Fail(fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
1310 | }
1311 |
1312 | return true
1313 | }
1314 |
1315 | // InDeltaSlice is the same as InDelta, except it compares two slices.
1316 | func InDeltaSlice(expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
1317 | if expected == nil || actual == nil ||
1318 | reflect.TypeOf(actual).Kind() != reflect.Slice ||
1319 | reflect.TypeOf(expected).Kind() != reflect.Slice {
1320 | return Fail("Parameters must be slice", msgAndArgs...)
1321 | }
1322 |
1323 | actualSlice := reflect.ValueOf(actual)
1324 | expectedSlice := reflect.ValueOf(expected)
1325 |
1326 | for i := 0; i < actualSlice.Len(); i++ {
1327 | result := InDelta(actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta, msgAndArgs...)
1328 | if !result {
1329 | return result
1330 | }
1331 | }
1332 |
1333 | return true
1334 | }
1335 |
1336 | // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
1337 | func InDeltaMapValues(expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
1338 | if expected == nil || actual == nil ||
1339 | reflect.TypeOf(actual).Kind() != reflect.Map ||
1340 | reflect.TypeOf(expected).Kind() != reflect.Map {
1341 | return Fail("Arguments must be maps", msgAndArgs...)
1342 | }
1343 |
1344 | expectedMap := reflect.ValueOf(expected)
1345 | actualMap := reflect.ValueOf(actual)
1346 |
1347 | if expectedMap.Len() != actualMap.Len() {
1348 | return Fail("Arguments must have the same number of keys", msgAndArgs...)
1349 | }
1350 |
1351 | for _, k := range expectedMap.MapKeys() {
1352 | ev := expectedMap.MapIndex(k)
1353 | av := actualMap.MapIndex(k)
1354 |
1355 | if !ev.IsValid() {
1356 | return Fail(fmt.Sprintf("missing key %q in expected map", k), msgAndArgs...)
1357 | }
1358 |
1359 | if !av.IsValid() {
1360 | return Fail(fmt.Sprintf("missing key %q in actual map", k), msgAndArgs...)
1361 | }
1362 |
1363 | if !InDelta(
1364 |
1365 | ev.Interface(),
1366 | av.Interface(),
1367 | delta,
1368 | msgAndArgs...,
1369 | ) {
1370 | return false
1371 | }
1372 | }
1373 |
1374 | return true
1375 | }
1376 |
1377 | func calcRelativeError(expected, actual interface{}) (float64, error) {
1378 | af, aok := toFloat(expected)
1379 | bf, bok := toFloat(actual)
1380 | if !aok || !bok {
1381 | return 0, fmt.Errorf("Parameters must be numerical")
1382 | }
1383 | if math.IsNaN(af) && math.IsNaN(bf) {
1384 | return 0, nil
1385 | }
1386 | if math.IsNaN(af) {
1387 | return 0, errors.New("expected value must not be NaN")
1388 | }
1389 | if af == 0 {
1390 | return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error")
1391 | }
1392 | if math.IsNaN(bf) {
1393 | return 0, errors.New("actual value must not be NaN")
1394 | }
1395 |
1396 | return math.Abs(af-bf) / math.Abs(af), nil
1397 | }
1398 |
1399 | // InEpsilon asserts that expected and actual have a relative error less than epsilon
1400 | func InEpsilon(expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
1401 | if math.IsNaN(epsilon) {
1402 | return Fail("epsilon must not be NaN", msgAndArgs...)
1403 | }
1404 | actualEpsilon, err := calcRelativeError(expected, actual)
1405 | if err != nil {
1406 | return Fail(err.Error(), msgAndArgs...)
1407 | }
1408 | if math.IsNaN(actualEpsilon) {
1409 | return Fail("relative error is NaN", msgAndArgs...)
1410 | }
1411 | if actualEpsilon > epsilon {
1412 | return Fail(fmt.Sprintf("Relative error is too high: %#v (expected)\n"+
1413 | " < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...)
1414 | }
1415 |
1416 | return true
1417 | }
1418 |
1419 | // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
1420 | func InEpsilonSlice(expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
1421 |
1422 | if expected == nil || actual == nil {
1423 | return Fail("Parameters must be slice", msgAndArgs...)
1424 | }
1425 |
1426 | expectedSlice := reflect.ValueOf(expected)
1427 | actualSlice := reflect.ValueOf(actual)
1428 |
1429 | if expectedSlice.Type().Kind() != reflect.Slice {
1430 | return Fail("Expected value must be slice", msgAndArgs...)
1431 | }
1432 |
1433 | expectedLen := expectedSlice.Len()
1434 | if !IsType(expected, actual) || !Len(actual, expectedLen) {
1435 | return false
1436 | }
1437 |
1438 | for i := 0; i < expectedLen; i++ {
1439 | if !InEpsilon(expectedSlice.Index(i).Interface(), actualSlice.Index(i).Interface(), epsilon, "at index %d", i) {
1440 | return false
1441 | }
1442 | }
1443 |
1444 | return true
1445 | }
1446 |
1447 | /*
1448 | Errors
1449 | */
1450 |
1451 | // NoError asserts that a function returned no error (i.e. `nil`).
1452 | //
1453 | // actualObj, err := SomeFunction()
1454 | // if assert.NoError(err) {
1455 | // assert.Equal(expectedObj, actualObj)
1456 | // }
1457 | func NoError(err error, msgAndArgs ...interface{}) bool {
1458 | if err != nil {
1459 | return Fail(fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...)
1460 | }
1461 |
1462 | return true
1463 | }
1464 |
1465 | // Error asserts that a function returned an error (i.e. not `nil`).
1466 | //
1467 | // actualObj, err := SomeFunction()
1468 | // if assert.Error(err) {
1469 | // assert.Equal(expectedError, err)
1470 | // }
1471 | func Error(err error, msgAndArgs ...interface{}) bool {
1472 | if err == nil {
1473 | return Fail("An error is expected but got nil.", msgAndArgs...)
1474 | }
1475 |
1476 | return true
1477 | }
1478 |
1479 | // EqualError asserts that a function returned an error (i.e. not `nil`)
1480 | // and that it is equal to the provided error.
1481 | //
1482 | // actualObj, err := SomeFunction()
1483 | // assert.EqualError(err, expectedErrorString)
1484 | func EqualError(theError error, errString string, msgAndArgs ...interface{}) bool {
1485 | if !Error(theError, msgAndArgs...) {
1486 | return false
1487 | }
1488 | expected := errString
1489 | actual := theError.Error()
1490 | // don't need to use deep equals here, we know they are both strings
1491 | if expected != actual {
1492 | return Fail(fmt.Sprintf("Error message not equal:\n"+
1493 | "expected: %q\n"+
1494 | "actual : %q", expected, actual), msgAndArgs...)
1495 | }
1496 | return true
1497 | }
1498 |
1499 | // ErrorContains asserts that a function returned an error (i.e. not `nil`)
1500 | // and that the error contains the specified substring.
1501 | //
1502 | // actualObj, err := SomeFunction()
1503 | // assert.ErrorContains(err, expectedErrorSubString)
1504 | func ErrorContains(theError error, contains string, msgAndArgs ...interface{}) bool {
1505 | if !Error(theError, msgAndArgs...) {
1506 | return false
1507 | }
1508 |
1509 | actual := theError.Error()
1510 | if !strings.Contains(actual, contains) {
1511 | return Fail(fmt.Sprintf("Error %#v does not contain %#v", actual, contains), msgAndArgs...)
1512 | }
1513 |
1514 | return true
1515 | }
1516 |
1517 | // matchRegexp return true if a specified regexp matches a string.
1518 | func matchRegexp(rx interface{}, str interface{}) bool {
1519 | var r *regexp.Regexp
1520 | if rr, ok := rx.(*regexp.Regexp); ok {
1521 | r = rr
1522 | } else {
1523 | r = regexp.MustCompile(fmt.Sprint(rx))
1524 | }
1525 |
1526 | switch v := str.(type) {
1527 | case []byte:
1528 | return r.Match(v)
1529 | case string:
1530 | return r.MatchString(v)
1531 | default:
1532 | return r.MatchString(fmt.Sprint(v))
1533 | }
1534 |
1535 | }
1536 |
1537 | // Regexp asserts that a specified regexp matches a string.
1538 | //
1539 | // assert.Regexp(regexp.MustCompile("start"), "it's starting")
1540 | // assert.Regexp("start...$", "it's not starting")
1541 | func Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
1542 |
1543 | match := matchRegexp(rx, str)
1544 |
1545 | if !match {
1546 | Fail(fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...)
1547 | }
1548 |
1549 | return match
1550 | }
1551 |
1552 | // NotRegexp asserts that a specified regexp does not match a string.
1553 | //
1554 | // assert.NotRegexp(regexp.MustCompile("starts"), "it's starting")
1555 | // assert.NotRegexp("^start", "it's not starting")
1556 | func NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
1557 | match := matchRegexp(rx, str)
1558 |
1559 | if match {
1560 | Fail(fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...)
1561 | }
1562 |
1563 | return !match
1564 |
1565 | }
1566 |
1567 | // Zero asserts that i is the zero value for its type.
1568 | func Zero(i interface{}, msgAndArgs ...interface{}) bool {
1569 | if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
1570 | return Fail(fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...)
1571 | }
1572 | return true
1573 | }
1574 |
1575 | // NotZero asserts that i is not the zero value for its type.
1576 | func NotZero(i interface{}, msgAndArgs ...interface{}) bool {
1577 | if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
1578 | return Fail(fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...)
1579 | }
1580 | return true
1581 | }
1582 |
1583 | // FileExists checks whether a file exists in the given path. It also fails if
1584 | // the path points to a directory or there is an error when trying to check the file.
1585 | func FileExists(path string, msgAndArgs ...interface{}) bool {
1586 | info, err := os.Lstat(path)
1587 | if err != nil {
1588 | if os.IsNotExist(err) {
1589 | return Fail(fmt.Sprintf("unable to find file %q", path), msgAndArgs...)
1590 | }
1591 | return Fail(fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...)
1592 | }
1593 | if info.IsDir() {
1594 | return Fail(fmt.Sprintf("%q is a directory", path), msgAndArgs...)
1595 | }
1596 | return true
1597 | }
1598 |
1599 | // NoFileExists checks whether a file does not exist in a given path. It fails
1600 | // if the path points to an existing _file_ only.
1601 | func NoFileExists(path string, msgAndArgs ...interface{}) bool {
1602 | info, err := os.Lstat(path)
1603 | if err != nil {
1604 | return true
1605 | }
1606 | if info.IsDir() {
1607 | return true
1608 | }
1609 | return Fail(fmt.Sprintf("file %q exists", path), msgAndArgs...)
1610 | }
1611 |
1612 | // DirExists checks whether a directory exists in the given path. It also fails
1613 | // if the path is a file rather a directory or there is an error checking whether it exists.
1614 | func DirExists(path string, msgAndArgs ...interface{}) bool {
1615 | info, err := os.Lstat(path)
1616 | if err != nil {
1617 | if os.IsNotExist(err) {
1618 | return Fail(fmt.Sprintf("unable to find file %q", path), msgAndArgs...)
1619 | }
1620 | return Fail(fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...)
1621 | }
1622 | if !info.IsDir() {
1623 | return Fail(fmt.Sprintf("%q is a file", path), msgAndArgs...)
1624 | }
1625 | return true
1626 | }
1627 |
1628 | // NoDirExists checks whether a directory does not exist in the given path.
1629 | // It fails if the path points to an existing _directory_ only.
1630 | func NoDirExists(path string, msgAndArgs ...interface{}) bool {
1631 | info, err := os.Lstat(path)
1632 | if err != nil {
1633 | if os.IsNotExist(err) {
1634 | return true
1635 | }
1636 | return true
1637 | }
1638 | if !info.IsDir() {
1639 | return true
1640 | }
1641 | return Fail(fmt.Sprintf("directory %q exists", path), msgAndArgs...)
1642 | }
1643 |
1644 | // JSONEq asserts that two JSON strings are equivalent.
1645 | //
1646 | // assert.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
1647 | func JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool {
1648 | var expectedJSONAsInterface, actualJSONAsInterface interface{}
1649 |
1650 | if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil {
1651 | return Fail(fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...)
1652 | }
1653 |
1654 | if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil {
1655 | return Fail(fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...)
1656 | }
1657 |
1658 | return Equal(expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...)
1659 | }
1660 |
1661 | // YAMLEq asserts that two YAML strings are equivalent.
1662 |
1663 | func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) {
1664 | t := reflect.TypeOf(v)
1665 | k := t.Kind()
1666 |
1667 | if k == reflect.Ptr {
1668 | t = t.Elem()
1669 | k = t.Kind()
1670 | }
1671 | return t, k
1672 | }
1673 |
1674 | // diff returns a diff of both values as long as both are of the same type and
1675 | // are a struct, map, slice, array or string. Otherwise it returns an empty string.
1676 | func diff(expected interface{}, actual interface{}) string {
1677 | if expected == nil || actual == nil {
1678 | return ""
1679 | }
1680 |
1681 | et, ek := typeAndKind(expected)
1682 | at, _ := typeAndKind(actual)
1683 |
1684 | if et != at {
1685 | return ""
1686 | }
1687 |
1688 | if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String {
1689 | return ""
1690 | }
1691 |
1692 | var e, a string
1693 |
1694 | switch et {
1695 | case reflect.TypeOf(""):
1696 | e = reflect.ValueOf(expected).String()
1697 | a = reflect.ValueOf(actual).String()
1698 | case reflect.TypeOf(time.Time{}):
1699 | e = spewConfigStringerEnabled.Sdump(expected)
1700 | a = spewConfigStringerEnabled.Sdump(actual)
1701 | default:
1702 | e = spewConfig.Sdump(expected)
1703 | a = spewConfig.Sdump(actual)
1704 | }
1705 |
1706 | diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
1707 | A: difflib.SplitLines(e),
1708 | B: difflib.SplitLines(a),
1709 | FromFile: "Expected",
1710 | FromDate: "",
1711 | ToFile: "Actual",
1712 | ToDate: "",
1713 | Context: 1,
1714 | })
1715 |
1716 | return "\n\nDiff:\n" + diff
1717 | }
1718 |
1719 | func isFunction(arg interface{}) bool {
1720 | if arg == nil {
1721 | return false
1722 | }
1723 | return reflect.TypeOf(arg).Kind() == reflect.Func
1724 | }
1725 |
1726 | var spewConfig = spew.ConfigState{
1727 | Indent: " ",
1728 | DisablePointerAddresses: true,
1729 | DisableCapacities: true,
1730 | SortKeys: true,
1731 | DisableMethods: true,
1732 | MaxDepth: 10,
1733 | }
1734 |
1735 | var spewConfigStringerEnabled = spew.ConfigState{
1736 | Indent: " ",
1737 | DisablePointerAddresses: true,
1738 | DisableCapacities: true,
1739 | SortKeys: true,
1740 | MaxDepth: 10,
1741 | }
1742 |
1743 | type tHelper = interface {
1744 | Helper()
1745 | }
1746 |
1747 | // Eventually asserts that given condition will be met in waitFor time,
1748 | // periodically checking target function each tick.
1749 | //
1750 | // assert.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond)
1751 | func Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
1752 |
1753 | ch := make(chan bool, 1)
1754 |
1755 | timer := time.NewTimer(waitFor)
1756 | defer timer.Stop()
1757 |
1758 | ticker := time.NewTicker(tick)
1759 | defer ticker.Stop()
1760 |
1761 | for tick := ticker.C; ; {
1762 | select {
1763 | case <-timer.C:
1764 | return Fail("Condition never satisfied", msgAndArgs...)
1765 | case <-tick:
1766 | tick = nil
1767 | go func() { ch <- condition() }()
1768 | case v := <-ch:
1769 | if v {
1770 | return true
1771 | }
1772 | tick = ticker.C
1773 | }
1774 | }
1775 | }
1776 |
1777 | // CollectT implements the TestingT interface and collects all errors.
1778 | type CollectT struct {
1779 | // A slice of errors. Non-nil slice denotes a failure.
1780 | // If it's non-nil but len(c.errors) == 0, this is also a failure
1781 | // obtained by direct c.FailNow() call.
1782 | errors []error
1783 | }
1784 |
1785 | // Errorf collects the error.
1786 | func (c *CollectT) Errorf(format string, args ...interface{}) {
1787 | c.errors = append(c.errors, fmt.Errorf(format, args...))
1788 | }
1789 |
1790 | // FailNow stops execution by calling runtime.Goexit.
1791 | func (c *CollectT) FailNow() {
1792 | c.fail()
1793 | runtime.Goexit()
1794 | }
1795 |
1796 | // Deprecated: That was a method for internal usage that should not have been published. Now just panics.
1797 | func (*CollectT) Reset() {
1798 | panic("Reset() is deprecated")
1799 | }
1800 |
1801 | // Deprecated: That was a method for internal usage that should not have been published. Now just panics.
1802 | func (*CollectT) Copy(TestingT) {
1803 | panic("Copy() is deprecated")
1804 | }
1805 |
1806 | func (c *CollectT) fail() {
1807 | if !c.failed() {
1808 | c.errors = []error{} // Make it non-nil to mark a failure.
1809 | }
1810 | }
1811 |
1812 | func (c *CollectT) failed() bool {
1813 | return c.errors != nil
1814 | }
1815 |
1816 | // EventuallyWithT asserts that given condition will be met in waitFor time,
1817 | // periodically checking target function each tick. In contrast to Eventually,
1818 | // it supplies a CollectT to the condition function, so that the condition
1819 | // function can use the CollectT to call other assertions.
1820 | // The condition is considered "met" if no errors are raised in a tick.
1821 | // The supplied CollectT collects all errors from one tick (if there are any).
1822 | // If the condition is not met before waitFor, the collected errors of
1823 | // the last tick are copied to t.
1824 | //
1825 | // externalValue := false
1826 | // go func() {
1827 | // time.Sleep(8*time.Second)
1828 | // externalValue = true
1829 | // }()
1830 | // assert.EventuallyWithT(func(c *assert.CollectT) {
1831 | // // add assertions as needed; any assertion failure will fail the current tick
1832 | // assert.True(c, externalValue, "expected 'externalValue' to be true")
1833 | // }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
1834 | func EventuallyWithT(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
1835 |
1836 | var lastFinishedTickErrs []error
1837 | ch := make(chan *CollectT, 1)
1838 |
1839 | timer := time.NewTimer(waitFor)
1840 | defer timer.Stop()
1841 |
1842 | ticker := time.NewTicker(tick)
1843 | defer ticker.Stop()
1844 |
1845 | for tick := ticker.C; ; {
1846 | select {
1847 | case <-timer.C:
1848 | for _, err := range lastFinishedTickErrs {
1849 | panic(fmt.Errorf("%v", err))
1850 | }
1851 | return Fail("Condition never satisfied", msgAndArgs...)
1852 | case <-tick:
1853 | tick = nil
1854 | go func() {
1855 | collect := new(CollectT)
1856 | defer func() {
1857 | ch <- collect
1858 | }()
1859 | condition(collect)
1860 | }()
1861 | case collect := <-ch:
1862 | if !collect.failed() {
1863 | return true
1864 | }
1865 | // Keep the errors from the last ended condition, so that they can be copied to t if timeout is reached.
1866 | lastFinishedTickErrs = collect.errors
1867 | tick = ticker.C
1868 | }
1869 | }
1870 | }
1871 |
1872 | // Never asserts that the given condition doesn't satisfy in waitFor time,
1873 | // periodically checking the target function each tick.
1874 | //
1875 | // assert.Never(func() bool { return false; }, time.Second, 10*time.Millisecond)
1876 | func Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
1877 |
1878 | ch := make(chan bool, 1)
1879 |
1880 | timer := time.NewTimer(waitFor)
1881 | defer timer.Stop()
1882 |
1883 | ticker := time.NewTicker(tick)
1884 | defer ticker.Stop()
1885 |
1886 | for tick := ticker.C; ; {
1887 | select {
1888 | case <-timer.C:
1889 | return true
1890 | case <-tick:
1891 | tick = nil
1892 | go func() { ch <- condition() }()
1893 | case v := <-ch:
1894 | if v {
1895 | return Fail("Condition satisfied", msgAndArgs...)
1896 | }
1897 | tick = ticker.C
1898 | }
1899 | }
1900 | }
1901 |
1902 | // ErrorIs asserts that at least one of the errors in err's chain matches target.
1903 | // This is a wrapper for errors.Is.
1904 | func ErrorIs(err, target error, msgAndArgs ...interface{}) bool {
1905 | if errors.Is(err, target) {
1906 | return true
1907 | }
1908 |
1909 | var expectedText string
1910 | if target != nil {
1911 | expectedText = target.Error()
1912 | }
1913 |
1914 | chain := buildErrorChainString(err)
1915 |
1916 | return Fail(fmt.Sprintf("Target error should be in err chain:\n"+
1917 | "expected: %q\n"+
1918 | "in chain: %s", expectedText, chain,
1919 | ), msgAndArgs...)
1920 | }
1921 |
1922 | // NotErrorIs asserts that none of the errors in err's chain matches target.
1923 | // This is a wrapper for errors.Is.
1924 | func NotErrorIs(err, target error, msgAndArgs ...interface{}) bool {
1925 | if !errors.Is(err, target) {
1926 | return true
1927 | }
1928 |
1929 | var expectedText string
1930 | if target != nil {
1931 | expectedText = target.Error()
1932 | }
1933 |
1934 | chain := buildErrorChainString(err)
1935 |
1936 | return Fail(fmt.Sprintf("Target error should not be in err chain:\n"+
1937 | "found: %q\n"+
1938 | "in chain: %s", expectedText, chain,
1939 | ), msgAndArgs...)
1940 | }
1941 |
1942 | // ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
1943 | // This is a wrapper for errors.As.
1944 | func ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) bool {
1945 | if errors.As(err, target) {
1946 | return true
1947 | }
1948 |
1949 | chain := buildErrorChainString(err)
1950 |
1951 | return Fail(fmt.Sprintf("Should be in error chain:\n"+
1952 | "expected: %q\n"+
1953 | "in chain: %s", target, chain,
1954 | ), msgAndArgs...)
1955 | }
1956 |
1957 | // NotErrorAs asserts that none of the errors in err's chain matches target,
1958 | // but if so, sets target to that error value.
1959 | func NotErrorAs(err error, target interface{}, msgAndArgs ...interface{}) bool {
1960 | if !errors.As(err, target) {
1961 | return true
1962 | }
1963 |
1964 | chain := buildErrorChainString(err)
1965 |
1966 | return Fail(fmt.Sprintf("Target error should not be in err chain:\n"+
1967 | "found: %q\n"+
1968 | "in chain: %s", target, chain,
1969 | ), msgAndArgs...)
1970 | }
1971 |
1972 | func buildErrorChainString(err error) string {
1973 | if err == nil {
1974 | return ""
1975 | }
1976 |
1977 | e := errors.Unwrap(err)
1978 | chain := fmt.Sprintf("%q", err.Error())
1979 | for e != nil {
1980 | chain += fmt.Sprintf("\n\t%q", e.Error())
1981 | e = errors.Unwrap(e)
1982 | }
1983 | return chain
1984 | }
1985 |
--------------------------------------------------------------------------------
/codegen.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -euo pipefail
4 | shopt -s inherit_errexit
5 |
6 | testify_file_skiplist=("assertion_forward.go" "forward_assertions.go" "doc.go" "extra")
7 |
8 | # Copy testify files.
9 | for f in ./testify/assert/*.go; do
10 | basename_f="$(basename "$f")"
11 |
12 | # Skip file.
13 | # shellcheck disable=SC2076
14 | if [[ " ${testify_file_skiplist[*]} " =~ " $basename_f " ]]; then
15 | echo "skipping $f"
16 | continue
17 | fi
18 |
19 | cp "$f" "$basename_f"
20 | done
21 |
22 | rm -f ./*_test.go
23 |
24 | for f in ./*.go; do
25 | # Remove TestingT arguments in function signature.
26 | sed -i -E 's/(t )?TestingT, //g' "$f"
27 |
28 | # Remove TestingT arguments in function call.
29 | sed -i 's/(t, /(/g' "$f"
30 | sed -i -E 's/^\s+t,$//g' "$f"
31 |
32 | # Remove:
33 | # if h, ok := t.(tHelper); ok {
34 | # h.Helper()
35 | # }
36 | sed -i '/if h, ok := t.(tHelper); ok {/,/}/d' "$f"
37 |
38 | # Remove:
39 | # if n, ok := t.(interface {
40 | # Name() string
41 | # }); ok {
42 | # content = append(content, labeledContent{"Test", n.Name()})
43 | # }
44 | sed -i '/if n, ok := t.(interface {/,/}$/d' "$f"
45 |
46 | # Replace:
47 | # t.Errorf(.*) with panic(fmt.Errorf(.*))
48 | sed -i -E 's/\s+t\.Errorf\((.*)\)/panic(fmt.Errorf(\1))/g' "$f"
49 |
50 | # Delete:
51 | # if t, ok := t.(failNower); ok {
52 | # t.FailNow()
53 | # } else {
54 | # panic("test failed and t is missing `FailNow()`")
55 | # }
56 | sed -i '/if t, ok := t.(failNower); ok {/,/}$/d' "$f"
57 |
58 | # Delete YAML functions:
59 | sed -i '/func YAML.*{/,/^}$/d' "$f"
60 | done
61 |
62 | # Create prod_* files that will contain empty function.
63 | for f in *.go; do
64 | if [ "$f" == "doc.go" ]; then
65 | continue
66 | fi
67 |
68 | # Prepend build tag to files if needed.
69 | if ! grep "//go:build assert" < "$f" > /dev/null; then
70 | sed -i '1i //go:build assert' "$f"
71 | fi
72 |
73 | cp "$f" "prod_$f"
74 |
75 | # Change build tag on prod file.
76 | sed -i 's|^//go:build assert|//go:build !assert|' "prod_$f"
77 |
78 | # Remove function body in prod file.
79 | sed -i 's/func\(.*\){$/func\1{}\n{/' "prod_$f"
80 | sed -i '/^{$/,/^}$/d' "prod_$f"
81 |
82 | # Replace:
83 | # func () returnType with func ()
84 | sed -i 's/func\(.*\) [^()]* {}$/func\1{}/' "prod_$f"
85 | sed -i 's/func\(.*\) \(([^)]*)\) {}$/func\1{}/' "prod_$f"
86 | done
87 |
88 | gofmt -w ./*.go
89 | goimports -w ./*.go
90 | go mod tidy
91 |
--------------------------------------------------------------------------------
/doc.go:
--------------------------------------------------------------------------------
1 | // Package assert provides a set of comprehensive debug assertions.
2 | //
3 | // # Example Usage
4 | //
5 | // The following is a complete example using assert in a function:
6 | //
7 | // import (
8 | // "github.com/negrel/assert"
9 | // )
10 | //
11 | // func Divide(a, b int) int {
12 | // assert.NotEqual(b, 0, "Can't divide by 0.")
13 | // return a / b
14 | // }
15 | //
16 | // # Debug Assertions
17 | //
18 | // Debug assertions are programming statements that help developers catch
19 | // logical errors during development by verifying assumptions about the
20 | // program's state. They're typically used to check conditions that should
21 | // always be true during normal program execution. If the condition is false,
22 | // the assertions is either wrong or there is a programming error. In
23 | // both case, program panics if it was compiled with the `assert` tags
24 | // (`go build -tags assert ./path/to/my/package`)
25 | //
26 | // Every assertion function also takes an optional string message as the final argument,
27 | // allowing custom error messages to be appended to the message the assertion method outputs.
28 | package assert
29 |
--------------------------------------------------------------------------------
/errors.go:
--------------------------------------------------------------------------------
1 | //go:build assert
2 |
3 | package assert
4 |
5 | import (
6 | "errors"
7 | )
8 |
9 | // AnError is an error instance useful for testing. If the code does not care
10 | // about error specifics, and only needs to return the error for example, this
11 | // error should be used to make the test code more readable.
12 | var AnError = errors.New("assert.AnError general error for testing")
13 |
--------------------------------------------------------------------------------
/extra.go:
--------------------------------------------------------------------------------
1 | //go:build assert
2 |
3 | package assert
4 |
5 | import "sync"
6 |
7 | // A TryLocker represents an object that can attempt to acquire a lock and report
8 | // whether it succeeded.
9 | //
10 | // [sync.Mutex] and [sync.RWMutex] implements this interface.
11 | type TryLocker interface {
12 | sync.Locker
13 | TryLock() bool
14 | }
15 |
16 | // Locked asserts that the [TryLocker] is already locked.
17 | //
18 | // assert.IsDecreasing([]int{2, 1, 0})
19 | // assert.IsDecreasing([]float{2, 1})
20 | // assert.IsDecreasing([]string{"b", "a"})
21 | func Locked(locker TryLocker, msgAndArgs ...any) {
22 | if locker.TryLock() {
23 | Fail("Expected sync.Locker to be locked", msgAndArgs...)
24 | }
25 | }
26 |
27 | // Lockedf asserts that the [TryLocker] is already locked.
28 | //
29 | // assert.IsDecreasing([]int{2, 1, 0})
30 | // assert.IsDecreasing([]float{2, 1})
31 | // assert.IsDecreasing([]string{"b", "a"})
32 | func Lockedf(locker TryLocker, msg string, args ...any) {
33 | Locked(locker, append([]interface{}{msg}, args...)...)
34 | }
35 |
36 | // Unlocked asserts that the [TryLocker] is unlocked.
37 | //
38 | // assert.IsDecreasing([]int{2, 1, 0})
39 | // assert.IsDecreasing([]float{2, 1})
40 | // assert.IsDecreasing([]string{"b", "a"})
41 | func Unlocked(locker TryLocker, msgAndArgs ...any) {
42 | if !locker.TryLock() {
43 | Fail("Expected sync.Locker to be unlocked", msgAndArgs...)
44 | }
45 | locker.Unlock()
46 | }
47 |
48 | // UnLockedf asserts that the [TryLocker] is unlocked.
49 | //
50 | // assert.IsDecreasing([]int{2, 1, 0})
51 | // assert.IsDecreasing([]float{2, 1})
52 | // assert.IsDecreasing([]string{"b", "a"})
53 | func Unlockedf(locker TryLocker, msg string, args ...any) {
54 | Unlocked(locker, append([]interface{}{msg}, args...)...)
55 | }
56 |
--------------------------------------------------------------------------------
/flake.lock:
--------------------------------------------------------------------------------
1 | {
2 | "nodes": {
3 | "flake-utils": {
4 | "inputs": {
5 | "systems": "systems"
6 | },
7 | "locked": {
8 | "lastModified": 1694529238,
9 | "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
10 | "owner": "numtide",
11 | "repo": "flake-utils",
12 | "rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
13 | "type": "github"
14 | },
15 | "original": {
16 | "owner": "numtide",
17 | "repo": "flake-utils",
18 | "type": "github"
19 | }
20 | },
21 | "nixpkgs": {
22 | "locked": {
23 | "lastModified": 1698890957,
24 | "narHash": "sha256-DJ+SppjpPBoJr0Aro9TAcP3sxApCSieY6BYBCoWGUX8=",
25 | "owner": "NixOS",
26 | "repo": "nixpkgs",
27 | "rev": "c082856b850ec60cda9f0a0db2bc7bd8900d708c",
28 | "type": "github"
29 | },
30 | "original": {
31 | "id": "nixpkgs",
32 | "type": "indirect"
33 | }
34 | },
35 | "root": {
36 | "inputs": {
37 | "flake-utils": "flake-utils",
38 | "nixpkgs": "nixpkgs"
39 | }
40 | },
41 | "systems": {
42 | "locked": {
43 | "lastModified": 1681028828,
44 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
45 | "owner": "nix-systems",
46 | "repo": "default",
47 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
48 | "type": "github"
49 | },
50 | "original": {
51 | "owner": "nix-systems",
52 | "repo": "default",
53 | "type": "github"
54 | }
55 | }
56 | },
57 | "root": "root",
58 | "version": 7
59 | }
60 |
--------------------------------------------------------------------------------
/flake.nix:
--------------------------------------------------------------------------------
1 | {
2 | inputs = { flake-utils.url = "github:numtide/flake-utils"; };
3 |
4 | outputs = { nixpkgs, flake-utils, ... }:
5 | let
6 | outputsWithoutSystem = { };
7 | outputsWithSystem = flake-utils.lib.eachDefaultSystem (system:
8 | let
9 | pkgs = import nixpkgs { inherit system; };
10 | #lib = pkgs.lib;
11 | in {
12 | devShells = {
13 | default = pkgs.mkShell {
14 | buildInputs = with pkgs; [ go gopls gotools shellcheck ];
15 | };
16 | };
17 | });
18 | in outputsWithSystem // outputsWithoutSystem;
19 | }
20 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/negrel/assert
2 |
3 | go 1.20
4 |
5 | require github.com/davecgh/go-spew v1.1.1
6 |
7 | require github.com/pmezard/go-difflib v1.0.0
8 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
4 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
5 |
--------------------------------------------------------------------------------
/http_assertions.go:
--------------------------------------------------------------------------------
1 | //go:build assert
2 |
3 | package assert
4 |
5 | import (
6 | "fmt"
7 | "net/http"
8 | "net/http/httptest"
9 | "net/url"
10 | "strings"
11 | )
12 |
13 | // httpCode is a helper that returns HTTP code of the response. It returns -1 and
14 | // an error if building a new request fails.
15 | func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) {
16 | w := httptest.NewRecorder()
17 | req, err := http.NewRequest(method, url, http.NoBody)
18 | if err != nil {
19 | return -1, err
20 | }
21 | req.URL.RawQuery = values.Encode()
22 | handler(w, req)
23 | return w.Code, nil
24 | }
25 |
26 | // HTTPSuccess asserts that a specified handler returns a success status code.
27 | //
28 | // assert.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
29 | //
30 | // Returns whether the assertion was successful (true) or not (false).
31 | func HTTPSuccess(handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
32 | code, err := httpCode(handler, method, url, values)
33 | if err != nil {
34 | Fail(fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
35 | }
36 |
37 | isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent
38 | if !isSuccessCode {
39 | Fail(fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...)
40 | }
41 |
42 | return isSuccessCode
43 | }
44 |
45 | // HTTPRedirect asserts that a specified handler returns a redirect status code.
46 | //
47 | // assert.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
48 | //
49 | // Returns whether the assertion was successful (true) or not (false).
50 | func HTTPRedirect(handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
51 | code, err := httpCode(handler, method, url, values)
52 | if err != nil {
53 | Fail(fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
54 | }
55 |
56 | isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
57 | if !isRedirectCode {
58 | Fail(fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...)
59 | }
60 |
61 | return isRedirectCode
62 | }
63 |
64 | // HTTPError asserts that a specified handler returns an error status code.
65 | //
66 | // assert.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
67 | //
68 | // Returns whether the assertion was successful (true) or not (false).
69 | func HTTPError(handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
70 | code, err := httpCode(handler, method, url, values)
71 | if err != nil {
72 | Fail(fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
73 | }
74 |
75 | isErrorCode := code >= http.StatusBadRequest
76 | if !isErrorCode {
77 | Fail(fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...)
78 | }
79 |
80 | return isErrorCode
81 | }
82 |
83 | // HTTPStatusCode asserts that a specified handler returns a specified status code.
84 | //
85 | // assert.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501)
86 | //
87 | // Returns whether the assertion was successful (true) or not (false).
88 | func HTTPStatusCode(handler http.HandlerFunc, method, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool {
89 | code, err := httpCode(handler, method, url, values)
90 | if err != nil {
91 | Fail(fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
92 | }
93 |
94 | successful := code == statuscode
95 | if !successful {
96 | Fail(fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code), msgAndArgs...)
97 | }
98 |
99 | return successful
100 | }
101 |
102 | // HTTPBody is a helper that returns HTTP body of the response. It returns
103 | // empty string if building a new request fails.
104 | func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
105 | w := httptest.NewRecorder()
106 | if len(values) > 0 {
107 | url += "?" + values.Encode()
108 | }
109 | req, err := http.NewRequest(method, url, http.NoBody)
110 | if err != nil {
111 | return ""
112 | }
113 | handler(w, req)
114 | return w.Body.String()
115 | }
116 |
117 | // HTTPBodyContains asserts that a specified handler returns a
118 | // body that contains a string.
119 | //
120 | // assert.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
121 | //
122 | // Returns whether the assertion was successful (true) or not (false).
123 | func HTTPBodyContains(handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
124 | body := HTTPBody(handler, method, url, values)
125 |
126 | contains := strings.Contains(body, fmt.Sprint(str))
127 | if !contains {
128 | Fail(fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...)
129 | }
130 |
131 | return contains
132 | }
133 |
134 | // HTTPBodyNotContains asserts that a specified handler returns a
135 | // body that does not contain a string.
136 | //
137 | // assert.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
138 | //
139 | // Returns whether the assertion was successful (true) or not (false).
140 | func HTTPBodyNotContains(handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
141 | body := HTTPBody(handler, method, url, values)
142 |
143 | contains := strings.Contains(body, fmt.Sprint(str))
144 | if contains {
145 | Fail(fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...)
146 | }
147 |
148 | return !contains
149 | }
150 |
--------------------------------------------------------------------------------
/prod_assertion_compare.go:
--------------------------------------------------------------------------------
1 | //go:build !assert
2 |
3 | package assert
4 |
5 | import (
6 | "reflect"
7 | "time"
8 | )
9 |
10 | // Deprecated: CompareType has only ever been for internal use and has accidentally been published since v1.6.0. Do not use it.
11 | type CompareType = compareResult
12 |
13 | type compareResult int
14 |
15 | const (
16 | compareLess compareResult = iota - 1
17 | compareEqual
18 | compareGreater
19 | )
20 |
21 | var (
22 | intType = reflect.TypeOf(int(1))
23 | int8Type = reflect.TypeOf(int8(1))
24 | int16Type = reflect.TypeOf(int16(1))
25 | int32Type = reflect.TypeOf(int32(1))
26 | int64Type = reflect.TypeOf(int64(1))
27 |
28 | uintType = reflect.TypeOf(uint(1))
29 | uint8Type = reflect.TypeOf(uint8(1))
30 | uint16Type = reflect.TypeOf(uint16(1))
31 | uint32Type = reflect.TypeOf(uint32(1))
32 | uint64Type = reflect.TypeOf(uint64(1))
33 |
34 | uintptrType = reflect.TypeOf(uintptr(1))
35 |
36 | float32Type = reflect.TypeOf(float32(1))
37 | float64Type = reflect.TypeOf(float64(1))
38 |
39 | stringType = reflect.TypeOf("")
40 |
41 | timeType = reflect.TypeOf(time.Time{})
42 | bytesType = reflect.TypeOf([]byte{})
43 | )
44 |
45 | func compare(obj1, obj2 interface{}, kind reflect.Kind) {}
46 |
47 | // Greater asserts that the first element is greater than the second
48 | //
49 | // assert.Greater(2, 1)
50 | // assert.Greater(float64(2), float64(1))
51 | // assert.Greater("b", "a")
52 | func Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {}
53 |
54 | // GreaterOrEqual asserts that the first element is greater than or equal to the second
55 | //
56 | // assert.GreaterOrEqual(2, 1)
57 | // assert.GreaterOrEqual(2, 2)
58 | // assert.GreaterOrEqual("b", "a")
59 | // assert.GreaterOrEqual("b", "b")
60 | func GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {}
61 |
62 | // Less asserts that the first element is less than the second
63 | //
64 | // assert.Less(1, 2)
65 | // assert.Less(float64(1), float64(2))
66 | // assert.Less("a", "b")
67 | func Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {}
68 |
69 | // LessOrEqual asserts that the first element is less than or equal to the second
70 | //
71 | // assert.LessOrEqual(1, 2)
72 | // assert.LessOrEqual(2, 2)
73 | // assert.LessOrEqual("a", "b")
74 | // assert.LessOrEqual("b", "b")
75 | func LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {}
76 |
77 | // Positive asserts that the specified element is positive
78 | //
79 | // assert.Positive(1)
80 | // assert.Positive(1.23)
81 | func Positive(e interface{}, msgAndArgs ...interface{}) {}
82 |
83 | // Negative asserts that the specified element is negative
84 | //
85 | // assert.Negative(-1)
86 | // assert.Negative(-1.23)
87 | func Negative(e interface{}, msgAndArgs ...interface{}) {}
88 |
89 | func compareTwoValues(e1 interface{}, e2 interface{}, allowedComparesResults []compareResult, failMessage string, msgAndArgs ...interface{}) {
90 | }
91 |
92 | func containsValue(values []compareResult, value compareResult) {}
93 |
--------------------------------------------------------------------------------
/prod_assertion_format.go:
--------------------------------------------------------------------------------
1 | //go:build !assert
2 |
3 | // Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT.
4 |
5 | package assert
6 |
7 | import (
8 | http "net/http"
9 | url "net/url"
10 | time "time"
11 | )
12 |
13 | // Conditionf uses a Comparison to assert a complex condition.
14 | func Conditionf(comp Comparison, msg string, args ...interface{}) {}
15 |
16 | // Containsf asserts that the specified string, list(array, slice...) or map contains the
17 | // specified substring or element.
18 | //
19 | // assert.Containsf("Hello World", "World", "error message %s", "formatted")
20 | // assert.Containsf(["Hello", "World"], "World", "error message %s", "formatted")
21 | // assert.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted")
22 | func Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) {}
23 |
24 | // DirExistsf checks whether a directory exists in the given path. It also fails
25 | // if the path is a file rather a directory or there is an error checking whether it exists.
26 | func DirExistsf(path string, msg string, args ...interface{}) {}
27 |
28 | // ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified
29 | // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
30 | // the number of appearances of each of them in both lists should match.
31 | //
32 | // assert.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
33 | func ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) {}
34 |
35 | // Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
36 | // a slice or a channel with len == 0.
37 | //
38 | // assert.Emptyf(obj, "error message %s", "formatted")
39 | func Emptyf(object interface{}, msg string, args ...interface{}) {}
40 |
41 | // Equalf asserts that two objects are equal.
42 | //
43 | // assert.Equalf(123, 123, "error message %s", "formatted")
44 | //
45 | // Pointer variable equality is determined based on the equality of the
46 | // referenced values (as opposed to the memory addresses). Function equality
47 | // cannot be determined and will always fail.
48 | func Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) {}
49 |
50 | // EqualErrorf asserts that a function returned an error (i.e. not `nil`)
51 | // and that it is equal to the provided error.
52 | //
53 | // actualObj, err := SomeFunction()
54 | // assert.EqualErrorf(err, expectedErrorString, "error message %s", "formatted")
55 | func EqualErrorf(theError error, errString string, msg string, args ...interface{}) {}
56 |
57 | // EqualExportedValuesf asserts that the types of two objects are equal and their public
58 | // fields are also equal. This is useful for comparing structs that have private fields
59 | // that could potentially differ.
60 | //
61 | // type S struct {
62 | // Exported int
63 | // notExported int
64 | // }
65 | // assert.EqualExportedValuesf(S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
66 | // assert.EqualExportedValuesf(S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
67 | func EqualExportedValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
68 | }
69 |
70 | // EqualValuesf asserts that two objects are equal or convertible to the larger
71 | // type and equal.
72 | //
73 | // assert.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
74 | func EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) {}
75 |
76 | // Errorf asserts that a function returned an error (i.e. not `nil`).
77 | //
78 | // actualObj, err := SomeFunction()
79 | // if assert.Errorf(err, "error message %s", "formatted") {
80 | // assert.Equal(expectedErrorf, err)
81 | // }
82 | func Errorf(err error, msg string, args ...interface{}) {}
83 |
84 | // ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
85 | // This is a wrapper for errors.As.
86 | func ErrorAsf(err error, target interface{}, msg string, args ...interface{}) {}
87 |
88 | // ErrorContainsf asserts that a function returned an error (i.e. not `nil`)
89 | // and that the error contains the specified substring.
90 | //
91 | // actualObj, err := SomeFunction()
92 | // assert.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted")
93 | func ErrorContainsf(theError error, contains string, msg string, args ...interface{}) {}
94 |
95 | // ErrorIsf asserts that at least one of the errors in err's chain matches target.
96 | // This is a wrapper for errors.Is.
97 | func ErrorIsf(err error, target error, msg string, args ...interface{}) {}
98 |
99 | // Eventuallyf asserts that given condition will be met in waitFor time,
100 | // periodically checking target function each tick.
101 | //
102 | // assert.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
103 | func Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
104 | }
105 |
106 | // EventuallyWithTf asserts that given condition will be met in waitFor time,
107 | // periodically checking target function each tick. In contrast to Eventually,
108 | // it supplies a CollectT to the condition function, so that the condition
109 | // function can use the CollectT to call other assertions.
110 | // The condition is considered "met" if no errors are raised in a tick.
111 | // The supplied CollectT collects all errors from one tick (if there are any).
112 | // If the condition is not met before waitFor, the collected errors of
113 | // the last tick are copied to t.
114 | //
115 | // externalValue := false
116 | // go func() {}
117 |
118 | // Exactlyf asserts that two objects are equal in value and type.
119 | //
120 | // assert.Exactlyf(int32(123), int64(123), "error message %s", "formatted")
121 | func Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) {}
122 |
123 | // Failf reports a failure through
124 | func Failf(failureMessage string, msg string, args ...interface{}) {}
125 |
126 | // FailNowf fails test
127 | func FailNowf(failureMessage string, msg string, args ...interface{}) {}
128 |
129 | // Falsef asserts that the specified value is false.
130 | //
131 | // assert.Falsef(myBool, "error message %s", "formatted")
132 | func Falsef(value bool, msg string, args ...interface{}) {}
133 |
134 | // FileExistsf checks whether a file exists in the given path. It also fails if
135 | // the path points to a directory or there is an error when trying to check the file.
136 | func FileExistsf(path string, msg string, args ...interface{}) {}
137 |
138 | // Greaterf asserts that the first element is greater than the second
139 | //
140 | // assert.Greaterf(2, 1, "error message %s", "formatted")
141 | // assert.Greaterf(float64(2), float64(1), "error message %s", "formatted")
142 | // assert.Greaterf("b", "a", "error message %s", "formatted")
143 | func Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) {}
144 |
145 | // GreaterOrEqualf asserts that the first element is greater than or equal to the second
146 | //
147 | // assert.GreaterOrEqualf(2, 1, "error message %s", "formatted")
148 | // assert.GreaterOrEqualf(2, 2, "error message %s", "formatted")
149 | // assert.GreaterOrEqualf("b", "a", "error message %s", "formatted")
150 | // assert.GreaterOrEqualf("b", "b", "error message %s", "formatted")
151 | func GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) {}
152 |
153 | // HTTPBodyContainsf asserts that a specified handler returns a
154 | // body that contains a string.
155 | //
156 | // assert.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
157 | //
158 | // Returns whether the assertion was successful (true) or not (false).
159 | func HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) {
160 | }
161 |
162 | // HTTPBodyNotContainsf asserts that a specified handler returns a
163 | // body that does not contain a string.
164 | //
165 | // assert.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
166 | //
167 | // Returns whether the assertion was successful (true) or not (false).
168 | func HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) {
169 | }
170 |
171 | // HTTPErrorf asserts that a specified handler returns an error status code.
172 | //
173 | // assert.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
174 | //
175 | // Returns whether the assertion was successful (true) or not (false).
176 | func HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
177 | }
178 |
179 | // HTTPRedirectf asserts that a specified handler returns a redirect status code.
180 | //
181 | // assert.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
182 | //
183 | // Returns whether the assertion was successful (true) or not (false).
184 | func HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
185 | }
186 |
187 | // HTTPStatusCodef asserts that a specified handler returns a specified status code.
188 | //
189 | // assert.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
190 | //
191 | // Returns whether the assertion was successful (true) or not (false).
192 | func HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) {
193 | }
194 |
195 | // HTTPSuccessf asserts that a specified handler returns a success status code.
196 | //
197 | // assert.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
198 | //
199 | // Returns whether the assertion was successful (true) or not (false).
200 | func HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
201 | }
202 |
203 | // Implementsf asserts that an object is implemented by the specified interface.
204 | //
205 | // assert.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
206 | func Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) {}
207 |
208 | // InDeltaf asserts that the two numerals are within delta of each other.
209 | //
210 | // assert.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted")
211 | func InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) {
212 | }
213 |
214 | // InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
215 | func InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) {
216 | }
217 |
218 | // InDeltaSlicef is the same as InDelta, except it compares two slices.
219 | func InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) {
220 | }
221 |
222 | // InEpsilonf asserts that expected and actual have a relative error less than epsilon
223 | func InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) {
224 | }
225 |
226 | // InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
227 | func InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) {
228 | }
229 |
230 | // IsDecreasingf asserts that the collection is decreasing
231 | //
232 | // assert.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted")
233 | // assert.IsDecreasingf([]float{2, 1}, "error message %s", "formatted")
234 | // assert.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted")
235 | func IsDecreasingf(object interface{}, msg string, args ...interface{}) {}
236 |
237 | // IsIncreasingf asserts that the collection is increasing
238 | //
239 | // assert.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted")
240 | // assert.IsIncreasingf([]float{1, 2}, "error message %s", "formatted")
241 | // assert.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted")
242 | func IsIncreasingf(object interface{}, msg string, args ...interface{}) {}
243 |
244 | // IsNonDecreasingf asserts that the collection is not decreasing
245 | //
246 | // assert.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted")
247 | // assert.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted")
248 | // assert.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted")
249 | func IsNonDecreasingf(object interface{}, msg string, args ...interface{}) {}
250 |
251 | // IsNonIncreasingf asserts that the collection is not increasing
252 | //
253 | // assert.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted")
254 | // assert.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted")
255 | // assert.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted")
256 | func IsNonIncreasingf(object interface{}, msg string, args ...interface{}) {}
257 |
258 | // IsTypef asserts that the specified objects are of the same type.
259 | func IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) {}
260 |
261 | // JSONEqf asserts that two JSON strings are equivalent.
262 | //
263 | // assert.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
264 | func JSONEqf(expected string, actual string, msg string, args ...interface{}) {}
265 |
266 | // Lenf asserts that the specified object has specific length.
267 | // Lenf also fails if the object has a type that len() not accept.
268 | //
269 | // assert.Lenf(mySlice, 3, "error message %s", "formatted")
270 | func Lenf(object interface{}, length int, msg string, args ...interface{}) {}
271 |
272 | // Lessf asserts that the first element is less than the second
273 | //
274 | // assert.Lessf(1, 2, "error message %s", "formatted")
275 | // assert.Lessf(float64(1), float64(2), "error message %s", "formatted")
276 | // assert.Lessf("a", "b", "error message %s", "formatted")
277 | func Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) {}
278 |
279 | // LessOrEqualf asserts that the first element is less than or equal to the second
280 | //
281 | // assert.LessOrEqualf(1, 2, "error message %s", "formatted")
282 | // assert.LessOrEqualf(2, 2, "error message %s", "formatted")
283 | // assert.LessOrEqualf("a", "b", "error message %s", "formatted")
284 | // assert.LessOrEqualf("b", "b", "error message %s", "formatted")
285 | func LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) {}
286 |
287 | // Negativef asserts that the specified element is negative
288 | //
289 | // assert.Negativef(-1, "error message %s", "formatted")
290 | // assert.Negativef(-1.23, "error message %s", "formatted")
291 | func Negativef(e interface{}, msg string, args ...interface{}) {}
292 |
293 | // Neverf asserts that the given condition doesn't satisfy in waitFor time,
294 | // periodically checking the target function each tick.
295 | //
296 | // assert.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
297 | func Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
298 | }
299 |
300 | // Nilf asserts that the specified object is nil.
301 | //
302 | // assert.Nilf(err, "error message %s", "formatted")
303 | func Nilf(object interface{}, msg string, args ...interface{}) {}
304 |
305 | // NoDirExistsf checks whether a directory does not exist in the given path.
306 | // It fails if the path points to an existing _directory_ only.
307 | func NoDirExistsf(path string, msg string, args ...interface{}) {}
308 |
309 | // NoErrorf asserts that a function returned no error (i.e. `nil`).
310 | //
311 | // actualObj, err := SomeFunction()
312 | // if assert.NoErrorf(err, "error message %s", "formatted") {
313 | // assert.Equal(expectedObj, actualObj)
314 | // }
315 | func NoErrorf(err error, msg string, args ...interface{}) {}
316 |
317 | // NoFileExistsf checks whether a file does not exist in a given path. It fails
318 | // if the path points to an existing _file_ only.
319 | func NoFileExistsf(path string, msg string, args ...interface{}) {}
320 |
321 | // NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
322 | // specified substring or element.
323 | //
324 | // assert.NotContainsf("Hello World", "Earth", "error message %s", "formatted")
325 | // assert.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted")
326 | // assert.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted")
327 | func NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) {}
328 |
329 | // NotElementsMatchf asserts that the specified listA(array, slice...) is NOT equal to specified
330 | // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
331 | // the number of appearances of each of them in both lists should not match.
332 | // This is an inverse of ElementsMatch.
333 | //
334 | // assert.NotElementsMatchf([1, 1, 2, 3], [1, 1, 2, 3], "error message %s", "formatted") -> false
335 | //
336 | // assert.NotElementsMatchf([1, 1, 2, 3], [1, 2, 3], "error message %s", "formatted") -> true
337 | //
338 | // assert.NotElementsMatchf([1, 2, 3], [1, 2, 4], "error message %s", "formatted") -> true
339 | func NotElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) {}
340 |
341 | // NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
342 | // a slice or a channel with len == 0.
343 | //
344 | // if assert.NotEmptyf(obj, "error message %s", "formatted") {
345 | // assert.Equal("two", obj[1])
346 | // }
347 | func NotEmptyf(object interface{}, msg string, args ...interface{}) {}
348 |
349 | // NotEqualf asserts that the specified values are NOT equal.
350 | //
351 | // assert.NotEqualf(obj1, obj2, "error message %s", "formatted")
352 | //
353 | // Pointer variable equality is determined based on the equality of the
354 | // referenced values (as opposed to the memory addresses).
355 | func NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) {}
356 |
357 | // NotEqualValuesf asserts that two objects are not equal even when converted to the same type
358 | //
359 | // assert.NotEqualValuesf(obj1, obj2, "error message %s", "formatted")
360 | func NotEqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) {}
361 |
362 | // NotErrorAsf asserts that none of the errors in err's chain matches target,
363 | // but if so, sets target to that error value.
364 | func NotErrorAsf(err error, target interface{}, msg string, args ...interface{}) {}
365 |
366 | // NotErrorIsf asserts that none of the errors in err's chain matches target.
367 | // This is a wrapper for errors.Is.
368 | func NotErrorIsf(err error, target error, msg string, args ...interface{}) {}
369 |
370 | // NotImplementsf asserts that an object does not implement the specified interface.
371 | //
372 | // assert.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
373 | func NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) {
374 | }
375 |
376 | // NotNilf asserts that the specified object is not nil.
377 | //
378 | // assert.NotNilf(err, "error message %s", "formatted")
379 | func NotNilf(object interface{}, msg string, args ...interface{}) {}
380 |
381 | // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
382 | //
383 | // assert.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted")
384 | func NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) {}
385 |
386 | // NotRegexpf asserts that a specified regexp does not match a string.
387 | //
388 | // assert.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted")
389 | // assert.NotRegexpf("^start", "it's not starting", "error message %s", "formatted")
390 | func NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) {}
391 |
392 | // NotSamef asserts that two pointers do not reference the same object.
393 | //
394 | // assert.NotSamef(ptr1, ptr2, "error message %s", "formatted")
395 | //
396 | // Both arguments must be pointer variables. Pointer variable sameness is
397 | // determined based on the equality of both type and value.
398 | func NotSamef(expected interface{}, actual interface{}, msg string, args ...interface{}) {}
399 |
400 | // NotSubsetf asserts that the specified list(array, slice...) or map does NOT
401 | // contain all elements given in the specified subset list(array, slice...) or
402 | // map.
403 | //
404 | // assert.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted")
405 | // assert.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
406 | func NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) {}
407 |
408 | // NotZerof asserts that i is not the zero value for its type.
409 | func NotZerof(i interface{}, msg string, args ...interface{}) {}
410 |
411 | // Panicsf asserts that the code inside the specified PanicTestFunc panics.
412 | //
413 | // assert.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted")
414 | func Panicsf(f PanicTestFunc, msg string, args ...interface{}) {}
415 |
416 | // PanicsWithErrorf asserts that the code inside the specified PanicTestFunc
417 | // panics, and that the recovered panic value is an error that satisfies the
418 | // EqualError comparison.
419 | //
420 | // assert.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
421 | func PanicsWithErrorf(errString string, f PanicTestFunc, msg string, args ...interface{}) {}
422 |
423 | // PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
424 | // the recovered panic value equals the expected panic value.
425 | //
426 | // assert.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
427 | func PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) {}
428 |
429 | // Positivef asserts that the specified element is positive
430 | //
431 | // assert.Positivef(1, "error message %s", "formatted")
432 | // assert.Positivef(1.23, "error message %s", "formatted")
433 | func Positivef(e interface{}, msg string, args ...interface{}) {}
434 |
435 | // Regexpf asserts that a specified regexp matches a string.
436 | //
437 | // assert.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted")
438 | // assert.Regexpf("start...$", "it's not starting", "error message %s", "formatted")
439 | func Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) {}
440 |
441 | // Samef asserts that two pointers reference the same object.
442 | //
443 | // assert.Samef(ptr1, ptr2, "error message %s", "formatted")
444 | //
445 | // Both arguments must be pointer variables. Pointer variable sameness is
446 | // determined based on the equality of both type and value.
447 | func Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) {}
448 |
449 | // Subsetf asserts that the specified list(array, slice...) or map contains all
450 | // elements given in the specified subset list(array, slice...) or map.
451 | //
452 | // assert.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted")
453 | // assert.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
454 | func Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) {}
455 |
456 | // Truef asserts that the specified value is true.
457 | //
458 | // assert.Truef(myBool, "error message %s", "formatted")
459 | func Truef(value bool, msg string, args ...interface{}) {}
460 |
461 | // WithinDurationf asserts that the two times are within duration delta of each other.
462 | //
463 | // assert.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
464 | func WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) {
465 | }
466 |
467 | // WithinRangef asserts that a time is within a time range (inclusive).
468 | //
469 | // assert.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
470 | func WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) {
471 | }
472 |
473 | // YAMLEqf asserts that two YAML strings are equivalent.
474 |
475 | // Zerof asserts that i is the zero value for its type.
476 | func Zerof(i interface{}, msg string, args ...interface{}) {}
477 |
--------------------------------------------------------------------------------
/prod_assertion_order.go:
--------------------------------------------------------------------------------
1 | //go:build !assert
2 |
3 | package assert
4 |
5 | // isOrdered checks that collection contains orderable elements.
6 | func isOrdered(object interface{}, allowedComparesResults []compareResult, failMessage string, msgAndArgs ...interface{}) {
7 | }
8 |
9 | // IsIncreasing asserts that the collection is increasing
10 | //
11 | // assert.IsIncreasing([]int{1, 2, 3})
12 | // assert.IsIncreasing([]float{1, 2})
13 | // assert.IsIncreasing([]string{"a", "b"})
14 | func IsIncreasing(object interface{}, msgAndArgs ...interface{}) {}
15 |
16 | // IsNonIncreasing asserts that the collection is not increasing
17 | //
18 | // assert.IsNonIncreasing([]int{2, 1, 1})
19 | // assert.IsNonIncreasing([]float{2, 1})
20 | // assert.IsNonIncreasing([]string{"b", "a"})
21 | func IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) {}
22 |
23 | // IsDecreasing asserts that the collection is decreasing
24 | //
25 | // assert.IsDecreasing([]int{2, 1, 0})
26 | // assert.IsDecreasing([]float{2, 1})
27 | // assert.IsDecreasing([]string{"b", "a"})
28 | func IsDecreasing(object interface{}, msgAndArgs ...interface{}) {}
29 |
30 | // IsNonDecreasing asserts that the collection is not decreasing
31 | //
32 | // assert.IsNonDecreasing([]int{1, 1, 2})
33 | // assert.IsNonDecreasing([]float{1, 2})
34 | // assert.IsNonDecreasing([]string{"a", "b"})
35 | func IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) {}
36 |
--------------------------------------------------------------------------------
/prod_assertions.go:
--------------------------------------------------------------------------------
1 | //go:build !assert
2 |
3 | package assert
4 |
5 | import (
6 | "reflect"
7 | "time"
8 |
9 | "github.com/davecgh/go-spew/spew"
10 | // Wrapper around gopkg.in/yaml.v3
11 | )
12 |
13 | //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl"
14 |
15 | // TestingT is an interface wrapper around *testing.T
16 | type TestingT interface {
17 | Errorf(format string, args ...interface{})
18 | }
19 |
20 | // ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful
21 | // for table driven tests.
22 | type ComparisonAssertionFunc func(interface{}, interface{}, ...interface{}) bool
23 |
24 | // ValueAssertionFunc is a common function prototype when validating a single value. Can be useful
25 | // for table driven tests.
26 | type ValueAssertionFunc func(interface{}, ...interface{}) bool
27 |
28 | // BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful
29 | // for table driven tests.
30 | type BoolAssertionFunc func(bool, ...interface{}) bool
31 |
32 | // ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful
33 | // for table driven tests.
34 | type ErrorAssertionFunc func(error, ...interface{}) bool
35 |
36 | // PanicAssertionFunc is a common function prototype when validating a panic value. Can be useful
37 | // for table driven tests.
38 | type PanicAssertionFunc = func(f PanicTestFunc, msgAndArgs ...interface{}) bool
39 |
40 | // Comparison is a custom function that returns true on success and false on failure
41 | type Comparison func() (success bool)
42 |
43 | /*
44 | Helper functions
45 | */
46 |
47 | // ObjectsAreEqual determines if two objects are considered equal.
48 | //
49 | // This function does no assertion of any kind.
50 | func ObjectsAreEqual(expected, actual interface{}) {}
51 |
52 | // copyExportedFields iterates downward through nested data structures and creates a copy
53 | // that only contains the exported struct fields.
54 | func copyExportedFields(expected interface{}) {}
55 |
56 | // ObjectsExportedFieldsAreEqual determines if the exported (public) fields of two objects are
57 | // considered equal. This comparison of only exported fields is applied recursively to nested data
58 | // structures.
59 | //
60 | // This function does no assertion of any kind.
61 | //
62 | // Deprecated: Use [EqualExportedValues] instead.
63 | func ObjectsExportedFieldsAreEqual(expected, actual interface{}) {}
64 |
65 | // ObjectsAreEqualValues gets whether two objects are equal, or if their
66 | // values are equal.
67 | func ObjectsAreEqualValues(expected, actual interface{}) {}
68 |
69 | // isNumericType returns true if the type is one of:
70 | // int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64,
71 | // float32, float64, complex64, complex128
72 | func isNumericType(t reflect.Type) {}
73 |
74 | /* CallerInfo is necessary because the assert functions use the testing object
75 | internally, causing it to print the file:line of the assert method, rather than where
76 | the problem actually occurred in calling code.*/
77 |
78 | // CallerInfo returns an array of strings containing the file and line number
79 | // of each stack frame leading from the current test to the assert call that
80 | // failed.
81 | func CallerInfo() {}
82 |
83 | // Stolen from the `go test` tool.
84 | // isTest tells whether name looks like a test (or benchmark, according to prefix).
85 | // It is a Test (say) if there is a character after Test that is not a lower-case letter.
86 | // We don't want TesticularCancer.
87 | func isTest(name, prefix string) {}
88 |
89 | func messageFromMsgAndArgs(msgAndArgs ...interface{}) {}
90 |
91 | // Aligns the provided message so that all lines after the first line start at the same location as the first line.
92 | // Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab).
93 | // The longestLabelLen parameter specifies the length of the longest label in the output (required because this is the
94 | // basis on which the alignment occurs).
95 | func indentMessageLines(message string, longestLabelLen int) {}
96 |
97 | type failNower interface {
98 | FailNow()
99 | }
100 |
101 | // FailNow fails test
102 | func FailNow(failureMessage string, msgAndArgs ...interface{}) {}
103 |
104 | // Fail reports a failure through
105 | func Fail(failureMessage string, msgAndArgs ...interface{}) {}
106 |
107 | type labeledContent struct {
108 | label string
109 | content string
110 | }
111 |
112 | // labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner:
113 | //
114 | // \t{{label}}:{{align_spaces}}\t{{content}}\n
115 | //
116 | // The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label.
117 | // If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this
118 | // alignment is achieved, "\t{{content}}\n" is added for the output.
119 | //
120 | // If the content of the labeledOutput contains line breaks, the subsequent lines are aligned so that they start at the same location as the first line.
121 | func labeledOutput(content ...labeledContent) {}
122 |
123 | // Implements asserts that an object is implemented by the specified interface.
124 | //
125 | // assert.Implements((*MyInterface)(nil), new(MyObject))
126 | func Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) {}
127 |
128 | // NotImplements asserts that an object does not implement the specified interface.
129 | //
130 | // assert.NotImplements((*MyInterface)(nil), new(MyObject))
131 | func NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) {}
132 |
133 | // IsType asserts that the specified objects are of the same type.
134 | func IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) {}
135 |
136 | // Equal asserts that two objects are equal.
137 | //
138 | // assert.Equal(123, 123)
139 | //
140 | // Pointer variable equality is determined based on the equality of the
141 | // referenced values (as opposed to the memory addresses). Function equality
142 | // cannot be determined and will always fail.
143 | func Equal(expected, actual interface{}, msgAndArgs ...interface{}) {}
144 |
145 | // validateEqualArgs checks whether provided arguments can be safely used in the
146 | // Equal/NotEqual functions.
147 | func validateEqualArgs(expected, actual interface{}) {}
148 |
149 | // Same asserts that two pointers reference the same object.
150 | //
151 | // assert.Same(ptr1, ptr2)
152 | //
153 | // Both arguments must be pointer variables. Pointer variable sameness is
154 | // determined based on the equality of both type and value.
155 | func Same(expected, actual interface{}, msgAndArgs ...interface{}) {}
156 |
157 | // NotSame asserts that two pointers do not reference the same object.
158 | //
159 | // assert.NotSame(ptr1, ptr2)
160 | //
161 | // Both arguments must be pointer variables. Pointer variable sameness is
162 | // determined based on the equality of both type and value.
163 | func NotSame(expected, actual interface{}, msgAndArgs ...interface{}) {}
164 |
165 | // samePointers checks if two generic interface objects are pointers of the same
166 | // type pointing to the same object. It returns two values: same indicating if
167 | // they are the same type and point to the same object, and ok indicating that
168 | // both inputs are pointers.
169 | func samePointers(first, second interface{}) {}
170 |
171 | // formatUnequalValues takes two values of arbitrary types and returns string
172 | // representations appropriate to be presented to the user.
173 | //
174 | // If the values are not of like type, the returned strings will be prefixed
175 | // with the type name, and the value will be enclosed in parentheses similar
176 | // to a type conversion in the Go grammar.
177 | func formatUnequalValues(expected, actual interface{}) {}
178 |
179 | // truncatingFormat formats the data and truncates it if it's too long.
180 | //
181 | // This helps keep formatted error messages lines from exceeding the
182 | // bufio.MaxScanTokenSize max line length that the go testing framework imposes.
183 | func truncatingFormat(data interface{}) {}
184 |
185 | // EqualValues asserts that two objects are equal or convertible to the larger
186 | // type and equal.
187 | //
188 | // assert.EqualValues(uint32(123), int32(123))
189 | func EqualValues(expected, actual interface{}, msgAndArgs ...interface{}) {}
190 |
191 | // EqualExportedValues asserts that the types of two objects are equal and their public
192 | // fields are also equal. This is useful for comparing structs that have private fields
193 | // that could potentially differ.
194 | //
195 | // type S struct {
196 | // Exported int
197 | // notExported int
198 | // }
199 | // assert.EqualExportedValues(S{1, 2}, S{1, 3}) => true
200 | // assert.EqualExportedValues(S{1, 2}, S{2, 3}) => false
201 | func EqualExportedValues(expected, actual interface{}, msgAndArgs ...interface{}) {}
202 |
203 | // Exactly asserts that two objects are equal in value and type.
204 | //
205 | // assert.Exactly(int32(123), int64(123))
206 | func Exactly(expected, actual interface{}, msgAndArgs ...interface{}) {}
207 |
208 | // NotNil asserts that the specified object is not nil.
209 | //
210 | // assert.NotNil(err)
211 | func NotNil(object interface{}, msgAndArgs ...interface{}) {}
212 |
213 | // isNil checks if a specified object is nil or not, without Failing.
214 | func isNil(object interface{}) {}
215 |
216 | // Nil asserts that the specified object is nil.
217 | //
218 | // assert.Nil(err)
219 | func Nil(object interface{}, msgAndArgs ...interface{}) {}
220 |
221 | // isEmpty gets whether the specified object is considered empty or not.
222 | func isEmpty(object interface{}) {}
223 |
224 | // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
225 | // a slice or a channel with len == 0.
226 | //
227 | // assert.Empty(obj)
228 | func Empty(object interface{}, msgAndArgs ...interface{}) {}
229 |
230 | // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
231 | // a slice or a channel with len == 0.
232 | //
233 | // if assert.NotEmpty(obj) {
234 | // assert.Equal("two", obj[1])
235 | // }
236 | func NotEmpty(object interface{}, msgAndArgs ...interface{}) {}
237 |
238 | // getLen tries to get the length of an object.
239 | // It returns (0, false) if impossible.
240 | func getLen(x interface{}) {}
241 |
242 | // Len asserts that the specified object has specific length.
243 | // Len also fails if the object has a type that len() not accept.
244 | //
245 | // assert.Len(mySlice, 3)
246 | func Len(object interface{}, length int, msgAndArgs ...interface{}) {}
247 |
248 | // True asserts that the specified value is true.
249 | //
250 | // assert.True(myBool)
251 | func True(value bool, msgAndArgs ...interface{}) {}
252 |
253 | // False asserts that the specified value is false.
254 | //
255 | // assert.False(myBool)
256 | func False(value bool, msgAndArgs ...interface{}) {}
257 |
258 | // NotEqual asserts that the specified values are NOT equal.
259 | //
260 | // assert.NotEqual(obj1, obj2)
261 | //
262 | // Pointer variable equality is determined based on the equality of the
263 | // referenced values (as opposed to the memory addresses).
264 | func NotEqual(expected, actual interface{}, msgAndArgs ...interface{}) {}
265 |
266 | // NotEqualValues asserts that two objects are not equal even when converted to the same type
267 | //
268 | // assert.NotEqualValues(obj1, obj2)
269 | func NotEqualValues(expected, actual interface{}, msgAndArgs ...interface{}) {}
270 |
271 | // containsElement try loop over the list check if the list includes the element.
272 | // return (false, false) if impossible.
273 | // return (true, false) if element was not found.
274 | // return (true, true) if element was found.
275 | func containsElement(list interface{}, element interface{}) {}
276 |
277 | // Contains asserts that the specified string, list(array, slice...) or map contains the
278 | // specified substring or element.
279 | //
280 | // assert.Contains("Hello World", "World")
281 | // assert.Contains(["Hello", "World"], "World")
282 | // assert.Contains({"Hello": "World"}, "Hello")
283 | func Contains(s, contains interface{}, msgAndArgs ...interface{}) {}
284 |
285 | // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
286 | // specified substring or element.
287 | //
288 | // assert.NotContains("Hello World", "Earth")
289 | // assert.NotContains(["Hello", "World"], "Earth")
290 | // assert.NotContains({"Hello": "World"}, "Earth")
291 | func NotContains(s, contains interface{}, msgAndArgs ...interface{}) {}
292 |
293 | // Subset asserts that the specified list(array, slice...) or map contains all
294 | // elements given in the specified subset list(array, slice...) or map.
295 | //
296 | // assert.Subset([1, 2, 3], [1, 2])
297 | // assert.Subset({"x": 1, "y": 2}, {"x": 1})
298 | func Subset(list, subset interface{}, msgAndArgs ...interface{}) {}
299 |
300 | // NotSubset asserts that the specified list(array, slice...) or map does NOT
301 | // contain all elements given in the specified subset list(array, slice...) or
302 | // map.
303 | //
304 | // assert.NotSubset([1, 3, 4], [1, 2])
305 | // assert.NotSubset({"x": 1, "y": 2}, {"z": 3})
306 | func NotSubset(list, subset interface{}, msgAndArgs ...interface{}) {}
307 |
308 | // ElementsMatch asserts that the specified listA(array, slice...) is equal to specified
309 | // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
310 | // the number of appearances of each of them in both lists should match.
311 | //
312 | // assert.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2])
313 | func ElementsMatch(listA, listB interface{}, msgAndArgs ...interface{}) {}
314 |
315 | // isList checks that the provided value is array or slice.
316 | func isList(list interface{}, msgAndArgs ...interface{}) {}
317 |
318 | // diffLists diffs two arrays/slices and returns slices of elements that are only in A and only in B.
319 | // If some element is present multiple times, each instance is counted separately (e.g. if something is 2x in A and
320 | // 5x in B, it will be 0x in extraA and 3x in extraB). The order of items in both lists is ignored.
321 | func diffLists(listA, listB interface{}) {}
322 |
323 | func formatListDiff(listA, listB interface{}, extraA, extraB []interface{}) {}
324 |
325 | // NotElementsMatch asserts that the specified listA(array, slice...) is NOT equal to specified
326 | // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
327 | // the number of appearances of each of them in both lists should not match.
328 | // This is an inverse of ElementsMatch.
329 | //
330 | // assert.NotElementsMatch([1, 1, 2, 3], [1, 1, 2, 3]) -> false
331 | //
332 | // assert.NotElementsMatch([1, 1, 2, 3], [1, 2, 3]) -> true
333 | //
334 | // assert.NotElementsMatch([1, 2, 3], [1, 2, 4]) -> true
335 | func NotElementsMatch(listA, listB interface{}, msgAndArgs ...interface{}) {}
336 |
337 | // Condition uses a Comparison to assert a complex condition.
338 | func Condition(comp Comparison, msgAndArgs ...interface{}) {}
339 |
340 | // PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics
341 | // methods, and represents a simple func that takes no arguments, and returns nothing.
342 | type PanicTestFunc func()
343 |
344 | // didPanic returns true if the function passed to it panics. Otherwise, it returns false.
345 | func didPanic(f PanicTestFunc) {}
346 |
347 | // Panics asserts that the code inside the specified PanicTestFunc panics.
348 | //
349 | // assert.Panics(func(){ GoCrazy() })
350 | func Panics(f PanicTestFunc, msgAndArgs ...interface{}) {}
351 |
352 | // PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
353 | // the recovered panic value equals the expected panic value.
354 | //
355 | // assert.PanicsWithValue("crazy error", func(){ GoCrazy() })
356 | func PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) {}
357 |
358 | // PanicsWithError asserts that the code inside the specified PanicTestFunc
359 | // panics, and that the recovered panic value is an error that satisfies the
360 | // EqualError comparison.
361 | //
362 | // assert.PanicsWithError("crazy error", func(){ GoCrazy() })
363 | func PanicsWithError(errString string, f PanicTestFunc, msgAndArgs ...interface{}) {}
364 |
365 | // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
366 | //
367 | // assert.NotPanics(func(){ RemainCalm() })
368 | func NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) {}
369 |
370 | // WithinDuration asserts that the two times are within duration delta of each other.
371 | //
372 | // assert.WithinDuration(time.Now(), time.Now(), 10*time.Second)
373 | func WithinDuration(expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) {}
374 |
375 | // WithinRange asserts that a time is within a time range (inclusive).
376 | //
377 | // assert.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second))
378 | func WithinRange(actual, start, end time.Time, msgAndArgs ...interface{}) {}
379 |
380 | func toFloat(x interface{}) {}
381 |
382 | // InDelta asserts that the two numerals are within delta of each other.
383 | //
384 | // assert.InDelta(math.Pi, 22/7.0, 0.01)
385 | func InDelta(expected, actual interface{}, delta float64, msgAndArgs ...interface{}) {}
386 |
387 | // InDeltaSlice is the same as InDelta, except it compares two slices.
388 | func InDeltaSlice(expected, actual interface{}, delta float64, msgAndArgs ...interface{}) {}
389 |
390 | // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
391 | func InDeltaMapValues(expected, actual interface{}, delta float64, msgAndArgs ...interface{}) {}
392 |
393 | func calcRelativeError(expected, actual interface{}) {}
394 |
395 | // InEpsilon asserts that expected and actual have a relative error less than epsilon
396 | func InEpsilon(expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) {}
397 |
398 | // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
399 | func InEpsilonSlice(expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) {}
400 |
401 | /*
402 | Errors
403 | */
404 |
405 | // NoError asserts that a function returned no error (i.e. `nil`).
406 | //
407 | // actualObj, err := SomeFunction()
408 | // if assert.NoError(err) {
409 | // assert.Equal(expectedObj, actualObj)
410 | // }
411 | func NoError(err error, msgAndArgs ...interface{}) {}
412 |
413 | // Error asserts that a function returned an error (i.e. not `nil`).
414 | //
415 | // actualObj, err := SomeFunction()
416 | // if assert.Error(err) {
417 | // assert.Equal(expectedError, err)
418 | // }
419 | func Error(err error, msgAndArgs ...interface{}) {}
420 |
421 | // EqualError asserts that a function returned an error (i.e. not `nil`)
422 | // and that it is equal to the provided error.
423 | //
424 | // actualObj, err := SomeFunction()
425 | // assert.EqualError(err, expectedErrorString)
426 | func EqualError(theError error, errString string, msgAndArgs ...interface{}) {}
427 |
428 | // ErrorContains asserts that a function returned an error (i.e. not `nil`)
429 | // and that the error contains the specified substring.
430 | //
431 | // actualObj, err := SomeFunction()
432 | // assert.ErrorContains(err, expectedErrorSubString)
433 | func ErrorContains(theError error, contains string, msgAndArgs ...interface{}) {}
434 |
435 | // matchRegexp return true if a specified regexp matches a string.
436 | func matchRegexp(rx interface{}, str interface{}) {}
437 |
438 | // Regexp asserts that a specified regexp matches a string.
439 | //
440 | // assert.Regexp(regexp.MustCompile("start"), "it's starting")
441 | // assert.Regexp("start...$", "it's not starting")
442 | func Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) {}
443 |
444 | // NotRegexp asserts that a specified regexp does not match a string.
445 | //
446 | // assert.NotRegexp(regexp.MustCompile("starts"), "it's starting")
447 | // assert.NotRegexp("^start", "it's not starting")
448 | func NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) {}
449 |
450 | // Zero asserts that i is the zero value for its type.
451 | func Zero(i interface{}, msgAndArgs ...interface{}) {}
452 |
453 | // NotZero asserts that i is not the zero value for its type.
454 | func NotZero(i interface{}, msgAndArgs ...interface{}) {}
455 |
456 | // FileExists checks whether a file exists in the given path. It also fails if
457 | // the path points to a directory or there is an error when trying to check the file.
458 | func FileExists(path string, msgAndArgs ...interface{}) {}
459 |
460 | // NoFileExists checks whether a file does not exist in a given path. It fails
461 | // if the path points to an existing _file_ only.
462 | func NoFileExists(path string, msgAndArgs ...interface{}) {}
463 |
464 | // DirExists checks whether a directory exists in the given path. It also fails
465 | // if the path is a file rather a directory or there is an error checking whether it exists.
466 | func DirExists(path string, msgAndArgs ...interface{}) {}
467 |
468 | // NoDirExists checks whether a directory does not exist in the given path.
469 | // It fails if the path points to an existing _directory_ only.
470 | func NoDirExists(path string, msgAndArgs ...interface{}) {}
471 |
472 | // JSONEq asserts that two JSON strings are equivalent.
473 | //
474 | // assert.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
475 | func JSONEq(expected string, actual string, msgAndArgs ...interface{}) {}
476 |
477 | // YAMLEq asserts that two YAML strings are equivalent.
478 |
479 | func typeAndKind(v interface{}) {}
480 |
481 | // diff returns a diff of both values as long as both are of the same type and
482 | // are a struct, map, slice, array or string. Otherwise it returns an empty string.
483 | func diff(expected interface{}, actual interface{}) {}
484 |
485 | func isFunction(arg interface{}) {}
486 |
487 | var spewConfig = spew.ConfigState{
488 | Indent: " ",
489 | DisablePointerAddresses: true,
490 | DisableCapacities: true,
491 | SortKeys: true,
492 | DisableMethods: true,
493 | MaxDepth: 10,
494 | }
495 |
496 | var spewConfigStringerEnabled = spew.ConfigState{
497 | Indent: " ",
498 | DisablePointerAddresses: true,
499 | DisableCapacities: true,
500 | SortKeys: true,
501 | MaxDepth: 10,
502 | }
503 |
504 | type tHelper = interface {
505 | Helper()
506 | }
507 |
508 | // Eventually asserts that given condition will be met in waitFor time,
509 | // periodically checking target function each tick.
510 | //
511 | // assert.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond)
512 | func Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
513 | }
514 |
515 | // CollectT implements the TestingT interface and collects all errors.
516 | type CollectT struct {
517 | // A slice of errors. Non-nil slice denotes a failure.
518 | // If it's non-nil but len(c.errors) == 0, this is also a failure
519 | // obtained by direct c.FailNow() call.
520 | errors []error
521 | }
522 |
523 | // Errorf collects the error.
524 | func (c *CollectT) Errorf(format string, args ...interface{}) {}
525 |
526 | // FailNow stops execution by calling runtime.Goexit.
527 | func (c *CollectT) FailNow() {}
528 |
529 | // Deprecated: That was a method for internal usage that should not have been published. Now just panics.
530 | func (*CollectT) Reset() {}
531 |
532 | // Deprecated: That was a method for internal usage that should not have been published. Now just panics.
533 | func (*CollectT) Copy(TestingT) {}
534 |
535 | func (c *CollectT) fail() {}
536 |
537 | func (c *CollectT) failed() {}
538 |
539 | // EventuallyWithT asserts that given condition will be met in waitFor time,
540 | // periodically checking target function each tick. In contrast to Eventually,
541 | // it supplies a CollectT to the condition function, so that the condition
542 | // function can use the CollectT to call other assertions.
543 | // The condition is considered "met" if no errors are raised in a tick.
544 | // The supplied CollectT collects all errors from one tick (if there are any).
545 | // If the condition is not met before waitFor, the collected errors of
546 | // the last tick are copied to t.
547 | //
548 | // externalValue := false
549 | // go func() {}
550 |
551 | // Never asserts that the given condition doesn't satisfy in waitFor time,
552 | // periodically checking the target function each tick.
553 | //
554 | // assert.Never(func() bool { return false; }, time.Second, 10*time.Millisecond)
555 | func Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
556 | }
557 |
558 | // ErrorIs asserts that at least one of the errors in err's chain matches target.
559 | // This is a wrapper for errors.Is.
560 | func ErrorIs(err, target error, msgAndArgs ...interface{}) {}
561 |
562 | // NotErrorIs asserts that none of the errors in err's chain matches target.
563 | // This is a wrapper for errors.Is.
564 | func NotErrorIs(err, target error, msgAndArgs ...interface{}) {}
565 |
566 | // ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
567 | // This is a wrapper for errors.As.
568 | func ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) {}
569 |
570 | // NotErrorAs asserts that none of the errors in err's chain matches target,
571 | // but if so, sets target to that error value.
572 | func NotErrorAs(err error, target interface{}, msgAndArgs ...interface{}) {}
573 |
574 | func buildErrorChainString(err error) {}
575 |
--------------------------------------------------------------------------------
/prod_errors.go:
--------------------------------------------------------------------------------
1 | //go:build !assert
2 |
3 | package assert
4 |
5 | import (
6 | "errors"
7 | )
8 |
9 | // AnError is an error instance useful for testing. If the code does not care
10 | // about error specifics, and only needs to return the error for example, this
11 | // error should be used to make the test code more readable.
12 | var AnError = errors.New("assert.AnError general error for testing")
13 |
--------------------------------------------------------------------------------
/prod_extra.go:
--------------------------------------------------------------------------------
1 | //go:build !assert
2 |
3 | package assert
4 |
5 | import "sync"
6 |
7 | // A TryLocker represents an object that can attempt to acquire a lock and report
8 | // whether it succeeded.
9 | //
10 | // [sync.Mutex] and [sync.RWMutex] implements this interface.
11 | type TryLocker interface {
12 | sync.Locker
13 | TryLock() bool
14 | }
15 |
16 | // Locked asserts that the [TryLocker] is already locked.
17 | //
18 | // assert.IsDecreasing([]int{2, 1, 0})
19 | // assert.IsDecreasing([]float{2, 1})
20 | // assert.IsDecreasing([]string{"b", "a"})
21 | func Locked(locker TryLocker, msgAndArgs ...any) {}
22 |
23 | // Lockedf asserts that the [TryLocker] is already locked.
24 | //
25 | // assert.IsDecreasing([]int{2, 1, 0})
26 | // assert.IsDecreasing([]float{2, 1})
27 | // assert.IsDecreasing([]string{"b", "a"})
28 | func Lockedf(locker TryLocker, msg string, args ...any) {}
29 |
30 | // Unlocked asserts that the [TryLocker] is unlocked.
31 | //
32 | // assert.IsDecreasing([]int{2, 1, 0})
33 | // assert.IsDecreasing([]float{2, 1})
34 | // assert.IsDecreasing([]string{"b", "a"})
35 | func Unlocked(locker TryLocker, msgAndArgs ...any) {}
36 |
37 | // UnLockedf asserts that the [TryLocker] is unlocked.
38 | //
39 | // assert.IsDecreasing([]int{2, 1, 0})
40 | // assert.IsDecreasing([]float{2, 1})
41 | // assert.IsDecreasing([]string{"b", "a"})
42 | func Unlockedf(locker TryLocker, msg string, args ...any) {}
43 |
--------------------------------------------------------------------------------
/prod_http_assertions.go:
--------------------------------------------------------------------------------
1 | //go:build !assert
2 |
3 | package assert
4 |
5 | import (
6 | "net/http"
7 | "net/url"
8 | )
9 |
10 | // httpCode is a helper that returns HTTP code of the response. It returns -1 and
11 | // an error if building a new request fails.
12 | func httpCode(handler http.HandlerFunc, method, url string, values url.Values) {}
13 |
14 | // HTTPSuccess asserts that a specified handler returns a success status code.
15 | //
16 | // assert.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
17 | //
18 | // Returns whether the assertion was successful (true) or not (false).
19 | func HTTPSuccess(handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) {
20 | }
21 |
22 | // HTTPRedirect asserts that a specified handler returns a redirect status code.
23 | //
24 | // assert.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
25 | //
26 | // Returns whether the assertion was successful (true) or not (false).
27 | func HTTPRedirect(handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) {
28 | }
29 |
30 | // HTTPError asserts that a specified handler returns an error status code.
31 | //
32 | // assert.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
33 | //
34 | // Returns whether the assertion was successful (true) or not (false).
35 | func HTTPError(handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) {
36 | }
37 |
38 | // HTTPStatusCode asserts that a specified handler returns a specified status code.
39 | //
40 | // assert.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501)
41 | //
42 | // Returns whether the assertion was successful (true) or not (false).
43 | func HTTPStatusCode(handler http.HandlerFunc, method, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) {
44 | }
45 |
46 | // HTTPBody is a helper that returns HTTP body of the response. It returns
47 | // empty string if building a new request fails.
48 | func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) {}
49 |
50 | // HTTPBodyContains asserts that a specified handler returns a
51 | // body that contains a string.
52 | //
53 | // assert.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
54 | //
55 | // Returns whether the assertion was successful (true) or not (false).
56 | func HTTPBodyContains(handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) {
57 | }
58 |
59 | // HTTPBodyNotContains asserts that a specified handler returns a
60 | // body that does not contain a string.
61 | //
62 | // assert.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
63 | //
64 | // Returns whether the assertion was successful (true) or not (false).
65 | func HTTPBodyNotContains(handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) {
66 | }
67 |
--------------------------------------------------------------------------------
/tests/assertions_test.go:
--------------------------------------------------------------------------------
1 | package assert
2 |
3 | import (
4 | "errors"
5 | "io"
6 | "regexp"
7 | "sync"
8 | "testing"
9 |
10 | "github.com/negrel/assert"
11 | )
12 |
13 | type TestingT interface {
14 | Errorf(format string, args ...interface{})
15 | FailNow()
16 | }
17 |
18 | func requirePanics(t *testing.T, cb func()) {
19 | defer func() {
20 | if err := recover(); err == nil {
21 | t.Fatal("no panics")
22 | }
23 | }()
24 |
25 | cb()
26 | }
27 |
28 | func BenchmarkSliceIndexWithoutBoundCheckAssertions(b *testing.B) {
29 | get := func(slice []string, index int) string {
30 | return slice[index]
31 | }
32 | days := []string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}
33 |
34 | for i := 0; i < b.N; i++ {
35 | _ = get(days, i%len(days))
36 | }
37 | }
38 |
39 | func BenchmarkSliceIndexWithBoundCheckAssertions(b *testing.B) {
40 | get := func(slice []string, index int) string {
41 | assert.GreaterOrEqual(index, 0)
42 | assert.Less(index, len(slice))
43 | return slice[index]
44 | }
45 | days := []string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}
46 |
47 | for i := 0; i < b.N; i++ {
48 | _ = get(days, i%len(days))
49 | }
50 | }
51 |
52 | func TestAssertCondition(t *testing.T) {
53 | t.Run("ReturnsTrueOk", func(t *testing.T) {
54 | assert.Condition(func() bool {
55 | return true
56 | })
57 | })
58 |
59 | t.Run("ReturnsFalsePanics", func(t *testing.T) {
60 | requirePanics(t, func() {
61 | assert.Condition(func() bool {
62 | return false
63 | })
64 | })
65 | })
66 | }
67 |
68 | func TestAssertContains(t *testing.T) {
69 | t.Run("Substring", func(t *testing.T) {
70 | t.Run("PresentOk", func(t *testing.T) {
71 | assert.Contains("Hello World", "World")
72 | })
73 | t.Run("AbsentPanics", func(t *testing.T) {
74 | requirePanics(t, func() {
75 | assert.Contains("Hello World", "bye")
76 | })
77 | })
78 | })
79 |
80 | t.Run("SliceElement", func(t *testing.T) {
81 | t.Run("PresentOk", func(t *testing.T) {
82 | assert.Contains([]string{"Hello", "World"}, "World")
83 | })
84 | t.Run("AbsentPanics", func(t *testing.T) {
85 | requirePanics(t, func() {
86 | assert.Contains([]string{"Hello", "World"}, "bye")
87 | })
88 | })
89 | })
90 |
91 | t.Run("MapKey", func(t *testing.T) {
92 | t.Run("PresentOk", func(t *testing.T) {
93 | assert.Contains(map[string]string{"Hello": "World"}, "Hello")
94 | })
95 | t.Run("AbsentPanics", func(t *testing.T) {
96 | requirePanics(t, func() {
97 | assert.Contains(map[string]string{"Hello": "World"}, "bye")
98 | })
99 | })
100 | })
101 | }
102 |
103 | func TestAssertDirExists(t *testing.T) {
104 | t.Run("ExistOk", func(t *testing.T) {
105 | assert.DirExists(".")
106 | })
107 |
108 | t.Run("DoesNotExistPanics", func(t *testing.T) {
109 | requirePanics(t, func() {
110 | assert.DirExists("./nonexistentdir")
111 | })
112 | })
113 | }
114 |
115 | func TestAssertElementsMatch(t *testing.T) {
116 | t.Run("Array", func(t *testing.T) {
117 | t.Run("MatchOk", func(t *testing.T) {
118 | assert.ElementsMatch([3]int{1, 2, 3}, [3]int{3, 2, 1})
119 | })
120 | t.Run("NoMatchPanics", func(t *testing.T) {
121 | requirePanics(t, func() {
122 | assert.ElementsMatch([3]int{4, 5, 6}, [3]int{3, 2, 1})
123 | })
124 | })
125 | })
126 |
127 | t.Run("Slice", func(t *testing.T) {
128 | t.Run("MatchOk", func(t *testing.T) {
129 | assert.ElementsMatch([]int{1, 2, 3}, []int{3, 2, 1})
130 | })
131 | t.Run("NoMatchPanics", func(t *testing.T) {
132 | requirePanics(t, func() {
133 | assert.ElementsMatch([]int{4, 5, 6}, []int{3, 2, 1})
134 | })
135 | })
136 | })
137 | }
138 |
139 | func TestAssertEmpty(t *testing.T) {
140 | t.Run("Slice", func(t *testing.T) {
141 | t.Run("EmptyOk", func(t *testing.T) {
142 | assert.Empty([]string{})
143 | })
144 | t.Run("NotEmptyPanics", func(t *testing.T) {
145 | requirePanics(t, func() {
146 | assert.Empty([]string{""})
147 | })
148 | })
149 | })
150 |
151 | t.Run("Ptr", func(t *testing.T) {
152 | t.Run("EmptyOk", func(t *testing.T) {
153 | assert.Empty(nil)
154 | })
155 | t.Run("NotEmptyPanics", func(t *testing.T) {
156 | requirePanics(t, func() {
157 | assert.Empty(t)
158 | })
159 | })
160 | })
161 |
162 | t.Run("String", func(t *testing.T) {
163 | t.Run("EmptyOk", func(t *testing.T) {
164 | assert.Empty("")
165 | })
166 | t.Run("NotEmptyPanics", func(t *testing.T) {
167 | requirePanics(t, func() {
168 | assert.Empty("Hello world")
169 | })
170 | })
171 | })
172 |
173 | t.Run("Bool", func(t *testing.T) {
174 | t.Run("EmptyOk", func(t *testing.T) {
175 | assert.Empty(false)
176 | })
177 | t.Run("NotEmptyPanics", func(t *testing.T) {
178 | requirePanics(t, func() {
179 | assert.Empty(true)
180 | })
181 | })
182 | })
183 | }
184 |
185 | func TestAssertEqual(t *testing.T) {
186 | t.Run("Int", func(t *testing.T) {
187 | t.Run("EqualOk", func(t *testing.T) {
188 | assert.Equal(123, 123)
189 | })
190 | t.Run("NotEqualPanics", func(t *testing.T) {
191 | requirePanics(t, func() {
192 | assert.Equal(123, 456)
193 | })
194 | })
195 | })
196 |
197 | t.Run("Bool", func(t *testing.T) {
198 | t.Run("EqualOk", func(t *testing.T) {
199 | assert.Equal(false, false)
200 | })
201 | t.Run("NotEqualPanics", func(t *testing.T) {
202 | requirePanics(t, func() {
203 | assert.Equal(true, false)
204 | })
205 | })
206 | })
207 | }
208 |
209 | func TestAssertEqualError(t *testing.T) {
210 | t.Run("EqualOk", func(t *testing.T) {
211 | assert.EqualError(errors.New("foo"), "foo")
212 | })
213 | t.Run("NotEqualPanics", func(t *testing.T) {
214 | requirePanics(t, func() {
215 | assert.EqualError(errors.New("foo"), "bar")
216 | })
217 | })
218 | }
219 |
220 | func TestAssertEqualExportedValue(t *testing.T) {
221 | type S struct {
222 | private int
223 | Public bool
224 | }
225 |
226 | t.Run("EqualOk", func(t *testing.T) {
227 | expected := S{-1, true}
228 | actual := S{-3, true}
229 | assert.EqualExportedValues(expected, actual)
230 | })
231 | t.Run("NotEqualPanics", func(t *testing.T) {
232 | requirePanics(t, func() {
233 | expected := S{-1, true}
234 | actual := S{-1, false}
235 | assert.EqualExportedValues(expected, actual)
236 | })
237 | })
238 | }
239 |
240 | func TestAssertEqualValues(t *testing.T) {
241 | t.Run("EqualOk", func(t *testing.T) {
242 | assert.EqualValues(uint32(123), uint64(123))
243 | })
244 | t.Run("NotEqualPanics", func(t *testing.T) {
245 | requirePanics(t, func() {
246 | assert.EqualValues(uint32(123), uint32(456))
247 | })
248 | })
249 | }
250 |
251 | func TestAssertError(t *testing.T) {
252 | t.Run("ErrorOk", func(t *testing.T) {
253 | assert.Error(errors.New("foo"))
254 | })
255 | t.Run("NoErrorPanics", func(t *testing.T) {
256 | requirePanics(t, func() {
257 | assert.Error(nil)
258 | })
259 | })
260 | }
261 |
262 | func TestAssertErrorAs(t *testing.T) {
263 | t.Run("MatchOk", func(t *testing.T) {
264 | assert.ErrorAs(errors.Join(errors.New("foo"), io.EOF), &io.EOF)
265 | })
266 | t.Run("NoMatchOk", func(t *testing.T) {
267 | // ErrorAs never panics
268 | // requirePanics(t, func() {
269 | assert.ErrorAs(errors.Join(errors.New("foo"), errors.New("bar")), &io.EOF)
270 | // })
271 | })
272 | }
273 |
274 | func TestAssertErrorContains(t *testing.T) {
275 | t.Run("ContainsOk", func(t *testing.T) {
276 | assert.ErrorContains(errors.New("foobarqux"), "qux")
277 | })
278 | t.Run("DoesNotContainPanics", func(t *testing.T) {
279 | requirePanics(t, func() {
280 | assert.ErrorContains(errors.New("foobarqux"), "baz")
281 | })
282 | })
283 | }
284 |
285 | func TestAssertErrorIs(t *testing.T) {
286 | t.Run("MatchOk", func(t *testing.T) {
287 | assert.ErrorIs(errors.Join(errors.New("foo"), io.EOF), io.EOF)
288 | })
289 | t.Run("DoesNotMatchPanics", func(t *testing.T) {
290 | requirePanics(t, func() {
291 | assert.ErrorIs(errors.Join(errors.New("foo"), errors.New("bar")), io.EOF)
292 | })
293 | })
294 | }
295 |
296 | func TestAssertExactly(t *testing.T) {
297 | t.Run("EqualOk", func(t *testing.T) {
298 | assert.Exactly(uint32(123), uint32(123))
299 | })
300 | t.Run("NotEqualPanics", func(t *testing.T) {
301 | requirePanics(t, func() {
302 | assert.Exactly(uint32(123), uint64(123))
303 | })
304 | })
305 | }
306 |
307 | func TestAssertFalse(t *testing.T) {
308 | t.Run("TrueValuePanic", func(t *testing.T) {
309 | requirePanics(t, func() {
310 | assert.False(true)
311 | })
312 | })
313 |
314 | t.Run("FalseValueOk", func(t *testing.T) {
315 | assert.False(false)
316 | })
317 | }
318 |
319 | func TestAssertFileExists(t *testing.T) {
320 | t.Run("ExistsOk", func(t *testing.T) {
321 | assert.FileExists("assertions_test.go")
322 | })
323 |
324 | t.Run("DoesNotExistPanics", func(t *testing.T) {
325 | requirePanics(t, func() {
326 | assert.FileExists("nonexistentfile")
327 | })
328 | })
329 | }
330 |
331 | func TestAssertGreater(t *testing.T) {
332 | t.Run("GreaterOk", func(t *testing.T) {
333 | assert.Greater(2, 1)
334 | })
335 |
336 | t.Run("EqualPanics", func(t *testing.T) {
337 | requirePanics(t, func() {
338 | assert.Greater(2, 2)
339 | })
340 | })
341 |
342 | t.Run("LessPanics", func(t *testing.T) {
343 | requirePanics(t, func() {
344 | assert.Greater(1, 2)
345 | })
346 | })
347 | }
348 |
349 | func TestAssertGreaterOrEqual(t *testing.T) {
350 | t.Run("GreaterOk", func(t *testing.T) {
351 | assert.GreaterOrEqual(2, 1)
352 | })
353 |
354 | t.Run("EqualOk", func(t *testing.T) {
355 | assert.GreaterOrEqual(2, 2)
356 | })
357 |
358 | t.Run("LessPanics", func(t *testing.T) {
359 | requirePanics(t, func() {
360 | assert.GreaterOrEqual(1, 2)
361 | })
362 | })
363 | }
364 |
365 | func TestAssertImplements(t *testing.T) {
366 | t.Run("ImplementsOk", func(t *testing.T) {
367 | assert.Implements((*TestingT)(nil), t)
368 | })
369 |
370 | t.Run("DoesNotImplementPanics", func(t *testing.T) {
371 | requirePanics(t, func() {
372 | assert.Implements((interface{ abc() })(nil), t)
373 | })
374 | })
375 | }
376 |
377 | func TestAssertInDelta(t *testing.T) {
378 | t.Run("WithinOk", func(t *testing.T) {
379 | assert.InDelta(1, 3, 2)
380 | })
381 |
382 | t.Run("NotWithinPanics", func(t *testing.T) {
383 | requirePanics(t, func() {
384 | assert.InDelta(1, 3, 0)
385 | })
386 | })
387 | }
388 |
389 | func TestAssertIsDecreasing(t *testing.T) {
390 | t.Run("DecreasingOk", func(t *testing.T) {
391 | assert.IsDecreasing([]int{3, 2, 1})
392 | })
393 |
394 | t.Run("NotDecreasingPanics", func(t *testing.T) {
395 | requirePanics(t, func() {
396 | assert.IsDecreasing([]int{3, 2, 3})
397 | })
398 | })
399 | }
400 |
401 | func TestAssertIsIncreasing(t *testing.T) {
402 | t.Run("IncreasingOk", func(t *testing.T) {
403 | assert.IsIncreasing([]int{1, 2, 3})
404 | })
405 |
406 | t.Run("NotIncreasingPanics", func(t *testing.T) {
407 | requirePanics(t, func() {
408 | assert.IsIncreasing([]int{1, 2, 1})
409 | })
410 | })
411 | }
412 |
413 | func TestAssertIsNonDecreasing(t *testing.T) {
414 | t.Run("NotDecreasingOk", func(t *testing.T) {
415 | assert.IsNonDecreasing([]int{1, 2, 3})
416 | })
417 |
418 | t.Run("DecreasingPanics", func(t *testing.T) {
419 | requirePanics(t, func() {
420 | assert.IsNonDecreasing([]int{1, 2, 1})
421 | })
422 | })
423 | }
424 |
425 | func TestAssertIsNonIncreasing(t *testing.T) {
426 | t.Run("NonIncreasingOk", func(t *testing.T) {
427 | assert.IsNonIncreasing([]int{3, 2, 1})
428 | })
429 |
430 | t.Run("DecreasingPanics", func(t *testing.T) {
431 | requirePanics(t, func() {
432 | assert.IsNonIncreasing([]int{3, 2, 3})
433 | })
434 | })
435 | }
436 |
437 | func TestAssertIsType(t *testing.T) {
438 | t.Run("MatchOk", func(t *testing.T) {
439 | assert.IsType(int32(0), int32(0))
440 | })
441 |
442 | t.Run("NotMatchPanics", func(t *testing.T) {
443 | requirePanics(t, func() {
444 | assert.IsType(uint32(0), int32(0))
445 | })
446 | })
447 | }
448 |
449 | func TestAssertJSONEq(t *testing.T) {
450 | t.Run("EqualOk", func(t *testing.T) {
451 | assert.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
452 | })
453 |
454 | t.Run("NotMatchPanics", func(t *testing.T) {
455 | requirePanics(t, func() {
456 | assert.JSONEq(`{"bye": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
457 | })
458 | })
459 | }
460 |
461 | func TestAssertLen(t *testing.T) {
462 | t.Run("MatchOk", func(t *testing.T) {
463 | assert.Len([]int{1, 2, 3}, 3)
464 | })
465 |
466 | t.Run("NotMatchPanics", func(t *testing.T) {
467 | requirePanics(t, func() {
468 | assert.Len([]int{1, 2, 3}, 0)
469 | })
470 | })
471 | }
472 |
473 | func TestAssertLess(t *testing.T) {
474 | t.Run("LessOk", func(t *testing.T) {
475 | assert.Less(1, 2)
476 | })
477 |
478 | t.Run("EqualPanics", func(t *testing.T) {
479 | requirePanics(t, func() {
480 | assert.Less(2, 2)
481 | })
482 | })
483 |
484 | t.Run("GreaterPanics", func(t *testing.T) {
485 | requirePanics(t, func() {
486 | assert.Less(2, 1)
487 | })
488 | })
489 | }
490 |
491 | func TestAssertLessOrEqual(t *testing.T) {
492 | t.Run("LessOk", func(t *testing.T) {
493 | assert.LessOrEqual(1, 2)
494 | })
495 |
496 | t.Run("EqualOk", func(t *testing.T) {
497 | assert.LessOrEqual(2, 2)
498 | })
499 |
500 | t.Run("GreaterPanics", func(t *testing.T) {
501 | requirePanics(t, func() {
502 | assert.LessOrEqual(2, 1)
503 | })
504 | })
505 | }
506 |
507 | func TestAssertNegative(t *testing.T) {
508 | t.Run("NegativeOk", func(t *testing.T) {
509 | assert.Negative(-1)
510 | })
511 |
512 | t.Run("PositivePanics", func(t *testing.T) {
513 | requirePanics(t, func() {
514 | assert.Negative(2)
515 | })
516 | })
517 | }
518 |
519 | func TestAssertNil(t *testing.T) {
520 | t.Run("NilOk", func(t *testing.T) {
521 | assert.Nil(nil)
522 | })
523 |
524 | t.Run("NotNilPanics", func(t *testing.T) {
525 | requirePanics(t, func() {
526 | assert.Nil(t)
527 | })
528 | })
529 | }
530 |
531 | func TestAssertNoDirExists(t *testing.T) {
532 | t.Run("ExistPanics", func(t *testing.T) {
533 | requirePanics(t, func() {
534 | assert.NoDirExists(".")
535 | })
536 | })
537 |
538 | t.Run("DoesNotExistOk", func(t *testing.T) {
539 | assert.NoDirExists("./nonexistentdir")
540 | })
541 | }
542 |
543 | func TestAssertNoError(t *testing.T) {
544 | t.Run("NoErrorOk", func(t *testing.T) {
545 | requirePanics(t, func() {
546 | assert.NoError(errors.New("foo"))
547 | })
548 | })
549 |
550 | t.Run("ErrorPanics", func(t *testing.T) {
551 | assert.NoError(nil)
552 | })
553 | }
554 |
555 | func TestAssertNoFileExists(t *testing.T) {
556 | t.Run("ExistsPanics", func(t *testing.T) {
557 | requirePanics(t, func() {
558 | assert.NoFileExists("assertions_test.go")
559 | })
560 | })
561 |
562 | t.Run("DoesNotExistOk", func(t *testing.T) {
563 | assert.NoFileExists("nonexistentfile")
564 | })
565 | }
566 |
567 | func TestAssertNotContains(t *testing.T) {
568 | t.Run("Substring", func(t *testing.T) {
569 | t.Run("PresentPanics", func(t *testing.T) {
570 | requirePanics(t, func() {
571 | assert.NotContains("Hello World", "World")
572 | })
573 | })
574 | t.Run("AbsentOk", func(t *testing.T) {
575 | assert.NotContains("Hello World", "bye")
576 | })
577 | })
578 |
579 | t.Run("SliceElement", func(t *testing.T) {
580 | t.Run("PresentPanics", func(t *testing.T) {
581 | requirePanics(t, func() {
582 | assert.NotContains([]string{"Hello", "World"}, "World")
583 | })
584 | })
585 | t.Run("AbsentOk", func(t *testing.T) {
586 | assert.NotContains([]string{"Hello", "World"}, "bye")
587 | })
588 | })
589 |
590 | t.Run("MapKey", func(t *testing.T) {
591 | t.Run("PresentPanics", func(t *testing.T) {
592 | requirePanics(t, func() {
593 | assert.NotContains(map[string]string{"Hello": "World"}, "Hello")
594 | })
595 | })
596 | t.Run("AbsentOk", func(t *testing.T) {
597 | assert.NotContains(map[string]string{"Hello": "World"}, "bye")
598 | })
599 | })
600 | }
601 |
602 | func TestAssertNotEmpty(t *testing.T) {
603 | t.Run("Slice", func(t *testing.T) {
604 | t.Run("EmptyPanics", func(t *testing.T) {
605 | requirePanics(t, func() {
606 | assert.NotEmpty([]string{})
607 | })
608 | })
609 | t.Run("NotEmptyOk", func(t *testing.T) {
610 | assert.NotEmpty([]string{""})
611 | })
612 | })
613 |
614 | t.Run("Ptr", func(t *testing.T) {
615 | t.Run("EmptyPanics", func(t *testing.T) {
616 | requirePanics(t, func() {
617 | assert.NotEmpty(nil)
618 | })
619 | })
620 | t.Run("NotEmptyOk", func(t *testing.T) {
621 | assert.NotEmpty(t)
622 | })
623 | })
624 |
625 | t.Run("String", func(t *testing.T) {
626 | t.Run("EmptyPanics", func(t *testing.T) {
627 | requirePanics(t, func() {
628 | assert.NotEmpty("")
629 | })
630 | })
631 | t.Run("NotEmptyOk", func(t *testing.T) {
632 | assert.NotEmpty("Hello world")
633 | })
634 | })
635 |
636 | t.Run("Bool", func(t *testing.T) {
637 | t.Run("EmptyPanics", func(t *testing.T) {
638 | requirePanics(t, func() {
639 | assert.NotEmpty(false)
640 | })
641 | })
642 | t.Run("NotEmptyOk", func(t *testing.T) {
643 | assert.NotEmpty(true)
644 | })
645 | })
646 | }
647 |
648 | func TestAssertNotEqual(t *testing.T) {
649 | t.Run("Int", func(t *testing.T) {
650 | t.Run("EqualPanics", func(t *testing.T) {
651 | requirePanics(t, func() {
652 | assert.NotEqual(123, 123)
653 | })
654 | })
655 | t.Run("NotEqualOk", func(t *testing.T) {
656 | assert.NotEqual(123, 456)
657 | })
658 | })
659 |
660 | t.Run("Bool", func(t *testing.T) {
661 | t.Run("EqualPanics", func(t *testing.T) {
662 | requirePanics(t, func() {
663 | assert.NotEqual(false, false)
664 | })
665 | })
666 | t.Run("NotEqualOk", func(t *testing.T) {
667 | assert.NotEqual(true, false)
668 | })
669 | })
670 | }
671 |
672 | func TestAssertNotEqualValues(t *testing.T) {
673 | t.Run("EqualPanics", func(t *testing.T) {
674 | requirePanics(t, func() {
675 | assert.NotEqualValues(uint32(123), uint64(123))
676 | })
677 | })
678 | t.Run("NotEqualOk", func(t *testing.T) {
679 | assert.NotEqualValues(uint32(123), uint32(456))
680 | })
681 | }
682 |
683 | func TestAssertNotErrorIs(t *testing.T) {
684 | t.Run("MatchPanics", func(t *testing.T) {
685 | requirePanics(t, func() {
686 | assert.NotErrorIs(errors.Join(errors.New("foo"), io.EOF), io.EOF)
687 | })
688 | })
689 | t.Run("DoesNotMatchOk", func(t *testing.T) {
690 | assert.NotErrorIs(errors.Join(errors.New("foo"), errors.New("bar")), io.EOF)
691 | })
692 | }
693 |
694 | func TestAssertNotNil(t *testing.T) {
695 | t.Run("NilPanics", func(t *testing.T) {
696 | requirePanics(t, func() {
697 | assert.NotNil(nil)
698 | })
699 | })
700 |
701 | t.Run("NotNilOk", func(t *testing.T) {
702 | assert.NotNil(t)
703 | })
704 | }
705 |
706 | func TestAssertNotSame(t *testing.T) {
707 | t.Run("SamePanics", func(t *testing.T) {
708 | requirePanics(t, func() {
709 | assert.NotSame(t, t)
710 | })
711 | })
712 |
713 | t.Run("NotSameOk", func(t *testing.T) {
714 | var f *TestingT
715 | assert.NotSame(t, f)
716 | })
717 | }
718 |
719 | func TestAssertNotSubset(t *testing.T) {
720 | t.Run("SubsetPanics", func(t *testing.T) {
721 | requirePanics(t, func() {
722 | assert.NotSubset([]int{1, 3, 4}, []int{1, 3})
723 | })
724 | })
725 |
726 | t.Run("NotSubsetOk", func(t *testing.T) {
727 | assert.NotSubset([]int{1, 3, 4}, []int{1, 2})
728 | })
729 | }
730 |
731 | func TestAssertNotZero(t *testing.T) {
732 | t.Run("ZeroPanics", func(t *testing.T) {
733 | requirePanics(t, func() {
734 | assert.NotZero(false)
735 | })
736 | })
737 |
738 | t.Run("NotZeroOk", func(t *testing.T) {
739 | assert.NotZero(true)
740 | })
741 | }
742 |
743 | func TestAssertPositive(t *testing.T) {
744 | t.Run("PositiveOk", func(t *testing.T) {
745 | assert.Positive(1)
746 | })
747 |
748 | t.Run("NegativePanics", func(t *testing.T) {
749 | requirePanics(t, func() {
750 | assert.Positive(-2)
751 | })
752 | })
753 | }
754 |
755 | func TestAssertRegexp(t *testing.T) {
756 | t.Run("MatchOk", func(t *testing.T) {
757 | assert.Regexp(regexp.MustCompile(`\d+`), "123")
758 | })
759 |
760 | t.Run("NoMatchPanics", func(t *testing.T) {
761 | requirePanics(t, func() {
762 | assert.Regexp(regexp.MustCompile(`\d+`), "abc")
763 | })
764 | })
765 | }
766 |
767 | func TestAssertSame(t *testing.T) {
768 | t.Run("SameOk", func(t *testing.T) {
769 | assert.Same(t, t)
770 | })
771 |
772 | t.Run("NotSamePanics", func(t *testing.T) {
773 | requirePanics(t, func() {
774 | assert.Same(t, nil)
775 | })
776 | })
777 | }
778 |
779 | func TestAssertSubset(t *testing.T) {
780 | t.Run("SubsetOk", func(t *testing.T) {
781 | assert.Subset([]int{1, 3, 4}, []int{1, 3})
782 | })
783 |
784 | t.Run("NotSubsetPanics", func(t *testing.T) {
785 | requirePanics(t, func() {
786 | assert.Subset([]int{1, 3, 4}, []int{1, 2})
787 | })
788 | })
789 | }
790 |
791 | func TestAssertTrue(t *testing.T) {
792 | t.Run("FalseValuePanic", func(t *testing.T) {
793 | requirePanics(t, func() {
794 | assert.True(false)
795 | })
796 | })
797 |
798 | t.Run("TrueValueOk", func(t *testing.T) {
799 | assert.True(true)
800 | })
801 | }
802 |
803 | func TestAssertZero(t *testing.T) {
804 | t.Run("ZeroOk", func(t *testing.T) {
805 | assert.Zero(false)
806 | })
807 |
808 | t.Run("NotZeroOk", func(t *testing.T) {
809 | requirePanics(t, func() {
810 | assert.Zero(true)
811 | })
812 | })
813 | }
814 |
815 | func TestAssertLocked(t *testing.T) {
816 | t.Run("Locked", func(t *testing.T) {
817 | var mu sync.Mutex
818 | mu.Lock()
819 | assert.Locked(&mu)
820 | })
821 |
822 | t.Run("Unlocked", func(t *testing.T) {
823 | var mu sync.Mutex
824 | requirePanics(t, func() {
825 | assert.Locked(&mu)
826 | })
827 | })
828 | }
829 |
830 | func TestAssertUnlocked(t *testing.T) {
831 | t.Run("Unlocked", func(t *testing.T) {
832 | var mu sync.Mutex
833 | assert.Unlocked(&mu)
834 | })
835 |
836 | t.Run("Locked", func(t *testing.T) {
837 | var mu sync.Mutex
838 | mu.Lock()
839 | requirePanics(t, func() {
840 | assert.Unlocked(&mu)
841 | })
842 | })
843 | }
844 |
--------------------------------------------------------------------------------