services/datareporting/tests/xpcshell/test_policy.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* Any copyright is dedicated to the Public Domain.
     2  * http://creativecommons.org/publicdomain/zero/1.0/ */
     4 "use strict";
     6 const {utils: Cu} = Components;
     8 Cu.import("resource://gre/modules/Preferences.jsm");
     9 Cu.import("resource://gre/modules/services/datareporting/policy.jsm");
    10 Cu.import("resource://testing-common/services/datareporting/mocks.jsm");
    11 Cu.import("resource://gre/modules/UpdateChannel.jsm");
    13 function getPolicy(name,
    14                    aCurrentPolicyVersion = 1,
    15                    aMinimumPolicyVersion = 1,
    16                    aBranchMinimumVersionOverride) {
    17   let branch = "testing.datareporting." + name;
    19   // The version prefs should not be removed on reset, so set them in the
    20   // default branch.
    21   let defaultPolicyPrefs = new Preferences({ branch: branch + ".policy."
    22                                            , defaultBranch: true });
    23   defaultPolicyPrefs.set("currentPolicyVersion", aCurrentPolicyVersion);
    24   defaultPolicyPrefs.set("minimumPolicyVersion", aMinimumPolicyVersion);
    25   let branchOverridePrefName = "minimumPolicyVersion.channel-" + UpdateChannel.get(false);
    26   if (aBranchMinimumVersionOverride !== undefined)
    27     defaultPolicyPrefs.set(branchOverridePrefName, aBranchMinimumVersionOverride);
    28   else
    29     defaultPolicyPrefs.reset(branchOverridePrefName);
    31   let policyPrefs = new Preferences(branch + ".policy.");
    32   let healthReportPrefs = new Preferences(branch + ".healthreport.");
    34   let listener = new MockPolicyListener();
    35   let policy = new DataReportingPolicy(policyPrefs, healthReportPrefs, listener);
    37   return [policy, policyPrefs, healthReportPrefs, listener];
    38 }
    40 function defineNow(policy, now) {
    41   print("Adjusting fake system clock to " + now);
    42   Object.defineProperty(policy, "now", {
    43     value: function customNow() {
    44       return now;
    45     },
    46     writable: true,
    47   });
    48 }
    50 function run_test() {
    51   run_next_test();
    52 }
    54 add_test(function test_constructor() {
    55   let policyPrefs = new Preferences("foo.bar.policy.");
    56   let hrPrefs = new Preferences("foo.bar.healthreport.");
    57   let listener = {
    58     onRequestDataUpload: function() {},
    59     onRequestRemoteDelete: function() {},
    60     onNotifyDataPolicy: function() {},
    61   };
    63   let policy = new DataReportingPolicy(policyPrefs, hrPrefs, listener);
    64   do_check_true(Date.now() - policy.firstRunDate.getTime() < 1000);
    66   let tomorrow = Date.now() + 24 * 60 * 60 * 1000;
    67   do_check_true(tomorrow - policy.nextDataSubmissionDate.getTime() < 1000);
    69   do_check_eq(policy.notifyState, policy.STATE_NOTIFY_UNNOTIFIED);
    71   run_next_test();
    72 });
    74 add_test(function test_prefs() {
    75   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("prefs");
    77   let now = new Date();
    78   let nowT = now.getTime();
    80   policy.firstRunDate = now;
    81   do_check_eq(policyPrefs.get("firstRunTime"), nowT);
    82   do_check_eq(policy.firstRunDate.getTime(), nowT);
    84   policy.dataSubmissionPolicyNotifiedDate= now;
    85   do_check_eq(policyPrefs.get("dataSubmissionPolicyNotifiedTime"), nowT);
    86   do_check_eq(policy.dataSubmissionPolicyNotifiedDate.getTime(), nowT);
    88   policy.dataSubmissionPolicyResponseDate = now;
    89   do_check_eq(policyPrefs.get("dataSubmissionPolicyResponseTime"), nowT);
    90   do_check_eq(policy.dataSubmissionPolicyResponseDate.getTime(), nowT);
    92   policy.dataSubmissionPolicyResponseType = "type-1";
    93   do_check_eq(policyPrefs.get("dataSubmissionPolicyResponseType"), "type-1");
    94   do_check_eq(policy.dataSubmissionPolicyResponseType, "type-1");
    96   policy.dataSubmissionEnabled = false;
    97   do_check_false(policyPrefs.get("dataSubmissionEnabled", true));
    98   do_check_false(policy.dataSubmissionEnabled);
   100   policy.dataSubmissionPolicyAccepted = false;
   101   do_check_false(policyPrefs.get("dataSubmissionPolicyAccepted", true));
   102   do_check_false(policy.dataSubmissionPolicyAccepted);
   104   do_check_false(policy.dataSubmissionPolicyBypassAcceptance);
   105   policyPrefs.set("dataSubmissionPolicyBypassAcceptance", true);
   106   do_check_true(policy.dataSubmissionPolicyBypassAcceptance);
   108   policy.lastDataSubmissionRequestedDate = now;
   109   do_check_eq(hrPrefs.get("lastDataSubmissionRequestedTime"), nowT);
   110   do_check_eq(policy.lastDataSubmissionRequestedDate.getTime(), nowT);
   112   policy.lastDataSubmissionSuccessfulDate = now;
   113   do_check_eq(hrPrefs.get("lastDataSubmissionSuccessfulTime"), nowT);
   114   do_check_eq(policy.lastDataSubmissionSuccessfulDate.getTime(), nowT);
   116   policy.lastDataSubmissionFailureDate = now;
   117   do_check_eq(hrPrefs.get("lastDataSubmissionFailureTime"), nowT);
   118   do_check_eq(policy.lastDataSubmissionFailureDate.getTime(), nowT);
   120   policy.nextDataSubmissionDate = now;
   121   do_check_eq(hrPrefs.get("nextDataSubmissionTime"), nowT);
   122   do_check_eq(policy.nextDataSubmissionDate.getTime(), nowT);
   124   policy.currentDaySubmissionFailureCount = 2;
   125   do_check_eq(hrPrefs.get("currentDaySubmissionFailureCount", 0), 2);
   126   do_check_eq(policy.currentDaySubmissionFailureCount, 2);
   128   policy.pendingDeleteRemoteData = true;
   129   do_check_true(hrPrefs.get("pendingDeleteRemoteData"));
   130   do_check_true(policy.pendingDeleteRemoteData);
   132   policy.healthReportUploadEnabled = false;
   133   do_check_false(hrPrefs.get("uploadEnabled"));
   134   do_check_false(policy.healthReportUploadEnabled);
   136   do_check_false(policy.healthReportUploadLocked);
   137   hrPrefs.lock("uploadEnabled");
   138   do_check_true(policy.healthReportUploadLocked);
   139   hrPrefs.unlock("uploadEnabled");
   140   do_check_false(policy.healthReportUploadLocked);
   142   run_next_test();
   143 });
   145 add_test(function test_notify_state_prefs() {
   146   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notify_state_prefs");
   148   do_check_eq(policy.notifyState, policy.STATE_NOTIFY_UNNOTIFIED);
   150   policy._dataSubmissionPolicyNotifiedDate = new Date();
   151   do_check_eq(policy.notifyState, policy.STATE_NOTIFY_WAIT);
   153   policy.dataSubmissionPolicyResponseDate = new Date();
   154   policy._dataSubmissionPolicyNotifiedDate = null;
   155   do_check_eq(policy.notifyState, policy.STATE_NOTIFY_COMPLETE);
   157   run_next_test();
   158 });
   160 add_task(function test_initial_submission_notification() {
   161   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("initial_submission_notification");
   163   do_check_eq(listener.notifyUserCount, 0);
   165   // Fresh instances should not do anything initially.
   166   policy.checkStateAndTrigger();
   167   do_check_eq(listener.notifyUserCount, 0);
   169   // We still shouldn't notify up to the millisecond before the barrier.
   170   defineNow(policy, new Date(policy.firstRunDate.getTime() +
   171                              policy.SUBMISSION_NOTIFY_INTERVAL_MSEC - 1));
   172   policy.checkStateAndTrigger();
   173   do_check_eq(listener.notifyUserCount, 0);
   174   do_check_null(policy._dataSubmissionPolicyNotifiedDate);
   175   do_check_eq(policy.dataSubmissionPolicyNotifiedDate.getTime(), 0);
   177   // We have crossed the threshold. We should see notification.
   178   defineNow(policy, new Date(policy.firstRunDate.getTime() +
   179                              policy.SUBMISSION_NOTIFY_INTERVAL_MSEC));
   180   policy.checkStateAndTrigger();
   181   do_check_eq(listener.notifyUserCount, 1);
   182   yield listener.lastNotifyRequest.onUserNotifyComplete();
   183   do_check_true(policy._dataSubmissionPolicyNotifiedDate instanceof Date);
   184   do_check_true(policy.dataSubmissionPolicyNotifiedDate.getTime() > 0);
   185   do_check_eq(policy.dataSubmissionPolicyNotifiedDate.getTime(),
   186               policy._dataSubmissionPolicyNotifiedDate.getTime());
   187   do_check_eq(policy.notifyState, policy.STATE_NOTIFY_WAIT);
   188 });
   190 add_test(function test_bypass_acceptance() {
   191   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("bypass_acceptance");
   193   policyPrefs.set("dataSubmissionPolicyBypassAcceptance", true);
   194   do_check_false(policy.dataSubmissionPolicyAccepted);
   195   do_check_true(policy.dataSubmissionPolicyBypassAcceptance);
   196   defineNow(policy, new Date(policy.nextDataSubmissionDate.getTime()));
   197   policy.checkStateAndTrigger();
   198   do_check_eq(listener.requestDataUploadCount, 1);
   200   run_next_test();
   201 });
   203 add_task(function test_notification_implicit_acceptance() {
   204   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_implicit_acceptance");
   206   let now = new Date(policy.nextDataSubmissionDate.getTime() -
   207                      policy.SUBMISSION_NOTIFY_INTERVAL_MSEC + 1);
   208   defineNow(policy, now);
   209   policy.checkStateAndTrigger();
   210   do_check_eq(listener.notifyUserCount, 1);
   211   yield listener.lastNotifyRequest.onUserNotifyComplete();
   212   do_check_eq(policy.dataSubmissionPolicyResponseType, "none-recorded");
   214   do_check_true(5000 < policy.IMPLICIT_ACCEPTANCE_INTERVAL_MSEC);
   215   defineNow(policy, new Date(now.getTime() + 5000));
   216   policy.checkStateAndTrigger();
   217   do_check_eq(listener.notifyUserCount, 1);
   218   do_check_eq(policy.notifyState, policy.STATE_NOTIFY_WAIT);
   219   do_check_eq(policy.dataSubmissionPolicyResponseDate.getTime(), 0);
   220   do_check_eq(policy.dataSubmissionPolicyResponseType, "none-recorded");
   222   defineNow(policy, new Date(now.getTime() + policy.IMPLICIT_ACCEPTANCE_INTERVAL_MSEC + 1));
   223   policy.checkStateAndTrigger();
   224   do_check_eq(listener.notifyUserCount, 1);
   225   do_check_eq(policy.notifyState, policy.STATE_NOTIFY_COMPLETE);
   226   do_check_eq(policy.dataSubmissionPolicyResponseDate.getTime(), policy.now().getTime());
   227   do_check_eq(policy.dataSubmissionPolicyResponseType, "accepted-implicit-time-elapsed");
   228 });
   230 add_task(function test_notification_rejected() {
   231   // User notification failed. We should not record it as being presented.
   232   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_failed");
   234   let now = new Date(policy.nextDataSubmissionDate.getTime() -
   235                      policy.SUBMISSION_NOTIFY_INTERVAL_MSEC + 1);
   236   defineNow(policy, now);
   237   policy.checkStateAndTrigger();
   238   do_check_eq(listener.notifyUserCount, 1);
   239   yield listener.lastNotifyRequest.onUserNotifyFailed(new Error("testing failed."));
   240   do_check_null(policy._dataSubmissionPolicyNotifiedDate);
   241   do_check_eq(policy.dataSubmissionPolicyNotifiedDate.getTime(), 0);
   242   do_check_eq(policy.notifyState, policy.STATE_NOTIFY_UNNOTIFIED);
   243 });
   245 add_task(function test_notification_accepted() {
   246   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_accepted");
   248   let now = new Date(policy.nextDataSubmissionDate.getTime() -
   249                      policy.SUBMISSION_NOTIFY_INTERVAL_MSEC + 1);
   250   defineNow(policy, now);
   251   policy.checkStateAndTrigger();
   252   yield listener.lastNotifyRequest.onUserNotifyComplete();
   253   do_check_eq(policy.notifyState, policy.STATE_NOTIFY_WAIT);
   254   do_check_false(policy.dataSubmissionPolicyAccepted);
   255   listener.lastNotifyRequest.onUserNotifyComplete();
   256   listener.lastNotifyRequest.onUserAccept("foo-bar");
   257   do_check_eq(policy.notifyState, policy.STATE_NOTIFY_COMPLETE);
   258   do_check_eq(policy.dataSubmissionPolicyResponseType, "accepted-foo-bar");
   259   do_check_true(policy.dataSubmissionPolicyAccepted);
   260   do_check_eq(policy.dataSubmissionPolicyResponseDate.getTime(), now.getTime());
   261 });
   263 add_task(function test_notification_rejected() {
   264   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_rejected");
   266   let now = new Date(policy.nextDataSubmissionDate.getTime() -
   267                      policy.SUBMISSION_NOTIFY_INTERVAL_MSEC + 1);
   268   defineNow(policy, now);
   269   policy.checkStateAndTrigger();
   270   yield listener.lastNotifyRequest.onUserNotifyComplete();
   271   do_check_eq(policy.notifyState, policy.STATE_NOTIFY_WAIT);
   272   do_check_false(policy.dataSubmissionPolicyAccepted);
   273   listener.lastNotifyRequest.onUserReject();
   274   do_check_eq(policy.notifyState, policy.STATE_NOTIFY_COMPLETE);
   275   do_check_eq(policy.dataSubmissionPolicyResponseType, "rejected-no-reason");
   276   do_check_false(policy.dataSubmissionPolicyAccepted);
   278   // No requests for submission should occur if user has rejected.
   279   defineNow(policy, new Date(policy.nextDataSubmissionDate.getTime() + 10000));
   280   policy.checkStateAndTrigger();
   281   do_check_eq(listener.requestDataUploadCount, 0);
   282 });
   284 add_test(function test_submission_kill_switch() {
   285   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("submission_kill_switch");
   287   policy.firstRunDate = new Date(Date.now() - 3 * 24 * 60 * 60 * 1000);
   288   policy.nextDataSubmissionDate = new Date(Date.now() - 24 * 60 * 60 * 1000);
   289   policy.recordUserAcceptance("accept-old-ack");
   290   do_check_true(policyPrefs.has("dataSubmissionPolicyAcceptedVersion"));
   291   policy.checkStateAndTrigger();
   292   do_check_eq(listener.requestDataUploadCount, 1);
   294   defineNow(policy,
   295     new Date(Date.now() + policy.SUBMISSION_REQUEST_EXPIRE_INTERVAL_MSEC + 100));
   296   policy.dataSubmissionEnabled = false;
   297   policy.checkStateAndTrigger();
   298   do_check_eq(listener.requestDataUploadCount, 1);
   300   run_next_test();
   301 });
   303 add_test(function test_upload_kill_switch() {
   304   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("upload_kill_switch");
   306   defineNow(policy, policy._futureDate(-24 * 60 * 60 * 1000));
   307   policy.recordUserAcceptance();
   308   defineNow(policy, policy.nextDataSubmissionDate);
   310   // So that we don't trigger deletions, which cause uploads to be delayed.
   311   hrPrefs.ignore("uploadEnabled", policy.uploadEnabledObserver);
   313   policy.healthReportUploadEnabled = false;
   314   policy.checkStateAndTrigger();
   315   do_check_eq(listener.requestDataUploadCount, 0);
   316   policy.healthReportUploadEnabled = true;
   317   policy.checkStateAndTrigger();
   318   do_check_eq(listener.requestDataUploadCount, 1);
   320   run_next_test();
   321 });
   323 add_test(function test_data_submission_no_data() {
   324   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("data_submission_no_data");
   326   policy.dataSubmissionPolicyResponseDate = new Date(Date.now() - 24 * 60 * 60 * 1000);
   327   policy.dataSubmissionPolicyAccepted = true;
   328   let now = new Date(policy.nextDataSubmissionDate.getTime() + 1);
   329   defineNow(policy, now);
   330   do_check_eq(listener.requestDataUploadCount, 0);
   331   policy.checkStateAndTrigger();
   332   do_check_eq(listener.requestDataUploadCount, 1);
   333   listener.lastDataRequest.onNoDataAvailable();
   335   // The next trigger should try again.
   336   defineNow(policy, new Date(now.getTime() + 155 * 60 * 1000));
   337   policy.checkStateAndTrigger();
   338   do_check_eq(listener.requestDataUploadCount, 2);
   340   run_next_test();
   341 });
   343 add_task(function test_data_submission_submit_failure_hard() {
   344   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("data_submission_submit_failure_hard");
   346   policy.dataSubmissionPolicyResponseDate = new Date(Date.now() - 24 * 60 * 60 * 1000);
   347   policy.dataSubmissionPolicyAccepted = true;
   348   let nextDataSubmissionDate = policy.nextDataSubmissionDate;
   349   let now = new Date(policy.nextDataSubmissionDate.getTime() + 1);
   350   defineNow(policy, now);
   352   policy.checkStateAndTrigger();
   353   do_check_eq(listener.requestDataUploadCount, 1);
   354   yield listener.lastDataRequest.onSubmissionFailureHard();
   355   do_check_eq(listener.lastDataRequest.state,
   356               listener.lastDataRequest.SUBMISSION_FAILURE_HARD);
   358   let expected = new Date(now.getTime() + 24 * 60 * 60 * 1000);
   359   do_check_eq(policy.nextDataSubmissionDate.getTime(), expected.getTime());
   361   defineNow(policy, new Date(now.getTime() + 10));
   362   policy.checkStateAndTrigger();
   363   do_check_eq(listener.requestDataUploadCount, 1);
   364 });
   366 add_task(function test_data_submission_submit_try_again() {
   367   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("data_submission_failure_soft");
   369   policy.recordUserAcceptance();
   370   let nextDataSubmissionDate = policy.nextDataSubmissionDate;
   371   let now = new Date(policy.nextDataSubmissionDate.getTime());
   372   defineNow(policy, now);
   373   policy.checkStateAndTrigger();
   374   yield listener.lastDataRequest.onSubmissionFailureSoft();
   375   do_check_eq(policy.nextDataSubmissionDate.getTime(),
   376               nextDataSubmissionDate.getTime() + 15 * 60 * 1000);
   377 });
   379 add_task(function test_submission_daily_scheduling() {
   380   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("submission_daily_scheduling");
   382   policy.dataSubmissionPolicyResponseDate = new Date(Date.now() - 24 * 60 * 60 * 1000);
   383   policy.dataSubmissionPolicyAccepted = true;
   384   let nextDataSubmissionDate = policy.nextDataSubmissionDate;
   386   // Skip ahead to next submission date. We should get a submission request.
   387   let now = new Date(policy.nextDataSubmissionDate.getTime());
   388   defineNow(policy, now);
   389   policy.checkStateAndTrigger();
   390   do_check_eq(listener.requestDataUploadCount, 1);
   391   do_check_eq(policy.lastDataSubmissionRequestedDate.getTime(), now.getTime());
   393   let finishedDate = new Date(now.getTime() + 250);
   394   defineNow(policy, new Date(finishedDate.getTime() + 50));
   395   yield listener.lastDataRequest.onSubmissionSuccess(finishedDate);
   396   do_check_eq(policy.lastDataSubmissionSuccessfulDate.getTime(), finishedDate.getTime());
   398   // Next scheduled submission should be exactly 1 day after the reported
   399   // submission success.
   401   let nextScheduled = new Date(finishedDate.getTime() + 24 * 60 * 60 * 1000);
   402   do_check_eq(policy.nextDataSubmissionDate.getTime(), nextScheduled.getTime());
   404   // Fast forward some arbitrary time. We shouldn't do any work yet.
   405   defineNow(policy, new Date(now.getTime() + 40000));
   406   policy.checkStateAndTrigger();
   407   do_check_eq(listener.requestDataUploadCount, 1);
   409   defineNow(policy, nextScheduled);
   410   policy.checkStateAndTrigger();
   411   do_check_eq(listener.requestDataUploadCount, 2);
   412   yield listener.lastDataRequest.onSubmissionSuccess(new Date(nextScheduled.getTime() + 200));
   413   do_check_eq(policy.nextDataSubmissionDate.getTime(),
   414     new Date(nextScheduled.getTime() + 24 * 60 * 60 * 1000 + 200).getTime());
   415 });
   417 add_test(function test_submission_far_future_scheduling() {
   418   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("submission_far_future_scheduling");
   420   let now = new Date(Date.now() - 24 * 60 * 60 * 1000);
   421   defineNow(policy, now);
   422   policy.recordUserAcceptance();
   423   now = new Date();
   424   defineNow(policy, now);
   426   let nextDate = policy._futureDate(3 * 24 * 60 * 60 * 1000 - 1);
   427   policy.nextDataSubmissionDate = nextDate;
   428   policy.checkStateAndTrigger();
   429   do_check_eq(listener.requestDataUploadCount, 0);
   430   do_check_eq(policy.nextDataSubmissionDate.getTime(), nextDate.getTime());
   432   policy.nextDataSubmissionDate = new Date(nextDate.getTime() + 1);
   433   policy.checkStateAndTrigger();
   434   do_check_eq(listener.requestDataUploadCount, 0);
   435   do_check_eq(policy.nextDataSubmissionDate.getTime(),
   436               policy._futureDate(24 * 60 * 60 * 1000).getTime());
   438   run_next_test();
   439 });
   441 add_task(function test_submission_backoff() {
   442   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("submission_backoff");
   444   do_check_eq(policy.FAILURE_BACKOFF_INTERVALS.length, 2);
   446   policy.dataSubmissionPolicyResponseDate = new Date(Date.now() - 24 * 60 * 60 * 1000);
   447   policy.dataSubmissionPolicyAccepted = true;
   449   let now = new Date(policy.nextDataSubmissionDate.getTime());
   450   defineNow(policy, now);
   451   policy.checkStateAndTrigger();
   452   do_check_eq(listener.requestDataUploadCount, 1);
   453   do_check_eq(policy.currentDaySubmissionFailureCount, 0);
   455   now = new Date(now.getTime() + 5000);
   456   defineNow(policy, now);
   458   // On first soft failure we should back off by scheduled interval.
   459   yield listener.lastDataRequest.onSubmissionFailureSoft();
   460   do_check_eq(policy.currentDaySubmissionFailureCount, 1);
   461   do_check_eq(policy.nextDataSubmissionDate.getTime(),
   462               new Date(now.getTime() + policy.FAILURE_BACKOFF_INTERVALS[0]).getTime());
   463   do_check_eq(policy.lastDataSubmissionFailureDate.getTime(), now.getTime());
   465   // Should not request submission until scheduled.
   466   now = new Date(policy.nextDataSubmissionDate.getTime() - 1);
   467   defineNow(policy, now);
   468   policy.checkStateAndTrigger();
   469   do_check_eq(listener.requestDataUploadCount, 1);
   471   // 2nd request for submission.
   472   now = new Date(policy.nextDataSubmissionDate.getTime());
   473   defineNow(policy, now);
   474   policy.checkStateAndTrigger();
   475   do_check_eq(listener.requestDataUploadCount, 2);
   477   now = new Date(now.getTime() + 5000);
   478   defineNow(policy, now);
   480   // On second failure we should back off by more.
   481   yield listener.lastDataRequest.onSubmissionFailureSoft();
   482   do_check_eq(policy.currentDaySubmissionFailureCount, 2);
   483   do_check_eq(policy.nextDataSubmissionDate.getTime(),
   484               new Date(now.getTime() + policy.FAILURE_BACKOFF_INTERVALS[1]).getTime());
   486   now = new Date(policy.nextDataSubmissionDate.getTime());
   487   defineNow(policy, now);
   488   policy.checkStateAndTrigger();
   489   do_check_eq(listener.requestDataUploadCount, 3);
   491   now = new Date(now.getTime() + 5000);
   492   defineNow(policy, now);
   494   // On 3rd failure we should back off by a whole day.
   495   yield listener.lastDataRequest.onSubmissionFailureSoft();
   496   do_check_eq(policy.currentDaySubmissionFailureCount, 0);
   497   do_check_eq(policy.nextDataSubmissionDate.getTime(),
   498               new Date(now.getTime() + 24 * 60 * 60 * 1000).getTime());
   499 });
   501 // Ensure that only one submission request can be active at a time.
   502 add_test(function test_submission_expiring() {
   503   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("submission_expiring");
   505   policy.dataSubmissionPolicyResponseDate = new Date(Date.now() - 24 * 60 * 60 * 1000);
   506   policy.dataSubmissionPolicyAccepted = true;
   507   let nextDataSubmission = policy.nextDataSubmissionDate;
   508   let now = new Date(policy.nextDataSubmissionDate.getTime());
   509   defineNow(policy, now);
   510   policy.checkStateAndTrigger();
   511   do_check_eq(listener.requestDataUploadCount, 1);
   512   defineNow(policy, new Date(now.getTime() + 500));
   513   policy.checkStateAndTrigger();
   514   do_check_eq(listener.requestDataUploadCount, 1);
   516   defineNow(policy, new Date(policy.now().getTime() +
   517                              policy.SUBMISSION_REQUEST_EXPIRE_INTERVAL_MSEC));
   519   policy.checkStateAndTrigger();
   520   do_check_eq(listener.requestDataUploadCount, 2);
   522   run_next_test();
   523 });
   525 add_task(function test_delete_remote_data() {
   526   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("delete_remote_data");
   528   do_check_false(policy.pendingDeleteRemoteData);
   529   let nextSubmissionDate = policy.nextDataSubmissionDate;
   531   let now = new Date();
   532   defineNow(policy, now);
   534   policy.deleteRemoteData();
   535   do_check_true(policy.pendingDeleteRemoteData);
   536   do_check_neq(nextSubmissionDate.getTime(),
   537                policy.nextDataSubmissionDate.getTime());
   538   do_check_eq(now.getTime(), policy.nextDataSubmissionDate.getTime());
   540   do_check_eq(listener.requestRemoteDeleteCount, 1);
   541   do_check_true(listener.lastRemoteDeleteRequest.isDelete);
   542   defineNow(policy, policy._futureDate(1000));
   544   yield listener.lastRemoteDeleteRequest.onSubmissionSuccess(policy.now());
   545   do_check_false(policy.pendingDeleteRemoteData);
   546 });
   548 // Ensure that deletion requests take priority over regular data submission.
   549 add_test(function test_delete_remote_data_priority() {
   550   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("delete_remote_data_priority");
   552   let now = new Date();
   553   defineNow(policy, policy._futureDate(-24 * 60 * 60 * 1000));
   554   policy.recordUserAcceptance();
   555   defineNow(policy, new Date(now.getTime() + 3 * 24 * 60 * 60 * 1000));
   557   policy.checkStateAndTrigger();
   558   do_check_eq(listener.requestDataUploadCount, 1);
   559   policy._inProgressSubmissionRequest = null;
   561   policy.deleteRemoteData();
   562   policy.checkStateAndTrigger();
   564   do_check_eq(listener.requestRemoteDeleteCount, 1);
   565   do_check_eq(listener.requestDataUploadCount, 1);
   567   run_next_test();
   568 });
   570 add_test(function test_delete_remote_data_backoff() {
   571   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("delete_remote_data_backoff");
   573   let now = new Date();
   574   defineNow(policy, policy._futureDate(-24 * 60 * 60 * 1000));
   575   policy.recordUserAcceptance();
   576   defineNow(policy, now);
   577   policy.nextDataSubmissionDate = now;
   578   policy.deleteRemoteData();
   580   policy.checkStateAndTrigger();
   581   do_check_eq(listener.requestRemoteDeleteCount, 1);
   582   defineNow(policy, policy._futureDate(1000));
   583   policy.checkStateAndTrigger();
   584   do_check_eq(listener.requestDataUploadCount, 0);
   585   do_check_eq(listener.requestRemoteDeleteCount, 1);
   587   defineNow(policy, policy._futureDate(500));
   588   listener.lastRemoteDeleteRequest.onSubmissionFailureSoft();
   589   defineNow(policy, policy._futureDate(50));
   591   policy.checkStateAndTrigger();
   592   do_check_eq(listener.requestRemoteDeleteCount, 1);
   594   defineNow(policy, policy._futureDate(policy.FAILURE_BACKOFF_INTERVALS[0] - 50));
   595   policy.checkStateAndTrigger();
   596   do_check_eq(listener.requestRemoteDeleteCount, 2);
   598   run_next_test();
   599 });
   601 // If we request delete while an upload is in progress, delete should be
   602 // scheduled immediately after upload.
   603 add_task(function test_delete_remote_data_in_progress_upload() {
   604   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("delete_remote_data_in_progress_upload");
   606   let now = new Date();
   607   defineNow(policy, policy._futureDate(-24 * 60 * 60 * 1000));
   608   policy.recordUserAcceptance();
   609   defineNow(policy, policy.nextDataSubmissionDate);
   611   policy.checkStateAndTrigger();
   612   do_check_eq(listener.requestDataUploadCount, 1);
   613   defineNow(policy, policy._futureDate(50 * 1000));
   615   // If we request a delete during a pending request, nothing should be done.
   616   policy.deleteRemoteData();
   617   policy.checkStateAndTrigger();
   618   do_check_eq(listener.requestDataUploadCount, 1);
   619   do_check_eq(listener.requestRemoteDeleteCount, 0);
   621   // Now wait a little bit and finish the request.
   622   defineNow(policy, policy._futureDate(10 * 1000));
   623   yield listener.lastDataRequest.onSubmissionSuccess(policy._futureDate(1000));
   624   defineNow(policy, policy._futureDate(5000));
   626   policy.checkStateAndTrigger();
   627   do_check_eq(listener.requestDataUploadCount, 1);
   628   do_check_eq(listener.requestRemoteDeleteCount, 1);
   629 });
   631 add_test(function test_polling() {
   632   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("polling");
   633   let intended = 500;
   634   let acceptable = 250;     // Because nsITimer doesn't guarantee times.
   636   // Ensure checkStateAndTrigger is called at a regular interval.
   637   let then = Date.now();
   638   print("Starting run: " + then);
   639   Object.defineProperty(policy, "POLL_INTERVAL_MSEC", {
   640     value: intended,
   641   });
   642   let count = 0;
   644   Object.defineProperty(policy, "checkStateAndTrigger", {
   645     value: function fakeCheckStateAndTrigger() {
   646       let now = Date.now();
   647       let after = now - then;
   648       count++;
   650       print("Polled at " + now + " after " + after + "ms, intended " + intended);
   651       do_check_true(after >= acceptable);
   652       DataReportingPolicy.prototype.checkStateAndTrigger.call(policy);
   654       if (count >= 2) {
   655         policy.stopPolling();
   657         do_check_eq(listener.notifyUserCount, 0);
   658         do_check_eq(listener.requestDataUploadCount, 0);
   660         run_next_test();
   661       }
   663       // "Specified timer period will be at least the time between when
   664       // processing for last firing the callback completes and when the next
   665       // firing occurs."
   666       //
   667       // That means we should set 'then' at the *end* of our handler, not
   668       // earlier.
   669       then = Date.now();
   670     }
   671   });
   672   policy.startPolling();
   673 });
   675 // Ensure that implicit acceptance of policy is resolved through polling.
   676 //
   677 // This is probably covered by other tests. But, it's best to have explicit
   678 // coverage from a higher-level.
   679 add_test(function test_polling_implicit_acceptance() {
   680   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("polling_implicit_acceptance");
   682   // Redefine intervals with shorter, test-friendly values.
   683   Object.defineProperty(policy, "POLL_INTERVAL_MSEC", {
   684     value: 250,
   685   });
   687   Object.defineProperty(policy, "IMPLICIT_ACCEPTANCE_INTERVAL_MSEC", {
   688     value: 700,
   689   });
   691   let count = 0;
   693   // Track JS elapsed time, so we can decide if we've waited for enough ticks.
   694   let start;
   695   Object.defineProperty(policy, "checkStateAndTrigger", {
   696     value: function CheckStateAndTriggerProxy() {
   697       count++;
   698       let now = Date.now();
   699       let delta = now - start;
   700       print("checkStateAndTrigger count: " + count + ", now " + now +
   701             ", delta " + delta);
   703       // Account for some slack.
   704       DataReportingPolicy.prototype.checkStateAndTrigger.call(policy);
   706       // What should happen on different invocations:
   707       //
   708       //   1) We are inside the prompt interval so user gets prompted.
   709       //   2) still ~300ms away from implicit acceptance
   710       //   3) still ~50ms away from implicit acceptance
   711       //   4) Implicit acceptance recorded. Data submission requested.
   712       //   5) Request still pending. No new submission requested.
   713       //
   714       // Note that, due to the inaccuracy of timers, 4 might not happen until 5
   715       // firings have occurred. Yay. So we watch times, not just counts.
   717       do_check_eq(listener.notifyUserCount, 1);
   719       if (count == 1) {
   720         listener.lastNotifyRequest.onUserNotifyComplete();
   721       }
   723       if (delta <= (policy.IMPLICIT_ACCEPTANCE_INTERVAL_MSEC + policy.POLL_INTERVAL_MSEC)) {
   724         do_check_false(policy.dataSubmissionPolicyAccepted);
   725         do_check_eq(listener.requestDataUploadCount, 0);
   726       } else if (count > 3) {
   727         do_check_true(policy.dataSubmissionPolicyAccepted);
   728         do_check_eq(policy.dataSubmissionPolicyResponseType,
   729                     "accepted-implicit-time-elapsed");
   730         do_check_eq(listener.requestDataUploadCount, 1);
   731       }
   733       if ((count > 4) && policy.dataSubmissionPolicyAccepted) {
   734         do_check_eq(listener.requestDataUploadCount, 1);
   735         policy.stopPolling();
   736         run_next_test();
   737       }
   738     }
   739   });
   741   policy.firstRunDate = new Date(Date.now() - 4 * 24 * 60 * 60 * 1000);
   742   policy.nextDataSubmissionDate = new Date(Date.now());
   743   start = Date.now();
   744   policy.startPolling();
   745 });
   747 add_task(function test_record_health_report_upload_enabled() {
   748   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("record_health_report_upload_enabled");
   750   // Preconditions.
   751   do_check_false(policy.pendingDeleteRemoteData);
   752   do_check_true(policy.healthReportUploadEnabled);
   753   do_check_eq(listener.requestRemoteDeleteCount, 0);
   755   // User intent to disable should immediately result in a pending
   756   // delete request.
   757   policy.recordHealthReportUploadEnabled(false, "testing 1 2 3");
   758   do_check_false(policy.healthReportUploadEnabled);
   759   do_check_true(policy.pendingDeleteRemoteData);
   760   do_check_eq(listener.requestRemoteDeleteCount, 1);
   762   // Fulfilling it should make it go away.
   763   yield listener.lastRemoteDeleteRequest.onNoDataAvailable();
   764   do_check_false(policy.pendingDeleteRemoteData);
   766   // User intent to enable should get us back to default state.
   767   policy.recordHealthReportUploadEnabled(true, "testing 1 2 3");
   768   do_check_false(policy.pendingDeleteRemoteData);
   769   do_check_true(policy.healthReportUploadEnabled);
   770 });
   772 add_test(function test_pref_change_initiates_deletion() {
   773   let [policy, policyPrefs, hrPrefs, listener] = getPolicy("record_health_report_upload_enabled");
   775   // Preconditions.
   776   do_check_false(policy.pendingDeleteRemoteData);
   777   do_check_true(policy.healthReportUploadEnabled);
   778   do_check_eq(listener.requestRemoteDeleteCount, 0);
   780   // User intent to disable should indirectly result in a pending
   781   // delete request, because the policy is watching for the pref
   782   // to change.
   783   Object.defineProperty(policy, "deleteRemoteData", {
   784     value: function deleteRemoteDataProxy() {
   785       do_check_false(policy.healthReportUploadEnabled);
   786       do_check_false(policy.pendingDeleteRemoteData);     // Just called.
   788       run_next_test();
   789     },
   790   });
   792   hrPrefs.set("uploadEnabled", false);
   793 });
   795 add_task(function* test_policy_version() {
   796   let policy, policyPrefs, hrPrefs, listener, now, firstRunTime;
   797   function createPolicy(shouldBeAccepted = false,
   798                         currentPolicyVersion = 1, minimumPolicyVersion = 1,
   799                         branchMinimumVersionOverride) {
   800     [policy, policyPrefs, hrPrefs, listener] =
   801       getPolicy("policy_version_test", currentPolicyVersion,
   802                 minimumPolicyVersion, branchMinimumVersionOverride);
   803     let firstRun = now === undefined;
   804     if (firstRun) {
   805       firstRunTime = policy.firstRunDate.getTime();
   806       do_check_true(firstRunTime > 0);
   807       now = new Date(policy.firstRunDate.getTime() +
   808                      policy.SUBMISSION_NOTIFY_INTERVAL_MSEC);
   809     }
   810     else {
   811       // The first-run time should not be reset even after policy-version
   812       // upgrades.
   813       do_check_eq(policy.firstRunDate.getTime(), firstRunTime);
   814     }
   815     defineNow(policy, now);
   816     do_check_eq(policy.dataSubmissionPolicyAccepted, shouldBeAccepted);
   817   }
   819   function* triggerPolicyCheckAndEnsureNotified(notified = true, accept = true) {
   820     policy.checkStateAndTrigger();
   821     do_check_eq(listener.notifyUserCount, Number(notified));
   822     if (notified) {
   823       yield listener.lastNotifyRequest.onUserNotifyComplete();
   824       if (accept) {
   825         listener.lastNotifyRequest.onUserAccept("because,");
   826         do_check_true(policy.dataSubmissionPolicyAccepted);
   827         do_check_eq(policyPrefs.get("dataSubmissionPolicyAcceptedVersion"),
   828                     policyPrefs.get("currentPolicyVersion"));
   829       }
   830       else {
   831         do_check_false(policyPrefs.has("dataSubmissionPolicyAcceptedVersion"));
   832       }
   833     }
   834   }
   836   createPolicy();
   837   yield triggerPolicyCheckAndEnsureNotified();
   839   // We shouldn't be notified again if the current version is still valid;
   840   createPolicy(true);
   841   yield triggerPolicyCheckAndEnsureNotified(false);
   843   // Just increasing the current version isn't enough. The minimum
   844   // version must be changed.
   845   let currentPolicyVersion = policyPrefs.get("currentPolicyVersion");
   846   let minimumPolicyVersion = policyPrefs.get("minimumPolicyVersion");
   847   createPolicy(true, ++currentPolicyVersion, minimumPolicyVersion);
   848   yield triggerPolicyCheckAndEnsureNotified(false);
   849   do_check_true(policy.dataSubmissionPolicyAccepted);
   850   do_check_eq(policyPrefs.get("dataSubmissionPolicyAcceptedVersion"),
   851               minimumPolicyVersion);
   853   // Increase the minimum policy version and check if we're notified.
   854   createPolicy(false, currentPolicyVersion, ++minimumPolicyVersion);
   855   do_check_false(policyPrefs.has("dataSubmissionPolicyAcceptedVersion"));
   856   yield triggerPolicyCheckAndEnsureNotified();
   858   // Test increasing the minimum version just on the current channel.
   859   createPolicy(true, currentPolicyVersion, minimumPolicyVersion);
   860   yield triggerPolicyCheckAndEnsureNotified(false);
   861   createPolicy(false, ++currentPolicyVersion, minimumPolicyVersion, minimumPolicyVersion + 1);
   862   yield triggerPolicyCheckAndEnsureNotified(true);
   863 });

mercurial