1 /* 2 * Copyright (c) 2019, 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 25 /* 26 * @test 27 * @summary Ensure that certain JFR events return correct results for resource values 28 * when run inside Docker container, such as available CPU and memory. 29 * Also make sure that PIDs are based on value provided by container, 30 * not by the host system. 31 * @requires (docker.support & os.maxMemory >= 2g) 32 * @library /test/lib 33 * @modules java.base/jdk.internal.misc 34 * java.management 35 * jdk.jartool/sun.tools.jar 36 * @build JfrReporter 37 * @run driver TestJFREvents 38 */ 39 import java.util.List; 40 import jdk.test.lib.containers.docker.Common; 41 import jdk.test.lib.containers.docker.DockerRunOptions; 42 import jdk.test.lib.containers.docker.DockerTestUtils; 43 import jdk.test.lib.Asserts; 44 import jdk.test.lib.process.OutputAnalyzer; 45 import jdk.test.lib.Utils; 46 47 48 public class TestJFREvents { 49 private static final String imageName = Common.imageName("jfr-events"); 50 private static final String TEST_ENV_VARIABLE = "UNIQUE_VARIABLE_ABC592903XYZ"; 51 private static final String TEST_ENV_VALUE = "unique_value_abc592903xyz"; 52 private static final int availableCPUs = Runtime.getRuntime().availableProcessors(); 53 54 public static void main(String[] args) throws Exception { 55 System.out.println("Test Environment: detected availableCPUs = " + availableCPUs); 56 if (!DockerTestUtils.canTestDocker()) { 57 return; 58 } 59 60 DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker"); 61 62 try { 63 // leave one CPU for system and tools, otherwise this test may be unstable 64 int maxNrOfAvailableCpus = availableCPUs - 1; 65 for (int i=1; i < maxNrOfAvailableCpus; i = i * 2) { 66 testCPUInfo(i, i); 67 } 68 69 long MB = 1024*1024; 70 testMemory("200m", "" + 200*MB); 71 testMemory("500m", "" + 500*MB); 72 testMemory("1g", "" + 1024*MB); 73 74 testProcessInfo(); 75 76 testEnvironmentVariables(); 77 } finally { 78 DockerTestUtils.removeDockerImage(imageName); 79 } 80 } 81 82 83 private static void testCPUInfo(int valueToSet, int expectedValue) throws Exception { 84 Common.logNewTestCase("CPUInfo: --cpus = " + valueToSet); 85 DockerTestUtils.dockerRunJava( 86 commonDockerOpts() 87 .addDockerOpts("--cpus=" + valueToSet) 88 .addClassOptions("jdk.CPUInformation")) 89 .shouldHaveExitValue(0); 90 // The following assertion is currently disabled due to JFR reporting incorrect values. 91 // JFR reports values for the host system as opposed to values for the container. 92 // @ignore 8219999 93 // .shouldContain("cores = " + expectedValue"); 94 } 95 96 97 private static void testMemory(String valueToSet, String expectedValue) throws Exception { 98 Common.logNewTestCase("Memory: --memory = " + valueToSet); 99 DockerTestUtils.dockerRunJava( 100 commonDockerOpts() 101 .addDockerOpts("--memory=" + valueToSet) 102 .addClassOptions("jdk.PhysicalMemory")) 103 .shouldHaveExitValue(0) 104 .shouldContain("totalSize = " + expectedValue); 105 } 106 107 108 private static void testProcessInfo() throws Exception { 109 Common.logNewTestCase("ProcessInfo"); 110 DockerTestUtils.dockerRunJava( 111 commonDockerOpts() 112 .addClassOptions("jdk.SystemProcess")) 113 .shouldHaveExitValue(0) 114 .shouldContain("pid = 1"); 115 } 116 117 118 private static DockerRunOptions commonDockerOpts() { 119 return new DockerRunOptions(imageName, "/jdk/bin/java", "JfrReporter") 120 .addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/") 121 .addJavaOpts("-cp", "/test-classes/"); 122 } 123 124 125 private static void testEnvironmentVariables() throws Exception { 126 Common.logNewTestCase("EnvironmentVariables"); 127 128 List<String> cmd = DockerTestUtils.buildJavaCommand( 129 commonDockerOpts() 130 .addClassOptions("jdk.InitialEnvironmentVariable")); 131 132 ProcessBuilder pb = new ProcessBuilder(cmd); 133 // Container has JAVA_HOME defined via the Dockerfile; make sure 134 // it is reported by JFR event. 135 // Environment variable set in host system should not be visible inside a container, 136 // and should not be reported by JFR. 137 pb.environment().put(TEST_ENV_VARIABLE, TEST_ENV_VALUE); 138 139 System.out.println("[COMMAND]\n" + Utils.getCommandLine(pb)); 140 OutputAnalyzer out = new OutputAnalyzer(pb.start()); 141 System.out.println("[STDERR]\n" + out.getStderr()); 142 System.out.println("[STDOUT]\n" + out.getStdout()); 143 144 out.shouldHaveExitValue(0) 145 .shouldContain("key = JAVA_HOME") 146 .shouldContain("value = /jdk") 147 .shouldNotContain(TEST_ENV_VARIABLE) 148 .shouldNotContain(TEST_ENV_VALUE); 149 } 150 }