summaryrefslogtreecommitdiff
path: root/integrationtests/expectations.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-02-21 16:13:40 +0200
committerPaul Buetow <paul@buetow.org>2026-02-21 16:13:40 +0200
commit2c2cbe07f5e10fdb996e2a039cde84be44866f18 (patch)
tree97654c2c9ba9fc91cb569ab0521c4c67247abc0b /integrationtests/expectations.go
parenteebc9cba272c1b20296ab998262298c5da99e047 (diff)
Add integration test framework: plan, workload binary, harness scaffolding
- INTEGRATIONTESTS-PLAN.md: full design for e2e integration tests - integrationtests/cmd/ioworkload: standalone binary with 13 I/O scenarios - integrationtests/expectations.go: ExpectedEvent type and assertion helpers - integrationtests/parse.go: .ior.zst parser producing TestResult - Export IterRecord and LoadFromFile in flamegraph package - Fix TraceId -> TraceID, StringByName returns error instead of panic Amp-Thread-ID: https://ampcode.com/threads/T-019c8031-c106-757a-95a0-7a5457163ce7 Co-authored-by: Amp <amp@ampcode.com>
Diffstat (limited to 'integrationtests/expectations.go')
-rw-r--r--integrationtests/expectations.go83
1 files changed, 83 insertions, 0 deletions
diff --git a/integrationtests/expectations.go b/integrationtests/expectations.go
new file mode 100644
index 0000000..ed155bc
--- /dev/null
+++ b/integrationtests/expectations.go
@@ -0,0 +1,83 @@
+package integrationtests
+
+import (
+ "ior/internal/flamegraph"
+ "strings"
+ "testing"
+)
+
+// ExpectedEvent describes an I/O event that should appear in the test output.
+type ExpectedEvent struct {
+ PathContains string // substring match on file path
+ Tracepoint string // tracepoint name substring, e.g. "openat"
+ Comm string // expected comm name, e.g. "ioworkload"
+ MinCount uint64 // minimum total occurrences across all matching records
+}
+
+// AssertEventsPresent verifies that each expected event is found in the test result.
+// Counts are summed across all matching records before comparing to MinCount.
+func AssertEventsPresent(t *testing.T, result TestResult, expected []ExpectedEvent) {
+ t.Helper()
+ for _, exp := range expected {
+ var totalCount uint64
+ var matched bool
+ for _, rec := range result.Records {
+ if matchesExpectation(rec, exp) {
+ matched = true
+ totalCount += rec.Cnt.Count
+ }
+ }
+ if !matched {
+ t.Errorf("expected event not found: %+v", exp)
+ continue
+ }
+ if exp.MinCount > 0 && totalCount < exp.MinCount {
+ t.Errorf("event matching %+v has total count %d, want >= %d",
+ exp, totalCount, exp.MinCount)
+ }
+ }
+}
+
+// AssertNoUnexpectedComm verifies all records have the expected comm name.
+// Fails fast on the first mismatch and reports the total count of unexpected records.
+func AssertNoUnexpectedComm(t *testing.T, result TestResult, expectedComm string) {
+ t.Helper()
+ var count int
+ for _, rec := range result.Records {
+ if rec.Comm != expectedComm {
+ count++
+ }
+ }
+ if count > 0 {
+ t.Fatalf("found %d records with unexpected comm (want %q)", count, expectedComm)
+ }
+}
+
+// AssertNoUnexpectedPID verifies all records belong to the expected PID.
+// Accepts int to match os.Getpid() return type.
+func AssertNoUnexpectedPID(t *testing.T, result TestResult, expectedPID int) {
+ t.Helper()
+ pid := uint32(expectedPID)
+ var count int
+ for _, rec := range result.Records {
+ if rec.Pid != pid {
+ count++
+ }
+ }
+ if count > 0 {
+ t.Fatalf("found %d records with unexpected PID (want %d)", count, expectedPID)
+ }
+}
+
+func matchesExpectation(rec flamegraph.IterRecord, exp ExpectedEvent) bool {
+ if exp.PathContains != "" && !strings.Contains(rec.Path, exp.PathContains) {
+ return false
+ }
+ if exp.Tracepoint != "" && !strings.Contains(rec.TraceID.String(), exp.Tracepoint) {
+ return false
+ }
+ if exp.Comm != "" && rec.Comm != exp.Comm {
+ return false
+ }
+ return true
+}