Merge

Sat, 18 Aug 2018 12:58:53 +0100

author
aefimov
date
Sat, 18 Aug 2018 12:58:53 +0100
changeset 9525
3a4af1679351
parent 9524
36292661185e
parent 9425
b34293b7f77e
child 9526
2b0ebd23e2c4

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  }

mercurial