github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/internal/testutils/feature.go (about) 1 package testutils 2 3 import ( 4 "errors" 5 "os" 6 "strings" 7 "testing" 8 9 "github.com/cilium/ebpf/internal" 10 ) 11 12 const ( 13 ignoreKernelVersionEnvVar = "EBPF_TEST_IGNORE_KERNEL_VERSION" 14 ) 15 16 func CheckFeatureTest(t *testing.T, fn func() error) { 17 checkFeatureTestError(t, fn()) 18 } 19 20 func checkFeatureTestError(t *testing.T, err error) { 21 if err == nil { 22 return 23 } 24 25 var ufe *internal.UnsupportedFeatureError 26 if errors.As(err, &ufe) { 27 checkKernelVersion(t, ufe) 28 } else { 29 t.Error("Feature test failed:", err) 30 } 31 } 32 33 func CheckFeatureMatrix[K comparable](t *testing.T, fm internal.FeatureMatrix[K]) { 34 t.Helper() 35 36 for key, ft := range fm { 37 t.Run(ft.Name, func(t *testing.T) { 38 checkFeatureTestError(t, fm.Result(key)) 39 }) 40 } 41 } 42 43 func SkipIfNotSupported(tb testing.TB, err error) { 44 tb.Helper() 45 46 if err == internal.ErrNotSupported { 47 tb.Fatal("Unwrapped ErrNotSupported") 48 } 49 50 var ufe *internal.UnsupportedFeatureError 51 if errors.As(err, &ufe) { 52 checkKernelVersion(tb, ufe) 53 tb.Skip(ufe.Error()) 54 } 55 if errors.Is(err, internal.ErrNotSupported) { 56 tb.Skip(err.Error()) 57 } 58 } 59 60 func checkKernelVersion(tb testing.TB, ufe *internal.UnsupportedFeatureError) { 61 if ufe.MinimumVersion.Unspecified() { 62 return 63 } 64 65 tb.Helper() 66 67 if ignoreKernelVersionCheck(tb.Name()) { 68 tb.Skipf("Ignoring error due to %s: %s", ignoreKernelVersionEnvVar, ufe.Error()) 69 } 70 71 if !isKernelLessThan(tb, ufe.MinimumVersion) { 72 tb.Fatalf("Feature '%s' isn't supported even though kernel is newer than %s", 73 ufe.Name, ufe.MinimumVersion) 74 } 75 } 76 77 func SkipOnOldKernel(tb testing.TB, minVersion, feature string) { 78 tb.Helper() 79 80 if IsKernelLessThan(tb, minVersion) { 81 tb.Skipf("Test requires at least kernel %s (due to missing %s)", minVersion, feature) 82 } 83 } 84 85 func IsKernelLessThan(tb testing.TB, minVersion string) bool { 86 tb.Helper() 87 88 minv, err := internal.NewVersion(minVersion) 89 if err != nil { 90 tb.Fatalf("Invalid version %s: %s", minVersion, err) 91 } 92 93 return isKernelLessThan(tb, minv) 94 } 95 96 func isKernelLessThan(tb testing.TB, minv internal.Version) bool { 97 tb.Helper() 98 99 if max := os.Getenv("CI_MAX_KERNEL_VERSION"); max != "" { 100 maxv, err := internal.NewVersion(max) 101 if err != nil { 102 tb.Fatalf("Invalid version %q in CI_MAX_KERNEL_VERSION: %s", max, err) 103 } 104 105 if maxv.Less(minv) { 106 tb.Fatalf("Test for %s will never execute on CI since %s is the most recent kernel", minv, maxv) 107 } 108 } 109 110 return kernelVersion(tb).Less(minv) 111 } 112 113 func kernelVersion(tb testing.TB) internal.Version { 114 tb.Helper() 115 116 v, err := internal.KernelVersion() 117 if err != nil { 118 tb.Fatal(err) 119 } 120 return v 121 } 122 123 // ignoreKernelVersionCheck checks if test name should be ignored for kernel version check by checking against environment var EBPF_TEST_IGNORE_KERNEL_VERSION. 124 // EBPF_TEST_IGNORE_KERNEL_VERSION is a comma (,) separated list of test names for which kernel version check should be ignored. 125 // 126 // eg: EBPF_TEST_IGNORE_KERNEL_VERSION=TestABC,TestXYZ 127 func ignoreKernelVersionCheck(tName string) bool { 128 tNames := os.Getenv(ignoreKernelVersionEnvVar) 129 if tNames == "" { 130 return false 131 } 132 133 ignored := strings.Split(tNames, ",") 134 for _, n := range ignored { 135 if strings.TrimSpace(n) == tName { 136 return true 137 } 138 } 139 return false 140 }