// 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.Assert.fail;
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;

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);
      fail("Expected NullPointerException");
    } catch (NullPointerException npe) {
      System.out.println("Expected NPE");
    }

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

@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);
  }
}
