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