// 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().withMaximumApiLevel().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)
        .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.uniqueMethodWithOriginalName(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)
        .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.uniqueMethodWithOriginalName(DEFAULT_METHOD_NAME);
              assertThat(method, isPresent());
              assertTrue(method.streamInstructions().anyMatch(InstructionSubject::isJumboString));
              MethodSubject method2 = main.uniqueMethodWithOriginalName(DEFAULT_METHOD_NAME + "2");
              assertThat(method2, isPresent());
              assertTrue(method2.streamInstructions().anyMatch(InstructionSubject::isJumboString));
            });
  }
}
