test_protocol_simple.js (7615B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 /** 7 * Test simple requests using the protocol helpers. 8 */ 9 10 var protocol = require("resource://devtools/shared/protocol.js"); 11 var { Arg, Option, RetVal } = protocol; 12 13 const rootSpec = protocol.generateActorSpec({ 14 typeName: "root", 15 16 events: { 17 oneway: { a: Arg(0) }, 18 falsyOptions: { 19 zero: Option(0), 20 farce: Option(0), 21 }, 22 }, 23 24 methods: { 25 simpleReturn: { 26 response: { value: RetVal() }, 27 }, 28 promiseReturn: { 29 response: { value: RetVal("number") }, 30 }, 31 simpleArgs: { 32 request: { 33 firstArg: Arg(0), 34 secondArg: Arg(1), 35 }, 36 response: RetVal(), 37 }, 38 optionArgs: { 39 request: { 40 option1: Option(0), 41 option2: Option(0), 42 }, 43 response: RetVal(), 44 }, 45 optionalArgs: { 46 request: { 47 a: Arg(0), 48 b: Arg(1, "nullable:number"), 49 }, 50 response: { 51 value: RetVal("number"), 52 }, 53 }, 54 arrayArgs: { 55 request: { 56 a: Arg(0, "array:number"), 57 }, 58 response: { 59 arrayReturn: RetVal("array:number"), 60 }, 61 }, 62 nestedArrayArgs: { 63 request: { a: Arg(0, "array:array:number") }, 64 response: { value: RetVal("array:array:number") }, 65 }, 66 renamedEcho: { 67 request: { 68 type: "echo", 69 a: Arg(0), 70 }, 71 response: { 72 value: RetVal("string"), 73 }, 74 }, 75 testOneWay: { 76 request: { a: Arg(0) }, 77 oneway: true, 78 }, 79 emitFalsyOptions: { 80 oneway: true, 81 }, 82 }, 83 }); 84 85 class RootActor extends protocol.Actor { 86 constructor(conn) { 87 super(conn, rootSpec); 88 89 // Root actor owns itself. 90 this.manage(this); 91 this.actorID = "root"; 92 } 93 94 sayHello() { 95 return { 96 from: "root", 97 applicationType: "xpcshell-tests", 98 traits: [], 99 }; 100 } 101 102 simpleReturn() { 103 return 1; 104 } 105 106 promiseReturn() { 107 return Promise.resolve(1); 108 } 109 110 simpleArgs(a, b) { 111 return { firstResponse: a + 1, secondResponse: b + 1 }; 112 } 113 114 optionArgs(options) { 115 return { option1: options.option1, option2: options.option2 }; 116 } 117 118 optionalArgs(a, b = 200) { 119 return b; 120 } 121 122 arrayArgs(a) { 123 return a; 124 } 125 126 nestedArrayArgs(a) { 127 return a; 128 } 129 130 /** 131 * Test that the 'type' part of the request packet works 132 * correctly when the type isn't the same as the method name 133 */ 134 renamedEcho(a) { 135 if (this.conn.currentPacket.type != "echo") { 136 return "goodbye"; 137 } 138 return a; 139 } 140 141 testOneWay(a) { 142 // Emit to show that we got this message, because there won't be a response. 143 this.emit("oneway", a); 144 } 145 146 emitFalsyOptions() { 147 this.emit("falsyOptions", { zero: 0, farce: false }); 148 } 149 } 150 151 class RootFront extends protocol.FrontClassWithSpec(rootSpec) { 152 constructor(client) { 153 super(client); 154 this.actorID = "root"; 155 // Root owns itself. 156 this.manage(this); 157 } 158 159 connect({ frontendVersion }) { 160 this.frontendVersion = frontendVersion; 161 } 162 } 163 protocol.registerFront(RootFront); 164 165 add_task(async function () { 166 DevToolsServer.createRootActor = conn => { 167 return new RootActor(conn); 168 }; 169 DevToolsServer.init(); 170 171 protocol.types.getType("array:array:array:number"); 172 protocol.types.getType("array:array:array:number"); 173 174 Assert.throws( 175 () => protocol.types.getType("unknown"), 176 /Unknown type:/, 177 "Should throw for unknown type" 178 ); 179 Assert.throws( 180 () => protocol.types.getType("array:unknown"), 181 /Unknown type:/, 182 "Should throw for unknown type" 183 ); 184 Assert.throws( 185 () => protocol.types.getType("unknown:number"), 186 /Unknown collection type:/, 187 "Should throw for unknown collection type" 188 ); 189 const trace = connectPipeTracing(); 190 const client = new DevToolsClient(trace); 191 192 const [applicationType] = await client.connect(); 193 trace.expectReceive({ 194 from: "<actorid>", 195 applicationType: "xpcshell-tests", 196 traits: [], 197 }); 198 Assert.equal(applicationType, "xpcshell-tests"); 199 200 const rootFront = client.mainRoot; 201 Assert.equal(typeof rootFront.frontendVersion, "string"); 202 203 let ret = await rootFront.simpleReturn(); 204 trace.expectSend({ type: "simpleReturn", to: "<actorid>" }); 205 trace.expectReceive({ value: 1, from: "<actorid>" }); 206 Assert.equal(ret, 1); 207 208 ret = await rootFront.promiseReturn(); 209 trace.expectSend({ type: "promiseReturn", to: "<actorid>" }); 210 trace.expectReceive({ value: 1, from: "<actorid>" }); 211 Assert.equal(ret, 1); 212 213 Assert.throws( 214 () => rootFront.simpleArgs(5), 215 /undefined passed where a value is required/, 216 "Should throw if simpleArgs is missing an argument." 217 ); 218 219 ret = await rootFront.simpleArgs(5, 10); 220 trace.expectSend({ 221 type: "simpleArgs", 222 firstArg: 5, 223 secondArg: 10, 224 to: "<actorid>", 225 }); 226 trace.expectReceive({ 227 firstResponse: 6, 228 secondResponse: 11, 229 from: "<actorid>", 230 }); 231 Assert.equal(ret.firstResponse, 6); 232 Assert.equal(ret.secondResponse, 11); 233 234 ret = await rootFront.optionArgs({ 235 option1: 5, 236 option2: 10, 237 }); 238 trace.expectSend({ 239 type: "optionArgs", 240 option1: 5, 241 option2: 10, 242 to: "<actorid>", 243 }); 244 trace.expectReceive({ option1: 5, option2: 10, from: "<actorid>" }); 245 Assert.equal(ret.option1, 5); 246 Assert.equal(ret.option2, 10); 247 248 ret = await rootFront.optionArgs({}); 249 trace.expectSend({ type: "optionArgs", to: "<actorid>" }); 250 trace.expectReceive({ from: "<actorid>" }); 251 Assert.strictEqual(typeof ret.option1, "undefined"); 252 Assert.strictEqual(typeof ret.option2, "undefined"); 253 254 // Explicitly call an optional argument... 255 ret = await rootFront.optionalArgs(5, 10); 256 trace.expectSend({ 257 type: "optionalArgs", 258 a: 5, 259 b: 10, 260 to: "<actorid>", 261 }); 262 trace.expectReceive({ value: 10, from: "<actorid>" }); 263 Assert.equal(ret, 10); 264 265 // Now don't pass the optional argument, expect the default. 266 ret = await rootFront.optionalArgs(5); 267 trace.expectSend({ type: "optionalArgs", a: 5, to: "<actorid>" }); 268 trace.expectReceive({ value: 200, from: "<actorid>" }); 269 Assert.equal(ret, 200); 270 271 ret = await rootFront.arrayArgs([0, 1, 2, 3, 4, 5]); 272 trace.expectSend({ 273 type: "arrayArgs", 274 a: [0, 1, 2, 3, 4, 5], 275 to: "<actorid>", 276 }); 277 trace.expectReceive({ 278 arrayReturn: [0, 1, 2, 3, 4, 5], 279 from: "<actorid>", 280 }); 281 Assert.equal(ret[0], 0); 282 Assert.equal(ret[5], 5); 283 284 ret = await rootFront.arrayArgs([[5]]); 285 trace.expectSend({ type: "arrayArgs", a: [[5]], to: "<actorid>" }); 286 trace.expectReceive({ arrayReturn: [[5]], from: "<actorid>" }); 287 Assert.equal(ret[0][0], 5); 288 289 const str = await rootFront.renamedEcho("hello"); 290 trace.expectSend({ type: "echo", a: "hello", to: "<actorid>" }); 291 trace.expectReceive({ value: "hello", from: "<actorid>" }); 292 Assert.equal(str, "hello"); 293 294 const onOneWay = rootFront.once("oneway"); 295 Assert.strictEqual(typeof rootFront.testOneWay("hello"), "undefined"); 296 const response = await onOneWay; 297 trace.expectSend({ type: "testOneWay", a: "hello", to: "<actorid>" }); 298 trace.expectReceive({ 299 type: "oneway", 300 a: "hello", 301 from: "<actorid>", 302 }); 303 Assert.equal(response, "hello"); 304 305 const onFalsyOptions = rootFront.once("falsyOptions"); 306 rootFront.emitFalsyOptions(); 307 const res = await onFalsyOptions; 308 trace.expectSend({ type: "emitFalsyOptions", to: "<actorid>" }); 309 trace.expectReceive({ 310 type: "falsyOptions", 311 farce: false, 312 zero: 0, 313 from: "<actorid>", 314 }); 315 316 Assert.strictEqual(res.zero, 0); 317 Assert.strictEqual(res.farce, false); 318 319 await client.close(); 320 });