1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package org.apache.harmony.luni.tests.java.util; 19 20import java.lang.ref.ReferenceQueue; 21import java.lang.ref.WeakReference; 22import java.util.AbstractMap; 23import java.util.Arrays; 24import java.util.Collection; 25import java.util.Iterator; 26import java.util.List; 27import java.util.Map; 28import java.util.Set; 29import java.util.WeakHashMap; 30import tests.support.Support_MapTest2; 31 32public class WeakHashMapTest extends junit.framework.TestCase { 33 class MockMap extends AbstractMap { 34 public Set entrySet() { 35 return null; 36 } 37 public int size(){ 38 return 0; 39 } 40 } 41 42 Object[] keyArray = new Object[100]; 43 44 Object[] valueArray = new Object[100]; 45 46 WeakHashMap whm; 47 48 Object[] KEY_ARRAY; 49 50 Object[] VALUE_ARRAY; 51 52 /** 53 * @tests java.util.WeakHashMap#WeakHashMap() 54 */ 55 public void test_Constructor() { 56 // Test for method java.util.WeakHashMap() 57 new Support_MapTest2(new WeakHashMap()).runTest(); 58 59 whm = new WeakHashMap(); 60 for (int i = 0; i < 100; i++) 61 whm.put(keyArray[i], valueArray[i]); 62 for (int i = 0; i < 100; i++) 63 assertTrue("Incorrect value retrieved", 64 whm.get(keyArray[i]) == valueArray[i]); 65 66 } 67 68 /** 69 * @tests java.util.WeakHashMap#WeakHashMap(int) 70 */ 71 public void test_ConstructorI() { 72 // Test for method java.util.WeakHashMap(int) 73 whm = new WeakHashMap(50); 74 for (int i = 0; i < 100; i++) 75 whm.put(keyArray[i], valueArray[i]); 76 for (int i = 0; i < 100; i++) 77 assertTrue("Incorrect value retrieved", 78 whm.get(keyArray[i]) == valueArray[i]); 79 80 WeakHashMap empty = new WeakHashMap(0); 81 assertNull("Empty weakhashmap access", empty.get("nothing")); 82 empty.put("something", "here"); 83 assertTrue("cannot get element", empty.get("something") == "here"); 84 } 85 86 /** 87 * @tests java.util.WeakHashMap#WeakHashMap(int, float) 88 */ 89 public void test_ConstructorIF() { 90 // Test for method java.util.WeakHashMap(int, float) 91 whm = new WeakHashMap(50, 0.5f); 92 for (int i = 0; i < 100; i++) 93 whm.put(keyArray[i], valueArray[i]); 94 for (int i = 0; i < 100; i++) 95 assertTrue("Incorrect value retrieved", 96 whm.get(keyArray[i]) == valueArray[i]); 97 98 WeakHashMap empty = new WeakHashMap(0, 0.75f); 99 assertNull("Empty hashtable access", empty.get("nothing")); 100 empty.put("something", "here"); 101 assertTrue("cannot get element", empty.get("something") == "here"); 102 } 103 104 /** 105 * @tests java.util.WeakHashMap#WeakHashMap(java.util.Map) 106 */ 107 public void test_ConstructorLjava_util_Map() { 108 Map mockMap = new MockMap(); 109 WeakHashMap map = new WeakHashMap(mockMap); 110 assertEquals("Size should be 0", 0, map.size()); 111 } 112 113 /** 114 * @tests java.util.WeakHashMap#clear() 115 */ 116 public void test_clear() { 117 // Test for method boolean java.util.WeakHashMap.clear() 118 whm = new WeakHashMap(); 119 for (int i = 0; i < 100; i++) 120 whm.put(keyArray[i], valueArray[i]); 121 whm.clear(); 122 assertTrue("Cleared map should be empty", whm.isEmpty()); 123 for (int i = 0; i < 100; i++) 124 assertNull("Cleared map should only return null", whm 125 .get(keyArray[i])); 126 127 } 128 129 /** 130 * @tests java.util.WeakHashMap#containsKey(java.lang.Object) 131 */ 132 public void test_containsKeyLjava_lang_Object() { 133 // Test for method boolean java.util.WeakHashMap.containsKey() 134 whm = new WeakHashMap(); 135 for (int i = 0; i < 100; i++) 136 whm.put(keyArray[i], valueArray[i]); 137 for (int i = 0; i < 100; i++) 138 assertTrue("Should contain referenced key", whm 139 .containsKey(keyArray[i])); 140 keyArray[25] = null; 141 keyArray[50] = null; 142 } 143 144 /** 145 * @tests java.util.WeakHashMap#containsValue(java.lang.Object) 146 */ 147 public void test_containsValueLjava_lang_Object() { 148 // Test for method boolean java.util.WeakHashMap.containsValue() 149 whm = new WeakHashMap(); 150 for (int i = 0; i < 100; i++) 151 whm.put(keyArray[i], valueArray[i]); 152 for (int i = 0; i < 100; i++) 153 assertTrue("Should contain referenced value", whm 154 .containsValue(valueArray[i])); 155 keyArray[25] = null; 156 keyArray[50] = null; 157 } 158 159 /** 160 * @tests java.util.WeakHashMap#entrySet() 161 */ 162 public void test_entrySet() { 163 WeakHashMap<Object, Object> weakMap = new WeakHashMap<Object, Object>(); 164 KEY_ARRAY = new Object[100]; 165 VALUE_ARRAY = new Object[100]; 166 for (int i = 0; i < 100; i++) { 167 KEY_ARRAY[i] = new Integer(i); 168 VALUE_ARRAY[i] = new Long(i); 169 weakMap.put(KEY_ARRAY[i], VALUE_ARRAY[i]); 170 } 171 172 List<Object> keys = Arrays.asList(KEY_ARRAY); 173 List<Object> values = Arrays.asList(VALUE_ARRAY); 174 175 // Check the entry set has correct size & content 176 Set<Map.Entry<Object, Object>> entrySet = weakMap.entrySet(); 177 assertEquals("Assert 0: Incorrect number of entries returned", 100, 178 entrySet.size()); 179 Iterator<Map.Entry<Object, Object>> it = entrySet.iterator(); 180 while (it.hasNext()) { 181 Map.Entry<Object, Object> entry = it.next(); 182 assertTrue("Assert 1: Invalid map entry key returned", keys 183 .contains(entry.getKey())); 184 assertTrue("Assert 2: Invalid map entry value returned", values 185 .contains(entry.getValue())); 186 assertTrue("Assert 3: Entry not in entry set", entrySet 187 .contains(entry)); 188 } 189 190 // Dereference list of key/value objects 191 keys = values = null; 192 193 // Dereference a single key, then try to 194 // force a collection of the weak ref'd obj 195 KEY_ARRAY[50] = null; 196 enqueueWeakReferences(); 197 198 assertEquals("Assert 4: Incorrect number of entries after gc", 99, 199 entrySet.size()); 200 assertSame("Assert 5: Entries not identical", entrySet.iterator() 201 .next(), entrySet.iterator().next()); 202 203 // remove alternate entries using the iterator, and ensure the 204 // iteration count is consistent 205 int size = entrySet.size(); 206 it = entrySet.iterator(); 207 while (it.hasNext()) { 208 it.next(); 209 it.remove(); 210 size--; 211 if (it.hasNext()) { 212 it.next(); 213 } 214 215 } 216 assertEquals("Assert 6: entry set count mismatch", size, entrySet 217 .size()); 218 219 int entries = 0; 220 it = entrySet.iterator(); 221 while (it.hasNext()) { 222 it.next(); 223 entries++; 224 } 225 assertEquals("Assert 6: count mismatch", size, entries); 226 227 it = entrySet.iterator(); 228 while (it.hasNext()) { 229 it.next(); 230 it.remove(); 231 } 232 assertEquals("Assert 7: entry set not empty", 0, entrySet.size()); 233 assertTrue("Assert 8: iterator not empty", !entrySet.iterator() 234 .hasNext()); 235 } 236 237 /** 238 * @tests java.util.WeakHashMap#entrySet() 239 */ 240 public void test_entrySet_2() { 241 // Test for method java.util.Set java.util.WeakHashMap.entrySet() 242 whm = new WeakHashMap(); 243 for (int i = 0; i < 100; i++) 244 whm.put(keyArray[i], valueArray[i]); 245 List keys = Arrays.asList(keyArray); 246 List values = Arrays.asList(valueArray); 247 Set entrySet = whm.entrySet(); 248 assertTrue("Incorrect number of entries returned--wanted 100, got: " 249 + entrySet.size(), entrySet.size() == 100); 250 Iterator it = entrySet.iterator(); 251 while (it.hasNext()) { 252 Map.Entry entry = (Map.Entry) it.next(); 253 assertTrue("Invalid map entry returned--bad key", keys 254 .contains(entry.getKey())); 255 assertTrue("Invalid map entry returned--bad key", values 256 .contains(entry.getValue())); 257 } 258 keys = null; 259 values = null; 260 keyArray[50] = null; 261 262 enqueueWeakReferences(); 263 264 assertTrue( 265 "Incorrect number of entries returned after gc--wanted 99, got: " 266 + entrySet.size(), entrySet.size() == 99); 267 } 268 269 /** 270 * @tests java.util.WeakHashMap#get(java.lang.Object) 271 */ 272 public void test_getLjava_lang_Object() { 273 // Test for method java.lang.Object 274 // java.util.WeakHashMap.get(java.lang.Object) 275 assertTrue("Used to test", true); 276 } 277 278 /** 279 * @tests java.util.WeakHashMap#isEmpty() 280 */ 281 public void test_isEmpty() { 282 // Test for method boolean java.util.WeakHashMap.isEmpty() 283 whm = new WeakHashMap(); 284 assertTrue("New map should be empty", whm.isEmpty()); 285 Object myObject = new Object(); 286 whm.put(myObject, myObject); 287 assertTrue("Map should not be empty", !whm.isEmpty()); 288 whm.remove(myObject); 289 assertTrue("Map with elements removed should be empty", whm.isEmpty()); 290 } 291 292 /** 293 * @tests java.util.WeakHashMap#put(java.lang.Object, java.lang.Object) 294 */ 295 public void test_putLjava_lang_ObjectLjava_lang_Object() { 296 // Test for method java.lang.Object 297 // java.util.WeakHashMap.put(java.lang.Object, java.lang.Object) 298 WeakHashMap map = new WeakHashMap(); 299 map.put(null, "value"); // add null key 300 enqueueWeakReferences(); 301 map.remove("nothing"); // Cause objects in queue to be removed 302 assertEquals("null key was removed", 1, map.size()); 303 } 304 305 /** 306 * @tests java.util.WeakHashMap#putAll(java.util.Map) 307 */ 308 public void test_putAllLjava_util_Map() { 309 Map mockMap=new MockMap(); 310 WeakHashMap map = new WeakHashMap(); 311 map.putAll(mockMap); 312 assertEquals("Size should be 0", 0, map.size()); 313 } 314 315 /** 316 * @tests java.util.WeakHashMap#remove(java.lang.Object) 317 */ 318 public void test_removeLjava_lang_Object() { 319 // Test for method java.lang.Object 320 // java.util.WeakHashMap.remove(java.lang.Object) 321 whm = new WeakHashMap(); 322 for (int i = 0; i < 100; i++) 323 whm.put(keyArray[i], valueArray[i]); 324 325 assertTrue("Remove returned incorrect value", 326 whm.remove(keyArray[25]) == valueArray[25]); 327 assertNull("Remove returned incorrect value", 328 whm.remove(keyArray[25])); 329 assertEquals("Size should be 99 after remove", 99, whm.size()); 330 } 331 332 /** 333 * @tests java.util.WeakHashMap#size() 334 */ 335 public void test_size() { 336 // Test for method int java.util.WeakHashMap.size() 337 assertTrue("Used to test", true); 338 } 339 340 /** 341 * @tests java.util.WeakHashMap#keySet() 342 */ 343 public void test_keySet() { 344 // Test for method java.util.Set java.util.WeakHashMap.keySet() 345 whm = new WeakHashMap(); 346 for (int i = 0; i < 100; i++) 347 whm.put(keyArray[i], valueArray[i]); 348 349 List keys = Arrays.asList(keyArray); 350 List values = Arrays.asList(valueArray); 351 352 Set keySet = whm.keySet(); 353 assertEquals("Incorrect number of keys returned,", 100, keySet.size()); 354 Iterator it = keySet.iterator(); 355 while (it.hasNext()) { 356 Object key = it.next(); 357 assertTrue("Invalid map entry returned--bad key", keys 358 .contains(key)); 359 } 360 keys = null; 361 values = null; 362 keyArray[50] = null; 363 364 enqueueWeakReferences(); 365 366 assertEquals("Incorrect number of keys returned after gc,", 99, keySet 367 .size()); 368 } 369 370 /** 371 * Regression test for HARMONY-3883 372 * @tests java.util.WeakHashMap#keySet() 373 */ 374 public void test_keySet_hasNext() { 375 WeakHashMap map = new WeakHashMap(); 376 ConstantHashClass cl = new ConstantHashClass(2); 377 map.put(new ConstantHashClass(1), null); 378 map.put(cl, null); 379 map.put(new ConstantHashClass(3), null); 380 Iterator iter = map.keySet().iterator(); 381 iter.next(); 382 iter.next(); 383 enqueueWeakReferences(); 384 assertFalse("Wrong hasNext() value", iter.hasNext()); 385 } 386 387 static class ConstantHashClass { 388 private int id = 0; 389 390 public ConstantHashClass(int id) { 391 this.id = id; 392 } 393 394 public int hashCode() { 395 return 0; 396 } 397 398 public String toString() { 399 return "ConstantHashClass[id=" + id + "]"; 400 } 401 } 402 403 404 /** 405 * @tests java.util.WeakHashMap#values() 406 */ 407 public void test_values() { 408 // Test for method java.util.Set java.util.WeakHashMap.values() 409 whm = new WeakHashMap(); 410 for (int i = 0; i < 100; i++) 411 whm.put(keyArray[i], valueArray[i]); 412 413 List keys = Arrays.asList(keyArray); 414 List values = Arrays.asList(valueArray); 415 416 Collection valuesCollection = whm.values(); 417 assertEquals("Incorrect number of keys returned,", 100, 418 valuesCollection.size()); 419 Iterator it = valuesCollection.iterator(); 420 while (it.hasNext()) { 421 Object value = it.next(); 422 assertTrue("Invalid map entry returned--bad value", values 423 .contains(value)); 424 } 425 keys = null; 426 values = null; 427 keyArray[50] = null; 428 429 enqueueWeakReferences(); 430 431 assertEquals("Incorrect number of keys returned after gc,", 99, 432 valuesCollection.size()); 433 } 434 435 /** 436 * Induce the VM to enqueue weak references into the corresponding reference 437 * queues. This guarantees that all weak hash maps can observe their own 438 * references as both cleared and enqueued. 439 * 440 * <p>This method assumes that one value enqueued implies all others will be 441 * enqueued. This behavior isn't specified, and this method may return too 442 * early on some VMs. 443 */ 444 private void enqueueWeakReferences() { 445 ReferenceQueue<Object> queue = new ReferenceQueue<Object>(); 446 new WeakReference<Object>(new Object(), queue); 447 System.gc(); 448 try { 449 queue.remove(200); // '200' shouldn't be necessary, but works on more VMs 450 } catch (InterruptedException e) { 451 } 452 } 453 454 /** 455 * Sets up the fixture, for example, open a network connection. This method 456 * is called before a test is executed. 457 */ 458 protected void setUp() { 459 for (int i = 0; i < 100; i++) { 460 keyArray[i] = new Object(); 461 valueArray[i] = new Object(); 462 } 463 464 } 465 466 /** 467 * Tears down the fixture, for example, close a network connection. This 468 * method is called after a test is executed. 469 */ 470 protected void tearDown() { 471 } 472} 473