Skip to content

Commit 9b9a851

Browse files
authored
Merge pull request #22 from lainio/assert-no-error
assert no error
2 parents 5ddb751 + c7af375 commit 9b9a851

File tree

10 files changed

+241
-120
lines changed

10 files changed

+241
-120
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
### Version history
44

5+
##### 0.9.51
6+
- `flag` package support to set `err2` and `assert` package configuration
7+
- `err2.Catch` default mode is to log error
8+
- cleanup and refactoring, new tests and benchmarks
9+
510
##### 0.9.5 **mistake in build number: 5 < 41**
611
- `flag` package support to set `err2` and `assert` package configuration
712
- `err2.Catch` default mode is to log error

README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ little error handling. But most importantly, it doesn't help developers with
8787
> Automation is not just about efficiency but primarily about repeatability and
8888
> resilience. -- Gregor Hohpe
8989
90-
Automatic error propagation is crucial because it makes your code tolerant
91-
of the change. And, of course, it helps to make your code error-safe:
90+
Automatic error propagation is crucial because it makes your code change
91+
tolerant. And, of course, it helps to make your code error-safe:
9292

9393
![Never send a human to do a machine's job](https://www.magicalquote.com/wp-content/uploads/2013/10/Never-send-a-human-to-do-a-machines-job.jpg)
9494

@@ -242,7 +242,7 @@ notExist := try.Is(r2.err, plugin.ErrNotExist)
242242
**Note.** Any other error than `plugin.ErrNotExist` is treated as an real error:
243243
1. `try.Is` function first checks `if err == nil`, and if yes, it returns
244244
`false`.
245-
2. Then it checks if `errors.Is` == `plugin.ErrNotExist` and if yes, it returns
245+
2. Then it checks if `errors.Is(err, plugin.ErrNotExist)` and if yes, it returns
246246
`true`.
247247
3. Finally, it calls `try.To` for the non nil error, and we already know what then
248248
happens: nearest `err2.Handle` gets it first.
@@ -527,10 +527,11 @@ Please see the full version history from [CHANGELOG](./CHANGELOG.md).
527527
528528
### Latest Release
529529
530-
##### 0.9.51
531-
- `flag` package support to set `err2` and `assert` package configuration
532-
- `err2.Catch` default mode is to log error
533-
- cleanup and refactoring, new tests and benchmarks
530+
##### 0.9.52
531+
- `err2.Stderr` helpers for `Catch/Handle` to direct auto-logging + snippets
532+
- `assert` package `Shorter` `Longer` helpers for automatic messages
533+
- `asserter` package remove deprecated slow reflection based funcs
534+
- cleanup and refactoring for sample apps
534535
535536
### Upcoming releases
536537

assert/assert.go

Lines changed: 124 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,10 @@ var (
146146
)
147147

148148
const (
149-
assertionMsg = "assertion violation"
150-
gotWantFmt = ": got '%v', want '%v'"
149+
assertionMsg = "assertion violation"
150+
gotWantFmt = ": got '%v', want '%v'"
151+
gotWantLongerFmt = ": got '%v', should be longer than '%v'"
152+
gotWantShorterFmt = ": got '%v', should be shorter than '%v'"
151153
)
152154

153155
// PushTester sets the current testing context for default asserter. This must
@@ -400,6 +402,32 @@ func Len(obj string, length int, a ...any) {
400402
}
401403
}
402404

405+
// Longer asserts that the length of the string is longer to the given. If not
406+
// it panics/errors (current Asserter) with the given message. Note! This is
407+
// reasonably fast but not as fast as 'That' because of lacking inlining for the
408+
// current implementation of Go's type parametric functions.
409+
func Longer(obj string, length int, a ...any) {
410+
l := len(obj)
411+
412+
if l > length {
413+
defMsg := fmt.Sprintf(assertionMsg+gotWantLongerFmt, l, length)
414+
Default().reportAssertionFault(defMsg, a...)
415+
}
416+
}
417+
418+
// Shorter asserts that the length of the string is shorter to the given. If not
419+
// it panics/errors (current Asserter) with the given message. Note! This is
420+
// reasonably fast but not as fast as 'That' because of lacking inlining for the
421+
// current implementation of Go's type parametric functions.
422+
func Shorter(obj string, length int, a ...any) {
423+
l := len(obj)
424+
425+
if l <= length {
426+
defMsg := fmt.Sprintf(assertionMsg+gotWantShorterFmt, l, length)
427+
Default().reportAssertionFault(defMsg, a...)
428+
}
429+
}
430+
403431
// SLen asserts that the length of the slice is equal to the given. If not it
404432
// panics/errors (current Asserter) with the given message. Note! This is
405433
// reasonably fast but not as fast as 'That' because of lacking inlining for the
@@ -413,6 +441,32 @@ func SLen[S ~[]T, T any](obj S, length int, a ...any) {
413441
}
414442
}
415443

