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