Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  Test1953.java

  Sprache: JAVA
 

/*
 * 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.Field;
import java.lang.reflect.Method;
import java.util.Base64;
import java.util.EnumSet;
import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;

import static art.SuspendEvents.setupTest;
import static art.SuspendEvents.setupSuspendBreakpointFor;
import static art.SuspendEvents.clearSuspendBreakpointFor;
import static art.SuspendEvents.setupSuspendSingleStepAt;
import static art.SuspendEvents.setupFieldSuspendFor;
import static art.SuspendEvents.setupSuspendMethodEvent;
import static art.SuspendEvents.setupSuspendExceptionEvent;
import static art.SuspendEvents.setupSuspendPopFrameEvent;
import static art.SuspendEvents.EVENT_TYPE_CLASS_LOAD;
import static art.SuspendEvents.EVENT_TYPE_CLASS_PREPARE;
import static art.SuspendEvents.setupSuspendClassEvent;

public class Test1953 {
  private static boolean IS_ART = System.getProperty("java.vm.name").equals("Dalvik");
  public final boolean canRunClassLoadTests;
  public static void doNothing() {}

  public interface TestRunnable extends Runnable {
    public int getBaseCallCount();
    public Method getCalledMethod() throws Exception;
    public default Method getCallingMethod() throws Exception {
      return this.getClass().getMethod("run");
    };
  }

  public static interface TestSuspender {
    public void setup(Thread thr);
    public void waitForSuspend(Thread thr);
    public void cleanup(Thread thr);
  }

  public static interface ThreadRunnable { public void run(Thread thr); }
  public static TestSuspender makeSuspend(final ThreadRunnable setup, final ThreadRunnable clean) {
    return new TestSuspender() {
      public void setup(Thread thr) { setup.run(thr); }
      public void waitForSuspend(Thread thr) { SuspendEvents.waitForSuspendHit(thr); }
      public void cleanup(Thread thr) { clean.run(thr); }
    };
  }

  public void runTestOn(TestRunnable testObj, ThreadRunnable su, ThreadRunnable cl) throws
      Exception {
    runTestOn(testObj, makeSuspend(su, cl));
  }

  private static void SafePrintStackTrace(StackTraceElement st[]) {
    for (StackTraceElement e : st) {
      System.out.println("\t" + e.getClassName() + "." + e.getMethodName() + "(" +
          (e.isNativeMethod() ? "Native Method" : e.getFileName()) + ")");
      if (e.getClassName().equals("art.Test1953") && e.getMethodName().equals("runTests")) {
        System.out.println("\t<Additional frames hidden>");
        break;
      }
    }
  }

  public void runTestOn(TestRunnable testObj, TestSuspender su) throws Exception {
    System.out.println("Single call with PopFrame on " + testObj + " base-call-count: " +
        testObj.getBaseCallCount());
    final CountDownLatch continue_latch = new CountDownLatch(1);
    final CountDownLatch startup_latch = new CountDownLatch(1);
    Runnable await = () -> {
      try {
        startup_latch.countDown();
        continue_latch.await();
      } catch (Exception e) {
        throw new Error("Failed to await latch", e);
      }
    };
    Thread thr = new Thread(() -> { await.run(); testObj.run(); });
    thr.start();

    // Wait until the other thread is started.
    startup_latch.await();

    // Do any final setup.
    preTest.accept(testObj);

    // Setup suspension method on the thread.
    su.setup(thr);

    // Let the other thread go.
    continue_latch.countDown();

    // Wait for the other thread to hit the breakpoint/watchpoint/whatever and suspend itself
    // (without re-entering java)
    su.waitForSuspend(thr);

    // Cleanup the breakpoint/watchpoint/etc.
    su.cleanup(thr);

    try {
      // Pop the frame.
      popFrame(thr);
    } catch (Exception e) {
      System.out.println("Failed to pop frame due to " + e);
      SafePrintStackTrace(e.getStackTrace());
    }

    // Start the other thread going again.
    Suspension.resume(thr);

    // Wait for the other thread to finish.
    thr.join();

    // See how many times calledFunction was called.
    System.out.println("result is " + testObj + " base-call count: " + testObj.getBaseCallCount());
  }

  public static abstract class AbstractTestObject implements TestRunnable {
    public int callerCnt;

    public AbstractTestObject() {
      callerCnt = 0;
    }

    public int getBaseCallCount() {
      return callerCnt;
    }

    public void run() {
      callerCnt++;
      // This function should be re-executed by the popFrame.
      calledFunction();
    }

    public Method getCalledMethod() throws Exception {
      return this.getClass().getMethod("calledFunction");
    }

    public abstract void calledFunction();
  }

  public static class RedefineTestObject extends AbstractTestObject implements Runnable {
    public static enum RedefineState { ORIGINAL, REDEFINED, };
    /* public static class RedefineTestObject extends AbstractTestObject implements Runnable {
     *   public static final byte[] CLASS_BYTES;
     *   public static final byte[] DEX_BYTES;
     *   static {
     *     CLASS_BYTES = null;
     *     DEX_BYTES = null;
     *   }
     *
     *   public EnumSet<RedefineState> redefine_states;
     *   public RedefineTestObject() {
     *     super();
     *     redefine_states = EnumSet.noneOf(RedefineState.class);
     *   }
     *   public String toString() {
     *     return "RedefineTestObject { states: " + redefine_states.toString()
     *                                            + " current: REDEFINED }";
     *   }
     *   public void calledFunction() {
     *     redefine_states.add(RedefineState.REDEFINED);  // line +0
     *     // We will trigger the redefinition using a breakpoint on the next line.
     *     doNothing();                                   // line +2
     *   }
     * }
     */

    public static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
      "yv66vgAAADUATQoADQAjBwAkCgAlACYJAAwAJwoAJQAoEgAAACwJAAIALQoAJQAuCgAvADAJAAwA" +
      "MQkADAAyBwAzBwA0BwA2AQASUmVkZWZpbmVUZXN0T2JqZWN0AQAMSW5uZXJDbGFzc2VzAQANUmVk" +
      "ZWZpbmVTdGF0ZQEAC0NMQVNTX0JZVEVTAQACW0IBAAlERVhfQllURVMBAA9yZWRlZmluZV9zdGF0" +
      "ZXMBABNMamF2YS91dGlsL0VudW1TZXQ7AQAJU2lnbmF0dXJlAQBETGphdmEvdXRpbC9FbnVtU2V0" +
      "PExhcnQvVGVzdDE5NTMkUmVkZWZpbmVUZXN0T2JqZWN0JFJlZGVmaW5lU3RhdGU7PjsBAAY8aW5p" +
      "dD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQAIdG9TdHJpbmcBABQoKUxqYXZhL2xh" +
      "bmcvU3RyaW5nOwEADmNhbGxlZEZ1bmN0aW9uAQAIPGNsaW5pdD4BAApTb3VyY2VGaWxlAQANVGVz" +
      "dDE5NTMuamF2YQwAGQAaAQAtYXJ0L1Rlc3QxOTUzJFJlZGVmaW5lVGVzdE9iamVjdCRSZWRlZmlu" +
      "ZVN0YXRlBwA3DAA4ADkMABUAFgwAHQAeAQAQQm9vdHN0cmFwTWV0aG9kcw8GADoIADsMADwAPQwA" +
      "PgA/DABAAEEHAEIMAEMAGgwAEgATDAAUABMBAB9hcnQvVGVzdDE5NTMkUmVkZWZpbmVUZXN0T2Jq" +
      "ZWN0AQAfYXJ0L1Rlc3QxOTUzJEFic3RyYWN0VGVzdE9iamVjdAEAEkFic3RyYWN0VGVzdE9iamVj" +
      "dAEAEmphdmEvbGFuZy9SdW5uYWJsZQEAEWphdmEvdXRpbC9FbnVtU2V0AQAGbm9uZU9mAQAmKExq" +
      "YXZhL2xhbmcvQ2xhc3M7KUxqYXZhL3V0aWwvRW51bVNldDsKAEQARQEAM1JlZGVmaW5lVGVzdE9i" +
      "amVjdCB7IHN0YXRlczogASBjdXJyZW50OiBSRURFRklORUQgfQEAF21ha2VDb25jYXRXaXRoQ29u" +
      "c3RhbnRzAQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsBAAlSRURFRklO" +
      "RUQBAC9MYXJ0L1Rlc3QxOTUzJFJlZGVmaW5lVGVzdE9iamVjdCRSZWRlZmluZVN0YXRlOwEAA2Fk" +
      "ZAEAFShMamF2YS9sYW5nL09iamVjdDspWgEADGFydC9UZXN0MTk1MwEACWRvTm90aGluZwcARgwA" +
      "PABJAQAkamF2YS9sYW5nL2ludm9rZS9TdHJpbmdDb25jYXRGYWN0b3J5BwBLAQAGTG9va3VwAQCY" +
      "KExqYXZhL2xhbmcvaW52b2tlL01ldGhvZEhhbmRsZXMkTG9va3VwO0xqYXZhL2xhbmcvU3RyaW5n" +
      "O0xqYXZhL2xhbmcvaW52b2tlL01ldGhvZFR5cGU7TGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xh" +
      "bmcvT2JqZWN0OylMamF2YS9sYW5nL2ludm9rZS9DYWxsU2l0ZTsHAEwBACVqYXZhL2xhbmcvaW52" +
      "b2tlL01ldGhvZEhhbmRsZXMkTG9va3VwAQAeamF2YS9sYW5nL2ludm9rZS9NZXRob2RIYW5kbGVz" +
      "ACEADAANAAEADgADABkAEgATAAAAGQAUABMAAAABABUAFgABABcAAAACABgABAABABkAGgABABsA" +
      "AAAuAAIAAQAAAA4qtwABKhICuAADtQAEsQAAAAEAHAAAAA4AAwAAACEABAAiAA0AIwABAB0AHgAB" +
      "ABsAAAAlAAEAAQAAAA0qtAAEtgAFugAGAACwAAAAAQAcAAAABgABAAAAJQABAB8AGgABABsAAAAv" +
      "AAIAAQAAAA8qtAAEsgAHtgAIV7gACbEAAAABABwAAAAOAAMAAAApAAsAKwAOACwACAAgABoAAQAb" +
      "AAAAKQABAAAAAAAJAbMACgGzAAuxAAAAAQAcAAAADgADAAAAGwAEABwACAAdAAMAIQAAAAIAIgAQ" +
      "AAAAIgAEAAwALwAPAAkAAgAMABFAGQANAC8ANQQJAEcASgBIABkAKQAAAAgAAQAqAAEAKw==");
    public static final byte[] DEX_BYTES = Base64.getDecoder().decode(
      "ZGV4CjAzNQAaR23N6WpunLRVX+BexSuzzNNiHNOvQpFoBwAAcAAAAHhWNBIAAAAAAAAAAKQGAAAq" +
      "AAAAcAAAABEAAAAYAQAABQAAAFwBAAAEAAAAmAEAAAwAAAC4AQAAAQAAABgCAAAwBQAAOAIAACID" +
      "AAA5AwAAQwMAAEsDAABPAwAAXAMAAGcDAABqAwAAbgMAAJEDAADCAwAA5QMAAPUDAAAZBAAAOQQA" +
      "AFwEAAB7BAAAjgQAAKIEAAC4BAAAzAQAAOcEAAD8BAAAEQUAABwFAAAwBQAATwUAAF4FAABhBQAA" +
      "ZAUAAGgFAABsBQAAeQUAAH4FAACGBQAAlgUAAKEFAACnBQAArwUAAMAFAADKBQAA0QUAAAgAAAAJ" +
      "AAAACgAAAAsAAAAMAAAADQAAAA4AAAAPAAAAEAAAABEAAAASAAAAEwAAABQAAAAVAAAAGwAAABwA" +
      "AAAeAAAABgAAAAsAAAAAAAAABwAAAAwAAAAMAwAABwAAAA0AAAAUAwAAGwAAAA4AAAAAAAAAHQAA" +
      "AA8AAAAcAwAAAQABABcAAAACABAABAAAAAIAEAAFAAAAAgANACYAAAAAAAMAAgAAAAIAAwABAAAA" +
      "AgADAAIAAAACAAMAIgAAAAIAAAAnAAAAAwADACMAAAAMAAMAAgAAAAwAAQAhAAAADAAAACcAAAAN" +
      "AAQAIAAAAA0AAgAlAAAADQAAACcAAAACAAAAAQAAAAAAAAAEAwAAGgAAAIwGAABRBgAAAAAAAAQA" +
      "AQACAAAA+gIAAB0AAABUMAMAbhALAAAADAAiAQwAcBAGAAEAGgIZAG4gBwAhAG4gBwABABoAAABu" +
      "IAcAAQBuEAgAAQAMABEAAAABAAAAAAAAAPQCAAAGAAAAEgBpAAEAaQACAA4AAgABAAEAAADuAgAA" +
      "DAAAAHAQAAABABwAAQBxEAoAAAAMAFsQAwAOAAMAAQACAAAA/gIAAAsAAABUIAMAYgEAAG4gCQAQ" +
      "AHEABQAAAA4AIQAOPIcAGwAOPC0AJQAOACkADnk8AAEAAAAKAAAAAQAAAAsAAAABAAAACAAAAAEA" +
      "AAAJABUgY3VycmVudDogUkVERUZJTkVEIH0ACDxjbGluaXQ+AAY8aW5pdD4AAj47AAtDTEFTU19C" +
      "WVRFUwAJREVYX0JZVEVTAAFMAAJMTAAhTGFydC9UZXN0MTk1MyRBYnN0cmFjdFRlc3RPYmplY3Q7" +
      "AC9MYXJ0L1Rlc3QxOTUzJFJlZGVmaW5lVGVzdE9iamVjdCRSZWRlZmluZVN0YXRlOwAhTGFydC9U" +
      "ZXN0MTk1MyRSZWRlZmluZVRlc3RPYmplY3Q7AA5MYXJ0L1Rlc3QxOTUzOwAiTGRhbHZpay9hbm5v" +
      "dGF0aW9uL0VuY2xvc2luZ0NsYXNzOwAeTGRhbHZpay9hbm5vdGF0aW9uL0lubmVyQ2xhc3M7ACFM" +
      "ZGFsdmlrL2Fubm90YXRpb24vTWVtYmVyQ2xhc3NlczsAHUxkYWx2aWsvYW5ub3RhdGlvbi9TaWdu" +
      "YXR1cmU7ABFMamF2YS9sYW5nL0NsYXNzOwASTGphdmEvbGFuZy9PYmplY3Q7ABRMamF2YS9sYW5n" +
      "L1J1bm5hYmxlOwASTGphdmEvbGFuZy9TdHJpbmc7ABlMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7" +
      "ABNMamF2YS91dGlsL0VudW1TZXQ7ABNMamF2YS91dGlsL0VudW1TZXQ8AAlSRURFRklORUQAElJl" +
      "ZGVmaW5lVGVzdE9iamVjdAAdUmVkZWZpbmVUZXN0T2JqZWN0IHsgc3RhdGVzOiAADVRlc3QxOTUz" +
      "LmphdmEAAVYAAVoAAlpMAAJbQgALYWNjZXNzRmxhZ3MAA2FkZAAGYXBwZW5kAA5jYWxsZWRGdW5j" +
      "dGlvbgAJZG9Ob3RoaW5nAARuYW1lAAZub25lT2YAD3JlZGVmaW5lX3N0YXRlcwAIdG9TdHJpbmcA" +
      "BXZhbHVlAFt+fkQ4eyJtaW4tYXBpIjoxLCJzaGEtMSI6IjUyNzNjM2RmZWUxMDQ2NzIwYWY0MjVm" +
      "YTg1NTMxNmM5OWM4NmM4ZDIiLCJ2ZXJzaW9uIjoiMS4zLjE4LWRldiJ9AAIHASgcAxcWFwkXAwIE" +
      "ASgYAwIFAh8ECSQXGAIGASgcARgBAgECAgEZARkDAQGIgASEBQGBgASgBQMByAUBAbgEAAAAAAAB" +
      "AAAALgYAAAMAAAA6BgAAQAYAAEkGAAB8BgAAAQAAAAAAAAAAAAAAAwAAAHQGAAAQAAAAAAAAAAEA" +
      "AAAAAAAAAQAAACoAAABwAAAAAgAAABEAAAAYAQAAAwAAAAUAAABcAQAABAAAAAQAAACYAQAABQAA" +
      "AAwAAAC4AQAABgAAAAEAAAAYAgAAASAAAAQAAAA4AgAAAyAAAAQAAADuAgAAARAAAAQAAAAEAwAA" +
      "AiAAACoAAAAiAwAABCAAAAQAAAAuBgAAACAAAAEAAABRBgAAAxAAAAMAAABwBgAABiAAAAEAAACM" +
      "BgAAABAAAAEAAACkBgAA");

    public EnumSet<RedefineState> redefine_states;
    public RedefineTestObject() {
      super();
      redefine_states = EnumSet.noneOf(RedefineState.class);
    }

    public String toString() {
      return "RedefineTestObject { states: " + redefine_states.toString() + " current: ORIGINAL }";
    }

    public void calledFunction() {
      redefine_states.add(RedefineState.ORIGINAL);  // line +0
      // We will trigger the redefinition using a breakpoint on the next line.
      doNothing();                                  // line +2
    }
  }

  public static class ClassLoadObject implements TestRunnable {
    public int cnt;
    public int baseCallCnt;

    public static final String[] CLASS_NAMES = new String[] {
      "Lart/Test1953$ClassLoadObject$TC0;",
      "Lart/Test1953$ClassLoadObject$TC1;",
      "Lart/Test1953$ClassLoadObject$TC2;",
      "Lart/Test1953$ClassLoadObject$TC3;",
      "Lart/Test1953$ClassLoadObject$TC4;",
      "Lart/Test1953$ClassLoadObject$TC5;",
      "Lart/Test1953$ClassLoadObject$TC6;",
      "Lart/Test1953$ClassLoadObject$TC7;",
      "Lart/Test1953$ClassLoadObject$TC8;",
      "Lart/Test1953$ClassLoadObject$TC9;",
    };

    private static int curClass = 0;

    private static class TC0 { public static int foo; static { foo = 1; } }
    private static class TC1 { public static int foo; static { foo = 2; } }
    private static class TC2 { public static int foo; static { foo = 3; } }
    private static class TC3 { public static int foo; static { foo = 4; } }
    private static class TC4 { public static int foo; static { foo = 5; } }
    private static class TC5 { public static int foo; static { foo = 6; } }
    private static class TC6 { public static int foo; static { foo = 7; } }
    private static class TC7 { public static int foo; static { foo = 8; } }
    private static class TC8 { public static int foo; static { foo = 9; } }
    private static class TC9 { public static int foo; static { foo = 10; } }

    public ClassLoadObject() {
      super();
      cnt = 0;
      baseCallCnt = 0;
    }

    public int getBaseCallCount() {
      return baseCallCnt;
    }

    public void run() {
      baseCallCnt++;
      if (curClass == 0) {
        $noprecompile$calledFunction0();
      } else if (curClass == 1) {
        $noprecompile$calledFunction1();
      } else if (curClass == 2) {
        $noprecompile$calledFunction2();
      } else if (curClass == 3) {
        $noprecompile$calledFunction3();
      } else if (curClass == 4) {
        $noprecompile$calledFunction4();
      } else if (curClass == 5) {
        $noprecompile$calledFunction5();
      } else if (curClass == 6) {
        $noprecompile$calledFunction6();
      } else if (curClass == 7) {
        $noprecompile$calledFunction7();
      } else if (curClass == 8) {
        $noprecompile$calledFunction8();
      } else if (curClass == 9) {
        $noprecompile$calledFunction9();
      }
      curClass++;
    }

    public Method getCalledMethod() throws Exception {
      return this.getClass().getMethod("jnoprecompile$calledFunction" + curClass);
    }

    // Give these all a tag to prevent 1954 from compiling them (and loading the class as a
    // consequence).
    public void $noprecompile$calledFunction0() {
      cnt++;
      System.out.println("TC0.foo == " + TC0.foo);
    }

    public void $noprecompile$calledFunction1() {
      cnt++;
      System.out.println("TC1.foo == " + TC1.foo);
    }

    public void $noprecompile$calledFunction2() {
      cnt++;
      System.out.println("TC2.foo == " + TC2.foo);
    }

    public void $noprecompile$calledFunction3() {
      cnt++;
      System.out.println("TC3.foo == " + TC3.foo);
    }

    public void $noprecompile$calledFunction4() {
      cnt++;
      System.out.println("TC4.foo == " + TC4.foo);
    }

    public void $noprecompile$calledFunction5() {
      cnt++;
      System.out.println("TC5.foo == " + TC5.foo);
    }

    public void $noprecompile$calledFunction6() {
      cnt++;
      System.out.println("TC6.foo == " + TC6.foo);
    }

    public void $noprecompile$calledFunction7() {
      cnt++;
      System.out.println("TC7.foo == " + TC7.foo);
    }

    public void $noprecompile$calledFunction8() {
      cnt++;
      System.out.println("TC8.foo == " + TC8.foo);
    }

    public void $noprecompile$calledFunction9() {
      cnt++;
      System.out.println("TC9.foo == " + TC9.foo);
    }

    public String toString() {
      return "ClassLoadObject { cnt: " + cnt + ", curClass: " + curClass + "}";
    }
  }

  public static class FieldBasedTestObject extends AbstractTestObject implements Runnable {
    public int cnt;
    public int TARGET_FIELD;
    public FieldBasedTestObject() {
      super();
      cnt = 0;
      TARGET_FIELD = 0;
    }

    public void calledFunction() {
      cnt++;
      // We put a watchpoint here and PopFrame when we are at it.
      TARGET_FIELD += 10;
      if (cnt == 1) { System.out.println("FAILED: No pop on first call!"); }
    }

    public String toString() {
      return "FieldBasedTestObject { cnt: " + cnt + ", TARGET_FIELD: " + TARGET_FIELD + " }";
    }
  }

  public static class StandardTestObject extends AbstractTestObject implements Runnable {
    public int cnt;
    public final boolean check;

    public StandardTestObject(boolean check) {
      super();
      cnt = 0;
      this.check = check;
    }

    public StandardTestObject() {
      this(true);
    }

    public void calledFunction() {
      cnt++;       // line +0
      // We put a breakpoint here and PopFrame when we are at it.
      doNothing(); // line +2
      if (check && cnt == 1) { System.out.println("FAILED: No pop on first call!"); }
    }

    public String toString() {
      return "StandardTestObject { cnt: " + cnt + " }";
    }
  }

  public static class SynchronizedFunctionTestObject extends AbstractTestObject implements Runnable {
    public int cnt;

    public SynchronizedFunctionTestObject() {
      super();
      cnt = 0;
    }

    public synchronized void calledFunction() {
      cnt++;               // line +0
      // We put a breakpoint here and PopFrame when we are at it.
      doNothing();         // line +2
    }

    public String toString() {
      return "SynchronizedFunctionTestObject { cnt: " + cnt + " }";
    }
  }
  public static class SynchronizedTestObject extends AbstractTestObject implements Runnable {
    public int cnt;
    public final Object lock;

    public SynchronizedTestObject() {
      this(new Object());
    }

    public SynchronizedTestObject(Object l) {
      super();
      cnt = 0;
      lock = l;
    }

    public void calledFunction() {
      synchronized (lock) {  // line +0
        cnt++;               // line +1
        // We put a breakpoint here and PopFrame when we are at it.
        doNothing();         // line +3
      }
    }

    public String toString() {
      return "SynchronizedTestObject { cnt: " + cnt + " }";
    }
  }

  public static class ExceptionCatchTestObject extends AbstractTestObject implements Runnable {
    public static class TestError extends Error {}

    public int cnt;
    public ExceptionCatchTestObject() {
      super();
      cnt = 0;
    }

    public void calledFunction() {
      cnt++;
      try {
        doThrow();
      } catch (TestError e) {
        System.out.println(e.getClass().getName() + " caught in called function.");
      }
    }

    public void doThrow() {
      throw new TestError();
    }

    public String toString() {
      return "ExceptionCatchTestObject { cnt: " + cnt + " }";
    }
  }

  public static class ExceptionThrowFarTestObject implements TestRunnable {
    public static class TestError extends Error {}

    public int cnt;
    public int baseCallCnt;
    public final boolean catchInCalled;
    public ExceptionThrowFarTestObject(boolean catchInCalled) {
      super();
      cnt = 0;
      baseCallCnt = 0;
      this.catchInCalled = catchInCalled;
    }

    public int getBaseCallCount() {
      return baseCallCnt;
    }

    public void run() {
      baseCallCnt++;
      try {
        callingFunction();
      } catch (TestError e) {
        System.out.println(e.getClass().getName() + " thrown and caught!");
      }
    }

    public void callingFunction() {
      calledFunction();
    }
    public void calledFunction() {
      cnt++;
      if (catchInCalled) {
        try {
          throw new TestError(); // We put a watch here.
        } catch (TestError e) {
          System.out.println(e.getClass().getName() + " caught in same function.");
        }
      } else {
        throw new TestError(); // We put a watch here.
      }
    }

    public Method getCallingMethod() throws Exception {
      return this.getClass().getMethod("callingFunction");
    }

    public Method getCalledMethod() throws Exception {
      return this.getClass().getMethod("calledFunction");
    }

    public String toString() {
      return "ExceptionThrowFarTestObject { cnt: " + cnt + " }";
    }
  }

  public static class ExceptionOnceObject extends AbstractTestObject {
    public static final class TestError extends Error {}
    public int cnt;
    public final boolean throwInSub;
    public ExceptionOnceObject(boolean throwInSub) {
      super();
      cnt = 0;
      this.throwInSub = throwInSub;
    }

    public void calledFunction() {
      cnt++;
      if (cnt == 1) {
        if (throwInSub) {
          doThrow();
        } else {
          throw new TestError();
        }
      }
    }

    public void doThrow() {
      throw new TestError();
    }

    public String toString() {
      return "ExceptionOnceObject { cnt: " + cnt + ", throwInSub: " + throwInSub + " }";
    }
  }

  public static class ExceptionThrowTestObject implements TestRunnable {
    public static class TestError extends Error {}

    public int cnt;
    public int baseCallCnt;
    public final boolean catchInCalled;
    public ExceptionThrowTestObject(boolean catchInCalled) {
      super();
      cnt = 0;
      baseCallCnt = 0;
      this.catchInCalled = catchInCalled;
    }

    public int getBaseCallCount() {
      return baseCallCnt;
    }

    public void run() {
      baseCallCnt++;
      try {
        calledFunction();
      } catch (TestError e) {
        System.out.println(e.getClass().getName() + " thrown and caught!");
      }
    }

    public void calledFunction() {
      cnt++;
      if (catchInCalled) {
        try {
          throw new TestError(); // We put a watch here.
        } catch (TestError e) {
          System.out.println(e.getClass().getName() + " caught in same function.");
        }
      } else {
        throw new TestError(); // We put a watch here.
      }
    }

    public Method getCalledMethod() throws Exception {
      return this.getClass().getMethod("calledFunction");
    }

    public String toString() {
      return "ExceptionThrowTestObject { cnt: " + cnt + " }";
    }
  }

  public static class NativeCalledObject extends AbstractTestObject {
    public int cnt = 0;

    public native void calledFunction();

    public String toString() {
      return "NativeCalledObject { cnt: " + cnt + " }";
    }
  }

  public static class NativeCallerObject implements TestRunnable {
    public int baseCnt = 0;
    public int cnt = 0;

    public int getBaseCallCount() {
      return baseCnt;
    }

    public native void run();

    public void calledFunction() {
      cnt++;
      // We will stop using a MethodExit event.
    }

    public Method getCalledMethod() throws Exception {
      return this.getClass().getMethod("calledFunction");
    }

    public String toString() {
      return "NativeCallerObject { cnt: " + cnt + " }";
    }
  }
  public static class SuspendSuddenlyObject extends AbstractTestObject {
    public volatile boolean stop_spinning = false;
    public volatile boolean is_spinning = false;
    public int cnt = 0;

    public void calledFunction() {
      cnt++;
      while (!stop_spinning) {
        is_spinning = true;
      }
    }

    public String toString() {
      return "SuspendSuddenlyObject { cnt: " + cnt + " }";
    }
  }

  public static void run(boolean canRunClassLoadTests) throws Exception {
    new Test1953(canRunClassLoadTests, (x)-> {}).runTests();
  }

  // This entrypoint is used by CTS only. */
  public static void run() throws Exception {
    /* TODO: Due to the way that CTS tests are verified we cannot run class-load-tests since the
     *       verifier will be delayed until runtime and then load the classes all at once. This
     *       makes the test impossible to run.
     */

    run(/*canRunClassLoadTests*/ false);
  }

  public Test1953(boolean canRunClassLoadTests, Consumer<TestRunnable> preTest) {
    this.canRunClassLoadTests = canRunClassLoadTests;
    this.preTest = preTest;
  }

  private Consumer<TestRunnable> preTest;

  public void runTests() throws Exception {
    setupTest();

    final Method calledFunction = StandardTestObject.class.getDeclaredMethod("calledFunction");
    final Method doNothingMethod = Test1953.class.getDeclaredMethod("doNothing");
    // Add a breakpoint on the second line after the start of the function
    final int line = Breakpoint.locationToLine(calledFunction, 0) + 2;
    final long loc = Breakpoint.lineToLocation(calledFunction, line);
    System.out.println("Test stopped using breakpoint");
    runTestOn(new StandardTestObject(),
        (thr) -> setupSuspendBreakpointFor(calledFunction, loc, thr),
        SuspendEvents::clearSuspendBreakpointFor);

    final Method syncFunctionCalledFunction =
        SynchronizedFunctionTestObject.class.getDeclaredMethod("calledFunction");
    // Add a breakpoint on the second line after the start of the function
    // Annoyingly r8 generally has the first instruction (a monitor enter) not be marked as being
    // on any line but javac has it marked as being on the first line of the function. Just use the
    // second entry on the line-number table to get the breakpoint. This should be good for both.
    final long syncFunctionLoc =
        Breakpoint.getLineNumberTable(syncFunctionCalledFunction)[1].location;
    System.out.println("Test stopped using breakpoint with declared synchronized function");
    runTestOn(new SynchronizedFunctionTestObject(),
        (thr) -> setupSuspendBreakpointFor(syncFunctionCalledFunction, syncFunctionLoc, thr),
        SuspendEvents::clearSuspendBreakpointFor);

    final Method syncCalledFunction =
        SynchronizedTestObject.class.getDeclaredMethod("calledFunction");
    // Add a breakpoint on the second line after the start of the function
    final int syncLine = Breakpoint.locationToLine(syncCalledFunction, 0) + 3;
    final long syncLoc = Breakpoint.lineToLocation(syncCalledFunction, syncLine);
    System.out.println("Test stopped using breakpoint with synchronized block");
    Object lock = new Object();
    synchronized (lock) {}
    runTestOn(new SynchronizedTestObject(lock),
        (thr) -> setupSuspendBreakpointFor(syncCalledFunction, syncLoc, thr),
        SuspendEvents::clearSuspendBreakpointFor);
    synchronized (lock) {}

    System.out.println("Test stopped on single step");
    runTestOn(new StandardTestObject(),
        (thr) -> setupSuspendSingleStepAt(calledFunction, loc, thr),
        SuspendEvents::clearSuspendSingleStepFor);

    final Field target_field = FieldBasedTestObject.class.getDeclaredField("TARGET_FIELD");
    System.out.println("Test stopped on field access");
    runTestOn(new FieldBasedTestObject(),
        (thr) -> setupFieldSuspendFor(FieldBasedTestObject.class, target_field, true, thr),
        SuspendEvents::clearFieldSuspendFor);

    System.out.println("Test stopped on field modification");
    runTestOn(new FieldBasedTestObject(),
        (thr) -> setupFieldSuspendFor(FieldBasedTestObject.class, target_field, false, thr),
        SuspendEvents::clearFieldSuspendFor);

    System.out.println("Test stopped during Method Exit of doNothing");
    runTestOn(new StandardTestObject(false),
        (thr) -> setupSuspendMethodEvent(doNothingMethod, /*enter*/ false, thr),
        SuspendEvents::clearSuspendMethodEvent);

    // NB We need another test to make sure the MethodEntered event is triggered twice.
    System.out.println("Test stopped during Method Enter of doNothing");
    runTestOn(new StandardTestObject(false),
        (thr) -> setupSuspendMethodEvent(doNothingMethod, /*enter*/ true, thr),
        SuspendEvents::clearSuspendMethodEvent);

    System.out.println("Test stopped during Method Exit of calledFunction");
    runTestOn(new StandardTestObject(false),
        (thr) -> setupSuspendMethodEvent(calledFunction, /*enter*/ false, thr),
        SuspendEvents::clearSuspendMethodEvent);

    System.out.println("Test stopped during Method Enter of calledFunction");
    runTestOn(new StandardTestObject(false),
        (thr) -> setupSuspendMethodEvent(calledFunction, /*enter*/ true, thr),
        SuspendEvents::clearSuspendMethodEvent);

    final Method exceptionOnceCalledMethod =
        ExceptionOnceObject.class.getDeclaredMethod("calledFunction");
    System.out.println("Test stopped during Method Exit due to exception thrown in same function");
    runTestOn(new ExceptionOnceObject(/*throwInSub*/ false),
        (thr) -> setupSuspendMethodEvent(exceptionOnceCalledMethod, /*enter*/ false, thr),
        SuspendEvents::clearSuspendMethodEvent);

    System.out.println("Test stopped during Method Exit due to exception thrown in subroutine");
    runTestOn(new ExceptionOnceObject(/*throwInSub*/ true),
        (thr) -> setupSuspendMethodEvent(exceptionOnceCalledMethod, /*enter*/ false, thr),
        SuspendEvents::clearSuspendMethodEvent);

    final Method exceptionThrowCalledMethod =
        ExceptionThrowTestObject.class.getDeclaredMethod("calledFunction");
    final Method exceptionCatchThrowMethod =
        ExceptionCatchTestObject.class.getDeclaredMethod("doThrow");
    // Disable more often then we technically need to in order to avoid the need
    // for a huge number of possible results and allow the test to be easily
    // used in CTS.
    if (IS_ART && canRunClassLoadTests && CanRunClassLoadingTests()) {
      System.out.println("Test stopped during notifyFramePop without exception on pop of calledFunction");
      runTestOn(new StandardTestObject(false),
          (thr) -> setupSuspendPopFrameEvent(1, doNothingMethod, thr),
          SuspendEvents::clearSuspendPopFrameEvent);

      System.out.println("Test stopped during notifyFramePop without exception on pop of doNothing");
      runTestOn(new StandardTestObject(false),
          (thr) -> setupSuspendPopFrameEvent(0, doNothingMethod, thr),
          SuspendEvents::clearSuspendPopFrameEvent);

      System.out.println("Test stopped during notifyFramePop with exception on pop of calledFunction");
      runTestOn(new ExceptionThrowTestObject(false),
          (thr) -> setupSuspendPopFrameEvent(0, exceptionThrowCalledMethod, thr),
          SuspendEvents::clearSuspendPopFrameEvent);

      System.out.println("Test stopped during notifyFramePop with exception on pop of doThrow");
      runTestOn(new ExceptionCatchTestObject(),
          (thr) -> setupSuspendPopFrameEvent(0, exceptionCatchThrowMethod, thr),
          SuspendEvents::clearSuspendPopFrameEvent);
    }

    System.out.println("Test stopped during ExceptionCatch event of calledFunction " +
        "(catch in called function, throw in called function)");
    runTestOn(new ExceptionThrowTestObject(true),
        (thr) -> setupSuspendExceptionEvent(exceptionThrowCalledMethod, /*catch*/ true, thr),
        SuspendEvents::clearSuspendExceptionEvent);

    final Method exceptionCatchCalledMethod =
        ExceptionCatchTestObject.class.getDeclaredMethod("calledFunction");
    System.out.println("Test stopped during ExceptionCatch event of calledFunction " +
        "(catch in called function, throw in subroutine)");
    runTestOn(new ExceptionCatchTestObject(),
        (thr) -> setupSuspendExceptionEvent(exceptionCatchCalledMethod, /*catch*/ true, thr),
        SuspendEvents::clearSuspendExceptionEvent);

    System.out.println("Test stopped during Exception event of calledFunction " +
        "(catch in calling function)");
    runTestOn(new ExceptionThrowTestObject(false),
        (thr) -> setupSuspendExceptionEvent(exceptionThrowCalledMethod, /*catch*/ false, thr),
        SuspendEvents::clearSuspendExceptionEvent);

    System.out.println("Test stopped during Exception event of calledFunction " +
        "(catch in called function)");
    runTestOn(new ExceptionThrowTestObject(true),
        (thr) -> setupSuspendExceptionEvent(exceptionThrowCalledMethod, /*catch*/ false, thr),
        SuspendEvents::clearSuspendExceptionEvent);

    final Method exceptionThrowFarCalledMethod =
        ExceptionThrowFarTestObject.class.getDeclaredMethod("calledFunction");
    System.out.println("Test stopped during Exception event of calledFunction " +
        "(catch in parent of calling function)");
    runTestOn(new ExceptionThrowFarTestObject(false),
        (thr) -> setupSuspendExceptionEvent(exceptionThrowFarCalledMethod, /*catch*/ false, thr),
        SuspendEvents::clearSuspendExceptionEvent);

    System.out.println("Test stopped during Exception event of calledFunction " +
        "(catch in called function)");
    runTestOn(new ExceptionThrowFarTestObject(true),
        (thr) -> setupSuspendExceptionEvent(exceptionThrowFarCalledMethod, /*catch*/ false, thr),
        SuspendEvents::clearSuspendExceptionEvent);

    // These tests are disabled for either the RI (b/116003018) or for jvmti-stress. For the
    // later it is due to the additional agent causing classes to be loaded earlier as it forces
    // deeper verification during class redefinition, causing failures.
    // NB the agent is prevented from popping frames in either of these events in ART. See
    // b/117615146 for more information about this restriction.
    if (canRunClassLoadTests && CanRunClassLoadingTests()) {
      // This test doesn't work on RI since the RI disallows use of PopFrame during a ClassLoad
      // event. See b/116003018 for more information.
      System.out.println("Test stopped during a ClassLoad event.");
      runTestOn(new ClassLoadObject(),
          (thr) -> setupSuspendClassEvent(EVENT_TYPE_CLASS_LOAD, ClassLoadObject.CLASS_NAMES, thr),
          SuspendEvents::clearSuspendClassEvent);

      // The RI handles a PopFrame during a ClassPrepare event incorrectly. See b/116003018 for
      // more information.
      System.out.println("Test stopped during a ClassPrepare event.");
      runTestOn(new ClassLoadObject(),
          (thr) -> setupSuspendClassEvent(EVENT_TYPE_CLASS_PREPARE,
                                          ClassLoadObject.CLASS_NAMES,
                                          thr),
          SuspendEvents::clearSuspendClassEvent);
    }
    System.out.println("Test stopped during random Suspend.");
    final SuspendSuddenlyObject sso = new SuspendSuddenlyObject();
    runTestOn(
        sso,
        new TestSuspender() {
          public void setup(Thread thr) { }
          public void waitForSuspend(Thread thr) {
            while (!sso.is_spinning) {}
            Suspension.suspend(thr);
          }
          public void cleanup(Thread thr) {
            sso.stop_spinning = true;
          }
        });

    final Method redefineCalledFunction =
       RedefineTestObject.class.getDeclaredMethod("calledFunction");
    final int redefLine = Breakpoint.locationToLine(redefineCalledFunction, 0) + 2;
    final long redefLoc = Breakpoint.lineToLocation(redefineCalledFunction, redefLine);
    System.out.println("Test redefining frame being popped.");
    runTestOn(new RedefineTestObject(),
        (thr) -> setupSuspendBreakpointFor(redefineCalledFunction, redefLoc, thr),
        (thr) -> {
          clearSuspendBreakpointFor(thr);
          Redefinition.doCommonClassRedefinition(RedefineTestObject.class,
                                                 RedefineTestObject.CLASS_BYTES,
                                                 RedefineTestObject.DEX_BYTES);
        });

    System.out.println("Test stopped during a native method fails");
    runTestOn(new NativeCalledObject(),
        SuspendEvents::setupWaitForNativeCall,
        SuspendEvents::clearWaitForNativeCall);

    System.out.println("Test stopped in a method called by native fails");
    final Method nativeCallerMethod = NativeCallerObject.class.getDeclaredMethod("calledFunction");
    runTestOn(new NativeCallerObject(),
        (thr) -> setupSuspendMethodEvent(nativeCallerMethod, /*enter*/ false, thr),
        SuspendEvents::clearSuspendMethodEvent);


    final Object lock2 = new Object();
    synchronized (lock2) {}
    System.out.println("Test stopped with monitor in enclosing frame.");
    runTestOn(new StandardTestObject() {
          @Override
          public void run() {
            synchronized (lock2) {
              super.run();
            }
          }
        },
        (thr) -> setupSuspendBreakpointFor(calledFunction, loc, thr),
        SuspendEvents::clearSuspendBreakpointFor);
    synchronized (lock2) {}
  }

  // Volatile is to prevent any future optimizations that could invalidate this test by doing
  // constant propagation and eliminating the failing paths before the verifier is able to load the
  // class.
  static volatile boolean ranClassLoadTest = false;
  static boolean classesPreverified = false;
  private static final class RCLT0 { public void foo() {} }
  private static final class RCLT1 { public void foo() {} }
  // If classes are not preverified for some reason (interp-ac, no-image, etc) the verifier will
  // actually load classes as it runs. This means that we cannot use the class-load tests as they
  // are written. TODO Support this.
  public boolean CanRunClassLoadingTests() {
    if (ranClassLoadTest) {
      return classesPreverified;
    }
    if (!ranClassLoadTest) {
      // Only this will ever be executed.
      new RCLT0().foo();
    } else {
      // This will never be executed. If classes are not preverified the verifier will load RCLT1
      // when the enclosing method is run. This behavior makes the class-load/prepare test cases
      // impossible to successfully run (they will deadlock).
      new RCLT1().foo();
      System.out.println("FAILURE: UNREACHABLE Location!");
    }
    classesPreverified = !isClassLoaded("Lart/Test1953$RCLT1;");
    ranClassLoadTest = true;
    return classesPreverified;
  }

  public static native boolean isClassLoaded(String name);
  public static native void popFrame(Thread thr);
}

Messung V0.5 in Prozent
C=88 H=92 G=89

¤ Dauer der Verarbeitung: 0.17 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik