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