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