1 /*
2  * Copyright (c) 2007, 2014, 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 
24 /*
25  * @test
26  * @bug 6529795
27  * @summary next() does not change iterator state if throws NoSuchElementException
28  * @author Martin Buchholz
29  */
30 package test.java.util.Collection;
31 
32 import java.util.ArrayDeque;
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.HashMap;
36 import java.util.Hashtable;
37 import java.util.IdentityHashMap;
38 import java.util.Iterator;
39 import java.util.LinkedHashMap;
40 import java.util.LinkedList;
41 import java.util.List;
42 import java.util.ListIterator;
43 import java.util.Map;
44 import java.util.NoSuchElementException;
45 import java.util.PriorityQueue;
46 import java.util.TreeMap;
47 import java.util.TreeSet;
48 import java.util.Vector;
49 import java.util.WeakHashMap;
50 import java.util.concurrent.ArrayBlockingQueue;
51 import java.util.concurrent.ConcurrentHashMap;
52 import java.util.concurrent.ConcurrentLinkedDeque;
53 import java.util.concurrent.ConcurrentLinkedQueue;
54 import java.util.concurrent.ConcurrentSkipListMap;
55 import java.util.concurrent.ConcurrentSkipListSet;
56 import java.util.concurrent.CopyOnWriteArrayList;
57 import java.util.concurrent.CopyOnWriteArraySet;
58 import java.util.concurrent.LinkedBlockingQueue;
59 import java.util.concurrent.LinkedTransferQueue;
60 import org.testng.Assert;
61 import org.testng.annotations.Test;
62 
63 @SuppressWarnings("unchecked")
64 public class IteratorAtEnd {
65 
66     private static final int SIZE = 6;
67 
68     @Test
testArrayList()69     public void testArrayList() {
70         testCollection(new ArrayList());
71     }
72 
73     @Test
testVector()74     public void testVector() {
75         testCollection(new Vector());
76     }
77 
78     @Test
testLinkedList()79     public void testLinkedList() {
80         testCollection(new LinkedList());
81     }
82 
83     @Test
testArrayDeque()84     public void testArrayDeque() {
85         testCollection(new ArrayDeque());
86     }
87 
88     @Test
testTreeSet()89     public void testTreeSet() {
90         testCollection(new TreeSet());
91     }
92 
93     @Test
testCopyOnWriteArrayList()94     public void testCopyOnWriteArrayList() {
95         testCollection(new CopyOnWriteArrayList());
96     }
97 
98     @Test
testCopyOnWriteArraySet()99     public void testCopyOnWriteArraySet() {
100         testCollection(new CopyOnWriteArraySet());
101     }
102 
103     @Test
testConcurrentSkipListSet()104     public void testConcurrentSkipListSet() {
105         testCollection(new ConcurrentSkipListSet());
106     }
107 
108     @Test
testPriorityQueue()109     public void testPriorityQueue() {
110         testCollection(new PriorityQueue());
111     }
112 
113     @Test
testLinkedBlockingQueue()114     public void testLinkedBlockingQueue() {
115         testCollection(new LinkedBlockingQueue());
116     }
117 
118     @Test
testArrayBlockingQueue()119     public void testArrayBlockingQueue() {
120         testCollection(new ArrayBlockingQueue(100));
121     }
122 
123     @Test
testConcurrentLinkedDeque()124     public void testConcurrentLinkedDeque() {
125         testCollection(new ConcurrentLinkedDeque());
126     }
127 
128     @Test
testConcurrentLinkedQueue()129     public void testConcurrentLinkedQueue() {
130         testCollection(new ConcurrentLinkedQueue());
131     }
132 
133     @Test
testLinkedTransferQueue()134     public void testLinkedTransferQueue() {
135         testCollection(new LinkedTransferQueue());
136     }
137 
138     @Test
testHashMap()139     public void testHashMap() {
140         testMap(new HashMap());
141     }
142 
143     @Test
testHashtable()144     public void testHashtable() {
145         testMap(new Hashtable());
146     }
147 
148     @Test
testLinkedHashMap()149     public void testLinkedHashMap() {
150         testMap(new LinkedHashMap());
151     }
152 
153     @Test
testWeakHashMap()154     public void testWeakHashMap() {
155         testMap(new WeakHashMap());
156     }
157 
158     @Test
testIdentityHashMap()159     public void testIdentityHashMap() {
160         testMap(new IdentityHashMap());
161     }
162 
163     @Test
testConcurrentHashMap()164     public void testConcurrentHashMap() {
165         testMap(new ConcurrentHashMap());
166     }
167 
168     @Test
testConcurrentSkipListMap()169     public void testConcurrentSkipListMap() {
170         testMap(new ConcurrentSkipListMap());
171     }
172 
173     @Test
testTreeMap()174     public void testTreeMap() {
175         testMap(new TreeMap());
176     }
177 
testCollection(Collection c)178     static void testCollection(Collection c) {
179         try {
180             for (int i = 0; i < SIZE; i++) {
181                 c.add(i);
182             }
183             test(c);
184         } catch (Throwable t) {
185             Assert.fail("Unexpected exception: " + t.getMessage());
186         }
187     }
188 
testMap(Map m)189     static void testMap(Map m) {
190         try {
191             for (int i = 0; i < 3 * SIZE; i++) {
192                 m.put(i, i);
193             }
194             test(m.values());
195             test(m.keySet());
196             test(m.entrySet());
197         } catch (Throwable t) {
198             Assert.fail("Unexpected exception: " + t.getMessage());
199         }
200     }
201 
test(Collection c)202     static void test(Collection c) {
203         try {
204             final Iterator it = c.iterator();
205             THROWS(NoSuchElementException.class,
206                     () -> {
207                         while (true) {
208                             it.next();
209                         }
210                     });
211             try {
212                 it.remove();
213             } catch (UnsupportedOperationException exc) {
214                 return;
215             }
216         } catch (Throwable t) {
217             Assert.fail("Unexpected exception: " + t.getMessage());
218         }
219 
220         if (c instanceof List) {
221             final List list = (List) c;
222             try {
223                 final ListIterator it = list.listIterator(0);
224                 it.next();
225                 final Object x = it.previous();
226                 THROWS(NoSuchElementException.class, it::previous);
227                 try {
228                     it.remove();
229                 } catch (UnsupportedOperationException exc) {
230                     return;
231                 }
232                 Assert.assertFalse(list.get(0).equals(x));
233             } catch (Throwable t) {
234                 Assert.fail("Unexpected exception: " + t.getMessage());
235             }
236 
237             try {
238                 final ListIterator it = list.listIterator(list.size());
239                 it.previous();
240                 final Object x = it.next();
241                 THROWS(NoSuchElementException.class, it::next);
242                 try {
243                     it.remove();
244                 } catch (UnsupportedOperationException exc) {
245                     return;
246                 }
247                 Assert.assertFalse(list.get(list.size() - 1).equals(x));
248             } catch (Throwable t) {
249                 Assert.fail("Unexpected exception: " + t.getMessage());
250             }
251         }
252     }
253 
254     interface Fun {
255 
f()256         void f() throws Throwable;
257     }
258 
THROWS(Class<? extends Throwable> k, Fun... fs)259     static void THROWS(Class<? extends Throwable> k, Fun... fs) {
260         for (Fun f : fs) {
261             try {
262                 f.f();
263                 Assert.fail("Expected " + k.getName() + " not thrown");
264             } catch (Throwable t) {
265                 if (!k.isAssignableFrom(t.getClass())) {
266                     Assert.fail("Unexpected exception: " + t.getMessage());
267                 }
268             }
269         }
270     }
271 }
272