Home | History | Annotate | Download | only in calendar
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.calendar;
     18 
     19 import com.android.calendar.AsyncQueryService.Operation;
     20 import com.android.calendar.AsyncQueryServiceHelper.OperationInfo;
     21 
     22 import android.content.ComponentName;
     23 import android.content.ContentProvider;
     24 import android.content.ContentProviderOperation;
     25 import android.content.ContentProviderResult;
     26 import android.content.ContentResolver;
     27 import android.content.ContentValues;
     28 import android.content.Context;
     29 import android.content.Intent;
     30 import android.database.Cursor;
     31 import android.net.Uri;
     32 import android.os.Handler;
     33 import android.os.HandlerThread;
     34 import android.os.Message;
     35 import android.test.ServiceTestCase;
     36 import android.test.mock.MockContentResolver;
     37 import android.test.mock.MockContext;
     38 import android.test.mock.MockCursor;
     39 import android.test.suitebuilder.annotation.LargeTest;
     40 import android.test.suitebuilder.annotation.SmallTest;
     41 import android.test.suitebuilder.annotation.Smoke;
     42 import android.util.Log;
     43 
     44 import java.util.ArrayList;
     45 import java.util.Arrays;
     46 import java.util.concurrent.Semaphore;
     47 import java.util.concurrent.TimeUnit;
     48 
     49 /**
     50  * Unit tests for {@link android.text.format.DateUtils#formatDateRange}.
     51  */
     52 public class AsyncQueryServiceTest extends ServiceTestCase<AsyncQueryServiceHelper> {
     53     private static final String TAG = "AsyncQueryServiceTest";
     54 
     55     private static final String AUTHORITY_URI = "content://AsyncQueryAuthority/";
     56 
     57     private static final String AUTHORITY = "AsyncQueryAuthority";
     58 
     59     private static final int MIN_DELAY = 50;
     60 
     61     private static final int BASE_TEST_WAIT_TIME = MIN_DELAY * 5;
     62 
     63     private static int mId = 0;
     64 
     65     private static final String[] TEST_PROJECTION = new String[] {
     66             "col1", "col2", "col3"
     67     };
     68 
     69     private static final String TEST_SELECTION = "selection";
     70 
     71     private static final String[] TEST_SELECTION_ARGS = new String[] {
     72             "arg1", "arg2", "arg3"
     73     };
     74 
     75     public AsyncQueryServiceTest() {
     76         super(AsyncQueryServiceHelper.class);
     77     }
     78 
     79     @Override
     80     protected void setUp() throws Exception {
     81         super.setUp();
     82     }
     83 
     84     @Smoke
     85     @SmallTest
     86     public void testQuery() throws Exception {
     87         int index = 0;
     88         final OperationInfo[] work = new OperationInfo[1];
     89         work[index] = new OperationInfo();
     90         work[index].op = Operation.EVENT_ARG_QUERY;
     91 
     92         work[index].token = ++mId;
     93         work[index].cookie = ++mId;
     94         work[index].uri = Uri.parse(AUTHORITY_URI + "blah");
     95         work[index].projection = TEST_PROJECTION;
     96         work[index].selection = TEST_SELECTION;
     97         work[index].selectionArgs = TEST_SELECTION_ARGS;
     98         work[index].orderBy = "order";
     99 
    100         work[index].delayMillis = 0;
    101         work[index].result = new TestCursor();
    102 
    103         TestAsyncQueryService aqs = new TestAsyncQueryService(buildTestContext(work), work);
    104         aqs.startQuery(work[index].token, work[index].cookie, work[index].uri,
    105                 work[index].projection, work[index].selection, work[index].selectionArgs,
    106                 work[index].orderBy);
    107 
    108         Log.d(TAG, "testQuery Waiting >>>>>>>>>>>");
    109         assertEquals("Not all operations were executed.", work.length, aqs
    110                 .waitForCompletion(BASE_TEST_WAIT_TIME));
    111         Log.d(TAG, "testQuery Done <<<<<<<<<<<<<<");
    112     }
    113 
    114     @SmallTest
    115     public void testInsert() throws Exception {
    116         int index = 0;
    117         final OperationInfo[] work = new OperationInfo[1];
    118         work[index] = new OperationInfo();
    119         work[index].op = Operation.EVENT_ARG_INSERT;
    120 
    121         work[index].token = ++mId;
    122         work[index].cookie = ++mId;
    123         work[index].uri = Uri.parse(AUTHORITY_URI + "blah");
    124         work[index].values = new ContentValues();
    125         work[index].values.put("key", ++mId);
    126 
    127         work[index].delayMillis = 0;
    128         work[index].result = Uri.parse(AUTHORITY_URI + "Result=" + ++mId);
    129 
    130         TestAsyncQueryService aqs = new TestAsyncQueryService(buildTestContext(work), work);
    131         aqs.startInsert(work[index].token, work[index].cookie, work[index].uri, work[index].values,
    132                 work[index].delayMillis);
    133 
    134         Log.d(TAG, "testInsert Waiting >>>>>>>>>>>");
    135         assertEquals("Not all operations were executed.", work.length, aqs
    136                 .waitForCompletion(BASE_TEST_WAIT_TIME));
    137         Log.d(TAG, "testInsert Done <<<<<<<<<<<<<<");
    138     }
    139 
    140     @SmallTest
    141     public void testUpdate() throws Exception {
    142         int index = 0;
    143         final OperationInfo[] work = new OperationInfo[1];
    144         work[index] = new OperationInfo();
    145         work[index].op = Operation.EVENT_ARG_UPDATE;
    146 
    147         work[index].token = ++mId;
    148         work[index].cookie = ++mId;
    149         work[index].uri = Uri.parse(AUTHORITY_URI + ++mId);
    150         work[index].values = new ContentValues();
    151         work[index].values.put("key", ++mId);
    152         work[index].selection = TEST_SELECTION;
    153         work[index].selectionArgs = TEST_SELECTION_ARGS;
    154 
    155         work[index].delayMillis = 0;
    156         work[index].result = ++mId;
    157 
    158         TestAsyncQueryService aqs = new TestAsyncQueryService(buildTestContext(work), work);
    159         aqs.startUpdate(work[index].token, work[index].cookie, work[index].uri, work[index].values,
    160                 work[index].selection, work[index].selectionArgs, work[index].delayMillis);
    161 
    162         Log.d(TAG, "testUpdate Waiting >>>>>>>>>>>");
    163         assertEquals("Not all operations were executed.", work.length, aqs
    164                 .waitForCompletion(BASE_TEST_WAIT_TIME));
    165         Log.d(TAG, "testUpdate Done <<<<<<<<<<<<<<");
    166     }
    167 
    168     @SmallTest
    169     public void testDelete() throws Exception {
    170         int index = 0;
    171         final OperationInfo[] work = new OperationInfo[1];
    172         work[index] = new OperationInfo();
    173         work[index].op = Operation.EVENT_ARG_DELETE;
    174 
    175         work[index].token = ++mId;
    176         work[index].cookie = ++mId;
    177         work[index].uri = Uri.parse(AUTHORITY_URI + "blah");
    178         work[index].selection = TEST_SELECTION;
    179         work[index].selectionArgs = TEST_SELECTION_ARGS;
    180 
    181         work[index].delayMillis = 0;
    182         work[index].result = ++mId;
    183 
    184         TestAsyncQueryService aqs = new TestAsyncQueryService(buildTestContext(work), work);
    185         aqs.startDelete(work[index].token,
    186                 work[index].cookie,
    187                 work[index].uri,
    188                 work[index].selection,
    189                 work[index].selectionArgs,
    190                 work[index].delayMillis);
    191 
    192         Log.d(TAG, "testDelete Waiting >>>>>>>>>>>");
    193         assertEquals("Not all operations were executed.", work.length, aqs
    194                 .waitForCompletion(BASE_TEST_WAIT_TIME));
    195         Log.d(TAG, "testDelete Done <<<<<<<<<<<<<<");
    196     }
    197 
    198     @SmallTest
    199     public void testBatch() throws Exception {
    200         int index = 0;
    201         final OperationInfo[] work = new OperationInfo[1];
    202         work[index] = new OperationInfo();
    203         work[index].op = Operation.EVENT_ARG_BATCH;
    204 
    205         work[index].token = ++mId;
    206         work[index].cookie = ++mId;
    207         work[index].authority = AUTHORITY;
    208         work[index].cpo = new ArrayList<ContentProviderOperation>();
    209         work[index].cpo.add(ContentProviderOperation.newInsert(Uri.parse(AUTHORITY_URI + ++mId))
    210                 .build());
    211 
    212         work[index].delayMillis = 0;
    213         ContentProviderResult[] resultArray = new ContentProviderResult[1];
    214         resultArray[0] = new ContentProviderResult(++mId);
    215         work[index].result = resultArray;
    216 
    217         TestAsyncQueryService aqs = new TestAsyncQueryService(buildTestContext(work), work);
    218         aqs.startBatch(work[index].token,
    219                 work[index].cookie,
    220                 work[index].authority,
    221                 work[index].cpo,
    222                 work[index].delayMillis);
    223 
    224         Log.d(TAG, "testBatch Waiting >>>>>>>>>>>");
    225         assertEquals("Not all operations were executed.", work.length, aqs
    226                 .waitForCompletion(BASE_TEST_WAIT_TIME));
    227         Log.d(TAG, "testBatch Done <<<<<<<<<<<<<<");
    228     }
    229 
    230     @LargeTest
    231     public void testDelay() throws Exception {
    232         // Tests the ordering of the workqueue
    233         int index = 0;
    234         OperationInfo[] work = new OperationInfo[5];
    235         work[index++] = generateWork(MIN_DELAY * 2);
    236         work[index++] = generateWork(0);
    237         work[index++] = generateWork(MIN_DELAY * 1);
    238         work[index++] = generateWork(0);
    239         work[index++] = generateWork(MIN_DELAY * 3);
    240 
    241         OperationInfo[] sorted = generateSortedWork(work, work.length);
    242 
    243         TestAsyncQueryService aqs = new TestAsyncQueryService(buildTestContext(sorted), sorted);
    244         startWork(aqs, work);
    245 
    246         Log.d(TAG, "testDelay Waiting >>>>>>>>>>>");
    247         assertEquals("Not all operations were executed.", work.length, aqs
    248                 .waitForCompletion(BASE_TEST_WAIT_TIME));
    249         Log.d(TAG, "testDelay Done <<<<<<<<<<<<<<");
    250     }
    251 
    252     @LargeTest
    253     public void testCancel_simpleCancelLastTest() throws Exception {
    254         int index = 0;
    255         OperationInfo[] work = new OperationInfo[5];
    256         work[index++] = generateWork(MIN_DELAY * 2);
    257         work[index++] = generateWork(0);
    258         work[index++] = generateWork(MIN_DELAY);
    259         work[index++] = generateWork(0);
    260         work[index] = generateWork(MIN_DELAY * 3);
    261 
    262         // Not part of the expected as it will be canceled
    263         OperationInfo toBeCancelled1 = work[index];
    264         OperationInfo[] expected = generateSortedWork(work, work.length - 1);
    265 
    266         TestAsyncQueryService aqs = new TestAsyncQueryService(buildTestContext(expected), expected);
    267         startWork(aqs, work);
    268         Operation lastOne = aqs.getLastCancelableOperation();
    269         // Log.d(TAG, "lastOne = " + lastOne.toString());
    270         // Log.d(TAG, "toBeCancelled1 = " + toBeCancelled1.toString());
    271         assertTrue("1) delay=3 is not last", toBeCancelled1.equivalent(lastOne));
    272         assertEquals("Can't cancel delay 3", 1, aqs.cancelOperation(lastOne.token));
    273 
    274         Log.d(TAG, "testCancel_simpleCancelLastTest Waiting >>>>>>>>>>>");
    275         assertEquals("Not all operations were executed.", expected.length, aqs
    276                 .waitForCompletion(BASE_TEST_WAIT_TIME));
    277         Log.d(TAG, "testCancel_simpleCancelLastTest Done <<<<<<<<<<<<<<");
    278     }
    279 
    280     @LargeTest
    281     public void testCancel_cancelSecondToLast() throws Exception {
    282         int index = 0;
    283         OperationInfo[] work = new OperationInfo[5];
    284         work[index++] = generateWork(MIN_DELAY * 2);
    285         work[index++] = generateWork(0);
    286         work[index++] = generateWork(MIN_DELAY);
    287         work[index++] = generateWork(0);
    288         work[index] = generateWork(MIN_DELAY * 3);
    289 
    290         // Not part of the expected as it will be canceled
    291         OperationInfo toBeCancelled1 = work[index];
    292         OperationInfo[] expected = new OperationInfo[4];
    293         expected[0] = work[1]; // delay = 0
    294         expected[1] = work[3]; // delay = 0
    295         expected[2] = work[2]; // delay = MIN_DELAY
    296         expected[3] = work[4]; // delay = MIN_DELAY * 3
    297 
    298         TestAsyncQueryService aqs = new TestAsyncQueryService(buildTestContext(expected), expected);
    299         startWork(aqs, work);
    300 
    301         Operation lastOne = aqs.getLastCancelableOperation(); // delay = 3
    302         assertTrue("2) delay=3 is not last", toBeCancelled1.equivalent(lastOne));
    303         assertEquals("Can't cancel delay 2", 1, aqs.cancelOperation(work[0].token));
    304         assertEquals("Delay 2 should be gone", 0, aqs.cancelOperation(work[0].token));
    305 
    306         Log.d(TAG, "testCancel_cancelSecondToLast Waiting >>>>>>>>>>>");
    307         assertEquals("Not all operations were executed.", expected.length, aqs
    308                 .waitForCompletion(BASE_TEST_WAIT_TIME));
    309         Log.d(TAG, "testCancel_cancelSecondToLast Done <<<<<<<<<<<<<<");
    310     }
    311 
    312     @LargeTest
    313     public void testCancel_multipleCancels() throws Exception {
    314         int index = 0;
    315         OperationInfo[] work = new OperationInfo[5];
    316         work[index++] = generateWork(MIN_DELAY * 2);
    317         work[index++] = generateWork(0);
    318         work[index++] = generateWork(MIN_DELAY);
    319         work[index++] = generateWork(0);
    320         work[index] = generateWork(MIN_DELAY * 3);
    321 
    322         // Not part of the expected as it will be canceled
    323         OperationInfo[] expected = new OperationInfo[3];
    324         expected[0] = work[1]; // delay = 0
    325         expected[1] = work[3]; // delay = 0
    326         expected[2] = work[2]; // delay = MIN_DELAY
    327 
    328         TestAsyncQueryService aqs = new TestAsyncQueryService(buildTestContext(expected), expected);
    329         startWork(aqs, work);
    330 
    331         Operation lastOne = aqs.getLastCancelableOperation(); // delay = 3
    332         assertTrue("3) delay=3 is not last", work[4].equivalent(lastOne));
    333         assertEquals("Can't cancel delay 2", 1, aqs.cancelOperation(work[0].token));
    334         assertEquals("Delay 2 should be gone", 0, aqs.cancelOperation(work[0].token));
    335         assertEquals("Can't cancel delay 3", 1, aqs.cancelOperation(work[4].token));
    336         assertEquals("Delay 3 should be gone", 0, aqs.cancelOperation(work[4].token));
    337 
    338         Log.d(TAG, "testCancel_multipleCancels Waiting >>>>>>>>>>>");
    339         assertEquals("Not all operations were executed.", expected.length, aqs
    340                 .waitForCompletion(BASE_TEST_WAIT_TIME));
    341         Log.d(TAG, "testCancel_multipleCancels Done <<<<<<<<<<<<<<");
    342     }
    343 
    344     private OperationInfo generateWork(long delayMillis) {
    345         OperationInfo work = new OperationInfo();
    346         work.op = Operation.EVENT_ARG_DELETE;
    347 
    348         work.token = ++mId;
    349         work.cookie = 100 + work.token;
    350         work.uri = Uri.parse(AUTHORITY_URI + "blah");
    351         work.selection = TEST_SELECTION;
    352         work.selectionArgs = TEST_SELECTION_ARGS;
    353 
    354         work.delayMillis = delayMillis;
    355         work.result = 1000 + work.token;
    356         return work;
    357     }
    358 
    359     private void startWork(TestAsyncQueryService aqs, OperationInfo[] work) {
    360         for (OperationInfo w : work) {
    361             if (w != null) {
    362                 aqs.startDelete(w.token, w.cookie, w.uri, w.selection, w.selectionArgs,
    363                         w.delayMillis);
    364             }
    365         }
    366     }
    367 
    368     OperationInfo[] generateSortedWork(OperationInfo[] work, int length) {
    369         OperationInfo[] sorted = new OperationInfo[length];
    370         System.arraycopy(work, 0, sorted, 0, length);
    371 
    372         // Set the scheduled time so they get sorted properly
    373         for (OperationInfo w : sorted) {
    374             if (w != null) {
    375                 w.calculateScheduledTime();
    376             }
    377         }
    378 
    379         // Stable sort by scheduled time
    380         Arrays.sort(sorted);
    381 
    382         Log.d(TAG, "Unsorted work: " + work.length);
    383         for (OperationInfo w : work) {
    384             if (w != null) {
    385                 Log.d(TAG, "Token#" + w.token + " delay=" + w.delayMillis);
    386             }
    387         }
    388         Log.d(TAG, "Sorted work: " + sorted.length);
    389         for (OperationInfo w : sorted) {
    390             if (w != null) {
    391                 Log.d(TAG, "Token#" + w.token + " delay=" + w.delayMillis);
    392             }
    393         }
    394 
    395         return sorted;
    396     }
    397 
    398     private Context buildTestContext(final OperationInfo[] work) {
    399         MockContext context = new MockContext() {
    400             MockContentResolver mResolver;
    401 
    402             @Override
    403             public ContentResolver getContentResolver() {
    404                 if (mResolver == null) {
    405                     ContentProvider provider = new TestProvider(work);
    406                     mResolver = new MockContentResolver();
    407                     mResolver.addProvider(AUTHORITY, provider);
    408                 }
    409                 return mResolver;
    410             }
    411 
    412             @Override
    413             public String getPackageName() {
    414                 return AsyncQueryServiceTest.class.getPackage().getName();
    415             }
    416 
    417             public ComponentName startService(Intent service) {
    418                 AsyncQueryServiceTest.this.startService(service);
    419                 return service.getComponent();
    420             }
    421         };
    422 
    423         return context;
    424     }
    425 
    426     private final class TestCursor extends MockCursor {
    427         int mUnique = ++mId;
    428 
    429         @Override
    430         public int getCount() {
    431             return mUnique;
    432         }
    433     }
    434 
    435     /**
    436      * TestAsyncQueryService takes the expected results in the constructor. They
    437      * are used to verify the data passed to the callbacks.
    438      */
    439     class TestAsyncQueryService extends AsyncQueryService {
    440         int mIndex = 0;
    441 
    442         private OperationInfo[] mWork;
    443 
    444         private Semaphore mCountingSemaphore;
    445 
    446         public TestAsyncQueryService(Context context, OperationInfo[] work) {
    447             super(context);
    448             mCountingSemaphore = new Semaphore(0);
    449 
    450             // run in a separate thread but call the same code
    451             HandlerThread thread = new HandlerThread("TestAsyncQueryService");
    452             thread.start();
    453             super.setTestHandler(new Handler(thread.getLooper()) {
    454                 @Override
    455                 public void handleMessage(Message msg) {
    456                     TestAsyncQueryService.this.handleMessage(msg);
    457                 }
    458             });
    459 
    460             mWork = work;
    461         }
    462 
    463         @Override
    464         protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
    465             Log.d(TAG, "onQueryComplete tid=" + Thread.currentThread().getId());
    466             Log.d(TAG, "mWork.length=" + mWork.length + " mIndex=" + mIndex);
    467 
    468             assertEquals(mWork[mIndex].op, Operation.EVENT_ARG_QUERY);
    469             assertEquals(mWork[mIndex].token, token);
    470             /*
    471              * Even though our TestProvider returned mWork[mIndex].result, it is
    472              * wrapped with new'ed CursorWrapperInner and there's no equal() in
    473              * CursorWrapperInner. assertEquals the two cursor will always fail.
    474              * So just compare the count which will be unique in our TestCursor;
    475              */
    476             assertEquals(((Cursor) mWork[mIndex].result).getCount(), cursor.getCount());
    477 
    478             mIndex++;
    479             mCountingSemaphore.release();
    480         }
    481 
    482         @Override
    483         protected void onInsertComplete(int token, Object cookie, Uri uri) {
    484             Log.d(TAG, "onInsertComplete tid=" + Thread.currentThread().getId());
    485             Log.d(TAG, "mWork.length=" + mWork.length + " mIndex=" + mIndex);
    486 
    487             assertEquals(mWork[mIndex].op, Operation.EVENT_ARG_INSERT);
    488             assertEquals(mWork[mIndex].token, token);
    489             assertEquals(mWork[mIndex].result, uri);
    490 
    491             mIndex++;
    492             mCountingSemaphore.release();
    493         }
    494 
    495         @Override
    496         protected void onUpdateComplete(int token, Object cookie, int result) {
    497             Log.d(TAG, "onUpdateComplete tid=" + Thread.currentThread().getId());
    498             Log.d(TAG, "mWork.length=" + mWork.length + " mIndex=" + mIndex);
    499 
    500             assertEquals(mWork[mIndex].op, Operation.EVENT_ARG_UPDATE);
    501             assertEquals(mWork[mIndex].token, token);
    502             assertEquals(mWork[mIndex].result, result);
    503 
    504             mIndex++;
    505             mCountingSemaphore.release();
    506         }
    507 
    508         @Override
    509         protected void onDeleteComplete(int token, Object cookie, int result) {
    510             Log.d(TAG, "onDeleteComplete tid=" + Thread.currentThread().getId());
    511             Log.d(TAG, "mWork.length=" + mWork.length + " mIndex=" + mIndex);
    512 
    513             assertEquals(mWork[mIndex].op, Operation.EVENT_ARG_DELETE);
    514             assertEquals(mWork[mIndex].token, token);
    515             assertEquals(mWork[mIndex].result, result);
    516 
    517             mIndex++;
    518             mCountingSemaphore.release();
    519         }
    520 
    521         @Override
    522         protected void onBatchComplete(int token, Object cookie, ContentProviderResult[] results) {
    523             Log.d(TAG, "onBatchComplete tid=" + Thread.currentThread().getId());
    524             Log.d(TAG, "mWork.length=" + mWork.length + " mIndex=" + mIndex);
    525 
    526             assertEquals(mWork[mIndex].op, Operation.EVENT_ARG_BATCH);
    527             assertEquals(mWork[mIndex].token, token);
    528 
    529             ContentProviderResult[] expected = (ContentProviderResult[]) mWork[mIndex].result;
    530             assertEquals(expected.length, results.length);
    531             for (int i = 0; i < expected.length; ++i) {
    532                 assertEquals(expected[i].count, results[i].count);
    533                 assertEquals(expected[i].uri, results[i].uri);
    534             }
    535 
    536             mIndex++;
    537             mCountingSemaphore.release();
    538         }
    539 
    540         public int waitForCompletion(long timeoutMills) {
    541             Log.d(TAG, "waitForCompletion tid=" + Thread.currentThread().getId());
    542             int count = 0;
    543             try {
    544                 while (count < mWork.length) {
    545                     if (!mCountingSemaphore.tryAcquire(timeoutMills, TimeUnit.MILLISECONDS)) {
    546                         break;
    547                     }
    548                     count++;
    549                 }
    550             } catch (InterruptedException e) {
    551             }
    552             return count;
    553         }
    554     }
    555 
    556     /**
    557      * This gets called by AsyncQueryServiceHelper to read or write the data. It
    558      * also verifies the data against the data passed in the constructor
    559      */
    560     class TestProvider extends ContentProvider {
    561         OperationInfo[] mWork;
    562 
    563         int index = 0;
    564 
    565         public TestProvider(OperationInfo[] work) {
    566             mWork = work;
    567         }
    568 
    569         @Override
    570         public final Cursor query(Uri uri, String[] projection, String selection,
    571                 String[] selectionArgs, String orderBy) {
    572             Log.d(TAG, "Provider query index=" + index);
    573             assertEquals(mWork[index].op, Operation.EVENT_ARG_QUERY);
    574             assertEquals(mWork[index].uri, uri);
    575             assertEquals(mWork[index].projection, projection);
    576             assertEquals(mWork[index].selection, selection);
    577             assertEquals(mWork[index].selectionArgs, selectionArgs);
    578             assertEquals(mWork[index].orderBy, orderBy);
    579             return (Cursor) mWork[index++].result;
    580         }
    581 
    582         @Override
    583         public Uri insert(Uri uri, ContentValues values) {
    584             Log.d(TAG, "Provider insert index=" + index);
    585             assertEquals(mWork[index].op, Operation.EVENT_ARG_INSERT);
    586             assertEquals(mWork[index].uri, uri);
    587             assertEquals(mWork[index].values, values);
    588             return (Uri) mWork[index++].result;
    589         }
    590 
    591         @Override
    592         public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    593             Log.d(TAG, "Provider update index=" + index);
    594             assertEquals(mWork[index].op, Operation.EVENT_ARG_UPDATE);
    595             assertEquals(mWork[index].uri, uri);
    596             assertEquals(mWork[index].values, values);
    597             assertEquals(mWork[index].selection, selection);
    598             assertEquals(mWork[index].selectionArgs, selectionArgs);
    599             return (Integer) mWork[index++].result;
    600         }
    601 
    602         @Override
    603         public int delete(Uri uri, String selection, String[] selectionArgs) {
    604             Log.d(TAG, "Provider delete index=" + index);
    605             assertEquals(mWork[index].op, Operation.EVENT_ARG_DELETE);
    606             assertEquals(mWork[index].uri, uri);
    607             assertEquals(mWork[index].selection, selection);
    608             assertEquals(mWork[index].selectionArgs, selectionArgs);
    609             return (Integer) mWork[index++].result;
    610         }
    611 
    612         @Override
    613         public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) {
    614             Log.d(TAG, "Provider applyBatch index=" + index);
    615             assertEquals(mWork[index].op, Operation.EVENT_ARG_BATCH);
    616             assertEquals(mWork[index].cpo, operations);
    617             return (ContentProviderResult[]) mWork[index++].result;
    618         }
    619 
    620         @Override
    621         public String getType(Uri uri) {
    622             return null;
    623         }
    624 
    625         @Override
    626         public boolean onCreate() {
    627             return false;
    628         }
    629     }
    630 }
    631