444+
// SLonger asserts that the length of the slice is equal to the given. If not it
445+
// panics/errors (current Asserter) with the given message. Note! This is
446+
// reasonably fast but not as fast as 'That' because of lacking inlining for the
447+
// current implementation of Go's type parametric functions.
448+
func SLonger[S ~[]T, T any](obj S, length int, a ...any) {
449+
l := len(obj)
450+
451+
if l <= length {
452+
defMsg := fmt.Sprintf(assertionMsg+gotWantLongerFmt, l, length)
453+
Default().reportAssertionFault(defMsg, a...)
454+
}
455+
}
456+
457+
// SShorter asserts that the length of the slice is equal to the given. If not it
458+
// panics/errors (current Asserter) with the given message. Note! This is
459+
// reasonably fast but not as fast as 'That' because of lacking inlining for the
460+
// current implementation of Go's type parametric functions.
461+
func SShorter[S ~[]T, T any](obj S, length int, a ...any) {
462+
l := len(obj)
463+
464+
if l >= length {
465+
defMsg := fmt.Sprintf(assertionMsg+gotWantShorterFmt, l, length)
466+
Default().reportAssertionFault(defMsg, a...)
467+
}
468+
}
469+
416470
// MLen asserts that the length of the map is equal to the given. If not it
417471
// panics/errors (current Asserter) with the given message. Note! This is
418472
// reasonably fast but not as fast as 'That' because of lacking inlining for the
@@ -426,6 +480,71 @@ func MLen[M ~map[T]U, T comparable, U any](obj M, length int, a ...any) {
426480
}
427481
}
428482

