cmd/gitbay-runner/cgroup_test.go

v1.29.0
gitbay/cmd/gitbay-runner/cgroup_test.go history · blame · raw

92 lines · 2683 bytes

 1package main
 2
 3import (
 4	"os"
 5	"path/filepath"
 6	"testing"
 7)
 8
 9// Podman's --memory and --cpus never applied under rootless cgroupfs: the
10// container ran in the service's own cgroup and crun could not create a
11// child (#188). The runner now owns the build cgroups itself and places
12// podman inside one, so the limits are written by the runner in cgroup
13// v2's own units.
14func TestMemoryBytes(t *testing.T) {
15	cases := map[string]int64{
16		"64m":  64 << 20,
17		"6g":   6 << 30,
18		"512k": 512 << 10,
19		"100b": 100,
20		"4096": 4096,
21		"1G":   1 << 30,
22	}
23	for in, want := range cases {
24		got, err := memoryBytes(in)
25		if err != nil || got != want {
26			t.Errorf("memoryBytes(%q) = %d, %v; want %d", in, got, err, want)
27		}
28	}
29	for _, bad := range []string{"", "lots", "6gb", "-1g", "1.5g"} {
30		if _, err := memoryBytes(bad); err == nil {
31			t.Errorf("memoryBytes(%q) accepted", bad)
32		}
33	}
34}
35
36func TestCPUMax(t *testing.T) {
37	cases := map[string]string{
38		"3":    "300000 100000",
39		"1":    "100000 100000",
40		"1.5":  "150000 100000",
41		"0.25": "25000 100000",
42	}
43	for in, want := range cases {
44		got, err := cpuMax(in)
45		if err != nil || got != want {
46			t.Errorf("cpuMax(%q) = %q, %v; want %q", in, got, err, want)
47		}
48	}
49	for _, bad := range []string{"", "0", "-1", "two"} {
50		if _, err := cpuMax(bad); err == nil {
51			t.Errorf("cpuMax(%q) accepted", bad)
52		}
53	}
54}
55
56// /proc/self/cgroup on cgroup v2 is one line, "0::<path>".
57func TestOwnCgroupPath(t *testing.T) {
58	got, err := ownCgroupPath("0::/system.slice/gitbay-runner.service\n")
59	if err != nil || got != "/system.slice/gitbay-runner.service" {
60		t.Fatalf("ownCgroupPath = %q, %v", got, err)
61	}
62	// A v1 hierarchy, or anything else, is not something the runner
63	// manages.
64	if _, err := ownCgroupPath("12:memory:/user.slice\n0::/init.scope\n"); err == nil {
65		t.Fatal("v1 hierarchy accepted")
66	}
67}
68
69// Limits land as cgroup v2 interface files in the build's directory;
70// an unset limit writes nothing, which means "inherit", not "max".
71func TestWriteLimits(t *testing.T) {
72	dir := t.TempDir()
73	if err := writeLimits(dir, "6g", "3"); err != nil {
74		t.Fatal(err)
75	}
76	if got, _ := os.ReadFile(filepath.Join(dir, "memory.max")); string(got) != "6442450944" {
77		t.Errorf("memory.max = %q", got)
78	}
79	if got, _ := os.ReadFile(filepath.Join(dir, "cpu.max")); string(got) != "300000 100000" {
80		t.Errorf("cpu.max = %q", got)
81	}
82	empty := t.TempDir()
83	if err := writeLimits(empty, "", ""); err != nil {
84		t.Fatal(err)
85	}
86	if entries, _ := os.ReadDir(empty); len(entries) != 0 {
87		t.Errorf("unset limits wrote %v", entries)
88	}
89	if err := writeLimits(t.TempDir(), "lots", ""); err == nil {
90		t.Error("a bad memory limit was accepted")
91	}
92}