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 
  29 import static org.junit.Assert.assertEquals;
  30 import static org.junit.Assert.assertFalse;
  31 import static org.junit.Assert.assertTrue;
  32 
  33 import javafx.beans.InvalidationListenerMock;
  34 import javafx.beans.value.ChangeListenerMock;
  35 import javafx.beans.value.ObservableDoubleValueStub;
  36 import javafx.beans.value.ObservableObjectValueStub;
  37 
  38 import org.junit.Before;
  39 import org.junit.Test;
  40 
  41 public class ReadOnlyDoubleWrapperTest {
  42 
  43     private static final Double UNDEFINED = null;
  44     private static final double DEFAULT = 0.0;
  45     private static final double VALUE_1 = Math.PI;
  46     private static final double VALUE_2 = Math.E;
  47     private static final double EPSILON = 1e-12;
  48     
  49     private ReadOnlyDoubleWrapperMock property;
  50     private ReadOnlyDoubleProperty readOnlyProperty;
  51     private InvalidationListenerMock internalInvalidationListener;
  52     private InvalidationListenerMock publicInvalidationListener;
  53     private ChangeListenerMock<Number> internalChangeListener;
  54     private ChangeListenerMock<Number> publicChangeListener;
  55     
  56     @Before
  57     public void setUp() throws Exception {
  58         property = new ReadOnlyDoubleWrapperMock();
  59         readOnlyProperty = property.getReadOnlyProperty();
  60         internalInvalidationListener = new InvalidationListenerMock();
  61         publicInvalidationListener = new InvalidationListenerMock();
  62         internalChangeListener = new ChangeListenerMock<Number>(UNDEFINED);
  63         publicChangeListener = new ChangeListenerMock<Number>(UNDEFINED);
  64     }
  65     
  66     private void attachInvalidationListeners() {
  67         property.addListener(internalInvalidationListener);
  68         readOnlyProperty.addListener(publicInvalidationListener);
  69         property.get();
  70         readOnlyProperty.get();
  71         internalInvalidationListener.reset();
  72         publicInvalidationListener.reset();
  73     }
  74 
  75     private void attachInternalChangeListener() {
  76         property.addListener(internalChangeListener);
  77         property.get();
  78         internalChangeListener.reset();
  79     }
  80 
  81     private void attachPublicChangeListener() {
  82         readOnlyProperty.addListener(publicChangeListener);
  83         readOnlyProperty.get();
  84         publicChangeListener.reset();
  85     }
  86 
  87     @Test
  88     public void testConstructor_NoArguments() {
  89         final ReadOnlyDoubleWrapper p1 = new ReadOnlyDoubleWrapper();
  90         assertEquals(DEFAULT, p1.get(), EPSILON);
  91         assertEquals((Double)DEFAULT, p1.getValue(), EPSILON);
  92         assertFalse(property.isBound());
  93         assertEquals(null, p1.getBean());
  94         assertEquals("", p1.getName());
  95         final ReadOnlyDoubleProperty r1 = p1.getReadOnlyProperty();
  96         assertEquals(DEFAULT, r1.get(), EPSILON);
  97         assertEquals((Double)DEFAULT, r1.getValue(), EPSILON);
  98         assertEquals(null, r1.getBean());
  99         assertEquals("", r1.getName());
 100     }
 101     
 102     @Test
 103     public void testConstructor_InitialValue() {
 104         final ReadOnlyDoubleWrapper p1 = new ReadOnlyDoubleWrapper(VALUE_1);
 105         assertEquals(VALUE_1, p1.get(), EPSILON);
 106         assertEquals((Double)VALUE_1, p1.getValue(), EPSILON);
 107         assertFalse(property.isBound());
 108         assertEquals(null, p1.getBean());
 109         assertEquals("", p1.getName());
 110         final ReadOnlyDoubleProperty r1 = p1.getReadOnlyProperty();
 111         assertEquals(VALUE_1, r1.get(), EPSILON);
 112         assertEquals((Double)VALUE_1, r1.getValue(), EPSILON);
 113         assertEquals(null, r1.getBean());
 114         assertEquals("", r1.getName());
 115     }
 116     
 117     @Test
 118     public void testConstructor_Bean_Name() {
 119         final Object bean = new Object();
 120         final String name = "My name";
 121         final ReadOnlyDoubleWrapper p1 = new ReadOnlyDoubleWrapper(bean, name);
 122         assertEquals(DEFAULT, p1.get(), EPSILON);
 123         assertEquals((Double)DEFAULT, p1.getValue(), EPSILON);
 124         assertFalse(property.isBound());
 125         assertEquals(bean, p1.getBean());
 126         assertEquals(name, p1.getName());
 127         final ReadOnlyDoubleProperty r1 = p1.getReadOnlyProperty();
 128         assertEquals(DEFAULT, r1.get(), EPSILON);
 129         assertEquals((Double)DEFAULT, r1.getValue(), EPSILON);
 130         assertEquals(bean, r1.getBean());
 131         assertEquals(name, r1.getName());
 132     }
 133     
 134     @Test
 135     public void testConstructor_Bean_Name_InitialValue() {
 136         final Object bean = new Object();
 137         final String name = "My name";
 138         final ReadOnlyDoubleWrapper p1 = new ReadOnlyDoubleWrapper(bean, name, VALUE_1);
 139         assertEquals(VALUE_1, p1.get(), EPSILON);
 140         assertEquals((Double)VALUE_1, p1.getValue(), EPSILON);
 141         assertFalse(property.isBound());
 142         assertEquals(bean, p1.getBean());
 143         assertEquals(name, p1.getName());
 144         final ReadOnlyDoubleProperty r1 = p1.getReadOnlyProperty();
 145         assertEquals(VALUE_1, r1.get(), EPSILON);
 146         assertEquals((Double)VALUE_1, r1.getValue(), EPSILON);
 147         assertEquals(bean, r1.getBean());
 148         assertEquals(name, r1.getName());
 149     }
 150 
 151     @Test
 152     public void testLazySet() {
 153         attachInvalidationListeners();
 154         
 155         // set value once
 156         property.set(VALUE_1);
 157         assertEquals(VALUE_1, property.get(), EPSILON);
 158         property.check(1);
 159         internalInvalidationListener.check(readOnlyProperty, 1);
 160         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 161         publicInvalidationListener.check(readOnlyProperty, 1);
 162         
 163         // set same value again
 164         property.set(VALUE_1);
 165         assertEquals(VALUE_1, property.get(), EPSILON);
 166         property.check(0);
 167         internalInvalidationListener.check(null, 0);
 168         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 169         publicInvalidationListener.check(null, 0);
 170         
 171         // set value twice without reading
 172         property.set(VALUE_2);
 173         property.set(VALUE_1);
 174         assertEquals(VALUE_1, property.get(), EPSILON);
 175         property.check(1);
 176         internalInvalidationListener.check(readOnlyProperty, 1);
 177         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 178         publicInvalidationListener.check(readOnlyProperty, 1);
 179     }
 180     
 181     @Test
 182     public void testInternalEagerSet() {
 183         attachInternalChangeListener();
 184         
 185         // set value once
 186         property.set(VALUE_1);
 187         assertEquals(VALUE_1, property.get(), EPSILON);
 188         property.check(1);
 189         internalChangeListener.check(readOnlyProperty, DEFAULT, VALUE_1, 1);
 190         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 191         
 192         // set same value again
 193         property.set(VALUE_1);
 194         assertEquals(VALUE_1, property.get(), EPSILON);
 195         property.check(0);
 196         internalChangeListener.check(null, UNDEFINED, UNDEFINED, 0);
 197         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 198         
 199         // set value twice without reading
 200         property.set(VALUE_2);
 201         property.set(VALUE_1);
 202         assertEquals(VALUE_1, property.get(), EPSILON);
 203         property.check(2);
 204         internalChangeListener.check(readOnlyProperty, VALUE_2, VALUE_1, 2);
 205         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 206     }
 207     
 208     @Test
 209     public void testPublicEagerSet() {
 210         attachPublicChangeListener();
 211         
 212         // set value once
 213         property.set(VALUE_1);
 214         assertEquals(VALUE_1, property.get(), EPSILON);
 215         property.check(1);
 216         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 217         publicChangeListener.check(readOnlyProperty, DEFAULT, VALUE_1, 1);
 218         
 219         // set same value again
 220         property.set(VALUE_1);
 221         assertEquals(VALUE_1, property.get(), EPSILON);
 222         property.check(0);
 223         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 224         publicChangeListener.check(null, UNDEFINED, UNDEFINED, 0);
 225         
 226         // set value twice without reading
 227         property.set(VALUE_2);
 228         property.set(VALUE_1);
 229         assertEquals(VALUE_1, property.get(), EPSILON);
 230         property.check(2);
 231         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 232         publicChangeListener.check(readOnlyProperty, VALUE_2, VALUE_1, 2);
 233     }
 234 
 235     @Test
 236     public void testLazySetValue() {
 237         attachInvalidationListeners();
 238         
 239         // set value once
 240         property.setValue(VALUE_1);
 241         assertEquals(VALUE_1, property.get(), EPSILON);
 242         property.check(1);
 243         internalInvalidationListener.check(readOnlyProperty, 1);
 244         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 245         publicInvalidationListener.check(readOnlyProperty, 1);
 246         
 247         // set same value again
 248         property.setValue(VALUE_1);
 249         assertEquals(VALUE_1, property.get(), EPSILON);
 250         property.check(0);
 251         internalInvalidationListener.check(null, 0);
 252         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 253         publicInvalidationListener.check(null, 0);
 254         
 255         // set value twice without reading
 256         property.setValue(VALUE_2);
 257         property.setValue(VALUE_1);
 258         assertEquals(VALUE_1, property.get(), EPSILON);
 259         property.check(1);
 260         internalInvalidationListener.check(readOnlyProperty, 1);
 261         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 262         publicInvalidationListener.check(readOnlyProperty, 1);
 263     }
 264     
 265     @Test
 266     public void testInternalEagerSetValue() {
 267         attachInternalChangeListener();
 268         
 269         // set value once
 270         property.setValue(VALUE_1);
 271         assertEquals(VALUE_1, property.get(), EPSILON);
 272         property.check(1);
 273         internalChangeListener.check(readOnlyProperty, DEFAULT, VALUE_1, 1);
 274         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 275         
 276         // set same value again
 277         property.setValue(VALUE_1);
 278         assertEquals(VALUE_1, property.get(), EPSILON);
 279         property.check(0);
 280         internalChangeListener.check(null, UNDEFINED, UNDEFINED, 0);
 281         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 282         
 283         // set value twice without reading
 284         property.setValue(VALUE_2);
 285         property.setValue(VALUE_1);
 286         assertEquals(VALUE_1, property.get(), EPSILON);
 287         property.check(2);
 288         internalChangeListener.check(readOnlyProperty, VALUE_2, VALUE_1, 2);
 289         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 290     }
 291     
 292     @Test
 293     public void testPublicEagerSetValue() {
 294         attachPublicChangeListener();
 295         
 296         // set value once
 297         property.setValue(VALUE_1);
 298         assertEquals(VALUE_1, property.get(), EPSILON);
 299         property.check(1);
 300         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 301         publicChangeListener.check(readOnlyProperty, DEFAULT, VALUE_1, 1);
 302         
 303         // set same value again
 304         property.setValue(VALUE_1);
 305         assertEquals(VALUE_1, property.get(), EPSILON);
 306         property.check(0);
 307         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 308         publicChangeListener.check(null, UNDEFINED, UNDEFINED, 0);
 309         
 310         // set value twice without reading
 311         property.setValue(VALUE_2);
 312         property.setValue(VALUE_1);
 313         assertEquals(VALUE_1, property.get(), EPSILON);
 314         property.check(2);
 315         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 316         publicChangeListener.check(readOnlyProperty, VALUE_2, VALUE_1, 2);
 317     }
 318     
 319     @Test(expected=RuntimeException.class)
 320     public void testSetBoundValue() {
 321         final DoubleProperty v = new SimpleDoubleProperty(VALUE_1);
 322         property.bind(v);
 323         property.set(VALUE_1);
 324     }
 325 
 326     @Test
 327     public void testLazyBind_primitive() {
 328         attachInvalidationListeners();
 329         final ObservableDoubleValueStub v = new ObservableDoubleValueStub(VALUE_1);
 330 
 331         property.bind(v);
 332         assertEquals(VALUE_1, property.get(), EPSILON);
 333         assertTrue(property.isBound());
 334         property.check(1);
 335         internalInvalidationListener.check(readOnlyProperty, 1);
 336         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 337         publicInvalidationListener.check(readOnlyProperty, 1);
 338 
 339         // change binding once
 340         v.set(VALUE_2);
 341         assertEquals(VALUE_2, property.get(), EPSILON);
 342         property.check(1);
 343         internalInvalidationListener.check(readOnlyProperty, 1);
 344         assertEquals(VALUE_2, readOnlyProperty.get(), EPSILON);
 345         publicInvalidationListener.check(readOnlyProperty, 1);
 346 
 347         // change binding twice without reading
 348         v.set(VALUE_1);
 349         v.set(VALUE_2);
 350         assertEquals(VALUE_2, property.get(), EPSILON);
 351         property.check(1);
 352         internalInvalidationListener.check(readOnlyProperty, 1);
 353         assertEquals(VALUE_2, readOnlyProperty.get(), EPSILON);
 354         publicInvalidationListener.check(readOnlyProperty, 1);
 355 
 356         // change binding twice to same value
 357         v.set(VALUE_1);
 358         v.set(VALUE_1);
 359         assertEquals(VALUE_1, property.get(), EPSILON);
 360         property.check(1);
 361         internalInvalidationListener.check(readOnlyProperty, 1);
 362         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 363         publicInvalidationListener.check(readOnlyProperty, 1);
 364     }
 365 
 366     @Test
 367     public void testInternalEagerBind_primitive() {
 368         attachInternalChangeListener();
 369         final ObservableDoubleValueStub v = new ObservableDoubleValueStub(VALUE_1);
 370 
 371         property.bind(v);
 372         assertEquals(VALUE_1, property.get(), EPSILON);
 373         assertTrue(property.isBound());
 374         property.check(1);
 375         internalChangeListener.check(readOnlyProperty, DEFAULT, VALUE_1, 1);
 376         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 377 
 378         // change binding once
 379         v.set(VALUE_2);
 380         assertEquals(VALUE_2, property.get(), EPSILON);
 381         property.check(1);
 382         internalChangeListener.check(readOnlyProperty, VALUE_1, VALUE_2, 1);
 383         assertEquals(VALUE_2, readOnlyProperty.get(), EPSILON);
 384 
 385         // change binding twice without reading
 386         v.set(VALUE_1);
 387         v.set(VALUE_2);
 388         assertEquals(VALUE_2, property.get(), EPSILON);
 389         property.check(2);
 390         internalChangeListener.check(readOnlyProperty, VALUE_1, VALUE_2, 2);
 391         assertEquals(VALUE_2, readOnlyProperty.get(), EPSILON);
 392 
 393         // change binding twice to same value
 394         v.set(VALUE_1);
 395         v.set(VALUE_1);
 396         assertEquals(VALUE_1, property.get(), EPSILON);
 397         property.check(2);
 398         internalChangeListener.check(readOnlyProperty, VALUE_2, VALUE_1, 1);
 399         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 400     }
 401     
 402     @Test
 403     public void testPublicEagerBind_primitive() {
 404         attachPublicChangeListener();
 405         final ObservableDoubleValueStub v = new ObservableDoubleValueStub(VALUE_1);
 406 
 407         property.bind(v);
 408         assertEquals(VALUE_1, property.get(), EPSILON);
 409         assertTrue(property.isBound());
 410         property.check(1);
 411         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 412         publicChangeListener.check(readOnlyProperty, DEFAULT, VALUE_1, 1);
 413 
 414         // change binding once
 415         v.set(VALUE_2);
 416         assertEquals(VALUE_2, property.get(), EPSILON);
 417         property.check(1);
 418         assertEquals(VALUE_2, readOnlyProperty.get(), EPSILON);
 419         publicChangeListener.check(readOnlyProperty, VALUE_1, VALUE_2, 1);
 420 
 421         // change binding twice without reading
 422         v.set(VALUE_1);
 423         v.set(VALUE_2);
 424         assertEquals(VALUE_2, property.get(), EPSILON);
 425         property.check(2);
 426         assertEquals(VALUE_2, readOnlyProperty.get(), EPSILON);
 427         publicChangeListener.check(readOnlyProperty, VALUE_1, VALUE_2, 2);
 428 
 429         // change binding twice to same value
 430         v.set(VALUE_1);
 431         v.set(VALUE_1);
 432         assertEquals(VALUE_1, property.get(), EPSILON);
 433         property.check(2);
 434         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 435         publicChangeListener.check(readOnlyProperty, VALUE_2, VALUE_1, 1);
 436     }
 437     
 438     @Test
 439     public void testLazyBind_generic() {
 440         attachInvalidationListeners();
 441         final ObservableObjectValueStub<Double> v = new ObservableObjectValueStub<Double>(VALUE_1);
 442 
 443         property.bind(v);
 444         assertEquals(VALUE_1, property.get(), EPSILON);
 445         assertTrue(property.isBound());
 446         property.check(1);
 447         internalInvalidationListener.check(readOnlyProperty, 1);
 448         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 449         publicInvalidationListener.check(readOnlyProperty, 1);
 450 
 451         // change binding once
 452         v.set(VALUE_2);
 453         assertEquals(VALUE_2, property.get(), EPSILON);
 454         property.check(1);
 455         internalInvalidationListener.check(readOnlyProperty, 1);
 456         assertEquals(VALUE_2, readOnlyProperty.get(), EPSILON);
 457         publicInvalidationListener.check(readOnlyProperty, 1);
 458 
 459         // change binding twice without reading
 460         v.set(VALUE_1);
 461         v.set(VALUE_2);
 462         assertEquals(VALUE_2, property.get(), EPSILON);
 463         property.check(1);
 464         internalInvalidationListener.check(readOnlyProperty, 1);
 465         assertEquals(VALUE_2, readOnlyProperty.get(), EPSILON);
 466         publicInvalidationListener.check(readOnlyProperty, 1);
 467 
 468         // change binding twice to same value
 469         v.set(VALUE_1);
 470         v.set(VALUE_1);
 471         assertEquals(VALUE_1, property.get(), EPSILON);
 472         property.check(1);
 473         internalInvalidationListener.check(readOnlyProperty, 1);
 474         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 475         publicInvalidationListener.check(readOnlyProperty, 1);
 476     }
 477 
 478     @Test
 479     public void testInternalEagerBind_generic() {
 480         attachInternalChangeListener();
 481         final ObservableObjectValueStub<Double> v = new ObservableObjectValueStub<Double>(VALUE_1);
 482 
 483         property.bind(v);
 484         assertEquals(VALUE_1, property.get(), EPSILON);
 485         assertTrue(property.isBound());
 486         property.check(1);
 487         internalChangeListener.check(readOnlyProperty, DEFAULT, VALUE_1, 1);
 488         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 489 
 490         // change binding once
 491         v.set(VALUE_2);
 492         assertEquals(VALUE_2, property.get(), EPSILON);
 493         property.check(1);
 494         internalChangeListener.check(readOnlyProperty, VALUE_1, VALUE_2, 1);
 495         assertEquals(VALUE_2, readOnlyProperty.get(), EPSILON);
 496 
 497         // change binding twice without reading
 498         v.set(VALUE_1);
 499         v.set(VALUE_2);
 500         assertEquals(VALUE_2, property.get(), EPSILON);
 501         property.check(2);
 502         internalChangeListener.check(readOnlyProperty, VALUE_1, VALUE_2, 2);
 503         assertEquals(VALUE_2, readOnlyProperty.get(), EPSILON);
 504 
 505         // change binding twice to same value
 506         v.set(VALUE_1);
 507         v.set(VALUE_1);
 508         assertEquals(VALUE_1, property.get(), EPSILON);
 509         property.check(2);
 510         internalChangeListener.check(readOnlyProperty, VALUE_2, VALUE_1, 1);
 511         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 512     }
 513 
 514     @Test
 515     public void testPublicEagerBind_generic() {
 516         attachPublicChangeListener();
 517         final ObservableObjectValueStub<Double> v = new ObservableObjectValueStub<Double>(VALUE_1);
 518 
 519         property.bind(v);
 520         assertEquals(VALUE_1, property.get(), EPSILON);
 521         assertTrue(property.isBound());
 522         property.check(1);
 523         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 524         publicChangeListener.check(readOnlyProperty, DEFAULT, VALUE_1, 1);
 525 
 526         // change binding once
 527         v.set(VALUE_2);
 528         assertEquals(VALUE_2, property.get(), EPSILON);
 529         property.check(1);
 530         assertEquals(VALUE_2, readOnlyProperty.get(), EPSILON);
 531         publicChangeListener.check(readOnlyProperty, VALUE_1, VALUE_2, 1);
 532 
 533         // change binding twice without reading
 534         v.set(VALUE_1);
 535         v.set(VALUE_2);
 536         assertEquals(VALUE_2, property.get(), EPSILON);
 537         property.check(2);
 538         assertEquals(VALUE_2, readOnlyProperty.get(), EPSILON);
 539         publicChangeListener.check(readOnlyProperty, VALUE_1, VALUE_2, 2);
 540 
 541         // change binding twice to same value
 542         v.set(VALUE_1);
 543         v.set(VALUE_1);
 544         assertEquals(VALUE_1, property.get(), EPSILON);
 545         property.check(2);
 546         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 547         publicChangeListener.check(readOnlyProperty, VALUE_2, VALUE_1, 1);
 548     }
 549     
 550     @Test(expected=NullPointerException.class)
 551     public void testBindToNull() {
 552         property.bind(null);
 553     }
 554 
 555     @Test
 556     public void testRebind() {
 557         attachInvalidationListeners();
 558         final DoubleProperty v1 = new SimpleDoubleProperty(VALUE_1);
 559         final DoubleProperty v2 = new SimpleDoubleProperty(VALUE_2);
 560         property.bind(v1);
 561         property.get();
 562         readOnlyProperty.get();
 563         property.reset();
 564         internalInvalidationListener.reset();
 565         publicInvalidationListener.reset();
 566         
 567         // rebind causes invalidation event
 568         property.bind(v2);
 569         assertEquals(VALUE_2, property.get(), EPSILON);
 570         assertTrue(property.isBound());
 571         property.check(1);
 572         internalInvalidationListener.check(readOnlyProperty, 1);
 573         assertEquals(VALUE_2, readOnlyProperty.get(), EPSILON);
 574         publicInvalidationListener.check(readOnlyProperty, 1);
 575         
 576         // change new binding
 577         v2.set(VALUE_1);
 578         assertEquals(VALUE_1, property.get(), EPSILON);
 579         property.check(1);
 580         internalInvalidationListener.check(readOnlyProperty, 1);
 581         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 582         publicInvalidationListener.check(readOnlyProperty, 1);
 583         
 584         // change old binding
 585         v1.set(VALUE_2);
 586         assertEquals(VALUE_1, property.get(), EPSILON);
 587         property.check(0);
 588         internalInvalidationListener.check(null, 0);
 589         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 590         publicInvalidationListener.check(null, 0);
 591         
 592         // rebind to same observable should have no effect
 593         property.bind(v2);
 594         assertEquals(VALUE_1, property.get(), EPSILON);
 595         assertTrue(property.isBound());
 596         property.check(0);
 597         internalInvalidationListener.check(null, 0);
 598         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 599         publicInvalidationListener.check(null, 0);
 600     }
 601 
 602     @Test
 603     public void testUnbind() {
 604         attachInvalidationListeners();
 605         final DoubleProperty v = new SimpleDoubleProperty(VALUE_1);
 606         property.bind(v);
 607         property.unbind();
 608         assertEquals(VALUE_1, property.get(), EPSILON);
 609         assertFalse(property.isBound());
 610         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 611         property.reset();
 612         internalInvalidationListener.reset();
 613         publicInvalidationListener.reset();
 614         
 615         // change binding
 616         v.set(VALUE_2);
 617         assertEquals(VALUE_1, property.get(), EPSILON);
 618         property.check(0);
 619         internalInvalidationListener.check(null, 0);
 620         assertEquals(VALUE_1, readOnlyProperty.get(), EPSILON);
 621         publicInvalidationListener.check(null, 0);
 622         
 623         // set value
 624         property.set(VALUE_2);
 625         assertEquals(VALUE_2, property.get(), EPSILON);
 626         property.check(1);
 627         internalInvalidationListener.check(readOnlyProperty, 1);
 628         assertEquals(VALUE_2, readOnlyProperty.get(), EPSILON);
 629         publicInvalidationListener.check(readOnlyProperty, 1);
 630     }
 631     
 632     @Test
 633     public void testAddingListenerWillAlwaysReceiveInvalidationEvent() {
 634         final DoubleProperty v = new SimpleDoubleProperty(VALUE_1);
 635         final InvalidationListenerMock internalListener2 = new InvalidationListenerMock();
 636         final InvalidationListenerMock internalListener3 = new InvalidationListenerMock();
 637         final InvalidationListenerMock publicListener2 = new InvalidationListenerMock();
 638         final InvalidationListenerMock publicListener3 = new InvalidationListenerMock();
 639 
 640         // setting the property,checking internal
 641         property.set(VALUE_1);
 642         property.addListener(internalListener2);
 643         internalListener2.reset();
 644         property.set(VALUE_2);
 645         internalListener2.check(readOnlyProperty, 1);
 646         
 647         // setting the property, checking public
 648         property.set(VALUE_1);
 649         readOnlyProperty.addListener(publicListener2);
 650         publicListener2.reset();
 651         property.set(VALUE_2);
 652         publicListener2.check(readOnlyProperty, 1);
 653         
 654         // binding the property, checking internal
 655         property.bind(v);
 656         v.set(VALUE_2);
 657         property.addListener(internalListener3);
 658         v.get();
 659         internalListener3.reset();
 660         v.set(VALUE_1);
 661         internalListener3.check(readOnlyProperty, 1);
 662         
 663         // binding the property, checking public
 664         property.bind(v);
 665         v.set(VALUE_2);
 666         readOnlyProperty.addListener(publicListener3);
 667         v.get();
 668         publicListener3.reset();
 669         v.set(VALUE_1);
 670         publicListener3.check(readOnlyProperty, 1);
 671     }
 672     
 673     @Test
 674     public void testRemoveListeners() {
 675         attachInvalidationListeners();
 676         attachInternalChangeListener();
 677         property.removeListener(internalInvalidationListener);
 678         property.removeListener(internalChangeListener);
 679         property.get();
 680         internalInvalidationListener.reset();
 681         internalChangeListener.reset();
 682         
 683         property.set(VALUE_1);
 684         internalInvalidationListener.check(null, 0);
 685         internalChangeListener.check(null, UNDEFINED, UNDEFINED, 0);
 686         
 687         // no read only property created => no-op
 688         final ReadOnlyDoubleWrapper v1 = new ReadOnlyDoubleWrapper();
 689         v1.removeListener(internalInvalidationListener);
 690         v1.removeListener(internalChangeListener);
 691     }
 692     
 693     @Test
 694     public void testNoReadOnlyPropertyCreated() {
 695         final DoubleProperty v1 = new SimpleDoubleProperty(VALUE_1);
 696         final ReadOnlyDoubleWrapper p1 = new ReadOnlyDoubleWrapper();
 697         
 698         p1.set(VALUE_1);
 699         p1.bind(v1);
 700         assertEquals(VALUE_1, p1.get(), EPSILON);
 701         v1.set(VALUE_2);
 702         assertEquals(VALUE_2, p1.get(), EPSILON);
 703     }
 704     
 705     @Test
 706     public void testToString() {
 707         final DoubleProperty v1 = new SimpleDoubleProperty(VALUE_1);
 708         
 709         property.set(VALUE_1);
 710         assertEquals("DoubleProperty [value: " + VALUE_1 + "]", property.toString());
 711         assertEquals("ReadOnlyDoubleProperty [value: " + VALUE_1 + "]", readOnlyProperty.toString());
 712         
 713         property.bind(v1);
 714         assertEquals("DoubleProperty [bound, invalid]", property.toString());
 715         assertEquals("ReadOnlyDoubleProperty [value: " + VALUE_1 + "]", readOnlyProperty.toString());
 716         property.get();
 717         assertEquals("DoubleProperty [bound, value: " + VALUE_1 + "]", property.toString());
 718         assertEquals("ReadOnlyDoubleProperty [value: " + VALUE_1 + "]", readOnlyProperty.toString());
 719         v1.set(VALUE_2);
 720         assertEquals("DoubleProperty [bound, invalid]", property.toString());
 721         assertEquals("ReadOnlyDoubleProperty [value: " + VALUE_2 + "]", readOnlyProperty.toString());
 722         property.get();
 723         assertEquals("DoubleProperty [bound, value: " + VALUE_2 + "]", property.toString());
 724         assertEquals("ReadOnlyDoubleProperty [value: " + VALUE_2 + "]", readOnlyProperty.toString());
 725         
 726         final Object bean = new Object();
 727         final String name = "My name";
 728         final ReadOnlyDoubleWrapper v2 = new ReadOnlyDoubleWrapper(bean, name);
 729         assertEquals("DoubleProperty [bean: " + bean.toString() + ", name: My name, value: " + DEFAULT + "]", v2.toString());
 730         assertEquals("ReadOnlyDoubleProperty [bean: " + bean.toString() + ", name: My name, value: " + DEFAULT + "]", v2.getReadOnlyProperty().toString());
 731         
 732         final ReadOnlyDoubleWrapper v3 = new ReadOnlyDoubleWrapper(bean, "");
 733         assertEquals("DoubleProperty [bean: " + bean.toString() + ", value: " + DEFAULT + "]", v3.toString());
 734         assertEquals("ReadOnlyDoubleProperty [bean: " + bean.toString() + ", value: " + DEFAULT + "]", v3.getReadOnlyProperty().toString());
 735 
 736         final ReadOnlyDoubleWrapper v4 = new ReadOnlyDoubleWrapper(null, name);
 737         assertEquals("DoubleProperty [name: My name, value: " + DEFAULT + "]", v4.toString());
 738         assertEquals("ReadOnlyDoubleProperty [name: My name, value: " + DEFAULT + "]", v4.getReadOnlyProperty().toString());
 739     }
 740     
 741     private static class ReadOnlyDoubleWrapperMock extends ReadOnlyDoubleWrapper {
 742         
 743         private int counter;
 744         
 745         @Override
 746         protected void invalidated() {
 747             counter++;
 748         }
 749         
 750         private void check(int expected) {
 751             assertEquals(expected, counter);
 752             reset();
 753         }
 754         
 755         private void reset() {
 756             counter = 0;
 757         }
 758     }
 759 }