package collector import ( "testing" "time" ) func TestSortConnections(t *testing.T) { conns := []Connection{ {PID: 3, Process: "nginx", Lport: 80, State: "ESTABLISHED"}, {PID: 1, Process: "sshd", Lport: 22, State: "LISTEN"}, {PID: 2, Process: "postgres", Lport: 5432, State: "LISTEN"}, } t.Run("sort by PID ascending", func(t *testing.T) { c := make([]Connection, len(conns)) copy(c, conns) SortConnections(c, SortOptions{Field: SortByPID, Direction: SortAsc}) if c[0].PID != 1 || c[1].PID != 2 || c[2].PID != 3 { t.Errorf("expected PIDs [1,2,3], got [%d,%d,%d]", c[0].PID, c[1].PID, c[2].PID) } }) t.Run("sort by PID descending", func(t *testing.T) { c := make([]Connection, len(conns)) copy(c, conns) SortConnections(c, SortOptions{Field: SortByPID, Direction: SortDesc}) if c[0].PID != 3 || c[1].PID != 2 || c[2].PID != 1 { t.Errorf("expected PIDs [3,2,1], got [%d,%d,%d]", c[0].PID, c[1].PID, c[2].PID) } }) t.Run("sort by port ascending", func(t *testing.T) { c := make([]Connection, len(conns)) copy(c, conns) SortConnections(c, SortOptions{Field: SortByLport, Direction: SortAsc}) if c[0].Lport != 22 || c[1].Lport != 80 || c[2].Lport != 5432 { t.Errorf("expected ports [22,80,5432], got [%d,%d,%d]", c[0].Lport, c[1].Lport, c[2].Lport) } }) t.Run("sort by state puts LISTEN first", func(t *testing.T) { c := make([]Connection, len(conns)) copy(c, conns) SortConnections(c, SortOptions{Field: SortByState, Direction: SortAsc}) if c[0].State != "LISTEN" || c[1].State != "LISTEN" || c[2].State != "ESTABLISHED" { t.Errorf("expected LISTEN states first, got [%s,%s,%s]", c[0].State, c[1].State, c[2].State) } }) t.Run("sort by process case insensitive", func(t *testing.T) { c := []Connection{ {Process: "Nginx"}, {Process: "apache"}, {Process: "SSHD"}, } SortConnections(c, SortOptions{Field: SortByProcess, Direction: SortAsc}) if c[0].Process != "apache" { t.Errorf("expected apache first, got %s", c[0].Process) } }) } func TestParseSortOptions(t *testing.T) { tests := []struct { input string wantField SortField wantDir SortDirection }{ {"pid", SortByPID, SortAsc}, {"pid:asc", SortByPID, SortAsc}, {"pid:desc", SortByPID, SortDesc}, {"lport", SortByLport, SortAsc}, {"LPORT:DESC", SortByLport, SortDesc}, {"", SortByLport, SortAsc}, // default } for _, tt := range tests { t.Run(tt.input, func(t *testing.T) { opts := ParseSortOptions(tt.input) if opts.Field != tt.wantField { t.Errorf("field: got %v, want %v", opts.Field, tt.wantField) } if opts.Direction != tt.wantDir { t.Errorf("direction: got %v, want %v", opts.Direction, tt.wantDir) } }) } } func TestStateOrder(t *testing.T) { if stateOrder("LISTEN") >= stateOrder("ESTABLISHED") { t.Error("LISTEN should come before ESTABLISHED") } if stateOrder("ESTABLISHED") >= stateOrder("TIME_WAIT") { t.Error("ESTABLISHED should come before TIME_WAIT") } if stateOrder("UNKNOWN") != 99 { t.Error("unknown states should return 99") } } func TestSortByTimestamp(t *testing.T) { now := time.Now() conns := []Connection{ {TS: now.Add(2 * time.Second)}, {TS: now}, {TS: now.Add(1 * time.Second)}, } SortConnections(conns, SortOptions{Field: SortByTimestamp, Direction: SortAsc}) if !conns[0].TS.Equal(now) { t.Error("oldest timestamp should be first") } if !conns[2].TS.Equal(now.Add(2 * time.Second)) { t.Error("newest timestamp should be last") } }