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 8293540 8287107
54+ * @bug 8287107 8287073 8293540
5455 * @requires os.family == "linux"
5556 * @modules java.base/jdk.internal.platform
5657 * @library /lib/testlibrary
@@ -64,6 +65,7 @@ public class TestCgroupSubsystemFactory {
6465 private Path cgroupv1CgInfoZeroHierarchy ;
6566 private Path cgroupv1MntInfoZeroHierarchy ;
6667 private Path cgroupv2CgInfoZeroHierarchy ;
68+ private Path cgroupv2CgInfoZeroMinimal ;
6769 private Path cgroupv2MntInfoZeroHierarchy ;
6870 private Path cgroupv1CgInfoNonZeroHierarchy ;
6971 private Path cgroupv1MntInfoNonZeroHierarchy ;
@@ -125,6 +127,9 @@ public class TestCgroupSubsystemFactory {
125127 "net_cls 0 1 1\n " +
126128 "blkio 0 1 1\n " +
127129 "perf_event 0 1 1 " ;
130+ private String cgroupsZeroHierarchyMinimal =
131+ "#subsys_name hierarchy num_cgroups enabled\n " +
132+ "cpu 0 1 1\n " ;
128133 private String mntInfoHybrid =
129134 "30 23 0:26 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:4 - tmpfs tmpfs ro,seclabel,mode=755\n " +
130135 "31 30 0:27 / /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime shared:5 - cgroup2 none rw,seclabel,nsdelegate\n " +
@@ -308,6 +313,9 @@ public void setup() {
308313 cgroupv1MountInfoCgroupsOnlyCPUCtrl = Paths .get (existingDirectory .toString (), "self_mountinfo_cpu_only_controller" );
309314 Files .write (cgroupv1MountInfoCgroupsOnlyCPUCtrl , mntInfoCpuOnly .getBytes (StandardCharsets .UTF_8 ));
310315
316+ cgroupv2CgInfoZeroMinimal = Paths .get (existingDirectory .toString (), "cgv2_proc_cgroups_minimal" );
317+ Files .write (cgroupv2CgInfoZeroMinimal , cgroupsZeroHierarchyMinimal .getBytes (StandardCharsets .UTF_8 ));
318+
311319 cgroupv2CgInfoNoZeroHierarchyOnlyFreezer = Paths .get (existingDirectory .toString (), "cgroups_cgv2_non_zero_only_freezer" );
312320 Files .write (cgroupv2CgInfoNoZeroHierarchyOnlyFreezer , cgroupsNonZeroHierarchyOnlyFreezer .getBytes (StandardCharsets .UTF_8 ));
313321
@@ -489,6 +497,30 @@ public void testZeroHierarchyCgroupsV2() throws IOException {
489497 assertEquals ("/sys/fs/cgroup" , cpuInfo .getMountPoint ());
490498 }
491499
500+ /*
501+ * On some systems the memory controller might not show up in /proc/cgroups
502+ * which may provoke a NPE on instantiation. See bug 8287073.
503+ */
504+ @ Test
505+ public void testZeroHierarchyCgroupsV2Minimal () throws IOException {
506+ String cgroups = cgroupv2CgInfoZeroMinimal .toString ();
507+ String mountInfo = cgroupv2MntInfoZeroHierarchy .toString ();
508+ String selfCgroup = cgroupv2SelfCgroup .toString ();
509+ Optional <CgroupTypeResult > result = CgroupSubsystemFactory .determineType (mountInfo , cgroups , selfCgroup );
510+
511+ assertTrue ("Expected non-empty cgroup result" , result .isPresent ());
512+ CgroupTypeResult res = result .get ();
513+
514+ assertTrue ("zero hierarchy ids with mounted controllers expected cgroups v2" , res .isCgroupV2 ());
515+ assertNull ("Only cpu controller present" , res .getInfos ().get ("memory" ));
516+ try {
517+ CgroupSubsystemFactory .create (result );
518+ // pass
519+ } catch (NullPointerException e ) {
520+ fail ("Missing memory controller should not cause any NPE" );
521+ }
522+ }
523+
492524 @ Test (expected = IOException .class )
493525 public void mountInfoFileNotFound () throws IOException {
494526 String cgroups = cgroupv1CgInfoZeroHierarchy .toString (); // any existing file
0 commit comments