1 /* 2 * Copyright 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.collection; 18 19 import static org.hamcrest.CoreMatchers.is; 20 import static org.hamcrest.CoreMatchers.nullValue; 21 import static org.hamcrest.MatcherAssert.assertThat; 22 23 import androidx.arch.core.internal.SafeIterableMap; 24 25 import org.junit.Test; 26 import org.junit.runner.RunWith; 27 import org.junit.runners.JUnit4; 28 29 import java.util.ArrayList; 30 import java.util.Iterator; 31 import java.util.Map.Entry; 32 33 @RunWith(JUnit4.class) 34 public class SafeIterableMapTest { 35 36 @Test 37 public void testToString() { 38 SafeIterableMap<Integer, String> map = from(1, 2, 3, 4).to("a", "b", "c", "d"); 39 assertThat(map.toString(), is("[1=a, 2=b, 3=c, 4=d]")); 40 } 41 42 @Test 43 public void testEmptyToString() { 44 SafeIterableMap<Integer, Boolean> map = mapOf(); 45 assertThat(map.toString(), is("[]")); 46 } 47 48 @Test 49 public void testOneElementToString() { 50 SafeIterableMap<Integer, Boolean> map = mapOf(1); 51 assertThat(map.toString(), is("[1=true]")); 52 } 53 54 55 @Test 56 public void testEquality1() { 57 SafeIterableMap<Integer, Integer> map1 = from(1, 2, 3, 4).to(10, 20, 30, 40); 58 SafeIterableMap<Integer, Integer> map2 = from(1, 2, 3, 4).to(10, 20, 30, 40); 59 assertThat(map1.equals(map2), is(true)); 60 } 61 62 @Test 63 public void testEquality2() { 64 SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); 65 //noinspection ObjectEqualsNull 66 assertThat(map.equals(null), is(false)); 67 } 68 69 @Test 70 public void testEquality3() { 71 SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); 72 //noinspection EqualsBetweenInconvertibleTypes 73 assertThat(map.equals(new ArrayList<>()), is(false)); 74 } 75 76 @Test 77 public void testEquality4() { 78 SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); 79 assertThat(map.equals(new SafeIterableMap<Integer, Boolean>()), is(false)); 80 } 81 82 @Test 83 public void testEquality5() { 84 SafeIterableMap<Integer, Boolean> map1 = mapOf(1, 2, 3, 4); 85 SafeIterableMap<Integer, Boolean> map2 = mapOf(1); 86 assertThat(map1.equals(map2), is(false)); 87 } 88 89 @Test 90 public void testEquality6() { 91 SafeIterableMap<Integer, Boolean> map1 = mapOf(1, 2, 3, 4); 92 SafeIterableMap<Integer, Boolean> map2 = mapOf(1, 2, 3, 5); 93 assertThat(map1.equals(map2), is(false)); 94 } 95 96 @Test 97 public void testEquality7() { 98 SafeIterableMap<Integer, Integer> map1 = from(1, 2, 3, 4).to(1, 2, 3, 4); 99 SafeIterableMap<Integer, Integer> map2 = from(1, 2, 3, 4).to(1, 2, 3, 5); 100 assertThat(map1.equals(map2), is(false)); 101 } 102 103 104 @Test 105 public void testEquality8() { 106 SafeIterableMap<Integer, Boolean> map1 = mapOf(); 107 SafeIterableMap<Integer, Boolean> map2 = mapOf(); 108 assertThat(map1.equals(map2), is(true)); 109 } 110 111 @Test 112 public void testEqualityRespectsOrder() { 113 SafeIterableMap<Integer, Boolean> map1 = mapOf(1, 2, 3, 4); 114 SafeIterableMap<Integer, Boolean> map2 = mapOf(1, 3, 2, 4); 115 assertThat(map1.equals(map2), is(false)); 116 } 117 118 @Test 119 public void testPut() { 120 SafeIterableMap<Integer, Integer> map = from(1, 2, 3, 4).to(10, 20, 30, 40); 121 assertThat(map.putIfAbsent(5, 10), is((Integer) null)); 122 assertThat(map, is(from(1, 2, 3, 4, 5).to(10, 20, 30, 40, 10))); 123 } 124 125 @Test 126 public void testAddExisted() { 127 SafeIterableMap<Integer, Integer> map = from(1, 2, 3, 4).to(10, 20, 261, 40); 128 assertThat(map.putIfAbsent(3, 239), is(261)); 129 assertThat(map, is(from(1, 2, 3, 4).to(10, 20, 261, 40))); 130 } 131 132 @Test 133 public void testRemoveLast() { 134 SafeIterableMap<Integer, Integer> map = from(1, 2, 3, 4).to(10, 20, 30, 40); 135 assertThat(map.remove(4), is(40)); 136 assertThat(map, is(from(1, 2, 3).to(10, 20, 30))); 137 } 138 139 @Test 140 public void testRemoveFirst() { 141 SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); 142 assertThat(map.remove(1), is(true)); 143 assertThat(map, is(mapOf(2, 3, 4))); 144 } 145 146 @Test 147 public void testRemoveMiddle() { 148 SafeIterableMap<Integer, Integer> map = from(1, 2, 3, 4).to(10, 20, 30, 40); 149 assertThat(map.remove(2), is(20)); 150 assertThat(map.remove(3), is(30)); 151 assertThat(map, is(from(1, 4).to(10, 40))); 152 } 153 154 @Test 155 public void testRemoveNotExisted() { 156 SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); 157 assertThat(map.remove(5), is((Boolean) null)); 158 assertThat(map, is(mapOf(1, 2, 3, 4))); 159 } 160 161 @Test 162 public void testRemoveSole() { 163 SafeIterableMap<Integer, Integer> map = from(1).to(261); 164 assertThat(map.remove(1), is(261)); 165 assertThat(map, is(new SafeIterableMap<Integer, Integer>())); 166 } 167 168 @Test 169 public void testRemoveDuringIteration1() { 170 SafeIterableMap<Integer, Integer> map = from(1, 2, 3, 4).to(10, 20, 30, 40); 171 int index = 0; 172 int[] expected = new int[]{1, 4}; 173 for (Entry<Integer, Integer> i : map) { 174 assertThat(i.getKey(), is(expected[index++])); 175 if (index == 1) { 176 assertThat(map.remove(2), is(20)); 177 assertThat(map.remove(3), is(30)); 178 } 179 } 180 } 181 182 @Test 183 public void testRemoveDuringIteration2() { 184 SafeIterableMap<Integer, Integer> map = from(1, 2).to(10, 20); 185 Iterator<Entry<Integer, Integer>> iter = map.iterator(); 186 assertThat(map.remove(2), is(20)); 187 assertThat(map.remove(1), is(10)); 188 assertThat(iter.hasNext(), is(false)); 189 } 190 191 @Test 192 public void testRemoveDuringIteration3() { 193 SafeIterableMap<Integer, Integer> map = from(1, 2, 3, 4).to(10, 20, 30, 40); 194 int index = 0; 195 Iterator<Entry<Integer, Integer>> iter = map.iterator(); 196 assertThat(map.remove(1), is(10)); 197 assertThat(map.remove(2), is(20)); 198 int[] expected = new int[]{3, 4}; 199 while (iter.hasNext()) { 200 assertThat(iter.next().getKey(), is(expected[index++])); 201 } 202 } 203 204 @Test 205 public void testRemoveDuringIteration4() { 206 SafeIterableMap<Integer, Boolean> map = mapOf(1, 2); 207 int[] expected = new int[]{1, 2}; 208 int index = 0; 209 for (Entry<Integer, Boolean> entry : map) { 210 assertThat(entry.getKey(), is(expected[index++])); 211 if (index == 1) { 212 map.remove(1); 213 } 214 } 215 assertThat(index, is(2)); 216 } 217 218 @Test 219 public void testAdditionDuringIteration() { 220 SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); 221 int[] expected = new int[]{1, 2, 3, 4}; 222 int index = 0; 223 for (Entry<Integer, Boolean> entry : map) { 224 assertThat(entry.getKey(), is(expected[index++])); 225 if (index == 1) { 226 map.putIfAbsent(5, true); 227 } 228 } 229 } 230 231 @Test 232 public void testReAdditionDuringIteration() { 233 SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); 234 int[] expected = new int[]{1, 2, 4}; 235 int index = 0; 236 for (Entry<Integer, Boolean> entry : map) { 237 assertThat(entry.getKey(), is(expected[index++])); 238 if (index == 1) { 239 map.remove(3); 240 map.putIfAbsent(3, true); 241 } 242 } 243 } 244 245 @Test 246 public void testSize() { 247 SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); 248 assertThat(map.size(), is(4)); 249 map.putIfAbsent(5, true); 250 map.putIfAbsent(6, true); 251 assertThat(map.size(), is(6)); 252 map.remove(5); 253 map.remove(5); 254 assertThat(map.size(), is(5)); 255 map.remove(1); 256 map.remove(2); 257 map.remove(4); 258 map.remove(3); 259 map.remove(6); 260 assertThat(map.size(), is(0)); 261 map.putIfAbsent(4, true); 262 assertThat(map.size(), is(1)); 263 assertThat(mapOf().size(), is(0)); 264 } 265 266 @Test 267 public void testIteratorWithAdditions1() { 268 SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); 269 int[] expected = new int[]{1, 2, 3, 5}; 270 int index = 0; 271 Iterator<Entry<Integer, Boolean>> iterator = map.iteratorWithAdditions(); 272 while (iterator.hasNext()) { 273 Entry<Integer, Boolean> entry = iterator.next(); 274 assertThat(entry.getKey(), is(expected[index++])); 275 if (index == 3) { 276 map.remove(4); 277 map.putIfAbsent(5, true); 278 } 279 } 280 } 281 282 @Test 283 public void testIteratorWithAdditions2() { 284 SafeIterableMap<Integer, Boolean> map = mapOf(1); 285 int[] expected = new int[]{1, 2, 3}; 286 int index = 0; 287 Iterator<Entry<Integer, Boolean>> iterator = map.iteratorWithAdditions(); 288 while (iterator.hasNext()) { 289 Entry<Integer, Boolean> entry = iterator.next(); 290 assertThat(entry.getKey(), is(expected[index++])); 291 if (index == 1) { 292 map.putIfAbsent(2, true); 293 map.putIfAbsent(3, true); 294 } 295 } 296 assertThat(index, is(3)); 297 } 298 299 300 @Test 301 public void testIteratorWithAdditions3() { 302 SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3); 303 int[] expected = new int[]{1}; 304 int index = 0; 305 Iterator<Entry<Integer, Boolean>> iterator = map.iteratorWithAdditions(); 306 while (iterator.hasNext()) { 307 Entry<Integer, Boolean> entry = iterator.next(); 308 assertThat(entry.getKey(), is(expected[index++])); 309 map.remove(2); 310 map.remove(3); 311 } 312 assertThat(index, is(1)); 313 } 314 315 @Test 316 public void testIteratorWithAdditions4() { 317 SafeIterableMap<Integer, Boolean> map = mapOf(); 318 int[] expected = new int[]{1, 2, 3}; 319 int index = 0; 320 Iterator<Entry<Integer, Boolean>> iterator = map.iteratorWithAdditions(); 321 map.putIfAbsent(1, true); 322 while (iterator.hasNext()) { 323 Entry<Integer, Boolean> entry = iterator.next(); 324 assertThat(entry.getKey(), is(expected[index++])); 325 if (index == 1) { 326 map.putIfAbsent(2, false); 327 } 328 if (index == 2) { 329 map.putIfAbsent(3, false); 330 } 331 } 332 assertThat(index, is(3)); 333 } 334 335 @Test 336 public void testIteratorWithAddition5() { 337 SafeIterableMap<Integer, Boolean> map = mapOf(1, 2); 338 int[] expected = new int[]{1, 2}; 339 int index = 0; 340 Iterator<Entry<Integer, Boolean>> iterator = map.iteratorWithAdditions(); 341 while (iterator.hasNext()) { 342 Entry<Integer, Boolean> entry = iterator.next(); 343 assertThat(entry.getKey(), is(expected[index++])); 344 if (index == 1) { 345 map.remove(1); 346 } 347 } 348 assertThat(index, is(2)); 349 } 350 351 @Test 352 public void testDescendingIteration() { 353 SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); 354 int[] expected = new int[]{4, 3, 2, 1}; 355 int index = 0; 356 for (Iterator<Entry<Integer, Boolean>> iter = map.descendingIterator(); iter.hasNext(); ) { 357 assertThat(iter.next().getKey(), is(expected[index++])); 358 } 359 assertThat(index, is(4)); 360 } 361 362 @Test 363 public void testDescendingIterationRemove1() { 364 SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); 365 int[] expected = new int[]{4, 3, 2}; 366 int index = 0; 367 for (Iterator<Entry<Integer, Boolean>> iter = map.descendingIterator(); iter.hasNext(); ) { 368 if (index == 1) { 369 map.remove(1); 370 } 371 assertThat(iter.next().getKey(), is(expected[index++])); 372 } 373 assertThat(index, is(3)); 374 assertThat(map.size(), is(3)); 375 } 376 377 @Test 378 public void testDescendingIterationRemove2() { 379 SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); 380 int[] expected = new int[]{3, 2, 1}; 381 int index = 0; 382 for (Iterator<Entry<Integer, Boolean>> iter = map.descendingIterator(); iter.hasNext(); ) { 383 if (index == 0) { 384 map.remove(4); 385 } 386 assertThat(iter.next().getKey(), is(expected[index++])); 387 } 388 assertThat(index, is(3)); 389 assertThat(map.size(), is(3)); 390 } 391 392 @Test 393 public void testDescendingIterationRemove3() { 394 SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); 395 int[] expected = new int[]{4, 1}; 396 int index = 0; 397 for (Iterator<Entry<Integer, Boolean>> iter = map.descendingIterator(); iter.hasNext(); ) { 398 if (index == 1) { 399 map.remove(3); 400 map.remove(2); 401 } 402 assertThat(iter.next().getKey(), is(expected[index++])); 403 } 404 assertThat(index, is(2)); 405 assertThat(map.size(), is(2)); 406 } 407 408 @Test 409 public void testDescendingIterationAddition() { 410 SafeIterableMap<Integer, Boolean> map = mapOf(1, 2, 3, 4); 411 int[] expected = new int[]{4, 3, 2, 1}; 412 int index = 0; 413 for (Iterator<Entry<Integer, Boolean>> iter = map.descendingIterator(); iter.hasNext(); ) { 414 if (index == 0) { 415 map.putIfAbsent(5, false); 416 } 417 assertThat(iter.next().getKey(), is(expected[index++])); 418 } 419 assertThat(index, is(4)); 420 assertThat(map.size(), is(5)); 421 } 422 423 @Test 424 public void testDescendingIteratorEmpty() { 425 SafeIterableMap<Integer, Boolean> map = mapOf(); 426 Iterator<Entry<Integer, Boolean>> iterator = map.descendingIterator(); 427 assertThat(iterator.hasNext(), is(false)); 428 } 429 430 @Test 431 public void testIteratorEmpty() { 432 SafeIterableMap<Integer, Boolean> map = mapOf(); 433 Iterator<Entry<Integer, Boolean>> iterator = map.iterator(); 434 assertThat(iterator.hasNext(), is(false)); 435 } 436 437 @Test 438 public void testIteratorWithAdditionEmpty() { 439 SafeIterableMap<Integer, Boolean> map = mapOf(); 440 Iterator<Entry<Integer, Boolean>> iterator = map.iteratorWithAdditions(); 441 assertThat(iterator.hasNext(), is(false)); 442 } 443 444 @Test 445 public void testEldest() { 446 SafeIterableMap<Integer, Boolean> map = mapOf(); 447 assertThat(map.eldest(), nullValue()); 448 map.putIfAbsent(1, false); 449 assertThat(map.eldest().getKey(), is(1)); 450 map.putIfAbsent(2, false); 451 assertThat(map.eldest().getKey(), is(1)); 452 map.remove(1); 453 assertThat(map.eldest().getKey(), is(2)); 454 map.remove(2); 455 assertThat(map.eldest(), nullValue()); 456 } 457 458 @Test 459 public void testNewest() { 460 SafeIterableMap<Integer, Boolean> map = mapOf(); 461 assertThat(map.newest(), nullValue()); 462 map.putIfAbsent(1, false); 463 assertThat(map.newest().getKey(), is(1)); 464 map.putIfAbsent(2, false); 465 assertThat(map.newest().getKey(), is(2)); 466 map.remove(2); 467 assertThat(map.eldest().getKey(), is(1)); 468 map.remove(1); 469 assertThat(map.newest(), nullValue()); 470 } 471 472 473 // for most operations we don't care about values, so we create map from key to true 474 @SafeVarargs 475 private static <K> SafeIterableMap<K, Boolean> mapOf(K... keys) { 476 SafeIterableMap<K, Boolean> map = new SafeIterableMap<>(); 477 for (K key : keys) { 478 map.putIfAbsent(key, true); 479 } 480 return map; 481 } 482 483 @SafeVarargs 484 private static <K> MapBuilder<K> from(K... keys) { 485 return new MapBuilder<>(keys); 486 } 487 488 private static class MapBuilder<K> { 489 final K[] mKeys; 490 491 MapBuilder(K[] keys) { 492 this.mKeys = keys; 493 } 494 495 @SafeVarargs 496 public final <V> SafeIterableMap<K, V> to(V... values) { 497 assertThat("Failed to build Map", mKeys.length, is(values.length)); 498 SafeIterableMap<K, V> map = new SafeIterableMap<>(); 499 for (int i = 0; i < mKeys.length; i++) { 500 map.putIfAbsent(mKeys[i], values[i]); 501 } 502 return map; 503 } 504 } 505 } 506 507 508