github.com/dylandreimerink/gobpfld@v0.6.1-0.20220205171531-e79c330ad608/cmd/testsuite/integration/global_data_test.go (about)

     1  //go:build bpftests
     2  // +build bpftests
     3  
     4  package integration
     5  
     6  import (
     7  	"bytes"
     8  	"embed"
     9  	"math"
    10  	"os"
    11  	"strconv"
    12  	"testing"
    13  
    14  	"github.com/dylandreimerink/gobpfld"
    15  	"github.com/dylandreimerink/gobpfld/bpftypes"
    16  	"github.com/dylandreimerink/gobpfld/kernelsupport"
    17  )
    18  
    19  // ebpf contains all files in the ebpf sub-dir
    20  //go:embed ebpf
    21  var ebpf embed.FS
    22  
    23  // This intergration test, tests the loaders capability to relocate global data
    24  func TestIntegrationGlobalData(t *testing.T) {
    25  	if !kernelsupport.CurrentFeatures.Misc.Has(kernelsupport.KFeatGlobalData) {
    26  		t.Skip("skipping, current kernel version doesn't support global data")
    27  	}
    28  
    29  	elfFileBytes, err := ebpf.ReadFile("ebpf/global_data_test")
    30  	if err != nil {
    31  		t.Fatalf("error opening ELF file: %s\n", err.Error())
    32  	}
    33  
    34  	elf, err := gobpfld.LoadProgramFromELF(bytes.NewReader(elfFileBytes), gobpfld.ELFParseSettings{
    35  		TruncateNames: true,
    36  	})
    37  	if err != nil {
    38  		t.Fatalf("error while reading ELF file: %s\n", err.Error())
    39  	}
    40  
    41  	prog := elf.Programs["load_static_data"].(*gobpfld.ProgramXDP)
    42  	log, err := prog.Load(gobpfld.ProgXDPLoadOpts{
    43  		VerifierLogLevel: bpftypes.BPFLogLevelVerbose,
    44  	})
    45  	if err != nil {
    46  		prog.DecodeToReader(os.Stdout)
    47  		t.Log(log)
    48  		t.Fatalf("error while loading program: %s\n", err.Error())
    49  	}
    50  
    51  	_, err = prog.XDPTestProgram(gobpfld.TestXDPProgSettings{
    52  		Repeat: 1,
    53  		Data:   make([]byte, 20),
    54  	})
    55  	if err != nil {
    56  		t.Fatalf("error while testing program: %s\n", err.Error())
    57  	}
    58  
    59  	numTests := []struct {
    60  		Name     string
    61  		Index    uint32
    62  		Expected uint64
    63  	}{
    64  		{Name: "relocate .bss reference", Index: 0, Expected: 0},
    65  		{Name: "relocate .data reference", Index: 1, Expected: 42},
    66  		{Name: "relocate .rodata reference", Index: 2, Expected: 24},
    67  		{Name: "relocate .bss reference", Index: 3, Expected: 0},
    68  		{Name: "relocate .data reference", Index: 4, Expected: 0xffeeff},
    69  		{Name: "relocate .rodata reference", Index: 5, Expected: 0xabab},
    70  		{Name: "relocate .bss reference", Index: 6, Expected: 1234},
    71  		{Name: "relocate .bss reference", Index: 7, Expected: 0},
    72  		{Name: "relocate .rodata reference", Index: 8, Expected: 0xab},
    73  		{Name: "relocate .rodata reference", Index: 9, Expected: 0x1111111111111111},
    74  		{Name: "relocate .rodata reference", Index: 10, Expected: math.MaxUint64},
    75  	}
    76  
    77  	resultNumber := elf.Maps["result_number"].(*gobpfld.ArrayMap)
    78  	for _, test := range numTests {
    79  		t.Run("num_"+test.Name+"_"+strconv.Itoa(int(test.Index)), func(t *testing.T) {
    80  			var v uint64
    81  			err = resultNumber.Get(test.Index, &v)
    82  			if err != nil {
    83  				t.Fatalf("map get: %s", err.Error())
    84  			}
    85  
    86  			if v != test.Expected {
    87  				t.Fatalf("expected: '%d', got: '%d'", test.Expected, v)
    88  			}
    89  		})
    90  	}
    91  
    92  	strTests := []struct {
    93  		Name     string
    94  		Index    uint32
    95  		Expected string
    96  	}{
    97  		{Name: "relocate .rodata reference", Index: 0, Expected: "abcdefghijklmnopqrstuvwxyz"},
    98  		{Name: "relocate .data reference", Index: 1, Expected: "abcdefghijklmnopqrstuvwxyz"},
    99  		{Name: "relocate .bss reference", Index: 2, Expected: ""},
   100  		{Name: "relocate .data reference", Index: 3, Expected: "abcdexghijklmnopqrstuvwxyz"},
   101  		{Name: "relocate .bss reference", Index: 4, Expected: "\x00\x00hello"},
   102  	}
   103  
   104  	resultStr := elf.Maps["result_string"].(*gobpfld.ArrayMap)
   105  	for _, test := range strTests {
   106  		t.Run("num_"+test.Name+"_"+strconv.Itoa(int(test.Index)), func(t *testing.T) {
   107  			v := make([]byte, 32)
   108  			err = resultStr.Get(test.Index, &v)
   109  			if err != nil {
   110  				t.Fatalf("map get: %s", err.Error())
   111  			}
   112  
   113  			vStr := string(bytes.TrimRight(v, "\x00"))
   114  			if vStr != test.Expected {
   115  				t.Fatalf("expected: '%s', got: '%s'", test.Expected, vStr)
   116  			}
   117  		})
   118  	}
   119  
   120  	type foo struct {
   121  		a uint8
   122  		b uint32
   123  		c uint64
   124  	}
   125  
   126  	structTests := []struct {
   127  		Name     string
   128  		Index    uint32
   129  		Expected foo
   130  	}{
   131  		{Name: "relocate .rodata reference", Index: 0, Expected: foo{a: 42, b: 0xfefeefef, c: 0x1111111111111111}},
   132  		{Name: "relocate .bss reference", Index: 1, Expected: foo{}},
   133  		{Name: "relocate .rodata reference", Index: 2, Expected: foo{}},
   134  		{Name: "relocate .data reference", Index: 3, Expected: foo{a: 41, b: 0xeeeeefef, c: 0x2111111111111111}},
   135  	}
   136  
   137  	resultStruct := elf.Maps["result_struct"].(*gobpfld.ArrayMap)
   138  	for _, test := range structTests {
   139  		t.Run("struct_"+test.Name+"_"+strconv.Itoa(int(test.Index)), func(t *testing.T) {
   140  			var v foo
   141  			err = resultStruct.Get(test.Index, &v)
   142  			if err != nil {
   143  				t.Fatalf("map get: %s", err.Error())
   144  			}
   145  
   146  			if v != test.Expected {
   147  				t.Fatalf("expected: '%v', got: '%v'", test.Expected, v)
   148  			}
   149  		})
   150  	}
   151  }