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  }