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 java.util.concurrent.ArrayBlockingQueue;
26 import java.util.concurrent.ConcurrentHashMap;
27 import java.util.concurrent.ConcurrentLinkedDeque;
28 import java.util.concurrent.ConcurrentLinkedQueue;
29 import java.util.concurrent.ConcurrentSkipListMap;
30 import java.util.concurrent.ConcurrentSkipListSet;
31 import java.util.concurrent.CopyOnWriteArrayList;
32 import java.util.concurrent.CopyOnWriteArraySet;
33 import java.util.concurrent.LinkedBlockingDeque;
34 import java.util.concurrent.LinkedBlockingQueue;
35 import java.util.concurrent.LinkedTransferQueue;
36 import java.util.concurrent.PriorityBlockingQueue;
37 import java.util.function.Supplier;
38 import java.util.stream.LambdaTestHelpers;
39 import org.testng.annotations.DataProvider;
40 import org.testng.annotations.Test;
41
42 import java.util.*;
43 import java.util.stream.Stream;
44
45 import static org.testng.Assert.assertEquals;
46 import static org.testng.Assert.assertTrue;
47
48 /**
49 * Tests laziness of stream operations -- mutations to the source after the stream() but prior to terminal operations
50 * are reflected in the stream contents.
51 */
52 @Test
53 public class CollectionAndMapModifyStreamTest {
54
55 @DataProvider(name = "collections")
56 public Object[][] createCollections() {
57 List<Integer> content = LambdaTestHelpers.countTo(10);
58
59 List<Collection<Integer>> collections = new ArrayList<>();
60 collections.add(new ArrayList<>(content));
61 collections.add(new LinkedList<>(content));
62 collections.add(new Vector<>(content));
63
64 collections.add(new HashSet<>(content));
65 collections.add(new LinkedHashSet<>(content));
66 collections.add(new TreeSet<>(content));
67
68 Stack<Integer> stack = new Stack<>();
69 stack.addAll(content);
70 collections.add(stack);
71 collections.add(new PriorityQueue<>(content));
72 collections.add(new ArrayDeque<>(content));
73
74 // Concurrent collections
75
76 collections.add(new ConcurrentSkipListSet<>(content));
77
78 ArrayBlockingQueue<Integer> arrayBlockingQueue = new ArrayBlockingQueue<>(content.size());
79 for (Integer i : content)
80 arrayBlockingQueue.add(i);
81 collections.add(arrayBlockingQueue);
82 collections.add(new PriorityBlockingQueue<>(content));
83 collections.add(new LinkedBlockingQueue<>(content));
84 collections.add(new LinkedTransferQueue<>(content));
85 collections.add(new ConcurrentLinkedQueue<>(content));
86 collections.add(new LinkedBlockingDeque<>(content));
87 collections.add(new ConcurrentLinkedDeque<>(content));
88
89 Object[][] params = new Object[collections.size()][];
90 for (int i = 0; i < collections.size(); i++) {
91 params[i] = new Object[]{collections.get(i).getClass().getName(), collections.get(i)};
92 }
93
94 return params;
95 }
96
97 @Test(dataProvider = "collections")
98 public void testCollectionSizeRemove(String name, Collection<Integer> c) {
99 assertTrue(c.remove(1));
100 Stream<Integer> s = c.stream();
101 assertTrue(c.remove(2));
102 Object[] result = s.toArray();
103 assertEquals(result.length, c.size());
104 }
105
106 @DataProvider(name = "maps")
107 public Object[][] createMaps() {
108 Map<Integer, Integer> content = new HashMap<>();
109 for (int i = 0; i < 10; i++) {
110 content.put(i, i);
111 }
112
113 Map<String, Supplier<Map<Integer, Integer>>> maps = new HashMap<>();
114
115 maps.put(HashMap.class.getName(), () -> new HashMap<>(content));
116 maps.put(LinkedHashMap.class.getName(), () -> new LinkedHashMap<>(content));
117 maps.put(IdentityHashMap.class.getName(), () -> new IdentityHashMap<>(content));
118 maps.put(WeakHashMap.class.getName(), () -> new WeakHashMap<>(content));
119
120 maps.put(TreeMap.class.getName(), () -> new TreeMap<>(content));
121 maps.put(TreeMap.class.getName() + ".descendingMap()", () -> new TreeMap<>(content).descendingMap());
122
123 // The following are not lazy
124 // maps.put(TreeMap.class.getName() + ".descendingMap().descendingMap()", () -> new TreeMap<>(content).descendingMap().descendingMap());
125 // maps.put(TreeMap.class.getName() + ".headMap()", () -> new TreeMap<>(content).headMap(content.size() - 1));
126 // maps.put(TreeMap.class.getName() + ".descendingMap().headMap()", () -> new TreeMap<>(content).descendingMap().tailMap(content.size() - 1, false));
127
128 // Concurrent collections
129
130 maps.put(ConcurrentHashMap.class.getName(), () -> new ConcurrentHashMap<>(content));
131 maps.put(ConcurrentSkipListMap.class.getName(), () -> new ConcurrentSkipListMap<>(content));
132
133 Object[][] params = new Object[maps.size()][];
134 int i = 0;
135 for (Map.Entry<String, Supplier<Map<Integer, Integer>>> e : maps.entrySet()) {
136 params[i++] = new Object[]{e.getKey(), e.getValue()};
137
138 }
139
140 return params;
141 }
142
143 @Test(dataProvider = "maps", groups = { "serialization-hostile" })
144 public void testMapKeysSizeRemove(String name, Supplier<Map<Integer, Integer>> c) {
145 testCollectionSizeRemove(name + " key set", c.get().keySet());
146 }
147
148 @Test(dataProvider = "maps", groups = { "serialization-hostile" })
149 public void testMapValuesSizeRemove(String name, Supplier<Map<Integer, Integer>> c) {
150 testCollectionSizeRemove(name + " value set", c.get().values());
151 }
152
153 @Test(dataProvider = "maps")
154 public void testMapEntriesSizeRemove(String name, Supplier<Map<Integer, Integer>> c) {
155 testEntrySetSizeRemove(name + " entry set", c.get().entrySet());
156 }
157
158 private void testEntrySetSizeRemove(String name, Set<Map.Entry<Integer, Integer>> c) {
159 Map.Entry<Integer, Integer> first = c.iterator().next();
160 assertTrue(c.remove(first));
161 Stream<Map.Entry<Integer, Integer>> s = c.stream();
162 Map.Entry<Integer, Integer> second = c.iterator().next();
163 assertTrue(c.remove(second));
164 Object[] result = s.toArray();
165 assertEquals(result.length, c.size());
166 }
167 }
|
1 /*
2 * Copyright (c) 2012, 2024, 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 java.util.concurrent.ArrayBlockingQueue;
26 import java.util.concurrent.ConcurrentHashMap;
27 import java.util.concurrent.ConcurrentLinkedDeque;
28 import java.util.concurrent.ConcurrentLinkedQueue;
29 import java.util.concurrent.ConcurrentSkipListMap;
30 import java.util.concurrent.ConcurrentSkipListSet;
31 import java.util.concurrent.LinkedBlockingDeque;
32 import java.util.concurrent.LinkedBlockingQueue;
33 import java.util.concurrent.LinkedTransferQueue;
34 import java.util.concurrent.PriorityBlockingQueue;
35 import java.util.function.Supplier;
36 import java.util.stream.IntStream;
37
38 import org.testng.annotations.DataProvider;
39 import org.testng.annotations.Test;
40
41 import java.util.*;
42 import java.util.stream.Stream;
43
44 import static org.testng.Assert.assertEquals;
45 import static org.testng.Assert.assertTrue;
46
47 /*
48 * @test
49 * @summary Tests laziness of stream operations
50 * @bug 8336672
51 */
52
53 /**
54 * Tests laziness of stream operations -- mutations to the source after the stream() but prior to terminal operations
55 * are reflected in the stream contents.
56 */
57 @Test
58 public class CollectionAndMapModifyStreamTest {
59 // Well known Identity instances; needed for IdentityHashMap
60 static List<String> CONTENT = IntStream.range(0, 10).mapToObj(i -> "BASE-" + i).toList();
61
62 @DataProvider(name = "collections")
63 public Object[][] createCollections() {
64
65 List<Collection<String>> collections = new ArrayList<>();
66 collections.add(new ArrayList<>(CONTENT));
67 collections.add(new LinkedList<>(CONTENT));
68 collections.add(new Vector<>(CONTENT));
69
70 collections.add(new HashSet<>(CONTENT));
71 collections.add(new LinkedHashSet<>(CONTENT));
72 collections.add(new TreeSet<>(CONTENT));
73
74 Stack<String> stack = new Stack<>();
75 stack.addAll(CONTENT);
76 collections.add(stack);
77 collections.add(new PriorityQueue<>(CONTENT));
78 collections.add(new ArrayDeque<>(CONTENT));
79
80 // Concurrent collections
81
82 collections.add(new ConcurrentSkipListSet<>(CONTENT));
83
84 ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(CONTENT.size());
85 for (String i : CONTENT)
86 arrayBlockingQueue.add(i);
87 collections.add(arrayBlockingQueue);
88 collections.add(new PriorityBlockingQueue<>(CONTENT));
89 collections.add(new LinkedBlockingQueue<>(CONTENT));
90 collections.add(new LinkedTransferQueue<>(CONTENT));
91 collections.add(new ConcurrentLinkedQueue<>(CONTENT));
92 collections.add(new LinkedBlockingDeque<>(CONTENT));
93 collections.add(new ConcurrentLinkedDeque<>(CONTENT));
94
95 Object[][] params = new Object[collections.size()][];
96 for (int i = 0; i < collections.size(); i++) {
97 params[i] = new Object[]{collections.get(i).getClass().getName(), collections.get(i)};
98 }
99
100 return params;
101 }
102
103 @Test(dataProvider = "collections")
104 public void testCollectionSizeRemove(String name, Collection<String> c) {
105 assertTrue(c.remove(CONTENT.get(0)));
106 Stream<String> s = c.stream();
107 assertTrue(c.remove(CONTENT.get(1)));
108 Object[] result = s.toArray();
109 assertEquals(result.length, c.size());
110 }
111
112 @DataProvider(name = "maps")
113 public Object[][] createMaps() {
114 Map<String, String> content = new HashMap<>();
115 for (int i = 0; i < 10; i++) {
116 var ix = CONTENT.get(i);
117 content.put(ix, ix);
118 }
119
120 Map<String, Supplier<Map<String, String>>> maps = new HashMap<>();
121
122 maps.put(HashMap.class.getName(), () -> new HashMap<>(content));
123 maps.put(LinkedHashMap.class.getName(), () -> new LinkedHashMap<>(content));
124 maps.put(IdentityHashMap.class.getName(), () -> new IdentityHashMap<>(content));
125 maps.put(WeakHashMap.class.getName(), () -> new WeakHashMap<>(content));
126
127 maps.put(TreeMap.class.getName(), () -> new TreeMap<>(content));
128 maps.put(TreeMap.class.getName() + ".descendingMap()", () -> new TreeMap<>(content).descendingMap());
129
130 // The following are not lazy
131 // maps.put(TreeMap.class.getName() + ".descendingMap().descendingMap()", () -> new TreeMap<>(content).descendingMap().descendingMap());
132 // maps.put(TreeMap.class.getName() + ".headMap()", () -> new TreeMap<>(content).headMap(content.size() - 1));
133 // maps.put(TreeMap.class.getName() + ".descendingMap().headMap()", () -> new TreeMap<>(content).descendingMap().tailMap(content.size() - 1, false));
134
135 // Concurrent collections
136
137 maps.put(ConcurrentHashMap.class.getName(), () -> new ConcurrentHashMap<>(content));
138 maps.put(ConcurrentSkipListMap.class.getName(), () -> new ConcurrentSkipListMap<>(content));
139
140 Object[][] params = new Object[maps.size()][];
141 int i = 0;
142 for (Map.Entry<String, Supplier<Map<String, String>>> e : maps.entrySet()) {
143 params[i++] = new Object[]{e.getKey(), e.getValue()};
144 }
145
146 return params;
147 }
148
149 @Test(dataProvider = "maps", groups = { "serialization-hostile" })
150 public void testMapKeysSizeRemove(String name, Supplier<Map<String, String>> c) {
151 testCollectionSizeRemove(name + " key set", c.get().keySet());
152 }
153
154 @Test(dataProvider = "maps", groups = { "serialization-hostile" })
155 public void testMapValuesSizeRemove(String name, Supplier<Map<String, String>> c) {
156 testCollectionSizeRemove(name + " value set", c.get().values());
157 }
158
159 @Test(dataProvider = "maps")
160 public void testMapEntriesSizeRemove(String name, Supplier<Map<String, String>> c) {
161 testEntrySetSizeRemove(name + " entry set", c.get().entrySet());
162 }
163
164 private void testEntrySetSizeRemove(String name, Set<Map.Entry<String, String>> c) {
165 Map.Entry<String, String> first = c.iterator().next();
166 assertTrue(c.remove(first));
167 Stream<Map.Entry<String, String>> s = c.stream();
168 Map.Entry<String, String> second = c.iterator().next();
169 assertTrue(c.remove(second));
170 Object[] result = s.toArray();
171 assertEquals(result.length, c.size());
172 }
173 }
|