Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* Any copyright is dedicated to the Public Domain.
"use strict";
/**
* Test simple requests using the protocol helpers.
*/
var protocol = require("resource://devtools/shared/protocol.js");
var { Arg, Option, RetVal } = protocol;
var EventEmitter = require("resource://devtools/shared/event-emitter.js");
const rootSpec = protocol.generateActorSpec({
typeName: "root",
events: {
oneway: { a: Arg(0) },
falsyOptions: {
zero: Option(0),
farce: Option(0),
},
},
methods: {
simpleReturn: {
response: { value: RetVal() },
},
promiseReturn: {
response: { value: RetVal("number") },
},
simpleArgs: {
request: {
firstArg: Arg(0),
secondArg: Arg(1),
},
response: RetVal(),
},
optionArgs: {
request: {
option1: Option(0),
option2: Option(0),
},
response: RetVal(),
},
optionalArgs: {
request: {
a: Arg(0),
b: Arg(1, "nullable:number"),
},
response: {
value: RetVal("number"),
},
},
arrayArgs: {
request: {
a: Arg(0, "array:number"),
},
response: {
arrayReturn: RetVal("array:number"),
},
},
nestedArrayArgs: {
request: { a: Arg(0, "array:array:number") },
response: { value: RetVal("array:array:number") },
},
renamedEcho: {
request: {
type: "echo",
a: Arg(0),
},
response: {
value: RetVal("string"),
},
},
testOneWay: {
request: { a: Arg(0) },
oneway: true,
},
emitFalsyOptions: {
oneway: true,
},
},
});
class RootActor extends protocol.Actor {
constructor(conn) {
super(conn, rootSpec);
// Root actor owns itself.
this.manage(this);
this.actorID = "root";
}
sayHello() {
return {
from: "root",
applicationType: "xpcshell-tests",
traits: [],
};
}
simpleReturn() {
return 1;
}
promiseReturn() {
return Promise.resolve(1);
}
simpleArgs(a, b) {
return { firstResponse: a + 1, secondResponse: b + 1 };
}
optionArgs(options) {
return { option1: options.option1, option2: options.option2 };
}
optionalArgs(a, b = 200) {
return b;
}
arrayArgs(a) {
return a;
}
nestedArrayArgs(a) {
return a;
}
/**
* Test that the 'type' part of the request packet works
* correctly when the type isn't the same as the method name
*/
renamedEcho(a) {
if (this.conn.currentPacket.type != "echo") {
return "goodbye";
}
return a;
}
testOneWay(a) {
// Emit to show that we got this message, because there won't be a response.
EventEmitter.emit(this, "oneway", a);
}
emitFalsyOptions() {
EventEmitter.emit(this, "falsyOptions", { zero: 0, farce: false });
}
}
class RootFront extends protocol.FrontClassWithSpec(rootSpec) {
constructor(client) {
super(client);
this.actorID = "root";
// Root owns itself.
this.manage(this);
}
}
protocol.registerFront(RootFront);
add_task(async function () {
DevToolsServer.createRootActor = conn => {
return new RootActor(conn);
};
DevToolsServer.init();
protocol.types.getType("array:array:array:number");
protocol.types.getType("array:array:array:number");
Assert.throws(
() => protocol.types.getType("unknown"),
/Unknown type:/,
"Should throw for unknown type"
);
Assert.throws(
() => protocol.types.getType("array:unknown"),
/Unknown type:/,
"Should throw for unknown type"
);
Assert.throws(
() => protocol.types.getType("unknown:number"),
/Unknown collection type:/,
"Should throw for unknown collection type"
);
const trace = connectPipeTracing();
const client = new DevToolsClient(trace);
const [applicationType] = await client.connect();
trace.expectReceive({
from: "<actorid>",
applicationType: "xpcshell-tests",
traits: [],
});
Assert.equal(applicationType, "xpcshell-tests");
const rootFront = client.mainRoot;
let ret = await rootFront.simpleReturn();
trace.expectSend({ type: "simpleReturn", to: "<actorid>" });
trace.expectReceive({ value: 1, from: "<actorid>" });
Assert.equal(ret, 1);
ret = await rootFront.promiseReturn();
trace.expectSend({ type: "promiseReturn", to: "<actorid>" });
trace.expectReceive({ value: 1, from: "<actorid>" });
Assert.equal(ret, 1);
Assert.throws(
() => rootFront.simpleArgs(5),
/undefined passed where a value is required/,
"Should throw if simpleArgs is missing an argument."
);
ret = await rootFront.simpleArgs(5, 10);
trace.expectSend({
type: "simpleArgs",
firstArg: 5,
secondArg: 10,
to: "<actorid>",
});
trace.expectReceive({
firstResponse: 6,
secondResponse: 11,
from: "<actorid>",
});
Assert.equal(ret.firstResponse, 6);
Assert.equal(ret.secondResponse, 11);
ret = await rootFront.optionArgs({
option1: 5,
option2: 10,
});
trace.expectSend({
type: "optionArgs",
option1: 5,
option2: 10,
to: "<actorid>",
});
trace.expectReceive({ option1: 5, option2: 10, from: "<actorid>" });
Assert.equal(ret.option1, 5);
Assert.equal(ret.option2, 10);
ret = await rootFront.optionArgs({});
trace.expectSend({ type: "optionArgs", to: "<actorid>" });
trace.expectReceive({ from: "<actorid>" });
Assert.ok(typeof ret.option1 === "undefined");
Assert.ok(typeof ret.option2 === "undefined");
// Explicitly call an optional argument...
ret = await rootFront.optionalArgs(5, 10);
trace.expectSend({
type: "optionalArgs",
a: 5,
b: 10,
to: "<actorid>",
});
trace.expectReceive({ value: 10, from: "<actorid>" });
Assert.equal(ret, 10);
// Now don't pass the optional argument, expect the default.
ret = await rootFront.optionalArgs(5);
trace.expectSend({ type: "optionalArgs", a: 5, to: "<actorid>" });
trace.expectReceive({ value: 200, from: "<actorid>" });
Assert.equal(ret, 200);
ret = await rootFront.arrayArgs([0, 1, 2, 3, 4, 5]);
trace.expectSend({
type: "arrayArgs",
a: [0, 1, 2, 3, 4, 5],
to: "<actorid>",
});
trace.expectReceive({
arrayReturn: [0, 1, 2, 3, 4, 5],
from: "<actorid>",
});
Assert.equal(ret[0], 0);
Assert.equal(ret[5], 5);
ret = await rootFront.arrayArgs([[5]]);
trace.expectSend({ type: "arrayArgs", a: [[5]], to: "<actorid>" });
trace.expectReceive({ arrayReturn: [[5]], from: "<actorid>" });
Assert.equal(ret[0][0], 5);
const str = await rootFront.renamedEcho("hello");
trace.expectSend({ type: "echo", a: "hello", to: "<actorid>" });
trace.expectReceive({ value: "hello", from: "<actorid>" });
Assert.equal(str, "hello");
const onOneWay = rootFront.once("oneway");
Assert.ok(typeof rootFront.testOneWay("hello") === "undefined");
const response = await onOneWay;
trace.expectSend({ type: "testOneWay", a: "hello", to: "<actorid>" });
trace.expectReceive({
type: "oneway",
a: "hello",
from: "<actorid>",
});
Assert.equal(response, "hello");
const onFalsyOptions = rootFront.once("falsyOptions");
rootFront.emitFalsyOptions();
const res = await onFalsyOptions;
trace.expectSend({ type: "emitFalsyOptions", to: "<actorid>" });
trace.expectReceive({
type: "falsyOptions",
farce: false,
zero: 0,
from: "<actorid>",
});
Assert.ok(res.zero === 0);
Assert.ok(res.farce === false);
await client.close();
});