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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import com.android.tools.r8.D8TestBuilder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexCode.Try;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Add;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.util.Arrays;
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;

// Regression test for b/297320921
@RunWith(Parameterized.class)
public class TryCatchRangeOverflowTest extends TestBase {

  @Parameter(0)
  public TestParameters parameters;

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

  // Each add/2addr instruction has size 1, so we add have as many instruction minus some padding
  // to make room for the instructions before and after but still in the same block.
  // Notice that this value may change if the generated code by the compiler changes. It must then
  // be updated to the precise limit again so that the test for jumbo-string exactly hits the
  // crossing point.
  private final int PADDING = 33;
  private final int UNSPLIT_LIMIT = 0xFFFF - PADDING;
  private final int SPLIT_2_LIMIT = 0xFFFF * 2 - PADDING;

  @Test
  public void testWithinU2() throws Exception {
    parameters.assumeDexRuntime();
    int addCount = UNSPLIT_LIMIT;
    compile(addCount)
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutputLines("" + addCount)
        .inspect(inspector -> checkTryCatchHandlers(1, inspector));
  }

  @Test
  public void testJumboExceedsU2() throws Exception {
    parameters.assumeDexRuntime();
    int addCount = UNSPLIT_LIMIT;
    compile(addCount)
        .addOptionsModification(o -> o.testing.forceJumboStringProcessing = true)
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutputLines("" + addCount)
        .inspect(inspector -> checkTryCatchHandlers(2, inspector));
  }

  @Test
  public void testExceedsU2() throws Exception {
    parameters.assumeDexRuntime();
    // Test with a few values above the limit.
    for (int addCount : Arrays.asList(UNSPLIT_LIMIT + 1, UNSPLIT_LIMIT + 2, UNSPLIT_LIMIT + 100)) {
      compile(addCount)
          .run(parameters.getRuntime(), TestClass.class)
          .assertSuccessWithOutputLines("" + addCount)
          .inspect(inspector -> checkTryCatchHandlers(2, inspector));
    }
  }

  @Test
  public void testWithinU2x2() throws Exception {
    parameters.assumeDexRuntime();
    int addCount = SPLIT_2_LIMIT;
    compile(addCount)
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutputLines("" + addCount)
        .inspect(inspector -> checkTryCatchHandlers(2, inspector));
  }

  @Test
  public void testJumboExceedsU2x2() throws Exception {
    parameters.assumeDexRuntime();
    int addCount = SPLIT_2_LIMIT;
    compile(addCount)
        .addOptionsModification(o -> o.testing.forceJumboStringProcessing = true)
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutputLines("" + addCount)
        .inspect(inspector -> checkTryCatchHandlers(3, inspector));
  }

  @Test
  public void testExceedsU2x2() throws Exception {
    parameters.assumeDexRuntime();
    int addCount = SPLIT_2_LIMIT + 1;
    compile(addCount)
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutputLines("" + addCount)
        .inspect(inspector -> checkTryCatchHandlers(3, inspector));
  }

  private D8TestBuilder compile(int addCount) {
    return testForD8(Backend.DEX)
        .addProgramClasses(TestClass.class)
        .addOptionsModification(
            o ->
                o.testing.irModifier =
                    (code, appView) -> amendCodeWithAddInstructions(addCount, code))
        .debug()
        .setMinApi(parameters);
  }

  private static void amendCodeWithAddInstructions(int addCount, IRCode code) {
    if (!code.context().getReference().qualifiedName().endsWith("main")) {
      return;
    }
    InstructionListIterator it = code.instructionListIterator();
    while (it.hasNext()) {
      Instruction instruction = it.next();
      if (instruction.isAdd()) {
        TypeElement outType = instruction.getOutType();
        DebugLocalInfo localInfo = instruction.getLocalInfo();
        // Create the last value which will replace the users of the original value in the
        // continuations.
        Value newLastValue = code.createValue(outType, localInfo);
        instruction.outValue().replaceUsers(newLastValue);

        Add add = instruction.asAdd();
        NumericType numericType = add.getNumericType();
        assert add.rightValue().isConstNumber();
        for (int i = 1; i < addCount; i++) {
          Value dest = i == addCount - 1 ? newLastValue : code.createValue(outType, localInfo);
          Add newAdd = Add.create(numericType, dest, add.outValue(), add.rightValue());
          add.outValue().addDebugLocalEnd(newAdd);
          newAdd.setPosition(add.getPosition());
          it.add(newAdd);
          add = newAdd;
        }
        return;
      }
    }
    fail("Expected to find an Add instruction.");
  }

  private static void checkTryCatchHandlers(int tryCount, CodeInspector inspector)
      throws NoSuchMethodException {

    MethodSubject main = inspector.method(TestClass.class.getMethod("main", String[].class));
    Try[] tries = main.getMethod().getCode().asDexCode().tries;
    assertEquals(Arrays.toString(tries), tryCount, tries.length);
  }

  static class TestClass {

    public static void main(String[] args) {
      int i = 0;
      try {
        String str;
        int len = args.length;
        if (len == 0) {
          str = "";
        } else if (len == 1 /* Using a constant 1 here causes the add to be an add/2addr */) {
          str = "Strings might become jumbos";
        } else if (len % 2 == 0) {
          str = "We need 4";
        } else {
          str = "to ensure overflow.";
        }
        i = str.length();
        ++i; // repeated count number of times.
        i += args[0].length();
      } catch (Throwable e) {
        System.out.println(i);
        return;
      }
      System.out.println("unexpected i " + i);
    }
  }
}
