// Copyright (c) 2019, 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.ir.optimize.string;

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.D8TestRunResult;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRunResult;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.InstructionOffsetSubject;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.InstructionSubject.JumboStringMode;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.android.tools.r8.utils.codeinspector.RangeSubject;
import com.android.tools.r8.utils.codeinspector.TryCatchSubject;
import com.google.common.collect.Streams;
import java.util.Iterator;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

class StringInMonitorTestMain {
  static final Object lock = new Object();

  private static int foo = 0;

  @NeverInline
  private static synchronized void sync() throws OutOfMemoryError {
    String bar = foo == 0 ? "bar" : "";
    if (bar == "") {
      System.out.println("bar");
      throw new OutOfMemoryError();
    }
  }

  @NeverInline
  private static void oom() throws OutOfMemoryError {
    System.out.println("oom");
    if (System.currentTimeMillis() > 0) {
      throw new OutOfMemoryError();
    }
    System.out.println("oom");
    System.out.println("this-string-will-not-be-loaded.");
    System.out.println("this-string-will-not-be-loaded.");
  }

  public static void main(String[] args) {
    try {
      synchronized (lock) {
        System.out.println("1st sync");
        sync();
        oom();
        System.out.println("1st sync");
      }
    } catch (OutOfMemoryError oom) {
      // Pretend to recover from OOM
      synchronized (lock) {
        System.out.println("2nd sync");
      }
    }
  }
}

@RunWith(Parameterized.class)
public class StringInMonitorTest extends TestBase {
  private static final Class<?> MAIN = StringInMonitorTestMain.class;
  private static final String JAVA_OUTPUT = StringUtils.lines(
      "1st sync",
      "oom",
      "2nd sync"
  );

  @Parameterized.Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withAllRuntimes().build();
  }

  private final TestParameters parameters;

  public StringInMonitorTest(TestParameters parameters) {
    this.parameters = parameters;
  }

  @Test
  public void testJVMOutput() throws Exception {
    assumeTrue("Only run JVM reference on CF runtimes", parameters.isCfRuntime());
    testForJvm()
        .addTestClasspath()
        .run(parameters.getRuntime(), MAIN)
        .assertSuccessWithOutput(JAVA_OUTPUT);
  }

  private void test(
      TestRunResult result,
      int expectedConstStringCount1,
      int expectedConstStringCount2,
      int expectedConstStringCount3) throws Exception {
    CodeInspector codeInspector = result.inspector();
    ClassSubject mainClass = codeInspector.clazz(MAIN);
    MethodSubject mainMethod = mainClass.mainMethod();
    assertThat(mainMethod, isPresent());

    long count = Streams.stream(mainMethod.iterateInstructions(
        i -> i.isConstString("1st sync", JumboStringMode.ALLOW))).count();
    assertEquals(expectedConstStringCount1, count);

    // TODO(b/122302789): CfInstruction#getOffset()
    if (parameters.isDexRuntime()) {
      Iterator<InstructionSubject> constStringIterator =
          mainMethod.iterateInstructions(i -> i.isConstString(JumboStringMode.ALLOW));
      // All const-string's in main(...) should be covered by try (or synthetic catch-all) region.
      while (constStringIterator.hasNext()) {
        InstructionSubject constString = constStringIterator.next();
        InstructionOffsetSubject offsetSubject = constString.getOffset(mainMethod);
        // const-string of interest is indirectly covered. See b/122285813 for reference.
        Iterator<TryCatchSubject> catchAllIterator =
            mainMethod.iterateTryCatches(TryCatchSubject::hasCatchAll);
        boolean covered = false;
        while (catchAllIterator.hasNext()) {
          RangeSubject tryRange = catchAllIterator.next().getRange();
          covered |= tryRange.includes(offsetSubject);
          if (covered) {
            break;
          }
        }
        assertTrue(covered);
      }
    }

    MethodSubject sync = mainClass.uniqueMethodWithName("sync");
    assertThat(sync, isPresent());
    count = Streams.stream(sync.iterateInstructions(
        i -> i.isConstString("", JumboStringMode.ALLOW))).count();
    assertEquals(expectedConstStringCount2, count);

    // In CF, we don't explicitly add monitor-{enter|exit} and catch-all for synchronized methods.
    if (parameters.isDexRuntime()) {
      Iterator<InstructionSubject> constStringIterator =
          sync.iterateInstructions(i -> i.isConstString(JumboStringMode.ALLOW));
      // All const-string's in sync() should be covered by the synthetic catch-all regions.
      while (constStringIterator.hasNext()) {
        InstructionSubject constString = constStringIterator.next();
        InstructionOffsetSubject offsetSubject = constString.getOffset(mainMethod);
        Iterator<TryCatchSubject> catchAllIterator =
            sync.iterateTryCatches(TryCatchSubject::hasCatchAll);
        boolean covered = false;
        while (catchAllIterator.hasNext()) {
          RangeSubject tryRange = catchAllIterator.next().getRange();
          covered |= tryRange.includes(offsetSubject);
          if (covered) {
            break;
          }
        }
        assertTrue(covered);
      }
    }

    MethodSubject oom = mainClass.uniqueMethodWithName("oom");
    assertThat(oom, isPresent());
    count = Streams.stream(oom.iterateInstructions(
        i -> i.isConstString("this-string-will-not-be-loaded.", JumboStringMode.ALLOW))).count();
    assertEquals(expectedConstStringCount3, count);
  }

  @Test
  public void testD8() throws Exception {
    assumeTrue("Only run D8 for Dex backend", parameters.isDexRuntime());

    D8TestRunResult result =
        testForD8()
            .debug()
            .addProgramClasses(MAIN)
            .setMinApi(parameters.getRuntime())
            .run(parameters.getRuntime(), MAIN)
            .assertSuccessWithOutput(JAVA_OUTPUT);
    test(result, 2, 2, 1);

    result =
        testForD8()
            .release()
            .addProgramClasses(MAIN)
            .setMinApi(parameters.getRuntime())
            .run(parameters.getRuntime(), MAIN)
            .assertSuccessWithOutput(JAVA_OUTPUT);
    test(result, 2, 2, 1);
  }

  @Test
  public void testR8() throws Exception {
    R8TestRunResult result =
        testForR8(parameters.getBackend())
            .addProgramClasses(MAIN)
            .enableInliningAnnotations()
            .addKeepMainRule(MAIN)
            .setMinApi(parameters.getRuntime())
            .run(parameters.getRuntime(), MAIN)
            .assertSuccessWithOutput(JAVA_OUTPUT);
    // Due to the different behavior regarding constant canonicalization.
    int expectedConstStringCount3 = parameters.isCfRuntime() ? 2 : 1;
    test(result, 2, 2, expectedConstStringCount3);
  }

}
