1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package art; 18 19 import java.lang.reflect.Executable; 20 import java.lang.reflect.Constructor; 21 import java.lang.reflect.Method; 22 23 import java.time.Duration; 24 25 import java.util.ArrayList; 26 import java.util.Arrays; 27 import java.util.List; 28 import java.util.Optional; 29 import java.util.Random; 30 import java.util.Stack; 31 import java.util.Vector; 32 33 import java.util.function.Supplier; 34 35 public class Test993 { 36 37 public static final Breakpoint.Manager MANAGER = new Breakpoint.Manager(); 38 39 // A function we can use as a start breakpoint. breakpoint()40 public static void breakpoint() { 41 return; 42 } 43 privateBreakpoint()44 private static void privateBreakpoint() { 45 return; 46 } 47 48 // An interface with a default method we can break on. 49 static interface Breakable { iBreakpoint()50 public static void iBreakpoint() { 51 return; 52 } 53 breakit()54 public default void breakit() { 55 return; 56 } 57 } 58 59 // A class that has a default method we breakpoint on. 60 public static class TestClass1 implements Breakable { TestClass1()61 public TestClass1() { 62 super(); 63 } toString()64 public String toString() { return "TestClass1"; } 65 } 66 67 // A class that overrides a default method that we can breakpoint on and calls super. 68 public static class TestClass1ext extends TestClass1 { TestClass1ext()69 public TestClass1ext() { 70 super(); 71 } toString()72 public String toString() { return "TestClass1Ext"; } breakit()73 public void breakit() { 74 super.breakit(); 75 } 76 } 77 78 79 // A class that overrides a default method that we can breakpoint on. 80 public static class TestClass2 implements Breakable { toString()81 public String toString() { return "TestClass2"; } breakit()82 public void breakit() { 83 return; 84 } 85 } 86 87 // A class that overrides a default method that we can breakpoint on and calls super. 88 public static class TestClass2ext extends TestClass2 { toString()89 public String toString() { return "TestClass2ext"; } breakit()90 public void breakit() { 91 super.breakit(); 92 } 93 } 94 95 // A class that overrides a default method and calls it directly with interface invoke-super 96 public static class TestClass3 implements Breakable { toString()97 public String toString() { return "TestClass3"; } breakit()98 public void breakit() { 99 Breakable.super.breakit(); 100 } 101 } 102 103 // A class that overrides a default method that we can breakpoint on and calls super to a class 104 // that uses interface-invoke-super. 105 public static class TestClass3ext extends TestClass3 { toString()106 public String toString() { return "TestClass3ext"; } breakit()107 public void breakit() { 108 super.breakit(); 109 } 110 } 111 112 public static class TestClass4 { toString()113 public String toString() { return "TestClass4"; } callPrivateMethod()114 public void callPrivateMethod() { 115 privateMethod(); 116 } privateMethod()117 private void privateMethod() { 118 return; 119 } 120 } 121 notifyBreakpointReached(Thread thr, Executable e, long loc)122 public static void notifyBreakpointReached(Thread thr, Executable e, long loc) { 123 String line; 124 if (e.getDeclaringClass().getPackage().equals(Test993.class.getPackage())) { 125 line = Integer.valueOf(Breakpoint.locationToLine(e, loc)).toString(); 126 } else { 127 line = "<NON-DETERMINISTIC>"; 128 } 129 System.out.println("\t\t\tBreakpoint: " + e + " @ line=" + line); 130 } 131 132 public static interface ThrowRunnable extends Runnable { run()133 public default void run() { 134 try { 135 runThrow(); 136 } catch (Exception e) { 137 throw new Error("Caught error while running " + this, e); 138 } 139 } runThrow()140 public void runThrow() throws Exception; 141 } 142 143 public static class InvokeDirect implements Runnable { 144 String msg; 145 Runnable r; InvokeDirect(String msg, Runnable r)146 public InvokeDirect(String msg, Runnable r) { 147 this.msg = msg; 148 this.r = r; 149 } 150 @Override run()151 public void run() { 152 System.out.println("\t\tInvoking \"" + msg + "\""); 153 r.run(); 154 } 155 } 156 157 public static class InvokeReflect implements ThrowRunnable { 158 Method m; 159 Object this_arg; InvokeReflect(Method m, Object this_arg)160 public InvokeReflect(Method m, Object this_arg) { 161 this.m = m; 162 this.this_arg = this_arg; 163 } 164 165 @Override runThrow()166 public void runThrow() throws Exception { 167 System.out.println("\t\tReflective invoking: " + m + " args: [this: " + this_arg + "]"); 168 m.invoke(this_arg); 169 } 170 } 171 172 public static class InvokeNative implements Runnable { 173 Method m; 174 Object this_arg; InvokeNative(Method m, Object this_arg)175 public InvokeNative(Method m, Object this_arg) { 176 this.m = m; 177 this.this_arg = this_arg; 178 } 179 180 @Override run()181 public void run() { 182 System.out.println("\t\tNative invoking: " + m + " args: [this: " + this_arg + "]"); 183 invokeNative(m, m.getDeclaringClass(), this_arg); 184 } 185 } 186 invokeNative(Method m, Class<?> clazz, Object thizz)187 public static native void invokeNative(Method m, Class<?> clazz, Object thizz); 188 189 public static class InvokeNativeBool implements Runnable { 190 Method m; 191 Object this_arg; InvokeNativeBool(Method m, Object this_arg)192 public InvokeNativeBool(Method m, Object this_arg) { 193 this.m = m; 194 this.this_arg = this_arg; 195 } 196 197 @Override run()198 public void run() { 199 System.out.println("\t\tNative invoking: " + m + " args: [this: " + this_arg + "]"); 200 invokeNativeBool(m, m.getDeclaringClass(), this_arg); 201 } 202 } 203 invokeNativeBool(Method m, Class<?> clazz, Object thizz)204 public static native void invokeNativeBool(Method m, Class<?> clazz, Object thizz); 205 206 public static class InvokeNativeObject implements Runnable { 207 Method m; 208 Object this_arg; InvokeNativeObject(Method m, Object this_arg)209 public InvokeNativeObject(Method m, Object this_arg) { 210 this.m = m; 211 this.this_arg = this_arg; 212 } 213 214 @Override run()215 public void run() { 216 System.out.println("\t\tNative invoking: " + m + " args: [this: " + this_arg + "]"); 217 invokeNativeObject(m, m.getDeclaringClass(), this_arg); 218 } 219 } 220 invokeNativeObject(Method m, Class<?> clazz, Object thizz)221 public static native void invokeNativeObject(Method m, Class<?> clazz, Object thizz); 222 223 public static class InvokeNativeLong implements Runnable { 224 Method m; 225 Object this_arg; InvokeNativeLong(Method m, Object this_arg)226 public InvokeNativeLong(Method m, Object this_arg) { 227 this.m = m; 228 this.this_arg = this_arg; 229 } 230 231 @Override run()232 public void run() { 233 System.out.println("\t\tNative invoking: " + m + " args: [this: " + this_arg + "]"); 234 invokeNativeLong(m, m.getDeclaringClass(), this_arg); 235 } 236 } 237 invokeNativeLong(Method m, Class<?> clazz, Object thizz)238 public static native void invokeNativeLong(Method m, Class<?> clazz, Object thizz); 239 240 public static class ConstructDirect implements Runnable { 241 String msg; 242 Supplier<Object> s; ConstructDirect(String msg, Supplier<Object> s)243 public ConstructDirect(String msg, Supplier<Object> s) { 244 this.msg = msg; 245 this.s = s; 246 } 247 248 @Override run()249 public void run() { 250 System.out.println("\t\tConstructing: " + msg); 251 System.out.println("\t\t\tCreated: " + s.get()); 252 } 253 } 254 255 public static class ConstructReflect implements ThrowRunnable { 256 Constructor<?> m; ConstructReflect(Constructor<?> m)257 public ConstructReflect(Constructor<?> m) { 258 this.m = m; 259 } 260 261 @Override runThrow()262 public void runThrow() throws Exception { 263 System.out.println("\t\tReflective constructor: " + m); 264 System.out.println("\t\t\tCreated: " + m.newInstance()); 265 } 266 } 267 268 public static class ConstructNative implements Runnable { 269 Constructor<?> m; 270 Class type; ConstructNative(Constructor<?> m)271 public ConstructNative(Constructor<?> m) { 272 this.m = m; 273 this.type = m.getDeclaringClass(); 274 } 275 276 @Override run()277 public void run() { 278 System.out.println("\t\tNative constructor: " + m + ", type: " + type); 279 System.out.println("\t\t\tCreated: " + constructNative(m, type)); 280 } 281 } 282 constructNative(Constructor m, Class<?> clazz)283 public static native Object constructNative(Constructor m, Class<?> clazz); 284 combinations(List<T> items, int len)285 private static <T> List<List<T>> combinations(List<T> items, int len) { 286 if (len > items.size()) { 287 throw new Error("Bad length" + len + " " + items); 288 } 289 if (len == 1) { 290 List<List<T>> out = new ArrayList<>(); 291 for (T t : items) { 292 out.add(Arrays.asList(t)); 293 } 294 return out; 295 } 296 List<List<T>> out = new ArrayList<>(); 297 for (int rem = 0; rem <= items.size() - len; rem++) { 298 for (List<T> others : combinations(items.subList(rem + 1, items.size()), len - 1)) { 299 List<T> newone = new ArrayList<>(); 300 newone.add(items.get(rem)); 301 newone.addAll(others); 302 out.add(newone); 303 } 304 } 305 return out; 306 } 307 allCombinations(List<T> items)308 private static <T> List<List<T>> allCombinations(List<T> items) { 309 List<List<T>> out = new ArrayList<List<T>>(); 310 out.add(new ArrayList<>()); 311 for (int i = 0; i < items.size(); i++) { 312 out.addAll(combinations(items, i + 1)); 313 } 314 return out; 315 } 316 BP(Executable m)317 private static Breakpoint.Manager.BP BP(Executable m) { 318 return new Breakpoint.Manager.BP(m) { 319 public String toString() { 320 if (method.getDeclaringClass().getPackage().equals(Test993.class.getPackage())) { 321 return super.toString(); 322 } else { 323 return method.toString() + " @ <NON-DETERMINISTIC>"; 324 } 325 } 326 }; 327 } 328 329 public static void run() throws Exception { 330 // Set up breakpoints 331 Breakpoint.stopBreakpointWatch(Thread.currentThread()); 332 Breakpoint.startBreakpointWatch( 333 Test993.class, 334 Test993.class.getDeclaredMethod("notifyBreakpointReached", 335 Thread.class, Executable.class, Long.TYPE), 336 Thread.currentThread()); 337 338 runMethodTests(); 339 runBCPMethodTests(); 340 runConstructorTests(); 341 342 Breakpoint.stopBreakpointWatch(Thread.currentThread()); 343 } 344 345 public static void runConstructorTests() throws Exception { 346 // The constructors we will be breaking on. 347 Constructor<?> tc1_construct = TestClass1.class.getConstructor(); 348 Constructor<?> tc1ext_construct = TestClass1ext.class.getConstructor(); 349 350 Runnable[] tc1_constructors = new Runnable[] { 351 new ConstructNative(tc1_construct), 352 new ConstructReflect(tc1_construct), 353 new ConstructDirect("new TestClass1()", TestClass1::new), 354 }; 355 Breakpoint.Manager.BP[] tc1_bps = new Breakpoint.Manager.BP[] { 356 BP(tc1_construct), 357 }; 358 runTestGroups("TestClass1 constructor", tc1_constructors, tc1_bps); 359 360 Runnable[] tc1ext_constructors = new Runnable[] { 361 new ConstructNative(tc1ext_construct), 362 new ConstructReflect(tc1ext_construct), 363 new ConstructDirect("new TestClass1ext()", TestClass1ext::new), 364 }; 365 Breakpoint.Manager.BP[] tc1ext_bps = new Breakpoint.Manager.BP[] { 366 BP(tc1_construct), BP(tc1ext_construct), 367 }; 368 runTestGroups("TestClass1ext constructor", tc1ext_constructors, tc1ext_bps); 369 } 370 371 // These test to make sure we are able to break on functions that might have been quickened or 372 // inlined from the boot-image. These were all chosen for being in the bootclasspath, not being 373 // long enough to prevent inlining, and not being used for the testing framework. 374 public static void runBCPMethodTests() throws Exception { 375 // The methods we will be breaking on. 376 Method bcp_private_method = Duration.class.getDeclaredMethod("toSeconds"); 377 Method bcp_virtual_method = Optional.class.getDeclaredMethod("isPresent"); 378 Method bcp_static_method = Optional.class.getDeclaredMethod("empty"); 379 Method bcp_private_static_method = Random.class.getDeclaredMethod("seedUniquifier"); 380 381 // Some constructors we will break on. 382 Constructor<?> bcp_stack_constructor = Stack.class.getConstructor(); 383 Constructor<?> bcp_vector_constructor = Vector.class.getConstructor(); 384 if (!(Vector.class.isAssignableFrom(Stack.class))) { 385 throw new Error("Expected Stack to extend Vector!"); 386 } 387 388 // BCP constructors. 389 Runnable[] vector_constructors = new Runnable[] { 390 new ConstructNative(bcp_vector_constructor), 391 new ConstructReflect(bcp_vector_constructor), 392 new ConstructDirect("new Vector()", Vector::new), 393 }; 394 Breakpoint.Manager.BP[] vector_breakpoints = new Breakpoint.Manager.BP[] { 395 BP(bcp_vector_constructor), 396 }; 397 runTestGroups("Vector constructor", vector_constructors, vector_breakpoints); 398 399 Runnable[] stack_constructors = new Runnable[] { 400 new ConstructNative(bcp_stack_constructor), 401 new ConstructReflect(bcp_stack_constructor), 402 new ConstructDirect("new Stack()", Stack::new), 403 }; 404 Breakpoint.Manager.BP[] stack_breakpoints = new Breakpoint.Manager.BP[] { 405 BP(bcp_stack_constructor), BP(bcp_vector_constructor), 406 }; 407 runTestGroups("Stack constructor", stack_constructors, stack_breakpoints); 408 409 // Static function 410 Runnable[] static_invokes = new Runnable[] { 411 new InvokeNativeObject(bcp_static_method, null), 412 413 new InvokeReflect(bcp_static_method, null), 414 415 new InvokeDirect("Optional::empty", () -> { Optional.empty(); }), 416 }; 417 Breakpoint.Manager.BP[] static_breakpoints = new Breakpoint.Manager.BP[] { 418 BP(bcp_static_method) 419 }; 420 runTestGroups("bcp static invoke", static_invokes, static_breakpoints); 421 422 // Static private class function 423 Runnable[] private_static_invokes = new Runnable[] { 424 new InvokeNativeLong(bcp_private_static_method, null), 425 426 new InvokeDirect("Random::seedUniquifier", () -> { new Random(); }), 427 }; 428 Breakpoint.Manager.BP[] private_static_breakpoints = new Breakpoint.Manager.BP[] { 429 BP(bcp_private_static_method) 430 }; 431 runTestGroups("bcp private static invoke", private_static_invokes, private_static_breakpoints); 432 433 // private class method 434 Duration test_duration = Duration.ofDays(14); 435 Runnable[] private_invokes = new Runnable[] { 436 new InvokeNativeObject(bcp_private_method, test_duration), 437 438 new InvokeDirect("Duration::toSeconds", () -> { test_duration.multipliedBy(2); }), 439 }; 440 Breakpoint.Manager.BP[] private_breakpoints = new Breakpoint.Manager.BP[] { 441 BP(bcp_private_method) 442 }; 443 runTestGroups("bcp private invoke", private_invokes, private_breakpoints); 444 445 // class method 446 Runnable[] public_invokes = new Runnable[] { 447 new InvokeNativeBool(bcp_virtual_method, Optional.of("test")), 448 449 new InvokeReflect(bcp_virtual_method, Optional.of("test2")), 450 451 new InvokeDirect("Optional::isPresent", () -> { Optional.of("test3").isPresent(); }), 452 }; 453 Breakpoint.Manager.BP[] public_breakpoints = new Breakpoint.Manager.BP[] { 454 BP(bcp_virtual_method) 455 }; 456 runTestGroups("bcp invoke", public_invokes, public_breakpoints); 457 } 458 459 public static void runMethodTests() throws Exception { 460 // The methods we will be breaking on. 461 Method breakpoint_method = Test993.class.getDeclaredMethod("breakpoint"); 462 Method private_breakpoint_method = Test993.class.getDeclaredMethod("privateBreakpoint"); 463 Method i_breakpoint_method = Breakable.class.getDeclaredMethod("iBreakpoint"); 464 Method breakit_method = Breakable.class.getDeclaredMethod("breakit"); 465 Method breakit_method_tc1ext = TestClass1ext.class.getDeclaredMethod("breakit"); 466 Method breakit_method_tc2 = TestClass2.class.getDeclaredMethod("breakit"); 467 Method breakit_method_tc2ext = TestClass2ext.class.getDeclaredMethod("breakit"); 468 Method breakit_method_tc3 = TestClass3.class.getDeclaredMethod("breakit"); 469 Method breakit_method_tc3ext = TestClass3ext.class.getDeclaredMethod("breakit"); 470 Method private_method = TestClass4.class.getDeclaredMethod("privateMethod"); 471 472 // Static class function 473 Runnable[] static_invokes = new Runnable[] { 474 new InvokeNative(breakpoint_method, null), 475 476 new InvokeReflect(breakpoint_method, null), 477 478 new InvokeDirect("Test993::breakpoint", Test993::breakpoint), 479 }; 480 Breakpoint.Manager.BP[] static_breakpoints = new Breakpoint.Manager.BP[] { 481 BP(breakpoint_method) 482 }; 483 runTestGroups("static invoke", static_invokes, static_breakpoints); 484 485 // Static private class function 486 Runnable[] private_static_invokes = new Runnable[] { 487 new InvokeNative(private_breakpoint_method, null), 488 489 new InvokeDirect("Test993::privateBreakpoint", Test993::privateBreakpoint), 490 }; 491 Breakpoint.Manager.BP[] private_static_breakpoints = new Breakpoint.Manager.BP[] { 492 BP(private_breakpoint_method) 493 }; 494 runTestGroups("private static invoke", private_static_invokes, private_static_breakpoints); 495 496 // Static interface function. 497 Runnable[] i_static_invokes = new Runnable[] { 498 new InvokeNative(i_breakpoint_method, null), 499 500 new InvokeReflect(i_breakpoint_method, null), 501 502 new InvokeDirect("Breakable::iBreakpoint", Breakable::iBreakpoint), 503 }; 504 Breakpoint.Manager.BP[] i_static_breakpoints = new Breakpoint.Manager.BP[] { 505 BP(i_breakpoint_method) 506 }; 507 runTestGroups("interface static invoke", i_static_invokes, i_static_breakpoints); 508 509 // Call default method through a class. 510 Runnable[] tc1_invokes = new Runnable[] { 511 new InvokeNative(breakit_method, new TestClass1()), 512 513 new InvokeReflect(breakit_method, new TestClass1()), 514 515 new InvokeDirect("((Breakable)new TestClass1()).breakit()", 516 () -> ((Breakable)new TestClass1()).breakit()), 517 new InvokeDirect("new TestClass1().breakit()", 518 () -> new TestClass1().breakit()), 519 }; 520 Breakpoint.Manager.BP[] tc1_breakpoints = new Breakpoint.Manager.BP[] { 521 BP(breakit_method) 522 }; 523 runTestGroups("TestClass1 invokes", tc1_invokes, tc1_breakpoints); 524 525 // Call default method through an override and normal invoke-super 526 Runnable[] tc1ext_invokes = new Runnable[] { 527 new InvokeNative(breakit_method, new TestClass1ext()), 528 new InvokeNative(breakit_method_tc1ext, new TestClass1ext()), 529 530 new InvokeReflect(breakit_method, new TestClass1ext()), 531 new InvokeReflect(breakit_method_tc1ext, new TestClass1ext()), 532 533 new InvokeDirect("((Breakable)new TestClass1ext()).breakit()", 534 () -> ((Breakable)new TestClass1ext()).breakit()), 535 new InvokeDirect("((TestClass1)new TestClass1ext()).breakit()", 536 () -> ((TestClass1)new TestClass1ext()).breakit()), 537 new InvokeDirect("new TestClass1ext().breakit()", 538 () -> new TestClass1ext().breakit()), 539 }; 540 Breakpoint.Manager.BP[] tc1ext_breakpoints = new Breakpoint.Manager.BP[] { 541 BP(breakit_method), BP(breakit_method_tc1ext) 542 }; 543 runTestGroups("TestClass1ext invokes", tc1ext_invokes, tc1ext_breakpoints); 544 545 // Override default/interface method. 546 Runnable[] tc2_invokes = new Runnable[] { 547 new InvokeNative(breakit_method, new TestClass2()), 548 new InvokeNative(breakit_method_tc2, new TestClass2()), 549 550 new InvokeReflect(breakit_method, new TestClass2()), 551 new InvokeReflect(breakit_method_tc2, new TestClass2()), 552 553 new InvokeDirect("((Breakable)new TestClass2()).breakit()", 554 () -> ((Breakable)new TestClass2()).breakit()), 555 new InvokeDirect("new TestClass2().breakit()", 556 () -> new TestClass2().breakit()), 557 }; 558 Breakpoint.Manager.BP[] tc2_breakpoints = new Breakpoint.Manager.BP[] { 559 BP(breakit_method), BP(breakit_method_tc2) 560 }; 561 runTestGroups("TestClass2 invokes", tc2_invokes, tc2_breakpoints); 562 563 // Call overridden method using invoke-super 564 Runnable[] tc2ext_invokes = new Runnable[] { 565 new InvokeNative(breakit_method, new TestClass2ext()), 566 new InvokeNative(breakit_method_tc2, new TestClass2ext()), 567 new InvokeNative(breakit_method_tc2ext, new TestClass2ext()), 568 569 new InvokeReflect(breakit_method, new TestClass2ext()), 570 new InvokeReflect(breakit_method_tc2, new TestClass2ext()), 571 new InvokeReflect(breakit_method_tc2ext, new TestClass2ext()), 572 573 new InvokeDirect("((Breakable)new TestClass2ext()).breakit()", 574 () -> ((Breakable)new TestClass2ext()).breakit()), 575 new InvokeDirect("((TestClass2)new TestClass2ext()).breakit()", 576 () -> ((TestClass2)new TestClass2ext()).breakit()), 577 new InvokeDirect("new TestClass2ext().breakit())", 578 () -> new TestClass2ext().breakit()), 579 }; 580 Breakpoint.Manager.BP[] tc2ext_breakpoints = new Breakpoint.Manager.BP[] { 581 BP(breakit_method), BP(breakit_method_tc2), BP(breakit_method_tc2ext) 582 }; 583 runTestGroups("TestClass2ext invokes", tc2ext_invokes, tc2ext_breakpoints); 584 585 // Override default method and call it using interface-invoke-super 586 Runnable[] tc3_invokes = new Runnable[] { 587 new InvokeNative(breakit_method, new TestClass3()), 588 new InvokeNative(breakit_method_tc3, new TestClass3()), 589 590 new InvokeReflect(breakit_method, new TestClass3()), 591 new InvokeReflect(breakit_method_tc3, new TestClass3()), 592 593 new InvokeDirect("((Breakable)new TestClass3()).breakit()", 594 () -> ((Breakable)new TestClass3()).breakit()), 595 new InvokeDirect("new TestClass3().breakit())", 596 () -> new TestClass3().breakit()), 597 }; 598 Breakpoint.Manager.BP[] tc3_breakpoints = new Breakpoint.Manager.BP[] { 599 BP(breakit_method), BP(breakit_method_tc3) 600 }; 601 runTestGroups("TestClass3 invokes", tc3_invokes, tc3_breakpoints); 602 603 // Call overridden method using invoke-super 604 Runnable[] tc3ext_invokes = new Runnable[] { 605 new InvokeNative(breakit_method, new TestClass3ext()), 606 new InvokeNative(breakit_method_tc3, new TestClass3ext()), 607 new InvokeNative(breakit_method_tc3ext, new TestClass3ext()), 608 609 new InvokeReflect(breakit_method, new TestClass3ext()), 610 new InvokeReflect(breakit_method_tc3, new TestClass3ext()), 611 new InvokeReflect(breakit_method_tc3ext, new TestClass3ext()), 612 613 new InvokeDirect("((Breakable)new TestClass3ext()).breakit()", 614 () -> ((Breakable)new TestClass3ext()).breakit()), 615 new InvokeDirect("((TestClass3)new TestClass3ext()).breakit()", 616 () -> ((TestClass3)new TestClass3ext()).breakit()), 617 new InvokeDirect("new TestClass3ext().breakit())", 618 () -> new TestClass3ext().breakit()), 619 }; 620 Breakpoint.Manager.BP[] tc3ext_breakpoints = new Breakpoint.Manager.BP[] { 621 BP(breakit_method), BP(breakit_method_tc3), BP(breakit_method_tc3ext) 622 }; 623 runTestGroups("TestClass3ext invokes", tc3ext_invokes, tc3ext_breakpoints); 624 625 // private instance method. 626 Runnable[] private_instance_invokes = new Runnable[] { 627 new InvokeNative(private_method, new TestClass4()), 628 629 new InvokeDirect("new TestClass4().callPrivateMethod()", 630 () -> new TestClass4().callPrivateMethod()), 631 }; 632 Breakpoint.Manager.BP[] private_instance_breakpoints = new Breakpoint.Manager.BP[] { 633 BP(private_method) 634 }; 635 runTestGroups( 636 "private instance invoke", private_instance_invokes, private_instance_breakpoints); 637 } 638 639 private static void runTestGroups(String name, 640 Runnable[] invokes, 641 Breakpoint.Manager.BP[] breakpoints) throws Exception { 642 System.out.println("Running " + name); 643 for (List<Breakpoint.Manager.BP> bps : allCombinations(Arrays.asList(breakpoints))) { 644 System.out.println("\tBreaking on " + bps); 645 for (Runnable test : invokes) { 646 MANAGER.clearAllBreakpoints(); 647 MANAGER.setBreakpoints(bps.toArray(new Breakpoint.Manager.BP[0])); 648 test.run(); 649 } 650 } 651 } 652 } 653