1 /* 2 * Copyright (C) 2015 The Android Open Source Project 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 package com.android.internal.util; 17 18 import junit.framework.TestCase; 19 20 import org.junit.Test; 21 22 import java.util.ArrayList; 23 import java.util.Objects; 24 25 import static org.junit.Assert.assertEquals; 26 import static org.junit.Assert.assertFalse; 27 import static org.junit.Assert.assertNotNull; 28 import static org.junit.Assert.assertTrue; 29 30 public class CallbackRegistryTest extends TestCase { 31 32 final Integer callback1 = 1; 33 final Integer callback2 = 2; 34 final Integer callback3 = 3; 35 CallbackRegistry<Integer, CallbackRegistryTest, Integer> registry; 36 int notify1; 37 int notify2; 38 int notify3; 39 int[] deepNotifyCount = new int[300]; 40 Integer argValue; 41 addNotifyCount(Integer callback)42 private void addNotifyCount(Integer callback) { 43 if (Objects.equals(callback, callback1)) { 44 notify1++; 45 } else if (Objects.equals(callback, callback2)) { 46 notify2++; 47 } else if (Objects.equals(callback, callback3)) { 48 notify3++; 49 } 50 deepNotifyCount[callback]++; 51 } 52 testAddListener()53 public void testAddListener() { 54 CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier = 55 new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() { 56 @Override 57 public void onNotifyCallback(Integer callback, CallbackRegistryTest sender, 58 int arg, Integer arg2) { 59 } 60 }; 61 registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier); 62 Integer callback = 0; 63 64 assertNotNull(registry.copyListeners()); 65 assertEquals(0, registry.copyListeners().size()); 66 67 registry.add(callback); 68 ArrayList<Integer> callbacks = registry.copyListeners(); 69 assertEquals(1, callbacks.size()); 70 assertEquals(callback, callbacks.get(0)); 71 72 registry.add(callback); 73 callbacks = registry.copyListeners(); 74 assertEquals(1, callbacks.size()); 75 assertEquals(callback, callbacks.get(0)); 76 77 Integer otherListener = 1; 78 registry.add(otherListener); 79 callbacks = registry.copyListeners(); 80 assertEquals(2, callbacks.size()); 81 assertEquals(callback, callbacks.get(0)); 82 assertEquals(otherListener, callbacks.get(1)); 83 84 registry.remove(callback); 85 registry.add(callback); 86 callbacks = registry.copyListeners(); 87 assertEquals(2, callbacks.size()); 88 assertEquals(callback, callbacks.get(1)); 89 assertEquals(otherListener, callbacks.get(0)); 90 } 91 testSimpleNotify()92 public void testSimpleNotify() { 93 CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier = 94 new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() { 95 @Override 96 public void onNotifyCallback(Integer callback, CallbackRegistryTest sender, 97 int arg1, Integer arg) { 98 assertEquals(arg1, (int) arg); 99 addNotifyCount(callback); 100 argValue = arg; 101 } 102 }; 103 registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier); 104 registry.add(callback2); 105 Integer arg = 1; 106 registry.notifyCallbacks(this, arg, arg); 107 assertEquals(arg, argValue); 108 assertEquals(1, notify2); 109 } 110 testRemoveWhileNotifying()111 public void testRemoveWhileNotifying() { 112 CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier = 113 new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() { 114 @Override 115 public void onNotifyCallback(Integer callback, CallbackRegistryTest sender, 116 int arg1, Integer arg) { 117 addNotifyCount(callback); 118 if (Objects.equals(callback, callback1)) { 119 registry.remove(callback1); 120 registry.remove(callback2); 121 } 122 } 123 }; 124 registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier); 125 registry.add(callback1); 126 registry.add(callback2); 127 registry.add(callback3); 128 registry.notifyCallbacks(this, 0, null); 129 assertEquals(1, notify1); 130 assertEquals(1, notify2); 131 assertEquals(1, notify3); 132 133 ArrayList<Integer> callbacks = registry.copyListeners(); 134 assertEquals(1, callbacks.size()); 135 assertEquals(callback3, callbacks.get(0)); 136 } 137 testDeepRemoveWhileNotifying()138 public void testDeepRemoveWhileNotifying() { 139 CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier = 140 new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() { 141 @Override 142 public void onNotifyCallback(Integer callback, CallbackRegistryTest sender, 143 int arg1, Integer arg) { 144 addNotifyCount(callback); 145 registry.remove(callback); 146 registry.notifyCallbacks(CallbackRegistryTest.this, arg1, null); 147 } 148 }; 149 registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier); 150 registry.add(callback1); 151 registry.add(callback2); 152 registry.add(callback3); 153 registry.notifyCallbacks(this, 0, null); 154 assertEquals(1, notify1); 155 assertEquals(2, notify2); 156 assertEquals(3, notify3); 157 158 ArrayList<Integer> callbacks = registry.copyListeners(); 159 assertEquals(0, callbacks.size()); 160 } 161 testAddRemovedListener()162 public void testAddRemovedListener() { 163 164 CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier = 165 new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() { 166 @Override 167 public void onNotifyCallback(Integer callback, CallbackRegistryTest sender, 168 int arg1, Integer arg) { 169 addNotifyCount(callback); 170 if (Objects.equals(callback, callback1)) { 171 registry.remove(callback2); 172 } else if (Objects.equals(callback, callback3)) { 173 registry.add(callback2); 174 } 175 } 176 }; 177 registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier); 178 179 registry.add(callback1); 180 registry.add(callback2); 181 registry.add(callback3); 182 registry.notifyCallbacks(this, 0, null); 183 184 ArrayList<Integer> callbacks = registry.copyListeners(); 185 assertEquals(3, callbacks.size()); 186 assertEquals(callback1, callbacks.get(0)); 187 assertEquals(callback3, callbacks.get(1)); 188 assertEquals(callback2, callbacks.get(2)); 189 assertEquals(1, notify1); 190 assertEquals(1, notify2); 191 assertEquals(1, notify3); 192 } 193 testVeryDeepRemoveWhileNotifying()194 public void testVeryDeepRemoveWhileNotifying() { 195 final Integer[] callbacks = new Integer[deepNotifyCount.length]; 196 for (int i = 0; i < callbacks.length; i++) { 197 callbacks[i] = i; 198 } 199 CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier = 200 new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() { 201 @Override 202 public void onNotifyCallback(Integer callback, CallbackRegistryTest sender, 203 int arg1, Integer arg) { 204 addNotifyCount(callback); 205 registry.remove(callback); 206 registry.remove(callbacks[callbacks.length - callback - 1]); 207 registry.notifyCallbacks(CallbackRegistryTest.this, arg1, null); 208 } 209 }; 210 registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier); 211 for (int i = 0; i < callbacks.length; i++) { 212 registry.add(callbacks[i]); 213 } 214 registry.notifyCallbacks(this, 0, null); 215 for (int i = 0; i < deepNotifyCount.length; i++) { 216 int expectedCount = Math.min(i + 1, deepNotifyCount.length - i); 217 assertEquals(expectedCount, deepNotifyCount[i]); 218 } 219 220 ArrayList<Integer> callbackList = registry.copyListeners(); 221 assertEquals(0, callbackList.size()); 222 } 223 testClear()224 public void testClear() { 225 CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier = 226 new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() { 227 @Override 228 public void onNotifyCallback(Integer callback, CallbackRegistryTest sender, 229 int arg1, Integer arg) { 230 addNotifyCount(callback); 231 } 232 }; 233 registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier); 234 for (int i = 0; i < deepNotifyCount.length; i++) { 235 registry.add(i); 236 } 237 registry.clear(); 238 239 ArrayList<Integer> callbackList = registry.copyListeners(); 240 assertEquals(0, callbackList.size()); 241 242 registry.notifyCallbacks(this, 0, null); 243 for (int i = 0; i < deepNotifyCount.length; i++) { 244 assertEquals(0, deepNotifyCount[i]); 245 } 246 } 247 testNestedClear()248 public void testNestedClear() { 249 CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier = 250 new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() { 251 @Override 252 public void onNotifyCallback(Integer callback, CallbackRegistryTest sender, 253 int arg1, Integer arg) { 254 addNotifyCount(callback); 255 registry.clear(); 256 } 257 }; 258 registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier); 259 for (int i = 0; i < deepNotifyCount.length; i++) { 260 registry.add(i); 261 } 262 registry.notifyCallbacks(this, 0, null); 263 for (int i = 0; i < deepNotifyCount.length; i++) { 264 assertEquals(1, deepNotifyCount[i]); 265 } 266 267 ArrayList<Integer> callbackList = registry.copyListeners(); 268 assertEquals(0, callbackList.size()); 269 } 270 testIsEmpty()271 public void testIsEmpty() throws Exception { 272 CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier = 273 new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() { 274 @Override 275 public void onNotifyCallback(Integer callback, CallbackRegistryTest sender, 276 int arg, Integer arg2) { 277 } 278 }; 279 registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier); 280 Integer callback = 0; 281 282 assertTrue(registry.isEmpty()); 283 registry.add(callback); 284 assertFalse(registry.isEmpty()); 285 } 286 testClone()287 public void testClone() throws Exception { 288 CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier = 289 new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() { 290 @Override 291 public void onNotifyCallback(Integer callback, CallbackRegistryTest sender, 292 int arg, Integer arg2) { 293 } 294 }; 295 registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier); 296 297 assertTrue(registry.isEmpty()); 298 CallbackRegistry<Integer, CallbackRegistryTest, Integer> registry2 = registry.clone(); 299 Integer callback = 0; 300 registry.add(callback); 301 assertFalse(registry.isEmpty()); 302 assertTrue(registry2.isEmpty()); 303 registry2 = registry.clone(); 304 assertFalse(registry2.isEmpty()); 305 } 306 } 307