tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 });