gotry/try/try_test.go
Theta-Dev 34a01c6279
All checks were successful
continuous-integration/drone/push Build is passing
Pass through try-compatible errors
2021-10-17 10:59:33 +02:00

338 lines
5.7 KiB
Go

package try
/*
try is a fork of lainio's err2 package
Copyright (c) 2019 Lainio, MIT License
https://github.com/lainio/err2
*/
import (
"errors"
"fmt"
"strings"
"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 Err
defer Return(&err)
Any(throw())
t.Fail() // If everything works we are never here
}
func TestAny_Error(t *testing.T) {
var err Err
defer Handle(&err, func() {})
Any(throw())
t.Fail() // If everything works we are never here
}
func panickingHandle() {
var err Err
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 Err) {}, func(v interface{}) {})
Any(wrongSignature())
}
func TestPanickingCatchAll(t *testing.T) {
defer func() {
if recover() != nil {
t.Error("panics should not fly thru")
}
}()
panickingCatchAll()
}
func panickingReturn() {
var err Err
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 Err) {})
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 Err) {
// fmt.Printf("error and defer handling:%s\n", err)
})
Any(throw())
t.Fail() // If everything works we are never here
}
func TestNewTryErr(t *testing.T) {
tryErr := NewErr("I f*cked up")
callStack := tryErr.CallStackString()
if !strings.HasPrefix(callStack, "ERROR: I f*cked up\n") {
fmt.Println("Call stack does not have prefix.\n" + callStack)
t.Fail()
}
if strings.Count(callStack, "\n") != 9 {
fmt.Println("Call stack is not 9 lines long.\n" +
fmt.Sprint(strings.Count(callStack, "\n")))
t.Fail()
}
}
func TestGetData(t *testing.T) {
tryErr := NewErr("I f*cked up")
tryErr.Annotate("test1")
tryErr.Annotate("test2")
data := tryErr.GetData()
if data.Msg != "I f*cked up" {
fmt.Println("wrong msg")
t.Fail()
}
if data.Annotations[0] != "test1" {
fmt.Println("wrong annotation#0")
t.Fail()
}
if data.Annotations[1] != "test2" {
fmt.Println("wrong annotation#1")
t.Fail()
}
if len(data.CallStack) != 3 {
fmt.Println("call stack length != 3, " + fmt.Sprint(len(data.CallStack)))
t.Fail()
}
}
func TestErrCompare(t *testing.T) {
err := errors.New("TestError")
tryErr := FromErr(err)
if !errors.Is(tryErr, err) {
t.Fail()
}
}
func TestReturnStd(t *testing.T) {
tf := func() (err error) {
defer ReturnStd(&err)
String(throw())
return
}
err := tf()
if err.Error() != "this is an ERROR" {
t.Fail()
}
}
func TestCheckTryErr(t *testing.T) {
testErr := NewErr("TestErr")
tf := func() (err Err) {
defer Return(&err)
Check(testErr)
return
}
err := tf()
if err != testErr {
t.Fail()
}
}
func ExampleReturn() {
var err Err
defer Return(&err)
Any(noThrow())
// Output:
}
func ExampleAnnotate() {
annotated := func() (err Err) {
defer Annotate(&err, "annotated")
Any(throw())
return err
}
err := annotated()
fmt.Printf("%v", err)
// Output: annotated: this is an ERROR
}
func ExampleAnnotate_deferStack() {
annotated := func() (err Err) {
defer Annotate(&err, "annotated 2nd")
defer Annotate(&err, "annotated 1st")
Any(throw())
return err
}
err := annotated()
fmt.Printf("%v", err)
// Output: annotated 1st: annotated 2nd: this is an ERROR
}
func ExampleHandle() {
doSomething := func(a, b int) (err Err) {
defer Handle(&err, func() {
err.Annotate(fmt.Sprintf("error with (%d, %d)", a, b))
})
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
}
}
}