// Copyright (c) 2020, 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.regress.b165825758;

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 com.android.tools.r8.NeverInline;
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 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.MethodSubject;
import com.android.tools.r8.utils.codeinspector.RangeSubject;
import com.android.tools.r8.utils.codeinspector.TryCatchSubject;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

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

  static final String EXPECTED = StringUtils.lines("Hello, world");

  private final TestParameters parameters;

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

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

  @Test
  public void testReference() throws Exception {
    testForRuntime(parameters)
        .addInnerClasses(Regress165825758Test.class)
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(EXPECTED);
  }

  @Test
  public void testR8() throws Exception {
    testForR8(parameters.getBackend())
        .enableInliningAnnotations()
        .addInnerClasses(Regress165825758Test.class)
        .addKeepMainRule(TestClass.class)
        .addKeepClassRules(A.class)
        .setMinApi(parameters.getApiLevel())
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(EXPECTED)
        .inspect(this::checkDeadCodeThrowInTryRange);
  }

  private void checkDeadCodeThrowInTryRange(CodeInspector inspector) {
    ClassSubject classSubject = inspector.clazz(A.class);
    assertThat(classSubject, isPresent());
    MethodSubject method = classSubject.uniqueMethodWithName("synchronizedMethod");
    assertThat(method, isPresent());

    // Ensure that the "throwNpe" method remains and that it was not inlined by checking that no
    // allocations of NullPointerException are in the method.
    assertTrue(method.streamInstructions().noneMatch(InstructionSubject::isNewInstance));
    assertThat(inspector.clazz(TestClass.class).uniqueMethodWithName("throwNpe"), isPresent());

    // Source has 2 catch ranges:
    // 1st try catch is the source range, 2nd is the compiler inserted catch over monitor-exit.
    // When compiled with R8 the catch ranges are collapsed.
    List<TryCatchSubject> tryCatchSubjects = method.streamTryCatches().collect(Collectors.toList());
    assertEquals(1, tryCatchSubjects.size());
    TryCatchSubject sourceTry = tryCatchSubjects.get(0);

    // 1st throw is the "dead code" throw, the 2nd is the exceptional rethrow after method exit.
    List<InstructionSubject> throwInstructions =
        method
            .streamInstructions()
            .filter(InstructionSubject::isThrow)
            .collect(Collectors.toList());
    assertEquals(2, throwInstructions.size());
    InstructionSubject deadCodeThrow = throwInstructions.get(0);
    InstructionOffsetSubject throwOffset = deadCodeThrow.getOffset(method);
    RangeSubject range = sourceTry.getRange();
    assertTrue(
        "Expected throw@" + throwOffset + " to be in try-range " + range,
        range.includes(throwOffset));
  }

  static class A {

    @NeverInline
    void synchronizedMethod() {
      synchronized (this) {
        TestClass.throwNpe();
        System.out.println("Never hit");
      }
    }
  }

  static class TestClass {

    @NeverInline
    static void throwNpe() {
      throw new NullPointerException();
    }

    public static void main(String[] args) {
      try {
        new A().synchronizedMethod();
      } catch (NullPointerException e) {
        System.out.println("Hello, world");
      }
    }
  }
}
