File: exception_test.go

package info (click to toggle)
elvish 0.21.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 6,372 kB
  • sloc: javascript: 236; sh: 130; python: 104; makefile: 88; xml: 9
file content (111 lines) | stat: -rw-r--r-- 2,913 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package eval_test

import (
	"errors"
	"reflect"
	"testing"
	"unsafe"

	"src.elv.sh/pkg/diag"
	. "src.elv.sh/pkg/eval"
	"src.elv.sh/pkg/testutil"

	"src.elv.sh/pkg/eval/vals"
	"src.elv.sh/pkg/persistent/hash"
	"src.elv.sh/pkg/tt"
)

func TestReason(t *testing.T) {
	err := errors.New("ordinary error")
	tt.Test(t, Reason,
		Args(err).Rets(err),
		Args(makeException(err)).Rets(err),
	)
}

func TestException(t *testing.T) {
	err := FailError{"error"}
	exc := makeException(err)
	vals.TestValue(t, exc).
		Kind("exception").
		Bool(false).
		Hash(hash.Pointer(unsafe.Pointer(reflect.ValueOf(exc).Pointer()))).
		Equal(exc).
		NotEqual(makeException(errors.New("error"))).
		AllKeys("reason", "stack-trace").
		Index("reason", err).
		IndexError("stack", vals.NoSuchKey("stack")).
		Repr("[^exception &reason=[^fail-error &content=error &type=fail] &stack-trace=<...>]")

	vals.TestValue(t, OK).
		Kind("exception").
		Bool(true).
		Repr("$ok")
}

func TestException_Show(t *testing.T) {
	for _, p := range []*string{
		ExceptionCauseStartMarker, ExceptionCauseEndMarker,
		&diag.ContextBodyStartMarker, &diag.ContextBodyEndMarker} {

		testutil.Set(t, p, "")
	}

	tt.Test(t, Exception.Show,
		It("supports exceptions with one traceback frame").
			Args(makeException(
				errors.New("internal error"),
				diag.NewContext("a.elv", "echo bad", diag.Ranging{From: 5, To: 8})), "").
			Rets(Dedent(`
				Exception: internal error
				  a.elv:1:6-8: echo bad`)),

		It("supports exceptions with multiple traceback frames").
			Args(makeException(
				errors.New("internal error"),
				diag.NewContext("a.elv", "echo bad", diag.Ranging{From: 5, To: 8}),
				diag.NewContext("b.elv", "use foo", diag.Ranging{From: 0, To: 7})), "").
			Rets(Dedent(`
				Exception: internal error
				  a.elv:1:6-8: echo bad
				  b.elv:1:1-7: use foo`)),

		It("supports traceback frames with multi-line body text").
			Args(makeException(
				errors.New("internal error"),
				diag.NewContext("a.elv", "echo ba\nd", diag.Ranging{From: 5, To: 9})), "").
			Rets(Dedent(`
				Exception: internal error
				  a.elv:1:6-2:1:
				    echo ba
				    d`)),
	)
}

func makeException(cause error, entries ...*diag.Context) Exception {
	return NewException(cause, makeStackTrace(entries...))
}

// Creates a new StackTrace, using the first entry as the head.
func makeStackTrace(entries ...*diag.Context) *StackTrace {
	var s *StackTrace
	for i := len(entries) - 1; i >= 0; i-- {
		s = &StackTrace{Head: entries[i], Next: s}
	}
	return s
}

func TestErrorMethods(t *testing.T) {
	tt.Test(t, error.Error,
		Args(makeException(errors.New("err"))).Rets("err"),

		Args(MakePipelineError([]Exception{
			makeException(errors.New("err1")),
			makeException(errors.New("err2"))})).Rets("(err1 | err2)"),

		Args(Return).Rets("return"),
		Args(Break).Rets("break"),
		Args(Continue).Rets("continue"),
		Args(Flow(1000)).Rets("!(BAD FLOW: 1000)"),
	)
}