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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mobile/android/tests/background/junit3/src/sync/TestResetting.java	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,205 @@
     1.4 +/* Any copyright is dedicated to the Public Domain.
     1.5 +   http://creativecommons.org/publicdomain/zero/1.0/ */
     1.6 +
     1.7 +package org.mozilla.gecko.background.sync;
     1.8 +
     1.9 +import java.io.IOException;
    1.10 +
    1.11 +import org.json.simple.parser.ParseException;
    1.12 +import org.mozilla.gecko.background.helpers.AndroidSyncTestCase;
    1.13 +import org.mozilla.gecko.background.testhelpers.BaseMockServerSyncStage;
    1.14 +import org.mozilla.gecko.background.testhelpers.DefaultGlobalSessionCallback;
    1.15 +import org.mozilla.gecko.background.testhelpers.MockRecord;
    1.16 +import org.mozilla.gecko.background.testhelpers.MockSharedPreferences;
    1.17 +import org.mozilla.gecko.background.testhelpers.WBORepository;
    1.18 +import org.mozilla.gecko.background.testhelpers.WaitHelper;
    1.19 +import org.mozilla.gecko.sync.EngineSettings;
    1.20 +import org.mozilla.gecko.sync.GlobalSession;
    1.21 +import org.mozilla.gecko.sync.MetaGlobalException;
    1.22 +import org.mozilla.gecko.sync.NonObjectJSONException;
    1.23 +import org.mozilla.gecko.sync.SyncConfiguration;
    1.24 +import org.mozilla.gecko.sync.SyncConfigurationException;
    1.25 +import org.mozilla.gecko.sync.SynchronizerConfiguration;
    1.26 +import org.mozilla.gecko.sync.crypto.CryptoException;
    1.27 +import org.mozilla.gecko.sync.crypto.KeyBundle;
    1.28 +import org.mozilla.gecko.sync.delegates.GlobalSessionCallback;
    1.29 +import org.mozilla.gecko.sync.net.AuthHeaderProvider;
    1.30 +import org.mozilla.gecko.sync.net.BasicAuthHeaderProvider;
    1.31 +import org.mozilla.gecko.sync.repositories.domain.Record;
    1.32 +import org.mozilla.gecko.sync.stage.NoSuchStageException;
    1.33 +import org.mozilla.gecko.sync.synchronizer.Synchronizer;
    1.34 +
    1.35 +import android.content.SharedPreferences;
    1.36 +
    1.37 +/**
    1.38 + * Test the on-device side effects of reset operations on a stage.
    1.39 + *
    1.40 + * See also "TestResetCommands" in the unit test suite.
    1.41 + */
    1.42 +public class TestResetting extends AndroidSyncTestCase {
    1.43 +  private static final String TEST_USERNAME    = "johndoe";
    1.44 +  private static final String TEST_PASSWORD    = "password";
    1.45 +  private static final String TEST_SYNC_KEY    = "abcdeabcdeabcdeabcdeabcdea";
    1.46 +
    1.47 +  @Override
    1.48 +  public void setUp() {
    1.49 +    assertTrue(WaitHelper.getTestWaiter().isIdle());
    1.50 +  }
    1.51 +
    1.52 +  /**
    1.53 +   * Set up a mock stage that synchronizes two mock repositories. Apply various
    1.54 +   * reset/sync/wipe permutations and check state.
    1.55 +   */
    1.56 +  public void testResetAndWipeStage() throws Exception {
    1.57 +
    1.58 +    final long startTime = System.currentTimeMillis();
    1.59 +    final GlobalSessionCallback callback = createGlobalSessionCallback();
    1.60 +    final GlobalSession session = createDefaultGlobalSession(callback);
    1.61 +
    1.62 +    final ExecutableMockServerSyncStage stage = new ExecutableMockServerSyncStage() {
    1.63 +      @Override
    1.64 +      public void onSynchronized(Synchronizer synchronizer) {
    1.65 +        try {
    1.66 +          assertTrue(startTime <= synchronizer.bundleA.getTimestamp());
    1.67 +          assertTrue(startTime <= synchronizer.bundleB.getTimestamp());
    1.68 +
    1.69 +          // Call up to allow the usual persistence etc. to happen.
    1.70 +          super.onSynchronized(synchronizer);
    1.71 +        } catch (Throwable e) {
    1.72 +          performNotify(e);
    1.73 +          return;
    1.74 +        }
    1.75 +        performNotify();
    1.76 +      }
    1.77 +    };
    1.78 +
    1.79 +    final boolean bumpTimestamps = true;
    1.80 +    WBORepository local = new WBORepository(bumpTimestamps);
    1.81 +    WBORepository remote = new WBORepository(bumpTimestamps);
    1.82 +
    1.83 +    stage.name       = "mock";
    1.84 +    stage.collection = "mock";
    1.85 +    stage.local      = local;
    1.86 +    stage.remote     = remote;
    1.87 +
    1.88 +    stage.executeSynchronously(session);
    1.89 +
    1.90 +    // Verify the persisted values.
    1.91 +    assertConfigTimestampsGreaterThan(stage.leakConfig(), startTime, startTime);
    1.92 +
    1.93 +    // Reset.
    1.94 +    stage.resetLocal(session);
    1.95 +
    1.96 +    // Verify that they're gone.
    1.97 +    assertConfigTimestampsEqual(stage.leakConfig(), 0, 0);
    1.98 +
    1.99 +    // Now sync data, ensure that timestamps come back.
   1.100 +    final long afterReset = System.currentTimeMillis();
   1.101 +    final String recordGUID = "abcdefghijkl";
   1.102 +    local.wbos.put(recordGUID, new MockRecord(recordGUID, "mock", startTime, false));
   1.103 +
   1.104 +    // Sync again with data and verify timestamps and data.
   1.105 +    stage.executeSynchronously(session);
   1.106 +
   1.107 +    assertConfigTimestampsGreaterThan(stage.leakConfig(), afterReset, afterReset);
   1.108 +    assertEquals(1, remote.wbos.size());
   1.109 +    assertEquals(1, local.wbos.size());
   1.110 +
   1.111 +    Record remoteRecord = remote.wbos.get(recordGUID);
   1.112 +    assertNotNull(remoteRecord);
   1.113 +    assertNotNull(local.wbos.get(recordGUID));
   1.114 +    assertEquals(recordGUID, remoteRecord.guid);
   1.115 +    assertTrue(afterReset <= remoteRecord.lastModified);
   1.116 +
   1.117 +    // Reset doesn't clear data.
   1.118 +    stage.resetLocal(session);
   1.119 +    assertConfigTimestampsEqual(stage.leakConfig(), 0, 0);
   1.120 +    assertEquals(1, remote.wbos.size());
   1.121 +    assertEquals(1, local.wbos.size());
   1.122 +    remoteRecord = remote.wbos.get(recordGUID);
   1.123 +    assertNotNull(remoteRecord);
   1.124 +    assertNotNull(local.wbos.get(recordGUID));
   1.125 +
   1.126 +    // Wipe does. Recover from reset...
   1.127 +    final long beforeWipe = System.currentTimeMillis();
   1.128 +    stage.executeSynchronously(session);
   1.129 +    assertEquals(1, remote.wbos.size());
   1.130 +    assertEquals(1, local.wbos.size());
   1.131 +    assertConfigTimestampsGreaterThan(stage.leakConfig(), beforeWipe, beforeWipe);
   1.132 +
   1.133 +    // ... then wipe.
   1.134 +    stage.wipeLocal(session);
   1.135 +    assertConfigTimestampsEqual(stage.leakConfig(), 0, 0);
   1.136 +    assertEquals(1, remote.wbos.size());     // We don't wipe the server.
   1.137 +    assertEquals(0, local.wbos.size());      // We do wipe local.
   1.138 +  }
   1.139 +
   1.140 +  /**
   1.141 +   * A stage that joins two Repositories with no wrapping.
   1.142 +   */
   1.143 +  public class ExecutableMockServerSyncStage extends BaseMockServerSyncStage {
   1.144 +    /**
   1.145 +     * Run this stage synchronously.
   1.146 +     */
   1.147 +    public void executeSynchronously(final GlobalSession session) {
   1.148 +      final BaseMockServerSyncStage self = this;
   1.149 +      performWait(new Runnable() {
   1.150 +        @Override
   1.151 +        public void run() {
   1.152 +          try {
   1.153 +            self.execute(session);
   1.154 +          } catch (NoSuchStageException e) {
   1.155 +            performNotify(e);
   1.156 +          }
   1.157 +        }
   1.158 +      });
   1.159 +    }
   1.160 +  }
   1.161 +
   1.162 +  private GlobalSession createDefaultGlobalSession(final GlobalSessionCallback callback) throws SyncConfigurationException, IllegalArgumentException, NonObjectJSONException, IOException, ParseException, CryptoException {
   1.163 +
   1.164 +    final KeyBundle keyBundle = new KeyBundle(TEST_USERNAME, TEST_SYNC_KEY);
   1.165 +    final AuthHeaderProvider authHeaderProvider = new BasicAuthHeaderProvider(TEST_USERNAME, TEST_PASSWORD);
   1.166 +    final SharedPreferences prefs = new MockSharedPreferences();
   1.167 +    final SyncConfiguration config = new SyncConfiguration(TEST_USERNAME, authHeaderProvider, prefs);
   1.168 +    config.syncKeyBundle = keyBundle;
   1.169 +    return new GlobalSession(config, callback, getApplicationContext(), null, callback) {
   1.170 +      @Override
   1.171 +      public boolean isEngineRemotelyEnabled(String engineName,
   1.172 +                                     EngineSettings engineSettings)
   1.173 +        throws MetaGlobalException {
   1.174 +        return true;
   1.175 +      }
   1.176 +
   1.177 +      @Override
   1.178 +      public void advance() {
   1.179 +        // So we don't proceed and run other stages.
   1.180 +      }
   1.181 +    };
   1.182 +  }
   1.183 +
   1.184 +  private static GlobalSessionCallback createGlobalSessionCallback() {
   1.185 +    return new DefaultGlobalSessionCallback() {
   1.186 +
   1.187 +      @Override
   1.188 +      public void handleAborted(GlobalSession globalSession, String reason) {
   1.189 +        performNotify(new Exception("Aborted"));
   1.190 +      }
   1.191 +
   1.192 +      @Override
   1.193 +      public void handleError(GlobalSession globalSession, Exception ex) {
   1.194 +        performNotify(ex);
   1.195 +      }
   1.196 +    };
   1.197 +  }
   1.198 +
   1.199 +  private static void assertConfigTimestampsGreaterThan(SynchronizerConfiguration config, long local, long remote) {
   1.200 +    assertTrue(local <= config.localBundle.getTimestamp());
   1.201 +    assertTrue(remote <= config.remoteBundle.getTimestamp());
   1.202 +  }
   1.203 +
   1.204 +  private static void assertConfigTimestampsEqual(SynchronizerConfiguration config, long local, long remote) {
   1.205 +    assertEquals(local, config.localBundle.getTimestamp());
   1.206 +    assertEquals(remote, config.remoteBundle.getTimestamp());
   1.207 +  }
   1.208 +}

mercurial