项目文件夹

文件
2026-07-13 13:00:08 +08:00

119 行
4.1 KiB
Go

package winsandbox
import (
"strings"
"testing"
"time"
)
func TestWindowsRootLockTimeoutPrecedence(t *testing.T) {
// The explicit env override wins, then the caller's per-run budget, then the
// short interactive default.
t.Setenv("WINDOWS_SANDBOX_LOCK_MS", "")
if got := windowsRootLockTimeout(0); got != defaultWindowsRootLockTimeout {
t.Fatalf("default = %s, want %s", got, defaultWindowsRootLockTimeout)
}
if got := windowsRootLockTimeout(10 * time.Minute); got != 10*time.Minute {
t.Fatalf("spec budget = %s, want 10m", got)
}
t.Setenv("WINDOWS_SANDBOX_LOCK_MS", "1234")
if got := windowsRootLockTimeout(10 * time.Minute); got != 1234*time.Millisecond {
t.Fatalf("env override = %s, want 1.234s", got)
}
// A malformed override falls back instead of hanging or failing.
t.Setenv("WINDOWS_SANDBOX_LOCK_MS", "not-a-number")
if got := windowsRootLockTimeout(0); got != defaultWindowsRootLockTimeout {
t.Fatalf("malformed env = %s, want %s", got, defaultWindowsRootLockTimeout)
}
}
func TestLockHolderRecordRoundTrip(t *testing.T) {
rec := lockHolderRecord{pid: 1234, startUnixMS: 1_700_000_000_000, label: `npm run dev`}
got, ok := parseLockHolderRecord(formatLockHolderRecord(rec))
if !ok || got != rec {
t.Fatalf("round trip = %+v ok=%v, want %+v", got, ok, rec)
}
// A label containing spaces survives; tabs never occur (sanitized on write).
rec.label = "cmd /c echo ok"
if got, ok := parseLockHolderRecord(formatLockHolderRecord(rec)); !ok || got != rec {
t.Fatalf("spaced label round trip = %+v ok=%v", got, ok)
}
}
func TestLockHolderRecordRejectsMalformed(t *testing.T) {
for _, data := range []string{
"",
"garbage",
"12\t34", // missing label field
"0\t123\tcmd", // pid 0 is never a real holder
"-1\t123\tcmd", // negative pid
"nope\t123\tcmd", // non-numeric pid
"12\tnope\tcmd", // non-numeric start
"12\t0\tcmd", // zero start time
"12 34 cmd", // wrong separator
} {
if rec, ok := parseLockHolderRecord(data); ok {
t.Fatalf("parse(%q) = %+v, want rejection", data, rec)
}
}
// Only the first line counts; a trailing partial write cannot corrupt it.
rec, ok := parseLockHolderRecord("12\t34\tcmd\ntrailing garbage")
if !ok || rec.label != "cmd" {
t.Fatalf("multi-line parse = %+v ok=%v, want first line only", rec, ok)
}
}
func TestLockHolderLabelSanitizesAndTruncates(t *testing.T) {
got := lockHolderLabel([]string{"pwsh", "-Command", "npm\trun\ndev"})
if strings.ContainsAny(got, "\t\n\r") {
t.Fatalf("label %q still contains control characters", got)
}
if got != "pwsh -Command npm run dev" {
t.Fatalf("label = %q", got)
}
long := lockHolderLabel([]string{strings.Repeat("x", 500)})
if r := []rune(long); len(r) > lockHolderLabelMaxRunes+1 {
t.Fatalf("label not truncated: %d runes", len(r))
}
if !strings.HasSuffix(long, "…") {
t.Fatalf("truncated label %q missing ellipsis", long)
}
}
func TestDescribeLockHolder(t *testing.T) {
start := time.UnixMilli(1_700_000_000_000)
rec := lockHolderRecord{pid: 1234, startUnixMS: start.UnixMilli(), label: "npm run dev"}
if got := describeLockHolder(rec, start.Add(25*time.Minute)); got != `held by "npm run dev", pid 1234, running 25m` {
t.Fatalf("describe = %q", got)
}
rec.label = ""
if got := describeLockHolder(rec, start.Add(3*time.Second)); got != "held by pid 1234, running 3s" {
t.Fatalf("describe without label = %q", got)
}
}
func TestLockHolderRunningFor(t *testing.T) {
for _, tc := range []struct {
d time.Duration
want string
}{
{-5 * time.Second, "0s"}, // clock skew clamps, never negative
{12 * time.Second, "12s"},
{90 * time.Second, "1m"},
{25 * time.Minute, "25m"},
{2*time.Hour + 5*time.Minute, "2h05m"},
} {
if got := lockHolderRunningFor(tc.d); got != tc.want {
t.Fatalf("runningFor(%s) = %q, want %q", tc.d, got, tc.want)
}
}
}
func TestLockHolderFileNameMatchesMutexDigest(t *testing.T) {
// The holder file is keyed by the same root digest as the mutex name, so the
// two can never pair up differently.
if got := lockHolderFileName(`Local\windows-sandbox.deadbeef00112233`); got != "deadbeef00112233.txt" {
t.Fatalf("holder file = %q, want digest-keyed name", got)
}
}