aboutsummaryrefslogtreecommitdiff
path: root/tools/addon-sdk-1.5/packages/api-utils/tests/test-unload.js
blob: e05b4e09b7a38c19f5072310c1597b778f99048b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

var unload = require("unload");
var { Loader } = require("./helpers");

exports.testUnloading = function(test) {
  var loader = Loader(module);
  var ul = loader.require("unload");
  var unloadCalled = 0;
  var errorsReported = 0;
  function unload() {
    unloadCalled++;
    throw new Error("error");
  }
  ul.when(unload);

  // This should be ignored, as we already registered it
  ul.when(unload);

  function unload2() { unloadCalled++; }
  ul.when(unload2);
  loader.unload(undefined, function onError() { errorsReported++; });
  test.assertEqual(unloadCalled, 2,
                   "Unloader functions are called on unload.");
  test.assertEqual(errorsReported, 1,
                   "One unload handler threw exception");
};

exports.testEnsure = function(test) {
  test.assertRaises(function() { unload.ensure({}); },
                    "object has no 'unload' property",
                    "passing obj with no unload prop should fail");
  test.assertRaises(function() { unload.ensure({}, "destroy"); },
                    "object has no 'destroy' property",
                    "passing obj with no custom unload prop should fail");

  var called = 0;
  var obj = {unload: function() { called++; }};

  unload.ensure(obj);
  obj.unload();
  test.assertEqual(called, 1,
                   "unload() should be called");
  obj.unload();
  test.assertEqual(called, 1,
                   "unload() should be called only once");
};

/**
 * Check that destructors are called only once with Traits.
 * - check that public API is calling the destructor and unregister it,
 * - check that composed traits with multiple ensure calls, leads to only
 * one destructor call.
 */
exports.testEnsureWithTraits = function(test) {

  let { Trait } = require("traits");
  let loader = Loader(module);
  let ul = loader.require("unload");

  let called = 0;
  let composedCalled = 0;
  let composedTrait = Trait.compose({
      constructor: function () {
        // We have to give "public interface" of this trait, as we want to
        // call public `unload` method and ensure that we call it only once,
        // either when we call this public function manually or on add-on unload
        ul.ensure(this._public);
      },
      unload: function unload() {
        composedCalled++;
      }
    });
  let obj = Trait.compose(
    composedTrait.resolve({
      constructor: "_constructor",
      unload : "_unload" 
    }), {
      constructor: function constructor() {
        // Same thing applies here, we need to pass public interface
        ul.ensure(this._public);
        this._constructor();
      },
      unload: function unload() {
        called++;
        this._unload();
      }
    })();

  obj.unload();
  test.assertEqual(called, 1,
                   "unload() should be called");

  test.assertEqual(composedCalled, 1,
                   "composed object unload() should be called");

  obj.unload();
  test.assertEqual(called, 1,
                   "unload() should be called only once");
  test.assertEqual(composedCalled, 1,
                   "composed object unload() should be called only once");

  loader.unload();
  test.assertEqual(called, 1,
                   "unload() should be called only once, after addon unload");
  test.assertEqual(composedCalled, 1,
                   "composed object unload() should be called only once, " +
                   "after addon unload");
};

exports.testEnsureWithTraitsPrivate = function(test) {

  let { Trait } = require("traits");
  let loader = Loader(module);
  let ul = loader.require("unload");

  let called = 0;
  let privateObj = null;
  let obj = Trait.compose({
      constructor: function constructor() {
        // This time wa don't have to give public interface,
        // as we want to call a private method:
        ul.ensure(this, "_unload");
        privateObj = this;
      },
      _unload: function unload() {
        called++;
        this._unload();
      }
    })();

  loader.unload();
  test.assertEqual(called, 1,
                   "unload() should be called");

  privateObj._unload();
  test.assertEqual(called, 1,
                   "_unload() should be called only once, after addon unload");
};

exports.testReason = function (test) {
  var reason = "Reason doesn't actually have to be anything in particular.";
  var loader = Loader(module);
  var ul = loader.require("unload");
  ul.when(function (rsn) {
    test.assertEqual(rsn, reason,
                     "when() reason should be reason given to loader");
  });
  var obj = {
    unload: function (rsn) {
      test.assertEqual(rsn, reason,
                       "ensure() reason should be reason given to loader");
    }
  };
  ul.ensure(obj);
  loader.unload(reason);
};