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

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class JumboStringTest extends SmaliTestBase {
  private static Pair<StringBuilder, StringBuilder> builders;

  @Parameter() public TestParameters parameters;

  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withDexRuntimes().withOnlyDexRuntimeApiLevel().build();
  }

  @BeforeClass
  public static void createBuilders() {
    StringBuilder builder = new StringBuilder();
    StringBuilder expectedBuilder = new StringBuilder();
    builder.append("    new-instance         v0, Ljava/lang/StringBuilder;");
    builder.append("    invoke-direct        { v0 }, Ljava/lang/StringBuilder;-><init>()V");
    for (int i = 0; i <= 0xffff + 2; i++) {
      String prefixed = StringUtils.zeroPrefix(i, 5);
      expectedBuilder.append(prefixed);
      expectedBuilder.append(StringUtils.lines(""));
      builder.append("  const-string         v1, \"" + prefixed + "\\n\"");
      builder.append(
          "  invoke-virtual       { v0, v1 }, Ljava/lang/StringBuilder;"
              + "->append(Ljava/lang/String;)Ljava/lang/StringBuilder;");
    }
    builder.append(
        "    invoke-virtual       { v0 }, Ljava/lang/StringBuilder;"
            + "->toString()Ljava/lang/String;");
    builder.append(StringUtils.lines("    move-result-object   v0"));
    builder.append(StringUtils.lines("    return-object        v0"));
    builders = new Pair<>(builder, expectedBuilder);
  }

  @Test
  public void test() throws Exception {
    SmaliBuilder smaliBuilder = new SmaliBuilder(DEFAULT_CLASS_NAME);

    smaliBuilder.addStaticMethod(
        "java.lang.String",
        DEFAULT_METHOD_NAME,
        ImmutableList.of(),
        2,
        builders.getFirst().toString()
    );

    smaliBuilder.addMainMethod(
        2,
        "    sget-object         v0, Ljava/lang/System;->out:Ljava/io/PrintStream;",
        "    invoke-static       {}, LTest;->method()Ljava/lang/String;",
        "    move-result-object  v1",
        "    invoke-virtual      { v0, v1 }, Ljava/io/PrintStream;->print(Ljava/lang/String;)V",
        "    return-void"
    );

    testForR8(parameters.getBackend())
        .addProgramDexFileData(smaliBuilder.compile())
        .addKeepMainRule(DEFAULT_CLASS_NAME)
        .setMinApi(parameters.getApiLevel())
        .addOptionsModification(
            options -> {
              options.enableStringConcatenationOptimization = false;
            })
        .run(parameters.getRuntime(), DEFAULT_CLASS_NAME)
        .assertSuccessWithOutput(builders.getSecond().toString())
        .inspect(
            inspector -> {
              ClassSubject main = inspector.clazz(DEFAULT_CLASS_NAME);
              assertThat(main, isPresent());
              MethodSubject method = main.uniqueMethodWithName(DEFAULT_METHOD_NAME);
              assertThat(method, isPresent());
              assertTrue(method.streamInstructions().anyMatch(InstructionSubject::isJumboString));
            });
  }

  @Test
  public void test_addconfigurationdebugging() throws Exception {
    SmaliBuilder smaliBuilder = new SmaliBuilder(DEFAULT_CLASS_NAME);

    smaliBuilder.addStaticMethod(
        "java.lang.String",
        DEFAULT_METHOD_NAME,
        ImmutableList.of(),
        2,
        builders.getFirst().toString()
    );

    // Intentionally dead code, but will be kept due to -addconfigurationdebugging.
    smaliBuilder.addStaticMethod(
        "java.lang.String",
        DEFAULT_METHOD_NAME + "2",
        ImmutableList.of(),
        2,
        builders.getFirst().toString()
    );

    smaliBuilder.addMainMethod(
        2,
        "    sget-object         v0, Ljava/lang/System;->out:Ljava/io/PrintStream;",
        "    invoke-static       {}, LTest;->method()Ljava/lang/String;",
        "    move-result-object  v1",
        "    invoke-virtual      { v0, v1 }, Ljava/io/PrintStream;->print(Ljava/lang/String;)V",
        "    return-void"
    );

    testForR8(parameters.getBackend())
        .addProgramDexFileData(smaliBuilder.compile())
        .addKeepMainRule(DEFAULT_CLASS_NAME)
        .addKeepRules("-addconfigurationdebugging")
        .setMinApi(parameters.getApiLevel())
        .addOptionsModification(
            options -> {
              options.enableStringConcatenationOptimization = false;
            })
        .run(parameters.getRuntime(), DEFAULT_CLASS_NAME)
        .assertSuccessWithOutput(builders.getSecond().toString())
        .inspect(
            inspector -> {
              ClassSubject main = inspector.clazz(DEFAULT_CLASS_NAME);
              assertThat(main, isPresent());
              MethodSubject method = main.uniqueMethodWithName(DEFAULT_METHOD_NAME);
              assertThat(method, isPresent());
              assertTrue(method.streamInstructions().anyMatch(InstructionSubject::isJumboString));
              MethodSubject method2 = main.uniqueMethodWithName(DEFAULT_METHOD_NAME + "2");
              assertThat(method2, isPresent());
              assertTrue(method2.streamInstructions().anyMatch(InstructionSubject::isJumboString));
            });
  }
}
