Backport List/Map/Set.copyOf factories

Test: tools/test.py --dex_vm all --no-internal -v *Backport*Test*
Test: tools/test.py --no-internal -v *GenerateBackportMethods*
Change-Id: I18521bbdfd8b72eaaa78b4cc09ea5d06a44ec6f3
diff --git a/src/test/examplesJava10/backport/ListBackportJava10Main.java b/src/test/examplesJava10/backport/ListBackportJava10Main.java
new file mode 100644
index 0000000..376f67a
--- /dev/null
+++ b/src/test/examplesJava10/backport/ListBackportJava10Main.java
@@ -0,0 +1,67 @@
+// 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 java.util.Arrays;
+import java.util.List;
+
+public class ListBackportJava10Main {
+
+  public static void main(String[] args) {
+    testCopyOf();
+  }
+
+  private static void testCopyOf() {
+    Object anObject0 = new Object();
+    Object anObject1 = new Object();
+    List<Object> original = Arrays.asList(anObject0, anObject1);
+    List<Object> copy = List.copyOf(original);
+    assertEquals(2, copy.size());
+    assertEquals(original, copy);
+    assertSame(anObject0, copy.get(0));
+    assertSame(anObject1, copy.get(1));
+    assertMutationNotAllowed(copy);
+
+    // Mutate the original backing collection and ensure it's not reflected in copy.
+    original.set(0, new Object());
+    assertSame(anObject0, copy.get(0));
+
+    try {
+      List.copyOf(null);
+      throw new AssertionError();
+    } catch (NullPointerException expected) {
+    }
+    try {
+      List.copyOf(Arrays.asList(1, null, 2));
+      throw new AssertionError();
+    } catch (NullPointerException expected) {
+    }
+  }
+
+  private static void assertMutationNotAllowed(List<Object> ofObject) {
+    try {
+      ofObject.add(new Object());
+      throw new AssertionError();
+    } catch (UnsupportedOperationException expected) {
+    }
+    try {
+      ofObject.set(0, 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 + ">");
+    }
+  }
+}
diff --git a/src/test/examplesJava10/backport/MapBackportJava10Main.java b/src/test/examplesJava10/backport/MapBackportJava10Main.java
new file mode 100644
index 0000000..95413e9
--- /dev/null
+++ b/src/test/examplesJava10/backport/MapBackportJava10Main.java
@@ -0,0 +1,82 @@
+// 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 java.util.HashMap;
+import java.util.Map;
+
+public class MapBackportJava10Main {
+
+  public static void main(String[] args) {
+    testCopyOf();
+  }
+
+  private static void testCopyOf() {
+    Object key0 = new Object();
+    Object value0 = new Object();
+    Object key1 = new Object();
+    Object value1 = new Object();
+    Map<Object, Object> original = new HashMap<>();
+    original.put(key0, value0);
+    original.put(key1, value1);
+    Map<Object, Object> copy = Map.copyOf(original);
+    assertEquals(2, copy.size());
+    assertEquals(original, copy);
+    assertSame(value0, copy.get(key0));
+    assertSame(value1, copy.get(key1));
+    assertMutationNotAllowed(copy);
+
+    // Mutate the original backing collection and ensure it's not reflected in copy.
+    original.put(key0, new Object());
+    assertSame(value0, copy.get(key0));
+
+    try {
+      Map.copyOf(null);
+      throw new AssertionError();
+    } catch (NullPointerException expected) {
+    }
+    try {
+      Map<Object, Object> map = new HashMap<>();
+      map.put(null, new Object());
+      Map.copyOf(map);
+      throw new AssertionError();
+    } catch (NullPointerException expected) {
+    }
+    try {
+      Map<Object, Object> map = new HashMap<>();
+      map.put(new Object(), null);
+      Map.copyOf(map);
+      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 + ">");
+    }
+  }
+}
diff --git a/src/test/examplesJava10/backport/SetBackportJava10Main.java b/src/test/examplesJava10/backport/SetBackportJava10Main.java
new file mode 100644
index 0000000..b8fb356
--- /dev/null
+++ b/src/test/examplesJava10/backport/SetBackportJava10Main.java
@@ -0,0 +1,74 @@
+// 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 java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class SetBackportJava10Main {
+
+  public static void main(String[] args) {
+    testCopyOf();
+  }
+
+  private static void testCopyOf() {
+    Object anObject0 = new Object();
+    Object anObject1 = new Object();
+    List<Object> original = Arrays.asList(anObject0, anObject1);
+    Set<Object> copy = Set.copyOf(original);
+    assertEquals(2, copy.size());
+    assertEquals(new HashSet<>(original), copy);
+    assertTrue(copy.contains(anObject0));
+    assertTrue(copy.contains(anObject1));
+    assertMutationNotAllowed(copy);
+
+    // Mutate the original backing collection and ensure it's not reflected in copy.
+    Object newObject = new Object();
+    original.set(0, newObject);
+    assertFalse(copy.contains(newObject));
+
+    // Ensure duplicates are allowed and are de-duped.
+    assertEquals(Set.of(1, 2), Set.copyOf(List.of(1, 2, 1, 2)));
+
+    try {
+      Set.copyOf(null);
+      throw new AssertionError();
+    } catch (NullPointerException expected) {
+    }
+    try {
+      Set.copyOf(Arrays.asList(1, null, 2));
+      throw new AssertionError();
+    } catch (NullPointerException expected) {
+    }
+  }
+
+  private static void assertMutationNotAllowed(Set<Object> ofObject) {
+    try {
+      ofObject.add(new Object());
+      throw new AssertionError();
+    } catch (UnsupportedOperationException expected) {
+    }
+  }
+
+  private static void assertTrue(boolean value) {
+    if (!value) {
+      throw new AssertionError("Expected <true> but was <false>");
+    }
+  }
+
+  private static void assertFalse(boolean value) {
+    if (value) {
+      throw new AssertionError("Expected <false> but was <true>");
+    }
+  }
+
+  private static void assertEquals(Object expected, Object actual) {
+    if (expected != actual && !expected.equals(actual)) {
+      throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
+    }
+  }
+}