1 /* 2 * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. 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 24 import java.util.stream.Collectors; 25 import java.util.stream.IntStream; 26 import jdk.internal.platform.Metrics; 27 import jdk.test.lib.Utils; 28 import jdk.test.lib.containers.cgroup.CPUSetsReader; 29 import jdk.test.lib.containers.docker.Common; 30 import jdk.test.lib.containers.docker.DockerRunOptions; 31 import jdk.test.lib.containers.docker.DockerTestUtils; 32 33 /* 34 * @test 35 * @summary Test JDK Metrics class when running inside docker container 36 * @requires docker.support 37 * @library /test/lib 38 * @modules java.base/jdk.internal.platform 39 * @build MetricsCpuTester 40 * @run main/timeout=360 TestDockerCpuMetrics 41 */ 42 43 public class TestDockerCpuMetrics { 44 private static final String imageName = Common.imageName("metrics-cpu"); 45 46 public static void main(String[] args) throws Exception { 47 if (!DockerTestUtils.canTestDocker()) { 48 return; 49 } 50 51 // These tests create a docker image and run this image with 52 // varying docker cpu options. The arguments passed to the docker 53 // container include the Java test class to be run along with the 54 // resource to be examined and expected result. 55 56 DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker"); 57 58 try { 59 int numCpus = CPUSetsReader.getNumCpus(); 60 testCpuSet("0"); 61 testCpuSet("0-" + (numCpus - 1)); 62 if (numCpus > 2) { 63 testCpuSet("0-" + ((numCpus - 1) / 2)); 64 testCpuSet((((numCpus - 1) / 2) + 1) + "-" + (numCpus - 1)); 65 } 66 testCpuSet(IntStream.range(0, numCpus).mapToObj(a -> Integer.toString(a)).collect(Collectors.joining(","))); 67 68 testCpuQuota(50 * 1000, 100 * 1000); 69 testCpuQuota(100 * 1000, 100 * 1000); 70 testCpuQuota(150 * 1000, 100 * 1000); 71 testCpuQuota(400 * 1000, 100 * 1000); 72 73 testCpuShares(256); 74 testCpuShares(2048); 75 testCpuShares(4096); 76 77 testCpuThrottling(0.5);// --cpus=<value> 78 79 int[] cpuSetMems = Metrics.systemMetrics().getCpuSetMems(); 80 String memNodes = null; 81 if (cpuSetMems != null && cpuSetMems.length > 1) { 82 int endNode = (cpuSetMems[cpuSetMems.length - 1] - cpuSetMems[0]) / 2 + cpuSetMems[0]; 83 memNodes = cpuSetMems[0] + "-" + endNode; 84 } else if (cpuSetMems != null && cpuSetMems.length == 1) { 85 memNodes = cpuSetMems[0] + ""; 86 } 87 88 if(memNodes != null) 89 testCpuSetMems(memNodes); 90 91 testComboOptions("0-" + (numCpus - 1), 200 * 1000, 100 * 1000, 4 * 1024); 92 testComboOptions("0", 200 * 1000, 100 * 1000, 1023); 93 } finally { 94 DockerTestUtils.removeDockerImage(imageName); 95 } 96 } 97 98 private static void testCpuSetMems(String value) throws Exception { 99 Common.logNewTestCase("testCpuSetMems, mem nodes = " + value); 100 DockerRunOptions opts = 101 new DockerRunOptions(imageName, "/jdk/bin/java", "MetricsCpuTester"); 102 opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/"); 103 opts.addDockerOpts("--cpuset-mems=" + value); 104 opts.addJavaOpts("-cp", "/test-classes/").addJavaOpts("--add-exports", "java.base/jdk.internal.platform=ALL-UNNAMED"); 105 opts.addClassOptions("cpumems", value); 106 DockerTestUtils.dockerRunJava(opts).shouldHaveExitValue(0).shouldContain("TEST PASSED!!!"); 107 } 108 109 private static void testCpuSet(String value) throws Exception { 110 Common.logNewTestCase("testCpuSet, value = " + value); 111 DockerRunOptions opts = 112 new DockerRunOptions(imageName, "/jdk/bin/java", "MetricsCpuTester"); 113 opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/"); 114 opts.addJavaOpts("-cp", "/test-classes/"); 115 opts.addJavaOpts("--add-exports", "java.base/jdk.internal.platform=ALL-UNNAMED"); 116 opts.addClassOptions("cpusets", value); 117 opts.addDockerOpts("--cpuset-cpus=" + value); 118 DockerTestUtils.dockerRunJava(opts).shouldHaveExitValue(0).shouldContain("TEST PASSED!!!"); 119 } 120 121 private static void testCpuQuota(long quota, long period) throws Exception { 122 Common.logNewTestCase("testCpuQuota, quota = " + quota + ", period = " + period); 123 DockerRunOptions opts = 124 new DockerRunOptions(imageName, "/jdk/bin/java", "MetricsCpuTester"); 125 opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/"); 126 opts.addDockerOpts("--cpu-period=" + period).addDockerOpts("--cpu-quota=" + quota); 127 opts.addJavaOpts("-cp", "/test-classes/").addJavaOpts("--add-exports", "java.base/jdk.internal.platform=ALL-UNNAMED"); 128 opts.addClassOptions("cpuquota", quota + "", period + ""); 129 DockerTestUtils.dockerRunJava(opts).shouldHaveExitValue(0).shouldContain("TEST PASSED!!!"); 130 } 131 132 private static void testCpuShares(int shares) throws Exception { 133 Common.logNewTestCase("testCpuShares, shares = " + shares); 134 DockerRunOptions opts = 135 new DockerRunOptions(imageName, "/jdk/bin/java", "MetricsCpuTester"); 136 opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/"); 137 opts.addDockerOpts("--cpu-shares=" + shares); 138 opts.addJavaOpts("-cp", "/test-classes/").addJavaOpts("--add-exports", "java.base/jdk.internal.platform=ALL-UNNAMED"); 139 opts.addClassOptions("cpushares", shares + ""); 140 DockerTestUtils.dockerRunJava(opts).shouldHaveExitValue(0).shouldContain("TEST PASSED!!!"); 141 } 142 143 private static void testCpuThrottling(double cpus) throws Exception { 144 Common.logNewTestCase("testCpuThrottling, cpus = " + cpus); 145 DockerRunOptions opts = 146 new DockerRunOptions(imageName, "/jdk/bin/java", "MetricsCpuTester"); 147 opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/"); 148 opts.addDockerOpts("--cpus=" + cpus); 149 opts.addJavaOpts("-cp", "/test-classes/").addJavaOpts("--add-exports", "java.base/jdk.internal.platform=ALL-UNNAMED"); 150 opts.addClassOptions("cpus", cpus + ""); 151 DockerTestUtils.dockerRunJava(opts).shouldHaveExitValue(0).shouldContain("TEST PASSED!!!"); 152 } 153 154 private static void testComboOptions(String cpuset, int quota, int period, int shares) throws Exception { 155 Common.logNewTestCase("testComboOptions, shares = " + shares); 156 DockerRunOptions opts = 157 new DockerRunOptions(imageName, "/jdk/bin/java", "MetricsCpuTester"); 158 opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/"); 159 opts.addDockerOpts("--cpuset-cpus", "" + cpuset) 160 .addDockerOpts("--cpu-period=" + period) 161 .addDockerOpts("--cpu-quota=" + quota) 162 .addDockerOpts("--cpu-shares=" + shares); 163 opts.addJavaOpts("-cp", "/test-classes/").addJavaOpts("--add-exports", "java.base/jdk.internal.platform=ALL-UNNAMED"); 164 opts.addClassOptions("combo", cpuset, quota + "", period + "", shares + ""); 165 DockerTestUtils.dockerRunJava(opts).shouldHaveExitValue(0).shouldContain("TEST PASSED!!!"); 166 } 167 }