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             @Override
    418             public ComponentName startService(Intent service) {
    419                 AsyncQueryServiceTest.this.startService(service);
    420                 return service.getComponent();
    421             }
    422         };
    423 
    424         return context;
    425     }
    426 
    427     private final class TestCursor extends MockCursor {
    428         int mUnique = ++mId;
    429 
    430         @Override
    431         public int getCount() {
    432             return mUnique;
    433         }
    434     }
    435 
    436     /**
    437      * TestAsyncQueryService takes the expected results in the constructor. They
    438      * are used to verify the data passed to the callbacks.
    439      */
    440     class TestAsyncQueryService extends AsyncQueryService {
    441         int mIndex = 0;
    442 
    443         private OperationInfo[] mWork;
    444 
    445         private Semaphore mCountingSemaphore;
    446 
    447         public TestAsyncQueryService(Context context, OperationInfo[] work) {
    448             super(context);
    449             mCountingSemaphore = new Semaphore(0);
    450 
    451             // run in a separate thread but call the same code
    452             HandlerThread thread = new HandlerThread("TestAsyncQueryService");
    453             thread.start();
    454             super.setTestHandler(new Handler(thread.getLooper()) {
    455                 @Override
    456                 public void handleMessage(Message msg) {
    457                     TestAsyncQueryService.this.handleMessage(msg);
    458                 }
    459             });
    460 
    461             mWork = work;
    462         }
    463 
    464         @Override
    465         protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
    466             Log.d(TAG, "onQueryComplete tid=" + Thread.currentThread().getId());
    467             Log.d(TAG, "mWork.length=" + mWork.length + " mIndex=" + mIndex);
    468 
    469             assertEquals(mWork[mIndex].op, Operation.EVENT_ARG_QUERY);
    470             assertEquals(mWork[mIndex].token, token);
    471             /*
    472              * Even though our TestProvider returned mWork[mIndex].result, it is
    473              * wrapped with new'ed CursorWrapperInner and there's no equal() in
    474              * CursorWrapperInner. assertEquals the two cursor will always fail.
    475              * So just compare the count which will be unique in our TestCursor;
    476              */
    477             assertEquals(((Cursor) mWork[mIndex].result).getCount(), cursor.getCount());
    478 
    479             mIndex++;
    480             mCountingSemaphore.release();
    481         }
    482 
    483         @Override
    484         protected void onInsertComplete(int token, Object cookie, Uri uri) {
    485             Log.d(TAG, "onInsertComplete tid=" + Thread.currentThread().getId());
    486             Log.d(TAG, "mWork.length=" + mWork.length + " mIndex=" + mIndex);
    487 
    488             assertEquals(mWork[mIndex].op, Operation.EVENT_ARG_INSERT);
    489             assertEquals(mWork[mIndex].token, token);
    490             assertEquals(mWork[mIndex].result, uri);
    491 
    492             mIndex++;
    493             mCountingSemaphore.release();
    494         }
    495 
    496         @Override
    497         protected void onUpdateComplete(int token, Object cookie, int result) {
    498             Log.d(TAG, "onUpdateComplete tid=" + Thread.currentThread().getId());
    499             Log.d(TAG, "mWork.length=" + mWork.length + " mIndex=" + mIndex);
    500 
    501             assertEquals(mWork[mIndex].op, Operation.EVENT_ARG_UPDATE);
    502             assertEquals(mWork[mIndex].token, token);
    503             assertEquals(mWork[mIndex].result, result);
    504 
    505             mIndex++;
    506             mCountingSemaphore.release();
    507         }
    508 
    509         @Override
    510         protected void onDeleteComplete(int token, Object cookie, int result) {
    511             Log.d(TAG, "onDeleteComplete tid=" + Thread.currentThread().getId());
    512             Log.d(TAG, "mWork.length=" + mWork.length + " mIndex=" + mIndex);
    513 
    514             assertEquals(mWork[mIndex].op, Operation.EVENT_ARG_DELETE);
    515             assertEquals(mWork[mIndex].token, token);
    516             assertEquals(mWork[mIndex].result, result);
    517 
    518             mIndex++;
    519             mCountingSemaphore.release();
    520         }
    521 
    522         @Override
    523         protected void onBatchComplete(int token, Object cookie, ContentProviderResult[] results) {
    524             Log.d(TAG, "onBatchComplete tid=" + Thread.currentThread().getId());
    525             Log.d(TAG, "mWork.length=" + mWork.length + " mIndex=" + mIndex);
    526 
    527             assertEquals(mWork[mIndex].op, Operation.EVENT_ARG_BATCH);
    528             assertEquals(mWork[mIndex].token, token);
    529 
    530             ContentProviderResult[] expected = (ContentProviderResult[]) mWork[mIndex].result;
    531             assertEquals(expected.length, results.length);
    532             for (int i = 0; i < expected.length; ++i) {
    533                 assertEquals(expected[i].count, results[i].count);
    534                 assertEquals(expected[i].uri, results[i].uri);
    535             }
    536 
    537             mIndex++;
    538             mCountingSemaphore.release();
    539         }
    540 
    541         public int waitForCompletion(long timeoutMills) {
    542             Log.d(TAG, "waitForCompletion tid=" + Thread.currentThread().getId());
    543             int count = 0;
    544             try {
    545                 while (count < mWork.length) {
    546                     if (!mCountingSemaphore.tryAcquire(timeoutMills, TimeUnit.MILLISECONDS)) {
    547                         break;
    548                     }
    549                     count++;
    550                 }
    551             } catch (InterruptedException e) {
    552             }
    553             return count;
    554         }
    555     }
    556 
    557     /**
    558      * This gets called by AsyncQueryServiceHelper to read or write the data. It
    559      * also verifies the data against the data passed in the constructor
    560      */
    561     class TestProvider extends ContentProvider {
    562         OperationInfo[] mWork;
    563 
    564         int index = 0;
    565 
    566         public TestProvider(OperationInfo[] work) {
    567             mWork = work;
    568         }
    569 
    570         @Override
    571         public final Cursor query(Uri uri, String[] projection, String selection,
    572                 String[] selectionArgs, String orderBy) {
    573             Log.d(TAG, "Provider query index=" + index);
    574             assertEquals(mWork[index].op, Operation.EVENT_ARG_QUERY);
    575             assertEquals(mWork[index].uri, uri);
    576             assertEquals(mWork[index].projection, projection);
    577             assertEquals(mWork[index].selection, selection);
    578             assertEquals(mWork[index].selectionArgs, selectionArgs);
    579             assertEquals(mWork[index].orderBy, orderBy);
    580             return (Cursor) mWork[index++].result;
    581         }
    582 
    583         @Override
    584         public Uri insert(Uri uri, ContentValues values) {
    585             Log.d(TAG, "Provider insert index=" + index);
    586             assertEquals(mWork[index].op, Operation.EVENT_ARG_INSERT);
    587             assertEquals(mWork[index].uri, uri);
    588             assertEquals(mWork[index].values, values);
    589             return (Uri) mWork[index++].result;
    590         }
    591 
    592         @Override
    593         public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    594             Log.d(TAG, "Provider update index=" + index);
    595             assertEquals(mWork[index].op, Operation.EVENT_ARG_UPDATE);
    596             assertEquals(mWork[index].uri, uri);
    597             assertEquals(mWork[index].values, values);
    598             assertEquals(mWork[index].selection, selection);
    599             assertEquals(mWork[index].selectionArgs, selectionArgs);
    600             return (Integer) mWork[index++].result;
    601         }
    602 
    603         @Override
    604         public int delete(Uri uri, String selection, String[] selectionArgs) {
    605             Log.d(TAG, "Provider delete index=" + index);
    606             assertEquals(mWork[index].op, Operation.EVENT_ARG_DELETE);
    607             assertEquals(mWork[index].uri, uri);
    608             assertEquals(mWork[index].selection, selection);
    609             assertEquals(mWork[index].selectionArgs, selectionArgs);
    610             return (Integer) mWork[index++].result;
    611         }
    612 
    613         @Override
    614         public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) {
    615             Log.d(TAG, "Provider applyBatch index=" + index);
    616             assertEquals(mWork[index].op, Operation.EVENT_ARG_BATCH);
    617             assertEquals(mWork[index].cpo, operations);
    618             return (ContentProviderResult[]) mWork[index++].result;
    619         }
    620 
    621         @Override
    622         public String getType(Uri uri) {
    623             return null;
    624         }
    625 
    626         @Override
    627         public boolean onCreate() {
    628             return false;
    629         }
    630     }
    631 }
    632