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