github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/btf/traversal_test.go (about) 1 package btf 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/go-quicktest/qt" 8 ) 9 10 func TestPostorderTraversal(t *testing.T) { 11 ptr := newCyclicalType(2).(*Pointer) 12 cst := ptr.Target.(*Const) 13 str := cst.Type.(*Struct) 14 15 t.Logf("%3v", ptr) 16 pending := []Type{str, cst, ptr} 17 visitInPostorder(ptr, nil, func(typ Type) bool { 18 qt.Assert(t, qt.Equals(typ, pending[0])) 19 pending = pending[1:] 20 return true 21 }) 22 qt.Assert(t, qt.HasLen(pending, 0)) 23 24 i := &Int{Name: "foo"} 25 // i appears twice at the same nesting depth. 26 arr := &Array{Index: i, Type: i} 27 seen := make(map[Type]bool) 28 visitInPostorder(arr, nil, func(typ Type) bool { 29 qt.Assert(t, qt.IsFalse(seen[typ])) 30 seen[typ] = true 31 return true 32 }) 33 qt.Assert(t, qt.IsTrue(seen[arr])) 34 qt.Assert(t, qt.IsTrue(seen[i])) 35 } 36 37 func TestPostorderTraversalVmlinux(t *testing.T) { 38 spec := vmlinuxTestdataSpec(t) 39 40 typ, err := spec.AnyTypeByName("gov_update_cpu_data") 41 if err != nil { 42 t.Fatal(err) 43 } 44 45 for _, typ := range []Type{typ} { 46 t.Run(fmt.Sprintf("%s", typ), func(t *testing.T) { 47 seen := make(map[Type]bool) 48 var last Type 49 visitInPostorder(typ, nil, func(typ Type) bool { 50 if seen[typ] { 51 t.Fatalf("%s visited twice", typ) 52 } 53 seen[typ] = true 54 last = typ 55 return true 56 }) 57 if last != typ { 58 t.Fatalf("Expected %s got %s as last type", typ, last) 59 } 60 61 children(typ, func(child *Type) bool { 62 qt.Check(t, qt.IsTrue(seen[*child]), qt.Commentf("missing child %s", *child)) 63 return true 64 }) 65 }) 66 } 67 } 68 69 func BenchmarkPostorderTraversal(b *testing.B) { 70 spec := vmlinuxTestdataSpec(b) 71 72 var fn *Func 73 err := spec.TypeByName("gov_update_cpu_data", &fn) 74 if err != nil { 75 b.Fatal(err) 76 } 77 78 for _, test := range []struct { 79 name string 80 typ Type 81 }{ 82 {"single type", &Int{}}, 83 {"cycle(1)", newCyclicalType(1)}, 84 {"cycle(10)", newCyclicalType(10)}, 85 {"gov_update_cpu_data", fn}, 86 } { 87 b.Logf("%10v", test.typ) 88 89 b.Run(test.name, func(b *testing.B) { 90 b.ReportAllocs() 91 for i := 0; i < b.N; i++ { 92 visitInPostorder(test.typ, nil, func(t Type) bool { return true }) 93 } 94 }) 95 } 96 }