gecko-dev/devtools/server/tests/unit/test_client_request.js

264 строки
6.6 KiB
JavaScript

/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// 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() {
ActorRegistry.addGlobalActor(
{
constructorName: "TestActor",
constructorFun: TestActor,
},
"test"
);
DebuggerServer.init();
DebuggerServer.registerAllActors();
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.mainRoot.rootForm)
.then(response => {
gActorId = response.test;
run_next_test();
});
}
function checkStack(expectedName) {
if (!Services.prefs.getBoolPref("javascript.options.asyncstack")) {
info("Async stacks are disabled.");
return;
}
let stack = Components.stack;
while (stack) {
info(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 => {
Assert.equal(response.from, gActorId);
Assert.equal(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
const request = gClient.request({
to: gActorId,
type: "hello",
});
request.then(response => {
Assert.equal(response.from, gActorId);
Assert.equal(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
const request = gClient.request({
to: gActorId,
type: "error",
});
request.then(
() => {
do_throw("Promise shouldn't be resolved on error");
},
response => {
Assert.equal(response.from, gActorId);
Assert.equal(response.error, "code");
Assert.equal(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
const request = gClient.request({
to: gActorId,
type: "hello",
});
request.on("json-reply", reply => {
Assert.equal(reply.from, gActorId);
Assert.equal(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.
const activeRequest = gClient.request({
to: gActorId,
type: "hello",
});
// Pile up a second one that will be "pending".
// i.e. won't event be sent.
const pendingRequest = gClient.request({
to: gActorId,
type: "hello",
});
const expectReply = defer();
gClient.expectReply("root", function(response) {
Assert.equal(response.error, "connectionClosed");
Assert.equal(
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 => {
Assert.equal(response.error, "connectionClosed");
Assert.equal(
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 => {
Assert.equal(response.error, "connectionClosed");
Assert.equal(
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)
const 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");
Assert.equal(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)
gClient
.request(
{
to: gActorId,
type: "hello",
},
response => {
ok(true, "Request failed after client.close");
Assert.equal(response.error, "connectionClosed");
ok(
response.message.match(
/'hello' request packet to '.*' can't be sent as the connection is closed./
)
);
run_next_test();
}
)
.catch(() => info("Caught rejected promise as expected"));
}