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 com.sun.javafx.binding; 27 28 import javafx.beans.InvalidationListener; 29 import javafx.beans.InvalidationListenerMock; 30 import javafx.beans.Observable; 31 import javafx.beans.WeakInvalidationListenerMock; 32 import javafx.beans.value.ChangeListener; 33 import javafx.beans.value.ChangeListenerMock; 34 import javafx.beans.value.ObservableValue; 35 import javafx.beans.value.ObservableValueStub; 36 import javafx.beans.value.WeakChangeListenerMock; 37 import org.junit.Before; 38 import org.junit.Test; 39 40 import java.util.BitSet; 41 import java.util.concurrent.atomic.AtomicBoolean; 42 import java.util.concurrent.atomic.AtomicInteger; 43 44 import static org.junit.Assert.assertEquals; 45 import static org.junit.Assert.assertTrue; 46 47 public class ExpressionHelperTest { 48 49 private static final Object UNDEFINED = new Object(); 50 private static final Object DATA_1 = new Object(); 51 private static final Object DATA_2 = new Object(); 52 53 private ExpressionHelper helper; 54 private ObservableValueStub observable; 55 private InvalidationListenerMock[] invalidationListener; 56 private ChangeListenerMock<Object>[] changeListener; 57 58 @Before 59 public void setUp() { 60 helper = null; 61 observable = new ObservableValueStub(DATA_1); 62 invalidationListener = new InvalidationListenerMock[] { 63 new InvalidationListenerMock(), new InvalidationListenerMock(), new InvalidationListenerMock(), new InvalidationListenerMock() 64 }; 65 changeListener = new ChangeListenerMock[] { 66 new ChangeListenerMock<Object>(UNDEFINED), new ChangeListenerMock<Object>(UNDEFINED), new ChangeListenerMock<Object>(UNDEFINED), new ChangeListenerMock<Object>(UNDEFINED) 67 }; 68 } 69 70 @Test (expected = NullPointerException.class) 71 public void testAddInvalidation_Null_X() { 72 ExpressionHelper.addListener(helper, null, invalidationListener[0]); 73 } 74 75 @Test (expected = NullPointerException.class) 76 public void testAddInvalidation_X_Null() { 77 ExpressionHelper.addListener(helper, observable, (InvalidationListener) null); 78 } 79 80 @Test (expected = NullPointerException.class) 81 public void testRemoveInvalidation_Null() { 82 ExpressionHelper.removeListener(helper, (InvalidationListener) null); 83 } 84 85 @Test (expected = NullPointerException.class) 86 public void testAddChange_Null_X() { 87 ExpressionHelper.addListener(helper, null, changeListener[0]); 88 } 89 90 @Test (expected = NullPointerException.class) 91 public void testAddChange_X_Null() { 92 ExpressionHelper.addListener(helper, observable, (ChangeListener) null); 93 } 94 95 @Test (expected = NullPointerException.class) 96 public void testRemoveChange_Null() { 97 ExpressionHelper.removeListener(helper, (ChangeListener) null); 98 } 99 100 @Test 101 public void testEmptyHelper() { 102 // all of these calls should be no-ops 103 ExpressionHelper.removeListener(helper, invalidationListener[0]); 104 ExpressionHelper.removeListener(helper, changeListener[0]); 105 ExpressionHelper.fireValueChangedEvent(helper); 106 } 107 108 @Test 109 public void testSingeInvalidation() { 110 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[0]); 111 ExpressionHelper.fireValueChangedEvent(helper); 112 invalidationListener[0].check(observable, 1); 113 114 helper = ExpressionHelper.removeListener(helper, invalidationListener[1]); 115 ExpressionHelper.fireValueChangedEvent(helper); 116 invalidationListener[0].check(observable, 1); 117 invalidationListener[1].check(null, 0); 118 119 helper = ExpressionHelper.removeListener(helper, changeListener[1]); 120 ExpressionHelper.fireValueChangedEvent(helper); 121 invalidationListener[0].check(observable, 1); 122 changeListener[1].check(null, UNDEFINED, UNDEFINED, 0); 123 124 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[1]); 125 ExpressionHelper.fireValueChangedEvent(helper); 126 invalidationListener[0].check(observable, 1); 127 invalidationListener[1].check(observable, 1); 128 129 helper = ExpressionHelper.removeListener(helper, invalidationListener[1]); 130 ExpressionHelper.fireValueChangedEvent(helper); 131 invalidationListener[0].check(observable, 1); 132 invalidationListener[1].check(null, 0); 133 134 helper = ExpressionHelper.addListener(helper, observable, changeListener[1]); 135 observable.set(DATA_2); 136 ExpressionHelper.fireValueChangedEvent(helper); 137 invalidationListener[0].check(observable, 1); 138 changeListener[1].check(observable, DATA_1, DATA_2, 1); 139 140 helper = ExpressionHelper.removeListener(helper, changeListener[1]); 141 observable.set(DATA_1); 142 ExpressionHelper.fireValueChangedEvent(helper); 143 invalidationListener[0].check(observable, 1); 144 changeListener[1].check(null, UNDEFINED, UNDEFINED, 0); 145 146 helper = ExpressionHelper.removeListener(helper, invalidationListener[0]); 147 ExpressionHelper.fireValueChangedEvent(helper); 148 invalidationListener[0].check(null, 0); 149 } 150 151 @Test 152 public void testSingeChange() { 153 helper = ExpressionHelper.addListener(helper, observable, changeListener[0]); 154 observable.set(DATA_2); 155 ExpressionHelper.fireValueChangedEvent(helper); 156 changeListener[0].check(observable, DATA_1, DATA_2, 1); 157 158 helper = ExpressionHelper.removeListener(helper, invalidationListener[1]); 159 observable.set(DATA_1); 160 ExpressionHelper.fireValueChangedEvent(helper); 161 changeListener[0].check(observable, DATA_2, DATA_1, 1); 162 invalidationListener[1].check(null, 0); 163 164 helper = ExpressionHelper.removeListener(helper, changeListener[1]); 165 observable.set(DATA_2); 166 ExpressionHelper.fireValueChangedEvent(helper); 167 changeListener[0].check(observable, DATA_1, DATA_2, 1); 168 changeListener[1].check(null, UNDEFINED, UNDEFINED, 0); 169 170 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[1]); 171 observable.set(DATA_1); 172 ExpressionHelper.fireValueChangedEvent(helper); 173 changeListener[0].check(observable, DATA_2, DATA_1, 1); 174 invalidationListener[1].check(observable, 1); 175 176 helper = ExpressionHelper.removeListener(helper, invalidationListener[1]); 177 observable.set(DATA_2); 178 ExpressionHelper.fireValueChangedEvent(helper); 179 changeListener[0].check(observable, DATA_1, DATA_2, 1); 180 invalidationListener[1].check(null, 0); 181 182 helper = ExpressionHelper.addListener(helper, observable, changeListener[1]); 183 observable.set(DATA_1); 184 ExpressionHelper.fireValueChangedEvent(helper); 185 changeListener[0].check(observable, DATA_2, DATA_1, 1); 186 changeListener[1].check(observable, DATA_2, DATA_1, 1); 187 188 helper = ExpressionHelper.removeListener(helper, changeListener[1]); 189 observable.set(DATA_2); 190 ExpressionHelper.fireValueChangedEvent(helper); 191 changeListener[0].check(observable, DATA_1, DATA_2, 1); 192 changeListener[1].check(null, UNDEFINED, UNDEFINED, 0); 193 194 helper = ExpressionHelper.removeListener(helper, changeListener[0]); 195 ExpressionHelper.fireValueChangedEvent(helper); 196 changeListener[0].check(null, UNDEFINED, UNDEFINED, 0); 197 } 198 199 @Test 200 public void testAddInvalidation() { 201 final InvalidationListener weakListener = new WeakInvalidationListenerMock(); 202 203 helper = ExpressionHelper.addListener(helper, observable, changeListener[0]); 204 helper = ExpressionHelper.addListener(helper, observable, changeListener[1]); 205 206 helper = ExpressionHelper.addListener(helper, observable, weakListener); 207 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[0]); 208 ExpressionHelper.fireValueChangedEvent(helper); 209 invalidationListener[0].check(observable, 1); 210 211 helper = ExpressionHelper.addListener(helper, observable, weakListener); 212 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[1]); 213 ExpressionHelper.fireValueChangedEvent(helper); 214 invalidationListener[0].check(observable, 1); 215 invalidationListener[1].check(observable, 1); 216 217 helper = ExpressionHelper.addListener(helper, observable, weakListener); 218 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[2]); 219 ExpressionHelper.fireValueChangedEvent(helper); 220 invalidationListener[0].check(observable, 1); 221 invalidationListener[1].check(observable, 1); 222 invalidationListener[2].check(observable, 1); 223 } 224 225 @Test 226 public void testRemoveInvalidation() { 227 helper = ExpressionHelper.addListener(helper, observable, changeListener[0]); 228 helper = ExpressionHelper.addListener(helper, observable, changeListener[1]); 229 230 helper = ExpressionHelper.removeListener(helper, invalidationListener[1]); 231 232 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[0]); 233 234 helper = ExpressionHelper.removeListener(helper, invalidationListener[1]); 235 236 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[2]); 237 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[1]); 238 239 helper = ExpressionHelper.removeListener(helper, invalidationListener[0]); 240 ExpressionHelper.fireValueChangedEvent(helper); 241 invalidationListener[0].check(null, 0); 242 invalidationListener[1].check(observable, 1); 243 invalidationListener[2].check(observable, 1); 244 245 helper = ExpressionHelper.removeListener(helper, invalidationListener[1]); 246 ExpressionHelper.fireValueChangedEvent(helper); 247 invalidationListener[0].check(null, 0); 248 invalidationListener[1].check(null, 0); 249 invalidationListener[2].check(observable, 1); 250 251 helper = ExpressionHelper.removeListener(helper, invalidationListener[2]); 252 ExpressionHelper.fireValueChangedEvent(helper); 253 invalidationListener[0].check(null, 0); 254 invalidationListener[1].check(null, 0); 255 invalidationListener[2].check(null, 0); 256 } 257 258 @Test 259 public void testAddInvalidationWhileLocked() { 260 final ChangeListener<Object> addingListener = new ChangeListener() { 261 int index = 0; 262 @Override public void changed(ObservableValue observable, Object oldValue, Object newValue) { 263 if (index < invalidationListener.length) { 264 helper = ExpressionHelper.addListener(helper, ExpressionHelperTest.this.observable, invalidationListener[index++]); 265 } 266 } 267 }; 268 helper = ExpressionHelper.addListener(helper, observable, addingListener); 269 helper = ExpressionHelper.addListener(helper, observable, changeListener[0]); 270 271 observable.set(DATA_2); 272 ExpressionHelper.fireValueChangedEvent(helper); 273 274 invalidationListener[0].reset(); 275 observable.set(DATA_1); 276 ExpressionHelper.fireValueChangedEvent(helper); 277 invalidationListener[0].check(observable, 1); 278 279 invalidationListener[1].reset(); 280 observable.set(DATA_2); 281 ExpressionHelper.fireValueChangedEvent(helper); 282 invalidationListener[0].check(observable, 1); 283 invalidationListener[1].check(observable, 1); 284 285 invalidationListener[2].reset(); 286 observable.set(DATA_1); 287 ExpressionHelper.fireValueChangedEvent(helper); 288 invalidationListener[0].check(observable, 1); 289 invalidationListener[1].check(observable, 1); 290 invalidationListener[2].check(observable, 1); 291 292 invalidationListener[3].reset(); 293 observable.set(DATA_2); 294 ExpressionHelper.fireValueChangedEvent(helper); 295 invalidationListener[0].check(observable, 1); 296 invalidationListener[1].check(observable, 1); 297 invalidationListener[2].check(observable, 1); 298 invalidationListener[3].check(observable, 1); 299 } 300 301 @Test 302 public void testRemoveInvalidationWhileLocked() { 303 final ChangeListener<Object> removingListener = new ChangeListener() { 304 int index = 0; 305 @Override public void changed(ObservableValue observable, Object oldValue, Object newValue) { 306 if (index < invalidationListener.length) { 307 helper = ExpressionHelper.removeListener(helper, invalidationListener[index++]); 308 } 309 } 310 }; 311 helper = ExpressionHelper.addListener(helper, observable, removingListener); 312 helper = ExpressionHelper.addListener(helper, observable, changeListener[0]); 313 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[0]); 314 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[2]); 315 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[1]); 316 317 observable.set(DATA_2); 318 ExpressionHelper.fireValueChangedEvent(helper); 319 invalidationListener[0].reset(); 320 invalidationListener[1].check(observable, 1); 321 invalidationListener[2].check(observable, 1); 322 323 observable.set(DATA_1); 324 ExpressionHelper.fireValueChangedEvent(helper); 325 invalidationListener[0].check(null, 0); 326 invalidationListener[1].reset(); 327 invalidationListener[2].check(observable, 1); 328 329 observable.set(DATA_2); 330 ExpressionHelper.fireValueChangedEvent(helper); 331 invalidationListener[0].check(null, 0); 332 invalidationListener[1].check(null, 0); 333 invalidationListener[2].reset(); 334 335 observable.set(DATA_1); 336 ExpressionHelper.fireValueChangedEvent(helper); 337 invalidationListener[0].check(null, 0); 338 invalidationListener[1].check(null, 0); 339 invalidationListener[2].check(null, 0); 340 } 341 342 @Test 343 public void testAddChange() { 344 final ChangeListener<Object> weakListener = new WeakChangeListenerMock(); 345 346 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[0]); 347 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[1]); 348 349 helper = ExpressionHelper.addListener(helper, observable, weakListener); 350 helper = ExpressionHelper.addListener(helper, observable, changeListener[0]); 351 observable.set(DATA_2); 352 ExpressionHelper.fireValueChangedEvent(helper); 353 changeListener[0].check(observable, DATA_1, DATA_2, 1); 354 355 helper = ExpressionHelper.addListener(helper, observable, weakListener); 356 helper = ExpressionHelper.addListener(helper, observable, changeListener[1]); 357 observable.set(DATA_1); 358 ExpressionHelper.fireValueChangedEvent(helper); 359 changeListener[0].check(observable, DATA_2, DATA_1, 1); 360 changeListener[1].check(observable, DATA_2, DATA_1, 1); 361 362 helper = ExpressionHelper.addListener(helper, observable, weakListener); 363 helper = ExpressionHelper.addListener(helper, observable, changeListener[2]); 364 observable.set(DATA_2); 365 ExpressionHelper.fireValueChangedEvent(helper); 366 changeListener[0].check(observable, DATA_1, DATA_2, 1); 367 changeListener[1].check(observable, DATA_1, DATA_2, 1); 368 changeListener[2].check(observable, DATA_1, DATA_2, 1); 369 } 370 371 @Test 372 public void testRemoveChange() { 373 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[0]); 374 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[1]); 375 376 helper = ExpressionHelper.removeListener(helper, changeListener[1]); 377 378 helper = ExpressionHelper.addListener(helper, observable, changeListener[0]); 379 380 helper = ExpressionHelper.removeListener(helper, changeListener[1]); 381 382 helper = ExpressionHelper.addListener(helper, observable, changeListener[2]); 383 helper = ExpressionHelper.addListener(helper, observable, changeListener[1]); 384 385 helper = ExpressionHelper.removeListener(helper, changeListener[0]); 386 observable.set(DATA_2); 387 ExpressionHelper.fireValueChangedEvent(helper); 388 changeListener[0].check(null, UNDEFINED, UNDEFINED, 0); 389 changeListener[1].check(observable, DATA_1, DATA_2, 1); 390 changeListener[2].check(observable, DATA_1, DATA_2, 1); 391 392 helper = ExpressionHelper.removeListener(helper, changeListener[1]); 393 observable.set(DATA_1); 394 ExpressionHelper.fireValueChangedEvent(helper); 395 changeListener[0].check(null, UNDEFINED, UNDEFINED, 0); 396 changeListener[1].check(null, UNDEFINED, UNDEFINED, 0); 397 changeListener[2].check(observable, DATA_2, DATA_1, 1); 398 399 helper = ExpressionHelper.removeListener(helper, changeListener[2]); 400 observable.set(DATA_2); 401 ExpressionHelper.fireValueChangedEvent(helper); 402 changeListener[0].check(null, UNDEFINED, UNDEFINED, 0); 403 changeListener[1].check(null, UNDEFINED, UNDEFINED, 0); 404 changeListener[2].check(null, UNDEFINED, UNDEFINED, 0); 405 } 406 407 @Test 408 public void testAddChangeWhileLocked() { 409 final InvalidationListener addingListener = new InvalidationListener() { 410 int index = 0; 411 @Override public void invalidated(Observable observable) { 412 if (index < invalidationListener.length) { 413 helper = ExpressionHelper.addListener(helper, ExpressionHelperTest.this.observable, changeListener[index++]); 414 } 415 } 416 }; 417 helper = ExpressionHelper.addListener(helper, observable, addingListener); 418 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[0]); 419 420 observable.set(DATA_2); 421 ExpressionHelper.fireValueChangedEvent(helper); 422 423 changeListener[0].reset(); 424 observable.set(DATA_1); 425 ExpressionHelper.fireValueChangedEvent(helper); 426 changeListener[0].check(observable, DATA_2, DATA_1, 1); 427 428 changeListener[1].reset(); 429 observable.set(DATA_2); 430 ExpressionHelper.fireValueChangedEvent(helper); 431 changeListener[0].check(observable, DATA_1, DATA_2, 1); 432 changeListener[1].check(observable, DATA_1, DATA_2, 1); 433 434 changeListener[2].reset(); 435 observable.set(DATA_1); 436 ExpressionHelper.fireValueChangedEvent(helper); 437 changeListener[0].check(observable, DATA_2, DATA_1, 1); 438 changeListener[1].check(observable, DATA_2, DATA_1, 1); 439 changeListener[2].check(observable, DATA_2, DATA_1, 1); 440 441 changeListener[3].reset(); 442 observable.set(DATA_2); 443 ExpressionHelper.fireValueChangedEvent(helper); 444 changeListener[0].check(observable, DATA_1, DATA_2, 1); 445 changeListener[1].check(observable, DATA_1, DATA_2, 1); 446 changeListener[2].check(observable, DATA_1, DATA_2, 1); 447 changeListener[3].check(observable, DATA_1, DATA_2, 1); 448 } 449 450 @Test 451 public void testRemoveChangeWhileLocked() { 452 final InvalidationListener removingListener = new InvalidationListener() { 453 int index = 0; 454 @Override public void invalidated(Observable observable) { 455 if (index < invalidationListener.length) { 456 helper = ExpressionHelper.removeListener(helper, changeListener[index++]); 457 } 458 } 459 }; 460 helper = ExpressionHelper.addListener(helper, observable, removingListener); 461 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[0]); 462 helper = ExpressionHelper.addListener(helper, observable, changeListener[0]); 463 helper = ExpressionHelper.addListener(helper, observable, changeListener[2]); 464 helper = ExpressionHelper.addListener(helper, observable, changeListener[1]); 465 466 observable.set(DATA_2); 467 ExpressionHelper.fireValueChangedEvent(helper); 468 changeListener[0].reset(); 469 changeListener[1].check(observable, DATA_1, DATA_2, 1); 470 changeListener[2].check(observable, DATA_1, DATA_2, 1); 471 472 observable.set(DATA_1); 473 ExpressionHelper.fireValueChangedEvent(helper); 474 changeListener[0].check(null, UNDEFINED, UNDEFINED, 0); 475 changeListener[1].reset(); 476 changeListener[2].check(observable, DATA_2, DATA_1, 1); 477 478 observable.set(DATA_2); 479 ExpressionHelper.fireValueChangedEvent(helper); 480 changeListener[0].check(null, UNDEFINED, UNDEFINED, 0); 481 changeListener[1].check(null, UNDEFINED, UNDEFINED, 0); 482 changeListener[2].reset(); 483 484 observable.set(DATA_1); 485 ExpressionHelper.fireValueChangedEvent(helper); 486 changeListener[0].check(null, UNDEFINED, UNDEFINED, 0); 487 changeListener[1].check(null, UNDEFINED, UNDEFINED, 0); 488 changeListener[2].check(null, UNDEFINED, UNDEFINED, 0); 489 } 490 491 @Test 492 public void testFireValueChangedEvent() { 493 helper = ExpressionHelper.addListener(helper, observable, invalidationListener[0]); 494 helper = ExpressionHelper.addListener(helper, observable, changeListener[0]); 495 496 ExpressionHelper.fireValueChangedEvent(helper); 497 invalidationListener[0].check(observable, 1); 498 changeListener[0].check(null, UNDEFINED, UNDEFINED, 0); 499 500 observable.set(null); 501 ExpressionHelper.fireValueChangedEvent(helper); 502 invalidationListener[0].check(observable, 1); 503 changeListener[0].check(observable, DATA_1, null, 1); 504 505 ExpressionHelper.fireValueChangedEvent(helper); 506 invalidationListener[0].check(observable, 1); 507 changeListener[0].check(null, UNDEFINED, UNDEFINED, 0); 508 509 observable.set(DATA_1); 510 ExpressionHelper.fireValueChangedEvent(helper); 511 invalidationListener[0].check(observable, 1); 512 changeListener[0].check(observable, null, DATA_1, 1); 513 514 ExpressionHelper.fireValueChangedEvent(helper); 515 invalidationListener[0].check(observable, 1); 516 changeListener[0].check(null, UNDEFINED, UNDEFINED, 0); 517 } 518 519 @Test 520 public void testExceptionNotPropagatedFromSingleInvalidation() { 521 helper = ExpressionHelper.addListener(helper, observable,(o) -> {throw new RuntimeException();}); 522 observable.set(null); 523 helper.fireValueChangedEvent(); 524 } 525 526 @Test 527 public void testExceptionNotPropagatedFromMultipleInvalidation() { 528 BitSet called = new BitSet(); 529 530 helper = ExpressionHelper.addListener(helper, observable, (o) -> {called.set(0); throw new RuntimeException();}); 531 helper = ExpressionHelper.addListener(helper, observable, (o) -> {called.set(1); throw new RuntimeException();}); 532 observable.set(null); 533 helper.fireValueChangedEvent(); 534 535 assertTrue(called.get(0)); 536 assertTrue(called.get(1)); 537 } 538 539 @Test 540 public void testExceptionNotPropagatedFromSingleChange() { 541 helper = ExpressionHelper.addListener(helper, observable, (value, o1, o2) -> {throw new RuntimeException();}); 542 observable.set(null); 543 helper.fireValueChangedEvent(); 544 } 545 546 @Test 547 public void testExceptionNotPropagatedFromMultipleChange() { 548 BitSet called = new BitSet(); 549 550 helper = ExpressionHelper.addListener(helper, observable, (value, o1, o2) -> {called.set(0); throw new RuntimeException();}); 551 helper = ExpressionHelper.addListener(helper, observable, (value, o1, o2) -> {called.set(1); throw new RuntimeException();}); 552 observable.set(null); 553 helper.fireValueChangedEvent(); 554 555 assertTrue(called.get(0)); 556 assertTrue(called.get(1)); 557 } 558 559 @Test 560 public void testExceptionNotPropagatedFromMultipleChangeAndInvalidation() { 561 BitSet called = new BitSet(); 562 563 helper = ExpressionHelper.addListener(helper, observable, (value, o1, o2) -> {called.set(0); throw new RuntimeException();}); 564 helper = ExpressionHelper.addListener(helper, observable, (value, o1, o2) -> {called.set(1); throw new RuntimeException();}); 565 helper = ExpressionHelper.addListener(helper, observable, (o) -> {called.set(2); throw new RuntimeException();}); 566 helper = ExpressionHelper.addListener(helper, observable, (o) -> {called.set(3); throw new RuntimeException();}); 567 observable.set(null); 568 helper.fireValueChangedEvent(); 569 570 assertTrue(called.get(0)); 571 assertTrue(called.get(1)); 572 assertTrue(called.get(2)); 573 assertTrue(called.get(3)); 574 } 575 576 @Test 577 public void testExceptionHandledByThreadUncaughtHandlerInSingleInvalidation() { 578 AtomicBoolean called = new AtomicBoolean(false); 579 580 Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.set(true)); 581 582 helper = ExpressionHelper.addListener(helper, observable,(o) -> {throw new RuntimeException();}); 583 observable.set(null); 584 helper.fireValueChangedEvent(); 585 586 assertTrue(called.get()); 587 } 588 589 590 @Test 591 public void testExceptionHandledByThreadUncaughtHandlerInMultipleInvalidation() { 592 AtomicInteger called = new AtomicInteger(0); 593 594 Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.incrementAndGet()); 595 596 helper = ExpressionHelper.addListener(helper, observable, (o) -> {throw new RuntimeException();}); 597 helper = ExpressionHelper.addListener(helper, observable, (o) -> {throw new RuntimeException();}); 598 observable.set(null); 599 helper.fireValueChangedEvent(); 600 601 assertEquals(2, called.get()); 602 } 603 604 @Test 605 public void testExceptionHandledByThreadUncaughtHandlerInSingleChange() { 606 AtomicBoolean called = new AtomicBoolean(false); 607 608 Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.set(true)); 609 helper = ExpressionHelper.addListener(helper, observable, (value, o1, o2) -> {throw new RuntimeException();}); 610 observable.set(null); 611 helper.fireValueChangedEvent(); 612 613 assertTrue(called.get()); 614 } 615 616 @Test 617 public void testExceptionHandledByThreadUncaughtHandlerInMultipleChange() { 618 AtomicInteger called = new AtomicInteger(0); 619 620 Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.incrementAndGet()); 621 622 helper = ExpressionHelper.addListener(helper, observable, (value, o1, o2) -> {throw new RuntimeException();}); 623 helper = ExpressionHelper.addListener(helper, observable, (value, o1, o2) -> {throw new RuntimeException();}); 624 observable.set(null); 625 helper.fireValueChangedEvent(); 626 627 assertEquals(2, called.get()); 628 } 629 630 @Test 631 public void testExceptionHandledByThreadUncaughtHandlerInMultipleChangeAndInvalidation() { 632 AtomicInteger called = new AtomicInteger(0); 633 634 Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.incrementAndGet()); 635 636 helper = ExpressionHelper.addListener(helper, observable, (value, o1, o2) -> { throw new RuntimeException();}); 637 helper = ExpressionHelper.addListener(helper, observable, (value, o1, o2) -> { throw new RuntimeException();}); 638 helper = ExpressionHelper.addListener(helper, observable, (o) -> { throw new RuntimeException();}); 639 helper = ExpressionHelper.addListener(helper, observable, (o) -> {throw new RuntimeException();}); 640 observable.set(null); 641 helper.fireValueChangedEvent(); 642 643 assertEquals(4, called.get()); 644 } 645 646 }