Add structural redef tests to CTS
This adds structural redefinition and other JVMTI run-tests to CTS
where possible.
Test: atest -bit --test-mapping cts/hostsidetests/jvmti/TEST_MAPPING
Bug: 134162467
Change-Id: If8e36ea8d228253928cb9b9f6a35a284250641e9
diff --git a/test/1981-structural-redef-private-method-handles/expected_no_mh.txt b/test/1981-structural-redef-private-method-handles/expected_no_mh.txt
new file mode 100644
index 0000000..183fcc8
--- /dev/null
+++ b/test/1981-structural-redef-private-method-handles/expected_no_mh.txt
@@ -0,0 +1,21 @@
+Initial: class art.Test1981$Transform[FOO: value of <FOO FIELD>, BAR: value of <BAR FIELD>]
+Reading field FOO using (ID: 0) MethodHandle()Object = (ID: 1) value of <FOO FIELD>
+Reading field BAR using (ID: 2) MethodHandle()Object = (ID: 3) value of <BAR FIELD>
+Redefining Transform class
+Post redefinition : class art.Test1981$Transform[FOO: value of <FOO FIELD>, BAR: value of <BAR FIELD>, BAZ: null]
+Reading field FOO using (ID: 0) MethodHandle()Object = (ID: 1) value of <FOO FIELD>
+Reading field BAR using (ID: 2) MethodHandle()Object = (ID: 3) value of <BAR FIELD>
+Reading new field BAZ using (ID: 4) MethodHandle()Object = (ID: 5) <NULL>
+Reading new field FOO using (ID: 6) MethodHandle()Object = (ID: 1) value of <FOO FIELD>
+Reading new field BAR using (ID: 7) MethodHandle()Object = (ID: 3) value of <BAR FIELD>
+Setting BAZ to (ID: 8) foo with new mh.
+Post set with new mh: class art.Test1981$Transform[FOO: value of <FOO FIELD>, BAR: value of <BAR FIELD>, BAZ: foo]
+Setting FOO to (ID: 9) class art.Test1981$Transform with old mh.
+Post set with old mh: class art.Test1981$Transform[FOO: class art.Test1981$Transform, BAR: value of <BAR FIELD>, BAZ: foo]
+Using mh to call new private method.
+Post reinit with mh: class art.Test1981$Transform[FOO: class art.Test1981$Transform, BAR: value of <BAR FIELD>, BAZ: 42]
+Reading field FOO using (ID: 0) MethodHandle()Object = (ID: 9) class art.Test1981$Transform
+Reading field BAR using (ID: 2) MethodHandle()Object = (ID: 3) value of <BAR FIELD>
+Reading new field BAZ using (ID: 4) MethodHandle()Object = (ID: 10) 42
+Reading new field FOO using (ID: 6) MethodHandle()Object = (ID: 9) class art.Test1981$Transform
+Reading new field BAR using (ID: 7) MethodHandle()Object = (ID: 3) value of <BAR FIELD>
diff --git a/test/1981-structural-redef-private-method-handles/src/Main.java b/test/1981-structural-redef-private-method-handles/src/Main.java
index 9d6f74d..7c546fd 100644
--- a/test/1981-structural-redef-private-method-handles/src/Main.java
+++ b/test/1981-structural-redef-private-method-handles/src/Main.java
@@ -16,6 +16,6 @@
public class Main {
public static void main(String[] args) throws Exception {
- art.Test1981.run();
+ art.Test1981.run(new art.Test1981_Varhandles());
}
}
diff --git a/test/1981-structural-redef-private-method-handles/src/art/Test1981.java b/test/1981-structural-redef-private-method-handles/src/art/Test1981.java
index 2c19d8b..ac8a019 100644
--- a/test/1981-structural-redef-private-method-handles/src/art/Test1981.java
+++ b/test/1981-structural-redef-private-method-handles/src/art/Test1981.java
@@ -22,9 +22,38 @@
import java.util.*;
public class Test1981 {
+ // Allow us to hide the var-handle portions when running this on CTS.
+ public interface VarHandler {
+ public boolean doVarHandleTests();
+
+ public default Object findStaticVarHandle(MethodHandles.Lookup l, Class c, String n, Class t)
+ throws Throwable {
+ return null;
+ }
+
+ public default Object get(Object vh) throws Throwable {
+ throw new Error("Illegal call!");
+ }
+
+ public default void set(Object vh, Object v) throws Throwable {
+ throw new Error("Illegal call!");
+ }
+ public default boolean instanceofVarHandle(Object v) {
+ return false;
+ }
+ public default Object getVarTypeName(Object v) {
+ throw new Error("Illegal call!");
+ }
+ }
+
+ // CTS Entrypoint.
public static void run() throws Exception {
+ run(() -> false);
+ }
+
+ public static void run(VarHandler varhandle_portion) throws Exception {
Redefinition.setTestConfiguration(Redefinition.Config.COMMON_REDEFINE);
- doTest();
+ doTest(varhandle_portion);
}
private static final boolean PRINT_NONDETERMINISTIC = false;
@@ -32,7 +61,7 @@
public static WeakHashMap<Object, Long> id_nums = new WeakHashMap<>();
public static long next_id = 0;
- public static String printGeneric(Object o) {
+ public static String printGeneric(VarHandler vh, Object o) {
Long id = id_nums.get(o);
if (id == null) {
id = Long.valueOf(next_id++);
@@ -48,10 +77,9 @@
+ ") "
+ Arrays.toString(Arrays.copyOf((byte[]) o, 10)).replace(']', ',')
+ " ...]";
- } else if (o instanceof VarHandle) {
+ } else if (vh.instanceofVarHandle(o)) {
// These don't have a good to-string. Give them one.
- VarHandle v = (VarHandle)o;
- return "(ID: " + id + ") " + o.getClass().getName() + "()->" + v.varType().getName();
+ return "(ID: " + id + ") " + o.getClass().getName() + "()->" + vh.getVarTypeName(o);
} else {
return "(ID: " + id + ") " + o.toString();
}
@@ -140,21 +168,23 @@
+ "AAEgAAAFAAAAEAIAAAMgAAAFAAAA7gIAAAEQAAADAAAABAMAAAIgAAAkAAAAGgMAAAQgAAACAAAA"
+ "WwUAAAAgAAABAAAAagUAAAMQAAACAAAAjAUAAAYgAAABAAAAnAUAAAAQAAABAAAArAUAAA==");
- public static void doTest() throws Exception {
+ public static void doTest(VarHandler vh) throws Exception {
try {
System.out.println("Initial: " + Transform.staticToString());
MethodHandles.Lookup lookup = Transform.getLookup();
- String[] names = new String[] { "FOO", "BAR", };
+ String[] names =
+ new String[] {
+ "FOO", "BAR",
+ };
MethodHandle[] handles =
new MethodHandle[] {
lookup.findStaticGetter(Transform.class, "FOO", Object.class),
lookup.findStaticGetter(Transform.class, "BAR", Object.class),
};
- VarHandle foo_handle = lookup.findStaticVarHandle(Transform.class, "FOO", Object.class);
- VarHandle[] var_handles =
- new VarHandle[] {
- foo_handle,
- lookup.findStaticVarHandle(Transform.class, "BAR", Object.class),
+ Object foo_handle = vh.findStaticVarHandle(lookup, Transform.class, "FOO", Object.class);
+ Object[] var_handles =
+ new Object[] {
+ foo_handle, vh.findStaticVarHandle(lookup, Transform.class, "BAR", Object.class),
};
for (int i = 0; i < names.length; i++) {
@@ -162,16 +192,18 @@
"Reading field "
+ names[i]
+ " using "
- + printGeneric(handles[i])
+ + printGeneric(vh, handles[i])
+ " = "
- + printGeneric(handles[i].invoke()));
- System.out.println(
- "Reading field "
- + names[i]
- + " using "
- + printGeneric(var_handles[i])
- + " = "
- + printGeneric(var_handles[i].get()));
+ + printGeneric(vh, handles[i].invoke()));
+ if (vh.doVarHandleTests()) {
+ System.out.println(
+ "Reading field "
+ + names[i]
+ + " using "
+ + printGeneric(vh, var_handles[i])
+ + " = "
+ + printGeneric(vh, vh.get(var_handles[i])));
+ }
}
MethodHandle old_field_write = lookup.findStaticSetter(Transform.class, "FOO", Object.class);
@@ -179,19 +211,22 @@
Redefinition.doCommonStructuralClassRedefinition(Transform.class, REDEFINED_DEX_BYTES);
System.out.println("Post redefinition : " + Transform.staticToString());
- String[] new_names = new String[] { "BAZ", "FOO", "BAR", };
+ String[] new_names =
+ new String[] {
+ "BAZ", "FOO", "BAR",
+ };
MethodHandle[] new_handles =
new MethodHandle[] {
lookup.findStaticGetter(Transform.class, "BAZ", Object.class),
lookup.findStaticGetter(Transform.class, "FOO", Object.class),
lookup.findStaticGetter(Transform.class, "BAR", Object.class),
};
- VarHandle baz_handle = lookup.findStaticVarHandle(Transform.class, "BAZ", Object.class);
- VarHandle[] new_var_handles =
- new VarHandle[] {
+ Object baz_handle = vh.findStaticVarHandle(lookup, Transform.class, "BAZ", Object.class);
+ Object[] new_var_handles =
+ new Object[] {
baz_handle,
- lookup.findStaticVarHandle(Transform.class, "FOO", Object.class),
- lookup.findStaticVarHandle(Transform.class, "BAR", Object.class),
+ vh.findStaticVarHandle(lookup, Transform.class, "FOO", Object.class),
+ vh.findStaticVarHandle(lookup, Transform.class, "BAR", Object.class),
};
for (int i = 0; i < names.length; i++) {
@@ -199,16 +234,18 @@
"Reading field "
+ names[i]
+ " using "
- + printGeneric(handles[i])
+ + printGeneric(vh, handles[i])
+ " = "
- + printGeneric(handles[i].invoke()));
- System.out.println(
- "Reading field "
- + names[i]
- + " using "
- + printGeneric(var_handles[i])
- + " = "
- + printGeneric(var_handles[i].get()));
+ + printGeneric(vh, handles[i].invoke()));
+ if (vh.doVarHandleTests()) {
+ System.out.println(
+ "Reading field "
+ + names[i]
+ + " using "
+ + printGeneric(vh, var_handles[i])
+ + " = "
+ + printGeneric(vh, vh.get(var_handles[i])));
+ }
}
for (int i = 0; i < new_names.length; i++) {
@@ -216,39 +253,44 @@
"Reading new field "
+ new_names[i]
+ " using "
- + printGeneric(new_handles[i])
+ + printGeneric(vh, new_handles[i])
+ " = "
- + printGeneric(new_handles[i].invoke()));
- System.out.println(
- "Reading new field "
- + new_names[i]
- + " using "
- + printGeneric(new_var_handles[i])
- + " = "
- + printGeneric(new_var_handles[i].get()));
+ + printGeneric(vh, new_handles[i].invoke()));
+ if (vh.doVarHandleTests()) {
+ System.out.println(
+ "Reading new field "
+ + new_names[i]
+ + " using "
+ + printGeneric(vh, new_var_handles[i])
+ + " = "
+ + printGeneric(vh, vh.get(new_var_handles[i])));
+ }
}
String val = "foo";
- System.out.println("Setting BAZ to " + printGeneric(val) + " with new mh.");
+ System.out.println("Setting BAZ to " + printGeneric(vh, val) + " with new mh.");
lookup.findStaticSetter(Transform.class, "BAZ", Object.class).invoke(val);
System.out.println("Post set with new mh: " + Transform.staticToString());
- System.out.println("Setting FOO to " + printGeneric(Transform.class) + " with old mh.");
+ System.out.println("Setting FOO to " + printGeneric(vh, Transform.class) + " with old mh.");
old_field_write.invoke(Transform.class);
System.out.println("Post set with old mh: " + Transform.staticToString());
- Object new_val = new Object() {
- public String toString() {
- return "new_value object";
- }
- };
- System.out.println("Setting FOO to '" + printGeneric(new_val) + "' with old varhandle.");
- foo_handle.set(new_val);
- System.out.println("Post set with new varhandle: " + Transform.staticToString());
+ Object new_val =
+ new Object() {
+ public String toString() {
+ return "new_value object";
+ }
+ };
+ if (vh.doVarHandleTests()) {
+ System.out.println("Setting FOO to '" + printGeneric(vh, new_val) + "' with old varhandle.");
+ vh.set(foo_handle, new_val);
+ System.out.println("Post set with new varhandle: " + Transform.staticToString());
- System.out.println("Setting BAZ to 'bar' with new varhandle.");
- baz_handle.set("bar");
- System.out.println("Post set with old varhandle: " + Transform.staticToString());
+ System.out.println("Setting BAZ to 'bar' with new varhandle.");
+ vh.set(baz_handle, "bar");
+ System.out.println("Post set with old varhandle: " + Transform.staticToString());
+ }
System.out.println("Using mh to call new private method.");
MethodHandle reinit =
@@ -256,38 +298,41 @@
reinit.invoke();
System.out.println("Post reinit with mh: " + Transform.staticToString());
-
for (int i = 0; i < names.length; i++) {
System.out.println(
"Reading field "
+ names[i]
+ " using "
- + printGeneric(handles[i])
+ + printGeneric(vh, handles[i])
+ " = "
- + printGeneric(handles[i].invoke()));
- System.out.println(
- "Reading field "
- + names[i]
- + " using "
- + printGeneric(var_handles[i])
- + " = "
- + printGeneric(var_handles[i].get()));
+ + printGeneric(vh, handles[i].invoke()));
+ if (vh.doVarHandleTests()) {
+ System.out.println(
+ "Reading field "
+ + names[i]
+ + " using "
+ + printGeneric(vh, var_handles[i])
+ + " = "
+ + printGeneric(vh, vh.get(var_handles[i])));
+ }
}
for (int i = 0; i < new_names.length; i++) {
System.out.println(
"Reading new field "
+ new_names[i]
+ " using "
- + printGeneric(new_handles[i])
+ + printGeneric(vh, new_handles[i])
+ " = "
- + printGeneric(new_handles[i].invoke()));
- System.out.println(
- "Reading new field "
- + new_names[i]
- + " using "
- + printGeneric(new_var_handles[i])
- + " = "
- + printGeneric(new_var_handles[i].get()));
+ + printGeneric(vh, new_handles[i].invoke()));
+ if (vh.doVarHandleTests()) {
+ System.out.println(
+ "Reading new field "
+ + new_names[i]
+ + " using "
+ + printGeneric(vh, new_var_handles[i])
+ + " = "
+ + printGeneric(vh, vh.get(new_var_handles[i])));
+ }
}
} catch (Throwable t) {
if (t instanceof Exception) {
diff --git a/test/1981-structural-redef-private-method-handles/src/art/Test1981_Varhandles.java b/test/1981-structural-redef-private-method-handles/src/art/Test1981_Varhandles.java
new file mode 100644
index 0000000..dbb63e7
--- /dev/null
+++ b/test/1981-structural-redef-private-method-handles/src/art/Test1981_Varhandles.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+import java.lang.invoke.*;
+import java.lang.ref.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+public class Test1981_Varhandles implements Test1981.VarHandler {
+ public Test1981_Varhandles() {}
+
+ public boolean doVarHandleTests() {
+ return true;
+ }
+
+ public Object findStaticVarHandle(MethodHandles.Lookup l, Class c, String n, Class t)
+ throws Throwable {
+ return l.findStaticVarHandle(c, n, t);
+ }
+
+ public Object get(Object vh) throws Throwable {
+ return ((VarHandle) vh).get();
+ }
+
+ public void set(Object vh, Object v) throws Throwable {
+ ((VarHandle) vh).set(v);
+ }
+ public boolean instanceofVarHandle(Object v) {
+ return v instanceof VarHandle;
+ }
+ public Object getVarTypeName(Object v) {
+ return ((VarHandle)v).varType().getName();
+ }
+}
diff --git a/test/1983-structural-redefinition-failures/src/art/Test1983.java b/test/1983-structural-redefinition-failures/src/art/Test1983.java
index d6e09f7..10ec108 100644
--- a/test/1983-structural-redefinition-failures/src/art/Test1983.java
+++ b/test/1983-structural-redefinition-failures/src/art/Test1983.java
@@ -67,7 +67,8 @@
Class.forName("dalvik.system.EmulatedStackFrame"),
Executable.class,
Field.class,
- FinalizerReference.class,
+ // @hide on CTS
+ Class.forName("java.lang.ref.FinalizerReference"),
MethodHandle.class,
MethodHandles.Lookup.class,
MethodType.class,
@@ -79,8 +80,10 @@
String.class,
Thread.class,
Throwable.class,
- VarHandle.class,
+ // @hide on CTS
+ Class.forName("java.lang.invoke.VarHandle"),
// TODO all the var handle types.
+ // @hide on CTS
Class.forName("java.lang.invoke.FieldVarHandle"),
};
System.out.println("Checking mirror'd classes");
diff --git a/test/Android.bp b/test/Android.bp
index 427c3a6..d33d4bf 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -615,6 +615,7 @@
"jvmti-common/FramePop.java",
"jvmti-common/Exceptions.java",
"jvmti-common/Monitors.java",
+ "jvmti-common/NonStandardExit.java",
"jvmti-common/Threads.java",
"jvmti-common/SuspendEvents.java",
@@ -721,10 +722,44 @@
"1953-pop-frame/src/art/Test1953.java",
"1958-transform-try-jit/src/art/Test1958.java",
"1962-multi-thread-events/src/art/Test1962.java",
- // TODO Renumber
- // "1962-force-early-return/src/art/Test1962.java",
- // "1963-force-early-return-void/src/art/Test1963.java",
- // "1964-force-early-return-long/src/art/Test1964.java",
+ "1963-add-to-dex-classloader-in-memory/src/art/Test1963.java",
+ "1967-get-set-local-bad-slot/src/art/Test1967.java",
+ "1968-force-early-return/src/art/Test1968.java",
+ "1969-force-early-return-void/src/art/Test1969.java",
+ "1970-force-early-return-long/src/art/Test1970.java",
+ "1971-multi-force-early-return/src/art/Test1971.java",
+ "1974-resize-array/src/art/Test1974.java",
+ "1975-hello-structural-transformation/src/art/Test1975.java",
+ "1975-hello-structural-transformation/src/art/Transform1975.java",
+ "1976-hello-structural-static-methods/src/art/Test1976.java",
+ "1976-hello-structural-static-methods/src/art/Transform1976.java",
+ "1977-hello-structural-obsolescence/src/art/Test1977.java",
+ "1978-regular-obsolete-then-structural-obsolescence/src/art/Test1978.java",
+ "1979-threaded-structural-transformation/src/art/Test1979.java",
+ "1981-structural-redef-private-method-handles/src/art/Test1981.java",
+ // TODO Requires VarHandles to be un-@hide. See b/64382372
+ // "1981-structural-redef-private-method-handles/src/art/Test1981_Varhandles.java",
+ "1982-no-virtuals-structural-redefinition/src/art/Test1982.java",
+ "1983-structural-redefinition-failures/src/art/Test1983.java",
+ "1984-structural-redefine-field-trace/src/art/Test1984.java",
+ "1988-multi-structural-redefine/src/art/Test1988.java",
+ "1989-transform-bad-monitor/src/art/Test1989.java",
+ "1990-structural-bad-verify/src/art/Test1990.java",
+ "1991-hello-structural-retransform/src/art/Test1991.java",
+ "1992-retransform-no-such-field/src/art/Test1992.java",
+ "1994-final-virtual-structural/src/art/Test1994.java",
+ "1995-final-virtual-structural-multithread/src/art/Test1995.java",
+ "1996-final-override-virtual-structural/src/art/Test1996.java",
+ "1997-structural-shadow-method/src/art/Test1997.java",
+ "1998-structural-shadow-field/src/art/Test1998.java",
+ "1999-virtual-structural/src/art/Test1999.java",
+ "2001-virtual-structural-multithread/src-art/art/Test2001.java",
+ "2002-virtual-structural-initializing/src-art/art/Test2002.java",
+ "2003-double-virtual-structural/src/art/Test2003.java",
+ "2004-double-virtual-structural-abstract/src/art/Test2004.java",
+ "2005-pause-all-redefine-multithreaded/src/art/Test2005.java",
+ "2006-virtual-structural-finalizing/src-art/art/Test2006.java",
+ "2007-virtual-structural-finalizable/src-art/art/Test2007.java",
],
}
@@ -827,6 +862,43 @@
"1943-suspend-raw-monitor-wait/expected.txt",
"1953-pop-frame/expected.txt",
"1958-transform-try-jit/expected.txt",
+ "1962-multi-thread-events/expected.txt",
+ "1963-add-to-dex-classloader-in-memory/expected.txt",
+ "1967-get-set-local-bad-slot/expected.txt",
+ "1968-force-early-return/expected.txt",
+ "1969-force-early-return-void/expected.txt",
+ "1970-force-early-return-long/expected.txt",
+ "1971-multi-force-early-return/expected.txt",
+ "1974-resize-array/expected.txt",
+ "1975-hello-structural-transformation/expected.txt",
+ "1976-hello-structural-static-methods/expected.txt",
+ "1977-hello-structural-obsolescence/expected.txt",
+ "1978-regular-obsolete-then-structural-obsolescence/expected.txt",
+ "1979-threaded-structural-transformation/expected.txt",
+ // TODO Requires VarHandles to be un-@hide. See b/64382372
+ // "test/1981-structural-redef-private-method-handles/expected.txt",
+ "1981-structural-redef-private-method-handles/expected_no_mh.txt",
+ "1982-no-virtuals-structural-redefinition/expected.txt",
+ "1983-structural-redefinition-failures/expected.txt",
+ "1984-structural-redefine-field-trace/expected.txt",
+ "1988-multi-structural-redefine/expected.txt",
+ "1989-transform-bad-monitor/expected.txt",
+ "1990-structural-bad-verify/expected.txt",
+ "1991-hello-structural-retransform/expected.txt",
+ "1992-retransform-no-such-field/expected.txt",
+ "1994-final-virtual-structural/expected.txt",
+ "1995-final-virtual-structural-multithread/expected.txt",
+ "1996-final-override-virtual-structural/expected.txt",
+ "1997-structural-shadow-method/expected.txt",
+ "1998-structural-shadow-field/expected.txt",
+ "1999-virtual-structural/expected.txt",
+ "2001-virtual-structural-multithread/expected.txt",
+ "2002-virtual-structural-initializing/expected.txt",
+ "2003-double-virtual-structural/expected.txt",
+ "2004-double-virtual-structural-abstract/expected.txt",
+ "2005-pause-all-redefine-multithreaded/expected.txt",
+ "2006-virtual-structural-finalizing/expected.txt",
+ "2007-virtual-structural-finalizable/expected.txt",
],
out: ["expected_cts_outputs.jar"],
tools: ["soong_zip"],