// 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.rewrite.arrays;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.utils.BooleanUtils;
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 org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class ArrayLengthRewriteTest extends TestBase {
  @Parameters(name = "{0}, debug = {1}")
  public static Iterable<?> data() {
    return buildParameters(
        getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
  }

  private final TestParameters parameters;
  private final boolean debugMode;

  public ArrayLengthRewriteTest(TestParameters parameters, boolean debugMode) {
    this.parameters = parameters;
    this.debugMode = debugMode;
  }

  private static final String[] expectedOutput = {
      "boolean 1",
      "byte 2",
      "char 3",
      "double 4",
      "float 5",
      "int 6",
      "long 7",
      "short 8",
      "class java.lang.String 1",
      "class java.lang.Object 2",
      "class java.lang.String 3",
      "NPE",
      "class java.lang.Object 2",
      "boolean 1",
      "class java.lang.String 0",
      "class java.lang.String 1",
      "class java.lang.String 2",
      "class java.lang.String 1",
      "class java.lang.String 1",
  };

  @Test public void d8() throws Exception {
    assumeTrue(parameters.isDexRuntime());

    testForD8()
        .setMinApi(parameters.getApiLevel())
        .setMode(debugMode ? CompilationMode.DEBUG : CompilationMode.RELEASE)
        .addProgramClasses(Main.class)
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutputLines(expectedOutput)
        .inspect(this::inspect);
  }

  @Test public void r8() throws Exception {
    testForR8(parameters.getBackend())
        .setMinApi(parameters.getApiLevel())
        .setMode(debugMode ? CompilationMode.DEBUG : CompilationMode.RELEASE)
        .addProgramClasses(Main.class)
        .addKeepMainRule(Main.class)
        .enableInliningAnnotations()
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutputLines(expectedOutput)
        .inspect(this::inspect);
  }

  private void inspect(CodeInspector inspector) {
    ClassSubject mainClass = inspector.clazz(Main.class);
    assertTrue(mainClass.isPresent());

    MethodSubject primitives = mainClass.uniqueMethodWithName("primitives");
    assertArrayLengthCallCount(primitives, debugMode ? 8 : 0);

    MethodSubject nonNullReferences = mainClass.uniqueMethodWithName("nonNullReferences");
    assertArrayLengthCallCount(nonNullReferences, debugMode ? 3 : 0);

    // No assertion on nullReference() because it's seen as always throwing an NPE and
    // the array-length instruction is removed. The output check validates behavior.

    MethodSubject argument = mainClass.uniqueMethodWithName("argument");
    assertArrayLengthCallCount(argument, 1);

    MethodSubject phi = mainClass.uniqueMethodWithName("phi");
    assertArrayLengthCallCount(phi, 1);

    // TODO(139489070): these should be rewritten and result in 0 array-length bytecodes
    MethodSubject staticConstants = mainClass.uniqueMethodWithName("staticConstants");
    assertArrayLengthCallCount(staticConstants, 3);

    MethodSubject staticNonConstants = mainClass.uniqueMethodWithName("staticNonConstants");
    assertArrayLengthCallCount(staticNonConstants, 2);
  }

  private static void assertArrayLengthCallCount(MethodSubject subject, int expected) {
    assertTrue(subject.isPresent());
    long actual = subject.streamInstructions()
        .filter(InstructionSubject::isArrayLength)
        .count();
    assertEquals(expected, actual);
  }

  public static final class Main {
    public static void main(String[] args) {
      primitives();
      nonNullReferences();
      nullReferences();
      argument("one", "two");
      phi();
      staticConstants();
      staticNonConstants();
    }

    @NeverInline
    private static void primitives() {
      boolean[] booleanArray = new boolean[1];
      byte[] byteArray = new byte[2];
      char[] charArray = new char[3];
      double[] doubleArray = new double[4];
      float[] floatArray = new float[5];
      int[] intArray = new int[6];
      long[] longArray = new long[7];
      short[] shortArray = new short[8];

      System.out.println(booleanArray.getClass().getComponentType() + " " + booleanArray.length);
      System.out.println(byteArray.getClass().getComponentType() + " " + byteArray.length);
      System.out.println(charArray.getClass().getComponentType() + " " + charArray.length);
      System.out.println(doubleArray.getClass().getComponentType() + " " + doubleArray.length);
      System.out.println(floatArray.getClass().getComponentType() + " " + floatArray.length);
      System.out.println(intArray.getClass().getComponentType() + " " + intArray.length);
      System.out.println(longArray.getClass().getComponentType() + " " + longArray.length);
      System.out.println(shortArray.getClass().getComponentType() + " " + shortArray.length);
    }

    @NeverInline
    private static void nonNullReferences() {
      String[] stringArray = new String[1];
      Object[] objectArray = new Object[2];
      Object[] stringAsObjectArray = new String[3];

      System.out.println(stringArray.getClass().getComponentType() + " " + stringArray.length);
      System.out.println(objectArray.getClass().getComponentType() + " " + objectArray.length);
      System.out.println(
          stringAsObjectArray.getClass().getComponentType() + " " + stringAsObjectArray.length);
    }

    @NeverInline
    private static void nullReferences() {
      String[] nullArray = null;
      try {
        System.out.println(nullArray.length);
      } catch (NullPointerException expected) {
        System.out.println("NPE");
      }
    }

    @NeverInline
    private static void argument(Object... input) {
      System.out.println(input.getClass().getComponentType() + " " + input.length);
    }

    @NeverInline
    private static void phi() {
      boolean[] booleanArray;
      if (System.nanoTime() > 0) {
        booleanArray = new boolean[1];
      } else {
        booleanArray = new boolean[2];
      }
      System.out.println(booleanArray.getClass().getComponentType() + " " + booleanArray.length);
    }

    private static final String[] zero = {};
    private static final String[] one = { "one" };
    private static final String[] two = { "one", "two" };

    @NeverInline
    private static void staticConstants() {
      System.out.println(zero.getClass().getComponentType() + " " + zero.length);
      System.out.println(one.getClass().getComponentType() + " " + one.length);
      System.out.println(two.getClass().getComponentType() + " " + two.length);
    }

    private static String[] mutable = { "one" };
    private static final String[] runtimeInit = { System.lineSeparator() };

    @NeverInline
    private static void staticNonConstants() {
      System.out.println(mutable.getClass().getComponentType() + " " + mutable.length);
      System.out.println(runtimeInit.getClass().getComponentType() + " " + runtimeInit.length);
    }
  }
}
