github.com/cilium/ebpf@v0.10.0/btf/marshal_test.go (about) 1 package btf 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "math/rand" 7 "testing" 8 9 "github.com/cilium/ebpf/internal" 10 "github.com/cilium/ebpf/internal/testutils" 11 12 qt "github.com/frankban/quicktest" 13 ) 14 15 func TestBuild(t *testing.T) { 16 typ := &Int{ 17 Name: "foo", 18 Size: 2, 19 Encoding: Signed | Char, 20 } 21 22 enc := newEncoder(encoderOptions{ByteOrder: internal.NativeEndian}, nil) 23 24 id, err := enc.Add(typ) 25 qt.Assert(t, err, qt.IsNil) 26 qt.Assert(t, id, qt.Equals, TypeID(1), qt.Commentf("First non-void type doesn't get id 1")) 27 28 id, err = enc.Add(typ) 29 qt.Assert(t, err, qt.IsNil) 30 qt.Assert(t, id, qt.Equals, TypeID(1), qt.Commentf("Adding a type twice returns different ids")) 31 32 raw, err := enc.Encode() 33 qt.Assert(t, err, qt.IsNil, qt.Commentf("Build returned an error")) 34 35 spec, err := loadRawSpec(bytes.NewReader(raw), internal.NativeEndian, nil, nil) 36 qt.Assert(t, err, qt.IsNil, qt.Commentf("Couldn't parse BTF")) 37 38 have, err := spec.AnyTypeByName("foo") 39 qt.Assert(t, err, qt.IsNil) 40 qt.Assert(t, have, qt.DeepEquals, typ) 41 } 42 43 func TestRoundtripVMlinux(t *testing.T) { 44 types := vmlinuxSpec(t).types 45 46 // Randomize the order to force different permutations of walking the type 47 // graph. 48 rand.Shuffle(len(types), func(i, j int) { 49 types[i], types[j] = types[j], types[i] 50 }) 51 52 b := newEncoder(kernelEncoderOptions, nil) 53 54 for i, typ := range types { 55 _, err := b.Add(typ) 56 qt.Assert(t, err, qt.IsNil, qt.Commentf("add type #%d: %s", i, typ)) 57 58 if b.nextID >= 65_000 { 59 // IDs exceeding math.MaxUint16 can trigger a bug when loading BTF. 60 // This can be removed once the patch lands. 61 // See https://lore.kernel.org/bpf/20220909092107.3035-1-oss@lmb.io/ 62 break 63 } 64 } 65 66 nStr := len(b.strings.strings) 67 nTypes := len(types) 68 t.Log(nStr, "strings", nTypes, "types") 69 t.Log(float64(nStr)/float64(nTypes), "avg strings per type") 70 71 raw, err := b.Encode() 72 qt.Assert(t, err, qt.IsNil, qt.Commentf("build BTF")) 73 74 rebuilt, err := loadRawSpec(bytes.NewReader(raw), binary.LittleEndian, nil, nil) 75 qt.Assert(t, err, qt.IsNil, qt.Commentf("round tripping BTF failed")) 76 77 h, err := NewHandle(rebuilt) 78 testutils.SkipIfNotSupported(t, err) 79 qt.Assert(t, err, qt.IsNil, qt.Commentf("loading rebuilt BTF failed")) 80 h.Close() 81 } 82 83 func BenchmarkBuildVmlinux(b *testing.B) { 84 spec := vmlinuxTestdataSpec(b) 85 86 b.ReportAllocs() 87 b.ResetTimer() 88 89 types := spec.types 90 strings := spec.strings 91 92 for i := 0; i < b.N; i++ { 93 enc := newEncoder(encoderOptions{ByteOrder: internal.NativeEndian}, newStringTableBuilderFromTable(strings)) 94 95 for _, typ := range types { 96 if _, err := enc.Add(typ); err != nil { 97 b.Fatal(err) 98 } 99 } 100 101 _, err := enc.Encode() 102 if err != nil { 103 b.Fatal(err) 104 } 105 } 106 }