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