summaryrefslogtreecommitdiff
path: root/integrationtests
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-31 19:22:22 +0300
committerPaul Buetow <paul@buetow.org>2026-05-31 19:22:22 +0300
commit63a20d8498bf161d16e8a8c8cc0b096a8355aa6f (patch)
tree18aa764dacba2a6ddc3aabc6e36e44db6ea6b5dd /integrationtests
parent8a1bf6236f6a525881c647fd881093b393436411 (diff)
test(readahead): add end-to-end integration coverage
readahead(2) was traced (KindFd enter fd_event from args[0], UNCLASSIFIED exit ret_event) but had no integration or ioworkload scenario coverage, unlike its sibling sync_file_range. Add readwrite-readahead and readwrite-readahead-ebadf scenarios plus TestReadwriteReadahead / TestReadwriteReadaheadEbadf, asserting enter_readahead capture with path attribution, zero attributed bytes (readahead returns 0/-1, not a byte count, so it is correctly UNCLASSIFIED), and positive end-to-end duration. No classification change: inspection confirms KindFd / UNCLASSIFIED is correct per man 2 readahead; bytesFromRet returns 0 for UNCLASSIFIED so the 0/-1 return is never misattributed as bytes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'integrationtests')
-rw-r--r--integrationtests/readwrite_test.go42
1 files changed, 42 insertions, 0 deletions
diff --git a/integrationtests/readwrite_test.go b/integrationtests/readwrite_test.go
index 7a479b7..c1efbb4 100644
--- a/integrationtests/readwrite_test.go
+++ b/integrationtests/readwrite_test.go
@@ -221,6 +221,48 @@ func TestReadwritePwriteInvalid(t *testing.T) {
})
}
+func TestReadwriteReadahead(t *testing.T) {
+ // readahead(2) is KindFd / UNCLASSIFIED: despite its ssize_t prototype it
+ // returns 0/-1 and transfers no bytes to userspace, so the tracer must
+ // attribute zero bytes (not misread the 0/-1 return as a byte count) while
+ // still capturing the fd (args[0]) on enter and timing the syscall.
+ result, _ := runScenarioResult(t, "readwrite-readahead", []ExpectedEvent{
+ {
+ PathContains: "readaheadfile.txt",
+ Tracepoint: "enter_readahead",
+ Comm: "ioworkload",
+ MinCount: 1,
+ },
+ })
+ exp := ExpectedEvent{
+ PathContains: "readaheadfile.txt",
+ Tracepoint: "enter_readahead",
+ Comm: "ioworkload",
+ }
+ // UNCLASSIFIED: no byte count is attributed for a successful readahead.
+ assertEventBytesEqual(t, result, exp, 0)
+ // Timing is captured end-to-end (enter/exit paired into a duration).
+ assertEventDurationPositive(t, result, exp)
+}
+
+func TestReadwriteReadaheadEbadf(t *testing.T) {
+ // readahead on an invalid fd fails with EBADF, but ior still captures the
+ // enter_readahead tracepoint because arguments are read on syscall entry
+ // before the kernel returns the error. The UNCLASSIFIED -1 return must not
+ // be attributed as bytes.
+ result, _ := runScenarioResult(t, "readwrite-readahead-ebadf", []ExpectedEvent{
+ {
+ Tracepoint: "enter_readahead",
+ Comm: "ioworkload",
+ MinCount: 1,
+ },
+ })
+ assertEventBytesEqual(t, result, ExpectedEvent{
+ Tracepoint: "enter_readahead",
+ Comm: "ioworkload",
+ }, 0)
+}
+
func assertEventBytesAtLeast(t *testing.T, result TestResult, exp ExpectedEvent, minBytes uint64) {
t.Helper()
var matched bool