147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light/*
247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * Copyright (C) 2017 The Android Open Source Project
347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light *
447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * Licensed under the Apache License, Version 2.0 (the "License");
547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * you may not use this file except in compliance with the License.
647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * You may obtain a copy of the License at
747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light *
847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light *      http://www.apache.org/licenses/LICENSE-2.0
947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light *
1047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * Unless required by applicable law or agreed to in writing, software
1147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * distributed under the License is distributed on an "AS IS" BASIS,
1247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * See the License for the specific language governing permissions and
1447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * limitations under the License.
1547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light */
1647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light
1747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightpackage art;
1847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light
1947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.io.PrintWriter;
2047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.io.StringWriter;
2147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.lang.reflect.Executable;
2247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.lang.reflect.Method;
2347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.lang.reflect.Field;
2447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.ArrayList;
2547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.Arrays;
2647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.Collection;
2747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.HashSet;
2847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.List;
2947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.concurrent.Semaphore;
3047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.Vector;
3147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.function.Function;
3247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.function.Predicate;
3347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.function.Supplier;
3447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.function.Consumer;
3547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light
3647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightpublic class Test1917 {
3747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light  public final static boolean TEST_PRINT_ALL = false;
3847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light
3947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light  public static class ThreadPauser implements Runnable {
4047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    public Semaphore sem_wakeup_main = new Semaphore(0);
4147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    public Semaphore sem_wait = new Semaphore(0);
4247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light
4347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    public void run() {
4447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      try {
4547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light        sem_wakeup_main.release();
4647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light        sem_wait.acquire();
4747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      } catch (Exception e) {
4847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light        throw new Error("Error with semaphores!", e);
4947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      }
5047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    }
5147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light
5247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    public void waitForOtherThreadToPause() throws Exception {
5347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      sem_wakeup_main.acquire();
544013595d91898c5a18fbc480cbd4023c4307ec62Alex Light      while (!sem_wait.hasQueuedThreads()) {}
5547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    }
5647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light
5747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    public void wakeupOtherThread() throws Exception {
5847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      sem_wait.release();
5947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    }
6047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light  }
6147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light
6247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light  public static class StackTraceGenerator implements Runnable {
6347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    private final Thread thr;
6447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    private final Consumer<StackTrace.StackFrameData> con;
6547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    public StackTraceGenerator(Thread thr, Consumer<StackTrace.StackFrameData> con) {
6647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      this.thr = thr;
6747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      this.con = con;
6847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    }
6947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light
7047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    public StackTraceGenerator(Consumer<StackTrace.StackFrameData> con) {
7147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      this(null, con);
7247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    }
7347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light
7447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    public Thread getThread() {
7547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      if (thr == null) {
7647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light        return Thread.currentThread();
7747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      } else {
7847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light        return thr;
7947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      }
8047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    }
8147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    public void run() {
8247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      for (StackTrace.StackFrameData s : StackTrace.GetStackTrace(getThread())) {
8347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light        con.accept(s);
8447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      }
8547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    }
8647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light  }
8747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light
8847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light  public static class RecurCount implements Runnable {
8947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    private final int cnt;
9047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    private final Runnable then;
9147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    public RecurCount(int cnt, Runnable then) {
9247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      this.cnt = cnt;
9347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      this.then = then;
9447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    }
9547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light
9647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    public void run() {
9747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      doRecur(0);
9847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    }
9947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light
10047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    public void doRecur(int n) {
10147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      if (n < cnt) {
10247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light        doRecur(n + 1);
10347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      } else {
10447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light        then.run();
10547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      }
10647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    }
10747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light  }
10847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light
10947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light  public static Consumer<StackTrace.StackFrameData> makePrintStackFramesConsumer()
11047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      throws Exception {
11147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    final Method end_method = Test1917.class.getDeclaredMethod("run");
11247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    return new Consumer<StackTrace.StackFrameData>() {
11347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      public void accept(StackTrace.StackFrameData data) {
11447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light        if (TEST_PRINT_ALL) {
11547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light          System.out.println(data);
11647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light        } else {
11747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light          Package p = data.method.getDeclaringClass().getPackage();
11847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light          // Filter out anything to do with the testing harness.
11947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light          if (p != null && p.equals(Test1917.class.getPackage())) {
12047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light            System.out.printf("'%s' line: %d\n",
12147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light                data.method,
12247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light                Breakpoint.locationToLine(data.method, data.current_location));
12347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light          } else if (data.method.getDeclaringClass().equals(Semaphore.class)) {
12447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light            System.out.printf("'%s' line: <NOT-DETERMINISTIC>\n", data.method);
12547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light          }
12647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light        }
12747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light      }
12847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    };
12947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light  }
13047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light
13147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light  public static void run() throws Exception {
13247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    System.out.println("Recurring 5 times");
13347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    new RecurCount(5, new StackTraceGenerator(makePrintStackFramesConsumer())).run();
13447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light
13547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    System.out.println("Recurring 5 times on another thread");
13647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    Thread thr = new Thread(
13747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light        new RecurCount(5, new StackTraceGenerator(makePrintStackFramesConsumer())));
13847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    thr.start();
13947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    thr.join();
14047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light
14147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    System.out.println("Recurring 5 times on another thread. Stack trace from main thread!");
14247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    ThreadPauser pause = new ThreadPauser();
14347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    Thread thr2 = new Thread(new RecurCount(5, pause));
14447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    thr2.start();
14547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    pause.waitForOtherThreadToPause();
14647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    new StackTraceGenerator(thr2, makePrintStackFramesConsumer()).run();
14747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    pause.wakeupOtherThread();
14847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light    thr2.join();
14947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light  }
15047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light}
151