1 /* 2 * Copyright (C) 2010 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package libcore.java.util.beans; 18 19 import java.beans.PropertyChangeEvent; 20 import java.beans.PropertyChangeListener; 21 import java.beans.PropertyChangeListenerProxy; 22 import java.beans.PropertyChangeSupport; 23 import java.io.Serializable; 24 import java.util.ArrayList; 25 import java.util.Arrays; 26 import java.util.Collections; 27 import java.util.EventListener; 28 import java.util.List; 29 import junit.framework.TestCase; 30 import libcore.util.SerializationTester; 31 32 public final class PropertyChangeSupportTest extends TestCase { 33 testOldAndNewAreBothNull()34 public void testOldAndNewAreBothNull() { 35 Object bean = new Object(); 36 PropertyChangeSupport support = new PropertyChangeSupport(bean); 37 EventLog listener = new EventLog(); 38 support.addPropertyChangeListener(listener); 39 40 PropertyChangeEvent nullToNull = new PropertyChangeEvent(bean, "a", null, null); 41 support.firePropertyChange(nullToNull); 42 assertEquals(Arrays.<PropertyChangeEvent>asList(nullToNull), listener.log); 43 } 44 testOldAndNewAreTheSame()45 public void testOldAndNewAreTheSame() { 46 Object bean = new Object(); 47 PropertyChangeSupport support = new PropertyChangeSupport(bean); 48 EventLog listener = new EventLog(); 49 support.addPropertyChangeListener(listener); 50 51 PropertyChangeEvent xToX = new PropertyChangeEvent(bean, "a", "x", new String("x")); 52 support.firePropertyChange(xToX); 53 assertEquals(Arrays.<PropertyChangeEvent>asList(), listener.log); 54 } 55 testEventsFilteredByProxies()56 public void testEventsFilteredByProxies() { 57 Object bean = new Object(); 58 PropertyChangeEvent eventA = new PropertyChangeEvent(bean, "a", false, true); 59 PropertyChangeEvent eventB = new PropertyChangeEvent(bean, "b", false, true); 60 PropertyChangeEvent eventC = new PropertyChangeEvent(bean, "c", false, true); 61 62 PropertyChangeSupport support = new PropertyChangeSupport(bean); 63 64 EventLog all = new EventLog(); 65 support.addPropertyChangeListener(all); 66 67 EventLog proxiedA = new EventLog(); 68 support.addPropertyChangeListener(new PropertyChangeListenerProxy("a", proxiedA)); 69 70 EventLog addA = new EventLog(); 71 support.addPropertyChangeListener("a", addA); 72 73 EventLog addAProxiedB = new EventLog(); 74 support.addPropertyChangeListener("a", new PropertyChangeListenerProxy("b", addAProxiedB)); 75 76 EventLog proxiedAB = new EventLog(); 77 support.addPropertyChangeListener(new PropertyChangeListenerProxy( 78 "a", new PropertyChangeListenerProxy("b", proxiedAB))); 79 80 EventLog proxiedAA = new EventLog(); 81 support.addPropertyChangeListener(new PropertyChangeListenerProxy("a", 82 new PropertyChangeListenerProxy("a", proxiedAA))); 83 84 EventLog proxiedAAC = new EventLog(); 85 support.addPropertyChangeListener(new PropertyChangeListenerProxy("a", 86 new PropertyChangeListenerProxy("a", 87 new PropertyChangeListenerProxy("c", proxiedAAC)))); 88 89 support.firePropertyChange(eventA); 90 support.firePropertyChange(eventB); 91 support.firePropertyChange(eventC); 92 93 assertEquals(Arrays.asList(eventA, eventB, eventC), all.log); 94 assertEquals(Arrays.asList(eventA), proxiedA.log); 95 assertEquals(Arrays.asList(eventA), addA.log); 96 assertEquals(Arrays.<PropertyChangeEvent>asList(), addAProxiedB.log); 97 assertEquals(Arrays.<PropertyChangeEvent>asList(), proxiedAB.log); 98 assertEquals(Arrays.<PropertyChangeEvent>asList(eventA), proxiedAA.log); 99 assertEquals(Arrays.<PropertyChangeEvent>asList(), proxiedAAC.log); 100 } 101 102 /** 103 * Test that we need to do our own equals() work to manually unwrap an 104 * arbitrary number of proxies. 105 */ testRemoveWithProxies()106 public void testRemoveWithProxies() { 107 Object bean = new Object(); 108 PropertyChangeSupport support = new PropertyChangeSupport(bean); 109 110 EventLog all = new EventLog(); 111 support.addPropertyChangeListener(all); 112 assertEquals(1, support.getPropertyChangeListeners().length); 113 114 EventLog proxiedA = new EventLog(); 115 support.addPropertyChangeListener(new PropertyChangeListenerProxy("a", proxiedA)); 116 assertEquals(2, support.getPropertyChangeListeners().length); 117 118 EventLog addA = new EventLog(); 119 support.addPropertyChangeListener("a", addA); 120 assertEquals(3, support.getPropertyChangeListeners().length); 121 122 EventLog addAProxiedB = new EventLog(); 123 support.addPropertyChangeListener("a", new PropertyChangeListenerProxy("b", addAProxiedB)); 124 assertEquals(4, support.getPropertyChangeListeners().length); 125 126 EventLog proxiedAB = new EventLog(); 127 PropertyChangeListenerProxy proxyAB = new PropertyChangeListenerProxy( 128 "a", new PropertyChangeListenerProxy("b", proxiedAB)); 129 support.addPropertyChangeListener(proxyAB); 130 assertEquals(5, support.getPropertyChangeListeners().length); 131 132 EventLog proxiedAAC = new EventLog(); 133 support.addPropertyChangeListener(new PropertyChangeListenerProxy("a", 134 new PropertyChangeListenerProxy("a", 135 new PropertyChangeListenerProxy("c", proxiedAAC)))); 136 assertEquals(6, support.getPropertyChangeListeners().length); 137 138 support.removePropertyChangeListener(all); 139 assertEquals(5, support.getPropertyChangeListeners().length); 140 support.removePropertyChangeListener("a", proxiedA); 141 assertEquals(4, support.getPropertyChangeListeners().length); 142 support.removePropertyChangeListener(new PropertyChangeListenerProxy("a", addA)); 143 assertEquals(3, support.getPropertyChangeListeners().length); 144 support.removePropertyChangeListener( 145 "a", new PropertyChangeListenerProxy("b", addAProxiedB)); 146 assertEquals(2, support.getPropertyChangeListeners().length); 147 support.removePropertyChangeListener(proxyAB); 148 assertEquals(1, support.getPropertyChangeListeners().length); 149 150 support.removePropertyChangeListener(proxiedAAC); 151 support.removePropertyChangeListener(new PropertyChangeListenerProxy("a", proxiedAAC)); 152 support.removePropertyChangeListener("a", new PropertyChangeListenerProxy("c", proxiedAAC)); 153 support.removePropertyChangeListener("a", new PropertyChangeListenerProxy("c", 154 new PropertyChangeListenerProxy("a", proxiedAAC))); 155 assertEquals(1, support.getPropertyChangeListeners().length); 156 157 support.removePropertyChangeListener("a", new PropertyChangeListenerProxy("a", 158 new PropertyChangeListenerProxy("c", proxiedAAC))); 159 assertEquals(0, support.getPropertyChangeListeners().length); 160 } 161 testAddingOneListenerTwice()162 public void testAddingOneListenerTwice() { 163 Object bean = new Object(); 164 PropertyChangeSupport support = new PropertyChangeSupport(bean); 165 EventLog log = new EventLog(); 166 support.addPropertyChangeListener("a", log); 167 support.addPropertyChangeListener(log); 168 support.addPropertyChangeListener(log); 169 support.addPropertyChangeListener("a", log); 170 171 PropertyChangeEvent eventA = new PropertyChangeEvent(bean, "a", false, true); 172 PropertyChangeEvent eventB = new PropertyChangeEvent(bean, "b", false, true); 173 174 support.firePropertyChange(eventA); 175 support.firePropertyChange(eventB); 176 177 assertEquals(Arrays.asList(eventA, eventA, eventA, eventA, eventB, eventB), log.log); 178 } 179 testAddingAListenerActuallyAddsAProxy()180 public void testAddingAListenerActuallyAddsAProxy() { 181 Object bean = new Object(); 182 PropertyChangeSupport support = new PropertyChangeSupport(bean); 183 PropertyChangeListener listener = new PropertyChangeListener() { 184 public void propertyChange(PropertyChangeEvent event) {} 185 }; 186 support.addPropertyChangeListener("a", listener); 187 188 PropertyChangeListenerProxy p1 189 = (PropertyChangeListenerProxy) support.getPropertyChangeListeners()[0]; 190 assertEquals(PropertyChangeListenerProxy.class, p1.getClass()); 191 assertTrue(p1 != listener); // weird but consistent with the RI 192 assertEquals("a", p1.getPropertyName()); 193 assertEquals(listener, p1.getListener()); 194 } 195 testAddingAProxy()196 public void testAddingAProxy() { 197 Object bean = new Object(); 198 PropertyChangeSupport support = new PropertyChangeSupport(bean); 199 PropertyChangeListener listener = new PropertyChangeListener() { 200 public void propertyChange(PropertyChangeEvent event) {} 201 }; 202 PropertyChangeListenerProxy proxy = new PropertyChangeListenerProxy("a", listener); 203 support.addPropertyChangeListener("b", proxy); 204 205 // this proxy sets us up to receive 'b' events 206 PropertyChangeListenerProxy p1 207 = (PropertyChangeListenerProxy) support.getPropertyChangeListeners()[0]; 208 assertEquals(PropertyChangeListenerProxy.class, p1.getClass()); 209 assertEquals("b", p1.getPropertyName()); 210 211 // this proxy sets us up to receive 'a' events 212 PropertyChangeListenerProxy p2 = (PropertyChangeListenerProxy) p1.getListener(); 213 assertEquals(PropertyChangeListenerProxy.class, p2.getClass()); 214 assertEquals("a", p2.getPropertyName()); 215 assertEquals(listener, p2.getListener()); 216 } 217 testSerialize()218 public void testSerialize() { 219 String s = "aced0005737200206a6176612e6265616e732e50726f70657274794368616e67" 220 + "65537570706f727458d5d264574860bb03000349002a70726f706572747943686" 221 + "16e6765537570706f727453657269616c697a65644461746156657273696f6e4c" 222 + "00086368696c6472656e7400154c6a6176612f7574696c2f486173687461626c6" 223 + "53b4c0006736f757263657400124c6a6176612f6c616e672f4f626a6563743b78" 224 + "7000000002737200136a6176612e7574696c2e486173687461626c6513bb0f252" 225 + "14ae4b803000246000a6c6f6164466163746f724900097468726573686f6c6478" 226 + "703f4000000000000877080000000b00000001740001617371007e00000000000" 227 + "2707400046265616e7372003a6c6962636f72652e6a6176612e7574696c2e6265" 228 + "616e732e50726f70657274794368616e6765537570706f7274546573742445766" 229 + "56e744c6f67b92667637d0b6f450200024c00036c6f677400104c6a6176612f75" 230 + "74696c2f4c6973743b4c00046e616d657400124c6a6176612f6c616e672f53747" 231 + "2696e673b7870737200136a6176612e7574696c2e41727261794c6973747881d2" 232 + "1d99c7619d03000149000473697a6578700000000077040000000a7874000b6c6" 233 + "97374656e6572546f4171007e000c70787871007e00087371007e00097371007e" 234 + "000d0000000077040000000a7874000d6c697374656e6572546f416c6c7078"; 235 236 Object bean = "bean"; 237 PropertyChangeSupport support = new PropertyChangeSupport(bean); 238 EventLog listenerToAll = new EventLog(); 239 listenerToAll.name = "listenerToAll"; 240 EventLog listenerToA = new EventLog(); 241 listenerToA.name = "listenerToA"; 242 support.addPropertyChangeListener(listenerToAll); 243 support.addPropertyChangeListener("a", listenerToA); 244 support.addPropertyChangeListener("a", listenerToA); 245 246 new SerializationTester<PropertyChangeSupport>(support, s) { 247 @Override protected boolean equals(PropertyChangeSupport a, PropertyChangeSupport b) { 248 return describe(a.getPropertyChangeListeners()) 249 .equals(describe(b.getPropertyChangeListeners())); 250 } 251 @Override protected void verify(PropertyChangeSupport deserialized) { 252 assertEquals("[a to listenerToA, a to listenerToA, listenerToAll]", 253 describe(deserialized.getPropertyChangeListeners())); 254 } 255 }.test(); 256 } 257 describe(PropertyChangeListener[] listeners)258 private String describe(PropertyChangeListener[] listeners) { 259 List<String> result = new ArrayList<String>(); 260 for (PropertyChangeListener listener : listeners) { 261 result.add(describe(listener)); 262 } 263 Collections.sort(result); 264 return result.toString(); 265 } 266 describe(EventListener listener)267 private String describe(EventListener listener) { 268 if (listener instanceof PropertyChangeListenerProxy) { 269 PropertyChangeListenerProxy proxy = (PropertyChangeListenerProxy) listener; 270 return proxy.getPropertyName() + " to " + describe(proxy.getListener()); 271 } else { 272 return listener.toString(); 273 } 274 } 275 276 static class EventLog implements PropertyChangeListener, Serializable { 277 String name = "EventLog"; 278 List<PropertyChangeEvent> log = new ArrayList<PropertyChangeEvent>(); propertyChange(PropertyChangeEvent event)279 public void propertyChange(PropertyChangeEvent event) { 280 log.add(event); 281 } toString()282 @Override public String toString() { 283 return name; 284 } 285 } 286 } 287