blob: 2f2aebe34f3f4020467baad160bdaa63e761817d [file] [log] [blame]
/*
* Copyright (c) 2016, 2018, 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.
*
*/
// Structure of the test:
// TransformRelatedClassesAppCDS -- common main test driver
// Invoked from test driver classes:
// TransformInterfaceAndImplementor, TransformSuperAndSubClasses.java
// prepares test artifacts, launches tests, checks results
// SuperClazz, SubClass -- classes under test
// Interface, Implementor -- classes under test
// TransformerAgent -- an agent that is used when JVM-under-test is executed
// to transform specific strings inside specified classes
// TransformerAgent.mf - accompanies transformer agent
// CustomLoaderApp -- a test "application" that is used to load
// classes-under-test (Parent, Child) via custom class loader, using
// AppCDS-v2 mechanism (unregistered custom loaders, aka FP)
// This "app" is launched in a child process by this driver with sharing on.
import java.io.File;
import java.util.ArrayList;
import jdk.test.lib.Platform;
import jdk.test.lib.process.OutputAnalyzer;
// This class is intended to test 2 parent-child relationships:
// 1. Base Class (parent) and Derived Class (child)
// 2. Interface (parent) and Implementor (child)
// Parameters to main(): parent, child
public class TransformRelatedClassesAppCDS extends TransformRelatedClasses {
private static void log(String msg, Object... args) {
String msg0 = String.format(msg, args);
System.out.println("TransformRelatedClassesAppCDS: " + msg0);
}
// Initial Test Matrix:
// (ParentTransformed = true/false, ChildTransformed = true/false) x
// (BootCDS - see open tests, AppCDS-v1, AppCDS-v2-unregistered)
// Total cases: 2 x 4 = 8
public static void main(String args[]) throws Exception {
TransformRelatedClassesAppCDS test =
new TransformRelatedClassesAppCDS(args[0], args[1]);
test.prepareAgent(agentClasses);
// Test Table
// testCaseId | transformParent | tranformChild | isParentExpectedShared | isChildExpectedShared
ArrayList<TestEntry> testTable = new ArrayList<>();
// base case - no tranformation - all expected to be shared
testTable.add(new TestEntry(0, false, false, true, true));
// transform parent only - both parent and child should not be shared
testTable.add(new TestEntry(1, true, false, false, false));
// transform parent and child - both parent and child should not be shared
testTable.add(new TestEntry(2, true, true, false, false));
// transform child only - parent should still be shared, but not child
testTable.add(new TestEntry(3, false, true, true, false));
// run the tests
test.runWithAppLoader(testTable);
test.runWithCustomLoader(testTable);
}
public TransformRelatedClassesAppCDS(String parent, String child) {
super(parent, child);
// a trick to get it compiled by jtreg
CustomLoaderApp.ping();
}
private void prepareAgent(String[] agentClasses) throws Exception {
String manifest = "../../../../testlibrary/jvmti/TransformerAgent.mf";
agentJar = ClassFileInstaller.writeJar("TransformerAgent.jar",
ClassFileInstaller.Manifest.fromSourceFile(manifest),
agentClasses);
}
private void runWithAppLoader(ArrayList<TestEntry> testTable) throws Exception {
String appJar = writeJar("app", testClasses);
// create an archive
OutputAnalyzer out = TestCommon.dump(appJar, testClasses);
TestCommon.checkDump(out);
// execute with archive
for (TestEntry entry : testTable) {
log("runTestWithAppLoader(): testCaseId = %d", entry.testCaseId);
String params = TransformTestCommon.getAgentParams(entry, parent, child);
String agentParam = String.format("-javaagent:%s=%s", agentJar, params);
TestCommon.run("-Xlog:class+load=info", "-cp", appJar,
agentParam, child)
.assertNormalExit(output -> TransformTestCommon.checkResults(entry, output, parent, child));
}
}
private String[] getCustomClassList(String loaderType, String customJar) {
String type = child + "-" + loaderType;
switch (type) {
case "SubClass-unregistered":
return new String[] {
"CustomLoaderApp",
"java/lang/Object id: 0",
parent + " id: 1 super: 0 source: " + customJar,
child + " id: 2 super: 1 source: " + customJar,
};
case "Implementor-unregistered":
return new String[] {
"CustomLoaderApp",
"java/lang/Object id: 0",
parent + " id: 1 super: 0 source: " + customJar,
child + " id: 2 super: 0 interfaces: 1 source: " + customJar,
};
default:
throw new IllegalArgumentException("getCustomClassList - wrong type: " + type);
}
}
private void runWithCustomLoader(ArrayList<TestEntry> testTable) throws Exception {
if (!Platform.areCustomLoadersSupportedForCDS()) {
log("custom loader not supported for this platform" +
" - skipping test case for custom loader");
return;
}
String appClasses[] = {
"CustomLoaderApp",
};
String customClasses[] = { parent, child };
// create jar files: appJar, customJar (for custom loaders to load classes from)
String appJar = writeJar("custldr-app", appClasses);
String customJar = writeJar("custldr-custom", customClasses);
for (TestEntry entry : testTable) {
log("runTestWithCustomLoader(): testCaseId = %d", entry.testCaseId);
// unregistered (aka FP) case
String[] classList = getCustomClassList("unregistered",customJar);
execAndCheckWithCustomLoader(entry, "unregistered", classList,
appJar, agentJar, customJar);
}
}
private void
execAndCheckWithCustomLoader(TestEntry entry, String loaderType,
String[] classList, String appJar,
String agentJar, String customJar)
throws Exception {
OutputAnalyzer out = TestCommon.dump(appJar, classList);
TestCommon.checkDump(out);
String agentParam = "-javaagent:" + agentJar + "=" +
TransformTestCommon.getAgentParams(entry, parent, child);
TestCommon.run("-Xlog:class+load=info",
"-cp", appJar,
"--add-opens=java.base/java.security=ALL-UNNAMED",
agentParam,
"CustomLoaderApp",
customJar, loaderType, child)
.assertNormalExit(output -> TransformTestCommon.checkResults(entry, output, parent, child));
}
private String writeJar(String type, String[] classes)
throws Exception {
String jarName = String.format("%s-%s.jar", child, type);
return ClassFileInstaller.writeJar(jarName, classes);
}
}