diff --git a/test/integration/app_test.go b/test/integration/app_test.go new file mode 100644 index 000000000..dea18f513 --- /dev/null +++ b/test/integration/app_test.go @@ -0,0 +1,90 @@ +//go:build integration_tests +// +build integration_tests + +package integration + +import ( + "bytes" + "context" + "io" + "testing" + "time" + + "github.com/kong/kubernetes-testing-framework/pkg/clusters" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + appGoCounterKustomize = "https://github.com/bpfman/bpfman/examples/config/default/go-app-counter/?timeout=120&ref=main" + appGoCounterUserspaceNs = "go-application-counter" + appGoCounterUserspaceDsName = "go-application-counter-ds" +) + +func TestApplicationGoCounter(t *testing.T) { + t.Log("deploying target required for uprobe counter program") + require.NoError(t, clusters.KustomizeDeployForCluster(ctx, env.Cluster(), targetKustomize)) + addCleanup(func(context.Context) error { + cleanupLog("cleaning up target program") + return clusters.KustomizeDeleteForCluster(ctx, env.Cluster(), targetKustomize) + }) + + t.Log("waiting for go target userspace daemon to be available") + require.Eventually(t, func() bool { + daemon, err := env.Cluster().Client().AppsV1().DaemonSets(targetUserspaceNs).Get(ctx, targetUserspaceDsName, metav1.GetOptions{}) + require.NoError(t, err) + return daemon.Status.DesiredNumberScheduled == daemon.Status.NumberAvailable + }, + // Wait 5 minutes since cosign is slow, https://github.com/bpfman/bpfman/issues/1043 + 5*time.Minute, 10*time.Second) + + t.Log("deploying application counter program") + require.NoError(t, clusters.KustomizeDeployForCluster(ctx, env.Cluster(), appGoCounterKustomize)) + addCleanup(func(context.Context) error { + cleanupLog("cleaning up application counter program") + return clusters.KustomizeDeleteForCluster(ctx, env.Cluster(), appGoCounterKustomize) + }) + + t.Log("waiting for go application counter userspace daemon to be available") + require.Eventually(t, func() bool { + daemon, err := env.Cluster().Client().AppsV1().DaemonSets(appGoCounterUserspaceNs).Get(ctx, appGoCounterUserspaceDsName, metav1.GetOptions{}) + require.NoError(t, err) + return daemon.Status.DesiredNumberScheduled == daemon.Status.NumberAvailable + }, + // Wait 5 minutes since cosign is slow, https://github.com/bpfman/bpfman/issues/1043 + 5*time.Minute, 10*time.Second) + + pods, err := env.Cluster().Client().CoreV1().Pods(appGoCounterUserspaceNs).List(ctx, metav1.ListOptions{LabelSelector: "name=go-application-counter"}) + require.NoError(t, err) + goAppCounterPod := pods.Items[0] + + req := env.Cluster().Client().CoreV1().Pods(appGoCounterUserspaceNs).GetLogs(goAppCounterPod.Name, &corev1.PodLogOptions{}) + + checkFunctions := []func(t *testing.T, output *bytes.Buffer) bool{ + doKprobeCheck, + doTcCheck, + doTracepointCheck, + doUprobeCheck, + doXdpCheck, + } + + for _, f := range checkFunctions { + require.Eventually(t, func() bool { + logs, err := req.Stream(ctx) + require.NoError(t, err) + defer logs.Close() + output := new(bytes.Buffer) + _, err = io.Copy(output, logs) + require.NoError(t, err) + t.Logf("counter pod log %s", output.String()) + + if f(t, output) { + return true + } + + return false + }, 30*time.Second, time.Second) + } + +} diff --git a/test/integration/common.go b/test/integration/common.go new file mode 100644 index 000000000..21547ced1 --- /dev/null +++ b/test/integration/common.go @@ -0,0 +1,70 @@ +//go:build integration_tests +// +build integration_tests + +package integration + +import ( + "bytes" + "regexp" + "strconv" + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func doKprobeCheck(t *testing.T, output *bytes.Buffer) bool { + want := regexp.MustCompile(`Kprobe count: ([0-9]+)`) + matches := want.FindAllStringSubmatch(output.String(), -1) + if len(matches) >= 1 && len(matches[0]) >= 2 { + count, err := strconv.Atoi(matches[0][1]) + require.NoError(t, err) + if count > 0 { + t.Logf("counted %d application executions so far, BPF program is functioning", count) + return true + } + } + return false +} + +func doTcCheck(t *testing.T, output *bytes.Buffer) bool { + if strings.Contains(output.String(), "packets received") && strings.Contains(output.String(), "bytes received") { + return true + } + return false +} + +func doTracepointCheck(t *testing.T, output *bytes.Buffer) bool { + want := regexp.MustCompile(`SIGUSR1 signal count: ([0-9]+)`) + matches := want.FindAllStringSubmatch(output.String(), -1) + if len(matches) >= 1 && len(matches[0]) >= 2 { + count, err := strconv.Atoi(matches[0][1]) + require.NoError(t, err) + if count > 0 { + t.Logf("counted %d SIGUSR1 signals so far, BPF program is functioning", count) + return true + } + } + return false +} + +func doUprobeCheck(t *testing.T, output *bytes.Buffer) bool { + want := regexp.MustCompile(`Uprobe count: ([0-9]+)`) + matches := want.FindAllStringSubmatch(output.String(), -1) + if len(matches) >= 1 && len(matches[0]) >= 2 { + count, err := strconv.Atoi(matches[0][1]) + require.NoError(t, err) + if count > 0 { + t.Logf("counted %d uprobe executions so far, BPF program is functioning", count) + return true + } + } + return false +} + +func doXdpCheck(t *testing.T, output *bytes.Buffer) bool { + if strings.Contains(output.String(), "packets received") && strings.Contains(output.String(), "bytes received") { + return true + } + return false +} diff --git a/test/integration/kprobe_test.go b/test/integration/kprobe_test.go index 9c9e89709..e52e7ac97 100644 --- a/test/integration/kprobe_test.go +++ b/test/integration/kprobe_test.go @@ -7,8 +7,6 @@ import ( "bytes" "context" "io" - "regexp" - "strconv" "testing" "time" @@ -45,7 +43,6 @@ func TestKprobeGoCounter(t *testing.T) { require.NoError(t, err) goKprobeCounterPod := pods.Items[0] - want := regexp.MustCompile(`Kprobe count: ([0-9]+)`) req := env.Cluster().Client().CoreV1().Pods(kprobeGoCounterUserspaceNs).GetLogs(goKprobeCounterPod.Name, &corev1.PodLogOptions{}) require.Eventually(t, func() bool { logs, err := req.Stream(ctx) @@ -56,14 +53,8 @@ func TestKprobeGoCounter(t *testing.T) { require.NoError(t, err) t.Logf("counter pod log %s", output.String()) - matches := want.FindAllStringSubmatch(output.String(), -1) - if len(matches) >= 1 && len(matches[0]) >= 2 { - count, err := strconv.Atoi(matches[0][1]) - require.NoError(t, err) - if count > 0 { - t.Logf("counted %d kprobe executions so far, BPF program is functioning", count) - return true - } + if doKprobeCheck(t, output) { + return true } return false }, 30*time.Second, time.Second) diff --git a/test/integration/tc_test.go b/test/integration/tc_test.go index ca6469fb4..15002a8d5 100644 --- a/test/integration/tc_test.go +++ b/test/integration/tc_test.go @@ -7,7 +7,6 @@ import ( "bytes" "context" "io" - "strings" "testing" "time" @@ -54,7 +53,8 @@ func TestTcGoCounter(t *testing.T) { _, err = io.Copy(output, logs) require.NoError(t, err) t.Logf("counter pod log %s", output.String()) - if strings.Contains(output.String(), "packets received") && strings.Contains(output.String(), "bytes received") { + + if doTcCheck(t, output) { return true } return false diff --git a/test/integration/tracepoint_test.go b/test/integration/tracepoint_test.go index 15619f38c..d1b2a985d 100644 --- a/test/integration/tracepoint_test.go +++ b/test/integration/tracepoint_test.go @@ -7,8 +7,6 @@ import ( "bytes" "context" "io" - "regexp" - "strconv" "testing" "time" @@ -45,7 +43,6 @@ func TestTracepointGoCounter(t *testing.T) { require.NoError(t, err) goTracepointCounterPod := pods.Items[0] - want := regexp.MustCompile(`SIGUSR1 signal count: ([0-9]+)`) req := env.Cluster().Client().CoreV1().Pods(tracepointGoCounterUserspaceNs).GetLogs(goTracepointCounterPod.Name, &corev1.PodLogOptions{}) require.Eventually(t, func() bool { logs, err := req.Stream(ctx) @@ -55,15 +52,8 @@ func TestTracepointGoCounter(t *testing.T) { _, err = io.Copy(output, logs) require.NoError(t, err) t.Logf("counter pod log %s", output.String()) - - matches := want.FindAllStringSubmatch(output.String(), -1) - if len(matches) >= 1 && len(matches[0]) >= 2 { - count, err := strconv.Atoi(matches[0][1]) - require.NoError(t, err) - if count > 0 { - t.Logf("counted %d SIGUSR1 signals so far, BPF program is functioning", count) - return true - } + if doTracepointCheck(t, output) { + return true } return false }, 30*time.Second, time.Second) diff --git a/test/integration/uprobe_test.go b/test/integration/uprobe_test.go index 8b19ab899..6a6d87bb8 100644 --- a/test/integration/uprobe_test.go +++ b/test/integration/uprobe_test.go @@ -7,8 +7,6 @@ import ( "bytes" "context" "io" - "regexp" - "strconv" "testing" "time" @@ -64,7 +62,6 @@ func TestUprobeGoCounter(t *testing.T) { require.NoError(t, err) goUprobeCounterPod := pods.Items[0] - want := regexp.MustCompile(`Uprobe count: ([0-9]+)`) req := env.Cluster().Client().CoreV1().Pods(uprobeGoCounterUserspaceNs).GetLogs(goUprobeCounterPod.Name, &corev1.PodLogOptions{}) require.Eventually(t, func() bool { logs, err := req.Stream(ctx) @@ -74,15 +71,8 @@ func TestUprobeGoCounter(t *testing.T) { _, err = io.Copy(output, logs) require.NoError(t, err) t.Logf("counter pod log %s", output.String()) - - matches := want.FindAllStringSubmatch(output.String(), -1) - if len(matches) >= 1 && len(matches[0]) >= 2 { - count, err := strconv.Atoi(matches[0][1]) - require.NoError(t, err) - if count > 0 { - t.Logf("counted %d uprobe executions so far, BPF program is functioning", count) - return true - } + if doUprobeCheck(t, output) { + return true } return false }, 30*time.Second, time.Second) diff --git a/test/integration/xdp_test.go b/test/integration/xdp_test.go index 9473c7f3e..c9ab37f40 100644 --- a/test/integration/xdp_test.go +++ b/test/integration/xdp_test.go @@ -9,7 +9,6 @@ import ( "encoding/base64" "io" "os" - "strings" "testing" "time" @@ -136,7 +135,8 @@ func TestXdpGoCounter(t *testing.T) { _, err = io.Copy(output, logs) require.NoError(t, err) t.Logf("counter pod log %s", output.String()) - if strings.Contains(output.String(), "packets received") && strings.Contains(output.String(), "bytes received") { + + if doXdpCheck(t, output) { return true } return false