Skip to content

Commit

Permalink
add ut + change error field type
Browse files Browse the repository at this point in the history
Signed-off-by: Gyuho Lee <[email protected]>
  • Loading branch information
gyuho committed Jan 7, 2025
1 parent 6a3d57a commit 51cc934
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 7 deletions.
2 changes: 1 addition & 1 deletion components/accelerator/nvidia/fabric-manager/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func (c *component) Events(ctx context.Context, since time.Time) ([]components.E
b, _ := ev.Matched.JSON()
es := ""
if ev.Error != nil {
es = ev.Error.Error()
es = *ev.Error
}
evs = append(evs, components.Event{
Time: ev.Time,
Expand Down
2 changes: 1 addition & 1 deletion components/dmesg/component_event.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (ev *Event) Events() []components.Event {

es := ""
if logItem.Error != nil {
es = logItem.Error.Error()
es = *logItem.Error
}

ob, err := logItem.JSON()
Expand Down
6 changes: 3 additions & 3 deletions components/dmesg/component_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package dmesg

import (
"encoding/json"
"errors"
"fmt"
"strconv"
"time"
Expand Down Expand Up @@ -91,7 +90,8 @@ func ParseStateDmesgTailScanMatched(m map[string]string) (query_log.Item, error)
ev.Matched = f

if m[EventKeyDmesgMatchedError] != "" {
ev.Error = errors.New(m[EventKeyDmesgMatchedError])
v := m[EventKeyDmesgMatchedError]
ev.Error = &v
}

return ev, nil
Expand Down Expand Up @@ -138,7 +138,7 @@ func (s *State) States() []components.State {
b, _ := item.Matched.JSON()
es := ""
if item.Error != nil {
es = item.Error.Error()
es = *item.Error
}
cs = append(cs, components.State{
Name: StateNameDmesgTailScanMatched,
Expand Down
10 changes: 8 additions & 2 deletions components/query/log/poller.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ type Item struct {
// Matched filter that was applied to this item/line.
Matched *query_log_common.Filter `json:"matched,omitempty"`

Error error `json:"error,omitempty"`
Error *string `json:"error,omitempty"`
}

func (item Item) JSON() ([]byte, error) {
Expand Down Expand Up @@ -187,11 +187,17 @@ func newPoller(ctx context.Context, cfg query_log_config.Config, extractTime que
// This only catches the realtime/latest and all the future logs.
func (pl *poller) pollSync(ctx context.Context) {
for line := range pl.tailLogger.Line() {
var errStr *string
if line.Err != nil {
s := line.Err.Error()
errStr = &s
}

item := Item{
Time: metav1.Time{Time: line.Time},
Line: line.Text,
Matched: line.MatchedFilter,
Error: line.Err,
Error: errStr,
}

pl.bufferedItemsMu.Lock()
Expand Down
152 changes: 152 additions & 0 deletions components/query/log/poller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import (

"github.com/leptonai/gpud/components/query"
query_config "github.com/leptonai/gpud/components/query/config"
query_log_common "github.com/leptonai/gpud/components/query/log/common"
query_log_config "github.com/leptonai/gpud/components/query/log/config"
query_log_tail "github.com/leptonai/gpud/components/query/log/tail"

"github.com/nxadm/tail"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
)

func TestPoller(t *testing.T) {
Expand Down Expand Up @@ -143,3 +145,153 @@ func TestPollerTail(t *testing.T) {
t.Fatalf("expected 2 events, got %d", len(evs))
}
}

func TestItemJSON(t *testing.T) {
t.Parallel()

testCases := []struct {
name string
item Item
wantErr bool
wantJSON string // Add expected JSON string for verification
validate func(t *testing.T, got Item)
}{
{
name: "basic item",
item: Item{
Time: metav1.Time{Time: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)},
Line: "test log line",
},
wantJSON: `{"time":"2024-01-01T00:00:00Z","line":"test log line"}`,
validate: func(t *testing.T, got Item) {
if got.Line != "test log line" {
t.Errorf("expected line %q, got %q", "test log line", got.Line)
}
if !got.Time.Equal(&metav1.Time{Time: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)}) {
t.Errorf("expected time %v, got %v", time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC), got.Time)
}
},
},
{
name: "item with error",
item: Item{
Time: metav1.Time{Time: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)},
Line: "test log line",
Error: ptr.To("test error"),
},
wantJSON: `{"time":"2024-01-01T00:00:00Z","line":"test log line","error":"test error"}`,
validate: func(t *testing.T, got Item) {
if got.Error == nil || *got.Error != "test error" {
t.Errorf("expected error %q, got %v", "test error", got.Error)
}
},
},
{
name: "item with matched filter",
item: Item{
Time: metav1.Time{Time: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)},
Line: "test log line",
Matched: &query_log_common.Filter{
Name: "test filter",
Regex: ptr.To("test.*"),
},
},
wantJSON: `{"time":"2024-01-01T00:00:00Z","line":"test log line","matched":{"name":"test filter","regex":"test.*"}}`,
validate: func(t *testing.T, got Item) {
if got.Matched == nil {
t.Fatal("expected matched filter, got nil")
}
if got.Matched.Name != "test filter" {
t.Errorf("expected filter name %q, got %q", "test filter", got.Matched.Name)
}
if got.Matched.Regex == nil || *got.Matched.Regex != "test.*" {
t.Errorf("expected filter regex %q, got %v", "test.*", got.Matched.Regex)
}
},
},
{
name: "item with nil error",
item: Item{
Time: metav1.Time{Time: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)},
Line: "test log line",
Error: nil,
},
wantJSON: `{"time":"2024-01-01T00:00:00Z","line":"test log line"}`,
validate: func(t *testing.T, got Item) {
if got.Error != nil {
t.Errorf("expected nil error, got %v", got.Error)
}
},
},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()

// Test marshaling
data, err := tc.item.JSON()
if (err != nil) != tc.wantErr {
t.Fatalf("JSON() error = %v, wantErr %v", err, tc.wantErr)
}
if tc.wantErr {
return
}

// Verify JSON string matches expected
if tc.wantJSON != "" {
if got := string(data); got != tc.wantJSON {
t.Errorf("JSON() = %v, want %v", got, tc.wantJSON)
}
}

// Test unmarshaling
got, err := ParseItemJSON(data)
if err != nil {
t.Fatalf("ParseItemJSON() error = %v", err)
}

// Run validation
tc.validate(t, got)
})
}
}

func TestParseItemJSONErrors(t *testing.T) {
t.Parallel()

testCases := []struct {
name string
input string
wantErr bool
}{
{
name: "invalid json",
input: "invalid json",
wantErr: true,
},
{
name: "empty json",
input: "{}",
wantErr: false,
},
{
name: "invalid regex in filter",
input: `{"time":"2024-01-01T00:00:00Z","line":"test","matched":{"regex":"[invalid"}}`,
wantErr: true,
},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()

_, err := ParseItemJSON([]byte(tc.input))
if (err != nil) != tc.wantErr {
t.Errorf("ParseItemJSON() error = %v, wantErr %v", err, tc.wantErr)
}
})
}
}

0 comments on commit 51cc934

Please sign in to comment.