2323import static org .junit .Assert .assertEquals ;
2424import static org .junit .Assert .assertFalse ;
2525import static org .junit .Assert .assertTrue ;
26+ import static org .junit .Assert .assertNull ;
27+ import static org .junit .Assert .assertNotNull ;
2628
2729import java .io .IOException ;
2830import java .nio .charset .StandardCharsets ;
2931import java .nio .file .Files ;
3032import java .nio .file .Path ;
3133import java .nio .file .Paths ;
3234import java .util .Optional ;
35+ import java .util .Map ;
3336
3437import org .junit .After ;
3538import org .junit .Before ;
3841import jdk .internal .platform .CgroupInfo ;
3942import jdk .internal .platform .CgroupSubsystemFactory ;
4043import jdk .internal .platform .CgroupSubsystemFactory .CgroupTypeResult ;
44+ import jdk .internal .platform .CgroupV1MetricsImpl ;
45+ import jdk .internal .platform .cgroupv1 .CgroupV1Subsystem ;
46+ import jdk .internal .platform .Metrics ;
4147import jdk .testlibrary .Utils ;
4248import jdk .testlibrary .FileUtils ;
4349
@@ -66,6 +72,9 @@ public class TestCgroupSubsystemFactory {
6672 private Path cgroupv1SelfCgroup ;
6773 private Path cgroupv2SelfCgroup ;
6874 private Path cgroupv1SelfCgroupJoinCtrl ;
75+ private Path cgroupv1CgroupsOnlyCPUCtrl ;
76+ private Path cgroupv1SelfCgroupsOnlyCPUCtrl ;
77+ private Path cgroupv1MountInfoCgroupsOnlyCPUCtrl ;
6978 private String mntInfoEmpty = "" ;
7079 private String cgroupsNonZeroJoinControllers =
7180 "#subsys_name hierarchy num_cgroups enabled\n " +
@@ -82,6 +91,12 @@ public class TestCgroupSubsystemFactory {
8291 "hugetlb\t 4\t 153\t 1\n " +
8392 "pids\t 5\t 95\t 1\n " +
8493 "rdma\t 8\t 1\t 1\n " ;
94+ private String cgroupsNonZeroCpuControllerOnly =
95+ "#subsys_name hierarchy num_cgroups enabled\n " +
96+ "cpu\t 4\t 153\t 1\n " +
97+ "cpuacct\t 4\t 153\t 1\n " ;
98+ private String selfCgroupNonZeroCpuControllerOnly =
99+ "4:cpu,cpuacct:/user.slice/user-1000.slice/session-3.scope\n " ;
85100 private String selfCgroupNonZeroJoinControllers =
86101 "9:cpuset:/\n " +
87102 "8:perf_event:/\n " +
@@ -118,6 +133,9 @@ public class TestCgroupSubsystemFactory {
118133 "42 30 0:38 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:14 - cgroup none rw,seclabel,cpuset\n " +
119134 "43 30 0:39 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:15 - cgroup none rw,seclabel,blkio\n " +
120135 "44 30 0:40 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:16 - cgroup none rw,seclabel,freezer\n " ;
136+ private String mntInfoCpuOnly =
137+ "30 23 0:26 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:4 - tmpfs tmpfs ro,seclabel,mode=755\n " +
138+ "40 30 0:36 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:12 - cgroup none rw,seclabel,cpu,cpuacct\n " ;
121139 private String mntInfoCgroupv1JoinControllers =
122140 "31 22 0:26 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:9 - tmpfs tmpfs ro,mode=755\n " +
123141 "32 31 0:27 / /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime shared:10 - cgroup2 cgroup2 rw,nsdelegate\n " +
@@ -209,6 +227,15 @@ public void setup() {
209227
210228 cgroupv1SelfCgroupJoinCtrl = Paths .get (existingDirectory .toString (), "self_cgroup_cgv1_join_controllers" );
211229 Files .write (cgroupv1SelfCgroupJoinCtrl , selfCgroupNonZeroJoinControllers .getBytes ());
230+
231+ cgroupv1CgroupsOnlyCPUCtrl = Paths .get (existingDirectory .toString (), "cgroups_cpu_only_controller" );
232+ Files .write (cgroupv1CgroupsOnlyCPUCtrl , cgroupsNonZeroCpuControllerOnly .getBytes ());
233+
234+ cgroupv1SelfCgroupsOnlyCPUCtrl = Paths .get (existingDirectory .toString (), "self_cgroup_cpu_only_controller" );
235+ Files .write (cgroupv1SelfCgroupsOnlyCPUCtrl , selfCgroupNonZeroCpuControllerOnly .getBytes ());
236+
237+ cgroupv1MountInfoCgroupsOnlyCPUCtrl = Paths .get (existingDirectory .toString (), "self_mountinfo_cpu_only_controller" );
238+ Files .write (cgroupv1MountInfoCgroupsOnlyCPUCtrl , mntInfoCpuOnly .getBytes ());
212239 } catch (IOException e ) {
213240 throw new RuntimeException (e );
214241 }
@@ -223,6 +250,34 @@ public void teardown() {
223250 }
224251 }
225252
253+ @ Test
254+ public void testCgroupv1CpuControllerOnly () throws IOException {
255+ String cgroups = cgroupv1CgroupsOnlyCPUCtrl .toString ();
256+ String mountInfo = cgroupv1MountInfoCgroupsOnlyCPUCtrl .toString ();
257+ String selfCgroup = cgroupv1SelfCgroupsOnlyCPUCtrl .toString ();
258+ Optional <CgroupTypeResult > result = CgroupSubsystemFactory .determineType (mountInfo , cgroups , selfCgroup );
259+
260+ assertTrue ("Expected non-empty cgroup result" , result .isPresent ());
261+ CgroupTypeResult res = result .get ();
262+ assertFalse ("Expected cgroup v1" , res .isCgroupV2 ());
263+ Map <String , CgroupInfo > infos = res .getInfos ();
264+ assertNull ("Memory controller expected null" , infos .get ("memory" ));
265+ assertNotNull ("Cpu controller expected non-null" , infos .get ("cpu" ));
266+
267+ // cgroup v1 tests only as this isn't possible with unified hierarchy
268+ // where all controllers have the same mount point
269+ CgroupV1Subsystem subsystem = CgroupV1Subsystem .getInstance (infos );
270+ // This throws NPEs prior JDK-8257746
271+ long val = subsystem .getMemoryAndSwapLimit ();
272+ assertEquals ("expected unlimited, and no NPE" , -1 , val );
273+ val = subsystem .getMemoryAndSwapFailCount ();
274+ assertEquals ("expected unlimited, and no NPE" , -1 , val );
275+ val = subsystem .getMemoryAndSwapMaxUsage ();
276+ assertEquals ("expected unlimited, and no NPE" , -1 , val );
277+ val = subsystem .getMemoryAndSwapUsage ();
278+ assertEquals ("expected unlimited, and no NPE" , -1 , val );
279+ }
280+
226281 @ Test
227282 public void testCgroupv1JoinControllerCombo () throws IOException {
228283 String cgroups = cgroupv1CgroupsJoinControllers .toString ();
0 commit comments