Move Java9 backport test to java 9 module
Bug: b/380808556
Change-Id: I37db6d24aad86adbb57f86ef9054f09a4ed721bb
diff --git a/src/test/examplesJava9/backport/MapBackportJava9Test.java b/src/test/examplesJava9/backport/MapBackportJava9Test.java
new file mode 100644
index 0000000..df6af49
--- /dev/null
+++ b/src/test/examplesJava9/backport/MapBackportJava9Test.java
@@ -0,0 +1,346 @@
+// 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.AbstractMap;
+import java.util.Map;
+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 class MapBackportJava9Test extends AbstractBackportTest {
+ @Parameters(name = "{0}")
+ public static Iterable<?> data() {
+ return TestBase.getTestParameters()
+ .withCfRuntimesStartingFromIncluding(CfVm.JDK9)
+ .withDexRuntimes()
+ .withAllApiLevelsAlsoForCf()
+ .build();
+ }
+
+ public MapBackportJava9Test(TestParameters parameters) {
+ super(parameters, Map.class, MapBackportJava9Main.class);
+ // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
+ // an actual API level, migrate these tests to MapBackportTest.
+
+ // Available since API 1 and used to test created maps.
+ ignoreInvokes("entrySet");
+ ignoreInvokes("get");
+ ignoreInvokes("put");
+ ignoreInvokes("size");
+
+ // Map.entry, Map.of and Map.ofEntries added in API 30.
+ registerTarget(AndroidApiLevel.R, 29);
+ }
+
+ @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 check and remove this.
+ if (parameters.getRuntime().isDex() && parameters.getApiLevel().isEqualTo(AndroidApiLevel.R)) {
+ testForD8()
+ .setMinApi(AndroidApiLevel.R)
+ .addProgramClasses(MiniAssert.class, IgnoreInvokes.class)
+ .addProgramClasses(MapBackportJava9Main.class)
+ .setIncludeClassesChecksum(true)
+ .compile()
+ .run(parameters.getRuntime(), MapBackportJava9Main.class)
+ .assertFailureWithErrorThatMatches(
+ CoreMatchers.containsString("java.lang.NoSuchMethodError"));
+ }
+ }
+
+ public static class MapBackportJava9Main {
+
+ public static void main(String[] args) {
+ testOf0();
+ testOf1();
+ testOf2();
+ testOf10();
+ testOfEntries();
+ testEntry();
+ }
+
+ private static void testOf0() {
+ Map<Object, Object> ofObject = Map.of();
+ assertEquals(0, ofObject.size());
+ assertEquals(null, ofObject.get(new Object()));
+ assertMutationNotAllowed(ofObject);
+
+ Map<Integer, Integer> ofInteger = Map.of();
+ assertEquals(0, ofInteger.size());
+ assertEquals(null, ofInteger.get(0));
+ }
+
+ private static void testOf1() {
+ Object objectKey0 = new Object();
+ Object objectValue0 = new Object();
+ Map<Object, Object> ofObject = Map.of(objectKey0, objectValue0);
+ assertEquals(1, ofObject.size());
+ assertSame(objectValue0, ofObject.get(objectKey0));
+ assertEquals(null, ofObject.get(new Object()));
+ assertMutationNotAllowed(ofObject);
+
+ Map<Integer, Integer> ofInteger = Map.of(0, 0);
+ assertEquals(1, ofInteger.size());
+ assertEquals(0, ofInteger.get(0));
+ assertEquals(null, ofInteger.get(1));
+
+ try {
+ Map.of((Object) null, 1);
+ throw new AssertionError();
+ } catch (NullPointerException expected) {
+ }
+ try {
+ Map.of(1, (Object) null);
+ throw new AssertionError();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ private static void testOf2() {
+ Object objectKey0 = new Object();
+ Object objectValue0 = new Object();
+ Object objectKey1 = new Object();
+ Object objectValue1 = new Object();
+ Map<Object, Object> ofObject = Map.of(objectKey0, objectValue0, objectKey1, objectValue1);
+ assertEquals(2, ofObject.size());
+ assertSame(objectValue0, ofObject.get(objectKey0));
+ assertSame(objectValue1, ofObject.get(objectKey1));
+ assertEquals(null, ofObject.get(new Object()));
+ assertMutationNotAllowed(ofObject);
+
+ Map<Integer, Integer> ofInteger = Map.of(0, 0, 1, 1);
+ assertEquals(2, ofInteger.size());
+ assertEquals(0, ofInteger.get(0));
+ assertEquals(1, ofInteger.get(1));
+ assertEquals(null, ofInteger.get(3));
+
+ Map<Object, Object> ofMixed = Map.of(objectKey0, 0, objectKey1, 1);
+ assertEquals(2, ofMixed.size());
+ assertEquals(0, ofMixed.get(objectKey0));
+ assertEquals(1, ofMixed.get(objectKey1));
+ assertEquals(null, ofMixed.get(new Object()));
+
+ try {
+ Map.of(1, 1, null, 2);
+ throw new AssertionError();
+ } catch (NullPointerException expected) {
+ }
+ try {
+ Map.of(1, 1, 2, null);
+ throw new AssertionError();
+ } catch (NullPointerException expected) {
+ }
+
+ try {
+ Map.of(1, 1, 1, 2);
+ throw new AssertionError();
+ } catch (IllegalArgumentException expected) {
+ assertEquals("duplicate key: 1", expected.getMessage());
+ }
+ }
+
+ private static void testOf10() {
+ Object objectKey0 = new Object();
+ Object objectValue0 = new Object();
+ Object objectKey6 = new Object();
+ Object objectValue6 = new Object();
+ Object objectKey9 = new Object();
+ Object objectValue9 = new Object();
+ Map<Object, Object> ofObject =
+ Map.of(
+ objectKey0,
+ objectValue0,
+ new Object(),
+ new Object(),
+ new Object(),
+ new Object(),
+ new Object(),
+ new Object(),
+ new Object(),
+ new Object(),
+ new Object(),
+ new Object(),
+ objectKey6,
+ objectValue6,
+ new Object(),
+ new Object(),
+ new Object(),
+ new Object(),
+ objectKey9,
+ objectValue9);
+ assertEquals(10, ofObject.size());
+ assertSame(objectValue0, ofObject.get(objectKey0));
+ assertSame(objectValue6, ofObject.get(objectKey6));
+ assertSame(objectValue9, ofObject.get(objectKey9));
+ assertEquals(null, ofObject.get(new Object()));
+ assertMutationNotAllowed(ofObject);
+
+ Map<Integer, Integer> ofInteger =
+ Map.of(0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9);
+ assertEquals(10, ofInteger.size());
+ assertEquals(0, ofInteger.get(0));
+ assertEquals(6, ofInteger.get(6));
+ assertEquals(9, ofInteger.get(9));
+ assertEquals(null, ofInteger.get(10));
+
+ Map<Object, Object> ofMixed =
+ Map.of(0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, objectKey9, objectValue9);
+ assertEquals(10, ofMixed.size());
+ assertEquals(0, ofMixed.get(0));
+ assertEquals(6, ofMixed.get(6));
+ assertSame(objectValue9, ofMixed.get(objectKey9));
+ assertEquals(null, ofMixed.get(9));
+
+ try {
+ Map.of(0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, null, objectValue9);
+ throw new AssertionError();
+ } catch (NullPointerException expected) {
+ }
+ try {
+ Map.of(0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, objectKey9, null);
+ throw new AssertionError();
+ } catch (NullPointerException expected) {
+ }
+
+ try {
+ Map.of(0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 0, 9);
+ throw new AssertionError();
+ } catch (IllegalArgumentException expected) {
+ assertEquals("duplicate key: 0", expected.getMessage());
+ }
+ }
+
+ private static void testOfEntries() {
+ Object objectKey0 = new Object();
+ Object objectValue0 = new Object();
+ Object objectKey1 = new Object();
+ Object objectValue1 = new Object();
+ Map<Object, Object> ofObject =
+ Map.ofEntries(
+ new AbstractMap.SimpleEntry<>(objectKey0, objectValue0),
+ new AbstractMap.SimpleEntry<>(objectKey1, objectValue1));
+ assertEquals(2, ofObject.size());
+ assertSame(objectValue0, ofObject.get(objectKey0));
+ assertSame(objectValue1, ofObject.get(objectKey1));
+ assertEquals(null, ofObject.get(new Object()));
+ assertMutationNotAllowed(ofObject);
+
+ Map<Integer, Integer> ofInteger =
+ Map.ofEntries(new AbstractMap.SimpleEntry<>(0, 0), new AbstractMap.SimpleEntry<>(1, 1));
+ assertEquals(2, ofInteger.size());
+ assertEquals(0, ofInteger.get(0));
+ assertEquals(1, ofInteger.get(1));
+ assertEquals(null, ofInteger.get(2));
+
+ Map<Object, Object> ofMixed =
+ Map.ofEntries(
+ new AbstractMap.SimpleEntry<>(0, objectValue0),
+ new AbstractMap.SimpleEntry<>(objectKey1, 1));
+ assertEquals(2, ofMixed.size());
+ assertSame(objectValue0, ofMixed.get(0));
+ assertEquals(1, ofMixed.get(objectKey1));
+ assertEquals(null, ofMixed.get(1));
+
+ // Ensure the supplied entry objects are not used directly since they are mutable.
+ Map.Entry<Object, Object> mutableEntry =
+ new AbstractMap.SimpleEntry<>(objectKey0, objectValue0);
+ Map<Object, Object> ofMutableEntry = Map.ofEntries(mutableEntry);
+ mutableEntry.setValue(objectValue1);
+ assertSame(objectValue0, ofMutableEntry.get(objectKey0));
+
+ // Ensure the supplied mutable array is not used directly since it is mutable.
+ @SuppressWarnings("unchecked")
+ Map.Entry<Object, Object>[] mutableArray =
+ new Map.Entry[] {new AbstractMap.SimpleEntry<>(objectKey0, objectValue0)};
+ Map<Object, Object> ofArray = Map.ofEntries(mutableArray);
+ mutableArray[0] = new AbstractMap.SimpleEntry<>(objectKey1, objectValue1);
+ assertSame(objectValue0, ofArray.get(objectKey0));
+ assertEquals(null, ofArray.get(objectKey1));
+
+ try {
+ Map.ofEntries(new AbstractMap.SimpleEntry<Object, Integer>(null, 1));
+ throw new AssertionError();
+ } catch (NullPointerException expected) {
+ }
+ try {
+ Map.ofEntries(new AbstractMap.SimpleEntry<Object, Integer>(1, null));
+ throw new AssertionError();
+ } catch (NullPointerException expected) {
+ }
+
+ try {
+ Map.ofEntries(
+ new AbstractMap.SimpleEntry<>(0, objectValue0),
+ new AbstractMap.SimpleEntry<>(0, objectValue1));
+ throw new AssertionError();
+ } catch (IllegalArgumentException expected) {
+ assertEquals("duplicate key: 0", expected.getMessage());
+ }
+ }
+
+ private static void testEntry() {
+ Object key = new Object();
+ Object value = new Object();
+ Map.Entry<Object, Object> entry = Map.entry(key, value);
+ assertSame(key, entry.getKey());
+ assertSame(value, entry.getValue());
+
+ try {
+ entry.setValue(new Object());
+ throw new AssertionError();
+ } catch (UnsupportedOperationException expected) {
+ }
+
+ try {
+ Map.entry(null, value);
+ throw new AssertionError();
+ } catch (NullPointerException expected) {
+ }
+ try {
+ Map.entry(key, null);
+ throw new AssertionError();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ private static void assertMutationNotAllowed(Map<Object, Object> ofObject) {
+ try {
+ ofObject.put(new Object(), new Object());
+ throw new AssertionError();
+ } catch (UnsupportedOperationException expected) {
+ }
+ for (Map.Entry<Object, Object> entry : ofObject.entrySet()) {
+ try {
+ entry.setValue(new Object());
+ throw new AssertionError();
+ } catch (UnsupportedOperationException expected) {
+ }
+ }
+ }
+
+ private static void assertSame(Object expected, Object actual) {
+ if (expected != actual) {
+ throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
+ }
+ }
+
+ private static void assertEquals(Object expected, Object actual) {
+ if (expected != actual && !expected.equals(actual)) {
+ throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
+ }
+ }
+ }
+}