2525import static org .junit .Assert .assertTrue ;
2626import static org .junit .Assert .assertNull ;
2727import static org .junit .Assert .assertNotNull ;
28+ import static org .junit .Assert .fail ;
2829
2930import java .io .IOException ;
3031import java .nio .charset .StandardCharsets ;
5051
5152/*
5253 * @test
53- * @bug 8287107
54+ * @bug 8287107 8287073
5455 * @key cgroups
5556 * @requires os.family == "linux"
5657 * @modules java.base/jdk.internal.platform
@@ -66,6 +67,7 @@ public class TestCgroupSubsystemFactory {
6667 private Path cgroupv1CgInfoZeroHierarchy ;
6768 private Path cgroupv1MntInfoZeroHierarchy ;
6869 private Path cgroupv2CgInfoZeroHierarchy ;
70+ private Path cgroupv2CgInfoZeroMinimal ;
6971 private Path cgroupv2MntInfoZeroHierarchy ;
7072 private Path cgroupv1CgInfoNonZeroHierarchy ;
7173 private Path cgroupv1MntInfoNonZeroHierarchy ;
@@ -127,6 +129,9 @@ public class TestCgroupSubsystemFactory {
127129 "net_cls 0 1 1\n " +
128130 "blkio 0 1 1\n " +
129131 "perf_event 0 1 1 " ;
132+ private String cgroupsZeroHierarchyMinimal =
133+ "#subsys_name hierarchy num_cgroups enabled\n " +
134+ "cpu 0 1 1\n " ;
130135 private String mntInfoHybrid =
131136 "30 23 0:26 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:4 - tmpfs tmpfs ro,seclabel,mode=755\n " +
132137 "31 30 0:27 / /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime shared:5 - cgroup2 none rw,seclabel,nsdelegate\n " +
@@ -306,6 +311,9 @@ public void setup() {
306311 cgroupv1MountInfoCgroupsOnlyCPUCtrl = Paths .get (existingDirectory .toString (), "self_mountinfo_cpu_only_controller" );
307312 Files .writeString (cgroupv1MountInfoCgroupsOnlyCPUCtrl , mntInfoCpuOnly );
308313
314+ cgroupv2CgInfoZeroMinimal = Paths .get (existingDirectory .toString (), "cgv2_proc_cgroups_minimal" );
315+ Files .writeString (cgroupv2CgInfoZeroMinimal , cgroupsZeroHierarchyMinimal );
316+
309317 cgroupv2CgInfoNoZeroHierarchyOnlyFreezer = Paths .get (existingDirectory .toString (), "cgroups_cgv2_non_zero_only_freezer" );
310318 Files .writeString (cgroupv2CgInfoNoZeroHierarchyOnlyFreezer , cgroupsNonZeroHierarchyOnlyFreezer );
311319
@@ -480,6 +488,30 @@ public void testZeroHierarchyCgroupsV2() throws IOException {
480488 assertEquals ("/sys/fs/cgroup" , cpuInfo .getMountPoint ());
481489 }
482490
491+ /*
492+ * On some systems the memory controller might not show up in /proc/cgroups
493+ * which may provoke a NPE on instantiation. See bug 8287073.
494+ */
495+ @ Test
496+ public void testZeroHierarchyCgroupsV2Minimal () throws IOException {
497+ String cgroups = cgroupv2CgInfoZeroMinimal .toString ();
498+ String mountInfo = cgroupv2MntInfoZeroHierarchy .toString ();
499+ String selfCgroup = cgroupv2SelfCgroup .toString ();
500+ Optional <CgroupTypeResult > result = CgroupSubsystemFactory .determineType (mountInfo , cgroups , selfCgroup );
501+
502+ assertTrue ("Expected non-empty cgroup result" , result .isPresent ());
503+ CgroupTypeResult res = result .get ();
504+
505+ assertTrue ("zero hierarchy ids with mounted controllers expected cgroups v2" , res .isCgroupV2 ());
506+ assertNull ("Only cpu controller present" , res .getInfos ().get ("memory" ));
507+ try {
508+ CgroupSubsystemFactory .create (result );
509+ // pass
510+ } catch (NullPointerException e ) {
511+ fail ("Missing memory controller should not cause any NPE" );
512+ }
513+ }
514+
483515 @ Test (expected = IOException .class )
484516 public void mountInfoFileNotFound () throws IOException {
485517 String cgroups = cgroupv1CgInfoZeroHierarchy .toString (); // any existing file
0 commit comments