// 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.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRunResult;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.graph.DexMethod;
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)
        .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(
      TestRunResult 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.getRuntime())
            .run(parameters.getRuntime(), MAIN)
            .assertSuccessWithOutput(JAVA_OUTPUT);
    test(result, 2, 1);

    result =
        testForD8()
            .release()
            .addProgramClassesAndInnerClasses(MAIN)
            .setMinApi(parameters.getRuntime())
            .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.getRuntime())
            .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 {
        unknownArg(null);
        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");
      }
    }
  }
}
