// Copyright (c) 2018, 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.canonicalization;

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.D8TestCompileResult;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestCompileResult;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
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.JumboStringMode;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.Streams;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

class MessageLoader {
  private static int index = 0;

  @NeverInline
  static String buildSuffix(int i) {
    if (i % 2 == 0) {
      return "$" + i;
    }
    return "/" + i;
  }

  @NeverInline
  static String getSuffix() {
    if (index <= 8) {
      return "$" + index++;
    }
    throw new IndexOutOfBoundsException("index >= " + index);
  }

  public static void main(String[] args) {
    {
      // In debug mode, we need two: one for the below with the local
      // The other for literal constants that are canonicalized.
      // In release mode, all occurrences are canonicalized.
      String tag = "1st-tag";
      System.out.println("1st-tag" + buildSuffix(1));
      System.out.println(tag + buildSuffix(2));
      System.out.println(tag + buildSuffix(3));
      System.out.println(tag + buildSuffix(4));
      System.out.println(tag + buildSuffix(5));
      System.out.println("1st-tag" + buildSuffix(6));
      System.out.println(tag + buildSuffix(7));
      System.out.println(tag + buildSuffix(8));
    }
    {
      // All occurrences are canonicalized.
      System.out.println("2nd-tag" + buildSuffix(1));
      System.out.println("2nd-tag" + buildSuffix(2));
      System.out.println("2nd-tag" + buildSuffix(3));
      System.out.println("2nd-tag" + buildSuffix(4));
      System.out.println("2nd-tag" + buildSuffix(5));
      System.out.println("2nd-tag" + buildSuffix(6));
      System.out.println("2nd-tag" + buildSuffix(7));
      System.out.println("2nd-tag" + buildSuffix(8));
    }
    {
      // All occurrences are canonicalized.
      System.out.println("3rd-tag" + getSuffix());
      System.out.println("3rd-tag" + getSuffix());
      System.out.println("3rd-tag" + getSuffix());
      System.out.println("3rd-tag" + getSuffix());
      System.out.println("3rd-tag" + getSuffix());
      System.out.println("3rd-tag" + getSuffix());
      System.out.println("3rd-tag" + getSuffix());
      try {
        // Then we need one more in a catch handler.
        System.out.println("3rd-tag" + getSuffix());
      } catch (IndexOutOfBoundsException e) {
        // Intentionally empty.
      }
    }
    // Mimic part of Art596_app_imagesTest.
    {
      StringBuffer builder = new StringBuffer();
      builder.append("int");
      builder.append("er");
      builder.append("n");
      String tmp = builder.toString();
      String intern = tmp.intern();
      System.out.println(intern != tmp);
      System.out.println(intern == StaticInternString.INTERN);
      System.out.println(StaticInternString.getIntern() == StaticInternString2.getIntern());
    }
    // Mimic part of Art624_checker_stringops.
    {
      StringBuffer s = new StringBuffer();
      System.out.println(2 == s.append("x").append("x").length());
    }
  }

  static class StaticInternString {
    public final static String INTERN = "intern";
    @NeverInline
    public static String getIntern() {
      return INTERN;
    }
  }

  static class StaticInternString2 {
    public final static String INTERN = "intern";
    @NeverInline
    public static String getIntern() {
      return INTERN;
    }
  }
}

@RunWith(Parameterized.class)
public class StringCanonicalizationTest extends TestBase {
  private static final Class<?> MAIN = MessageLoader.class;
  private static final String EXPECTED = StringUtils.lines(
      "1st-tag/1",
      "1st-tag$2",
      "1st-tag/3",
      "1st-tag$4",
      "1st-tag/5",
      "1st-tag$6",
      "1st-tag/7",
      "1st-tag$8",
      "2nd-tag/1",
      "2nd-tag$2",
      "2nd-tag/3",
      "2nd-tag$4",
      "2nd-tag/5",
      "2nd-tag$6",
      "2nd-tag/7",
      "2nd-tag$8",
      "3rd-tag$0",
      "3rd-tag$1",
      "3rd-tag$2",
      "3rd-tag$3",
      "3rd-tag$4",
      "3rd-tag$5",
      "3rd-tag$6",
      "3rd-tag$7",
      "false",
      "true",
      "true",
      "true"
  );

  @Parameterized.Parameters(name = "{0}")
  public static TestParametersCollection data() {
    // CF should not canonicalize strings or lower them. See (r8g/30163) and (r8g/30320).
    return getTestParameters().withDexRuntimes().build();
  }

  private final TestParameters parameters;

  public StringCanonicalizationTest(TestParameters parameters) {
    this.parameters = parameters;
  }

  private void test(
      TestCompileResult result,
      int expectedConstStringCount0,
      int expectedConstStringCount1,
      int expectedConstStringCount2,
      int expectedInternCount,
      int expectedStringOpsCount) throws Exception {
    String main = MessageLoader.class.getCanonicalName();
    result
        .run(parameters.getRuntime(), main)
        .assertSuccessWithOutput(EXPECTED);

    CodeInspector codeInspector = result.inspector();
    ClassSubject mainClass = codeInspector.clazz(main);
    MethodSubject mainMethod = mainClass.mainMethod();
    assertThat(mainMethod, isPresent());
    long count = Streams.stream(mainMethod.iterateInstructions(
        i -> i.isConstString("1st-tag", JumboStringMode.ALLOW))).count();
    assertEquals(expectedConstStringCount0, count);
    count = Streams.stream(mainMethod.iterateInstructions(
        i -> i.isConstString("2nd-tag", JumboStringMode.ALLOW))).count();
    assertEquals(expectedConstStringCount1, count);
    count = Streams.stream(mainMethod.iterateInstructions(
        i -> i.isConstString("3rd-tag", JumboStringMode.ALLOW))).count();
    assertEquals(expectedConstStringCount2, count);
    count = Streams.stream(mainMethod.iterateInstructions(
        i -> i.isConstString("intern", JumboStringMode.ALLOW))).count();
    assertEquals(expectedInternCount, count);
    count = Streams.stream(mainMethod.iterateInstructions(
        i -> i.isConstString("x", JumboStringMode.ALLOW))).count();
    assertEquals(expectedStringOpsCount, count);
  }

  @Test
  public void testD8() throws Exception {
    assumeTrue("Only run D8 for Dex backend", parameters.isDexRuntime());

    D8TestCompileResult result =
        testForD8()
            .release()
            .addProgramClassesAndInnerClasses(MAIN)
            .setMinApi(parameters.getRuntime())
            .compile();
    test(result, 1, 1, 1, 1, 1);

    result =
        testForD8()
            .debug()
            .addProgramClassesAndInnerClasses(MAIN)
            .setMinApi(parameters.getRuntime())
            .compile();
    test(result, 2, 1, 1, 1, 1);
  }

  @Test
  public void testR8() throws Exception {
    R8TestCompileResult result =
        testForR8(parameters.getBackend())
            .addProgramClassesAndInnerClasses(MAIN)
            .enableProguardTestOptions()
            .enableInliningAnnotations()
            .addKeepMainRule(MessageLoader.class)
            .setMinApi(parameters.getRuntime())
            .compile();
    test(result, 1, 1, 1, 1, 1);
  }

}
