toolkit/devtools/tests/unit/test_async-utils.js

changeset 0
6474c204b198
     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 +}

mercurial