mobile/android/tests/background/junit3/src/db/TestPasswordsRepository.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.db;
     6 import java.util.HashSet;
     7 import java.util.Set;
     9 import org.mozilla.gecko.background.helpers.AndroidSyncTestCase;
    10 import org.mozilla.gecko.background.sync.helpers.ExpectFetchDelegate;
    11 import org.mozilla.gecko.background.sync.helpers.ExpectFetchSinceDelegate;
    12 import org.mozilla.gecko.background.sync.helpers.ExpectGuidsSinceDelegate;
    13 import org.mozilla.gecko.background.sync.helpers.ExpectStoredDelegate;
    14 import org.mozilla.gecko.background.sync.helpers.PasswordHelpers;
    15 import org.mozilla.gecko.background.sync.helpers.SessionTestHelper;
    16 import org.mozilla.gecko.background.testhelpers.WaitHelper;
    17 import org.mozilla.gecko.db.BrowserContract;
    18 import org.mozilla.gecko.sync.Utils;
    19 import org.mozilla.gecko.sync.repositories.InactiveSessionException;
    20 import org.mozilla.gecko.sync.repositories.NoStoreDelegateException;
    21 import org.mozilla.gecko.sync.repositories.Repository;
    22 import org.mozilla.gecko.sync.repositories.RepositorySession;
    23 import org.mozilla.gecko.sync.repositories.android.BrowserContractHelpers;
    24 import org.mozilla.gecko.sync.repositories.android.PasswordsRepositorySession;
    25 import org.mozilla.gecko.sync.repositories.android.RepoUtils;
    26 import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionCreationDelegate;
    27 import org.mozilla.gecko.sync.repositories.domain.PasswordRecord;
    28 import org.mozilla.gecko.sync.repositories.domain.Record;
    30 import android.content.ContentProviderClient;
    31 import android.content.Context;
    32 import android.database.Cursor;
    33 import android.os.RemoteException;
    35 public class TestPasswordsRepository extends AndroidSyncTestCase {
    36   private final String NEW_PASSWORD1 = "password";
    37   private final String NEW_PASSWORD2 = "drowssap";
    39   @Override
    40   public void setUp() {
    41     wipe();
    42     assertTrue(WaitHelper.getTestWaiter().isIdle());
    43   }
    45   public void testFetchAll() {
    46     RepositorySession session = createAndBeginSession();
    47     Record[] expected = new Record[] { PasswordHelpers.createPassword1(),
    48                                        PasswordHelpers.createPassword2() };
    50     performWait(storeRunnable(session, expected[0]));
    51     performWait(storeRunnable(session, expected[1]));
    53     performWait(fetchAllRunnable(session, expected));
    54     dispose(session);
    55   }
    57   public void testGuidsSinceReturnMultipleRecords() {
    58     RepositorySession session = createAndBeginSession();
    60     PasswordRecord record1 = PasswordHelpers.createPassword1();
    61     PasswordRecord record2 = PasswordHelpers.createPassword2();
    63     updatePassword(NEW_PASSWORD1, record1);
    64     long timestamp = updatePassword(NEW_PASSWORD2, record2);
    66     String[] expected = new String[] { record1.guid, record2.guid };
    68     performWait(storeRunnable(session, record1));
    69     performWait(storeRunnable(session, record2));
    71     performWait(guidsSinceRunnable(session, timestamp, expected));
    72     dispose(session);
    73   }
    75   public void testGuidsSinceReturnNoRecords() {
    76     RepositorySession session = createAndBeginSession();
    78     //  Store 1 record in the past.
    79     performWait(storeRunnable(session, PasswordHelpers.createPassword1()));
    81     String[] expected = {};
    82     performWait(guidsSinceRunnable(session, System.currentTimeMillis() + 1000, expected));
    83     dispose(session);
    84   }
    86   public void testFetchSinceOneRecord() {
    87     RepositorySession session = createAndBeginSession();
    89     // Passwords fetchSince checks timePasswordChanged, not insertion time.
    90     PasswordRecord record1 = PasswordHelpers.createPassword1();
    91     long timeModified1 = updatePassword(NEW_PASSWORD1, record1);
    92     performWait(storeRunnable(session, record1));
    94     PasswordRecord record2 = PasswordHelpers.createPassword2();
    95     long timeModified2 = updatePassword(NEW_PASSWORD2, record2);
    96     performWait(storeRunnable(session, record2));
    98     String[] expectedOne = new String[] { record2.guid };
    99     performWait(fetchSinceRunnable(session, timeModified2 - 10, expectedOne));
   101     String[] expectedBoth = new String[] { record1.guid, record2.guid };
   102     performWait(fetchSinceRunnable(session, timeModified1 - 10, expectedBoth));
   104     dispose(session);
   105   }
   107   public void testFetchSinceReturnNoRecords() {
   108    RepositorySession session = createAndBeginSession();
   110     performWait(storeRunnable(session, PasswordHelpers.createPassword2()));
   112     long timestamp = System.currentTimeMillis();
   114     performWait(fetchSinceRunnable(session, timestamp + 2000, new String[] {}));
   115     dispose(session);
   116   }
   118   public void testFetchOneRecordByGuid() {
   119     RepositorySession session = createAndBeginSession();
   120     Record record = PasswordHelpers.createPassword1();
   121     performWait(storeRunnable(session, record));
   122     performWait(storeRunnable(session, PasswordHelpers.createPassword2()));
   124     String[] guids = new String[] { record.guid };
   125     Record[] expected = new Record[] { record };
   126     performWait(fetchRunnable(session, guids, expected));
   127     dispose(session);
   128   }
   130   public void testFetchMultipleRecordsByGuids() {
   131     RepositorySession session = createAndBeginSession();
   132     PasswordRecord record1 = PasswordHelpers.createPassword1();
   133     PasswordRecord record2 = PasswordHelpers.createPassword2();
   134     PasswordRecord record3 = PasswordHelpers.createPassword3();
   136     performWait(storeRunnable(session, record1));
   137     performWait(storeRunnable(session, record2));
   138     performWait(storeRunnable(session, record3));
   140     String[] guids = new String[] { record1.guid, record2.guid };
   141     Record[] expected = new Record[] { record1, record2 };
   142     performWait(fetchRunnable(session, guids, expected));
   143     dispose(session);
   144   }
   146   public void testFetchNoRecordByGuid() {
   147     RepositorySession session = createAndBeginSession();
   148     Record record = PasswordHelpers.createPassword1();
   150     performWait(storeRunnable(session, record));
   151     performWait(fetchRunnable(session,
   152                               new String[] { Utils.generateGuid() },
   153                               new Record[] {}));
   154     dispose(session);
   155   }
   157   public void testStore() {
   158     final RepositorySession session = createAndBeginSession();
   159     performWait(storeRunnable(session, PasswordHelpers.createPassword1()));
   160     dispose(session);
   161   }
   163   public void testRemoteNewerTimeStamp() {
   164     final RepositorySession session = createAndBeginSession();
   166     // Store updated local record.
   167     PasswordRecord local = PasswordHelpers.createPassword1();
   168     updatePassword(NEW_PASSWORD1, local, System.currentTimeMillis() - 1000);
   169     performWait(storeRunnable(session, local));
   171     // Sync a remote record version that is newer.
   172     PasswordRecord remote = PasswordHelpers.createPassword2();
   173     remote.guid = local.guid;
   174     updatePassword(NEW_PASSWORD2, remote);
   175     performWait(storeRunnable(session, remote));
   177     // Make a fetch, expecting only the newer (remote) record.
   178     performWait(fetchAllRunnable(session, new Record[] { remote }));
   179     dispose(session);
   180   }
   182   public void testLocalNewerTimeStamp() {
   183     final RepositorySession session = createAndBeginSession();
   184     // Remote record updated before local record.
   185     PasswordRecord remote = PasswordHelpers.createPassword1();
   186     updatePassword(NEW_PASSWORD1, remote, System.currentTimeMillis() - 1000);
   188     // Store updated local record.
   189     PasswordRecord local = PasswordHelpers.createPassword2();
   190     updatePassword(NEW_PASSWORD2, local);
   191     performWait(storeRunnable(session, local));
   193     // Sync a remote record version that is older.
   194     remote.guid = local.guid;
   195     performWait(storeRunnable(session, remote));
   197     // Make a fetch, expecting only the newer (local) record.
   198     performWait(fetchAllRunnable(session, new Record[] { local }));
   199     dispose(session);
   200   }
   202   /*
   203    * Store two records that are identical except for guid. Expect to find the
   204    * remote one after reconciling.
   205    */
   206   public void testStoreIdenticalExceptGuid() {
   207     RepositorySession session = createAndBeginSession();
   208     PasswordRecord record = PasswordHelpers.createPassword1();
   209     record.guid = "before1";
   210     // Store record.
   211     performWait(storeRunnable(session, record));
   213     // Store same record, but with different guid.
   214     record.guid = Utils.generateGuid();
   215     performWait(storeRunnable(session, record));
   217     performWait(fetchAllRunnable(session, new Record[] { record }));
   218     dispose(session);
   220     session = createAndBeginSession();
   222     PasswordRecord record2 = PasswordHelpers.createPassword2();
   223     record2.guid = "before2";
   224     // Store record.
   225     performWait(storeRunnable(session, record2));
   227     // Store same record, but with different guid.
   228     record2.guid = Utils.generateGuid();
   229     performWait(storeRunnable(session, record2));
   231     performWait(fetchAllRunnable(session, new Record[] { record, record2 }));
   232     dispose(session);
   233   }
   235   /*
   236    * Store two records that are identical except for guid when they both point
   237    * to the same site and there are multiple records for that site. Expect to
   238    * find the remote one after reconciling.
   239    */
   240   public void testStoreIdenticalExceptGuidOnSameSite() {
   241     RepositorySession session = createAndBeginSession();
   242     PasswordRecord record1 = PasswordHelpers.createPassword1();
   243     record1.encryptedUsername = "original";
   244     record1.guid = "before1";
   245     PasswordRecord record2 = PasswordHelpers.createPassword1();
   246     record2.encryptedUsername = "different";
   247     record1.guid = "before2";
   248     // Store records.
   249     performWait(storeRunnable(session, record1));
   250     performWait(storeRunnable(session, record2));
   251     performWait(fetchAllRunnable(session, new Record[] { record1, record2 }));
   253     dispose(session);
   254     session = createAndBeginSession();
   256     // Store same records, but with different guids.
   257     record1.guid = Utils.generateGuid();
   258     performWait(storeRunnable(session, record1));
   259     performWait(fetchAllRunnable(session, new Record[] { record1, record2 }));
   261     record2.guid = Utils.generateGuid();
   262     performWait(storeRunnable(session, record2));
   263     performWait(fetchAllRunnable(session, new Record[] { record1, record2 }));
   265     dispose(session);
   266   }
   268   public void testRawFetch() throws RemoteException {
   269     RepositorySession session = createAndBeginSession();
   270     Record[] expected = new Record[] { PasswordHelpers.createPassword1(),
   271                                        PasswordHelpers.createPassword2() };
   273     performWait(storeRunnable(session, expected[0]));
   274     performWait(storeRunnable(session, expected[1]));
   276     ContentProviderClient client = getApplicationContext().getContentResolver().acquireContentProviderClient(BrowserContract.PASSWORDS_AUTHORITY_URI);
   277     Cursor cursor = client.query(BrowserContractHelpers.PASSWORDS_CONTENT_URI, null, null, null, null);
   278     assertEquals(2, cursor.getCount());
   279     cursor.moveToFirst();
   280     Set<String> guids = new HashSet<String>();
   281     while (!cursor.isAfterLast()) {
   282       String guid = RepoUtils.getStringFromCursor(cursor, BrowserContract.Passwords.GUID);
   283       guids.add(guid);
   284       cursor.moveToNext();
   285     }
   286     cursor.close();
   287     assertEquals(2, guids.size());
   288     assertTrue(guids.contains(expected[0].guid));
   289     assertTrue(guids.contains(expected[1].guid));
   290     dispose(session);
   291   }
   293   // Helper methods.
   294   private RepositorySession createAndBeginSession() {
   295     return SessionTestHelper.createAndBeginSession(
   296         getApplicationContext(),
   297         getRepository());
   298   }
   300   private Repository getRepository() {
   301     /**
   302      * Override this chain in order to avoid our test code having to create two
   303      * sessions all the time. Don't track records, so they filtering doesn't happen.
   304      */
   305     return new PasswordsRepositorySession.PasswordsRepository() {
   306       @Override
   307       public void createSession(RepositorySessionCreationDelegate delegate,
   308           Context context) {
   309         PasswordsRepositorySession session;
   310         session = new PasswordsRepositorySession(this, context) {
   311           @Override
   312           protected synchronized void trackGUID(String guid) {
   313           }
   314         };
   315         delegate.onSessionCreated(session);
   316       }
   317     };
   318   }
   320   private void wipe() {
   321     Context context = getApplicationContext();
   322     context.getContentResolver().delete(BrowserContractHelpers.PASSWORDS_CONTENT_URI, null, null);
   323     context.getContentResolver().delete(BrowserContractHelpers.DELETED_PASSWORDS_CONTENT_URI, null, null);
   324   }
   326   private static void dispose(RepositorySession session) {
   327     if (session != null) {
   328       session.abort();
   329     }
   330   }
   332   private static long updatePassword(String password, PasswordRecord record, long timestamp) {
   333     record.encryptedPassword = password;
   334     long modifiedTime = System.currentTimeMillis();
   335     record.timePasswordChanged = record.lastModified = modifiedTime;
   336     return modifiedTime;
   337   }
   339   private static long updatePassword(String password, PasswordRecord record) {
   340     return updatePassword(password, record, System.currentTimeMillis());
   341   }
   343   // Runnable Helpers.
   344   private static Runnable storeRunnable(final RepositorySession session, final Record record) {
   345     return new Runnable() {
   346       @Override
   347       public void run() {
   348         session.setStoreDelegate(new ExpectStoredDelegate(record.guid));
   349         try {
   350           session.store(record);
   351           session.storeDone();
   352         } catch (NoStoreDelegateException e) {
   353           fail("NoStoreDelegateException should not occur.");
   354         }
   355       }
   356     };
   357   }
   359   private static Runnable fetchAllRunnable(final RepositorySession session, final Record[] records) {
   360     return new Runnable() {
   361       @Override
   362       public void run() {
   363         session.fetchAll(new ExpectFetchDelegate(records));
   364       }
   365     };
   366   }
   368   private static Runnable guidsSinceRunnable(final RepositorySession session, final long timestamp, final String[] expected) {
   369     return new Runnable() {
   370       @Override
   371       public void run() {
   372         session.guidsSince(timestamp, new ExpectGuidsSinceDelegate(expected));
   373       }
   374     };
   375   }
   377   private static Runnable fetchSinceRunnable(final RepositorySession session, final long timestamp, final String[] expected) {
   378     return new Runnable() {
   379       @Override
   380       public void run() {
   381         session.fetchSince(timestamp, new ExpectFetchSinceDelegate(timestamp, expected));
   382       }
   383     };
   384   }
   386   private static Runnable fetchRunnable(final RepositorySession session, final String[] guids, final Record[] expected) {
   387     return new Runnable() {
   388       @Override
   389       public void run() {
   390         try {
   391           session.fetch(guids, new ExpectFetchDelegate(expected));
   392         } catch (InactiveSessionException e) {
   393           performNotify(e);
   394         }
   395       }
   396     };
   397   }
   398 }

mercurial