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 run(false); 331 } 332 public static void run(boolean test_BCP_private) throws Exception { 333 // Set up breakpoints 334 Breakpoint.stopBreakpointWatch(Thread.currentThread()); 335 Breakpoint.startBreakpointWatch( 336 Test993.class, 337 Test993.class.getDeclaredMethod("notifyBreakpointReached", 338 Thread.class, Executable.class, Long.TYPE), 339 Thread.currentThread()); 340 341 runMethodTests(); 342 runBCPMethodTests(test_BCP_private); 343 runConstructorTests(); 344 345 Breakpoint.stopBreakpointWatch(Thread.currentThread()); 346 } 347 348 public static void runConstructorTests() throws Exception { 349 // The constructors we will be breaking on. 350 Constructor<?> tc1_construct = TestClass1.class.getConstructor(); 351 Constructor<?> tc1ext_construct = TestClass1ext.class.getConstructor(); 352 353 Runnable[] tc1_constructors = new Runnable[] { 354 new ConstructNative(tc1_construct), 355 new ConstructReflect(tc1_construct), 356 new ConstructDirect("new TestClass1()", TestClass1::new), 357 }; 358 Breakpoint.Manager.BP[] tc1_bps = new Breakpoint.Manager.BP[] { 359 BP(tc1_construct), 360 }; 361 runTestGroups("TestClass1 constructor", tc1_constructors, tc1_bps); 362 363 Runnable[] tc1ext_constructors = new Runnable[] { 364 new ConstructNative(tc1ext_construct), 365 new ConstructReflect(tc1ext_construct), 366 new ConstructDirect("new TestClass1ext()", TestClass1ext::new), 367 }; 368 Breakpoint.Manager.BP[] tc1ext_bps = new Breakpoint.Manager.BP[] { 369 BP(tc1_construct), BP(tc1ext_construct), 370 }; 371 runTestGroups("TestClass1ext constructor", tc1ext_constructors, tc1ext_bps); 372 } 373 374 // These test to make sure we are able to break on functions that might have been quickened or 375 // inlined from the boot-image. These were all chosen for being in the bootclasspath, not being 376 // long enough to prevent inlining, and not being used for the testing framework. 377 public static void runBCPMethodTests(boolean test_BCP_private) throws Exception { 378 // The methods we will be breaking on. 379 Method bcp_private_method = 380 test_BCP_private ? Duration.class.getDeclaredMethod("toBigDecimalSeconds") : null; 381 Method bcp_virtual_method = Optional.class.getDeclaredMethod("isPresent"); 382 Method bcp_static_method = Optional.class.getDeclaredMethod("empty"); 383 Method bcp_private_static_method = 384 test_BCP_private ? Random.class.getDeclaredMethod("seedUniquifier") : null; 385 386 // Some constructors we will break on. 387 Constructor<?> bcp_stack_constructor = Stack.class.getConstructor(); 388 Constructor<?> bcp_vector_constructor = Vector.class.getConstructor(); 389 if (!(Vector.class.isAssignableFrom(Stack.class))) { 390 throw new Error("Expected Stack to extend Vector!"); 391 } 392 393 // BCP constructors. 394 Runnable[] vector_constructors = new Runnable[] { 395 new ConstructNative(bcp_vector_constructor), 396 new ConstructReflect(bcp_vector_constructor), 397 new ConstructDirect("new Vector()", Vector::new), 398 }; 399 Breakpoint.Manager.BP[] vector_breakpoints = new Breakpoint.Manager.BP[] { 400 BP(bcp_vector_constructor), 401 }; 402 runTestGroups("Vector constructor", vector_constructors, vector_breakpoints); 403 404 Runnable[] stack_constructors = new Runnable[] { 405 new ConstructNative(bcp_stack_constructor), 406 new ConstructReflect(bcp_stack_constructor), 407 new ConstructDirect("new Stack()", Stack::new), 408 }; 409 Breakpoint.Manager.BP[] stack_breakpoints = new Breakpoint.Manager.BP[] { 410 BP(bcp_stack_constructor), BP(bcp_vector_constructor), 411 }; 412 runTestGroups("Stack constructor", stack_constructors, stack_breakpoints); 413 414 // Static function 415 Runnable[] static_invokes = new Runnable[] { 416 new InvokeNativeObject(bcp_static_method, null), 417 418 new InvokeReflect(bcp_static_method, null), 419 420 new InvokeDirect("Optional::empty", () -> { Optional.empty(); }), 421 }; 422 Breakpoint.Manager.BP[] static_breakpoints = new Breakpoint.Manager.BP[] { 423 BP(bcp_static_method) 424 }; 425 runTestGroups("bcp static invoke", static_invokes, static_breakpoints); 426 427 // Static private class function 428 if (test_BCP_private) { 429 Runnable[] private_static_invokes = new Runnable[] { 430 new InvokeNativeLong(bcp_private_static_method, null), 431 432 new InvokeDirect("Random::seedUniquifier", () -> { new Random(); }), 433 }; 434 Breakpoint.Manager.BP[] private_static_breakpoints = new Breakpoint.Manager.BP[] { 435 BP(bcp_private_static_method) 436 }; 437 runTestGroups("bcp private static invoke", private_static_invokes, private_static_breakpoints); 438 } 439 440 // private class method 441 if (test_BCP_private) { 442 Duration test_duration = Duration.ofDays(14); 443 Runnable[] private_invokes = new Runnable[] { 444 new InvokeNativeObject(bcp_private_method, test_duration), 445 446 new InvokeDirect("Duration::toBigDecimalSeconds", () -> { test_duration.multipliedBy(2); }), 447 }; 448 Breakpoint.Manager.BP[] private_breakpoints = new Breakpoint.Manager.BP[] { 449 BP(bcp_private_method) 450 }; 451 runTestGroups("bcp private invoke", private_invokes, private_breakpoints); 452 } 453 454 // class method 455 Runnable[] public_invokes = new Runnable[] { 456 new InvokeNativeBool(bcp_virtual_method, Optional.of("test")), 457 458 new InvokeReflect(bcp_virtual_method, Optional.of("test2")), 459 460 new InvokeDirect("Optional::isPresent", () -> { Optional.of("test3").isPresent(); }), 461 }; 462 Breakpoint.Manager.BP[] public_breakpoints = new Breakpoint.Manager.BP[] { 463 BP(bcp_virtual_method) 464 }; 465 runTestGroups("bcp invoke", public_invokes, public_breakpoints); 466 } 467 468 public static void runMethodTests() throws Exception { 469 // The methods we will be breaking on. 470 Method breakpoint_method = Test993.class.getDeclaredMethod("breakpoint"); 471 Method private_breakpoint_method = Test993.class.getDeclaredMethod("privateBreakpoint"); 472 Method i_breakpoint_method = Breakable.class.getDeclaredMethod("iBreakpoint"); 473 Method breakit_method = Breakable.class.getDeclaredMethod("breakit"); 474 Method breakit_method_tc1ext = TestClass1ext.class.getDeclaredMethod("breakit"); 475 Method breakit_method_tc2 = TestClass2.class.getDeclaredMethod("breakit"); 476 Method breakit_method_tc2ext = TestClass2ext.class.getDeclaredMethod("breakit"); 477 Method breakit_method_tc3 = TestClass3.class.getDeclaredMethod("breakit"); 478 Method breakit_method_tc3ext = TestClass3ext.class.getDeclaredMethod("breakit"); 479 Method private_method = TestClass4.class.getDeclaredMethod("privateMethod"); 480 481 // Static class function 482 Runnable[] static_invokes = new Runnable[] { 483 new InvokeNative(breakpoint_method, null), 484 485 new InvokeReflect(breakpoint_method, null), 486 487 new InvokeDirect("Test993::breakpoint", Test993::breakpoint), 488 }; 489 Breakpoint.Manager.BP[] static_breakpoints = new Breakpoint.Manager.BP[] { 490 BP(breakpoint_method) 491 }; 492 runTestGroups("static invoke", static_invokes, static_breakpoints); 493 494 // Static private class function 495 Runnable[] private_static_invokes = new Runnable[] { 496 new InvokeNative(private_breakpoint_method, null), 497 498 new InvokeDirect("Test993::privateBreakpoint", Test993::privateBreakpoint), 499 }; 500 Breakpoint.Manager.BP[] private_static_breakpoints = new Breakpoint.Manager.BP[] { 501 BP(private_breakpoint_method) 502 }; 503 runTestGroups("private static invoke", private_static_invokes, private_static_breakpoints); 504 505 // Static interface function. 506 Runnable[] i_static_invokes = new Runnable[] { 507 new InvokeNative(i_breakpoint_method, null), 508 509 new InvokeReflect(i_breakpoint_method, null), 510 511 new InvokeDirect("Breakable::iBreakpoint", Breakable::iBreakpoint), 512 }; 513 Breakpoint.Manager.BP[] i_static_breakpoints = new Breakpoint.Manager.BP[] { 514 BP(i_breakpoint_method) 515 }; 516 runTestGroups("interface static invoke", i_static_invokes, i_static_breakpoints); 517 518 // Call default method through a class. 519 Runnable[] tc1_invokes = new Runnable[] { 520 new InvokeNative(breakit_method, new TestClass1()), 521 522 new InvokeReflect(breakit_method, new TestClass1()), 523 524 new InvokeDirect("((Breakable)new TestClass1()).breakit()", 525 () -> ((Breakable)new TestClass1()).breakit()), 526 new InvokeDirect("new TestClass1().breakit()", 527 () -> new TestClass1().breakit()), 528 }; 529 Breakpoint.Manager.BP[] tc1_breakpoints = new Breakpoint.Manager.BP[] { 530 BP(breakit_method) 531 }; 532 runTestGroups("TestClass1 invokes", tc1_invokes, tc1_breakpoints); 533 534 // Call default method through an override and normal invoke-super 535 Runnable[] tc1ext_invokes = new Runnable[] { 536 new InvokeNative(breakit_method, new TestClass1ext()), 537 new InvokeNative(breakit_method_tc1ext, new TestClass1ext()), 538 539 new InvokeReflect(breakit_method, new TestClass1ext()), 540 new InvokeReflect(breakit_method_tc1ext, new TestClass1ext()), 541 542 new InvokeDirect("((Breakable)new TestClass1ext()).breakit()", 543 () -> ((Breakable)new TestClass1ext()).breakit()), 544 new InvokeDirect("((TestClass1)new TestClass1ext()).breakit()", 545 () -> ((TestClass1)new TestClass1ext()).breakit()), 546 new InvokeDirect("new TestClass1ext().breakit()", 547 () -> new TestClass1ext().breakit()), 548 }; 549 Breakpoint.Manager.BP[] tc1ext_breakpoints = new Breakpoint.Manager.BP[] { 550 BP(breakit_method), BP(breakit_method_tc1ext) 551 }; 552 runTestGroups("TestClass1ext invokes", tc1ext_invokes, tc1ext_breakpoints); 553 554 // Override default/interface method. 555 Runnable[] tc2_invokes = new Runnable[] { 556 new InvokeNative(breakit_method, new TestClass2()), 557 new InvokeNative(breakit_method_tc2, new TestClass2()), 558 559 new InvokeReflect(breakit_method, new TestClass2()), 560 new InvokeReflect(breakit_method_tc2, new TestClass2()), 561 562 new InvokeDirect("((Breakable)new TestClass2()).breakit()", 563 () -> ((Breakable)new TestClass2()).breakit()), 564 new InvokeDirect("new TestClass2().breakit()", 565 () -> new TestClass2().breakit()), 566 }; 567 Breakpoint.Manager.BP[] tc2_breakpoints = new Breakpoint.Manager.BP[] { 568 BP(breakit_method), BP(breakit_method_tc2) 569 }; 570 runTestGroups("TestClass2 invokes", tc2_invokes, tc2_breakpoints); 571 572 // Call overridden method using invoke-super 573 Runnable[] tc2ext_invokes = new Runnable[] { 574 new InvokeNative(breakit_method, new TestClass2ext()), 575 new InvokeNative(breakit_method_tc2, new TestClass2ext()), 576 new InvokeNative(breakit_method_tc2ext, new TestClass2ext()), 577 578 new InvokeReflect(breakit_method, new TestClass2ext()), 579 new InvokeReflect(breakit_method_tc2, new TestClass2ext()), 580 new InvokeReflect(breakit_method_tc2ext, new TestClass2ext()), 581 582 new InvokeDirect("((Breakable)new TestClass2ext()).breakit()", 583 () -> ((Breakable)new TestClass2ext()).breakit()), 584 new InvokeDirect("((TestClass2)new TestClass2ext()).breakit()", 585 () -> ((TestClass2)new TestClass2ext()).breakit()), 586 new InvokeDirect("new TestClass2ext().breakit())", 587 () -> new TestClass2ext().breakit()), 588 }; 589 Breakpoint.Manager.BP[] tc2ext_breakpoints = new Breakpoint.Manager.BP[] { 590 BP(breakit_method), BP(breakit_method_tc2), BP(breakit_method_tc2ext) 591 }; 592 runTestGroups("TestClass2ext invokes", tc2ext_invokes, tc2ext_breakpoints); 593 594 // Override default method and call it using interface-invoke-super 595 Runnable[] tc3_invokes = new Runnable[] { 596 new InvokeNative(breakit_method, new TestClass3()), 597 new InvokeNative(breakit_method_tc3, new TestClass3()), 598 599 new InvokeReflect(breakit_method, new TestClass3()), 600 new InvokeReflect(breakit_method_tc3, new TestClass3()), 601 602 new InvokeDirect("((Breakable)new TestClass3()).breakit()", 603 () -> ((Breakable)new TestClass3()).breakit()), 604 new InvokeDirect("new TestClass3().breakit())", 605 () -> new TestClass3().breakit()), 606 }; 607 Breakpoint.Manager.BP[] tc3_breakpoints = new Breakpoint.Manager.BP[] { 608 BP(breakit_method), BP(breakit_method_tc3) 609 }; 610 runTestGroups("TestClass3 invokes", tc3_invokes, tc3_breakpoints); 611 612 // Call overridden method using invoke-super 613 Runnable[] tc3ext_invokes = new Runnable[] { 614 new InvokeNative(breakit_method, new TestClass3ext()), 615 new InvokeNative(breakit_method_tc3, new TestClass3ext()), 616 new InvokeNative(breakit_method_tc3ext, new TestClass3ext()), 617 618 new InvokeReflect(breakit_method, new TestClass3ext()), 619 new InvokeReflect(breakit_method_tc3, new TestClass3ext()), 620 new InvokeReflect(breakit_method_tc3ext, new TestClass3ext()), 621 622 new InvokeDirect("((Breakable)new TestClass3ext()).breakit()", 623 () -> ((Breakable)new TestClass3ext()).breakit()), 624 new InvokeDirect("((TestClass3)new TestClass3ext()).breakit()", 625 () -> ((TestClass3)new TestClass3ext()).breakit()), 626 new InvokeDirect("new TestClass3ext().breakit())", 627 () -> new TestClass3ext().breakit()), 628 }; 629 Breakpoint.Manager.BP[] tc3ext_breakpoints = new Breakpoint.Manager.BP[] { 630 BP(breakit_method), BP(breakit_method_tc3), BP(breakit_method_tc3ext) 631 }; 632 runTestGroups("TestClass3ext invokes", tc3ext_invokes, tc3ext_breakpoints); 633 634 // private instance method. 635 Runnable[] private_instance_invokes = new Runnable[] { 636 new InvokeNative(private_method, new TestClass4()), 637 638 new InvokeDirect("new TestClass4().callPrivateMethod()", 639 () -> new TestClass4().callPrivateMethod()), 640 }; 641 Breakpoint.Manager.BP[] private_instance_breakpoints = new Breakpoint.Manager.BP[] { 642 BP(private_method) 643 }; 644 runTestGroups( 645 "private instance invoke", private_instance_invokes, private_instance_breakpoints); 646 } 647 648 private static void runTestGroups(String name, 649 Runnable[] invokes, 650 Breakpoint.Manager.BP[] breakpoints) throws Exception { 651 System.out.println("Running " + name); 652 for (List<Breakpoint.Manager.BP> bps : allCombinations(Arrays.asList(breakpoints))) { 653 System.out.println("\tBreaking on " + bps); 654 for (Runnable test : invokes) { 655 MANAGER.clearAllBreakpoints(); 656 MANAGER.setBreakpoints(bps.toArray(new Breakpoint.Manager.BP[0])); 657 test.run(); 658 } 659 } 660 } 661 } 662