...

Source file src/github.com/cilium/ebpf/internal/errors_test.go

Documentation: github.com/cilium/ebpf/internal

     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,  // \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  }
   124  

View as plain text