tor-browser

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

test_net_addr.js (5606B)


      1 "use strict";
      2 
      3 var CC = Components.Constructor;
      4 
      5 const ServerSocket = CC(
      6  "@mozilla.org/network/server-socket;1",
      7  "nsIServerSocket",
      8  "init"
      9 );
     10 
     11 /**
     12 * TestServer: A single instance of this is created as |serv|.  When created,
     13 * it starts listening on the loopback address on port |serv.port|.  Tests will
     14 * connect to it after setting |serv.acceptCallback|, which is invoked after it
     15 * accepts a connection.
     16 *
     17 * Within |serv.acceptCallback|, various properties of |serv| can be used to
     18 * run checks. After the callback, the connection is closed, but the server
     19 * remains listening until |serv.stop|
     20 *
     21 * Note: TestServer can only handle a single connection at a time.  Tests
     22 * should use run_next_test at the end of |serv.acceptCallback| to start the
     23 * following test which creates a connection.
     24 */
     25 function TestServer() {
     26  this.reset();
     27 
     28  // start server.
     29  // any port (-1), loopback only (true), default backlog (-1)
     30  this.listener = ServerSocket(-1, true, -1);
     31  this.port = this.listener.port;
     32  info("server: listening on " + this.port);
     33  this.listener.asyncListen(this);
     34 }
     35 
     36 TestServer.prototype = {
     37  onSocketAccepted(socket, trans) {
     38    info("server: got client connection");
     39 
     40    // one connection at a time.
     41    if (this.input !== null) {
     42      try {
     43        socket.close();
     44      } catch (ignore) {}
     45      do_throw("Test written to handle one connection at a time.");
     46    }
     47 
     48    try {
     49      this.input = trans.openInputStream(0, 0, 0);
     50      this.output = trans.openOutputStream(0, 0, 0);
     51      this.selfAddr = trans.getScriptableSelfAddr();
     52      this.peerAddr = trans.getScriptablePeerAddr();
     53 
     54      this.acceptCallback();
     55    } catch (e) {
     56      /* In a native callback such as onSocketAccepted, exceptions might not
     57       * get output correctly or logged to test output. Send them through
     58       * do_throw, which fails the test immediately. */
     59      do_report_unexpected_exception(e, "in TestServer.onSocketAccepted");
     60    }
     61 
     62    this.reset();
     63  },
     64 
     65  onStopListening() {},
     66 
     67  /**
     68   * Called to close a connection and clean up properties.
     69   */
     70  reset() {
     71    if (this.input) {
     72      try {
     73        this.input.close();
     74      } catch (ignore) {}
     75    }
     76    if (this.output) {
     77      try {
     78        this.output.close();
     79      } catch (ignore) {}
     80    }
     81 
     82    this.input = null;
     83    this.output = null;
     84    this.acceptCallback = null;
     85    this.selfAddr = null;
     86    this.peerAddr = null;
     87  },
     88 
     89  /**
     90   * Cleanup for TestServer and this test case.
     91   */
     92  stop() {
     93    this.reset();
     94    try {
     95      this.listener.close();
     96    } catch (ignore) {}
     97  },
     98 };
     99 
    100 /**
    101 * Helper function.
    102 * Compares two nsINetAddr objects and ensures they are logically equivalent.
    103 */
    104 function checkAddrEqual(lhs, rhs) {
    105  Assert.equal(lhs.family, rhs.family);
    106 
    107  if (lhs.family === Ci.nsINetAddr.FAMILY_INET) {
    108    Assert.equal(lhs.address, rhs.address);
    109    Assert.equal(lhs.port, rhs.port);
    110  }
    111 
    112  /* TODO: fully support ipv6 and local */
    113 }
    114 
    115 /**
    116 * An instance of SocketTransportService, used to create connections.
    117 */
    118 var sts;
    119 
    120 /**
    121 * Single instance of TestServer
    122 */
    123 var serv;
    124 
    125 /**
    126 * A place for individual tests to place Objects of importance for access
    127 * throughout asynchronous testing.  Particularly important for any output or
    128 * input streams opened, as cleanup of those objects (by the garbage collector)
    129 * causes the stream to close and may have other side effects.
    130 */
    131 var testDataStore = null;
    132 
    133 /**
    134 * IPv4 test.
    135 */
    136 function testIpv4() {
    137  testDataStore = {
    138    transport: null,
    139    ouput: null,
    140  };
    141 
    142  serv.acceptCallback = function () {
    143    // disable the timeoutCallback
    144    serv.timeoutCallback = function () {};
    145 
    146    var selfAddr = testDataStore.transport.getScriptableSelfAddr();
    147    var peerAddr = testDataStore.transport.getScriptablePeerAddr();
    148 
    149    // check peerAddr against expected values
    150    Assert.equal(peerAddr.family, Ci.nsINetAddr.FAMILY_INET);
    151    Assert.equal(peerAddr.port, testDataStore.transport.port);
    152    Assert.equal(peerAddr.port, serv.port);
    153    Assert.equal(peerAddr.address, "127.0.0.1");
    154 
    155    // check selfAddr against expected values
    156    Assert.equal(selfAddr.family, Ci.nsINetAddr.FAMILY_INET);
    157    Assert.equal(selfAddr.address, "127.0.0.1");
    158 
    159    // check that selfAddr = server.peerAddr and vice versa.
    160    checkAddrEqual(selfAddr, serv.peerAddr);
    161    checkAddrEqual(peerAddr, serv.selfAddr);
    162 
    163    testDataStore = null;
    164    executeSoon(run_next_test);
    165  };
    166 
    167  // Useful timeout for debugging test hangs
    168  /*serv.timeoutCallback = function(tname) {
    169    if (tname === 'testIpv4')
    170      do_throw('testIpv4 never completed a connection to TestServ');
    171  };
    172  do_timeout(connectTimeout, function(){ serv.timeoutCallback('testIpv4'); });*/
    173 
    174  testDataStore.transport = sts.createTransport(
    175    [],
    176    "127.0.0.1",
    177    serv.port,
    178    null,
    179    null
    180  );
    181  /*
    182   * Need to hold |output| so that the output stream doesn't close itself and
    183   * the associated connection.
    184   */
    185  testDataStore.output = testDataStore.transport.openOutputStream(
    186    Ci.nsITransport.OPEN_BLOCKING,
    187    0,
    188    0
    189  );
    190 
    191  /* NEXT:
    192   * openOutputStream -> onSocketAccepted -> acceptedCallback -> run_next_test
    193   * OR (if the above timeout is uncommented)
    194   * <connectTimeout lapses> -> timeoutCallback -> do_throw
    195   */
    196 }
    197 
    198 /**
    199 * Running the tests.
    200 */
    201 function run_test() {
    202  sts = Cc["@mozilla.org/network/socket-transport-service;1"].getService(
    203    Ci.nsISocketTransportService
    204  );
    205  serv = new TestServer();
    206 
    207  registerCleanupFunction(function () {
    208    serv.stop();
    209  });
    210 
    211  add_test(testIpv4);
    212  /* TODO: testIpv6 */
    213  /* TODO: testLocal */
    214 
    215  run_next_test();
    216 }