Skip to content

Commit

Permalink
info: make it harder to add backwards incompatible API
Browse files Browse the repository at this point in the history
People adding new fields to the Info API always get tripped up by
how it works. Add a comment which explains why it works the way it does.
Also add a test which ensures that new exported fields are only
added when they are really warranted.

Signed-off-by: Lorenz Bauer <lmb@isovalent.com>
  • Loading branch information
lmb committed Jul 15, 2024
1 parent 88e8f88 commit 7e18818
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 0 deletions.
17 changes: 17 additions & 0 deletions info.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,23 @@ import (
"github.com/cilium/ebpf/internal/unix"
)

// The *Info structs expose metadata about a program or map. Most
// fields are exposed via a getter:
//
// func (*MapInfo) ID() (MapID, bool)
//
// This is because the metadata available changes based on kernel version.
// The second boolean return value indicates whether a particular field is
// available on the current kernel.
//
// Always add new metadata as such a getter, unless you can somehow get the
// value of the field on all supported kernels. Also document which version
// a particular field first appeared in.
//
// Some metadata is a buffer which needs additional parsing. In this case,
// store the undecoded data in the Info struct and provide a getter which
// decodes it when necessary. See ProgramInfo.Instructions for an example.

// MapInfo describes a map.
type MapInfo struct {
Type MapType
Expand Down
33 changes: 33 additions & 0 deletions info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"os"
"reflect"
"strings"
"testing"

Expand Down Expand Up @@ -436,3 +437,35 @@ func TestProgInfoExtBTF(t *testing.T) {
}
}
}

func TestInfoExportedFields(t *testing.T) {
// It is highly unlikely that you should be adjusting the asserts below.
// See the comment at the top of info.go for more information.

var names []string
for _, field := range reflect.VisibleFields(reflect.TypeOf(MapInfo{})) {
if field.IsExported() {
names = append(names, field.Name)
}
}
qt.Assert(t, qt.ContentEquals(names, []string{
"Type",
"KeySize",
"ValueSize",
"MaxEntries",
"Flags",
"Name",
}))

names = nil
for _, field := range reflect.VisibleFields(reflect.TypeOf(ProgramInfo{})) {
if field.IsExported() {
names = append(names, field.Name)
}
}
qt.Assert(t, qt.ContentEquals(names, []string{
"Type",
"Tag",
"Name",
}))
}

0 comments on commit 7e18818

Please sign in to comment.