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

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

@RunWith(Parameterized.class)
public class ArrayLengthRewriteTest extends TestBase {
  @Parameters(name = "{0}, debug = {1}")
  public static Iterable<?> data() {
    return buildParameters(getTestParameters().withAllRuntimes().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.getRuntime())
        .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.getRuntime())
        .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);
    }
  }
}
