src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/eval/exception_test.go (about) 1 package eval_test 2 3 import ( 4 "errors" 5 "reflect" 6 "testing" 7 "unsafe" 8 9 "src.elv.sh/pkg/diag" 10 . "src.elv.sh/pkg/eval" 11 "src.elv.sh/pkg/testutil" 12 13 "src.elv.sh/pkg/eval/vals" 14 "src.elv.sh/pkg/persistent/hash" 15 "src.elv.sh/pkg/tt" 16 ) 17 18 func TestReason(t *testing.T) { 19 err := errors.New("ordinary error") 20 tt.Test(t, Reason, 21 Args(err).Rets(err), 22 Args(makeException(err)).Rets(err), 23 ) 24 } 25 26 func TestException(t *testing.T) { 27 err := FailError{"error"} 28 exc := makeException(err) 29 vals.TestValue(t, exc). 30 Kind("exception"). 31 Bool(false). 32 Hash(hash.Pointer(unsafe.Pointer(reflect.ValueOf(exc).Pointer()))). 33 Equal(exc). 34 NotEqual(makeException(errors.New("error"))). 35 AllKeys("reason", "stack-trace"). 36 Index("reason", err). 37 IndexError("stack", vals.NoSuchKey("stack")). 38 Repr("[^exception &reason=[^fail-error &content=error &type=fail] &stack-trace=<...>]") 39 40 vals.TestValue(t, OK). 41 Kind("exception"). 42 Bool(true). 43 Repr("$ok") 44 } 45 46 func TestException_Show(t *testing.T) { 47 for _, p := range []*string{ 48 ExceptionCauseStartMarker, ExceptionCauseEndMarker, 49 &diag.ContextBodyStartMarker, &diag.ContextBodyEndMarker} { 50 51 testutil.Set(t, p, "") 52 } 53 54 tt.Test(t, Exception.Show, 55 It("supports exceptions with one traceback frame"). 56 Args(makeException( 57 errors.New("internal error"), 58 diag.NewContext("a.elv", "echo bad", diag.Ranging{From: 5, To: 8})), ""). 59 Rets(Dedent(` 60 Exception: internal error 61 a.elv:1:6-8: echo bad`)), 62 63 It("supports exceptions with multiple traceback frames"). 64 Args(makeException( 65 errors.New("internal error"), 66 diag.NewContext("a.elv", "echo bad", diag.Ranging{From: 5, To: 8}), 67 diag.NewContext("b.elv", "use foo", diag.Ranging{From: 0, To: 7})), ""). 68 Rets(Dedent(` 69 Exception: internal error 70 a.elv:1:6-8: echo bad 71 b.elv:1:1-7: use foo`)), 72 73 It("supports traceback frames with multi-line body text"). 74 Args(makeException( 75 errors.New("internal error"), 76 diag.NewContext("a.elv", "echo ba\nd", diag.Ranging{From: 5, To: 9})), ""). 77 Rets(Dedent(` 78 Exception: internal error 79 a.elv:1:6-2:1: 80 echo ba 81 d`)), 82 ) 83 } 84 85 func makeException(cause error, entries ...*diag.Context) Exception { 86 return NewException(cause, makeStackTrace(entries...)) 87 } 88 89 // Creates a new StackTrace, using the first entry as the head. 90 func makeStackTrace(entries ...*diag.Context) *StackTrace { 91 var s *StackTrace 92 for i := len(entries) - 1; i >= 0; i-- { 93 s = &StackTrace{Head: entries[i], Next: s} 94 } 95 return s 96 } 97 98 func TestErrorMethods(t *testing.T) { 99 tt.Test(t, error.Error, 100 Args(makeException(errors.New("err"))).Rets("err"), 101 102 Args(MakePipelineError([]Exception{ 103 makeException(errors.New("err1")), 104 makeException(errors.New("err2"))})).Rets("(err1 | err2)"), 105 106 Args(Return).Rets("return"), 107 Args(Break).Rets("break"), 108 Args(Continue).Rets("continue"), 109 Args(Flow(1000)).Rets("!(BAD FLOW: 1000)"), 110 ) 111 }