test/hotspot/jtreg/runtime/appcds/dynamicArchive/DynamicArchiveTestBase.java
branchJDK-8200758-branch
changeset 57588 dac8f245de8e
parent 57587 16c4975e9e09
parent 57586 f459f98aa30d
child 57591 6805e0ef7453
equal deleted inserted replaced
57587:16c4975e9e09 57588:dac8f245de8e
     1 /*
       
     2  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 import java.io.File;
       
    26 import jdk.test.lib.process.OutputAnalyzer;
       
    27 import jdk.test.lib.process.ProcessTools;
       
    28 import jdk.test.lib.cds.CDSOptions;
       
    29 import jdk.test.lib.cds.CDSTestUtils;
       
    30 import jdk.test.lib.cds.CDSTestUtils.Result;
       
    31 
       
    32 /**
       
    33  * Base class for test cases in test/hotspot/jtreg/runtime/appcds/dynamicArchive/
       
    34  */
       
    35 class DynamicArchiveTestBase {
       
    36     private static boolean executedIn_run = false;
       
    37 
       
    38     public static interface DynamicArchiveTest {
       
    39         public void run() throws Exception;
       
    40     }
       
    41 
       
    42     public static interface DynamicArchiveTestWithArgs {
       
    43         public void run(String args[]) throws Exception;
       
    44     }
       
    45 
       
    46 
       
    47     /*
       
    48      * Tests for dynamic archives should be written using this pattern:
       
    49      *
       
    50      * public class HelloDynamic extends DynamicArchiveTestBase {
       
    51      *     public static void main(String[] args) throws Exception {
       
    52      *        runTest(HelloDynamic::testDefaultBase); // launch one test case
       
    53      *     }
       
    54      *
       
    55      *     // the body of a test case
       
    56      *     static void testDefaultBase() throws Exception {
       
    57      *         String topArchiveName = getNewArchiveName("top");
       
    58      *         doTest(null, topArchiveName);
       
    59      *     }
       
    60      * }
       
    61      *
       
    62      * The reason for this is so that we can clean up the archive files
       
    63      * created by prior test cases. Otherwise tests with lots of
       
    64      * test cases may fill up the scratch directory.
       
    65      */
       
    66     public static void runTest(DynamicArchiveTest t) throws Exception {
       
    67         executedIn_run = true;
       
    68         try {
       
    69             TestCommon.deletePriorArchives();
       
    70             t.run();
       
    71         } finally {
       
    72             executedIn_run = false;
       
    73         }
       
    74     }
       
    75 
       
    76     public static void runTest(DynamicArchiveTestWithArgs t, String... args) throws Exception {
       
    77         executedIn_run = true;
       
    78         try {
       
    79             TestCommon.deletePriorArchives();
       
    80             t.run(args);
       
    81         } finally {
       
    82             executedIn_run = false;
       
    83         }
       
    84     }
       
    85 
       
    86     public static String getNewArchiveName() {
       
    87         return TestCommon.getNewArchiveName();
       
    88     }
       
    89     public static String getNewArchiveName(String stem) {
       
    90         return TestCommon.getNewArchiveName(stem);
       
    91     }
       
    92 
       
    93     /**
       
    94      * Execute a JVM using the base archive (given by baseArchiveName) with the command line
       
    95      * (given by cmdLineSuffix). At JVM exit, dump all eligible classes into the top archive
       
    96      * (give by topArchiveName).
       
    97      *
       
    98      * If baseArchiveName is null, use the JDK's default archive as the base archive.
       
    99      */
       
   100     public static Result dump2(String baseArchiveName, String topArchiveName, String ... cmdLineSuffix)
       
   101         throws Exception
       
   102     {
       
   103         String[] cmdLine = TestCommon.concat(
       
   104             "-XX:ArchiveClassesAtExit=" + topArchiveName);
       
   105         // to allow dynamic archive tests to be run in the "rt-non-cds-mode"
       
   106         cmdLine = TestCommon.concat(cmdLine, "-Xshare:auto");
       
   107         if (baseArchiveName != null) {
       
   108             cmdLine = TestCommon.concat(cmdLine, "-XX:SharedArchiveFile=" + baseArchiveName);
       
   109         }
       
   110         cmdLine = TestCommon.concat(cmdLine, cmdLineSuffix);
       
   111         return execProcess("dump", null, cmdLine);
       
   112     }
       
   113 
       
   114     public static Result dump2_WB(String baseArchiveName, String topArchiveName, String ... cmdLineSuffix)
       
   115         throws Exception
       
   116     {
       
   117         return dump2(baseArchiveName, topArchiveName,
       
   118                      TestCommon.concat(wbRuntimeArgs(), cmdLineSuffix));
       
   119     }
       
   120 
       
   121     /**
       
   122      * A convenience method similar to dump2, but always use the JDK's default archive
       
   123      * as the base archive.
       
   124      *
       
   125      * Most dynamicArchive/*.java test cases should be using this method instead of run2.
       
   126      */
       
   127     public static Result dump(String topArchiveName, String ... cmdLineSuffix)
       
   128         throws Exception
       
   129     {
       
   130         return dump2(null, topArchiveName, cmdLineSuffix);
       
   131     }
       
   132 
       
   133     /**
       
   134      * Dump the base archive. The JDK's default class list is used (unless otherwise specified
       
   135      * in cmdLineSuffix).
       
   136      */
       
   137     public static void dumpBaseArchive(String baseArchiveName, String ... cmdLineSuffix)
       
   138         throws Exception
       
   139     {
       
   140         CDSOptions opts = new CDSOptions();
       
   141         opts.setArchiveName(baseArchiveName);
       
   142         opts.addSuffix(cmdLineSuffix);
       
   143         opts.addSuffix("-Djava.class.path=");
       
   144         OutputAnalyzer out = CDSTestUtils.createArchive(opts);
       
   145         CDSTestUtils.checkDump(out);
       
   146     }
       
   147 
       
   148     /**
       
   149      * Same as dumpBaseArchive, but also add WhiteBox to the bootcp
       
   150      */
       
   151     public static void dumpBaseArchive_WB(String baseArchiveName, String ... cmdLineSuffix)
       
   152         throws Exception
       
   153     {
       
   154         dumpBaseArchive(baseArchiveName,
       
   155                         TestCommon.concat("-Xbootclasspath/a:" + getWhiteBoxJar(), cmdLineSuffix));
       
   156     }
       
   157 
       
   158     private static String getWhiteBoxJar() {
       
   159         String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar");
       
   160         if (!(new File(wbJar)).exists()) {
       
   161             throw new RuntimeException("Test error: your test must have " +
       
   162                                        "'@run driver ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox'");
       
   163         }
       
   164         return wbJar;
       
   165     }
       
   166 
       
   167     private static String[] wbRuntimeArgs() {
       
   168         return TestCommon.concat("-Xbootclasspath/a:" + getWhiteBoxJar(),
       
   169                                  "-XX:+UnlockDiagnosticVMOptions",
       
   170                                  "-XX:+WhiteBoxAPI");
       
   171     }
       
   172 
       
   173     /**
       
   174      * Execute a JVM using the base archive (given by baseArchiveName) and the top archive
       
   175      * (give by topArchiveName), using the command line (given by cmdLineSuffix).
       
   176      *
       
   177      * If baseArchiveName is null, use the JDK's default archive as the base archive.
       
   178      */
       
   179     public static Result run2(String baseArchiveName, String topArchiveName, String ... cmdLineSuffix)
       
   180         throws Exception {
       
   181         if (baseArchiveName == null && topArchiveName == null) {
       
   182             throw new RuntimeException("Both baseArchiveName and topArchiveName cannot be null at the same time.");
       
   183         }
       
   184         String archiveFiles = (baseArchiveName == null) ? topArchiveName :
       
   185             (topArchiveName == null) ? baseArchiveName :
       
   186             baseArchiveName + File.pathSeparator + topArchiveName;
       
   187         String[] cmdLine = TestCommon.concat(
       
   188             "-Xshare:on",
       
   189             "-XX:SharedArchiveFile=" + archiveFiles);
       
   190         cmdLine = TestCommon.concat(cmdLine, cmdLineSuffix);
       
   191         return execProcess("exec", null, cmdLine);
       
   192     }
       
   193 
       
   194     public static Result runWithRelativePath(String baseArchiveName, String topArchiveName,
       
   195                               String jarDir, String ... cmdLineSuffix)
       
   196         throws Exception {
       
   197         if (baseArchiveName == null && topArchiveName == null) {
       
   198             throw new RuntimeException("Both baseArchiveName and topArchiveName cannot be null at the same time.");
       
   199         }
       
   200         String archiveFiles = (baseArchiveName == null) ? topArchiveName :
       
   201             (topArchiveName == null) ? baseArchiveName :
       
   202             baseArchiveName + File.pathSeparator + topArchiveName;
       
   203         String[] cmdLine = TestCommon.concat(
       
   204             "-Xshare:on",
       
   205             "-XX:SharedArchiveFile=" + archiveFiles);
       
   206         cmdLine = TestCommon.concat(cmdLine, cmdLineSuffix);
       
   207         return execProcess("exec", jarDir, cmdLine);
       
   208     }
       
   209 
       
   210     public static Result run2_WB(String baseArchiveName, String topArchiveName, String ... cmdLineSuffix)
       
   211         throws Exception
       
   212     {
       
   213         return run2(baseArchiveName, topArchiveName,
       
   214                     TestCommon.concat(wbRuntimeArgs(), cmdLineSuffix));
       
   215     }
       
   216 
       
   217     /**
       
   218      * A convenience method similar to run2, but always use the JDK's default archive
       
   219      * as the base archive.
       
   220      *
       
   221      * Most dynamicArchive/*.java test cases should be using this method instead of run2.
       
   222      */
       
   223     public static Result run(String topArchiveName, String ... cmdLineSuffix)
       
   224         throws Exception
       
   225     {
       
   226         return run2(null, topArchiveName, cmdLineSuffix);
       
   227     }
       
   228 
       
   229     private static String getXshareMode(String[] cmdLine) {
       
   230         for (int i = 0; i <= cmdLine.length - 1; i++) {
       
   231             int j = cmdLine[i].indexOf("-Xshare:");
       
   232             if (j != -1) {
       
   233                 return (cmdLine[i].substring(j));
       
   234             }
       
   235         }
       
   236         return null;
       
   237    }
       
   238 
       
   239 
       
   240     private static Result execProcess(String mode, String jarDir, String[] cmdLine) throws Exception {
       
   241         if (!executedIn_run) {
       
   242             throw new Exception("Test error: dynamic archive tests must be executed via DynamicArchiveTestBase.run()");
       
   243         }
       
   244         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmdLine);
       
   245         if (jarDir != null) {
       
   246             pb.directory(new File(jarDir));
       
   247         }
       
   248         OutputAnalyzer output = TestCommon.executeAndLog(pb, mode);
       
   249         CDSOptions opts = new CDSOptions();
       
   250         String xShareMode = getXshareMode(cmdLine);
       
   251         if (xShareMode != null) {
       
   252             opts.setXShareMode(xShareMode);
       
   253         }
       
   254         return new Result(opts, output);
       
   255     }
       
   256 
       
   257     /**
       
   258      * A convenience method for dumping and running, using the default CDS archive from the
       
   259      * JDK. Both dumping and running should exit normally.
       
   260      */
       
   261     public static void dumpAndRun(String topArchiveName, String ... cmdLineSuffix) throws Exception {
       
   262         dump(topArchiveName, cmdLineSuffix).assertNormalExit();
       
   263         run(topArchiveName,  cmdLineSuffix).assertNormalExit();
       
   264     }
       
   265 }