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