483+
// MLonger asserts that the length of the map is longer to the given. If not it
484+
// panics/errors (current Asserter) with the given message. Note! This is
485+
// reasonably fast but not as fast as 'That' because of lacking inlining for the
486+
// current implementation of Go's type parametric functions.
487+
func MLonger[M ~map[T]U, T comparable, U any](obj M, length int, a ...any) {
488+
l := len(obj)
489+
490+
if l <= length {
491+
defMsg := fmt.Sprintf(assertionMsg+gotWantLongerFmt, l, length)
492+
Default().reportAssertionFault(defMsg, a...)
493+
}
494+
}
495+
496+
// MShorter asserts that the length of the map is shorter to the given. If not
497+
// it panics/errors (current Asserter) with the given message. Note! This is
498+
// reasonably fast but not as fast as 'That' because of lacking inlining for the
499+
// current implementation of Go's type parametric functions.
500+
func MShorter[M ~map[T]U, T comparable, U any](obj M, length int, a ...any) {
501+
l := len(obj)
502+
503+
if l >= length {
504+
defMsg := fmt.Sprintf(assertionMsg+gotWantShorterFmt, l, length)
505+
Default().reportAssertionFault(defMsg, a...)
506+
}
507+
}
508+
509+
// CLen asserts that the length of the chan is equal to the given. If not it
510+
// panics/errors (current Asserter) with the given message. Note! This is
511+
// reasonably fast but not as fast as 'That' because of lacking inlining for the
512+
// current implementation of Go's type parametric functions.
513+
func CLen[C ~chan T, T any](obj C, length int, a ...any) {
514+
l := len(obj)
515+
516+
if l != length {
517+
defMsg := fmt.Sprintf(assertionMsg+gotWantFmt, l, length)
518+
Default().reportAssertionFault(defMsg, a...)
519+
}
520+
}
521+
522+
// CLonger asserts that the length of the chan is longer to the given. If not it
523+
// panics/errors (current Asserter) with the given message. Note! This is
524+
// reasonably fast but not as fast as 'That' because of lacking inlining for the
525+
// current implementation of Go's type parametric functions.
526+
func CLonger[C ~chan T, T any](obj C, length int, a ...any) {
527+
l := len(obj)
528+
529+
if l <= length {
530+
defMsg := fmt.Sprintf(assertionMsg+gotWantLongerFmt, l, length)
531+
Default().reportAssertionFault(defMsg, a...)
532+
}
533+
}
534+
535+
// CShorter asserts that the length of the chan is shorter to the given. If not
536+
// it panics/errors (current Asserter) with the given message. Note! This is
537+
// reasonably fast but not as fast as 'That' because of lacking inlining for the
538+
// current implementation of Go's type parametric functions.
539+
func CShorter[C ~chan T, T any](obj C, length int, a ...any) {
540+
l := len(obj)
541+
542+
if l >= length {
543+
defMsg := fmt.Sprintf(assertionMsg+gotWantShorterFmt, l, length)
544+
Default().reportAssertionFault(defMsg, a...)
545+
}
546+
}
547+
429548
// MKeyExists asserts that the map key exists. If not it panics/errors (current
430549
// Asserter) with the given message.
431550
func MKeyExists[M ~map[T]U, T comparable, U any](obj M, key T, a ...any) (val U) {
@@ -485,7 +604,9 @@ func MNotEmpty[M ~map[T]U, T comparable, U any](obj M, a ...any) {
485604

486605
// NoError asserts that the error is nil. If is not it panics with the given
487606
// formatting string. Thanks to inlining, the performance penalty is equal to a
488-
// single 'if-statement' that is almost nothing.
607+
// single 'if-statement' that is almost nothing. Note. We recommend that you
608+
// prefer try.To every case even in tests because they work exactly the same
609+
// during the test runs and you can use same code for both: runtime and tests.
489610
func NoError(err error, a ...any) {
490611
if err != nil {
491612
defMsg := "NoError:" + assertionMsg + ": " + err.Error()

assert/assert_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,32 @@ func ExampleZero() {
152152
// Output: sample: assert_test.go:146: ExampleZero.func1(): assertion violation: got '1', want (== '0')
153153
}
154154

155+
func ExampleSLonger() {
156+
sample := func(b []byte) (err error) {
157+
defer err2.Handle(&err, "sample")
158+
159+
assert.SLonger(b, 0) // ok
160+
assert.SLonger(b, 1) // not ok
161+
return err
162+
}
163+
err := sample([]byte{01}) // len = 1
164+
fmt.Printf("%v", err)
165+
// Output: sample: assert_test.go:160: ExampleSLonger.func1(): assertion violation: got '1', should be longer than '1'
166+
}
167+
168+
func ExampleMShorter() {
169+
sample := func(b map[byte]byte) (err error) {
170+
defer err2.Handle(&err, "sample")
171+
172+
assert.MShorter(b, 1) // ok
173+
assert.MShorter(b, 0) // not ok
174+
return err
175+
}
176+
err := sample(map[byte]byte{01: 01}) // len = 1
177+
fmt.Printf("%v", err)
178+
// Output: sample: assert_test.go:172: ExampleMShorter.func1(): assertion violation: got '1', should be shorter than '1'
179+
}
180+
155181
func assertZero(i int) {
156182
assert.Zero(i)
157183
}

assert/asserter.go

Lines changed: 0 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -47,109 +47,6 @@ const (
4747
// every test log or result output has 4 spaces in them
4848
const officialTestOutputPrefix = " "
4949

50-
// NoImplementation always fails with no implementation.
51-
// Deprecated: use e.g. assert.NotImplemented(), only default asserter is used.
52-
func (asserter Asserter) NoImplementation(a ...any) {
53-
asserter.reportAssertionFault("not implemented", a...)
54-
}
55-
56-
// True asserts that term is true. If not it panics with the given formatting
57-
// string. Note! This and Truef are the most performant of all the assertion
58-
// functions.
59-
// Deprecated: use e.g. assert.That(), only default asserter is used.
60-
func (asserter Asserter) True(term bool, a ...any) {
61-
if !term {
62-
asserter.reportAssertionFault("assertion fault", a...)
63-
}
64-
}
65-
66-
// Truef asserts that term is true. If not it panics with the given formatting
67-
// string.
68-
// Deprecated: use e.g. assert.That(), only default asserter is used.
69-
func (asserter Asserter) Truef(term bool, format string, a ...any) {
70-
if !term {
71-
if asserter.hasStackTrace() {
72-
debug.PrintStack(1)
73-
}
74-
asserter.reportPanic(fmt.Sprintf(format, a...))
75-
}
76-
}
77-
78-
// Len asserts that length of the object is equal to given. If not it
79-
// panics/errors (current Asserter) with the given msg. Note! This is very slow
80-
// (before we have generics). If you need performance use EqualInt. It's not so
81-
// convenient, though.
82-
// Deprecated: use e.g. assert.Len(), only default asserter is used.
83-
func (asserter Asserter) Len(obj any, length int, a ...any) {
84-
ok, l := getLen(obj)
85-
if !ok {
86-
panic("cannot get length")
87-
}
88-
89-
if l != length {
90-
defMsg := fmt.Sprintf("got %d, want %d", l, length)
91-
asserter.reportAssertionFault(defMsg, a...)
92-
}
93-
}
94-
95-
// EqualInt asserts that integers are equal. If not it panics/errors (current
96-
// Asserter) with the given msg.
97-
// Deprecated: use e.g. assert.Equal(), only default asserter is used.
98-
func (asserter Asserter) EqualInt(val, want int, a ...any) {
99-
if want != val {
100-
defMsg := fmt.Sprintf("got %d, want %d", val, want)
101-
asserter.reportAssertionFault(defMsg, a...)
102-
}
103-
}
104-
105-
// Lenf asserts that length of the object is equal to given. If not it
106-
// panics/errors (current Asserter) with the given msg. Note! This is very slow
107-
// (before we have generics). If you need performance use EqualInt. It's not so
108-
// convenient, though.
109-
// Deprecated: use e.g. assert.Len(), only default asserter is used.
110-
func (asserter Asserter) Lenf(obj any, length int, format string, a ...any) {
111-
args := combineArgs(format, a)
112-
asserter.Len(obj, length, args...)
113-
}
114-
115-
// Empty asserts that length of the object is zero. If not it panics with the
116-
// given formatting string. Note! This is slow.
117-
// Deprecated: use e.g. assert.Empty(), only default asserter is used.
118-
func (asserter Asserter) Empty(obj any, msg ...any) {
119-
ok, l := getLen(obj)
120-
if !ok {
121-
panic("cannot get length")
122-
}
123-
124-
if l != 0 {
125-
defMsg := fmt.Sprintf("got %d, want == 0", l)
126-
asserter.reportAssertionFault(defMsg, msg...)
127-
}
128-
}
129-
130-
// NotEmptyf asserts that length of the object greater than zero. If not it
131-
// panics with the given formatting string. Note! This is slow.
132-
// Deprecated: use e.g. assert.NotEmpty(), only default asserter is used.
133-
func (asserter Asserter) NotEmptyf(obj any, format string, msg ...any) {
134-
args := combineArgs(format, msg)
135-
asserter.Empty(obj, args...)
136-
}
137-
138-
// NotEmpty asserts that length of the object greater than zero. If not it
139-
// panics with the given formatting string. Note! This is slow.
140-
// Deprecated: use e.g. assert.NotEmpty(), only default asserter is used.
141-
func (asserter Asserter) NotEmpty(obj any, msg ...any) {
142-
ok, l := getLen(obj)
143-
if !ok {
144-
panic("cannot get length")
145-
}
146-
147-
if l == 0 {
148-
defMsg := fmt.Sprintf("got %d, want > 0", l)
149-
asserter.reportAssertionFault(defMsg, msg...)
150-
}
151-
}
152-
15350
func (asserter Asserter) reportAssertionFault(defaultMsg string, a ...any) {
15451
if asserter.hasStackTrace() {
15552
if asserter.isUnitTesting() {

0 commit comments

Comments
 (0)