// Copyright (c) 2021, 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 backport;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.desugar.backports.AbstractBackportTest;
import com.android.tools.r8.utils.AndroidApiLevel;
import java.math.BigInteger;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public final class LongBackportJava9Test extends AbstractBackportTest {
  @Parameters(name = "{0}")
  public static Iterable<?> data() {
    return TestBase.getTestParameters()
        .withCfRuntimesStartingFromIncluding(CfVm.JDK9)
        .withDexRuntimes()
        .withAllApiLevelsAlsoForCf()
        .build();
  }

  public LongBackportJava9Test(TestParameters parameters) {
    super(parameters, Long.class, LongBackportJava9Main.class);
    // Note: The methods in this test exist in android.jar from Android T. When R8 builds targeting
    // Java 11 move these tests to LongBackportTest (out of examplesJava9).

    ignoreInvokes("toString");

    registerTarget(AndroidApiLevel.T, 17);
  }

  public static class LongBackportJava9Main {
    private static final long[] interestingValues = {
      Long.MIN_VALUE,
      Long.MAX_VALUE,
      Integer.MIN_VALUE,
      Integer.MAX_VALUE,
      Short.MIN_VALUE,
      Short.MAX_VALUE,
      Byte.MIN_VALUE,
      Byte.MAX_VALUE,
      0L,
      -1L,
      1L,
      -42L,
      42L
    };

    public static void main(String[] args) {
      testParseLongSubsequenceWithRadix();
      testParseUnsignedLongSubsequenceWithRadix();
    }

    private static void testParseLongSubsequenceWithRadix() {
      for (long value : interestingValues) {
        for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
          for (String prefix : new String[] {"", "x", "xxx"}) {
            for (String postfix : new String[] {"", "x", "xxx"}) {
              String valueString = prefix + Long.toString(value, radix) + postfix;
              int start = prefix.length();
              int end = valueString.length() - postfix.length();
              assertEquals(valueString, value, Long.parseLong(valueString, start, end, radix));
              if (value > 0) {
                valueString = prefix + "+" + Long.toString(value, radix) + postfix;
                end++;
                assertEquals(valueString, value, Long.parseLong(valueString, start, end, radix));
              }
            }
          }
        }
      }

      try {
        throw new AssertionError(Long.parseLong("0", 0, 1, Character.MIN_RADIX - 1));
      } catch (IllegalArgumentException expected) {
      }
      try {
        throw new AssertionError(Long.parseLong("0", 0, 1, Character.MAX_RADIX + 1));
      } catch (IllegalArgumentException expected) {
      }

      try {
        throw new AssertionError(Long.parseLong("", 0, 0, 16));
      } catch (NumberFormatException expected) {
      }
      try {
        throw new AssertionError(Long.parseLong("-", 0, 1, 16));
      } catch (NumberFormatException expected) {
      }
      try {
        throw new AssertionError(Long.parseLong("+", 0, 1, 16));
      } catch (NumberFormatException expected) {
      }

      try {
        throw new AssertionError(Long.parseLong("+a", 0, 2, 10));
      } catch (NumberFormatException expected) {
      }

      BigInteger overflow = new BigInteger("18446744073709551616");
      for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
        for (String prefix : new String[] {"", "x", "xxx"}) {
          for (String postfix : new String[] {"", "x", "xxx"}) {
            String overflowString = prefix + overflow.toString(radix) + postfix;
            int start = prefix.length();
            int end = overflowString.length() - postfix.length();
            try {
              throw new AssertionError(Long.parseLong(overflowString, start, end, radix));
            } catch (NumberFormatException expected) {
            }
          }
        }
      }
    }

    private static void testParseUnsignedLongSubsequenceWithRadix() {
      for (long value : interestingValues) {
        for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
          for (String prefix : new String[] {"", "x", "xxx"}) {
            for (String postfix : new String[] {"", "x", "xxx"}) {
              String valueString =
                  prefix + unsignedLongToBigInteger(value).toString(radix) + postfix;
              int start = prefix.length();
              int end = valueString.length() - postfix.length();
              assertEquals(
                  valueString, value, Long.parseUnsignedLong(valueString, start, end, radix));
              valueString =
                  prefix + "+" + unsignedLongToBigInteger(value).toString(radix) + postfix;
              end++;
              assertEquals(
                  valueString, value, Long.parseUnsignedLong(valueString, start, end, radix));
            }
          }
        }
      }

      try {
        throw new AssertionError(Long.parseUnsignedLong("0", 0, 1, Character.MIN_RADIX - 1));
      } catch (IllegalArgumentException expected) {
      }
      try {
        throw new AssertionError(Long.parseUnsignedLong("0", 0, 1, Character.MAX_RADIX + 1));
      } catch (IllegalArgumentException expected) {
      }

      try {
        throw new AssertionError(Long.parseUnsignedLong("", 0, 0, 16));
      } catch (NumberFormatException expected) {
      }
      try {
        throw new AssertionError(Long.parseUnsignedLong("+", 0, 1, 16));
      } catch (NumberFormatException expected) {
      }

      try {
        throw new AssertionError(Long.parseUnsignedLong("+a", 0, 2, 10));
      } catch (NumberFormatException expected) {
      }

      BigInteger overflow = new BigInteger("18446744073709551616");
      for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
        for (String prefix : new String[] {"", "x", "xxx", "+", "x+", "xxx+"}) {
          for (String postfix : new String[] {"", "x", "xxx"}) {
            String overflowString = prefix + overflow.toString(radix) + postfix;
            int start = prefix.length();
            int end = overflowString.length() - postfix.length();
            try {
              throw new AssertionError(Long.parseUnsignedLong(overflowString, start, end, radix));
            } catch (NumberFormatException expected) {
            }
          }
        }
      }
    }

    private static BigInteger unsignedLongToBigInteger(long value) {
      BigInteger bigInt = BigInteger.valueOf(value & 0x7fffffffffffffffL);
      if (value < 0) {
        bigInt = bigInt.setBit(Long.SIZE - 1);
      }
      return bigInt;
    }

    private static void assertEquals(String m, long expected, long actual) {
      if (expected != actual) {
        throw new AssertionError(m + " Expected <" + expected + "> but was <" + actual + '>');
      }
    }
  }
}
