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 static org.junit.Assert.assertEquals; 29 import static org.junit.Assert.assertFalse; 30 import static org.junit.Assert.assertTrue; 31 32 import javafx.beans.InvalidationListenerMock; 33 import javafx.beans.value.ChangeListenerMock; 34 import javafx.beans.value.ObservableObjectValueStub; 35 36 import org.junit.Before; 37 import org.junit.Test; 38 39 public class ObjectPropertyBaseTest { 40 41 private static final Object NO_BEAN = null; 42 private static final String NO_NAME_1 = null; 43 private static final String NO_NAME_2 = ""; 44 private static final Object UNDEFINED = new Object(); 45 private static final Object VALUE_1a = new Object(); 46 private static final Object VALUE_1b = new Object(); 47 private static final Object VALUE_2a = new Object(); 48 private static final Object VALUE_2b = new Object(); 49 50 private ObjectPropertyMock property; 51 private InvalidationListenerMock invalidationListener; 52 private ChangeListenerMock<Object> changeListener; 53 54 @Before 55 public void setUp() throws Exception { 56 property = new ObjectPropertyMock(); 57 invalidationListener = new InvalidationListenerMock(); 58 changeListener = new ChangeListenerMock<Object>(UNDEFINED); 59 } 60 61 private void attachInvalidationListener() { 62 property.addListener(invalidationListener); 63 property.get(); 64 invalidationListener.reset(); 65 } 66 67 private void attachChangeListener() { 68 property.addListener(changeListener); 69 property.get(); 70 changeListener.reset(); 71 } 72 73 @Test 74 public void testConstructor() { 75 final ObjectProperty<Object> p1 = new SimpleObjectProperty<Object>(); 76 assertEquals(null, p1.get()); 77 assertEquals(null, p1.getValue()); 78 assertFalse(property.isBound()); 79 80 final ObjectProperty<Object> p2 = new SimpleObjectProperty<Object>(VALUE_1b); 81 assertEquals(VALUE_1b, p2.get()); 82 assertEquals(VALUE_1b, p2.getValue()); 83 assertFalse(property.isBound()); 84 } 85 86 @Test 87 public void testInvalidationListener() { 88 attachInvalidationListener(); 89 property.set(VALUE_2a); 90 invalidationListener.check(property, 1); 91 property.removeListener(invalidationListener); 92 invalidationListener.reset(); 93 property.set(VALUE_1a); 94 invalidationListener.check(null, 0); 95 } 96 97 @Test 98 public void testChangeListener() { 99 attachChangeListener(); 100 property.set(VALUE_2a); 101 changeListener.check(property, null, VALUE_2a, 1); 102 property.removeListener(changeListener); 103 changeListener.reset(); 104 property.set(VALUE_1a); 105 changeListener.check(null, UNDEFINED, UNDEFINED, 0); 106 } 107 108 @Test 109 public void testLazySet() { 110 attachInvalidationListener(); 111 112 // set value once 113 property.set(VALUE_2a); 114 assertEquals(VALUE_2a, property.get()); 115 property.check(1); 116 invalidationListener.check(property, 1); 117 118 // set same value again 119 property.set(VALUE_2a); 120 assertEquals(VALUE_2a, property.get()); 121 property.check(0); 122 invalidationListener.check(null, 0); 123 124 // set value twice without reading 125 property.set(VALUE_1a); 126 property.set(VALUE_1b); 127 assertEquals(VALUE_1b, property.get()); 128 property.check(1); 129 invalidationListener.check(property, 1); 130 } 131 132 @Test 133 public void testEagerSet() { 134 attachChangeListener(); 135 136 // set value once 137 property.set(VALUE_2a); 138 assertEquals(VALUE_2a, property.get()); 139 property.check(1); 140 changeListener.check(property, null, VALUE_2a, 1); 141 142 // set same value again 143 property.set(VALUE_2a); 144 assertEquals(VALUE_2a, property.get()); 145 property.check(0); 146 changeListener.check(null, UNDEFINED, UNDEFINED, 0); 147 148 // set value twice without reading 149 property.set(VALUE_1a); 150 property.set(VALUE_1b); 151 assertEquals(VALUE_1b, property.get()); 152 property.check(2); 153 changeListener.check(property, VALUE_1a, VALUE_1b, 2); 154 } 155 156 @Test 157 public void testLazySetValue() { 158 attachInvalidationListener(); 159 160 // set value once 161 property.setValue(VALUE_2a); 162 assertEquals(VALUE_2a, property.get()); 163 property.check(1); 164 invalidationListener.check(property, 1); 165 166 // set same value again 167 property.setValue(VALUE_2a); 168 assertEquals(VALUE_2a, property.get()); 169 property.check(0); 170 invalidationListener.check(null, 0); 171 172 // set value twice without reading 173 property.setValue(VALUE_1a); 174 property.setValue(VALUE_1b); 175 assertEquals(VALUE_1b, property.get()); 176 property.check(1); 177 invalidationListener.check(property, 1); 178 } 179 180 @Test 181 public void testEagerSetValue() { 182 attachChangeListener(); 183 184 // set value once 185 property.setValue(VALUE_2a); 186 assertEquals(VALUE_2a, property.get()); 187 property.check(1); 188 changeListener.check(property, null, VALUE_2a, 1); 189 190 // set same value again 191 property.setValue(VALUE_2a); 192 assertEquals(VALUE_2a, property.get()); 193 property.check(0); 194 changeListener.check(null, UNDEFINED, UNDEFINED, 0); 195 196 // set value twice without reading 197 property.setValue(VALUE_1a); 198 property.setValue(VALUE_1b); 199 assertEquals(VALUE_1b, property.get()); 200 property.check(2); 201 changeListener.check(property, VALUE_1a, VALUE_1b, 2); 202 } 203 204 @Test(expected=RuntimeException.class) 205 public void testSetBoundValue() { 206 final ObjectProperty<Object> v = new SimpleObjectProperty<Object>(VALUE_1a); 207 property.bind(v); 208 property.set(VALUE_1a); 209 } 210 211 @Test 212 public void testLazyBind() { 213 attachInvalidationListener(); 214 final ObservableObjectValueStub<Object> v = new ObservableObjectValueStub<Object>(VALUE_1a); 215 216 property.bind(v); 217 assertEquals(VALUE_1a, property.get()); 218 assertTrue(property.isBound()); 219 property.check(1); 220 invalidationListener.check(property, 1); 221 222 // change binding once 223 v.set(VALUE_2a); 224 assertEquals(VALUE_2a, property.get()); 225 property.check(1); 226 invalidationListener.check(property, 1); 227 228 // change binding twice without reading 229 v.set(VALUE_1a); 230 v.set(VALUE_1b); 231 assertEquals(VALUE_1b, property.get()); 232 property.check(1); 233 invalidationListener.check(property, 1); 234 235 // change binding twice to same value 236 v.set(VALUE_1a); 237 v.set(VALUE_1a); 238 assertEquals(VALUE_1a, property.get()); 239 property.check(1); 240 invalidationListener.check(property, 1); 241 } 242 243 @Test 244 public void testEagerBind() { 245 attachChangeListener(); 246 final ObservableObjectValueStub<Object> v = new ObservableObjectValueStub<Object>(VALUE_1a); 247 248 property.bind(v); 249 assertEquals(VALUE_1a, property.get()); 250 assertTrue(property.isBound()); 251 property.check(1); 252 changeListener.check(property, null, VALUE_1a, 1); 253 254 // change binding once 255 v.set(VALUE_2a); 256 assertEquals(VALUE_2a, property.get()); 257 property.check(1); 258 changeListener.check(property, VALUE_1a, VALUE_2a, 1); 259 260 // change binding twice without reading 261 v.set(VALUE_1a); 262 v.set(VALUE_1b); 263 assertEquals(VALUE_1b, property.get()); 264 property.check(2); 265 changeListener.check(property, VALUE_1a, VALUE_1b, 2); 266 267 // change binding twice to same value 268 v.set(VALUE_1a); 269 v.set(VALUE_1a); 270 assertEquals(VALUE_1a, property.get()); 271 property.check(2); 272 changeListener.check(property, VALUE_1b, VALUE_1a, 1); 273 } 274 275 @Test(expected=NullPointerException.class) 276 public void testBindToNull() { 277 property.bind(null); 278 } 279 280 @Test 281 public void testRebind() { 282 attachInvalidationListener(); 283 final ObjectProperty<Object> v1 = new SimpleObjectProperty<Object>(VALUE_1a); 284 final ObjectProperty<Object> v2 = new SimpleObjectProperty<Object>(VALUE_2a); 285 property.bind(v1); 286 property.get(); 287 property.reset(); 288 invalidationListener.reset(); 289 290 // rebind causes invalidation event 291 property.bind(v2); 292 assertEquals(VALUE_2a, property.get()); 293 assertTrue(property.isBound()); 294 assertEquals(1, property.counter); 295 invalidationListener.check(property, 1); 296 property.reset(); 297 298 // change old binding 299 v1.set(VALUE_1b); 300 assertEquals(VALUE_2a, property.get()); 301 assertEquals(0, property.counter); 302 invalidationListener.check(null, 0); 303 property.reset(); 304 305 // change new binding 306 v2.set(VALUE_2b); 307 assertEquals(VALUE_2b, property.get()); 308 assertEquals(1, property.counter); 309 invalidationListener.check(property, 1); 310 property.reset(); 311 312 // rebind to same observable should have no effect 313 property.bind(v2); 314 assertEquals(VALUE_2b, property.get()); 315 assertTrue(property.isBound()); 316 assertEquals(0, property.counter); 317 invalidationListener.check(null, 0); 318 } 319 320 @Test 321 public void testUnbind() { 322 attachInvalidationListener(); 323 final ObjectProperty<Object> v = new SimpleObjectProperty<Object>(VALUE_1a); 324 property.bind(v); 325 property.unbind(); 326 assertEquals(VALUE_1a, property.get()); 327 assertFalse(property.isBound()); 328 property.reset(); 329 invalidationListener.reset(); 330 331 // change binding 332 v.set(VALUE_2a); 333 assertEquals(VALUE_1a, property.get()); 334 assertEquals(0, property.counter); 335 invalidationListener.check(null, 0); 336 property.reset(); 337 338 // set value 339 property.set(VALUE_1b); 340 assertEquals(VALUE_1b, property.get()); 341 assertEquals(1, property.counter); 342 invalidationListener.check(property, 1); 343 } 344 345 @Test 346 public void testAddingListenerWillAlwaysReceiveInvalidationEvent() { 347 final ObjectProperty<Object> v = new SimpleObjectProperty<Object>(VALUE_1a); 348 final InvalidationListenerMock listener2 = new InvalidationListenerMock(); 349 final InvalidationListenerMock listener3 = new InvalidationListenerMock(); 350 351 // setting the property 352 property.set(VALUE_1a); 353 property.addListener(listener2); 354 listener2.reset(); 355 property.set(VALUE_1b); 356 listener2.check(property, 1); 357 358 // binding the property 359 property.bind(v); 360 v.set(VALUE_2a); 361 property.addListener(listener3); 362 v.get(); 363 listener3.reset(); 364 v.set(VALUE_2b); 365 listener3.check(property, 1); 366 } 367 368 @Test 369 public void testToString() { 370 final Object value1 = new Object(); 371 final Object value2 = new Object(); 372 final ObjectProperty<Object> v = new SimpleObjectProperty<Object>(value2); 373 374 property.set(value1); 375 assertEquals("ObjectProperty [value: " + value1 + "]", property.toString()); 376 377 property.bind(v); 378 assertEquals("ObjectProperty [bound, invalid]", property.toString()); 379 property.get(); 380 assertEquals("ObjectProperty [bound, value: " + value2 + "]", property.toString()); 381 v.set(value1); 382 assertEquals("ObjectProperty [bound, invalid]", property.toString()); 383 property.get(); 384 assertEquals("ObjectProperty [bound, value: " + value1 + "]", property.toString()); 385 386 final Object bean = new Object(); 387 final String name = "My name"; 388 final ObjectProperty<Object> v1 = new ObjectPropertyMock(bean, name); 389 assertEquals("ObjectProperty [bean: " + bean.toString() + ", name: My name, value: " + null + "]", v1.toString()); 390 v1.set(value1); 391 assertEquals("ObjectProperty [bean: " + bean.toString() + ", name: My name, value: " + value1 + "]", v1.toString()); 392 393 final ObjectProperty<Object> v2 = new ObjectPropertyMock(bean, NO_NAME_1); 394 assertEquals("ObjectProperty [bean: " + bean.toString() + ", value: " + null + "]", v2.toString()); 395 v2.set(value1); 396 assertEquals("ObjectProperty [bean: " + bean.toString() + ", value: " + value1 + "]", v2.toString()); 397 398 final ObjectProperty<Object> v3 = new ObjectPropertyMock(bean, NO_NAME_2); 399 assertEquals("ObjectProperty [bean: " + bean.toString() + ", value: " + null + "]", v3.toString()); 400 v3.set(value1); 401 assertEquals("ObjectProperty [bean: " + bean.toString() + ", value: " + value1 + "]", v3.toString()); 402 403 final ObjectProperty<Object> v4 = new ObjectPropertyMock(NO_BEAN, name); 404 assertEquals("ObjectProperty [name: My name, value: " + null + "]", v4.toString()); 405 v4.set(value1); 406 assertEquals("ObjectProperty [name: My name, value: " + value1 + "]", v4.toString()); 407 } 408 409 private static class ObjectPropertyMock extends ObjectPropertyBase<Object> { 410 411 private final Object bean; 412 private final String name; 413 private int counter; 414 415 private ObjectPropertyMock() { 416 this.bean = NO_BEAN; 417 this.name = NO_NAME_1; 418 } 419 420 private ObjectPropertyMock(Object bean, String name) { 421 this.bean = bean; 422 this.name = name; 423 } 424 425 @Override 426 protected void invalidated() { 427 counter++; 428 } 429 430 private void check(int expected) { 431 assertEquals(expected, counter); 432 reset(); 433 } 434 435 private void reset() { 436 counter = 0; 437 } 438 439 @Override public Object getBean() { return bean; } 440 441 @Override public String getName() { return name; } 442 } 443 444 }