diff options
author | Abhisek Devkota <ciwrl@cyanogenmod.com> | 2015-08-28 17:43:17 -0700 |
---|---|---|
committer | Abhisek Devkota <ciwrl@cyanogenmod.com> | 2015-08-28 17:43:17 -0700 |
commit | f6ebac34baf99592f414a228490c2625a0fa8e37 (patch) | |
tree | 8f15ab75baa1eb3572309ac639c062a61de92705 /src/tests/src/com/android/browser/tests | |
parent | 8b6a361c4b0d45d3e3e01019db1900d86ccba3b1 (diff) | |
download | android_packages_apps_Gello-f6ebac34baf99592f414a228490c2625a0fa8e37.tar.gz android_packages_apps_Gello-f6ebac34baf99592f414a228490c2625a0fa8e37.tar.bz2 android_packages_apps_Gello-f6ebac34baf99592f414a228490c2625a0fa8e37.zip |
Combine source & prebuilt to single project
Todo: Makefile logic
Diffstat (limited to 'src/tests/src/com/android/browser/tests')
8 files changed, 1154 insertions, 0 deletions
diff --git a/src/tests/src/com/android/browser/tests/BP1to2UpgradeTests.java b/src/tests/src/com/android/browser/tests/BP1to2UpgradeTests.java new file mode 100644 index 00000000..ea5cfaa5 --- /dev/null +++ b/src/tests/src/com/android/browser/tests/BP1to2UpgradeTests.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.browser.tests; + +import android.content.ContentUris; +import android.content.ContentValues; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.net.Uri; +import android.provider.Browser; +import android.test.suitebuilder.annotation.SmallTest; + +import com.android.browser.platformsupport.BookmarkColumns; +import com.android.browser.platformsupport.BrowserContract; +import com.android.browser.platformsupport.BrowserContract.Bookmarks; +import com.android.browser.platformsupport.BrowserContract.History; +import com.android.browser.platformsupport.BrowserContract.Images; +import com.android.browser.provider.BrowserProvider; +import com.android.browser.tests.utils.BP2TestCaseHelper; + +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; + +@SmallTest +public class BP1to2UpgradeTests extends BP2TestCaseHelper { + + BrowserProvider mBp1; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mBp1 = new BrowserProvider(); + mBp1.attachInfo(getMockContext(), null); + } + + /** + * Test that simply makes sure BP1->BP2 with no changes works as intended + */ + public void testStockUpgrade() { + Cursor c = mBp1.query(Browser.BOOKMARKS_URI, + new String[] { BookmarkColumns.URL }, null, null, + BookmarkColumns.URL + " DESC"); + ArrayList<String> urls = new ArrayList<String>(c.getCount()); + while (c.moveToNext()) { + urls.add(c.getString(0)); + } + c.close(); + // First, test the public API (which will hit BP2) + c = getMockContentResolver().query(Browser.BOOKMARKS_URI, + new String[] { BookmarkColumns.URL }, null, null, + BookmarkColumns.URL + " DESC"); + assertEquals(urls.size(), c.getCount()); + int i = 0; + while (c.moveToNext()) { + assertEquals(urls.get(i++), c.getString(0)); + } + c.close(); + // Next, test BP2's new API (not a public API) + c = getMockContentResolver().query(Bookmarks.CONTENT_URI, + new String[] { Bookmarks.URL }, null, null, + Bookmarks.URL + " DESC"); + assertEquals(urls.size(), c.getCount()); + i = 0; + while (c.moveToNext()) { + assertEquals(urls.get(i++), c.getString(0)); + } + c.close(); + } + + public void testPreserveHistory() { + ContentValues values = new ContentValues(); + values.put(BookmarkColumns.URL, "http://slashdot.org/"); + values.put(BookmarkColumns.BOOKMARK, 0); + values.put(BookmarkColumns.DATE, 123456); + mBp1.insert(Browser.BOOKMARKS_URI, values); + // First, test internal API + Cursor c = getMockContentResolver().query(History.CONTENT_URI, + new String[] { History.URL, History.DATE_LAST_VISITED }, + null, null, null); + assertEquals(1, c.getCount()); + assertTrue(c.moveToFirst()); + assertEquals("http://slashdot.org/", c.getString(0)); + assertEquals(123456, c.getInt(1)); + c.close(); + // Next, test public API + c = getMockContentResolver().query(Browser.BOOKMARKS_URI, + Browser.HISTORY_PROJECTION, BookmarkColumns.BOOKMARK + " = 0", + null, null); + assertEquals("public API", 1, c.getCount()); + assertTrue(c.moveToFirst()); + assertEquals("http://slashdot.org/", + c.getString(Browser.HISTORY_PROJECTION_URL_INDEX)); + assertEquals(123456, c.getInt(Browser.HISTORY_PROJECTION_DATE_INDEX)); + c.close(); + } + + public void testPreserveBookmarks() { + // First, nuke 'er (deletes stock bookmarks) + mBp1.delete(Browser.BOOKMARKS_URI, null, null); + ContentValues values = new ContentValues(); + values.put(BookmarkColumns.URL, "http://slashdot.org/"); + values.put(BookmarkColumns.BOOKMARK, 1); + values.put(BookmarkColumns.CREATED, 123456); + mBp1.insert(Browser.BOOKMARKS_URI, values); + // First, test internal API + Cursor c = getMockContentResolver().query(Bookmarks.CONTENT_URI, + new String[] { Bookmarks.URL, Bookmarks.DATE_CREATED }, + null, null, null); + assertEquals(1, c.getCount()); + assertTrue(c.moveToFirst()); + assertEquals("http://slashdot.org/", c.getString(0)); + assertEquals(123456, c.getInt(1)); + c.close(); + // Next, test public API + c = getMockContentResolver().query(Browser.BOOKMARKS_URI, + new String[] { BookmarkColumns.URL, BookmarkColumns.CREATED }, + BookmarkColumns.BOOKMARK + " = 1", null, null); + assertEquals("public API", 1, c.getCount()); + assertTrue(c.moveToFirst()); + assertEquals("http://slashdot.org/", c.getString(0)); + assertEquals(123456, c.getInt(1)); + c.close(); + } + + public void testEmptyUpgrade() { + mBp1.delete(Browser.BOOKMARKS_URI, null, null); + Cursor c = getMockContentResolver().query(Bookmarks.CONTENT_URI, + null, null, null, null); + assertEquals(0, c.getCount()); + c.close(); + } + +} diff --git a/src/tests/src/com/android/browser/tests/BP2ProviderTests.java b/src/tests/src/com/android/browser/tests/BP2ProviderTests.java new file mode 100644 index 00000000..23b75d0e --- /dev/null +++ b/src/tests/src/com/android/browser/tests/BP2ProviderTests.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.browser.tests; + +import com.android.browser.tests.utils.BP2TestCaseHelper; + +import android.content.ContentUris; +import android.content.ContentValues; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.net.Uri; +import android.test.suitebuilder.annotation.SmallTest; + +import com.android.browser.platformsupport.BrowserContract; +import com.android.browser.platformsupport.BrowserContract.Images; + +import java.io.ByteArrayOutputStream; + +@SmallTest +public class BP2ProviderTests extends BP2TestCaseHelper { + + static final String[] PROJECTION = new String[] { + BrowserContract.Bookmarks.PARENT, + BrowserContract.Bookmarks.ACCOUNT_NAME, + BrowserContract.Bookmarks.ACCOUNT_TYPE, + }; + static final int INDEX_PARENT = 0; + static final int INDEX_ACCOUNT_NAME = 1; + static final int INDEX_ACCOUNT_TYPE = 2; + + public void testUpdateImage() { + String url = "http://stub1.com"; + insertBookmark(url, "stub 1"); + ContentValues values = new ContentValues(); + values.put(Images.URL, url); + Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + bitmap.compress(Bitmap.CompressFormat.PNG, 100, os); + values.put(Images.THUMBNAIL, os.toByteArray()); + // Use updateBookmarks because the bookmarks URI observer should + // be triggered, even though we aren't giving it a bookmarks URI + assertTrue(updateBookmark(Images.CONTENT_URI, values)); + } + + public void testIsValidParentNullAccount() { + doTestIsValidParent(null, null); + } + + public void testIsValidParentWithAccount() { + doTestIsValidParent("test@gmail.com", "com.google"); + } + + private void doTestIsValidParent(String accountName, String accountType) { + // Create the folder + ContentValues values = new ContentValues(); + values.put(BrowserContract.Bookmarks.TITLE, "New Folder"); + values.put(BrowserContract.Bookmarks.IS_FOLDER, 1); + values.put(BrowserContract.Bookmarks.ACCOUNT_NAME, accountName); + values.put(BrowserContract.Bookmarks.ACCOUNT_TYPE, accountType); + Uri folderUri = insertBookmark(values); + assertNotNull(folderUri); + long folderId = ContentUris.parseId(folderUri); + assertTrue("Failed to parse folder id!", folderId > 0); + // Insert a bookmark with the same ACCOUNT_* info as parent + values.put(BrowserContract.Bookmarks.TITLE, "google"); + values.put(BrowserContract.Bookmarks.URL, "http://google.com"); + values.put(BrowserContract.Bookmarks.IS_FOLDER, 0); + values.put(BrowserContract.Bookmarks.PARENT, folderId); + Uri insertedUri = insertBookmark(values); + assertNotNull(insertedUri); + Cursor c = getMockContentResolver().query(insertedUri, + PROJECTION, null, null, null); + try { + assertNotNull(c); + assertTrue(c.moveToFirst()); + long insertedParentId = c.getLong(INDEX_PARENT); + String insertedAccountName = c.getString(INDEX_ACCOUNT_NAME); + String insertedAccountType = c.getString(INDEX_ACCOUNT_TYPE); + assertEquals(folderId, insertedParentId); + assertEquals(accountName, insertedAccountName); + assertEquals(accountType, insertedAccountType); + + // Insert a bookmark with no ACCOUNT_* set, BUT with a valid parent + // The inserted should end up with the ACCOUNT_* of the parent + values.remove(BrowserContract.Bookmarks.ACCOUNT_NAME); + values.remove(BrowserContract.Bookmarks.ACCOUNT_TYPE); + insertedUri = insertBookmark(values); + assertNotNull(insertedUri); + c.close(); + c = getMockContentResolver().query(insertedUri, + PROJECTION, null, null, null); + assertNotNull(c); + assertTrue(c.moveToFirst()); + insertedParentId = c.getLong(INDEX_PARENT); + insertedAccountName = c.getString(INDEX_ACCOUNT_NAME); + insertedAccountType = c.getString(INDEX_ACCOUNT_TYPE); + assertEquals(folderId, insertedParentId); + assertEquals(accountName, insertedAccountName); + assertEquals(accountType, insertedAccountType); + + // Insert a bookmark with a different ACCOUNT_* than it's parent + // ACCOUNT_* should override parent + accountName = accountName + "@something.else"; + accountType = "com.google"; + values.put(BrowserContract.Bookmarks.ACCOUNT_NAME, accountName); + values.put(BrowserContract.Bookmarks.ACCOUNT_TYPE, accountType); + insertedUri = insertBookmark(values); + assertNotNull(insertedUri); + c.close(); + c = getMockContentResolver().query(insertedUri, + PROJECTION, null, null, null); + assertNotNull(c); + assertTrue(c.moveToFirst()); + insertedParentId = c.getLong(INDEX_PARENT); + insertedAccountName = c.getString(INDEX_ACCOUNT_NAME); + insertedAccountType = c.getString(INDEX_ACCOUNT_TYPE); + assertNotSame(folderId, insertedParentId); + assertEquals(accountName, insertedAccountName); + assertEquals(accountType, insertedAccountType); + } finally { + c.close(); + } + } +} diff --git a/src/tests/src/com/android/browser/tests/BP2UriObserverTests.java b/src/tests/src/com/android/browser/tests/BP2UriObserverTests.java new file mode 100644 index 00000000..a3b001aa --- /dev/null +++ b/src/tests/src/com/android/browser/tests/BP2UriObserverTests.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.browser.tests; + +import android.content.ContentValues; +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.net.Uri; +import android.test.suitebuilder.annotation.SmallTest; + +import com.android.browser.platformsupport.BrowserContract.Bookmarks; +import com.android.browser.platformsupport.BrowserContract.History; +import com.android.browser.tests.utils.BP2TestCaseHelper; + +import java.io.ByteArrayOutputStream; + +@SmallTest +public class BP2UriObserverTests extends BP2TestCaseHelper { + + public void testInsertBookmark() { + Uri insertedUri = insertBookmark("http://stub1.com", "Stub1"); + TriggeredObserver stubObs = new TriggeredObserver(insertedUri); + assertObserversTriggered(false, stubObs); + insertBookmark("http://stub2.com", "Stub2"); + perfIdeallyUntriggered(stubObs); + } + + public void testUpdateBookmark() { + Uri toUpdate = insertBookmark("http://stub1.com", "Stub1"); + Uri unchanged = insertBookmark("http://stub2.com", "Stub2"); + TriggeredObserver updateObs = new TriggeredObserver(toUpdate); + TriggeredObserver unchangedObs = new TriggeredObserver(unchanged); + assertObserversTriggered(false, updateObs, unchangedObs); + assertTrue(updateBookmark(toUpdate, "http://stub1.com", "Stub1: Revenge of the stubs")); + assertTrue("Update observer not notified!", updateObs.checkTriggered()); + perfIdeallyUntriggered(unchangedObs); + } + + public void testUpdateBookmarkImages() { + Uri toUpdate = insertBookmark("http://stub1.com", "Stub1"); + Uri unchanged = insertBookmark("http://stub2.com", "Stub2"); + Bitmap favicon = Bitmap.createBitmap(16, 16, Config.ARGB_8888); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + favicon.compress(Bitmap.CompressFormat.PNG, 100, os); + byte[] rawFavicon = os.toByteArray(); + ContentValues values = new ContentValues(); + values.put(Bookmarks.FAVICON, rawFavicon); + values.put(Bookmarks.TITLE, "Stub1"); + TriggeredObserver updateObs = new TriggeredObserver(toUpdate); + TriggeredObserver unchangedObs = new TriggeredObserver(unchanged); + assertTrue(updateBookmark(toUpdate, values)); + assertTrue("Update observer not notified!", updateObs.checkTriggered()); + perfIdeallyUntriggered(unchangedObs); + } + + public void testInsertHistory() { + Uri insertedUri = insertHistory("http://stub1.com", "Stub1"); + TriggeredObserver stubObs = new TriggeredObserver(insertedUri); + assertObserversTriggered(false, stubObs); + insertHistory("http://stub2.com", "Stub2"); + perfIdeallyUntriggered(stubObs); + } + + public void testUpdateHistory() { + Uri toUpdate = insertHistory("http://stub1.com", "Stub1"); + Uri unchanged = insertHistory("http://stub2.com", "Stub2"); + TriggeredObserver updateObs = new TriggeredObserver(toUpdate); + TriggeredObserver unchangedObs = new TriggeredObserver(unchanged); + assertObserversTriggered(false, updateObs, unchangedObs); + assertTrue(updateHistory(toUpdate, "http://stub1.com", "Stub1: Revenge of the stubs")); + assertTrue("Update observer not notified!", updateObs.checkTriggered()); + perfIdeallyUntriggered(unchangedObs); + } + + public void testUpdateHistoryImages() { + Uri toUpdate = insertHistory("http://stub1.com", "Stub1"); + Uri unchanged = insertHistory("http://stub2.com", "Stub2"); + Bitmap favicon = Bitmap.createBitmap(16, 16, Config.ARGB_8888); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + favicon.compress(Bitmap.CompressFormat.PNG, 100, os); + byte[] rawFavicon = os.toByteArray(); + ContentValues values = new ContentValues(); + values.put(History.FAVICON, rawFavicon); + values.put(History.TITLE, "Stub1"); + TriggeredObserver updateObs = new TriggeredObserver(toUpdate); + TriggeredObserver unchangedObs = new TriggeredObserver(unchanged); + assertTrue(updateHistory(toUpdate, values)); + assertTrue("Update observer not notified!", updateObs.checkTriggered()); + perfIdeallyUntriggered(unchangedObs); + } +} diff --git a/src/tests/src/com/android/browser/tests/BookmarksTests.java b/src/tests/src/com/android/browser/tests/BookmarksTests.java new file mode 100644 index 00000000..f4b91093 --- /dev/null +++ b/src/tests/src/com/android/browser/tests/BookmarksTests.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.browser.tests; + +import android.content.ContentResolver; +import android.database.Cursor; +import android.test.suitebuilder.annotation.SmallTest; + +import com.android.browser.Bookmarks; +import com.android.browser.tests.utils.BP2TestCaseHelper; + +/** + * Extends from BP2TestCaseHelper for the helper methods + * and to get the mock database + */ +@SmallTest +public class BookmarksTests extends BP2TestCaseHelper { + + public void testQueryCombinedForUrl() { + // First, add some bookmarks + assertNotNull(insertBookmark( + "http://google.com/search?q=test", "Test search")); + assertNotNull(insertBookmark( + "http://google.com/search?q=mustang", "Mustang search")); + assertNotNull(insertBookmark( + "http://google.com/search?q=aliens", "Aliens search")); + ContentResolver cr = getMockContentResolver(); + + Cursor c = null; + try { + // First, search for a match + String url = "http://google.com/search?q=test"; + c = Bookmarks.queryCombinedForUrl(cr, null, url); + assertEquals(1, c.getCount()); + assertTrue(c.moveToFirst()); + assertEquals(url, c.getString(0)); + c.close(); + + // Next, search for no match + url = "http://google.com/search"; + c = Bookmarks.queryCombinedForUrl(cr, null, url); + assertEquals(0, c.getCount()); + assertFalse(c.moveToFirst()); + c.close(); + } finally { + if (c != null) c.close(); + } + } + +} diff --git a/src/tests/src/com/android/browser/tests/utils/BP2TestCaseHelper.java b/src/tests/src/com/android/browser/tests/utils/BP2TestCaseHelper.java new file mode 100644 index 00000000..9133a872 --- /dev/null +++ b/src/tests/src/com/android/browser/tests/utils/BP2TestCaseHelper.java @@ -0,0 +1,233 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.browser.tests.utils; + +import com.android.browser.provider.BrowserProvider2; + +import java.io.File; +import java.io.FilenameFilter; + +import android.content.ContentValues; +import android.database.ContentObserver; +import android.net.Uri; +import android.provider.Browser; +import android.util.Log; + +import com.android.browser.platformsupport.BrowserContract; +import com.android.browser.platformsupport.BrowserContract.Bookmarks; +import com.android.browser.platformsupport.BrowserContract.History; + +/** + * This is a replacement for ProviderTestCase2 that can handle notifyChange testing. + * It also has helper methods specifically for testing BrowserProvider2 + */ +public abstract class BP2TestCaseHelper extends ProviderTestCase3<BrowserProvider2> { + + // Tag for potential performance impacts + private static final String PERFTAG = "BP2-PerfCheck"; + + private TriggeredObserver mLegacyObserver; + private TriggeredObserver mRootObserver; + private TriggeredObserver mBookmarksObserver; + private TriggeredObserver mHistoryObserver; + private TriggeredObserver mWidgetObserver; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mLegacyObserver = new TriggeredObserver(Browser.BOOKMARKS_URI); + mRootObserver = new TriggeredObserver(BrowserContract.AUTHORITY_URI); + mBookmarksObserver = new TriggeredObserver(Bookmarks.CONTENT_URI); + mHistoryObserver = new TriggeredObserver(History.CONTENT_URI); + mWidgetObserver = new TriggeredObserver(); + // We don't need to worry about setting this back to null since this + // is a private instance local to the MockContentResolver + getProvider().setWidgetObserver(mWidgetObserver); + } + + public BP2TestCaseHelper() { + super(BrowserProvider2.class, + BrowserContract.AUTHORITY, BrowserProvider2.LEGACY_AUTHORITY); + } + + public void perfIdeallyUntriggered(TriggeredObserver... obs) { + for (TriggeredObserver ob : obs) { + if (ob.checkTriggered()) { + // Not ideal, unnecessary notification + Log.i(PERFTAG, ob.mUri + " onChange called but content unaltered!"); + } + } + } + + public void assertObserversTriggered(boolean triggered, + TriggeredObserver... observers) { + for (TriggeredObserver obs : observers) { + assertEquals(obs.mUri + ", descendents:" + obs.mNotifyForDescendents, + triggered, obs.checkTriggered()); + } + } + + public class TriggeredObserver extends ContentObserver { + private boolean mTriggered; + Uri mUri; + boolean mNotifyForDescendents; + + /** + * Creates an unmanaged TriggeredObserver + */ + public TriggeredObserver() { + super(null); + } + + /** + * Same as TriggeredObserver(uri, true); + */ + public TriggeredObserver(Uri uri) { + this(uri, true); + } + + /** + * Creates a managed TriggeredObserver that self-registers with the + * mock ContentResolver + */ + public TriggeredObserver(Uri uri, boolean notifyForDescendents) { + super(null); + mUri = uri; + mNotifyForDescendents = notifyForDescendents; + registerContentObserver(uri, notifyForDescendents, this); + } + + @Override + public void onChange(boolean selfChange) { + super.onChange(selfChange); + mTriggered = true; + } + + public boolean checkTriggered() { + boolean ret = mTriggered; + mTriggered = false; + return ret; + } + } + + Uri mockInsert(Uri uri, ContentValues values) { + assertObserversTriggered(false, mLegacyObserver, mRootObserver); + Uri ret = getMockContentResolver().insert(uri, values); + assertObserversTriggered(true, mLegacyObserver, mRootObserver); + return ret; + } + + int mockUpdate(Uri uri, ContentValues values, String where, + String[] selectionArgs) { + assertObserversTriggered(false, mLegacyObserver, mRootObserver); + int ret = getMockContentResolver().update(uri, values, where, selectionArgs); + if (ret > 0) { + assertObserversTriggered(true, mLegacyObserver, mRootObserver); + } else { + perfIdeallyUntriggered(mLegacyObserver); + perfIdeallyUntriggered(mRootObserver); + } + return ret; + } + + public Uri insertBookmark(String url, String title) { + ContentValues values = new ContentValues(); + values.put(BrowserContract.Bookmarks.TITLE, title); + values.put(BrowserContract.Bookmarks.URL, url); + values.put(BrowserContract.Bookmarks.IS_FOLDER, 0); + return insertBookmark(values); + } + + public Uri insertBookmark(ContentValues values) { + assertObserversTriggered(false, mBookmarksObserver, mWidgetObserver); + Uri ret = mockInsert(Bookmarks.CONTENT_URI, values); + assertObserversTriggered(true, mBookmarksObserver, mWidgetObserver); + perfIdeallyUntriggered(mHistoryObserver); + return ret; + } + + public boolean updateBookmark(Uri uri, String url, String title) { + ContentValues values = new ContentValues(); + values.put(BrowserContract.Bookmarks.TITLE, title); + values.put(BrowserContract.Bookmarks.URL, url); + return updateBookmark(uri, values); + } + + public boolean updateBookmark(Uri uri, ContentValues values) { + assertObserversTriggered(false, mBookmarksObserver, mWidgetObserver); + int modifyCount = mockUpdate(uri, values, null, null); + assertTrue("UpdatedBookmark modified too much! " + uri, modifyCount <= 1); + boolean updated = modifyCount == 1; + if (updated) { + assertObserversTriggered(updated, mBookmarksObserver, mWidgetObserver); + } else { + perfIdeallyUntriggered(mBookmarksObserver, mWidgetObserver); + } + perfIdeallyUntriggered(mHistoryObserver); + return updated; + } + + public Uri insertHistory(String url, String title) { + ContentValues values = new ContentValues(); + values.put(BrowserContract.History.TITLE, title); + values.put(BrowserContract.History.URL, url); + assertObserversTriggered(false, mHistoryObserver); + Uri ret = mockInsert(History.CONTENT_URI, values); + assertObserversTriggered(true, mHistoryObserver); + perfIdeallyUntriggered(mBookmarksObserver, mWidgetObserver); + return ret; + } + + public boolean updateHistory(Uri uri, String url, String title) { + ContentValues values = new ContentValues(); + values.put(BrowserContract.History.TITLE, title); + values.put(BrowserContract.History.URL, url); + return updateHistory(uri, values); + } + + public boolean updateHistory(Uri uri, ContentValues values) { + assertObserversTriggered(false, mHistoryObserver); + int modifyCount = mockUpdate(uri, values, null, null); + assertTrue("UpdatedHistory modified too much! " + uri, modifyCount <= 1); + boolean updated = modifyCount == 1; + if (updated) { + assertObserversTriggered(updated, mHistoryObserver); + } else { + perfIdeallyUntriggered(mHistoryObserver); + } + perfIdeallyUntriggered(mBookmarksObserver, mWidgetObserver); + return updated; + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + // Delete the test databases so that subsequent runs have a clean slate + File f = getMockContext().getDatabasePath("test"); + File dir = f.getParentFile(); + File testFiles[] = dir.listFiles(new FilenameFilter() { + + @Override + public boolean accept(File dir, String filename) { + return filename.startsWith(ProviderTestCase3.FILENAME_PREFIX); + } + }); + for (File testFile : testFiles) { + testFile.delete(); + } + } +} diff --git a/src/tests/src/com/android/browser/tests/utils/MockContentResolver2.java b/src/tests/src/com/android/browser/tests/utils/MockContentResolver2.java new file mode 100644 index 00000000..4fed65a0 --- /dev/null +++ b/src/tests/src/com/android/browser/tests/utils/MockContentResolver2.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.browser.tests.utils; + +import com.google.android.collect.Maps; + +import android.content.ContentProvider; +import android.content.ContentResolver; +import android.content.Context; +import android.content.IContentProvider; +import android.database.ContentObserver; +import android.net.Uri; + +import java.util.Map; + +public class MockContentResolver2 extends ContentResolver { + + Map<String, ContentProvider> mProviders; + private final MockObserverNode mRootNode = new MockObserverNode(""); + + /* + * Creates a local map of providers. This map is used instead of the global map when an + * API call tries to acquire a provider. + */ + public MockContentResolver2() { + super(null); + mProviders = Maps.newHashMap(); + } + + /** + * Adds access to a provider based on its authority + * + * @param name The authority name associated with the provider. + * @param provider An instance of {@link android.content.ContentProvider} or one of its + * subclasses, or null. + */ + public void addProvider(String name, ContentProvider provider) { + + /* + * Maps the authority to the provider locally. + */ + mProviders.put(name, provider); + } + + /** @hide */ + @Override + protected IContentProvider acquireProvider(Context context, String name) { + return acquireExistingProvider(context, name); + } + + /** @hide */ + @Override + protected IContentProvider acquireExistingProvider(Context context, String name) { + + /* + * Gets the content provider from the local map + */ + final ContentProvider provider = mProviders.get(name); + + if (provider != null) { + return provider.getIContentProvider(); + } else { + return null; + } + } + + /** @hide */ + @Override + public boolean releaseProvider(IContentProvider provider) { + return true; + } + + /** @hide */ + protected IContentProvider acquireUnstableProvider(Context c, String name) { + return acquireProvider(c, name); + } + + /** @hide */ + public boolean releaseUnstableProvider(IContentProvider icp) { + return releaseProvider(icp); + } + + /** @hide */ + public void unstableProviderDied(IContentProvider icp) { + } + + @Override + public void notifyChange(Uri uri, ContentObserver observer, + boolean syncToNetwork) { + mRootNode.notifyMyObservers(uri, 0, observer, false); + } + + public void safeRegisterContentObserver(Uri uri, boolean notifyForDescendents, + ContentObserver observer) { + mRootNode.addObserver(uri, observer, notifyForDescendents); + } + + public void safeUnregisterContentObserver(ContentObserver observer) { + mRootNode.removeObserver(observer); + } + +} diff --git a/src/tests/src/com/android/browser/tests/utils/MockObserverNode.java b/src/tests/src/com/android/browser/tests/utils/MockObserverNode.java new file mode 100644 index 00000000..edcffd4f --- /dev/null +++ b/src/tests/src/com/android/browser/tests/utils/MockObserverNode.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.browser.tests.utils; + +import android.database.ContentObserver; +import android.net.Uri; + +import java.util.ArrayList; + +public final class MockObserverNode { + private class MockObserverEntry { + public final ContentObserver observer; + public final boolean notifyForDescendents; + + public MockObserverEntry(ContentObserver o, boolean n) { + observer = o; + notifyForDescendents = n; + } + } + + public static final int INSERT_TYPE = 0; + public static final int UPDATE_TYPE = 1; + public static final int DELETE_TYPE = 2; + + private String mName; + private ArrayList<MockObserverNode> mChildren = new ArrayList<MockObserverNode>(); + private ArrayList<MockObserverEntry> mObservers = new ArrayList<MockObserverEntry>(); + + public MockObserverNode(String name) { + mName = name; + } + + private String getUriSegment(Uri uri, int index) { + if (uri != null) { + if (index == 0) { + return uri.getAuthority(); + } else { + return uri.getPathSegments().get(index - 1); + } + } else { + return null; + } + } + + private int countUriSegments(Uri uri) { + if (uri == null) { + return 0; + } + return uri.getPathSegments().size() + 1; + } + + public void addObserver(Uri uri, ContentObserver observer, + boolean notifyForDescendents) { + addObserver(uri, 0, observer, notifyForDescendents); + } + + private void addObserver(Uri uri, int index, ContentObserver observer, + boolean notifyForDescendents) { + // If this is the leaf node add the observer + if (index == countUriSegments(uri)) { + mObservers.add(new MockObserverEntry(observer, notifyForDescendents)); + return; + } + + // Look to see if the proper child already exists + String segment = getUriSegment(uri, index); + if (segment == null) { + throw new IllegalArgumentException("Invalid Uri (" + uri + ") used for observer"); + } + int N = mChildren.size(); + for (int i = 0; i < N; i++) { + MockObserverNode node = mChildren.get(i); + if (node.mName.equals(segment)) { + node.addObserver(uri, index + 1, observer, notifyForDescendents); + return; + } + } + + // No child found, create one + MockObserverNode node = new MockObserverNode(segment); + mChildren.add(node); + node.addObserver(uri, index + 1, observer, notifyForDescendents); + } + + public boolean removeObserver(ContentObserver observer) { + int size = mChildren.size(); + for (int i = 0; i < size; i++) { + boolean empty = mChildren.get(i).removeObserver(observer); + if (empty) { + mChildren.remove(i); + i--; + size--; + } + } + + size = mObservers.size(); + for (int i = 0; i < size; i++) { + MockObserverEntry entry = mObservers.get(i); + if (entry.observer == observer) { + mObservers.remove(i); + break; + } + } + + if (mChildren.size() == 0 && mObservers.size() == 0) { + return true; + } + return false; + } + + private void notifyMyObservers(boolean leaf, ContentObserver observer, + boolean selfNotify) { + int N = mObservers.size(); + for (int i = 0; i < N; i++) { + MockObserverEntry entry = mObservers.get(i); + + // Don't notify the observer if it sent the notification and isn't interesed + // in self notifications + if (entry.observer == observer && !selfNotify) { + continue; + } + + // Make sure the observer is interested in the notification + if (leaf || (!leaf && entry.notifyForDescendents)) { + entry.observer.onChange(selfNotify); + } + } + } + + public void notifyMyObservers(Uri uri, int index, ContentObserver observer, + boolean selfNotify) { + String segment = null; + int segmentCount = countUriSegments(uri); + if (index >= segmentCount) { + // This is the leaf node, notify all observers + notifyMyObservers(true, observer, selfNotify); + } else if (index < segmentCount){ + segment = getUriSegment(uri, index); + // Notify any observers at this level who are interested in descendents + notifyMyObservers(false, observer, selfNotify); + } + + int N = mChildren.size(); + for (int i = 0; i < N; i++) { + MockObserverNode node = mChildren.get(i); + if (segment == null || node.mName.equals(segment)) { + // We found the child, + node.notifyMyObservers(uri, index + 1, observer, selfNotify); + if (segment != null) { + break; + } + } + } + } +} diff --git a/src/tests/src/com/android/browser/tests/utils/ProviderTestCase3.java b/src/tests/src/com/android/browser/tests/utils/ProviderTestCase3.java new file mode 100644 index 00000000..75bc052e --- /dev/null +++ b/src/tests/src/com/android/browser/tests/utils/ProviderTestCase3.java @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.browser.tests.utils; + +import android.content.ContentProvider; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.Resources; +import android.database.ContentObserver; +import android.net.Uri; +import android.test.AndroidTestCase; +import android.test.IsolatedContext; +import android.test.RenamingDelegatingContext; +import android.test.mock.MockContext; + +import java.io.File; + +/** + * Replacement for ProviderTestCase2 that keeps calls to ContentResolver.notifyChanged + * internal to observers registered with ProviderTestCase3.registerContentObserver + */ +public abstract class ProviderTestCase3<T extends ContentProvider> extends AndroidTestCase { + + public static final String FILENAME_PREFIX = "test."; + + Class<T> mProviderClass; + String[] mProviderAuthority; + + private IsolatedContext mProviderContext; + private MockContentResolver2 mResolver; + + private class MockContext2 extends MockContext { + + @Override + public Resources getResources() { + return getContext().getResources(); + } + + @Override + public File getDir(String name, int mode) { + // name the directory so the directory will be separated from + // one created through the regular Context + return getContext().getDir("mockcontext2_" + name, mode); + } + + @Override + public String getPackageName() { + return getContext().getPackageName(); + } + + @Override + public SharedPreferences getSharedPreferences(String name, int mode) { + return getContext().getSharedPreferences("mockcontext2_" + name, mode); + } + + @Override + public Context getApplicationContext() { + return this; + } + + @Override + public Object getSystemService(String name) { + return null; + } + } + /** + * Constructor. + * + * @param providerClass The class name of the provider under test + * @param providerAuthorities The provider's authority string + */ + public ProviderTestCase3(Class<T> providerClass, String... providerAuthorities) { + mProviderClass = providerClass; + mProviderAuthority = providerAuthorities; + } + + private T mProvider; + + /** + * Returns the content provider created by this class in the {@link #setUp()} method. + * @return T An instance of the provider class given as a parameter to the test case class. + */ + public T getProvider() { + return mProvider; + } + + /** + * Sets up the environment for the test fixture. + * <p> + * Creates a new + * {@link com.android.browser.tests.utils.MockContentResolver2}, a new IsolatedContext + * that isolates the provider's file operations, and a new instance of + * the provider under test within the isolated environment. + * </p> + * + * @throws Exception + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + + mResolver = new MockContentResolver2(); + RenamingDelegatingContext targetContextWrapper = new + RenamingDelegatingContext( + new MockContext2(), // The context that most methods are + //delegated to + getContext(), // The context that file methods are delegated to + FILENAME_PREFIX); + // The default IsolatedContext has a mock AccountManager that doesn't + // work for us, so override getSystemService to always return null + mProviderContext = new IsolatedContext(mResolver, targetContextWrapper) { + + @Override + public Object getSystemService(String name) { + return null; + } + }; + + mProvider = mProviderClass.newInstance(); + mProvider.attachInfo(mProviderContext, null); + assertNotNull(mProvider); + for (String auth : mProviderAuthority) { + mResolver.addProvider(auth, getProvider()); + } + } + + /** + * Tears down the environment for the test fixture. + * <p> + * Calls {@link android.content.ContentProvider#shutdown()} on the + * {@link android.content.ContentProvider} represented by mProvider. + */ + @Override + protected void tearDown() throws Exception { + mProvider.shutdown(); + super.tearDown(); + } + + /** + * Gets the {@link MockContentResolver2} created by this class during initialization. You + * must use the methods of this resolver to access the provider under test. + * + * @return A {@link MockContentResolver2} instance. + */ + public MockContentResolver2 getMockContentResolver() { + return mResolver; + } + + /** + * Gets the {@link IsolatedContext} created by this class during initialization. + * @return The {@link IsolatedContext} instance + */ + public IsolatedContext getMockContext() { + return mProviderContext; + } + + public void registerContentObserver(Uri uri, boolean notifyForDescendents, + ContentObserver observer) { + mResolver.safeRegisterContentObserver(uri, notifyForDescendents, observer); + } + + public void unregisterContentObserver(ContentObserver observer) { + mResolver.safeUnregisterContentObserver(observer); + } + +} |