114 lines
2.9 KiB
Go
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)
|
|
}
|
|
}
|