1 /*
2  * Copyright (c) 2015, 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 test.java.util.Collections;
24 
25 /**
26  * @test
27  * @bug 8072726
28  * @summary Tests for Enumeration-to-Iterator conversion.
29  * @run testng EnumerationAsIterator
30  */
31 
32 import org.testng.annotations.DataProvider;
33 import org.testng.annotations.Test;
34 
35 import java.util.ArrayList;
36 import java.util.Arrays;
37 import java.util.Collection;
38 import java.util.Collections;
39 import java.util.Enumeration;
40 import java.util.Iterator;
41 import java.util.List;
42 import java.util.NoSuchElementException;
43 import java.util.concurrent.atomic.AtomicInteger;
44 import java.util.function.Supplier;
45 
46 import static org.testng.Assert.*;
47 
48 @Test
49 public class EnumerationAsIterator {
of(String description, Supplier<Enumeration<?>> s, Collection<?> exp)50     static Object[] of(String description, Supplier<Enumeration<?>> s, Collection<?> exp) {
51         return new Object[]{description, s, exp};
52     }
53 
of(String description, Collection<?> c, Collection<?> exp)54     static Object[] of(String description, Collection<?> c, Collection<?> exp) {
55         return of(description, () -> Collections.enumeration(c), exp);
56     }
57 
58     /**
59      * A wrapper Enumeration that doesn't override the
60      * default method on Enumeration.
61      */
wrapInDefault(Enumeration<T> e)62     static <T> Enumeration<T> wrapInDefault(Enumeration<T> e) {
63         return new Enumeration<>() {
64             @Override
65             public boolean hasMoreElements() {
66                 return e.hasMoreElements();
67             }
68 
69             @Override
70             public T nextElement() {
71                 return e.nextElement();
72             }
73         };
74     }
75 
76     @DataProvider
77     public static Iterator<Object[]> unmodifiable() {
78         return Arrays.asList(
79             of("Default-wrapped ArrayList",
80                () -> wrapInDefault(
81                    Collections.enumeration(new ArrayList<>(Arrays.asList("a")))),
82                Arrays.asList("a")),
83 
84             of("Unmodifiable ArrayList",
85                Collections.unmodifiableList(new ArrayList<>(Arrays.asList("a"))),
86                Arrays.asList("a")),
87 
88             of("Modifiable ArrayList",
89                new ArrayList<>(Arrays.asList("a")),
90                Arrays.asList("a"))
91         ).iterator();
92     }
93 
94     @DataProvider
95     public static Iterator<Object[]> others() {
96         return Arrays.asList(
97             of("Default Collections.emptyEnumeration()",
98                () -> wrapInDefault(Collections.emptyEnumeration()),
99                Collections.emptyList()),
100 
101             of("Collections.emptyEnumeration()",
102                Collections::emptyEnumeration,
103                Collections.emptyList()),
104 
105             of("Collections.emptyList()",
106                Collections.emptyList(),
107                Collections.emptyList()),
108 
109             of("Collections.singletonList()",
110                Collections.singletonList("a"),
111                Collections.singletonList("a")),
112 
113             of("Arrays.asList(...)",
114                Arrays.asList("a", "b", "c"),
115                Arrays.asList("a", "b", "c"))
116         ).iterator();
117     }
118 
119     @DataProvider
120     public static Iterator<Object[]> all() {
121         List<Object[]> all = new ArrayList<>();
122         unmodifiable().forEachRemaining(all::add);
123         others().forEachRemaining(all::add);
124         return all.iterator();
125     }
126 
127     @Test(dataProvider = "all")
128     public void consumeByNext(String description, Supplier<Enumeration<?>> s, Collection<?> exp) {
129         Iterator<?> i = s.get().asIterator();
130         int count = 0;
131         while (i.hasNext()) {
132             assertTrue(i.hasNext());
133 
134             i.next();
135             count++;
136         }
137         assertEquals(count, exp.size());
138 
139         assertFalse(i.hasNext());
140 
141         try {
142             i.next();
143             fail();
144         } catch (NoSuchElementException e) {
145         }
146     }
147 
148     @Test(dataProvider = "all")
149     public void consumeByForEachRemaining(String description,
150                                           Supplier<Enumeration<?>> s,
151                                           Collection<?> exp) {
152         Iterator<?> i = s.get().asIterator();
153         AtomicInteger ai = new AtomicInteger();
154         i.forEachRemaining(e -> ai.getAndIncrement());
155         assertEquals(ai.get(), exp.size());
156         i.forEachRemaining(e -> ai.getAndIncrement());
157         assertEquals(ai.get(), exp.size());
158 
159         assertFalse(i.hasNext());
160 
161         try {
162             i.next();
163             fail();
164         } catch (NoSuchElementException e) {
165         }
166     }
167 
168     @Test(dataProvider = "all")
169     public void consumeByNextThenForEachRemaining(String description,
170                                                   Supplier<Enumeration<?>> s,
171                                                   Collection<?> exp) {
172         Iterator<?> i = s.get().asIterator();
173         AtomicInteger ai = new AtomicInteger();
174         if (i.hasNext()) {
175             i.next();
176             ai.getAndIncrement();
177         }
178         i.forEachRemaining(e -> ai.getAndIncrement());
179         assertEquals(ai.get(), exp.size());
180         i.forEachRemaining(e -> ai.getAndIncrement());
181         assertEquals(ai.get(), exp.size());
182 
183         assertFalse(i.hasNext());
184 
185         try {
186             i.next();
187             fail();
188         } catch (NoSuchElementException e) {
189         }
190     }
191 
192     @Test(dataProvider = "all")
193     public void contents(String description, Supplier<Enumeration<?>> s, Collection<?> exp) {
194         assertEquals(copy(s.get()), exp);
195     }
196 
197     private List<?> copy(Enumeration<?> input) {
198         List<Object> output = new ArrayList<>();
199         input.asIterator().forEachRemaining(output::add);
200         return output;
201     }
202 
203     @Test(dataProvider = "unmodifiable",
204           expectedExceptions=UnsupportedOperationException.class)
205     public void removeThrowsAfterAdvancingE(String description,
206                                             Supplier<Enumeration<?>> s,
207                                             Collection<?> exp) {
208         Enumeration<?> e = s.get();
209         e.nextElement();
210         e.asIterator().remove();
211     }
212 
213     @Test(dataProvider = "unmodifiable",
214           expectedExceptions=UnsupportedOperationException.class)
215     public void removeThrowsAfterAdvancingI(String description,
216                                             Supplier<Enumeration<?>> s,
217                                             Collection<?> exp) {
218         Iterator<?> i = s.get().asIterator();
219         i.next();
220         i.remove();
221     }
222 }
223