Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pre main #103

Merged
merged 19 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions pkg/eBPF/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ import (
"github.com/intelops/tarian-detector/pkg/err"
)

var handlerErr = err.New("ebpf.handler")

// Handler represents an eBPF handler.
type Handler struct {
name string
mapReaders []any
probeLinks []link.Link
name string // Name of the handler
mapReaders []any // List of map readers
probeLinks []link.Link // List of probe links
}

var handlerErr = err.New("ebpf.handler")

// NewHandler creates a new eBPF handler with the given name.
func NewHandler(n string) *Handler {
return &Handler{
name: n,
Expand All @@ -24,22 +26,27 @@ func NewHandler(n string) *Handler {
}
}

// AddProbeLink adds a probe link to the handler.
func (h *Handler) AddProbeLink(l link.Link) {
h.probeLinks = append(h.probeLinks, l)
}

// AddMapReaders adds map readers to the handler.
func (h *Handler) AddMapReaders(mrs []any) {
h.mapReaders = append(h.mapReaders, mrs...)
}

// ReadAsInterface returns a slice of functions that read data from maps.
func (h *Handler) ReadAsInterface() ([]func() ([]byte, error), error) {
return read(h.mapReaders)
}

// Count returns the number of probe links in the handler.
func (h *Handler) Count() int {
return len(h.probeLinks)
}

// Close detaches probes and closes map readers.
func (h *Handler) Close() error {
if err := detachProbes(h.probeLinks); err != nil {
return handlerErr.Throwf("%v", err)
Expand All @@ -48,14 +55,17 @@ func (h *Handler) Close() error {
return closeMapReaders(h.mapReaders)
}

// GetName returns the name of the handler.
func (h *Handler) GetName() string {
return h.name
}

// GetMapReaders returns the map readers associated with the handler.
func (h *Handler) GetMapReaders() []any {
return h.mapReaders
}

// GetProbeLinks returns the probe links associated with the handler.
func (h *Handler) GetProbeLinks() []link.Link {
return h.probeLinks
}
289 changes: 289 additions & 0 deletions pkg/eBPF/handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2024 Authors of Tarian & the Organization created Tarian

package ebpf

import (
"os"
"reflect"
"testing"

"github.com/cilium/ebpf/link"
"github.com/cilium/ebpf/perf"
)

// TestHandler_GetName tests the GetName function
func TestHandler_GetName(t *testing.T) {
type fields struct {
name string
mapReaders []any
probeLinks []link.Link
}
tests := []struct {
name string
fields fields
want string
}{
{
name: "valid values",
fields: fields{
name: "test",
mapReaders: make([]any, 0),
probeLinks: make([]link.Link, 0),
},
want: "test",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := &Handler{
name: tt.fields.name,
mapReaders: tt.fields.mapReaders,
probeLinks: tt.fields.probeLinks,
}
if got := h.GetName(); got != tt.want {
t.Errorf("Handler.GetName() = %v, want %v", got, tt.want)
}
})
}
}

// TestHandler_GetMapReaders tests the GetMapReaders function
func TestHandler_GetMapReaders(t *testing.T) {
type fields struct {
name string
mapReaders []any
probeLinks []link.Link
}
tests := []struct {
name string
fields fields
want []any
}{
{
name: "valid values",
fields: fields{
name: "test",
mapReaders: make([]any, 0),
probeLinks: make([]link.Link, 0),
},
want: make([]any, 0),
},
{
name: "nil values",
fields: fields{
name: "test",
mapReaders: nil,
probeLinks: nil,
},
want: nil,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := &Handler{
name: tt.fields.name,
mapReaders: tt.fields.mapReaders,
probeLinks: tt.fields.probeLinks,
}
if got := h.GetMapReaders(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Handler.GetMapReaders() = %v, want %v", got, tt.want)
}
})
}
}

// TestHandler_GetProbeLinks tests the GetProbeLinks function
func TestHandler_GetProbeLinks(t *testing.T) {
type fields struct {
name string
mapReaders []any
probeLinks []link.Link
}
tests := []struct {
name string
fields fields
want []link.Link
}{
{
name: "valid values",
fields: fields{
name: "test",
mapReaders: make([]any, 0),
probeLinks: make([]link.Link, 0),
},
want: make([]link.Link, 0),
},
{
name: "nil values",
fields: fields{
name: "test",
mapReaders: nil,
probeLinks: nil,
},
want: nil,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := &Handler{
name: tt.fields.name,
mapReaders: tt.fields.mapReaders,
probeLinks: tt.fields.probeLinks,
}
if got := h.GetProbeLinks(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Handler.GetProbeLinks() = %v, want %v", got, tt.want)
}
})
}
}

// TestHandler_Count tests the Count function
func TestHandler_Count(t *testing.T) {
prog := dummy_kprobe_prog(t)
l, _ := link.Kprobe("vprintk", prog, nil)

type fields struct {
name string
mapReaders []any
probeLinks []link.Link
}
tests := []struct {
name string
fields fields
want int
}{
{
name: "valid values",
fields: fields{
name: "test",
mapReaders: make([]any, 0),
probeLinks: make([]link.Link, 0),
},
want: 0,
},
{
name: "add an item to the probelink",
fields: fields{
name: "test",
mapReaders: nil,
probeLinks: []link.Link{l, l, l},
},
want: 3,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := &Handler{
name: tt.fields.name,
mapReaders: tt.fields.mapReaders,
probeLinks: tt.fields.probeLinks,
}
if got := h.Count(); got != tt.want {
t.Errorf("Handler.Count() = %v, want %v", got, tt.want)
}
})
}
}

// TestHandler_ReadAsInterface tests the ReadAsInterface function
func TestHandler_ReadAsInterface(t *testing.T) {
mapP := dummy_perf_map(t)

type fields struct {
name string
mapReaders []any
probeLinks []link.Link
}
tests := []struct {
name string
fields fields
want int
wantErr bool
}{
{
name: "valid values",
fields: fields{
name: "test",
mapReaders: make([]any, 0),
probeLinks: make([]link.Link, 0),
},
want: 0,
wantErr: false,
},
{
name: "invalid values",
fields: fields{
name: "test",
mapReaders: []any{
func() *perf.Reader {
r, _ := perf.NewReader(mapP, os.Getpagesize())
return r
}(),
},
probeLinks: make([]link.Link, 0),
},
want: 1,
wantErr: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := &Handler{
name: tt.fields.name,
mapReaders: tt.fields.mapReaders,
probeLinks: tt.fields.probeLinks,
}
got, err := h.ReadAsInterface()
if (err != nil) != tt.wantErr {
t.Errorf("Handler.ReadAsInterface() error = %v, wantErr %v", err, tt.wantErr)
return
}
if len(got) != tt.want {
t.Errorf("Handler.ReadAsInterface() = %v, want %v", got, tt.want)
}
})
}
}

// TestHandler_Close tests the Close function
func TestHandler_Close(t *testing.T) {
type fields struct {
name string
mapReaders []any
probeLinks []link.Link
}
tests := []struct {
name string
fields fields
wantErr bool
}{
{
name: "valid values",
fields: fields{
name: "test",
mapReaders: make([]any, 0),
probeLinks: make([]link.Link, 0),
},
wantErr: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := &Handler{
name: tt.fields.name,
mapReaders: tt.fields.mapReaders,
probeLinks: tt.fields.probeLinks,
}
if err := h.Close(); (err != nil) != tt.wantErr {
t.Errorf("Handler.Close() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
Loading