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