1 /*
   2  * Copyright (c) 2016, 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 // This is the main test class for testing transformation of related classes
  26 // in combination with CDS, to ensure these features work well together.
  27 // The relationships that can be tested using this test class are:
  28 // superclass/subclass, and interface/implementor relationships.
  29 //
  30 // The test uses combinatorial approach.
  31 // For details on test table and test cases see main() method in this class.
  32 //
  33 // This test consists of multiple classes for better flexibility and reuse,
  34 // and also relies on certain common utility code.
  35 // Here are the details on the structure of the test
  36 //
  37 // Structure of the test:
  38 // TransformRelatedClasses -- common main test driver
  39 //     The TransformRelatedClasses is invoked from test driver classes:
  40 //     TransformInterfaceAndImplementor, TransformSuperAndSubClasses
  41 //     It is responsible for preparing test artifacts (test jar, agent jar
  42 //     and the shared archive), running test cases and checking the results.
  43 // The following test classes below are launched in a sub-process with use
  44 // of shared archive:
  45 //     SuperClazz, SubClass -- super/sub class pair under test
  46 //     Interface, Implementor -- classes under test
  47 // This test will transform these classes, based on the test case data,
  48 // by changing a predefined unique string in each class.
  49 // For more details, see the test classes' code and comments.
  50 //
  51 // Other related classes:
  52 //     TestEntry - a class representing a single test case, as test entry in the table
  53 //     TransformTestCommon - common methods for transformation test cases
  54 //
  55 // Other utility/helper classes and files used in this test:
  56 //     TransformerAgent - an agent that is used when JVM-under-test is executed
  57 //         to transform specific strings inside specified classes
  58 //     TransformerAgent.mf - accompanies transformer agent
  59 //     CDSTestUtils - Test Utilities common to all CDS tests
  60 
  61 import java.io.File;
  62 import java.util.ArrayList;
  63 import jdk.test.lib.process.OutputAnalyzer;
  64 import jdk.test.lib.process.ProcessTools;
  65 
  66 
  67 public class TransformRelatedClasses {
  68     static final String archiveName = "./TransformRelatedClasses.jsa";
  69     static String agentClasses[] = {
  70         "TransformerAgent",
  71         "TransformerAgent$SimpleTransformer",
  72         "TransformUtil"
  73     };
  74 
  75     String parent;
  76     String child;
  77     String[] testClasses = new String[2];
  78     String[] testNames = new String[2];
  79     String testJar;
  80     String agentJar;
  81 
  82 
  83     private static void log(String msg) {
  84         System.out.println("TransformRelatedClasses: " + msg);
  85     }
  86 
  87 
  88     // This class is intended to test 2 parent-child relationships:
  89     // 1. Base Class (parent) and Derived Class (child)
  90     // 2. Interface (parent) and Implementor (child)
  91     //    Parameters to main(): parent, child
  92     public static void main(String args[]) throws Exception {
  93         TransformRelatedClasses test = new TransformRelatedClasses(args[0], args[1]);
  94         test.prepare();
  95 
  96         // Test Table
  97         // TestEntry:  (testCaseId, transformParent, tranformChild,
  98         //             isParentExpectedShared, isChildExpectedShared)
  99         ArrayList<TestEntry> testTable = new ArrayList<>();
 100 
 101         // base case - no tranformation - all expected to be shared
 102         testTable.add(new TestEntry(0, false, false, true, true));
 103 
 104         // transform parent only - both parent and child should not be shared
 105         testTable.add(new TestEntry(1, true, false, false, false));
 106 
 107         // transform parent and child - both parent and child should not be shared
 108         testTable.add(new TestEntry(2, true, true, false, false));
 109 
 110         // transform child only - parent should still be shared, but not child
 111         testTable.add(new TestEntry(3, false, true, true, false));
 112 
 113         // run the tests
 114         for (TestEntry entry : testTable) {
 115             test.runTest(entry);
 116         }
 117     }
 118 
 119 
 120     public TransformRelatedClasses(String parent, String child) {
 121         log("Constructor: parent = " + parent + ", child = " + child);
 122         this.parent = parent;
 123         this.child = child;
 124         testClasses[0] = parent;
 125         testClasses[1] = child;
 126         testNames[0] = parent.replace('.', '/');
 127         testNames[1] = child.replace('.', '/');
 128     }
 129 
 130 
 131     // same test jar and archive can be used for all test cases
 132     private void prepare() throws Exception {
 133         // create agent jar
 134         // Agent is the same for all test cases
 135         String pathToManifest = "../../../../testlibrary/jvmti/TransformerAgent.mf";
 136         agentJar = ClassFileInstaller.writeJar("TransformerAgent.jar",
 137                        ClassFileInstaller.Manifest.fromSourceFile(pathToManifest),
 138                                            agentClasses);
 139 
 140         // create a test jar
 141         testJar =
 142             ClassFileInstaller.writeJar(parent + "-" + child + ".jar",
 143                                            testClasses);
 144 
 145         // create an archive
 146         File classList = CDSTestUtils.makeClassList("transform-" + parent,
 147                                                     testNames);
 148         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true,
 149                                         "-Xbootclasspath/a:" + testJar,
 150                                         "-XX:+UnlockDiagnosticVMOptions",
 151                                         "-XX:ExtraSharedClassListFile=" +
 152                                         classList.getPath(),
 153                                         "-XX:SharedArchiveFile=" + archiveName,
 154                                         "-XX:+PrintSharedSpaces",
 155                                         "-Xshare:dump");
 156         OutputAnalyzer out = new OutputAnalyzer(pb.start());
 157         CDSTestUtils.checkDump(out);
 158     }
 159 
 160 
 161     private void runTest(TestEntry entry) throws Exception {
 162         log("runTest(): testCaseId = " + entry.testCaseId);
 163 
 164         // execute with archive
 165         String agentParam = "-javaagent:" + agentJar + "=" +
 166             TransformTestCommon.getAgentParams(entry, parent, child);
 167 
 168         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true,
 169                                         "-Xbootclasspath/a:" + testJar,
 170                                         "-XX:+UnlockDiagnosticVMOptions",
 171                                         "-XX:SharedArchiveFile=" + archiveName,
 172                                         "-Xlog:class+load=info",
 173                                         "-Xshare:on", "-showversion",
 174                                         agentParam, child);
 175         OutputAnalyzer out = new OutputAnalyzer(pb.start());
 176 
 177         TransformTestCommon.checkResults(entry, out, parent, child);
 178     }
 179 }