Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168//go:build linux
package microvm
import ( "log/slog" "os" "testing"
cgroups "github.com/containerd/cgroups/v3" "github.com/containerd/cgroups/v3/cgroup2/stats")
func TestSanitizeCgroupName(t *testing.T) { cases := []struct { in string want string }{ {"workflow-abc123", "workflow-abc123"}, {"a/b:c", "a-b-c"}, {"--lead--", "lead"}, {"a__b..c", "a-b-c"}, {"keep.dots_and-dashes", "keep.dots_and-dashes"}, {"", ""}, {"///", ""}, } for _, tc := range cases { if got := sanitizeCgroupName(tc.in); got != tc.want { t.Errorf("sanitizeCgroupName(%q) = %q, want %q", tc.in, got, tc.want) } }}
// regression test for the cgroup-namespace-root case: at a populated// namespace root the engine must vacate the parent before enabling// subtree controllers.//// run with://// go test -c -o microvm.test ./spindle/engines/microvm/// podman run --rm --cap-add SYS_ADMIN --security-opt seccomp=unconfined \// -v $PWD/microvm.test:/t:Z -e SPINDLE_CGROUP_INTEGRATION=1 \// --entrypoint /bin/sh docker.io/library/golang:1.25 \// -c "mount -t cgroup2 cgroup2 /sys/fs/cgroup && exec /t -test.run TestCgroupParentVacatesPopulatedNamespaceRoot"func TestCgroupParentVacatesPopulatedNamespaceRoot(t *testing.T) { if os.Getenv("SPINDLE_CGROUP_INTEGRATION") != "1" { t.Skip("see test doc comment on how to run") } if cgroups.Mode() != cgroups.Unified { t.Skip("requires cgroup v2 unified mode") }
group, err := selfCgroupV2Path() if err != nil { t.Fatal(err) } if group != "/" { t.Skipf("only meaningful at a cgroup namespace root, self cgroup is %q", group) }
logger := slog.Default() parent, err := initCgroupParent(cgroupParentSelf, 0, logger) if err != nil { t.Fatalf("initCgroupParent at a cgroup namespace root: %v", err) }
procs, err := parent.root.Procs(false) if err != nil { t.Fatalf("list parent cgroup processes: %v", err) } if len(procs) != 0 { t.Errorf("namespace root still holds %d processes after initCgroupParent; "+ "enabling subtree controllers for microVM cgroups would fail EBUSY", len(procs)) }
handle, err := prepareCgroup(CgroupLimits{ Enabled: true, Parent: parent, Name: "cgtest-nsroot", MemoryMaxMiB: 64, PidsMax: 256, }, logger) if err != nil { t.Fatalf("create controller-enabled child at namespace root: %v", err) } t.Cleanup(func() { _ = handle.Close() })}
func TestCgroupResourcesSwapOnlyStillSetsMemory(t *testing.T) { swap := int64(8) r := cgroupResources(CgroupLimits{SwapMaxMiB: &swap}) if r.Memory == nil { t.Fatal("a swap limit alone should still produce a memory controller config") } if r.Memory.Max != nil { t.Errorf("memory max should be unset when only swap is limited, got %v", *r.Memory.Max) } if r.Memory.Swap == nil || *r.Memory.Swap != 8*1024*1024 { t.Errorf("swap = %v, want %d bytes", r.Memory.Swap, 8*1024*1024) }}
func TestParseCgroupUsage(t *testing.T) { metrics := &stats.Metrics{ CPU: &stats.CPUStat{ UsageUsec: 12345, }, Memory: &stats.MemoryStat{ Usage: 654321, MaxUsage: 999999, SwapUsage: 111111, SwapMaxUsage: 222222, }, Pids: &stats.PidsStat{ Current: 42, }, Io: &stats.IOStat{ Usage: []*stats.IOEntry{ { Rbytes: 100, Wbytes: 200, Rios: 5, Wios: 10, }, { Rbytes: 50, Wbytes: 80, Rios: 2, Wios: 4, }, }, }, }
usage := parseCgroupUsage(metrics)
if usage.CPU.UsageUsec != 12345 { t.Errorf("CPU.UsageUsec = %d, want 12345", usage.CPU.UsageUsec) } if usage.Memory.Usage != 654321 { t.Errorf("Memory.Usage = %d, want 654321", usage.Memory.Usage) } if usage.Memory.MaxUsage != 999999 { t.Errorf("Memory.MaxUsage = %d, want 999999", usage.Memory.MaxUsage) } if usage.Memory.SwapUsage != 111111 { t.Errorf("Memory.SwapUsage = %d, want 111111", usage.Memory.SwapUsage) } if usage.Memory.SwapMaxUsage != 222222 { t.Errorf("Memory.SwapMaxUsage = %d, want 222222", usage.Memory.SwapMaxUsage) } if usage.Pids.Current != 42 { t.Errorf("Pids.Current = %d, want 42", usage.Pids.Current) } if usage.IO.Rbytes != 150 { t.Errorf("IO.Rbytes = %d, want 150", usage.IO.Rbytes) } if usage.IO.Wbytes != 280 { t.Errorf("IO.Wbytes = %d, want 280", usage.IO.Wbytes) } if usage.IO.Rios != 7 { t.Errorf("IO.Rios = %d, want 7", usage.IO.Rios) } if usage.IO.Wios != 14 { t.Errorf("IO.Wios = %d, want 14", usage.IO.Wios) }}