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