Sat, 18 Aug 2018 12:58:53 +0100
Merge
.hgtags | file | annotate | diff | comparison | revisions |
1.1 --- a/.hgtags Fri Aug 10 12:27:32 2018 +0100 1.2 +++ b/.hgtags Sat Aug 18 12:58:53 2018 +0100 1.3 @@ -1194,6 +1194,7 @@ 1.4 dd79b482625361458b2b34e7d669ee982eee06a4 jdk8u191-b03 1.5 541c205d7fd15ab840f48aaeeaea3f63209d1687 jdk8u191-b04 1.6 14c62eae2f8f56f571abfc8435055bb6094c8440 jdk8u191-b05 1.7 +6cfec782c42c25f772bfd51a8b47e6926aa8f69f jdk8u191-b06 1.8 c19c5b73704e3d188bedfe52a473b408ca39009f jdk8u182-b00 1.9 0341fa6dbb363ee4dc5dbf5bfc4f820523400a72 jdk8u192-b00 1.10 5792d995ed26eec0417d96a2423446bbcd6951a9 jdk8u192-b01 1.11 @@ -1201,3 +1202,4 @@ 1.12 1c0a59cee0e4e680dd0973f022b86de5637b9b75 jdk8u192-b03 1.13 a8d61d7f13b0de755da1335c15b72c53c59e92b5 jdk8u192-b04 1.14 65409bcab2ad83d7043d508448a04fe18cf1c262 jdk8u192-b05 1.15 +7070edbacb29f03b9a77dbe09425da2c888625f1 jdk8u192-b06
2.1 --- a/src/share/vm/prims/whitebox.cpp Fri Aug 10 12:27:32 2018 +0100 2.2 +++ b/src/share/vm/prims/whitebox.cpp Sat Aug 18 12:58:53 2018 +0100 2.3 @@ -160,6 +160,7 @@ 2.4 2.5 #ifdef LINUX 2.6 #include "utilities/elfFile.hpp" 2.7 +#include "osContainer_linux.hpp" 2.8 #endif 2.9 2.10 WB_ENTRY(jlong, WB_GetCompressedOopsMaxHeapSize(JNIEnv* env, jobject o)) { 2.11 @@ -1028,6 +1029,15 @@ 2.12 return ret; 2.13 WB_END 2.14 2.15 +WB_ENTRY(jboolean, WB_IsContainerized(JNIEnv* env, jobject o)) 2.16 + LINUX_ONLY(return OSContainer::is_containerized();) 2.17 + return false; 2.18 +WB_END 2.19 + 2.20 +WB_ENTRY(void, WB_PrintOsInfo(JNIEnv* env, jobject o)) 2.21 + os::print_os_info(tty); 2.22 +WB_END 2.23 + 2.24 #define CC (char*) 2.25 2.26 static JNINativeMethod methods[] = { 2.27 @@ -1141,6 +1151,8 @@ 2.28 {CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint }, 2.29 {CC"checkLibSpecifiesNoexecstack", CC"(Ljava/lang/String;)Z", 2.30 (void*)&WB_CheckLibSpecifiesNoexecstack}, 2.31 + {CC"isContainerized", CC"()Z", (void*)&WB_IsContainerized }, 2.32 + {CC"printOsInfo", CC"()V", (void*)&WB_PrintOsInfo }, 2.33 }; 2.34 2.35 #undef CC
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/runtime/containers/docker/AttemptOOM.java Sat Aug 18 12:58:53 2018 +0100 3.3 @@ -0,0 +1,49 @@ 3.4 +/* 3.5 + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. 3.11 + * 3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.15 + * version 2 for more details (a copy is included in the LICENSE file that 3.16 + * accompanied this code). 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License version 3.19 + * 2 along with this work; if not, write to the Free Software Foundation, 3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.21 + * 3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.23 + * or visit www.oracle.com if you need additional information or have any 3.24 + * questions. 3.25 + */ 3.26 + 3.27 +public class AttemptOOM { 3.28 + private static MyObj[] data; 3.29 + 3.30 + public static void main(String[] args) throws Exception { 3.31 + System.out.println("Entering AttemptOOM main"); 3.32 + 3.33 + // each MyObj will allocate 1024 byte array 3.34 + int sizeInMb = Integer.parseInt(args[0]); 3.35 + data = new MyObj[sizeInMb*1024]; 3.36 + 3.37 + System.out.println("data.length = " + data.length); 3.38 + 3.39 + for (int i=0; i < data.length; i++) { 3.40 + data[i] = new MyObj(1024); 3.41 + } 3.42 + 3.43 + System.out.println("AttemptOOM allocation successful"); 3.44 + } 3.45 + 3.46 + private static class MyObj { 3.47 + private byte[] myData; 3.48 + MyObj(int size) { 3.49 + myData = new byte[size]; 3.50 + } 3.51 + } 3.52 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/runtime/containers/docker/CPUSetsReader.java Sat Aug 18 12:58:53 2018 +0100 4.3 @@ -0,0 +1,141 @@ 4.4 +/* 4.5 + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 + * 4.8 + * This code is free software; you can redistribute it and/or modify it 4.9 + * under the terms of the GNU General Public License version 2 only, as 4.10 + * published by the Free Software Foundation. 4.11 + * 4.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 4.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.15 + * version 2 for more details (a copy is included in the LICENSE file that 4.16 + * accompanied this code). 4.17 + * 4.18 + * You should have received a copy of the GNU General Public License version 4.19 + * 2 along with this work; if not, write to the Free Software Foundation, 4.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.21 + * 4.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4.23 + * or visit www.oracle.com if you need additional information or have any 4.24 + * questions. 4.25 + */ 4.26 +import java.io.BufferedReader; 4.27 +import java.io.File; 4.28 +import java.io.IOException; 4.29 +import java.nio.file.Files; 4.30 +import java.nio.file.Paths; 4.31 +import java.io.FileReader; 4.32 +import java.util.ArrayList; 4.33 +import java.util.Optional; 4.34 +import java.util.List; 4.35 +import java.util.stream.Collectors; 4.36 +import java.util.stream.Stream; 4.37 +import com.oracle.java.testlibrary.Asserts; 4.38 + 4.39 + 4.40 +// A simple CPU sets reader and parser 4.41 +public class CPUSetsReader { 4.42 + public static String PROC_SELF_STATUS_PATH="/proc/self/status"; 4.43 + 4.44 + // Test the parser 4.45 + public static void test() { 4.46 + assertParse("0-7", "0,1,2,3,4,5,6,7"); 4.47 + assertParse("1,3,6", "1,3,6"); 4.48 + assertParse("0,2-4,6,10-11", "0,2,3,4,6,10,11"); 4.49 + assertParse("0", "0"); 4.50 + } 4.51 + 4.52 + 4.53 + private static void assertParse(String cpuSet, String expectedResult) { 4.54 + Asserts.assertEquals(listToString(parseCpuSet(cpuSet)), expectedResult); 4.55 + } 4.56 + 4.57 + 4.58 + public static String readFromProcStatus(String setType) { 4.59 + String path = PROC_SELF_STATUS_PATH; 4.60 + Optional<String> o = Optional.empty(); 4.61 + 4.62 + System.out.println("readFromProcStatus() entering for: " + setType); 4.63 + 4.64 + try (Stream<String> stream = Files.lines(Paths.get(path))) { 4.65 + o = stream 4.66 + .filter(line -> line.contains(setType)) 4.67 + .findFirst(); 4.68 + } catch (IOException e) { 4.69 + return null; 4.70 + } 4.71 + 4.72 + if (!o.isPresent()) { 4.73 + return null; // entry not found 4.74 + } 4.75 + 4.76 + String[] parts = o.get().replaceAll("\\s","").split(":"); 4.77 + 4.78 + // Should be 2 parts, before and after ":" 4.79 + Asserts.assertEquals(parts.length, 2); 4.80 + 4.81 + String result = parts[1]; 4.82 + System.out.println("readFromProcStatus() returning: " + result); 4.83 + return result; 4.84 + } 4.85 + 4.86 + 4.87 + public static List<Integer> parseCpuSet(String value) { 4.88 + ArrayList<Integer> result = new ArrayList<Integer>(); 4.89 + 4.90 + try { 4.91 + String[] commaSeparated = value.split(","); 4.92 + 4.93 + for (String item : commaSeparated) { 4.94 + if (item.contains("-")) { 4.95 + addRange(result, item); 4.96 + } else { 4.97 + result.add(Integer.parseInt(item)); 4.98 + } 4.99 + } 4.100 + } catch (Exception e) { 4.101 + System.err.println("Exception in getMaxCpuSets(): " + e); 4.102 + return null; 4.103 + } 4.104 + 4.105 + return result; 4.106 + } 4.107 + 4.108 + 4.109 + private static void addRange(ArrayList<Integer> list, String s) { 4.110 + String[] range = s.split("-"); 4.111 + if ( range.length != 2 ) { 4.112 + throw new RuntimeException("Range should only contain two items, but contains " 4.113 + + range.length + " items"); 4.114 + } 4.115 + 4.116 + int min = Integer.parseInt(range[0]); 4.117 + int max = Integer.parseInt(range[1]); 4.118 + 4.119 + if (min >= max) { 4.120 + String msg = String.format("min is greater or equals to max, min = %d, max = %d", 4.121 + min, max); 4.122 + throw new RuntimeException(msg); 4.123 + } 4.124 + 4.125 + for (int i = min; i <= max; i++) { 4.126 + list.add(i); 4.127 + } 4.128 + } 4.129 + 4.130 + 4.131 + // Convert list of integers to string with comma-separated values 4.132 + public static String listToString(List<Integer> list) { 4.133 + return listToString(list, Integer.MAX_VALUE); 4.134 + } 4.135 + 4.136 + // Convert list of integers to a string with comma-separated values; 4.137 + // include up to maxCount. 4.138 + public static String listToString(List<Integer> list, int maxCount) { 4.139 + return list.stream() 4.140 + .limit(maxCount) 4.141 + .map(Object::toString) 4.142 + .collect(Collectors.joining(",")); 4.143 + } 4.144 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/runtime/containers/docker/CheckContainerized.java Sat Aug 18 12:58:53 2018 +0100 5.3 @@ -0,0 +1,44 @@ 5.4 +/* 5.5 + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.7 + * 5.8 + * This code is free software; you can redistribute it and/or modify it 5.9 + * under the terms of the GNU General Public License version 2 only, as 5.10 + * published by the Free Software Foundation. 5.11 + * 5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 5.15 + * version 2 for more details (a copy is included in the LICENSE file that 5.16 + * accompanied this code). 5.17 + * 5.18 + * You should have received a copy of the GNU General Public License version 5.19 + * 2 along with this work; if not, write to the Free Software Foundation, 5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 5.21 + * 5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 5.23 + * or visit www.oracle.com if you need additional information or have any 5.24 + * questions. 5.25 + */ 5.26 + 5.27 +import sun.hotspot.WhiteBox; 5.28 + 5.29 +public class CheckContainerized { 5.30 + public static String OUTSIDE_OF_CONTAINER = 5.31 + "CheckContainerized: Running outside of a container"; 5.32 + public static String INSIDE_A_CONTAINER = 5.33 + "CheckContainerized: Running inside a container"; 5.34 + 5.35 + public static void main(String[] args) { 5.36 + System.out.println("CheckContainerized: Entering"); 5.37 + WhiteBox wb = WhiteBox.getWhiteBox(); 5.38 + 5.39 + if (wb.isContainerized()) { 5.40 + System.out.println(INSIDE_A_CONTAINER); 5.41 + 5.42 + } else { 5.43 + System.out.println(OUTSIDE_OF_CONTAINER); 5.44 + } 5.45 + } 5.46 +} 5.47 +
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/runtime/containers/docker/DockerBasicTest.java Sat Aug 18 12:58:53 2018 +0100 6.3 @@ -0,0 +1,80 @@ 6.4 +/* 6.5 + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.7 + * 6.8 + * This code is free software; you can redistribute it and/or modify it 6.9 + * under the terms of the GNU General Public License version 2 only, as 6.10 + * published by the Free Software Foundation. 6.11 + * 6.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 6.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 6.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 6.15 + * version 2 for more details (a copy is included in the LICENSE file that 6.16 + * accompanied this code). 6.17 + * 6.18 + * You should have received a copy of the GNU General Public License version 6.19 + * 2 along with this work; if not, write to the Free Software Foundation, 6.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 6.21 + * 6.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 6.23 + * or visit www.oracle.com if you need additional information or have any 6.24 + * questions. 6.25 + */ 6.26 + 6.27 + 6.28 +/* 6.29 + * @test 6.30 + * @summary Basic (sanity) test for JDK-under-test inside a docker image. 6.31 + * @library /testlibrary 6.32 + * @build HelloDocker 6.33 + * @run driver DockerBasicTest 6.34 + */ 6.35 + 6.36 +import com.oracle.java.testlibrary.Utils; 6.37 +import com.oracle.java.testlibrary.Platform; 6.38 +import com.oracle.java.testlibrary.DockerTestUtils; 6.39 +import com.oracle.java.testlibrary.DockerRunOptions; 6.40 + 6.41 +public class DockerBasicTest { 6.42 + private static final String imageNameAndTag = "jdk8-internal:test"; 6.43 + // Diganostics: set to false to examine image after the test 6.44 + private static final boolean removeImageAfterTest = true; 6.45 + 6.46 + public static void main(String[] args) throws Exception { 6.47 + if (!DockerTestUtils.canTestDocker()) { 6.48 + return; 6.49 + } 6.50 + DockerTestUtils.buildJdkDockerImage(imageNameAndTag, "Dockerfile-BasicTest", "jdk-docker"); 6.51 + 6.52 + try { 6.53 + testJavaVersion(); 6.54 + testHelloDocker(); 6.55 + } finally { 6.56 + if (removeImageAfterTest) 6.57 + DockerTestUtils.removeDockerImage(imageNameAndTag); 6.58 + } 6.59 + } 6.60 + 6.61 + 6.62 + private static void testJavaVersion() throws Exception { 6.63 + DockerRunOptions opts = 6.64 + new DockerRunOptions(imageNameAndTag, "/jdk/bin/java", "-version"); 6.65 + 6.66 + DockerTestUtils.dockerRunJava(opts) 6.67 + .shouldHaveExitValue(0) 6.68 + .shouldContain(Platform.vmName); 6.69 + } 6.70 + 6.71 + 6.72 + private static void testHelloDocker() throws Exception { 6.73 + DockerRunOptions opts = 6.74 + new DockerRunOptions(imageNameAndTag, "/jdk/bin/java", "HelloDocker") 6.75 + .addJavaOpts("-cp", "/test-classes/") 6.76 + .addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/"); 6.77 + 6.78 + DockerTestUtils.dockerRunJava(opts) 6.79 + .shouldHaveExitValue(0) 6.80 + .shouldContain("Hello Docker"); 6.81 + } 6.82 +} 6.83 +
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/test/runtime/containers/docker/Dockerfile-BasicTest Sat Aug 18 12:58:53 2018 +0100 7.3 @@ -0,0 +1,8 @@ 7.4 +FROM oraclelinux:7.2 7.5 +MAINTAINER mikhailo.seledtsov@oracle.com 7.6 + 7.7 +COPY /jdk /jdk 7.8 + 7.9 +ENV JAVA_HOME=/jdk 7.10 + 7.11 +CMD ["/bin/bash"]
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/test/runtime/containers/docker/Dockerfile-BasicTest-aarch64 Sat Aug 18 12:58:53 2018 +0100 8.3 @@ -0,0 +1,8 @@ 8.4 +# Use generic ubuntu Linux on AArch64 8.5 +FROM aarch64/ubuntu 8.6 + 8.7 +COPY /jdk /jdk 8.8 + 8.9 +ENV JAVA_HOME=/jdk 8.10 + 8.11 +CMD ["/bin/bash"]
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/test/runtime/containers/docker/Dockerfile-BasicTest-ppc64le Sat Aug 18 12:58:53 2018 +0100 9.3 @@ -0,0 +1,10 @@ 9.4 +# test on x86_64 uses Oracle Linux but we do not have this for ppc64le 9.5 +# so use some other Linux where OpenJDK works 9.6 +# FROM oraclelinux:7.2 9.7 +FROM ppc64le/ubuntu 9.8 + 9.9 +COPY /jdk /jdk 9.10 + 9.11 +ENV JAVA_HOME=/jdk 9.12 + 9.13 +CMD ["/bin/bash"]
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/test/runtime/containers/docker/Dockerfile-BasicTest-s390x Sat Aug 18 12:58:53 2018 +0100 10.3 @@ -0,0 +1,7 @@ 10.4 +FROM s390x/ubuntu 10.5 + 10.6 +COPY /jdk /jdk 10.7 + 10.8 +ENV JAVA_HOME=/jdk 10.9 + 10.10 +CMD ["/bin/bash"]
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/test/runtime/containers/docker/HelloDocker.java Sat Aug 18 12:58:53 2018 +0100 11.3 @@ -0,0 +1,28 @@ 11.4 +/* 11.5 + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 11.7 + * 11.8 + * This code is free software; you can redistribute it and/or modify it 11.9 + * under the terms of the GNU General Public License version 2 only, as 11.10 + * published by the Free Software Foundation. 11.11 + * 11.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 11.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11.15 + * version 2 for more details (a copy is included in the LICENSE file that 11.16 + * accompanied this code). 11.17 + * 11.18 + * You should have received a copy of the GNU General Public License version 11.19 + * 2 along with this work; if not, write to the Free Software Foundation, 11.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 11.21 + * 11.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 11.23 + * or visit www.oracle.com if you need additional information or have any 11.24 + * questions. 11.25 + */ 11.26 + 11.27 +public class HelloDocker { 11.28 + public static void main(String args[]) { 11.29 + System.out.println("Hello Docker"); 11.30 + } 11.31 +}
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/test/runtime/containers/docker/PrintContainerInfo.java Sat Aug 18 12:58:53 2018 +0100 12.3 @@ -0,0 +1,34 @@ 12.4 +/* 12.5 + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 12.7 + * 12.8 + * This code is free software; you can redistribute it and/or modify it 12.9 + * under the terms of the GNU General Public License version 2 only, as 12.10 + * published by the Free Software Foundation. 12.11 + * 12.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 12.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12.15 + * version 2 for more details (a copy is included in the LICENSE file that 12.16 + * accompanied this code). 12.17 + * 12.18 + * You should have received a copy of the GNU General Public License version 12.19 + * 2 along with this work; if not, write to the Free Software Foundation, 12.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 12.21 + * 12.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 12.23 + * or visit www.oracle.com if you need additional information or have any 12.24 + * questions. 12.25 + */ 12.26 + 12.27 +import sun.hotspot.WhiteBox; 12.28 + 12.29 +public class PrintContainerInfo { 12.30 + 12.31 + public static void main(String[] args) { 12.32 + System.out.println("PrintContainerInfo: Entering"); 12.33 + WhiteBox wb = WhiteBox.getWhiteBox(); 12.34 + 12.35 + wb.printOsInfo(); 12.36 + } 12.37 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/test/runtime/containers/docker/TEST.properties Sat Aug 18 12:58:53 2018 +0100 13.3 @@ -0,0 +1,1 @@ 13.4 +exclusiveAccess.dirs=.
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/test/runtime/containers/docker/TestCPUAwareness.java Sat Aug 18 12:58:53 2018 +0100 14.3 @@ -0,0 +1,204 @@ 14.4 +/* 14.5 + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 14.7 + * 14.8 + * This code is free software; you can redistribute it and/or modify it 14.9 + * under the terms of the GNU General Public License version 2 only, as 14.10 + * published by the Free Software Foundation. 14.11 + * 14.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 14.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14.15 + * version 2 for more details (a copy is included in the LICENSE file that 14.16 + * accompanied this code). 14.17 + * 14.18 + * You should have received a copy of the GNU General Public License version 14.19 + * 2 along with this work; if not, write to the Free Software Foundation, 14.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 14.21 + * 14.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 14.23 + * or visit www.oracle.com if you need additional information or have any 14.24 + * questions. 14.25 + */ 14.26 + 14.27 + 14.28 +/* 14.29 + * @test 14.30 + * @summary Test JVM's CPU resource awareness when running inside docker container 14.31 + * @library /testlibrary 14.32 + * @run driver TestCPUAwareness 14.33 + */ 14.34 + 14.35 +import java.util.List; 14.36 +import com.oracle.java.testlibrary.Common; 14.37 +import com.oracle.java.testlibrary.DockerTestUtils; 14.38 +import com.oracle.java.testlibrary.DockerRunOptions; 14.39 + 14.40 +public class TestCPUAwareness { 14.41 +private static final String imageName = Common.imageName("cpu"); 14.42 + private static final int availableCPUs = Runtime.getRuntime().availableProcessors(); 14.43 + 14.44 + public static void main(String[] args) throws Exception { 14.45 + if (!DockerTestUtils.canTestDocker()) { 14.46 + return; 14.47 + } 14.48 + 14.49 + System.out.println("Test Environment: detected availableCPUs = " + availableCPUs); 14.50 + DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker"); 14.51 + 14.52 + try { 14.53 + // cpuset, period, shares, expected Active Processor Count 14.54 + testComboWithCpuSets(); 14.55 + 14.56 + // cpu shares - it should be safe to use CPU shares exceeding available CPUs 14.57 + testCpuShares(256, 1); 14.58 + testCpuShares(2048, 2); 14.59 + testCpuShares(4096, 4); 14.60 + 14.61 + // leave one CPU for system and tools, otherwise this test may be unstable 14.62 + int maxNrOfAvailableCpus = availableCPUs - 1; 14.63 + for (int i=1; i < maxNrOfAvailableCpus; i = i * 2) { 14.64 + testCpus(i, i); 14.65 + } 14.66 + 14.67 + // If ActiveProcessorCount is set, the VM should use it, regardless of other 14.68 + // container settings, host settings or available CPUs on the host. 14.69 + testActiveProcessorCount(1, 1); 14.70 + testActiveProcessorCount(2, 2); 14.71 + 14.72 + // cpu quota and period 14.73 + testCpuQuotaAndPeriod(50*1000, 100*1000); 14.74 + testCpuQuotaAndPeriod(100*1000, 100*1000); 14.75 + testCpuQuotaAndPeriod(150*1000, 100*1000); 14.76 + testCpuQuotaAndPeriod(400*1000, 100*1000); 14.77 + 14.78 + } finally { 14.79 + DockerTestUtils.removeDockerImage(imageName); 14.80 + } 14.81 + } 14.82 + 14.83 + 14.84 + private static void testComboWithCpuSets() throws Exception { 14.85 + String cpuSetStr = CPUSetsReader.readFromProcStatus("Cpus_allowed_list"); 14.86 + System.out.println("cpuSetStr = " + cpuSetStr); 14.87 + 14.88 + if (cpuSetStr == null) { 14.89 + System.out.printf("The cpuset test cases are skipped"); 14.90 + } else { 14.91 + List<Integer> cpuSet = CPUSetsReader.parseCpuSet(cpuSetStr); 14.92 + 14.93 + // Test subset of cpuset with one element 14.94 + if (cpuSet.size() >= 1) { 14.95 + String testCpuSet = CPUSetsReader.listToString(cpuSet, 1); 14.96 + testAPCCombo(testCpuSet, 200*1000, 100*1000, 4*1024, true, 1); 14.97 + } 14.98 + 14.99 + // Test subset of cpuset with two elements 14.100 + if (cpuSet.size() >= 2) { 14.101 + String testCpuSet = CPUSetsReader.listToString(cpuSet, 2); 14.102 + testAPCCombo(testCpuSet, 200*1000, 100*1000, 4*1024, true, 2); 14.103 + testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, true, 2); 14.104 + testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, false, 1); 14.105 + } 14.106 + 14.107 + // Test subset of cpuset with three elements 14.108 + if (cpuSet.size() >= 3) { 14.109 + String testCpuSet = CPUSetsReader.listToString(cpuSet, 3); 14.110 + testAPCCombo(testCpuSet, 100*1000, 100*1000, 2*1024, true, 1); 14.111 + testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, true, 2); 14.112 + testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, false, 1); 14.113 + } 14.114 + } 14.115 + } 14.116 + 14.117 + 14.118 + private static void testActiveProcessorCount(int valueToSet, int expectedValue) throws Exception { 14.119 + Common.logNewTestCase("Test ActiveProcessorCount: valueToSet = " + valueToSet); 14.120 + 14.121 + DockerRunOptions opts = Common.newOpts(imageName) 14.122 + .addJavaOpts("-XX:ActiveProcessorCount=" + valueToSet, "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintActiveCpus"); 14.123 + Common.run(opts) 14.124 + .shouldMatch("active processor count set by user.*" + expectedValue); 14.125 + } 14.126 + 14.127 + 14.128 + private static void testCpus(int valueToSet, int expectedTraceValue) throws Exception { 14.129 + Common.logNewTestCase("test cpus: " + valueToSet); 14.130 + DockerRunOptions opts = Common.newOpts(imageName) 14.131 + .addDockerOpts("--cpus", "" + valueToSet); 14.132 + Common.run(opts) 14.133 + .shouldMatch("active_processor_count.*" + expectedTraceValue); 14.134 + } 14.135 + 14.136 + 14.137 + // Expected active processor count can not exceed available CPU count 14.138 + private static int adjustExpectedAPCForAvailableCPUs(int expectedAPC) { 14.139 + if (expectedAPC > availableCPUs) { 14.140 + expectedAPC = availableCPUs; 14.141 + System.out.println("Adjusted expectedAPC = " + expectedAPC); 14.142 + } 14.143 + return expectedAPC; 14.144 + } 14.145 + 14.146 + 14.147 + private static void testCpuQuotaAndPeriod(int quota, int period) 14.148 + throws Exception { 14.149 + Common.logNewTestCase("test cpu quota and period: "); 14.150 + System.out.println("quota = " + quota); 14.151 + System.out.println("period = " + period); 14.152 + 14.153 + int expectedAPC = (int) Math.ceil((float) quota / (float) period); 14.154 + System.out.println("expectedAPC = " + expectedAPC); 14.155 + expectedAPC = adjustExpectedAPCForAvailableCPUs(expectedAPC); 14.156 + 14.157 + DockerRunOptions opts = Common.newOpts(imageName) 14.158 + .addDockerOpts("--cpu-period=" + period) 14.159 + .addDockerOpts("--cpu-quota=" + quota); 14.160 + 14.161 + Common.run(opts) 14.162 + .shouldMatch("CPU Period is.*" + period) 14.163 + .shouldMatch("CPU Quota is.*" + quota) 14.164 + .shouldMatch("active_processor_count.*" + expectedAPC); 14.165 + } 14.166 + 14.167 + 14.168 + // Test correctess of automatically selected active processor cound 14.169 + private static void testAPCCombo(String cpuset, int quota, int period, int shares, 14.170 + boolean usePreferContainerQuotaForCPUCount, 14.171 + int expectedAPC) throws Exception { 14.172 + Common.logNewTestCase("test APC Combo"); 14.173 + System.out.println("cpuset = " + cpuset); 14.174 + System.out.println("quota = " + quota); 14.175 + System.out.println("period = " + period); 14.176 + System.out.println("shares = " + period); 14.177 + System.out.println("usePreferContainerQuotaForCPUCount = " + usePreferContainerQuotaForCPUCount); 14.178 + System.out.println("expectedAPC = " + expectedAPC); 14.179 + 14.180 + expectedAPC = adjustExpectedAPCForAvailableCPUs(expectedAPC); 14.181 + 14.182 + DockerRunOptions opts = Common.newOpts(imageName) 14.183 + .addDockerOpts("--cpuset-cpus", "" + cpuset) 14.184 + .addDockerOpts("--cpu-period=" + period) 14.185 + .addDockerOpts("--cpu-quota=" + quota) 14.186 + .addDockerOpts("--cpu-shares=" + shares); 14.187 + 14.188 + if (!usePreferContainerQuotaForCPUCount) opts.addJavaOpts("-XX:-PreferContainerQuotaForCPUCount"); 14.189 + 14.190 + Common.run(opts) 14.191 + .shouldMatch("active_processor_count.*" + expectedAPC); 14.192 + } 14.193 + 14.194 + 14.195 + private static void testCpuShares(int shares, int expectedAPC) throws Exception { 14.196 + Common.logNewTestCase("test cpu shares, shares = " + shares); 14.197 + System.out.println("expectedAPC = " + expectedAPC); 14.198 + 14.199 + expectedAPC = adjustExpectedAPCForAvailableCPUs(expectedAPC); 14.200 + 14.201 + DockerRunOptions opts = Common.newOpts(imageName) 14.202 + .addDockerOpts("--cpu-shares=" + shares); 14.203 + Common.run(opts) 14.204 + .shouldMatch("CPU Shares is.*" + shares) 14.205 + .shouldMatch("active_processor_count.*" + expectedAPC); 14.206 + } 14.207 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/test/runtime/containers/docker/TestCPUSets.java Sat Aug 18 12:58:53 2018 +0100 15.3 @@ -0,0 +1,137 @@ 15.4 +/* 15.5 + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 15.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 15.7 + * 15.8 + * This code is free software; you can redistribute it and/or modify it 15.9 + * under the terms of the GNU General Public License version 2 only, as 15.10 + * published by the Free Software Foundation. 15.11 + * 15.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 15.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15.15 + * version 2 for more details (a copy is included in the LICENSE file that 15.16 + * accompanied this code). 15.17 + * 15.18 + * You should have received a copy of the GNU General Public License version 15.19 + * 2 along with this work; if not, write to the Free Software Foundation, 15.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 15.21 + * 15.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 15.23 + * or visit www.oracle.com if you need additional information or have any 15.24 + * questions. 15.25 + */ 15.26 + 15.27 + 15.28 +/* 15.29 + * @test 15.30 + * @summary Test JVM's awareness of cpu sets (cpus and mems) 15.31 + * @library /testlibrary /testlibrary/whitebox 15.32 + * @build AttemptOOM CPUSetsReader sun.hotspot.WhiteBox PrintContainerInfo 15.33 + * @run driver ClassFileInstaller -jar whitebox.jar sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission 15.34 + * @run driver TestCPUSets 15.35 + */ 15.36 + 15.37 +import java.util.List; 15.38 +import com.oracle.java.testlibrary.Common; 15.39 +import com.oracle.java.testlibrary.DockerRunOptions; 15.40 +import com.oracle.java.testlibrary.DockerTestUtils; 15.41 +import com.oracle.java.testlibrary.Asserts; 15.42 +import com.oracle.java.testlibrary.Platform; 15.43 +import com.oracle.java.testlibrary.Utils; 15.44 +import com.oracle.java.testlibrary.OutputAnalyzer; 15.45 + 15.46 + 15.47 +public class TestCPUSets { 15.48 + private static final String imageName = Common.imageName("cpusets"); 15.49 + 15.50 + public static void main(String[] args) throws Exception { 15.51 + if (!DockerTestUtils.canTestDocker()) { 15.52 + return; 15.53 + } 15.54 + 15.55 + Common.prepareWhiteBox(); 15.56 + DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker"); 15.57 + 15.58 + try { 15.59 + // Sanity test the cpu sets reader and parser 15.60 + CPUSetsReader.test(); 15.61 + testTheSet("Cpus_allowed_list"); 15.62 + testTheSet("Mems_allowed_list"); 15.63 + } finally { 15.64 + DockerTestUtils.removeDockerImage(imageName); 15.65 + } 15.66 + } 15.67 + 15.68 + 15.69 + private static void testTheSet(String setType) throws Exception { 15.70 + String cpuSetStr = CPUSetsReader.readFromProcStatus(setType); 15.71 + 15.72 + if (cpuSetStr == null) { 15.73 + System.out.printf("The %s test is skipped %n", setType); 15.74 + } else { 15.75 + List<Integer> cpuSet = CPUSetsReader.parseCpuSet(cpuSetStr); 15.76 + 15.77 + // Test subset of one, full subset, and half of the subset 15.78 + testCpuSet(CPUSetsReader.listToString(cpuSet, 1)); 15.79 + if (cpuSet.size() > 1) { 15.80 + testCpuSet(CPUSetsReader.listToString(cpuSet)); 15.81 + } 15.82 + if (cpuSet.size() > 2) { 15.83 + testCpuSet(CPUSetsReader.listToString(cpuSet, cpuSet.size()/2 )); 15.84 + } 15.85 + } 15.86 + } 15.87 + 15.88 + 15.89 + private static DockerRunOptions commonOpts() { 15.90 + DockerRunOptions opts = new DockerRunOptions(imageName, "/jdk/bin/java", 15.91 + "PrintContainerInfo"); 15.92 + opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/"); 15.93 + opts.addJavaOpts("-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintContainerInfo", "-cp", "/test-classes/"); 15.94 + Common.addWhiteBoxOpts(opts); 15.95 + return opts; 15.96 + } 15.97 + 15.98 + 15.99 + private static void checkResult(List<String> lines, String lineMarker, String value) { 15.100 + boolean lineMarkerFound = false; 15.101 + 15.102 + for (String line : lines) { 15.103 + if (line.contains(lineMarker)) { 15.104 + lineMarkerFound = true; 15.105 + String[] parts = line.split(":"); 15.106 + System.out.println("DEBUG: line = " + line); 15.107 + System.out.println("DEBUG: parts.length = " + parts.length); 15.108 + 15.109 + Asserts.assertEquals(parts.length, 2); 15.110 + String set = parts[1].replaceAll("\\s",""); 15.111 + String actual = CPUSetsReader.listToString(CPUSetsReader.parseCpuSet(set)); 15.112 + Asserts.assertEquals(actual, value); 15.113 + break; 15.114 + } 15.115 + } 15.116 + Asserts.assertTrue(lineMarkerFound); 15.117 + } 15.118 + 15.119 + 15.120 + private static void testCpuSet(String value) throws Exception { 15.121 + Common.logNewTestCase("cpusets.cpus, value = " + value); 15.122 + 15.123 + DockerRunOptions opts = commonOpts(); 15.124 + opts.addDockerOpts("--cpuset-cpus=" + value); 15.125 + 15.126 + List<String> lines = Common.run(opts).asLines(); 15.127 + checkResult(lines, "cpuset.cpus is:", value); 15.128 + } 15.129 + 15.130 + private static void testMemSet(String value) throws Exception { 15.131 + Common.logNewTestCase("cpusets.mems, value = " + value); 15.132 + 15.133 + DockerRunOptions opts = commonOpts(); 15.134 + opts.addDockerOpts("--cpuset-mems=" + value); 15.135 + 15.136 + List<String> lines = Common.run(opts).asLines(); 15.137 + checkResult(lines, "cpuset.mems is:", value); 15.138 + } 15.139 + 15.140 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/test/runtime/containers/docker/TestMemoryAwareness.java Sat Aug 18 12:58:53 2018 +0100 16.3 @@ -0,0 +1,109 @@ 16.4 +/* 16.5 + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 16.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 16.7 + * 16.8 + * This code is free software; you can redistribute it and/or modify it 16.9 + * under the terms of the GNU General Public License version 2 only, as 16.10 + * published by the Free Software Foundation. 16.11 + * 16.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 16.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16.15 + * version 2 for more details (a copy is included in the LICENSE file that 16.16 + * accompanied this code). 16.17 + * 16.18 + * You should have received a copy of the GNU General Public License version 16.19 + * 2 along with this work; if not, write to the Free Software Foundation, 16.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 16.21 + * 16.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 16.23 + * or visit www.oracle.com if you need additional information or have any 16.24 + * questions. 16.25 + */ 16.26 + 16.27 + 16.28 +/* 16.29 + * @test 16.30 + * @summary Test JVM's memory resource awareness when running inside docker container 16.31 + * @library /testlibrary /testlibrary/whitebox 16.32 + * @build AttemptOOM sun.hotspot.WhiteBox PrintContainerInfo 16.33 + * @run driver ClassFileInstaller -jar whitebox.jar sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission 16.34 + * @run driver TestMemoryAwareness 16.35 + */ 16.36 + 16.37 +import com.oracle.java.testlibrary.Common; 16.38 +import com.oracle.java.testlibrary.DockerRunOptions; 16.39 +import com.oracle.java.testlibrary.DockerTestUtils; 16.40 + 16.41 + 16.42 +public class TestMemoryAwareness { 16.43 + private static final String imageName = Common.imageName("memory"); 16.44 + 16.45 + public static void main(String[] args) throws Exception { 16.46 + if (!DockerTestUtils.canTestDocker()) { 16.47 + return; 16.48 + } 16.49 + 16.50 + Common.prepareWhiteBox(); 16.51 + DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker"); 16.52 + 16.53 + try { 16.54 + testMemoryLimit("100m", "104857600"); 16.55 + testMemoryLimit("500m", "524288000"); 16.56 + testMemoryLimit("1g", "1073741824"); 16.57 + testMemoryLimit("4g", "4294967296"); 16.58 + 16.59 + testMemorySoftLimit("500m", "524288000"); 16.60 + testMemorySoftLimit("1g", "1073741824"); 16.61 + 16.62 + // Add extra 10 Mb to allocator limit, to be sure to cause OOM 16.63 + testOOM("256m", 256 + 10); 16.64 + 16.65 + } finally { 16.66 + DockerTestUtils.removeDockerImage(imageName); 16.67 + } 16.68 + } 16.69 + 16.70 + 16.71 + private static void testMemoryLimit(String valueToSet, String expectedTraceValue) 16.72 + throws Exception { 16.73 + 16.74 + Common.logNewTestCase("memory limit: " + valueToSet); 16.75 + 16.76 + DockerRunOptions opts = Common.newOpts(imageName) 16.77 + .addDockerOpts("--memory", valueToSet); 16.78 + 16.79 + Common.run(opts) 16.80 + .shouldMatch("Memory Limit is:.*" + expectedTraceValue); 16.81 + } 16.82 + 16.83 + 16.84 + private static void testMemorySoftLimit(String valueToSet, String expectedTraceValue) 16.85 + throws Exception { 16.86 + Common.logNewTestCase("memory soft limit: " + valueToSet); 16.87 + 16.88 + DockerRunOptions opts = Common.newOpts(imageName, "PrintContainerInfo"); 16.89 + Common.addWhiteBoxOpts(opts); 16.90 + opts.addDockerOpts("--memory-reservation=" + valueToSet); 16.91 + 16.92 + Common.run(opts) 16.93 + .shouldMatch("Memory Soft Limit.*" + expectedTraceValue); 16.94 + } 16.95 + 16.96 + 16.97 + // provoke OOM inside the container, see how VM reacts 16.98 + private static void testOOM(String dockerMemLimit, int sizeToAllocInMb) throws Exception { 16.99 + Common.logNewTestCase("OOM"); 16.100 + 16.101 + DockerRunOptions opts = Common.newOpts(imageName, "AttemptOOM") 16.102 + .addDockerOpts("--memory", dockerMemLimit, "--memory-swap", dockerMemLimit); 16.103 + opts.classParams.add("" + sizeToAllocInMb); 16.104 + 16.105 + DockerTestUtils.dockerRunJava(opts) 16.106 + .shouldHaveExitValue(1) 16.107 + .shouldContain("Entering AttemptOOM main") 16.108 + .shouldNotContain("AttemptOOM allocation successful") 16.109 + .shouldContain("java.lang.OutOfMemoryError"); 16.110 + } 16.111 + 16.112 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/test/runtime/containers/docker/TestMisc.java Sat Aug 18 12:58:53 2018 +0100 17.3 @@ -0,0 +1,113 @@ 17.4 +/* 17.5 + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 17.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 17.7 + * 17.8 + * This code is free software; you can redistribute it and/or modify it 17.9 + * under the terms of the GNU General Public License version 2 only, as 17.10 + * published by the Free Software Foundation. 17.11 + * 17.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 17.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17.15 + * version 2 for more details (a copy is included in the LICENSE file that 17.16 + * accompanied this code). 17.17 + * 17.18 + * You should have received a copy of the GNU General Public License version 17.19 + * 2 along with this work; if not, write to the Free Software Foundation, 17.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17.21 + * 17.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 17.23 + * or visit www.oracle.com if you need additional information or have any 17.24 + * questions. 17.25 + */ 17.26 + 17.27 + 17.28 +/* 17.29 + * @test 17.30 + * @summary Test miscellanous functionality related to JVM running in docker container 17.31 + * @library /testlibrary /testlibrary/whitebox 17.32 + * @build CheckContainerized sun.hotspot.WhiteBox PrintContainerInfo 17.33 + * @run driver ClassFileInstaller -jar whitebox.jar sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission 17.34 + * @run driver TestMisc 17.35 + */ 17.36 + 17.37 +import com.oracle.java.testlibrary.Common; 17.38 +import com.oracle.java.testlibrary.DockerTestUtils; 17.39 +import com.oracle.java.testlibrary.DockerRunOptions; 17.40 +import com.oracle.java.testlibrary.OutputAnalyzer; 17.41 +import com.oracle.java.testlibrary.ProcessTools; 17.42 + 17.43 + 17.44 +public class TestMisc { 17.45 + private static final String imageName = Common.imageName("misc"); 17.46 + 17.47 + public static void main(String[] args) throws Exception { 17.48 + if (!DockerTestUtils.canTestDocker()) { 17.49 + return; 17.50 + } 17.51 + 17.52 + Common.prepareWhiteBox(); 17.53 + DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker"); 17.54 + 17.55 + try { 17.56 + testMinusContainerSupport(); 17.57 + testIsContainerized(); 17.58 + testPrintContainerInfo(); 17.59 + } finally { 17.60 + DockerTestUtils.removeDockerImage(imageName); 17.61 + } 17.62 + } 17.63 + 17.64 + 17.65 + private static void testMinusContainerSupport() throws Exception { 17.66 + Common.logNewTestCase("Test related flags: '-UseContainerSupport'"); 17.67 + DockerRunOptions opts = new DockerRunOptions(imageName, "/jdk/bin/java", "-version"); 17.68 + opts.addJavaOpts("-XX:+UnlockDiagnosticVMOptions", "-XX:-UseContainerSupport", "-XX:+PrintContainerInfo"); 17.69 + 17.70 + Common.run(opts) 17.71 + .shouldContain("Container Support not enabled"); 17.72 + } 17.73 + 17.74 + 17.75 + private static void testIsContainerized() throws Exception { 17.76 + Common.logNewTestCase("Test is_containerized() inside a docker container"); 17.77 + 17.78 + DockerRunOptions opts = Common.newOpts(imageName, "CheckContainerized"); 17.79 + Common.addWhiteBoxOpts(opts); 17.80 + 17.81 + Common.run(opts) 17.82 + .shouldContain(CheckContainerized.INSIDE_A_CONTAINER); 17.83 + } 17.84 + 17.85 + 17.86 + private static void testPrintContainerInfo() throws Exception { 17.87 + Common.logNewTestCase("Test print_container_info()"); 17.88 + 17.89 + DockerRunOptions opts = Common.newOpts(imageName, "PrintContainerInfo"); 17.90 + Common.addWhiteBoxOpts(opts); 17.91 + 17.92 + checkContainerInfo(Common.run(opts)); 17.93 + } 17.94 + 17.95 + 17.96 + private static void checkContainerInfo(OutputAnalyzer out) throws Exception { 17.97 + String[] expectedToContain = new String[] { 17.98 + "cpuset.cpus", 17.99 + "cpuset.mems", 17.100 + "CPU Shares", 17.101 + "CPU Quota", 17.102 + "CPU Period", 17.103 + "OSContainer::active_processor_count", 17.104 + "Memory Limit", 17.105 + "Memory Soft Limit", 17.106 + "Memory Usage", 17.107 + "Maximum Memory Usage", 17.108 + "memory_max_usage_in_bytes" 17.109 + }; 17.110 + 17.111 + for (String s : expectedToContain) { 17.112 + out.shouldContain(s); 17.113 + } 17.114 + } 17.115 + 17.116 +}
18.1 --- a/test/testlibrary/ClassFileInstaller.java Fri Aug 10 12:27:32 2018 +0100 18.2 +++ b/test/testlibrary/ClassFileInstaller.java Sat Aug 18 12:58:53 2018 +0100 18.3 @@ -1,5 +1,5 @@ 18.4 /* 18.5 - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 18.6 + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. 18.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 18.8 * 18.9 * This code is free software; you can redistribute it and/or modify it 18.10 @@ -21,28 +21,229 @@ 18.11 * questions. 18.12 */ 18.13 18.14 +import java.io.ByteArrayInputStream; 18.15 +import java.io.File; 18.16 +import java.io.FileInputStream; 18.17 +import java.io.FileOutputStream; 18.18 +import java.io.FileNotFoundException; 18.19 import java.io.InputStream; 18.20 +import java.io.ByteArrayInputStream; 18.21 import java.nio.file.Files; 18.22 import java.nio.file.Path; 18.23 import java.nio.file.Paths; 18.24 import java.nio.file.StandardCopyOption; 18.25 +import java.util.zip.ZipEntry; 18.26 +import java.util.zip.ZipOutputStream; 18.27 18.28 /** 18.29 - * Dump a class file for a class on the class path in the current directory 18.30 + * Dump a class file for a class on the class path in the current directory, or 18.31 + * in the specified JAR file. This class is usually used when you build a class 18.32 + * from a test library, but want to use this class in a sub-process. 18.33 + * 18.34 + * For example, to build the following library class: 18.35 + * test/lib/sun/hotspot/WhiteBox.java 18.36 + * 18.37 + * You would use the following tags: 18.38 + * 18.39 + * @library /test/lib 18.40 + * @build sun.hotspot.WhiteBox 18.41 + * 18.42 + * JTREG would build the class file under 18.43 + * ${JTWork}/classes/test/lib/sun/hotspot/WhiteBox.class 18.44 + * 18.45 + * With you run your main test class using "@run main MyMainClass", JTREG would setup the 18.46 + * -classpath to include "${JTWork}/classes/test/lib/", so MyMainClass would be able to 18.47 + * load the WhiteBox class. 18.48 + * 18.49 + * However, if you run a sub process, and do not wish to use the exact same -classpath, 18.50 + * You can use ClassFileInstaller to ensure that WhiteBox is available in the current 18.51 + * directory of your test: 18.52 + * 18.53 + * @run main ClassFileInstaller sun.hotspot.WhiteBox 18.54 + * 18.55 + * Or, you can use the -jar option to store the class in the specified JAR file. If a relative 18.56 + * path name is given, the JAR file would be relative to the current directory of 18.57 + * 18.58 + * @run main ClassFileInstaller -jar myjar.jar sun.hotspot.WhiteBox 18.59 */ 18.60 public class ClassFileInstaller { 18.61 /** 18.62 + * You can enable debug tracing of ClassFileInstaller by running JTREG with 18.63 + * jtreg -DClassFileInstaller.debug=true ... <names of tests> 18.64 + */ 18.65 + public static boolean DEBUG = Boolean.getBoolean("ClassFileInstaller.debug"); 18.66 + 18.67 + /** 18.68 * @param args The names of the classes to dump 18.69 * @throws Exception 18.70 */ 18.71 public static void main(String... args) throws Exception { 18.72 - for (String arg : args) { 18.73 - ClassLoader cl = ClassFileInstaller.class.getClassLoader(); 18.74 + if (args.length > 1 && args[0].equals("-jar")) { 18.75 + if (args.length < 2) { 18.76 + throw new RuntimeException("Usage: ClassFileInstaller <options> <classes>\n" + 18.77 + "where possible options include:\n" + 18.78 + " -jar <path> Write to the JAR file <path>"); 18.79 + } 18.80 + writeJar(args[1], null, args, 2, args.length); 18.81 + } else { 18.82 + if (DEBUG) { 18.83 + System.out.println("ClassFileInstaller: Writing to " + System.getProperty("user.dir")); 18.84 + } 18.85 + for (String arg : args) { 18.86 + writeClassToDisk(arg); 18.87 + } 18.88 + } 18.89 + } 18.90 18.91 - // Convert dotted class name to a path to a class file 18.92 - String pathName = arg.replace('.', '/').concat(".class"); 18.93 - InputStream is = cl.getResourceAsStream(pathName); 18.94 + public static class Manifest { 18.95 + private InputStream in; 18.96 18.97 + private Manifest(InputStream in) { 18.98 + this.in = in; 18.99 + } 18.100 + 18.101 + static Manifest fromSourceFile(String fileName) throws Exception { 18.102 + String pathName = System.getProperty("test.src") + File.separator + fileName; 18.103 + return new Manifest(new FileInputStream(pathName)); 18.104 + } 18.105 + 18.106 + // Example: 18.107 + // String manifest = "Premain-Class: RedefineClassHelper\n" + 18.108 + // "Can-Redefine-Classes: true\n"; 18.109 + // ClassFileInstaller.writeJar("redefineagent.jar", 18.110 + // ClassFileInstaller.Manifest.fromString(manifest), 18.111 + // "RedefineClassHelper"); 18.112 + static Manifest fromString(String manifest) throws Exception { 18.113 + return new Manifest(new ByteArrayInputStream(manifest.getBytes())); 18.114 + } 18.115 + 18.116 + public InputStream getInputStream() { 18.117 + return in; 18.118 + } 18.119 + } 18.120 + 18.121 + private static void writeJar(String jarFile, Manifest manifest, String classes[], int from, int to) throws Exception { 18.122 + if (DEBUG) { 18.123 + System.out.println("ClassFileInstaller: Writing to " + getJarPath(jarFile)); 18.124 + } 18.125 + 18.126 + (new File(jarFile)).delete(); 18.127 + FileOutputStream fos = new FileOutputStream(jarFile); 18.128 + ZipOutputStream zos = new ZipOutputStream(fos); 18.129 + 18.130 + // The manifest must be the first or second entry. See comments in JarInputStream 18.131 + // constructor and JDK-5046178. 18.132 + if (manifest != null) { 18.133 + writeToDisk(zos, "META-INF/MANIFEST.MF", manifest.getInputStream()); 18.134 + } 18.135 + 18.136 + for (int i=from; i<to; i++) { 18.137 + writeClassToDisk(zos, classes[i]); 18.138 + } 18.139 + 18.140 + zos.close(); 18.141 + fos.close(); 18.142 + } 18.143 + 18.144 + /* 18.145 + * You can call ClassFileInstaller.writeJar() from your main test class instead of 18.146 + * using "@run ClassFileInstaller -jar ...". E.g., 18.147 + * 18.148 + * String jarPath = ClassFileInstaller.getJarPath("myjar.jar", "sun.hotspot.WhiteBox") 18.149 + * 18.150 + * If you call this API, make sure you build ClassFileInstaller with the following tags: 18.151 + * 18.152 + * @library testlibrary 18.153 + * @build ClassFileInstaller 18.154 + */ 18.155 + public static String writeJar(String jarFile, String... classes) throws Exception { 18.156 + writeJar(jarFile, null, classes, 0, classes.length); 18.157 + return getJarPath(jarFile); 18.158 + } 18.159 + 18.160 + public static String writeJar(String jarFile, Manifest manifest, String... classes) throws Exception { 18.161 + writeJar(jarFile, manifest, classes, 0, classes.length); 18.162 + return getJarPath(jarFile); 18.163 + } 18.164 + 18.165 + /** 18.166 + * This returns the absolute path to the file specified in "@ClassFileInstaller -jar myjar.jar", 18.167 + * In your test program, instead of using the JAR file name directly: 18.168 + * 18.169 + * String jarPath = "myjar.jar"; 18.170 + * 18.171 + * you should call this function, like: 18.172 + * 18.173 + * String jarPath = ClassFileInstaller.getJarPath("myjar.jar") 18.174 + * 18.175 + * The reasons are: 18.176 + * (1) Using absolute path makes it easy to cut-and-paste from the JTR file and rerun your 18.177 + * test in any directory. 18.178 + * (2) In the future, we may make the JAR file name unique to avoid clobbering 18.179 + * during parallel JTREG execution. 18.180 + * 18.181 + */ 18.182 + public static String getJarPath(String jarFileName) { 18.183 + return new File(jarFileName).getAbsolutePath(); 18.184 + } 18.185 + 18.186 + public static void writeClassToDisk(String className) throws Exception { 18.187 + writeClassToDisk((ZipOutputStream)null, className); 18.188 + } 18.189 + private static void writeClassToDisk(ZipOutputStream zos, String className) throws Exception { 18.190 + writeClassToDisk(zos, className, ""); 18.191 + } 18.192 + 18.193 + public static void writeClassToDisk(String className, String prependPath) throws Exception { 18.194 + writeClassToDisk(null, className, prependPath); 18.195 + } 18.196 + private static void writeClassToDisk(ZipOutputStream zos, String className, String prependPath) throws Exception { 18.197 + ClassLoader cl = ClassFileInstaller.class.getClassLoader(); 18.198 + 18.199 + // Convert dotted class name to a path to a class file 18.200 + String pathName = className.replace('.', '/').concat(".class"); 18.201 + InputStream is = cl.getResourceAsStream(pathName); 18.202 + if (is == null) { 18.203 + throw new RuntimeException("Failed to find " + pathName); 18.204 + } 18.205 + if (prependPath.length() > 0) { 18.206 + pathName = prependPath + "/" + pathName; 18.207 + } 18.208 + writeToDisk(zos, pathName, is); 18.209 + } 18.210 + 18.211 + public static void writeClassToDisk(String className, byte[] bytecode) throws Exception { 18.212 + writeClassToDisk(null, className, bytecode); 18.213 + } 18.214 + private static void writeClassToDisk(ZipOutputStream zos, String className, byte[] bytecode) throws Exception { 18.215 + writeClassToDisk(zos, className, bytecode, ""); 18.216 + } 18.217 + 18.218 + public static void writeClassToDisk(String className, byte[] bytecode, String prependPath) throws Exception { 18.219 + writeClassToDisk(null, className, bytecode, prependPath); 18.220 + } 18.221 + private static void writeClassToDisk(ZipOutputStream zos, String className, byte[] bytecode, String prependPath) throws Exception { 18.222 + // Convert dotted class name to a path to a class file 18.223 + String pathName = className.replace('.', '/').concat(".class"); 18.224 + if (prependPath.length() > 0) { 18.225 + pathName = prependPath + "/" + pathName; 18.226 + } 18.227 + writeToDisk(zos, pathName, new ByteArrayInputStream(bytecode)); 18.228 + } 18.229 + 18.230 + private static void writeToDisk(ZipOutputStream zos, String pathName, InputStream is) throws Exception { 18.231 + if (DEBUG) { 18.232 + System.out.println("ClassFileInstaller: Writing " + pathName); 18.233 + } 18.234 + if (zos != null) { 18.235 + ZipEntry ze = new ZipEntry(pathName); 18.236 + zos.putNextEntry(ze); 18.237 + byte[] buf = new byte[1024]; 18.238 + int len; 18.239 + while ((len = is.read(buf))>0){ 18.240 + zos.write(buf, 0, len); 18.241 + } 18.242 + } else { 18.243 // Create the class file's package directory 18.244 Path p = Paths.get(pathName); 18.245 if (pathName.contains("/")) { 18.246 @@ -51,5 +252,6 @@ 18.247 // Create the class file 18.248 Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING); 18.249 } 18.250 + is.close(); 18.251 } 18.252 }
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/test/testlibrary/com/oracle/java/testlibrary/Common.java Sat Aug 18 12:58:53 2018 +0100 19.3 @@ -0,0 +1,89 @@ 19.4 +/* 19.5 + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 19.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 19.7 + * 19.8 + * This code is free software; you can redistribute it and/or modify it 19.9 + * under the terms of the GNU General Public License version 2 only, as 19.10 + * published by the Free Software Foundation. 19.11 + * 19.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 19.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 19.15 + * version 2 for more details (a copy is included in the LICENSE file that 19.16 + * accompanied this code). 19.17 + * 19.18 + * You should have received a copy of the GNU General Public License version 19.19 + * 2 along with this work; if not, write to the Free Software Foundation, 19.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19.21 + * 19.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19.23 + * or visit www.oracle.com if you need additional information or have any 19.24 + * questions. 19.25 + */ 19.26 + 19.27 +package com.oracle.java.testlibrary; 19.28 + 19.29 +/* 19.30 + * Methods and definitions common to docker tests container in this directory 19.31 + */ 19.32 + 19.33 +import java.io.File; 19.34 +import java.nio.file.Files; 19.35 +import java.nio.file.Path; 19.36 +import java.nio.file.Paths; 19.37 +import com.oracle.java.testlibrary.DockerTestUtils; 19.38 +import com.oracle.java.testlibrary.DockerRunOptions; 19.39 +import com.oracle.java.testlibrary.Utils; 19.40 +import com.oracle.java.testlibrary.OutputAnalyzer; 19.41 + 19.42 + 19.43 +public class Common { 19.44 + public static final String imageNameAndTag = "jdk-internal:test"; 19.45 + 19.46 + public static String imageName(String suffix) { 19.47 + return imageNameAndTag + "-" + suffix; 19.48 + } 19.49 + 19.50 + public static void prepareWhiteBox() throws Exception { 19.51 + Path whiteboxPath = Paths.get(Utils.TEST_CLASSES, "whitebox.jar"); 19.52 + if( !Files.exists(whiteboxPath) ) { 19.53 + Files.copy(Paths.get(new File("whitebox.jar").getAbsolutePath()), 19.54 + Paths.get(Utils.TEST_CLASSES, "whitebox.jar")); 19.55 + } 19.56 + } 19.57 + 19.58 + // create simple commonly used options 19.59 + public static DockerRunOptions newOpts(String imageNameAndTag) { 19.60 + return new DockerRunOptions(imageNameAndTag, "/jdk/bin/java", "-version") 19.61 + .addJavaOpts("-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintContainerInfo"); 19.62 + } 19.63 + 19.64 + 19.65 + // create commonly used options with class to be launched inside container 19.66 + public static DockerRunOptions newOpts(String imageNameAndTag, String testClass) { 19.67 + DockerRunOptions opts = 19.68 + new DockerRunOptions(imageNameAndTag, "/jdk/bin/java", testClass); 19.69 + opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/"); 19.70 + opts.addJavaOpts("-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintContainerInfo", "-cp", "/test-classes/"); 19.71 + return opts; 19.72 + } 19.73 + 19.74 + public static DockerRunOptions addWhiteBoxOpts(DockerRunOptions opts) { 19.75 + opts.addJavaOpts("-Xbootclasspath/a:/test-classes/whitebox.jar", 19.76 + "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI"); 19.77 + return opts; 19.78 + } 19.79 + 19.80 + // most common type of run and checks 19.81 + public static OutputAnalyzer run(DockerRunOptions opts) throws Exception { 19.82 + return DockerTestUtils.dockerRunJava(opts) 19.83 + .shouldHaveExitValue(0).shouldContain("Initializing Container Support"); 19.84 + } 19.85 + 19.86 + 19.87 + // log beginning of a test case 19.88 + public static void logNewTestCase(String msg) { 19.89 + System.out.println("========== NEW TEST CASE: " + msg); 19.90 + } 19.91 + 19.92 +}
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/test/testlibrary/com/oracle/java/testlibrary/DockerRunOptions.java Sat Aug 18 12:58:53 2018 +0100 20.3 @@ -0,0 +1,73 @@ 20.4 +/* 20.5 + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 20.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 20.7 + * 20.8 + * This code is free software; you can redistribute it and/or modify it 20.9 + * under the terms of the GNU General Public License version 2 only, as 20.10 + * published by the Free Software Foundation. 20.11 + * 20.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 20.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 20.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 20.15 + * version 2 for more details (a copy is included in the LICENSE file that 20.16 + * accompanied this code). 20.17 + * 20.18 + * You should have received a copy of the GNU General Public License version 20.19 + * 2 along with this work; if not, write to the Free Software Foundation, 20.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20.21 + * 20.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20.23 + * or visit www.oracle.com if you need additional information or have any 20.24 + * questions. 20.25 + */ 20.26 + 20.27 +package com.oracle.java.testlibrary; 20.28 + 20.29 +import java.util.ArrayList; 20.30 +import java.util.Collections; 20.31 + 20.32 + 20.33 +// This class represents options for running java inside docker containers 20.34 +// in test environment. 20.35 +public class DockerRunOptions { 20.36 + public String imageNameAndTag; 20.37 + public ArrayList<String> dockerOpts = new ArrayList<String>(); 20.38 + public String command; // normally a full path to java 20.39 + public ArrayList<String> javaOpts = new ArrayList<String>(); 20.40 + public String classToRun; // class or "-version" 20.41 + public ArrayList<String> classParams = new ArrayList<String>(); 20.42 + 20.43 + public boolean tty = true; 20.44 + public boolean removeContainerAfterUse = true; 20.45 + public boolean appendTestJavaOptions = true; 20.46 + public boolean retainChildStdout = false; 20.47 + 20.48 + /** 20.49 + * Convenience constructor for most common use cases in testing. 20.50 + * @param imageNameAndTag a string representing name and tag for the 20.51 + * docker image to run, as "name:tag" 20.52 + * @param javaCmd a java command to run (e.g. /jdk/bin/java) 20.53 + * @param classToRun a class to run, or "-version" 20.54 + * @param javaOpts java options to use 20.55 + * 20.56 + * @return Default docker run options 20.57 + */ 20.58 + public DockerRunOptions(String imageNameAndTag, String javaCmd, 20.59 + String classToRun, String... javaOpts) { 20.60 + this.imageNameAndTag = imageNameAndTag; 20.61 + this.command = javaCmd; 20.62 + this.classToRun = classToRun; 20.63 + this.addJavaOpts(javaOpts); 20.64 + } 20.65 + 20.66 + public DockerRunOptions addDockerOpts(String... opts) { 20.67 + Collections.addAll(dockerOpts, opts); 20.68 + return this; 20.69 + } 20.70 + 20.71 + public DockerRunOptions addJavaOpts(String... opts) { 20.72 + Collections.addAll(javaOpts, opts); 20.73 + return this; 20.74 + } 20.75 + 20.76 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/test/testlibrary/com/oracle/java/testlibrary/DockerTestUtils.java Sat Aug 18 12:58:53 2018 +0100 21.3 @@ -0,0 +1,282 @@ 21.4 +/* 21.5 + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 21.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 21.7 + * 21.8 + * This code is free software; you can redistribute it and/or modify it 21.9 + * under the terms of the GNU General Public License version 2 only, as 21.10 + * published by the Free Software Foundation. 21.11 + * 21.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 21.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 21.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 21.15 + * version 2 for more details (a copy is included in the LICENSE file that 21.16 + * accompanied this code). 21.17 + * 21.18 + * You should have received a copy of the GNU General Public License version 21.19 + * 2 along with this work; if not, write to the Free Software Foundation, 21.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21.21 + * 21.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21.23 + * or visit www.oracle.com if you need additional information or have any 21.24 + * questions. 21.25 + */ 21.26 + 21.27 +package com.oracle.java.testlibrary; 21.28 + 21.29 +import java.io.File; 21.30 +import java.io.IOException; 21.31 +import java.nio.file.Files; 21.32 +import java.nio.file.FileVisitResult; 21.33 +import java.nio.file.Path; 21.34 +import java.nio.file.Paths; 21.35 +import java.nio.file.SimpleFileVisitor; 21.36 +import java.nio.file.StandardCopyOption; 21.37 +import java.nio.file.attribute.BasicFileAttributes; 21.38 +import java.util.ArrayList; 21.39 +import java.util.Collections; 21.40 +import java.util.List; 21.41 + 21.42 +import com.oracle.java.testlibrary.Utils; 21.43 +import com.oracle.java.testlibrary.Platform; 21.44 +import com.oracle.java.testlibrary.OutputAnalyzer; 21.45 +import com.oracle.java.testlibrary.ProcessTools; 21.46 + 21.47 +public class DockerTestUtils { 21.48 + private static final String FS = File.separator; 21.49 + private static boolean isDockerEngineAvailable = false; 21.50 + private static boolean wasDockerEngineChecked = false; 21.51 + 21.52 + // Diagnostics: set to true to enable more diagnostic info 21.53 + private static final boolean DEBUG = false; 21.54 + 21.55 + /** 21.56 + * Optimized check of whether the docker engine is available in a given 21.57 + * environment. Checks only once, then remembers the result in a singleton. 21.58 + * 21.59 + * @return true if docker engine is available 21.60 + * @throws Exception 21.61 + */ 21.62 + public static boolean isDockerEngineAvailable() throws Exception { 21.63 + if (wasDockerEngineChecked) 21.64 + return isDockerEngineAvailable; 21.65 + 21.66 + isDockerEngineAvailable = isDockerEngineAvailableCheck(); 21.67 + wasDockerEngineChecked = true; 21.68 + return isDockerEngineAvailable; 21.69 + } 21.70 + 21.71 + 21.72 + /** 21.73 + * Convenience method, will check if docker engine is available and usable; 21.74 + * will print the appropriate message when not available. 21.75 + * 21.76 + * @return true if docker engine is available 21.77 + * @throws Exception 21.78 + */ 21.79 + public static boolean canTestDocker() throws Exception { 21.80 + if (isDockerEngineAvailable()) { 21.81 + return true; 21.82 + } else { 21.83 + System.out.println("Docker engine is not available on this system"); 21.84 + System.out.println("This test is SKIPPED"); 21.85 + return false; 21.86 + } 21.87 + } 21.88 + 21.89 + 21.90 + /** 21.91 + * Simple check - is docker engine available, accessible and usable. 21.92 + * Run basic docker command: 'docker ps' - list docker instances. 21.93 + * If docker engine is available and accesible then true is returned 21.94 + * and we can proceed with testing docker. 21.95 + * 21.96 + * @return true if docker engine is available and usable 21.97 + * @throws Exception 21.98 + */ 21.99 + private static boolean isDockerEngineAvailableCheck() throws Exception { 21.100 + try { 21.101 + execute("docker", "ps") 21.102 + .shouldHaveExitValue(0) 21.103 + .shouldContain("CONTAINER") 21.104 + .shouldContain("IMAGE"); 21.105 + } catch (Exception e) { 21.106 + return false; 21.107 + } 21.108 + return true; 21.109 + } 21.110 + 21.111 + 21.112 + /** 21.113 + * Build a docker image that contains JDK under test. 21.114 + * The jdk will be placed under the "/jdk/" folder inside the docker file system. 21.115 + * 21.116 + * @param imageName name of the image to be created, including version tag 21.117 + * @param dockerfile name of the dockerfile residing in the test source; 21.118 + * we check for a platform specific dockerfile as well 21.119 + * and use this one in case it exists 21.120 + * @param buildDirName name of the docker build/staging directory, which will 21.121 + * be created in the jtreg's scratch folder 21.122 + * @throws Exception 21.123 + */ 21.124 + public static void 21.125 + buildJdkDockerImage(String imageName, String dockerfile, String buildDirName) 21.126 + throws Exception { 21.127 + Path buildDir = Paths.get(".", buildDirName); 21.128 + if (Files.exists(buildDir)) { 21.129 + throw new RuntimeException("The docker build directory already exists: " + buildDir); 21.130 + } 21.131 + // check for the existance of a platform specific docker file as well 21.132 + String platformSpecificDockerfile = dockerfile + "-" + Platform.getOsArch(); 21.133 + if (Files.exists(Paths.get(Utils.TEST_SRC, platformSpecificDockerfile))) { 21.134 + dockerfile = platformSpecificDockerfile; 21.135 + } 21.136 + 21.137 + Path jdkSrcDir = Paths.get(Utils.TEST_JDK); 21.138 + Path jdkDstDir = buildDir.resolve("jdk"); 21.139 + 21.140 + Files.createDirectories(jdkDstDir); 21.141 + 21.142 + // Copy JDK-under-test tree to the docker build directory. 21.143 + // This step is required for building a docker image. 21.144 + Files.walkFileTree(jdkSrcDir, new CopyFileVisitor(jdkSrcDir, jdkDstDir)); 21.145 + buildDockerImage(imageName, Paths.get(Utils.TEST_SRC, dockerfile), buildDir); 21.146 + } 21.147 + 21.148 + 21.149 + /** 21.150 + * Build a docker image based on given docker file and docker build directory. 21.151 + * 21.152 + * @param imageName name of the image to be created, including version tag 21.153 + * @param dockerfile path to the Dockerfile to be used for building the docker 21.154 + * image. The specified dockerfile will be copied to the docker build 21.155 + * directory as 'Dockerfile' 21.156 + * @param buildDir build directory; it should already contain all the content 21.157 + * needed to build the docker image. 21.158 + * @throws Exception 21.159 + */ 21.160 + public static void 21.161 + buildDockerImage(String imageName, Path dockerfile, Path buildDir) throws Exception { 21.162 + // Copy docker file to the build dir 21.163 + Files.copy(dockerfile, buildDir.resolve("Dockerfile")); 21.164 + 21.165 + // Build the docker 21.166 + execute("docker", "build", "--no-cache", "--tag", imageName, buildDir.toString()) 21.167 + .shouldHaveExitValue(0) 21.168 + .shouldContain("Successfully built"); 21.169 + } 21.170 + 21.171 + 21.172 + /** 21.173 + * Run Java inside the docker image with specified parameters and options. 21.174 + * 21.175 + * @param DockerRunOptions optins for running docker 21.176 + * 21.177 + * @return output of the run command 21.178 + * @throws Exception 21.179 + */ 21.180 + public static OutputAnalyzer dockerRunJava(DockerRunOptions opts) throws Exception { 21.181 + ArrayList<String> cmd = new ArrayList<>(); 21.182 + 21.183 + cmd.add("docker"); 21.184 + cmd.add("run"); 21.185 + if (opts.tty) 21.186 + cmd.add("--tty=true"); 21.187 + if (opts.removeContainerAfterUse) 21.188 + cmd.add("--rm"); 21.189 + 21.190 + cmd.addAll(opts.dockerOpts); 21.191 + cmd.add(opts.imageNameAndTag); 21.192 + cmd.add(opts.command); 21.193 + 21.194 + cmd.addAll(opts.javaOpts); 21.195 + if (opts.appendTestJavaOptions) { 21.196 + Collections.addAll(cmd, Utils.getTestJavaOpts()); 21.197 + } 21.198 + 21.199 + cmd.add(opts.classToRun); 21.200 + cmd.addAll(opts.classParams); 21.201 + return execute(cmd); 21.202 + } 21.203 + 21.204 + 21.205 + /** 21.206 + * Remove docker image 21.207 + * 21.208 + * @param DockerRunOptions optins for running docker 21.209 + * @return output of the command 21.210 + * @throws Exception 21.211 + */ 21.212 + public static OutputAnalyzer removeDockerImage(String imageNameAndTag) throws Exception { 21.213 + return execute("docker", "rmi", "--force", imageNameAndTag); 21.214 + } 21.215 + 21.216 + 21.217 + 21.218 + /** 21.219 + * Convenience method - express command as sequence of strings 21.220 + * 21.221 + * @param command to execute 21.222 + * @return The output from the process 21.223 + * @throws Exception 21.224 + */ 21.225 + public static OutputAnalyzer execute(List<String> command) throws Exception { 21.226 + return execute(command.toArray(new String[command.size()])); 21.227 + } 21.228 + 21.229 + 21.230 + /** 21.231 + * Execute a specified command in a process, report diagnostic info. 21.232 + * 21.233 + * @param command to be executed 21.234 + * @return The output from the process 21.235 + * @throws Exception 21.236 + */ 21.237 + public static OutputAnalyzer execute(String... command) throws Exception { 21.238 + 21.239 + ProcessBuilder pb = new ProcessBuilder(command); 21.240 + System.out.println("[COMMAND]\n" + Utils.getCommandLine(pb)); 21.241 + 21.242 + long started = System.currentTimeMillis(); 21.243 + OutputAnalyzer output = new OutputAnalyzer(pb.start()); 21.244 + 21.245 + System.out.println("[ELAPSED: " + (System.currentTimeMillis() - started) + " ms]"); 21.246 + System.out.println("[STDERR]\n" + output.getStderr()); 21.247 + System.out.println("[STDOUT]\n" + output.getStdout()); 21.248 + 21.249 + return output; 21.250 + } 21.251 + 21.252 + 21.253 + private static class CopyFileVisitor extends SimpleFileVisitor<Path> { 21.254 + private final Path src; 21.255 + private final Path dst; 21.256 + 21.257 + public CopyFileVisitor(Path src, Path dst) { 21.258 + this.src = src; 21.259 + this.dst = dst; 21.260 + } 21.261 + 21.262 + 21.263 + @Override 21.264 + public FileVisitResult preVisitDirectory(Path file, 21.265 + BasicFileAttributes attrs) throws IOException { 21.266 + Path dstDir = dst.resolve(src.relativize(file)); 21.267 + if (!dstDir.toFile().exists()) { 21.268 + Files.createDirectories(dstDir); 21.269 + } 21.270 + return FileVisitResult.CONTINUE; 21.271 + } 21.272 + 21.273 + 21.274 + @Override 21.275 + public FileVisitResult visitFile(Path file, 21.276 + BasicFileAttributes attrs) throws IOException { 21.277 + if (!file.toFile().isFile()) { 21.278 + return FileVisitResult.CONTINUE; 21.279 + } 21.280 + Path dstFile = dst.resolve(src.relativize(file)); 21.281 + Files.copy(file, dstFile, StandardCopyOption.COPY_ATTRIBUTES); 21.282 + return FileVisitResult.CONTINUE; 21.283 + } 21.284 + } 21.285 +}
22.1 --- a/test/testlibrary/com/oracle/java/testlibrary/Platform.java Fri Aug 10 12:27:32 2018 +0100 22.2 +++ b/test/testlibrary/com/oracle/java/testlibrary/Platform.java Sat Aug 18 12:58:53 2018 +0100 22.3 @@ -1,5 +1,5 @@ 22.4 /* 22.5 - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. 22.6 + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. 22.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 22.8 * 22.9 * This code is free software; you can redistribute it and/or modify it 22.10 @@ -32,7 +32,7 @@ 22.11 private static final String dataModel = System.getProperty("sun.arch.data.model"); 22.12 private static final String vmVersion = System.getProperty("java.vm.version"); 22.13 private static final String osArch = System.getProperty("os.arch"); 22.14 - private static final String vmName = System.getProperty("java.vm.name"); 22.15 + public static final String vmName = System.getProperty("java.vm.name"); 22.16 private static final String userName = System.getProperty("user.name"); 22.17 22.18 public static boolean isClient() {
23.1 --- a/test/testlibrary/com/oracle/java/testlibrary/Utils.java Fri Aug 10 12:27:32 2018 +0100 23.2 +++ b/test/testlibrary/com/oracle/java/testlibrary/Utils.java Sat Aug 18 12:58:53 2018 +0100 23.3 @@ -1,5 +1,5 @@ 23.4 /* 23.5 - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. 23.6 + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. 23.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 23.8 * 23.9 * This code is free software; you can redistribute it and/or modify it 23.10 @@ -61,6 +61,15 @@ 23.11 */ 23.12 public static final String JAVA_OPTIONS = System.getProperty("test.java.opts", "").trim(); 23.13 23.14 + public static final String TEST_JDK = System.getProperty("test.jdk"); 23.15 + 23.16 + public static final String COMPILE_JDK= System.getProperty("compile.jdk", TEST_JDK); 23.17 + 23.18 + public static final String TEST_SRC = System.getProperty("test.src", "").trim(); 23.19 + 23.20 + public static final String TEST_CLASSES = System.getProperty("test.classes", "."); 23.21 + 23.22 + 23.23 private static Unsafe unsafe = null; 23.24 23.25 /**
24.1 --- a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Fri Aug 10 12:27:32 2018 +0100 24.2 +++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Sat Aug 18 12:58:53 2018 +0100 24.3 @@ -238,4 +238,9 @@ 24.4 24.5 // Returns true on linux if library has the noexecstack flag set. 24.6 public native boolean checkLibSpecifiesNoexecstack(String libfilename); 24.7 + 24.8 + // Container testing 24.9 + public native boolean isContainerized(); 24.10 + public native void printOsInfo(); 24.11 + 24.12 }