// This is testing the frankenstein situation Sync forces Places into.
// Sync does runInBatchMode() and before the callback returns the Places async
// APIs are used (either by Sync itself, or by any other code in the system)
// As seen in bug 1197856 and bug 1190131.

Cu.import("resource://gre/modules/PlacesUtils.jsm");

// This function "waits" for a promise to resolve by spinning a nested event
// loop.
function waitForPromise(promise) {
  let tm = Cc["@mozilla.org/thread-manager;1"].getService();

  let finalResult, finalException;

  promise.then(result => {
    finalResult = result;
  }, err => {
    finalException = err;
  });

  // Keep waiting until our callback is triggered (unless the app is quitting).
  tm.spinEventLoopUntil(() => finalResult || finalException);

  if (finalException) {
    throw finalException;
  }
  return finalResult;
}

add_test(function() {
  let testCompleted = false;
  PlacesUtils.bookmarks.runInBatchMode({
    runBatched() {
      // create a bookmark.
      let info = { parentGuid: PlacesUtils.bookmarks.unfiledGuid,
                   type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
                   url: "http://example.com/" };
      let insertPromise = PlacesUtils.bookmarks.insert(info);
      let bookmark = waitForPromise(insertPromise);
      // Check we got a bookmark (bookmark creation failed completely in
      // bug 1190131)
      equal(bookmark.url, info.url);
      // Check the promiseItemGuid and promiseItemId helpers - failure in these
      // was the underlying reason for the failure.
      let id = waitForPromise(PlacesUtils.promiseItemId(bookmark.guid));
      let guid = waitForPromise(PlacesUtils.promiseItemGuid(id));
      equal(guid, bookmark.guid, "id and guid round-tripped correctly");
      testCompleted = true;
    }
  }, null);
  // make sure we tested what we think we tested.
  ok(testCompleted);
  run_next_test();
});
