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