Bug 1274394 - Run the bookmark validator after each phase of TPS tests r?markh draft
authorThom Chiovoloni <tchiovoloni@mozilla.com>
Thu, 19 May 2016 16:54:37 -0400
changeset 371007 03e55d9d1fab4fea89c6dc7dc6c8c01ae9aac5c2
parent 371006 5c66fb81be682bf7602a8a7b8655186cbeaed1d2
child 521877 18b652c182d0f618639a2429fd188ae8c7f64d01
push id19197
push userbmo:tchiovoloni@mozilla.com
push dateWed, 25 May 2016 18:25:46 +0000
reviewersmarkh
bugs1274394
milestone49.0a1
Bug 1274394 - Run the bookmark validator after each phase of TPS tests r?markh MozReview-Commit-ID: 9WH965qdhAE
services/sync/tps/extensions/tps/resource/tps.jsm
--- a/services/sync/tps/extensions/tps/resource/tps.jsm
+++ b/services/sync/tps/extensions/tps/resource/tps.jsm
@@ -13,21 +13,22 @@ const {classes: Cc, interfaces: Ci, util
 
 var module = this;
 
 // Global modules
 Cu.import("resource://gre/modules/Log.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/AppConstants.jsm");
+Cu.import("resource://gre/modules/PlacesUtils.jsm");
 Cu.import("resource://services-common/async.js");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/main.js");
 Cu.import("resource://services-sync/util.js");
-
+Cu.import("resource://services-sync/bookmark_validator.js");
 // TPS modules
 Cu.import("resource://tps/logger.jsm");
 
 // Module wrappers for tests
 Cu.import("resource://tps/modules/addons.jsm");
 Cu.import("resource://tps/modules/bookmarks.jsm");
 Cu.import("resource://tps/modules/forms.jsm");
 Cu.import("resource://tps/modules/history.jsm");
@@ -578,20 +579,85 @@ var TPS = {
       }, 2000, this, "postmozmilltest");
     }
   },
 
   MozmillSetTestListener: function TPS__MozmillSetTestListener(obj) {
     Logger.logInfo("mozmill setTest: " + obj.name);
   },
 
+
+
+  /**
+   * Use Sync's bookmark validation code to see if we've corrupted the tree.
+   */
+  ValidateBookmarks: function TPS__ValidateBookmarks() {
+
+    let getServerBookmarkState = () => {
+      let bookmarkEngine = Weave.Service.engineManager.get('bookmarks');
+      let collection = bookmarkEngine._itemSource();
+      let collectionKey = bookmarkEngine.service.collectionKeys.keyForCollection(bookmarkEngine.name);
+      collection.full = true;
+      let items = [];
+      collection.recordHandler = function(item) {
+        item.decrypt(collectionKey);
+        items.push(item.cleartext);
+      };
+      collection.get();
+      return items;
+    };
+    let serverRecordDumpStr;
+    try {
+      Logger.logInfo("About to perform bookmark validation");
+      let clientTree = Async.promiseSpinningly(PlacesUtils.promiseBookmarksTree("", {
+        includeItemIds: true
+      }));
+      let serverRecords = getServerBookmarkState();
+      // We can't wait until catch to stringify this, since at that point it will have cycles.
+      serverRecordDumpStr = JSON.stringify(serverRecords);
+
+      let validator = new BookmarkValidator();
+      let {problemData} = validator.compareServerWithClient(serverRecords, clientTree);
+
+      for (let {name, count} of problemData.getSummary()) {
+        if (name === "serverUnexpected" && problemData.serverUnexpected.indexOf("mobile") >= 0) {
+          // Exclude this hackily so that we don't report this every time until
+          // we figure out what to do with it. See bug 1273234 and 1274394 for
+          // more information.
+
+          // Decrement count so that we still report other "serverUnexpected" errors,
+          // and log the 'correct' number of them when we do.
+          --count;
+        }
+        if (count) {
+          // Log this out before we assert. This is useful in the context of TPS logs, since we
+          // can see the IDs in the test files.
+          Logger.logInfo(`Validation problem: "${name}": ${JSON.stringify(problemData[name])}`);
+        }
+        Logger.AssertEqual(count, 0, `Bookmark validation error of type ${name}`);
+      }
+    } catch (e) {
+      // Dump the client records (should always be doable)
+      DumpBookmarks();
+      // Dump the server records if gotten them already.
+      if (serverRecordDumpStr) {
+        Logger.logInfo("Server bookmark records:\n" + serverRecordDumpStr + "\n");
+      }
+      this.DumpError("Bookmark validation failed", e);
+    }
+    Logger.logInfo("Bookmark validation finished");
+  },
+
   RunNextTestAction: function() {
     try {
       if (this._currentAction >=
           this._phaselist["phase" + this._currentPhase].length) {
+
+        // Run bookmark validation and then finish up
+        this.ValidateBookmarks();
         // we're all done
         Logger.logInfo("test phase " + this._currentPhase + ": " +
                        (this._errors ? "FAIL" : "PASS"));
         this._phaseFinished = true;
         this.quit();
         return;
       }