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

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.Assume.assumeTrue;

import com.android.tools.r8.D8TestRunResult;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.NeverPropagateValue;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.SingleTestRunResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.utils.AndroidApiLevel;
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.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.Streams;
import java.util.Objects;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class ObjectsRequireNonNullTest extends TestBase {
  private static final String JAVA_OUTPUT = StringUtils.lines(
      "Foo::toString",
      "Foo::bar",
      "Foo::bar",
      "Expected NPE",
      "Expected NPE"
  );
  private static final Class<?> MAIN = ObjectsRequireNonNullTestMain.class;

  @Parameterized.Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters()
        .withCfRuntimes()
        // Objects#requireNonNull will be desugared VMs older than API level K.
        .withDexRuntimesStartingFromExcluding(Version.V4_4_4)
        .withApiLevelsStartingAtIncluding(AndroidApiLevel.K)
        .build();
  }

  private final TestParameters parameters;

  public ObjectsRequireNonNullTest(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 static boolean isObjectsRequireNonNull(DexMethod method) {
    return method.toSourceString().equals(
        "java.lang.Object java.util.Objects.requireNonNull(java.lang.Object)");
  }

  private long countObjectsRequireNonNull(MethodSubject method) {
    return Streams.stream(method.iterateInstructions(instructionSubject -> {
      if (instructionSubject.isInvoke()) {
        return isObjectsRequireNonNull(instructionSubject.getMethod());
      }
      return false;
    })).count();
  }

  private void test(
      SingleTestRunResult<?> result, int expectedCountInMain, int expectedCountInConsumer)
      throws Exception {
    CodeInspector codeInspector = result.inspector();
    ClassSubject mainClass = codeInspector.clazz(MAIN);
    MethodSubject mainMethod = mainClass.mainMethod();
    assertThat(mainMethod, isPresent());
    assertEquals(expectedCountInMain, countObjectsRequireNonNull(mainMethod));

    MethodSubject unknownArg = mainClass.uniqueMethodWithName("unknownArg");
    assertThat(unknownArg, isPresent());
    // Due to the nullable argument, requireNonNull should remain.
    assertEquals(1, countObjectsRequireNonNull(unknownArg));

    MethodSubject uninit = mainClass.uniqueMethodWithName("consumeUninitialized");
    assertThat(uninit, isPresent());
    assertEquals(expectedCountInConsumer, countObjectsRequireNonNull(uninit));
    if (expectedCountInConsumer == 0) {
      assertEquals(
          0, Streams.stream(uninit.iterateInstructions(InstructionSubject::isInvoke)).count());
      assertEquals(
          1, Streams.stream(uninit.iterateInstructions(InstructionSubject::isThrow)).count());
    }
  }

  @Test
  public void testD8() throws Exception {
    assumeTrue("Only run D8 for Dex backend", parameters.isDexRuntime());
    D8TestRunResult result =
        testForD8()
            .debug()
            .addProgramClassesAndInnerClasses(MAIN)
            .setMinApi(parameters.getApiLevel())
            .run(parameters.getRuntime(), MAIN)
            .assertSuccessWithOutput(JAVA_OUTPUT);
    test(result, 2, 1);

    result =
        testForD8()
            .release()
            .addProgramClassesAndInnerClasses(MAIN)
            .setMinApi(parameters.getApiLevel())
            .run(parameters.getRuntime(), MAIN)
            .assertSuccessWithOutput(JAVA_OUTPUT);
    test(result, 0, 1);
  }

  @Test
  public void testR8() throws Exception {
    assumeTrue("CF disables move result optimization", parameters.isDexRuntime());
    R8TestRunResult result =
        testForR8(parameters.getBackend())
            .addProgramClassesAndInnerClasses(MAIN)
            .enableInliningAnnotations()
            .enableMemberValuePropagationAnnotations()
            .addKeepMainRule(MAIN)
            .noMinification()
            .setMinApi(parameters.getApiLevel())
            .run(parameters.getRuntime(), MAIN)
            .assertSuccessWithOutput(JAVA_OUTPUT);
    test(result, 0, 0);
  }

  static class ObjectsRequireNonNullTestMain {

    static class Uninitialized {
      void noWayToCall() {
        System.out.println("Uninitialized, hence no way to call this.");
      }
    }

    @NeverPropagateValue
    @NeverInline
    static void consumeUninitialized(Uninitialized arg) {
      Uninitialized nonNullArg = Objects.requireNonNull(arg);
      // Dead code.
      nonNullArg.noWayToCall();
    }

    static class Foo {
      @NeverInline
      void bar() {
        System.out.println("Foo::bar");
      }

      @NeverInline
      @Override
      public String toString() {
        return "Foo::toString";
      }
    }

    @NeverInline
    static void unknownArg(Foo foo) {
      // It's unclear the argument is definitely null or not null.
      Foo checked = Objects.requireNonNull(foo);
      checked.bar();
    }

    public static void main(String[] args) {
      Foo instance = new Foo();
      // Not removable in debug mode.
      Object nonNull = Objects.requireNonNull(instance);
      System.out.println(nonNull);
      // Removable because associated locals are changed while type casting.
      Foo checked = Objects.requireNonNull(instance);
      checked.bar();

      unknownArg(instance);
      try {
        Foo alwaysNull = System.currentTimeMillis() > 0 ? null : instance;
        unknownArg(alwaysNull);
        throw new AssertionError("Expected NullPointerException");
      } catch (NullPointerException npe) {
        System.out.println("Expected NPE");
      }

      try {
        consumeUninitialized(null);
        throw new AssertionError("Expected NullPointerException");
      } catch (NullPointerException npe) {
        System.out.println("Expected NPE");
      }
    }
  }
}
