Files
monlet/agent/internal/runner/runner_test.go
2026-05-26 16:41:27 +04:00

114 lines
2.9 KiB
Go

package runner
import (
"context"
"strings"
"testing"
"time"
"unicode/utf8"
)
func TestMapExit(t *testing.T) {
cases := map[int]Status{0: StatusOK, 1: StatusWarning, 2: StatusCritical, 3: StatusUnknown, 255: StatusUnknown}
for code, want := range cases {
if got := MapExit(code); got != want {
t.Errorf("MapExit(%d)=%s want %s", code, got, want)
}
}
}
func TestTruncateUTF8Short(t *testing.T) {
out, tr := TruncateUTF8([]byte("hi"), 100)
if tr || out != "hi" {
t.Fatalf("got %q tr=%v", out, tr)
}
}
func TestTruncateUTF8Long(t *testing.T) {
in := strings.Repeat("a", 9000)
out, tr := TruncateUTF8([]byte(in), MaxOutputBytes)
if !tr {
t.Fatal("expected truncated")
}
if len([]byte(out)) > MaxOutputBytes {
t.Fatalf("byte len %d > %d", len([]byte(out)), MaxOutputBytes)
}
if !strings.Contains(out, "truncated") {
t.Fatalf("no marker: %q", out[len(out)-50:])
}
}
func TestTruncateUTF8SanitizesInvalidBytes(t *testing.T) {
// invalid UTF-8 bytes that json.Marshal would replace with U+FFFD (3 bytes each)
in := append([]byte("hello"), 0xff, 0xfe, 0xfd)
out, tr := TruncateUTF8(in, 100)
if tr {
t.Fatal("should fit")
}
if !utf8.ValidString(out) {
t.Fatalf("output must be valid UTF-8: %q", out)
}
}
func TestTruncateUTF8Multibyte(t *testing.T) {
in := strings.Repeat("ё", 5000) // 2 bytes per rune = 10000 bytes
out, tr := TruncateUTF8([]byte(in), MaxOutputBytes)
if !tr {
t.Fatal("expected truncated")
}
if !utf8.ValidString(out) {
t.Fatal("invalid UTF-8 after truncate")
}
if len([]byte(out)) > MaxOutputBytes {
t.Fatalf("byte len %d > %d", len([]byte(out)), MaxOutputBytes)
}
}
func TestRunOK(t *testing.T) {
r := Run(context.Background(), []string{"sh", "-c", "echo ok"}, 2*time.Second)
if r.Status != StatusOK || r.ExitCode != 0 {
t.Fatalf("got %+v", r)
}
if !strings.Contains(r.Output, "ok") {
t.Fatalf("output: %q", r.Output)
}
}
func TestRunWarning(t *testing.T) {
r := Run(context.Background(), []string{"sh", "-c", "exit 1"}, 2*time.Second)
if r.Status != StatusWarning || r.ExitCode != 1 {
t.Fatalf("got %+v", r)
}
}
func TestRunCritical(t *testing.T) {
r := Run(context.Background(), []string{"sh", "-c", "exit 2"}, 2*time.Second)
if r.Status != StatusCritical {
t.Fatalf("got %+v", r)
}
}
func TestRunUnknownExit(t *testing.T) {
r := Run(context.Background(), []string{"sh", "-c", "exit 7"}, 2*time.Second)
if r.Status != StatusUnknown || r.ExitCode != 7 {
t.Fatalf("got %+v", r)
}
}
func TestRunTimeout(t *testing.T) {
r := Run(context.Background(), []string{"sh", "-c", "sleep 5"}, 200*time.Millisecond)
if r.Status != StatusUnknown {
t.Fatalf("got %+v", r)
}
if r.DurationMs > 2000 {
t.Fatalf("duration too long: %d", r.DurationMs)
}
}
func TestRunNoExec(t *testing.T) {
r := Run(context.Background(), []string{"/does/not/exist/zzz"}, 1*time.Second)
if r.Status != StatusUnknown {
t.Fatalf("got %+v", r)
}
}