summaryrefslogtreecommitdiff
path: root/internal/generate/family_test.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-06-01 10:07:16 +0300
committerPaul Buetow <paul@buetow.org>2026-06-01 10:07:16 +0300
commit2bb05af8e0b08910c01045d7cd7cd375e6b83613 (patch)
treec06a458a15cb6550ed03480162d86c8a09588aa8 /internal/generate/family_test.go
parent7243b7c079f5d63b32e3e8dd639146d2714efa9d (diff)
test(generate): remove redundant pure-classification unit tests
Classification correctness (which family/kind/return-class a syscall maps to) is verified by inspection against the man pages and the classifier rules, not by dedicated unit tests. The tracing-relevant outcome — which fd/path/byte-count the generated BPF C actually captures — is covered by the GenerateTracepointsC codegen tests and the end-to-end integration tests, all of which are retained. Removed: - internal/generate/family_test.go (ClassifySyscallFamily / .Family table) - internal/generate/retclassify_test.go (ClassifyRet read/write/transfer/ unclassified tables) - ~70 pure-classification tests trimmed from classify_test.go, keeping only the GenerateTracepointsC codegen/tracing tests plus the shared helpers (mustParseAll, mqFormats, phaseAFormats, syntheticEnter/Exit, itoa) used by codegen_test.go. - pure-classification funcs interleaved in codegen_test.go (TestClassifyRet*Unclassified, TestClassifyTkillFallsThroughToNull, Test{Mkdirat,Rmdir}FamilyAndKindMatchSiblings). Kept all TestGenerate* handler tests (they assert the generated BPF C captures the correct fd/path/arg-index/return classification), the isNoreturnSyscall tests, docs-drift guards, eventloop dispatch tests, and the integration suite — so every affected syscall still has tracing coverage. No tracing gaps discovered. generate package: go test (incl. -race) green; mage build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'internal/generate/family_test.go')
-rw-r--r--internal/generate/family_test.go365
1 files changed, 0 insertions, 365 deletions
diff --git a/internal/generate/family_test.go b/internal/generate/family_test.go
deleted file mode 100644
index c350977..0000000
--- a/internal/generate/family_test.go
+++ /dev/null
@@ -1,365 +0,0 @@
-package generate
-
-import "testing"
-
-func TestClassifySyscallFamily(t *testing.T) {
- tests := []struct {
- name string
- want SyscallFamily
- }{
- {"sys_enter_accept", FamilyNetwork},
- {"sys_exit_accept", FamilyNetwork},
- // bind(2) assigns an address to a socket; it is a socket-setup syscall and
- // shares FamilyNetwork with its connect/listen/accept/getsockname/
- // getpeername siblings. Assert both enter and exit (and the closest
- // siblings) so a stray reclassification of any one trips this test. Keep in
- // sync with the Network list in docs/syscall-tracing-plan.md.
- {"sys_enter_bind", FamilyNetwork},
- {"sys_exit_bind", FamilyNetwork},
- {"sys_enter_connect", FamilyNetwork},
- {"sys_enter_listen", FamilyNetwork},
- {"sys_enter_getsockname", FamilyNetwork},
- {"sys_enter_getpeername", FamilyNetwork},
- // setsockopt(2)/getsockopt(2) set and read socket options on the socket
- // referred to by sockfd (args[0], KindFd). They are socket-configuration
- // syscalls and share FamilyNetwork with the bind/connect/getsockname/
- // getpeername siblings above. Assert both enter and exit for the
- // setsockopt pair so a stray reclassification of either direction trips
- // this test; keep in sync with the Network list in
- // docs/syscall-tracing-plan.md.
- {"sys_enter_setsockopt", FamilyNetwork},
- {"sys_exit_setsockopt", FamilyNetwork},
- {"sys_enter_getsockopt", FamilyNetwork},
- {"sys_enter_pipe2", FamilyIPC},
- {"sys_enter_munmap", FamilyMemory},
- // process_madvise(2) gives memory advice (MADV_COLD/PAGEOUT/...) about
- // address ranges of another process selected by a pidfd. Although its
- // first arg is a pidfd (KindFd) rather than an address, the operation is
- // fundamentally a memory-advice call, so it shares FamilyMemory with its
- // madvise(2)/process_mrelease(2)/process_vm_readv/writev(2) siblings — not
- // FamilyIPC (where the pidfd_* lifecycle syscalls live).
- {"sys_enter_process_madvise", FamilyMemory},
- {"sys_exit_process_madvise", FamilyMemory},
- // set_mempolicy_home_node(2) (Linux 5.17+) sets the home NUMA node for a
- // memory range (start,len,home_node,flags); it returns 0/-1 with no byte
- // count, so it is KindNull and Unclassified. It is a NUMA memory-policy
- // syscall and shares FamilyMemory with its siblings set_mempolicy(2),
- // get_mempolicy(2), mbind(2), migrate_pages(2), and move_pages(2). Pin the
- // whole NUMA memory-policy cluster (enter+exit) so a stray reclassification
- // of any one syscall trips this test. In particular get_mempolicy(2)
- // retrieves the NUMA policy of a thread/address (not a security operation)
- // and was previously misclassified FamilySecurity; assert it here so the
- // group stays consistent. Keep in sync with the Memory list in
- // docs/syscall-tracing-plan.md.
- {"sys_enter_set_mempolicy_home_node", FamilyMemory},
- {"sys_exit_set_mempolicy_home_node", FamilyMemory},
- {"sys_enter_set_mempolicy", FamilyMemory},
- {"sys_exit_set_mempolicy", FamilyMemory},
- {"sys_enter_get_mempolicy", FamilyMemory},
- {"sys_exit_get_mempolicy", FamilyMemory},
- {"sys_enter_mbind", FamilyMemory},
- {"sys_enter_migrate_pages", FamilyMemory},
- {"sys_enter_move_pages", FamilyMemory},
- {"sys_enter_execve", FamilyProcess},
- // setsid(2) creates a new session and returns the new session ID
- // (a pid_t), or -1 on error; it takes no arguments. It is a
- // process/session-management syscall and shares FamilyProcess with its
- // session/process-group siblings getsid(2), setpgid(2), getpgid(2), and
- // getpgrp(2), as well as the pid-returning getpid(2)/getppid(2). Assert
- // the whole session/pgrp cluster so a stray reclassification of any one
- // trips this test. Keep in sync with the Process list in
- // docs/syscall-tracing-plan.md.
- {"sys_enter_setsid", FamilyProcess},
- {"sys_exit_setsid", FamilyProcess},
- {"sys_enter_getsid", FamilyProcess},
- {"sys_enter_setpgid", FamilyProcess},
- {"sys_enter_getpgid", FamilyProcess},
- {"sys_enter_getpgrp", FamilyProcess},
- {"sys_enter_getpid", FamilyProcess},
- {"sys_enter_getppid", FamilyProcess},
- // gettid(2) ("pid_t gettid(void)") returns the caller's thread ID and
- // belongs with the no-arg id-returning reader cluster
- // getpid/getppid/getuid/getgid under FamilyProcess (it is a per-thread
- // identity query, not Time/Sched/Misc). Assert enter+exit so a stray
- // reclassification trips this test. Keep in sync with the Process list in
- // docs/syscall-tracing-plan.md.
- {"sys_enter_gettid", FamilyProcess},
- {"sys_exit_gettid", FamilyProcess},
- {"sys_enter_rt_sigaction", FamilySignals},
- {"sys_enter_clock_gettime", FamilyTime},
- // gettimeofday(2) gets wall-clock time via a userspace timeval/timezone
- // pointer; it is a time/clock syscall and shares FamilyTime with its
- // sibling clock_gettime/settimeofday/time syscalls.
- {"sys_enter_gettimeofday", FamilyTime},
- {"sys_exit_gettimeofday", FamilyTime},
- // times(2) stores the calling process's CPU times (struct tms *buf) and
- // returns a clock_t tick count. It is a time/clock syscall and shares
- // FamilyTime with gettimeofday/clock_gettime — NOT FamilyProcess (where
- // getrusage lives). Assert both enter and exit so a stray reclassification
- // trips this test. Keep in sync with the Time list in
- // docs/syscall-tracing-plan.md.
- {"sys_enter_times", FamilyTime},
- {"sys_exit_times", FamilyTime},
- {"sys_enter_sched_yield", FamilySched},
- {"sys_enter_openat", FamilyFS},
- // lseek(2) repositions the file offset of an open fd; it is a per-file
- // positioning syscall and shares FamilyFS with its fd-based I/O siblings
- // read/write/fsync (also FamilyFS). Assert both enter and exit so a stray
- // reclassification trips this test. Keep in sync with the FS list in
- // docs/syscall-tracing-plan.md.
- {"sys_enter_lseek", FamilyFS},
- {"sys_exit_lseek", FamilyFS},
- // access(2) checks the calling process's permissions for a file named by
- // a real filesystem path (pathname at args[0]; no dirfd). Its siblings
- // faccessat(2)/faccessat2(2) perform the same check relative to a dirfd
- // (path at args[1]). All three are filesystem-metadata syscalls and must
- // stay in FamilyFS together — assert the whole cluster so a stray
- // reclassification of any one trips this test. Keep in sync with the FS
- // list in docs/syscall-tracing-plan.md.
- {"sys_enter_access", FamilyFS},
- {"sys_exit_access", FamilyFS},
- {"sys_enter_faccessat", FamilyFS},
- {"sys_exit_faccessat", FamilyFS},
- {"sys_enter_faccessat2", FamilyFS},
- {"sys_exit_faccessat2", FamilyFS},
- // utime(2)/utimes(2) change a file's access and modification times by
- // path (filename at args[0] is a real filesystem path, captured as
- // KindPathname). They are filesystem-metadata syscalls and share
- // FamilyFS with their siblings utimensat(2) and futimesat(2); they must
- // NOT fall through to Misc. Assert all four siblings so a stray
- // reclassification of any one trips this test. Keep in sync with the FS
- // list in docs/syscall-tracing-plan.md.
- {"sys_enter_utime", FamilyFS},
- {"sys_exit_utime", FamilyFS},
- {"sys_enter_utimes", FamilyFS},
- {"sys_exit_utimes", FamilyFS},
- {"sys_enter_utimensat", FamilyFS},
- {"sys_enter_futimesat", FamilyFS},
- // The filesystem-sync family commits cached file data/metadata to disk
- // and all classify as FamilyFS: sync(2) (no args, whole system),
- // syncfs(2) (one fd, the filesystem containing that fd), and the
- // per-file fsync(2)/fdatasync(2)/sync_file_range(2). syncfs and its
- // siblings must stay together in FamilyFS — assert the whole group so a
- // stray reclassification of any one trips this test. Keep in sync with
- // the FS list in docs/syscall-tracing-plan.md.
- {"sys_enter_sync", FamilyFS},
- {"sys_exit_sync", FamilyFS},
- {"sys_enter_syncfs", FamilyFS},
- {"sys_exit_syncfs", FamilyFS},
- {"sys_enter_fsync", FamilyFS},
- {"sys_enter_fdatasync", FamilyFS},
- {"sys_enter_sync_file_range", FamilyFS},
- // fallocate(2) manipulates the allocated disk space (preallocate,
- // punch-hole, collapse, zero, insert) for the file referred to by its
- // args[0] fd; it is a per-file space-management syscall and shares
- // FamilyFS with its fd-based siblings fadvise64(2) (access-pattern
- // advice), ftruncate(2) (resize by fd), and sync_file_range(2) (flush a
- // byte range). Assert the group so a stray reclassification of any one
- // trips this test. Keep in sync with the FS list in
- // docs/syscall-tracing-plan.md.
- {"sys_enter_fallocate", FamilyFS},
- {"sys_exit_fallocate", FamilyFS},
- {"sys_enter_fadvise64", FamilyFS},
- {"sys_enter_ftruncate", FamilyFS},
- {"sys_enter_epoll_wait", FamilyPolling},
- {"sys_enter_io_uring_enter", FamilyAIO},
- {"sys_enter_bpf", FamilySecurity},
- // kexec_load and kexec_file_load are siblings on the kexec_load(2) man
- // page (both load a new kernel for later execution by reboot(2)) and
- // must share the Security family even though kexec_load takes raw user
- // pointers (KindNull) and kexec_file_load takes fds (KindFd).
- {"sys_enter_kexec_load", FamilySecurity},
- {"sys_enter_kexec_file_load", FamilySecurity},
- {"sys_exit_kexec_load", FamilySecurity},
- // Futexes are shared-memory synchronization/IPC primitives ("fast
- // user-space locking", futex(2)); the classic futex() and the Linux
- // 6.7+ split syscalls all classify as IPC alongside the System V
- // semaphores, not Misc.
- {"sys_enter_futex", FamilyIPC},
- {"sys_enter_futex_wait", FamilyIPC},
- {"sys_enter_futex_wake", FamilyIPC},
- {"sys_exit_futex_wake", FamilyIPC},
- {"sys_enter_futex_requeue", FamilyIPC},
- {"sys_enter_futex_waitv", FamilyIPC},
- // x86 I/O-port / CPU-state syscalls are not in the explicit family
- // table and intentionally fall through to Misc (ioperm/iopl/modify_ldt
- // set port-access or LDT state, not file I/O). arch_prctl/personality
- // are deliberately classified as Process (they are in the explicit family
- // table) — locked in below to guard against drift toward Misc with their
- // x86 siblings.
- {"sys_enter_ioperm", FamilyMisc},
- {"sys_enter_iopl", FamilyMisc},
- {"sys_enter_modify_ldt", FamilyMisc},
- // arch_prctl(2) sets/gets x86-64 thread state (FS/GS base, CPUID faulting).
- // It is per-thread process/architecture state, grouped with the rest of the
- // process-state cluster, NOT with the port-access/LDT siblings above.
- {"sys_enter_arch_prctl", FamilyProcess},
- {"sys_exit_arch_prctl", FamilyProcess},
- // personality(2) sets the process execution domain — also Process, never Misc.
- {"sys_enter_personality", FamilyProcess},
- {"sys_exit_personality", FamilyProcess},
- // rseq(2) registers/unregisters a per-thread restartable-sequences area
- // (a userspace struct pointer, not an fd/path). It is not in the explicit
- // family table and intentionally falls through to Misc, sharing the family
- // with its closest per-thread sibling set_robust_list/get_robust_list
- // (also Misc). set_tid_address is Process, but rseq is grouped with the
- // robust-list pair rather than the tid-address syscall; keep this in sync
- // with the Misc list in docs/syscall-tracing-plan.md.
- //
- // Boundary rule (see family.go futex block): a syscall is IPC only if it
- // PERFORMS the actual IPC/sync operation (futex wait/wake/requeue, or an
- // op on an IPC object). set_robust_list/get_robust_list merely register or
- // query the per-thread robust-futex list head pointer — "managed in user
- // space: the kernel knows only about the location of the head"
- // (get_robust_list(2)) — and never wait/wake or touch the shared futex
- // word. That is registration/bookkeeping, exactly like rseq, so they stay
- // Misc and are NOT promoted to IPC alongside futex_* (asserted as IPC just
- // above). The split axis is operation-vs-registration, not name similarity.
- {"sys_enter_rseq", FamilyMisc},
- {"sys_exit_rseq", FamilyMisc},
- {"sys_enter_set_robust_list", FamilyMisc},
- {"sys_enter_get_robust_list", FamilyMisc},
- // set_tid_address(2) is the deliberate counterpoint to the
- // rseq/robust_list cluster above: it shares the surface form
- // ("per-thread registration of a pointer the kernel consults later")
- // but stays Process, NOT Misc. WHY: the tidptr it registers is
- // clear_child_tid — the kernel's primary thread-EXIT notification
- // mechanism (zeroed + FUTEX_WAKEd at thread teardown), set by the C
- // runtime for essentially every thread (clone(2) CLONE_CHILD_CLEARTID),
- // and the call returns the caller's thread ID like gettid/getpid. It is
- // mandatory thread-lifecycle plumbing and belongs with
- // clone/fork/exit/gettid, whereas rseq (scheduling optimization) and
- // robust_list (opt-in futex cleanup) are OPTIONAL per-thread features a
- // thread runs fine without. The Process-vs-Misc axis here is
- // mandatory-lifecycle vs optional-opt-in-feature, not registration-vs-
- // operation. Assert enter+exit so a stray move to Misc trips this test.
- // See the Process-vs-Misc boundary block in family.go and keep in sync
- // with the Process list in docs/syscall-tracing-plan.md.
- {"sys_enter_set_tid_address", FamilyProcess},
- {"sys_exit_set_tid_address", FamilyProcess},
- // sysinfo(2) returns overall system statistics (memory/swap usage and
- // load averages) into a single userspace struct sysinfo *info pointer
- // (an output buffer, not an fd/path). It is not in the explicit family
- // table and intentionally falls through to Misc, sharing the family with
- // its closest system-introspection siblings newuname/sysfs (also Misc).
- // NOTE: other "system info" relatives are deliberately classified
- // elsewhere — getrusage is Process, times/gettimeofday are Time — so
- // sysinfo is grouped with the uname/sysfs cluster rather than any of
- // those. ustat(2) is NOT a sibling here: it contains the "stat" name
- // marker and is classified FamilyFS by isFSSyscall. Keep this in sync
- // with the Misc list in docs/syscall-tracing-plan.md.
- {"sys_enter_sysinfo", FamilyMisc},
- {"sys_exit_sysinfo", FamilyMisc},
- {"sys_enter_newuname", FamilyMisc},
- {"sys_enter_sysfs", FamilyMisc},
- // rt_sigpending(2) examines the set of signals pending for delivery
- // (sigset_t *set, size_t sigsetsize). It is a signal-handling syscall and
- // shares FamilySignals with the whole rt_sig* group as well as kill/pause/
- // sigaltstack/tkill/tgkill. The entire group must stay consistent; assert
- // every rt_sig* sibling alongside rt_sigpending so a stray reclassification
- // of any one of them trips this test. Keep in sync with the Signals list in
- // docs/syscall-tracing-plan.md.
- {"sys_enter_rt_sigpending", FamilySignals},
- {"sys_exit_rt_sigpending", FamilySignals},
- {"sys_enter_rt_sigprocmask", FamilySignals},
- {"sys_enter_rt_sigsuspend", FamilySignals},
- {"sys_enter_rt_sigtimedwait", FamilySignals},
- {"sys_enter_rt_sigreturn", FamilySignals},
- {"sys_enter_rt_sigqueueinfo", FamilySignals},
- {"sys_enter_rt_tgsigqueueinfo", FamilySignals},
- {"sys_enter_sigaltstack", FamilySignals},
- // tkill(tid, sig) and its successor tgkill(tgid, tid, sig) deliver a signal
- // to a specific thread; kill(pid, sig) signals a whole process. All three
- // are signal-delivery syscalls and belong in FamilySignals with the rest of
- // the group above. tkill is the obsolete predecessor of tgkill (man 2 tkill)
- // and must not drift into FamilyProcess just because its first arg is a
- // thread id — the tid is a signal target, not a process-control operand.
- // Assert both enter and exit for tkill/tgkill/kill so a stray
- // reclassification of any of them trips this test.
- {"sys_enter_kill", FamilySignals},
- {"sys_exit_kill", FamilySignals},
- {"sys_enter_tkill", FamilySignals},
- {"sys_exit_tkill", FamilySignals},
- {"sys_enter_tgkill", FamilySignals},
- {"sys_exit_tgkill", FamilySignals},
- // ioprio_get/ioprio_set query/set the I/O scheduling class and priority of
- // a process, process group, or user. They are the I/O-priority analogues of
- // getpriority/setpriority (the CPU nice value) and share the identical
- // which/who selector signature, so they classify as Process alongside them
- // rather than falling through to Misc. Assert the ioprio pair together with
- // their getpriority/setpriority siblings so a stray reclassification of any
- // one of them trips this test. Note: the x86 I/O-port syscalls ioperm/iopl
- // (asserted above as Misc) only share an "io" name prefix; they set
- // port-access state, not process I/O priority, and stay in Misc. Keep in
- // sync with the Process list in docs/syscall-tracing-plan.md.
- {"sys_enter_ioprio_get", FamilyProcess},
- {"sys_exit_ioprio_get", FamilyProcess},
- {"sys_enter_ioprio_set", FamilyProcess},
- {"sys_exit_ioprio_set", FamilyProcess},
- {"sys_enter_getpriority", FamilyProcess},
- {"sys_enter_setpriority", FamilyProcess},
- // setuid(2) sets the process credential (effective, and possibly real and
- // saved, user ID); it is a process/credential-management syscall and shares
- // FamilyProcess with its credential-setting cluster — the uid setters
- // setresuid/setreuid/setfsuid, the gid analogues
- // setgid/setresgid/setregid/setfsgid/setgroups, and the matching credential
- // readers getuid/geteuid/getgid/getegid/getresuid/getresgid/getgroups.
- // Assert the cluster (enter and exit for setuid) so a stray
- // reclassification of any one credential syscall trips this test.
- // seteuid/setegid (set effective uid/gid) belong with the cluster too,
- // but have no dedicated kernel tracepoints (they are libc wrappers over
- // setreuid/setresuid), so they never reach the generated tracepoint map
- // or docs/syscall-tracing-plan.md. They are still classified as Process
- // in family.go for consistency, so assert them here by name directly
- // (no tracepoint required) to lock in that latent classification.
- {"sys_enter_setuid", FamilyProcess},
- {"sys_exit_setuid", FamilyProcess},
- {"sys_enter_seteuid", FamilyProcess},
- {"sys_exit_seteuid", FamilyProcess},
- {"sys_enter_setegid", FamilyProcess},
- {"sys_exit_setegid", FamilyProcess},
- {"sys_enter_setresuid", FamilyProcess},
- {"sys_enter_setreuid", FamilyProcess},
- {"sys_enter_setfsuid", FamilyProcess},
- {"sys_enter_setgid", FamilyProcess},
- {"sys_enter_setresgid", FamilyProcess},
- {"sys_enter_setregid", FamilyProcess},
- {"sys_enter_setfsgid", FamilyProcess},
- {"sys_enter_setgroups", FamilyProcess},
- {"sys_enter_getuid", FamilyProcess},
- {"sys_enter_geteuid", FamilyProcess},
- {"sys_enter_getgid", FamilyProcess},
- {"sys_enter_getegid", FamilyProcess},
- {"sys_enter_getresuid", FamilyProcess},
- {"sys_enter_getresgid", FamilyProcess},
- {"sys_enter_getgroups", FamilyProcess},
- {"sys_enter_unlisted_future_syscall", FamilyMisc},
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- if got := ClassifySyscallFamily(tt.name); got != tt.want {
- t.Errorf("ClassifySyscallFamily(%q) = %s, want %s", tt.name, got, tt.want)
- }
- })
- }
-}
-
-func TestParseFormatsTagsEveryFormatWithFamily(t *testing.T) {
- formats := mustParseAll(t, FormatRead+"\n"+FormatExitSocket+"\n"+FormatExitKill)
-
- tests := []struct {
- index int
- want SyscallFamily
- }{
- {0, FamilyFS},
- {1, FamilyNetwork},
- {2, FamilySignals},
- }
-
- for _, tt := range tests {
- if got := formats[tt.index].Family; got != tt.want {
- t.Errorf("formats[%d].Family = %s, want %s", tt.index, got, tt.want)
- }
- }
-}