1 /* 2 * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.openjdk.tests.java.util.stream; 24 25 import org.openjdk.testlib.java.util.stream.LambdaTestHelpers; 26 27 import java.util.concurrent.ArrayBlockingQueue; 28 import java.util.concurrent.ConcurrentHashMap; 29 import java.util.concurrent.ConcurrentLinkedDeque; 30 import java.util.concurrent.ConcurrentLinkedQueue; 31 import java.util.concurrent.ConcurrentSkipListMap; 32 import java.util.concurrent.ConcurrentSkipListSet; 33 import java.util.concurrent.CopyOnWriteArrayList; 34 import java.util.concurrent.CopyOnWriteArraySet; 35 import java.util.concurrent.LinkedBlockingDeque; 36 import java.util.concurrent.LinkedBlockingQueue; 37 import java.util.concurrent.LinkedTransferQueue; 38 import java.util.concurrent.PriorityBlockingQueue; 39 import java.util.function.Supplier; 40 import org.openjdk.testlib.java.util.stream.LambdaTestHelpers; 41 import org.testng.annotations.DataProvider; 42 import org.testng.annotations.Test; 43 44 import java.util.*; 45 import java.util.stream.Stream; 46 47 import static org.testng.Assert.assertEquals; 48 import static org.testng.Assert.assertTrue; 49 50 /** 51 * Tests laziness of stream operations -- mutations to the source after the stream() but prior to terminal operations 52 * are reflected in the stream contents. 53 */ 54 @Test 55 public class CollectionAndMapModifyStreamTest { 56 57 @DataProvider(name = "collections") createCollections()58 public Object[][] createCollections() { 59 List<Integer> content = LambdaTestHelpers.countTo(10); 60 61 List<Collection<Integer>> collections = new ArrayList<>(); 62 collections.add(new ArrayList<>(content)); 63 collections.add(new LinkedList<>(content)); 64 collections.add(new Vector<>(content)); 65 66 collections.add(new HashSet<>(content)); 67 collections.add(new LinkedHashSet<>(content)); 68 collections.add(new TreeSet<>(content)); 69 70 Stack<Integer> stack = new Stack<>(); 71 stack.addAll(content); 72 collections.add(stack); 73 collections.add(new PriorityQueue<>(content)); 74 collections.add(new ArrayDeque<>(content)); 75 76 // Concurrent collections 77 78 collections.add(new ConcurrentSkipListSet<>(content)); 79 80 ArrayBlockingQueue<Integer> arrayBlockingQueue = new ArrayBlockingQueue<>(content.size()); 81 for (Integer i : content) 82 arrayBlockingQueue.add(i); 83 collections.add(arrayBlockingQueue); 84 collections.add(new PriorityBlockingQueue<>(content)); 85 collections.add(new LinkedBlockingQueue<>(content)); 86 collections.add(new LinkedTransferQueue<>(content)); 87 collections.add(new ConcurrentLinkedQueue<>(content)); 88 collections.add(new LinkedBlockingDeque<>(content)); 89 collections.add(new ConcurrentLinkedDeque<>(content)); 90 91 Object[][] params = new Object[collections.size()][]; 92 for (int i = 0; i < collections.size(); i++) { 93 params[i] = new Object[]{collections.get(i).getClass().getName(), collections.get(i)}; 94 } 95 96 return params; 97 } 98 99 @Test(dataProvider = "collections") testCollectionSizeRemove(String name, Collection<Integer> c)100 public void testCollectionSizeRemove(String name, Collection<Integer> c) { 101 assertTrue(c.remove(1)); 102 Stream<Integer> s = c.stream(); 103 assertTrue(c.remove(2)); 104 Object[] result = s.toArray(); 105 assertEquals(result.length, c.size()); 106 } 107 108 @DataProvider(name = "maps") createMaps()109 public Object[][] createMaps() { 110 Map<Integer, Integer> content = new HashMap<>(); 111 for (int i = 0; i < 10; i++) { 112 content.put(i, i); 113 } 114 115 Map<String, Supplier<Map<Integer, Integer>>> maps = new HashMap<>(); 116 117 maps.put(HashMap.class.getName(), () -> new HashMap<>(content)); 118 maps.put(LinkedHashMap.class.getName(), () -> new LinkedHashMap<>(content)); 119 maps.put(IdentityHashMap.class.getName(), () -> new IdentityHashMap<>(content)); 120 maps.put(WeakHashMap.class.getName(), () -> new WeakHashMap<>(content)); 121 122 maps.put(TreeMap.class.getName(), () -> new TreeMap<>(content)); 123 maps.put(TreeMap.class.getName() + ".descendingMap()", () -> new TreeMap<>(content).descendingMap()); 124 125 // The following are not lazy 126 // maps.put(TreeMap.class.getName() + ".descendingMap().descendingMap()", () -> new TreeMap<>(content).descendingMap().descendingMap()); 127 // maps.put(TreeMap.class.getName() + ".headMap()", () -> new TreeMap<>(content).headMap(content.size() - 1)); 128 // maps.put(TreeMap.class.getName() + ".descendingMap().headMap()", () -> new TreeMap<>(content).descendingMap().tailMap(content.size() - 1, false)); 129 130 // Concurrent collections 131 132 maps.put(ConcurrentHashMap.class.getName(), () -> new ConcurrentHashMap<>(content)); 133 maps.put(ConcurrentSkipListMap.class.getName(), () -> new ConcurrentSkipListMap<>(content)); 134 135 Object[][] params = new Object[maps.size()][]; 136 int i = 0; 137 for (Map.Entry<String, Supplier<Map<Integer, Integer>>> e : maps.entrySet()) { 138 params[i++] = new Object[]{e.getKey(), e.getValue()}; 139 140 } 141 142 return params; 143 } 144 145 @Test(dataProvider = "maps", groups = { "serialization-hostile" }) testMapKeysSizeRemove(String name, Supplier<Map<Integer, Integer>> c)146 public void testMapKeysSizeRemove(String name, Supplier<Map<Integer, Integer>> c) { 147 testCollectionSizeRemove(name + " key set", c.get().keySet()); 148 } 149 150 @Test(dataProvider = "maps", groups = { "serialization-hostile" }) testMapValuesSizeRemove(String name, Supplier<Map<Integer, Integer>> c)151 public void testMapValuesSizeRemove(String name, Supplier<Map<Integer, Integer>> c) { 152 testCollectionSizeRemove(name + " value set", c.get().values()); 153 } 154 155 @Test(dataProvider = "maps") testMapEntriesSizeRemove(String name, Supplier<Map<Integer, Integer>> c)156 public void testMapEntriesSizeRemove(String name, Supplier<Map<Integer, Integer>> c) { 157 testEntrySetSizeRemove(name + " entry set", c.get().entrySet()); 158 } 159 testEntrySetSizeRemove(String name, Set<Map.Entry<Integer, Integer>> c)160 private void testEntrySetSizeRemove(String name, Set<Map.Entry<Integer, Integer>> c) { 161 Map.Entry<Integer, Integer> first = c.iterator().next(); 162 assertTrue(c.remove(first)); 163 Stream<Map.Entry<Integer, Integer>> s = c.stream(); 164 Map.Entry<Integer, Integer> second = c.iterator().next(); 165 assertTrue(c.remove(second)); 166 Object[] result = s.toArray(); 167 assertEquals(result.length, c.size()); 168 } 169 } 170