1 package fs
2
3 import (
4 "reflect"
5 "testing"
6
7 "github.com/opencontainers/runc/libcontainer/cgroups"
8 "github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
9 "github.com/opencontainers/runc/libcontainer/configs"
10 )
11
12 const (
13 cpus = "0-2,7,12-14\n"
14 cpuExclusive = "1\n"
15 mems = "1-4,6,9\n"
16 memHardwall = "0\n"
17 memExclusive = "0\n"
18 memoryMigrate = "1\n"
19 memorySpreadPage = "0\n"
20 memorySpeadSlab = "1\n"
21 memoryPressure = "34377\n"
22 schedLoadBalance = "1\n"
23 schedRelaxDomainLevel = "-1\n"
24 )
25
26 var cpusetTestFiles = map[string]string{
27 "cpuset.cpus": cpus,
28 "cpuset.cpu_exclusive": cpuExclusive,
29 "cpuset.mems": mems,
30 "cpuset.mem_hardwall": memHardwall,
31 "cpuset.mem_exclusive": memExclusive,
32 "cpuset.memory_migrate": memoryMigrate,
33 "cpuset.memory_spread_page": memorySpreadPage,
34 "cpuset.memory_spread_slab": memorySpeadSlab,
35 "cpuset.memory_pressure": memoryPressure,
36 "cpuset.sched_load_balance": schedLoadBalance,
37 "cpuset.sched_relax_domain_level": schedRelaxDomainLevel,
38 }
39
40 func TestCPUSetSetCpus(t *testing.T) {
41 path := tempDir(t, "cpuset")
42
43 const (
44 cpusBefore = "0"
45 cpusAfter = "1-3"
46 )
47
48 writeFileContents(t, path, map[string]string{
49 "cpuset.cpus": cpusBefore,
50 })
51
52 r := &configs.Resources{
53 CpusetCpus: cpusAfter,
54 }
55 cpuset := &CpusetGroup{}
56 if err := cpuset.Set(path, r); err != nil {
57 t.Fatal(err)
58 }
59
60 value, err := fscommon.GetCgroupParamString(path, "cpuset.cpus")
61 if err != nil {
62 t.Fatal(err)
63 }
64 if value != cpusAfter {
65 t.Fatal("Got the wrong value, set cpuset.cpus failed.")
66 }
67 }
68
69 func TestCPUSetSetMems(t *testing.T) {
70 path := tempDir(t, "cpuset")
71
72 const (
73 memsBefore = "0"
74 memsAfter = "1"
75 )
76
77 writeFileContents(t, path, map[string]string{
78 "cpuset.mems": memsBefore,
79 })
80
81 r := &configs.Resources{
82 CpusetMems: memsAfter,
83 }
84 cpuset := &CpusetGroup{}
85 if err := cpuset.Set(path, r); err != nil {
86 t.Fatal(err)
87 }
88
89 value, err := fscommon.GetCgroupParamString(path, "cpuset.mems")
90 if err != nil {
91 t.Fatal(err)
92 }
93 if value != memsAfter {
94 t.Fatal("Got the wrong value, set cpuset.mems failed.")
95 }
96 }
97
98 func TestCPUSetStatsCorrect(t *testing.T) {
99 path := tempDir(t, "cpuset")
100 writeFileContents(t, path, cpusetTestFiles)
101
102 cpuset := &CpusetGroup{}
103 actualStats := *cgroups.NewStats()
104 err := cpuset.GetStats(path, &actualStats)
105 if err != nil {
106 t.Fatal(err)
107 }
108 expectedStats := cgroups.CPUSetStats{
109 CPUs: []uint16{0, 1, 2, 7, 12, 13, 14},
110 CPUExclusive: 1,
111 Mems: []uint16{1, 2, 3, 4, 6, 9},
112 MemoryMigrate: 1,
113 MemHardwall: 0,
114 MemExclusive: 0,
115 MemorySpreadPage: 0,
116 MemorySpreadSlab: 1,
117 MemoryPressure: 34377,
118 SchedLoadBalance: 1,
119 SchedRelaxDomainLevel: -1,
120 }
121 if !reflect.DeepEqual(expectedStats, actualStats.CPUSetStats) {
122 t.Fatalf("Expected Cpuset stats usage %#v but found %#v",
123 expectedStats, actualStats.CPUSetStats)
124 }
125 }
126
127 func TestCPUSetStatsMissingFiles(t *testing.T) {
128 for _, testCase := range []struct {
129 desc string
130 filename, contents string
131 removeFile bool
132 }{
133 {
134 desc: "empty cpus file",
135 filename: "cpuset.cpus",
136 contents: "",
137 removeFile: false,
138 },
139 {
140 desc: "empty mems file",
141 filename: "cpuset.mems",
142 contents: "",
143 removeFile: false,
144 },
145 {
146 desc: "corrupted cpus file",
147 filename: "cpuset.cpus",
148 contents: "0-3,*4^2",
149 removeFile: false,
150 },
151 {
152 desc: "corrupted mems file",
153 filename: "cpuset.mems",
154 contents: "0,1,2-5,8-7",
155 removeFile: false,
156 },
157 {
158 desc: "missing cpu_exclusive file",
159 filename: "cpuset.cpu_exclusive",
160 contents: "",
161 removeFile: true,
162 },
163 {
164 desc: "missing memory_migrate file",
165 filename: "cpuset.memory_migrate",
166 contents: "",
167 removeFile: true,
168 },
169 {
170 desc: "missing mem_hardwall file",
171 filename: "cpuset.mem_hardwall",
172 contents: "",
173 removeFile: true,
174 },
175 {
176 desc: "missing mem_exclusive file",
177 filename: "cpuset.mem_exclusive",
178 contents: "",
179 removeFile: true,
180 },
181 {
182 desc: "missing memory_spread_page file",
183 filename: "cpuset.memory_spread_page",
184 contents: "",
185 removeFile: true,
186 },
187 {
188 desc: "missing memory_spread_slab file",
189 filename: "cpuset.memory_spread_slab",
190 contents: "",
191 removeFile: true,
192 },
193 {
194 desc: "missing memory_pressure file",
195 filename: "cpuset.memory_pressure",
196 contents: "",
197 removeFile: true,
198 },
199 {
200 desc: "missing sched_load_balance file",
201 filename: "cpuset.sched_load_balance",
202 contents: "",
203 removeFile: true,
204 },
205 {
206 desc: "missing sched_relax_domain_level file",
207 filename: "cpuset.sched_relax_domain_level",
208 contents: "",
209 removeFile: true,
210 },
211 } {
212 t.Run(testCase.desc, func(t *testing.T) {
213 path := tempDir(t, "cpuset")
214
215 tempCpusetTestFiles := map[string]string{}
216 for i, v := range cpusetTestFiles {
217 tempCpusetTestFiles[i] = v
218 }
219
220 if testCase.removeFile {
221 delete(tempCpusetTestFiles, testCase.filename)
222 writeFileContents(t, path, tempCpusetTestFiles)
223 cpuset := &CpusetGroup{}
224 actualStats := *cgroups.NewStats()
225 err := cpuset.GetStats(path, &actualStats)
226 if err != nil {
227 t.Errorf("failed unexpectedly: %q", err)
228 }
229 } else {
230 tempCpusetTestFiles[testCase.filename] = testCase.contents
231 writeFileContents(t, path, tempCpusetTestFiles)
232 cpuset := &CpusetGroup{}
233 actualStats := *cgroups.NewStats()
234 err := cpuset.GetStats(path, &actualStats)
235
236 if err == nil {
237 t.Error("failed to return expected error")
238 }
239 }
240 })
241 }
242 }
243
View as plain text