summaryrefslogtreecommitdiff
path: root/internal/generate/classify_test.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-30 17:16:09 +0300
committerPaul Buetow <paul@buetow.org>2026-05-30 17:16:09 +0300
commit8b64d566300b7e952da63e11cba7575d7b06e7e2 (patch)
treec218d42c3d0bcb027e9cc91410d18f1608d7f408 /internal/generate/classify_test.go
parente462a4d9963a2949f0670a00a013dd362b5219d1 (diff)
test(generate): lock in lseek classification (offset, not byte count)
Audit of lseek(2) confirmed the tracing implementation is already correct: enter is a KindFd fd_event capturing the fd from args[0], the syscall is FamilyFS alongside its read/write/fsync siblings, and the exit is a plain ret_event that stays UNCLASSIFIED. lseek returns the RESULTING file offset (off_t, bytes from the start of the file), which is a file position, NOT a count of bytes transferred — so it must never be READ/WRITE/TRANSFER classified, which would wrongly inflate I/O byte totals. Add lock-in tests pinning that behaviour so a future reclassification trips: - FormatLseek/FormatExitLseek tracepoint fixtures. - TestClassifyFdLseek: enter resolves to KindFd (fd at args[0]). - TestClassifyRetExitLseek: exit is KindRet and ClassifyRet stays UNCLASSIFIED. - lseek entry in TestClassifySyscallPairAccepted (end-to-end pair). - FS-family asserts for sys_enter/exit_lseek in family_test. - Enriched UNCLASSIFIED comment in retclassify_test explaining offset != bytes. No generated-artifact changes (mage generate produces no diff); no in-scope bugs and no out-of-scope follow-ups found. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'internal/generate/classify_test.go')
-rw-r--r--internal/generate/classify_test.go30
1 files changed, 30 insertions, 0 deletions
diff --git a/internal/generate/classify_test.go b/internal/generate/classify_test.go
index 7dddab7..d150bdf 100644
--- a/internal/generate/classify_test.go
+++ b/internal/generate/classify_test.go
@@ -40,6 +40,35 @@ func TestClassifyFdWrite(t *testing.T) {
}
}
+// TestClassifyFdLseek pins lseek(2) as a single-fd KindFd event. lseek's
+// tracepoint exposes a generic "fd" field of an fd-like type at args[0], so it
+// classifies via classifyByField exactly like read/write — the fd is captured
+// from args[0], while the off_t offset and whence args are ignored. The return
+// value (resulting file offset) is asserted UNCLASSIFIED separately in
+// retclassify_test.go (TestClassifyRetUnclassified) and end-to-end in
+// TestClassifyRetExitLseek below.
+func TestClassifyFdLseek(t *testing.T) {
+ r := classifyFromData(t, FormatLseek)
+ if r.Kind != KindFd {
+ t.Errorf("lseek: got kind %d, want KindFd", r.Kind)
+ }
+}
+
+// TestClassifyRetExitLseek locks in that sys_exit_lseek is a plain ret_event
+// (KindRet) and that ClassifyRet keeps it UNCLASSIFIED. lseek returns the new
+// file OFFSET (bytes-from-start), not a transferred byte count, so it must
+// never be classified as READ/WRITE/TRANSFER — doing so would inflate I/O byte
+// accounting.
+func TestClassifyRetExitLseek(t *testing.T) {
+ r := classifyFromData(t, FormatExitLseek)
+ if r.Kind != KindRet {
+ t.Errorf("lseek exit: got kind %d, want KindRet", r.Kind)
+ }
+ if got := ClassifyRet("sys_exit_lseek"); got != Unclassified {
+ t.Errorf("lseek exit: ClassifyRet = %q, want UNCLASSIFIED", got)
+ }
+}
+
func TestClassifyFdPidfdGetfd(t *testing.T) {
r := classifyFromData(t, FormatPidfdGetfd)
if r.Kind != KindFd {
@@ -2072,6 +2101,7 @@ func TestClassifySyscallPairAccepted(t *testing.T) {
enterKind TracepointKind
}{
{"read", FormatRead, FormatExitRead, KindFd},
+ {"lseek", FormatLseek, FormatExitLseek, KindFd},
{"openat", FormatOpenat, FormatExitOpenat, KindOpen},
{"rename", FormatRename, FormatExitRename, KindName},
{"close", FormatClose, FormatExitClose, KindFd},