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