diff options
author | Will Chandler <wchandler@gitlab.com> | 2023-11-09 06:07:45 +0300 |
---|---|---|
committer | Will Chandler <wchandler@gitlab.com> | 2023-11-10 17:55:33 +0300 |
commit | d7d074c8800fd1ec26af2c06c0cc0dbb332d18f6 (patch) | |
tree | d8bc970313f6047783beac27c8952b4cd61257fe | |
parent | 0a07f3e3d4b5e24e5525d5f4c03919ad032e811a (diff) |
cgroups: Unify TestSetup_ParentCgroups
Coalesce `TestSetup_ParentCgroups()` and `TestSetup_ParentCgroupsV2()`
into a single test that handles both v1 and v2 cgroups.
Note that the `requireCgroupComponents()` helper introduced slightly
changes the conditions checked versus the v1 test. The v2 manager
requires that `setupMockCgroupFiles()` be executed before running
`Setup()`. The v1 test used `requireCgroup()`, which would verify that a
file was _not_ present, which is no longer be the case now that we have
setup the cgroup files. We switch to `requireCgroupWithInt()` to avoid
this failure.
-rw-r--r-- | internal/cgroups/handler_linux_test.go | 139 | ||||
-rw-r--r-- | internal/cgroups/v1_linux_test.go | 83 | ||||
-rw-r--r-- | internal/cgroups/v2_linux_test.go | 78 |
3 files changed, 139 insertions, 161 deletions
diff --git a/internal/cgroups/handler_linux_test.go b/internal/cgroups/handler_linux_test.go index 12ac52b4e..ab22af6f1 100644 --- a/internal/cgroups/handler_linux_test.go +++ b/internal/cgroups/handler_linux_test.go @@ -3,6 +3,9 @@ package cgroups import ( + "fmt" + "path/filepath" + "strconv" "testing" cgrps "github.com/containerd/cgroups/v3" @@ -23,3 +26,139 @@ func TestNewManager(t *testing.T) { manager = newCgroupManagerWithMode(cfg, testhelper.SharedLogger(t), 1, cgrps.Unavailable) require.Nil(t, manager) } + +type expectedCgroup struct { + wantMemoryBytes int + wantCPUShares int + wantCPUQuotaUs int + wantCFSPeriod int + wantCPUWeight int + wantCPUMax string +} + +func TestSetup_ParentCgroups(t *testing.T) { + tests := []struct { + name string + cfg cgroups.Config + expectedV1 expectedCgroup + expectedV2 expectedCgroup + }{ + { + name: "all config specified", + cfg: cgroups.Config{ + MemoryBytes: 102400, + CPUShares: 256, + CPUQuotaUs: 200, + }, + expectedV1: expectedCgroup{ + wantMemoryBytes: 102400, + wantCPUShares: 256, + wantCPUQuotaUs: 200, + wantCFSPeriod: int(cfsPeriodUs), + }, + expectedV2: expectedCgroup{ + wantMemoryBytes: 102400, + wantCPUWeight: 256, + wantCPUMax: "200 100000", + }, + }, + { + name: "only memory limit set", + cfg: cgroups.Config{ + MemoryBytes: 102400, + }, + expectedV1: expectedCgroup{ + wantMemoryBytes: 102400, + }, + expectedV2: expectedCgroup{ + wantMemoryBytes: 102400, + }, + }, + { + name: "only cpu shares set", + cfg: cgroups.Config{ + CPUShares: 512, + }, + expectedV1: expectedCgroup{ + wantCPUShares: 512, + }, + expectedV2: expectedCgroup{ + wantCPUWeight: 512, + }, + }, + { + name: "only cpu quota set", + cfg: cgroups.Config{ + CPUQuotaUs: 200, + }, + expectedV1: expectedCgroup{ + wantCPUQuotaUs: 200, + wantCFSPeriod: int(cfsPeriodUs), + }, + expectedV2: expectedCgroup{ + wantCPUMax: "200 100000", + }, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + for _, version := range []int{1, 2} { + version := version + t.Run("cgroups-v"+strconv.Itoa(version), func(t *testing.T) { + t.Parallel() + + mock := newMock(t, version) + + pid := 1 + + cfg := tt.cfg + cfg.HierarchyRoot = "gitaly" + cfg.Mountpoint = mock.rootPath() + + manager := mock.newCgroupManager(cfg, testhelper.SharedLogger(t), pid) + mock.setupMockCgroupFiles(t, manager, []uint{}) + + require.False(t, manager.Ready()) + require.NoError(t, manager.Setup()) + require.True(t, manager.Ready()) + + cgroupPath := filepath.Join("gitaly", fmt.Sprintf("gitaly-%d", pid)) + if version == 1 { + requireCgroupComponents(t, version, mock.rootPath(), cgroupPath, tt.expectedV1) + } else { + requireCgroupComponents(t, version, mock.rootPath(), cgroupPath, tt.expectedV2) + } + }) + } + }) + } +} + +func requireCgroupComponents(t *testing.T, version int, root string, cgroupPath string, expected expectedCgroup) { + t.Helper() + + if version == 1 { + memoryLimitPath := filepath.Join(root, "memory", cgroupPath, "memory.limit_in_bytes") + requireCgroupWithInt(t, memoryLimitPath, expected.wantMemoryBytes) + + cpuSharesPath := filepath.Join(root, "cpu", cgroupPath, "cpu.shares") + requireCgroupWithInt(t, cpuSharesPath, expected.wantCPUShares) + + cpuCFSQuotaPath := filepath.Join(root, "cpu", cgroupPath, "cpu.cfs_quota_us") + requireCgroupWithInt(t, cpuCFSQuotaPath, expected.wantCPUQuotaUs) + + cpuCFSPeriodPath := filepath.Join(root, "cpu", cgroupPath, "cpu.cfs_period_us") + requireCgroupWithInt(t, cpuCFSPeriodPath, expected.wantCFSPeriod) + } else { + memoryMaxPath := filepath.Join(root, cgroupPath, "memory.max") + requireCgroupWithInt(t, memoryMaxPath, expected.wantMemoryBytes) + + cpuWeightPath := filepath.Join(root, cgroupPath, "cpu.weight") + requireCgroupWithInt(t, cpuWeightPath, calculateWantCPUWeight(expected.wantCPUWeight)) + + cpuMaxPath := filepath.Join(root, cgroupPath, "cpu.max") + requireCgroupWithString(t, cpuMaxPath, expected.wantCPUMax) + } +} diff --git a/internal/cgroups/v1_linux_test.go b/internal/cgroups/v1_linux_test.go index 73be99f9d..11ae09209 100644 --- a/internal/cgroups/v1_linux_test.go +++ b/internal/cgroups/v1_linux_test.go @@ -33,89 +33,6 @@ func defaultCgroupsConfig() cgroups.Config { } } -func TestSetup_ParentCgroups(t *testing.T) { - tests := []struct { - name string - cfg cgroups.Config - wantMemoryBytes int - wantCPUShares int - wantCPUQuotaUs int - wantCFSPeriod int - }{ - { - name: "all config specified", - cfg: cgroups.Config{ - MemoryBytes: 102400, - CPUShares: 256, - CPUQuotaUs: 200, - }, - wantMemoryBytes: 102400, - wantCPUShares: 256, - wantCPUQuotaUs: 200, - wantCFSPeriod: int(cfsPeriodUs), - }, - { - name: "only memory limit set", - cfg: cgroups.Config{ - MemoryBytes: 102400, - }, - wantMemoryBytes: 102400, - }, - { - name: "only cpu shares set", - cfg: cgroups.Config{ - CPUShares: 512, - }, - wantCPUShares: 512, - }, - { - name: "only cpu quota set", - cfg: cgroups.Config{ - CPUQuotaUs: 200, - }, - wantCPUQuotaUs: 200, - wantCFSPeriod: int(cfsPeriodUs), - }, - } - - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - mock := newMockV1(t) - pid := 1 - tt.cfg.HierarchyRoot = "gitaly" - tt.cfg.Mountpoint = mock.root - - v1Manager := mock.newCgroupManager(tt.cfg, testhelper.SharedLogger(t), pid) - require.False(t, v1Manager.Ready()) - require.NoError(t, v1Manager.Setup()) - require.True(t, v1Manager.Ready()) - - memoryLimitPath := filepath.Join( - mock.root, "memory", "gitaly", fmt.Sprintf("gitaly-%d", pid), "memory.limit_in_bytes", - ) - requireCgroup(t, memoryLimitPath, tt.wantMemoryBytes) - - cpuSharesPath := filepath.Join( - mock.root, "cpu", "gitaly", fmt.Sprintf("gitaly-%d", pid), "cpu.shares", - ) - requireCgroup(t, cpuSharesPath, tt.wantCPUShares) - - cpuCFSQuotaPath := filepath.Join( - mock.root, "cpu", "gitaly", fmt.Sprintf("gitaly-%d", pid), "cpu.cfs_quota_us", - ) - requireCgroup(t, cpuCFSQuotaPath, tt.wantCPUQuotaUs) - - cpuCFSPeriodPath := filepath.Join( - mock.root, "cpu", "gitaly", fmt.Sprintf("gitaly-%d", pid), "cpu.cfs_period_us", - ) - requireCgroup(t, cpuCFSPeriodPath, tt.wantCFSPeriod) - }) - } -} - func TestSetup_RepoCgroups(t *testing.T) { tests := []struct { name string diff --git a/internal/cgroups/v2_linux_test.go b/internal/cgroups/v2_linux_test.go index 88004c1fe..5bbd62669 100644 --- a/internal/cgroups/v2_linux_test.go +++ b/internal/cgroups/v2_linux_test.go @@ -33,84 +33,6 @@ func defaultCgroupsV2Config() cgroups.Config { } } -func TestSetup_ParentCgroupsV2(t *testing.T) { - tests := []struct { - name string - cfg cgroups.Config - wantMemoryBytes int - wantCPUWeight int - wantCPUMax string - }{ - { - name: "all config specified", - cfg: cgroups.Config{ - MemoryBytes: 102400, - CPUShares: 256, - CPUQuotaUs: 2000, - }, - wantMemoryBytes: 102400, - wantCPUWeight: 256, - wantCPUMax: "2000 100000", - }, - { - name: "only memory limit set", - cfg: cgroups.Config{ - MemoryBytes: 102400, - }, - wantMemoryBytes: 102400, - }, - { - name: "only cpu shares set", - cfg: cgroups.Config{ - CPUShares: 512, - }, - wantCPUWeight: 512, - }, - { - name: "only cpu quota set", - cfg: cgroups.Config{ - CPUQuotaUs: 2000, - }, - wantCPUMax: "2000 100000", - }, - } - - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - mock := newMockV2(t) - - pid := 1 - tt.cfg.HierarchyRoot = "gitaly" - tt.cfg.Mountpoint = mock.root - - v2Manager := mock.newCgroupManager(tt.cfg, testhelper.SharedLogger(t), pid) - mock.setupMockCgroupFiles(t, v2Manager, []uint{}) - - require.False(t, v2Manager.Ready()) - require.NoError(t, v2Manager.Setup()) - require.True(t, v2Manager.Ready()) - - memoryMaxPath := filepath.Join( - mock.root, "gitaly", fmt.Sprintf("gitaly-%d", pid), "memory.max", - ) - requireCgroupWithInt(t, memoryMaxPath, tt.wantMemoryBytes) - - cpuWeightPath := filepath.Join( - mock.root, "gitaly", fmt.Sprintf("gitaly-%d", pid), "cpu.weight", - ) - requireCgroupWithInt(t, cpuWeightPath, calculateWantCPUWeight(tt.wantCPUWeight)) - - cpuMaxPath := filepath.Join( - mock.root, "gitaly", fmt.Sprintf("gitaly-%d", pid), "cpu.max", - ) - requireCgroupWithString(t, cpuMaxPath, tt.wantCPUMax) - }) - } -} - func TestSetup_RepoCgroupsV2(t *testing.T) { tests := []struct { name string |