diff options
Diffstat (limited to 'addon-sdk/source/test/test-observers.js')
-rw-r--r-- | addon-sdk/source/test/test-observers.js | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/addon-sdk/source/test/test-observers.js b/addon-sdk/source/test/test-observers.js new file mode 100644 index 000000000..4f15a87f1 --- /dev/null +++ b/addon-sdk/source/test/test-observers.js @@ -0,0 +1,183 @@ +/* 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/. */ +"use strict"; + +const { Loader } = require("sdk/test/loader"); +const { isWeak, WeakReference } = require("sdk/core/reference"); +const { subscribe, unsubscribe, + observe, Observer } = require("sdk/core/observer"); +const { Class } = require("sdk/core/heritage"); + +const { Cc, Ci, Cu } = require("chrome"); +const { notifyObservers } = Cc["@mozilla.org/observer-service;1"]. + getService(Ci.nsIObserverService); +const { defer } = require("sdk/core/promise"); + +const message = x => ({wrappedJSObject: x}); + +exports["test subscribe unsubscribe"] = assert => { + const topic = Date.now().toString(32); + const Subscriber = Class({ + extends: Observer, + initialize: function(observe) { + this.observe = observe; + } + }); + observe.define(Subscriber, (x, subject, _, data) => + x.observe(subject.wrappedJSObject.x)); + + let xs = []; + const x = Subscriber((...rest) => xs.push(...rest)); + + let ys = []; + const y = Subscriber((...rest) => ys.push(...rest)); + + const publish = (topic, data) => + notifyObservers(message(data), topic, null); + + publish({x:0}); + + subscribe(x, topic); + + publish(topic, {x:1}); + + subscribe(y, topic); + + publish(topic, {x:2}); + publish(topic + "!", {x: 2.5}); + + unsubscribe(x, topic); + + publish(topic, {x:3}); + + subscribe(y, topic); + + publish(topic, {x:4}); + + subscribe(x, topic); + + publish(topic, {x:5}); + + unsubscribe(x, topic); + unsubscribe(y, topic); + + publish(topic, {x:6}); + + assert.deepEqual(xs, [1, 2, 5]); + assert.deepEqual(ys, [2, 3, 4, 5]); +} + +exports["test weak observers are GC-ed on unload"] = (assert, end) => { + const topic = Date.now().toString(32); + const loader = Loader(module); + const { Observer, observe, + subscribe, unsubscribe } = loader.require("sdk/core/observer"); + const { isWeak, WeakReference } = loader.require("sdk/core/reference"); + + const MyObserver = Class({ + extends: Observer, + initialize: function(observe) { + this.observe = observe; + } + }); + observe.define(MyObserver, (x, ...rest) => x.observe(...rest)); + + const MyWeakObserver = Class({ + extends: MyObserver, + implements: [WeakReference] + }); + + let xs = []; + let ys = []; + let x = new MyObserver((subject, topic, data) => { + xs.push(subject.wrappedJSObject, topic, data); + }); + let y = new MyWeakObserver((subject, topic, data) => { + ys.push(subject.wrappedJSObject, topic, data); + }); + + subscribe(x, topic); + subscribe(y, topic); + + + notifyObservers(message({ foo: 1 }), topic, null); + x = null; + y = null; + loader.unload(); + + Cu.schedulePreciseGC(() => { + + notifyObservers(message({ bar: 2 }), topic, ":)"); + + assert.deepEqual(xs, [{ foo: 1 }, topic, null, + { bar: 2 }, topic, ":)"], + "non week observer is kept"); + + assert.deepEqual(ys, [{ foo: 1 }, topic, null], + "week observer was GC-ed"); + + end(); + }); +}; + +exports["test weak observer unsubscribe"] = function*(assert) { + const loader = Loader(module); + const { Observer, observe, subscribe, unsubscribe } = loader.require("sdk/core/observer"); + const { WeakReference } = loader.require("sdk/core/reference"); + + let sawNotification = false; + let firstWait = defer(); + let secondWait = defer(); + + const WeakObserver = Class({ + extends: Observer, + implements: [WeakReference], + observe: function() { + sawNotification = true; + firstWait.resolve(); + } + }); + + const StrongObserver = Class({ + extends: Observer, + observe: function() { + secondWait.resolve(); + } + }); + + observe.define(Observer, (x, ...rest) => x.observe(...rest)); + + let weakObserver = new WeakObserver; + let strongObserver = new StrongObserver(); + subscribe(weakObserver, "test-topic"); + subscribe(strongObserver, "test-wait"); + + notifyObservers(null, "test-topic", null); + yield firstWait.promise; + + assert.ok(sawNotification, "Should have seen notification before GC"); + sawNotification = false; + + yield loader.require("sdk/test/memory").gc(); + + notifyObservers(null, "test-topic", null); + notifyObservers(null, "test-wait", null); + yield secondWait.promise; + + assert.ok(sawNotification, "Should have seen notification after GC"); + sawNotification = false; + + try { + unsubscribe(weakObserver, "test-topic"); + unsubscribe(strongObserver, "test-wait"); + assert.pass("Should not have seen an exception"); + } + catch (e) { + assert.fail("Should not have seen an exception"); + } + + loader.unload(); +}; + +require("sdk/test").run(exports); |