package try /* try is a fork of lainio's err2 package Copyright (c) 2019 Lainio, MIT License https://github.com/lainio/err2 */ import ( "fmt" "testing" ) func throw() (string, error) { return "", fmt.Errorf("this is an ERROR") } func twoStrNoThrow() (string, string, error) { return "test", "test", nil } func noThrow() (string, error) { return "test", nil } func wrongSignature() (int, int) { return 0, 0 } func recursion(a int) int { if a == 0 { return 0 } s, err := noThrow() Check(err) _ = s return a + recursion(a-1) } func recursionWithErrorCheck(a int) (int, error) { if a == 0 { return 0, nil } s, err := noThrow() if err != nil { return 0, err } _ = s v, err := recursionWithErrorCheck(a - 1) if err != nil { return 0, err } return a + v, nil } func noErr() error { return nil } func TestAny_noError(t *testing.T) { d := Any(noThrow()) if d[0].(string) != "test" { t.Fail() } d = Any(twoStrNoThrow()) if d[0].(string) != "test" || d[1].(string) != "test" { t.Fail() } } func TestDefault_Error(t *testing.T) { var err error defer Return(&err) Any(throw()) t.Fail() // If everything works we are never here } func TestAny_Error(t *testing.T) { var err error defer Handle(&err, func() {}) Any(throw()) t.Fail() // If everything works we are never here } func panickingHandle() { var err error defer Handle(&err, func() {}) Any(wrongSignature()) } func TestPanickingCarryOn_Handle(t *testing.T) { defer func() { if recover() == nil { t.Error("panics should went thru when not our errors") } }() panickingHandle() } func panickingCatchAll() { defer CatchAll(func(err error) {}, func(v interface{}) {}) Any(wrongSignature()) } func TestPanickingCatchAll(t *testing.T) { defer func() { if recover() != nil { t.Error("panics should not fly thru") } }() panickingCatchAll() } func panickingCatchTrace() { defer CatchTrace(func(err error) {}) Any(wrongSignature()) } func TestPanickingCatchTrace(t *testing.T) { defer func() { if recover() != nil { t.Error("panics should NOT carry on when tracing") } }() panickingCatchTrace() } func panickingReturn() { var err error defer Return(&err) Any(wrongSignature()) } func TestPanicking_Return(t *testing.T) { defer func() { if recover() == nil { t.Error("panics should carry on") } }() panickingReturn() } func panickingCatch() { defer Catch(func(err error) {}) Any(wrongSignature()) } func TestPanicking_Catch(t *testing.T) { defer func() { if recover() == nil { t.Error("panics should carry on") } }() panickingCatch() } func TestCatch_Error(t *testing.T) { defer Catch(func(err error) { //fmt.Printf("error and defer handling:%s\n", err) }) Any(throw()) t.Fail() // If everything works we are never here } func ExampleReturn() { var err error defer Return(&err) Any(noThrow()) // Output: } func ExampleAnnotate() { annotated := func() (err error) { defer Annotate("annotated", &err) Any(throw()) return err } err := annotated() fmt.Printf("%v", err) // Output: annotated: this is an ERROR } func ExampleReturnf() { annotated := func() (err error) { defer Returnf(&err, "annotated: %s", "err2") Any(throw()) return err } err := annotated() fmt.Printf("%v", err) // Output: annotated: err2: this is an ERROR } func ExampleAnnotate_deferStack() { annotated := func() (err error) { defer Annotate("annotated 2nd", &err) defer Annotate("annotated 1st", &err) Any(throw()) return err } err := annotated() fmt.Printf("%v", err) // Output: annotated 2nd: annotated 1st: this is an ERROR } func ExampleHandle() { doSomething := func(a, b int) (err error) { defer Handle(&err, func() { err = fmt.Errorf("error with (%d, %d): %v", a, b, err) }) Any(throw()) return err } err := doSomething(1, 2) fmt.Printf("%v", err) // Output: error with (1, 2): this is an ERROR } func BenchmarkOldErrorCheckingWithIfClause(b *testing.B) { for n := 0; n < b.N; n++ { _, err := noThrow() if err != nil { return } } } func BenchmarkAny(b *testing.B) { for n := 0; n < b.N; n++ { Any(noThrow()) } } func BenchmarkAny_ErrVar(b *testing.B) { for n := 0; n < b.N; n++ { _, err := noThrow() Any(err) } } func BenchmarkCheckInsideCall(b *testing.B) { for n := 0; n < b.N; n++ { Check(noErr()) } } func BenchmarkCheckVarCall(b *testing.B) { for n := 0; n < b.N; n++ { err := noErr() Check(err) } } func BenchmarkCheck_ErrVar(b *testing.B) { for n := 0; n < b.N; n++ { _, err := noThrow() Check(err) } } func BenchmarkRecursionNoCheck_NotRelated(b *testing.B) { for n := 0; n < b.N; n++ { _ = recursion(100) } } func BenchmarkRecursionWithErrorCheck_NotRelated(b *testing.B) { for n := 0; n < b.N; n++ { _, err := recursionWithErrorCheck(100) if err != nil { return } } }