Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / chrome / android / javatests / src / org / chromium / chrome / browser / invalidation / InvalidationControllerTest.java
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.invalidation;
6
7 import android.accounts.Account;
8 import android.app.Activity;
9 import android.content.ComponentName;
10 import android.content.Context;
11 import android.content.Intent;
12 import android.content.pm.PackageManager;
13 import android.test.InstrumentationTestCase;
14 import android.test.suitebuilder.annotation.SmallTest;
15
16 import com.google.ipc.invalidation.external.client.types.ObjectId;
17
18 import org.chromium.base.ActivityState;
19 import org.chromium.base.ApplicationState;
20 import org.chromium.base.ApplicationStatus;
21 import org.chromium.base.CollectionUtil;
22 import org.chromium.base.test.util.AdvancedMockContext;
23 import org.chromium.base.test.util.Feature;
24 import org.chromium.sync.internal_api.pub.base.ModelType;
25 import org.chromium.sync.notifier.InvalidationIntentProtocol;
26 import org.chromium.sync.notifier.InvalidationPreferences;
27 import org.chromium.sync.notifier.InvalidationService;
28 import org.chromium.sync.notifier.SyncStatusHelper;
29 import org.chromium.sync.signin.AccountManagerHelper;
30 import org.chromium.sync.signin.ChromeSigninController;
31 import org.chromium.sync.test.util.MockSyncContentResolverDelegate;
32
33 import java.util.ArrayList;
34 import java.util.HashSet;
35 import java.util.List;
36 import java.util.Set;
37 import java.util.concurrent.atomic.AtomicBoolean;
38 import java.util.concurrent.atomic.AtomicReference;
39
40 /**
41  * Tests for the {@link InvalidationController}.
42  */
43 public class InvalidationControllerTest extends InstrumentationTestCase {
44     private IntentSavingContext mContext;
45     private InvalidationController mController;
46
47     @Override
48     protected void setUp() throws Exception {
49         mContext = new IntentSavingContext(getInstrumentation().getTargetContext());
50         mController = InvalidationController.get(mContext);
51         // We don't want to use the system content resolver, so we override it.
52         MockSyncContentResolverDelegate delegate = new MockSyncContentResolverDelegate();
53         // Android master sync can safely always be on.
54         delegate.setMasterSyncAutomatically(true);
55         SyncStatusHelper.overrideSyncStatusHelperForTests(mContext, delegate);
56     }
57
58     @SmallTest
59     @Feature({"Sync"})
60     public void testStart() throws Exception {
61         mController.start();
62         assertEquals(1, mContext.getNumStartedIntents());
63         Intent intent = mContext.getStartedIntent(0);
64         validateIntentComponent(intent);
65     }
66
67     @SmallTest
68     @Feature({"Sync"})
69     public void testStop() throws Exception {
70         mController.stop();
71         assertEquals(1, mContext.getNumStartedIntents());
72         Intent intent = mContext.getStartedIntent(0);
73         validateIntentComponent(intent);
74         assertEquals(1, intent.getExtras().size());
75         assertTrue(intent.hasExtra(InvalidationIntentProtocol.EXTRA_STOP));
76         assertTrue(intent.getBooleanExtra(InvalidationIntentProtocol.EXTRA_STOP, false));
77     }
78
79     @SmallTest
80     @Feature({"Sync"})
81     public void testResumingMainActivity() throws Exception {
82         // Resuming main activity should trigger a start if sync is enabled.
83         setupSync(true);
84         mController.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES);
85         assertEquals(1, mContext.getNumStartedIntents());
86         Intent intent = mContext.getStartedIntent(0);
87         validateIntentComponent(intent);
88     }
89
90     @SmallTest
91     @Feature({"Sync"})
92     public void testResumingMainActivityWithSyncDisabled() throws Exception {
93         // Resuming main activity should NOT trigger a start if sync is disabled.
94         setupSync(false);
95         mController.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES);
96         assertEquals(0, mContext.getNumStartedIntents());
97     }
98
99     @SmallTest
100     @Feature({"Sync"})
101     public void testPausingMainActivity() throws Exception {
102         // Resuming main activity should trigger a stop if sync is enabled.
103         setupSync(true);
104         mController.onApplicationStateChange(ApplicationState.HAS_PAUSED_ACTIVITIES);
105         assertEquals(1, mContext.getNumStartedIntents());
106         Intent intent = mContext.getStartedIntent(0);
107         validateIntentComponent(intent);
108         assertEquals(1, intent.getExtras().size());
109         assertTrue(intent.hasExtra(InvalidationIntentProtocol.EXTRA_STOP));
110         assertTrue(intent.getBooleanExtra(InvalidationIntentProtocol.EXTRA_STOP, false));
111     }
112
113     @SmallTest
114     @Feature({"Sync"})
115     public void testPausingMainActivityWithSyncDisabled() throws Exception {
116         // Resuming main activity should NOT trigger a stop if sync is disabled.
117         setupSync(false);
118         mController.onApplicationStateChange(ApplicationState.HAS_PAUSED_ACTIVITIES);
119         assertEquals(0, mContext.getNumStartedIntents());
120     }
121
122     private void setupSync(boolean syncEnabled) {
123         Account account = AccountManagerHelper.createAccountFromName("test@gmail.com");
124         ChromeSigninController chromeSigninController = ChromeSigninController.get(mContext);
125         chromeSigninController.setSignedInAccountName(account.name);
126         SyncStatusHelper syncStatusHelper = SyncStatusHelper.get(mContext);
127         if (syncEnabled) {
128             syncStatusHelper.enableAndroidSync(account);
129         } else {
130             syncStatusHelper.disableAndroidSync(account);
131         }
132     }
133
134     @SmallTest
135     @Feature({"Sync"})
136     public void testEnsureConstructorRegistersListener() throws Exception {
137         final AtomicBoolean listenerCallbackCalled = new AtomicBoolean();
138
139         // Create instance.
140         new InvalidationController(mContext) {
141             @Override
142             public void onApplicationStateChange(int newState) {
143                 listenerCallbackCalled.set(true);
144             }
145         };
146
147         // Ensure initial state is correct.
148         assertFalse(listenerCallbackCalled.get());
149
150         // Ensure we get a callback, which means we have registered for them.
151         ApplicationStatus.onStateChangeForTesting(new Activity(), ActivityState.CREATED);
152         assertTrue(listenerCallbackCalled.get());
153     }
154
155     @SmallTest
156     @Feature({"Sync"})
157     public void testRegisterForSpecificTypes() {
158         InvalidationController controller = new InvalidationController(mContext);
159         Account account = new Account("test@example.com", "bogus");
160         controller.setRegisteredTypes(account, false,
161                 CollectionUtil.newHashSet(ModelType.BOOKMARK, ModelType.SESSION));
162         assertEquals(1, mContext.getNumStartedIntents());
163
164         // Validate destination.
165         Intent intent = mContext.getStartedIntent(0);
166         validateIntentComponent(intent);
167         assertEquals(InvalidationIntentProtocol.ACTION_REGISTER, intent.getAction());
168
169         // Validate account.
170         Account intentAccount =
171                 intent.getParcelableExtra(InvalidationIntentProtocol.EXTRA_ACCOUNT);
172         assertEquals(account, intentAccount);
173
174         // Validate registered types.
175         Set<String> expectedTypes = CollectionUtil.newHashSet(ModelType.BOOKMARK.name(),
176                 ModelType.SESSION.name());
177         Set<String> actualTypes = new HashSet<String>();
178         actualTypes.addAll(intent.getStringArrayListExtra(
179                                 InvalidationIntentProtocol.EXTRA_REGISTERED_TYPES));
180         assertEquals(expectedTypes, actualTypes);
181         assertNull(InvalidationIntentProtocol.getRegisteredObjectIds(intent));
182     }
183
184     @SmallTest
185     @Feature({"Sync"})
186     public void testRegisterForAllTypes() {
187         Account account = new Account("test@example.com", "bogus");
188         mController.setRegisteredTypes(account, true,
189                 CollectionUtil.newHashSet(ModelType.BOOKMARK, ModelType.SESSION));
190         assertEquals(1, mContext.getNumStartedIntents());
191
192         // Validate destination.
193         Intent intent = mContext.getStartedIntent(0);
194         validateIntentComponent(intent);
195         assertEquals(InvalidationIntentProtocol.ACTION_REGISTER, intent.getAction());
196
197         // Validate account.
198         Account intentAccount =
199                 intent.getParcelableExtra(InvalidationIntentProtocol.EXTRA_ACCOUNT);
200         assertEquals(account, intentAccount);
201
202         // Validate registered types.
203         Set<String> expectedTypes = CollectionUtil.newHashSet(ModelType.ALL_TYPES_TYPE);
204         Set<String> actualTypes = new HashSet<String>();
205         actualTypes.addAll(intent.getStringArrayListExtra(
206                                 InvalidationIntentProtocol.EXTRA_REGISTERED_TYPES));
207         assertEquals(expectedTypes, actualTypes);
208         assertNull(InvalidationIntentProtocol.getRegisteredObjectIds(intent));
209     }
210
211     @SmallTest
212     @Feature({"Sync"})
213     public void testRefreshShouldReadValuesFromDiskWithSpecificTypes() {
214         // Store some preferences for ModelTypes and account. We are using the helper class
215         // for this, so we don't have to deal with low-level details such as preference keys.
216         InvalidationPreferences invalidationPreferences = new InvalidationPreferences(mContext);
217         InvalidationPreferences.EditContext edit = invalidationPreferences.edit();
218         Set<String> storedModelTypes = new HashSet<String>();
219         storedModelTypes.add(ModelType.BOOKMARK.name());
220         storedModelTypes.add(ModelType.TYPED_URL.name());
221         Set<ModelType> refreshedTypes = new HashSet<ModelType>();
222         refreshedTypes.add(ModelType.BOOKMARK);
223         refreshedTypes.add(ModelType.TYPED_URL);
224         invalidationPreferences.setSyncTypes(edit, storedModelTypes);
225         Account storedAccount = AccountManagerHelper.createAccountFromName("test@gmail.com");
226         invalidationPreferences.setAccount(edit, storedAccount);
227         invalidationPreferences.commit(edit);
228
229         // Ensure all calls to {@link InvalidationController#setRegisteredTypes} store values
230         // we can inspect in the test.
231         final AtomicReference<Account> resultAccount = new AtomicReference<Account>();
232         final AtomicBoolean resultAllTypes = new AtomicBoolean();
233         final AtomicReference<Set<ModelType>> resultTypes = new AtomicReference<Set<ModelType>>();
234         InvalidationController controller = new InvalidationController(mContext) {
235             @Override
236             public void setRegisteredTypes(
237                     Account account, boolean allTypes, Set<ModelType> types) {
238                 resultAccount.set(account);
239                 resultAllTypes.set(allTypes);
240                 resultTypes.set(types);
241             }
242         };
243
244         // Execute the test.
245         controller.refreshRegisteredTypes(refreshedTypes);
246
247         // Validate the values.
248         assertEquals(storedAccount, resultAccount.get());
249         assertEquals(false, resultAllTypes.get());
250         assertEquals(ModelType.syncTypesToModelTypes(storedModelTypes), resultTypes.get());
251     }
252
253     @SmallTest
254     @Feature({"Sync"})
255     public void testRefreshShouldReadValuesFromDiskWithAllTypes() {
256         // Store preferences for the ModelType.ALL_TYPES_TYPE and account. We
257         // are using the helper class for this, so we don't have to deal with
258         // low-level details such as preference keys.
259         InvalidationPreferences invalidationPreferences = new InvalidationPreferences(mContext);
260         InvalidationPreferences.EditContext edit = invalidationPreferences.edit();
261         List<String> storedModelTypes = new ArrayList<String>();
262         storedModelTypes.add(ModelType.ALL_TYPES_TYPE);
263         invalidationPreferences.setSyncTypes(edit, storedModelTypes);
264         Account storedAccount = AccountManagerHelper.createAccountFromName("test@gmail.com");
265         invalidationPreferences.setAccount(edit, storedAccount);
266         invalidationPreferences.commit(edit);
267
268         // Ensure all calls to {@link InvalidationController#setRegisteredTypes} store values
269         // we can inspect in the test.
270         final AtomicReference<Account> resultAccount = new AtomicReference<Account>();
271         final AtomicBoolean resultAllTypes = new AtomicBoolean();
272         final AtomicReference<Set<ModelType>> resultTypes = new AtomicReference<Set<ModelType>>();
273         InvalidationController controller = new InvalidationController(mContext) {
274             @Override
275             public void setRegisteredTypes(
276                     Account account, boolean allTypes, Set<ModelType> types) {
277                 resultAccount.set(account);
278                 resultAllTypes.set(allTypes);
279                 resultTypes.set(types);
280             }
281         };
282
283         // Execute the test.
284         controller.refreshRegisteredTypes(new HashSet<ModelType>());
285
286         // Validate the values.
287         assertEquals(storedAccount, resultAccount.get());
288         assertEquals(true, resultAllTypes.get());
289     }
290
291     @SmallTest
292     @Feature({"Sync"})
293     public void testSetRegisteredObjectIds() {
294         InvalidationController controller = new InvalidationController(mContext);
295         ObjectId bookmark = ModelType.BOOKMARK.toObjectId();
296         controller.setRegisteredObjectIds(new int[] {1, 2, bookmark.getSource()},
297                                           new String[] {"a", "b", new String(bookmark.getName())});
298         assertEquals(1, mContext.getNumStartedIntents());
299
300         // Validate destination.
301         Intent intent = mContext.getStartedIntent(0);
302         validateIntentComponent(intent);
303         assertEquals(InvalidationIntentProtocol.ACTION_REGISTER, intent.getAction());
304
305         // Validate registered object ids. The bookmark object should not be registered since it is
306         // a Sync type.
307         assertNull(intent.getStringArrayListExtra(
308                                 InvalidationIntentProtocol.EXTRA_REGISTERED_TYPES));
309         Set<ObjectId> objectIds = InvalidationIntentProtocol.getRegisteredObjectIds(intent);
310         assertEquals(2, objectIds.size());
311         assertTrue(objectIds.contains(ObjectId.newInstance(1, "a".getBytes())));
312         assertTrue(objectIds.contains(ObjectId.newInstance(2, "b".getBytes())));
313     }
314
315     /**
316      * Asserts that {@code intent} is destined for the correct component.
317      */
318     private static void validateIntentComponent(Intent intent) {
319         assertNotNull(intent.getComponent());
320         assertEquals(InvalidationService.class.getName(),
321                 intent.getComponent().getClassName());
322     }
323
324     /**
325      * Mock context that saves all intents given to {@code startService}.
326      */
327     private static class IntentSavingContext extends AdvancedMockContext {
328         private final List<Intent> startedIntents = new ArrayList<Intent>();
329
330         IntentSavingContext(Context targetContext) {
331             super(targetContext);
332         }
333
334         @Override
335         public ComponentName startService(Intent intent) {
336             startedIntents.add(intent);
337             return new ComponentName(this, getClass());
338         }
339
340         int getNumStartedIntents() {
341             return startedIntents.size();
342         }
343
344         Intent getStartedIntent(int idx) {
345             return startedIntents.get(idx);
346         }
347
348         @Override
349         public PackageManager getPackageManager() {
350             return getBaseContext().getPackageManager();
351         }
352     }
353
354 }