summaryrefslogtreecommitdiff
path: root/internal/generate/classify_test.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-02-21 11:51:01 +0200
committerPaul Buetow <paul@buetow.org>2026-02-21 11:51:01 +0200
commit6c912a9d72ae2a43923c638538d320e6bf585952 (patch)
tree727f66d158210e01abf8c18a83ef4db6066e0c1a /internal/generate/classify_test.go
parent32136b8cb18944157ff1f361bc0755f6b627fd47 (diff)
Migrate make targets to mage
Amp-Thread-ID: https://ampcode.com/threads/T-019c7f4e-cc5f-76f1-aaf0-dd7cbaabbb18 Co-authored-by: Amp <amp@ampcode.com>
Diffstat (limited to 'internal/generate/classify_test.go')
-rw-r--r--internal/generate/classify_test.go332
1 files changed, 332 insertions, 0 deletions
diff --git a/internal/generate/classify_test.go b/internal/generate/classify_test.go
new file mode 100644
index 0000000..c94e359
--- /dev/null
+++ b/internal/generate/classify_test.go
@@ -0,0 +1,332 @@
+package generate
+
+import (
+ "strings"
+ "testing"
+)
+
+func classifyFromData(t *testing.T, data string) ClassificationResult {
+ t.Helper()
+ f := mustParseOne(t, data)
+ return ClassifyFormat(&f)
+}
+
+func TestClassifyFdRead(t *testing.T) {
+ r := classifyFromData(t, FormatRead)
+ if r.Kind != KindFd {
+ t.Errorf("read: got kind %d, want KindFd", r.Kind)
+ }
+}
+
+func TestClassifyFdClose(t *testing.T) {
+ r := classifyFromData(t, FormatClose)
+ if r.Kind != KindFd {
+ t.Errorf("close: got kind %d, want KindFd", r.Kind)
+ }
+}
+
+func TestClassifyFdPread64(t *testing.T) {
+ r := classifyFromData(t, FormatPread64)
+ if r.Kind != KindFd {
+ t.Errorf("pread64: got kind %d, want KindFd", r.Kind)
+ }
+}
+
+func TestClassifyFdWrite(t *testing.T) {
+ r := classifyFromData(t, FormatWrite)
+ if r.Kind != KindFd {
+ t.Errorf("write: got kind %d, want KindFd", r.Kind)
+ }
+}
+
+func TestClassifyOpenOpenat(t *testing.T) {
+ r := classifyFromData(t, FormatOpenat)
+ if r.Kind != KindOpen {
+ t.Errorf("openat: got kind %d, want KindOpen", r.Kind)
+ }
+}
+
+func TestClassifyOpenOpen(t *testing.T) {
+ r := classifyFromData(t, FormatOpen)
+ if r.Kind != KindOpen {
+ t.Errorf("open: got kind %d, want KindOpen", r.Kind)
+ }
+}
+
+func TestClassifyOpenOpenat2(t *testing.T) {
+ r := classifyFromData(t, FormatOpenat2)
+ if r.Kind != KindOpen {
+ t.Errorf("openat2: got kind %d, want KindOpen", r.Kind)
+ }
+}
+
+func TestClassifyPathnameCreat(t *testing.T) {
+ r := classifyFromData(t, FormatCreat)
+ if r.Kind != KindPathname {
+ t.Errorf("creat: got kind %d, want KindPathname", r.Kind)
+ }
+ if r.PathnameField != "pathname" {
+ t.Errorf("creat: PathnameField = %q, want pathname", r.PathnameField)
+ }
+}
+
+func TestClassifyPathnameUnlink(t *testing.T) {
+ r := classifyFromData(t, FormatUnlink)
+ if r.Kind != KindPathname {
+ t.Errorf("unlink: got kind %d, want KindPathname", r.Kind)
+ }
+ if r.PathnameField != "pathname" {
+ t.Errorf("unlink: PathnameField = %q, want pathname", r.PathnameField)
+ }
+}
+
+func TestClassifyNameRename(t *testing.T) {
+ r := classifyFromData(t, FormatRename)
+ if r.Kind != KindName {
+ t.Errorf("rename: got kind %d, want KindName", r.Kind)
+ }
+}
+
+func TestClassifyNameLinkat(t *testing.T) {
+ r := classifyFromData(t, FormatLinkat)
+ if r.Kind != KindName {
+ t.Errorf("linkat: got kind %d, want KindName", r.Kind)
+ }
+}
+
+func TestClassifyNameSymlink(t *testing.T) {
+ r := classifyFromData(t, FormatSymlink)
+ if r.Kind != KindName {
+ t.Errorf("symlink: got kind %d, want KindName", r.Kind)
+ }
+}
+
+func TestClassifyFcntl(t *testing.T) {
+ r := classifyFromData(t, FormatFcntl)
+ if r.Kind != KindFcntl {
+ t.Errorf("fcntl: got kind %d, want KindFcntl", r.Kind)
+ }
+}
+
+func TestClassifyDup(t *testing.T) {
+ r := classifyFromData(t, FormatDup)
+ if r.Kind != KindFd {
+ t.Errorf("dup: got kind %d, want KindFd", r.Kind)
+ }
+}
+
+func TestClassifyDup2(t *testing.T) {
+ r := classifyFromData(t, FormatDup2)
+ if r.Kind != KindFd {
+ t.Errorf("dup2: got kind %d, want KindFd", r.Kind)
+ }
+}
+
+func TestClassifyDup3(t *testing.T) {
+ r := classifyFromData(t, FormatDup3)
+ if r.Kind != KindDup3 {
+ t.Errorf("dup3: got kind %d, want KindDup3", r.Kind)
+ }
+}
+
+func TestClassifyOpenByHandleAt(t *testing.T) {
+ r := classifyFromData(t, FormatOpenByHandleAt)
+ if r.Kind != KindOpenByHandleAt {
+ t.Errorf("open_by_handle_at: got kind %d, want KindOpenByHandleAt", r.Kind)
+ }
+}
+
+func TestClassifyNullSync(t *testing.T) {
+ r := classifyFromData(t, FormatSync)
+ if r.Kind != KindNull {
+ t.Errorf("sync: got kind %d, want KindNull", r.Kind)
+ }
+}
+
+func TestClassifyNullSyslog(t *testing.T) {
+ r := classifyFromData(t, FormatSyslog)
+ if r.Kind != KindNull {
+ t.Errorf("syslog: got kind %d, want KindNull", r.Kind)
+ }
+}
+
+func TestClassifyNullIoUring(t *testing.T) {
+ r := classifyFromData(t, FormatIoUringEnter)
+ if r.Kind != KindNull {
+ t.Errorf("io_uring_enter: got kind %d, want KindNull", r.Kind)
+ }
+}
+
+func TestClassifyRetExitRead(t *testing.T) {
+ r := classifyFromData(t, FormatExitRead)
+ if r.Kind != KindRet {
+ t.Errorf("exit_read: got kind %d, want KindRet", r.Kind)
+ }
+}
+
+func TestClassifyRetExitWrite(t *testing.T) {
+ r := classifyFromData(t, FormatExitWrite)
+ if r.Kind != KindRet {
+ t.Errorf("exit_write: got kind %d, want KindRet", r.Kind)
+ }
+}
+
+func TestClassifyRetExitOpenat(t *testing.T) {
+ r := classifyFromData(t, FormatExitOpenat)
+ if r.Kind != KindRet {
+ t.Errorf("exit_openat: got kind %d, want KindRet", r.Kind)
+ }
+}
+
+func TestClassifyRetExitPread64(t *testing.T) {
+ r := classifyFromData(t, FormatExitPread64)
+ if r.Kind != KindRet {
+ t.Errorf("exit_pread64: got kind %d, want KindRet", r.Kind)
+ }
+}
+
+func TestClassifyRetExitSymlink(t *testing.T) {
+ r := classifyFromData(t, FormatExitSymlink)
+ if r.Kind != KindRet {
+ t.Errorf("exit_symlink: got kind %d, want KindRet", r.Kind)
+ }
+}
+
+// --- Ignore tests ---
+
+func TestIgnoreMknod(t *testing.T) {
+ r := classifyFromData(t, FormatMknod)
+ if r.Kind != KindNone {
+ t.Errorf("mknod: got kind %d, want KindNone (ignored)", r.Kind)
+ }
+}
+
+func TestIgnoreExecve(t *testing.T) {
+ r := classifyFromData(t, FormatExecve)
+ if r.Kind != KindNone {
+ t.Errorf("execve: got kind %d, want KindNone (ignored)", r.Kind)
+ }
+}
+
+func TestIgnoreAccept(t *testing.T) {
+ r := classifyFromData(t, FormatAccept)
+ if r.Kind != KindNone {
+ t.Errorf("accept: got kind %d, want KindNone (ignored)", r.Kind)
+ }
+}
+
+func TestIgnoreSocket(t *testing.T) {
+ r := classifyFromData(t, FormatSocket)
+ if r.Kind != KindNone {
+ t.Errorf("socket: got kind %d, want KindNone (ignored)", r.Kind)
+ }
+}
+
+func TestIgnoreKill(t *testing.T) {
+ r := classifyFromData(t, FormatKill)
+ if r.Kind != KindNone {
+ t.Errorf("kill: got kind %d, want KindNone (no matching type)", r.Kind)
+ }
+}
+
+func TestShouldIgnorePatterns(t *testing.T) {
+ ignoreNames := []string{
+ "sys_enter_mknod", "sys_enter_mknodat",
+ "sys_enter_execve", "sys_enter_execveat",
+ "sys_enter_accept", "sys_enter_accept4",
+ "sys_enter_listen",
+ "sys_enter_epoll_ctl", "sys_enter_epoll_pwait",
+ "sys_enter_recvfrom", "sys_enter_recvmsg", "sys_enter_recvmmsg",
+ "sys_enter_sendto", "sys_enter_sendmsg", "sys_enter_sendmmsg",
+ "sys_enter_socket", "sys_enter_socketpair", "sys_enter_getsockname",
+ "sys_enter_inotify_init", "sys_enter_inotify_add_watch",
+ "sys_enter_pidfd_open", "sys_enter_pidfd_getfd",
+ "sys_enter_bind", "sys_enter_setns", "sys_enter_shutdown",
+ "sys_enter_connect", "sys_enter_fanotify_init", "sys_enter_getpeername",
+ }
+ for _, name := range ignoreNames {
+ if !shouldIgnore(name) {
+ t.Errorf("shouldIgnore(%q) = false, want true", name)
+ }
+ }
+}
+
+func TestShouldNotIgnore(t *testing.T) {
+ noIgnore := []string{
+ "sys_enter_read", "sys_enter_write", "sys_enter_openat",
+ "sys_enter_close", "sys_enter_rename", "sys_enter_unlink",
+ "sys_exit_read", "sys_exit_openat",
+ }
+ for _, name := range noIgnore {
+ if shouldIgnore(name) {
+ t.Errorf("shouldIgnore(%q) = true, want false", name)
+ }
+ }
+}
+
+// --- End-to-end classification with enter+exit pairs ---
+
+func TestClassifySyscallPairAccepted(t *testing.T) {
+ tests := []struct {
+ name string
+ enter string
+ exit string
+ enterKind TracepointKind
+ }{
+ {"read", FormatRead, FormatExitRead, KindFd},
+ {"openat", FormatOpenat, FormatExitOpenat, KindOpen},
+ {"rename", FormatRename, FormatExitRename, KindName},
+ {"close", FormatClose, FormatExitClose, KindFd},
+ {"dup3", FormatDup3, FormatExitDup3, KindDup3},
+ {"fcntl", FormatFcntl, FormatExitFcntl, KindFcntl},
+ {"sync", FormatSync, FormatExitSync, KindNull},
+ {"syslog", FormatSyslog, FormatExitSyslog, KindNull},
+ {"open_by_handle_at", FormatOpenByHandleAt, FormatExitOpenByHandleAt, KindOpenByHandleAt},
+ {"io_uring_enter", FormatIoUringEnter, FormatExitIoUringEnter, KindNull},
+ {"pread64", FormatPread64, FormatExitPread64, KindFd},
+ {"symlink", FormatSymlink, FormatExitSymlink, KindName},
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ input := tt.enter + "\n" + tt.exit
+ output := GenerateTracepointsC(mustParseAll(t, input))
+ if strings.Contains(output, "Ignoring") {
+ t.Errorf("syscall %s was ignored, expected accepted", tt.name)
+ }
+ })
+ }
+}
+
+func TestClassifySyscallPairIgnored(t *testing.T) {
+ tests := []struct {
+ name string
+ enter string
+ exit string
+ }{
+ {"mknod", FormatMknod, FormatExitMknod},
+ {"execve", FormatExecve, FormatExitExecve},
+ {"accept", FormatAccept, FormatExitAccept},
+ {"socket", FormatSocket, FormatExitSocket},
+ {"kill", FormatKill, FormatExitKill},
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ input := tt.enter + "\n" + tt.exit
+ output := GenerateTracepointsC(mustParseAll(t, input))
+ if !strings.Contains(output, "Ignoring") {
+ t.Errorf("syscall %s was accepted, expected ignored", tt.name)
+ }
+ })
+ }
+}
+
+func mustParseAll(t *testing.T, data string) []Format {
+ t.Helper()
+ formats, err := ParseFormats(strings.NewReader(data))
+ if err != nil {
+ t.Fatalf("ParseFormats failed: %v", err)
+ }
+ return formats
+}