diff options
Diffstat (limited to 'tests')
10 files changed, 876 insertions, 65 deletions
diff --git a/tests/AndroidTests/run_test.sh b/tests/AndroidTests/run_test.sh index 0cdf63f..6c3710a 100755 --- a/tests/AndroidTests/run_test.sh +++ b/tests/AndroidTests/run_test.sh @@ -1,4 +1,4 @@ framework=/system/framework bpath=$framework/core.jar:$framework/ext.jar:$framework/framework.jar:$framework/android.test.runner.jar -adb shell exec dalvikvm -Xbootclasspath:$bpath -cp system/app/AndroidTests.apk \ +adb shell exec dalvikvm -Xbootclasspath:$bpath -cp system/app/AndroidTests.apk:data/app/AndroidTests.apk \ com.android.internal.util.WithFramework junit.textui.TestRunner $* diff --git a/tests/AndroidTests/src/com/android/unit_tests/accounts/AccountManagerServiceTest.java b/tests/AndroidTests/src/com/android/unit_tests/accounts/AccountManagerServiceTest.java new file mode 100644 index 0000000..6b8e1f0 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/accounts/AccountManagerServiceTest.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2009 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.unit_tests.accounts; + +import android.test.AndroidTestCase; +import android.test.RenamingDelegatingContext; +import android.test.IsolatedContext; +import android.test.mock.MockContext; +import android.test.mock.MockContentResolver; +import android.content.*; +import android.accounts.Account; +import android.accounts.AccountManagerService; +import android.os.Bundle; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.Map; + +public class AccountManagerServiceTest extends AndroidTestCase { + @Override + protected void setUp() throws Exception { + final String filenamePrefix = "test."; + MockContentResolver resolver = new MockContentResolver(); + RenamingDelegatingContext targetContextWrapper = new RenamingDelegatingContext( + new MockContext(), // The context that most methods are delegated to + getContext(), // The context that file methods are delegated to + filenamePrefix); + Context context = new IsolatedContext(resolver, targetContextWrapper); + setContext(context); + } + + public class AccountSorter implements Comparator<Account> { + public int compare(Account object1, Account object2) { + if (object1 == object2) return 0; + if (object1 == null) return 1; + if (object2 == null) return -1; + int result = object1.mType.compareTo(object2.mType); + if (result != 0) return result; + return object1.mName.compareTo(object2.mName); + } + } + + public void testCheckAddAccount() throws Exception { + AccountManagerService ams = new AccountManagerService(getContext()); + Account a11 = new Account("account1", "type1"); + Account a21 = new Account("account2", "type1"); + Account a31 = new Account("account3", "type1"); + Account a12 = new Account("account1", "type2"); + Account a22 = new Account("account2", "type2"); + Account a32 = new Account("account3", "type2"); + assertTrue(ams.addAccount(a11, "p11", null)); + assertTrue(ams.addAccount(a12, "p12", null)); + assertTrue(ams.addAccount(a21, "p21", null)); + assertTrue(ams.addAccount(a22, "p22", null)); + assertTrue(ams.addAccount(a31, "p31", null)); + assertTrue(ams.addAccount(a32, "p32", null)); + + assertFalse("duplicate account insertion should fail", ams.addAccount(a32, "p", null)); + + Account[] accounts = ams.getAccounts(); + Arrays.sort(accounts, new AccountSorter()); + assertEquals(6, accounts.length); + assertEquals(a11, accounts[0]); + assertEquals(a21, accounts[1]); + assertEquals(a31, accounts[2]); + assertEquals(a12, accounts[3]); + assertEquals(a22, accounts[4]); + assertEquals(a32, accounts[5]); + + accounts = ams.getAccountsByType("type1" ); + Arrays.sort(accounts, new AccountSorter()); + assertEquals(3, accounts.length); + assertEquals(a11, accounts[0]); + assertEquals(a21, accounts[1]); + assertEquals(a31, accounts[2]); + + ams.removeAccount(a21); + + accounts = ams.getAccountsByType("type1" ); + Arrays.sort(accounts, new AccountSorter()); + assertEquals(2, accounts.length); + assertEquals(a11, accounts[0]); + assertEquals(a31, accounts[1]); + } + + public void testPasswords() throws Exception { + AccountManagerService ams = new AccountManagerService(getContext()); + Account a11 = new Account("account1", "type1"); + Account a12 = new Account("account1", "type2"); + assertTrue(ams.addAccount(a11, "p11", null)); + assertTrue(ams.addAccount(a12, "p12", null)); + + assertEquals("p11", ams.getPassword(a11)); + assertEquals("p12", ams.getPassword(a12)); + + ams.setPassword(a11, "p11b"); + + assertEquals("p11b", ams.getPassword(a11)); + assertEquals("p12", ams.getPassword(a12)); + } + + public void testUserdata() throws Exception { + AccountManagerService ams = new AccountManagerService(getContext()); + Account a11 = new Account("account1", "type1"); + Bundle u11 = new Bundle(); + u11.putString("a", "a_a11"); + u11.putString("b", "b_a11"); + u11.putString("c", "c_a11"); + Account a12 = new Account("account1", "type2"); + Bundle u12 = new Bundle(); + u12.putString("a", "a_a12"); + u12.putString("b", "b_a12"); + u12.putString("c", "c_a12"); + assertTrue(ams.addAccount(a11, "p11", u11)); + assertTrue(ams.addAccount(a12, "p12", u12)); + + assertEquals("a_a11", ams.getUserData(a11, "a")); + assertEquals("b_a11", ams.getUserData(a11, "b")); + assertEquals("c_a11", ams.getUserData(a11, "c")); + assertEquals("a_a12", ams.getUserData(a12, "a")); + assertEquals("b_a12", ams.getUserData(a12, "b")); + assertEquals("c_a12", ams.getUserData(a12, "c")); + + ams.setUserData(a11, "b", "b_a11b"); + + assertEquals("a_a11", ams.getUserData(a11, "a")); + assertEquals("b_a11b", ams.getUserData(a11, "b")); + assertEquals("c_a11", ams.getUserData(a11, "c")); + assertEquals("a_a12", ams.getUserData(a12, "a")); + assertEquals("b_a12", ams.getUserData(a12, "b")); + assertEquals("c_a12", ams.getUserData(a12, "c")); + } + + public void testAuthtokens() throws Exception { + AccountManagerService ams = new AccountManagerService(getContext()); + Account a11 = new Account("account1", "type1"); + Account a12 = new Account("account1", "type2"); + assertTrue(ams.addAccount(a11, "p11", null)); + assertTrue(ams.addAccount(a12, "p12", null)); + + ams.setAuthToken(a11, "att1", "a11_att1"); + ams.setAuthToken(a11, "att2", "a11_att2"); + ams.setAuthToken(a11, "att3", "a11_att3"); + ams.setAuthToken(a12, "att1", "a12_att1"); + ams.setAuthToken(a12, "att2", "a12_att2"); + ams.setAuthToken(a12, "att3", "a12_att3"); + + assertEquals("a11_att1", ams.peekAuthToken(a11, "att1")); + assertEquals("a11_att2", ams.peekAuthToken(a11, "att2")); + assertEquals("a11_att3", ams.peekAuthToken(a11, "att3")); + assertEquals("a12_att1", ams.peekAuthToken(a12, "att1")); + assertEquals("a12_att2", ams.peekAuthToken(a12, "att2")); + assertEquals("a12_att3", ams.peekAuthToken(a12, "att3")); + + ams.setAuthToken(a11, "att3", "a11_att3b"); + ams.invalidateAuthToken(a12.mType, "a12_att2"); + + assertEquals("a11_att1", ams.peekAuthToken(a11, "att1")); + assertEquals("a11_att2", ams.peekAuthToken(a11, "att2")); + assertEquals("a11_att3b", ams.peekAuthToken(a11, "att3")); + assertEquals("a12_att1", ams.peekAuthToken(a12, "att1")); + assertNull(ams.peekAuthToken(a12, "att2")); + assertEquals("a12_att3", ams.peekAuthToken(a12, "att3")); + + assertNull(ams.readAuthTokenFromDatabase(a12, "att2")); + } +}
\ No newline at end of file diff --git a/tests/CoreTests/android/content/SyncStorageEngineTest.java b/tests/CoreTests/android/content/SyncStorageEngineTest.java index dee6e38..533338e 100644 --- a/tests/CoreTests/android/content/SyncStorageEngineTest.java +++ b/tests/CoreTests/android/content/SyncStorageEngineTest.java @@ -20,6 +20,7 @@ import android.test.AndroidTestCase; import android.test.RenamingDelegatingContext; import android.test.mock.MockContext; import android.test.mock.MockContentResolver; +import android.accounts.Account; public class SyncStorageEngineTest extends AndroidTestCase { @@ -28,7 +29,7 @@ public class SyncStorageEngineTest extends AndroidTestCase { * correcponding sync is finished. This can happen if the clock changes while we are syncing. */ public void testPurgeActiveSync() throws Exception { - final String account = "a@example.com"; + final Account account = new Account("a@example.com", "example.type"); final String authority = "testprovider"; MockContentResolver mockResolver = new MockContentResolver(); diff --git a/tests/CoreTests/com/android/internal/telephony/PhoneNumberUtilsTest.java b/tests/CoreTests/com/android/internal/telephony/PhoneNumberUtilsTest.java index e8bd239..ae11ed1 100644 --- a/tests/CoreTests/com/android/internal/telephony/PhoneNumberUtilsTest.java +++ b/tests/CoreTests/com/android/internal/telephony/PhoneNumberUtilsTest.java @@ -302,6 +302,11 @@ public class PhoneNumberUtilsTest extends TestCase { number.append("800-55512"); PhoneNumberUtils.formatNanpNumber(number); assertEquals("800-555-12", number.toString()); + + number.clear(); + number.append("46645"); + PhoneNumberUtils.formatNanpNumber(number); + assertEquals("46645", number.toString()); } @SmallTest diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java index a389461..39ce1f2 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java @@ -18,6 +18,7 @@ package com.android.dumprendertree; import android.os.Handler; import android.os.Message; +import android.webkit.WebStorage; import java.util.HashMap; @@ -25,7 +26,7 @@ public class CallbackProxy extends Handler implements EventSender, LayoutTestCon private EventSender mEventSender; private LayoutTestController mLayoutTestController; - + private static final int EVENT_DOM_LOG = 1; private static final int EVENT_FIRE_KBD = 2; private static final int EVENT_KEY_DOWN_1 = 3; @@ -57,6 +58,8 @@ public class CallbackProxy extends Handler implements EventSender, LayoutTestCon private static final int LAYOUT_SET_WINDOW_KEY = 38; private static final int LAYOUT_TEST_REPAINT = 39; private static final int LAYOUT_WAIT_UNTIL_DONE = 40; + private static final int LAYOUT_DUMP_DATABASE_CALLBACKS = 41; + private static final int LAYOUT_SET_CAN_OPEN_WINDOWS = 42; CallbackProxy(EventSender eventSender, LayoutTestController layoutTestController) { @@ -190,6 +193,14 @@ public class CallbackProxy extends Handler implements EventSender, LayoutTestCon case LAYOUT_WAIT_UNTIL_DONE: mLayoutTestController.waitUntilDone(); break; + + case LAYOUT_DUMP_DATABASE_CALLBACKS: + mLayoutTestController.dumpDatabaseCallbacks(); + break; + + case LAYOUT_SET_CAN_OPEN_WINDOWS: + mLayoutTestController.setCanOpenWindows(); + break; } } @@ -325,4 +336,20 @@ public class CallbackProxy extends Handler implements EventSender, LayoutTestCon obtainMessage(LAYOUT_WAIT_UNTIL_DONE).sendToTarget(); } + public void dumpDatabaseCallbacks() { + obtainMessage(LAYOUT_DUMP_DATABASE_CALLBACKS).sendToTarget(); + } + + public void clearAllDatabases() { + WebStorage.getInstance().deleteAllDatabases(); + } + + public void setDatabaseQuota(long quota) { + WebStorage.getInstance().setQuotaForOrigin("file://", quota); + } + + public void setCanOpenWindows() { + obtainMessage(LAYOUT_SET_CAN_OPEN_WINDOWS).sendToTarget(); + } + } diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java index 4f162b3..ede5197 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java @@ -83,7 +83,20 @@ public class FileFilter { }; static final String [] ignoreTestList = { - }; + // RegExp is exponatal + "fast/regex/test1.html", + "fast/regex/slow.html", + // RegExp is too large, causing OOM + "fast/js/regexp-charclass-crash.html", + // The Android browser has no notion of private browsing. + "storage/private-browsing-readonly.html", + "storage/domstorage/localstorage/private-browsing-affects-storage.html", + "storage/domstorage/sessionstorage/private-browsing-affects-storage.html", + // Android layout tests are stored in "layout_tests". The following two + // tests expect "LayoutTests" in their output. + "storage/domstorage/localstorage/iframe-events.html", + "storage/domstorage/sessionstorage/iframe-events.html" + }; static void fillIgnoreResultSet() { // need test plugin @@ -195,11 +208,7 @@ public class FileFilter { ignoreResultList.add("fast/loader/local-iFrame-source-from-local.html"); // extra spacing because iFrames rendered next to each other on Apple ignoreResultList.add("fast/loader/opaque-base-url.html"); - // RegExp is too large, causing OOM - ignoreResultList.add("fast/js/regexp-charclass-crash.html"); ignoreResultList.add("fast/text/plain-text-line-breaks.html"); - - } static void fillBugTable() { diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java index 6166dd0..e1d802a 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java @@ -58,5 +58,8 @@ public interface LayoutTestController { public void queueLoad(String Url, String frameTarget); public void setAcceptsEditing(boolean b); - + + // For storage tests + public void dumpDatabaseCallbacks(); + public void setCanOpenWindows(); } diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java index 1ba291c..02658a1 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java @@ -31,6 +31,7 @@ import android.webkit.JsResult; import android.webkit.SslErrorHandler; import android.webkit.WebChromeClient; import android.webkit.WebSettings; +import android.webkit.WebStorage; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.LinearLayout; @@ -38,6 +39,8 @@ import android.widget.LinearLayout; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; import java.util.Vector; public class TestShellActivity extends Activity implements LayoutTestController { @@ -90,52 +93,13 @@ public class TestShellActivity extends Activity implements LayoutTestController setContentView(contentView); mWebView = new WebView(this); - mWebView.getSettings().setJavaScriptEnabled(true); - mWebView.setWebChromeClient(mChromeClient); - mWebView.setWebViewClient(new WebViewClient(){ - - @Override - public void onPageFinished(WebView view, String url) { - Log.v(LOGTAG, "onPageFinished, url=" + url); - super.onPageFinished(view, url); - } - - @Override - public void onPageStarted(WebView view, String url, Bitmap favicon) { - Log.v(LOGTAG, "onPageStarted, url=" + url); - super.onPageStarted(view, url, favicon); - } - - @Override - public void onReceivedError(WebView view, int errorCode, String description, - String failingUrl) { - Log.v(LOGTAG, "onReceivedError, errorCode=" + errorCode - + ", desc=" + description + ", url=" + failingUrl); - super.onReceivedError(view, errorCode, description, failingUrl); - } - - @Override - public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, - String host, String realm) { - handler.cancel(); - } - - @Override - public void onReceivedSslError(WebView view, SslErrorHandler handler, - SslError error) { - handler.proceed(); - } - - }); mEventSender = new WebViewEventSender(mWebView); mCallbackProxy = new CallbackProxy(mEventSender, this); - mWebView.addJavascriptInterface(mCallbackProxy, "layoutTestController"); - mWebView.addJavascriptInterface(mCallbackProxy, "eventSender"); + setupWebViewForLayoutTests(mWebView, mCallbackProxy); + contentView.addView(mWebView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT, 0.0f)); - mWebView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL); - mHandler = new AsyncHandler(); Intent intent = getIntent(); @@ -217,6 +181,12 @@ public class TestShellActivity extends Activity implements LayoutTestController if (mDialogStrings != null) os.write(mDialogStrings.toString().getBytes()); mDialogStrings = null; + if (mDatabaseCallbackStrings != null) + os.write(mDatabaseCallbackStrings.toString().getBytes()); + mDatabaseCallbackStrings = null; + if (mConsoleMessages != null) + os.write(mConsoleMessages.toString().getBytes()); + mConsoleMessages = null; if (webkitData != null) os.write(webkitData.getBytes()); os.flush(); @@ -359,7 +329,52 @@ public class TestShellActivity extends Activity implements LayoutTestController public void testRepaint() { mWebView.invalidate(); } - + + public void dumpDatabaseCallbacks() { + Log.v(LOGTAG, "dumpDatabaseCallbacks called."); + mDumpDatabaseCallbacks = true; + } + + public void setCanOpenWindows() { + Log.v(LOGTAG, "setCanOpenWindows called."); + mCanOpenWindows = true; + } + + private final WebViewClient mViewClient = new WebViewClient(){ + @Override + public void onPageFinished(WebView view, String url) { + Log.v(LOGTAG, "onPageFinished, url=" + url); + super.onPageFinished(view, url); + } + + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + Log.v(LOGTAG, "onPageStarted, url=" + url); + super.onPageStarted(view, url, favicon); + } + + @Override + public void onReceivedError(WebView view, int errorCode, String description, + String failingUrl) { + Log.v(LOGTAG, "onReceivedError, errorCode=" + errorCode + + ", desc=" + description + ", url=" + failingUrl); + super.onReceivedError(view, errorCode, description, failingUrl); + } + + @Override + public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, + String host, String realm) { + handler.cancel(); + } + + @Override + public void onReceivedSslError(WebView view, SslErrorHandler handler, + SslError error) { + handler.proceed(); + } + }; + + private final WebChromeClient mChromeClient = new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { @@ -434,6 +449,72 @@ public class TestShellActivity extends Activity implements LayoutTestController result.confirm(); return true; } + + @Override + public void onExceededDatabaseQuota(String url_str, + String databaseIdentifier, long currentQuota, + WebStorage.QuotaUpdater callback) { + if (mDumpDatabaseCallbacks) { + if (mDatabaseCallbackStrings == null) { + mDatabaseCallbackStrings = new StringBuffer(); + } + + String protocol = ""; + String host = ""; + int port = 0; + + try { + URL url = new URL(url_str); + protocol = url.getProtocol(); + host = url.getHost(); + if (url.getPort() > -1) { + port = url.getPort(); + } + } catch (MalformedURLException e) {} + + String databaseCallbackString = + "UI DELEGATE DATABASE CALLBACK: " + + "exceededDatabaseQuotaForSecurityOrigin:{" + protocol + + ", " + host + ", " + port + "} database:" + + databaseIdentifier + "\n"; + Log.v(LOGTAG, "LOG: "+databaseCallbackString); + mDatabaseCallbackStrings.append(databaseCallbackString); + } + // Give 5MB more quota. + callback.updateQuota(currentQuota + 1024 * 1024 * 5); + } + + @Override + public void addMessageToConsole(String message, int lineNumber, + String sourceID) { + if (mConsoleMessages == null) { + mConsoleMessages = new StringBuffer(); + } + String consoleMessage = "CONSOLE MESSAGE: line " + + lineNumber +": "+ message +"\n"; + mConsoleMessages.append(consoleMessage); + Log.v(LOGTAG, "LOG: "+consoleMessage); + } + + @Override + public boolean onCreateWindow(WebView view, boolean dialog, + boolean userGesture, Message resultMsg) { + if (!mCanOpenWindows) { + return false; + } + + // We never display the new window, just create the view and + // allow it's content to execute and be recorded by the test + // runner. + + WebView newWindowView = new WebView(TestShellActivity.this); + setupWebViewForLayoutTests(newWindowView, mCallbackProxy); + WebView.WebViewTransport transport = + (WebView.WebViewTransport) resultMsg.obj; + transport.setWebView(newWindowView); + resultMsg.sendToTarget(); + return true; + } }; private void resetTestStatus() { @@ -442,9 +523,32 @@ public class TestShellActivity extends Activity implements LayoutTestController mTimedOut = false; mDumpTitleChanges = false; mRequestedWebKitData = false; + mDumpDatabaseCallbacks = false; + mCanOpenWindows = false; mEventSender.resetMouse(); } - + + private void setupWebViewForLayoutTests(WebView webview, CallbackProxy callbackProxy) { + if (webview == null) { + return; + } + + WebSettings settings = webview.getSettings(); + settings.setJavaScriptEnabled(true); + settings.setJavaScriptCanOpenWindowsAutomatically(true); + settings.setSupportMultipleWindows(true); + settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL); + settings.setDatabaseEnabled(true); + settings.setDatabasePath(getDir("databases",0).getAbsolutePath()); + settings.setDomStorageEnabled(true); + + webview.addJavascriptInterface(callbackProxy, "layoutTestController"); + webview.addJavascriptInterface(callbackProxy, "eventSender"); + + webview.setWebChromeClient(mChromeClient); + webview.setWebViewClient(mViewClient); + } + private WebView mWebView; private WebViewEventSender mEventSender; private AsyncHandler mHandler; @@ -470,6 +574,10 @@ public class TestShellActivity extends Activity implements LayoutTestController private StringBuffer mDialogStrings; private boolean mKeepWebHistory; private Vector mWebHistory; + private boolean mDumpDatabaseCallbacks; + private StringBuffer mDatabaseCallbackStrings; + private StringBuffer mConsoleMessages; + private boolean mCanOpenWindows; static final String TIMEOUT_STR = "**Test timeout"; diff --git a/tests/FrameworkTest/tests/src/android/content/AbstractTableMergerTest.java b/tests/FrameworkTest/tests/src/android/content/AbstractTableMergerTest.java index aa3d186..42c1e78 100644 --- a/tests/FrameworkTest/tests/src/android/content/AbstractTableMergerTest.java +++ b/tests/FrameworkTest/tests/src/android/content/AbstractTableMergerTest.java @@ -8,6 +8,7 @@ import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.test.AndroidTestCase; import android.text.TextUtils; +import android.accounts.Account; import java.util.ArrayList; import java.util.Map; @@ -26,7 +27,7 @@ public class AbstractTableMergerTest extends AndroidTestCase { static final Uri TABLE_URI = Uri.withAppendedPath(CONTENT_URI, TABLE_NAME); static final Uri DELETED_TABLE_URI = Uri.withAppendedPath(CONTENT_URI, DELETED_TABLE_NAME); - private final String ACCOUNT = "account@goo.com"; + private final Account ACCOUNT = new Account("account@goo.com", "example.type"); private final ArrayList<Expectation> mExpectations = Lists.newArrayList(); @@ -65,25 +66,31 @@ public class AbstractTableMergerTest extends AndroidTestCase { mExpectations.clear(); } - ContentValues newValues(String data, String syncId, String syncAccount, + ContentValues newValues(String data, String syncId, Account syncAccount, String syncTime, String syncVersion, Long syncLocalId) { ContentValues values = new ContentValues(); if (data != null) values.put("data", data); if (syncTime != null) values.put("_sync_time", syncTime); if (syncVersion != null) values.put("_sync_version", syncVersion); if (syncId != null) values.put("_sync_id", syncId); - if (syncAccount != null) values.put("_sync_account", syncAccount); + if (syncAccount != null) { + values.put("_sync_account", syncAccount.mName); + values.put("_sync_account_type", syncAccount.mType); + } values.put("_sync_local_id", syncLocalId); values.put("_sync_dirty", 0); return values; } - ContentValues newDeletedValues(String syncId, String syncAccount, String syncVersion, + ContentValues newDeletedValues(String syncId, Account syncAccount, String syncVersion, Long syncLocalId) { ContentValues values = new ContentValues(); if (syncVersion != null) values.put("_sync_version", syncVersion); if (syncId != null) values.put("_sync_id", syncId); - if (syncAccount != null) values.put("_sync_account", syncAccount); + if (syncAccount != null) { + values.put("_sync_account", syncAccount.mName); + values.put("_sync_account_type", syncAccount.mType); + } if (syncLocalId != null) values.put("_sync_local_id", syncLocalId); return values; } @@ -380,6 +387,7 @@ public class AbstractTableMergerTest extends AndroidTestCase { + "_sync_local_id INTEGER, " + "_sync_dirty INTEGER NOT NULL DEFAULT 0, " + "_sync_account TEXT, " + + "_sync_account_type TEXT, " + "_sync_mark INTEGER)"); mDb.execSQL("CREATE TABLE deleted_items (" @@ -388,6 +396,7 @@ public class AbstractTableMergerTest extends AndroidTestCase { + "_sync_id TEXT, " + "_sync_local_id INTEGER, " + "_sync_account TEXT, " + + "_sync_account_type TEXT, " + "_sync_mark INTEGER)"); } @@ -501,7 +510,7 @@ public class AbstractTableMergerTest extends AndroidTestCase { throw new UnsupportedOperationException(); } - public void onSyncStart(SyncContext context, String account) { + public void onSyncStart(SyncContext context, Account account) { throw new UnsupportedOperationException(); } @@ -509,7 +518,7 @@ public class AbstractTableMergerTest extends AndroidTestCase { throw new UnsupportedOperationException(); } - public String getSyncingAccount() { + public Account getSyncingAccount() { throw new UnsupportedOperationException(); } @@ -544,24 +553,24 @@ public class AbstractTableMergerTest extends AndroidTestCase { throw new UnsupportedOperationException(); } - protected void onAccountsChanged(String[] accountsArray) { + protected void onAccountsChanged(Account[] accountsArray) { throw new UnsupportedOperationException(); } - protected void deleteRowsForRemovedAccounts(Map<String, Boolean> accounts, String table, - String accountColumnName) { + protected void deleteRowsForRemovedAccounts(Map<Account, Boolean> accounts, String table + ) { throw new UnsupportedOperationException(); } - public void wipeAccount(String account) { + public void wipeAccount(Account account) { throw new UnsupportedOperationException(); } - public byte[] readSyncDataBytes(String account) { + public byte[] readSyncDataBytes(Account account) { throw new UnsupportedOperationException(); } - public void writeSyncDataBytes(String account, byte[] data) { + public void writeSyncDataBytes(Account account, byte[] data) { throw new UnsupportedOperationException(); } } diff --git a/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java b/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java new file mode 100644 index 0000000..e9a43d7 --- /dev/null +++ b/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java @@ -0,0 +1,468 @@ +/* + * Copyright (C) 2009 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 android.content; + +import android.database.Cursor; +import android.net.Uri; +import android.os.Parcel; +import android.test.suitebuilder.annotation.SmallTest; +import android.text.TextUtils; +import junit.framework.TestCase; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; + +@SmallTest +public class ContentProviderOperationTest extends TestCase { + private final static Uri sTestUri1 = Uri.parse("content://authority/blah"); + private final static ContentValues sTestValues1; + + private final static Class<ContentProviderOperation.Builder> CLASS_BUILDER = + ContentProviderOperation.Builder.class; + private final static Class<ContentProviderOperation> CLASS_OPERATION = + ContentProviderOperation.class; + + static { + sTestValues1 = new ContentValues(); + sTestValues1.put("a", 1); + sTestValues1.put("b", "two"); + } + + public void testInsert() throws OperationApplicationException { + ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1) + .withValues(sTestValues1) + .build(); + ContentProviderResult result = op1.apply(new TestContentProvider() { + public Uri insert(Uri uri, ContentValues values) { + assertEquals(sTestUri1.toString(), uri.toString()); + assertEquals(sTestValues1.toString(), values.toString()); + return uri.buildUpon().appendPath("19").build(); + } + }, null, 0); + assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString()); + } + + public void testInsertNoValues() throws OperationApplicationException { + ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1) + .build(); + ContentProviderResult result = op1.apply(new TestContentProvider() { + public Uri insert(Uri uri, ContentValues values) { + assertEquals(sTestUri1.toString(), uri.toString()); + assertNull(values); + return uri.buildUpon().appendPath("19").build(); + } + }, null, 0); + assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString()); + } + + public void testInsertFailed() { + ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1) + .withValues(sTestValues1) + .build(); + try { + op1.apply(new TestContentProvider() { + public Uri insert(Uri uri, ContentValues values) { + assertEquals(sTestUri1.toString(), uri.toString()); + assertEquals(sTestValues1.toString(), values.toString()); + return null; + } + }, null, 0); + fail("the apply should have thrown an OperationApplicationException"); + } catch (OperationApplicationException e) { + // this is the expected case + } + } + + public void testInsertWithBackRefs() throws OperationApplicationException { + ContentProviderResult[] previousResults = new ContentProviderResult[4]; + previousResults[0] = new ContentProviderResult(100); + previousResults[1] = new ContentProviderResult(101); + previousResults[2] = new ContentProviderResult(102); + previousResults[3] = new ContentProviderResult(103); + ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1) + .withValues(sTestValues1) + .withValueBackReference("a1", 3) + .withValueBackReference("a2", 1) + .build(); + ContentProviderResult result = op1.apply(new TestContentProvider() { + public Uri insert(Uri uri, ContentValues values) { + assertEquals(sTestUri1.toString(), uri.toString()); + ContentValues expected = new ContentValues(sTestValues1); + expected.put("a1", 103); + expected.put("a2", 101); + assertEquals(expected.toString(), values.toString()); + return uri.buildUpon().appendPath("19").build(); + } + }, previousResults, previousResults.length); + assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString()); + } + + public void testUpdate() throws OperationApplicationException { + ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1) + .withValues(sTestValues1) + .build(); + ContentProviderResult[] backRefs = new ContentProviderResult[2]; + ContentProviderResult result = op1.apply(new TestContentProvider() { + public Uri insert(Uri uri, ContentValues values) { + assertEquals(sTestUri1.toString(), uri.toString()); + assertEquals(sTestValues1.toString(), values.toString()); + return uri.buildUpon().appendPath("19").build(); + } + }, backRefs, 1); + assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString()); + } + + public void testValueBackRefs() { + ContentValues values = new ContentValues(); + values.put("a", "in1"); + values.put("a2", "in2"); + values.put("b", "in3"); + values.put("c", "in4"); + + ContentProviderResult[] previousResults = new ContentProviderResult[4]; + previousResults[0] = new ContentProviderResult(100); + previousResults[1] = new ContentProviderResult(101); + previousResults[2] = new ContentProviderResult(102); + previousResults[3] = new ContentProviderResult(103); + + ContentValues expectedValues = new ContentValues(values); + expectedValues.put("a1", "103"); + expectedValues.put("a2", "101"); + expectedValues.put("a3", "102"); + + ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1) + .withValues(values) + .withValueBackReference("a1", 3) + .withValueBackReference("a2", 1) + .withValueBackReference("a3", 2) + .build(); + ContentValues v2 = op1.resolveValueBackReferences(previousResults, previousResults.length); + assertEquals(expectedValues, v2); + } + + public void testSelectionBackRefs() { + ContentProviderResult[] previousResults = new ContentProviderResult[4]; + previousResults[0] = new ContentProviderResult(100); + previousResults[1] = new ContentProviderResult(101); + previousResults[2] = new ContentProviderResult(102); + previousResults[3] = new ContentProviderResult(103); + + String[] selectionArgs = new String[]{"a", null, null, "b", null}; + + ContentProviderOperation op1 = ContentProviderOperation.newUpdate(sTestUri1) + .withSelectionBackReference(1, 3) + .withSelectionBackReference(2, 1) + .withSelectionBackReference(4, 2) + .withSelection("unused", selectionArgs) + .build(); + String[] s2 = op1.resolveSelectionArgsBackReferences( + previousResults, previousResults.length); + assertEquals("a,103,101,b,102", TextUtils.join(",", s2)); + } + + public void testParcelingOperation() throws NoSuchFieldException, IllegalAccessException, + NoSuchMethodException, InvocationTargetException, InstantiationException { + Parcel parcel = Parcel.obtain(); + ContentProviderOperation op1; + ContentProviderOperation op2; + + HashMap<Integer, Integer> selArgsBackRef = new HashMap<Integer, Integer>(); + selArgsBackRef.put(1, 2); + selArgsBackRef.put(3, 4); + + ContentValues values = new ContentValues(); + values.put("v1", "val1"); + values.put("v2", "43"); + + ContentValues valuesBackRef = new ContentValues(); + values.put("v3", "val3"); + values.put("v4", "44"); + + try { + ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert( + Uri.parse("content://goo/bar")); + + builderSetExpectedCount(builder, 42); + builderSetSelection(builder, "selection"); + builderSetSelectionArgs(builder, new String[]{"a", "b"}); + builderSetSelectionArgsBackReferences(builder, selArgsBackRef); + builderSetValues(builder, values); + builderSetValuesBackReferences(builder, valuesBackRef); + + op1 = newOperationFromBuilder(builder); + op1.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + op2 = ContentProviderOperation.CREATOR.createFromParcel(parcel); + + assertEquals(1 /* ContentProviderOperation.TYPE_INSERT */, operationGetType(op2)); + assertEquals("content://goo/bar", operationGetUri(op2).toString()); + assertEquals(Integer.valueOf(42), operationGetExpectedCount(op2)); + assertEquals("selection", operationGetSelection(op2)); + assertEquals(2, operationGetSelectionArgs(op2).length); + assertEquals("a", operationGetSelectionArgs(op2)[0]); + assertEquals("b", operationGetSelectionArgs(op2)[1]); + assertEquals(values, operationGetValues(op2)); + assertEquals(valuesBackRef, operationGetValuesBackReferences(op2)); + assertEquals(2, operationGetSelectionArgsBackReferences(op2).size()); + assertEquals(Integer.valueOf(2), operationGetSelectionArgsBackReferences(op2).get(1)); + assertEquals(Integer.valueOf(4), operationGetSelectionArgsBackReferences(op2).get(3)); + } finally { + parcel.recycle(); + } + + try { + ContentProviderOperation.Builder builder = ContentProviderOperation.newUpdate( + Uri.parse("content://goo/bar")); + + builderSetSelectionArgsBackReferences(builder, selArgsBackRef); + + op1 = newOperationFromBuilder(builder); + op1.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + op2 = ContentProviderOperation.CREATOR.createFromParcel(parcel); + assertEquals(2 /* ContentProviderOperation.TYPE_UPDATE */, operationGetType(op2)); + assertEquals("content://goo/bar", operationGetUri(op2).toString()); + assertNull(operationGetEntity(op2)); + assertNull(operationGetExpectedCount(op2)); + assertNull(operationGetSelection(op2)); + assertNull(operationGetSelectionArgs(op2)); + assertNull(operationGetValues(op2)); + assertNull(operationGetValuesBackReferences(op2)); + assertEquals(2, operationGetSelectionArgsBackReferences(op2).size()); + assertEquals(Integer.valueOf(2), operationGetSelectionArgsBackReferences(op2).get(1)); + assertEquals(Integer.valueOf(4), operationGetSelectionArgsBackReferences(op2).get(3)); + } finally { + parcel.recycle(); + } + + try { + ContentProviderOperation.Builder builder = ContentProviderOperation.newDelete( + Uri.parse("content://goo/bar")); + + op1 = newOperationFromBuilder(builder); + op1.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + op2 = ContentProviderOperation.CREATOR.createFromParcel(parcel); + assertEquals(3 /* ContentProviderOperation.TYPE_DELETE */, operationGetType(op2)); + assertEquals("content://goo/bar", operationGetUri(op2).toString()); + assertNull(operationGetEntity(op2)); + assertNull(operationGetExpectedCount(op2)); + assertNull(operationGetSelection(op2)); + assertNull(operationGetSelectionArgs(op2)); + assertNull(operationGetValues(op2)); + assertNull(operationGetValuesBackReferences(op2)); + assertNull(operationGetSelectionArgsBackReferences(op2)); + } finally { + parcel.recycle(); + } + } + + private static ContentProviderOperation newOperationFromBuilder( + ContentProviderOperation.Builder builder) + throws NoSuchMethodException, InstantiationException, IllegalAccessException, + InvocationTargetException { + final Constructor constructor = CLASS_OPERATION.getDeclaredConstructor(CLASS_BUILDER); + constructor.setAccessible(true); + return (ContentProviderOperation) constructor.newInstance(builder); + } + + private void builderSetSelectionArgsBackReferences( + ContentProviderOperation.Builder builder, HashMap<Integer, Integer> selArgsBackRef) + throws NoSuchFieldException, IllegalAccessException { + Field field; + field = CLASS_BUILDER.getDeclaredField("mSelectionArgsBackReferences"); + field.setAccessible(true); + field.set(builder, selArgsBackRef); + } + + private void builderSetValuesBackReferences( + ContentProviderOperation.Builder builder, ContentValues valuesBackReferences) + throws NoSuchFieldException, IllegalAccessException { + Field field; + field = CLASS_BUILDER.getDeclaredField("mValuesBackReferences"); + field.setAccessible(true); + field.set(builder, valuesBackReferences); + } + + private void builderSetSelection( + ContentProviderOperation.Builder builder, String selection) + throws NoSuchFieldException, IllegalAccessException { + Field field; + field = CLASS_BUILDER.getDeclaredField("mSelection"); + field.setAccessible(true); + field.set(builder, selection); + } + + private void builderSetSelectionArgs( + ContentProviderOperation.Builder builder, String[] selArgs) + throws NoSuchFieldException, IllegalAccessException { + Field field; + field = CLASS_BUILDER.getDeclaredField("mSelectionArgs"); + field.setAccessible(true); + field.set(builder, selArgs); + } + + private void builderSetValues( + ContentProviderOperation.Builder builder, ContentValues values) + throws NoSuchFieldException, IllegalAccessException { + Field field; + field = CLASS_BUILDER.getDeclaredField("mValues"); + field.setAccessible(true); + field.set(builder, values); + } + + private void builderSetEntity( + ContentProviderOperation.Builder builder, Entity entity) + throws NoSuchFieldException, IllegalAccessException { + Field field; + field = CLASS_BUILDER.getDeclaredField("mEntity"); + field.setAccessible(true); + field.set(builder, entity); + } + + private void builderSetExpectedCount( + ContentProviderOperation.Builder builder, Integer expectedCount) + throws NoSuchFieldException, IllegalAccessException { + Field field; + field = CLASS_BUILDER.getDeclaredField("mExpectedCount"); + field.setAccessible(true); + field.set(builder, expectedCount); + } + + private int operationGetType(ContentProviderOperation operation) + throws NoSuchFieldException, IllegalAccessException { + final Field field = CLASS_OPERATION.getDeclaredField("mType"); + field.setAccessible(true); + return field.getInt(operation); + } + + private Uri operationGetUri(ContentProviderOperation operation) + throws NoSuchFieldException, IllegalAccessException { + final Field field = CLASS_OPERATION.getDeclaredField("mUri"); + field.setAccessible(true); + return (Uri) field.get(operation); + } + + private String operationGetSelection(ContentProviderOperation operation) + throws NoSuchFieldException, IllegalAccessException { + final Field field = CLASS_OPERATION.getDeclaredField("mSelection"); + field.setAccessible(true); + return (String) field.get(operation); + } + + private String[] operationGetSelectionArgs(ContentProviderOperation operation) + throws NoSuchFieldException, IllegalAccessException { + final Field field = CLASS_OPERATION.getDeclaredField("mSelectionArgs"); + field.setAccessible(true); + return (String[]) field.get(operation); + } + + private ContentValues operationGetValues(ContentProviderOperation operation) + throws NoSuchFieldException, IllegalAccessException { + final Field field = CLASS_OPERATION.getDeclaredField("mValues"); + field.setAccessible(true); + return (ContentValues) field.get(operation); + } + + private Entity operationGetEntity(ContentProviderOperation operation) + throws NoSuchFieldException, IllegalAccessException { + final Field field = CLASS_OPERATION.getDeclaredField("mEntity"); + field.setAccessible(true); + return (Entity) field.get(operation); + } + + private Integer operationGetExpectedCount(ContentProviderOperation operation) + throws NoSuchFieldException, IllegalAccessException { + final Field field = CLASS_OPERATION.getDeclaredField("mExpectedCount"); + field.setAccessible(true); + return (Integer) field.get(operation); + } + + private ContentValues operationGetValuesBackReferences(ContentProviderOperation operation) + throws NoSuchFieldException, IllegalAccessException { + final Field field = CLASS_OPERATION.getDeclaredField("mValuesBackReferences"); + field.setAccessible(true); + return (ContentValues) field.get(operation); + } + + private Map<Integer, Integer> operationGetSelectionArgsBackReferences( + ContentProviderOperation operation) + throws NoSuchFieldException, IllegalAccessException { + final Field field = CLASS_OPERATION.getDeclaredField("mSelectionArgsBackReferences"); + field.setAccessible(true); + return (Map<Integer, Integer>) field.get(operation); + } + + public void testParcelingResult() { + Parcel parcel = Parcel.obtain(); + ContentProviderResult result1; + ContentProviderResult result2; + try { + result1 = new ContentProviderResult(Uri.parse("content://goo/bar")); + result1.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + result2 = ContentProviderResult.CREATOR.createFromParcel(parcel); + assertEquals("content://goo/bar", result2.uri.toString()); + assertNull(result2.count); + } finally { + parcel.recycle(); + } + + parcel = Parcel.obtain(); + try { + result1 = new ContentProviderResult(42); + result1.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + result2 = ContentProviderResult.CREATOR.createFromParcel(parcel); + assertEquals(Integer.valueOf(42), result2.count); + assertNull(result2.uri); + } finally { + parcel.recycle(); + } + } + + static class TestContentProvider extends ContentProvider { + public boolean onCreate() { + throw new UnsupportedOperationException(); + } + + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, + String sortOrder) { + throw new UnsupportedOperationException(); + } + + public String getType(Uri uri) { + throw new UnsupportedOperationException(); + } + + public Uri insert(Uri uri, ContentValues values) { + throw new UnsupportedOperationException(); + } + + public int delete(Uri uri, String selection, String[] selectionArgs) { + throw new UnsupportedOperationException(); + } + + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + throw new UnsupportedOperationException(); + } + } +}
\ No newline at end of file |