8189762: [TESTBUG] Create tests for JDK-8146115 container awareness and resource configuration
authormseledtsov
Thu, 16 Nov 2017 19:01:01 -0800
changeset 47908 d6d00f785f39
parent 47907 f5581b073aff
child 47909 da4fb7d2f917
8189762: [TESTBUG] Create tests for JDK-8146115 container awareness and resource configuration Summary: Created tests for the feature Reviewed-by: bobv, iignatyev
src/hotspot/share/prims/whitebox.cpp
test/hotspot/jtreg/TEST.groups
test/hotspot/jtreg/runtime/containers/docker/AttemptOOM.java
test/hotspot/jtreg/runtime/containers/docker/CPUSetsReader.java
test/hotspot/jtreg/runtime/containers/docker/CheckContainerized.java
test/hotspot/jtreg/runtime/containers/docker/Common.java
test/hotspot/jtreg/runtime/containers/docker/DockerBasicTest.java
test/hotspot/jtreg/runtime/containers/docker/PrintContainerInfo.java
test/hotspot/jtreg/runtime/containers/docker/TEST.properties
test/hotspot/jtreg/runtime/containers/docker/TestCPUAwareness.java
test/hotspot/jtreg/runtime/containers/docker/TestCPUSets.java
test/hotspot/jtreg/runtime/containers/docker/TestMemoryAwareness.java
test/hotspot/jtreg/runtime/containers/docker/TestMisc.java
test/lib/sun/hotspot/WhiteBox.java
--- a/src/hotspot/share/prims/whitebox.cpp	Thu Nov 16 18:34:33 2017 -0500
+++ b/src/hotspot/share/prims/whitebox.cpp	Thu Nov 16 19:01:01 2017 -0800
@@ -76,6 +76,7 @@
 
 #ifdef LINUX
 #include "utilities/elfFile.hpp"
+#include "osContainer_linux.hpp"
 #endif
 
 #define SIZE_T_MAX_VALUE ((size_t) -1)
@@ -1879,6 +1880,16 @@
   return ret;
 WB_END
 
+WB_ENTRY(jboolean, WB_IsContainerized(JNIEnv* env, jobject o))
+  LINUX_ONLY(return OSContainer::is_containerized();)
+  return false;
+WB_END
+
+WB_ENTRY(void, WB_PrintOsInfo(JNIEnv* env, jobject o))
+  os::print_os_info(tty);
+WB_END
+
+
 #define CC (char*)
 
 static JNINativeMethod methods[] = {
@@ -2087,8 +2098,11 @@
                                                       (void*)&WB_RequestConcurrentGCPhase},
   {CC"checkLibSpecifiesNoexecstack", CC"(Ljava/lang/String;)Z",
                                                       (void*)&WB_CheckLibSpecifiesNoexecstack},
+  {CC"isContainerized",           CC"()Z",            (void*)&WB_IsContainerized },
+  {CC"printOsInfo",               CC"()V",            (void*)&WB_PrintOsInfo },
 };
 
+
 #undef CC
 
 JVM_ENTRY(void, JVM_RegisterWhiteBoxMethods(JNIEnv* env, jclass wbclass))
--- a/test/hotspot/jtreg/TEST.groups	Thu Nov 16 18:34:33 2017 -0500
+++ b/test/hotspot/jtreg/TEST.groups	Thu Nov 16 19:01:01 2017 -0800
@@ -187,6 +187,7 @@
  -runtime/Thread/CancellableThreadTest.java \
  -runtime/Thread/TestThreadDumpMonitorContention.java \
  -runtime/Unsafe/RangeCheck.java \
+ -runtime/containers/ \
   sanity/ \
   testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java
 
@@ -216,6 +217,7 @@
   serviceability/ \
  -runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java \
  -runtime/Thread/TestThreadDumpMonitorContention.java \
+ -runtime/containers/ \
  -:hotspot_tier1_runtime \
  -:hotspot_tier1_serviceability \
  -:hotspot_tier2_runtime_platform_agnostic
@@ -227,6 +229,7 @@
 hotspot_tier3_runtime = \
   runtime/ \
   serviceability/ \
