toolkit/devtools/server/tests/unit/test_forwardingprefix.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* Any copyright is dedicated to the Public Domain.
michael@0 2 http://creativecommons.org/publicdomain/zero/1.0/ */
michael@0 3
michael@0 4 /* Exercise prefix-based forwarding of packets to other transports. */
michael@0 5
michael@0 6 var gMainConnection, gMainTransport;
michael@0 7 var gSubconnection1, gSubconnection2;
michael@0 8 var gClient;
michael@0 9
michael@0 10 function run_test()
michael@0 11 {
michael@0 12 DebuggerServer.init();
michael@0 13
michael@0 14 add_test(createMainConnection);
michael@0 15 add_test(TestNoForwardingYet);
michael@0 16 add_test(createSubconnection1);
michael@0 17 add_test(TestForwardPrefix1OnlyRoot);
michael@0 18 add_test(createSubconnection2);
michael@0 19 add_test(TestForwardPrefix12OnlyRoot);
michael@0 20 add_test(TestForwardPrefix12WithActor1);
michael@0 21 add_test(TestForwardPrefix12WithActor12);
michael@0 22 run_next_test();
michael@0 23 }
michael@0 24
michael@0 25 /*
michael@0 26 * Create a pipe connection, and return an object |{ conn, transport }|,
michael@0 27 * where |conn| is the new DebuggerServerConnection instance, and
michael@0 28 * |transport| is the client side of the transport on which it communicates
michael@0 29 * (that is, packets sent on |transport| go to the new connection, and
michael@0 30 * |transport|'s hooks receive replies).
michael@0 31 *
michael@0 32 * |aPrefix| is optional; if present, it's the prefix (minus the ':') for
michael@0 33 * actors in the new connection.
michael@0 34 */
michael@0 35 function newConnection(aPrefix)
michael@0 36 {
michael@0 37 var conn;
michael@0 38 DebuggerServer.createRootActor = function (aConn) {
michael@0 39 conn = aConn;
michael@0 40 return new DebuggerServer.RootActor(aConn, {});
michael@0 41 };
michael@0 42
michael@0 43 var transport = DebuggerServer.connectPipe(aPrefix);
michael@0 44
michael@0 45 return { conn: conn, transport: transport };
michael@0 46 }
michael@0 47
michael@0 48 /* Create the main connection for these tests. */
michael@0 49 function createMainConnection()
michael@0 50 {
michael@0 51 ({ conn: gMainConnection, transport: gMainTransport }) = newConnection();
michael@0 52 gClient = new DebuggerClient(gMainTransport);
michael@0 53 gClient.connect((aType, aTraits) => run_next_test());
michael@0 54 }
michael@0 55
michael@0 56 /*
michael@0 57 * Exchange 'echo' messages with five actors:
michael@0 58 * - root
michael@0 59 * - prefix1:root
michael@0 60 * - prefix1:actor
michael@0 61 * - prefix2:root
michael@0 62 * - prefix2:actor
michael@0 63 *
michael@0 64 * Expect proper echos from those named in |aReachables|, and 'noSuchActor'
michael@0 65 * errors from the others. When we've gotten all our replies (errors or
michael@0 66 * otherwise), call |aCompleted|.
michael@0 67 *
michael@0 68 * To avoid deep stacks, we call aCompleted from the next tick.
michael@0 69 */
michael@0 70 function tryActors(aReachables, aCompleted) {
michael@0 71 let count = 0;
michael@0 72
michael@0 73 let outerActor;
michael@0 74 for (outerActor of [ 'root',
michael@0 75 'prefix1:root', 'prefix1:actor',
michael@0 76 'prefix2:root', 'prefix2:actor' ]) {
michael@0 77 /*
michael@0 78 * Let each callback capture its own iteration's value; outerActor is
michael@0 79 * local to the whole loop, not to a single iteration.
michael@0 80 */
michael@0 81 let actor = outerActor;
michael@0 82
michael@0 83 count++;
michael@0 84
michael@0 85 gClient.request({ to: actor, type: 'echo', value: 'tango'}, // phone home
michael@0 86 (aResponse) => {
michael@0 87 if (aReachables.has(actor))
michael@0 88 do_check_matches({ from: actor, type: 'echo', value: 'tango' }, aResponse);
michael@0 89 else
michael@0 90 do_check_matches({ from: actor, error: 'noSuchActor' }, aResponse);
michael@0 91
michael@0 92 if (--count == 0)
michael@0 93 do_execute_soon(aCompleted, "tryActors callback " + aCompleted.name);
michael@0 94 });
michael@0 95 }
michael@0 96 }
michael@0 97
michael@0 98 /*
michael@0 99 * With no forwarding established, sending messages to root should work,
michael@0 100 * but sending messages to prefixed actor names, or anyone else, should get
michael@0 101 * an error.
michael@0 102 */
michael@0 103 function TestNoForwardingYet()
michael@0 104 {
michael@0 105 tryActors(Set(['root']), run_next_test);
michael@0 106 }
michael@0 107
michael@0 108 /*
michael@0 109 * Create a new pipe connection which forwards its reply packets to
michael@0 110 * gMainConnection's client, and to which gMainConnection forwards packets
michael@0 111 * directed to actors whose names begin with |aPrefix + ':'|, and.
michael@0 112 *
michael@0 113 * Return an object { conn, transport }, as for newConnection.
michael@0 114 */
michael@0 115 function newSubconnection(aPrefix)
michael@0 116 {
michael@0 117 let { conn, transport } = newConnection(aPrefix);
michael@0 118 transport.hooks = {
michael@0 119 onPacket: (aPacket) => gMainConnection.send(aPacket),
michael@0 120 onClosed: () => {}
michael@0 121 }
michael@0 122 gMainConnection.setForwarding(aPrefix, transport);
michael@0 123
michael@0 124 return { conn: conn, transport: transport };
michael@0 125 }
michael@0 126
michael@0 127 /* Create a second root actor, to which we can forward things. */
michael@0 128 function createSubconnection1()
michael@0 129 {
michael@0 130 let { conn, transport } = newSubconnection('prefix1');
michael@0 131 gSubconnection1 = conn;
michael@0 132 transport.ready();
michael@0 133 gClient.expectReply('prefix1:root', (aReply) => run_next_test());
michael@0 134 }
michael@0 135
michael@0 136 // Establish forwarding, but don't put any actors in that server.
michael@0 137 function TestForwardPrefix1OnlyRoot()
michael@0 138 {
michael@0 139 tryActors(Set(['root', 'prefix1:root']), run_next_test);
michael@0 140 }
michael@0 141
michael@0 142 /* Create a third root actor, to which we can forward things. */
michael@0 143 function createSubconnection2()
michael@0 144 {
michael@0 145 let { conn, transport } = newSubconnection('prefix2');
michael@0 146 gSubconnection2 = conn;
michael@0 147 transport.ready();
michael@0 148 gClient.expectReply('prefix2:root', (aReply) => run_next_test());
michael@0 149 }
michael@0 150
michael@0 151 function TestForwardPrefix12OnlyRoot()
michael@0 152 {
michael@0 153 tryActors(Set(['root', 'prefix1:root', 'prefix2:root']), run_next_test);
michael@0 154 }
michael@0 155
michael@0 156 // A dumb actor that implements 'echo'.
michael@0 157 //
michael@0 158 // It's okay that both subconnections' actors behave identically, because
michael@0 159 // the reply-sending code attaches the replying actor's name to the packet,
michael@0 160 // so simply matching the 'from' field in the reply ensures that we heard
michael@0 161 // from the right actor.
michael@0 162 function EchoActor(aConnection)
michael@0 163 {
michael@0 164 this.conn = aConnection;
michael@0 165 }
michael@0 166 EchoActor.prototype.actorPrefix = "EchoActor";
michael@0 167 EchoActor.prototype.onEcho = function (aRequest) {
michael@0 168 /*
michael@0 169 * Request packets are frozen. Copy aRequest, so that
michael@0 170 * DebuggerServerConnection.onPacket can attach a 'from' property.
michael@0 171 */
michael@0 172 return JSON.parse(JSON.stringify(aRequest));
michael@0 173 };
michael@0 174 EchoActor.prototype.requestTypes = {
michael@0 175 "echo": EchoActor.prototype.onEcho
michael@0 176 };
michael@0 177
michael@0 178 function TestForwardPrefix12WithActor1()
michael@0 179 {
michael@0 180 let actor = new EchoActor(gSubconnection1)
michael@0 181 actor.actorID = 'prefix1:actor';
michael@0 182 gSubconnection1.addActor(actor);
michael@0 183
michael@0 184 tryActors(Set(['root', 'prefix1:root', 'prefix1:actor', 'prefix2:root']), run_next_test);
michael@0 185 }
michael@0 186
michael@0 187 function TestForwardPrefix12WithActor12()
michael@0 188 {
michael@0 189 let actor = new EchoActor(gSubconnection2)
michael@0 190 actor.actorID = 'prefix2:actor';
michael@0 191 gSubconnection2.addActor(actor);
michael@0 192
michael@0 193 tryActors(Set(['root', 'prefix1:root', 'prefix1:actor', 'prefix2:root', 'prefix2:actor']), run_next_test);
michael@0 194 }

mercurial