mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 866306 - Add a library to make devtools protocol interaction a bit easier. r=jimb
--HG-- extra : rebase_source : 1b8d8b42ccea6bfea01297a16a561e55f192d554
This commit is contained in:
parent
14b0f79bbe
commit
26d4bf3695
@ -225,6 +225,7 @@ this.DebuggerClient = function DebuggerClient(aTransport)
|
||||
]);
|
||||
|
||||
this.request = this.request.bind(this);
|
||||
this.localTransport = (this._transport instanceof LocalDebuggerTransport);
|
||||
|
||||
/*
|
||||
* As the first thing on the connection, expect a greeting packet from
|
||||
@ -601,6 +602,14 @@ DebuggerClient.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have a registered Front for this actor, let it handle the packet
|
||||
// and skip all the rest of this unpleasantness.
|
||||
let front = this.getActor(aPacket.from);
|
||||
if (front) {
|
||||
front.onPacket(aPacket);
|
||||
return;
|
||||
}
|
||||
|
||||
let onResponse;
|
||||
// See if we have a handler function waiting for a reply from this
|
||||
// actor. (Don't count unsolicited notifications or pauses as
|
||||
@ -654,6 +663,36 @@ DebuggerClient.prototype = {
|
||||
onClosed: function DC_onClosed(aStatus) {
|
||||
this.notify("closed");
|
||||
},
|
||||
|
||||
/**
|
||||
* Actor lifetime management, echos the server's actor pools.
|
||||
*/
|
||||
__pools: null,
|
||||
get _pools() {
|
||||
if (this.__pools) {
|
||||
return this.__pools;
|
||||
}
|
||||
this.__pools = new Set();
|
||||
return this.__pools;
|
||||
},
|
||||
|
||||
addActorPool: function(pool) {
|
||||
this._pools.add(pool);
|
||||
},
|
||||
removeActorPool: function(pool) {
|
||||
this._pools.delete(pool);
|
||||
},
|
||||
getActor: function(actorID) {
|
||||
let pool = this.poolFor(actorID);
|
||||
return pool ? pool.get(actorID) : null;
|
||||
},
|
||||
|
||||
poolFor: function(actorID) {
|
||||
for (let pool of this._pools) {
|
||||
if (pool.has(actorID)) return pool;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
eventSource(DebuggerClient.prototype);
|
||||
|
145
toolkit/devtools/server/actors/string.js
Normal file
145
toolkit/devtools/server/actors/string.js
Normal file
@ -0,0 +1,145 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
let {Cu} = require("chrome");
|
||||
let {DebuggerServer} = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
|
||||
|
||||
let promise = require("sdk/core/promise");
|
||||
let {Class} = require("sdk/core/heritage");
|
||||
|
||||
let protocol = require("devtools/server/protocol");
|
||||
let {method, Arg, Option, RetVal} = protocol;
|
||||
|
||||
exports.LongStringActor = protocol.ActorClass({
|
||||
typeName: "longstractor",
|
||||
|
||||
initialize: function(conn, str) {
|
||||
protocol.Actor.prototype.initialize.call(this, conn);
|
||||
this.str = str;
|
||||
this.short = (this.str.length < DebuggerServer.LONG_STRING_LENGTH);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.str = null;
|
||||
protocol.Actor.prototype.destroy.call(this);
|
||||
},
|
||||
|
||||
form: function() {
|
||||
if (this.short) {
|
||||
return this.str;
|
||||
}
|
||||
return {
|
||||
type: "longString",
|
||||
actor: this.actorID,
|
||||
length: this.str.length,
|
||||
initial: this.str.substring(0, DebuggerServer.LONG_STRING_INITIAL_LENGTH)
|
||||
}
|
||||
},
|
||||
|
||||
substring: method(function(start, end) {
|
||||
return promise.resolve(this.str.substring(start, end));
|
||||
}, {
|
||||
request: {
|
||||
start: Arg(0),
|
||||
end: Arg(1)
|
||||
},
|
||||
response: { substring: RetVal() },
|
||||
}),
|
||||
|
||||
release: method(function() { }, { release: true })
|
||||
});
|
||||
|
||||
/**
|
||||
* When a LongString on the server is short enough to be passed
|
||||
* as a full string, the client will get a ShortLongString instead of
|
||||
* a LongStringFront. Its API should match.
|
||||
*
|
||||
* I'm very proud of this name.
|
||||
*/
|
||||
exports.ShortLongString = Class({
|
||||
initialize: function(str) {
|
||||
this.str = str;
|
||||
},
|
||||
|
||||
get length() { return this.str.length; },
|
||||
get initial() { return this.str; },
|
||||
string: function() { return promise.resolve(this.str) },
|
||||
|
||||
substring: function(start, end) {
|
||||
return promise.resolve(this.str.substring(start, end));
|
||||
},
|
||||
|
||||
release: function() {
|
||||
this.str = null;
|
||||
return promise.resolve(undefined);
|
||||
}
|
||||
})
|
||||
|
||||
exports.LongStringFront = protocol.FrontClass(exports.LongStringActor, {
|
||||
initialize: function(client, form) {
|
||||
// Don't give the form by default, because we're being tricky and it might just
|
||||
// be a string.
|
||||
protocol.Front.prototype.initialize.call(this, client, null);
|
||||
this.form(form);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.initial = null;
|
||||
this.length = null;
|
||||
this.strPromise = null;
|
||||
protocol.Front.prototype.destroy.call(this);
|
||||
},
|
||||
|
||||
form: function(form) {
|
||||
this.actorID = form.actorID;
|
||||
this.initial = form.initial;
|
||||
this.length = form.length;
|
||||
},
|
||||
|
||||
string: function() {
|
||||
if (!this.strPromise) {
|
||||
let promiseRest = (thusFar) => {
|
||||
if (thusFar.length === this.length)
|
||||
return promise.resolve(thusFar);
|
||||
else {
|
||||
return this.substring(thusFar.length,
|
||||
thusFar.length + DebuggerServer.LONG_STRING_READ_LENGTH)
|
||||
.then((next) => promiseRest(thusFar + next));
|
||||
}
|
||||
}
|
||||
|
||||
this.strPromise = promiseRest(this.initial);
|
||||
}
|
||||
return this.strPromise;
|
||||
}
|
||||
});
|
||||
|
||||
// The long string actor needs some custom marshalling, because it is sometimes
|
||||
// returned as a primitive rather than a complete form.
|
||||
|
||||
let stringActorType = protocol.types.getType("longstractor");
|
||||
protocol.types.addType("longstring", {
|
||||
_actor: true,
|
||||
write: (value, context, detail) => {
|
||||
if (!(context instanceof protocol.Actor)) {
|
||||
throw Error("Passing a longstring as an argument isn't supported.");
|
||||
}
|
||||
if (value.short) {
|
||||
return value.str;
|
||||
} else {
|
||||
return stringActorType.write(value, context, detail);
|
||||
}
|
||||
},
|
||||
read: (value, context, detail) => {
|
||||
if (context instanceof protocol.Actor) {
|
||||
throw Error("Passing a longstring as an argument isn't supported.");
|
||||
}
|
||||
if (typeof(value) === "string") {
|
||||
return exports.ShortLongString(value);
|
||||
}
|
||||
return stringActorType.read(value, context, detail);
|
||||
}
|
||||
});
|
@ -119,6 +119,7 @@ var DebuggerServer = {
|
||||
|
||||
LONG_STRING_LENGTH: 10000,
|
||||
LONG_STRING_INITIAL_LENGTH: 1000,
|
||||
LONG_STRING_READ_LENGTH: 1000,
|
||||
|
||||
/**
|
||||
* A handler function that prompts the user to accept or decline the incoming
|
||||
@ -608,6 +609,13 @@ ActorPool.prototype = {
|
||||
delete this._cleanups[aActor.actorID];
|
||||
},
|
||||
|
||||
/**
|
||||
* Match the api expected by the protocol library.
|
||||
*/
|
||||
unmanage: function(aActor) {
|
||||
return this.removeActor(aActor);
|
||||
},
|
||||
|
||||
/**
|
||||
* Run all actor cleanups.
|
||||
*/
|
||||
@ -702,6 +710,13 @@ DebuggerServerConnection.prototype = {
|
||||
this._actorPool.removeActor(aActor);
|
||||
},
|
||||
|
||||
/**
|
||||
* Match the api expected by the protocol library.
|
||||
*/
|
||||
unmanage: function(aActor) {
|
||||
return this.removeActor(aActor);
|
||||
},
|
||||
|
||||
/**
|
||||
* Look up an actor implementation for an actorID. Will search
|
||||
* all the actor pools registered with the connection.
|
||||
@ -710,14 +725,9 @@ DebuggerServerConnection.prototype = {
|
||||
* Actor ID to look up.
|
||||
*/
|
||||
getActor: function DSC_getActor(aActorID) {
|
||||
if (this._actorPool.has(aActorID)) {
|
||||
return this._actorPool.get(aActorID);
|
||||
}
|
||||
|
||||
for each (let pool in this._extraPools) {
|
||||
if (pool.has(aActorID)) {
|
||||
return pool.get(aActorID);
|
||||
}
|
||||
let pool = this.poolFor(aActorID);
|
||||
if (pool) {
|
||||
return pool.get(aActorID);
|
||||
}
|
||||
|
||||
if (aActorID === "root") {
|
||||
@ -727,6 +737,19 @@ DebuggerServerConnection.prototype = {
|
||||
return null;
|
||||
},
|
||||
|
||||
poolFor: function DSC_actorPool(aActorID) {
|
||||
if (this._actorPool && this._actorPool.has(aActorID)) {
|
||||
return this._actorPool;
|
||||
}
|
||||
|
||||
for (let pool of this._extraPools) {
|
||||
if (pool.has(aActorID)) {
|
||||
return pool;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
_unknownError: function DSC__unknownError(aPrefix, aError) {
|
||||
let errorString = safeErrorString(aError);
|
||||
errorString += "\n" + aError.stack;
|
||||
@ -777,11 +800,14 @@ DebuggerServerConnection.prototype = {
|
||||
// Dispatch the request to the actor.
|
||||
if (actor.requestTypes && actor.requestTypes[aPacket.type]) {
|
||||
try {
|
||||
ret = actor.requestTypes[aPacket.type].bind(actor)(aPacket);
|
||||
this.currentPacket = aPacket;
|
||||
ret = actor.requestTypes[aPacket.type].bind(actor)(aPacket, this);
|
||||
} catch(e) {
|
||||
this.transport.send(this._unknownError(
|
||||
"error occurred while processing '" + aPacket.type,
|
||||
e));
|
||||
} finally {
|
||||
delete this.currentPacket;
|
||||
}
|
||||
} else {
|
||||
ret = { error: "unrecognizedPacketType",
|
||||
|
1219
toolkit/devtools/server/protocol.js
Normal file
1219
toolkit/devtools/server/protocol.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -17,6 +17,7 @@ Services.prefs.setBoolPref("devtools.debugger.remote-enabled", true);
|
||||
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm");
|
||||
|
||||
function testExceptionHook(ex) {
|
||||
try {
|
||||
@ -233,3 +234,92 @@ function writeFile(aFileName, aContent) {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
|
||||
function connectPipeTracing() {
|
||||
return new TracingTransport(DebuggerServer.connectPipe());
|
||||
}
|
||||
|
||||
function TracingTransport(childTransport) {
|
||||
this.hooks = null;
|
||||
this.child = childTransport;
|
||||
this.child.hooks = this;
|
||||
|
||||
this.expectations = [];
|
||||
this.packets = [];
|
||||
this.checkIndex = 0;
|
||||
}
|
||||
|
||||
function deepEqual(a, b) {
|
||||
if (a === b)
|
||||
return true;
|
||||
if (typeof a != "object" || typeof b != "object")
|
||||
return false;
|
||||
if (a === null || b === null)
|
||||
return false;
|
||||
if (Object.keys(a).length != Object.keys(b).length)
|
||||
return false;
|
||||
for (let k in a) {
|
||||
if (!deepEqual(a[k], b[k]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TracingTransport.prototype = {
|
||||
// Remove actor names
|
||||
normalize: function(packet) {
|
||||
return JSON.parse(JSON.stringify(packet, (key, value) => {
|
||||
if (key === "to" || key === "from" || key === "actor") {
|
||||
return "<actorid>";
|
||||
}
|
||||
return value;
|
||||
}));
|
||||
},
|
||||
send: function(packet) {
|
||||
this.packets.push({
|
||||
type: "sent",
|
||||
packet: this.normalize(packet)
|
||||
});
|
||||
return this.child.send(packet);
|
||||
},
|
||||
close: function() {
|
||||
return this.child.close();
|
||||
},
|
||||
ready: function() {
|
||||
return this.child.ready();
|
||||
},
|
||||
onPacket: function(packet) {
|
||||
this.packets.push({
|
||||
type: "received",
|
||||
packet: this.normalize(packet)
|
||||
});
|
||||
this.hooks.onPacket(packet);
|
||||
},
|
||||
onClosed: function() {
|
||||
this.hooks.onClosed();
|
||||
},
|
||||
|
||||
expectSend: function(expected) {
|
||||
let packet = this.packets[this.checkIndex++];
|
||||
do_check_eq(packet.type, "sent");
|
||||
do_check_true(deepEqual(packet.packet, this.normalize(expected)));
|
||||
},
|
||||
|
||||
expectReceive: function(expected) {
|
||||
let packet = this.packets[this.checkIndex++];
|
||||
do_check_eq(packet.type, "received");
|
||||
do_check_true(deepEqual(packet.packet, this.normalize(expected)));
|
||||
},
|
||||
|
||||
// Write your tests, call dumpLog at the end, inspect the output,
|
||||
// then sprinkle the calls through the right places in your test.
|
||||
dumpLog: function() {
|
||||
for (let entry of this.packets) {
|
||||
if (entry.type === "sent") {
|
||||
dump("trace.expectSend(" + entry.packet + ");\n");
|
||||
} else {
|
||||
dump("trace.expectReceive(" + entry.packet + ");\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
434
toolkit/devtools/server/tests/unit/test_protocol_children.js
Normal file
434
toolkit/devtools/server/tests/unit/test_protocol_children.js
Normal file
@ -0,0 +1,434 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test simple requests using the protocol helpers.
|
||||
*/
|
||||
let protocol = devtools.require("devtools/server/protocol");
|
||||
let {method, preEvent, types, Arg, Option, RetVal} = protocol;
|
||||
|
||||
let {resolve} = devtools.require("sdk/core/promise");
|
||||
let events = devtools.require("sdk/event/core");
|
||||
|
||||
function simpleHello() {
|
||||
return {
|
||||
from: "root",
|
||||
applicationType: "xpcshell-tests",
|
||||
traits: [],
|
||||
}
|
||||
}
|
||||
|
||||
let testTypes = {};
|
||||
|
||||
// Predeclaring the actor type so that it can be used in the
|
||||
// implementation of the child actor.
|
||||
types.addActorType("childActor");
|
||||
|
||||
let ChildActor = protocol.ActorClass({
|
||||
typeName: "childActor",
|
||||
|
||||
// Actors returned by this actor should be owned by the root actor.
|
||||
marshallPool: function() { return this.parent() },
|
||||
|
||||
toString: function() "[ChildActor " + this.childID + "]",
|
||||
|
||||
initialize: function(conn, id) {
|
||||
protocol.Actor.prototype.initialize.call(this, conn);
|
||||
this.childID = id;
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
protocol.Actor.prototype.destroy.call(this);
|
||||
this.destroyed = true;
|
||||
},
|
||||
|
||||
form: function(detail) {
|
||||
return {
|
||||
actor: this.actorID,
|
||||
childID: this.childID,
|
||||
detail: detail
|
||||
};
|
||||
},
|
||||
|
||||
echo: method(function(str) {
|
||||
return str;
|
||||
}, {
|
||||
request: { str: Arg(0) },
|
||||
response: { str: RetVal("string") },
|
||||
telemetry: "ECHO"
|
||||
}),
|
||||
|
||||
getDetail1: method(function() {
|
||||
return this;
|
||||
}, {
|
||||
// This also exercises return-value-as-packet.
|
||||
response: RetVal("childActor#detail1"),
|
||||
}),
|
||||
|
||||
getDetail2: method(function() {
|
||||
return this;
|
||||
}, {
|
||||
// This also exercises return-value-as-packet.
|
||||
response: RetVal("childActor#detail2"),
|
||||
}),
|
||||
|
||||
getSibling: method(function(id) {
|
||||
return this.parent().getChild(id);
|
||||
}, {
|
||||
request: { id: Arg(0) },
|
||||
response: { sibling: RetVal("childActor") }
|
||||
}),
|
||||
|
||||
emitEvents: method(function() {
|
||||
events.emit(this, "event1", 1, 2, 3);
|
||||
events.emit(this, "named-event", 1, 2, 3);
|
||||
events.emit(this, "object-event", this);
|
||||
events.emit(this, "array-object-event", [this]);
|
||||
}, {
|
||||
response: { value: "correct response" },
|
||||
}),
|
||||
|
||||
release: method(function() { }, { release: true }),
|
||||
|
||||
events: {
|
||||
"event1" : {
|
||||
a: Arg(0),
|
||||
b: Arg(1),
|
||||
c: Arg(2)
|
||||
},
|
||||
"named-event": {
|
||||
type: "namedEvent",
|
||||
a: Arg(0),
|
||||
b: Arg(1),
|
||||
c: Arg(2)
|
||||
},
|
||||
"object-event": {
|
||||
type: "objectEvent",
|
||||
detail: Arg(0, "childActor#detail1"),
|
||||
},
|
||||
"array-object-event": {
|
||||
type: "arrayObjectEvent",
|
||||
detail: Arg(0, "array:childActor#detail2"),
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let ChildFront = protocol.FrontClass(ChildActor, {
|
||||
initialize: function(client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client, form);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.destroyed = true;
|
||||
protocol.Front.prototype.destroy.call(this);
|
||||
},
|
||||
|
||||
marshallPool: function() { return this.parent() },
|
||||
|
||||
toString: function() "[child front " + this.childID + "]",
|
||||
|
||||
form: function(form) {
|
||||
this.childID = form.childID;
|
||||
this.detail = form.detail;
|
||||
},
|
||||
|
||||
onEvent1: preEvent("event1", function(a, b, c) {
|
||||
this.event1arg3 = c;
|
||||
}),
|
||||
});
|
||||
|
||||
types.addDictType("manyChildrenDict", {
|
||||
child5: "childActor",
|
||||
more: "array:childActor",
|
||||
});
|
||||
|
||||
types.addLifetime("temp", "_temporaryHolder");
|
||||
|
||||
let rootActor = null;
|
||||
let RootActor = protocol.ActorClass({
|
||||
typeName: "root",
|
||||
|
||||
toString: function() "[root actor]",
|
||||
|
||||
initialize: function(conn) {
|
||||
rootActor = this;
|
||||
this.actorID = "root";
|
||||
this._children = {};
|
||||
protocol.Actor.prototype.initialize.call(this, conn);
|
||||
// Root actor owns itself.
|
||||
this.manage(this);
|
||||
},
|
||||
|
||||
toString: function() "root actor",
|
||||
|
||||
sayHello: simpleHello,
|
||||
|
||||
getChild: method(function(id) {
|
||||
if (id in this._children) {
|
||||
return this._children[id];
|
||||
}
|
||||
let child = new ChildActor(this.conn, id);
|
||||
this._children[id] = child;
|
||||
return child;
|
||||
}, {
|
||||
request: { str: Arg(0) },
|
||||
response: { actor: RetVal("childActor") },
|
||||
}),
|
||||
|
||||
getChildren: method(function(ids) {
|
||||
return [this.getChild(id) for (id of ids)];
|
||||
}, {
|
||||
request: { ids: Arg(0, "array:string") },
|
||||
response: { children: RetVal("array:childActor") },
|
||||
}),
|
||||
|
||||
getManyChildren: method(function() {
|
||||
return {
|
||||
foo: "bar", // note that this isn't in the specialization array.
|
||||
child5: this.getChild("child5"),
|
||||
more: [ this.getChild("child6"), this.getChild("child7") ]
|
||||
}
|
||||
}, {
|
||||
response: RetVal("manyChildrenDict")
|
||||
}),
|
||||
|
||||
// This should remind you of a pause actor.
|
||||
getTemporaryChild: method(function(id) {
|
||||
if (!this._temporaryHolder) {
|
||||
this._temporaryHolder = this.manage(new protocol.Actor(this.conn));
|
||||
}
|
||||
return new ChildActor(this.conn, id);
|
||||
}, {
|
||||
request: { id: Arg(0) },
|
||||
response: { child: RetVal("temp:childActor") }
|
||||
}),
|
||||
|
||||
clearTemporaryChildren: method(function(id) {
|
||||
if (!this._temporaryHolder) {
|
||||
return;
|
||||
}
|
||||
this._temporaryHolder.destroy();
|
||||
delete this._temporaryHolder;
|
||||
})
|
||||
});
|
||||
|
||||
let RootFront = protocol.FrontClass(RootActor, {
|
||||
toString: function() "[root front]",
|
||||
initialize: function(client) {
|
||||
this.actorID = "root";
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
// Root actor owns itself.
|
||||
this.manage(this);
|
||||
},
|
||||
|
||||
getTemporaryChild: protocol.custom(function(id) {
|
||||
if (!this._temporaryHolder) {
|
||||
this._temporaryHolder = this.manage(new protocol.Front(this.conn, {actor: this.actorID + "_temp"}));
|
||||
}
|
||||
return this._getTemporaryChild(id);
|
||||
},{
|
||||
impl: "_getTemporaryChild"
|
||||
}),
|
||||
|
||||
clearTemporaryChildren: protocol.custom(function() {
|
||||
if (!this._temporaryHolder) {
|
||||
return;
|
||||
}
|
||||
this._temporaryHolder.destroy();
|
||||
delete this._temporaryHolder;
|
||||
return this._clearTemporaryChildren();
|
||||
}, {
|
||||
impl: "_clearTemporaryChildren"
|
||||
})
|
||||
});
|
||||
|
||||
function run_test()
|
||||
{
|
||||
DebuggerServer.createRootActor = (conn => {
|
||||
return RootActor(conn);
|
||||
});
|
||||
DebuggerServer.init(() => true);
|
||||
|
||||
let trace = connectPipeTracing();
|
||||
let client = new DebuggerClient(trace);
|
||||
client.connect((applicationType, traits) => {
|
||||
trace.expectReceive({"from":"<actorid>","applicationType":"xpcshell-tests","traits":[]})
|
||||
do_check_eq(applicationType, "xpcshell-tests");
|
||||
|
||||
let rootFront = RootFront(client);
|
||||
let childFront = null;
|
||||
|
||||
let expectRootChildren = size => {
|
||||
do_check_eq(rootActor._poolMap.size, size + 1);
|
||||
do_check_eq(rootFront._poolMap.size, size + 1);
|
||||
if (childFront) {
|
||||
do_check_eq(childFront._poolMap.size, 0);
|
||||
}
|
||||
};
|
||||
|
||||
rootFront.getChild("child1").then(ret => {
|
||||
trace.expectSend({"type":"getChild","str":"child1","to":"<actorid>"})
|
||||
trace.expectReceive({"actor":"<actorid>","from":"<actorid>"})
|
||||
|
||||
childFront = ret;
|
||||
do_check_true(childFront instanceof ChildFront);
|
||||
do_check_eq(childFront.childID, "child1");
|
||||
expectRootChildren(1);
|
||||
}).then(() => {
|
||||
// Request the child again, make sure the same is returned.
|
||||
return rootFront.getChild("child1");
|
||||
}).then(ret => {
|
||||
trace.expectSend({"type":"getChild","str":"child1","to":"<actorid>"})
|
||||
trace.expectReceive({"actor":"<actorid>","from":"<actorid>"})
|
||||
|
||||
expectRootChildren(1);
|
||||
do_check_true(ret === childFront);
|
||||
}).then(() => {
|
||||
return childFront.echo("hello");
|
||||
}).then(ret => {
|
||||
trace.expectSend({"type":"echo","str":"hello","to":"<actorid>"})
|
||||
trace.expectReceive({"str":"hello","from":"<actorid>"})
|
||||
|
||||
do_check_eq(ret, "hello");
|
||||
}).then(() => {
|
||||
return childFront.getDetail1();
|
||||
}).then(ret => {
|
||||
trace.expectSend({"type":"getDetail1","to":"<actorid>"});
|
||||
trace.expectReceive({"actor":"<actorid>","childID":"child1","detail":"detail1","from":"<actorid>"});
|
||||
do_check_true(ret === childFront);
|
||||
do_check_eq(childFront.detail, "detail1");
|
||||
}).then(() => {
|
||||
return childFront.getDetail2();
|
||||
}).then(ret => {
|
||||
trace.expectSend({"type":"getDetail2","to":"<actorid>"});
|
||||
trace.expectReceive({"actor":"<actorid>","childID":"child1","detail":"detail2","from":"<actorid>"});
|
||||
do_check_true(ret === childFront);
|
||||
do_check_eq(childFront.detail, "detail2");
|
||||
}).then(() => {
|
||||
return childFront.getSibling("siblingID");
|
||||
}).then(ret => {
|
||||
trace.expectSend({"type":"getSibling","id":"siblingID","to":"<actorid>"});
|
||||
trace.expectReceive({"sibling":{"actor":"<actorid>","childID":"siblingID"},"from":"<actorid>"});
|
||||
|
||||
expectRootChildren(2);
|
||||
}).then(ret => {
|
||||
return rootFront.getTemporaryChild("temp1").then(temp1 => {
|
||||
trace.expectSend({"type":"getTemporaryChild","id":"temp1","to":"<actorid>"});
|
||||
trace.expectReceive({"child":{"actor":"<actorid>","childID":"temp1"},"from":"<actorid>"});
|
||||
|
||||
// At this point we expect two direct children, plus the temporary holder
|
||||
// which should hold 1 itself.
|
||||
do_check_eq(rootActor._temporaryHolder.__poolMap.size, 1);
|
||||
do_check_eq(rootFront._temporaryHolder.__poolMap.size, 1);
|
||||
|
||||
expectRootChildren(3);
|
||||
return rootFront.getTemporaryChild("temp2").then(temp2 => {
|
||||
trace.expectSend({"type":"getTemporaryChild","id":"temp2","to":"<actorid>"});
|
||||
trace.expectReceive({"child":{"actor":"<actorid>","childID":"temp2"},"from":"<actorid>"});
|
||||
|
||||
// Same amount of direct children, and an extra in the temporary holder.
|
||||
expectRootChildren(3);
|
||||
do_check_eq(rootActor._temporaryHolder.__poolMap.size, 2);
|
||||
do_check_eq(rootFront._temporaryHolder.__poolMap.size, 2);
|
||||
|
||||
// Get the children of the temporary holder...
|
||||
let checkActors = [entry[1] for (entry of rootActor._temporaryHolder.__poolMap)];
|
||||
let checkFronts = [entry[1] for (entry of rootFront._temporaryHolder.__poolMap)];
|
||||
|
||||
// Now release the temporary holders and expect them to drop again.
|
||||
return rootFront.clearTemporaryChildren().then(() => {
|
||||
trace.expectSend({"type":"clearTemporaryChildren","to":"<actorid>"});
|
||||
trace.expectReceive({"from":"<actorid>"});
|
||||
|
||||
expectRootChildren(2);
|
||||
do_check_false(!!rootActor._temporaryHolder);
|
||||
do_check_false(!!rootFront._temporaryHolder);
|
||||
for (let checkActor of checkActors) {
|
||||
do_check_true(checkActor.destroyed);
|
||||
do_check_true(checkActor.destroyed);
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
}).then(ret => {
|
||||
return rootFront.getChildren(["child1", "child2"]);
|
||||
}).then(ret => {
|
||||
trace.expectSend({"type":"getChildren","ids":["child1","child2"],"to":"<actorid>"});
|
||||
trace.expectReceive({"children":[{"actor":"<actorid>","childID":"child1"},{"actor":"<actorid>","childID":"child2"}],"from":"<actorid>"});
|
||||
|
||||
expectRootChildren(3);
|
||||
do_check_true(ret[0] === childFront);
|
||||
do_check_true(ret[1] !== childFront);
|
||||
do_check_true(ret[1] instanceof ChildFront);
|
||||
|
||||
// On both children, listen to events. We're only
|
||||
// going to trigger events on the first child, so an event
|
||||
// triggered on the second should cause immediate failures.
|
||||
|
||||
let set = new Set(["event1", "named-event", "object-event", "array-object-event"]);
|
||||
|
||||
childFront.on("event1", (a, b, c) => {
|
||||
do_check_eq(a, 1);
|
||||
do_check_eq(b, 2);
|
||||
do_check_eq(c, 3);
|
||||
// Verify that the pre-event handler was called.
|
||||
do_check_eq(childFront.event1arg3, 3);
|
||||
set.delete("event1");
|
||||
});
|
||||
childFront.on("named-event", (a, b, c) => {
|
||||
do_check_eq(a, 1);
|
||||
do_check_eq(b, 2);
|
||||
do_check_eq(c, 3);
|
||||
set.delete("named-event");
|
||||
});
|
||||
childFront.on("object-event", (obj) => {
|
||||
do_check_true(obj === childFront);
|
||||
do_check_eq(childFront.detail, "detail1");
|
||||
set.delete("object-event");
|
||||
});
|
||||
childFront.on("array-object-event", (array) => {
|
||||
do_check_true(array[0] === childFront);
|
||||
do_check_eq(childFront.detail, "detail2");
|
||||
set.delete("array-object-event");
|
||||
});
|
||||
|
||||
let fail = function() {
|
||||
do_throw("Unexpected event");
|
||||
}
|
||||
ret[1].on("event1", fail);
|
||||
ret[1].on("named-event", fail);
|
||||
ret[1].on("object-event", fail);
|
||||
ret[1].on("array-object-event", fail);
|
||||
|
||||
return childFront.emitEvents().then(() => {
|
||||
trace.expectSend({"type":"emitEvents","to":"<actorid>"});
|
||||
trace.expectReceive({"type":"event1","a":1,"b":2,"c":3,"from":"<actorid>"});
|
||||
trace.expectReceive({"type":"namedEvent","a":1,"b":2,"c":3,"from":"<actorid>"});
|
||||
trace.expectReceive({"type":"objectEvent","detail":{"actor":"<actorid>","childID":"child1","detail":"detail1"},"from":"<actorid>"});
|
||||
trace.expectReceive({"type":"arrayObjectEvent","detail":[{"actor":"<actorid>","childID":"child1","detail":"detail2"}],"from":"<actorid>"});
|
||||
trace.expectReceive({"value":"correct response","from":"<actorid>"});
|
||||
|
||||
|
||||
do_check_eq(set.size, 0);
|
||||
});
|
||||
}).then(ret => {
|
||||
return rootFront.getManyChildren();
|
||||
}).then(ret => {
|
||||
trace.expectSend({"type":"getManyChildren","to":"<actorid>"});
|
||||
trace.expectReceive({"foo":"bar","child5":{"actor":"<actorid>","childID":"child5"},"more":[{"actor":"<actorid>","childID":"child6"},{"actor":"<actorid>","childID":"child7"}],"from":"<actorid>"});
|
||||
|
||||
// Check all the crazy stuff we did in getManyChildren
|
||||
do_check_eq(ret.foo, "bar");
|
||||
do_check_eq(ret.child5.childID, "child5");
|
||||
do_check_eq(ret.more[0].childID, "child6");
|
||||
do_check_eq(ret.more[1].childID, "child7");
|
||||
}).then(() => {
|
||||
client.close(() => {
|
||||
do_test_finished();
|
||||
});
|
||||
}).then(null, err => {
|
||||
do_report_unexpected_exception(err, "Failure executing test");
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
204
toolkit/devtools/server/tests/unit/test_protocol_longstring.js
Normal file
204
toolkit/devtools/server/tests/unit/test_protocol_longstring.js
Normal file
@ -0,0 +1,204 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test simple requests using the protocol helpers.
|
||||
*/
|
||||
let protocol = devtools.require("devtools/server/protocol");
|
||||
let {method, RetVal, Arg, Option} = protocol;
|
||||
let {defer, resolve} = devtools.require("sdk/core/promise");
|
||||
let events = devtools.require("sdk/event/core");
|
||||
let {LongStringActor} = devtools.require("devtools/server/actors/string");
|
||||
|
||||
function simpleHello() {
|
||||
return {
|
||||
from: "root",
|
||||
applicationType: "xpcshell-tests",
|
||||
traits: [],
|
||||
}
|
||||
}
|
||||
|
||||
DebuggerServer.LONG_STRING_LENGTH = DebuggerServer.LONG_STRING_INITIAL_LENGTH = DebuggerServer.LONG_STRING_READ_LENGTH = 5;
|
||||
|
||||
let SHORT_STR = "abc";
|
||||
let LONG_STR = "abcdefghijklmnop";
|
||||
|
||||
let rootActor = null;
|
||||
|
||||
let RootActor = protocol.ActorClass({
|
||||
typeName: "root",
|
||||
|
||||
initialize: function(conn) {
|
||||
rootActor = this;
|
||||
protocol.Actor.prototype.initialize.call(this, conn);
|
||||
// Root actor owns itself.
|
||||
this.manage(this);
|
||||
this.actorID = "root";
|
||||
},
|
||||
|
||||
sayHello: simpleHello,
|
||||
|
||||
shortString: method(function() {
|
||||
return new LongStringActor(this.conn, SHORT_STR);
|
||||
}, {
|
||||
response: { value: RetVal("longstring") },
|
||||
}),
|
||||
|
||||
longString: method(function() {
|
||||
return new LongStringActor(this.conn, LONG_STR);
|
||||
}, {
|
||||
response: { value: RetVal("longstring") },
|
||||
}),
|
||||
|
||||
emitShortString: method(function() {
|
||||
events.emit(this, "string-event", new LongStringActor(this.conn, SHORT_STR));
|
||||
}, {
|
||||
oneway: true,
|
||||
}),
|
||||
|
||||
emitLongString: method(function() {
|
||||
events.emit(this, "string-event", new LongStringActor(this.conn, LONG_STR));
|
||||
}, {
|
||||
oneway: true,
|
||||
}),
|
||||
|
||||
events: {
|
||||
"string-event": {
|
||||
str: Arg(0, "longstring")
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let RootFront = protocol.FrontClass(RootActor, {
|
||||
initialize: function(client) {
|
||||
this.actorID = "root";
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
// Root owns itself.
|
||||
this.manage(this);
|
||||
}
|
||||
});
|
||||
|
||||
function run_test()
|
||||
{
|
||||
DebuggerServer.createRootActor = (conn => {
|
||||
return RootActor(conn);
|
||||
});
|
||||
|
||||
DebuggerServer.init(() => true);
|
||||
let trace = connectPipeTracing();
|
||||
let client = new DebuggerClient(trace);
|
||||
let rootClient = RootFront(client);
|
||||
|
||||
let strfront = null;
|
||||
|
||||
let expectRootChildren = function(size) {
|
||||
do_check_eq(rootActor.__poolMap.size, size + 1);
|
||||
do_check_eq(rootClient.__poolMap.size, size + 1);
|
||||
}
|
||||
|
||||
// Root actor has no children yet.
|
||||
expectRootChildren(0);
|
||||
|
||||
client.connect((applicationType, traits) => {
|
||||
trace.expectReceive({"from":"<actorid>","applicationType":"xpcshell-tests","traits":[]});
|
||||
do_check_eq(applicationType, "xpcshell-tests");
|
||||
rootClient.shortString().then(ret => {
|
||||
trace.expectSend({"type":"shortString","to":"<actorid>"});
|
||||
trace.expectReceive({"value":"abc","from":"<actorid>"});
|
||||
|
||||
// Should only own the one reference (itself) at this point.
|
||||
expectRootChildren(0);
|
||||
strfront = ret;
|
||||
}).then(() => {
|
||||
return strfront.string();
|
||||
}).then(ret => {
|
||||
do_check_eq(ret, SHORT_STR);
|
||||
}).then(() => {
|
||||
return rootClient.longString();
|
||||
}).then(ret => {
|
||||
trace.expectSend({"type":"longString","to":"<actorid>"});
|
||||
trace.expectReceive({"value":{"type":"longString","actor":"<actorid>","length":16,"initial":"abcde"},"from":"<actorid>"});
|
||||
|
||||
strfront = ret;
|
||||
// Should own a reference to itself and an extra string now.
|
||||
expectRootChildren(1);
|
||||
}).then(() => {
|
||||
return strfront.string();
|
||||
}).then(ret => {
|
||||
trace.expectSend({"type":"substring","start":5,"end":10,"to":"<actorid>"});
|
||||
trace.expectReceive({"substring":"fghij","from":"<actorid>"});
|
||||
trace.expectSend({"type":"substring","start":10,"end":15,"to":"<actorid>"});
|
||||
trace.expectReceive({"substring":"klmno","from":"<actorid>"});
|
||||
trace.expectSend({"type":"substring","start":15,"end":20,"to":"<actorid>"});
|
||||
trace.expectReceive({"substring":"p","from":"<actorid>"});
|
||||
|
||||
do_check_eq(ret, LONG_STR);
|
||||
}).then(() => {
|
||||
return strfront.release();
|
||||
}).then(() => {
|
||||
trace.expectSend({"type":"release","to":"<actorid>"});
|
||||
trace.expectReceive({"from":"<actorid>"});
|
||||
|
||||
// That reference should be removed now.
|
||||
expectRootChildren(0);
|
||||
}).then(() => {
|
||||
let deferred = defer();
|
||||
rootClient.once("string-event", (str) => {
|
||||
trace.expectSend({"type":"emitShortString","to":"<actorid>"});
|
||||
trace.expectReceive({"type":"string-event","str":"abc","from":"<actorid>"});
|
||||
|
||||
do_check_true(!!str);
|
||||
strfront = str;
|
||||
// Shouldn't generate any new references
|
||||
expectRootChildren(0);
|
||||
// will generate no packets.
|
||||
strfront.string().then((value) => { deferred.resolve(value) });
|
||||
});
|
||||
rootClient.emitShortString();
|
||||
return deferred.promise;
|
||||
}).then(value => {
|
||||
do_check_eq(value, SHORT_STR);
|
||||
}).then(() => {
|
||||
// Will generate no packets
|
||||
return strfront.release();
|
||||
}).then(() => {
|
||||
let deferred = defer();
|
||||
rootClient.once("string-event", (str) => {
|
||||
trace.expectSend({"type":"emitLongString","to":"<actorid>"});
|
||||
trace.expectReceive({"type":"string-event","str":{"type":"longString","actor":"<actorid>","length":16,"initial":"abcde"},"from":"<actorid>"});
|
||||
|
||||
do_check_true(!!str);
|
||||
// Should generate one new reference
|
||||
expectRootChildren(1);
|
||||
strfront = str;
|
||||
strfront.string().then((value) => {
|
||||
trace.expectSend({"type":"substring","start":5,"end":10,"to":"<actorid>"});
|
||||
trace.expectReceive({"substring":"fghij","from":"<actorid>"});
|
||||
trace.expectSend({"type":"substring","start":10,"end":15,"to":"<actorid>"});
|
||||
trace.expectReceive({"substring":"klmno","from":"<actorid>"});
|
||||
trace.expectSend({"type":"substring","start":15,"end":20,"to":"<actorid>"});
|
||||
trace.expectReceive({"substring":"p","from":"<actorid>"});
|
||||
|
||||
deferred.resolve(value);
|
||||
});
|
||||
});
|
||||
rootClient.emitLongString();
|
||||
return deferred.promise;
|
||||
}).then(value => {
|
||||
do_check_eq(value, LONG_STR);
|
||||
}).then(() => {
|
||||
return strfront.release();
|
||||
}).then(() => {
|
||||
trace.expectSend({"type":"release","to":"<actorid>"});
|
||||
trace.expectReceive({"from":"<actorid>"});
|
||||
expectRootChildren(0);
|
||||
}).then(() => {
|
||||
client.close(() => {
|
||||
do_test_finished();
|
||||
});
|
||||
}).then(null, err => {
|
||||
do_report_unexpected_exception(err, "Failure executing test");
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
275
toolkit/devtools/server/tests/unit/test_protocol_simple.js
Normal file
275
toolkit/devtools/server/tests/unit/test_protocol_simple.js
Normal file
@ -0,0 +1,275 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test simple requests using the protocol helpers.
|
||||
*/
|
||||
|
||||
let protocol = devtools.require("devtools/server/protocol");
|
||||
let {method, Arg, Option, RetVal} = protocol;
|
||||
let {defer, resolve} = devtools.require("sdk/core/promise");
|
||||
let events = devtools.require("sdk/event/core");
|
||||
|
||||
function simpleHello() {
|
||||
return {
|
||||
from: "root",
|
||||
applicationType: "xpcshell-tests",
|
||||
traits: [],
|
||||
}
|
||||
}
|
||||
|
||||
let RootActor = protocol.ActorClass({
|
||||
typeName: "root",
|
||||
initialize: function(conn) {
|
||||
protocol.Actor.prototype.initialize.call(this, conn);
|
||||
// Root actor owns itself.
|
||||
this.manage(this);
|
||||
this.actorID = "root";
|
||||
},
|
||||
|
||||
sayHello: simpleHello,
|
||||
|
||||
simpleReturn: method(function() {
|
||||
return 1;
|
||||
}, {
|
||||
response: { value: RetVal() },
|
||||
}),
|
||||
|
||||
promiseReturn: method(function() {
|
||||
return resolve(1);
|
||||
}, {
|
||||
response: { value: RetVal("number") },
|
||||
}),
|
||||
|
||||
simpleArgs: method(function(a, b) {
|
||||
return { firstResponse: a + 1, secondResponse: b + 1 };
|
||||
}, {
|
||||
request: {
|
||||
firstArg: Arg(0),
|
||||
secondArg: Arg(1),
|
||||
},
|
||||
response: RetVal()
|
||||
}),
|
||||
|
||||
nestedArgs: method(function(a, b, c) {
|
||||
return { a: a, b: b, c: c };
|
||||
}, {
|
||||
request: {
|
||||
firstArg: Arg(0),
|
||||
nest: {
|
||||
secondArg: Arg(1),
|
||||
nest: {
|
||||
thirdArg: Arg(2)
|
||||
}
|
||||
}
|
||||
},
|
||||
response: RetVal()
|
||||
}),
|
||||
|
||||
optionArgs: method(function(options) {
|
||||
return { option1: options.option1, option2: options.option2 };
|
||||
}, {
|
||||
request: {
|
||||
option1: Option(0),
|
||||
option2: Option(0)
|
||||
},
|
||||
response: RetVal()
|
||||
}),
|
||||
|
||||
optionalArgs: method(function(a, b=200) {
|
||||
return b;
|
||||
}, {
|
||||
request: {
|
||||
a: Arg(0),
|
||||
b: Arg(1, "number", { optional: true })
|
||||
},
|
||||
response: {
|
||||
value: RetVal("number")
|
||||
},
|
||||
}),
|
||||
|
||||
arrayArgs: method(function(a) {
|
||||
return a;
|
||||
}, {
|
||||
request: {
|
||||
a: Arg(0, "array:number")
|
||||
},
|
||||
response: {
|
||||
arrayReturn: RetVal("array:number")
|
||||
},
|
||||
}),
|
||||
|
||||
nestedArrayArgs: method(function(a) {
|
||||
return a;
|
||||
}, {
|
||||
request: { a: Arg(0, "array:array:number") },
|
||||
response: { value: RetVal("array:array:number") },
|
||||
}),
|
||||
|
||||
/**
|
||||
* Test that the 'type' part of the request packet works
|
||||
* correctly when the type isn't the same as the method name
|
||||
*/
|
||||
renamedEcho: method(function(a) {
|
||||
if (this.conn.currentPacket.type != "echo") {
|
||||
return "goodbye";
|
||||
}
|
||||
return a;
|
||||
}, {
|
||||
request: {
|
||||
type: "echo",
|
||||
a: Arg(0),
|
||||
},
|
||||
response: {
|
||||
value: RetVal("string")
|
||||
},
|
||||
}),
|
||||
|
||||
testOneWay: method(function(a) {
|
||||
// Emit to show that we got this message, because there won't be a response.
|
||||
events.emit(this, "oneway", a);
|
||||
}, {
|
||||
request: { a: Arg(0) },
|
||||
oneway: true
|
||||
}),
|
||||
|
||||
events: {
|
||||
"oneway": { a: Arg(0) }
|
||||
}
|
||||
});
|
||||
|
||||
let RootFront = protocol.FrontClass(RootActor, {
|
||||
initialize: function(client) {
|
||||
this.actorID = "root";
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
// Root owns itself.
|
||||
this.manage(this);
|
||||
}
|
||||
});
|
||||
|
||||
function run_test()
|
||||
{
|
||||
DebuggerServer.createRootActor = (conn => {
|
||||
return RootActor(conn);
|
||||
});
|
||||
DebuggerServer.init(() => true);
|
||||
|
||||
check_except(() => {
|
||||
let badActor = ActorClass({
|
||||
missing: preEvent("missing-event", function() {
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
protocol.types.getType("array:array:array:number");
|
||||
protocol.types.getType("array:array:array:number");
|
||||
|
||||
check_except(() => protocol.types.getType("unknown"));
|
||||
check_except(() => protocol.types.getType("array:unknown"));
|
||||
check_except(() => protocol.types.getType("unknown:number"));
|
||||
let trace = connectPipeTracing();
|
||||
let client = new DebuggerClient(trace);
|
||||
let rootClient = RootFront(client);
|
||||
|
||||
client.connect((applicationType, traits) => {
|
||||
trace.expectReceive({"from":"<actorid>","applicationType":"xpcshell-tests","traits":[]});
|
||||
do_check_eq(applicationType, "xpcshell-tests");
|
||||
|
||||
|
||||
rootClient.simpleReturn().then(ret => {
|
||||
trace.expectSend({"type":"simpleReturn","to":"<actorid>"});
|
||||
trace.expectReceive({"value":1,"from":"<actorid>"});
|
||||
do_check_eq(ret, 1);
|
||||
}).then(() => {
|
||||
return rootClient.promiseReturn();
|
||||
}).then(ret => {
|
||||
trace.expectSend({"type":"promiseReturn","to":"<actorid>"});
|
||||
trace.expectReceive({"value":1,"from":"<actorid>"});
|
||||
do_check_eq(ret, 1);
|
||||
}).then(() => {
|
||||
return rootClient.simpleArgs(5, 10)
|
||||
}).then(ret => {
|
||||
trace.expectSend({"type":"simpleArgs","firstArg":5,"secondArg":10,"to":"<actorid>"});
|
||||
trace.expectReceive({"firstResponse":6,"secondResponse":11,"from":"<actorid>"});
|
||||
do_check_eq(ret.firstResponse, 6);
|
||||
do_check_eq(ret.secondResponse, 11);
|
||||
}).then(() => {
|
||||
return rootClient.nestedArgs(1, 2, 3);
|
||||
}).then(ret => {
|
||||
trace.expectSend({"type":"nestedArgs","firstArg":1,"nest":{"secondArg":2,"nest":{"thirdArg":3}},"to":"<actorid>"});
|
||||
trace.expectReceive({"a":1,"b":2,"c":3,"from":"<actorid>"});
|
||||
do_check_eq(ret.a, 1);
|
||||
do_check_eq(ret.b, 2);
|
||||
do_check_eq(ret.c, 3);
|
||||
}).then(() => {
|
||||
return rootClient.optionArgs({
|
||||
"option1": 5,
|
||||
"option2": 10
|
||||
});
|
||||
}).then(ret => {
|
||||
trace.expectSend({"type":"optionArgs","option1":5,"option2":10,"to":"<actorid>"});
|
||||
trace.expectReceive({"option1":5,"option2":10,"from":"<actorid>"});
|
||||
do_check_eq(ret.option1, 5);
|
||||
do_check_eq(ret.option2, 10);
|
||||
}).then(() => {
|
||||
return rootClient.optionArgs({});
|
||||
}).then(ret => {
|
||||
trace.expectSend({"type":"optionArgs","to":"<actorid>"});
|
||||
trace.expectReceive({"from":"<actorid>"});
|
||||
do_check_true(typeof(ret.option1) === "undefined");
|
||||
do_check_true(typeof(ret.option2) === "undefined");
|
||||
}).then(ret => {
|
||||
// Explicitly call an optional argument...
|
||||
return rootClient.optionalArgs(5, 10);
|
||||
}).then(ret => {
|
||||
trace.expectSend({"type":"optionalArgs","a":5,"b":10,"to":"<actorid>"});
|
||||
trace.expectReceive({"value":10,"from":"<actorid>"});
|
||||
do_check_eq(ret, 10);
|
||||
}).then(() => {
|
||||
// Now don't pass the optional argument, expect the default.
|
||||
return rootClient.optionalArgs(5);
|
||||
}).then(ret => {
|
||||
trace.expectSend({"type":"optionalArgs","a":5,"to":"<actorid>"});
|
||||
trace.expectReceive({"value":200,"from":"<actorid>"});
|
||||
do_check_eq(ret, 200);
|
||||
}).then(ret => {
|
||||
return rootClient.arrayArgs([0, 1, 2, 3, 4, 5]);
|
||||
}).then(ret => {
|
||||
trace.expectSend({"type":"arrayArgs","a":[0,1,2,3,4,5],"to":"<actorid>"});
|
||||
trace.expectReceive({"arrayReturn":[0,1,2,3,4,5],"from":"<actorid>"});
|
||||
do_check_eq(ret[0], 0);
|
||||
do_check_eq(ret[5], 5);
|
||||
}).then(() => {
|
||||
return rootClient.arrayArgs([[5]]);
|
||||
}).then(ret => {
|
||||
trace.expectSend({"type":"arrayArgs","a":[[5]],"to":"<actorid>"});
|
||||
trace.expectReceive({"arrayReturn":[[5]],"from":"<actorid>"});
|
||||
do_check_eq(ret[0][0], 5);
|
||||
}).then(() => {
|
||||
return rootClient.renamedEcho("hello");
|
||||
}).then(str => {
|
||||
trace.expectSend({"type":"echo","a":"hello","to":"<actorid>"});
|
||||
trace.expectReceive({"value":"hello","from":"<actorid>"});
|
||||
|
||||
do_check_eq(str, "hello");
|
||||
|
||||
let deferred = defer();
|
||||
rootClient.on("oneway", (response) => {
|
||||
trace.expectSend({"type":"testOneWay","a":"hello","to":"<actorid>"});
|
||||
trace.expectReceive({"type":"oneway","a":"hello","from":"<actorid>"});
|
||||
|
||||
do_check_eq(response, "hello");
|
||||
deferred.resolve();
|
||||
});
|
||||
do_check_true(typeof(rootClient.testOneWay("hello")) === "undefined");
|
||||
return deferred.promise;
|
||||
}).then(() => {
|
||||
client.close(() => {
|
||||
do_test_finished();
|
||||
});
|
||||
}).then(null, err => {
|
||||
do_report_unexpected_exception(err, "Failure executing test");
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
@ -41,6 +41,9 @@ reason = bug 821285
|
||||
[test_eval-03.js]
|
||||
[test_eval-04.js]
|
||||
[test_eval-05.js]
|
||||
[test_protocol_simple.js]
|
||||
[test_protocol_longstring.js]
|
||||
[test_protocol_children.js]
|
||||
[test_breakpoint-01.js]
|
||||
[test_register_actor.js]
|
||||
skip-if = toolkit == "gonk"
|
||||
|
Loading…
Reference in New Issue
Block a user