Blame services/sync/tests/unit/test_history_tracker.js

Packit f0b94e
/* Any copyright is dedicated to the Public Domain.
Packit f0b94e
   http://creativecommons.org/publicdomain/zero/1.0/ */
Packit f0b94e
Packit f0b94e
ChromeUtils.import("resource://gre/modules/PlacesDBUtils.jsm");
Packit f0b94e
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
Packit f0b94e
ChromeUtils.import("resource://services-common/utils.js");
Packit f0b94e
ChromeUtils.import("resource://services-sync/engines.js");
Packit f0b94e
ChromeUtils.import("resource://services-sync/constants.js");
Packit f0b94e
ChromeUtils.import("resource://services-sync/engines/history.js");
Packit f0b94e
ChromeUtils.import("resource://services-sync/service.js");
Packit f0b94e
ChromeUtils.import("resource://services-sync/util.js");
Packit f0b94e
Packit f0b94e
let engine;
Packit f0b94e
let tracker;
Packit f0b94e
Packit f0b94e
add_task(async function setup() {
Packit f0b94e
Packit f0b94e
  await Service.engineManager.clear();
Packit f0b94e
  await Service.engineManager.register(HistoryEngine);
Packit f0b94e
  engine = Service.engineManager.get("history");
Packit f0b94e
  tracker = engine._tracker;
Packit f0b94e
Packit f0b94e
  // Don't write out by default.
Packit f0b94e
  tracker.persistChangedIDs = false;
Packit f0b94e
});
Packit f0b94e
Packit f0b94e
async function verifyTrackerEmpty() {
Packit f0b94e
  let changes = await engine.pullNewChanges();
Packit f0b94e
  do_check_empty(changes);
Packit f0b94e
  equal(tracker.score, 0);
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
async function verifyTrackedCount(expected) {
Packit f0b94e
  let changes = await engine.pullNewChanges();
Packit f0b94e
  do_check_attribute_count(changes, expected);
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
async function verifyTrackedItems(tracked) {
Packit f0b94e
  let changes = await engine.pullNewChanges();
Packit f0b94e
  let trackedIDs = new Set(Object.keys(changes));
Packit f0b94e
  for (let guid of tracked) {
Packit f0b94e
    ok(guid in changes, `${guid} should be tracked`);
Packit f0b94e
    ok(changes[guid] > 0, `${guid} should have a modified time`);
Packit f0b94e
    trackedIDs.delete(guid);
Packit f0b94e
  }
Packit f0b94e
  equal(trackedIDs.size, 0, `Unhandled tracked IDs: ${
Packit f0b94e
    JSON.stringify(Array.from(trackedIDs))}`);
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
async function resetTracker() {
Packit f0b94e
  await tracker.clearChangedIDs();
Packit f0b94e
  tracker.resetScore();
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
async function cleanup() {
Packit f0b94e
  await PlacesUtils.history.clear();
Packit f0b94e
  await resetTracker();
Packit f0b94e
  await tracker.stop();
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
add_task(async function test_empty() {
Packit f0b94e
  _("Verify we've got an empty, disabled tracker to work with.");
Packit f0b94e
  await verifyTrackerEmpty();
Packit f0b94e
  Assert.ok(!tracker._isTracking);
Packit f0b94e
Packit f0b94e
  await cleanup();
Packit f0b94e
});
Packit f0b94e
Packit f0b94e
add_task(async function test_not_tracking() {
Packit f0b94e
  _("Create history item. Won't show because we haven't started tracking yet");
Packit f0b94e
  await addVisit("not_tracking");
Packit f0b94e
  await verifyTrackerEmpty();
Packit f0b94e
Packit f0b94e
  await cleanup();
Packit f0b94e
});
Packit f0b94e
Packit f0b94e
add_task(async function test_start_tracking() {
Packit f0b94e
  _("Add hook for save completion.");
Packit f0b94e
  let savePromise = new Promise((resolve, reject) => {
Packit f0b94e
    tracker.persistChangedIDs = true;
Packit f0b94e
    let save = tracker._storage._save;
Packit f0b94e
    tracker._storage._save = async function() {
Packit f0b94e
      try {
Packit f0b94e
        await save.call(this);
Packit f0b94e
        resolve();
Packit f0b94e
      } catch (ex) {
Packit f0b94e
        reject(ex);
Packit f0b94e
      } finally {
Packit f0b94e
        // Turn this back off.
Packit f0b94e
        tracker.persistChangedIDs = false;
Packit f0b94e
        tracker._storage._save = save;
Packit f0b94e
      }
Packit f0b94e
    };
Packit f0b94e
  });
Packit f0b94e
Packit f0b94e
  _("Tell the tracker to start tracking changes.");
Packit f0b94e
  tracker.start();
Packit f0b94e
  let scorePromise = promiseOneObserver("weave:engine:score:updated");
Packit f0b94e
  await addVisit("start_tracking");
Packit f0b94e
  await scorePromise;
Packit f0b94e
Packit f0b94e
  _("Score updated in test_start_tracking.");
Packit f0b94e
  await verifyTrackedCount(1);
Packit f0b94e
  Assert.equal(tracker.score, SCORE_INCREMENT_SMALL);
Packit f0b94e
Packit f0b94e
  await savePromise;
Packit f0b94e
Packit f0b94e
  _("changedIDs written to disk. Proceeding.");
Packit f0b94e
  await cleanup();
Packit f0b94e
});
Packit f0b94e
Packit f0b94e
add_task(async function test_start_tracking_twice() {
Packit f0b94e
  _("Verifying preconditions.");
Packit f0b94e
  tracker.start();
Packit f0b94e
  await addVisit("start_tracking_twice1");
Packit f0b94e
  await verifyTrackedCount(1);
Packit f0b94e
  Assert.equal(tracker.score, SCORE_INCREMENT_SMALL);
Packit f0b94e
Packit f0b94e
  _("Notifying twice won't do any harm.");
Packit f0b94e
  tracker.start();
Packit f0b94e
  let scorePromise = promiseOneObserver("weave:engine:score:updated");
Packit f0b94e
  await addVisit("start_tracking_twice2");
Packit f0b94e
  await scorePromise;
Packit f0b94e
Packit f0b94e
  _("Score updated in test_start_tracking_twice.");
Packit f0b94e
  await verifyTrackedCount(2);
Packit f0b94e
  Assert.equal(tracker.score, 2 * SCORE_INCREMENT_SMALL);
Packit f0b94e
Packit f0b94e
  await cleanup();
Packit f0b94e
});
Packit f0b94e
Packit f0b94e
add_task(async function test_track_delete() {
Packit f0b94e
  _("Deletions are tracked.");
Packit f0b94e
Packit f0b94e
  // This isn't present because we weren't tracking when it was visited.
Packit f0b94e
  await addVisit("track_delete");
Packit f0b94e
  let uri = CommonUtils.makeURI("http://getfirefox.com/track_delete");
Packit f0b94e
  let guid = await engine._store.GUIDForUri(uri.spec);
Packit f0b94e
  await verifyTrackerEmpty();
Packit f0b94e
Packit f0b94e
  tracker.start();
Packit f0b94e
  let visitRemovedPromise = promiseVisit("removed", uri);
Packit f0b94e
  let scorePromise = promiseOneObserver("weave:engine:score:updated");
Packit f0b94e
  await PlacesUtils.history.remove(uri);
Packit f0b94e
  await Promise.all([scorePromise, visitRemovedPromise]);
Packit f0b94e
Packit f0b94e
  await verifyTrackedItems([guid]);
Packit f0b94e
  Assert.equal(tracker.score, SCORE_INCREMENT_XLARGE);
Packit f0b94e
Packit f0b94e
  await cleanup();
Packit f0b94e
});
Packit f0b94e
Packit f0b94e
add_task(async function test_dont_track_expiration() {
Packit f0b94e
  _("Expirations are not tracked.");
Packit f0b94e
  let uriToRemove = await addVisit("to_remove");
Packit f0b94e
  let guidToRemove = await engine._store.GUIDForUri(uriToRemove.spec);
Packit f0b94e
Packit f0b94e
  await resetTracker();
Packit f0b94e
  await verifyTrackerEmpty();
Packit f0b94e
Packit f0b94e
  tracker.start();
Packit f0b94e
  let visitRemovedPromise = promiseVisit("removed", uriToRemove);
Packit f0b94e
  let scorePromise = promiseOneObserver("weave:engine:score:updated");
Packit f0b94e
Packit f0b94e
  // Observe expiration.
Packit f0b94e
  Services.obs.addObserver(function onExpiration(aSubject, aTopic, aData) {
Packit f0b94e
    Services.obs.removeObserver(onExpiration, aTopic);
Packit f0b94e
    // Remove the remaining page to update its score.
Packit f0b94e
    PlacesUtils.history.remove(uriToRemove);
Packit f0b94e
  }, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
Packit f0b94e
Packit f0b94e
  // Force expiration of 1 entry.
Packit f0b94e
  Services.prefs.setIntPref("places.history.expiration.max_pages", 0);
Packit f0b94e
  Cc["@mozilla.org/places/expiration;1"]
Packit f0b94e
    .getService(Ci.nsIObserver)
Packit f0b94e
    .observe(null, "places-debug-start-expiration", 1);
Packit f0b94e
Packit f0b94e
  await Promise.all([scorePromise, visitRemovedPromise]);
Packit f0b94e
  await verifyTrackedItems([guidToRemove]);
Packit f0b94e
Packit f0b94e
  await cleanup();
Packit f0b94e
});
Packit f0b94e
Packit f0b94e
add_task(async function test_stop_tracking() {
Packit f0b94e
  _("Let's stop tracking again.");
Packit f0b94e
  await tracker.stop();
Packit f0b94e
  await addVisit("stop_tracking");
Packit f0b94e
  await verifyTrackerEmpty();
Packit f0b94e
Packit f0b94e
  await cleanup();
Packit f0b94e
});
Packit f0b94e
Packit f0b94e
add_task(async function test_stop_tracking_twice() {
Packit f0b94e
  await tracker.stop();
Packit f0b94e
  await addVisit("stop_tracking_twice1");
Packit f0b94e
Packit f0b94e
  _("Notifying twice won't do any harm.");
Packit f0b94e
  await tracker.stop();
Packit f0b94e
  await addVisit("stop_tracking_twice2");
Packit f0b94e
  await verifyTrackerEmpty();
Packit f0b94e
Packit f0b94e
  await cleanup();
Packit f0b94e
});
Packit f0b94e
Packit f0b94e
add_task(async function test_filter_file_uris() {
Packit f0b94e
  tracker.start();
Packit f0b94e
Packit f0b94e
  let uri = CommonUtils.makeURI("file:///Users/eoger/tps/config.json");
Packit f0b94e
  let visitAddedPromise = promiseVisit("added", uri);
Packit f0b94e
  await PlacesTestUtils.addVisits({
Packit f0b94e
    uri,
Packit f0b94e
    visitDate: Date.now() * 1000,
Packit f0b94e
    transition: PlacesUtils.history.TRANSITION_LINK
Packit f0b94e
  });
Packit f0b94e
  await visitAddedPromise;
Packit f0b94e
Packit f0b94e
  await verifyTrackerEmpty();
Packit f0b94e
  await tracker.stop();
Packit f0b94e
  await cleanup();
Packit f0b94e
});
Packit f0b94e
Packit f0b94e
add_task(async function test_filter_hidden() {
Packit f0b94e
  tracker.start();
Packit f0b94e
Packit f0b94e
  _("Add visit; should be hidden by the redirect");
Packit f0b94e
  let hiddenURI = await addVisit("hidden");
Packit f0b94e
  let hiddenGUID = await engine._store.GUIDForUri(hiddenURI.spec);
Packit f0b94e
  _(`Hidden visit GUID: ${hiddenGUID}`);
Packit f0b94e
Packit f0b94e
  _("Add redirect visit; should be tracked");
Packit f0b94e
  let trackedURI = await addVisit("redirect", hiddenURI.spec,
Packit f0b94e
    PlacesUtils.history.TRANSITION_REDIRECT_PERMANENT);
Packit f0b94e
  let trackedGUID = await engine._store.GUIDForUri(trackedURI.spec);
Packit f0b94e
  _(`Tracked visit GUID: ${trackedGUID}`);
Packit f0b94e
Packit f0b94e
  _("Add visit for framed link; should be ignored");
Packit f0b94e
  let embedURI = await addVisit("framed_link", null,
Packit f0b94e
    PlacesUtils.history.TRANSITION_FRAMED_LINK);
Packit f0b94e
  let embedGUID = await engine._store.GUIDForUri(embedURI.spec);
Packit f0b94e
  _(`Framed link visit GUID: ${embedGUID}`);
Packit f0b94e
Packit f0b94e
  _("Run Places maintenance to mark redirect visit as hidden");
Packit f0b94e
  await PlacesDBUtils.maintenanceOnIdle();
Packit f0b94e
Packit f0b94e
  await verifyTrackedItems([trackedGUID]);
Packit f0b94e
Packit f0b94e
  await cleanup();
Packit f0b94e
});