1 /*
   2  * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package test.javafx.beans.property;
  27 
  28 import javafx.beans.property.FloatProperty;
  29 import javafx.beans.property.FloatPropertyBase;
  30 import javafx.beans.property.SimpleFloatProperty;
  31 import static org.junit.Assert.assertEquals;
  32 import static org.junit.Assert.assertFalse;
  33 import static org.junit.Assert.assertTrue;
  34 
  35 import test.javafx.beans.InvalidationListenerMock;
  36 import test.javafx.beans.value.ChangeListenerMock;
  37 import javafx.beans.value.ObservableFloatValueStub;
  38 import javafx.beans.value.ObservableValueStub;
  39 
  40 import org.junit.Before;
  41 import org.junit.Test;
  42 
  43 public class FloatPropertyBaseTest {
  44 
  45     private static final Object NO_BEAN = null;
  46     private static final String NO_NAME_1 = null;
  47     private static final String NO_NAME_2 = "";
  48     private static final Float UNDEFINED = Float.MAX_VALUE;
  49         private static final float EPSILON = 1e-6f;
  50         private static final float PI = (float)Math.PI;
  51         private static final float E = (float)Math.E;
  52         
  53         private FloatPropertyMock property;
  54         private InvalidationListenerMock invalidationListener;
  55         private ChangeListenerMock<Number> changeListener;
  56 
  57         @Before
  58         public void setUp() throws Exception {
  59                 property = new FloatPropertyMock();
  60                 invalidationListener = new InvalidationListenerMock();
  61         changeListener = new ChangeListenerMock<Number>(UNDEFINED);
  62         }
  63 
  64         private void attachInvalidationListener() {
  65                 property.addListener(invalidationListener);
  66                 property.get();
  67                 invalidationListener.reset();
  68         }
  69 
  70         private void attachChangeListener() {
  71                 property.addListener(changeListener);
  72                 property.get();
  73                 changeListener.reset();
  74         }
  75 
  76         @Test
  77         public void testConstructor() {
  78                 final FloatProperty p1 = new SimpleFloatProperty();
  79                 assertEquals(0.0f, p1.get(), EPSILON);
  80                 assertEquals(Float.valueOf(0.0f), p1.getValue(), EPSILON);
  81                 assertFalse(property.isBound());
  82                 
  83                 final FloatProperty p2 = new SimpleFloatProperty(-PI);
  84                 assertEquals(-PI, p2.get(), EPSILON);
  85                 assertEquals(Float.valueOf(-PI), p2.getValue(), EPSILON);
  86                 assertFalse(property.isBound());
  87         }
  88 
  89     @Test
  90     public void testInvalidationListener() {
  91         attachInvalidationListener();
  92         property.set(E);
  93         invalidationListener.check(property, 1);
  94         property.removeListener(invalidationListener);
  95         invalidationListener.reset();
  96         property.set(PI);
  97         invalidationListener.check(null, 0);
  98     }
  99 
 100     @Test
 101     public void testChangeListener() {
 102         attachChangeListener();
 103         property.set(E);
 104         changeListener.check(property, 0.0f, E, 1);
 105         property.removeListener(changeListener);
 106         changeListener.reset();
 107         property.set(PI);
 108         changeListener.check(null, UNDEFINED, UNDEFINED, 0);
 109     }
 110 
 111         @Test
 112         public void testLazySet() {
 113                 attachInvalidationListener();
 114 
 115                 // set value once
 116                 property.set(E);
 117                 assertEquals(E, property.get(), EPSILON);
 118                 property.check(1);
 119                 invalidationListener.check(property, 1);
 120 
 121                 // set same value again
 122                 property.set(E);
 123                 assertEquals(E, property.get(), EPSILON);
 124                 property.check(0);
 125                 invalidationListener.check(null, 0);
 126 
 127                 // set value twice without reading
 128                 property.set(PI);
 129                 property.set(-PI);
 130                 assertEquals(-PI, property.get(), EPSILON);
 131                 property.check(1);
 132                 invalidationListener.check(property, 1);
 133         }
 134 
 135         @Test
 136         public void testEagerSet() {
 137                 attachChangeListener();
 138 
 139                 // set value once
 140                 property.set(E);
 141                 assertEquals(E, property.get(), EPSILON);
 142                 property.check(1);
 143                 changeListener.check(property, 0.0f, E, 1);
 144 
 145                 // set same value again
 146                 property.set(E);
 147                 assertEquals(E, property.get(), EPSILON);
 148                 property.check(0);
 149                 changeListener.check(null, UNDEFINED, UNDEFINED, 0);
 150 
 151                 // set value twice without reading
 152                 property.set(PI);
 153                 property.set(-PI);
 154                 assertEquals(-PI, property.get(), EPSILON);
 155                 property.check(2);
 156                 changeListener.check(property, PI, -PI, 2);
 157         }
 158 
 159         @Test
 160         public void testLazySetValue() {
 161                 attachInvalidationListener();
 162 
 163                 // set value once
 164                 property.setValue(E);
 165                 assertEquals(E, property.get(), EPSILON);
 166                 property.check(1);
 167                 invalidationListener.check(property, 1);
 168 
 169                 // set same value again
 170                 property.setValue(E);
 171                 assertEquals(E, property.get(), EPSILON);
 172                 property.check(0);
 173                 invalidationListener.check(null, 0);
 174 
 175                 // set value twice without reading
 176                 property.setValue(PI);
 177                 property.setValue(-PI);
 178                 assertEquals(-PI, property.get(), EPSILON);
 179                 property.check(1);
 180                 invalidationListener.check(property, 1);
 181         }
 182 
 183         @Test
 184         public void testEagerSetValue() {
 185                 attachChangeListener();
 186 
 187                 // set value once
 188                 property.setValue(E);
 189                 assertEquals(E, property.get(), EPSILON);
 190                 property.check(1);
 191                 changeListener.check(property, 0.0f, E, 1);
 192 
 193                 // set same value again
 194                 property.setValue(E);
 195                 assertEquals(E, property.get(), EPSILON);
 196                 property.check(0);
 197                 changeListener.check(null, UNDEFINED, UNDEFINED, 0);
 198 
 199                 // set value twice without reading
 200                 property.setValue(PI);
 201                 property.setValue(-PI);
 202                 assertEquals(-PI, property.get(), EPSILON);
 203                 property.check(2);
 204                 changeListener.check(property, PI, -PI, 2);
 205         }
 206 
 207         @Test(expected=RuntimeException.class)
 208         public void testSetBoundValue() {
 209                 final FloatProperty v = new SimpleFloatProperty(PI);
 210                 property.bind(v);
 211                 property.set(PI);
 212         }
 213 
 214         @Test
 215         public void testLazyBind() {
 216                 attachInvalidationListener();
 217                 final FloatProperty v = new SimpleFloatProperty(PI);
 218         property.reset();
 219 
 220                 property.bind(v);
 221                 assertEquals(PI, property.get(), EPSILON);
 222                 assertTrue(property.isBound());
 223                 property.check(1);
 224                 invalidationListener.check(property, 1);
 225 
 226                 // change binding once
 227                 v.set(E);
 228                 assertEquals(E, property.get(), EPSILON);
 229                 property.check(1);
 230                 invalidationListener.check(property, 1);
 231 
 232                 // change binding twice without reading
 233                 v.set(PI);
 234                 v.set(-PI);
 235                 assertEquals(-PI, property.get(), EPSILON);
 236                 property.check(1);
 237                 invalidationListener.check(property, 1);
 238 
 239                 // change binding twice to same value
 240                 v.set(PI);
 241                 v.set(PI);
 242                 assertEquals(PI, property.get(), EPSILON);
 243                 property.check(1);
 244                 invalidationListener.check(property, 1);
 245         }
 246 
 247         @Test
 248         public void testEagerBind() {
 249                 attachChangeListener();
 250                 final ObservableFloatValueStub v = new ObservableFloatValueStub(PI);
 251         property.reset();
 252 
 253                 property.bind(v);
 254                 assertEquals(PI, property.get(), EPSILON);
 255                 assertTrue(property.isBound());
 256                 property.check(1);
 257                 changeListener.check(property, 0.0f, PI, 1);
 258 
 259                 // change binding once
 260                 v.set(E);
 261                 assertEquals(E, property.get(), EPSILON);
 262                 property.check(1);
 263                 changeListener.check(property, PI, E, 1);
 264 
 265                 // change binding twice without reading
 266                 v.set(PI);
 267                 v.set(-PI);
 268                 assertEquals(-PI, property.get(), EPSILON);
 269                 property.check(2);
 270                 changeListener.check(property, PI, -PI, 2);
 271 
 272                 // change binding twice to same value
 273                 v.set(PI);
 274                 v.set(PI);
 275                 assertEquals(PI, property.get(), EPSILON);
 276                 property.check(2);
 277                 changeListener.check(property, -PI, PI, 1);
 278         }
 279 
 280     @Test
 281     public void testLazyBindObservableValue() {
 282         final float value1 = (float)Math.PI;
 283         final float value2 = (float)Math.E;
 284         attachInvalidationListener();
 285         final ObservableValueStub<Number> v = new ObservableValueStub<Number>(value1);
 286 
 287         property.bind(v);
 288         assertEquals(value1, property.get(), EPSILON);
 289         assertTrue(property.isBound());
 290         property.check(1);
 291         invalidationListener.check(property, 1);
 292 
 293         // change binding once
 294         v.set(value2);
 295         assertEquals(value2, property.get(), EPSILON);
 296         property.check(1);
 297         invalidationListener.check(property, 1);
 298 
 299         // change binding twice without reading
 300         v.set(value1);
 301         v.set(value2);
 302         assertEquals(value2, property.get(), EPSILON);
 303         property.check(1);
 304         invalidationListener.check(property, 1);
 305 
 306         // change binding twice to same value
 307         v.set(value1);
 308         v.set(value1);
 309         assertEquals(value1, property.get(), EPSILON);
 310         property.check(1);
 311         invalidationListener.check(property, 1);
 312 
 313         // set binding to null
 314         v.set(null);
 315         assertEquals(0.0f, property.get(), EPSILON);
 316         property.check(1);
 317         invalidationListener.check(property, 1);
 318     }
 319 
 320     @Test
 321     public void testEagerBindObservableValue() {
 322         final float value1 = (float)Math.PI;
 323         final float value2 = (float)Math.E;
 324         attachChangeListener();
 325         final ObservableValueStub<Number> v = new ObservableValueStub<Number>(value1);
 326 
 327         property.bind(v);
 328         assertEquals(value1, property.get(), EPSILON);
 329         assertTrue(property.isBound());
 330         property.check(1);
 331         changeListener.check(property, 0.0f, value1, 1);
 332 
 333         // change binding once
 334         v.set(value2);
 335         assertEquals(value2, property.get(), EPSILON);
 336         property.check(1);
 337         changeListener.check(property, value1, value2, 1);
 338 
 339         // change binding twice without reading
 340         v.set(value1);
 341         v.set(value2);
 342         assertEquals(value2, property.get(), EPSILON);
 343         property.check(2);
 344         changeListener.check(property, value1, value2, 2);
 345 
 346         // change binding twice to same value
 347         v.set(value1);
 348         v.set(value1);
 349         assertEquals(value1, property.get(), EPSILON);
 350         property.check(2);
 351         changeListener.check(property, value2, value1, 1);
 352 
 353         // set binding to null
 354         v.set(null);
 355         assertEquals(0.0f, property.get(), EPSILON);
 356         property.check(1);
 357         changeListener.check(property, value1, 0.0f, 1);
 358     }
 359 
 360         @Test(expected=NullPointerException.class)
 361         public void testBindToNull() {
 362                 property.bind(null);
 363         }
 364 
 365         @Test
 366         public void testRebind() {
 367                 attachInvalidationListener();
 368                 final FloatProperty v1 = new SimpleFloatProperty(PI);
 369                 final FloatProperty v2 = new SimpleFloatProperty(E);
 370                 property.bind(v1);
 371                 property.get();
 372                 property.reset();
 373                 invalidationListener.reset();
 374                 
 375                 // rebind causes invalidation event
 376                 property.bind(v2);
 377                 assertEquals(E, property.get(), EPSILON);
 378                 assertTrue(property.isBound());
 379                 assertEquals(1, property.counter);
 380                 invalidationListener.check(property, 1);
 381                 property.reset();
 382                 
 383                 // change old binding
 384                 v1.set(-PI);
 385                 assertEquals(E, property.get(), EPSILON);
 386                 assertEquals(0, property.counter);
 387                 invalidationListener.check(null, 0);
 388                 property.reset();
 389                 
 390                 // change new binding
 391                 v2.set(-E);
 392                 assertEquals(-E, property.get(), EPSILON);
 393                 assertEquals(1, property.counter);
 394                 invalidationListener.check(property, 1);
 395                 property.reset();
 396                 
 397                 // rebind to same observable should have no effect
 398                 property.bind(v2);
 399                 assertEquals(-E, property.get(), EPSILON);
 400                 assertTrue(property.isBound());
 401                 assertEquals(0, property.counter);
 402                 invalidationListener.check(null, 0);
 403         }
 404 
 405         @Test
 406         public void testUnbind() {
 407                 attachInvalidationListener();
 408                 final FloatProperty v = new SimpleFloatProperty(PI);
 409                 property.bind(v);
 410                 property.unbind();
 411                 assertEquals(PI, property.get(), EPSILON);
 412                 assertFalse(property.isBound());
 413         property.reset();
 414         invalidationListener.reset();
 415                 
 416                 // change binding
 417                 v.set(E);
 418                 assertEquals(PI, property.get(), EPSILON);
 419                 assertEquals(0, property.counter);
 420                 invalidationListener.check(null, 0);
 421                 property.reset();
 422                 
 423                 // set value
 424                 property.set(-PI);
 425                 assertEquals(-PI, property.get(), EPSILON);
 426                 assertEquals(1, property.counter);
 427                 invalidationListener.check(property, 1);
 428         }
 429         
 430     @Test
 431     public void testUnbindObservableValue() {
 432         final float value1 = (float)Math.PI;
 433         final float value2 = (float)Math.E;
 434         
 435         attachInvalidationListener();
 436         final ObservableValueStub<Number> v = new ObservableValueStub<Number>(value1);
 437         property.bind(v);
 438         property.unbind();
 439         assertEquals(value1, property.get(), EPSILON);
 440         assertFalse(property.isBound());
 441         property.reset();
 442         invalidationListener.reset();
 443         
 444         // change binding
 445         v.set(value2);
 446         assertEquals(value1, property.get(), EPSILON);
 447         assertEquals(0, property.counter);
 448         invalidationListener.check(null, 0);
 449         property.reset();
 450         
 451         // set value
 452         property.set(value2);
 453         assertEquals(value2, property.get(), EPSILON);
 454         assertEquals(1, property.counter);
 455         invalidationListener.check(property, 1);
 456     }
 457     
 458         @Test
 459         public void testAddingListenerWillAlwaysReceiveInvalidationEvent() {
 460                 final FloatProperty v = new SimpleFloatProperty(PI);
 461                 final InvalidationListenerMock listener2 = new InvalidationListenerMock();
 462                 final InvalidationListenerMock listener3 = new InvalidationListenerMock();
 463 
 464                 // setting the property
 465                 property.set(PI);
 466                 property.addListener(listener2);
 467                 listener2.reset();
 468                 property.set(-PI);
 469                 listener2.check(property, 1);
 470                 
 471                 // binding the property
 472                 property.bind(v);
 473                 v.set(E);
 474                 property.addListener(listener3);
 475                 v.get();
 476                 listener3.reset();
 477                 v.set(-E);
 478                 listener3.check(property, 1);
 479         }
 480         
 481         @Test
 482         public void testToString() {
 483                 final float value1 = (float)Math.E;
 484                 final float value2 = (float)-Math.PI;
 485                 final FloatProperty v = new SimpleFloatProperty(value2);
 486                 
 487                 property.set(value1);
 488                 assertEquals("FloatProperty [value: " + value1 + "]", property.toString());
 489                 
 490                 property.bind(v);
 491                 assertEquals("FloatProperty [bound, invalid]", property.toString());
 492                 property.get();
 493                 assertEquals("FloatProperty [bound, value: " + value2 + "]", property.toString());
 494                 v.set(value1);
 495                 assertEquals("FloatProperty [bound, invalid]", property.toString());
 496                 property.get();
 497                 assertEquals("FloatProperty [bound, value: " + value1 + "]", property.toString());
 498         
 499         final Object bean = new Object();
 500         final String name = "My name";
 501         final FloatProperty v1 = new FloatPropertyMock(bean, name);
 502         assertEquals("FloatProperty [bean: " + bean.toString() + ", name: My name, value: " + 0.0f + "]", v1.toString());
 503         v1.set(value1);
 504         assertEquals("FloatProperty [bean: " + bean.toString() + ", name: My name, value: " + value1 + "]", v1.toString());
 505         
 506         final FloatProperty v2 = new FloatPropertyMock(bean, NO_NAME_1);
 507         assertEquals("FloatProperty [bean: " + bean.toString() + ", value: " + 0.0f + "]", v2.toString());
 508         v2.set(value1);
 509         assertEquals("FloatProperty [bean: " + bean.toString() + ", value: " + value1 + "]", v2.toString());
 510 
 511         final FloatProperty v3 = new FloatPropertyMock(bean, NO_NAME_2);
 512         assertEquals("FloatProperty [bean: " + bean.toString() + ", value: " + 0.0f + "]", v3.toString());
 513         v3.set(value1);
 514         assertEquals("FloatProperty [bean: " + bean.toString() + ", value: " + value1 + "]", v3.toString());
 515 
 516         final FloatProperty v4 = new FloatPropertyMock(NO_BEAN, name);
 517         assertEquals("FloatProperty [name: My name, value: " + 0.0f + "]", v4.toString());
 518         v4.set(value1);
 519         assertEquals("FloatProperty [name: My name, value: " + value1 + "]", v4.toString());
 520         }
 521         
 522         private static class FloatPropertyMock extends FloatPropertyBase {
 523         
 524         private final Object bean;
 525         private final String name;
 526                 private int counter;
 527                 
 528         private FloatPropertyMock() {
 529             this.bean = NO_BEAN;
 530             this.name = NO_NAME_1;
 531         }
 532         
 533         private FloatPropertyMock(Object bean, String name) {
 534             this.bean = bean;
 535             this.name = name;
 536         }
 537         
 538                 @Override
 539                 protected void invalidated() {
 540                         counter++;
 541                 }
 542                 
 543                 private void check(int expected) {
 544                         assertEquals(expected, counter);
 545                         reset();
 546                 }
 547 
 548                 private void reset() {
 549                         counter = 0;
 550                 }
 551 
 552         @Override public Object getBean() { return bean; }
 553 
 554         @Override public String getName() { return name; }
 555         }
 556 
 557 }