michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: package org.mozilla.gecko.background.db; michael@0: michael@0: import org.json.simple.JSONArray; michael@0: import org.mozilla.gecko.background.helpers.AndroidSyncTestCase; michael@0: import org.mozilla.gecko.background.sync.helpers.ExpectFetchDelegate; michael@0: import org.mozilla.gecko.background.sync.helpers.SessionTestHelper; michael@0: import org.mozilla.gecko.db.BrowserContract; michael@0: import org.mozilla.gecko.sync.repositories.NoContentProviderException; michael@0: import org.mozilla.gecko.sync.repositories.RepositorySession; michael@0: import org.mozilla.gecko.sync.repositories.android.BrowserContractHelpers; michael@0: import org.mozilla.gecko.sync.repositories.android.FennecTabsRepository; michael@0: import org.mozilla.gecko.sync.repositories.android.FennecTabsRepository.FennecTabsRepositorySession; michael@0: import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionCreationDelegate; michael@0: import org.mozilla.gecko.sync.repositories.domain.Record; michael@0: import org.mozilla.gecko.sync.repositories.domain.TabsRecord; michael@0: michael@0: import android.content.ContentProviderClient; michael@0: import android.content.ContentResolver; michael@0: import android.content.Context; michael@0: import android.database.Cursor; michael@0: import android.os.RemoteException; michael@0: michael@0: public class TestFennecTabsRepositorySession extends AndroidSyncTestCase { michael@0: public static final String TEST_CLIENT_GUID = "test guid"; // Real GUIDs never contain spaces. michael@0: public static final String TEST_CLIENT_NAME = "test client name"; michael@0: michael@0: // Override these to test against data that is not live. michael@0: public static final String TEST_TABS_CLIENT_GUID_IS_LOCAL_SELECTION = BrowserContract.Tabs.CLIENT_GUID + " IS ?"; michael@0: public static final String[] TEST_TABS_CLIENT_GUID_IS_LOCAL_SELECTION_ARGS = new String[] { TEST_CLIENT_GUID }; michael@0: michael@0: protected ContentProviderClient tabsClient = null; michael@0: michael@0: protected ContentProviderClient getTabsClient() { michael@0: final ContentResolver cr = getApplicationContext().getContentResolver(); michael@0: return cr.acquireContentProviderClient(BrowserContractHelpers.TABS_CONTENT_URI); michael@0: } michael@0: michael@0: public TestFennecTabsRepositorySession() throws NoContentProviderException { michael@0: super(); michael@0: } michael@0: michael@0: @Override michael@0: public void setUp() { michael@0: if (tabsClient == null) { michael@0: tabsClient = getTabsClient(); michael@0: } michael@0: } michael@0: michael@0: protected int deleteAllTestTabs(final ContentProviderClient tabsClient) throws RemoteException { michael@0: if (tabsClient == null) { michael@0: return -1; michael@0: } michael@0: return tabsClient.delete(BrowserContractHelpers.TABS_CONTENT_URI, michael@0: TEST_TABS_CLIENT_GUID_IS_LOCAL_SELECTION, TEST_TABS_CLIENT_GUID_IS_LOCAL_SELECTION_ARGS); michael@0: } michael@0: michael@0: @Override michael@0: protected void tearDown() throws Exception { michael@0: if (tabsClient != null) { michael@0: deleteAllTestTabs(tabsClient); michael@0: michael@0: tabsClient.release(); michael@0: tabsClient = null; michael@0: } michael@0: } michael@0: michael@0: protected FennecTabsRepository getRepository() { michael@0: /** michael@0: * Override this chain in order to avoid our test code having to create two michael@0: * sessions all the time. michael@0: */ michael@0: return new FennecTabsRepository(TEST_CLIENT_NAME, TEST_CLIENT_GUID) { michael@0: @Override michael@0: public void createSession(RepositorySessionCreationDelegate delegate, michael@0: Context context) { michael@0: try { michael@0: final FennecTabsRepositorySession session = new FennecTabsRepositorySession(this, context) { michael@0: @Override michael@0: protected synchronized void trackGUID(String guid) { michael@0: } michael@0: michael@0: @Override michael@0: protected String localClientSelection() { michael@0: return TEST_TABS_CLIENT_GUID_IS_LOCAL_SELECTION; michael@0: } michael@0: michael@0: @Override michael@0: protected String[] localClientSelectionArgs() { michael@0: return TEST_TABS_CLIENT_GUID_IS_LOCAL_SELECTION_ARGS; michael@0: } michael@0: }; michael@0: delegate.onSessionCreated(session); michael@0: } catch (Exception e) { michael@0: delegate.onSessionCreateFailed(e); michael@0: } michael@0: } michael@0: }; michael@0: } michael@0: michael@0: protected FennecTabsRepositorySession createSession() { michael@0: return (FennecTabsRepositorySession) SessionTestHelper.createSession( michael@0: getApplicationContext(), michael@0: getRepository()); michael@0: } michael@0: michael@0: protected FennecTabsRepositorySession createAndBeginSession() { michael@0: return (FennecTabsRepositorySession) SessionTestHelper.createAndBeginSession( michael@0: getApplicationContext(), michael@0: getRepository()); michael@0: } michael@0: michael@0: protected Runnable fetchSinceRunnable(final RepositorySession session, final long timestamp, final Record[] expectedRecords) { michael@0: return new Runnable() { michael@0: @Override michael@0: public void run() { michael@0: session.fetchSince(timestamp, new ExpectFetchDelegate(expectedRecords)); michael@0: } michael@0: }; michael@0: } michael@0: michael@0: protected Runnable fetchAllRunnable(final RepositorySession session, final Record[] expectedRecords) { michael@0: return new Runnable() { michael@0: @Override michael@0: public void run() { michael@0: session.fetchAll(new ExpectFetchDelegate(expectedRecords)); michael@0: } michael@0: }; michael@0: } michael@0: michael@0: protected Tab testTab1; michael@0: protected Tab testTab2; michael@0: protected Tab testTab3; michael@0: michael@0: @SuppressWarnings("unchecked") michael@0: private void insertSomeTestTabs(ContentProviderClient tabsClient) throws RemoteException { michael@0: final JSONArray history1 = new JSONArray(); michael@0: history1.add("http://test.com/test1.html"); michael@0: testTab1 = new Tab("test title 1", "http://test.com/test1.png", history1, 1000); michael@0: michael@0: final JSONArray history2 = new JSONArray(); michael@0: history2.add("http://test.com/test2.html#1"); michael@0: history2.add("http://test.com/test2.html#2"); michael@0: history2.add("http://test.com/test2.html#3"); michael@0: testTab2 = new Tab("test title 2", "http://test.com/test2.png", history2, 2000); michael@0: michael@0: final JSONArray history3 = new JSONArray(); michael@0: history3.add("http://test.com/test3.html#1"); michael@0: history3.add("http://test.com/test3.html#2"); michael@0: testTab3 = new Tab("test title 3", "http://test.com/test3.png", history3, 3000); michael@0: michael@0: tabsClient.insert(BrowserContractHelpers.TABS_CONTENT_URI, testTab1.toContentValues(TEST_CLIENT_GUID, 0)); michael@0: tabsClient.insert(BrowserContractHelpers.TABS_CONTENT_URI, testTab2.toContentValues(TEST_CLIENT_GUID, 1)); michael@0: tabsClient.insert(BrowserContractHelpers.TABS_CONTENT_URI, testTab3.toContentValues(TEST_CLIENT_GUID, 2)); michael@0: } michael@0: michael@0: protected TabsRecord insertTestTabsAndExtractTabsRecord() throws RemoteException { michael@0: insertSomeTestTabs(tabsClient); michael@0: michael@0: final String positionAscending = BrowserContract.Tabs.POSITION + " ASC"; michael@0: Cursor cursor = null; michael@0: try { michael@0: cursor = tabsClient.query(BrowserContractHelpers.TABS_CONTENT_URI, null, michael@0: TEST_TABS_CLIENT_GUID_IS_LOCAL_SELECTION, TEST_TABS_CLIENT_GUID_IS_LOCAL_SELECTION_ARGS, positionAscending); michael@0: CursorDumper.dumpCursor(cursor); michael@0: michael@0: final TabsRecord tabsRecord = FennecTabsRepository.tabsRecordFromCursor(cursor, TEST_CLIENT_GUID, TEST_CLIENT_NAME); michael@0: michael@0: assertEquals(TEST_CLIENT_GUID, tabsRecord.guid); michael@0: assertEquals(TEST_CLIENT_NAME, tabsRecord.clientName); michael@0: michael@0: assertNotNull(tabsRecord.tabs); michael@0: assertEquals(cursor.getCount(), tabsRecord.tabs.size()); michael@0: michael@0: return tabsRecord; michael@0: } finally { michael@0: cursor.close(); michael@0: } michael@0: } michael@0: michael@0: public void testFetchAll() throws NoContentProviderException, RemoteException { michael@0: final TabsRecord tabsRecord = insertTestTabsAndExtractTabsRecord(); michael@0: michael@0: final FennecTabsRepositorySession session = createAndBeginSession(); michael@0: performWait(fetchAllRunnable(session, new Record[] { tabsRecord })); michael@0: michael@0: session.abort(); michael@0: } michael@0: michael@0: public void testFetchSince() throws NoContentProviderException, RemoteException { michael@0: final TabsRecord tabsRecord = insertTestTabsAndExtractTabsRecord(); michael@0: michael@0: final FennecTabsRepositorySession session = createAndBeginSession(); michael@0: michael@0: // Not all tabs are modified after this, but the record should contain them all. michael@0: performWait(fetchSinceRunnable(session, 1000, new Record[] { tabsRecord })); michael@0: michael@0: // No tabs are modified after this, so we shouldn't get a record at all. michael@0: performWait(fetchSinceRunnable(session, 4000, new Record[] { })); michael@0: michael@0: session.abort(); michael@0: } michael@0: }