| // Copyright (c) 2019, 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.desugar.backports.IgnoreInvokes; |
| import com.android.tools.r8.utils.AndroidApiLevel; |
| import java.util.Objects; |
| import org.hamcrest.CoreMatchers; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.Parameterized; |
| import org.junit.runners.Parameterized.Parameters; |
| |
| @RunWith(Parameterized.class) |
| public final class ObjectsBackportJava9Test extends AbstractBackportTest { |
| @Parameters(name = "{0}") |
| public static Iterable<?> data() { |
| return TestBase.getTestParameters() |
| .withDexRuntimes() |
| .withCfRuntimesStartingFromIncluding(CfVm.JDK9) |
| .withAllApiLevelsAlsoForCf() |
| .build(); |
| } |
| |
| public ObjectsBackportJava9Test(TestParameters parameters) { |
| super(parameters, Objects.class, ObjectsBackportJava9Main.class); |
| // Objects.checkFromIndexSize, Objects.checkFromToIndex, Objects.checkIndex, |
| // Objects.requireNonNullElse and Objects.requireNonNullElseGet added in API 30. |
| registerTarget(AndroidApiLevel.R, 28); |
| registerTarget(AndroidApiLevel.N, 0); |
| // Objects.requireNonNullElseGet is not desugared if Supplier is absent. |
| registerTarget(AndroidApiLevel.B, 4); |
| } |
| |
| @Test |
| public void desugaringApiLevelR() throws Exception { |
| // TODO(b/154759404): This test should start to fail when testing on an Android R VM. |
| // This has now been checked with S, when R testing is added chck and remove this. |
| if (parameters.getRuntime().isDex() && parameters.getApiLevel().isEqualTo(AndroidApiLevel.R)) { |
| testForD8() |
| .setMinApi(AndroidApiLevel.R) |
| .addProgramClasses(MiniAssert.class, IgnoreInvokes.class) |
| .addProgramClasses(ObjectsBackportJava9Main.class) |
| .setIncludeClassesChecksum(true) |
| .compile() |
| .run(parameters.getRuntime(), ObjectsBackportJava9Main.class) |
| .assertFailureWithErrorThatMatches( |
| CoreMatchers.containsString("java.lang.NoSuchMethodError")); |
| } |
| } |
| |
| public static class ObjectsBackportJava9Main { |
| public static void main(String[] args) { |
| boolean isAndroid = "Dalvik".equals(System.getProperty("java.vm.name")); |
| String majorVersion = System.getProperty("java.vm.version").split("\\.", -1)[0]; |
| |
| testRequireNonNullElse(); |
| if (!isAndroid || Integer.parseInt(majorVersion) >= 7) { |
| // TODO desugaring desugaredlibrary is blocked by |
| // https://issuetracker.google.com/issues/114481425 |
| testRequireNonNullElseGet(); |
| } |
| testCheckIndex(); |
| testCheckFromToIndex(); |
| testCheckFromIndexSize(); |
| } |
| |
| private static void testRequireNonNullElse() { |
| Object one = new Object(); |
| Object two = new Object(); |
| |
| assertSame(one, Objects.requireNonNullElse(one, two)); |
| assertSame(two, Objects.requireNonNullElse(null, two)); |
| |
| try { |
| throw new AssertionError(Objects.requireNonNullElse(null, null)); |
| } catch (NullPointerException expected) { |
| } |
| } |
| |
| private static void testRequireNonNullElseGet() { |
| Object one = new Object(); |
| Object two = new Object(); |
| |
| assertSame(one, Objects.requireNonNullElseGet(one, () -> two)); |
| assertSame(two, Objects.requireNonNullElseGet(null, () -> two)); |
| |
| try { |
| throw new AssertionError(Objects.requireNonNullElseGet(null, null)); |
| } catch (NullPointerException expected) { |
| } |
| try { |
| throw new AssertionError(Objects.requireNonNullElseGet(null, () -> null)); |
| } catch (NullPointerException expected) { |
| } |
| } |
| |
| private static void testCheckIndex() { |
| for (int i = 0; i < 10; i++) { |
| assertEquals(i, Objects.checkIndex(i, 10)); |
| } |
| |
| try { |
| throw new AssertionError(Objects.checkIndex(-1, 10)); |
| } catch (IndexOutOfBoundsException expected) { |
| } |
| try { |
| throw new AssertionError(Objects.checkIndex(10, 0)); |
| } catch (IndexOutOfBoundsException expected) { |
| } |
| try { |
| throw new AssertionError(Objects.checkIndex(0, 0)); |
| } catch (IndexOutOfBoundsException expected) { |
| } |
| } |
| |
| private static void testCheckFromToIndex() { |
| for (int i = 0; i <= 10; i++) { |
| for (int j = i; j <= 10; j++) { |
| assertEquals(i, Objects.checkFromToIndex(i, j, 10)); |
| } |
| } |
| assertEquals(0, Objects.checkFromToIndex(0, 0, 0)); |
| |
| try { |
| throw new AssertionError(Objects.checkFromToIndex(4, 2, 10)); |
| } catch (IndexOutOfBoundsException expected) { |
| } |
| try { |
| throw new AssertionError(Objects.checkFromToIndex(-1, 5, 10)); |
| } catch (IndexOutOfBoundsException expected) { |
| } |
| try { |
| throw new AssertionError(Objects.checkFromToIndex(0, -1, 10)); |
| } catch (IndexOutOfBoundsException expected) { |
| } |
| try { |
| throw new AssertionError(Objects.checkFromToIndex(11, 11, 10)); |
| } catch (IndexOutOfBoundsException expected) { |
| } |
| try { |
| throw new AssertionError(Objects.checkFromToIndex(0, 1, 0)); |
| } catch (IndexOutOfBoundsException expected) { |
| } |
| try { |
| throw new AssertionError(Objects.checkFromToIndex(1, 1, 0)); |
| } catch (IndexOutOfBoundsException expected) { |
| } |
| } |
| |
| private static void testCheckFromIndexSize() { |
| for (int i = 0; i <= 10; i++) { |
| for (int j = 10 - i; j >= 0; j--) { |
| assertEquals(i, Objects.checkFromIndexSize(i, j, 10)); |
| } |
| } |
| assertEquals(0, Objects.checkFromIndexSize(0, 0, 0)); |
| |
| try { |
| throw new AssertionError(Objects.checkFromIndexSize(8, 4, 10)); |
| } catch (IndexOutOfBoundsException expected) { |
| } |
| try { |
| throw new AssertionError(Objects.checkFromIndexSize(-1, 5, 10)); |
| } catch (IndexOutOfBoundsException expected) { |
| } |
| try { |
| throw new AssertionError(Objects.checkFromIndexSize(11, 0, 10)); |
| } catch (IndexOutOfBoundsException expected) { |
| } |
| try { |
| throw new AssertionError(Objects.checkFromIndexSize(0, 1, 0)); |
| } catch (IndexOutOfBoundsException expected) { |
| } |
| try { |
| throw new AssertionError(Objects.checkFromIndexSize(1, 1, 0)); |
| } catch (IndexOutOfBoundsException expected) { |
| } |
| |
| // Check for cases where overflow might occur producing incorrect results. |
| try { |
| throw new AssertionError( |
| Objects.checkFromIndexSize(Integer.MAX_VALUE, 1, Integer.MAX_VALUE)); |
| } catch (IndexOutOfBoundsException expected) { |
| } |
| try { |
| throw new AssertionError(Objects.checkFromIndexSize(0, 1, Integer.MIN_VALUE)); |
| } catch (IndexOutOfBoundsException expected) { |
| } |
| } |
| |
| private static void assertEquals(int expected, int actual) { |
| if (expected != actual) { |
| throw new AssertionError("Expected <" + expected + "> but was <" + actual + '>'); |
| } |
| } |
| |
| private static void assertSame(Object expected, Object actual) { |
| if (expected != actual) { |
| throw new AssertionError( |
| "Expected <" + expected + "> to be same instance as <" + actual + '>'); |
| } |
| } |
| } |
| } |