diff options
Diffstat (limited to 'devtools/server/tests/unit/test_client_request.js')
-rw-r--r-- | devtools/server/tests/unit/test_client_request.js | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/devtools/server/tests/unit/test_client_request.js b/devtools/server/tests/unit/test_client_request.js new file mode 100644 index 000000000..c0c2c3a92 --- /dev/null +++ b/devtools/server/tests/unit/test_client_request.js @@ -0,0 +1,214 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test the DebuggerClient.request API. + +var gClient, gActorId; + +function TestActor(conn) { + this.conn = conn; +} +TestActor.prototype = { + actorPrefix: "test", + + hello: function () { + return {hello: "world"}; + }, + + error: function () { + return {error: "code", message: "human message"}; + } +}; +TestActor.prototype.requestTypes = { + "hello": TestActor.prototype.hello, + "error": TestActor.prototype.error +}; + +function run_test() +{ + DebuggerServer.addGlobalActor(TestActor); + + DebuggerServer.init(); + DebuggerServer.addBrowserActors(); + + add_test(init); + add_test(test_client_request_callback); + add_test(test_client_request_promise); + add_test(test_client_request_promise_error); + add_test(test_client_request_event_emitter); + add_test(test_close_client_while_sending_requests); + add_test(test_client_request_after_close); + add_test(test_client_request_after_close_callback); + run_next_test(); +} + +function init() +{ + gClient = new DebuggerClient(DebuggerServer.connectPipe()); + gClient.connect() + .then(() => gClient.listTabs()) + .then(aResponse => { + gActorId = aResponse.test; + run_next_test(); + }); +} + +function checkStack(expectedName) { + if (!Services.prefs.getBoolPref("javascript.options.asyncstack")) { + do_print("Async stacks are disabled."); + return; + } + + let stack = Components.stack; + while (stack) { + do_print(stack.name); + if (stack.name == expectedName) { + // Reached back to outer function before request + ok(true, "Complete stack"); + return; + } + stack = stack.asyncCaller || stack.caller; + } + ok(false, "Incomplete stack"); +} + +function test_client_request_callback() +{ + // Test that DebuggerClient.request accepts a `onResponse` callback as 2nd argument + gClient.request({ + to: gActorId, + type: "hello" + }, response => { + do_check_eq(response.from, gActorId); + do_check_eq(response.hello, "world"); + checkStack("test_client_request_callback"); + run_next_test(); + }); +} + +function test_client_request_promise() +{ + // Test that DebuggerClient.request returns a promise that resolves on response + let request = gClient.request({ + to: gActorId, + type: "hello" + }); + + request.then(response => { + do_check_eq(response.from, gActorId); + do_check_eq(response.hello, "world"); + checkStack("test_client_request_promise"); + run_next_test(); + }); +} + +function test_client_request_promise_error() +{ + // Test that DebuggerClient.request returns a promise that reject when server + // returns an explicit error message + let request = gClient.request({ + to: gActorId, + type: "error" + }); + + request.then(() => { + do_throw("Promise shouldn't be resolved on error"); + }, response => { + do_check_eq(response.from, gActorId); + do_check_eq(response.error, "code"); + do_check_eq(response.message, "human message"); + checkStack("test_client_request_promise_error"); + run_next_test(); + }); +} + +function test_client_request_event_emitter() +{ + // Test that DebuggerClient.request returns also an EventEmitter object + let request = gClient.request({ + to: gActorId, + type: "hello" + }); + request.on("json-reply", reply => { + do_check_eq(reply.from, gActorId); + do_check_eq(reply.hello, "world"); + checkStack("test_client_request_event_emitter"); + run_next_test(); + }); +} + +function test_close_client_while_sending_requests() { + // First send a first request that will be "active" + // while the connection is closed. + // i.e. will be sent but no response received yet. + let activeRequest = gClient.request({ + to: gActorId, + type: "hello" + }); + + // Pile up a second one that will be "pending". + // i.e. won't event be sent. + let pendingRequest = gClient.request({ + to: gActorId, + type: "hello" + }); + + let expectReply = promise.defer(); + gClient.expectReply("root", function (response) { + do_check_eq(response.error, "connectionClosed"); + do_check_eq(response.message, "server side packet can't be received as the connection just closed."); + expectReply.resolve(); + }); + + gClient.close().then(() => { + activeRequest.then(() => { + ok(false, "First request unexpectedly succeed while closing the connection"); + }, response => { + do_check_eq(response.error, "connectionClosed"); + do_check_eq(response.message, "'hello' active request packet to '" + gActorId + "' can't be sent as the connection just closed."); + }) + .then(() => pendingRequest) + .then(() => { + ok(false, "Second request unexpectedly succeed while closing the connection"); + }, response => { + do_check_eq(response.error, "connectionClosed"); + do_check_eq(response.message, "'hello' pending request packet to '" + gActorId + "' can't be sent as the connection just closed."); + }) + .then(() => expectReply.promise) + .then(run_next_test); + }); +} + +function test_client_request_after_close() +{ + // Test that DebuggerClient.request fails after we called client.close() + // (with promise API) + let request = gClient.request({ + to: gActorId, + type: "hello" + }); + + request.then(response => { + ok(false, "Request succeed even after client.close"); + }, response => { + ok(true, "Request failed after client.close"); + do_check_eq(response.error, "connectionClosed"); + ok(response.message.match(/'hello' request packet to '.*' can't be sent as the connection is closed./)); + run_next_test(); + }); +} + +function test_client_request_after_close_callback() +{ + // Test that DebuggerClient.request fails after we called client.close() + // (with callback API) + let request = gClient.request({ + to: gActorId, + type: "hello" + }, response => { + ok(true, "Request failed after client.close"); + do_check_eq(response.error, "connectionClosed"); + ok(response.message.match(/'hello' request packet to '.*' can't be sent as the connection is closed./)); + run_next_test(); + }); +} |