michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: /** michael@0: * Test simple requests using the protocol helpers. michael@0: */ michael@0: michael@0: let protocol = devtools.require("devtools/server/protocol"); michael@0: let {method, Arg, Option, RetVal} = protocol; michael@0: let events = devtools.require("sdk/event/core"); michael@0: michael@0: function simpleHello() { michael@0: return { michael@0: from: "root", michael@0: applicationType: "xpcshell-tests", michael@0: traits: [], michael@0: } michael@0: } michael@0: michael@0: let RootActor = protocol.ActorClass({ michael@0: typeName: "root", michael@0: initialize: function(conn) { michael@0: protocol.Actor.prototype.initialize.call(this, conn); michael@0: // Root actor owns itself. michael@0: this.manage(this); michael@0: this.actorID = "root"; michael@0: }, michael@0: michael@0: sayHello: simpleHello, michael@0: michael@0: simpleReturn: method(function() { michael@0: return 1; michael@0: }, { michael@0: response: { value: RetVal() }, michael@0: }), michael@0: michael@0: promiseReturn: method(function() { michael@0: return promise.resolve(1); michael@0: }, { michael@0: response: { value: RetVal("number") }, michael@0: }), michael@0: michael@0: simpleArgs: method(function(a, b) { michael@0: return { firstResponse: a + 1, secondResponse: b + 1 }; michael@0: }, { michael@0: request: { michael@0: firstArg: Arg(0), michael@0: secondArg: Arg(1), michael@0: }, michael@0: response: RetVal() michael@0: }), michael@0: michael@0: nestedArgs: method(function(a, b, c) { michael@0: return { a: a, b: b, c: c }; michael@0: }, { michael@0: request: { michael@0: firstArg: Arg(0), michael@0: nest: { michael@0: secondArg: Arg(1), michael@0: nest: { michael@0: thirdArg: Arg(2) michael@0: } michael@0: } michael@0: }, michael@0: response: RetVal() michael@0: }), michael@0: michael@0: optionArgs: method(function(options) { michael@0: return { option1: options.option1, option2: options.option2 }; michael@0: }, { michael@0: request: { michael@0: option1: Option(0), michael@0: option2: Option(0) michael@0: }, michael@0: response: RetVal() michael@0: }), michael@0: michael@0: optionalArgs: method(function(a, b=200) { michael@0: return b; michael@0: }, { michael@0: request: { michael@0: a: Arg(0), michael@0: b: Arg(1, "nullable:number") michael@0: }, michael@0: response: { michael@0: value: RetVal("number") michael@0: }, michael@0: }), michael@0: michael@0: arrayArgs: method(function(a) { michael@0: return a; michael@0: }, { michael@0: request: { michael@0: a: Arg(0, "array:number") michael@0: }, michael@0: response: { michael@0: arrayReturn: RetVal("array:number") michael@0: }, michael@0: }), michael@0: michael@0: nestedArrayArgs: method(function(a) { michael@0: return a; michael@0: }, { michael@0: request: { a: Arg(0, "array:array:number") }, michael@0: response: { value: RetVal("array:array:number") }, michael@0: }), michael@0: michael@0: /** michael@0: * Test that the 'type' part of the request packet works michael@0: * correctly when the type isn't the same as the method name michael@0: */ michael@0: renamedEcho: method(function(a) { michael@0: if (this.conn.currentPacket.type != "echo") { michael@0: return "goodbye"; michael@0: } michael@0: return a; michael@0: }, { michael@0: request: { michael@0: type: "echo", michael@0: a: Arg(0), michael@0: }, michael@0: response: { michael@0: value: RetVal("string") michael@0: }, michael@0: }), michael@0: michael@0: testOneWay: method(function(a) { michael@0: // Emit to show that we got this message, because there won't be a response. michael@0: events.emit(this, "oneway", a); michael@0: }, { michael@0: request: { a: Arg(0) }, michael@0: oneway: true michael@0: }), michael@0: michael@0: events: { michael@0: "oneway": { a: Arg(0) } michael@0: } michael@0: }); michael@0: michael@0: let RootFront = protocol.FrontClass(RootActor, { michael@0: initialize: function(client) { michael@0: this.actorID = "root"; michael@0: protocol.Front.prototype.initialize.call(this, client); michael@0: // Root owns itself. michael@0: this.manage(this); michael@0: } michael@0: }); michael@0: michael@0: function run_test() michael@0: { michael@0: DebuggerServer.createRootActor = (conn => { michael@0: return RootActor(conn); michael@0: }); michael@0: DebuggerServer.init(() => true); michael@0: michael@0: check_except(() => { michael@0: let badActor = ActorClass({ michael@0: missing: preEvent("missing-event", function() { michael@0: }) michael@0: }) michael@0: }); michael@0: michael@0: protocol.types.getType("array:array:array:number"); michael@0: protocol.types.getType("array:array:array:number"); michael@0: michael@0: check_except(() => protocol.types.getType("unknown")); michael@0: check_except(() => protocol.types.getType("array:unknown")); michael@0: check_except(() => protocol.types.getType("unknown:number")); michael@0: let trace = connectPipeTracing(); michael@0: let client = new DebuggerClient(trace); michael@0: let rootClient; michael@0: michael@0: client.connect((applicationType, traits) => { michael@0: trace.expectReceive({"from":"","applicationType":"xpcshell-tests","traits":[]}); michael@0: do_check_eq(applicationType, "xpcshell-tests"); michael@0: michael@0: rootClient = RootFront(client); michael@0: michael@0: rootClient.simpleReturn().then(ret => { michael@0: trace.expectSend({"type":"simpleReturn","to":""}); michael@0: trace.expectReceive({"value":1,"from":""}); michael@0: do_check_eq(ret, 1); michael@0: }).then(() => { michael@0: return rootClient.promiseReturn(); michael@0: }).then(ret => { michael@0: trace.expectSend({"type":"promiseReturn","to":""}); michael@0: trace.expectReceive({"value":1,"from":""}); michael@0: do_check_eq(ret, 1); michael@0: }).then(() => { michael@0: // Missing argument should throw an exception michael@0: check_except(() => { michael@0: rootClient.simpleArgs(5); michael@0: }); michael@0: michael@0: return rootClient.simpleArgs(5, 10) michael@0: }).then(ret => { michael@0: trace.expectSend({"type":"simpleArgs","firstArg":5,"secondArg":10,"to":""}); michael@0: trace.expectReceive({"firstResponse":6,"secondResponse":11,"from":""}); michael@0: do_check_eq(ret.firstResponse, 6); michael@0: do_check_eq(ret.secondResponse, 11); michael@0: }).then(() => { michael@0: return rootClient.nestedArgs(1, 2, 3); michael@0: }).then(ret => { michael@0: trace.expectSend({"type":"nestedArgs","firstArg":1,"nest":{"secondArg":2,"nest":{"thirdArg":3}},"to":""}); michael@0: trace.expectReceive({"a":1,"b":2,"c":3,"from":""}); michael@0: do_check_eq(ret.a, 1); michael@0: do_check_eq(ret.b, 2); michael@0: do_check_eq(ret.c, 3); michael@0: }).then(() => { michael@0: return rootClient.optionArgs({ michael@0: "option1": 5, michael@0: "option2": 10 michael@0: }); michael@0: }).then(ret => { michael@0: trace.expectSend({"type":"optionArgs","option1":5,"option2":10,"to":""}); michael@0: trace.expectReceive({"option1":5,"option2":10,"from":""}); michael@0: do_check_eq(ret.option1, 5); michael@0: do_check_eq(ret.option2, 10); michael@0: }).then(() => { michael@0: return rootClient.optionArgs({}); michael@0: }).then(ret => { michael@0: trace.expectSend({"type":"optionArgs","to":""}); michael@0: trace.expectReceive({"from":""}); michael@0: do_check_true(typeof(ret.option1) === "undefined"); michael@0: do_check_true(typeof(ret.option2) === "undefined"); michael@0: }).then(ret => { michael@0: // Explicitly call an optional argument... michael@0: return rootClient.optionalArgs(5, 10); michael@0: }).then(ret => { michael@0: trace.expectSend({"type":"optionalArgs","a":5,"b":10,"to":""}); michael@0: trace.expectReceive({"value":10,"from":""}); michael@0: do_check_eq(ret, 10); michael@0: }).then(() => { michael@0: // Now don't pass the optional argument, expect the default. michael@0: return rootClient.optionalArgs(5); michael@0: }).then(ret => { michael@0: trace.expectSend({"type":"optionalArgs","a":5,"to":""}); michael@0: trace.expectReceive({"value":200,"from":""}); michael@0: do_check_eq(ret, 200); michael@0: }).then(ret => { michael@0: return rootClient.arrayArgs([0, 1, 2, 3, 4, 5]); michael@0: }).then(ret => { michael@0: trace.expectSend({"type":"arrayArgs","a":[0,1,2,3,4,5],"to":""}); michael@0: trace.expectReceive({"arrayReturn":[0,1,2,3,4,5],"from":""}); michael@0: do_check_eq(ret[0], 0); michael@0: do_check_eq(ret[5], 5); michael@0: }).then(() => { michael@0: return rootClient.arrayArgs([[5]]); michael@0: }).then(ret => { michael@0: trace.expectSend({"type":"arrayArgs","a":[[5]],"to":""}); michael@0: trace.expectReceive({"arrayReturn":[[5]],"from":""}); michael@0: do_check_eq(ret[0][0], 5); michael@0: }).then(() => { michael@0: return rootClient.renamedEcho("hello"); michael@0: }).then(str => { michael@0: trace.expectSend({"type":"echo","a":"hello","to":""}); michael@0: trace.expectReceive({"value":"hello","from":""}); michael@0: michael@0: do_check_eq(str, "hello"); michael@0: michael@0: let deferred = promise.defer(); michael@0: rootClient.on("oneway", (response) => { michael@0: trace.expectSend({"type":"testOneWay","a":"hello","to":""}); michael@0: trace.expectReceive({"type":"oneway","a":"hello","from":""}); michael@0: michael@0: do_check_eq(response, "hello"); michael@0: deferred.resolve(); michael@0: }); michael@0: do_check_true(typeof(rootClient.testOneWay("hello")) === "undefined"); michael@0: return deferred.promise; michael@0: }).then(() => { michael@0: client.close(() => { michael@0: do_test_finished(); michael@0: }); michael@0: }).then(null, err => { michael@0: do_report_unexpected_exception(err, "Failure executing test"); michael@0: }); michael@0: }); michael@0: do_test_pending(); michael@0: }