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: let protocol = devtools.require("devtools/server/protocol"); michael@0: let {method, RetVal, Arg, Option} = protocol; michael@0: let events = devtools.require("sdk/event/core"); michael@0: let {LongStringActor} = devtools.require("devtools/server/actors/string"); 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: DebuggerServer.LONG_STRING_LENGTH = DebuggerServer.LONG_STRING_INITIAL_LENGTH = DebuggerServer.LONG_STRING_READ_LENGTH = 5; michael@0: michael@0: let SHORT_STR = "abc"; michael@0: let LONG_STR = "abcdefghijklmnop"; michael@0: michael@0: let rootActor = null; michael@0: michael@0: let RootActor = protocol.ActorClass({ michael@0: typeName: "root", michael@0: michael@0: initialize: function(conn) { michael@0: rootActor = this; 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: shortString: method(function() { michael@0: return new LongStringActor(this.conn, SHORT_STR); michael@0: }, { michael@0: response: { value: RetVal("longstring") }, michael@0: }), michael@0: michael@0: longString: method(function() { michael@0: return new LongStringActor(this.conn, LONG_STR); michael@0: }, { michael@0: response: { value: RetVal("longstring") }, michael@0: }), michael@0: michael@0: emitShortString: method(function() { michael@0: events.emit(this, "string-event", new LongStringActor(this.conn, SHORT_STR)); michael@0: }, { michael@0: oneway: true, michael@0: }), michael@0: michael@0: emitLongString: method(function() { michael@0: events.emit(this, "string-event", new LongStringActor(this.conn, LONG_STR)); michael@0: }, { michael@0: oneway: true, michael@0: }), michael@0: michael@0: events: { michael@0: "string-event": { michael@0: str: Arg(0, "longstring") michael@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: michael@0: DebuggerServer.init(() => true); michael@0: let trace = connectPipeTracing(); michael@0: let client = new DebuggerClient(trace); michael@0: let rootClient; michael@0: michael@0: let strfront = null; michael@0: michael@0: let expectRootChildren = function(size) { michael@0: do_check_eq(rootActor.__poolMap.size, size + 1); michael@0: do_check_eq(rootClient.__poolMap.size, size + 1); michael@0: } michael@0: michael@0: michael@0: client.connect((applicationType, traits) => { michael@0: rootClient = RootFront(client); michael@0: michael@0: // Root actor has no children yet. michael@0: expectRootChildren(0); michael@0: michael@0: trace.expectReceive({"from":"","applicationType":"xpcshell-tests","traits":[]}); michael@0: do_check_eq(applicationType, "xpcshell-tests"); michael@0: rootClient.shortString().then(ret => { michael@0: trace.expectSend({"type":"shortString","to":""}); michael@0: trace.expectReceive({"value":"abc","from":""}); michael@0: michael@0: // Should only own the one reference (itself) at this point. michael@0: expectRootChildren(0); michael@0: strfront = ret; michael@0: }).then(() => { michael@0: return strfront.string(); michael@0: }).then(ret => { michael@0: do_check_eq(ret, SHORT_STR); michael@0: }).then(() => { michael@0: return rootClient.longString(); michael@0: }).then(ret => { michael@0: trace.expectSend({"type":"longString","to":""}); michael@0: trace.expectReceive({"value":{"type":"longString","actor":"","length":16,"initial":"abcde"},"from":""}); michael@0: michael@0: strfront = ret; michael@0: // Should own a reference to itself and an extra string now. michael@0: expectRootChildren(1); michael@0: }).then(() => { michael@0: return strfront.string(); michael@0: }).then(ret => { michael@0: trace.expectSend({"type":"substring","start":5,"end":10,"to":""}); michael@0: trace.expectReceive({"substring":"fghij","from":""}); michael@0: trace.expectSend({"type":"substring","start":10,"end":15,"to":""}); michael@0: trace.expectReceive({"substring":"klmno","from":""}); michael@0: trace.expectSend({"type":"substring","start":15,"end":20,"to":""}); michael@0: trace.expectReceive({"substring":"p","from":""}); michael@0: michael@0: do_check_eq(ret, LONG_STR); michael@0: }).then(() => { michael@0: return strfront.release(); michael@0: }).then(() => { michael@0: trace.expectSend({"type":"release","to":""}); michael@0: trace.expectReceive({"from":""}); michael@0: michael@0: // That reference should be removed now. michael@0: expectRootChildren(0); michael@0: }).then(() => { michael@0: let deferred = promise.defer(); michael@0: rootClient.once("string-event", (str) => { michael@0: trace.expectSend({"type":"emitShortString","to":""}); michael@0: trace.expectReceive({"type":"string-event","str":"abc","from":""}); michael@0: michael@0: do_check_true(!!str); michael@0: strfront = str; michael@0: // Shouldn't generate any new references michael@0: expectRootChildren(0); michael@0: // will generate no packets. michael@0: strfront.string().then((value) => { deferred.resolve(value) }); michael@0: }); michael@0: rootClient.emitShortString(); michael@0: return deferred.promise; michael@0: }).then(value => { michael@0: do_check_eq(value, SHORT_STR); michael@0: }).then(() => { michael@0: // Will generate no packets michael@0: return strfront.release(); michael@0: }).then(() => { michael@0: let deferred = promise.defer(); michael@0: rootClient.once("string-event", (str) => { michael@0: trace.expectSend({"type":"emitLongString","to":""}); michael@0: trace.expectReceive({"type":"string-event","str":{"type":"longString","actor":"","length":16,"initial":"abcde"},"from":""}); michael@0: michael@0: do_check_true(!!str); michael@0: // Should generate one new reference michael@0: expectRootChildren(1); michael@0: strfront = str; michael@0: strfront.string().then((value) => { michael@0: trace.expectSend({"type":"substring","start":5,"end":10,"to":""}); michael@0: trace.expectReceive({"substring":"fghij","from":""}); michael@0: trace.expectSend({"type":"substring","start":10,"end":15,"to":""}); michael@0: trace.expectReceive({"substring":"klmno","from":""}); michael@0: trace.expectSend({"type":"substring","start":15,"end":20,"to":""}); michael@0: trace.expectReceive({"substring":"p","from":""}); michael@0: michael@0: deferred.resolve(value); michael@0: }); michael@0: }); michael@0: rootClient.emitLongString(); michael@0: return deferred.promise; michael@0: }).then(value => { michael@0: do_check_eq(value, LONG_STR); michael@0: }).then(() => { michael@0: return strfront.release(); michael@0: }).then(() => { michael@0: trace.expectSend({"type":"release","to":""}); michael@0: trace.expectReceive({"from":""}); michael@0: expectRootChildren(0); 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: }