1 /* 2 * Copyright (c) 2020, Red Hat Inc. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 import static org.junit.Assert.assertFalse; 24 import static org.junit.Assert.assertTrue; 25 26 import java.io.IOException; 27 import java.nio.charset.StandardCharsets; 28 import java.nio.file.Files; 29 import java.nio.file.Path; 30 import java.nio.file.Paths; 31 import java.util.Optional; 32 33 import org.junit.After; 34 import org.junit.Before; 35 import org.junit.Test; 36 37 import jdk.internal.platform.CgroupSubsystemFactory; 38 import jdk.internal.platform.CgroupSubsystemFactory.CgroupTypeResult; 39 import jdk.test.lib.Utils; 40 import jdk.test.lib.util.FileUtils; 41 42 43 /* 44 * @test 45 * @requires os.family == "linux" 46 * @modules java.base/jdk.internal.platform 47 * @library /test/lib 48 * @run junit/othervm TestCgroupSubsystemFactory 49 */ 50 public class TestCgroupSubsystemFactory { 51 52 private Path existingDirectory; 53 private Path cgroupv1CgInfoZeroHierarchy; 54 private Path cgroupv1MntInfoZeroHierarchy; 55 private Path cgroupv2CgInfoZeroHierarchy; 56 private Path cgroupv2MntInfoZeroHierarchy; 57 private Path cgroupv1CgInfoNonZeroHierarchy; 58 private Path cgroupv1MntInfoNonZeroHierarchy; 59 private String mntInfoEmpty = ""; 60 private String cgroupsZeroHierarchy = 61 "#subsys_name hierarchy num_cgroups enabled\n" + 62 "cpuset 0 1 1\n" + 63 "cpu 0 1 1\n" + 64 "cpuacct 0 1 1\n" + 65 "memory 0 1 1\n" + 66 "devices 0 1 1\n" + 67 "freezer 0 1 1\n" + 68 "net_cls 0 1 1\n" + 69 "blkio 0 1 1\n" + 70 "perf_event 0 1 1 "; 71 private String mntInfoHybrid = 72 "30 23 0:26 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:4 - tmpfs tmpfs ro,seclabel,mode=755\n" + 73 "31 30 0:27 / /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime shared:5 - cgroup2 cgroup2 rw,seclabel,nsdelegate\n" + 74 "32 30 0:28 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:6 - cgroup cgroup rw,seclabel,xattr,name=systemd\n" + 75 "35 30 0:31 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:7 - cgroup cgroup rw,seclabel,memory\n" + 76 "36 30 0:32 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:8 - cgroup cgroup rw,seclabel,pids\n" + 77 "37 30 0:33 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:9 - cgroup cgroup rw,seclabel,perf_event\n" + 78 "38 30 0:34 / /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,seclabel,net_cls,net_prio\n" + 79 "39 30 0:35 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:11 - cgroup cgroup rw,seclabel,hugetlb\n" + 80 "40 30 0:36 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:12 - cgroup cgroup rw,seclabel,cpu,cpuacct\n" + 81 "41 30 0:37 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:13 - cgroup cgroup rw,seclabel,devices\n" + 82 "42 30 0:38 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:14 - cgroup cgroup rw,seclabel,cpuset\n" + 83 "43 30 0:39 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,seclabel,blkio\n" + 84 "44 30 0:40 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,seclabel,freezer"; 85 private String cgroupsNonZeroHierarchy = 86 "#subsys_name hierarchy num_cgroups enabled\n" + 87 "cpuset 9 1 1\n" + 88 "cpu 7 1 1\n" + 89 "cpuacct 7 1 1\n" + 90 "blkio 10 1 1\n" + 91 "memory 2 90 1\n" + 92 "devices 8 74 1\n" + 93 "freezer 11 1 1\n" + 94 "net_cls 5 1 1\n" + 95 "perf_event 4 1 1\n" + 96 "net_prio 5 1 1\n" + 97 "hugetlb 6 1 1\n" + 98 "pids 3 80 1"; 99 private String mntInfoCgroupsV2Only = 100 "28 21 0:25 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:4 - cgroup2 cgroup2 rw,seclabel,nsdelegate"; 101 102 @Before 103 public void setup() { 104 try { 105 existingDirectory = Utils.createTempDirectory(TestCgroupSubsystemFactory.class.getSimpleName()); 106 Path cgroupsZero = Paths.get(existingDirectory.toString(), "cgroups_zero"); 107 Files.writeString(cgroupsZero, cgroupsZeroHierarchy, StandardCharsets.UTF_8); 108 cgroupv1CgInfoZeroHierarchy = cgroupsZero; 109 cgroupv2CgInfoZeroHierarchy = cgroupsZero; 110 cgroupv1MntInfoZeroHierarchy = Paths.get(existingDirectory.toString(), "mountinfo_empty"); 111 Files.writeString(cgroupv1MntInfoZeroHierarchy, mntInfoEmpty); 112 113 cgroupv2MntInfoZeroHierarchy = Paths.get(existingDirectory.toString(), "mountinfo_cgroupv2"); 114 Files.writeString(cgroupv2MntInfoZeroHierarchy, mntInfoCgroupsV2Only); 115 116 cgroupv1CgInfoNonZeroHierarchy = Paths.get(existingDirectory.toString(), "cgroups_non_zero"); 117 Files.writeString(cgroupv1CgInfoNonZeroHierarchy, cgroupsNonZeroHierarchy); 118 119 cgroupv1MntInfoNonZeroHierarchy = Paths.get(existingDirectory.toString(), "mountinfo_non_zero"); 120 Files.writeString(cgroupv1MntInfoNonZeroHierarchy, mntInfoHybrid); 121 } catch (IOException e) { 122 throw new RuntimeException(e); 123 } 124 } 125 126 @After 127 public void teardown() { 128 try { 129 FileUtils.deleteFileTreeWithRetry(existingDirectory); 130 } catch (IOException e) { 131 System.err.println("Teardown failed. " + e.getMessage()); 132 } 133 } 134 135 @Test 136 public void testHybridCgroupsV1() throws IOException { 137 String cgroups = cgroupv1CgInfoNonZeroHierarchy.toString(); 138 String mountInfo = cgroupv1MntInfoNonZeroHierarchy.toString(); 139 Optional<CgroupTypeResult> result = CgroupSubsystemFactory.determineType(mountInfo, cgroups); 140 141 assertTrue("Expected non-empty cgroup result", result.isPresent()); 142 CgroupTypeResult res = result.get(); 143 assertFalse("hybrid hierarchy expected as cgroups v1", res.isCgroupV2()); 144 } 145 146 @Test 147 public void testZeroHierarchyCgroupsV1() throws IOException { 148 String cgroups = cgroupv1CgInfoZeroHierarchy.toString(); 149 String mountInfo = cgroupv1MntInfoZeroHierarchy.toString(); 150 Optional<CgroupTypeResult> result = CgroupSubsystemFactory.determineType(mountInfo, cgroups); 151 152 assertTrue("zero hierarchy ids with no mounted controllers => empty result", result.isEmpty()); 153 } 154 155 @Test 156 public void testZeroHierarchyCgroupsV2() throws IOException { 157 String cgroups = cgroupv2CgInfoZeroHierarchy.toString(); 158 String mountInfo = cgroupv2MntInfoZeroHierarchy.toString(); 159 Optional<CgroupTypeResult> result = CgroupSubsystemFactory.determineType(mountInfo, cgroups); 160 161 assertTrue("Expected non-empty cgroup result", result.isPresent()); 162 CgroupTypeResult res = result.get(); 163 164 assertTrue("zero hierarchy ids with mounted controllers expected cgroups v2", res.isCgroupV2()); 165 } 166 167 @Test(expected = IOException.class) 168 public void mountInfoFileNotFound() throws IOException { 169 String cgroups = cgroupv1CgInfoZeroHierarchy.toString(); // any existing file 170 String mountInfo = Paths.get(existingDirectory.toString(), "not-existing-mountinfo").toString(); 171 172 CgroupSubsystemFactory.determineType(mountInfo, cgroups); 173 } 174 175 @Test(expected = IOException.class) 176 public void cgroupsFileNotFound() throws IOException { 177 String cgroups = Paths.get(existingDirectory.toString(), "not-existing-cgroups").toString(); 178 String mountInfo = cgroupv2MntInfoZeroHierarchy.toString(); // any existing file 179 CgroupSubsystemFactory.determineType(mountInfo, cgroups); 180 } 181 }