1 package internal
2
3 import (
4 "errors"
5 "fmt"
6 "os"
7 "syscall"
8 "testing"
9
10 "github.com/cilium/ebpf/internal/unix"
11 qt "github.com/frankban/quicktest"
12 )
13
14 func TestVerifierErrorWhitespace(t *testing.T) {
15 b := []byte("unreachable insn 28")
16 b = append(b,
17 0xa,
18 0xd,
19 0x9,
20 0x20,
21 0, 0,
22 )
23
24 err := ErrorWithLog(errors.New("test"), b)
25
26 want := "test: unreachable insn 28"
27 got := err.Error()
28
29 t.Log(got)
30
31 if want != got {
32 t.Fatalf("\nwant: %s\ngot: %s", want, got)
33 }
34 }
35
36 func TestVerifierError(t *testing.T) {
37 for _, test := range []struct {
38 name string
39 log string
40 }{
41 {"missing null", "foo"},
42 {"missing newline before null", "foo\x00"},
43 } {
44 t.Run("truncate "+test.name, func(t *testing.T) {
45 ve := ErrorWithLog(syscall.ENOENT, []byte(test.log))
46 qt.Assert(t, ve, qt.IsNotNil, qt.Commentf("should return error"))
47 qt.Assert(t, ve.Truncated, qt.IsTrue, qt.Commentf("should be truncated"))
48 })
49 }
50
51 ve := ErrorWithLog(syscall.ENOENT, nil)
52 qt.Assert(t, ve, qt.IsNotNil, qt.Commentf("should return error without log or logErr"))
53
54 errno524 := readErrorFromFile(t, "testdata/errno524.log")
55 t.Log(errno524)
56 qt.Assert(t, errno524.Error(), qt.Contains, "JIT doesn't support bpf-to-bpf calls")
57 qt.Assert(t, errno524.Error(), qt.Not(qt.Contains), "processed 39 insns")
58
59 invalidMember := readErrorFromFile(t, "testdata/invalid-member.log")
60 t.Log(invalidMember)
61 qt.Assert(t, invalidMember.Error(), qt.Contains, "STRUCT task_struct size=7744 vlen=218: cpus_mask type_id=109 bitfield_size=0 bits_offset=7744 Invalid member")
62
63 issue43 := readErrorFromFile(t, "testdata/issue-43.log")
64 t.Log(issue43)
65 qt.Assert(t, issue43.Error(), qt.Contains, "[11] FUNC helper_func2 type_id=10 vlen != 0")
66 qt.Assert(t, issue43.Error(), qt.Not(qt.Contains), "[10] FUNC_PROTO (anon) return=3 args=(3 arg)")
67
68 truncated := readErrorFromFile(t, "testdata/truncated.log")
69 t.Log(truncated)
70 qt.Assert(t, truncated.Truncated, qt.IsTrue)
71 qt.Assert(t, truncated.Error(), qt.Contains, "str_off: 3166088: str_len: 228")
72
73 invalidR0 := readErrorFromFile(t, "testdata/invalid-R0.log")
74 t.Log(invalidR0)
75 qt.Assert(t, invalidR0.Error(), qt.Contains, "0: (95) exit: R0 !read_ok")
76
77 invalidCtx := readErrorFromFile(t, "testdata/invalid-ctx-access.log")
78 t.Log(invalidCtx)
79 qt.Assert(t, invalidCtx.Error(), qt.Contains, "func '__x64_sys_recvfrom' arg0 type FWD is not a struct: invalid bpf_context access off=0 size=8")
80 }
81
82 func ExampleVerifierError() {
83 err := &VerifierError{
84 syscall.ENOSPC,
85 []string{"first", "second", "third"},
86 false,
87 }
88
89 fmt.Printf("With %%s: %s\n", err)
90 err.Truncated = true
91 fmt.Printf("With %%v and a truncated log: %v\n", err)
92 fmt.Printf("All log lines: %+v\n", err)
93 fmt.Printf("First line: %+1v\n", err)
94 fmt.Printf("Last two lines: %-2v\n", err)
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 }
113
114 func readErrorFromFile(tb testing.TB, file string) *VerifierError {
115 tb.Helper()
116
117 contents, err := os.ReadFile(file)
118 if err != nil {
119 tb.Fatal("Read file:", err)
120 }
121
122 return ErrorWithLog(unix.EINVAL, contents)
123 }
124
View as plain text