| /* |
| * Copyright (C) 2017 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.reflect.Executable; |
| import java.lang.reflect.Constructor; |
| import java.lang.reflect.Method; |
| |
| import java.time.Duration; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.Optional; |
| import java.util.Random; |
| import java.util.Stack; |
| import java.util.Vector; |
| |
| import java.util.function.Supplier; |
| |
| public class Test993 { |
| |
| public static final Breakpoint.Manager MANAGER = new Breakpoint.Manager(); |
| |
| // A function we can use as a start breakpoint. |
| public static void breakpoint() { |
| return; |
| } |
| |
| private static void privateBreakpoint() { |
| return; |
| } |
| |
| // An interface with a default method we can break on. |
| static interface Breakable { |
| public static void iBreakpoint() { |
| return; |
| } |
| |
| public default void breakit() { |
| return; |
| } |
| } |
| |
| // A class that has a default method we breakpoint on. |
| public static class TestClass1 implements Breakable { |
| public TestClass1() { |
| super(); |
| } |
| public String toString() { return "TestClass1"; } |
| } |
| |
| // A class that overrides a default method that we can breakpoint on and calls super. |
| public static class TestClass1ext extends TestClass1 { |
| public TestClass1ext() { |
| super(); |
| } |
| public String toString() { return "TestClass1Ext"; } |
| public void breakit() { |
| super.breakit(); |
| } |
| } |
| |
| |
| // A class that overrides a default method that we can breakpoint on. |
| public static class TestClass2 implements Breakable { |
| public String toString() { return "TestClass2"; } |
| public void breakit() { |
| return; |
| } |
| } |
| |
| // A class that overrides a default method that we can breakpoint on and calls super. |
| public static class TestClass2ext extends TestClass2 { |
| public String toString() { return "TestClass2ext"; } |
| public void breakit() { |
| super.breakit(); |
| } |
| } |
| |
| // A class that overrides a default method and calls it directly with interface invoke-super |
| public static class TestClass3 implements Breakable { |
| public String toString() { return "TestClass3"; } |
| public void breakit() { |
| Breakable.super.breakit(); |
| } |
| } |
| |
| // A class that overrides a default method that we can breakpoint on and calls super to a class |
| // that uses interface-invoke-super. |
| public static class TestClass3ext extends TestClass3 { |
| public String toString() { return "TestClass3ext"; } |
| public void breakit() { |
| super.breakit(); |
| } |
| } |
| |
| public static class TestClass4 { |
| public String toString() { return "TestClass4"; } |
| public void callPrivateMethod() { |
| privateMethod(); |
| } |
| private void privateMethod() { |
| return; |
| } |
| } |
| |
| public static void notifyBreakpointReached(Thread thr, Executable e, long loc) { |
| String line; |
| if (e.getDeclaringClass().getPackage().equals(Test993.class.getPackage())) { |
| line = Integer.valueOf(Breakpoint.locationToLine(e, loc)).toString(); |
| } else { |
| line = "<NON-DETERMINISTIC>"; |
| } |
| System.out.println("\t\t\tBreakpoint: " + e + " @ line=" + line); |
| } |
| |
| public static interface ThrowRunnable extends Runnable { |
| public default void run() { |
| try { |
| runThrow(); |
| } catch (Exception e) { |
| throw new Error("Caught error while running " + this, e); |
| } |
| } |
| public void runThrow() throws Exception; |
| } |
| |
| public static class InvokeDirect implements Runnable { |
| String msg; |
| Runnable r; |
| public InvokeDirect(String msg, Runnable r) { |
| this.msg = msg; |
| this.r = r; |
| } |
| @Override |
| public void run() { |
| System.out.println("\t\tInvoking \"" + msg + "\""); |
| r.run(); |
| } |
| } |
| |
| public static class InvokeReflect implements ThrowRunnable { |
| Method m; |
| Object this_arg; |
| public InvokeReflect(Method m, Object this_arg) { |
| this.m = m; |
| this.this_arg = this_arg; |
| } |
| |
| @Override |
| public void runThrow() throws Exception { |
| System.out.println("\t\tReflective invoking: " + m + " args: [this: " + this_arg + "]"); |
| m.invoke(this_arg); |
| } |
| } |
| |
| public static class InvokeNative implements Runnable { |
| Method m; |
| Object this_arg; |
| public InvokeNative(Method m, Object this_arg) { |
| this.m = m; |
| this.this_arg = this_arg; |
| } |
| |
| @Override |
| public void run() { |
| System.out.println("\t\tNative invoking: " + m + " args: [this: " + this_arg + "]"); |
| invokeNative(m, m.getDeclaringClass(), this_arg); |
| } |
| } |
| |
| public static native void invokeNative(Method m, Class<?> clazz, Object thizz); |
| |
| public static class InvokeNativeBool implements Runnable { |
| Method m; |
| Object this_arg; |
| public InvokeNativeBool(Method m, Object this_arg) { |
| this.m = m; |
| this.this_arg = this_arg; |
| } |
| |
| @Override |
| public void run() { |
| System.out.println("\t\tNative invoking: " + m + " args: [this: " + this_arg + "]"); |
| invokeNativeBool(m, m.getDeclaringClass(), this_arg); |
| } |
| } |
| |
| public static native void invokeNativeBool(Method m, Class<?> clazz, Object thizz); |
| |
| public static class InvokeNativeObject implements Runnable { |
| Method m; |
| Object this_arg; |
| public InvokeNativeObject(Method m, Object this_arg) { |
| this.m = m; |
| this.this_arg = this_arg; |
| } |
| |
| @Override |
| public void run() { |
| System.out.println("\t\tNative invoking: " + m + " args: [this: " + this_arg + "]"); |
| invokeNativeObject(m, m.getDeclaringClass(), this_arg); |
| } |
| } |
| |
| public static native void invokeNativeObject(Method m, Class<?> clazz, Object thizz); |
| |
| public static class InvokeNativeLong implements Runnable { |
| Method m; |
| Object this_arg; |
| public InvokeNativeLong(Method m, Object this_arg) { |
| this.m = m; |
| this.this_arg = this_arg; |
| } |
| |
| @Override |
| public void run() { |
| System.out.println("\t\tNative invoking: " + m + " args: [this: " + this_arg + "]"); |
| invokeNativeLong(m, m.getDeclaringClass(), this_arg); |
| } |
| } |
| |
| public static native void invokeNativeLong(Method m, Class<?> clazz, Object thizz); |
| |
| public static class ConstructDirect implements Runnable { |
| String msg; |
| Supplier<Object> s; |
| public ConstructDirect(String msg, Supplier<Object> s) { |
| this.msg = msg; |
| this.s = s; |
| } |
| |
| @Override |
| public void run() { |
| System.out.println("\t\tConstructing: " + msg); |
| System.out.println("\t\t\tCreated: " + s.get()); |
| } |
| } |
| |
| public static class ConstructReflect implements ThrowRunnable { |
| Constructor<?> m; |
| public ConstructReflect(Constructor<?> m) { |
| this.m = m; |
| } |
| |
| @Override |
| public void runThrow() throws Exception { |
| System.out.println("\t\tReflective constructor: " + m); |
| System.out.println("\t\t\tCreated: " + m.newInstance()); |
| } |
| } |
| |
| public static class ConstructNative implements Runnable { |
| Constructor<?> m; |
| Class type; |
| public ConstructNative(Constructor<?> m) { |
| this.m = m; |
| this.type = m.getDeclaringClass(); |
| } |
| |
| @Override |
| public void run() { |
| System.out.println("\t\tNative constructor: " + m + ", type: " + type); |
| System.out.println("\t\t\tCreated: " + constructNative(m, type)); |
| } |
| } |
| |
| public static native Object constructNative(Constructor m, Class<?> clazz); |
| |
| private static <T> List<List<T>> combinations(List<T> items, int len) { |
| if (len > items.size()) { |
| throw new Error("Bad length" + len + " " + items); |
| } |
| if (len == 1) { |
| List<List<T>> out = new ArrayList<>(); |
| for (T t : items) { |
| out.add(Arrays.asList(t)); |
| } |
| return out; |
| } |
| List<List<T>> out = new ArrayList<>(); |
| for (int rem = 0; rem <= items.size() - len; rem++) { |
| for (List<T> others : combinations(items.subList(rem + 1, items.size()), len - 1)) { |
| List<T> newone = new ArrayList<>(); |
| newone.add(items.get(rem)); |
| newone.addAll(others); |
| out.add(newone); |
| } |
| } |
| return out; |
| } |
| |
| private static <T> List<List<T>> allCombinations(List<T> items) { |
| List<List<T>> out = new ArrayList<List<T>>(); |
| out.add(new ArrayList<>()); |
| for (int i = 0; i < items.size(); i++) { |
| out.addAll(combinations(items, i + 1)); |
| } |
| return out; |
| } |
| |
| private static Breakpoint.Manager.BP BP(Executable m) { |
| return new Breakpoint.Manager.BP(m) { |
| public String toString() { |
| if (method.getDeclaringClass().getPackage().equals(Test993.class.getPackage())) { |
| return super.toString(); |
| } else { |
| return method.toString() + " @ <NON-DETERMINISTIC>"; |
| } |
| } |
| }; |
| } |
| |
| public static void run() throws Exception { |
| run(false); |
| } |
| public static void run(boolean test_BCP_private) throws Exception { |
| // Set up breakpoints |
| Breakpoint.stopBreakpointWatch(Thread.currentThread()); |
| Breakpoint.startBreakpointWatch( |
| Test993.class, |
| Test993.class.getDeclaredMethod("notifyBreakpointReached", |
| Thread.class, Executable.class, Long.TYPE), |
| Thread.currentThread()); |
| |
| runMethodTests(); |
| runBCPMethodTests(test_BCP_private); |
| runConstructorTests(); |
| |
| Breakpoint.stopBreakpointWatch(Thread.currentThread()); |
| } |
| |
| public static void runConstructorTests() throws Exception { |
| // The constructors we will be breaking on. |
| Constructor<?> tc1_construct = TestClass1.class.getConstructor(); |
| Constructor<?> tc1ext_construct = TestClass1ext.class.getConstructor(); |
| |
| Runnable[] tc1_constructors = new Runnable[] { |
| new ConstructNative(tc1_construct), |
| new ConstructReflect(tc1_construct), |
| new ConstructDirect("new TestClass1()", TestClass1::new), |
| }; |
| Breakpoint.Manager.BP[] tc1_bps = new Breakpoint.Manager.BP[] { |
| BP(tc1_construct), |
| }; |
| runTestGroups("TestClass1 constructor", tc1_constructors, tc1_bps); |
| |
| Runnable[] tc1ext_constructors = new Runnable[] { |
| new ConstructNative(tc1ext_construct), |
| new ConstructReflect(tc1ext_construct), |
| new ConstructDirect("new TestClass1ext()", TestClass1ext::new), |
| }; |
| Breakpoint.Manager.BP[] tc1ext_bps = new Breakpoint.Manager.BP[] { |
| BP(tc1_construct), BP(tc1ext_construct), |
| }; |
| runTestGroups("TestClass1ext constructor", tc1ext_constructors, tc1ext_bps); |
| } |
| |
| // These test to make sure we are able to break on functions that might have been quickened or |
| // inlined from the boot-image. These were all chosen for being in the bootclasspath, not being |
| // long enough to prevent inlining, and not being used for the testing framework. |
| @SuppressWarnings("OptionalOfRedundantMethod") |
| public static void runBCPMethodTests(boolean test_BCP_private) throws Exception { |
| // The methods we will be breaking on. |
| Method bcp_private_method = |
| test_BCP_private ? Duration.class.getDeclaredMethod("toBigDecimalSeconds") : null; |
| Method bcp_virtual_method = Optional.class.getDeclaredMethod("isPresent"); |
| Method bcp_static_method = Optional.class.getDeclaredMethod("empty"); |
| Method bcp_private_static_method = |
| test_BCP_private ? Random.class.getDeclaredMethod("seedUniquifier") : null; |
| |
| // Some constructors we will break on. |
| Constructor<?> bcp_stack_constructor = Stack.class.getConstructor(); |
| Constructor<?> bcp_vector_constructor = Vector.class.getConstructor(); |
| if (!(Vector.class.isAssignableFrom(Stack.class))) { |
| throw new Error("Expected Stack to extend Vector!"); |
| } |
| |
| // BCP constructors. |
| Runnable[] vector_constructors = new Runnable[] { |
| new ConstructNative(bcp_vector_constructor), |
| new ConstructReflect(bcp_vector_constructor), |
| new ConstructDirect("new Vector()", Vector::new), |
| }; |
| Breakpoint.Manager.BP[] vector_breakpoints = new Breakpoint.Manager.BP[] { |
| BP(bcp_vector_constructor), |
| }; |
| runTestGroups("Vector constructor", vector_constructors, vector_breakpoints); |
| |
| Runnable[] stack_constructors = new Runnable[] { |
| new ConstructNative(bcp_stack_constructor), |
| new ConstructReflect(bcp_stack_constructor), |
| new ConstructDirect("new Stack()", Stack::new), |
| }; |
| Breakpoint.Manager.BP[] stack_breakpoints = new Breakpoint.Manager.BP[] { |
| BP(bcp_stack_constructor), BP(bcp_vector_constructor), |
| }; |
| runTestGroups("Stack constructor", stack_constructors, stack_breakpoints); |
| |
| // Static function |
| Runnable[] static_invokes = new Runnable[] { |
| new InvokeNativeObject(bcp_static_method, null), |
| |
| new InvokeReflect(bcp_static_method, null), |
| |
| new InvokeDirect("Optional::empty", () -> { Optional.empty(); }), |
| }; |
| Breakpoint.Manager.BP[] static_breakpoints = new Breakpoint.Manager.BP[] { |
| BP(bcp_static_method) |
| }; |
| runTestGroups("bcp static invoke", static_invokes, static_breakpoints); |
| |
| // Static private class function |
| if (test_BCP_private) { |
| Runnable[] private_static_invokes = new Runnable[] { |
| new InvokeNativeLong(bcp_private_static_method, null), |
| |
| new InvokeDirect("Random::seedUniquifier", () -> { new Random(); }), |
| }; |
| Breakpoint.Manager.BP[] private_static_breakpoints = new Breakpoint.Manager.BP[] { |
| BP(bcp_private_static_method) |
| }; |
| runTestGroups("bcp private static invoke", private_static_invokes, private_static_breakpoints); |
| } |
| |
| // private class method |
| if (test_BCP_private) { |
| Duration test_duration = Duration.ofDays(14); |
| Runnable[] private_invokes = new Runnable[] { |
| new InvokeNativeObject(bcp_private_method, test_duration), |
| |
| new InvokeDirect("Duration::toBigDecimalSeconds", () -> { test_duration.multipliedBy(2); }), |
| }; |
| Breakpoint.Manager.BP[] private_breakpoints = new Breakpoint.Manager.BP[] { |
| BP(bcp_private_method) |
| }; |
| runTestGroups("bcp private invoke", private_invokes, private_breakpoints); |
| } |
| |
| // class method |
| Runnable[] public_invokes = new Runnable[] { |
| new InvokeNativeBool(bcp_virtual_method, Optional.of("test")), |
| |
| new InvokeReflect(bcp_virtual_method, Optional.of("test2")), |
| |
| new InvokeDirect("Optional::isPresent", () -> { Optional.of("test3").isPresent(); }), |
| }; |
| Breakpoint.Manager.BP[] public_breakpoints = new Breakpoint.Manager.BP[] { |
| BP(bcp_virtual_method) |
| }; |
| runTestGroups("bcp invoke", public_invokes, public_breakpoints); |
| } |
| |
| public static void runMethodTests() throws Exception { |
| // The methods we will be breaking on. |
| Method breakpoint_method = Test993.class.getDeclaredMethod("breakpoint"); |
| Method private_breakpoint_method = Test993.class.getDeclaredMethod("privateBreakpoint"); |
| Method i_breakpoint_method = Breakable.class.getDeclaredMethod("iBreakpoint"); |
| Method breakit_method = Breakable.class.getDeclaredMethod("breakit"); |
| Method breakit_method_tc1ext = TestClass1ext.class.getDeclaredMethod("breakit"); |
| Method breakit_method_tc2 = TestClass2.class.getDeclaredMethod("breakit"); |
| Method breakit_method_tc2ext = TestClass2ext.class.getDeclaredMethod("breakit"); |
| Method breakit_method_tc3 = TestClass3.class.getDeclaredMethod("breakit"); |
| Method breakit_method_tc3ext = TestClass3ext.class.getDeclaredMethod("breakit"); |
| Method private_method = TestClass4.class.getDeclaredMethod("privateMethod"); |
| |
| // Static class function |
| Runnable[] static_invokes = new Runnable[] { |
| new InvokeNative(breakpoint_method, null), |
| |
| new InvokeReflect(breakpoint_method, null), |
| |
| new InvokeDirect("Test993::breakpoint", Test993::breakpoint), |
| }; |
| Breakpoint.Manager.BP[] static_breakpoints = new Breakpoint.Manager.BP[] { |
| BP(breakpoint_method) |
| }; |
| runTestGroups("static invoke", static_invokes, static_breakpoints); |
| |
| // Static private class function |
| Runnable[] private_static_invokes = new Runnable[] { |
| new InvokeNative(private_breakpoint_method, null), |
| |
| new InvokeDirect("Test993::privateBreakpoint", Test993::privateBreakpoint), |
| }; |
| Breakpoint.Manager.BP[] private_static_breakpoints = new Breakpoint.Manager.BP[] { |
| BP(private_breakpoint_method) |
| }; |
| runTestGroups("private static invoke", private_static_invokes, private_static_breakpoints); |
| |
| // Static interface function. |
| Runnable[] i_static_invokes = new Runnable[] { |
| new InvokeNative(i_breakpoint_method, null), |
| |
| new InvokeReflect(i_breakpoint_method, null), |
| |
| new InvokeDirect("Breakable::iBreakpoint", Breakable::iBreakpoint), |
| }; |
| Breakpoint.Manager.BP[] i_static_breakpoints = new Breakpoint.Manager.BP[] { |
| BP(i_breakpoint_method) |
| }; |
| runTestGroups("interface static invoke", i_static_invokes, i_static_breakpoints); |
| |
| // Call default method through a class. |
| Runnable[] tc1_invokes = new Runnable[] { |
| new InvokeNative(breakit_method, new TestClass1()), |
| |
| new InvokeReflect(breakit_method, new TestClass1()), |
| |
| new InvokeDirect("((Breakable)new TestClass1()).breakit()", |
| () -> ((Breakable)new TestClass1()).breakit()), |
| new InvokeDirect("new TestClass1().breakit()", |
| () -> new TestClass1().breakit()), |
| }; |
| Breakpoint.Manager.BP[] tc1_breakpoints = new Breakpoint.Manager.BP[] { |
| BP(breakit_method) |
| }; |
| runTestGroups("TestClass1 invokes", tc1_invokes, tc1_breakpoints); |
| |
| // Call default method through an override and normal invoke-super |
| Runnable[] tc1ext_invokes = new Runnable[] { |
| new InvokeNative(breakit_method, new TestClass1ext()), |
| new InvokeNative(breakit_method_tc1ext, new TestClass1ext()), |
| |
| new InvokeReflect(breakit_method, new TestClass1ext()), |
| new InvokeReflect(breakit_method_tc1ext, new TestClass1ext()), |
| |
| new InvokeDirect("((Breakable)new TestClass1ext()).breakit()", |
| () -> ((Breakable)new TestClass1ext()).breakit()), |
| new InvokeDirect("((TestClass1)new TestClass1ext()).breakit()", |
| () -> ((TestClass1)new TestClass1ext()).breakit()), |
| new InvokeDirect("new TestClass1ext().breakit()", |
| () -> new TestClass1ext().breakit()), |
| }; |
| Breakpoint.Manager.BP[] tc1ext_breakpoints = new Breakpoint.Manager.BP[] { |
| BP(breakit_method), BP(breakit_method_tc1ext) |
| }; |
| runTestGroups("TestClass1ext invokes", tc1ext_invokes, tc1ext_breakpoints); |
| |
| // Override default/interface method. |
| Runnable[] tc2_invokes = new Runnable[] { |
| new InvokeNative(breakit_method, new TestClass2()), |
| new InvokeNative(breakit_method_tc2, new TestClass2()), |
| |
| new InvokeReflect(breakit_method, new TestClass2()), |
| new InvokeReflect(breakit_method_tc2, new TestClass2()), |
| |
| new InvokeDirect("((Breakable)new TestClass2()).breakit()", |
| () -> ((Breakable)new TestClass2()).breakit()), |
| new InvokeDirect("new TestClass2().breakit()", |
| () -> new TestClass2().breakit()), |
| }; |
| Breakpoint.Manager.BP[] tc2_breakpoints = new Breakpoint.Manager.BP[] { |
| BP(breakit_method), BP(breakit_method_tc2) |
| }; |
| runTestGroups("TestClass2 invokes", tc2_invokes, tc2_breakpoints); |
| |
| // Call overridden method using invoke-super |
| Runnable[] tc2ext_invokes = new Runnable[] { |
| new InvokeNative(breakit_method, new TestClass2ext()), |
| new InvokeNative(breakit_method_tc2, new TestClass2ext()), |
| new InvokeNative(breakit_method_tc2ext, new TestClass2ext()), |
| |
| new InvokeReflect(breakit_method, new TestClass2ext()), |
| new InvokeReflect(breakit_method_tc2, new TestClass2ext()), |
| new InvokeReflect(breakit_method_tc2ext, new TestClass2ext()), |
| |
| new InvokeDirect("((Breakable)new TestClass2ext()).breakit()", |
| () -> ((Breakable)new TestClass2ext()).breakit()), |
| new InvokeDirect("((TestClass2)new TestClass2ext()).breakit()", |
| () -> ((TestClass2)new TestClass2ext()).breakit()), |
| new InvokeDirect("new TestClass2ext().breakit())", |
| () -> new TestClass2ext().breakit()), |
| }; |
| Breakpoint.Manager.BP[] tc2ext_breakpoints = new Breakpoint.Manager.BP[] { |
| BP(breakit_method), BP(breakit_method_tc2), BP(breakit_method_tc2ext) |
| }; |
| runTestGroups("TestClass2ext invokes", tc2ext_invokes, tc2ext_breakpoints); |
| |
| // Override default method and call it using interface-invoke-super |
| Runnable[] tc3_invokes = new Runnable[] { |
| new InvokeNative(breakit_method, new TestClass3()), |
| new InvokeNative(breakit_method_tc3, new TestClass3()), |
| |
| new InvokeReflect(breakit_method, new TestClass3()), |
| new InvokeReflect(breakit_method_tc3, new TestClass3()), |
| |
| new InvokeDirect("((Breakable)new TestClass3()).breakit()", |
| () -> ((Breakable)new TestClass3()).breakit()), |
| new InvokeDirect("new TestClass3().breakit())", |
| () -> new TestClass3().breakit()), |
| }; |
| Breakpoint.Manager.BP[] tc3_breakpoints = new Breakpoint.Manager.BP[] { |
| BP(breakit_method), BP(breakit_method_tc3) |
| }; |
| runTestGroups("TestClass3 invokes", tc3_invokes, tc3_breakpoints); |
| |
| // Call overridden method using invoke-super |
| Runnable[] tc3ext_invokes = new Runnable[] { |
| new InvokeNative(breakit_method, new TestClass3ext()), |
| new InvokeNative(breakit_method_tc3, new TestClass3ext()), |
| new InvokeNative(breakit_method_tc3ext, new TestClass3ext()), |
| |
| new InvokeReflect(breakit_method, new TestClass3ext()), |
| new InvokeReflect(breakit_method_tc3, new TestClass3ext()), |
| new InvokeReflect(breakit_method_tc3ext, new TestClass3ext()), |
| |
| new InvokeDirect("((Breakable)new TestClass3ext()).breakit()", |
| () -> ((Breakable)new TestClass3ext()).breakit()), |
| new InvokeDirect("((TestClass3)new TestClass3ext()).breakit()", |
| () -> ((TestClass3)new TestClass3ext()).breakit()), |
| new InvokeDirect("new TestClass3ext().breakit())", |
| () -> new TestClass3ext().breakit()), |
| }; |
| Breakpoint.Manager.BP[] tc3ext_breakpoints = new Breakpoint.Manager.BP[] { |
| BP(breakit_method), BP(breakit_method_tc3), BP(breakit_method_tc3ext) |
| }; |
| runTestGroups("TestClass3ext invokes", tc3ext_invokes, tc3ext_breakpoints); |
| |
| // private instance method. |
| Runnable[] private_instance_invokes = new Runnable[] { |
| new InvokeNative(private_method, new TestClass4()), |
| |
| new InvokeDirect("new TestClass4().callPrivateMethod()", |
| () -> new TestClass4().callPrivateMethod()), |
| }; |
| Breakpoint.Manager.BP[] private_instance_breakpoints = new Breakpoint.Manager.BP[] { |
| BP(private_method) |
| }; |
| runTestGroups( |
| "private instance invoke", private_instance_invokes, private_instance_breakpoints); |
| } |
| |
| private static void runTestGroups(String name, |
| Runnable[] invokes, |
| Breakpoint.Manager.BP[] breakpoints) throws Exception { |
| System.out.println("Running " + name); |
| for (List<Breakpoint.Manager.BP> bps : allCombinations(Arrays.asList(breakpoints))) { |
| System.out.println("\tBreaking on " + bps); |
| for (Runnable test : invokes) { |
| MANAGER.clearAllBreakpoints(); |
| MANAGER.setBreakpoints(bps.toArray(new Breakpoint.Manager.BP[0])); |
| test.run(); |
| } |
| } |
| } |
| } |