// 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.shaking;

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.NoHorizontalClassMerging;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

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

  private static final String DEX2OAT_WARNING =
      "is abstract, but the declaring class is neither abstract nor an interface";

  private final TestParameters parameters;

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

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

  @Test
  public void testCompat() throws Exception {
    R8TestCompileResult compileResult =
        testForR8Compat(parameters.getBackend())
            .addInnerClasses(AbstractMethodOnNonAbstractClassTest.class)
            .addKeepMainRule(TestClass.class)
            .enableNoHorizontalClassMergingAnnotations()
            .setMinApi(parameters.getApiLevel())
            .compile();

    // A is not made abstract in compat mode.
    ClassSubject classSubject = compileResult.inspector().clazz(A.class);
    assertThat(classSubject, isPresent());
    assertFalse(classSubject.isAbstract());

    // A.m() is also not made abstract in compat mode.
    MethodSubject methodSubject = classSubject.uniqueMethodWithName("m");
    assertThat(methodSubject, isPresent());
    assertFalse(methodSubject.isAbstract());

    if (parameters.isDexRuntime()) {
      compileResult
          .runDex2Oat(parameters.getRuntime())
          .assertStderrMatches(not(containsString(DEX2OAT_WARNING)));
    }

    compileResult
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutputLines("Hello world!");
  }

  @Test
  public void testFull() throws Exception {
    R8TestCompileResult compileResult =
        testForR8(parameters.getBackend())
            .addInnerClasses(AbstractMethodOnNonAbstractClassTest.class)
            .addKeepMainRule(TestClass.class)
            .enableNoHorizontalClassMergingAnnotations()
            .setMinApi(parameters.getApiLevel())
            .compile();

    // A is made abstract in full mode.
    ClassSubject classSubject = compileResult.inspector().clazz(A.class);
    assertThat(classSubject, isPresent());
    assertTrue(classSubject.isAbstract());

    // A.m() is also made abstract in full mode.
    MethodSubject methodSubject = classSubject.uniqueMethodWithName("m");
    assertThat(methodSubject, isPresent());
    assertTrue(methodSubject.isAbstract());

    if (parameters.isDexRuntime()) {
      // There is no warning due to both A and A.m() being abstract.
      compileResult
          .runDex2Oat(parameters.getRuntime())
          .assertStderrMatches(not(containsString(DEX2OAT_WARNING)));
    }

    compileResult
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutputLines("Hello world!");
  }

  static class TestClass {

    public static void main(String[] args) {
      A b = System.currentTimeMillis() > 0 ? new B() : new C();
      b.m();
    }
  }

  static class A {

    // Never called directly on A, thus can be made abstract.
    void m() {}
  }

  @NoHorizontalClassMerging
  static class B extends A {

    @Override
    void m() {
      System.out.println("Hello world!");
    }
  }

  static class C extends A {

    @Override
    void m() {
      throw new RuntimeException();
    }
  }
}
