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.

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

mercurial