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