blob: a972e4f84204b3462d5084a41866e7c1fdfb10af [file] [log] [blame]
Neil Fuller68f66662017-03-16 18:32:21 +00001/*
2 * Copyright (C) 2017 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.server.timezone;
18
19import org.hamcrest.BaseMatcher;
20import org.hamcrest.Description;
21import org.hamcrest.Matcher;
22import org.junit.After;
23import org.junit.Before;
24import org.junit.Test;
25
26import android.app.timezone.RulesUpdaterContract;
27import android.content.Context;
28import android.content.Intent;
29import android.provider.TimeZoneRulesDataContract;
30import android.support.test.InstrumentationRegistry;
31import android.support.test.filters.SmallTest;
32
Neil Fuller87b11282017-06-23 16:43:45 +010033import java.io.PrintWriter;
34import java.io.StringWriter;
35
Neil Fuller68f66662017-03-16 18:32:21 +000036import static org.junit.Assert.assertEquals;
37import static org.junit.Assert.assertFalse;
38import static org.junit.Assert.assertNotNull;
39import static org.junit.Assert.assertNull;
40import static org.junit.Assert.assertTrue;
41import static org.junit.Assert.fail;
42import static org.mockito.Mockito.eq;
43import static org.mockito.Mockito.mock;
44import static org.mockito.Mockito.when;
45import static org.mockito.hamcrest.MockitoHamcrest.argThat;
46
47/**
48 * White box interaction / unit testing of the {@link PackageTracker}.
49 */
50@SmallTest
51public class PackageTrackerTest {
52 private static final String UPDATE_APP_PACKAGE_NAME = "updateAppPackageName";
53 private static final String DATA_APP_PACKAGE_NAME = "dataAppPackageName";
54 private static final PackageVersions INITIAL_APP_PACKAGE_VERSIONS =
55 new PackageVersions(2 /* updateAppVersion */, 2 /* dataAppVersion */);
56
57 private ConfigHelper mMockConfigHelper;
58 private PackageManagerHelper mMockPackageManagerHelper;
59
60 private FakeClockHelper mFakeClock;
61 private FakeIntentHelper mFakeIntentHelper;
62 private PackageStatusStorage mPackageStatusStorage;
63 private PackageTracker mPackageTracker;
64
65 @Before
66 public void setUp() throws Exception {
67 Context context = InstrumentationRegistry.getContext();
68
69 mFakeClock = new FakeClockHelper();
70
71 // Read-only interfaces so are easy to mock.
72 mMockConfigHelper = mock(ConfigHelper.class);
73 mMockPackageManagerHelper = mock(PackageManagerHelper.class);
74
75 // Using the instrumentation context means the database is created in a test app-specific
76 // directory. We can use the real thing for this test.
Neil Fuller5f6750f2017-05-17 04:43:12 +010077 mPackageStatusStorage = new PackageStatusStorage(context.getFilesDir());
Neil Fuller68f66662017-03-16 18:32:21 +000078
79 // For other interactions with the Android framework we create a fake object.
80 mFakeIntentHelper = new FakeIntentHelper();
81
82 // Create the PackageTracker to use in tests.
83 mPackageTracker = new PackageTracker(
84 mFakeClock,
85 mMockConfigHelper,
86 mMockPackageManagerHelper,
87 mPackageStatusStorage,
88 mFakeIntentHelper);
89 }
90
91 @After
92 public void tearDown() throws Exception {
93 if (mPackageStatusStorage != null) {
Neil Fuller5f6750f2017-05-17 04:43:12 +010094 mPackageStatusStorage.deleteFileForTests();
Neil Fuller68f66662017-03-16 18:32:21 +000095 }
96 }
97
98 @Test
99 public void trackingDisabled_intentHelperNotUsed() {
100 // Set up device configuration.
101 configureTrackingDisabled();
102
103 // Initialize the tracker.
104 mPackageTracker.start();
105
106 // Check the IntentHelper was not initialized.
107 mFakeIntentHelper.assertNotInitialized();
108
109 // Check reliability triggering state.
110 mFakeIntentHelper.assertReliabilityTriggeringDisabled();
111 }
112
113 @Test
114 public void trackingDisabled_triggerUpdateIfNeededNotAllowed() {
115 // Set up device configuration.
116 configureTrackingDisabled();
117
118 // Initialize the tracker.
119 mPackageTracker.start();
120
121 // Check reliability triggering state.
122 mFakeIntentHelper.assertReliabilityTriggeringDisabled();
123
124 try {
125 // This call should also not be allowed and will throw an exception if tracking is
126 // disabled.
127 mPackageTracker.triggerUpdateIfNeeded(true);
128 fail();
129 } catch (IllegalStateException expected) {}
130
131 // Check reliability triggering state.
132 mFakeIntentHelper.assertReliabilityTriggeringDisabled();
133 }
134
135 @Test
136 public void trackingDisabled_unsolicitedResultsIgnored_withoutToken() {
137 // Set up device configuration.
138 configureTrackingDisabled();
139
140 // Initialize the tracker.
141 mPackageTracker.start();
142
143 // Check reliability triggering state.
144 mFakeIntentHelper.assertReliabilityTriggeringDisabled();
145
146 // Receiving a check result when tracking is disabled should cause the storage to be
147 // reset.
148 mPackageTracker.recordCheckResult(null /* checkToken */, true /* success */);
149
150 // Check reliability triggering state.
151 mFakeIntentHelper.assertReliabilityTriggeringDisabled();
152
153 // Assert the storage was reset.
154 checkPackageStorageStatusIsInitialOrReset();
155 }
156
157 @Test
158 public void trackingDisabled_unsolicitedResultsIgnored_withToken() {
159 // Set up device configuration.
160 configureTrackingDisabled();
161
162 // Set the storage into an arbitrary state so we can detect a reset.
163 mPackageStatusStorage.generateCheckToken(INITIAL_APP_PACKAGE_VERSIONS);
164
165 // Initialize the tracker.
166 mPackageTracker.start();
167
168 // Check reliability triggering state.
169 mFakeIntentHelper.assertReliabilityTriggeringDisabled();
170
171 // Receiving a check result when tracking is disabled should cause the storage to be reset.
172 mPackageTracker.recordCheckResult(createArbitraryCheckToken(), true /* success */);
173
174 // Check reliability triggering state.
175 mFakeIntentHelper.assertReliabilityTriggeringDisabled();
176
177 // Assert the storage was reset.
178 checkPackageStorageStatusIsInitialOrReset();
179 }
180
181 @Test
182 public void trackingEnabled_updateAppConfigMissing() throws Exception {
183 // Set up device configuration.
184 configureTrackingEnabled();
185 configureReliabilityConfigSettingsOk();
186 configureUpdateAppPackageNameMissing();
187 configureDataAppPackageOk(DATA_APP_PACKAGE_NAME);
188
189 try {
190 // Initialize the tracker.
191 mPackageTracker.start();
192 fail();
193 } catch (RuntimeException expected) {}
194
195 mFakeIntentHelper.assertNotInitialized();
196
197 // Check reliability triggering state.
198 mFakeIntentHelper.assertReliabilityTriggeringDisabled();
199 }
200
201 // TODO(nfuller): Uncomment or delete when it's clear what will happen with http://b/35995024
202 // @Test
203 // public void trackingEnabled_updateAppNotPrivileged() throws Exception {
204 // // Set up device configuration.
205 // configureTrackingEnabled();
206 // configureReliabilityConfigSettingsOk();
207 // configureUpdateAppPackageNotPrivileged(UPDATE_APP_PACKAGE_NAME);
208 // configureDataAppPackageOk(DATA_APP_PACKAGE_NAME);
209 //
210 // try {
211 // // Initialize the tracker.
212 // mPackageTracker.start();
213 // fail();
214 // } catch (RuntimeException expected) {}
215 //
216 // mFakeIntentHelper.assertNotInitialized();
217 //
218 // // Check reliability triggering state.
219 // mFakeIntentHelper.assertReliabilityTriggeringDisabled();
220 // }
221
222 @Test
223 public void trackingEnabled_dataAppConfigMissing() throws Exception {
224 // Set up device configuration.
225 configureTrackingEnabled();
226 configureReliabilityConfigSettingsOk();
227 configureUpdateAppPackageOk(UPDATE_APP_PACKAGE_NAME);
228 configureDataAppPackageNameMissing();
229
230 try {
231 // Initialize the tracker.
232 mPackageTracker.start();
233 fail();
234 } catch (RuntimeException expected) {}
235
236 mFakeIntentHelper.assertNotInitialized();
237
238 // Check reliability triggering state.
239 mFakeIntentHelper.assertReliabilityTriggeringDisabled();
240 }
241
242 // TODO(nfuller): Uncomment or delete when it's clear what will happen with http://b/35995024
243 // @Test
244 // public void trackingEnabled_dataAppNotPrivileged() throws Exception {
245 // // Set up device configuration.
246 // configureTrackingEnabled();
247 // configureReliabilityConfigSettingsOk();
248 // configureUpdateAppPackageOk(UPDATE_APP_PACKAGE_NAME);
249 // configureDataAppPackageNotPrivileged(DATA_APP_PACKAGE_NAME);
250 //
251 // try {
252 // // Initialize the tracker.
253 // mPackageTracker.start();
254 // fail();
255 // } catch (RuntimeException expected) {}
256 //
257 // mFakeIntentHelper.assertNotInitialized();
258 //
259 // // Check reliability triggering state.
260 // mFakeIntentHelper.assertReliabilityTriggeringDisabled();
261 // }
262
263 @Test
264 public void trackingEnabled_packageUpdate_badUpdateAppManifestEntry() throws Exception {
265 // Set up device configuration.
266 configureTrackingEnabled();
267 configureReliabilityConfigSettingsOk();
268 configureValidApplications();
269
270 // Initialize the tracker.
271 mPackageTracker.start();
272
273 // Check the intent helper is properly configured.
274 checkIntentHelperInitializedAndReliabilityTrackingEnabled();
275
276 // Check the initial storage state.
277 checkPackageStorageStatusIsInitialOrReset();
278
279 // Configure a bad manifest for the update app. Should effectively turn off tracking.
280 PackageVersions packageVersions =
281 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
282 configureUpdateAppManifestBad(UPDATE_APP_PACKAGE_NAME);
283 configureDataAppManifestOk(DATA_APP_PACKAGE_NAME);
284 configureUpdateAppPackageVersion(
285 UPDATE_APP_PACKAGE_NAME, packageVersions.mUpdateAppVersion);
286 configureDataAppPackageVersion(DATA_APP_PACKAGE_NAME, packageVersions.mDataAppVersion);
287 // Simulate a tracked package being updated.
288 mFakeIntentHelper.simulatePackageUpdatedEvent();
289
290 // Assert the PackageTracker did not attempt to trigger an update.
291 mFakeIntentHelper.assertUpdateNotTriggered();
292
293 // Check reliability triggering state.
294 mFakeIntentHelper.assertReliabilityTriggeringDisabled();
295
296 // Assert the storage was not touched.
297 checkPackageStorageStatusIsInitialOrReset();
298 }
299
300 @Test
301 public void trackingEnabled_packageUpdate_badDataAppManifestEntry() throws Exception {
302 // Set up device configuration.
303 configureTrackingEnabled();
304 configureReliabilityConfigSettingsOk();
305 configureValidApplications();
306
307 // Initialize the tracker.
308 mPackageTracker.start();
309
310 // Check the intent helper is properly configured.
311 checkIntentHelperInitializedAndReliabilityTrackingEnabled();
312
313 // Check the initial storage state.
314 checkPackageStorageStatusIsInitialOrReset();
315
316 // Configure a bad manifest for the data app. Should effectively turn off tracking.
317 PackageVersions packageVersions =
318 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
319 configureUpdateAppManifestOk(UPDATE_APP_PACKAGE_NAME);
320 configureDataAppManifestBad(DATA_APP_PACKAGE_NAME);
321 configureUpdateAppPackageVersion(
322 UPDATE_APP_PACKAGE_NAME, packageVersions.mUpdateAppVersion);
323 configureDataAppPackageVersion(DATA_APP_PACKAGE_NAME, packageVersions.mDataAppVersion);
324 mFakeIntentHelper.simulatePackageUpdatedEvent();
325
326 // Assert the PackageTracker did not attempt to trigger an update.
327 mFakeIntentHelper.assertUpdateNotTriggered();
328
329 // Check reliability triggering state.
330 mFakeIntentHelper.assertReliabilityTriggeringDisabled();
331
332 // Assert the storage was not touched.
333 checkPackageStorageStatusIsInitialOrReset();
334 }
335
336 @Test
337 public void trackingEnabled_packageUpdate_responseWithToken_success() throws Exception {
338 trackingEnabled_packageUpdate_responseWithToken(true);
339 }
340
341 @Test
342 public void trackingEnabled_packageUpdate_responseWithToken_failed() throws Exception {
343 trackingEnabled_packageUpdate_responseWithToken(false);
344 }
345
346 private void trackingEnabled_packageUpdate_responseWithToken(boolean success) throws Exception {
347 // Set up device configuration.
348 configureTrackingEnabled();
349 configureReliabilityConfigSettingsOk();
350 configureValidApplications();
351
352 // Initialize the tracker.
353 mPackageTracker.start();
354
355 // Check the intent helper is properly configured.
356 checkIntentHelperInitializedAndReliabilityTrackingEnabled();
357
358 // Check the initial storage state.
359 checkPackageStorageStatusIsInitialOrReset();
360
361 // Simulate a tracked package being updated.
362 PackageVersions packageVersions =
363 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
364 simulatePackageInstallation(packageVersions);
365
366 // Confirm an update was triggered.
367 checkUpdateCheckTriggered(packageVersions);
368
369 // Get the token that was passed to the intent helper, and pass it back.
370 CheckToken token = mFakeIntentHelper.captureAndResetLastToken();
371 mPackageTracker.recordCheckResult(token, success);
372
373 // Check storage and reliability triggering state.
374 if (success) {
375 checkUpdateCheckSuccessful(packageVersions);
376 } else {
377 checkUpdateCheckFailed(packageVersions);
378 }
379 }
380
381 @Test
382 public void trackingEnabled_packageUpdate_responseWithoutTokenCausesStorageReset_success()
383 throws Exception {
384 trackingEnabled_packageUpdate_responseWithoutTokenCausesStorageReset(true);
385 }
386
387 @Test
388 public void trackingEnabled_packageUpdate_responseWithoutTokenCausesStorageReset_failed()
389 throws Exception {
390 trackingEnabled_packageUpdate_responseWithoutTokenCausesStorageReset(false);
391 }
392
393 private void trackingEnabled_packageUpdate_responseWithoutTokenCausesStorageReset(
394 boolean success) throws Exception {
395 // Set up device configuration.
396 configureTrackingEnabled();
397 configureReliabilityConfigSettingsOk();
398 configureValidApplications();
399
400 // Initialize the tracker.
401 mPackageTracker.start();
402
403 // Check the intent helper is properly configured.
404 checkIntentHelperInitializedAndReliabilityTrackingEnabled();
405
406 // Check the initial storage state.
407 checkPackageStorageStatusIsInitialOrReset();
408
409 // Set up installed app versions / manifests.
410 PackageVersions packageVersions =
411 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
412 simulatePackageInstallation(packageVersions);
413
414 // Confirm an update was triggered.
415 checkUpdateCheckTriggered(packageVersions);
416
417 // Ignore the token that was given to the intent helper, just pass null.
418 mPackageTracker.recordCheckResult(null /* checkToken */, success);
419
420 // Check reliability triggering state.
421 mFakeIntentHelper.assertReliabilityTriggeringEnabled();
422
423 // Assert the storage was reset.
424 checkPackageStorageStatusIsInitialOrReset();
425 }
426
427 /**
428 * Two package updates triggered for the same package versions. The second is triggered while
429 * the first is still happening.
430 */
431 @Test
432 public void trackingEnabled_packageUpdate_twoChecksNoPackageChange_secondWhileFirstInProgress()
433 throws Exception {
434 // Set up device configuration.
435 configureTrackingEnabled();
436 configureReliabilityConfigSettingsOk();
437 configureValidApplications();
438
439 // Initialize the tracker.
440 mPackageTracker.start();
441
442 // Check the intent helper is properly configured.
443 checkIntentHelperInitializedAndReliabilityTrackingEnabled();
444
445 // Check the initial storage state.
446 checkPackageStorageStatusIsInitialOrReset();
447
448 // Simulate package installation.
449 PackageVersions packageVersions =
450 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
451 simulatePackageInstallation(packageVersions);
452
453 // Confirm an update was triggered.
454 checkUpdateCheckTriggered(packageVersions);
455
456 // Get the first token.
457 CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken();
458 assertEquals(packageVersions, token1.mPackageVersions);
459
460 // Now attempt to generate another check while the first is in progress and without having
461 // updated the package versions. The PackageTracker should trigger again for safety.
462 simulatePackageInstallation(packageVersions);
463
464 // Confirm an update was triggered.
465 checkUpdateCheckTriggered(packageVersions);
466
467 CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken();
468 assertEquals(packageVersions, token2.mPackageVersions);
469 assertEquals(token1.mPackageVersions, token2.mPackageVersions);
470 assertTrue(token1.mOptimisticLockId != token2.mOptimisticLockId);
471 }
472
473 /**
474 * Two package updates triggered for the same package versions. The second happens after
475 * the first has succeeded.
476 */
477 @Test
478 public void trackingEnabled_packageUpdate_twoChecksNoPackageChange_sequential()
479 throws Exception {
480 // Set up device configuration.
481 configureTrackingEnabled();
482 configureReliabilityConfigSettingsOk();
483 configureValidApplications();
484
485 // Initialize the tracker.
486 mPackageTracker.start();
487
488 // Check the intent helper is properly configured.
489 checkIntentHelperInitializedAndReliabilityTrackingEnabled();
490
491 // Check the initial storage state.
492 checkPackageStorageStatusIsInitialOrReset();
493
494 // Simulate package installation.
495 PackageVersions packageVersions =
496 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
497 simulatePackageInstallation(packageVersions);
498
499 // Confirm an update was triggered.
500 checkUpdateCheckTriggered(packageVersions);
501
502 // Get the token.
503 CheckToken token = mFakeIntentHelper.captureAndResetLastToken();
504 assertEquals(packageVersions, token.mPackageVersions);
505
506 // Simulate a successful check.
507 mPackageTracker.recordCheckResult(token, true /* success */);
508
509 // Check storage and reliability triggering state.
510 checkUpdateCheckSuccessful(packageVersions);
511
512 // Now attempt to generate another check, but without having updated the package. The
513 // PackageTracker should be smart enough to recognize there's nothing to do here.
514 simulatePackageInstallation(packageVersions);
515
516 // Assert the PackageTracker did not attempt to trigger an update.
517 mFakeIntentHelper.assertUpdateNotTriggered();
518
519 // Check storage and reliability triggering state.
520 checkUpdateCheckSuccessful(packageVersions);
521 }
522
523 /**
524 * Two package updates triggered for the same package versions. The second is triggered after
525 * the first has failed.
526 */
527 @Test
528 public void trackingEnabled_packageUpdate_afterFailure() throws Exception {
529 // Set up device configuration.
530 configureTrackingEnabled();
531 configureReliabilityConfigSettingsOk();
532 configureValidApplications();
533
534 // Initialize the tracker.
535 mPackageTracker.start();
536
537 // Check the intent helper is properly configured.
538 checkIntentHelperInitializedAndReliabilityTrackingEnabled();
539
540 // Check the initial storage state.
541 checkPackageStorageStatusIsInitialOrReset();
542
543 // Simulate package installation.
544 PackageVersions packageVersions =
545 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
546 simulatePackageInstallation(packageVersions);
547
548 // Confirm an update was triggered.
549 checkUpdateCheckTriggered(packageVersions);
550
551 // Get the first token.
552 CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken();
553 assertEquals(packageVersions, token1.mPackageVersions);
554
555 // Simulate an *unsuccessful* check.
556 mPackageTracker.recordCheckResult(token1, false /* success */);
557
558 // Check storage and reliability triggering state.
559 checkUpdateCheckFailed(packageVersions);
560
561 // Now generate another check, but without having updated the package. The
562 // PackageTracker should recognize the last check failed and trigger again.
563 simulatePackageInstallation(packageVersions);
564
565 // Confirm an update was triggered.
566 checkUpdateCheckTriggered(packageVersions);
567
568 // Get the second token.
569 CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken();
570
571 // Assert some things about the tokens.
572 assertEquals(packageVersions, token2.mPackageVersions);
573 assertTrue(token1.mOptimisticLockId != token2.mOptimisticLockId);
574
575 // For completeness, now simulate this check was successful.
576 mPackageTracker.recordCheckResult(token2, true /* success */);
577
578 // Check storage and reliability triggering state.
579 checkUpdateCheckSuccessful(packageVersions);
580 }
581
582 /**
583 * Two package updates triggered for different package versions. The second is triggered while
584 * the first is still happening.
585 */
586 @Test
587 public void trackingEnabled_packageUpdate_twoChecksWithPackageChange_firstCheckInProcess()
588 throws Exception {
589 // Set up device configuration.
590 configureTrackingEnabled();
591 configureReliabilityConfigSettingsOk();
592 configureValidApplications();
593
594 // Initialize the package tracker.
595 mPackageTracker.start();
596
597 // Check the intent helper is properly configured.
598 checkIntentHelperInitializedAndReliabilityTrackingEnabled();
599
600 // Check the initial storage state.
601 checkPackageStorageStatusIsInitialOrReset();
602
603 // Simulate package installation.
604 PackageVersions packageVersions1 =
605 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
606 simulatePackageInstallation(packageVersions1);
607
608 // Confirm an update was triggered.
609 checkUpdateCheckTriggered(packageVersions1);
610
611 // Get the first token.
612 CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken();
613 assertEquals(packageVersions1, token1.mPackageVersions);
614
615 // Simulate a tracked package being updated a second time (before the response for the
616 // first has been received).
617 PackageVersions packageVersions2 =
618 new PackageVersions(3 /* updateAppPackageVersion */, 4 /* dataAppPackageVersion */);
619 simulatePackageInstallation(packageVersions2);
620
621 // Confirm an update was triggered.
622 checkUpdateCheckTriggered(packageVersions2);
623
624 // Get the second token.
625 CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken();
626 assertEquals(packageVersions2, token2.mPackageVersions);
627
628 // token1 should be invalid because the token2 was generated.
629 mPackageTracker.recordCheckResult(token1, true /* success */);
630
631 // Reliability triggering should still be enabled.
632 mFakeIntentHelper.assertReliabilityTriggeringEnabled();
633
634 // Check the expected storage state.
635 checkPackageStorageStatus(PackageStatus.CHECK_STARTED, packageVersions2);
636
637 // token2 should still be accepted.
638 mPackageTracker.recordCheckResult(token2, true /* success */);
639
640 // Check storage and reliability triggering state.
641 checkUpdateCheckSuccessful(packageVersions2);
642 }
643
644 /**
645 * Two package updates triggered for different package versions. The second is triggered after
646 * the first has completed successfully.
647 */
648 @Test
649 public void trackingEnabled_packageUpdate_twoChecksWithPackageChange_sequential()
650 throws Exception {
651 // Set up device configuration.
652 configureTrackingEnabled();
653 configureReliabilityConfigSettingsOk();
654 configureValidApplications();
655
656 // Initialize the package tracker.
657 mPackageTracker.start();
658
659 // Check the intent helper is properly configured.
660 checkIntentHelperInitializedAndReliabilityTrackingEnabled();
661
662 // Check the initial storage state.
663 checkPackageStorageStatusIsInitialOrReset();
664
665 // Simulate package installation.
666 PackageVersions packageVersions1 =
667 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
668 simulatePackageInstallation(packageVersions1);
669
670 // Confirm an update was triggered.
671 checkUpdateCheckTriggered(packageVersions1);
672
673 // Get the first token.
674 CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken();
675 assertEquals(packageVersions1, token1.mPackageVersions);
676
677 // token1 should be accepted.
678 mPackageTracker.recordCheckResult(token1, true /* success */);
679
680 // Check storage and reliability triggering state.
681 checkUpdateCheckSuccessful(packageVersions1);
682
683 // Simulate a tracked package being updated a second time.
684 PackageVersions packageVersions2 =
685 new PackageVersions(3 /* updateAppPackageVersion */, 4 /* dataAppPackageVersion */);
686 simulatePackageInstallation(packageVersions2);
687
688 // Confirm an update was triggered.
689 checkUpdateCheckTriggered(packageVersions2);
690
691 // Get the second token.
692 CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken();
693 assertEquals(packageVersions2, token2.mPackageVersions);
694
695 // token2 should still be accepted.
696 mPackageTracker.recordCheckResult(token2, true /* success */);
697
698 // Check storage and reliability triggering state.
699 checkUpdateCheckSuccessful(packageVersions2);
700 }
701
702 /**
703 * Replaying the same token twice.
704 */
705 @Test
706 public void trackingEnabled_packageUpdate_sameTokenReplayFails() throws Exception {
707 // Set up device configuration.
708 configureTrackingEnabled();
709 configureReliabilityConfigSettingsOk();
710 configureValidApplications();
711
712 // Initialize the package tracker.
713 mPackageTracker.start();
714
715 // Check the intent helper is properly configured.
716 checkIntentHelperInitializedAndReliabilityTrackingEnabled();
717
718 // Check the initial storage state.
719 checkPackageStorageStatusIsInitialOrReset();
720
721 // Simulate package installation.
722 PackageVersions packageVersions1 =
723 new PackageVersions(2 /* updateAppPackageVersion */, 3 /* dataAppPackageVersion */);
724 simulatePackageInstallation(packageVersions1);
725
726 // Confirm an update was triggered.
727 checkUpdateCheckTriggered(packageVersions1);
728
729 // Get the first token.
730 CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken();
731 assertEquals(packageVersions1, token1.mPackageVersions);
732
733 // token1 should be accepted.
734 mPackageTracker.recordCheckResult(token1, true /* success */);
735
736 // Check storage and reliability triggering state.
737 checkUpdateCheckSuccessful(packageVersions1);
738
739 // Apply token1 again.
740 mPackageTracker.recordCheckResult(token1, true /* success */);
741
742 // Check the expected storage state. No real way to tell if it has been updated, but
743 // we can check the final state is still what it should be.
744 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions1);
745
746 // Under the covers we expect it to fail to update because the storage should recognize that
747 // the token is no longer valid.
748 mFakeIntentHelper.assertReliabilityTriggeringEnabled();
749
750 // Peek inside the package tracker to make sure it is tracking failure counts properly.
751 assertEquals(1, mPackageTracker.getCheckFailureCountForTests());
752 }
753
754 @Test
755 public void trackingEnabled_reliabilityTrigger_firstTime_initialStorage() throws Exception {
756 // Set up device configuration.
757 configureTrackingEnabled();
758 configureReliabilityConfigSettingsOk();
759 PackageVersions packageVersions = configureValidApplications();
760
761 // Initialize the package tracker.
762 mPackageTracker.start();
763
764 // Check the intent helper is properly configured.
765 checkIntentHelperInitializedAndReliabilityTrackingEnabled();
766
767 // Check the initial storage state.
768 checkPackageStorageStatusIsInitialOrReset();
769
770 // Simulate a reliability trigger.
771 mFakeIntentHelper.simulateReliabilityTrigger();
772
773 // Assert the PackageTracker did trigger an update.
774 checkUpdateCheckTriggered(packageVersions);
775
776 // Confirm the token was correct.
777 CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken();
778 assertEquals(packageVersions, token1.mPackageVersions);
779
780 // token1 should be accepted.
781 mPackageTracker.recordCheckResult(token1, true /* success */);
782
783 // Check storage and reliability triggering state.
784 checkUpdateCheckSuccessful(packageVersions);
785 }
786
787 @Test
788 public void trackingEnabled_reliabilityTrigger_afterRebootNoTriggerNeeded() throws Exception {
789 // Set up device configuration.
790 configureTrackingEnabled();
791 configureReliabilityConfigSettingsOk();
792 PackageVersions packageVersions = configureValidApplications();
793
794 // Force the storage into a state we want.
795 mPackageStatusStorage.forceCheckStateForTests(
796 PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions);
797
798 // Initialize the package tracker.
799 mPackageTracker.start();
800
801 // Check the intent helper is properly configured.
802 checkIntentHelperInitializedAndReliabilityTrackingEnabled();
803
804 // Check the initial storage state.
805 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions);
806
807 // Simulate a reliability trigger.
808 mFakeIntentHelper.simulateReliabilityTrigger();
809
810 // Assert the PackageTracker did not attempt to trigger an update.
811 mFakeIntentHelper.assertUpdateNotTriggered();
812
813 // Check storage and reliability triggering state.
814 checkUpdateCheckSuccessful(packageVersions);
815 }
816
817 /**
818 * Simulates the device starting where the storage records do not match the installed app
819 * versions. The reliability trigger should cause the package tracker to perform a check.
820 */
821 @Test
822 public void trackingEnabled_reliabilityTrigger_afterRebootTriggerNeededBecausePreviousFailed()
823 throws Exception {
824 // Set up device configuration.
825 configureTrackingEnabled();
826 configureReliabilityConfigSettingsOk();
827
828 PackageVersions oldPackageVersions = new PackageVersions(1, 1);
829 PackageVersions currentPackageVersions = new PackageVersions(2, 2);
830
831 // Simulate there being a newer version installed than the one recorded in storage.
832 configureValidApplications(currentPackageVersions);
833
834 // Force the storage into a state we want.
835 mPackageStatusStorage.forceCheckStateForTests(
836 PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions);
837
838 // Initialize the package tracker.
839 mPackageTracker.start();
840
841 // Check the intent helper is properly configured.
842 checkIntentHelperInitializedAndReliabilityTrackingEnabled();
843
844 // Check the initial storage state.
845 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions);
846
847 // Simulate a reliability trigger.
848 mFakeIntentHelper.simulateReliabilityTrigger();
849
850 // Assert the PackageTracker did trigger an update.
851 checkUpdateCheckTriggered(currentPackageVersions);
852
853 // Simulate the update check completing successfully.
854 CheckToken checkToken = mFakeIntentHelper.captureAndResetLastToken();
855 mPackageTracker.recordCheckResult(checkToken, true /* success */);
856
857 // Check storage and reliability triggering state.
858 checkUpdateCheckSuccessful(currentPackageVersions);
859 }
860
861 /**
862 * Simulates persistent failures of the reliability check. It should stop after the configured
863 * number of checks.
864 */
865 @Test
866 public void trackingEnabled_reliabilityTrigger_repeatedFailures() throws Exception {
867 // Set up device configuration.
868 configureTrackingEnabled();
869
870 int retriesAllowed = 3;
871 int checkDelayMillis = 5 * 60 * 1000;
872 configureReliabilityConfigSettings(retriesAllowed, checkDelayMillis);
873
874 PackageVersions oldPackageVersions = new PackageVersions(1, 1);
875 PackageVersions currentPackageVersions = new PackageVersions(2, 2);
876
877 // Simulate there being a newer version installed than the one recorded in storage.
878 configureValidApplications(currentPackageVersions);
879
880 // Force the storage into a state we want.
881 mPackageStatusStorage.forceCheckStateForTests(
882 PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions);
883
884 // Initialize the package tracker.
885 mPackageTracker.start();
886
887 // Check the intent helper is properly configured.
888 checkIntentHelperInitializedAndReliabilityTrackingEnabled();
889
890 // Check the initial storage state.
891 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions);
892
893 for (int i = 0; i < retriesAllowed + 1; i++) {
894 // Simulate a reliability trigger.
895 mFakeIntentHelper.simulateReliabilityTrigger();
896
897 // Assert the PackageTracker did trigger an update.
898 checkUpdateCheckTriggered(currentPackageVersions);
899
900 // Check the PackageTracker failure count before calling recordCheckResult.
901 assertEquals(i, mPackageTracker.getCheckFailureCountForTests());
902
903 // Simulate a check failure.
904 CheckToken checkToken = mFakeIntentHelper.captureAndResetLastToken();
905 mPackageTracker.recordCheckResult(checkToken, false /* success */);
906
907 // Peek inside the package tracker to make sure it is tracking failure counts properly.
908 assertEquals(i + 1, mPackageTracker.getCheckFailureCountForTests());
909
910 // Confirm nothing has changed.
911 mFakeIntentHelper.assertUpdateNotTriggered();
912 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE,
913 currentPackageVersions);
914
915 // Check reliability triggering is in the correct state.
916 if (i <= retriesAllowed) {
917 mFakeIntentHelper.assertReliabilityTriggeringEnabled();
918 } else {
919 mFakeIntentHelper.assertReliabilityTriggeringDisabled();
920 }
921 }
922 }
923
924 @Test
925 public void trackingEnabled_reliabilityTrigger_failureCountIsReset() throws Exception {
926 // Set up device configuration.
927 configureTrackingEnabled();
928
929 int retriesAllowed = 3;
930 int checkDelayMillis = 5 * 60 * 1000;
931 configureReliabilityConfigSettings(retriesAllowed, checkDelayMillis);
932
933 PackageVersions oldPackageVersions = new PackageVersions(1, 1);
934 PackageVersions currentPackageVersions = new PackageVersions(2, 2);
935
936 // Simulate there being a newer version installed than the one recorded in storage.
937 configureValidApplications(currentPackageVersions);
938
939 // Force the storage into a state we want.
940 mPackageStatusStorage.forceCheckStateForTests(
941 PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions);
942
943 // Initialize the package tracker.
944 mPackageTracker.start();
945
946 // Check the intent helper is properly configured.
947 checkIntentHelperInitializedAndReliabilityTrackingEnabled();
948
949 // Check the initial storage state.
950 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions);
951
952 // Fail (retries - 1) times.
953 for (int i = 0; i < retriesAllowed - 1; i++) {
954 // Simulate a reliability trigger.
955 mFakeIntentHelper.simulateReliabilityTrigger();
956
957 // Assert the PackageTracker did trigger an update.
958 checkUpdateCheckTriggered(currentPackageVersions);
959
960 // Check the PackageTracker failure count before calling recordCheckResult.
961 assertEquals(i, mPackageTracker.getCheckFailureCountForTests());
962
963 // Simulate a check failure.
964 CheckToken checkToken = mFakeIntentHelper.captureAndResetLastToken();
965 mPackageTracker.recordCheckResult(checkToken, false /* success */);
966
967 // Peek inside the package tracker to make sure it is tracking failure counts properly.
968 assertEquals(i + 1, mPackageTracker.getCheckFailureCountForTests());
969
970 // Confirm nothing has changed.
971 mFakeIntentHelper.assertUpdateNotTriggered();
972 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE,
973 currentPackageVersions);
974
975 // Check reliability triggering is still enabled.
976 mFakeIntentHelper.assertReliabilityTriggeringEnabled();
977 }
978
979 // Simulate a reliability trigger.
980 mFakeIntentHelper.simulateReliabilityTrigger();
981
982 // Assert the PackageTracker did trigger an update.
983 checkUpdateCheckTriggered(currentPackageVersions);
984
985 // Check the PackageTracker failure count before calling recordCheckResult.
986 assertEquals(retriesAllowed - 1, mPackageTracker.getCheckFailureCountForTests());
987
988 // On the last possible try, succeed.
989 CheckToken checkToken = mFakeIntentHelper.captureAndResetLastToken();
990 mPackageTracker.recordCheckResult(checkToken, true /* success */);
991
992 checkUpdateCheckSuccessful(currentPackageVersions);
993 }
994
995 /**
996 * Simulates reliability triggers happening too close together. Package tracker should ignore
997 * the ones it doesn't need.
998 */
999 @Test
1000 public void trackingEnabled_reliabilityTrigger_tooSoon() throws Exception {
1001 // Set up device configuration.
1002 configureTrackingEnabled();
1003
1004 int retriesAllowed = 5;
1005 int checkDelayMillis = 5 * 60 * 1000;
1006 configureReliabilityConfigSettings(retriesAllowed, checkDelayMillis);
1007
1008 PackageVersions oldPackageVersions = new PackageVersions(1, 1);
1009 PackageVersions currentPackageVersions = new PackageVersions(2, 2);
1010
1011 // Simulate there being a newer version installed than the one recorded in storage.
1012 configureValidApplications(currentPackageVersions);
1013
1014 // Force the storage into a state we want.
1015 mPackageStatusStorage.forceCheckStateForTests(
1016 PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions);
1017
1018 // Initialize the package tracker.
1019 mPackageTracker.start();
1020
1021 // Check the intent helper is properly configured.
1022 checkIntentHelperInitializedAndReliabilityTrackingEnabled();
1023
1024 // Check the initial storage state.
1025 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions);
1026
1027 // Simulate a reliability trigger.
1028 mFakeIntentHelper.simulateReliabilityTrigger();
1029
1030 // Assert the PackageTracker did trigger an update.
1031 checkUpdateCheckTriggered(currentPackageVersions);
1032 CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken();
1033
1034 // Increment the clock, but not enough.
1035 mFakeClock.incrementClock(checkDelayMillis - 1);
1036
1037 // Simulate a reliability trigger.
1038 mFakeIntentHelper.simulateReliabilityTrigger();
1039
1040 // Assert the PackageTracker did not trigger an update.
1041 mFakeIntentHelper.assertUpdateNotTriggered();
1042 checkPackageStorageStatus(PackageStatus.CHECK_STARTED, currentPackageVersions);
1043 mFakeIntentHelper.assertReliabilityTriggeringEnabled();
1044
1045 // Increment the clock slightly more. Should now consider the response overdue.
1046 mFakeClock.incrementClock(2);
1047
1048 // Simulate a reliability trigger.
1049 mFakeIntentHelper.simulateReliabilityTrigger();
1050
1051 // Triggering should have happened.
1052 checkUpdateCheckTriggered(currentPackageVersions);
1053 CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken();
1054
1055 // Check a new token was generated.
1056 assertFalse(token1.equals(token2));
1057 }
1058
1059 /**
1060 * Tests what happens when a package update doesn't complete and a reliability trigger cleans
1061 * up for it.
1062 */
1063 @Test
1064 public void trackingEnabled_reliabilityTrigger_afterPackageUpdateDidNotComplete()
1065 throws Exception {
1066
1067 // Set up device configuration.
1068 configureTrackingEnabled();
1069
1070 int retriesAllowed = 5;
1071 int checkDelayMillis = 5 * 60 * 1000;
1072 configureReliabilityConfigSettings(retriesAllowed, checkDelayMillis);
1073
1074 PackageVersions currentPackageVersions = new PackageVersions(1, 1);
1075 PackageVersions newPackageVersions = new PackageVersions(2, 2);
1076
1077 // Simulate there being a newer version installed than the one recorded in storage.
1078 configureValidApplications(currentPackageVersions);
1079
1080 // Force the storage into a state we want.
1081 mPackageStatusStorage.forceCheckStateForTests(
1082 PackageStatus.CHECK_COMPLETED_SUCCESS, currentPackageVersions);
1083
1084 // Initialize the package tracker.
1085 mPackageTracker.start();
1086
1087 // Check the intent helper is properly configured.
1088 checkIntentHelperInitializedAndReliabilityTrackingEnabled();
1089
1090 // Simulate a reliability trigger.
1091 simulatePackageInstallation(newPackageVersions);
1092
1093 // Assert the PackageTracker did trigger an update.
1094 checkUpdateCheckTriggered(newPackageVersions);
1095 CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken();
1096
1097 // Increment the clock, but not enough.
1098 mFakeClock.incrementClock(checkDelayMillis + 1);
1099
1100 // Simulate a reliability trigger.
1101 mFakeIntentHelper.simulateReliabilityTrigger();
1102
1103 // Assert the PackageTracker triggered an update.
1104 checkUpdateCheckTriggered(newPackageVersions);
1105 CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken();
1106
1107 // Check a new token was generated.
1108 assertFalse(token1.equals(token2));
1109
1110 // Simulate the reliability check completing.
1111 mPackageTracker.recordCheckResult(token2, true /* success */);
1112
1113 // Check everything is now as it should be.
1114 checkUpdateCheckSuccessful(newPackageVersions);
1115 }
1116
1117 /**
1118 * Simulates a reliability trigger happening too soon after a package update trigger occurred.
1119 */
1120 @Test
1121 public void trackingEnabled_reliabilityTriggerAfterUpdate_tooSoon() throws Exception {
1122 // Set up device configuration.
1123 configureTrackingEnabled();
1124
1125 int retriesAllowed = 5;
1126 int checkDelayMillis = 5 * 60 * 1000;
1127 configureReliabilityConfigSettings(retriesAllowed, checkDelayMillis);
1128
1129 PackageVersions currentPackageVersions = new PackageVersions(1, 1);
1130 PackageVersions newPackageVersions = new PackageVersions(2, 2);
1131
1132 // Simulate there being a newer version installed than the one recorded in storage.
1133 configureValidApplications(currentPackageVersions);
1134
1135 // Force the storage into a state we want.
1136 mPackageStatusStorage.forceCheckStateForTests(
1137 PackageStatus.CHECK_COMPLETED_SUCCESS, currentPackageVersions);
1138
1139 // Initialize the package tracker.
1140 mPackageTracker.start();
1141
1142 // Check the intent helper is properly configured.
1143 checkIntentHelperInitializedAndReliabilityTrackingEnabled();
1144
1145 // Check the initial storage state.
1146 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, currentPackageVersions);
1147
1148 // Simulate a package update trigger.
1149 simulatePackageInstallation(newPackageVersions);
1150
1151 // Assert the PackageTracker did trigger an update.
1152 checkUpdateCheckTriggered(newPackageVersions);
1153 CheckToken token1 = mFakeIntentHelper.captureAndResetLastToken();
1154
1155 // Increment the clock, but not enough.
1156 mFakeClock.incrementClock(checkDelayMillis - 1);
1157
1158 // Simulate a reliability trigger.
1159 mFakeIntentHelper.simulateReliabilityTrigger();
1160
1161 // Assert the PackageTracker did not trigger an update.
1162 mFakeIntentHelper.assertUpdateNotTriggered();
1163 checkPackageStorageStatus(PackageStatus.CHECK_STARTED, newPackageVersions);
1164 mFakeIntentHelper.assertReliabilityTriggeringEnabled();
1165
1166 // Increment the clock slightly more. Should now consider the response overdue.
1167 mFakeClock.incrementClock(2);
1168
1169 // Simulate a reliability trigger.
1170 mFakeIntentHelper.simulateReliabilityTrigger();
1171
1172 // Triggering should have happened.
1173 checkUpdateCheckTriggered(newPackageVersions);
1174 CheckToken token2 = mFakeIntentHelper.captureAndResetLastToken();
1175
1176 // Check a new token was generated.
1177 assertFalse(token1.equals(token2));
1178 }
1179
Neil Fuller87b11282017-06-23 16:43:45 +01001180 @Test
1181 public void dump() {
1182 StringWriter stringWriter = new StringWriter();
1183 PrintWriter printWriter = new PrintWriter(stringWriter);
1184
1185 mPackageTracker.dump(printWriter);
1186
1187 assertFalse(stringWriter.toString().isEmpty());
1188 }
1189
Neil Fuller68f66662017-03-16 18:32:21 +00001190 private void simulatePackageInstallation(PackageVersions packageVersions) throws Exception {
1191 configureApplicationsValidManifests(packageVersions);
1192
1193 // Simulate a tracked package being updated.
1194 mFakeIntentHelper.simulatePackageUpdatedEvent();
1195 }
1196
1197 /**
1198 * Checks an update check was triggered, reliability triggering is therefore enabled and the
1199 * storage state reflects that there is a check in progress.
1200 */
1201 private void checkUpdateCheckTriggered(PackageVersions packageVersions) {
1202 // Assert the PackageTracker attempted to trigger an update.
1203 mFakeIntentHelper.assertUpdateTriggered();
1204
1205 // If an update check was triggered reliability triggering should always be enabled to
1206 // ensure that it can be completed if it fails.
1207 mFakeIntentHelper.assertReliabilityTriggeringEnabled();
1208
1209 // Check the expected storage state.
1210 checkPackageStorageStatus(PackageStatus.CHECK_STARTED, packageVersions);
1211 }
1212
1213 private void checkUpdateCheckFailed(PackageVersions packageVersions) {
1214 // Check reliability triggering state.
1215 mFakeIntentHelper.assertReliabilityTriggeringEnabled();
1216
1217 // Assert the storage was updated.
1218 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, packageVersions);
1219 }
1220
1221 private void checkUpdateCheckSuccessful(PackageVersions packageVersions) {
1222 // Check reliability triggering state.
1223 mFakeIntentHelper.assertReliabilityTriggeringDisabled();
1224
1225 // Assert the storage was updated.
1226 checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions);
1227
1228 // Peek inside the package tracker to make sure it is tracking failure counts properly.
1229 assertEquals(0, mPackageTracker.getCheckFailureCountForTests());
1230 }
1231
1232 private PackageVersions configureValidApplications() throws Exception {
1233 configureValidApplications(INITIAL_APP_PACKAGE_VERSIONS);
1234 return INITIAL_APP_PACKAGE_VERSIONS;
1235 }
1236
1237 private void configureValidApplications(PackageVersions versions) throws Exception {
1238 configureUpdateAppPackageOk(UPDATE_APP_PACKAGE_NAME);
1239 configureDataAppPackageOk(DATA_APP_PACKAGE_NAME);
1240 configureApplicationsValidManifests(versions);
1241 }
1242
1243 private void configureApplicationsValidManifests(PackageVersions versions) throws Exception {
1244 configureUpdateAppManifestOk(UPDATE_APP_PACKAGE_NAME);
1245 configureDataAppManifestOk(DATA_APP_PACKAGE_NAME);
1246 configureUpdateAppPackageVersion(UPDATE_APP_PACKAGE_NAME, versions.mUpdateAppVersion);
1247 configureDataAppPackageVersion(DATA_APP_PACKAGE_NAME, versions.mDataAppVersion);
1248 }
1249
1250 private void configureUpdateAppPackageVersion(String updateAppPackageName,
1251 int updataAppPackageVersion) throws Exception {
1252 when(mMockPackageManagerHelper.getInstalledPackageVersion(updateAppPackageName))
1253 .thenReturn(updataAppPackageVersion);
1254 }
1255
1256 private void configureDataAppPackageVersion(String dataAppPackageName,
1257 int dataAppPackageVersion) throws Exception {
1258 when(mMockPackageManagerHelper.getInstalledPackageVersion(dataAppPackageName))
1259 .thenReturn(dataAppPackageVersion);
1260 }
1261
1262 private void configureUpdateAppManifestOk(String updateAppPackageName) throws Exception {
1263 Intent expectedIntent = RulesUpdaterContract.createUpdaterIntent(updateAppPackageName);
1264 when(mMockPackageManagerHelper.receiverRegistered(
1265 filterEquals(expectedIntent),
1266 eq(RulesUpdaterContract.TRIGGER_TIME_ZONE_RULES_CHECK_PERMISSION)))
1267 .thenReturn(true);
1268 when(mMockPackageManagerHelper.usesPermission(
1269 updateAppPackageName, RulesUpdaterContract.UPDATE_TIME_ZONE_RULES_PERMISSION))
1270 .thenReturn(true);
1271 }
1272
1273 private void configureUpdateAppManifestBad(String updateAppPackageName) throws Exception {
1274 Intent expectedIntent = RulesUpdaterContract.createUpdaterIntent(updateAppPackageName);
1275 when(mMockPackageManagerHelper.receiverRegistered(
1276 filterEquals(expectedIntent),
1277 eq(RulesUpdaterContract.TRIGGER_TIME_ZONE_RULES_CHECK_PERMISSION)))
1278 .thenReturn(false);
1279 // Has permission, but that shouldn't matter if the check above is false.
1280 when(mMockPackageManagerHelper.usesPermission(
1281 updateAppPackageName, RulesUpdaterContract.UPDATE_TIME_ZONE_RULES_PERMISSION))
1282 .thenReturn(true);
1283 }
1284
1285 private void configureDataAppManifestOk(String dataAppPackageName) throws Exception {
1286 when(mMockPackageManagerHelper.contentProviderRegistered(
1287 TimeZoneRulesDataContract.AUTHORITY, dataAppPackageName))
1288 .thenReturn(true);
1289 }
1290
1291 private void configureDataAppManifestBad(String dataAppPackageName) throws Exception {
1292 // Simulate the data app not exposing the content provider we require.
1293 when(mMockPackageManagerHelper.contentProviderRegistered(
1294 TimeZoneRulesDataContract.AUTHORITY, dataAppPackageName))
1295 .thenReturn(false);
1296 }
1297
1298 private void configureTrackingEnabled() {
1299 when(mMockConfigHelper.isTrackingEnabled()).thenReturn(true);
1300 }
1301
1302 private void configureTrackingDisabled() {
1303 when(mMockConfigHelper.isTrackingEnabled()).thenReturn(false);
1304 }
1305
1306 private void configureReliabilityConfigSettings(int retriesAllowed, int checkDelayMillis) {
1307 when(mMockConfigHelper.getFailedCheckRetryCount()).thenReturn(retriesAllowed);
1308 when(mMockConfigHelper.getCheckTimeAllowedMillis()).thenReturn(checkDelayMillis);
1309 }
1310
1311 private void configureReliabilityConfigSettingsOk() {
1312 configureReliabilityConfigSettings(5, 5 * 60 * 1000);
1313 }
1314
1315 private void configureUpdateAppPackageOk(String updateAppPackageName) throws Exception {
1316 when(mMockConfigHelper.getUpdateAppPackageName()).thenReturn(updateAppPackageName);
1317 when(mMockPackageManagerHelper.isPrivilegedApp(updateAppPackageName)).thenReturn(true);
1318 }
1319
1320 private void configureUpdateAppPackageNotPrivileged(String updateAppPackageName)
1321 throws Exception {
1322 when(mMockConfigHelper.getUpdateAppPackageName()).thenReturn(updateAppPackageName);
1323 when(mMockPackageManagerHelper.isPrivilegedApp(updateAppPackageName)).thenReturn(false);
1324 }
1325
1326 private void configureUpdateAppPackageNameMissing() {
1327 when(mMockConfigHelper.getUpdateAppPackageName()).thenReturn(null);
1328 }
1329
1330 private void configureDataAppPackageOk(String dataAppPackageName) throws Exception {
1331 when(mMockConfigHelper.getDataAppPackageName()).thenReturn(dataAppPackageName);
1332 when(mMockPackageManagerHelper.isPrivilegedApp(dataAppPackageName)).thenReturn(true);
1333 }
1334
1335 private void configureDataAppPackageNotPrivileged(String dataAppPackageName)
1336 throws Exception {
1337 when(mMockConfigHelper.getUpdateAppPackageName()).thenReturn(dataAppPackageName);
1338 when(mMockPackageManagerHelper.isPrivilegedApp(dataAppPackageName)).thenReturn(false);
1339 }
1340
1341 private void configureDataAppPackageNameMissing() {
1342 when(mMockConfigHelper.getDataAppPackageName()).thenThrow(new RuntimeException());
1343 }
1344
1345 private void checkIntentHelperInitializedAndReliabilityTrackingEnabled() {
1346 // Verify that calling start initialized the IntentHelper as well.
1347 mFakeIntentHelper.assertInitialized(UPDATE_APP_PACKAGE_NAME, DATA_APP_PACKAGE_NAME);
1348
1349 // Assert that reliability tracking is always enabled after initialization.
1350 mFakeIntentHelper.assertReliabilityTriggeringEnabled();
1351 }
1352
1353 private void checkPackageStorageStatus(
1354 int expectedCheckStatus, PackageVersions expectedPackageVersions) {
1355 PackageStatus packageStatus = mPackageStatusStorage.getPackageStatus();
1356 assertEquals(expectedCheckStatus, packageStatus.mCheckStatus);
1357 assertEquals(expectedPackageVersions, packageStatus.mVersions);
1358 }
1359
1360 private void checkPackageStorageStatusIsInitialOrReset() {
1361 assertNull(mPackageStatusStorage.getPackageStatus());
1362 }
1363
1364 private static CheckToken createArbitraryCheckToken() {
1365 return new CheckToken(1, INITIAL_APP_PACKAGE_VERSIONS);
1366 }
1367
1368 /**
1369 * A fake IntentHelper implementation for use in tests.
1370 */
1371 private static class FakeIntentHelper implements IntentHelper {
1372
1373 private Listener mListener;
1374 private String mUpdateAppPackageName;
1375 private String mDataAppPackageName;
1376
1377 private CheckToken mLastToken;
1378
1379 private boolean mReliabilityTriggeringEnabled;
1380
1381 @Override
1382 public void initialize(String updateAppPackageName, String dataAppPackageName,
1383 Listener listener) {
1384 assertNotNull(updateAppPackageName);
1385 assertNotNull(dataAppPackageName);
1386 assertNotNull(listener);
1387 mListener = listener;
1388 mUpdateAppPackageName = updateAppPackageName;
1389 mDataAppPackageName = dataAppPackageName;
1390 }
1391
1392 public void assertInitialized(
1393 String expectedUpdateAppPackageName, String expectedDataAppPackageName) {
1394 assertNotNull(mListener);
1395 assertEquals(expectedUpdateAppPackageName, mUpdateAppPackageName);
1396 assertEquals(expectedDataAppPackageName, mDataAppPackageName);
1397 }
1398
1399 public void assertNotInitialized() {
1400 assertNull(mListener);
1401 }
1402
1403 @Override
1404 public void sendTriggerUpdateCheck(CheckToken checkToken) {
1405 if (mLastToken != null) {
1406 fail("lastToken already set");
1407 }
1408 mLastToken = checkToken;
1409 }
1410
1411 @Override
1412 public void enableReliabilityTriggering() {
1413 mReliabilityTriggeringEnabled = true;
1414 }
1415
1416 @Override
1417 public void disableReliabilityTriggering() {
1418 mReliabilityTriggeringEnabled = false;
1419 }
1420
1421 public void assertReliabilityTriggeringEnabled() {
1422 assertTrue(mReliabilityTriggeringEnabled);
1423 }
1424
1425 public void assertReliabilityTriggeringDisabled() {
1426 assertFalse(mReliabilityTriggeringEnabled);
1427 }
1428
1429 public void assertUpdateTriggered() {
1430 assertNotNull(mLastToken);
1431 }
1432
1433 public void assertUpdateNotTriggered() {
1434 assertNull(mLastToken);
1435 }
1436
1437 public CheckToken captureAndResetLastToken() {
1438 CheckToken toReturn = mLastToken;
1439 assertNotNull("No update triggered", toReturn);
1440 mLastToken = null;
1441 return toReturn;
1442 }
1443
1444 public void simulatePackageUpdatedEvent() {
1445 mListener.triggerUpdateIfNeeded(true);
1446 }
1447
1448 public void simulateReliabilityTrigger() {
1449 mListener.triggerUpdateIfNeeded(false);
1450 }
1451 }
1452
1453 private static class FakeClockHelper implements ClockHelper {
1454
1455 private long currentTime = 1000;
1456
1457 @Override
1458 public long currentTimestamp() {
1459 return currentTime;
1460 }
1461
1462 public void incrementClock(long millis) {
1463 currentTime += millis;
1464 }
1465 }
1466
1467 /**
1468 * Registers a mockito parameter matcher that uses {@link Intent#filterEquals(Intent)}. to
1469 * check the parameter against the intent supplied.
1470 */
1471 private static Intent filterEquals(final Intent expected) {
1472 final Matcher<Intent> m = new BaseMatcher<Intent>() {
1473 @Override
1474 public boolean matches(Object actual) {
1475 return actual != null && expected.filterEquals((Intent) actual);
1476 }
1477 @Override
1478 public void describeTo(Description description) {
1479 description.appendText(expected.toString());
1480 }
1481 };
1482 return argThat(m);
1483 }
1484}