diff options
| author | Paul Buetow <paul@buetow.org> | 2025-04-16 23:19:15 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-04-16 23:19:15 +0300 |
| commit | cd289eb0d978297b1e331da202eee09ca4c1290c (patch) | |
| tree | 893466694b6cd7430bb00e353a8c8db55b42b07c /internal | |
| parent | ed7668ec893e21b4cf071c98dd5a292105aeec34 (diff) | |
add Equals
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/event/event.go | 1 | ||||
| -rw-r--r-- | internal/event/pair.go | 1 | ||||
| -rw-r--r-- | internal/eventloop.go | 2 | ||||
| -rw-r--r-- | internal/eventloop_test.go | 47 | ||||
| -rw-r--r-- | internal/file/file.go | 12 | ||||
| -rw-r--r-- | internal/types/generate_types_go.raku | 13 | ||||
| -rw-r--r-- | internal/types/generated_types.go | 64 | ||||
| -rw-r--r-- | internal/types/string.go | 8 |
8 files changed, 121 insertions, 27 deletions
diff --git a/internal/event/event.go b/internal/event/event.go index aa0e317..165ffe3 100644 --- a/internal/event/event.go +++ b/internal/event/event.go @@ -15,5 +15,6 @@ type Event interface { GetPid() uint32 GetTid() uint32 GetTime() uint64 + Equals(other any) bool Recycle() } diff --git a/internal/event/pair.go b/internal/event/pair.go index 13ad7e0..0900b27 100644 --- a/internal/event/pair.go +++ b/internal/event/pair.go @@ -15,6 +15,7 @@ type Pair struct { Comm string Duration uint64 DurationToPrev uint64 + Equals bool } func NewPair(enterEv Event) *Pair { diff --git a/internal/eventloop.go b/internal/eventloop.go index 6aa5fee..929f202 100644 --- a/internal/eventloop.go +++ b/internal/eventloop.go @@ -210,7 +210,7 @@ func (e *eventLoop) tracepointExited(exitEv event.Event, ch chan<- *event.Pair) switch v := ep.EnterEv.(type) { case *OpenEvent: openEv := ep.EnterEv.(*OpenEvent) - comm := file.StringValue(openEv.Comm[:]) + comm := types.StringValue(openEv.Comm[:]) if fd := int32(ep.ExitEv.(*RetEvent).Ret); fd >= 0 { file := file.NewFd(fd, openEv.Filename[:], v.Flags) e.files[fd] = file diff --git a/internal/eventloop_test.go b/internal/eventloop_test.go index f61487e..841fb8a 100644 --- a/internal/eventloop_test.go +++ b/internal/eventloop_test.go @@ -4,32 +4,30 @@ import ( "context" "fmt" "ior/internal/event" - "ior/internal/file" "ior/internal/types" "syscall" "testing" ) -type validateFunc func(t *testing.T, ev *event.Pair) - type testData struct { - rawTracepoints [][]byte // All the raw tracepoints sent to the event loop - validates []validateFunc // Validation functions to check the event pairs + rawTracepoints [][]byte // All the raw tracepoints sent to the event loop + validates []func(t *testing.T, ev *event.Pair) // Validation functions to be called on the event loop output } func TestEventloop(t *testing.T) { testTable := map[string]testData{ - "OpenEventTest": makeOpenEventTestData(t), + "OpenEventTest1": makeOpenEventTestData1(t), + "OpenEventTest2": makeOpenEventTestData2(t), } ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - inCh := make(chan []byte) - defer close(inCh) - outCh := make(chan *event.Pair) - defer close(outCh) + defer func() { + cancel() + close(inCh) + close(outCh) + }() ev := newEventLoop() ev.printCb = func(ev *event.Pair) { outCh <- ev } @@ -39,11 +37,14 @@ func TestEventloop(t *testing.T) { t.Run(testName, func(t *testing.T) { go func() { for _, raw := range td.rawTracepoints { + t.Log("Sending raw tracepoint", raw, "simulating BPF sending this") inCh <- raw } }() for _, validate := range td.validates { - validate(t, <-outCh) + ep := <-outCh + t.Log("Received", ep) + validate(t, ep) } select { case x := <-outCh: @@ -54,7 +55,7 @@ func TestEventloop(t *testing.T) { } } -func makeOpenEventTestData(t *testing.T) (td testData) { +func makeOpenEventTestData1(t *testing.T) (td testData) { enterEv, enterEvBytes := makeEnterOpenEvent(t) td.rawTracepoints = append(td.rawTracepoints, enterEvBytes) @@ -62,17 +63,17 @@ func makeOpenEventTestData(t *testing.T) (td testData) { td.rawTracepoints = append(td.rawTracepoints, exitEvBytes) td.validates = append(td.validates, func(t *testing.T, ep *event.Pair) { - if ep.EnterEv.GetTraceId() != enterEv.TraceId { - t.Errorf("Expected TraceId '%v' but got '%v'", enterEv.TraceId, ep.EnterEv.GetTraceId()) + if !enterEv.Equals(ep.EnterEv) { + t.Errorf("Expected '%v' but got '%v'", enterEv, ep.EnterEv) return } filenameA := ep.FileName() - filenameB := file.StringValue(enterEv.Filename[:]) + filenameB := types.StringValue(enterEv.Filename[:]) if filenameA != filenameB { t.Errorf("Expected file name '%v' but got '%v'", filenameB, filenameA) return } - comm := file.StringValue(enterEv.Comm[:]) + comm := types.StringValue(enterEv.Comm[:]) if ep.Comm != comm { t.Errorf("Expected comm name '%v' but got '%v'", comm, ep.Comm) return @@ -82,6 +83,18 @@ func makeOpenEventTestData(t *testing.T) (td testData) { return td } +func makeOpenEventTestData2(t *testing.T) (td testData) { + // Almost the same, but with duplicates + td1 := makeOpenEventTestData1(t) + td.rawTracepoints = append(td.rawTracepoints, td1.rawTracepoints[1]) // Will be ignored by the event loop + td.rawTracepoints = append(td.rawTracepoints, td1.rawTracepoints[0]) // Will be used by the event loop + td.rawTracepoints = append(td.rawTracepoints, td1.rawTracepoints[0]) // Will be ignored by the event loop + td.rawTracepoints = append(td.rawTracepoints, td1.rawTracepoints[1]) // Will be used by the event loop + td.rawTracepoints = append(td.rawTracepoints, td1.rawTracepoints[1]) // Will be ignored by the event loop + td.validates = td1.validates + + return td +} func makeEnterOpenEvent(t *testing.T) (types.OpenEvent, []byte) { ev := types.OpenEvent{ diff --git a/internal/file/file.go b/internal/file/file.go index aff9b8b..9edd27b 100644 --- a/internal/file/file.go +++ b/internal/file/file.go @@ -4,6 +4,7 @@ import ( "bufio" "bytes" "fmt" + "ior/internal/types" "os" "strconv" "strings" @@ -25,7 +26,7 @@ type FdFile struct { func NewFd(fd int32, name []byte, flags int32) FdFile { f := FdFile{ fd: fd, - name: StringValue(name), + name: types.StringValue(name), flags: Flags(flags), } if f.flags == -1 { @@ -106,7 +107,7 @@ type oldnameNewnameFile struct { } func NewOldnameNewname(oldname, newname []byte) oldnameNewnameFile { - return oldnameNewnameFile{StringValue(oldname), StringValue(newname)} + return oldnameNewnameFile{types.StringValue(oldname), types.StringValue(newname)} } func (f oldnameNewnameFile) Name() string { @@ -136,7 +137,7 @@ type pathnameFile struct { } func NewPathname(pathname []byte) pathnameFile { - return pathnameFile{StringValue(pathname)} + return pathnameFile{types.StringValue(pathname)} } func (f pathnameFile) Name() string { @@ -158,8 +159,3 @@ func (f pathnameFile) String() string { return sb.String() } - -// As data comes in from arrays, converted to slices, there will be null-bytes at the end.. -func StringValue(byteStr []byte) string { - return string(byteStr[:bytes.IndexByte(byteStr, 0)]) -} diff --git a/internal/types/generate_types_go.raku b/internal/types/generate_types_go.raku index febed82..dfba0b1 100644 --- a/internal/types/generate_types_go.raku +++ b/internal/types/generate_types_go.raku @@ -39,11 +39,22 @@ role StructGoMethods { ($_.<type> eq 'char' && $_.<arraysize>) ?? "string({$ref}[:])" !! $ref; }); + qq:to/END/; func ($self-ref {$<identifier>.made}) String() string \{ return fmt.Sprintf("{@format.join(' ')}", {@args.join(', ')}) \} + func ($self-ref {$<identifier>.made}) Equals(other any) bool \{ + otherConcrete, ok := other.(*{$<identifier>.made}) + if !ok \{ + return false + \} + return {$<member>.map({ $_.<identifier>.made }).map({ + "$self-ref.$_ == otherConcrete.$_" + }).join(' && ') } + \} + func ($self-ref *{$<identifier>.made}) GetEventType() EventType \{ return $self-ref.EventType \} @@ -148,7 +159,7 @@ class NQCToGoActions does StructGoMethods does ConstantGoMethods { make qq:to/END/; // Code generated - don't change manually! package types - + {self.constant-go-methods} {$<construct>.map(*.made).join('')} END diff --git a/internal/types/generated_types.go b/internal/types/generated_types.go index 1293ae3..9f220dd 100644 --- a/internal/types/generated_types.go +++ b/internal/types/generated_types.go @@ -69,6 +69,14 @@ func (o OpenEvent) String() string { return fmt.Sprintf("EventType:%v TraceId:%v Time:%v Pid:%v Tid:%v Flags:%v Filename:%v Comm:%v", o.EventType, o.TraceId, o.Time, o.Pid, o.Tid, o.Flags, string(o.Filename[:]), string(o.Comm[:])) } +func (o OpenEvent) Equals(other any) bool { + otherConcrete, ok := other.(*OpenEvent) + if !ok { + return false + } + return o.EventType == otherConcrete.EventType && o.TraceId == otherConcrete.TraceId && o.Time == otherConcrete.Time && o.Pid == otherConcrete.Pid && o.Tid == otherConcrete.Tid && o.Flags == otherConcrete.Flags && o.Filename == otherConcrete.Filename && o.Comm == otherConcrete.Comm +} + func (o *OpenEvent) GetEventType() EventType { return o.EventType } @@ -127,6 +135,14 @@ func (n NullEvent) String() string { return fmt.Sprintf("EventType:%v TraceId:%v Time:%v Pid:%v Tid:%v", n.EventType, n.TraceId, n.Time, n.Pid, n.Tid) } +func (n NullEvent) Equals(other any) bool { + otherConcrete, ok := other.(*NullEvent) + if !ok { + return false + } + return n.EventType == otherConcrete.EventType && n.TraceId == otherConcrete.TraceId && n.Time == otherConcrete.Time && n.Pid == otherConcrete.Pid && n.Tid == otherConcrete.Tid +} + func (n *NullEvent) GetEventType() EventType { return n.EventType } @@ -186,6 +202,14 @@ func (f FdEvent) String() string { return fmt.Sprintf("EventType:%v TraceId:%v Time:%v Pid:%v Tid:%v Fd:%v", f.EventType, f.TraceId, f.Time, f.Pid, f.Tid, f.Fd) } +func (f FdEvent) Equals(other any) bool { + otherConcrete, ok := other.(*FdEvent) + if !ok { + return false + } + return f.EventType == otherConcrete.EventType && f.TraceId == otherConcrete.TraceId && f.Time == otherConcrete.Time && f.Pid == otherConcrete.Pid && f.Tid == otherConcrete.Tid && f.Fd == otherConcrete.Fd +} + func (f *FdEvent) GetEventType() EventType { return f.EventType } @@ -245,6 +269,14 @@ func (r RetEvent) String() string { return fmt.Sprintf("EventType:%v TraceId:%v Time:%v Ret:%v Pid:%v Tid:%v", r.EventType, r.TraceId, r.Time, r.Ret, r.Pid, r.Tid) } +func (r RetEvent) Equals(other any) bool { + otherConcrete, ok := other.(*RetEvent) + if !ok { + return false + } + return r.EventType == otherConcrete.EventType && r.TraceId == otherConcrete.TraceId && r.Time == otherConcrete.Time && r.Ret == otherConcrete.Ret && r.Pid == otherConcrete.Pid && r.Tid == otherConcrete.Tid +} + func (r *RetEvent) GetEventType() EventType { return r.EventType } @@ -305,6 +337,14 @@ func (n NameEvent) String() string { return fmt.Sprintf("EventType:%v TraceId:%v Time:%v Pid:%v Tid:%v Oldname:%v Newname:%v", n.EventType, n.TraceId, n.Time, n.Pid, n.Tid, string(n.Oldname[:]), string(n.Newname[:])) } +func (n NameEvent) Equals(other any) bool { + otherConcrete, ok := other.(*NameEvent) + if !ok { + return false + } + return n.EventType == otherConcrete.EventType && n.TraceId == otherConcrete.TraceId && n.Time == otherConcrete.Time && n.Pid == otherConcrete.Pid && n.Tid == otherConcrete.Tid && n.Oldname == otherConcrete.Oldname && n.Newname == otherConcrete.Newname +} + func (n *NameEvent) GetEventType() EventType { return n.EventType } @@ -364,6 +404,14 @@ func (p PathEvent) String() string { return fmt.Sprintf("EventType:%v TraceId:%v Time:%v Pid:%v Tid:%v Pathname:%v", p.EventType, p.TraceId, p.Time, p.Pid, p.Tid, string(p.Pathname[:])) } +func (p PathEvent) Equals(other any) bool { + otherConcrete, ok := other.(*PathEvent) + if !ok { + return false + } + return p.EventType == otherConcrete.EventType && p.TraceId == otherConcrete.TraceId && p.Time == otherConcrete.Time && p.Pid == otherConcrete.Pid && p.Tid == otherConcrete.Tid && p.Pathname == otherConcrete.Pathname +} + func (p *PathEvent) GetEventType() EventType { return p.EventType } @@ -425,6 +473,14 @@ func (f FcntlEvent) String() string { return fmt.Sprintf("EventType:%v TraceId:%v Time:%v Pid:%v Tid:%v Fd:%v Cmd:%v Arg:%v", f.EventType, f.TraceId, f.Time, f.Pid, f.Tid, f.Fd, f.Cmd, f.Arg) } +func (f FcntlEvent) Equals(other any) bool { + otherConcrete, ok := other.(*FcntlEvent) + if !ok { + return false + } + return f.EventType == otherConcrete.EventType && f.TraceId == otherConcrete.TraceId && f.Time == otherConcrete.Time && f.Pid == otherConcrete.Pid && f.Tid == otherConcrete.Tid && f.Fd == otherConcrete.Fd && f.Cmd == otherConcrete.Cmd && f.Arg == otherConcrete.Arg +} + func (f *FcntlEvent) GetEventType() EventType { return f.EventType } @@ -485,6 +541,14 @@ func (d Dup3Event) String() string { return fmt.Sprintf("EventType:%v TraceId:%v Time:%v Pid:%v Tid:%v Fd:%v Flags:%v", d.EventType, d.TraceId, d.Time, d.Pid, d.Tid, d.Fd, d.Flags) } +func (d Dup3Event) Equals(other any) bool { + otherConcrete, ok := other.(*Dup3Event) + if !ok { + return false + } + return d.EventType == otherConcrete.EventType && d.TraceId == otherConcrete.TraceId && d.Time == otherConcrete.Time && d.Pid == otherConcrete.Pid && d.Tid == otherConcrete.Tid && d.Fd == otherConcrete.Fd && d.Flags == otherConcrete.Flags +} + func (d *Dup3Event) GetEventType() EventType { return d.EventType } diff --git a/internal/types/string.go b/internal/types/string.go new file mode 100644 index 0000000..363b746 --- /dev/null +++ b/internal/types/string.go @@ -0,0 +1,8 @@ +package types + +import "bytes" + +// As data comes in from arrays, converted to slices, there will be null-bytes at the end.. +func StringValue(byteStr []byte) string { + return string(byteStr[:bytes.IndexByte(byteStr, 0)]) +} |
