mobile/android/tests/background/junit3/src/sync/TestUpgradeRequired.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /* Any copyright is dedicated to the Public Domain.
     2    http://creativecommons.org/publicdomain/zero/1.0/ */
     4 package org.mozilla.gecko.background.sync;
     6 import java.io.IOException;
     7 import java.io.UnsupportedEncodingException;
     9 import org.json.simple.parser.ParseException;
    10 import org.mozilla.gecko.background.helpers.AndroidSyncTestCase;
    11 import org.mozilla.gecko.background.testhelpers.DefaultGlobalSessionCallback;
    12 import org.mozilla.gecko.background.testhelpers.MockGlobalSession;
    13 import org.mozilla.gecko.background.testhelpers.MockSharedPreferences;
    14 import org.mozilla.gecko.db.BrowserContract;
    15 import org.mozilla.gecko.sync.GlobalSession;
    16 import org.mozilla.gecko.sync.NonObjectJSONException;
    17 import org.mozilla.gecko.sync.SyncConfiguration;
    18 import org.mozilla.gecko.sync.SyncConfigurationException;
    19 import org.mozilla.gecko.sync.SyncConstants;
    20 import org.mozilla.gecko.sync.crypto.CryptoException;
    21 import org.mozilla.gecko.sync.crypto.KeyBundle;
    22 import org.mozilla.gecko.sync.delegates.GlobalSessionCallback;
    23 import org.mozilla.gecko.sync.net.BasicAuthHeaderProvider;
    24 import org.mozilla.gecko.sync.setup.Constants;
    25 import org.mozilla.gecko.sync.setup.SyncAccounts;
    26 import org.mozilla.gecko.sync.setup.SyncAccounts.SyncAccountParameters;
    27 import org.mozilla.gecko.sync.syncadapter.SyncAdapter;
    29 import android.accounts.Account;
    30 import android.accounts.AccountManager;
    31 import android.content.ContentResolver;
    32 import android.content.Context;
    33 import ch.boye.httpclientandroidlib.HttpEntity;
    34 import ch.boye.httpclientandroidlib.HttpResponse;
    35 import ch.boye.httpclientandroidlib.ProtocolVersion;
    36 import ch.boye.httpclientandroidlib.entity.StringEntity;
    37 import ch.boye.httpclientandroidlib.message.BasicHttpResponse;
    39 /**
    40  * When syncing and a server responds with a 400 "Upgrade Required," Sync
    41  * accounts should be disabled.
    42  *
    43  * (We are not testing for package updating, because MY_PACKAGE_REPLACED
    44  * broadcasts can only be sent by the system. Testing for package replacement
    45  * needs to be done manually on a device.)
    46  *
    47  * @author liuche
    48  *
    49  */
    50 public class TestUpgradeRequired extends AndroidSyncTestCase {
    51   private final String  TEST_SERVER      = "http://test.ser.ver/";
    53   private static final String TEST_USERNAME     = "user1";
    54   private static final String TEST_PASSWORD     = "pass1";
    55   private static final String TEST_SYNC_KEY     = "abcdeabcdeabcdeabcdeabcdea";
    57   private Context context;
    59   public static boolean syncsAutomatically(Account a) {
    60     return ContentResolver.getSyncAutomatically(a, BrowserContract.AUTHORITY);
    61   }
    63   public static boolean isSyncable(Account a) {
    64     return 1 == ContentResolver.getIsSyncable(a, BrowserContract.AUTHORITY);
    65   }
    67   public static boolean willEnableOnUpgrade(Account a, AccountManager accountManager) {
    68     return "1".equals(accountManager.getUserData(a, Constants.DATA_ENABLE_ON_UPGRADE));
    69   }
    71   private static Account getTestAccount(AccountManager accountManager) {
    72     final String type = SyncConstants.ACCOUNTTYPE_SYNC;
    73     Account[] existing = accountManager.getAccountsByType(type);
    74     for (Account account : existing) {
    75       if (account.name.equals(TEST_USERNAME)) {
    76         return account;
    77       }
    78     }
    79     return null;
    80   }
    82   private void deleteTestAccount() {
    83     final AccountManager accountManager = AccountManager.get(context);
    84     final Account found = getTestAccount(accountManager);
    85     if (found == null) {
    86       return;
    87     }
    88     TestSyncAccounts.deleteAccount(this, accountManager, found);
    89   }
    91   @Override
    92   public void setUp() {
    93     context = getApplicationContext();
    94     final AccountManager accountManager = AccountManager.get(context);
    96     deleteTestAccount();
    98     // Set up and enable Sync accounts.
    99     SyncAccountParameters syncAccountParams = new SyncAccountParameters(context, accountManager, TEST_USERNAME, TEST_PASSWORD, TEST_SYNC_KEY, TEST_SERVER, null, null, null);
   100     final Account account = SyncAccounts.createSyncAccount(syncAccountParams, true);
   101     assertNotNull(account);
   102     assertTrue(syncsAutomatically(account));
   103     assertTrue(isSyncable(account));
   104   }
   106   private static class LeakySyncAdapter extends SyncAdapter {
   107     public LeakySyncAdapter(Context context, boolean autoInitialize, Account account) {
   108       super(context, autoInitialize);
   109       this.localAccount = account;
   110     }
   111   }
   113   /**
   114    * Verify that when SyncAdapter is informed of an Upgrade Required
   115    * response, that it disables the account it's syncing.
   116    */
   117   public void testInformUpgradeRequired() {
   118     final AccountManager accountManager = AccountManager.get(context);
   119     final Account account = getTestAccount(accountManager);
   121     assertNotNull(account);
   122     assertTrue(syncsAutomatically(account));
   123     assertTrue(isSyncable(account));
   124     assertFalse(willEnableOnUpgrade(account, accountManager));
   126     LeakySyncAdapter adapter = new LeakySyncAdapter(context, true, account);
   127     adapter.informUpgradeRequiredResponse(null);
   129     // Oh god.
   130     try {
   131       Thread.sleep(1000);
   132     } catch (InterruptedException e) {
   133       e.printStackTrace();
   134     }
   136     // We have disabled the account, but it's still syncable.
   137     assertFalse(syncsAutomatically(account));
   138     assertTrue(isSyncable(account));
   139     assertTrue(willEnableOnUpgrade(account, accountManager));
   140   }
   142   private class Result {
   143     public boolean called = false;
   144   }
   146   public static HttpResponse simulate400() {
   147     HttpResponse response = new BasicHttpResponse(new ProtocolVersion("HTTP", 1, 1), 400, "Bad Request") {
   148       @Override
   149       public HttpEntity getEntity() {
   150         try {
   151           return new StringEntity("16");
   152         } catch (UnsupportedEncodingException e) {
   153           // Never happens.
   154           return null;
   155         }
   156       }
   157     };
   158     return response;
   159   }
   161   /**
   162    * Verify that when a 400 response is received with an
   163    * "Upgrade Required" response code body, we call
   164    * informUpgradeRequiredResponse on the delegate.
   165    */
   166   public void testUpgradeResponse() throws SyncConfigurationException, IllegalArgumentException, NonObjectJSONException, IOException, ParseException, CryptoException {
   167     final Result calledUpgradeRequired = new Result();
   168     final GlobalSessionCallback callback = new DefaultGlobalSessionCallback() {
   169       @Override
   170       public void informUpgradeRequiredResponse(final GlobalSession session) {
   171         calledUpgradeRequired.called = true;
   172       }
   173     };
   175     MockSharedPreferences prefs = new MockSharedPreferences();
   176     SyncConfiguration config = new SyncConfiguration(TEST_USERNAME, new BasicAuthHeaderProvider(TEST_USERNAME, TEST_PASSWORD), prefs);
   177     config.syncKeyBundle = new KeyBundle(TEST_USERNAME, TEST_SYNC_KEY);
   178     final GlobalSession session = new MockGlobalSession(config, callback);
   180     session.interpretHTTPFailure(simulate400());
   181     assertTrue(calledUpgradeRequired.called);
   182   }
   184   @Override
   185   public void tearDown() {
   186     deleteTestAccount();
   187   }
   188 }

mercurial