1 /* 2 * Copyright (c) 2011, 2013, 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 javafx.beans.property; 27 28 import static org.junit.Assert.assertEquals; 29 import static org.junit.Assert.assertFalse; 30 import static org.junit.Assert.assertTrue; 31 32 import javafx.beans.InvalidationListenerMock; 33 import javafx.beans.value.ChangeListenerMock; 34 import javafx.beans.value.ObservableBooleanValueStub; 35 import javafx.beans.value.ObservableObjectValueStub; 36 37 import org.junit.Before; 38 import org.junit.Test; 39 40 public class BooleanPropertyBaseTest { 41 42 private static final Object NO_BEAN = null; 43 private static final String NO_NAME_1 = null; 44 private static final String NO_NAME_2 = ""; 45 private static final Boolean UNDEFINED = null; 46 47 private BooleanPropertyMock property; 48 private InvalidationListenerMock invalidationListener; 49 private ChangeListenerMock<Boolean> changeListener; 50 51 @Before 52 public void setUp() throws Exception { 53 property = new BooleanPropertyMock(); 54 invalidationListener = new InvalidationListenerMock(); 55 changeListener = new ChangeListenerMock<Boolean>(UNDEFINED); 56 } 57 58 private void attachInvalidationListener() { 59 property.addListener(invalidationListener); 60 property.get(); 61 invalidationListener.reset(); 62 } 63 64 private void attachChangeListener() { 65 property.addListener(changeListener); 66 property.get(); 67 changeListener.reset(); 68 } 69 70 @Test 71 public void testConstructor() { 72 final BooleanProperty p1 = new SimpleBooleanProperty(); 73 assertEquals(false, p1.get()); 74 assertEquals(Boolean.FALSE, p1.getValue()); 75 assertFalse(property.isBound()); 76 77 final BooleanProperty p2 = new SimpleBooleanProperty(true); 78 assertEquals(true, p2.get()); 79 assertEquals(Boolean.TRUE, p2.getValue()); 80 assertFalse(property.isBound()); 81 } 82 83 @Test 84 public void testInvalidationListener() { 85 attachInvalidationListener(); 86 property.set(true); 87 invalidationListener.check(property, 1); 88 property.removeListener(invalidationListener); 89 invalidationListener.reset(); 90 property.set(false); 91 invalidationListener.check(null, 0); 92 } 93 94 @Test 95 public void testChangeListener() { 96 attachChangeListener(); 97 property.set(true); 98 changeListener.check(property, false, true, 1); 99 property.removeListener(changeListener); 100 changeListener.reset(); 101 property.set(false); 102 changeListener.check(null, UNDEFINED, UNDEFINED, 0); 103 } 104 105 @Test 106 public void testLazySet() { 107 attachInvalidationListener(); 108 109 // set value once 110 property.set(true); 111 assertEquals(true, property.get()); 112 property.check(1); 113 invalidationListener.check(property, 1); 114 115 // set same value again 116 property.set(true); 117 assertEquals(true, property.get()); 118 property.check(0); 119 invalidationListener.check(null, 0); 120 121 // set value twice without reading 122 property.set(false); 123 property.set(true); 124 assertEquals(true, property.get()); 125 property.check(1); 126 invalidationListener.check(property, 1); 127 } 128 129 @Test 130 public void testEagerSet() { 131 attachChangeListener(); 132 133 // set value once 134 property.set(true); 135 assertEquals(true, property.get()); 136 property.check(1); 137 changeListener.check(property, false, true, 1); 138 139 // set same value again 140 property.set(true); 141 assertEquals(true, property.get()); 142 property.check(0); 143 changeListener.check(null, UNDEFINED, UNDEFINED, 0); 144 145 // set value twice without reading 146 property.set(false); 147 property.set(true); 148 assertEquals(true, property.get()); 149 property.check(2); 150 changeListener.check(property, false, true, 2); 151 } 152 153 @Test 154 public void testLazySetValue() { 155 attachInvalidationListener(); 156 157 // set value once 158 property.setValue(true); 159 assertEquals(true, property.get()); 160 property.check(1); 161 invalidationListener.check(property, 1); 162 163 // set same value again 164 property.setValue(true); 165 assertEquals(true, property.get()); 166 property.check(0); 167 invalidationListener.check(null, 0); 168 169 // set value twice without reading 170 property.setValue(false); 171 property.setValue(true); 172 assertEquals(true, property.get()); 173 property.check(1); 174 invalidationListener.check(property, 1); 175 } 176 177 @Test 178 public void testEagerSetValue() { 179 attachChangeListener(); 180 181 // set value once 182 property.setValue(true); 183 assertEquals(true, property.get()); 184 property.check(1); 185 changeListener.check(property, false, true, 1); 186 187 // set same value again 188 property.setValue(true); 189 assertEquals(true, property.get()); 190 property.check(0); 191 changeListener.check(null, UNDEFINED, UNDEFINED, 0); 192 193 // set value twice without reading 194 property.setValue(false); 195 property.setValue(true); 196 assertEquals(true, property.get()); 197 property.check(2); 198 changeListener.check(property, false, true, 2); 199 } 200 201 @Test(expected=RuntimeException.class) 202 public void testSetBoundValue() { 203 final BooleanProperty v = new SimpleBooleanProperty(true); 204 property.bind(v); 205 property.set(true); 206 } 207 208 @Test 209 public void testLazyBind_primitive() { 210 attachInvalidationListener(); 211 final ObservableBooleanValueStub v = new ObservableBooleanValueStub(true); 212 213 property.bind(v); 214 assertEquals(true, property.get()); 215 assertTrue(property.isBound()); 216 property.check(1); 217 invalidationListener.check(property, 1); 218 219 // change binding once 220 v.set(false); 221 assertEquals(false, property.get()); 222 property.check(1); 223 invalidationListener.check(property, 1); 224 225 // change binding twice without reading 226 v.set(true); 227 v.set(false); 228 assertEquals(false, property.get()); 229 property.check(1); 230 invalidationListener.check(property, 1); 231 232 // change binding twice to same value 233 v.set(true); 234 v.set(true); 235 assertEquals(true, property.get()); 236 property.check(1); 237 invalidationListener.check(property, 1); 238 } 239 240 @Test 241 public void testEagerBind_primitive() { 242 attachChangeListener(); 243 final ObservableBooleanValueStub v = new ObservableBooleanValueStub(true); 244 245 property.bind(v); 246 assertEquals(true, property.get()); 247 assertTrue(property.isBound()); 248 property.check(1); 249 changeListener.check(property, false, true, 1); 250 251 // change binding once 252 v.set(false); 253 assertEquals(false, property.get()); 254 property.check(1); 255 changeListener.check(property, true, false, 1); 256 257 // change binding twice without reading 258 v.set(true); 259 v.set(false); 260 assertEquals(false, property.get()); 261 property.check(2); 262 changeListener.check(property, true, false, 2); 263 264 // change binding twice to same value 265 v.set(true); 266 v.set(true); 267 assertEquals(true, property.get()); 268 property.check(2); 269 changeListener.check(property, false, true, 1); 270 } 271 272 @Test 273 public void testLazyBind_generic() { 274 attachInvalidationListener(); 275 final ObservableObjectValueStub<Boolean> v = new ObservableObjectValueStub<Boolean>(true); 276 277 property.bind(v); 278 assertEquals(true, property.get()); 279 assertTrue(property.isBound()); 280 property.check(1); 281 invalidationListener.check(property, 1); 282 283 // change binding once 284 v.set(false); 285 assertEquals(false, property.get()); 286 property.check(1); 287 invalidationListener.check(property, 1); 288 289 // change binding twice without reading 290 v.set(true); 291 v.set(false); 292 assertEquals(false, property.get()); 293 property.check(1); 294 invalidationListener.check(property, 1); 295 296 // change binding twice to same value 297 v.set(true); 298 v.set(true); 299 assertEquals(true, property.get()); 300 property.check(1); 301 invalidationListener.check(property, 1); 302 303 // set binding to null 304 v.set(null); 305 assertEquals(false, property.get()); 306 property.check(1); 307 invalidationListener.check(property, 1); 308 } 309 310 @Test 311 public void testEagerBind_generic() { 312 attachChangeListener(); 313 final ObservableObjectValueStub<Boolean> v = new ObservableObjectValueStub<Boolean>(true); 314 315 property.bind(v); 316 assertEquals(true, property.get()); 317 assertTrue(property.isBound()); 318 property.check(1); 319 changeListener.check(property, false, true, 1); 320 321 // change binding once 322 v.set(false); 323 assertEquals(false, property.get()); 324 property.check(1); 325 changeListener.check(property, true, false, 1); 326 327 // change binding twice without reading 328 v.set(true); 329 v.set(false); 330 assertEquals(false, property.get()); 331 property.check(2); 332 changeListener.check(property, true, false, 2); 333 334 // change binding twice to same value 335 v.set(true); 336 v.set(true); 337 assertEquals(true, property.get()); 338 property.check(2); 339 changeListener.check(property, false, true, 1); 340 341 // set binding to null 342 v.set(null); 343 assertEquals(false, property.get()); 344 property.check(1); 345 changeListener.check(property, true, false, 1); 346 } 347 348 @Test(expected=NullPointerException.class) 349 public void testBindToNull() { 350 property.bind(null); 351 } 352 353 @Test 354 public void testRebind() { 355 attachInvalidationListener(); 356 final BooleanProperty v1 = new SimpleBooleanProperty(true); 357 final BooleanProperty v2 = new SimpleBooleanProperty(false); 358 property.bind(v1); 359 property.get(); 360 property.reset(); 361 invalidationListener.reset(); 362 363 // rebind causes invalidation event 364 property.bind(v2); 365 assertEquals(false, property.get()); 366 assertTrue(property.isBound()); 367 assertEquals(1, property.counter); 368 invalidationListener.check(property, 1); 369 property.reset(); 370 371 // change new binding 372 v2.set(true); 373 assertEquals(true, property.get()); 374 assertEquals(1, property.counter); 375 invalidationListener.check(property, 1); 376 property.reset(); 377 378 // change old binding 379 v1.set(false); 380 assertEquals(true, property.get()); 381 assertEquals(0, property.counter); 382 invalidationListener.check(null, 0); 383 property.reset(); 384 385 // rebind to same observable should have no effect 386 property.bind(v2); 387 assertEquals(true, property.get()); 388 assertTrue(property.isBound()); 389 assertEquals(0, property.counter); 390 invalidationListener.check(null, 0); 391 } 392 393 @Test 394 public void testUnbind() { 395 attachInvalidationListener(); 396 final BooleanProperty v = new SimpleBooleanProperty(true); 397 property.bind(v); 398 property.unbind(); 399 assertEquals(true, property.get()); 400 assertFalse(property.isBound()); 401 property.reset(); 402 invalidationListener.reset(); 403 404 // change binding 405 v.set(false); 406 assertEquals(true, property.get()); 407 assertEquals(0, property.counter); 408 invalidationListener.check(null, 0); 409 property.reset(); 410 411 // set value 412 property.set(false); 413 assertEquals(false, property.get()); 414 assertEquals(1, property.counter); 415 invalidationListener.check(property, 1); 416 } 417 418 @Test 419 public void testAddingListenerWillAlwaysReceiveInvalidationEvent() { 420 final BooleanProperty v = new SimpleBooleanProperty(true); 421 final InvalidationListenerMock listener2 = new InvalidationListenerMock(); 422 final InvalidationListenerMock listener3 = new InvalidationListenerMock(); 423 424 // setting the property 425 property.set(true); 426 property.addListener(listener2); 427 listener2.reset(); 428 property.set(false); 429 listener2.check(property, 1); 430 431 // binding the property 432 property.bind(v); 433 v.set(false); 434 property.addListener(listener3); 435 v.get(); 436 listener3.reset(); 437 v.set(true); 438 listener3.check(property, 1); 439 } 440 441 @Test 442 public void testToString() { 443 final BooleanProperty v = new SimpleBooleanProperty(true); 444 445 property.set(true); 446 assertEquals("BooleanProperty [value: true]", property.toString()); 447 448 property.bind(v); 449 assertEquals("BooleanProperty [bound, invalid]", property.toString()); 450 property.get(); 451 assertEquals("BooleanProperty [bound, value: true]", property.toString()); 452 v.set(false); 453 assertEquals("BooleanProperty [bound, invalid]", property.toString()); 454 property.get(); 455 assertEquals("BooleanProperty [bound, value: false]", property.toString()); 456 457 final Object bean = new Object(); 458 final String name = "My name"; 459 final BooleanProperty v1 = new BooleanPropertyMock(bean, name); 460 assertEquals("BooleanProperty [bean: " + bean.toString() + ", name: My name, value: false]", v1.toString()); 461 v1.set(true); 462 assertEquals("BooleanProperty [bean: " + bean.toString() + ", name: My name, value: true]", v1.toString()); 463 464 final BooleanProperty v2 = new BooleanPropertyMock(bean, NO_NAME_1); 465 assertEquals("BooleanProperty [bean: " + bean.toString() + ", value: false]", v2.toString()); 466 v2.set(true); 467 assertEquals("BooleanProperty [bean: " + bean.toString() + ", value: true]", v2.toString()); 468 469 final BooleanProperty v3 = new BooleanPropertyMock(bean, NO_NAME_2); 470 assertEquals("BooleanProperty [bean: " + bean.toString() + ", value: false]", v3.toString()); 471 v3.set(true); 472 assertEquals("BooleanProperty [bean: " + bean.toString() + ", value: true]", v3.toString()); 473 474 final BooleanProperty v4 = new BooleanPropertyMock(NO_BEAN, name); 475 assertEquals("BooleanProperty [name: My name, value: false]", v4.toString()); 476 v4.set(true); 477 assertEquals("BooleanProperty [name: My name, value: true]", v4.toString()); 478 } 479 480 private static class BooleanPropertyMock extends BooleanPropertyBase { 481 482 private final Object bean; 483 private final String name; 484 private int counter; 485 486 private BooleanPropertyMock() { 487 this.bean = NO_BEAN; 488 this.name = NO_NAME_1; 489 } 490 491 private BooleanPropertyMock(Object bean, String name) { 492 this.bean = bean; 493 this.name = name; 494 } 495 496 @Override 497 protected void invalidated() { 498 counter++; 499 } 500 501 private void check(int expected) { 502 assertEquals(expected, counter); 503 reset(); 504 } 505 506 private void reset() { 507 counter = 0; 508 } 509 510 @Override public Object getBean() { return bean; } 511 512 @Override public String getName() { return name; } 513 } 514 515 }