1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
package streamrow
import (
"sync"
"testing"
"ior/internal/event"
"ior/internal/file"
"ior/internal/types"
)
func TestSequencerStartsAfterSeed(t *testing.T) {
seq := NewSequencer(41)
if got, want := seq.Next(), uint64(42); got != want {
t.Fatalf("first Next() = %d, want %d", got, want)
}
if got, want := seq.Next(), uint64(43); got != want {
t.Fatalf("second Next() = %d, want %d", got, want)
}
}
func TestSequencerIsMonotonicUnderConcurrency(t *testing.T) {
seq := NewSequencer(0)
const workers = 8
const perWorker = 64
got := make(chan uint64, workers*perWorker)
var wg sync.WaitGroup
for i := 0; i < workers; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < perWorker; j++ {
got <- seq.Next()
}
}()
}
wg.Wait()
close(got)
seen := make(map[uint64]struct{}, workers*perWorker)
for n := range got {
if _, ok := seen[n]; ok {
t.Fatalf("duplicate sequence number %d", n)
}
seen[n] = struct{}{}
}
if got, want := len(seen), workers*perWorker; got != want {
t.Fatalf("unique sequence count = %d, want %d", got, want)
}
}
func TestNewPopulatesFieldsFromPair(t *testing.T) {
enter := &types.OpenEvent{TraceId: types.SYS_ENTER_OPENAT, Time: 1234, Pid: 42, Tid: 84}
exit := &types.RetEvent{TraceId: types.SYS_EXIT_OPENAT, Time: 1300, Ret: -2, Pid: 42, Tid: 84}
pair := event.NewPair(enter)
pair.ExitEv = exit
pair.File = file.NewFd(7, "/tmp/test.txt", 0)
pair.Comm = "cat"
pair.Duration = 66
pair.DurationToPrev = 19
pair.Bytes = 512
got := New(9, pair)
if got.Seq != 9 || got.TimeNs != 1234 {
t.Fatalf("Seq/TimeNs = %d/%d, want 9/1234", got.Seq, got.TimeNs)
}
if got.Syscall != "openat" || got.Comm != "cat" {
t.Fatalf("Syscall/Comm = %q/%q, want openat/cat", got.Syscall, got.Comm)
}
if got.PID != 42 || got.TID != 84 {
t.Fatalf("PID/TID = %d/%d, want 42/84", got.PID, got.TID)
}
if got.FileName != "/tmp/test.txt" || got.FD != 7 {
t.Fatalf("FileName/FD = %q/%d, want /tmp/test.txt/7", got.FileName, got.FD)
}
if got.DurationNs != 66 || got.GapNs != 19 || got.Bytes != 512 {
t.Fatalf("DurationNs/GapNs/Bytes = %d/%d/%d, want 66/19/512", got.DurationNs, got.GapNs, got.Bytes)
}
if got.RetVal != -2 || !got.IsError {
t.Fatalf("RetVal/IsError = %d/%v, want -2/true", got.RetVal, got.IsError)
}
}
func TestNewWarningPopulatesSyntheticWarningFields(t *testing.T) {
got := NewWarning(7, "Dropped malformed event")
if got.Seq != 7 || got.TimeNs == 0 {
t.Fatalf("Seq/TimeNs = %d/%d, want 7/non-zero", got.Seq, got.TimeNs)
}
if got.Syscall != "warning" || got.Comm != "ior" {
t.Fatalf("Syscall/Comm = %q/%q, want warning/ior", got.Syscall, got.Comm)
}
if got.FileName != "Dropped malformed event" || got.FD != UnknownFD {
t.Fatalf("FileName/FD = %q/%d, want warning text/%d", got.FileName, got.FD, UnknownFD)
}
if got.RetVal != -1 || !got.IsError {
t.Fatalf("RetVal/IsError = %d/%v, want -1/true", got.RetVal, got.IsError)
}
}
|