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