test/hotspot/jtreg/runtime/appcds/dynamicArchive/DynamicArchiveTestBase.java
changeset 54927 1512d88b24c6
child 55524 b279ae9843b8
equal deleted inserted replaced
54926:d4e7ccaf1445 54927:1512d88b24c6
       
     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", 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", cmdLine);
       
   192     }
       
   193 
       
   194     public static Result run2_WB(String baseArchiveName, String topArchiveName, String ... cmdLineSuffix)
       
   195         throws Exception
       
   196     {
       
   197         return run2(baseArchiveName, topArchiveName,
       
   198                     TestCommon.concat(wbRuntimeArgs(), cmdLineSuffix));
       
   199     }
       
   200 
       
   201     /**
       
   202      * A convenience method similar to run2, but always use the JDK's default archive
       
   203      * as the base archive.
       
   204      *
       
   205      * Most dynamicArchive/*.java test cases should be using this method instead of run2.
       
   206      */
       
   207     public static Result run(String topArchiveName, String ... cmdLineSuffix)
       
   208         throws Exception
       
   209     {
       
   210         return run2(null, topArchiveName, cmdLineSuffix);
       
   211     }
       
   212 
       
   213     private static String getXshareMode(String[] cmdLine) {
       
   214         for (int i = 0; i <= cmdLine.length - 1; i++) {
       
   215             int j = cmdLine[i].indexOf("-Xshare:");
       
   216             if (j != -1) {
       
   217                 return (cmdLine[i].substring(j));
       
   218             }
       
   219         }
       
   220         return null;
       
   221    }
       
   222 
       
   223 
       
   224     private static Result execProcess(String mode, String[] cmdLine) throws Exception {
       
   225         if (!executedIn_run) {
       
   226             throw new Exception("Test error: dynamic archive tests must be executed via DynamicArchiveTestBase.run()");
       
   227         }
       
   228         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmdLine);
       
   229         OutputAnalyzer output = TestCommon.executeAndLog(pb, mode);
       
   230         CDSOptions opts = new CDSOptions();
       
   231         String xShareMode = getXshareMode(cmdLine);
       
   232         if (xShareMode != null) {
       
   233             opts.setXShareMode(xShareMode);
       
   234         }
       
   235         return new Result(opts, output);
       
   236     }
       
   237 
       
   238     /**
       
   239      * A convenience method for dumping and running, using the default CDS archive from the
       
   240      * JDK. Both dumping and running should exit normally.
       
   241      */
       
   242     public static void dumpAndRun(String topArchiveName, String ... cmdLineSuffix) throws Exception {
       
   243         dump(topArchiveName, cmdLineSuffix).assertNormalExit();
       
   244         run(topArchiveName,  cmdLineSuffix).assertNormalExit();
       
   245     }
       
   246 }