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.value; 27 28 import test.javafx.beans.value.ChangeListenerMock; 29 import javafx.beans.InvalidationListener; 30 import test.javafx.beans.InvalidationListenerMock; 31 import javafx.beans.Observable; 32 import javafx.beans.value.ChangeListener; 33 import javafx.beans.value.ObservableObjectValueStub; 34 35 import org.junit.Before; 36 import org.junit.Test; 37 38 public class ObservableValueBaseTest { 39 40 private static final Object UNDEFINED_VALUE = new Object(); 41 private static final Object V1 = new Object(); 42 private static final Object V2 = new Object(); 43 44 private ObservableObjectValueStub<Object> valueModel; 45 private InvalidationListenerMock invalidationListener; 46 private ChangeListenerMock<Object> changeListener; 47 48 @Before 49 public void setUp() { 50 valueModel = new ObservableObjectValueStub<Object>(); 51 invalidationListener = new InvalidationListenerMock(); 52 changeListener = new ChangeListenerMock<Object>(UNDEFINED_VALUE); 53 } 54 55 @Test 56 public void testInitialState() { 57 // no exceptions etc. 58 valueModel.fireValueChangedEvent(); 59 } 60 61 @Test 62 public void testOneInvalidationListener() { 63 // adding one observer 64 valueModel.addListener(invalidationListener); 65 System.gc(); // making sure we did not not overdo weak references 66 valueModel.set(V1); 67 invalidationListener.check(valueModel, 1); 68 69 // remove observer 70 valueModel.removeListener(invalidationListener); 71 valueModel.set(V2); 72 invalidationListener.check(null, 0); 73 74 // remove observer again 75 valueModel.removeListener(invalidationListener); 76 valueModel.set(V1); 77 invalidationListener.check(null, 0); 78 } 79 80 @Test 81 public void testOneChangeListener() { 82 // adding one observer 83 valueModel.addListener(changeListener); 84 System.gc(); // making sure we did not not overdo weak references 85 valueModel.set(V1); 86 changeListener.check(valueModel, null, V1, 1); 87 88 // set same value again 89 valueModel.set(V1); 90 changeListener.check(null, UNDEFINED_VALUE, UNDEFINED_VALUE, 0); 91 92 // set null 93 valueModel.set(null); 94 changeListener.check(valueModel, V1, null, 1); 95 valueModel.set(null); 96 changeListener.check(null, UNDEFINED_VALUE, UNDEFINED_VALUE, 0); 97 98 // remove observer 99 valueModel.removeListener(changeListener); 100 valueModel.set(V2); 101 changeListener.check(null, UNDEFINED_VALUE, UNDEFINED_VALUE, 0); 102 103 // remove observer again 104 valueModel.removeListener(changeListener); 105 valueModel.set(V1); 106 changeListener.check(null, UNDEFINED_VALUE, UNDEFINED_VALUE, 0); 107 } 108 109 @Test 110 public void testTwoObservers() { 111 final InvalidationListenerMock observer2 = new InvalidationListenerMock(); 112 113 // adding two observers 114 valueModel.addListener(invalidationListener); 115 valueModel.addListener(observer2); 116 System.gc(); // making sure we did not not overdo weak references 117 valueModel.fireValueChangedEvent(); 118 invalidationListener.check(valueModel, 1); 119 observer2.check(valueModel, 1); 120 121 // remove first observer 122 invalidationListener.reset(); 123 observer2.reset(); 124 valueModel.removeListener(invalidationListener); 125 valueModel.fireValueChangedEvent(); 126 invalidationListener.check(null, 0); 127 observer2.check(valueModel, 1); 128 129 // remove second observer 130 observer2.reset(); 131 valueModel.removeListener(observer2); 132 valueModel.fireValueChangedEvent(); 133 invalidationListener.check(null, 0); 134 observer2.check(null, 0); 135 136 // remove observers in reverse order 137 observer2.reset(); 138 valueModel.removeListener(observer2); 139 valueModel.removeListener(invalidationListener); 140 valueModel.fireValueChangedEvent(); 141 invalidationListener.check(null, 0); 142 observer2.check(null, 0); 143 } 144 145 @Test 146 public void testConcurrentAdd() { 147 final InvalidationListenerMock observer2 = new AddingListenerMock(); 148 valueModel.addListener(observer2); 149 150 // fire event that adds a second observer 151 // Note: there is no assumption if observer that is being added is notified 152 valueModel.fireValueChangedEvent(); 153 observer2.check(valueModel, 1); 154 155 // fire event again, this time both observers need to be notified 156 invalidationListener.reset(); 157 observer2.reset(); 158 valueModel.fireValueChangedEvent(); 159 invalidationListener.check(valueModel, 1); 160 observer2.check(valueModel, 1); 161 } 162 163 @Test 164 public void testConcurrentRemove() { 165 final InvalidationListenerMock observer2 = new RemovingListenerMock(); 166 valueModel.addListener(observer2); 167 valueModel.addListener(invalidationListener); 168 169 // fire event that removes one observer 170 // Note: there is no assumption if observer that is being removed is notified 171 valueModel.fireValueChangedEvent(); 172 observer2.check(valueModel, 1); 173 174 // fire event again, this time only non-removed observer is notified 175 invalidationListener.reset(); 176 observer2.reset(); 177 valueModel.fireValueChangedEvent(); 178 invalidationListener.check(null, 0); 179 observer2.check(valueModel, 1); 180 } 181 182 @Test(expected=NullPointerException.class) 183 public void testAddingNull_InvalidationListener() { 184 valueModel.addListener((InvalidationListener)null); 185 } 186 187 @Test(expected=NullPointerException.class) 188 public void testAddingNull_ChangeListener() { 189 valueModel.addListener((ChangeListener<Object>)null); 190 } 191 192 @Test(expected=NullPointerException.class) 193 public void testRemovingNull_InvalidationListener() { 194 valueModel.removeListener((InvalidationListener)null); 195 } 196 197 @Test(expected=NullPointerException.class) 198 public void testRemovingNull_ChangeListener() { 199 valueModel.removeListener((ChangeListener<Object>)null); 200 } 201 202 private class AddingListenerMock extends InvalidationListenerMock { 203 @Override public void invalidated(Observable valueModel) { 204 super.invalidated(valueModel); 205 valueModel.addListener(invalidationListener); 206 } 207 } 208 209 private class RemovingListenerMock extends InvalidationListenerMock { 210 @Override public void invalidated(Observable valueModel) { 211 super.invalidated(valueModel); 212 valueModel.removeListener(invalidationListener); 213 } 214 } 215 }