blob: cabdced300b74262d80809d178c9fad035d14ab8 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.sync;
import android.accounts.Account;
import android.content.Context;
import android.os.Bundle;
import android.test.FlakyTest;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import org.chromium.base.ThreadUtils;
import org.chromium.base.test.util.DisabledTest;
import org.chromium.base.test.util.Feature;
import org.chromium.sync.AndroidSyncSettings.AndroidSyncSettingsObserver;
import org.chromium.sync.signin.AccountManagerHelper;
import org.chromium.sync.test.util.AccountHolder;
import org.chromium.sync.test.util.MockAccountManager;
import org.chromium.sync.test.util.MockSyncContentResolverDelegate;
/**
* Tests for AndroidSyncSettings.
*/
public class AndroidSyncSettingsTest extends InstrumentationTestCase {
private static class CountingMockSyncContentResolverDelegate
extends MockSyncContentResolverDelegate {
private int mGetMasterSyncAutomaticallyCalls;
private int mGetSyncAutomaticallyCalls;
private int mGetIsSyncableCalls;
private int mSetIsSyncableCalls;
private int mSetSyncAutomaticallyCalls;
private int mRemovePeriodicSyncCalls;
@Override
public boolean getMasterSyncAutomatically() {
mGetMasterSyncAutomaticallyCalls++;
return super.getMasterSyncAutomatically();
}
@Override
public boolean getSyncAutomatically(Account account, String authority) {
mGetSyncAutomaticallyCalls++;
return super.getSyncAutomatically(account, authority);
}
@Override
public int getIsSyncable(Account account, String authority) {
mGetIsSyncableCalls++;
return super.getIsSyncable(account, authority);
}
@Override
public void setIsSyncable(Account account, String authority, int syncable) {
mSetIsSyncableCalls++;
super.setIsSyncable(account, authority, syncable);
}
@Override
public void setSyncAutomatically(Account account, String authority, boolean sync) {
mSetSyncAutomaticallyCalls++;
super.setSyncAutomatically(account, authority, sync);
}
@Override
public void removePeriodicSync(Account account, String authority, Bundle extras) {
mRemovePeriodicSyncCalls++;
super.removePeriodicSync(account, authority, extras);
}
}
private static class MockSyncSettingsObserver implements AndroidSyncSettingsObserver {
private boolean mReceivedNotification;
public void clearNotification() {
mReceivedNotification = false;
}
public boolean receivedNotification() {
return mReceivedNotification;
}
@Override
public void androidSyncSettingsChanged() {
mReceivedNotification = true;
}
}
private Context mContext;
private CountingMockSyncContentResolverDelegate mSyncContentResolverDelegate;
private String mAuthority;
private Account mAccount;
private Account mAlternateAccount;
private MockSyncSettingsObserver mSyncSettingsObserver;
private MockAccountManager mAccountManager;
@Override
protected void setUp() throws Exception {
mSyncContentResolverDelegate = new CountingMockSyncContentResolverDelegate();
mContext = getInstrumentation().getTargetContext();
setupTestAccounts(mContext);
AndroidSyncSettings.overrideForTests(mContext, mSyncContentResolverDelegate);
mAuthority = AndroidSyncSettings.getContractAuthority(mContext);
AndroidSyncSettings.updateAccount(mContext, mAccount);
mSyncSettingsObserver = new MockSyncSettingsObserver();
AndroidSyncSettings.registerObserver(mContext, mSyncSettingsObserver);
super.setUp();
}
private void setupTestAccounts(Context context) {
mAccountManager = new MockAccountManager(context, context);
AccountManagerHelper.overrideAccountManagerHelperForTests(context, mAccountManager);
mAccount = setupTestAccount("account@example.com");
mAlternateAccount = setupTestAccount("alternate@example.com");
}
private Account setupTestAccount(String accountName) {
Account account = AccountManagerHelper.createAccountFromName(accountName);
AccountHolder.Builder accountHolder =
AccountHolder.create().account(account).password("password").alwaysAccept(true);
mAccountManager.addAccountHolderExplicitly(accountHolder.build());
return account;
}
private void enableChromeSyncOnUiThread() {
ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@Override
public void run() {
AndroidSyncSettings.enableChromeSync(mContext);
}
});
}
private void disableChromeSyncOnUiThread() {
ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@Override
public void run() {
AndroidSyncSettings.disableChromeSync(mContext);
}
});
}
@FlakyTest
/*
* http://crbug.com/554154
* @SmallTest
* @Feature({"Sync"})
*/
public void testAccountInitialization() throws InterruptedException {
// mAccount was set to be syncable and not have periodic syncs.
assertEquals(1, mSyncContentResolverDelegate.mSetIsSyncableCalls);
assertEquals(1, mSyncContentResolverDelegate.mRemovePeriodicSyncCalls);
AndroidSyncSettings.updateAccount(mContext, null);
getInstrumentation().waitForIdleSync();
// mAccount was set to be not syncable.
assertEquals(2, mSyncContentResolverDelegate.mSetIsSyncableCalls);
assertEquals(1, mSyncContentResolverDelegate.mRemovePeriodicSyncCalls);
AndroidSyncSettings.updateAccount(mContext, mAlternateAccount);
// mAlternateAccount was set to be syncable and not have periodic syncs.
assertEquals(3, mSyncContentResolverDelegate.mSetIsSyncableCalls);
assertEquals(2, mSyncContentResolverDelegate.mRemovePeriodicSyncCalls);
}
@SmallTest
@Feature({"Sync"})
public void testToggleMasterSyncFromSettings() throws InterruptedException {
mSyncContentResolverDelegate.setMasterSyncAutomatically(true);
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
assertTrue("master sync should be set",
AndroidSyncSettings.isMasterSyncEnabled(mContext));
mSyncContentResolverDelegate.setMasterSyncAutomatically(false);
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
assertFalse("master sync should be unset",
AndroidSyncSettings.isMasterSyncEnabled(mContext));
}
@SmallTest
@Feature({"Sync"})
public void testToggleChromeSyncFromSettings() throws InterruptedException {
// Turn on syncability.
mSyncContentResolverDelegate.setMasterSyncAutomatically(true);
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
// First sync
mSyncContentResolverDelegate.setIsSyncable(mAccount, mAuthority, 1);
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
mSyncContentResolverDelegate.setSyncAutomatically(mAccount, mAuthority, true);
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
assertTrue("sync should be set", AndroidSyncSettings.isSyncEnabled(mContext));
assertTrue("sync should be set for chrome app",
AndroidSyncSettings.isChromeSyncEnabled(mContext));
// Disable sync automatically for the app
mSyncContentResolverDelegate.setSyncAutomatically(mAccount, mAuthority, false);
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
assertFalse("sync should be unset", AndroidSyncSettings.isSyncEnabled(mContext));
assertFalse("sync should be unset for chrome app",
AndroidSyncSettings.isChromeSyncEnabled(mContext));
// Re-enable sync
mSyncContentResolverDelegate.setSyncAutomatically(mAccount, mAuthority, true);
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
assertTrue("sync should be re-enabled", AndroidSyncSettings.isSyncEnabled(mContext));
assertTrue("sync should be set for chrome app",
AndroidSyncSettings.isChromeSyncEnabled(mContext));
// Disabled from master sync
mSyncContentResolverDelegate.setMasterSyncAutomatically(false);
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
assertFalse("sync should be disabled due to master sync",
AndroidSyncSettings.isSyncEnabled(mContext));
assertFalse("master sync should be disabled",
AndroidSyncSettings.isMasterSyncEnabled(mContext));
assertTrue("sync should be set for chrome app",
AndroidSyncSettings.isChromeSyncEnabled(mContext));
}
@SmallTest
@Feature({"Sync"})
public void testToggleAccountSyncFromApplication() throws InterruptedException {
// Turn on syncability.
mSyncContentResolverDelegate.setMasterSyncAutomatically(true);
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
enableChromeSyncOnUiThread();
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
assertTrue("account should be synced", AndroidSyncSettings.isSyncEnabled(mContext));
disableChromeSyncOnUiThread();
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
assertFalse("account should not be synced", AndroidSyncSettings.isSyncEnabled(mContext));
}
@SmallTest
@Feature({"Sync"})
public void testToggleSyncabilityForMultipleAccounts() throws InterruptedException {
// Turn on syncability.
mSyncContentResolverDelegate.setMasterSyncAutomatically(true);
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
enableChromeSyncOnUiThread();
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
assertTrue("account should be synced", AndroidSyncSettings.isSyncEnabled(mContext));
AndroidSyncSettings.updateAccount(mContext, mAlternateAccount);
enableChromeSyncOnUiThread();
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
assertTrue("alternate account should be synced",
AndroidSyncSettings.isSyncEnabled(mContext));
disableChromeSyncOnUiThread();
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
assertFalse("alternate account should not be synced",
AndroidSyncSettings.isSyncEnabled(mContext));
AndroidSyncSettings.updateAccount(mContext, mAccount);
assertTrue("account should still be synced", AndroidSyncSettings.isSyncEnabled(mContext));
// Ensure we don't erroneously re-use cached data.
AndroidSyncSettings.updateAccount(mContext, null);
assertFalse("null account should not be synced",
AndroidSyncSettings.isSyncEnabled(mContext));
}
@SmallTest
@Feature({"Sync"})
public void testSyncSettingsCaching() throws InterruptedException {
// Turn on syncability.
mSyncContentResolverDelegate.setMasterSyncAutomatically(true);
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
enableChromeSyncOnUiThread();
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
assertTrue("account should be synced", AndroidSyncSettings.isSyncEnabled(mContext));
int masterSyncAutomaticallyCalls =
mSyncContentResolverDelegate.mGetMasterSyncAutomaticallyCalls;
int isSyncableCalls = mSyncContentResolverDelegate.mGetIsSyncableCalls;
int getSyncAutomaticallyAcalls = mSyncContentResolverDelegate.mGetSyncAutomaticallyCalls;
// Do a bunch of reads.
AndroidSyncSettings.isMasterSyncEnabled(mContext);
AndroidSyncSettings.isSyncEnabled(mContext);
AndroidSyncSettings.isChromeSyncEnabled(mContext);
// Ensure values were read from cache.
assertEquals(masterSyncAutomaticallyCalls,
mSyncContentResolverDelegate.mGetMasterSyncAutomaticallyCalls);
assertEquals(isSyncableCalls, mSyncContentResolverDelegate.mGetIsSyncableCalls);
assertEquals(getSyncAutomaticallyAcalls,
mSyncContentResolverDelegate.mGetSyncAutomaticallyCalls);
// Do a bunch of reads for alternate account.
AndroidSyncSettings.updateAccount(mContext, mAlternateAccount);
AndroidSyncSettings.isMasterSyncEnabled(mContext);
AndroidSyncSettings.isSyncEnabled(mContext);
AndroidSyncSettings.isChromeSyncEnabled(mContext);
// Ensure settings were only fetched once.
assertEquals(masterSyncAutomaticallyCalls + 1,
mSyncContentResolverDelegate.mGetMasterSyncAutomaticallyCalls);
assertEquals(isSyncableCalls + 1, mSyncContentResolverDelegate.mGetIsSyncableCalls);
assertEquals(getSyncAutomaticallyAcalls + 1,
mSyncContentResolverDelegate.mGetSyncAutomaticallyCalls);
}
@SmallTest
@Feature({"Sync"})
public void testGetContractAuthority() throws Exception {
assertEquals("The contract authority should be the package name.",
getInstrumentation().getTargetContext().getPackageName(),
AndroidSyncSettings.getContractAuthority(mContext));
}
/*@SmallTest
@Feature({"Sync"})*/
// http://crbug.com/527856
@DisabledTest
public void testAndroidSyncSettingsPostsNotifications() throws InterruptedException {
// Turn on syncability.
mSyncContentResolverDelegate.setMasterSyncAutomatically(true);
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
mSyncSettingsObserver.clearNotification();
AndroidSyncSettings.enableChromeSync(mContext);
assertTrue("enableChromeSync should trigger observers",
mSyncSettingsObserver.receivedNotification());
mSyncSettingsObserver.clearNotification();
AndroidSyncSettings.updateAccount(mContext, mAlternateAccount);
assertTrue("switching to account with different settings should notify",
mSyncSettingsObserver.receivedNotification());
mSyncSettingsObserver.clearNotification();
AndroidSyncSettings.updateAccount(mContext, mAccount);
assertTrue("switching to account with different settings should notify",
mSyncSettingsObserver.receivedNotification());
mSyncSettingsObserver.clearNotification();
AndroidSyncSettings.enableChromeSync(mContext);
assertFalse("enableChromeSync shouldn't trigger observers",
mSyncSettingsObserver.receivedNotification());
mSyncSettingsObserver.clearNotification();
AndroidSyncSettings.disableChromeSync(mContext);
assertTrue("disableChromeSync should trigger observers",
mSyncSettingsObserver.receivedNotification());
mSyncSettingsObserver.clearNotification();
AndroidSyncSettings.disableChromeSync(mContext);
assertFalse("disableChromeSync shouldn't observers",
mSyncSettingsObserver.receivedNotification());
}
@SmallTest
@Feature({"Sync"})
public void testIsSyncableOnSigninAndNotOnSignout() throws InterruptedException {
assertTrue(mSyncContentResolverDelegate.getIsSyncable(mAccount, mAuthority) == 1);
AndroidSyncSettings.updateAccount(mContext, null);
getInstrumentation().waitForIdleSync();
assertTrue(mSyncContentResolverDelegate.getIsSyncable(mAccount, mAuthority) == 0);
AndroidSyncSettings.updateAccount(mContext, mAccount);
assertTrue(mSyncContentResolverDelegate.getIsSyncable(mAccount, mAuthority) == 1);
}
/**
* Regression test for crbug.com/475299.
*/
@SmallTest
@Feature({"Sync"})
public void testSyncableIsAlwaysSetWhenEnablingSync() throws InterruptedException {
// Setup bad state.
mSyncContentResolverDelegate.setMasterSyncAutomatically(true);
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
mSyncContentResolverDelegate.setIsSyncable(mAccount, mAuthority, 1);
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
mSyncContentResolverDelegate.setSyncAutomatically(mAccount, mAuthority, true);
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
mSyncContentResolverDelegate.setIsSyncable(mAccount, mAuthority, 0);
mSyncContentResolverDelegate.waitForLastNotificationCompleted();
assertTrue(mSyncContentResolverDelegate.getIsSyncable(mAccount, mAuthority) == 0);
assertTrue(mSyncContentResolverDelegate.getSyncAutomatically(mAccount, mAuthority));
// Ensure bug is fixed.
AndroidSyncSettings.enableChromeSync(mContext);
assertTrue(mSyncContentResolverDelegate.getIsSyncable(mAccount, mAuthority) == 1);
// Should still be enabled.
assertTrue(mSyncContentResolverDelegate.getSyncAutomatically(mAccount, mAuthority));
}
}