github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/btf/strings_test.go (about) 1 package btf 2 3 import ( 4 "bytes" 5 "strings" 6 "testing" 7 8 "github.com/go-quicktest/qt" 9 ) 10 11 func TestStringTable(t *testing.T) { 12 const in = "\x00one\x00two\x00" 13 const splitIn = "three\x00four\x00" 14 15 st, err := readStringTable(strings.NewReader(in), nil) 16 if err != nil { 17 t.Fatal(err) 18 } 19 20 // Parse string table of split BTF 21 split, err := readStringTable(strings.NewReader(splitIn), st) 22 if err != nil { 23 t.Fatal(err) 24 } 25 26 testcases := []struct { 27 offset uint32 28 want string 29 }{ 30 {0, ""}, 31 {1, "one"}, 32 {5, "two"}, 33 {9, "three"}, 34 {15, "four"}, 35 } 36 37 for _, tc := range testcases { 38 have, err := split.Lookup(tc.offset) 39 if err != nil { 40 t.Errorf("Offset %d: %s", tc.offset, err) 41 continue 42 } 43 44 if have != tc.want { 45 t.Errorf("Offset %d: want %s but have %s", tc.offset, tc.want, have) 46 } 47 } 48 49 if _, err := st.Lookup(2); err == nil { 50 t.Error("No error when using offset pointing into middle of string") 51 } 52 53 // Make sure we reject bogus tables 54 _, err = readStringTable(strings.NewReader("\x00one"), nil) 55 if err == nil { 56 t.Fatal("Accepted non-terminated string") 57 } 58 59 _, err = readStringTable(strings.NewReader("one\x00"), nil) 60 if err == nil { 61 t.Fatal("Accepted non-empty first item") 62 } 63 } 64 65 func TestStringTableBuilder(t *testing.T) { 66 stb := newStringTableBuilder(0) 67 68 _, err := readStringTable(bytes.NewReader(stb.AppendEncoded(nil)), nil) 69 qt.Assert(t, qt.IsNil(err), qt.Commentf("Can't parse string table")) 70 71 _, err = stb.Add("foo\x00bar") 72 qt.Assert(t, qt.IsNotNil(err)) 73 74 empty, err := stb.Add("") 75 qt.Assert(t, qt.IsNil(err)) 76 qt.Assert(t, qt.Equals(empty, 0), qt.Commentf("The empty string is not at index 0")) 77 78 foo1, _ := stb.Add("foo") 79 foo2, _ := stb.Add("foo") 80 qt.Assert(t, qt.Equals(foo1, foo2), qt.Commentf("Adding the same string returns different offsets")) 81 82 table := stb.AppendEncoded(nil) 83 if n := bytes.Count(table, []byte("foo")); n != 1 { 84 t.Fatalf("Marshalled string table contains foo %d times instead of once", n) 85 } 86 87 _, err = readStringTable(bytes.NewReader(table), nil) 88 qt.Assert(t, qt.IsNil(err), qt.Commentf("Can't parse string table")) 89 } 90 91 func BenchmarkStringTableZeroLookup(b *testing.B) { 92 strings := vmlinuxTestdataSpec(b).strings 93 94 b.ResetTimer() 95 for i := 0; i < b.N; i++ { 96 s, err := strings.Lookup(0) 97 if err != nil { 98 b.Fatal(err) 99 } 100 if s != "" { 101 b.Fatal("0 is not the empty string") 102 } 103 } 104 } 105 106 func newStringTable(strings ...string) *stringTable { 107 offsets := make([]uint32, len(strings)) 108 109 var offset uint32 110 for i, str := range strings { 111 offsets[i] = offset 112 offset += uint32(len(str)) + 1 // account for NUL 113 } 114 115 return &stringTable{nil, offsets, 0, strings} 116 }