+ -runtime/containers/ \
  -:hotspot_tier1_runtime \
  -:hotspot_tier1_serviceability \
  -:hotspot_tier2_runtime_platform_agnostic \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/containers/docker/AttemptOOM.java	Thu Nov 16 19:01:01 2017 -0800
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+public class AttemptOOM {
+    private static MyObj[] data;
+
+    public static void main(String[] args) throws Exception {
+        System.out.println("Entering AttemptOOM main");
+
+        // each MyObj will allocate 1024 byte array
+        int sizeInMb = Integer.parseInt(args[0]);
+        data = new MyObj[sizeInMb*1024];
+
+        System.out.println("data.length = " + data.length);
+
+        for (int i=0; i < data.length; i++) {
+            data[i] = new MyObj(1024);
+        }
+
+        System.out.println("AttemptOOM allocation successful");
+    }
+
+    private static class MyObj {
+        private byte[] myData;
+        MyObj(int size) {
+            myData = new byte[size];
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/containers/docker/CPUSetsReader.java	Thu Nov 16 19:01:01 2017 -0800
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.io.FileReader;
+import java.util.ArrayList;
+import java.util.Optional;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import jdk.test.lib.Asserts;
+
+
+// A simple CPU sets reader and parser
+public class CPUSetsReader {
+    public static String PROC_SELF_STATUS_PATH="/proc/self/status";
+
+    // Test the parser
+    public static void test() {
+        assertParse("0-7", "0,1,2,3,4,5,6,7");
+        assertParse("1,3,6", "1,3,6");
+        assertParse("0,2-4,6,10-11", "0,2,3,4,6,10,11");
+        assertParse("0", "0");
+    }
+
+
+    private static void assertParse(String cpuSet, String expectedResult) {
+        Asserts.assertEquals(listToString(parseCpuSet(cpuSet)), expectedResult);
+    }
+
+
+    public static String readFromProcStatus(String setType) {
+        String path = PROC_SELF_STATUS_PATH;
+        Optional<String> o = Optional.empty();
+
+        System.out.println("readFromProcStatus() entering for: " + setType);
+
+        try (Stream<String> stream = Files.lines(Paths.get(path))) {
+            o = stream
+                .filter(line -> line.contains(setType))
+                .findFirst();
+        } catch (IOException e) {
+            return null;
+        }
+
+        if (!o.isPresent()) {
+            return null;    // entry not found
+        }
+
+        String[] parts = o.get().replaceAll("\\s","").split(":");
+
+        // Should be 2 parts, before and after ":"
+        Asserts.assertEquals(parts.length, 2);
+
+        String result = parts[1];
+        System.out.println("readFromProcStatus() returning: " + result);
+        return result;
+    }
+
+
+    public static List<Integer> parseCpuSet(String value) {
+        ArrayList<Integer> result = new ArrayList<Integer>();
+
+        try {
+            String[] commaSeparated = value.split(",");
+
+            for (String item : commaSeparated) {
+                if (item.contains("-")) {
+                    addRange(result, item);
+                } else {
+                    result.add(Integer.parseInt(item));
+                }
+            }
+        } catch (Exception e) {
+            System.err.println("Exception in getMaxCpuSets(): " + e);
+            return null;
+        }
+
+        return result;
+    }
+
+
+    private static void addRange(ArrayList<Integer> list, String s) {
+        String[] range = s.split("-");
+        if ( range.length != 2 ) {
+            throw new RuntimeException("Range should only contain two items, but contains "
+                                       + range.length + " items");
+        }
+
+        int min = Integer.parseInt(range[0]);
+        int max = Integer.parseInt(range[1]);
+
+        if (min >= max) {
+            String msg = String.format("min is greater or equals to max, min = %d, max = %d",
+                                       min, max);
+            throw new RuntimeException(msg);
+        }
+
+        for (int i = min; i <= max; i++) {
+            list.add(i);
+        }
+    }
+
+
+    // Convert list of integers to string with comma-separated values
+    public static String listToString(List<Integer> list) {
+        return listToString(list, Integer.MAX_VALUE);
+    }
+
+    // Convert list of integers to a string with comma-separated values;
+    // include up to maxCount.
+    public static String listToString(List<Integer> list, int maxCount) {
+        return list.stream()
+            .limit(maxCount)
+            .map(Object::toString)
+            .collect(Collectors.joining(","));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/containers/docker/CheckContainerized.java	Thu Nov 16 19:01:01 2017 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import sun.hotspot.WhiteBox;
+
+public class CheckContainerized {
+    public static String OUTSIDE_OF_CONTAINER =
+        "CheckContainerized: Running outside of a container";
+    public static String INSIDE_A_CONTAINER =
+        "CheckContainerized: Running inside a container";
+
+    public static void main(String[] args) {
+        System.out.println("CheckContainerized: Entering");
+        WhiteBox wb = WhiteBox.getWhiteBox();
+
+        if (wb.isContainerized()) {
+            System.out.println(INSIDE_A_CONTAINER);
+
+        } else {
+            System.out.println(OUTSIDE_OF_CONTAINER);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/containers/docker/Common.java	Thu Nov 16 19:01:01 2017 -0800
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * Methods and definitions common to docker tests container in this directory
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import jdk.test.lib.containers.docker.DockerRunOptions;
+import jdk.test.lib.containers.docker.DockerTestUtils;
+import jdk.test.lib.Utils;
+import jdk.test.lib.process.OutputAnalyzer;
+
+
+public class Common {
+    public static final String imageNameAndTag = "jdk-internal:test";
+
+    public static String imageName(String suffix) {
+        return imageNameAndTag + "-" + suffix;
+    }
+
+
+    public static void prepareWhiteBox() throws Exception {
+        Files.copy(Paths.get(ClassFileInstaller.getJarPath("whitebox.jar")),
+                   Paths.get(Utils.TEST_CLASSES, "whitebox.jar"));
+    }
+
+
+    // create simple commonly used options
+    public static DockerRunOptions newOpts(String imageNameAndTag) {
+        return new DockerRunOptions(imageNameAndTag, "/jdk/bin/java", "-version")
+            .addJavaOpts("-Xlog:os+container=trace");
+    }
+
+
+    // create commonly used options with class to be launched inside container
+    public static DockerRunOptions newOpts(String imageNameAndTag, String testClass) {
+        DockerRunOptions opts =
+            new DockerRunOptions(imageNameAndTag, "/jdk/bin/java", testClass);
+        opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/");
+        opts.addJavaOpts("-Xlog:os+container=trace", "-cp", "/test-classes/");
+        return opts;
+    }
+
+
+    public static DockerRunOptions addWhiteBoxOpts(DockerRunOptions opts) {
+        opts.addJavaOpts("-Xbootclasspath/a:/test-classes/whitebox.jar",
+                         "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI");
+        return opts;
+    }
+
+
+    // most common type of run and checks
+    public static OutputAnalyzer run(DockerRunOptions opts) throws Exception {
+        return DockerTestUtils.dockerRunJava(opts)
+            .shouldHaveExitValue(0).shouldContain("Initializing Container Support");
+    }
+
+
+    // log beginning of a test case
+    public static void logNewTestCase(String msg) {
+        System.out.println("========== NEW TEST CASE:      " + msg);
+    }
+
+}
--- a/test/hotspot/jtreg/runtime/containers/docker/DockerBasicTest.java	Thu Nov 16 18:34:33 2017 -0500
+++ b/test/hotspot/jtreg/runtime/containers/docker/DockerBasicTest.java	Thu Nov 16 19:01:01 2017 -0800
@@ -25,7 +25,7 @@
 /*
  * @test
  * @summary Basic (sanity) test for JDK-under-test inside a docker image.
- * @requires (docker.support)
+ * @requires docker.support
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
  *          java.management
@@ -62,8 +62,10 @@
 
 
     private static void testJavaVersion() throws Exception {
-        DockerTestUtils.dockerRunJava(
-            new DockerRunOptions(imageNameAndTag, "/jdk/bin/java", "-version"))
+        DockerRunOptions opts =
+            new DockerRunOptions(imageNameAndTag, "/jdk/bin/java", "-version");
+
+        DockerTestUtils.dockerRunJava(opts)
             .shouldHaveExitValue(0)
             .shouldContain(Platform.vmName);
     }
@@ -79,5 +81,4 @@
             .shouldHaveExitValue(0)
             .shouldContain("Hello Docker");
     }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/containers/docker/PrintContainerInfo.java	Thu Nov 16 19:01:01 2017 -0800
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import sun.hotspot.WhiteBox;
+
+public class PrintContainerInfo {
+
+    public static void main(String[] args) {
+        System.out.println("PrintContainerInfo: Entering");
+        WhiteBox wb = WhiteBox.getWhiteBox();
+
+        wb.printOsInfo();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/containers/docker/TEST.properties	Thu Nov 16 19:01:01 2017 -0800
@@ -0,0 +1,1 @@
+exclusiveAccess.dirs=.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/containers/docker/TestCPUAwareness.java	Thu Nov 16 19:01:01 2017 -0800
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * @test
+ * @summary Test JVM's CPU resource awareness when running inside docker container
+ * @requires docker.support
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ *          jdk.jartool/sun.tools.jar
+ * @build Common
+ * @run driver TestCPUAwareness
+ */
+import jdk.test.lib.containers.docker.DockerRunOptions;
+import jdk.test.lib.containers.docker.DockerTestUtils;
+
+
+public class TestCPUAwareness {
+    private static final String imageName = Common.imageName("cpu");
+
+    public static void main(String[] args) throws Exception {
+        if (!DockerTestUtils.canTestDocker()) {
+            return;
+        }
+
+        int availableCPUs = Runtime.getRuntime().availableProcessors();
+        System.out.println("Test Environment: detected availableCPUs = " + availableCPUs);
+        DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker");
+
+        try {
+            // cpuset, period, shares, expected Active Processor Count
+            testAPCCombo("0", 200*1000, 100*1000,   4*1024, 1);
+            testAPCCombo("0,1", 200*1000, 100*1000, 4*1024, 2);
+            testAPCCombo("0,1", 200*1000, 100*1000, 1*1024, 2);
+
+            testCpuShares(256, 1);
+            testCpuShares(2048, 2);
+            testCpuShares(4096, 4);
+
+            // leave one CPU for system and tools, otherwise this test may be unstable
+            int maxNrOfAvailableCpus =  availableCPUs - 1;
+            for (int i=1; i < maxNrOfAvailableCpus; i = i * 2) {
+                testCpus(i, i);
+            }
+
+            // If ActiveProcessorCount is set, the VM should use it, regardless of other
+            // container settings, host settings or available CPUs on the host.
+            testActiveProcessorCount(1, 1);
+            testActiveProcessorCount(2, 2);
+
+            testCpuQuotaAndPeriod(50*1000, 100*1000);
+            testCpuQuotaAndPeriod(100*1000, 100*1000);
+            testCpuQuotaAndPeriod(150*1000, 100*1000);
+
+        } finally {
+            DockerTestUtils.removeDockerImage(imageName);
+        }
+    }
+
+
+    private static void testActiveProcessorCount(int valueToSet, int expectedValue) throws Exception {
+        Common.logNewTestCase("Test ActiveProcessorCount: valueToSet = " + valueToSet);
+
+        DockerRunOptions opts = Common.newOpts(imageName)
+            .addJavaOpts("-XX:ActiveProcessorCount=" + valueToSet, "-Xlog:os=trace");
+        Common.run(opts)
+            .shouldMatch("active processor count set by user.*" + expectedValue);
+    }
+
+
+    private static void testCpus(int valueToSet, int expectedTraceValue) throws Exception {
+        Common.logNewTestCase("test cpus: " + valueToSet);
+        DockerRunOptions opts = Common.newOpts(imageName)
+            .addDockerOpts("--cpus", "" + valueToSet);
+        Common.run(opts)
+            .shouldMatch("active_processor_count.*" + expectedTraceValue);
+    }
+
+
+    private static void testCpuQuotaAndPeriod(int quota, int period)
+        throws Exception {
+        Common.logNewTestCase("test cpu quota and period: ");
+        System.out.println("quota = " + quota);
+        System.out.println("period = " + period);
+
+        int expectedAPC = (int) Math.ceil((float) quota / (float) period);
+        System.out.println("expectedAPC = " + expectedAPC);
+
+        DockerRunOptions opts = Common.newOpts(imageName)
+            .addDockerOpts("--cpu-period=" + period)
+            .addDockerOpts("--cpu-quota=" + quota);
+
+        Common.run(opts)
+            .shouldMatch("CPU Period is.*" + period)
+            .shouldMatch("CPU Quota is.*" + quota)
+            .shouldMatch("active_processor_count.*" + expectedAPC);
+    }
+
+
+    // Test correctess of automatically selected active processor cound
+    private static void testAPCCombo(String cpuset, int quota, int period, int shares,
+                                         int expectedAPC) throws Exception {
+        Common.logNewTestCase("test APC Combo");
+        System.out.println("cpuset = " + cpuset);
+        System.out.println("quota = " + quota);
+        System.out.println("period = " + period);
+        System.out.println("shares = " + period);
+        System.out.println("expectedAPC = " + expectedAPC);
+
+        DockerRunOptions opts = Common.newOpts(imageName)
+            .addDockerOpts("--cpuset-cpus", "" + cpuset)
+            .addDockerOpts("--cpu-period=" + period)
+            .addDockerOpts("--cpu-quota=" + quota)
+            .addDockerOpts("--cpu-shares=" + shares);
+        Common.run(opts)
+            .shouldMatch("active_processor_count.*" + expectedAPC);
+    }
+
+
+    private static void testCpuShares(int shares, int expectedAPC) throws Exception {
+        Common.logNewTestCase("test cpu shares, shares = " + shares);
+        DockerRunOptions opts = Common.newOpts(imageName)
+            .addDockerOpts("--cpu-shares=" + shares);
+        Common.run(opts)
+            .shouldMatch("CPU Shares is.*" + shares)
+            .shouldMatch("active_processor_count.*" + expectedAPC);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/containers/docker/TestCPUSets.java	Thu Nov 16 19:01:01 2017 -0800
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * @test
+ * @summary Test JVM's awareness of cpu sets (cpus and mems)
+ * @requires docker.support
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ *          jdk.jartool/sun.tools.jar
+ * @build Common AttemptOOM CPUSetsReader sun.hotspot.WhiteBox PrintContainerInfo
+ * @run driver ClassFileInstaller -jar whitebox.jar sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run driver TestCPUSets
+ */
+import java.util.List;
+import jdk.test.lib.containers.docker.DockerRunOptions;
+import jdk.test.lib.containers.docker.DockerTestUtils;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Platform;
+import jdk.test.lib.Utils;
+import jdk.test.lib.process.OutputAnalyzer;
+
+
+public class TestCPUSets {
+    private static final String imageName = Common.imageName("cpusets");
+
+    public static void main(String[] args) throws Exception {
+        if (!DockerTestUtils.canTestDocker()) {
+            return;
+        }
+
+        Common.prepareWhiteBox();
+        DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker");
+
+        try {
+            // Sanity test the cpu sets reader and parser
+            CPUSetsReader.test();
+            testTheSet("Cpus_allowed_list");
+            testTheSet("Mems_allowed_list");
+        } finally {
+            DockerTestUtils.removeDockerImage(imageName);
+        }
+    }
+
+
+    private static void testTheSet(String setType) throws Exception {
+        String cpuSetStr = CPUSetsReader.readFromProcStatus(setType);
+
+        if (cpuSetStr == null) {
+            System.out.printf("The %s test is skipped %n", setType);
+        } else {
+            List<Integer> cpuSet = CPUSetsReader.parseCpuSet(cpuSetStr);
+
+            // Test subset of one, full subset, and half of the subset
+            testCpuSet(CPUSetsReader.listToString(cpuSet, 1));
+            if (cpuSet.size() > 1) {
+                testCpuSet(CPUSetsReader.listToString(cpuSet));
+            }
+            if (cpuSet.size() > 2) {
+                testCpuSet(CPUSetsReader.listToString(cpuSet, cpuSet.size()/2 ));
+            }
+        }
+    }
+
+
+    private static DockerRunOptions commonOpts() {
+        DockerRunOptions opts = new DockerRunOptions(imageName, "/jdk/bin/java",
+                                                     "PrintContainerInfo");
+        opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/");
+        opts.addJavaOpts("-Xlog:os+container=trace", "-cp", "/test-classes/");
+        Common.addWhiteBoxOpts(opts);
+        return opts;
+    }
+
+
+    private static void checkResult(List<String> lines, String lineMarker, String value) {
+        boolean lineMarkerFound = false;
+
+        for (String line : lines) {
+            if (line.contains(lineMarker)) {
+                lineMarkerFound = true;
+                String[] parts = line.split(":");
+                System.out.println("DEBUG: line = " + line);
+                System.out.println("DEBUG: parts.length = " + parts.length);
+
+                Asserts.assertEquals(parts.length, 2);
+                String set = parts[1].replaceAll("\\s","");
+                String actual = CPUSetsReader.listToString(CPUSetsReader.parseCpuSet(set));
+                Asserts.assertEquals(actual, value);
+                break;
+            }
+        }
+        Asserts.assertTrue(lineMarkerFound);
+    }
+
+
+    private static void testCpuSet(String value) throws Exception {
+        Common.logNewTestCase("cpusets.cpus, value = " + value);
+
+        DockerRunOptions opts = commonOpts();
+        opts.addDockerOpts("--cpuset-cpus=" + value);
+
+        List<String> lines = Common.run(opts).asLines();
+        checkResult(lines, "cpuset.cpus is:", value);
+    }
+
+    private static void testMemSet(String value) throws Exception {
+        Common.logNewTestCase("cpusets.mems, value = " + value);
+
+        DockerRunOptions opts = commonOpts();
+        opts.addDockerOpts("--cpuset-mems=" + value);
+
+        List<String> lines = Common.run(opts).asLines();
+        checkResult(lines, "cpuset.mems is:", value);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/containers/docker/TestMemoryAwareness.java	Thu Nov 16 19:01:01 2017 -0800
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * @test
+ * @summary Test JVM's memory resource awareness when running inside docker container
+ * @requires docker.support
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ *          jdk.jartool/sun.tools.jar
+ * @build Common AttemptOOM sun.hotspot.WhiteBox PrintContainerInfo
+ * @run driver ClassFileInstaller -jar whitebox.jar sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run driver TestMemoryAwareness
+ */
+import jdk.test.lib.containers.docker.DockerRunOptions;
+import jdk.test.lib.containers.docker.DockerTestUtils;
+
+
+public class TestMemoryAwareness {
+    private static final String imageName = Common.imageName("memory");
+
+    public static void main(String[] args) throws Exception {
+        if (!DockerTestUtils.canTestDocker()) {
+            return;
+        }
+
+        Common.prepareWhiteBox();
+        DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker");
+
+        try {
+            testMemoryLimit("100m", "104857600");
+            testMemoryLimit("500m", "524288000");
+            testMemoryLimit("1g", "1073741824");
+            testMemoryLimit("4g", "4294967296");
+
+            testMemorySoftLimit("500m", "524288000");
+            testMemorySoftLimit("1g", "1073741824");
+
+            // Add extra 10 Mb to allocator limit, to be sure to cause OOM
+            testOOM("256m", 256 + 10);
+
+        } finally {
+            DockerTestUtils.removeDockerImage(imageName);
+        }
+    }
+
+
+    private static void testMemoryLimit(String valueToSet, String expectedTraceValue)
+            throws Exception {
+
+        Common.logNewTestCase("memory limit: " + valueToSet);
+
+        DockerRunOptions opts = Common.newOpts(imageName)
+            .addDockerOpts("--memory", valueToSet);
+
+        Common.run(opts)
+            .shouldMatch("Memory Limit is:.*" + expectedTraceValue);
+    }
+
+
+    private static void testMemorySoftLimit(String valueToSet, String expectedTraceValue)
+            throws Exception {
+        Common.logNewTestCase("memory soft limit: " + valueToSet);
+
+        DockerRunOptions opts = Common.newOpts(imageName, "PrintContainerInfo");
+        Common.addWhiteBoxOpts(opts);
+        opts.addDockerOpts("--memory-reservation=" + valueToSet);
+
+        Common.run(opts)
+            .shouldMatch("Memory Soft Limit.*" + expectedTraceValue);
+    }
+
+
+    // provoke OOM inside the container, see how VM reacts
+    private static void testOOM(String dockerMemLimit, int sizeToAllocInMb) throws Exception {
+        Common.logNewTestCase("OOM");
+
+        DockerRunOptions opts = Common.newOpts(imageName, "AttemptOOM")
+            .addDockerOpts("--memory", dockerMemLimit, "--memory-swap", dockerMemLimit);
+        opts.classParams.add("" + sizeToAllocInMb);
+
+        DockerTestUtils.dockerRunJava(opts)
+            .shouldHaveExitValue(1)
+            .shouldContain("Entering AttemptOOM main")
+            .shouldNotContain("AttemptOOM allocation successful")
+            .shouldContain("java.lang.OutOfMemoryError");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/containers/docker/TestMisc.java	Thu Nov 16 19:01:01 2017 -0800
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * @test
+ * @summary Test miscellanous functionality related to JVM running in docker container
+ * @requires docker.support
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ *          jdk.jartool/sun.tools.jar
+ * @build Common CheckContainerized sun.hotspot.WhiteBox PrintContainerInfo
+ * @run driver ClassFileInstaller -jar whitebox.jar sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run driver TestMisc
+ */
+import jdk.test.lib.containers.docker.DockerRunOptions;
+import jdk.test.lib.containers.docker.DockerTestUtils;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+
+public class TestMisc {
+    private static final String imageName = Common.imageName("misc");
+
+    public static void main(String[] args) throws Exception {
+        if (!DockerTestUtils.canTestDocker()) {
+            return;
+        }
+
+        Common.prepareWhiteBox();
+        DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker");
+
+        try {
+            testMinusContainerSupport();
+            testIsContainerized();
+            testPrintContainerInfo();
+        } finally {
+            DockerTestUtils.removeDockerImage(imageName);
+        }
+    }
+
+
+    private static void testMinusContainerSupport() throws Exception {
+        Common.logNewTestCase("Test related flags: '-UseContainerSupport'");
+        DockerRunOptions opts = new DockerRunOptions(imageName, "/jdk/bin/java", "-version");
+        opts.addJavaOpts("-XX:-UseContainerSupport", "-Xlog:os+container=trace");
+
+        Common.run(opts)
+            .shouldContain("Container Support not enabled");
+    }
+
+
+    private static void testIsContainerized() throws Exception {
+        Common.logNewTestCase("Test is_containerized() inside a docker container");
+
+        DockerRunOptions opts = Common.newOpts(imageName, "CheckContainerized");
+        Common.addWhiteBoxOpts(opts);
+
+        Common.run(opts)
+            .shouldContain(CheckContainerized.INSIDE_A_CONTAINER);
+    }
+
+
+    private static void testPrintContainerInfo() throws Exception {
+        Common.logNewTestCase("Test print_container_info()");
+
+        DockerRunOptions opts = Common.newOpts(imageName, "PrintContainerInfo");
+        Common.addWhiteBoxOpts(opts);
+
+        checkContainerInfo(Common.run(opts));
+    }
+
+
+    private static void checkContainerInfo(OutputAnalyzer out) throws Exception {
+        String[] expectedToContain = new String[] {
+            "cpuset.cpus",
+            "cpuset.mems",
+            "CPU Shares",
+            "CPU Quota",
+            "CPU Period",
+            "OSContainer::active_processor_count",
+            "Memory Limit",
+            "Memory Soft Limit",
+            "Memory Usage",
+            "Maximum Memory Usage",
+            "memory_max_usage_in_bytes"
+        };
+
+        for (String s : expectedToContain) {
+            out.shouldContain(s);
+        }
+    }
+
+}
--- a/test/lib/sun/hotspot/WhiteBox.java	Thu Nov 16 18:34:33 2017 -0500
+++ b/test/lib/sun/hotspot/WhiteBox.java	Thu Nov 16 19:01:01 2017 -0800
@@ -536,4 +536,9 @@
 
   // Returns true on linux if library has the noexecstack flag set.
   public native boolean checkLibSpecifiesNoexecstack(String libfilename);
+
+  // Container testing
+  public native boolean isContainerized();
+  public native void printOsInfo();
+
 }