1 /*
   2  * Copyright (c) 2010, 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.binding;
  27 
  28 import static org.junit.Assert.*;
  29 import javafx.beans.InvalidationListener;
  30 import test.javafx.beans.InvalidationListenerMock;
  31 import javafx.beans.binding.Bindings;
  32 import javafx.beans.binding.BooleanBinding;
  33 import javafx.beans.property.BooleanProperty;
  34 import javafx.beans.property.SimpleBooleanProperty;
  35 import javafx.beans.value.ChangeListener;
  36 import javafx.beans.value.ObservableBooleanValue;
  37 
  38 import org.junit.Before;
  39 import org.junit.Test;
  40 
  41 public class BindingsBooleanTest {
  42 
  43     private BooleanProperty op1;
  44     private BooleanProperty op2;
  45     private InvalidationListenerMock observer;
  46 
  47     @Before
  48     public void setUp() {
  49         op1 = new SimpleBooleanProperty(true);
  50         op2 = new SimpleBooleanProperty(false);
  51         observer = new InvalidationListenerMock();
  52     }
  53 
  54     @SuppressWarnings("unused")
  55         @Test
  56     public void testAnd() {
  57         final BooleanBinding binding = Bindings.and(op1, op2);
  58         binding.addListener(observer);
  59 
  60         // check initial value
  61         assertEquals(true && false, binding.get());
  62         DependencyUtils.checkDependencies(binding.getDependencies(), op1, op2);
  63 
  64         // change first operand
  65         observer.reset();
  66         op1.set(false);
  67         assertEquals(false && false, binding.get());
  68         observer.check(binding, 1);
  69 
  70         // change second operand
  71         op1.set(true); // avoid short-circuit invalidation
  72         binding.get();
  73         observer.reset();
  74         op2.set(true);
  75         assertEquals(true && true, binding.get());
  76         observer.check(binding, 1);
  77 
  78         // last possibility
  79         op1.set(false);
  80         assertEquals(false && true, binding.get());
  81         observer.check(binding, 1);
  82     }
  83 
  84     @Test
  85     public void testAnd_Efficiency() {
  86         final BooleanBinding binding = Bindings.and(op1, op2);
  87         binding.addListener(observer);
  88         binding.get();
  89 
  90         // change both values
  91         op1.set(false);
  92         op2.set(true);
  93         observer.check(binding, 1);
  94 
  95         // check short circuit invalidation
  96         op2.set(false);
  97         observer.check(null, 0);
  98     }
  99 
 100     @SuppressWarnings("unused")
 101         @Test
 102     public void testAnd_Self() {
 103         final BooleanBinding binding = Bindings.and(op1, op1);
 104         binding.addListener(observer);
 105 
 106         // check initial value
 107         assertEquals(true && true, binding.get());
 108         DependencyUtils.checkDependencies(binding.getDependencies(), op1);
 109 
 110         // change value
 111         observer.reset();
 112         op1.set(false);
 113         assertEquals(false && false, binding.get());
 114         observer.check(binding, 1);
 115 
 116         // change value again
 117         op1.set(true);
 118         assertEquals(true && true, binding.get());
 119         observer.check(binding, 1);
 120     }
 121     
 122     @Test
 123     public void testAnd_WeakReference() {
 124         final ObservableBooleanValueMock op1 = new ObservableBooleanValueMock();
 125         final ObservableBooleanValueMock op2 = new ObservableBooleanValueMock();
 126         BooleanBinding binding = Bindings.and(op1, op2);
 127         assertNotNull(op1.listener);
 128         assertNotNull(op2.listener);
 129         binding = null;
 130         System.gc();
 131         op1.fireInvalidationEvent();
 132         assertNull(op1.listener);
 133         assertNotNull(op2.listener);
 134         op2.fireInvalidationEvent();
 135         assertNull(op1.listener);
 136         assertNull(op2.listener);
 137     }
 138 
 139     @Test(expected=NullPointerException.class)
 140     public void testAnd_null_x() {
 141         Bindings.and(null, op1);
 142     }
 143 
 144     @Test(expected=NullPointerException.class)
 145     public void testAnd_x_null() {
 146         Bindings.and(op1, null);
 147     }
 148 
 149     @SuppressWarnings("unused")
 150         @Test
 151     public void testOr() {
 152         final BooleanBinding binding = Bindings.or(op1, op2);
 153         binding.addListener(observer);
 154 
 155         // check initial value
 156         assertEquals(true || false, binding.get());
 157         DependencyUtils.checkDependencies(binding.getDependencies(), op1, op2);
 158 
 159         // change first operand
 160         observer.reset();
 161         op1.set(false);
 162         assertEquals(false || false, binding.get());
 163         observer.check(binding, 1);
 164 
 165         // change second operand
 166         op2.set(true);
 167         assertEquals(false || true, binding.get());
 168         observer.check(binding, 1);
 169 
 170         // last possibility
 171         op1.set(true);
 172         assertEquals(true || true, binding.get());
 173         observer.check(binding, 1);
 174     }
 175 
 176     @Test
 177     public void testOr_Efficiency() {
 178         final BooleanBinding binding = Bindings.or(op1, op2);
 179         binding.addListener(observer);
 180         binding.get();
 181 
 182         // change both values
 183         op1.set(false);
 184         op2.set(true);
 185         observer.check(binding, 1);
 186 
 187         // check short circuit invalidation
 188         op1.set(true); // force short-circuit invalidation
 189         binding.get();
 190         observer.reset();
 191         op2.set(false);
 192         observer.check(null, 0);
 193     }
 194 
 195     @SuppressWarnings("unused")
 196         @Test
 197     public void testOr_Self() {
 198         final BooleanBinding binding = Bindings.or(op1, op1);
 199         binding.addListener(observer);
 200 
 201         // check initial value
 202         assertEquals(true || true, binding.get());
 203         DependencyUtils.checkDependencies(binding.getDependencies(), op1);
 204 
 205         // change value
 206         observer.reset();
 207         op1.set(false);
 208         assertEquals(false || false, binding.get());
 209         observer.check(binding, 1);
 210 
 211         // change value again
 212         op1.set(true);
 213         assertEquals(true || true, binding.get());
 214         observer.check(binding, 1);
 215     }
 216 
 217     @Test
 218     public void testOr_WeakReference() {
 219         final ObservableBooleanValueMock op1 = new ObservableBooleanValueMock();
 220         final ObservableBooleanValueMock op2 = new ObservableBooleanValueMock();
 221         BooleanBinding binding = Bindings.or(op1, op2);
 222         assertNotNull(op1.listener);
 223         assertNotNull(op2.listener);
 224         binding = null;
 225         System.gc();
 226         op1.fireInvalidationEvent();
 227         assertNull(op1.listener);
 228         assertNotNull(op2.listener);
 229         op2.fireInvalidationEvent();
 230         assertNull(op1.listener);
 231         assertNull(op2.listener);
 232     }
 233 
 234     @Test(expected=NullPointerException.class)
 235     public void testOr_null_x() {
 236         Bindings.or(null, op1);
 237     }
 238 
 239     @Test(expected=NullPointerException.class)
 240     public void testOr_x_null() {
 241         Bindings.or(op1, null);
 242     }
 243 
 244     @Test
 245     public void testNot() {
 246         final BooleanBinding binding = Bindings.not(op1);
 247         binding.addListener(observer);
 248 
 249         // check initial value
 250         assertEquals(!true, binding.get());
 251         DependencyUtils.checkDependencies(binding.getDependencies(), op1);
 252 
 253         // change first operand
 254         observer.reset();
 255         op1.set(false);
 256         assertEquals(!false, binding.get());
 257         observer.check(binding, 1);
 258 
 259         // change again
 260         op1.set(true);
 261         assertEquals(!true, binding.get());
 262         observer.check(binding, 1);
 263     }
 264 
 265     @Test
 266     public void testNot_Efficiency() {
 267         final BooleanBinding binding = Bindings.not(op1);
 268         binding.addListener(observer);
 269         binding.get();
 270 
 271         // change value twice
 272         op1.set(false);
 273         op1.set(true);
 274         observer.check(binding, 1);
 275     }
 276 
 277     @Test(expected=NullPointerException.class)
 278     public void testNot_null() {
 279         Bindings.not(null);
 280     }
 281 
 282     @Test
 283     public void testEqual() {
 284         final BooleanBinding binding = Bindings.equal(op1, op2);
 285         binding.addListener(observer);
 286 
 287         // check initial value
 288         assertEquals(true == false, binding.get());
 289         DependencyUtils.checkDependencies(binding.getDependencies(), op1, op2);
 290 
 291         // change first operand
 292         observer.reset();
 293         op1.set(false);
 294         assertEquals(false == false, binding.get());
 295         observer.check(binding, 1);
 296 
 297         // change second operand
 298         op2.set(true);
 299         assertEquals(false == true, binding.get());
 300         observer.check(binding, 1);
 301 
 302         // last possibility
 303         op1.set(true);
 304         assertEquals(true == true, binding.get());
 305         observer.check(binding, 1);
 306     }
 307 
 308     @Test
 309     public void testEqual_Efficiency() {
 310         final BooleanBinding binding = Bindings.equal(op1, op2);
 311         binding.addListener(observer);
 312         binding.get();
 313 
 314         // change both values
 315         op1.set(false);
 316         op2.set(true);
 317         observer.check(binding, 1);
 318     }
 319 
 320     @Test
 321     public void testEqual_Self() {
 322         final BooleanBinding binding = Bindings.equal(op1, op1);
 323         binding.addListener(observer);
 324 
 325         // check initial value
 326         assertEquals(true == true, binding.get());
 327         DependencyUtils.checkDependencies(binding.getDependencies(), op1);
 328 
 329         // change value
 330         observer.reset();
 331         op1.set(false);
 332         assertEquals(false == false, binding.get());
 333         observer.check(binding, 1);
 334 
 335         // change value again
 336         op1.set(true);
 337         assertEquals(true == true, binding.get());
 338         observer.check(binding, 1);
 339     }
 340 
 341     @Test(expected=NullPointerException.class)
 342     public void testEqual_null_x() {
 343         Bindings.equal((ObservableBooleanValue)null, op1);
 344     }
 345 
 346     @Test(expected=NullPointerException.class)
 347     public void testEqual_x_null() {
 348         Bindings.equal(op1, (ObservableBooleanValue)null);
 349     }
 350 
 351     @Test
 352     public void testNotEqual() {
 353         final BooleanBinding binding = Bindings.notEqual(op1, op2);
 354         binding.addListener(observer);
 355 
 356         // check initial value
 357         assertEquals(true != false, binding.get());
 358         DependencyUtils.checkDependencies(binding.getDependencies(), op1, op2);
 359 
 360         // change first operand
 361         observer.reset();
 362         op1.set(false);
 363         assertEquals(false != false, binding.get());
 364         observer.check(binding, 1);
 365 
 366         // change second operand
 367         op2.set(true);
 368         assertEquals(false != true, binding.get());
 369         observer.check(binding, 1);
 370 
 371         // last possibility
 372         op1.set(true);
 373         assertEquals(true != true, binding.get());
 374         observer.check(binding, 1);
 375     }
 376     
 377     private static class ObservableBooleanValueMock implements ObservableBooleanValue {
 378         private InvalidationListener listener;
 379 
 380         @Override
 381         public boolean get() {
 382             return false;
 383         }
 384         
 385         @Override
 386         public Boolean getValue() {
 387             return Boolean.FALSE;
 388         }
 389 
 390         private void fireInvalidationEvent() {
 391             if (listener == null) {
 392                 fail("Attempt to fire an event with no listener attached");
 393             }
 394             this.listener.invalidated(this);
 395         }
 396 
 397         @Override
 398         public void addListener(ChangeListener<? super Boolean> listener) {
 399             // not used
 400         }
 401 
 402         @Override
 403         public void removeListener(ChangeListener<? super Boolean> listener) {
 404             // not used
 405         }
 406 
 407         @Override
 408         public void addListener(InvalidationListener listener) {
 409             if ((this.listener != null) && !this.listener.equals(listener)) {
 410                 fail("More than one listener set in mock.");
 411             }
 412             this.listener = listener;
 413         }
 414 
 415         @Override
 416         public void removeListener(InvalidationListener listener) {
 417             if (this.listener != listener) {
 418                 fail("Attempt to remove unknown listener");
 419             }
 420             this.listener = null;
 421         }
 422 
 423     }
 424 }