diff options
author | Valery Piashchynski <[email protected]> | 2020-10-22 10:57:48 +0300 |
---|---|---|
committer | Valery Piashchynski <[email protected]> | 2020-10-22 10:57:48 +0300 |
commit | 77726578db6d539b151a5c4d36300b11e54a0bee (patch) | |
tree | 9c5247e50900bf6ab1b6ea2d54d11046be600ae0 /errors/errors_test.go | |
parent | 1102a5c1faf17ec3153b62b25749fafafd2c98eb (diff) |
A
Diffstat (limited to 'errors/errors_test.go')
-rwxr-xr-x | errors/errors_test.go | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/errors/errors_test.go b/errors/errors_test.go new file mode 100755 index 00000000..50d3d422 --- /dev/null +++ b/errors/errors_test.go @@ -0,0 +1,177 @@ +// +build !debug + +package errors + +import ( + "fmt" + "io" + "os" + "os/exec" + "testing" +) + +func TestDebug(t *testing.T) { + // Test with -tags debug to run the tests in debug_test.go + cmd := exec.Command("go", "test", "-tags", "prod") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + t.Fatalf("external go test failed: %v", err) + } +} + +func TestMarshal(t *testing.T) { + // Single error. No user is set, so we will have a zero-length field inside. + e1 := E(Op("Get"), Network, "caching in progress") + + // Nested error. + e2 := E(Op("Read"), Undefined, e1) + + b := MarshalError(e2) + e3 := UnmarshalError(b) + + in := e2.(*Error) + out := e3.(*Error) + + // Compare elementwise. + if in.Op != out.Op { + t.Errorf("expected Op %q; got %q", in.Op, out.Op) + } + if in.Kind != out.Kind { + t.Errorf("expected kind %d; got %d", in.Kind, out.Kind) + } + // Note that error will have lost type information, so just check its Error string. + if in.Err.Error() != out.Err.Error() { + t.Errorf("expected Err %q; got %q", in.Err, out.Err) + } +} + +func TestSeparator(t *testing.T) { + defer func(prev string) { + Separator = prev + }(Separator) + Separator = ":: " + + // Single error. No user is set, so we will have a zero-length field inside. + e1 := E(Op("Get"), Network, "network error") + + // Nested error. + e2 := E(Op("Get"), Network, e1) + + want := "Get: Network error:: Get: network error" + if errorAsString(e2) != want { + t.Errorf("expected %q; got %q", want, e2) + } +} + +func TestDoesNotChangePreviousError(t *testing.T) { + err := E(Network) + err2 := E(Op("I will NOT modify err"), err) + + expected := "I will NOT modify err: Network error" + if errorAsString(err2) != expected { + t.Fatalf("Expected %q, got %q", expected, err2) + } + kind := err.(*Error).Kind + if kind != Network { + t.Fatalf("Expected kind %v, got %v", Network, kind) + } +} + +//func TestNoArgs(t *testing.T) { +// defer func() { +// err := recover() +// if err == nil { +// t.Fatal("E() did not panic") +// } +// }() +// _ = E() +//} + +type matchTest struct { + err1, err2 error + matched bool +} + +const ( + op = Op("Op") + op1 = Op("Op1") + op2 = Op("Op2") +) + +var matchTests = []matchTest{ + // Errors not of type *Error fail outright. + {nil, nil, false}, + {io.EOF, io.EOF, false}, + {E(io.EOF), io.EOF, false}, + {io.EOF, E(io.EOF), false}, + // Success. We can drop fields from the first argument and still match. + {E(io.EOF), E(io.EOF), true}, + {E(op, Other, io.EOF), E(op, Other, io.EOF), true}, + {E(op, Other, io.EOF, "test"), E(op, Other, io.EOF, "test", "test"), true}, + {E(op, Other), E(op, Other, io.EOF, "test", "test"), true}, + {E(op), E(op, Other, io.EOF, "test", "test"), true}, + // Failure. + {E(io.EOF), E(io.ErrClosedPipe), false}, + {E(op1), E(op2), false}, + {E(Other), E(Network), false}, + {E("test"), E("test1"), false}, + {E(fmt.Errorf("error")), E(fmt.Errorf("error1")), false}, + {E(op, Other, io.EOF, "test", "test1"), E(op, Other, io.EOF, "test", "test"), false}, + {E("test", Str("something")), E("test"), false}, // Test nil error on rhs. + // Nested *Errors. + {E(op1, E("test")), E(op1, "1", E(op2, "2", "test")), true}, + {E(op1, "test"), E(op1, "1", E(op2, "2", "test")), false}, + {E(op1, E("test")), E(op1, "1", Str(E(op2, "2", "test").Error())), false}, +} + +func TestMatch(t *testing.T) { + for _, test := range matchTests { + matched := Match(test.err1, test.err2) + if matched != test.matched { + t.Errorf("Match(%q, %q)=%t; want %t", test.err1, test.err2, matched, test.matched) + } + } +} + +type kindTest struct { + err error + kind Kind + want bool +} + +var kindTests = []kindTest{ + //Non-Error errors. + {nil, Network, false}, + {Str("not an *Error"), Network, false}, + + // Basic comparisons. + {E(Network), Network, true}, + {E(Test), Network, false}, + {E("no kind"), Network, false}, + {E("no kind"), Other, false}, + + // Nested *Error values. + {E("Nesting", E(Network)), Network, true}, + {E("Nesting", E(Test)), Network, false}, + {E("Nesting", E("no kind")), Network, false}, + {E("Nesting", E("no kind")), Other, false}, +} + +func TestKind(t *testing.T) { + for _, test := range kindTests { + got := Is(test.kind, test.err) + if got != test.want { + t.Errorf("Is(%q, %q)=%t; want %t", test.kind, test.err, got, test.want) + } + } +} + +func errorAsString(err error) string { + if e, ok := err.(*Error); ok { + e2 := *e + e2.stack = stack{} + return e2.Error() + } + return err.Error() +} |