1/*
2 * Copyright (c) 2011, 2017, 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 4533691 7129185
27 * @summary Unit test for Collections.emptyNavigableSet
28 * @run testng EmptyNavigableSet
29 */
30import java.math.BigInteger;
31import java.util.Arrays;
32import java.util.Collection;
33import java.util.Collections;
34import java.util.Comparator;
35import java.util.Iterator;
36import java.util.NoSuchElementException;
37import java.util.NavigableSet;
38import java.util.SortedSet;
39import java.util.TreeSet;
40
41import org.testng.Assert;
42import org.testng.Assert.ThrowingRunnable;
43import org.testng.annotations.Test;
44import org.testng.annotations.DataProvider;
45
46import static org.testng.Assert.assertFalse;
47import static org.testng.Assert.assertSame;
48import static org.testng.Assert.assertTrue;
49
50public class EmptyNavigableSet {
51
52    public static <T> void assertInstance(T actual, Class<? extends T> expected) {
53        assertInstance(expected.isInstance(actual), null);
54    }
55
56    public static <T> void assertInstance(T actual, Class<? extends T> expected, String message) {
57        assertTrue(expected.isInstance(actual), ((null != message) ? message : "")
58            + " " + (actual == null ? "<null>" : actual.getClass().getSimpleName()) + " != " + expected.getSimpleName() + ". ");
59    }
60
61    public static <T extends Throwable> void assertEmptyNavigableSet(Object obj) {
62        assertInstance(obj, NavigableSet.class);
63        assertTrue(((NavigableSet)obj).isEmpty() && (((NavigableSet)obj).size() == 0));
64    }
65
66    public static <T extends Throwable> void assertEmptyNavigableSet(Object obj, String message) {
67        assertInstance(obj, NavigableSet.class, message);
68        assertTrue(((NavigableSet)obj).isEmpty() && (((NavigableSet)obj).size() == 0),
69            ((null != message) ? message : "") + " Not empty. ");
70    }
71
72    private <T extends Throwable> void assertThrows(Class<T> throwableClass,
73                                                    ThrowingRunnable runnable,
74                                                    String message) {
75        try {
76            Assert.assertThrows(throwableClass, runnable);
77        } catch (AssertionError e) {
78            throw new AssertionError(String.format("%s%n%s",
79                    ((null != message) ? message : ""), e.getMessage()), e);
80        }
81    }
82
83    private void assertThrowsCCE(ThrowingRunnable r, String s) {
84        assertThrows(ClassCastException.class, r, s);
85    }
86
87    private void assertThrowsNPE(ThrowingRunnable r, String s) {
88        assertThrows(NullPointerException.class, r, s);
89    }
90
91    private void assertThrowsIAE(ThrowingRunnable r, String s) {
92        assertThrows(IllegalArgumentException.class, r, s);
93    }
94
95    private void assertThrowsNSEE(ThrowingRunnable r, String s) {
96        assertThrows(NoSuchElementException.class, r, s);
97    }
98
99    public static final boolean isDescending(SortedSet<?> set) {
100        if (null == set.comparator()) {
101            // natural order
102            return false;
103        }
104
105        if (Collections.reverseOrder() == set.comparator()) {
106            // reverse natural order.
107            return true;
108        }
109
110        if (set.comparator().equals(Collections.reverseOrder(Collections.reverseOrder(set.comparator())))) {
111            // it's a Collections.reverseOrder(Comparator).
112            return true;
113        }
114
115        throw new IllegalStateException("can't determine ordering for " + set);
116    }
117
118    /**
119     * Tests that the comparator is {@code null}.
120     */
121    @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
122    public void testComparatorIsNull(String description, NavigableSet<?> navigableSet) {
123        Comparator comparator = navigableSet.comparator();
124
125        assertTrue(comparator == null || comparator == Collections.reverseOrder(), description + ": Comparator (" + comparator + ") is not null.");
126    }
127
128    /**
129     * Tests that contains requires Comparable
130     */
131    @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
132    public void testContainsRequiresComparable(String description, NavigableSet<?> navigableSet) {
133        assertThrowsCCE(() -> {
134            navigableSet.contains(new Object());
135        },
136            description + ": Compareable should be required");
137    }
138
139    /**
140     * Tests that the contains method returns {@code false}.
141     */
142    @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
143    public void testContains(String description, NavigableSet<?> navigableSet) {
144        assertFalse(navigableSet.contains(new Integer(1)),
145            description + ": Should not contain any elements.");
146    }
147
148    /**
149     * Tests that the containsAll method returns {@code false}.
150     */
151    @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
152    public void testContainsAll(String description, NavigableSet<?> navigableSet) {
153        TreeSet treeSet = new TreeSet();
154        treeSet.add("1");
155        treeSet.add("2");
156        treeSet.add("3");
157
158        assertFalse(navigableSet.containsAll(treeSet), "Should not contain any elements.");
159    }
160
161    /**
162     * Tests that the iterator is empty.
163     */
164    @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
165    public void testEmptyIterator(String description, NavigableSet<?> navigableSet) {
166        Iterator emptyIterator = navigableSet.iterator();
167
168        assertFalse((emptyIterator != null) && (emptyIterator.hasNext()),
169            "The iterator is not empty.");
170    }
171
172    /**
173     * Tests that the set is empty.
174     */
175    @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
176    public void testIsEmpty(String description, NavigableSet<?> navigableSet) {
177        assertTrue(navigableSet.isEmpty(), "The set is not empty.");
178    }
179
180    /**
181     * Tests that the first() method throws NoSuchElementException
182     */
183    @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
184    public void testFirst(String description, NavigableSet<?> navigableSet) {
185        assertThrowsNSEE(() -> {
186            navigableSet.first();
187        }, description);
188    }
189
190    /**
191     * Tests the headSet() method.
192     */
193    @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
194    public void testHeadSet(String description, NavigableSet navigableSet) {
195        assertThrowsNPE(
196            () -> { NavigableSet ns = navigableSet.headSet(null, false); },
197            description + ": Must throw NullPointerException for null element");
198
199        assertThrowsCCE(
200            () -> { NavigableSet ns = navigableSet.headSet(new Object(), true); },
201            description + ": Must throw ClassCastException for non-Comparable element");
202
203        NavigableSet ns = navigableSet.headSet("1", false);
204
205        assertEmptyNavigableSet(ns, description + ": Returned value is not empty navigable set.");
206    }
207
208    /**
209     * Tests that the last() method throws NoSuchElementException
210     */
211    @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
212    public void testLast(String description, NavigableSet<?> navigableSet) {
213        assertThrowsNSEE(() -> {
214            navigableSet.last();
215        }, description);
216    }
217
218    /**
219     * Tests that the size is 0.
220     */
221    @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
222    public void testSizeIsZero(String description, NavigableSet<?> navigableSet) {
223        assertTrue(0 == navigableSet.size(), "The size of the set is not 0.");
224    }
225
226    /**
227     * Tests the subSet() method.
228     */
229    @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
230    public void testSubSet(String description, NavigableSet navigableSet) {
231        assertThrowsNPE(
232            () -> {
233                SortedSet ss = navigableSet.subSet(null, BigInteger.TEN);
234            },
235            description + ": Must throw NullPointerException for null element");
236
237        assertThrowsNPE(
238            () -> {
239                SortedSet ss = navigableSet.subSet(BigInteger.ZERO, null);
240            },
241            description + ": Must throw NullPointerException for null element");
242
243        assertThrowsNPE(
244            () -> {
245                SortedSet ss = navigableSet.subSet(null, null);
246            },
247            description + ": Must throw NullPointerException for null element");
248
249        Object obj1 = new Object();
250        Object obj2 = new Object();
251
252        assertThrowsCCE(
253            () -> {
254                SortedSet ss = navigableSet.subSet(obj1, BigInteger.TEN);
255            },
256            description + ": Must throw ClassCastException for parameter which is not Comparable.");
257
258        assertThrowsCCE(
259            () -> {
260                SortedSet ss = navigableSet.subSet(BigInteger.ZERO, obj2);
261            },
262            description + ": Must throw ClassCastException for parameter which is not Comparable.");
263
264        assertThrowsCCE(
265            () -> {
266                SortedSet ss = navigableSet.subSet(obj1, obj2);
267            },
268            description + ": Must throw ClassCastException for parameter which is not Comparable.");
269
270        // minimal range
271        navigableSet.subSet(BigInteger.ZERO, false, BigInteger.ZERO, false);
272        navigableSet.subSet(BigInteger.ZERO, false, BigInteger.ZERO, true);
273        navigableSet.subSet(BigInteger.ZERO, true, BigInteger.ZERO, false);
274        navigableSet.subSet(BigInteger.ZERO, true, BigInteger.ZERO, true);
275
276        Object first = isDescending(navigableSet) ? BigInteger.TEN : BigInteger.ZERO;
277        Object last = (BigInteger.ZERO == first) ? BigInteger.TEN : BigInteger.ZERO;
278
279            assertThrowsIAE(
280                () -> {
281                    navigableSet.subSet(last, true, first, false);
282                },
283                description
284                + ": Must throw IllegalArgumentException when fromElement is not less than toElement.");
285
286        navigableSet.subSet(first, true, last, false);
287    }
288
289    @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
290    public void testSubSetRanges(String description, NavigableSet navigableSet) {
291        Object first = isDescending(navigableSet) ? BigInteger.TEN : BigInteger.ZERO;
292        Object last = (BigInteger.ZERO == first) ? BigInteger.TEN : BigInteger.ZERO;
293
294        NavigableSet subSet = navigableSet.subSet(first, true, last, true);
295
296        // same subset
297        subSet.subSet(first, true, last, true);
298
299        // slightly smaller
300        NavigableSet ns = subSet.subSet(first, false, last, false);
301        // slight expansion
302        assertThrowsIAE(() -> {
303            ns.subSet(first, true, last, true);
304        },
305            description + ": Expansion should not be allowed");
306
307        // much smaller
308        subSet.subSet(first, false, BigInteger.ONE, false);
309    }
310
311    @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
312    public void testheadSetRanges(String description, NavigableSet navigableSet) {
313        NavigableSet subSet = navigableSet.headSet(BigInteger.ONE, true);
314
315        // same subset
316        subSet.headSet(BigInteger.ONE, true);
317
318        // slightly smaller
319        NavigableSet ns = subSet.headSet(BigInteger.ONE, false);
320
321        // slight expansion
322        assertThrowsIAE(() -> {
323            ns.headSet(BigInteger.ONE, true);
324        },
325            description + ": Expansion should not be allowed");
326
327        // much smaller
328        subSet.headSet(isDescending(subSet) ? BigInteger.TEN : BigInteger.ZERO, true);
329    }
330
331    @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
332    public void testTailSetRanges(String description, NavigableSet navigableSet) {
333        NavigableSet subSet = navigableSet.tailSet(BigInteger.ONE, true);
334
335        // same subset
336        subSet.tailSet(BigInteger.ONE, true);
337
338        // slightly smaller
339        NavigableSet ns = subSet.tailSet(BigInteger.ONE, false);
340
341        // slight expansion
342        assertThrowsIAE(() -> {
343            ns.tailSet(BigInteger.ONE, true);
344        },
345            description + ": Expansion should not be allowed");
346
347        // much smaller
348        subSet.tailSet(isDescending(subSet) ? BigInteger.ZERO : BigInteger.TEN, false);
349    }
350
351    /**
352     * Tests the tailSet() method.
353     */
354    @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
355    public void testTailSet(String description, NavigableSet navigableSet) {
356        assertThrowsNPE(() -> {
357            navigableSet.tailSet(null);
358        },
359            description + ": Must throw NullPointerException for null element");
360
361        assertThrowsCCE(() -> {
362            navigableSet.tailSet(new Object());
363        }, description);
364
365        NavigableSet ss = navigableSet.tailSet("1", true);
366
367        assertEmptyNavigableSet(ss, description + ": Returned value is not empty navigable set.");
368    }
369
370    /**
371     * Tests that the array has a size of 0.
372     */
373    @Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
374    public void testToArray(String description, NavigableSet<?> navigableSet) {
375        Object[] emptyNavigableSetArray = navigableSet.toArray();
376
377        assertTrue(emptyNavigableSetArray.length == 0, "Returned non-empty Array.");
378
379        emptyNavigableSetArray = new Object[20];
380
381        Object[] result = navigableSet.toArray(emptyNavigableSetArray);
382
383        assertSame(emptyNavigableSetArray, result);
384
385        assertTrue(result[0] == null);
386    }
387
388    @DataProvider(name = "NavigableSet<?>", parallel = true)
389    public static Iterator<Object[]> navigableSetsProvider() {
390        return makeNavigableSets().iterator();
391    }
392
393    public static Collection<Object[]> makeNavigableSets() {
394        return Arrays.asList(
395            new Object[]{"UnmodifiableNavigableSet(TreeSet)", Collections.unmodifiableNavigableSet(new TreeSet())},
396            new Object[]{"UnmodifiableNavigableSet(TreeSet.descendingSet()", Collections.unmodifiableNavigableSet(new TreeSet().descendingSet())},
397            new Object[]{"UnmodifiableNavigableSet(TreeSet.descendingSet().descendingSet()", Collections.unmodifiableNavigableSet(new TreeSet().descendingSet().descendingSet())},
398            new Object[]{"emptyNavigableSet()", Collections.emptyNavigableSet()},
399            new Object[]{"emptyNavigableSet().descendingSet()", Collections.emptyNavigableSet().descendingSet()},
400            new Object[]{"emptyNavigableSet().descendingSet().descendingSet()", Collections.emptyNavigableSet().descendingSet().descendingSet()}
401        );
402    }
403}
404