github.com/kubeshark/ebpf@v0.9.2/internal/errors_test.go (about) 1 package internal 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 "syscall" 8 "testing" 9 10 qt "github.com/frankban/quicktest" 11 "github.com/kubeshark/ebpf/internal/unix" 12 ) 13 14 func TestVerifierErrorWhitespace(t *testing.T) { 15 b := []byte("unreachable insn 28") 16 b = append(b, 17 0xa, // \n 18 0xd, // \r 19 0x9, // \t 20 0x20, // space 21 0, 0, // trailing NUL bytes 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 // Output: With %s: no space left on device: third (2 line(s) omitted) 97 // With %v and a truncated log: no space left on device: second: third (truncated, 1 line(s) omitted) 98 // All log lines: no space left on device: 99 // first 100 // second 101 // third 102 // (truncated) 103 // First line: no space left on device: 104 // first 105 // (2 line(s) omitted) 106 // (truncated) 107 // Last two lines: no space left on device: 108 // (1 line(s) omitted) 109 // second 110 // third 111 // (truncated) 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 }