1 /* 2 * Copyright (c) 2006, 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 6415641 6377302 27 * @summary Concurrent collections are permitted to lie about their size 28 * @author Martin Buchholz 29 */ 30 package test.java.util.Collection; 31 32 import java.util.Arrays; 33 import java.util.Collection; 34 import java.util.Map; 35 import java.util.NavigableMap; 36 import java.util.NavigableSet; 37 import java.util.Objects; 38 import java.util.Random; 39 import java.util.Set; 40 import java.util.TreeSet; 41 import java.util.concurrent.ArrayBlockingQueue; 42 import java.util.concurrent.ConcurrentHashMap; 43 import java.util.concurrent.ConcurrentLinkedDeque; 44 import java.util.concurrent.ConcurrentLinkedQueue; 45 import java.util.concurrent.ConcurrentSkipListMap; 46 import java.util.concurrent.ConcurrentSkipListSet; 47 import java.util.concurrent.CopyOnWriteArrayList; 48 import java.util.concurrent.CopyOnWriteArraySet; 49 import java.util.concurrent.LinkedBlockingDeque; 50 import java.util.concurrent.LinkedBlockingQueue; 51 import java.util.concurrent.LinkedTransferQueue; 52 import java.util.concurrent.PriorityBlockingQueue; 53 import org.testng.Assert; 54 import org.testng.annotations.Test; 55 56 @SuppressWarnings("unchecked") 57 public class BiggernYours { 58 59 static final Random rnd = new Random(18675309); 60 compareCollections(Collection c1, Collection c2)61 static void compareCollections(Collection c1, Collection c2) { 62 Object[] c1Array = c1.toArray(); 63 Object[] c2Array = c2.toArray(); 64 65 Assert.assertEquals(c1Array.length, c2Array.length); 66 for (Object aC1 : c1Array) { 67 boolean found = false; 68 for (Object aC2 : c2Array) { 69 if (Objects.equals(aC1, aC2)) { 70 found = true; 71 break; 72 } 73 } 74 75 if (!found) { 76 Assert.fail(aC1 + " not found in " + Arrays.toString(c2Array)); 77 } 78 } 79 } 80 compareMaps(Map m1, Map m2)81 static void compareMaps(Map m1, Map m2) { 82 compareCollections(m1.keySet(), 83 m2.keySet()); 84 compareCollections(m1.values(), 85 m2.values()); 86 compareCollections(m1.entrySet(), 87 m2.entrySet()); 88 } 89 compareNavigableMaps(NavigableMap m1, NavigableMap m2)90 static void compareNavigableMaps(NavigableMap m1, NavigableMap m2) { 91 compareMaps(m1, m2); 92 compareMaps(m1.descendingMap(), 93 m2.descendingMap()); 94 compareMaps(m1.tailMap(Integer.MIN_VALUE), 95 m2.tailMap(Integer.MIN_VALUE)); 96 compareMaps(m1.headMap(Integer.MAX_VALUE), 97 m2.headMap(Integer.MAX_VALUE)); 98 } 99 compareNavigableSets(NavigableSet s1, NavigableSet s2)100 static void compareNavigableSets(NavigableSet s1, NavigableSet s2) { 101 compareCollections(s1, s2); 102 compareCollections(s1.descendingSet(), 103 s2.descendingSet()); 104 compareCollections(s1.tailSet(Integer.MIN_VALUE), 105 s2.tailSet(Integer.MIN_VALUE)); 106 } 107 108 abstract static class MapFrobber { 109 frob(Map m)110 abstract void frob(Map m); 111 } 112 113 abstract static class ColFrobber { 114 frob(Collection c)115 abstract void frob(Collection c); 116 } 117 adder(final int i)118 static ColFrobber adder(final int i) { 119 return new ColFrobber() { 120 void frob(Collection c) { 121 c.add(i); 122 } 123 }; 124 } 125 126 static final ColFrobber[] adders = 127 {adder(1), adder(3), adder(2)}; 128 129 static MapFrobber putter(final int k, final int v) { 130 return new MapFrobber() { 131 void frob(Map m) { 132 m.put(k, v); 133 } 134 }; 135 } 136 137 static final MapFrobber[] putters = 138 {putter(1, -2), putter(3, -6), putter(2, -4)}; 139 140 static void testCollections(Collection c1, Collection c2) { 141 try { 142 compareCollections(c1, c2); 143 for (ColFrobber adder : adders) { 144 for (Collection c : new Collection[]{c1, c2}) { 145 adder.frob(c); 146 } 147 compareCollections(c1, c2); 148 } 149 } catch (Throwable t) { 150 Assert.fail("Unexpected exception: " + t.getMessage()); 151 } 152 } 153 154 static void testNavigableSets(NavigableSet s1, NavigableSet s2) { 155 try { 156 compareNavigableSets(s1, s2); 157 for (ColFrobber adder : adders) { 158 for (Set s : new Set[]{s1, s2}) { 159 adder.frob(s); 160 } 161 compareNavigableSets(s1, s2); 162 } 163 } catch (Throwable t) { 164 Assert.fail("Unexpected exception: " + t.getMessage()); 165 } 166 } 167 168 static void testMaps(Map m1, Map m2) { 169 try { 170 compareMaps(m1, m2); 171 for (MapFrobber putter : putters) { 172 for (Map m : new Map[]{m1, m2}) { 173 putter.frob(m); 174 } 175 compareMaps(m1, m2); 176 } 177 } catch (Throwable t) { 178 Assert.fail("Unexpected exception: " + t.getMessage()); 179 } 180 } 181 182 static void testNavigableMaps(NavigableMap m1, NavigableMap m2) { 183 try { 184 compareNavigableMaps(m1, m2); 185 for (MapFrobber putter : putters) { 186 for (Map m : new Map[]{m1, m2}) { 187 putter.frob(m); 188 } 189 compareNavigableMaps(m1, m2); 190 } 191 } catch (Throwable t) { 192 Assert.fail("Unexpected exception: " + t.getMessage()); 193 } 194 } 195 196 static int randomize(int size) { 197 return rnd.nextInt(size + 2); 198 } 199 200 @Test 201 public void testConcurrentSkipListMap() { 202 testNavigableMaps( 203 new ConcurrentSkipListMap(), 204 new ConcurrentSkipListMap() { 205 public int size() { 206 return randomize(super.size()); 207 } 208 }); 209 } 210 211 @Test 212 public void testConcurrentSkipListSet() { 213 testNavigableSets( 214 new ConcurrentSkipListSet(), 215 new ConcurrentSkipListSet() { 216 public int size() { 217 return randomize(super.size()); 218 } 219 }); 220 } 221 222 @Test 223 public void testCopyOnWriteArraySet() { 224 testCollections( 225 new CopyOnWriteArraySet(), 226 new CopyOnWriteArraySet() { 227 public int size() { 228 return randomize(super.size()); 229 } 230 }); 231 } 232 233 @Test 234 public void testCopyOnWriteArrayList() { 235 testCollections( 236 new CopyOnWriteArrayList(), 237 new CopyOnWriteArrayList() { 238 public int size() { 239 return randomize(super.size()); 240 } 241 }); 242 } 243 244 @Test 245 public void testTreeSet() { 246 testCollections( 247 new TreeSet(), 248 new TreeSet() { 249 public int size() { 250 return randomize(super.size()); 251 } 252 }); 253 } 254 255 @Test 256 public void testConcurrentHashMap() { 257 testMaps( 258 new ConcurrentHashMap(), 259 new ConcurrentHashMap() { 260 public int size() { 261 return randomize(super.size()); 262 } 263 }); 264 } 265 266 @Test 267 public void testConcurrentLinkedDeque() { 268 testCollections( 269 new ConcurrentLinkedDeque(), 270 new ConcurrentLinkedDeque() { 271 public int size() { 272 return randomize(super.size()); 273 } 274 }); 275 } 276 277 @Test 278 public void testConcurrentLinkedQueue() { 279 testCollections( 280 new ConcurrentLinkedQueue(), 281 new ConcurrentLinkedQueue() { 282 public int size() { 283 return randomize(super.size()); 284 } 285 }); 286 } 287 288 @Test 289 public void testLinkedTransferQueue() { 290 testCollections( 291 new LinkedTransferQueue(), 292 new LinkedTransferQueue() { 293 public int size() { 294 return randomize(super.size()); 295 } 296 }); 297 } 298 299 @Test 300 public void testLinkedBlockingQueue() { 301 testCollections( 302 new LinkedBlockingQueue(), 303 new LinkedBlockingQueue() { 304 public int size() { 305 return randomize(super.size()); 306 } 307 }); 308 } 309 310 @Test 311 public void testLinkedBlockingDeque() { 312 testCollections( 313 new LinkedBlockingDeque(), 314 new LinkedBlockingDeque() { 315 public int size() { 316 return randomize(super.size()); 317 } 318 }); 319 } 320 321 @Test 322 public void testArrayBlockingQueue() { 323 testCollections( 324 new ArrayBlockingQueue(5), 325 new ArrayBlockingQueue(5) { 326 public int size() { 327 return randomize(super.size()); 328 } 329 }); 330 } 331 332 @Test 333 public void testPriorityBlockingQueue() { 334 testCollections( 335 new PriorityBlockingQueue(5), 336 new PriorityBlockingQueue(5) { 337 public int size() { 338 return randomize(super.size()); 339 } 340 }); 341 } 342 } 343