diff options
Diffstat (limited to 'runsc/cgroup')
-rw-r--r-- | runsc/cgroup/BUILD | 29 | ||||
-rw-r--r-- | runsc/cgroup/cgroup_state_autogen.go | 3 | ||||
-rw-r--r-- | runsc/cgroup/cgroup_test.go | 901 |
3 files changed, 3 insertions, 930 deletions
diff --git a/runsc/cgroup/BUILD b/runsc/cgroup/BUILD deleted file mode 100644 index d3aec1fff..000000000 --- a/runsc/cgroup/BUILD +++ /dev/null @@ -1,29 +0,0 @@ -load("//tools:defs.bzl", "go_library", "go_test") - -package(licenses = ["notice"]) - -go_library( - name = "cgroup", - srcs = ["cgroup.go"], - visibility = ["//:sandbox"], - deps = [ - "//pkg/cleanup", - "//pkg/log", - "//pkg/sync", - "@com_github_cenkalti_backoff//:go_default_library", - "@com_github_opencontainers_runtime_spec//specs-go:go_default_library", - "@org_golang_x_sys//unix:go_default_library", - ], -) - -go_test( - name = "cgroup_test", - size = "small", - srcs = ["cgroup_test.go"], - library = ":cgroup", - tags = ["local"], - deps = [ - "//pkg/test/testutil", - "@com_github_opencontainers_runtime_spec//specs-go:go_default_library", - ], -) diff --git a/runsc/cgroup/cgroup_state_autogen.go b/runsc/cgroup/cgroup_state_autogen.go new file mode 100644 index 000000000..934ed169b --- /dev/null +++ b/runsc/cgroup/cgroup_state_autogen.go @@ -0,0 +1,3 @@ +// automatically generated by stateify. + +package cgroup diff --git a/runsc/cgroup/cgroup_test.go b/runsc/cgroup/cgroup_test.go deleted file mode 100644 index 0b6a5431b..000000000 --- a/runsc/cgroup/cgroup_test.go +++ /dev/null @@ -1,901 +0,0 @@ -// Copyright 2018 The gVisor Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cgroup - -import ( - "io/ioutil" - "os" - "path/filepath" - "strings" - "testing" - - specs "github.com/opencontainers/runtime-spec/specs-go" - "gvisor.dev/gvisor/pkg/test/testutil" -) - -var debianMountinfo = ` -35 24 0:30 / /sys/fs/cgroup ro shared:9 - tmpfs tmpfs ro -36 35 0:31 / /sys/fs/cgroup/unified rw shared:10 - cgroup2 cgroup2 rw -37 35 0:32 / /sys/fs/cgroup/systemd rw - cgroup cgroup rw,name=systemd -41 35 0:36 / /sys/fs/cgroup/cpu,cpuacct rw shared:16 - cgroup cgroup rw,cpu,cpuacct -42 35 0:37 / /sys/fs/cgroup/freezer rw shared:17 - cgroup cgroup rw,freezer -43 35 0:38 / /sys/fs/cgroup/hugetlb rw shared:18 - cgroup cgroup rw,hugetlb -44 35 0:39 / /sys/fs/cgroup/cpuset rw shared:19 - cgroup cgroup rw,cpuset -45 35 0:40 / /sys/fs/cgroup/net_cls,net_prio rw shared:20 - cgroup cgroup rw,net_cls,net_prio -46 35 0:41 / /sys/fs/cgroup/pids rw shared:21 - cgroup cgroup rw,pids -47 35 0:42 / /sys/fs/cgroup/perf_event rw shared:22 - cgroup cgroup rw,perf_event -48 35 0:43 / /sys/fs/cgroup/memory rw shared:23 - cgroup cgroup rw,memory -49 35 0:44 / /sys/fs/cgroup/blkio rw shared:24 - cgroup cgroup rw,blkio -50 35 0:45 / /sys/fs/cgroup/devices rw shared:25 - cgroup cgroup rw,devices -51 35 0:46 / /sys/fs/cgroup/rdma rw shared:26 - cgroup cgroup rw,rdma -` - -var dindMountinfo = ` -05 04 0:64 / /sys/fs/cgroup rw - tmpfs tmpfs rw,mode=755 -06 05 0:32 /docker/136 /sys/fs/cgroup/systemd ro master:11 - cgroup cgroup rw,xattr,name=systemd -07 05 0:36 /docker/136 /sys/fs/cgroup/cpu,cpuacct ro master:16 - cgroup cgroup rw,cpu,cpuacct -08 05 0:37 /docker/136 /sys/fs/cgroup/freezer ro master:17 - cgroup cgroup rw,freezer -09 05 0:38 /docker/136 /sys/fs/cgroup/hugetlb ro master:18 - cgroup cgroup rw,hugetlb -10 05 0:39 /docker/136 /sys/fs/cgroup/cpuset ro master:19 - cgroup cgroup rw,cpuset -11 05 0:40 /docker/136 /sys/fs/cgroup/net_cls,net_prio ro master:20 - cgroup cgroup rw,net_cls,net_prio -12 05 0:41 /docker/136 /sys/fs/cgroup/pids ro master:21 - cgroup cgroup rw,pids -13 05 0:42 /docker/136 /sys/fs/cgroup/perf_event ro master:22 - cgroup cgroup rw,perf_event -14 05 0:43 /docker/136 /sys/fs/cgroup/memory ro master:23 - cgroup cgroup rw,memory -16 05 0:44 /docker/136 /sys/fs/cgroup/blkio ro master:24 - cgroup cgroup rw,blkio -17 05 0:45 /docker/136 /sys/fs/cgroup/devices ro master:25 - cgroup cgroup rw,devices -18 05 0:46 / /sys/fs/cgroup/rdma ro master:26 - cgroup cgroup rw,rdma -` - -func TestUninstallEnoent(t *testing.T) { - c := Cgroup{ - // Use a non-existent name. - Name: "runsc-test-uninstall-656e6f656e740a", - Own: make(map[string]bool), - } - for key := range controllers { - c.Own[key] = true - } - if err := c.Uninstall(); err != nil { - t.Errorf("Uninstall() failed: %v", err) - } -} - -func TestCountCpuset(t *testing.T) { - for _, tc := range []struct { - str string - want int - error bool - }{ - {str: "0", want: 1}, - {str: "0,1,2,8,9,10", want: 6}, - {str: "0-1", want: 2}, - {str: "0-7", want: 8}, - {str: "0-7,16,32-39,64,65", want: 19}, - {str: "a", error: true}, - {str: "5-a", error: true}, - {str: "a-5", error: true}, - {str: "-10", error: true}, - {str: "15-", error: true}, - {str: "-", error: true}, - {str: "--", error: true}, - } { - t.Run(tc.str, func(t *testing.T) { - got, err := countCpuset(tc.str) - if tc.error { - if err == nil { - t.Errorf("countCpuset(%q) should have failed", tc.str) - } - } else { - if err != nil { - t.Errorf("countCpuset(%q) failed: %v", tc.str, err) - } - if tc.want != got { - t.Errorf("countCpuset(%q) want: %d, got: %d", tc.str, tc.want, got) - } - } - }) - } -} - -func uint16Ptr(v uint16) *uint16 { - return &v -} - -func uint32Ptr(v uint32) *uint32 { - return &v -} - -func int64Ptr(v int64) *int64 { - return &v -} - -func uint64Ptr(v uint64) *uint64 { - return &v -} - -func boolPtr(v bool) *bool { - return &v -} - -func createDir(dir string, contents map[string]string) error { - for name := range contents { - path := filepath.Join(dir, name) - f, err := os.Create(path) - if err != nil { - return err - } - f.Close() - } - return nil -} - -func checkDir(t *testing.T, dir string, contents map[string]string) { - all, err := ioutil.ReadDir(dir) - if err != nil { - t.Fatalf("ReadDir(%q): %v", dir, err) - } - fileCount := 0 - for _, file := range all { - if file.IsDir() { - // Only want to compare files. - continue - } - fileCount++ - - want, ok := contents[file.Name()] - if !ok { - t.Errorf("file not expected: %q", file.Name()) - continue - } - gotBytes, err := ioutil.ReadFile(filepath.Join(dir, file.Name())) - if err != nil { - t.Fatal(err.Error()) - } - got := strings.TrimSuffix(string(gotBytes), "\n") - if got != want { - t.Errorf("wrong file content, file: %q, want: %q, got: %q", file.Name(), want, got) - } - } - if fileCount != len(contents) { - t.Errorf("file is missing, want: %v, got: %v", contents, all) - } -} - -func makeLinuxWeightDevice(major, minor int64, weight, leafWeight *uint16) specs.LinuxWeightDevice { - rv := specs.LinuxWeightDevice{ - Weight: weight, - LeafWeight: leafWeight, - } - rv.Major = major - rv.Minor = minor - return rv -} - -func makeLinuxThrottleDevice(major, minor int64, rate uint64) specs.LinuxThrottleDevice { - rv := specs.LinuxThrottleDevice{ - Rate: rate, - } - rv.Major = major - rv.Minor = minor - return rv -} - -func TestBlockIO(t *testing.T) { - for _, tc := range []struct { - name string - spec *specs.LinuxBlockIO - wants map[string]string - }{ - { - name: "simple", - spec: &specs.LinuxBlockIO{ - Weight: uint16Ptr(1), - LeafWeight: uint16Ptr(2), - }, - wants: map[string]string{ - "blkio.weight": "1", - "blkio.leaf_weight": "2", - }, - }, - { - name: "weight_device", - spec: &specs.LinuxBlockIO{ - WeightDevice: []specs.LinuxWeightDevice{ - makeLinuxWeightDevice(1, 2, uint16Ptr(3), uint16Ptr(4)), - }, - }, - wants: map[string]string{ - "blkio.weight_device": "1:2 3", - "blkio.leaf_weight_device": "1:2 4", - }, - }, - { - name: "weight_device_nil_values", - spec: &specs.LinuxBlockIO{ - WeightDevice: []specs.LinuxWeightDevice{ - makeLinuxWeightDevice(1, 2, nil, nil), - }, - }, - }, - { - name: "throttle", - spec: &specs.LinuxBlockIO{ - ThrottleReadBpsDevice: []specs.LinuxThrottleDevice{ - makeLinuxThrottleDevice(1, 2, 3), - }, - ThrottleReadIOPSDevice: []specs.LinuxThrottleDevice{ - makeLinuxThrottleDevice(4, 5, 6), - }, - ThrottleWriteBpsDevice: []specs.LinuxThrottleDevice{ - makeLinuxThrottleDevice(7, 8, 9), - }, - ThrottleWriteIOPSDevice: []specs.LinuxThrottleDevice{ - makeLinuxThrottleDevice(10, 11, 12), - }, - }, - wants: map[string]string{ - "blkio.throttle.read_bps_device": "1:2 3", - "blkio.throttle.read_iops_device": "4:5 6", - "blkio.throttle.write_bps_device": "7:8 9", - "blkio.throttle.write_iops_device": "10:11 12", - }, - }, - { - name: "nil_values", - spec: &specs.LinuxBlockIO{}, - }, - { - name: "nil", - }, - } { - t.Run(tc.name, func(t *testing.T) { - dir, err := ioutil.TempDir(testutil.TmpDir(), "cgroup") - if err != nil { - t.Fatalf("error creating temporary directory: %v", err) - } - defer os.RemoveAll(dir) - if err := createDir(dir, tc.wants); err != nil { - t.Fatalf("createDir(): %v", err) - } - - spec := &specs.LinuxResources{ - BlockIO: tc.spec, - } - ctrlr := blockIO{} - if err := ctrlr.set(spec, dir); err != nil { - t.Fatalf("ctrlr.set(): %v", err) - } - checkDir(t, dir, tc.wants) - }) - } -} - -func TestCPU(t *testing.T) { - for _, tc := range []struct { - name string - spec *specs.LinuxCPU - wants map[string]string - }{ - { - name: "all", - spec: &specs.LinuxCPU{ - Shares: uint64Ptr(1), - Quota: int64Ptr(2), - Period: uint64Ptr(3), - RealtimeRuntime: int64Ptr(4), - RealtimePeriod: uint64Ptr(5), - }, - wants: map[string]string{ - "cpu.shares": "1", - "cpu.cfs_quota_us": "2", - "cpu.cfs_period_us": "3", - "cpu.rt_runtime_us": "4", - "cpu.rt_period_us": "5", - }, - }, - { - name: "nil_values", - spec: &specs.LinuxCPU{}, - }, - { - name: "nil", - }, - } { - t.Run(tc.name, func(t *testing.T) { - dir, err := ioutil.TempDir(testutil.TmpDir(), "cgroup") - if err != nil { - t.Fatalf("error creating temporary directory: %v", err) - } - defer os.RemoveAll(dir) - if err := createDir(dir, tc.wants); err != nil { - t.Fatalf("createDir(): %v", err) - } - - spec := &specs.LinuxResources{ - CPU: tc.spec, - } - ctrlr := cpu{} - if err := ctrlr.set(spec, dir); err != nil { - t.Fatalf("ctrlr.set(): %v", err) - } - checkDir(t, dir, tc.wants) - }) - } -} - -func TestCPUSet(t *testing.T) { - for _, tc := range []struct { - name string - spec *specs.LinuxCPU - wants map[string]string - }{ - { - name: "all", - spec: &specs.LinuxCPU{ - Cpus: "foo", - Mems: "bar", - }, - wants: map[string]string{ - "cpuset.cpus": "foo", - "cpuset.mems": "bar", - }, - }, - // Don't test nil values because they are copied from the parent. - // See TestCPUSetAncestor(). - } { - t.Run(tc.name, func(t *testing.T) { - dir, err := ioutil.TempDir(testutil.TmpDir(), "cgroup") - if err != nil { - t.Fatalf("error creating temporary directory: %v", err) - } - defer os.RemoveAll(dir) - if err := createDir(dir, tc.wants); err != nil { - t.Fatalf("createDir(): %v", err) - } - - spec := &specs.LinuxResources{ - CPU: tc.spec, - } - ctrlr := cpuSet{} - if err := ctrlr.set(spec, dir); err != nil { - t.Fatalf("ctrlr.set(): %v", err) - } - checkDir(t, dir, tc.wants) - }) - } -} - -// TestCPUSetAncestor checks that, when not available, value is read from -// parent directory. -func TestCPUSetAncestor(t *testing.T) { - // Prepare master directory with cgroup files that will be propagated to - // children. - grandpa, err := ioutil.TempDir(testutil.TmpDir(), "cgroup") - if err != nil { - t.Fatalf("error creating temporary directory: %v", err) - } - defer os.RemoveAll(grandpa) - - if err := ioutil.WriteFile(filepath.Join(grandpa, "cpuset.cpus"), []byte("parent-cpus"), 0666); err != nil { - t.Fatalf("ioutil.WriteFile(): %v", err) - } - if err := ioutil.WriteFile(filepath.Join(grandpa, "cpuset.mems"), []byte("parent-mems"), 0666); err != nil { - t.Fatalf("ioutil.WriteFile(): %v", err) - } - - for _, tc := range []struct { - name string - spec *specs.LinuxCPU - }{ - { - name: "nil_values", - spec: &specs.LinuxCPU{}, - }, - { - name: "nil", - }, - } { - t.Run(tc.name, func(t *testing.T) { - // Create empty files in intermediate directory. They should be ignored - // when reading, and then populated from parent. - parent, err := ioutil.TempDir(grandpa, "parent") - if err != nil { - t.Fatalf("error creating temporary directory: %v", err) - } - defer os.RemoveAll(parent) - if _, err := os.Create(filepath.Join(parent, "cpuset.cpus")); err != nil { - t.Fatalf("os.Create(): %v", err) - } - if _, err := os.Create(filepath.Join(parent, "cpuset.mems")); err != nil { - t.Fatalf("os.Create(): %v", err) - } - - // cgroup files mmust exist. - dir, err := ioutil.TempDir(parent, "child") - if err != nil { - t.Fatalf("error creating temporary directory: %v", err) - } - if _, err := os.Create(filepath.Join(dir, "cpuset.cpus")); err != nil { - t.Fatalf("os.Create(): %v", err) - } - if _, err := os.Create(filepath.Join(dir, "cpuset.mems")); err != nil { - t.Fatalf("os.Create(): %v", err) - } - - spec := &specs.LinuxResources{ - CPU: tc.spec, - } - ctrlr := cpuSet{} - if err := ctrlr.set(spec, dir); err != nil { - t.Fatalf("ctrlr.set(): %v", err) - } - want := map[string]string{ - "cpuset.cpus": "parent-cpus", - "cpuset.mems": "parent-mems", - } - // Both path and dir must have been populated from grandpa. - checkDir(t, parent, want) - checkDir(t, dir, want) - }) - } -} - -func TestHugeTlb(t *testing.T) { - for _, tc := range []struct { - name string - spec []specs.LinuxHugepageLimit - wants map[string]string - }{ - { - name: "single", - spec: []specs.LinuxHugepageLimit{ - { - Pagesize: "1G", - Limit: 123, - }, - }, - wants: map[string]string{ - "hugetlb.1G.limit_in_bytes": "123", - }, - }, - { - name: "multiple", - spec: []specs.LinuxHugepageLimit{ - { - Pagesize: "1G", - Limit: 123, - }, - { - Pagesize: "2G", - Limit: 456, - }, - { - Pagesize: "1P", - Limit: 789, - }, - }, - wants: map[string]string{ - "hugetlb.1G.limit_in_bytes": "123", - "hugetlb.2G.limit_in_bytes": "456", - "hugetlb.1P.limit_in_bytes": "789", - }, - }, - { - name: "nil", - }, - } { - t.Run(tc.name, func(t *testing.T) { - dir, err := ioutil.TempDir(testutil.TmpDir(), "cgroup") - if err != nil { - t.Fatalf("error creating temporary directory: %v", err) - } - defer os.RemoveAll(dir) - if err := createDir(dir, tc.wants); err != nil { - t.Fatalf("createDir(): %v", err) - } - - spec := &specs.LinuxResources{ - HugepageLimits: tc.spec, - } - ctrlr := hugeTLB{} - if err := ctrlr.set(spec, dir); err != nil { - t.Fatalf("ctrlr.set(): %v", err) - } - checkDir(t, dir, tc.wants) - }) - } -} - -func TestMemory(t *testing.T) { - for _, tc := range []struct { - name string - spec *specs.LinuxMemory - wants map[string]string - }{ - { - name: "all", - spec: &specs.LinuxMemory{ - Limit: int64Ptr(1), - Reservation: int64Ptr(2), - Swap: int64Ptr(3), - Kernel: int64Ptr(4), - KernelTCP: int64Ptr(5), - Swappiness: uint64Ptr(6), - DisableOOMKiller: boolPtr(true), - }, - wants: map[string]string{ - "memory.limit_in_bytes": "1", - "memory.soft_limit_in_bytes": "2", - "memory.memsw.limit_in_bytes": "3", - "memory.kmem.limit_in_bytes": "4", - "memory.kmem.tcp.limit_in_bytes": "5", - "memory.swappiness": "6", - "memory.oom_control": "1", - }, - }, - { - // Disable OOM killer should only write when set to true. - name: "oomkiller", - spec: &specs.LinuxMemory{ - DisableOOMKiller: boolPtr(false), - }, - }, - { - name: "nil_values", - spec: &specs.LinuxMemory{}, - }, - { - name: "nil", - }, - } { - t.Run(tc.name, func(t *testing.T) { - dir, err := ioutil.TempDir(testutil.TmpDir(), "cgroup") - if err != nil { - t.Fatalf("error creating temporary directory: %v", err) - } - defer os.RemoveAll(dir) - if err := createDir(dir, tc.wants); err != nil { - t.Fatalf("createDir(): %v", err) - } - - spec := &specs.LinuxResources{ - Memory: tc.spec, - } - ctrlr := memory{} - if err := ctrlr.set(spec, dir); err != nil { - t.Fatalf("ctrlr.set(): %v", err) - } - checkDir(t, dir, tc.wants) - }) - } -} - -func TestNetworkClass(t *testing.T) { - for _, tc := range []struct { - name string - spec *specs.LinuxNetwork - wants map[string]string - }{ - { - name: "all", - spec: &specs.LinuxNetwork{ - ClassID: uint32Ptr(1), - }, - wants: map[string]string{ - "net_cls.classid": "1", - }, - }, - { - name: "nil_values", - spec: &specs.LinuxNetwork{}, - }, - { - name: "nil", - }, - } { - t.Run(tc.name, func(t *testing.T) { - dir, err := ioutil.TempDir(testutil.TmpDir(), "cgroup") - if err != nil { - t.Fatalf("error creating temporary directory: %v", err) - } - defer os.RemoveAll(dir) - if err := createDir(dir, tc.wants); err != nil { - t.Fatalf("createDir(): %v", err) - } - - spec := &specs.LinuxResources{ - Network: tc.spec, - } - ctrlr := networkClass{} - if err := ctrlr.set(spec, dir); err != nil { - t.Fatalf("ctrlr.set(): %v", err) - } - checkDir(t, dir, tc.wants) - }) - } -} - -func TestNetworkPriority(t *testing.T) { - for _, tc := range []struct { - name string - spec *specs.LinuxNetwork - wants map[string]string - }{ - { - name: "all", - spec: &specs.LinuxNetwork{ - Priorities: []specs.LinuxInterfacePriority{ - { - Name: "foo", - Priority: 1, - }, - }, - }, - wants: map[string]string{ - "net_prio.ifpriomap": "foo 1", - }, - }, - { - name: "nil_values", - spec: &specs.LinuxNetwork{}, - }, - { - name: "nil", - }, - } { - t.Run(tc.name, func(t *testing.T) { - dir, err := ioutil.TempDir(testutil.TmpDir(), "cgroup") - if err != nil { - t.Fatalf("error creating temporary directory: %v", err) - } - defer os.RemoveAll(dir) - if err := createDir(dir, tc.wants); err != nil { - t.Fatalf("createDir(): %v", err) - } - - spec := &specs.LinuxResources{ - Network: tc.spec, - } - ctrlr := networkPrio{} - if err := ctrlr.set(spec, dir); err != nil { - t.Fatalf("ctrlr.set(): %v", err) - } - checkDir(t, dir, tc.wants) - }) - } -} - -func TestPids(t *testing.T) { - for _, tc := range []struct { - name string - spec *specs.LinuxPids - wants map[string]string - }{ - { - name: "all", - spec: &specs.LinuxPids{Limit: 1}, - wants: map[string]string{ - "pids.max": "1", - }, - }, - { - name: "nil_values", - spec: &specs.LinuxPids{}, - }, - { - name: "nil", - }, - } { - t.Run(tc.name, func(t *testing.T) { - dir, err := ioutil.TempDir(testutil.TmpDir(), "cgroup") - if err != nil { - t.Fatalf("error creating temporary directory: %v", err) - } - defer os.RemoveAll(dir) - if err := createDir(dir, tc.wants); err != nil { - t.Fatalf("createDir(): %v", err) - } - - spec := &specs.LinuxResources{ - Pids: tc.spec, - } - ctrlr := pids{} - if err := ctrlr.set(spec, dir); err != nil { - t.Fatalf("ctrlr.set(): %v", err) - } - checkDir(t, dir, tc.wants) - }) - } -} - -func TestLoadPaths(t *testing.T) { - for _, tc := range []struct { - name string - cgroups string - mountinfo string - want map[string]string - err string - }{ - { - name: "empty", - mountinfo: debianMountinfo, - }, - { - name: "abs-path", - cgroups: "0:cpu:/path", - mountinfo: debianMountinfo, - want: map[string]string{"cpu": "/path"}, - }, - { - name: "rel-path", - cgroups: "0:cpu:rel-path", - mountinfo: debianMountinfo, - want: map[string]string{"cpu": "rel-path"}, - }, - { - name: "non-controller", - cgroups: "0:name=systemd:/path", - mountinfo: debianMountinfo, - want: map[string]string{"systemd": "/path"}, - }, - { - name: "unknown-controller", - cgroups: "0:ctr:/path", - mountinfo: debianMountinfo, - want: map[string]string{}, - }, - { - name: "multiple", - cgroups: "0:cpu:/path0\n" + - "1:memory:/path1\n" + - "2::/empty\n", - mountinfo: debianMountinfo, - want: map[string]string{ - "cpu": "/path0", - "memory": "/path1", - }, - }, - { - name: "missing-field", - cgroups: "0:nopath\n", - mountinfo: debianMountinfo, - err: "invalid cgroups file", - }, - { - name: "too-many-fields", - cgroups: "0:ctr:/path:extra\n", - mountinfo: debianMountinfo, - err: "invalid cgroups file", - }, - { - name: "multiple-malformed", - cgroups: "0:ctr0:/path0\n" + - "1:ctr1:/path1\n" + - "2:\n", - mountinfo: debianMountinfo, - err: "invalid cgroups file", - }, - { - name: "nested-cgroup", - cgroups: "9:memory:/docker/136\n" + - "2:cpu,cpuacct:/docker/136\n" + - "1:name=systemd:/docker/136\n" + - "0::/system.slice/containerd.service\n", - mountinfo: dindMountinfo, - // we want relative path to /sys/fs/cgroup inside the nested container. - // Subcroup inside the container will be created at /sys/fs/cgroup/cpu - // This will be /sys/fs/cgroup/cpu/docker/136/CGROUP_NAME - // outside the container - want: map[string]string{ - "memory": ".", - "cpu": ".", - "cpuacct": ".", - "systemd": ".", - }, - }, - { - name: "nested-cgroup-submount", - cgroups: "9:memory:/docker/136/test", - mountinfo: dindMountinfo, - want: map[string]string{ - "memory": "test", - }, - }, - { - name: "invalid-mount-info", - cgroups: "0:memory:/path", - mountinfo: "41 35 0:36 / /sys/fs/cgroup/memory rw shared:16 - invalid", - want: map[string]string{ - "memory": "/path", - }, - }, - { - name: "invalid-rel-path-in-proc-cgroup", - cgroups: "9:memory:invalid", - mountinfo: dindMountinfo, - err: "can't make invalid relative to /docker/136", - }, - } { - t.Run(tc.name, func(t *testing.T) { - r := strings.NewReader(tc.cgroups) - mountinfo := strings.NewReader(tc.mountinfo) - got, err := loadPathsHelper(r, mountinfo) - if len(tc.err) == 0 { - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - } else if err == nil || !strings.Contains(err.Error(), tc.err) { - t.Fatalf("Wrong error message, want: *%s*, got: %v", tc.err, err) - } - for key, vWant := range tc.want { - vGot, ok := got[key] - if !ok { - t.Errorf("Missing controller %q", key) - } - if vWant != vGot { - t.Errorf("Wrong controller %q value, want: %q, got: %q", key, vWant, vGot) - } - delete(got, key) - } - for k, v := range got { - t.Errorf("Unexpected controller %q: %q", k, v) - } - }) - } -} - -func TestOptional(t *testing.T) { - for _, tc := range []struct { - name string - ctrlr controller - spec *specs.LinuxResources - err string - }{ - { - name: "net-cls", - ctrlr: &networkClass{}, - spec: &specs.LinuxResources{Network: &specs.LinuxNetwork{ClassID: uint32Ptr(1)}}, - err: "Network.ClassID set but net_cls cgroup controller not found", - }, - { - name: "net-prio", - ctrlr: &networkPrio{}, - spec: &specs.LinuxResources{Network: &specs.LinuxNetwork{ - Priorities: []specs.LinuxInterfacePriority{ - {Name: "foo", Priority: 1}, - }, - }}, - err: "Network.Priorities set but net_prio cgroup controller not found", - }, - { - name: "hugetlb", - ctrlr: &hugeTLB{}, - spec: &specs.LinuxResources{HugepageLimits: []specs.LinuxHugepageLimit{ - {Pagesize: "1", Limit: 2}, - }}, - err: "HugepageLimits set but hugetlb cgroup controller not found", - }, - } { - t.Run(tc.name, func(t *testing.T) { - err := tc.ctrlr.skip(tc.spec) - if err == nil { - t.Fatalf("ctrlr.skip() didn't fail") - } - if !strings.Contains(err.Error(), tc.err) { - t.Errorf("ctrlr.skip() want: *%s*, got: %q", tc.err, err) - } - }) - } -} |