1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/addon-sdk/source/test/test-system-input-output.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,319 @@ 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 + 1.10 +const { id: addonID, name: addonName } = require("sdk/self"); 1.11 +const { Cc, Ci, Cu } = require("chrome"); 1.12 +const { Loader, LoaderWithHookedConsole2 } = require("sdk/test/loader"); 1.13 +const { InputPort } = require("sdk/input/system"); 1.14 +const { OutputPort } = require("sdk/output/system"); 1.15 + 1.16 +const { removeObserver, addObserver, 1.17 + notifyObservers } = Cc["@mozilla.org/observer-service;1"]. 1.18 + getService(Ci.nsIObserverService); 1.19 + 1.20 +const { lift, start, stop, send } = require("sdk/event/utils"); 1.21 + 1.22 +const isConsoleEvent = topic => 1.23 + ["console-api-log-event", 1.24 + "console-storage-cache-event"].indexOf(topic) >= 0; 1.25 + 1.26 +const message = x => ({wrappedJSObject: {data: x}}); 1.27 + 1.28 +exports["test start / stop ports"] = assert => { 1.29 + const input = new InputPort({ id: Date.now().toString(32), initial: {data:0} }); 1.30 + const topic = input.topic; 1.31 + 1.32 + assert.ok(topic.contains(addonID), "topics are namespaced to add-on"); 1.33 + 1.34 + const xs = lift(({data}) => "x:" + data, input); 1.35 + const ys = lift(({data}) => "y:" + data, input); 1.36 + 1.37 + assert.deepEqual(input.value, {data:0}, "initila value is set"); 1.38 + assert.deepEqual(xs.value, "x:0", "initial value is mapped"); 1.39 + assert.deepEqual(ys.value, "y:0", "initial value is mapped"); 1.40 + 1.41 + notifyObservers(message(1), topic, null); 1.42 + 1.43 + assert.deepEqual(input.value, {data:0}, "no message received on input port"); 1.44 + assert.deepEqual(xs.value, "x:0", "no message received on xs"); 1.45 + assert.deepEqual(ys.value, "y:0", "no message received on ys"); 1.46 + 1.47 + start(xs); 1.48 + 1.49 + 1.50 + notifyObservers(message(2), topic, null); 1.51 + 1.52 + assert.deepEqual(input.value, {data:2}, "message received on input port"); 1.53 + assert.deepEqual(xs.value, "x:2", "message received on xs"); 1.54 + assert.deepEqual(ys.value, "y:2", "no message received on (not started) ys"); 1.55 + 1.56 + 1.57 + notifyObservers(message(3), topic, null); 1.58 + 1.59 + 1.60 + assert.deepEqual(input.value, {data:3}, "message received on input port"); 1.61 + assert.deepEqual(xs.value, "x:3", "message received on xs"); 1.62 + assert.deepEqual(ys.value, "y:3", "message received on ys"); 1.63 + 1.64 + 1.65 + notifyObservers(message(4), topic, null); 1.66 + 1.67 + assert.deepEqual(input.value, {data:4}, "message received on input port"); 1.68 + assert.deepEqual(xs.value, "x:4", "message not received on (stopped) xs"); 1.69 + assert.deepEqual(ys.value, "y:4", "message received on ys"); 1.70 + 1.71 + 1.72 + stop(input); 1.73 + 1.74 + notifyObservers(message(5), topic, null); 1.75 + 1.76 + assert.deepEqual(input.value, {data:4}, "message note received on input port"); 1.77 + assert.deepEqual(xs.value, "x:4", "message not received on (stopped) xs"); 1.78 + assert.deepEqual(ys.value, "y:4", "message not received on (stopped) ys"); 1.79 +}; 1.80 + 1.81 +exports["test send messages to nsIObserverService"] = assert => { 1.82 + let messages = []; 1.83 + 1.84 + const { newURI } = Cc['@mozilla.org/network/io-service;1']. 1.85 + getService(Ci.nsIIOService); 1.86 + 1.87 + const output = new OutputPort({ id: Date.now().toString(32), sync: true }); 1.88 + const topic = output.topic; 1.89 + 1.90 + const observer = { 1.91 + QueryInterface: function() { 1.92 + return this; 1.93 + }, 1.94 + observe: (subject, topic, data) => { 1.95 + // Ignores internal console events 1.96 + if (!isConsoleEvent(topic)) { 1.97 + messages.push({ 1.98 + topic: topic, 1.99 + subject: subject 1.100 + }); 1.101 + } 1.102 + } 1.103 + }; 1.104 + 1.105 + addObserver(observer, topic, false); 1.106 + 1.107 + send(output, null); 1.108 + assert.deepEqual(messages.shift(), { topic: topic, subject: null }, 1.109 + "null message received"); 1.110 + 1.111 + 1.112 + const uri = newURI("http://www.foo.com", null, null); 1.113 + send(output, uri); 1.114 + 1.115 + assert.deepEqual(messages.shift(), { topic: topic, subject: uri }, 1.116 + "message received"); 1.117 + 1.118 + 1.119 + function customSubject() {} 1.120 + send(output, customSubject); 1.121 + 1.122 + let message = messages.shift(); 1.123 + assert.equal(message.topic, topic, "topic was received"); 1.124 + assert.equal(message.subject.wrappedJSObject, customSubject, 1.125 + "custom subject is received"); 1.126 + 1.127 + removeObserver(observer, topic); 1.128 + 1.129 + send(output, { data: "more data" }); 1.130 + 1.131 + assert.deepEqual(messages, [], 1.132 + "no more data received"); 1.133 + 1.134 + addObserver(observer, "*", false); 1.135 + 1.136 + send(output, { data: "data again" }); 1.137 + 1.138 + message = messages.shift(); 1.139 + assert.equal(message.topic, topic, "topic was received"); 1.140 + assert.deepEqual(message.subject.wrappedJSObject, 1.141 + { data: "data again" }, 1.142 + "wrapped message received"); 1.143 + 1.144 + removeObserver(observer, "*"); 1.145 + 1.146 + send(output, { data: "last data" }); 1.147 + assert.deepEqual(messages, [], 1.148 + "no more data received"); 1.149 + 1.150 + assert.throws(() => send(output, "hi"), 1.151 + /Unsupproted message type: `string`/, 1.152 + "strings can't be send"); 1.153 + 1.154 + assert.throws(() => send(output, 4), 1.155 + /Unsupproted message type: `number`/, 1.156 + "numbers can't be send"); 1.157 + 1.158 + assert.throws(() => send(output, void(0)), 1.159 + /Unsupproted message type: `undefined`/, 1.160 + "undefineds can't be send"); 1.161 + 1.162 + assert.throws(() => send(output, true), 1.163 + /Unsupproted message type: `boolean`/, 1.164 + "booleans can't be send"); 1.165 +}; 1.166 + 1.167 +exports["test async OutputPort"] = (assert, done) => { 1.168 + let async = false; 1.169 + const output = new OutputPort({ id: Date.now().toString(32) }); 1.170 + const observer = { 1.171 + observe: (subject, topic, data) => { 1.172 + removeObserver(observer, topic); 1.173 + assert.equal(topic, output.topic, "correct topic"); 1.174 + assert.deepEqual(subject.wrappedJSObject, {foo: "bar"}, "message received"); 1.175 + assert.ok(async, "message received async"); 1.176 + done(); 1.177 + } 1.178 + }; 1.179 + addObserver(observer, output.topic, false); 1.180 + send(output, {foo: "bar"}); 1.181 + 1.182 + assert.throws(() => send(output, "boom"), "can only send object"); 1.183 + async = true; 1.184 +}; 1.185 + 1.186 +exports["test explicit output topic"] = (assert, done) => { 1.187 + const topic = Date.now().toString(32); 1.188 + const output = new OutputPort({ topic: topic }); 1.189 + const observer = { 1.190 + observe: (subject, topic, data) => { 1.191 + removeObserver(observer, topic); 1.192 + assert.deepEqual(subject.wrappedJSObject, {foo: "bar"}, "message received"); 1.193 + done(); 1.194 + } 1.195 + }; 1.196 + 1.197 + assert.equal(output.topic, topic, "given topic is used"); 1.198 + 1.199 + addObserver(observer, topic, false); 1.200 + send(output, {foo: "bar"}); 1.201 +}; 1.202 + 1.203 +exports["test explicit input topic"] = (assert) => { 1.204 + const topic = Date.now().toString(32); 1.205 + const input = new InputPort({ topic: topic }); 1.206 + 1.207 + start(input); 1.208 + assert.equal(input.topic, topic, "given topic is used"); 1.209 + 1.210 + 1.211 + notifyObservers({wrappedJSObject: {foo: "bar"}}, topic, null); 1.212 + 1.213 + assert.deepEqual(input.value, {foo: "bar"}, "message received"); 1.214 +}; 1.215 + 1.216 + 1.217 +exports["test receive what was send"] = assert => { 1.218 + const id = Date.now().toString(32); 1.219 + const input = new InputPort({ id: id, initial: 0}); 1.220 + const output = new OutputPort({ id: id, sync: true }); 1.221 + 1.222 + assert.ok(input.topic.contains(addonID), 1.223 + "input topic is namespaced to addon"); 1.224 + assert.equal(input.topic, output.topic, 1.225 + "input & output get same topics from id."); 1.226 + 1.227 + start(input); 1.228 + 1.229 + assert.equal(input.value, 0, "initial value is set"); 1.230 + 1.231 + send(output, { data: 1 }); 1.232 + assert.deepEqual(input.value, {data: 1}, "message unwrapped"); 1.233 + 1.234 + send(output, []); 1.235 + assert.deepEqual(input.value, [], "array message unwrapped"); 1.236 + 1.237 + send(output, null); 1.238 + assert.deepEqual(input.value, null, "null message received"); 1.239 + 1.240 + send(output, new String("message")); 1.241 + assert.deepEqual(input.value, new String("message"), 1.242 + "string instance received"); 1.243 + 1.244 + send(output, /pattern/); 1.245 + assert.deepEqual(input.value, /pattern/, "regexp received"); 1.246 + 1.247 + assert.throws(() => send(output, "hi"), 1.248 + /Unsupproted message type: `string`/, 1.249 + "strings can't be send"); 1.250 + 1.251 + assert.throws(() => send(output, 4), 1.252 + /Unsupproted message type: `number`/, 1.253 + "numbers can't be send"); 1.254 + 1.255 + assert.throws(() => send(output, void(0)), 1.256 + /Unsupproted message type: `undefined`/, 1.257 + "undefineds can't be send"); 1.258 + 1.259 + assert.throws(() => send(output, true), 1.260 + /Unsupproted message type: `boolean`/, 1.261 + "booleans can't be send"); 1.262 + 1.263 + stop(input); 1.264 +}; 1.265 + 1.266 + 1.267 +exports["-test error reporting"] = function(assert) { 1.268 + let { loader, messages } = LoaderWithHookedConsole2(module); 1.269 + const { start, stop, lift } = loader.require("sdk/event/utils"); 1.270 + const { InputPort } = loader.require("sdk/input/system"); 1.271 + const { OutputPort } = loader.require("sdk/output/system"); 1.272 + const id = "error:" + Date.now().toString(32); 1.273 + 1.274 + const raise = x => { if (x) throw new Error("foo"); }; 1.275 + 1.276 + const input = new InputPort({ id: id }); 1.277 + const output = new OutputPort({ id: id, sync: true }); 1.278 + const xs = lift(raise, input); 1.279 + 1.280 + assert.equal(input.value, null, "initial inherited"); 1.281 + 1.282 + send(output, { data: "yo yo" }); 1.283 + 1.284 + assert.deepEqual(messages, [], "nothing happend yet"); 1.285 + 1.286 + start(xs); 1.287 + 1.288 + send(output, { data: "first" }); 1.289 + 1.290 + assert.equal(messages.length, 4, "Got an exception"); 1.291 + 1.292 + 1.293 + assert.equal(messages[0], "console.error: " + addonName + ": \n", 1.294 + "error is logged"); 1.295 + 1.296 + assert.ok(/Unhandled error/.test(messages[1]), 1.297 + "expected error message"); 1.298 + 1.299 + loader.unload(); 1.300 +}; 1.301 + 1.302 +exports["test unload ends input port"] = assert => { 1.303 + const loader = Loader(module); 1.304 + const { start, stop, lift } = loader.require("sdk/event/utils"); 1.305 + const { InputPort } = loader.require("sdk/input/system"); 1.306 + 1.307 + const id = "unload!" + Date.now().toString(32); 1.308 + const input = new InputPort({ id: id }); 1.309 + 1.310 + start(input); 1.311 + notifyObservers(message(1), input.topic, null); 1.312 + assert.deepEqual(input.value, {data: 1}, "message received"); 1.313 + 1.314 + notifyObservers(message(2), input.topic, null); 1.315 + assert.deepEqual(input.value, {data: 2}, "message received"); 1.316 + 1.317 + loader.unload(); 1.318 + notifyObservers(message(3), input.topic, null); 1.319 + assert.deepEqual(input.value, {data: 2}, "message wasn't received"); 1.320 +}; 1.321 + 1.322 +require("sdk/test").run(exports);