github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/libcontainer/cgroups/fs/cpu_test.go (about) 1 package fs 2 3 import ( 4 "fmt" 5 "strconv" 6 "testing" 7 8 "github.com/opencontainers/runc/libcontainer/cgroups" 9 "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" 10 "github.com/opencontainers/runc/libcontainer/configs" 11 ) 12 13 func TestCpuSetShares(t *testing.T) { 14 path := tempDir(t, "cpu") 15 16 const ( 17 sharesBefore = 1024 18 sharesAfter = 512 19 ) 20 21 writeFileContents(t, path, map[string]string{ 22 "cpu.shares": strconv.Itoa(sharesBefore), 23 }) 24 25 r := &configs.Resources{ 26 CpuShares: sharesAfter, 27 } 28 cpu := &CpuGroup{} 29 if err := cpu.Set(path, r); err != nil { 30 t.Fatal(err) 31 } 32 33 value, err := fscommon.GetCgroupParamUint(path, "cpu.shares") 34 if err != nil { 35 t.Fatal(err) 36 } 37 if value != sharesAfter { 38 t.Fatal("Got the wrong value, set cpu.shares failed.") 39 } 40 } 41 42 func TestCpuSetBandWidth(t *testing.T) { 43 path := tempDir(t, "cpu") 44 45 const ( 46 quotaBefore = 8000 47 quotaAfter = 5000 48 burstBefore = 2000 49 periodBefore = 10000 50 periodAfter = 7000 51 rtRuntimeBefore = 8000 52 rtRuntimeAfter = 5000 53 rtPeriodBefore = 10000 54 rtPeriodAfter = 7000 55 ) 56 burstAfter := uint64(1000) 57 58 writeFileContents(t, path, map[string]string{ 59 "cpu.cfs_quota_us": strconv.Itoa(quotaBefore), 60 "cpu.cfs_burst_us": strconv.Itoa(burstBefore), 61 "cpu.cfs_period_us": strconv.Itoa(periodBefore), 62 "cpu.rt_runtime_us": strconv.Itoa(rtRuntimeBefore), 63 "cpu.rt_period_us": strconv.Itoa(rtPeriodBefore), 64 }) 65 66 r := &configs.Resources{ 67 CpuQuota: quotaAfter, 68 CpuBurst: &burstAfter, 69 CpuPeriod: periodAfter, 70 CpuRtRuntime: rtRuntimeAfter, 71 CpuRtPeriod: rtPeriodAfter, 72 } 73 cpu := &CpuGroup{} 74 if err := cpu.Set(path, r); err != nil { 75 t.Fatal(err) 76 } 77 78 quota, err := fscommon.GetCgroupParamUint(path, "cpu.cfs_quota_us") 79 if err != nil { 80 t.Fatal(err) 81 } 82 if quota != quotaAfter { 83 t.Fatal("Got the wrong value, set cpu.cfs_quota_us failed.") 84 } 85 86 burst, err := fscommon.GetCgroupParamUint(path, "cpu.cfs_burst_us") 87 if err != nil { 88 t.Fatal(err) 89 } 90 if burst != burstAfter { 91 t.Fatal("Got the wrong value, set cpu.cfs_burst_us failed.") 92 } 93 94 period, err := fscommon.GetCgroupParamUint(path, "cpu.cfs_period_us") 95 if err != nil { 96 t.Fatal(err) 97 } 98 if period != periodAfter { 99 t.Fatal("Got the wrong value, set cpu.cfs_period_us failed.") 100 } 101 102 rtRuntime, err := fscommon.GetCgroupParamUint(path, "cpu.rt_runtime_us") 103 if err != nil { 104 t.Fatal(err) 105 } 106 if rtRuntime != rtRuntimeAfter { 107 t.Fatal("Got the wrong value, set cpu.rt_runtime_us failed.") 108 } 109 110 rtPeriod, err := fscommon.GetCgroupParamUint(path, "cpu.rt_period_us") 111 if err != nil { 112 t.Fatal(err) 113 } 114 if rtPeriod != rtPeriodAfter { 115 t.Fatal("Got the wrong value, set cpu.rt_period_us failed.") 116 } 117 } 118 119 func TestCpuStats(t *testing.T) { 120 path := tempDir(t, "cpu") 121 122 const ( 123 nrPeriods = 2000 124 nrThrottled = 200 125 throttledTime = uint64(18446744073709551615) 126 ) 127 128 cpuStatContent := fmt.Sprintf("nr_periods %d\nnr_throttled %d\nthrottled_time %d\n", 129 nrPeriods, nrThrottled, throttledTime) 130 writeFileContents(t, path, map[string]string{ 131 "cpu.stat": cpuStatContent, 132 }) 133 134 cpu := &CpuGroup{} 135 actualStats := *cgroups.NewStats() 136 err := cpu.GetStats(path, &actualStats) 137 if err != nil { 138 t.Fatal(err) 139 } 140 141 expectedStats := cgroups.ThrottlingData{ 142 Periods: nrPeriods, 143 ThrottledPeriods: nrThrottled, 144 ThrottledTime: throttledTime, 145 } 146 147 expectThrottlingDataEquals(t, expectedStats, actualStats.CpuStats.ThrottlingData) 148 } 149 150 func TestNoCpuStatFile(t *testing.T) { 151 path := tempDir(t, "cpu") 152 153 cpu := &CpuGroup{} 154 actualStats := *cgroups.NewStats() 155 err := cpu.GetStats(path, &actualStats) 156 if err != nil { 157 t.Fatal("Expected not to fail, but did") 158 } 159 } 160 161 func TestInvalidCpuStat(t *testing.T) { 162 path := tempDir(t, "cpu") 163 164 cpuStatContent := `nr_periods 2000 165 nr_throttled 200 166 throttled_time fortytwo` 167 writeFileContents(t, path, map[string]string{ 168 "cpu.stat": cpuStatContent, 169 }) 170 171 cpu := &CpuGroup{} 172 actualStats := *cgroups.NewStats() 173 err := cpu.GetStats(path, &actualStats) 174 if err == nil { 175 t.Fatal("Expected failed stat parsing.") 176 } 177 } 178 179 func TestCpuSetRtSchedAtApply(t *testing.T) { 180 path := tempDir(t, "cpu") 181 182 const ( 183 rtRuntimeBefore = 0 184 rtRuntimeAfter = 5000 185 rtPeriodBefore = 0 186 rtPeriodAfter = 7000 187 ) 188 189 writeFileContents(t, path, map[string]string{ 190 "cpu.rt_runtime_us": strconv.Itoa(rtRuntimeBefore), 191 "cpu.rt_period_us": strconv.Itoa(rtPeriodBefore), 192 }) 193 194 r := &configs.Resources{ 195 CpuRtRuntime: rtRuntimeAfter, 196 CpuRtPeriod: rtPeriodAfter, 197 } 198 cpu := &CpuGroup{} 199 200 if err := cpu.Apply(path, r, 1234); err != nil { 201 t.Fatal(err) 202 } 203 204 rtRuntime, err := fscommon.GetCgroupParamUint(path, "cpu.rt_runtime_us") 205 if err != nil { 206 t.Fatal(err) 207 } 208 if rtRuntime != rtRuntimeAfter { 209 t.Fatal("Got the wrong value, set cpu.rt_runtime_us failed.") 210 } 211 212 rtPeriod, err := fscommon.GetCgroupParamUint(path, "cpu.rt_period_us") 213 if err != nil { 214 t.Fatal(err) 215 } 216 if rtPeriod != rtPeriodAfter { 217 t.Fatal("Got the wrong value, set cpu.rt_period_us failed.") 218 } 219 220 pid, err := fscommon.GetCgroupParamUint(path, "cgroup.procs") 221 if err != nil { 222 t.Fatal(err) 223 } 224 if pid != 1234 { 225 t.Fatal("Got the wrong value, set cgroup.procs failed.") 226 } 227 }