Start of unit tests for ConversationCursor/Provider
* Includes modified TestProvider code originally intended for
the Exchange application (as MockProvider)
Change-Id: I40126892c2177260a8eb1ace6e21e47a9ecf7665
diff --git a/src/com/android/mail/browse/ConversationCursor.java b/src/com/android/mail/browse/ConversationCursor.java
index 5716697..05c1e69 100644
--- a/src/com/android/mail/browse/ConversationCursor.java
+++ b/src/com/android/mail/browse/ConversationCursor.java
@@ -36,6 +36,7 @@
import com.android.mail.providers.Conversation;
import com.android.mail.providers.UIProvider;
+import com.google.common.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.HashMap;
@@ -58,7 +59,8 @@
// The cursor instantiator's activity
private static Activity sActivity;
// The cursor underlying the caching cursor
- private static Cursor sUnderlyingCursor;
+ @VisibleForTesting
+ static Cursor sUnderlyingCursor;
// The new cursor obtained via a requery
private static Cursor sRequeryCursor;
// A mapping from Uri to updated ContentValues
@@ -79,7 +81,8 @@
// The listener registered for this cursor
private static ConversationListener sListener;
// The ConversationProvider instance
- private static ConversationProvider sProvider;
+ @VisibleForTesting
+ static ConversationProvider sProvider;
// Set when we're in the middle of a refresh of the underlying cursor
private static boolean sRefreshInProgress = false;
// Set when we've sent refreshReady() to listeners
@@ -756,14 +759,16 @@
// Placeholder for now; there's no local insert
}
- private void deleteLocal(Uri uri) {
+ @VisibleForTesting
+ void deleteLocal(Uri uri) {
Uri underlyingUri = uriFromCachingUri(uri);
// Remember to decode the underlying Uri as it might be encoded (as w/ Gmail)
String uriString = Uri.decode(underlyingUri.toString());
cacheValue(uriString, DELETED_COLUMN, true);
}
- private void updateLocal(Uri uri, ContentValues values) {
+ @VisibleForTesting
+ void updateLocal(Uri uri, ContentValues values) {
Uri underlyingUri = uriFromCachingUri(uri);
// Remember to decode the underlying Uri as it might be encoded (as w/ Gmail)
String uriString = Uri.decode(underlyingUri.toString());
diff --git a/tests/src/com/android/mail/browse/ConversationCursorTests.java b/tests/src/com/android/mail/browse/ConversationCursorTests.java
new file mode 100644
index 0000000..bb458aa
--- /dev/null
+++ b/tests/src/com/android/mail/browse/ConversationCursorTests.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * Copyright (C) 2012 Google Inc.
+ * Licensed to 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.mail.browse;
+
+import android.app.Activity;
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.OperationApplicationException;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.RemoteException;
+import android.test.ProviderTestCase2;
+import android.test.mock.MockContentResolver;
+
+import com.android.mail.browse.ConversationCursor.ConversationProvider;
+
+import java.util.ArrayList;
+
+public class ConversationCursorTests extends ProviderTestCase2<TestProvider> {
+
+ public ConversationCursorTests(Class<TestProvider> providerClass, String providerAuthority) {
+ super(providerClass, providerAuthority);
+ }
+
+ Activity mActivity;
+ Context mMockContext;
+ MockContentResolver mMockResolver;
+
+ private static final String CONVO_TABLE = "convo";
+
+ public ConversationCursorTests() {
+ super(TestProvider.class, TestProvider.AUTHORITY);
+ mActivity = new Activity() {
+ public ContentResolver getContentResolver() {
+ return mMockResolver;
+ }
+ };
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mMockContext = getMockContext();
+ mMockResolver = (MockContentResolver)mMockContext.getContentResolver();
+ mMockResolver.addProvider(TestProvider.AUTHORITY, new TestProvider(mMockContext));
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ private static final String SUBJECT_COLUMN = "subject";
+ private static final String FOLDER_COLUMN = "folder";
+ private static final String READ_COLUMN = "read";
+ private static final String STARRED_COLUMN = "starred";
+ private static final String URI_COLUMN = "uri";
+
+// private static final int SUBJECT_INDEX = 0;
+// private static final int FOLDER_INDEX = 1;
+// private static final int READ_INDEX = 2;
+// private static final int STARRED_INDEX = 3;
+ private static final int URI_INDEX = 4;
+
+ private static final String[] CONVO_PROJECTION = new String[] {
+ SUBJECT_COLUMN, FOLDER_COLUMN, READ_COLUMN, STARRED_COLUMN, URI_COLUMN};
+
+ private ContentValues makeConvo(String subject, String folder, int read, int starred) {
+ ContentValues cv = new ContentValues();
+ cv.put(SUBJECT_COLUMN, subject);
+ cv.put(FOLDER_COLUMN, folder);
+ cv.put(READ_COLUMN, read);
+ cv.put(STARRED_COLUMN, starred);
+ return cv;
+ }
+
+ private Uri setupConvoList() throws RemoteException, OperationApplicationException {
+ // The Uri is content://com.android.canhaz/pony
+ Uri uri = new Uri.Builder().scheme("content").authority(TestProvider.AUTHORITY)
+ .path(CONVO_TABLE).build();
+ // Our array of CPO's to be used with applyBatch
+ ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
+ // Insert 9 convos
+ ContentValues values = makeConvo("Subj1", "Folder", 0, 0);
+ ops.add(ContentProviderOperation.newInsert(uri).withValues(values).build());
+ values = makeConvo("Subj2", "Folder", 0, 1);
+ ops.add(ContentProviderOperation.newInsert(uri).withValues(values).build());
+ values = makeConvo("Subj3", "Folder", 0, 0);
+ ops.add(ContentProviderOperation.newInsert(uri).withValues(values).build());
+ values = makeConvo("Subj4", "Folder", 0, 1);
+ ops.add(ContentProviderOperation.newInsert(uri).withValues(values).build());
+ values = makeConvo("Subj5", "Folder", 1, 0);
+ ops.add(ContentProviderOperation.newInsert(uri).withValues(values).build());
+ values = makeConvo("Subj6", "Folder", 1, 1);
+ ops.add(ContentProviderOperation.newInsert(uri).withValues(values).build());
+ values = makeConvo("Subj7", "Folder", 1, 0);
+ ops.add(ContentProviderOperation.newInsert(uri).withValues(values).build());
+ values = makeConvo("Subj8", "Folder", 1, 1);
+ ops.add(ContentProviderOperation.newInsert(uri).withValues(values).build());
+ values = makeConvo("Subj9", "Folder", 1, 0);
+ ops.add(ContentProviderOperation.newInsert(uri).withValues(values).build());
+ // Apply the batch with one insert operation
+ ContentProviderResult[] results = mMockResolver.applyBatch(TestProvider.AUTHORITY, ops);
+ ops.clear();
+ // Set up the uri column (basis of the cache)
+ for (ContentProviderResult result: results) {
+ ops.add(ContentProviderOperation
+ .newUpdate(result.uri)
+ .withValue(URI_COLUMN, result.uri.toString())
+ .build());
+ }
+ mMockResolver.applyBatch(TestProvider.AUTHORITY, ops);
+ return uri;
+ }
+
+ public void testLocalDelete() throws RemoteException, OperationApplicationException {
+ Uri uri = setupConvoList();
+
+ // Now, get our CC
+ ConversationCursor cc =
+ ConversationCursor.create(mActivity, URI_COLUMN,
+ uri, CONVO_PROJECTION, null, null, null);
+ ConversationProvider cp = ConversationCursor.sProvider;
+ Cursor uc = ConversationCursor.sUnderlyingCursor;
+ // First things first; cc & uc should both have 9 rows
+ assertEquals(9, cc.getCount());
+ assertEquals(9, uc.getCount());
+
+ // Get the uri's of our convos (the mock provider doesn't order rows)
+ String[] uris = new String[cc.getCount()];
+ int i = 0;
+ while (cc.moveToNext()) {
+ uris[i++] = cc.getString(URI_INDEX);
+ }
+
+ // Get a random uri (first will do)
+ String uriString = uris[0];
+ Uri ccUri = Uri.parse(uriString);
+ // It should have the authority of CP
+ assertEquals(ccUri.getAuthority(), ConversationProvider.AUTHORITY);
+
+ // Try deleting a row locally
+ cp.deleteLocal(Uri.parse(uris[4]));
+ assertEquals(8, cc.getCount());
+ assertEquals(9, uc.getCount());
+ }
+}
diff --git a/tests/src/com/android/mail/browse/TestProvider.java b/tests/src/com/android/mail/browse/TestProvider.java
new file mode 100644
index 0000000..42b2d66
--- /dev/null
+++ b/tests/src/com/android/mail/browse/TestProvider.java
@@ -0,0 +1,235 @@
+/*******************************************************************************
+ * Copyright (C) 2012 Google Inc.
+ * Licensed to 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.mail.browse;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.Map.Entry;
+
+/**
+ * TestProvider is a ContentProvider that can be used to simulate the storage and retrieval of
+ * rows from any ContentProvider, even if that provider does not exist in the caller's package.
+ *
+ * It is specifically designed to enable testing of sync adapters that create
+ * ContentProviderOperations (CPOs) that are then executed using ContentResolver.applyBatch().
+ * Why is this useful? Because we can't instantiate CalendarProvider or ContactsProvider from our
+ * package, as required by MockContentResolver.addProvider()
+ *
+ * Usage:
+ *
+ * ContentResolver.applyBatch(MockProvider.AUTHORITY, batch) will cause the CPOs to be executed,
+ * returning an array of ContentProviderResult; in the case of inserts, the result will include
+ * a Uri that can be used via query(). Note that the CPOs can contain references to any authority.
+ *
+ * query() does not allow non-null selection, selectionArgs, or sortOrder arguments; the
+ * presence of these will result in an UnsupportedOperationException insert() acts as expected,
+ * returning a Uri that can be directly used in a query
+ *
+ * delete() and update() do not allow non-null selection or selectionArgs arguments; the presence
+ * of these will result in an UnsupportedOperationException
+ *
+ * NOTE: When using any operation other than applyBatch, the Uri to be used must be created with
+ * MockProvider.uri(yourUri). This guarantees that the operation is sent to MockProvider
+ *
+ * NOTE: MockProvider only simulates direct storage/retrieval of rows; it does not (and can not)
+ * simulate other actions (e.g. creation of ancillary data) that the actual provider might perform
+ *
+ * NOTE: See MockProviderTests for usage examples
+ **/
+public class TestProvider extends ContentProvider {
+ public static final String AUTHORITY = "com.android.mail.mock.provider";
+ /* package */static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+
+ /* package */static final int TABLE = 100;
+ /* package */static final int RECORD = 101;
+
+ public static final String ID_COLUMN = "_id";
+
+ public TestProvider() {
+ super();
+ }
+
+ public TestProvider(Context context) {
+ this();
+ attachInfo(context, null);
+ }
+
+ // We'll store our values here
+ private HashMap<String, ContentValues> mMockStore = new HashMap<String, ContentValues>();
+ // And we'll generate new id's from here
+ long mMockId = 1;
+
+ /**
+ * Create a Uri for MockProvider from a given Uri
+ *
+ * @param uri the Uri from which the MockProvider Uri will be created
+ * @return a Uri that can be used with MockProvider
+ */
+ public static Uri uri(Uri uri) {
+ return new Uri.Builder().scheme("content").authority(AUTHORITY)
+ .path(uri.getPath().substring(1)).build();
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ if (selection != null || selectionArgs != null) {
+ throw new UnsupportedOperationException();
+ }
+ String path = uri.getPath();
+ if (mMockStore.containsKey(path)) {
+ mMockStore.remove(path);
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ // Remove the leading slash
+ String table = uri.getPath().substring(1);
+ long id = mMockId++;
+ Uri newUri = new Uri.Builder().scheme("content").authority(AUTHORITY).path(table)
+ .appendPath(Long.toString(id)).build();
+ // Remember to store the _id
+ values.put(ID_COLUMN, id);
+ mMockStore.put(newUri.getPath(), values);
+ int match = sURIMatcher.match(uri);
+ if (match == UriMatcher.NO_MATCH) {
+ sURIMatcher.addURI(AUTHORITY, table, TABLE);
+ sURIMatcher.addURI(AUTHORITY, table + "/#", RECORD);
+ }
+ return newUri;
+ }
+
+ @Override
+ public boolean onCreate() {
+ return false;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ if (selection != null || selectionArgs != null || sortOrder != null || projection == null) {
+ throw new UnsupportedOperationException();
+ }
+ final int match = sURIMatcher.match(uri(uri));
+ ArrayList<ContentValues> valuesList = new ArrayList<ContentValues>();
+ switch (match) {
+ case TABLE:
+ Set<Entry<String, ContentValues>> entrySet = mMockStore.entrySet();
+ String prefix = uri.getPath() + "/";
+ for (Entry<String, ContentValues> entry : entrySet) {
+ if (entry.getKey().startsWith(prefix)) {
+ valuesList.add(entry.getValue());
+ }
+ }
+ break;
+ case RECORD:
+ ContentValues values = mMockStore.get(uri.getPath());
+ if (values != null) {
+ valuesList.add(values);
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+ MatrixCursor cursor = new MatrixCursor(projection, 1);
+ for (ContentValues cv : valuesList) {
+ Object[] rowValues = new Object[projection.length];
+ int i = 0;
+ for (String column : projection) {
+ rowValues[i++] = cv.get(column);
+ }
+ cursor.addRow(rowValues);
+ }
+ return cursor;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues newValues, String selection, String[] selectionArgs) {
+ if (selection != null || selectionArgs != null) {
+ throw new UnsupportedOperationException();
+ }
+ final int match = sURIMatcher.match(uri(uri));
+ ArrayList<ContentValues> updateValuesList = new ArrayList<ContentValues>();
+ String path = uri.getPath();
+ switch (match) {
+ case TABLE:
+ Set<Entry<String, ContentValues>> entrySet = mMockStore.entrySet();
+ String prefix = path + "/";
+ for (Entry<String, ContentValues> entry : entrySet) {
+ if (entry.getKey().startsWith(prefix)) {
+ updateValuesList.add(entry.getValue());
+ }
+ }
+ break;
+ case RECORD:
+ ContentValues cv = mMockStore.get(path);
+ if (cv != null) {
+ updateValuesList.add(cv);
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+ Set<Entry<String, Object>> newValuesSet = newValues.valueSet();
+ for (Entry<String, Object> entry : newValuesSet) {
+ String key = entry.getKey();
+ Object value = entry.getValue();
+ for (ContentValues targetValues : updateValuesList) {
+ if (value instanceof Integer) {
+ targetValues.put(key, (Integer) value);
+ } else if (value instanceof Long) {
+ targetValues.put(key, (Long) value);
+ } else if (value instanceof String) {
+ targetValues.put(key, (String) value);
+ } else if (value instanceof Boolean) {
+ targetValues.put(key, (Boolean) value);
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+ }
+ for (ContentValues targetValues : updateValuesList) {
+ switch(match) {
+ case TABLE:
+ mMockStore.put(path + "/" + targetValues.getAsLong(ID_COLUMN), targetValues);
+ break;
+ case RECORD:
+ mMockStore.put(path, targetValues);
+ break;
+ }
+ }
+ return updateValuesList.size();
+ }
+}
diff --git a/tests/src/com/android/mail/browse/TestProviderTests.java b/tests/src/com/android/mail/browse/TestProviderTests.java
new file mode 100644
index 0000000..8e3ff63
--- /dev/null
+++ b/tests/src/com/android/mail/browse/TestProviderTests.java
@@ -0,0 +1,189 @@
+/*******************************************************************************
+ * Copyright (C) 2012 Google Inc.
+ * Licensed to 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.mail.browse;
+
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.OperationApplicationException;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.RemoteException;
+import android.test.ProviderTestCase2;
+import android.test.mock.MockContentResolver;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.ArrayList;
+
+@SmallTest
+public class TestProviderTests extends ProviderTestCase2<TestProvider> {
+ Context mMockContext;
+ MockContentResolver mMockResolver;
+
+ private static final String CANHAZ_AUTHORITY = "com.android.canhaz";
+ private static final String PONY_TABLE = "pony";
+ private static final String PONY_COLUMN_NAME = "name";
+ private static final String PONY_COLUMN_TYPE = "type";
+ private static final String PONY_COLUMN_LEGS= "legs";
+ private static final String PONY_COLUMN_CAN_RIDE = "canRide";
+ private static final String[] PONY_PROJECTION = {TestProvider.ID_COLUMN, PONY_COLUMN_NAME,
+ PONY_COLUMN_TYPE, PONY_COLUMN_LEGS, PONY_COLUMN_CAN_RIDE};
+ private static final int PONY_ID = 0;
+ private static final int PONY_NAME = 1;
+ private static final int PONY_TYPE = 2;
+ private static final int PONY_LEGS = 3;
+ private static final int PONY_CAN_RIDE = 4;
+
+ public TestProviderTests() {
+ super(TestProvider.class, TestProvider.AUTHORITY);
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mMockContext = getMockContext();
+ mMockResolver = (MockContentResolver)mMockContext.getContentResolver();
+ mMockResolver.addProvider(CANHAZ_AUTHORITY, new TestProvider(mMockContext));
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ private ContentValues ponyValues(String name, String type, int legs, boolean canRide) {
+ ContentValues cv = new ContentValues();
+ cv.put(PONY_COLUMN_NAME, name);
+ cv.put(PONY_COLUMN_TYPE, type);
+ cv.put(PONY_COLUMN_LEGS, legs);
+ cv.put(PONY_COLUMN_CAN_RIDE, canRide ? 1 : 0);
+ return cv;
+ }
+
+ private ContentProviderResult[] setupPonies() throws RemoteException,
+ OperationApplicationException {
+ // The Uri is content://com.android.canhaz/pony
+ Uri uri = new Uri.Builder().scheme("content").authority(CANHAZ_AUTHORITY)
+ .path(PONY_TABLE).build();
+ // Our array of CPO's to be used with applyBatch
+ ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
+
+ // Insert two ponies
+ ContentValues pony1 = ponyValues("Flicka", "wayward", 4, true);
+ ops.add(ContentProviderOperation.newInsert(uri).withValues(pony1).build());
+ ContentValues pony2 = ponyValues("Elise", "dastardly", 3, false);
+ ops.add(ContentProviderOperation.newInsert(uri).withValues(pony2).build());
+ // Apply the batch with one insert operation
+ return mMockResolver.applyBatch(TestProvider.AUTHORITY, ops);
+ }
+
+ private Uri getPonyUri() {
+ return new Uri.Builder().scheme("content").authority(CANHAZ_AUTHORITY)
+ .path(PONY_TABLE).build();
+ }
+
+ public void testInsertQueryandDelete() throws RemoteException, OperationApplicationException {
+ // The Uri is content://com.android.canhaz/pony
+ ContentProviderResult[] results = setupPonies();
+ Uri uri = getPonyUri();
+
+ // Check the results
+ assertNotNull(results);
+ assertEquals(2, results.length);
+ // Make sure that we've created matcher entries for pony and pony/#
+ assertEquals(TestProvider.TABLE, TestProvider.sURIMatcher.match(TestProvider.uri(uri)));
+ assertEquals(TestProvider.RECORD,
+ TestProvider.sURIMatcher.match(TestProvider.uri(results[0].uri)));
+ Cursor c = mMockResolver.query(TestProvider.uri(uri), PONY_PROJECTION, null, null, null);
+ assertNotNull(c);
+ assertEquals(2, c.getCount());
+ long eliseId = -1;
+ long flickaId = -1;
+ while (c.moveToNext()) {
+ String name = c.getString(PONY_NAME);
+ if ("Flicka".equals(name)) {
+ assertEquals("Flicka", c.getString(PONY_NAME));
+ assertEquals("wayward", c.getString(PONY_TYPE));
+ assertEquals(4, c.getInt(PONY_LEGS));
+ assertEquals(1, c.getInt(PONY_CAN_RIDE));
+ flickaId = c.getLong(PONY_ID);
+ } else if ("Elise".equals(name)) {
+ assertEquals("dastardly", c.getString(PONY_TYPE));
+ assertEquals(3, c.getInt(PONY_LEGS));
+ assertEquals(0, c.getInt(PONY_CAN_RIDE));
+ eliseId = c.getLong(PONY_ID);
+ } else {
+ fail("Wrong record: " + name);
+ }
+ }
+
+ // eliseId and flickaId should have been set
+ assertNotSame(-1, eliseId);
+ assertNotSame(-1, flickaId);
+ // Delete the elise record
+ assertEquals(1, mMockResolver.delete(ContentUris.withAppendedId(TestProvider.uri(uri),
+ eliseId), null, null));
+ c = mMockResolver.query(TestProvider.uri(uri), PONY_PROJECTION, null, null, null);
+ assertNotNull(c);
+ // There should be one left (Flicka)
+ assertEquals(1, c.getCount());
+ assertTrue(c.moveToNext());
+ assertEquals("Flicka", c.getString(PONY_NAME));
+ }
+
+ public void testUpdate() throws RemoteException, OperationApplicationException {
+ // The Uri is content://com.android.canhaz/pony
+ Uri uri = getPonyUri();
+ setupPonies();
+ Cursor c = mMockResolver.query(TestProvider.uri(uri), PONY_PROJECTION, null, null, null);
+ assertNotNull(c);
+ assertEquals(2, c.getCount());
+ // Give all the ponies 5 legs
+ ContentValues cv = new ContentValues();
+ cv.put(PONY_COLUMN_LEGS, 5);
+ assertEquals(2, mMockResolver.update(TestProvider.uri(uri), cv, null, null));
+ c = mMockResolver.query(TestProvider.uri(uri), PONY_PROJECTION, null, null, null);
+ assertNotNull(c);
+ // We should still have two records, and each should have 5 legs, but otherwise be the same
+ assertEquals(2, c.getCount());
+ long eliseId = -1;
+ long flickaId = -1;
+ while (c.moveToNext()) {
+ String name = c.getString(PONY_NAME);
+ if ("Flicka".equals(name)) {
+ assertEquals("Flicka", c.getString(PONY_NAME));
+ assertEquals("wayward", c.getString(PONY_TYPE));
+ assertEquals(5, c.getInt(PONY_LEGS));
+ assertEquals(1, c.getInt(PONY_CAN_RIDE));
+ flickaId = c.getLong(PONY_ID);
+ } else if ("Elise".equals(name)) {
+ assertEquals("dastardly", c.getString(PONY_TYPE));
+ assertEquals(5, c.getInt(PONY_LEGS));
+ assertEquals(0, c.getInt(PONY_CAN_RIDE));
+ eliseId = c.getLong(PONY_ID);
+ } else {
+ fail("Wrong record: " + name);
+ }
+ }
+ // eliseId and flickaId should have been set
+ assertNotSame(-1, eliseId);
+ assertNotSame(-1, flickaId);
+ }
+}