dom/base/test/test_domrequesthelper.xul

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 <?xml version="1.0"?>
     2 <!--
     3   Any copyright is dedicated to the Public Domain.
     4   http://creativecommons.org/publicdomain/zero/1.0/
     5 -->
     6 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
     7 <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
     9 <window title="DOMRequestHelper Test"
    10         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
    11         onload="start();">
    13   <script type="application/javascript"
    14           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
    16   <script type="application/javascript">
    17   <![CDATA[
    18     const Cc = Components.classes;
    19     const Cu = Components.utils;
    20     const Ci = Components.interfaces;
    21     Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
    22     let obs = Cc["@mozilla.org/observer-service;1"].
    23               getService(Ci.nsIObserverService);
    25     function DummyHelperSubclass() {
    26       this.onuninit = null;
    27     }
    28     DummyHelperSubclass.prototype = {
    29       __proto__: DOMRequestIpcHelper.prototype,
    30       uninit: function() {
    31         if (typeof this.onuninit === "function") {
    32           this.onuninit();
    33         }
    34         this.onuninit = null;
    35       }
    36     };
    38     var dummy = new DummyHelperSubclass();
    40     /**
    41      * Init & destroy.
    42      */
    43     function initDOMRequestHelperTest(aMessages) {
    44       is(dummy._requests, undefined, "Request is undefined");
    45       is(dummy._messages, undefined, "Messages is undefined");
    46       is(dummy._window, undefined, "Window is undefined");
    48       dummy.initDOMRequestHelper(window, aMessages);
    50       ok(dummy._window, "Window exists");
    51       is(dummy._window, window, "Correct window");
    52       if (aMessages) {
    53         is(typeof dummy._listeners, "object", "Listeners is an object");
    54       }
    55     }
    57     function destroyDOMRequestHelperTest() {
    58       dummy.destroyDOMRequestHelper();
    60       is(dummy._requests, undefined, "Request is undefined");
    61       is(dummy._messages, undefined, "Messages is undefined");
    62       is(dummy._window, undefined, "Window is undefined");
    63     }
    65     /**
    66      * Message listeners.
    67      */
    68     function checkMessageListeners(aExpectedListeners, aCount) {
    69       ok(true, "Checking message listeners\n" + "Expected listeners " +
    70          JSON.stringify(aExpectedListeners) + " \nExpected count " + aCount);
    71       let count = 0;
    72       Object.keys(dummy._listeners).forEach(function(name) {
    73         count++;
    74         is(aExpectedListeners[name], dummy._listeners[name],
    75            "Message found " + name + " - Same listeners");
    76       });
    77       is(aCount, count, "Correct number of listeners");
    78     }
    80     function addMessageListenersTest(aMessages, aExpectedListeners, aCount) {
    81       dummy.addMessageListeners(aMessages);
    82       ok(true, JSON.stringify(dummy._listeners));
    83       checkMessageListeners(aExpectedListeners, aCount);
    84     }
    86     function removeMessageListenersTest(aMessages, aExpectedListeners, aCount) {
    87       dummy.removeMessageListeners(aMessages);
    88       checkMessageListeners(aExpectedListeners, aCount);
    89     }
    91     /**
    92      * Utility function to test window destruction behavior.  In general this
    93      * function does the following:
    94      *
    95      *  1) Create a new iframe
    96      *  2) Create a new DOMRequestHelper
    97      *  3) initDOMRequestHelper(), optionally with weak or strong listeners
    98      *  4) Optionally force a garbage collection to reap weak references
    99      *  5) Destroy the iframe triggering an inner-window-destroyed event
   100      *  6) Callback with a boolean indicating if DOMRequestHelper.uninit() was
   101      *     called.
   102      *
   103      * Example usage:
   104      *
   105      *    checkWindowDestruction({ messages: ["foo"], gc: true },
   106      *                           function(uninitCalled) {
   107      *      // expect uninitCalled === false since GC with only weak refs
   108      *    });
   109      */
   110     const TOPIC = "inner-window-destroyed";
   111     function checkWindowDestruction(aOptions, aCallback) {
   112       aOptions = aOptions || {};
   113       aOptions.messages = aOptions.messages || [];
   114       aOptions.gc = !!aOptions.gc;
   116       if (typeof aCallback !== "function") {
   117         aCallback = function() { };
   118       }
   120       let uninitCalled = false;
   122       // Use a secondary observer so we know when to expect the uninit().  We
   123       // can then reasonably expect uninitCalled to be set properly on the
   124       // next tick.
   125       let observer = {
   126         observe: function(aSubject, aTopic, aData) {
   127           if (aTopic !== TOPIC) {
   128             return;
   129           }
   130           obs.removeObserver(observer, TOPIC);
   131           setTimeout(function() {
   132             aCallback(uninitCalled);
   133           });
   134         }
   135       };
   137       let frame = document.createElement("iframe");
   138       frame.onload = function() {
   139         obs.addObserver(observer, TOPIC, false);
   140         // Create dummy DOMRequestHelper specific to checkWindowDestruction()
   141         let cwdDummy = new DummyHelperSubclass();
   142         cwdDummy.onuninit = function() {
   143           uninitCalled = true;
   144         };
   145         cwdDummy.initDOMRequestHelper(frame.contentWindow, aOptions.messages);
   146         // Make sure to clear our strong ref here so that we can test our
   147         // weak reference listeners and observer.
   148         cwdDummy = null;
   149         if (aOptions.gc) {
   150           Cu.schedulePreciseGC(function() {
   151             SpecialPowers.DOMWindowUtils.cycleCollect();
   152             SpecialPowers.DOMWindowUtils.garbageCollect();
   153             SpecialPowers.DOMWindowUtils.garbageCollect();
   154             document.documentElement.removeChild(frame);
   155           });
   156           return;
   157         }
   158         document.documentElement.removeChild(frame);
   159       };
   160       document.documentElement.appendChild(frame);
   161     }
   163     /**
   164      * Test steps.
   165      */
   166     var tests = [
   167       function() {
   168         ok(true, "== InitDOMRequestHelper no messages");
   169         initDOMRequestHelperTest(null);
   170         next();
   171       },
   172       function() {
   173         ok(true, "== DestroyDOMRequestHelper");
   174         destroyDOMRequestHelperTest();
   175         next();
   176       },
   177       function() {
   178         ok(true, "== InitDOMRequestHelper empty array");
   179         initDOMRequestHelperTest([]);
   180         checkMessageListeners({}, 0);
   181         next();
   182       },
   183       function() {
   184         ok(true, "== DestroyDOMRequestHelper");
   185         destroyDOMRequestHelperTest();
   186         next();
   187       },
   188       function() {
   189         ok(true, "== InitDOMRequestHelper with strings array");
   190         initDOMRequestHelperTest(["name1", "nameN"]);
   191         checkMessageListeners({"name1": false, "nameN": false}, 2);
   192         next();
   193       },
   194       function() {
   195         ok(true, "== DestroyDOMRequestHelper");
   196         destroyDOMRequestHelperTest();
   197         next();
   198       },
   199       function() {
   200         ok(true, "== InitDOMRequestHelper with objects array");
   201         initDOMRequestHelperTest([{
   202           name: "name1",
   203           weakRef: false
   204         }, {
   205           name: "nameN",
   206           weakRef: true
   207         }]);
   208         checkMessageListeners({"name1": false, "nameN": true}, 2);
   209         next();
   210       },
   211       function() {
   212         ok(true, "== AddMessageListeners empty array");
   213         addMessageListenersTest([], {"name1": false, "nameN": true}, 2);
   214         next();
   215       },
   216       function() {
   217         ok(true, "== AddMessageListeners null");
   218         addMessageListenersTest(null, {"name1": false, "nameN": true}, 2);
   219         next();
   220       },
   221       function() {
   222         ok(true, "== AddMessageListeners new listener, string only");
   223         addMessageListenersTest("name2", {
   224           "name1": false,
   225           "name2": false,
   226           "nameN": true
   227         }, 3);
   228         next();
   229       },
   230       function() {
   231         ok(true, "== AddMessageListeners new listeners, strings array");
   232         addMessageListenersTest(["name3", "name4"], {
   233           "name1": false,
   234           "name2": false,
   235           "name3": false,
   236           "name4": false,
   237           "nameN": true
   238         }, 5);
   239         next();
   240       },
   241       function() {
   242         ok(true, "== AddMessageListeners new listeners, objects array");
   243         addMessageListenersTest([{
   244           name: "name5",
   245           weakRef: true
   246         }, {
   247           name: "name6",
   248           weakRef: false
   249         }], {
   250           "name1": false,
   251           "name2": false,
   252           "name3": false,
   253           "name4": false,
   254           "name5": true,
   255           "name6": false,
   256           "nameN": true
   257         }, 7);
   258         next();
   259       },
   260       function() {
   261         ok(true, "== RemoveMessageListeners, null");
   262         removeMessageListenersTest(null, {
   263           "name1": false,
   264           "name2": false,
   265           "name3": false,
   266           "name4": false,
   267           "name5": true,
   268           "name6": false,
   269           "nameN": true
   270         }, 7);
   271         next();
   272       },
   273       function() {
   274         ok(true, "== RemoveMessageListeners, one message");
   275         removeMessageListenersTest("name1", {
   276           "name2": false,
   277           "name3": false,
   278           "name4": false,
   279           "name5": true,
   280           "name6": false,
   281           "nameN": true
   282         }, 6);
   283         next();
   284       },
   285       function() {
   286         ok(true, "== RemoveMessageListeners, array of messages");
   287         removeMessageListenersTest(["name2", "name3"], {
   288           "name4": false,
   289           "name5": true,
   290           "name6": false,
   291           "nameN": true
   292         }, 4);
   293         next();
   294       },
   295       function() {
   296         ok(true, "== RemoveMessageListeners, unknown message");
   297         removeMessageListenersTest("unknown", {
   298           "name4": false,
   299           "name5": true,
   300           "name6": false,
   301           "nameN": true
   302         }, 4);
   303         next();
   304       },
   305       function() {
   306         try {
   307           ok(true, "== AddMessageListeners, same message, same kind");
   308           addMessageListenersTest("name4", {
   309             "name4": false,
   310             "name5": true,
   311             "name6": false,
   312             "nameN": true
   313           }, 4);
   314           next();
   315         } catch (ex) {
   316           ok(false, "Unexpected exception " + ex);
   317         }
   318       },
   319       function() {
   320         ok(true, "== AddMessageListeners, same message, different kind");
   321         try {
   322           addMessageListenersTest({name: "name4", weakRef: true}, {
   323             "name4": true,
   324             "name5": true,
   325             "name6": false,
   326             "nameN": true
   327           }, 4);
   328           ok(false, "Should have thrown an exception");
   329         } catch (ex) {
   330           ok(true, "Expected exception");
   331           next();
   332         }
   333       },
   334       function() {
   335         ok(true, "== Test createRequest()");
   336         ok(DOMRequest, "DOMRequest object exists");
   337         var req = dummy.createRequest();
   338         ok(req instanceof DOMRequest, "Returned a DOMRequest");
   339         next();
   340       },
   341       function() {
   342         ok(true, "== Test getRequestId(), removeRequest() and getRequest()");
   343         var req = dummy.createRequest();
   344         var id = dummy.getRequestId(req);
   345         is(typeof id, "string", "id is a string");
   346         var req_ = dummy.getRequest(id);
   347         is(req, req_, "Got correct request");
   348         dummy.removeRequest(id);
   349         req = dummy.getRequest(id);
   350         is(req, null, "No request");
   351         next();
   352       },
   353       function() {
   354         ok(true, "== Test createPromise()");
   355         ok(Promise, "Promise object exists");
   356         var promise = dummy.createPromise(function(resolve, reject) {
   357           resolve(true);
   358         });
   359         ok(promise instanceof Promise, "Returned a Promise");
   360         promise.then(next);
   361       },
   362       function() {
   363         ok(true, "== Test getResolver()");
   364         var id;
   365         var resolver;
   366         var promise = dummy.createPromise(function(resolve, reject) {
   367           var r = { resolve: resolve, reject: reject };
   368           id = dummy.getPromiseResolverId(r);
   369           resolver = r;
   370           ok(typeof id === "string", "id is a string");
   371           r.resolve(true);
   372         }).then(function(unused) {
   373           var r = dummy.getPromiseResolver(id);
   374           ok(resolver === r, "Get succeeded");
   375           next();
   376         });
   377       },
   378       function() {
   379         ok(true, "== Test removeResolver");
   380         var id;
   381         var promise = dummy.createPromise(function(resolve, reject) {
   382           var r = { resolve: resolve, reject: reject };
   383           id = dummy.getPromiseResolverId(r);
   384           ok(typeof id === "string", "id is a string");
   386           var resolver = dummy.getPromiseResolver(id);
   387           ok(true, "Got resolver " + JSON.stringify(resolver));
   388           ok(resolver === r, "Resolver get succeeded");
   390           r.resolve(true);
   391         }).then(function(unused) {
   392           dummy.removePromiseResolver(id);
   393           var resolver = dummy.getPromiseResolver(id);
   394           ok(resolver === undefined, "removeResolver: get failed");
   395           next();
   396         });
   397       },
   398       function() {
   399         ok(true, "== Test takeResolver");
   400         var id;
   401         var resolver;
   402         var promise = dummy.createPromise(function(resolve, reject) {
   403           var r = { resolve: resolve, reject: reject };
   404           id = dummy.getPromiseResolverId(r);
   405           resolver = r;
   406           ok(typeof id === "string", "id is a string");
   408           var gotR = dummy.getPromiseResolver(id);
   409           ok(gotR === r, "resolver get succeeded");
   411           r.resolve(true);
   412         }).then(function(unused) {
   413           var r = dummy.takePromiseResolver(id);
   414           ok(resolver === r, "take should succeed");
   416           r = dummy.getPromiseResolver(id);
   417           ok(r === undefined, "takeResolver: get failed");
   418           next();
   419         });
   420       },
   421       function() {
   422         ok(true, "== Test window destroyed without messages and without GC");
   423         checkWindowDestruction({ gc: false }, function(uninitCalled) {
   424           ok(uninitCalled, "uninit() should have been called");
   425           next();
   426         });
   427       },
   428       function() {
   429         ok(true, "== Test window destroyed without messages and with GC");
   430         checkWindowDestruction({ gc: true }, function(uninitCalled) {
   431           ok(!uninitCalled, "uninit() should NOT have been called");
   432           next();
   433         });
   434       },
   435       function() {
   436         ok(true, "== Test window destroyed with weak messages and without GC");
   437         checkWindowDestruction({ messages: [{ name: "foo", weakRef: true }],
   438                                  gc: false }, function(uninitCalled) {
   439           ok(uninitCalled, "uninit() should have been called");
   440           next();
   441         });
   442       },
   443       function() {
   444         ok(true, "== Test window destroyed with weak messages and with GC");
   445         checkWindowDestruction({ messages: [{ name: "foo", weakRef: true }],
   446                                  gc: true }, function(uninitCalled) {
   447           ok(!uninitCalled, "uninit() should NOT have been called");
   448           next();
   449         });
   450       },
   451       function() {
   452         ok(true, "== Test window destroyed with strong messages and without GC");
   453         checkWindowDestruction({ messages: [{ name: "foo", weakRef: false }],
   454                                  gc: false }, function(uninitCalled) {
   455           ok(uninitCalled, "uninit() should have been called");
   456           next();
   457         });
   458       },
   459       function() {
   460         ok(true, "== Test window destroyed with strong messages and with GC");
   461         checkWindowDestruction({ messages: [{ name: "foo", weakRef: false }],
   462                                  gc: true }, function(uninitCalled) {
   463           ok(uninitCalled, "uninit() should have been called");
   464           next();
   465         });
   466       }
   467     ];
   469     function next() {
   470       if (!tests.length) {
   471         SimpleTest.finish();
   472         return;
   473       }
   475       var test = tests.shift();
   476       test();
   477     }
   479     function start() {
   480       SimpleTest.waitForExplicitFinish();
   481       next();
   482     }
   483   ]]>
   484   </script>
   486   <body xmlns="http://www.w3.org/1999/xhtml">
   487     <p id="display"></p>
   488     <div id="content" style="display: none"></div>
   489     <pre id="test"></pre>
   490   </body>
   491 </window>

mercurial