// Copyright (c) 2021, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.android.tools.r8.classmerging.horizontal;

import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.StringUtils;
import java.lang.Thread.State;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class ImplicitClassInitializationSynchronizationTest extends TestBase {

  @Parameter(0)
  public TestParameters parameters;

  @Parameters(name = "{0}")
  public static TestParametersCollection parameters() {
    return getTestParameters().withAllRuntimesAndApiLevels().build();
  }

  @Test
  public void test() throws Exception {
    testForR8(parameters.getBackend())
        .addInnerClasses(getClass())
        .addKeepMainRule(Main.class)
        // TODO(b/205611444): Should not be merged.
        .addHorizontallyMergedClassesInspector(
            inspector -> inspector.assertIsCompleteMergeGroup(B.class, C.class))
        .setMinApi(parameters.getApiLevel())
        .compile()
        .run(parameters.getRuntime(), Main.class)
        // TODO(b/205611444): Should succeed.
        .assertFailure()
        .assertStdoutMatches(
            equalTo(
                StringUtils.lines(
                    "Main: fork",
                    "Main: wait",
                    "Worker: notify",
                    "Worker: wait",
                    "Main: notified",
                    "Main: lock C",
                    "Worker: notified",
                    "Worker: lock B")));
  }

  @Test
  public void testJvm() throws Exception {
    assumeTrue(parameters.isCfRuntime());
    testForJvm()
        .addTestClasspath()
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutputLines(
            "Main: fork",
            "Main: wait",
            "Worker: notify",
            "Worker: wait",
            "Main: notified",
            "Main: lock C",
            "Worker: notified",
            "Worker: lock B",
            "B",
            "Worker: unlock B",
            "C",
            "Main: unlock C");
  }

  static class Main {

    static Object lock = new Object();
    static Thread mainThread = Thread.currentThread();

    public static void main(String[] args) throws Exception {
      System.out.println("Main: fork");
      Thread workerThread = new Thread(A::new);
      workerThread.start();

      // Wait for the worker thread to take the lock for A.
      System.out.println("Main: wait");
      synchronized (lock) {
        lock.wait();
      }

      // Wait for the worker thread to be waiting on the main thread.
      while (workerThread.getState() != State.WAITING) {
        Thread.sleep(100);
      }

      System.out.println("Main: notified");

      // In one second, let the worker thread continue.
      doAfter(
          1000,
          () -> {
            synchronized (lock) {
              lock.notify();
            }
          });

      // In five seconds, report a dead lock.
      doAfter(5000, () -> System.exit(1));

      System.out.println("Main: lock C");
      System.out.println(new C());
      System.out.println("Main: unlock C");

      // No deadlock, success.
      System.exit(0);
    }

    private static void doAfter(int ms, Runnable runnable) {
      new Thread(
              () -> {
                try {
                  Thread.sleep(ms);
                  runnable.run();
                } catch (InterruptedException e) {
                  throw new RuntimeException(e);
                }
              })
          .start();
    }
  }

  static class A {

    static {
      try {
        // Wait for the main thread to be waiting on the worker thread.
        while (Main.mainThread.getState() != State.WAITING) {
          Thread.sleep(100);
        }

        System.out.println("Worker: notify");
        synchronized (Main.lock) {
          Main.lock.notify();
        }

        // Wait for the main thread to take the lock for B.
        System.out.println("Worker: wait");
        synchronized (Main.lock) {
          Main.lock.wait();
        }
        System.out.println("Worker: notified");

        // Try to take the lock for B.
        System.out.println("Worker: lock B");
        System.out.println(new B());
        System.out.println("Worker: unlock B");
      } catch (InterruptedException e) {
        throw new RuntimeException(e);
      }
    }
  }

  static class B extends A {

    @Override
    public String toString() {
      return "B";
    }
  }

  static class C extends A {

    @Override
    public String toString() {
      return "C";
    }
  }
}
