122 lines
3.7 KiB
Go
122 lines
3.7 KiB
Go
package services
|
|
|
|
import "testing"
|
|
|
|
func TestParseJournalLine(t *testing.T) {
|
|
line := []byte(`{"__REALTIME_TIMESTAMP":"1750406104000000","PRIORITY":"6","MESSAGE":"Started OpenSSH server daemon.","_PID":"123"}`)
|
|
e, ok := parseJournalLine(line)
|
|
if !ok {
|
|
t.Fatal("expected parse to succeed")
|
|
}
|
|
if e.Message != "Started OpenSSH server daemon." {
|
|
t.Errorf("message = %q", e.Message)
|
|
}
|
|
if e.Priority != 6 {
|
|
t.Errorf("priority = %d", e.Priority)
|
|
}
|
|
if e.Time != "2025-06-20T07:55:04Z" {
|
|
t.Errorf("time = %q", e.Time)
|
|
}
|
|
}
|
|
|
|
func TestParseJournalLineBinaryMessage(t *testing.T) {
|
|
// Binary MESSAGE is encoded as a byte array; we yield an empty message, not an error.
|
|
line := []byte(`{"__REALTIME_TIMESTAMP":"1750406104000000","PRIORITY":"3","MESSAGE":[104,105]}`)
|
|
e, ok := parseJournalLine(line)
|
|
if !ok || e.Message != "" || e.Priority != 3 {
|
|
t.Errorf("got ok=%v entry=%+v", ok, e)
|
|
}
|
|
}
|
|
|
|
func TestParseJournalLineMissingPriority(t *testing.T) {
|
|
// PRIORITY is often absent; it must default to info (6), not emerg (0).
|
|
line := []byte(`{"__REALTIME_TIMESTAMP":"1750406104000000","MESSAGE":"hi"}`)
|
|
e, ok := parseJournalLine(line)
|
|
if !ok || e.Priority != 6 {
|
|
t.Errorf("got ok=%v priority=%d, want priority 6", ok, e.Priority)
|
|
}
|
|
}
|
|
|
|
func TestParseJournalLineGarbage(t *testing.T) {
|
|
if _, ok := parseJournalLine([]byte("not json")); ok {
|
|
t.Error("garbage line should not parse")
|
|
}
|
|
}
|
|
|
|
func TestResolveLogPath(t *testing.T) {
|
|
allow := map[string][]string{
|
|
"nginx.service": {"/var/log/nginx/access.log", "/var/log/nginx/error.log"},
|
|
}
|
|
|
|
t.Run("allowlisted path via bare name", func(t *testing.T) {
|
|
p, err := resolveLogPath(allow, "nginx", "/var/log/nginx/error.log")
|
|
if err != nil || p != "/var/log/nginx/error.log" {
|
|
t.Errorf("got %q, %v", p, err)
|
|
}
|
|
})
|
|
t.Run("allowlisted path via service suffix", func(t *testing.T) {
|
|
p, err := resolveLogPath(allow, "nginx.service", "/var/log/nginx/error.log")
|
|
if err != nil || p != "/var/log/nginx/error.log" {
|
|
t.Errorf("got %q, %v", p, err)
|
|
}
|
|
})
|
|
|
|
for _, tt := range []struct {
|
|
name string
|
|
unit string
|
|
path string
|
|
}{
|
|
{name: "empty path", unit: "nginx.service", path: ""},
|
|
{name: "non-allowlisted path", unit: "nginx.service", path: "/etc/shadow"},
|
|
{name: "path traversal", unit: "nginx.service", path: "/var/log/nginx/access.log/../../../etc/shadow"},
|
|
{name: "wrong unit", unit: "sshd.service", path: "/var/log/nginx/error.log"},
|
|
{name: "unknown unit", unit: "unknown.service", path: "/var/log/nginx/error.log"},
|
|
} {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if _, err := resolveLogPath(allow, tt.unit, tt.path); err == nil {
|
|
t.Errorf("resolveLogPath(%q, %q) = nil error, want rejection", tt.unit, tt.path)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestJournalUnit(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
in string
|
|
want string
|
|
}{
|
|
{name: "docker service", in: "docker.service", want: "docker"},
|
|
{name: "docker bare", in: "docker", want: "docker"},
|
|
{name: "sshd service", in: "sshd.service", want: "sshd"},
|
|
{name: "socket unit", in: "foo.socket", want: "foo.socket"},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := journalUnit(tt.in); got != tt.want {
|
|
t.Errorf("journalUnit(%q) = %q, want %q", tt.in, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestClampLines(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
in int
|
|
want int
|
|
}{
|
|
{name: "zero", in: 0, want: defaultLogLines},
|
|
{name: "negative", in: -5, want: defaultLogLines},
|
|
{name: "fifty", in: 50, want: 50},
|
|
{name: "too large", in: 999999, want: maxLogLines},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := clampLines(tt.in); got != tt.want {
|
|
t.Errorf("clampLines(%d) = %d, want %d", tt.in, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|