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 5017904 6356890 8004928
27 * @summary Test empty iterators, enumerations, and collections
28 */
29
30import static java.util.Collections.*;
31import java.util.*;
32import java.util.concurrent.SynchronousQueue;
33
34public class EmptyIterator {
35
36    void test(String[] args) throws Throwable {
37        testEmptyCollection(emptyList());
38        testEmptyCollection(emptySet());
39        testEmptyCollection(new SynchronousQueue<Object>());
40        testEmptyMap(emptyMap());
41
42        Hashtable<?,?> emptyTable = new Hashtable<>();
43        testEmptyEnumeration(emptyTable.keys());
44        testEmptyEnumeration(emptyTable.elements());
45        testEmptyIterator(emptyTable.keySet().iterator());
46        testEmptyIterator(emptyTable.values().iterator());
47        testEmptyIterator(emptyTable.entrySet().iterator());
48
49        final Enumeration<EmptyIterator> finalEmptyTyped = emptyEnumeration();
50        testEmptyEnumeration(finalEmptyTyped);
51
52        final Enumeration<?> finalEmptyAbstract = emptyEnumeration();
53        testEmptyEnumeration(finalEmptyAbstract);
54
55        testEmptyIterator(emptyIterator());
56    }
57
58    void testEmptyEnumeration(final Enumeration<?> e) {
59        check(e == emptyEnumeration());
60        check(!e.hasMoreElements());
61        THROWS(NoSuchElementException.class,
62               new F(){void f(){ e.nextElement(); }});
63    }
64
65    void testEmptyIterator(final Iterator<?> it) {
66        check(it == emptyIterator());
67        check(! it.hasNext());
68        THROWS(NoSuchElementException.class,
69               new F(){void f(){ it.next(); }});
70        THROWS(IllegalStateException.class,
71               new F(){void f(){ it.remove(); }});
72    }
73
74    void testEmptyMap(Map<?,?> m) {
75        check(m == emptyMap());
76        check(m.entrySet().iterator() ==
77              Collections.<Map.Entry<?,?>>emptyIterator());
78        check(m.values().iterator() == emptyIterator());
79        check(m.keySet().iterator() == emptyIterator());
80        equal(m, unmodifiableMap(m));
81
82        testEmptyCollection(m.keySet());
83        testEmptyCollection(m.entrySet());
84        testEmptyCollection(m.values());
85    }
86
87    void testToArray(final Collection<?> c) {
88        Object[] a = c.toArray();
89        equal(a.length, 0);
90        equal(a.getClass().getComponentType(), Object.class);
91        THROWS(NullPointerException.class,
92               new F(){void f(){ c.toArray((Object[])null); }});
93
94        {
95            String[] t = new String[0];
96            check(c.toArray(t) == t);
97        }
98
99        {
100            String[] t = nCopies(10, "").toArray(new String[0]);
101            check(c.toArray(t) == t);
102            check(t[0] == null);
103            for (int i=1; i<t.length; i++)
104                check(t[i] == "");
105        }
106    }
107
108    void testEmptyCollection(final Collection<?> c) {
109        testEmptyIterator(c.iterator());
110
111        check(c.iterator() == emptyIterator());
112        if (c instanceof List)
113            check(((List<?>)c).listIterator() == emptyListIterator());
114
115        testToArray(c);
116    }
117
118    //--------------------- Infrastructure ---------------------------
119    volatile int passed = 0, failed = 0;
120    void pass() {passed++;}
121    void fail() {failed++; Thread.dumpStack();}
122    void fail(String msg) {System.err.println(msg); fail();}
123    void unexpected(Throwable t) {failed++; t.printStackTrace();}
124    void check(boolean cond) {if (cond) pass(); else fail();}
125    void equal(Object x, Object y) {
126        if (x == null ? y == null : x.equals(y)) pass();
127        else fail(x + " not equal to " + y);}
128    public static void main(String[] args) throws Throwable {
129        new EmptyIterator().instanceMain(args);}
130    void instanceMain(String[] args) throws Throwable {
131        try {test(args);} catch (Throwable t) {unexpected(t);}
132        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
133        if (failed > 0) throw new AssertionError("Some tests failed");}
134    abstract class F {abstract void f() throws Throwable;}
135    void THROWS(Class<? extends Throwable> k, F... fs) {
136        for (F f : fs)
137            try {f.f(); fail("Expected " + k.getName() + " not thrown");}
138            catch (Throwable t) {
139                if (k.isAssignableFrom(t.getClass())) pass();
140                else unexpected(t);}}
141}
142