1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/devtools/tests/unit/test_async-utils.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,159 @@ 1.4 +/* -*- Mode: js; js-indent-level: 2; -*- */ 1.5 +/* Any copyright is dedicated to the Public Domain. 1.6 + http://creativecommons.org/publicdomain/zero/1.0/ */ 1.7 + 1.8 +// Test async-utils.js 1.9 + 1.10 +const {Task} = Cu.import("resource://gre/modules/Task.jsm", {}); 1.11 +// |const| will not work because 1.12 +// it will make the Promise object immutable before assigning. 1.13 +// Using Object.defineProperty() instead. 1.14 +Object.defineProperty(this, "Promise", { 1.15 + value: Cu.import("resource://gre/modules/Promise.jsm", {}).Promise, 1.16 + writable: false, configurable: false 1.17 +}); 1.18 +const {require} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools; 1.19 +const {async, asyncOnce, promiseInvoke, promiseCall} = require("devtools/async-utils"); 1.20 + 1.21 +function run_test() { 1.22 + do_test_pending(); 1.23 + Task.spawn(function*() { 1.24 + for (let helper of [async, asyncOnce]) { 1.25 + yield test_async_args(helper); 1.26 + yield test_async_return(helper); 1.27 + yield test_async_throw(helper); 1.28 + } 1.29 + yield test_async_once(); 1.30 + yield test_async_invoke(); 1.31 + do_test_finished(); 1.32 + }).then(null, error => { 1.33 + do_throw(error); 1.34 + }); 1.35 +} 1.36 + 1.37 +// Test that arguments are correctly passed through to the async function. 1.38 +function test_async_args(async) { 1.39 + let obj = { 1.40 + method: async(function*(a, b) { 1.41 + do_check_eq(this, obj); 1.42 + do_check_eq(a, "foo"); 1.43 + do_check_eq(b, "bar"); 1.44 + }) 1.45 + }; 1.46 + 1.47 + return obj.method("foo", "bar"); 1.48 +} 1.49 + 1.50 +// Test that the return value from the async function is resolution value of 1.51 +// the promise. 1.52 +function test_async_return(async) { 1.53 + let obj = { 1.54 + method: async(function*(a, b) { 1.55 + return a + b; 1.56 + }) 1.57 + }; 1.58 + 1.59 + return obj.method("foo", "bar").then(ret => { 1.60 + do_check_eq(ret, "foobar"); 1.61 + }); 1.62 +} 1.63 + 1.64 +// Test that the throwing from an async function rejects the promise. 1.65 +function test_async_throw(async) { 1.66 + let obj = { 1.67 + method: async(function*() { 1.68 + throw "boom"; 1.69 + }) 1.70 + }; 1.71 + 1.72 + return obj.method().then(null, error => { 1.73 + do_check_eq(error, "boom"); 1.74 + }); 1.75 +} 1.76 + 1.77 +// Test that asyncOnce only runs the async function once per instance and 1.78 +// returns the same promise for that instance. 1.79 +function test_async_once() { 1.80 + let counter = 0; 1.81 + 1.82 + function Foo() {} 1.83 + Foo.prototype = { 1.84 + ran: false, 1.85 + method: asyncOnce(function*() { 1.86 + yield Promise.resolve(); 1.87 + if (this.ran) { 1.88 + do_throw("asyncOnce function unexpectedly ran twice on the same object"); 1.89 + } 1.90 + this.ran = true; 1.91 + return counter++; 1.92 + }) 1.93 + }; 1.94 + 1.95 + let foo1 = new Foo(); 1.96 + let foo2 = new Foo(); 1.97 + let p1 = foo1.method(); 1.98 + let p2 = foo2.method(); 1.99 + 1.100 + do_check_neq(p1, p2); 1.101 + 1.102 + let p3 = foo1.method(); 1.103 + do_check_eq(p1, p3); 1.104 + do_check_false(foo1.ran); 1.105 + 1.106 + let p4 = foo2.method(); 1.107 + do_check_eq(p2, p4); 1.108 + do_check_false(foo2.ran); 1.109 + 1.110 + return p1.then(ret => { 1.111 + do_check_true(foo1.ran); 1.112 + do_check_eq(ret, 0); 1.113 + return p2; 1.114 + }).then(ret => { 1.115 + do_check_true(foo2.ran); 1.116 + do_check_eq(ret, 1); 1.117 + }); 1.118 +} 1.119 + 1.120 +// Test invoke and call. 1.121 +function test_async_invoke() { 1.122 + return Task.spawn(function*() { 1.123 + function func(a, b, expectedThis, callback) { 1.124 + "use strict"; 1.125 + do_check_eq(a, "foo"); 1.126 + do_check_eq(b, "bar"); 1.127 + do_check_eq(this, expectedThis); 1.128 + callback(a + b); 1.129 + } 1.130 + 1.131 + // Test call. 1.132 + let callResult = yield promiseCall(func, "foo", "bar", undefined); 1.133 + do_check_eq(callResult, "foobar"); 1.134 + 1.135 + 1.136 + // Test invoke. 1.137 + let obj = { method: func }; 1.138 + let invokeResult = yield promiseInvoke(obj, obj.method, "foo", "bar", obj); 1.139 + do_check_eq(invokeResult, "foobar"); 1.140 + 1.141 + 1.142 + // Test passing multiple values to the callback. 1.143 + function multipleResults(callback) { 1.144 + callback("foo", "bar"); 1.145 + } 1.146 + 1.147 + let results = yield promiseCall(multipleResults); 1.148 + do_check_eq(results.length, 2); 1.149 + do_check_eq(results[0], "foo"); 1.150 + do_check_eq(results[1], "bar"); 1.151 + 1.152 + 1.153 + // Test throwing from the function. 1.154 + function thrower() { 1.155 + throw "boom"; 1.156 + } 1.157 + 1.158 + yield promiseCall(thrower).then(null, error => { 1.159 + do_check_eq(error, "boom"); 1.160 + }); 1.161 + }); 1.162 +}