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