Bug 1435296 Address xpcshell test failures from increasing timer precision r?baku draft
authorTom Ritter <tom@mozilla.com>
Mon, 12 Feb 2018 11:41:38 -0600
changeset 753924 3986d4b4160d59d3012afd3afd97a237dcae79f9
parent 753923 4581ef36baae70079c0f833aea7548cb450755c5
push id98722
push userbmo:tom@mozilla.com
push dateMon, 12 Feb 2018 17:42:43 +0000
reviewersbaku
bugs1435296
milestone60.0a1
Bug 1435296 Address xpcshell test failures from increasing timer precision r?baku See the comment on "Address test failures caused by bumping timer precision to 2 ms" for more details. MozReview-Commit-ID: LrsucEPdZIo
browser/components/extensions/test/xpcshell/test_ext_browsingData_cookies_cache.js
browser/extensions/formautofill/test/unit/test_addressRecords.js
browser/extensions/formautofill/test/unit/test_creditCardRecords.js
devtools/server/tests/unit/test_promises_object_creationtimestamp.js
netwerk/test/unit/test_race_cache_with_network.js
services/fxaccounts/tests/xpcshell/test_profile.js
services/sync/tests/unit/test_addons_engine.js
toolkit/components/extensions/test/xpcshell/test_ext_downloads_search.js
toolkit/components/places/tests/bookmarks/test_bookmarks_notifications.js
toolkit/components/places/tests/bookmarks/test_keywords.js
toolkit/components/places/tests/unit/test_async_transactions.js
toolkit/components/places/tests/unit/test_keywords.js
toolkit/components/places/tests/unit/test_sync_utils.js
toolkit/components/satchel/test/unit/test_notify.js
--- a/browser/components/extensions/test/xpcshell/test_ext_browsingData_cookies_cache.js
+++ b/browser/components/extensions/test/xpcshell/test_ext_browsingData_cookies_cache.js
@@ -78,16 +78,30 @@ add_task(async function testCache() {
 
   await testRemovalMethod("removeCache");
   await testRemovalMethod("remove");
 
   await extension.unload();
 });
 
 add_task(async function testCookies() {
+  // Above in setUpCookies we create an 'old' cookies, wait 10ms, then log a timestamp.
+  // Here we ask the browser to delete all cookies after the timestamp, with the intention
+  // that the 'old' cookie is not removed. The issue arises when the timer precision is
+  // low enough such that the timestamp that gets logged is the same as the 'old' cookie.
+  // We hardcode a precision value to ensure that there is time between the 'old' cookie
+  // and the timestamp generation.
+  Services.prefs.setBoolPref("privacy.reduceTimerPrecision", true);
+  Services.prefs.setIntPref("privacy.resistFingerprinting.reduceTimerPrecision.microseconds", 2000);
+
+  registerCleanupFunction(function() {
+    Services.prefs.clearUserPref("privacy.reduceTimerPrecision");
+    Services.prefs.clearUserPref("privacy.resistFingerprinting.reduceTimerPrecision.microseconds");
+  });
+
   function background() {
     browser.test.onMessage.addListener(async (msg, options) => {
       if (msg == "removeCookies") {
         await browser.browsingData.removeCookies(options);
       } else {
         await browser.browsingData.remove(options, {cookies: true});
       }
       browser.test.sendMessage("cookiesRemoved");
--- a/browser/extensions/formautofill/test/unit/test_addressRecords.js
+++ b/browser/extensions/formautofill/test/unit/test_addressRecords.js
@@ -249,16 +249,19 @@ const MERGE_TESTCASES = [
       "given-name": "Timothy",
       "street-address": "331 E. Evelyn Avenue\nLine2\nLine3",
       "tel": "+16509030800",
       country: "US",
     },
   },
 ];
 
+ChromeUtils.defineModuleGetter(this, "Preferences",
+                               "resource://gre/modules/Preferences.jsm");
+
 let do_check_record_matches = (recordWithMeta, record) => {
   for (let key in record) {
     Assert.equal(recordWithMeta[key], record[key]);
   }
 };
 
 add_task(async function test_initialize() {
   let profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME);
@@ -364,16 +367,26 @@ add_task(async function test_add() {
   Assert.throws(() => profileStorage.addresses.add({}),
     /Record contains no valid field\./);
 
   Assert.throws(() => profileStorage.addresses.add(TEST_ADDRESS_EMPTY_AFTER_NORMALIZE),
     /Record contains no valid field\./);
 });
 
 add_task(async function test_update() {
+  // Test assumes that when an entry is saved a second time, it's last modified date will
+  // be different from the first. With high values of precision reduction, we execute too
+  // fast for that to be true.
+  let timerPrecision = Preferences.get("privacy.reduceTimerPrecision");
+  Preferences.set("privacy.reduceTimerPrecision", false);
+
+  registerCleanupFunction(function() {
+    Preferences.set("privacy.reduceTimerPrecision", timerPrecision);
+  });
+
   let profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME,
                                                 [TEST_ADDRESS_1, TEST_ADDRESS_2]);
 
   let addresses = profileStorage.addresses.getAll();
   let guid = addresses[1].guid;
   let timeLastModified = addresses[1].timeLastModified;
 
   let onChanged = TestUtils.topicObserved(
--- a/browser/extensions/formautofill/test/unit/test_creditCardRecords.js
+++ b/browser/extensions/formautofill/test/unit/test_creditCardRecords.js
@@ -1,15 +1,17 @@
 /**
  * Tests FormAutofillStorage object with creditCards records.
  */
 
 "use strict";
 
 const {FormAutofillStorage} = ChromeUtils.import("resource://formautofill/FormAutofillStorage.jsm", {});
+ChromeUtils.defineModuleGetter(this, "Preferences",
+                               "resource://gre/modules/Preferences.jsm");
 
 const TEST_STORE_FILE_NAME = "test-credit-card.json";
 const COLLECTION_NAME = "creditCards";
 
 const TEST_CREDIT_CARD_1 = {
   "cc-name": "John Doe",
   "cc-number": "1234567812345678",
   "cc-exp-month": 4,
@@ -285,16 +287,26 @@ add_task(async function test_add() {
   Assert.throws(() => profileStorage.creditCards.add({}),
     /Record contains no valid field\./);
 
   Assert.throws(() => profileStorage.creditCards.add(TEST_CREDIT_CARD_EMPTY_AFTER_NORMALIZE),
     /Record contains no valid field\./);
 });
 
 add_task(async function test_update() {
+  // Test assumes that when an entry is saved a second time, it's last modified date will
+  // be different from the first. With high values of precision reduction, we execute too
+  // fast for that to be true.
+  let timerPrecision = Preferences.get("privacy.reduceTimerPrecision");
+  Preferences.set("privacy.reduceTimerPrecision", false);
+
+  registerCleanupFunction(function() {
+    Preferences.set("privacy.reduceTimerPrecision", timerPrecision);
+  });
+
   let path = getTempFile(TEST_STORE_FILE_NAME).path;
   await prepareTestCreditCards(path);
 
   let profileStorage = new FormAutofillStorage(path);
   await profileStorage.initialize();
 
   let creditCards = profileStorage.creditCards.getAll();
   let guid = creditCards[1].guid;
--- a/devtools/server/tests/unit/test_promises_object_creationtimestamp.js
+++ b/devtools/server/tests/unit/test_promises_object_creationtimestamp.js
@@ -6,17 +6,27 @@
  */
 
 "use strict";
 
 const { PromisesFront } = require("devtools/shared/fronts/promises");
 
 var EventEmitter = require("devtools/shared/event-emitter");
 
+ChromeUtils.defineModuleGetter(this, "Preferences",
+                               "resource://gre/modules/Preferences.jsm");
+
 add_task(function* () {
+  let timerPrecision = Preferences.get("privacy.reduceTimerPrecision");
+  Preferences.set("privacy.reduceTimerPrecision", false);
+
+  registerCleanupFunction(function () {
+    Preferences.set("privacy.reduceTimerPrecision", timerPrecision);
+  });
+
   let client = yield startTestDebuggerServer("promises-object-test");
   let chromeActors = yield getChromeActors(client);
 
   ok(Promise.toString().includes("native code"), "Expect native DOM Promise.");
 
   // We have to attach the chrome TabActor before playing with the PromiseActor
   yield attachTab(client, chromeActors);
   yield testPromiseCreationTimestamp(client, chromeActors, v => {
@@ -58,14 +68,15 @@ function* testPromiseCreationTimestamp(c
   let end = Date.now();
 
   let grip = yield onNewPromise;
   ok(grip, "Found our new promise.");
 
   let creationTimestamp = grip.promiseState.creationTimestamp;
 
   ok(start - 1 <= creationTimestamp && creationTimestamp <= end + 1,
-    "Expect promise creation timestamp to be within elapsed time range.");
+    "Expect promise creation timestamp to be within elapsed time range: " +
+     (start - 1) + " <= " + creationTimestamp + " <= " + (end + 1));
 
   yield front.detach();
   // Appease eslint
   void promise;
 }
--- a/netwerk/test/unit/test_race_cache_with_network.js
+++ b/netwerk/test/unit/test_race_cache_with_network.js
@@ -75,16 +75,31 @@ function run_test() {
   httpserver.registerPathHandler("/rcwn", test_handler);
   httpserver.registerPathHandler("/rcwn_cached", cached_handler);
   testGenerator.next();
   do_test_pending();
 }
 
 let testGenerator = testSteps();
 function *testSteps() {
+  /*
+   * In this test, we have a relatively low timeout of 200ms and an assertion that
+   * the timer works properly by checking that the time was greater than 200ms.
+   * With a timer precision of 100ms (for example) we will clamp downwards to 200
+   * and cause the assertion to fail. To resolve this, we hardcode a precision of
+   * 20ms.
+   */
+  Services.prefs.setBoolPref("privacy.reduceTimerPrecision", true);
+  Services.prefs.setIntPref("privacy.resistFingerprinting.reduceTimerPrecision.microseconds", 20000);
+
+  registerCleanupFunction(function() {
+    Services.prefs.clearUserPref("privacy.reduceTimerPrecision");
+    Services.prefs.clearUserPref("privacy.resistFingerprinting.reduceTimerPrecision.microseconds");
+  });
+
   // Initial request. Stores the response in the cache.
   var channel = make_channel("http://localhost:" + PORT + "/rcwn");
   channel.asyncOpen2(new ChannelListener(checkContent, null));
   yield undefined;
   equal(gResponseCounter, 1);
   equal(g200Counter, 1, "check number of 200 responses");
   equal(g304Counter, 0, "check number of 304 responses");
 
--- a/services/fxaccounts/tests/xpcshell/test_profile.js
+++ b/services/fxaccounts/tests/xpcshell/test_profile.js
@@ -255,16 +255,26 @@ add_test(function fetchAndCacheProfile_a
       Assert.equal(fxa.profileCache.profile.avatar, cachedUrl);
       run_next_test();
     });
 });
 
 // Check that a new profile request within PROFILE_FRESHNESS_THRESHOLD of the
 // last one doesn't kick off a new request to check the cached copy is fresh.
 add_task(async function fetchAndCacheProfileAfterThreshold() {
+  /*
+   * This test was observed to cause a timeout for... any timer precision reduction.
+   * Even 1 us. Exact reason is still undiagnosed.
+   */
+  Services.prefs.setBoolPref("privacy.reduceTimerPrecision", false);
+
+  registerCleanupFunction(async () => {
+    Services.prefs.clearUserPref("privacy.reduceTimerPrecision");
+  });
+
   let numFetches = 0;
   let client = mockClient(mockFxa());
   client.fetchProfile = async function() {
     numFetches += 1;
     return {body: {uid: ACCOUNT_UID, email: ACCOUNT_EMAIL, avatar: "myimg"}};
   };
   let profile = CreateFxAccountsProfile(null, client);
   profile.PROFILE_FRESHNESS_THRESHOLD = 1000;
--- a/services/sync/tests/unit/test_addons_engine.js
+++ b/services/sync/tests/unit/test_addons_engine.js
@@ -6,16 +6,17 @@
 ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
 ChromeUtils.import("resource://gre/modules/Preferences.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://services-common/async.js");
 ChromeUtils.import("resource://services-sync/addonsreconciler.js");
 ChromeUtils.import("resource://services-sync/engines/addons.js");
 ChromeUtils.import("resource://services-sync/service.js");
 ChromeUtils.import("resource://services-sync/util.js");
+ChromeUtils.defineModuleGetter(this, "Preferences", "resource://gre/modules/Preferences.jsm");
 
 const prefs = new Preferences();
 prefs.set("extensions.getAddons.get.url",
           "http://localhost:8888/search/guid:%IDS%");
 prefs.set("extensions.install.requireSecureOrigin", false);
 
 let engine;
 let reconciler;
@@ -85,16 +86,23 @@ add_task(async function test_find_dupe()
   dupe = await engine._findDupe(record);
   Assert.equal(null, dupe);
 
   await uninstallAddon(addon, reconciler);
   await resetReconciler();
 });
 
 add_task(async function test_get_changed_ids() {
+  let timerPrecision = Preferences.get("privacy.reduceTimerPrecision");
+  Preferences.set("privacy.reduceTimerPrecision", false);
+
+  registerCleanupFunction(function() {
+    Preferences.set("privacy.reduceTimerPrecision", timerPrecision);
+  });
+
   _("Ensure getChangedIDs() has the appropriate behavior.");
 
   _("Ensure getChangedIDs() returns an empty object by default.");
   let changes = await engine.getChangedIDs();
   Assert.equal("object", typeof(changes));
   Assert.equal(0, Object.keys(changes).length);
 
   _("Ensure tracker changes are populated.");
--- a/toolkit/components/extensions/test/xpcshell/test_ext_downloads_search.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_downloads_search.js
@@ -81,20 +81,22 @@ add_task(async function test_search() {
   function downloadPath(filename) {
     let path = downloadDir.clone();
     path.append(filename);
     return path.path;
   }
 
   Services.prefs.setIntPref("browser.download.folderList", 2);
   Services.prefs.setComplexValue("browser.download.dir", nsIFile, downloadDir);
+  Services.prefs.setBoolPref("privacy.reduceTimerPrecision", false);
 
   registerCleanupFunction(async () => {
     Services.prefs.clearUserPref("browser.download.folderList");
     Services.prefs.clearUserPref("browser.download.dir");
+    Services.prefs.clearUserPref("privacy.reduceTimerPrecision");
     await cleanupDir(downloadDir);
     await clearDownloads();
   });
 
   await clearDownloads().then(downloads => {
     info(`removed ${downloads.length} pre-existing downloads from history`);
   });
 
--- a/toolkit/components/places/tests/bookmarks/test_bookmarks_notifications.js
+++ b/toolkit/components/places/tests/bookmarks/test_bookmarks_notifications.js
@@ -1,11 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
+ChromeUtils.defineModuleGetter(this, "Preferences",
+                               "resource://gre/modules/Preferences.jsm");
+
 add_task(async function insert_separator_notification() {
   let observer = expectNotifications();
   let bm = await PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
                                                 parentGuid: PlacesUtils.bookmarks.unfiledGuid});
   let itemId = await PlacesUtils.promiseItemId(bm.guid);
   let parentId = await PlacesUtils.promiseItemId(bm.parentGuid);
   observer.check([ { name: "onItemAdded",
                      arguments: [ itemId, parentId, bm.index, bm.type,
@@ -103,16 +106,23 @@ add_task(async function insert_bookmark_
                      arguments: [ itemId, "tags", false, "",
                                   PlacesUtils.toPRTime(bm.lastModified),
                                   bm.type, parentId, bm.guid, bm.parentGuid, "",
                                   Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
                  ]);
 });
 
 add_task(async function update_bookmark_lastModified() {
+  let timerPrecision = Preferences.get("privacy.reduceTimerPrecision");
+  Preferences.set("privacy.reduceTimerPrecision", false);
+
+  registerCleanupFunction(function() {
+    Preferences.set("privacy.reduceTimerPrecision", timerPrecision);
+  });
+
   let bm = await PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
                                                 parentGuid: PlacesUtils.bookmarks.unfiledGuid,
                                                 url: new URL("http://lastmod.example.com/") });
   let observer = expectNotifications();
   bm = await PlacesUtils.bookmarks.update({ guid: bm.guid,
                                             lastModified: new Date() });
   let itemId = await PlacesUtils.promiseItemId(bm.guid);
   let parentId = await PlacesUtils.promiseItemId(bm.parentGuid);
--- a/toolkit/components/places/tests/bookmarks/test_keywords.js
+++ b/toolkit/components/places/tests/bookmarks/test_keywords.js
@@ -1,8 +1,11 @@
+ChromeUtils.defineModuleGetter(this, "Preferences",
+                               "resource://gre/modules/Preferences.jsm");
+
 const URI1 = NetUtil.newURI("http://test1.mozilla.org/");
 const URI2 = NetUtil.newURI("http://test2.mozilla.org/");
 const URI3 = NetUtil.newURI("http://test3.mozilla.org/");
 
 async function check_keyword(aURI, aKeyword) {
   if (aKeyword)
     aKeyword = aKeyword.toLowerCase();
 
@@ -75,16 +78,23 @@ add_task(function test_invalid_input() {
                 /NS_ERROR_ILLEGAL_VALUE/);
   Assert.throws(() => PlacesUtils.bookmarks.setKeywordForBookmark(null, "k"),
                 /NS_ERROR_ILLEGAL_VALUE/);
   Assert.throws(() => PlacesUtils.bookmarks.setKeywordForBookmark(0, "k"),
                 /NS_ERROR_ILLEGAL_VALUE/);
 });
 
 add_task(async function test_addBookmarkAndKeyword() {
+  let timerPrecision = Preferences.get("privacy.reduceTimerPrecision");
+  Preferences.set("privacy.reduceTimerPrecision", false);
+
+  registerCleanupFunction(function() {
+    Preferences.set("privacy.reduceTimerPrecision", timerPrecision);
+  });
+
   await check_keyword(URI1, null);
   let fc = await foreign_count(URI1);
   let observer = expectNotifications();
 
   let itemId =
     PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
                                          URI1,
                                          PlacesUtils.bookmarks.DEFAULT_INDEX,
@@ -123,16 +133,23 @@ add_task(async function test_addBookmark
   Assert.equal((await foreign_count(URI1)), fc + 1); // + 1 bookmark
 
   PlacesUtils.bookmarks.removeItem(itemId);
   await PlacesTestUtils.promiseAsyncUpdates();
   await check_orphans();
 });
 
 add_task(async function test_sameKeywordDifferentURI() {
+  let timerPrecision = Preferences.get("privacy.reduceTimerPrecision");
+  Preferences.set("privacy.reduceTimerPrecision", false);
+
+  registerCleanupFunction(function() {
+    Preferences.set("privacy.reduceTimerPrecision", timerPrecision);
+  });
+
   let fc1 = await foreign_count(URI1);
   let fc2 = await foreign_count(URI2);
   let observer = expectNotifications();
 
   let itemId =
     PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
                                          URI2,
                                          PlacesUtils.bookmarks.DEFAULT_INDEX,
--- a/toolkit/components/places/tests/unit/test_async_transactions.js
+++ b/toolkit/components/places/tests/unit/test_async_transactions.js
@@ -7,16 +7,19 @@
 const bmsvc    = PlacesUtils.bookmarks;
 const tagssvc  = PlacesUtils.tagging;
 const annosvc  = PlacesUtils.annotations;
 const PT       = PlacesTransactions;
 const rootGuid = PlacesUtils.bookmarks.rootGuid;
 const menuGuid = PlacesUtils.bookmarks.menuGuid;
 
 Components.utils.importGlobalProperties(["URL"]);
+ChromeUtils.defineModuleGetter(this, "Preferences",
+                               "resource://gre/modules/Preferences.jsm");
+
 
 // Create and add bookmarks observer.
 var observer = {
   __proto__: NavBookmarkObserver.prototype,
 
   tagRelatedGuids: new Set(),
 
   reset() {
@@ -1584,16 +1587,23 @@ add_task(async function test_copy() {
     await redo();
 
     // Cleanup. This also remove the original item.
     await PT.undo();
     observer.reset();
     await PT.clearTransactionsHistory();
   }
 
+  let timerPrecision = Preferences.get("privacy.reduceTimerPrecision");
+  Preferences.set("privacy.reduceTimerPrecision", false);
+
+  registerCleanupFunction(function() {
+    Preferences.set("privacy.reduceTimerPrecision", timerPrecision);
+  });
+
   // Test duplicating leafs (bookmark, separator, empty folder)
   PT.NewBookmark({ url: new URL("http://test.item.duplicate"),
                    parentGuid: rootGuid,
                    annos: [{ name: "Anno", value: "AnnoValue"}] });
   let sepTxn = PT.NewSeparator({ parentGuid: rootGuid, index: 1 });
   let livemarkTxn = PT.NewLivemark(
     { feedUrl: new URL("http://test.feed.uri"),
       parentGuid: rootGuid,
--- a/toolkit/components/places/tests/unit/test_keywords.js
+++ b/toolkit/components/places/tests/unit/test_keywords.js
@@ -1,10 +1,13 @@
 "use strict";
 
+ChromeUtils.defineModuleGetter(this, "Preferences",
+                               "resource://gre/modules/Preferences.jsm");
+
 async function check_keyword(aExpectExists, aHref, aKeyword, aPostData = null) {
   // Check case-insensitivity.
   aKeyword = aKeyword.toUpperCase();
 
   let entry = await PlacesUtils.keywords.fetch(aKeyword);
 
   Assert.deepEqual(entry, await PlacesUtils.keywords.fetch({ keyword: aKeyword }));
 
@@ -170,16 +173,23 @@ add_task(async function test_addKeyword(
   await check_keyword(true, "http://example.com/", "keyword");
   await PlacesUtils.keywords.remove("keyword");
   await check_keyword(false, "http://example.com/", "keyword");
 
   await check_no_orphans();
 });
 
 add_task(async function test_addBookmarkAndKeyword() {
+  let timerPrecision = Preferences.get("privacy.reduceTimerPrecision");
+  Preferences.set("privacy.reduceTimerPrecision", false);
+
+  registerCleanupFunction(function() {
+    Preferences.set("privacy.reduceTimerPrecision", timerPrecision);
+  });
+
   await check_keyword(false, "http://example.com/", "keyword");
   let fc = await foreign_count("http://example.com/");
   let bookmark = await PlacesUtils.bookmarks.insert({ url: "http://example.com/",
                                                       parentGuid: PlacesUtils.bookmarks.unfiledGuid });
 
   let observer = expectBookmarkNotifications();
   await PlacesUtils.keywords.insert({ keyword: "keyword", url: "http://example.com/" });
 
--- a/toolkit/components/places/tests/unit/test_sync_utils.js
+++ b/toolkit/components/places/tests/unit/test_sync_utils.js
@@ -1,11 +1,13 @@
 ChromeUtils.import("resource://gre/modules/ObjectUtils.jsm");
 ChromeUtils.import("resource://gre/modules/PlacesSyncUtils.jsm");
 ChromeUtils.import("resource://testing-common/httpd.js");
+ChromeUtils.defineModuleGetter(this, "Preferences",
+                               "resource://gre/modules/Preferences.jsm");
 Cu.importGlobalProperties(["URLSearchParams"]);
 
 const DESCRIPTION_ANNO = "bookmarkProperties/description";
 const LOAD_IN_SIDEBAR_ANNO = "bookmarkProperties/loadInSidebar";
 const SYNC_PARENT_ANNO = "sync/parent";
 
 var makeGuid = PlacesUtils.history.makeGuid;
 
@@ -2804,16 +2806,23 @@ add_task(async function test_remove_part
     greatGrandChildNextSiblingBmk.recordId,
   ], "Should move descendants to closest living ancestor");
 
   await PlacesUtils.bookmarks.eraseEverything();
   await PlacesSyncUtils.bookmarks.reset();
 });
 
 add_task(async function test_migrateOldTrackerEntries() {
+  let timerPrecision = Preferences.get("privacy.reduceTimerPrecision");
+  Preferences.set("privacy.reduceTimerPrecision", false);
+
+  registerCleanupFunction(function() {
+    Preferences.set("privacy.reduceTimerPrecision", timerPrecision);
+  });
+
   let unknownBmk = await PlacesUtils.bookmarks.insert({
     parentGuid: PlacesUtils.bookmarks.menuGuid,
     url: "http://getfirefox.com",
     title: "Get Firefox!",
   });
   let newBmk = await PlacesUtils.bookmarks.insert({
     parentGuid: PlacesUtils.bookmarks.menuGuid,
     url: "http://getthunderbird.com",
--- a/toolkit/components/satchel/test/unit/test_notify.js
+++ b/toolkit/components/satchel/test/unit/test_notify.js
@@ -1,16 +1,17 @@
 /*
  * Test suite for satchel notifications
  *
  * Tests notifications dispatched when modifying form history.
  *
  */
 
 ChromeUtils.defineModuleGetter(this, "setTimeout", "resource://gre/modules/Timer.jsm");
+ChromeUtils.defineModuleGetter(this, "Preferences", "resource://gre/modules/Preferences.jsm");
 
 const TestObserver = {
   observed: [],
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
   observe(subject, topic, data) {
     if (subject instanceof Ci.nsISupportsString) {
       subject = subject.toString();
     }
@@ -129,16 +130,23 @@ add_task(async function removeEntriesFor
   count = await promiseCountEntries(null, null);
   Assert.equal(count, 2, "the other entries are still there");
 
   // Clean-up
   await promiseUpdateEntry("remove", null, null);
 });
 
 add_task(async function removeEntriesByTimeframe() {
+  let timerPrecision = Preferences.get("privacy.reduceTimerPrecision");
+  Preferences.set("privacy.reduceTimerPrecision", false);
+
+  registerCleanupFunction(function() {
+    Preferences.set("privacy.reduceTimerPrecision", timerPrecision);
+  });
+
   await promiseAddEntry(entry1[0], entry1[1]);
   await promiseAddEntry(entry2[0], entry2[1]);
 
   const cutoffDate = Date.now();
   // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
   await new Promise(res => setTimeout(res, 10));
 
   await promiseAddEntry(entry3[0], entry3[1]);