/*
 * 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.util.concurrent.CountDownLatch;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Test923 {
  public static void run() throws Exception {
    Main.bindAgentJNIForClass(Test923.class);
    doTest();
  }

  private static void doTest() throws Exception {
    // Start a watchdog, to make sure on deadlocks etc the test dies.
    startWatchdog();

    sharedId = createRawMonitor();

    output = new ArrayList<String>(100);

    simpleTests(sharedId);

    for (String s : output) {
      System.out.println(s);
    }
    output.clear();

    threadTests(sharedId);

    destroyRawMonitor(sharedId);
  }

  private static void simpleTests(long id) {
    unlock(id);  // Should fail.

    lock(id);
    unlock(id);
    unlock(id);  // Should fail.

    lock(id);
    lock(id);
    unlock(id);
    unlock(id);
    unlock(id);  // Should fail.

    rawWait(id, 0);   // Should fail.
    rawWait(id, -1);  // Should fail.
    rawWait(id, 1);   // Should fail.

    lock(id);
    rawWait(id, 50);
    unlock(id);
    unlock(id);  // Should fail.

    rawNotify(id);  // Should fail.
    lock(id);
    rawNotify(id);
    unlock(id);
    unlock(id);  // Should fail.

    rawNotifyAll(id);  // Should fail.
    lock(id);
    rawNotifyAll(id);
    unlock(id);
    unlock(id);  // Should fail.
  }

  private static void threadTests(final long id) throws Exception {
    final int N = 10;

    final CountDownLatch waitLatch = new CountDownLatch(N);
    final CountDownLatch wait2Latch = new CountDownLatch(1);

    Runnable r = new Runnable() {
      @Override
      public void run() {
        lock(id);
        waitLatch.countDown();
        rawWait(id, 0);
        firstAwakened = Thread.currentThread();
        appendToLog("Awakened");
        unlock(id);
        wait2Latch.countDown();
      }
    };

    List<Thread> threads = new ArrayList<Thread>();
    for (int i = 0; i < N; i++) {
      Thread t = new Thread(r);
      threads.add(t);
      t.start();
    }

    // Wait till all threads have been started.
    waitLatch.await();

    // Hopefully enough time for all the threads to progress into wait.
    Thread.yield();
    Thread.sleep(500);

    // Wake up one.
    lock(id);
    rawNotify(id);
    unlock(id);

    wait2Latch.await();

    // Wait a little bit more to see stragglers. This is flaky - spurious wakeups could
    // make the test fail.
    Thread.yield();
    Thread.sleep(500);
    if (firstAwakened != null) {
      firstAwakened.join();
    }

    // Wake up everyone else.
    lock(id);
    rawNotifyAll(id);
    unlock(id);

    // Wait for everyone to die.
    for (Thread t : threads) {
      t.join();
    }

    // Check threaded output.
    Iterator<String> it = output.iterator();
    // 1) Start with N locks and Waits.
    {
      int locks = 0;
      int waits = 0;
      for (int i = 0; i < 2*N; i++) {
        String s = it.next();
        if (s.equals("Lock")) {
          locks++;
        } else if (s.equals("Wait")) {
          if (locks <= waits) {
            System.out.println(output);
            throw new RuntimeException("Wait before Lock");
          }
          waits++;
        } else {
          System.out.println(output);
          throw new RuntimeException("Unexpected operation: " + s);
        }
      }
    }

    // 2) Expect Lock + Notify + Unlock.
    expect("Lock", it, output);
    expect("Notify", it, output);
    expect("Unlock", it, output);

    // 3) A single thread wakes up, runs, and dies.
    expect("Awakened", it, output);
    expect("Unlock", it, output);

    // 4) Expect Lock + NotifyAll + Unlock.
    expect("Lock", it, output);
    expect("NotifyAll", it, output);
    expect("Unlock", it, output);

    // 5) N-1 threads wake up, run, and die.
    {
      int expectedUnlocks = 0;
      int ops = 2 * (N-1);
      for (int i = 0; i < ops; i++) {
        String s = it.next();
        if (s.equals("Awakened")) {
          expectedUnlocks++;
        } else if (s.equals("Unlock")) {
          expectedUnlocks--;
          if (expectedUnlocks < 0) {
            System.out.println(output);
            throw new RuntimeException("Unexpected unlock");
          }
        }
      }
    }

    // 6) That should be it.
    if (it.hasNext()) {
      System.out.println(output);
      throw new RuntimeException("Unexpected trailing output, starting with " + it.next());
    }

    output.clear();
    System.out.println("Done");
  }

  private static void expect(String s, Iterator<String> it, List<String> output) {
    String t = it.next();
    if (!s.equals(t)) {
      System.out.println(output);
      throw new RuntimeException("Expected " + s + " but got " + t);
    }
  }

  private static void lock(long id) {
    appendToLog("Lock");
    rawMonitorEnter(id);
  }

  private static void unlock(long id) {
    appendToLog("Unlock");
    try {
      rawMonitorExit(id);
    } catch (RuntimeException e) {
      appendToLog(e.getMessage());
    }
  }

  private static void rawWait(long id, long millis) {
    appendToLog("Wait");
    try {
      rawMonitorWait(id, millis);
    } catch (RuntimeException e) {
      appendToLog(e.getMessage());
    }
  }

  private static void rawNotify(long id) {
    appendToLog("Notify");
    try {
      rawMonitorNotify(id);
    } catch (RuntimeException e) {
      appendToLog(e.getMessage());
    }
  }

  private static void rawNotifyAll(long id) {
    appendToLog("NotifyAll");
    try {
      rawMonitorNotifyAll(id);
    } catch (RuntimeException e) {
      appendToLog(e.getMessage());
    }
  }

  private static synchronized void appendToLog(String s) {
    output.add(s);
  }

  private static void startWatchdog() {
    Runnable r = new Runnable() {
      @Override
      public void run() {
        long start = System.currentTimeMillis();
        // Give it a minute.
        long end = 60 * 1000 + start;
        for (;;) {
          long delta = end - System.currentTimeMillis();
          if (delta <= 0) {
            break;
          }

          try {
            Thread.currentThread().sleep(delta);
          } catch (Exception e) {
          }
        }
        System.out.println("TIMEOUT!");
        System.exit(1);
      }
    };
    Thread t = new Thread(r);
    t.setDaemon(true);
    t.start();
  }

  static volatile long sharedId;
  static List<String> output;
  static Thread firstAwakened;

  private static native long createRawMonitor();
  private static native void destroyRawMonitor(long id);
  private static native void rawMonitorEnter(long id);
  private static native void rawMonitorExit(long id);
  private static native void rawMonitorWait(long id, long millis);
  private static native void rawMonitorNotify(long id);
  private static native void rawMonitorNotifyAll(long id);
}
