1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/addon-sdk/source/test/test-unload.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,161 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + "use strict"; 1.8 + 1.9 +var unload = require("sdk/system/unload"); 1.10 +var { Loader, LoaderWithHookedConsole } = require("sdk/test/loader"); 1.11 + 1.12 +exports.testUnloading = function(assert) { 1.13 + let { loader, messages } = LoaderWithHookedConsole(module); 1.14 + var ul = loader.require("sdk/system/unload"); 1.15 + var unloadCalled = 0; 1.16 + function unload() { 1.17 + unloadCalled++; 1.18 + throw new Error("error"); 1.19 + } 1.20 + ul.when(unload); 1.21 + 1.22 + // This should be ignored, as we already registered it 1.23 + ul.when(unload); 1.24 + 1.25 + function unload2() { unloadCalled++; } 1.26 + ul.when(unload2); 1.27 + loader.unload(); 1.28 + assert.equal(unloadCalled, 2, 1.29 + "Unloader functions are called on unload."); 1.30 + assert.equal(messages.length, 1, 1.31 + "One unload handler threw exception 1/2"); 1.32 + assert.equal(messages[0].type, "exception", 1.33 + "One unload handler threw exception 2/2"); 1.34 +}; 1.35 + 1.36 +exports.testEnsure = function(assert) { 1.37 + assert.throws(function() { unload.ensure({}); }, 1.38 + /object has no 'unload' property/, 1.39 + "passing obj with no unload prop should fail"); 1.40 + assert.throws(function() { unload.ensure({}, "destroy"); }, 1.41 + /object has no 'destroy' property/, 1.42 + "passing obj with no custom unload prop should fail"); 1.43 + 1.44 + var called = 0; 1.45 + var obj = {unload: function() { called++; }}; 1.46 + 1.47 + unload.ensure(obj); 1.48 + obj.unload(); 1.49 + assert.equal(called, 1, 1.50 + "unload() should be called"); 1.51 + obj.unload(); 1.52 + assert.equal(called, 1, 1.53 + "unload() should be called only once"); 1.54 +}; 1.55 + 1.56 +/** 1.57 + * Check that destructors are called only once with Traits. 1.58 + * - check that public API is calling the destructor and unregister it, 1.59 + * - check that composed traits with multiple ensure calls, leads to only 1.60 + * one destructor call. 1.61 + */ 1.62 +exports.testEnsureWithTraits = function(assert) { 1.63 + let { Trait } = require("sdk/deprecated/traits"); 1.64 + let loader = Loader(module); 1.65 + let ul = loader.require("sdk/system/unload"); 1.66 + 1.67 + let called = 0; 1.68 + let composedCalled = 0; 1.69 + let composedTrait = Trait.compose({ 1.70 + constructor: function () { 1.71 + // We have to give "public interface" of this trait, as we want to 1.72 + // call public `unload` method and ensure that we call it only once, 1.73 + // either when we call this public function manually or on add-on unload 1.74 + ul.ensure(this._public); 1.75 + }, 1.76 + unload: function unload() { 1.77 + composedCalled++; 1.78 + } 1.79 + }); 1.80 + let obj = Trait.compose( 1.81 + composedTrait.resolve({ 1.82 + constructor: "_constructor", 1.83 + unload : "_unload" 1.84 + }), { 1.85 + constructor: function constructor() { 1.86 + // Same thing applies here, we need to pass public interface 1.87 + ul.ensure(this._public); 1.88 + this._constructor(); 1.89 + }, 1.90 + unload: function unload() { 1.91 + called++; 1.92 + this._unload(); 1.93 + } 1.94 + })(); 1.95 + 1.96 + obj.unload(); 1.97 + assert.equal(called, 1, 1.98 + "unload() should be called"); 1.99 + 1.100 + assert.equal(composedCalled, 1, 1.101 + "composed object unload() should be called"); 1.102 + 1.103 + obj.unload(); 1.104 + assert.equal(called, 1, 1.105 + "unload() should be called only once"); 1.106 + assert.equal(composedCalled, 1, 1.107 + "composed object unload() should be called only once"); 1.108 + 1.109 + loader.unload(); 1.110 + assert.equal(called, 1, 1.111 + "unload() should be called only once, after addon unload"); 1.112 + assert.equal(composedCalled, 1, 1.113 + "composed object unload() should be called only once, " + 1.114 + "after addon unload"); 1.115 +}; 1.116 + 1.117 +exports.testEnsureWithTraitsPrivate = function(assert) { 1.118 + let { Trait } = require("sdk/deprecated/traits"); 1.119 + let loader = Loader(module); 1.120 + let ul = loader.require("sdk/system/unload"); 1.121 + 1.122 + let called = 0; 1.123 + let privateObj = null; 1.124 + let obj = Trait.compose({ 1.125 + constructor: function constructor() { 1.126 + // This time wa don't have to give public interface, 1.127 + // as we want to call a private method: 1.128 + ul.ensure(this, "_unload"); 1.129 + privateObj = this; 1.130 + }, 1.131 + _unload: function unload() { 1.132 + called++; 1.133 + this._unload(); 1.134 + } 1.135 + })(); 1.136 + 1.137 + loader.unload(); 1.138 + assert.equal(called, 1, 1.139 + "unload() should be called"); 1.140 + 1.141 + privateObj._unload(); 1.142 + assert.equal(called, 1, 1.143 + "_unload() should be called only once, after addon unload"); 1.144 +}; 1.145 + 1.146 +exports.testReason = function (assert) { 1.147 + var reason = "Reason doesn't actually have to be anything in particular."; 1.148 + var loader = Loader(module); 1.149 + var ul = loader.require("sdk/system/unload"); 1.150 + ul.when(function (rsn) { 1.151 + assert.equal(rsn, reason, 1.152 + "when() reason should be reason given to loader"); 1.153 + }); 1.154 + var obj = { 1.155 + unload: function (rsn) { 1.156 + assert.equal(rsn, reason, 1.157 + "ensure() reason should be reason given to loader"); 1.158 + } 1.159 + }; 1.160 + ul.ensure(obj); 1.161 + loader.unload(reason); 1.162 +}; 1.163 + 1.164 +require("sdk/test").run(exports);