github.com/cilium/ebpf@v0.10.0/btf/strings_test.go (about)

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