github.com/cilium/ebpf@v0.16.0/internal/errors_test.go (about) 1 package internal 2 3 import ( 4 "errors" 5 "os" 6 "testing" 7 8 "github.com/go-quicktest/qt" 9 10 "github.com/cilium/ebpf/internal/unix" 11 ) 12 13 func TestVerifierErrorWhitespace(t *testing.T) { 14 b := []byte("unreachable insn 28") 15 b = append(b, 16 0xa, // \n 17 0xd, // \r 18 0x9, // \t 19 0x20, // space 20 0, 0, // trailing NUL bytes 21 ) 22 23 err := ErrorWithLog("frob", errors.New("test"), b) 24 qt.Assert(t, qt.Equals(err.Error(), "frob: test: unreachable insn 28")) 25 26 for _, log := range [][]byte{ 27 nil, 28 []byte("\x00"), 29 []byte(" "), 30 } { 31 err = ErrorWithLog("frob", errors.New("test"), log) 32 qt.Assert(t, qt.Equals(err.Error(), "frob: test"), qt.Commentf("empty log %q has incorrect format", log)) 33 } 34 } 35 36 func TestVerifierErrorWrapping(t *testing.T) { 37 ve := ErrorWithLog("frob", unix.ENOENT, nil) 38 qt.Assert(t, qt.ErrorIs(ve, unix.ENOENT), qt.Commentf("should wrap provided error")) 39 40 ve = ErrorWithLog("frob", unix.EINVAL, nil) 41 qt.Assert(t, qt.ErrorIs(ve, unix.EINVAL), qt.Commentf("should wrap provided error")) 42 43 ve = ErrorWithLog("frob", unix.EINVAL, []byte("foo")) 44 qt.Assert(t, qt.ErrorIs(ve, unix.EINVAL), qt.Commentf("should wrap provided error")) 45 qt.Assert(t, qt.StringContains(ve.Error(), "foo"), qt.Commentf("verifier log should appear in error string")) 46 47 ve = ErrorWithLog("frob", unix.ENOSPC, []byte("foo")) 48 qt.Assert(t, qt.ErrorIs(ve, unix.ENOSPC), qt.Commentf("should wrap provided error")) 49 qt.Assert(t, qt.StringContains(ve.Error(), "foo"), qt.Commentf("verifier log should appear in error string")) 50 } 51 52 func TestVerifierErrorSummary(t *testing.T) { 53 // Suppress the last line containing 'processed ... insns'. 54 errno524 := readErrorFromFile(t, "testdata/errno524.log") 55 qt.Assert(t, qt.StringContains(errno524.Error(), "JIT doesn't support bpf-to-bpf calls")) 56 qt.Assert(t, qt.Not(qt.StringContains(errno524.Error(), "processed 39 insns"))) 57 58 // Include the previous line if the current one starts with a tab. 59 invalidMember := readErrorFromFile(t, "testdata/invalid-member.log") 60 qt.Assert(t, qt.StringContains(invalidMember.Error(), "STRUCT task_struct size=7744 vlen=218: cpus_mask type_id=109 bitfield_size=0 bits_offset=7744 Invalid member")) 61 62 // Only include the last line. 63 issue43 := readErrorFromFile(t, "testdata/issue-43.log") 64 qt.Assert(t, qt.StringContains(issue43.Error(), "[11] FUNC helper_func2 type_id=10 vlen != 0")) 65 qt.Assert(t, qt.Not(qt.StringContains(issue43.Error(), "[10] FUNC_PROTO (anon) return=3 args=(3 arg)"))) 66 67 // Include instruction that caused invalid register access. 68 invalidR0 := readErrorFromFile(t, "testdata/invalid-R0.log") 69 qt.Assert(t, qt.StringContains(invalidR0.Error(), "0: (95) exit: R0 !read_ok")) 70 71 // Include symbol that doesn't match context type. 72 invalidCtx := readErrorFromFile(t, "testdata/invalid-ctx-access.log") 73 qt.Assert(t, qt.StringContains(invalidCtx.Error(), "func '__x64_sys_recvfrom' arg0 type FWD is not a struct: invalid bpf_context access off=0 size=8")) 74 } 75 76 func readErrorFromFile(tb testing.TB, file string) *VerifierError { 77 tb.Helper() 78 79 contents, err := os.ReadFile(file) 80 if err != nil { 81 tb.Fatal("Read file:", err) 82 } 83 84 return ErrorWithLog("file", unix.EINVAL, contents) 85 }