1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/services/sync/tests/unit/test_history_tracker.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,204 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 + 1.7 +Cu.import("resource://gre/modules/PlacesUtils.jsm"); 1.8 +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 1.9 +Cu.import("resource://services-sync/engines.js"); 1.10 +Cu.import("resource://services-sync/constants.js"); 1.11 +Cu.import("resource://services-sync/engines/history.js"); 1.12 +Cu.import("resource://services-sync/service.js"); 1.13 +Cu.import("resource://services-sync/util.js"); 1.14 + 1.15 +function onScoreUpdated(callback) { 1.16 + Svc.Obs.add("weave:engine:score:updated", function observer() { 1.17 + Svc.Obs.remove("weave:engine:score:updated", observer); 1.18 + try { 1.19 + callback(); 1.20 + } catch (ex) { 1.21 + do_throw(ex); 1.22 + } 1.23 + }); 1.24 +} 1.25 + 1.26 +Service.engineManager.clear(); 1.27 +Service.engineManager.register(HistoryEngine); 1.28 +let engine = Service.engineManager.get("history"); 1.29 +let tracker = engine._tracker; 1.30 + 1.31 +// Don't write out by default. 1.32 +tracker.persistChangedIDs = false; 1.33 + 1.34 +let _counter = 0; 1.35 +function addVisit() { 1.36 + let uriString = "http://getfirefox.com/" + _counter++; 1.37 + let uri = Utils.makeURI(uriString); 1.38 + _("Adding visit for URI " + uriString); 1.39 + let place = { 1.40 + uri: uri, 1.41 + visits: [ { 1.42 + visitDate: Date.now() * 1000, 1.43 + transitionType: PlacesUtils.history.TRANSITION_LINK 1.44 + } ] 1.45 + }; 1.46 + 1.47 + let cb = Async.makeSpinningCallback(); 1.48 + PlacesUtils.asyncHistory.updatePlaces(place, { 1.49 + handleError: function () { 1.50 + _("Error adding visit for " + uriString); 1.51 + cb(new Error("Error adding history entry")); 1.52 + }, 1.53 + 1.54 + handleResult: function () { 1.55 + }, 1.56 + 1.57 + handleCompletion: function () { 1.58 + _("Added visit for " + uriString); 1.59 + cb(); 1.60 + } 1.61 + }); 1.62 + 1.63 + // Spin the event loop to embed this async call in a sync API. 1.64 + cb.wait(); 1.65 + return uri; 1.66 +} 1.67 + 1.68 +function run_test() { 1.69 + initTestLogging("Trace"); 1.70 + Log.repository.getLogger("Sync.Tracker.History").level = Log.Level.Trace; 1.71 + run_next_test(); 1.72 +} 1.73 + 1.74 +add_test(function test_empty() { 1.75 + _("Verify we've got an empty, disabled tracker to work with."); 1.76 + do_check_empty(tracker.changedIDs); 1.77 + do_check_eq(tracker.score, 0); 1.78 + do_check_false(tracker._isTracking); 1.79 + run_next_test(); 1.80 +}); 1.81 + 1.82 +add_test(function test_not_tracking(next) { 1.83 + _("Create history item. Won't show because we haven't started tracking yet"); 1.84 + addVisit(); 1.85 + Utils.nextTick(function() { 1.86 + do_check_empty(tracker.changedIDs); 1.87 + do_check_eq(tracker.score, 0); 1.88 + run_next_test(); 1.89 + }); 1.90 +}); 1.91 + 1.92 +add_test(function test_start_tracking() { 1.93 + _("Add hook for save completion."); 1.94 + tracker.persistChangedIDs = true; 1.95 + tracker.onSavedChangedIDs = function () { 1.96 + _("changedIDs written to disk. Proceeding."); 1.97 + // Turn this back off. 1.98 + tracker.persistChangedIDs = false; 1.99 + delete tracker.onSavedChangedIDs; 1.100 + run_next_test(); 1.101 + }; 1.102 + 1.103 + _("Tell the tracker to start tracking changes."); 1.104 + onScoreUpdated(function() { 1.105 + _("Score updated in test_start_tracking."); 1.106 + do_check_attribute_count(tracker.changedIDs, 1); 1.107 + do_check_eq(tracker.score, SCORE_INCREMENT_SMALL); 1.108 + }); 1.109 + 1.110 + Svc.Obs.notify("weave:engine:start-tracking"); 1.111 + addVisit(); 1.112 +}); 1.113 + 1.114 +add_test(function test_start_tracking_twice() { 1.115 + _("Verifying preconditions from test_start_tracking."); 1.116 + do_check_attribute_count(tracker.changedIDs, 1); 1.117 + do_check_eq(tracker.score, SCORE_INCREMENT_SMALL); 1.118 + 1.119 + _("Notifying twice won't do any harm."); 1.120 + onScoreUpdated(function() { 1.121 + _("Score updated in test_start_tracking_twice."); 1.122 + do_check_attribute_count(tracker.changedIDs, 2); 1.123 + do_check_eq(tracker.score, 2 * SCORE_INCREMENT_SMALL); 1.124 + run_next_test(); 1.125 + }); 1.126 + 1.127 + Svc.Obs.notify("weave:engine:start-tracking"); 1.128 + addVisit(); 1.129 +}); 1.130 + 1.131 +add_test(function test_track_delete() { 1.132 + _("Deletions are tracked."); 1.133 + 1.134 + // This isn't present because we weren't tracking when it was visited. 1.135 + let uri = Utils.makeURI("http://getfirefox.com/0"); 1.136 + let guid = engine._store.GUIDForUri(uri); 1.137 + do_check_false(guid in tracker.changedIDs); 1.138 + 1.139 + onScoreUpdated(function() { 1.140 + do_check_true(guid in tracker.changedIDs); 1.141 + do_check_attribute_count(tracker.changedIDs, 3); 1.142 + do_check_eq(tracker.score, SCORE_INCREMENT_XLARGE + 2 * SCORE_INCREMENT_SMALL); 1.143 + run_next_test(); 1.144 + }); 1.145 + 1.146 + do_check_eq(tracker.score, 2 * SCORE_INCREMENT_SMALL); 1.147 + PlacesUtils.history.removePage(uri); 1.148 +}); 1.149 + 1.150 +add_test(function test_dont_track_expiration() { 1.151 + _("Expirations are not tracked."); 1.152 + let uriToExpire = addVisit(); 1.153 + let guidToExpire = engine._store.GUIDForUri(uriToExpire); 1.154 + let uriToRemove = addVisit(); 1.155 + let guidToRemove = engine._store.GUIDForUri(uriToRemove); 1.156 + 1.157 + tracker.clearChangedIDs(); 1.158 + do_check_false(guidToExpire in tracker.changedIDs); 1.159 + do_check_false(guidToRemove in tracker.changedIDs); 1.160 + 1.161 + onScoreUpdated(function() { 1.162 + do_check_false(guidToExpire in tracker.changedIDs); 1.163 + do_check_true(guidToRemove in tracker.changedIDs); 1.164 + do_check_attribute_count(tracker.changedIDs, 1); 1.165 + run_next_test(); 1.166 + }); 1.167 + 1.168 + // Observe expiration. 1.169 + Services.obs.addObserver(function onExpiration(aSubject, aTopic, aData) { 1.170 + Services.obs.removeObserver(onExpiration, aTopic); 1.171 + // Remove the remaining page to update its score. 1.172 + PlacesUtils.history.removePage(uriToRemove); 1.173 + }, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false); 1.174 + 1.175 + // Force expiration of 1 entry. 1.176 + Services.prefs.setIntPref("places.history.expiration.max_pages", 0); 1.177 + Cc["@mozilla.org/places/expiration;1"] 1.178 + .getService(Ci.nsIObserver) 1.179 + .observe(null, "places-debug-start-expiration", 1); 1.180 +}); 1.181 + 1.182 +add_test(function test_stop_tracking() { 1.183 + _("Let's stop tracking again."); 1.184 + tracker.clearChangedIDs(); 1.185 + Svc.Obs.notify("weave:engine:stop-tracking"); 1.186 + addVisit(); 1.187 + Utils.nextTick(function() { 1.188 + do_check_empty(tracker.changedIDs); 1.189 + run_next_test(); 1.190 + }); 1.191 +}); 1.192 + 1.193 +add_test(function test_stop_tracking_twice() { 1.194 + _("Notifying twice won't do any harm."); 1.195 + Svc.Obs.notify("weave:engine:stop-tracking"); 1.196 + addVisit(); 1.197 + Utils.nextTick(function() { 1.198 + do_check_empty(tracker.changedIDs); 1.199 + run_next_test(); 1.200 + }); 1.201 +}); 1.202 + 1.203 +add_test(function cleanup() { 1.204 + _("Clean up."); 1.205 + PlacesUtils.history.removeAllPages(); 1.206 + run_next_test(); 1.207 +});