1 /* 2 * Copyright (c) 2012, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package test.com.sun.javafx.collections; 27 28 import com.sun.javafx.collections.ListListenerHelper; 29 import com.sun.javafx.collections.NonIterableChange; 30 import javafx.beans.InvalidationListener; 31 import test.javafx.beans.InvalidationListenerMock; 32 import javafx.beans.Observable; 33 import javafx.collections.FXCollections; 34 import javafx.collections.ListChangeListener; 35 import test.javafx.collections.MockListObserver; 36 import javafx.collections.ObservableList; 37 38 import org.junit.Before; 39 import org.junit.Test; 40 41 import java.util.BitSet; 42 import java.util.concurrent.atomic.AtomicBoolean; 43 import java.util.concurrent.atomic.AtomicInteger; 44 45 import static org.junit.Assert.assertEquals; 46 import static org.junit.Assert.assertFalse; 47 import static org.junit.Assert.assertTrue; 48 49 public class ListListenerHelperTest { 50 51 private InvalidationListenerMock[] invalidationListenerMock; 52 53 private MockListObserver<Object>[] changeListenerMock; 54 55 private ListListenerHelper<Object> helper; 56 57 private ObservableList<Object> list; 58 private ListChangeListener.Change<Object> change; 59 60 @Before 61 public void setUp() { 62 invalidationListenerMock = new InvalidationListenerMock[] { 63 new InvalidationListenerMock(), 64 new InvalidationListenerMock(), 65 new InvalidationListenerMock(), 66 new InvalidationListenerMock() 67 }; 68 changeListenerMock = new MockListObserver[] { 69 new MockListObserver<Object>(), 70 new MockListObserver<Object>(), 71 new MockListObserver<Object>(), 72 new MockListObserver<Object>() 73 }; 74 helper = null; 75 list = FXCollections.emptyObservableList(); 76 change = new NonIterableChange.SimpleRemovedChange<Object>(0, 1, new Object(), list); 77 } 78 79 private void resetAllListeners() { 80 for (final InvalidationListenerMock listener : invalidationListenerMock) { 81 listener.reset(); 82 } 83 for (final MockListObserver<Object> listener : changeListenerMock) { 84 listener.clear(); 85 } 86 } 87 88 @Test(expected = NullPointerException.class) 89 public void testAddInvalidationListener_Null() { 90 ListListenerHelper.addListener(helper, (InvalidationListener)null); 91 } 92 93 @Test(expected = NullPointerException.class) 94 public void testRemoveInvalidationListener_Null() { 95 ListListenerHelper.removeListener(helper, (InvalidationListener) null); 96 } 97 98 @Test(expected = NullPointerException.class) 99 public void testRemoveListChangeListener_Null() { 100 ListListenerHelper.removeListener(helper, (ListChangeListener<Object>) null); 101 } 102 103 @Test(expected = NullPointerException.class) 104 public void testAddListChangeListener_Null() { 105 ListListenerHelper.addListener(helper, (ListChangeListener<Object>) null); 106 } 107 108 @Test 109 public void testEmpty() { 110 assertFalse(ListListenerHelper.hasListeners(helper)); 111 112 // these should be no-ops 113 ListListenerHelper.fireValueChangedEvent(helper, change); 114 ListListenerHelper.removeListener(helper, invalidationListenerMock[0]); 115 ListListenerHelper.removeListener(helper, changeListenerMock[0]); 116 } 117 118 @Test 119 public void testInvalidation_Simple() { 120 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[0]); 121 ListListenerHelper.fireValueChangedEvent(helper, change); 122 invalidationListenerMock[0].check(list, 1); 123 124 helper = ListListenerHelper.removeListener(helper, invalidationListenerMock[1]); 125 ListListenerHelper.fireValueChangedEvent(helper, change); 126 invalidationListenerMock[0].check(list, 1); 127 invalidationListenerMock[1].check(null, 0); 128 129 helper = ListListenerHelper.removeListener(helper, changeListenerMock[0]); 130 ListListenerHelper.fireValueChangedEvent(helper, change); 131 invalidationListenerMock[0].check(list, 1); 132 changeListenerMock[0].check0(); 133 134 helper = ListListenerHelper.removeListener(helper, invalidationListenerMock[0]); 135 ListListenerHelper.fireValueChangedEvent(helper, change); 136 invalidationListenerMock[0].check(null, 0); 137 } 138 139 @Test 140 public void testInvalidation_AddInvalidation() { 141 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[0]); 142 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[1]); 143 ListListenerHelper.fireValueChangedEvent(helper, change); 144 invalidationListenerMock[0].check(list, 1); 145 invalidationListenerMock[1].check(list, 1); 146 } 147 148 @Test 149 public void testInvalidation_AddChange() { 150 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[0]); 151 helper = ListListenerHelper.addListener(helper, changeListenerMock[0]); 152 ListListenerHelper.fireValueChangedEvent(helper, change); 153 invalidationListenerMock[0].check(list, 1); 154 changeListenerMock[0].check1(); 155 } 156 157 @Test 158 public void testInvalidation_ChangeInPulse() { 159 final InvalidationListener listener = observable -> { 160 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[0]); 161 }; 162 helper = ListListenerHelper.addListener(helper, listener); 163 ListListenerHelper.fireValueChangedEvent(helper, change); 164 helper = ListListenerHelper.removeListener(helper, listener); 165 invalidationListenerMock[0].reset(); 166 ListListenerHelper.fireValueChangedEvent(helper, change); 167 invalidationListenerMock[0].check(list, 1); 168 } 169 170 @Test 171 public void testChange_Simple() { 172 helper = ListListenerHelper.addListener(helper, changeListenerMock[0]); 173 ListListenerHelper.fireValueChangedEvent(helper, change); 174 changeListenerMock[0].check1(); 175 changeListenerMock[0].clear(); 176 177 helper = ListListenerHelper.removeListener(helper, changeListenerMock[1]); 178 ListListenerHelper.fireValueChangedEvent(helper, change); 179 changeListenerMock[0].check1(); 180 changeListenerMock[1].check0(); 181 changeListenerMock[0].clear(); 182 183 helper = ListListenerHelper.removeListener(helper, invalidationListenerMock[0]); 184 ListListenerHelper.fireValueChangedEvent(helper, change); 185 changeListenerMock[0].check1(); 186 invalidationListenerMock[0].check(null, 0); 187 changeListenerMock[0].clear(); 188 189 helper = ListListenerHelper.removeListener(helper, changeListenerMock[0]); 190 ListListenerHelper.fireValueChangedEvent(helper, change); 191 changeListenerMock[0].check0(); 192 changeListenerMock[0].clear(); 193 } 194 195 @Test 196 public void testChange_AddInvalidation() { 197 helper = ListListenerHelper.addListener(helper, changeListenerMock[0]); 198 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[0]); 199 ListListenerHelper.fireValueChangedEvent(helper, change); 200 changeListenerMock[0].check1(); 201 invalidationListenerMock[0].check(list, 1); 202 } 203 204 @Test 205 public void testChange_AddChange() { 206 helper = ListListenerHelper.addListener(helper, changeListenerMock[0]); 207 helper = ListListenerHelper.addListener(helper, changeListenerMock[1]); 208 ListListenerHelper.fireValueChangedEvent(helper, change); 209 changeListenerMock[0].check1(); 210 changeListenerMock[1].check1(); 211 } 212 213 @Test 214 public void testChange_ChangeInPulse() { 215 final ListChangeListener<Object> listener = c -> { 216 helper = ListListenerHelper.addListener(helper, changeListenerMock[0]); 217 }; 218 helper = ListListenerHelper.addListener(helper, listener); 219 ListListenerHelper.fireValueChangedEvent(helper, change); 220 helper = ListListenerHelper.removeListener(helper, listener); 221 changeListenerMock[0].clear(); 222 ListListenerHelper.fireValueChangedEvent(helper, change); 223 changeListenerMock[0].check1(); 224 } 225 226 @Test 227 public void testGeneric_AddInvalidation() { 228 helper = ListListenerHelper.addListener(helper, changeListenerMock[0]); 229 helper = ListListenerHelper.addListener(helper, changeListenerMock[1]); 230 231 // first invalidation listener creates the array 232 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[0]); 233 ListListenerHelper.fireValueChangedEvent(helper, change); 234 invalidationListenerMock[0].check(list, 1); 235 236 // second and third invalidation listener enlarge the array 237 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[1]); 238 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[2]); 239 ListListenerHelper.fireValueChangedEvent(helper, change); 240 invalidationListenerMock[0].check(list, 1); 241 invalidationListenerMock[1].check(list, 1); 242 invalidationListenerMock[2].check(list, 1); 243 244 // fourth invalidation listener fits into the array 245 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[3]); 246 ListListenerHelper.fireValueChangedEvent(helper, change); 247 invalidationListenerMock[0].check(list, 1); 248 invalidationListenerMock[1].check(list, 1); 249 invalidationListenerMock[2].check(list, 1); 250 invalidationListenerMock[3].check(list, 1); 251 } 252 253 @Test 254 public void testGeneric_AddInvalidationInPulse() { 255 final ListChangeListener<Object> addListener = new ListChangeListener<Object>() { 256 int counter; 257 @Override 258 public void onChanged(Change<? extends Object> c) { 259 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[counter++]); 260 } 261 }; 262 helper = ListListenerHelper.addListener(helper, changeListenerMock[0]); 263 264 helper = ListListenerHelper.addListener(helper, addListener); 265 ListListenerHelper.fireValueChangedEvent(helper, change); 266 helper = ListListenerHelper.removeListener(helper, addListener); 267 resetAllListeners(); 268 ListListenerHelper.fireValueChangedEvent(helper, change); 269 invalidationListenerMock[0].check(list, 1); 270 invalidationListenerMock[1].check(null, 0); 271 invalidationListenerMock[2].check(null, 0); 272 invalidationListenerMock[3].check(null, 0); 273 274 helper = ListListenerHelper.addListener(helper, addListener); 275 ListListenerHelper.fireValueChangedEvent(helper, change); 276 helper = ListListenerHelper.removeListener(helper, addListener); 277 resetAllListeners(); 278 ListListenerHelper.fireValueChangedEvent(helper, change); 279 invalidationListenerMock[0].check(list, 1); 280 invalidationListenerMock[1].check(list, 1); 281 invalidationListenerMock[2].check(null, 0); 282 invalidationListenerMock[3].check(null, 0); 283 284 helper = ListListenerHelper.addListener(helper, addListener); 285 ListListenerHelper.fireValueChangedEvent(helper, change); 286 helper = ListListenerHelper.removeListener(helper, addListener); 287 resetAllListeners(); 288 ListListenerHelper.fireValueChangedEvent(helper, change); 289 invalidationListenerMock[0].check(list, 1); 290 invalidationListenerMock[1].check(list, 1); 291 invalidationListenerMock[2].check(list, 1); 292 invalidationListenerMock[3].check(null, 0); 293 294 helper = ListListenerHelper.addListener(helper, addListener); 295 ListListenerHelper.fireValueChangedEvent(helper, change); 296 helper = ListListenerHelper.removeListener(helper, addListener); 297 resetAllListeners(); 298 ListListenerHelper.fireValueChangedEvent(helper, change); 299 invalidationListenerMock[0].check(list, 1); 300 invalidationListenerMock[1].check(list, 1); 301 invalidationListenerMock[2].check(list, 1); 302 invalidationListenerMock[3].check(list, 1); 303 } 304 305 @Test 306 public void testGeneric_RemoveInvalidation() { 307 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[0]); 308 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[1]); 309 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[2]); 310 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[3]); 311 312 // remove first element 313 helper = ListListenerHelper.removeListener(helper, invalidationListenerMock[0]); 314 ListListenerHelper.fireValueChangedEvent(helper, change); 315 invalidationListenerMock[0].check(null, 0); 316 invalidationListenerMock[1].check(list, 1); 317 invalidationListenerMock[2].check(list, 1); 318 invalidationListenerMock[3].check(list, 1); 319 320 // remove middle element 321 helper = ListListenerHelper.removeListener(helper, invalidationListenerMock[2]); 322 ListListenerHelper.fireValueChangedEvent(helper, change); 323 invalidationListenerMock[0].check(null, 0); 324 invalidationListenerMock[1].check(list, 1); 325 invalidationListenerMock[2].check(null, 0); 326 invalidationListenerMock[3].check(list, 1); 327 328 // remove last element 329 helper = ListListenerHelper.removeListener(helper, invalidationListenerMock[3]); 330 ListListenerHelper.fireValueChangedEvent(helper, change); 331 invalidationListenerMock[0].check(null, 0); 332 invalidationListenerMock[1].check(list, 1); 333 invalidationListenerMock[2].check(null, 0); 334 invalidationListenerMock[3].check(null, 0); 335 336 // remove last invalidation with single change 337 helper = ListListenerHelper.addListener(helper, changeListenerMock[0]); 338 helper = ListListenerHelper.removeListener(helper, invalidationListenerMock[1]); 339 ListListenerHelper.fireValueChangedEvent(helper, change); 340 invalidationListenerMock[1].check(null, 0); 341 changeListenerMock[0].check1(); 342 changeListenerMock[0].clear(); 343 344 // remove invalidation if array is empty 345 helper = ListListenerHelper.addListener(helper, changeListenerMock[1]); 346 helper = ListListenerHelper.removeListener(helper, invalidationListenerMock[0]); 347 ListListenerHelper.fireValueChangedEvent(helper, change); 348 invalidationListenerMock[0].check(null, 0); 349 changeListenerMock[0].check1(); 350 changeListenerMock[1].check1(); 351 changeListenerMock[0].clear(); 352 changeListenerMock[1].clear(); 353 354 // remove last invalidation with two change 355 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[0]); 356 helper = ListListenerHelper.removeListener(helper, invalidationListenerMock[0]); 357 ListListenerHelper.fireValueChangedEvent(helper, change); 358 invalidationListenerMock[0].check(null, 0); 359 changeListenerMock[0].check1(); 360 changeListenerMock[1].check1(); 361 } 362 363 364 @Test 365 public void testGeneric_RemoveInvalidationInPulse() { 366 final ListChangeListener<Object> removeListener = new ListChangeListener<Object>() { 367 int counter; 368 @Override 369 public void onChanged(Change<? extends Object> c) { 370 helper = ListListenerHelper.removeListener(helper, invalidationListenerMock[counter++]); 371 } 372 }; 373 helper = ListListenerHelper.addListener(helper, changeListenerMock[0]); 374 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[0]); 375 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[3]); 376 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[1]); 377 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[2]); 378 379 helper = ListListenerHelper.addListener(helper, removeListener); 380 ListListenerHelper.fireValueChangedEvent(helper, change); 381 helper = ListListenerHelper.removeListener(helper, removeListener); 382 resetAllListeners(); 383 ListListenerHelper.fireValueChangedEvent(helper, change); 384 invalidationListenerMock[0].check(null, 0); 385 invalidationListenerMock[3].check(list, 1); 386 invalidationListenerMock[1].check(list, 1); 387 invalidationListenerMock[2].check(list, 1); 388 389 helper = ListListenerHelper.addListener(helper, removeListener); 390 ListListenerHelper.fireValueChangedEvent(helper, change); 391 helper = ListListenerHelper.removeListener(helper, removeListener); 392 resetAllListeners(); 393 ListListenerHelper.fireValueChangedEvent(helper, change); 394 invalidationListenerMock[0].check(null, 0); 395 invalidationListenerMock[3].check(list, 1); 396 invalidationListenerMock[1].check(null, 0); 397 invalidationListenerMock[2].check(list, 1); 398 399 helper = ListListenerHelper.addListener(helper, removeListener); 400 ListListenerHelper.fireValueChangedEvent(helper, change); 401 helper = ListListenerHelper.removeListener(helper, removeListener); 402 resetAllListeners(); 403 ListListenerHelper.fireValueChangedEvent(helper, change); 404 invalidationListenerMock[0].check(null, 0); 405 invalidationListenerMock[3].check(list, 1); 406 invalidationListenerMock[1].check(null, 0); 407 invalidationListenerMock[2].check(null, 0); 408 409 helper = ListListenerHelper.addListener(helper, removeListener); 410 ListListenerHelper.fireValueChangedEvent(helper, change); 411 helper = ListListenerHelper.removeListener(helper, removeListener); 412 resetAllListeners(); 413 ListListenerHelper.fireValueChangedEvent(helper, change); 414 invalidationListenerMock[0].check(null, 0); 415 invalidationListenerMock[3].check(null, 0); 416 invalidationListenerMock[1].check(null, 0); 417 invalidationListenerMock[2].check(null, 0); 418 } 419 420 @Test 421 public void testGeneric_AddChange() { 422 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[0]); 423 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[0]); 424 425 // first change listener creates the array 426 helper = ListListenerHelper.addListener(helper, changeListenerMock[0]); 427 ListListenerHelper.fireValueChangedEvent(helper, change); 428 changeListenerMock[0].check1(); 429 changeListenerMock[0].clear(); 430 431 // second and third change listener enlarge the array 432 helper = ListListenerHelper.addListener(helper, changeListenerMock[1]); 433 helper = ListListenerHelper.addListener(helper, changeListenerMock[2]); 434 ListListenerHelper.fireValueChangedEvent(helper, change); 435 changeListenerMock[0].check1(); 436 changeListenerMock[1].check1(); 437 changeListenerMock[2].check1(); 438 resetAllListeners(); 439 440 // fourth change listener fits into the array 441 helper = ListListenerHelper.addListener(helper, changeListenerMock[3]); 442 ListListenerHelper.fireValueChangedEvent(helper, change); 443 changeListenerMock[0].check1(); 444 changeListenerMock[1].check1(); 445 changeListenerMock[2].check1(); 446 changeListenerMock[3].check1(); 447 } 448 449 @Test 450 public void testGeneric_AddChangeInPulse() { 451 final InvalidationListener addListener = new InvalidationListener() { 452 int counter; 453 @Override 454 public void invalidated(Observable observable) { 455 helper = ListListenerHelper.addListener(helper, changeListenerMock[counter++]); 456 457 } 458 }; 459 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[0]); 460 461 helper = ListListenerHelper.addListener(helper, addListener); 462 ListListenerHelper.fireValueChangedEvent(helper, change); 463 helper = ListListenerHelper.removeListener(helper, addListener); 464 resetAllListeners(); 465 ListListenerHelper.fireValueChangedEvent(helper, change); 466 changeListenerMock[0].check1(); 467 changeListenerMock[1].check0(); 468 changeListenerMock[2].check0(); 469 changeListenerMock[3].check0(); 470 471 helper = ListListenerHelper.addListener(helper, addListener); 472 ListListenerHelper.fireValueChangedEvent(helper, change); 473 helper = ListListenerHelper.removeListener(helper, addListener); 474 resetAllListeners(); 475 ListListenerHelper.fireValueChangedEvent(helper, change); 476 changeListenerMock[0].check1(); 477 changeListenerMock[1].check1(); 478 changeListenerMock[2].check0(); 479 changeListenerMock[3].check0(); 480 481 helper = ListListenerHelper.addListener(helper, addListener); 482 ListListenerHelper.fireValueChangedEvent(helper, change); 483 helper = ListListenerHelper.removeListener(helper, addListener); 484 resetAllListeners(); 485 ListListenerHelper.fireValueChangedEvent(helper, change); 486 changeListenerMock[0].check1(); 487 changeListenerMock[1].check1(); 488 changeListenerMock[2].check1(); 489 changeListenerMock[3].check0(); 490 491 helper = ListListenerHelper.addListener(helper, addListener); 492 ListListenerHelper.fireValueChangedEvent(helper, change); 493 helper = ListListenerHelper.removeListener(helper, addListener); 494 resetAllListeners(); 495 ListListenerHelper.fireValueChangedEvent(helper, change); 496 changeListenerMock[0].check1(); 497 changeListenerMock[1].check1(); 498 changeListenerMock[2].check1(); 499 changeListenerMock[3].check1(); 500 } 501 502 @Test 503 public void testGeneric_RemoveChange() { 504 helper = ListListenerHelper.addListener(helper, changeListenerMock[0]); 505 helper = ListListenerHelper.addListener(helper, changeListenerMock[1]); 506 helper = ListListenerHelper.addListener(helper, changeListenerMock[2]); 507 helper = ListListenerHelper.addListener(helper, changeListenerMock[3]); 508 509 // remove first element 510 helper = ListListenerHelper.removeListener(helper, changeListenerMock[0]); 511 ListListenerHelper.fireValueChangedEvent(helper, change); 512 changeListenerMock[0].check0(); 513 changeListenerMock[1].check1(); 514 changeListenerMock[2].check1(); 515 changeListenerMock[3].check1(); 516 resetAllListeners(); 517 518 // remove middle element 519 helper = ListListenerHelper.removeListener(helper, changeListenerMock[2]); 520 ListListenerHelper.fireValueChangedEvent(helper, change); 521 changeListenerMock[0].check0(); 522 changeListenerMock[1].check1(); 523 changeListenerMock[2].check0(); 524 changeListenerMock[3].check1(); 525 resetAllListeners(); 526 527 // remove last element 528 helper = ListListenerHelper.removeListener(helper, changeListenerMock[3]); 529 ListListenerHelper.fireValueChangedEvent(helper, change); 530 changeListenerMock[0].check0(); 531 changeListenerMock[1].check1(); 532 changeListenerMock[2].check0(); 533 changeListenerMock[3].check0(); 534 resetAllListeners(); 535 536 // remove last change with single invalidation 537 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[0]); 538 helper = ListListenerHelper.removeListener(helper, changeListenerMock[1]); 539 ListListenerHelper.fireValueChangedEvent(helper, change); 540 invalidationListenerMock[0].check(list, 1); 541 changeListenerMock[1].check0(); 542 changeListenerMock[1].clear(); 543 544 // remove change if array is empty 545 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[1]); 546 helper = ListListenerHelper.removeListener(helper, changeListenerMock[0]); 547 ListListenerHelper.fireValueChangedEvent(helper, change); 548 invalidationListenerMock[0].check(list, 1); 549 invalidationListenerMock[1].check(list, 1); 550 changeListenerMock[0].check0(); 551 changeListenerMock[0].clear(); 552 553 // remove last change with two invalidation 554 helper = ListListenerHelper.addListener(helper, changeListenerMock[0]); 555 helper = ListListenerHelper.removeListener(helper, changeListenerMock[0]); 556 ListListenerHelper.fireValueChangedEvent(helper, change); 557 invalidationListenerMock[0].check(list, 1); 558 invalidationListenerMock[1].check(list, 1); 559 changeListenerMock[0].check0(); 560 changeListenerMock[0].clear(); 561 } 562 563 564 @Test 565 public void testGeneric_RemoveChangeInPulse() { 566 final InvalidationListener removeListener = new InvalidationListener() { 567 int counter; 568 @Override 569 public void invalidated(Observable observable) { 570 helper = ListListenerHelper.removeListener(helper, changeListenerMock[counter++]); 571 } 572 }; 573 helper = ListListenerHelper.addListener(helper, invalidationListenerMock[0]); 574 helper = ListListenerHelper.addListener(helper, changeListenerMock[0]); 575 helper = ListListenerHelper.addListener(helper, changeListenerMock[3]); 576 helper = ListListenerHelper.addListener(helper, changeListenerMock[1]); 577 helper = ListListenerHelper.addListener(helper, changeListenerMock[2]); 578 579 helper = ListListenerHelper.addListener(helper, removeListener); 580 ListListenerHelper.fireValueChangedEvent(helper, change); 581 helper = ListListenerHelper.removeListener(helper, removeListener); 582 resetAllListeners(); 583 ListListenerHelper.fireValueChangedEvent(helper, change); 584 changeListenerMock[0].check0(); 585 changeListenerMock[3].check1(); 586 changeListenerMock[1].check1(); 587 changeListenerMock[2].check1(); 588 589 helper = ListListenerHelper.addListener(helper, removeListener); 590 ListListenerHelper.fireValueChangedEvent(helper, change); 591 helper = ListListenerHelper.removeListener(helper, removeListener); 592 resetAllListeners(); 593 ListListenerHelper.fireValueChangedEvent(helper, change); 594 changeListenerMock[0].check0(); 595 changeListenerMock[3].check1(); 596 changeListenerMock[1].check0(); 597 changeListenerMock[2].check1(); 598 599 helper = ListListenerHelper.addListener(helper, removeListener); 600 ListListenerHelper.fireValueChangedEvent(helper, change); 601 helper = ListListenerHelper.removeListener(helper, removeListener); 602 resetAllListeners(); 603 ListListenerHelper.fireValueChangedEvent(helper, change); 604 changeListenerMock[0].check0(); 605 changeListenerMock[3].check1(); 606 changeListenerMock[1].check0(); 607 changeListenerMock[2].check0(); 608 609 helper = ListListenerHelper.addListener(helper, removeListener); 610 ListListenerHelper.fireValueChangedEvent(helper, change); 611 helper = ListListenerHelper.removeListener(helper, removeListener); 612 resetAllListeners(); 613 ListListenerHelper.fireValueChangedEvent(helper, change); 614 changeListenerMock[0].check0(); 615 changeListenerMock[3].check0(); 616 changeListenerMock[1].check0(); 617 changeListenerMock[2].check0(); 618 } 619 620 621 @Test 622 public void testExceptionNotPropagatedFromSingleInvalidation() { 623 helper = ListListenerHelper.addListener(helper,(Observable o) -> {throw new RuntimeException();}); 624 ListListenerHelper.fireValueChangedEvent(helper, change); 625 } 626 627 @Test 628 public void testExceptionNotPropagatedFromMultipleInvalidation() { 629 BitSet called = new BitSet(); 630 631 helper = ListListenerHelper.addListener(helper, (Observable o) -> {called.set(0); throw new RuntimeException();}); 632 helper = ListListenerHelper.addListener(helper, (Observable o) -> {called.set(1); throw new RuntimeException();}); 633 634 ListListenerHelper.fireValueChangedEvent(helper, change); 635 636 assertTrue(called.get(0)); 637 assertTrue(called.get(1)); 638 } 639 640 @Test 641 public void testExceptionNotPropagatedFromSingleChange() { 642 helper = ListListenerHelper.addListener(helper, (ListChangeListener.Change<? extends Object> c) -> { 643 throw new RuntimeException(); 644 }); 645 ListListenerHelper.fireValueChangedEvent(helper, change); 646 } 647 648 @Test 649 public void testExceptionNotPropagatedFromMultipleChange() { 650 BitSet called = new BitSet(); 651 652 helper = ListListenerHelper.addListener(helper, (ListChangeListener.Change<? extends Object> c) -> {called.set(0); throw new RuntimeException();}); 653 helper = ListListenerHelper.addListener(helper, (ListChangeListener.Change<? extends Object> c) -> {called.set(1); throw new RuntimeException();}); 654 ListListenerHelper.fireValueChangedEvent(helper, change); 655 656 assertTrue(called.get(0)); 657 assertTrue(called.get(1)); 658 } 659 660 @Test 661 public void testExceptionNotPropagatedFromMultipleChangeAndInvalidation() { 662 BitSet called = new BitSet(); 663 664 helper = ListListenerHelper.addListener(helper, (ListChangeListener.Change<? extends Object> c) -> {called.set(0); throw new RuntimeException();}); 665 helper = ListListenerHelper.addListener(helper, (ListChangeListener.Change<? extends Object> c) -> {called.set(1); throw new RuntimeException();}); 666 helper = ListListenerHelper.addListener(helper, (Observable o) -> {called.set(2); throw new RuntimeException();}); 667 helper = ListListenerHelper.addListener(helper, (Observable o) -> {called.set(3); throw new RuntimeException();}); 668 ListListenerHelper.fireValueChangedEvent(helper, change); 669 670 assertTrue(called.get(0)); 671 assertTrue(called.get(1)); 672 assertTrue(called.get(2)); 673 assertTrue(called.get(3)); 674 } 675 676 @Test 677 public void testExceptionHandledByThreadUncaughtHandlerInSingleInvalidation() { 678 AtomicBoolean called = new AtomicBoolean(false); 679 680 Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.set(true)); 681 682 helper = ListListenerHelper.addListener(helper,(Observable o) -> {throw new RuntimeException();}); 683 ListListenerHelper.fireValueChangedEvent(helper, change); 684 685 assertTrue(called.get()); 686 } 687 688 689 @Test 690 public void testExceptionHandledByThreadUncaughtHandlerInMultipleInvalidation() { 691 AtomicInteger called = new AtomicInteger(0); 692 693 Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.incrementAndGet()); 694 695 helper = ListListenerHelper.addListener(helper, (Observable o) -> {throw new RuntimeException();}); 696 helper = ListListenerHelper.addListener(helper, (Observable o) -> {throw new RuntimeException();}); 697 ListListenerHelper.fireValueChangedEvent(helper, change); 698 699 assertEquals(2, called.get()); 700 } 701 702 @Test 703 public void testExceptionHandledByThreadUncaughtHandlerInSingleChange() { 704 AtomicBoolean called = new AtomicBoolean(false); 705 706 Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.set(true)); 707 helper = ListListenerHelper.addListener(helper, (ListChangeListener.Change<? extends Object> c) -> {throw new RuntimeException();}); 708 ListListenerHelper.fireValueChangedEvent(helper, change); 709 710 assertTrue(called.get()); 711 } 712 713 @Test 714 public void testExceptionHandledByThreadUncaughtHandlerInMultipleChange() { 715 AtomicInteger called = new AtomicInteger(0); 716 717 Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.incrementAndGet()); 718 719 helper = ListListenerHelper.addListener(helper, (ListChangeListener.Change<? extends Object> c) -> {throw new RuntimeException();}); 720 helper = ListListenerHelper.addListener(helper, (ListChangeListener.Change<? extends Object> c) -> {throw new RuntimeException();}); 721 ListListenerHelper.fireValueChangedEvent(helper, change); 722 723 assertEquals(2, called.get()); 724 } 725 726 @Test 727 public void testExceptionHandledByThreadUncaughtHandlerInMultipleChangeAndInvalidation() { 728 AtomicInteger called = new AtomicInteger(0); 729 730 Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.incrementAndGet()); 731 732 helper = ListListenerHelper.addListener(helper, (ListChangeListener.Change<? extends Object> c) -> { throw new RuntimeException();}); 733 helper = ListListenerHelper.addListener(helper, (ListChangeListener.Change<? extends Object> c) -> { throw new RuntimeException();}); 734 helper = ListListenerHelper.addListener(helper, (Observable o) -> { throw new RuntimeException();}); 735 helper = ListListenerHelper.addListener(helper, (Observable o) -> {throw new RuntimeException();}); 736 ListListenerHelper.fireValueChangedEvent(helper, change); 737 738 assertEquals(4, called.get()); 739 } 740 741 }