This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / spindle / engines / microvm / cgroup_test.go
2.8 kB 100 lines
1//go:build linux 2 3package microvm 4 5import ( 6 "log/slog" 7 "os" 8 "testing" 9 10 cgroups "github.com/containerd/cgroups/v3" 11) 12 13func TestSanitizeCgroupName(t *testing.T) { 14 cases := []struct { 15 in string 16 want string 17 }{ 18 {"workflow-abc123", "workflow-abc123"}, 19 {"a/b:c", "a-b-c"}, 20 {"--lead--", "lead"}, 21 {"a__b..c", "a-b-c"}, 22 {"keep.dots_and-dashes", "keep.dots_and-dashes"}, 23 {"", ""}, 24 {"///", ""}, 25 } 26 for _, tc := range cases { 27 if got := sanitizeCgroupName(tc.in); got != tc.want { 28 t.Errorf("sanitizeCgroupName(%q) = %q, want %q", tc.in, got, tc.want) 29 } 30 } 31} 32 33// regression test for the cgroup-namespace-root case: at a populated 34// namespace root the engine must vacate the parent before enabling 35// subtree controllers. 36// 37// run with: 38// 39// go test -c -o microvm.test ./spindle/engines/microvm/ 40// podman run --rm --cap-add SYS_ADMIN --security-opt seccomp=unconfined \ 41// -v $PWD/microvm.test:/t:Z -e SPINDLE_CGROUP_INTEGRATION=1 \ 42// --entrypoint /bin/sh docker.io/library/golang:1.25 \ 43// -c "mount -t cgroup2 cgroup2 /sys/fs/cgroup && exec /t -test.run TestCgroupParentVacatesPopulatedNamespaceRoot" 44func TestCgroupParentVacatesPopulatedNamespaceRoot(t *testing.T) { 45 if os.Getenv("SPINDLE_CGROUP_INTEGRATION") != "1" { 46 t.Skip("see test doc comment on how to run") 47 } 48 if cgroups.Mode() != cgroups.Unified { 49 t.Skip("requires cgroup v2 unified mode") 50 } 51 52 group, err := selfCgroupV2Path() 53 if err != nil { 54 t.Fatal(err) 55 } 56 if group != "/" { 57 t.Skipf("only meaningful at a cgroup namespace root, self cgroup is %q", group) 58 } 59 60 logger := slog.Default() 61 parent, err := initCgroupParent(cgroupParentSelf, 0, logger) 62 if err != nil { 63 t.Fatalf("initCgroupParent at a cgroup namespace root: %v", err) 64 } 65 66 procs, err := parent.root.Procs(false) 67 if err != nil { 68 t.Fatalf("list parent cgroup processes: %v", err) 69 } 70 if len(procs) != 0 { 71 t.Errorf("namespace root still holds %d processes after initCgroupParent; "+ 72 "enabling subtree controllers for microVM cgroups would fail EBUSY", len(procs)) 73 } 74 75 handle, err := prepareCgroup(CgroupLimits{ 76 Enabled: true, 77 Parent: parent, 78 Name: "cgtest-nsroot", 79 MemoryMaxMiB: 64, 80 PidsMax: 256, 81 }, logger) 82 if err != nil { 83 t.Fatalf("create controller-enabled child at namespace root: %v", err) 84 } 85 t.Cleanup(func() { _ = handle.Close() }) 86} 87 88func TestCgroupResourcesSwapOnlyStillSetsMemory(t *testing.T) { 89 swap := int64(8) 90 r := cgroupResources(CgroupLimits{SwapMaxMiB: &swap}) 91 if r.Memory == nil { 92 t.Fatal("a swap limit alone should still produce a memory controller config") 93 } 94 if r.Memory.Max != nil { 95 t.Errorf("memory max should be unset when only swap is limited, got %v", *r.Memory.Max) 96 } 97 if r.Memory.Swap == nil || *r.Memory.Swap != 8*1024*1024 { 98 t.Errorf("swap = %v, want %d bytes", r.Memory.Swap, 8*1024*1024) 99 } 100}