summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-04-16 23:19:15 +0300
committerPaul Buetow <paul@buetow.org>2025-04-16 23:19:15 +0300
commitcd289eb0d978297b1e331da202eee09ca4c1290c (patch)
tree893466694b6cd7430bb00e353a8c8db55b42b07c /internal
parented7668ec893e21b4cf071c98dd5a292105aeec34 (diff)
add Equals
Diffstat (limited to 'internal')
-rw-r--r--internal/event/event.go1
-rw-r--r--internal/event/pair.go1
-rw-r--r--internal/eventloop.go2
-rw-r--r--internal/eventloop_test.go47
-rw-r--r--internal/file/file.go12
-rw-r--r--internal/types/generate_types_go.raku13
-rw-r--r--internal/types/generated_types.go64
-rw-r--r--internal/types/string.go8
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)])
+}