/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Test simple requests using the protocol helpers. */ var protocol = require("devtools/server/protocol"); var {method, Arg, Option, RetVal} = protocol; var events = require("sdk/event/core"); function simpleHello() { return { from: "root", applicationType: "xpcshell-tests", traits: [], } } var 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 promise.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, "nullable:number") }, 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 }), emitFalsyOptions: method(function() { events.emit(this, "falsyOptions", { zero: 0, farce: false }); }, { oneway: true }), events: { "oneway": { a: Arg(0) }, "falsyOptions": { zero: Option(0), farce: Option(0) } } }); var 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(); 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; client.connect((applicationType, traits) => { trace.expectReceive({"from":"","applicationType":"xpcshell-tests","traits":[]}); do_check_eq(applicationType, "xpcshell-tests"); rootClient = RootFront(client); rootClient.simpleReturn().then(ret => { trace.expectSend({"type":"simpleReturn","to":""}); trace.expectReceive({"value":1,"from":""}); do_check_eq(ret, 1); }).then(() => { return rootClient.promiseReturn(); }).then(ret => { trace.expectSend({"type":"promiseReturn","to":""}); trace.expectReceive({"value":1,"from":""}); do_check_eq(ret, 1); }).then(() => { // Missing argument should throw an exception check_except(() => { rootClient.simpleArgs(5); }); return rootClient.simpleArgs(5, 10) }).then(ret => { trace.expectSend({"type":"simpleArgs","firstArg":5,"secondArg":10,"to":""}); trace.expectReceive({"firstResponse":6,"secondResponse":11,"from":""}); 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":""}); trace.expectReceive({"a":1,"b":2,"c":3,"from":""}); 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":""}); trace.expectReceive({"option1":5,"option2":10,"from":""}); do_check_eq(ret.option1, 5); do_check_eq(ret.option2, 10); }).then(() => { return rootClient.optionArgs({}); }).then(ret => { trace.expectSend({"type":"optionArgs","to":""}); trace.expectReceive({"from":""}); do_check_true(typeof(ret.option1) === "undefined"); do_check_true(typeof(ret.option2) === "undefined"); }).then(() => { // Explicitly call an optional argument... return rootClient.optionalArgs(5, 10); }).then(ret => { trace.expectSend({"type":"optionalArgs","a":5,"b":10,"to":""}); trace.expectReceive({"value":10,"from":""}); 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":""}); trace.expectReceive({"value":200,"from":""}); 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":""}); trace.expectReceive({"arrayReturn":[0,1,2,3,4,5],"from":""}); 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":""}); trace.expectReceive({"arrayReturn":[[5]],"from":""}); do_check_eq(ret[0][0], 5); }).then(() => { return rootClient.renamedEcho("hello"); }).then(str => { trace.expectSend({"type":"echo","a":"hello","to":""}); trace.expectReceive({"value":"hello","from":""}); do_check_eq(str, "hello"); let deferred = promise.defer(); rootClient.on("oneway", (response) => { trace.expectSend({"type":"testOneWay","a":"hello","to":""}); trace.expectReceive({"type":"oneway","a":"hello","from":""}); do_check_eq(response, "hello"); deferred.resolve(); }); do_check_true(typeof(rootClient.testOneWay("hello")) === "undefined"); return deferred.promise; }).then(() => { let deferred = promise.defer(); rootClient.on("falsyOptions", res => { trace.expectSend({"type":"emitFalsyOptions", "to":""}); trace.expectReceive({"type":"falsyOptions", "farce":false, "zero": 0, "from":""}); do_check_true(res.zero === 0); do_check_true(res.farce === false); deferred.resolve(); }); rootClient.emitFalsyOptions(); return deferred.promise; }).then(() => { client.close(() => { do_test_finished(); }); }).then(null, err => { do_report_unexpected_exception(err, "Failure executing test"); }); }); do_test_pending(); }