netwerk/test/unit/test_unix_domain.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/netwerk/test/unit/test_unix_domain.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,545 @@
     1.4 +// Exercise Unix domain sockets.
     1.5 +
     1.6 +const CC = Components.Constructor;
     1.7 +
     1.8 +const UnixServerSocket = CC("@mozilla.org/network/server-socket;1",
     1.9 +                            "nsIServerSocket",
    1.10 +                            "initWithFilename");
    1.11 +
    1.12 +const ScriptableInputStream = CC("@mozilla.org/scriptableinputstream;1",
    1.13 +                                 "nsIScriptableInputStream",
    1.14 +                                 "init");
    1.15 +
    1.16 +const IOService = Cc["@mozilla.org/network/io-service;1"]
    1.17 +                  .getService(Ci.nsIIOService);
    1.18 +const socketTransportService = Cc["@mozilla.org/network/socket-transport-service;1"]
    1.19 +                               .getService(Ci.nsISocketTransportService);
    1.20 +
    1.21 +const threadManager = Cc["@mozilla.org/thread-manager;1"].getService();
    1.22 +
    1.23 +const allPermissions = parseInt("777", 8);
    1.24 +
    1.25 +function run_test()
    1.26 +{
    1.27 +  // If we're on Windows, simply check for graceful failure.
    1.28 +  if ("@mozilla.org/windows-registry-key;1" in Cc) {
    1.29 +    test_not_supported();
    1.30 +    return;
    1.31 +  }
    1.32 +
    1.33 +  add_test(test_echo);
    1.34 +  add_test(test_name_too_long);
    1.35 +  add_test(test_no_directory);
    1.36 +  add_test(test_no_such_socket);
    1.37 +  add_test(test_address_in_use);
    1.38 +  add_test(test_file_in_way);
    1.39 +  add_test(test_create_permission);
    1.40 +  add_test(test_connect_permission);
    1.41 +  add_test(test_long_socket_name);
    1.42 +  add_test(test_keep_when_offline);
    1.43 +
    1.44 +  run_next_test();
    1.45 +}
    1.46 +
    1.47 +// Check that creating a Unix domain socket fails gracefully on Windows.
    1.48 +function test_not_supported()
    1.49 +{
    1.50 +  let socketName = do_get_tempdir();
    1.51 +  socketName.append('socket');
    1.52 +  do_print("creating socket: " + socketName.path);
    1.53 +
    1.54 +  do_check_throws_nsIException(() => new UnixServerSocket(socketName, allPermissions, -1),
    1.55 +                               "NS_ERROR_SOCKET_ADDRESS_NOT_SUPPORTED");
    1.56 +
    1.57 +  do_check_throws_nsIException(() => socketTransportService.createUnixDomainTransport(socketName),
    1.58 +                               "NS_ERROR_SOCKET_ADDRESS_NOT_SUPPORTED");
    1.59 +}
    1.60 +
    1.61 +// Actually exchange data with Unix domain sockets.
    1.62 +function test_echo()
    1.63 +{
    1.64 +  let log = '';
    1.65 +
    1.66 +  let socketName = do_get_tempdir();
    1.67 +  socketName.append('socket');
    1.68 +
    1.69 +  // Create a server socket, listening for connections.
    1.70 +  do_print("creating socket: " + socketName.path);
    1.71 +  let server = new UnixServerSocket(socketName, allPermissions, -1);
    1.72 +  server.asyncListen({
    1.73 +    onSocketAccepted: function(aServ, aTransport) {
    1.74 +      do_print("called test_echo's onSocketAccepted");
    1.75 +      log += 'a';
    1.76 +
    1.77 +      do_check_eq(aServ, server);
    1.78 +
    1.79 +      let connection = aTransport;
    1.80 +
    1.81 +      // Check the server socket's self address.
    1.82 +      let connectionSelfAddr = connection.getScriptableSelfAddr();
    1.83 +      do_check_eq(connectionSelfAddr.family, Ci.nsINetAddr.FAMILY_LOCAL);
    1.84 +      do_check_eq(connectionSelfAddr.address, socketName.path);
    1.85 +
    1.86 +      // The client socket is anonymous, so the server transport should
    1.87 +      // have an empty peer address.
    1.88 +      do_check_eq(connection.host, '');
    1.89 +      do_check_eq(connection.port, 0);
    1.90 +      let connectionPeerAddr = connection.getScriptablePeerAddr();
    1.91 +      do_check_eq(connectionPeerAddr.family, Ci.nsINetAddr.FAMILY_LOCAL);
    1.92 +      do_check_eq(connectionPeerAddr.address, '');
    1.93 +
    1.94 +      let serverAsyncInput = connection.openInputStream(0, 0, 0).QueryInterface(Ci.nsIAsyncInputStream);
    1.95 +      let serverOutput = connection.openOutputStream(0, 0, 0);
    1.96 +
    1.97 +      serverAsyncInput.asyncWait(function (aStream) {
    1.98 +        do_print("called test_echo's server's onInputStreamReady");
    1.99 +        let serverScriptableInput = new ScriptableInputStream(aStream);
   1.100 +
   1.101 +        // Receive data from the client, and send back a response.
   1.102 +        do_check_eq(serverScriptableInput.readBytes(17), "Mervyn Murgatroyd");
   1.103 +        do_print("server has read message from client");
   1.104 +        serverOutput.write("Ruthven Murgatroyd", 18);
   1.105 +        do_print("server has written to client");
   1.106 +      }, 0, 0, threadManager.currentThread);
   1.107 +    },
   1.108 +
   1.109 +    onStopListening: function(aServ, aStatus) {
   1.110 +      do_print("called test_echo's onStopListening");
   1.111 +      log += 's';
   1.112 +
   1.113 +      do_check_eq(aServ, server);
   1.114 +      do_check_eq(log, 'acs');
   1.115 +
   1.116 +      run_next_test();
   1.117 +    }
   1.118 +  });
   1.119 +
   1.120 +  // Create a client socket, and connect to the server.
   1.121 +  let client = socketTransportService.createUnixDomainTransport(socketName);
   1.122 +  do_check_eq(client.host, socketName.path);
   1.123 +  do_check_eq(client.port, 0);
   1.124 +
   1.125 +  let clientAsyncInput = client.openInputStream(0, 0, 0).QueryInterface(Ci.nsIAsyncInputStream);
   1.126 +  let clientInput = new ScriptableInputStream(clientAsyncInput);
   1.127 +  let clientOutput = client.openOutputStream(0, 0, 0);
   1.128 +
   1.129 +  clientOutput.write("Mervyn Murgatroyd", 17);
   1.130 +  do_print("client has written to server");
   1.131 +
   1.132 +  clientAsyncInput.asyncWait(function (aStream) {
   1.133 +    do_print("called test_echo's client's onInputStreamReady");
   1.134 +    log += 'c';
   1.135 +
   1.136 +    do_check_eq(aStream, clientAsyncInput);
   1.137 +
   1.138 +    // Now that the connection has been established, we can check the
   1.139 +    // transport's self and peer addresses.
   1.140 +    let clientSelfAddr = client.getScriptableSelfAddr();
   1.141 +    do_check_eq(clientSelfAddr.family, Ci.nsINetAddr.FAMILY_LOCAL);
   1.142 +    do_check_eq(clientSelfAddr.address, '');
   1.143 +
   1.144 +    do_check_eq(client.host, socketName.path); // re-check, but hey
   1.145 +    let clientPeerAddr = client.getScriptablePeerAddr();
   1.146 +    do_check_eq(clientPeerAddr.family, Ci.nsINetAddr.FAMILY_LOCAL);
   1.147 +    do_check_eq(clientPeerAddr.address, socketName.path);
   1.148 +
   1.149 +    do_check_eq(clientInput.readBytes(18), "Ruthven Murgatroyd");
   1.150 +    do_print("client has read message from server");
   1.151 +
   1.152 +    server.close();
   1.153 +  }, 0, 0, threadManager.currentThread);
   1.154 +}
   1.155 +
   1.156 +// Create client and server sockets using a path that's too long.
   1.157 +function test_name_too_long()
   1.158 +{
   1.159 +  let socketName = do_get_tempdir();
   1.160 +  // The length limits on all the systems NSPR supports are a bit past 100.
   1.161 +  socketName.append(new Array(1000).join('x'));
   1.162 +
   1.163 +  // The length must be checked before we ever make any system calls --- we
   1.164 +  // have to create the sockaddr first --- so it's unambiguous which error
   1.165 +  // we should get here.
   1.166 +
   1.167 +  do_check_throws_nsIException(() => new UnixServerSocket(socketName, 0, -1),
   1.168 +                               "NS_ERROR_FILE_NAME_TOO_LONG");
   1.169 +
   1.170 +  // Unlike most other client socket errors, this one gets reported
   1.171 +  // immediately, as we can't even initialize the sockaddr with the given
   1.172 +  // name.
   1.173 +  do_check_throws_nsIException(() => socketTransportService.createUnixDomainTransport(socketName),
   1.174 +                               "NS_ERROR_FILE_NAME_TOO_LONG");
   1.175 +
   1.176 +  run_next_test();
   1.177 +}
   1.178 +
   1.179 +// Try creating a socket in a directory that doesn't exist.
   1.180 +function test_no_directory()
   1.181 +{
   1.182 +  let socketName = do_get_tempdir();
   1.183 +  socketName.append('directory-that-does-not-exist');
   1.184 +  socketName.append('socket');
   1.185 +
   1.186 +  do_check_throws_nsIException(() => new UnixServerSocket(socketName, 0, -1),
   1.187 +                               "NS_ERROR_FILE_NOT_FOUND");
   1.188 +
   1.189 +  run_next_test();
   1.190 +}
   1.191 +
   1.192 +// Try connecting to a server socket that isn't there.
   1.193 +function test_no_such_socket()
   1.194 +{
   1.195 +  let socketName = do_get_tempdir();
   1.196 +  socketName.append('nonexistent-socket');
   1.197 +
   1.198 +  let client = socketTransportService.createUnixDomainTransport(socketName);
   1.199 +  let clientAsyncInput = client.openInputStream(0, 0, 0).QueryInterface(Ci.nsIAsyncInputStream);
   1.200 +  clientAsyncInput.asyncWait(function (aStream) {
   1.201 +    do_print("called test_no_such_socket's onInputStreamReady");
   1.202 +
   1.203 +    do_check_eq(aStream, clientAsyncInput);
   1.204 +
   1.205 +    // nsISocketTransport puts off actually creating sockets as long as
   1.206 +    // possible, so the error in connecting doesn't actually show up until
   1.207 +    // this point.
   1.208 +    do_check_throws_nsIException(() => clientAsyncInput.available(),
   1.209 +                                 "NS_ERROR_FILE_NOT_FOUND");
   1.210 +
   1.211 +    clientAsyncInput.close();
   1.212 +    client.close(Cr.NS_OK);
   1.213 +
   1.214 +    run_next_test();
   1.215 +  }, 0, 0, threadManager.currentThread);
   1.216 +}
   1.217 +
   1.218 +// Creating a socket with a name that another socket is already using is an
   1.219 +// error.
   1.220 +function test_address_in_use()
   1.221 +{
   1.222 +  let socketName = do_get_tempdir();
   1.223 +  socketName.append('socket-in-use');
   1.224 +
   1.225 +  // Create one server socket.
   1.226 +  let server = new UnixServerSocket(socketName, allPermissions, -1);
   1.227 +
   1.228 +  // Now try to create another with the same name.
   1.229 +  do_check_throws_nsIException(() => new UnixServerSocket(socketName, allPermissions, -1),
   1.230 +                               "NS_ERROR_SOCKET_ADDRESS_IN_USE");
   1.231 +
   1.232 +  run_next_test();
   1.233 +}
   1.234 +
   1.235 +// Creating a socket with a name that is already a file is an error.
   1.236 +function test_file_in_way()
   1.237 +{
   1.238 +  let socketName = do_get_tempdir();
   1.239 +  socketName.append('file_in_way');
   1.240 +
   1.241 +  // Create a file with the given name.
   1.242 +  socketName.create(Ci.nsIFile.NORMAL_FILE_TYPE, allPermissions);
   1.243 +
   1.244 +  // Try to create a socket with the same name.
   1.245 +  do_check_throws_nsIException(() => new UnixServerSocket(socketName, allPermissions, -1),
   1.246 +                               "NS_ERROR_SOCKET_ADDRESS_IN_USE");
   1.247 +
   1.248 +  // Try to create a socket under a name that uses that as a parent directory.
   1.249 +  socketName.append('socket');
   1.250 +  do_check_throws_nsIException(() => new UnixServerSocket(socketName, 0, -1),
   1.251 +                               "NS_ERROR_FILE_NOT_DIRECTORY");
   1.252 +
   1.253 +  run_next_test();
   1.254 +}
   1.255 +
   1.256 +// It is not permitted to create a socket in a directory which we are not
   1.257 +// permitted to execute, or create files in.
   1.258 +function test_create_permission()
   1.259 +{
   1.260 +  let dirName = do_get_tempdir();
   1.261 +  dirName.append('unfriendly');
   1.262 +
   1.263 +  let socketName = dirName.clone();
   1.264 +  socketName.append('socket');
   1.265 +
   1.266 +  // The test harness has difficulty cleaning things up if we don't make
   1.267 +  // everything writable before we're done.
   1.268 +  try {
   1.269 +    // Create a directory which we are not permitted to search.
   1.270 +    dirName.create(Ci.nsIFile.DIRECTORY_TYPE, 0);
   1.271 +
   1.272 +    // Try to create a socket in that directory. Because Linux returns EACCES
   1.273 +    // when a 'connect' fails because of a local firewall rule,
   1.274 +    // nsIServerSocket returns NS_ERROR_CONNECTION_REFUSED in this case.
   1.275 +    do_check_throws_nsIException(() => new UnixServerSocket(socketName, allPermissions, -1),
   1.276 +                                 "NS_ERROR_CONNECTION_REFUSED");
   1.277 +
   1.278 +    // Grant read and execute permission, but not write permission on the directory.
   1.279 +    dirName.permissions = parseInt("0555", 8);
   1.280 +
   1.281 +    // This should also fail; we need write permission.
   1.282 +    do_check_throws_nsIException(() => new UnixServerSocket(socketName, allPermissions, -1),
   1.283 +                                 "NS_ERROR_CONNECTION_REFUSED");
   1.284 +
   1.285 +  } finally {
   1.286 +    // Make the directory writable, so the test harness can clean it up.
   1.287 +    dirName.permissions = allPermissions;
   1.288 +  }
   1.289 +
   1.290 +  // This should succeed, since we now have all the permissions on the
   1.291 +  // directory we could want.
   1.292 +  do_check_instanceof(new UnixServerSocket(socketName, allPermissions, -1),
   1.293 +                      Ci.nsIServerSocket);
   1.294 +
   1.295 +  run_next_test();
   1.296 +}
   1.297 +
   1.298 +// To connect to a Unix domain socket, we need search permission on the
   1.299 +// directories containing it, and some kind of permission or other on the
   1.300 +// socket itself.
   1.301 +function test_connect_permission()
   1.302 +{
   1.303 +  // This test involves a lot of callbacks, but they're written out so that
   1.304 +  // the actual control flow proceeds from top to bottom.
   1.305 +  let log = '';
   1.306 +
   1.307 +  // Create a directory which we are permitted to search - at first.
   1.308 +  let dirName = do_get_tempdir();
   1.309 +  dirName.append('inhospitable');
   1.310 +  dirName.create(Ci.nsIFile.DIRECTORY_TYPE, allPermissions);
   1.311 +
   1.312 +  let socketName = dirName.clone();
   1.313 +  socketName.append('socket');
   1.314 +
   1.315 +  // Create a server socket in that directory, listening for connections,
   1.316 +  // and accessible.
   1.317 +  let server = new UnixServerSocket(socketName, allPermissions, -1);
   1.318 +  server.asyncListen({ onSocketAccepted: socketAccepted, onStopListening: stopListening });
   1.319 +
   1.320 +  // Make the directory unsearchable.
   1.321 +  dirName.permissions = 0;
   1.322 +
   1.323 +  let client3;
   1.324 +
   1.325 +  let client1 = socketTransportService.createUnixDomainTransport(socketName);
   1.326 +  let client1AsyncInput = client1.openInputStream(0, 0, 0).QueryInterface(Ci.nsIAsyncInputStream);
   1.327 +  client1AsyncInput.asyncWait(function (aStream) {
   1.328 +    do_print("called test_connect_permission's client1's onInputStreamReady");
   1.329 +    log += '1';
   1.330 +
   1.331 +    // nsISocketTransport puts off actually creating sockets as long as
   1.332 +    // possible, so the error doesn't actually show up until this point.
   1.333 +    do_check_throws_nsIException(() => client1AsyncInput.available(),
   1.334 +                                 "NS_ERROR_CONNECTION_REFUSED");
   1.335 +
   1.336 +    client1AsyncInput.close();
   1.337 +    client1.close(Cr.NS_OK);
   1.338 +
   1.339 +    // Make the directory searchable, but make the socket inaccessible.
   1.340 +    dirName.permissions = allPermissions;
   1.341 +    socketName.permissions = 0;
   1.342 +
   1.343 +    let client2 = socketTransportService.createUnixDomainTransport(socketName);
   1.344 +    let client2AsyncInput = client2.openInputStream(0, 0, 0).QueryInterface(Ci.nsIAsyncInputStream);
   1.345 +    client2AsyncInput.asyncWait(function (aStream) {
   1.346 +      do_print("called test_connect_permission's client2's onInputStreamReady");
   1.347 +      log += '2';
   1.348 +
   1.349 +      do_check_throws_nsIException(() => client2AsyncInput.available(),
   1.350 +                                   "NS_ERROR_CONNECTION_REFUSED");
   1.351 +
   1.352 +      client2AsyncInput.close();
   1.353 +      client2.close(Cr.NS_OK);
   1.354 +
   1.355 +      // Now make everything accessible, and try one last time.
   1.356 +      socketName.permissions = allPermissions;
   1.357 +
   1.358 +      client3 = socketTransportService.createUnixDomainTransport(socketName);
   1.359 +
   1.360 +      let client3Output = client3.openOutputStream(0, 0, 0);
   1.361 +      client3Output.write("Hanratty", 8);
   1.362 +
   1.363 +      let client3AsyncInput = client3.openInputStream(0, 0, 0).QueryInterface(Ci.nsIAsyncInputStream);
   1.364 +      client3AsyncInput.asyncWait(client3InputStreamReady, 0, 0, threadManager.currentThread);
   1.365 +    }, 0, 0, threadManager.currentThread);
   1.366 +  }, 0, 0, threadManager.currentThread);
   1.367 +
   1.368 +  function socketAccepted(aServ, aTransport) {
   1.369 +    do_print("called test_connect_permission's onSocketAccepted");
   1.370 +    log += 'a';
   1.371 +
   1.372 +    let serverInput = aTransport.openInputStream(0, 0, 0).QueryInterface(Ci.nsIAsyncInputStream);
   1.373 +    let serverOutput = aTransport.openOutputStream(0, 0, 0);
   1.374 +
   1.375 +    serverInput.asyncWait(function (aStream) {
   1.376 +      do_print("called test_connect_permission's socketAccepted's onInputStreamReady");
   1.377 +      log += 'i';
   1.378 +
   1.379 +      // Receive data from the client, and send back a response.
   1.380 +      let serverScriptableInput = new ScriptableInputStream(serverInput);
   1.381 +      do_check_eq(serverScriptableInput.readBytes(8), "Hanratty");
   1.382 +      serverOutput.write("Ferlingatti", 11);
   1.383 +    }, 0, 0, threadManager.currentThread);
   1.384 +  }
   1.385 +
   1.386 +  function client3InputStreamReady(aStream) {
   1.387 +    do_print("called client3's onInputStreamReady");
   1.388 +    log += '3';
   1.389 +
   1.390 +    let client3Input = new ScriptableInputStream(aStream);
   1.391 +
   1.392 +    do_check_eq(client3Input.readBytes(11), "Ferlingatti");
   1.393 +
   1.394 +    client3.close(Cr.NS_OK);
   1.395 +    server.close();
   1.396 +  }
   1.397 +
   1.398 +  function stopListening(aServ, aStatus) {
   1.399 +    do_print("called test_connect_permission's server's stopListening");
   1.400 +    log += 's';
   1.401 +
   1.402 +    do_check_eq(log, '12ai3s');
   1.403 +
   1.404 +    run_next_test();
   1.405 +  }
   1.406 +}
   1.407 +
   1.408 +// Creating a socket with a long filename doesn't crash.
   1.409 +function test_long_socket_name()
   1.410 +{
   1.411 +  let socketName = do_get_tempdir();
   1.412 +  socketName.append(new Array(10000).join('long'));
   1.413 +
   1.414 +  // Try to create a server socket with the long name.
   1.415 +  do_check_throws_nsIException(() => new UnixServerSocket(socketName, allPermissions, -1),
   1.416 +                               "NS_ERROR_FILE_NAME_TOO_LONG");
   1.417 +
   1.418 +  // Try to connect to a socket with the long name.
   1.419 +  do_check_throws_nsIException(() => socketTransportService.createUnixDomainTransport(socketName),
   1.420 +                               "NS_ERROR_FILE_NAME_TOO_LONG");
   1.421 +
   1.422 +  run_next_test();
   1.423 +}
   1.424 +
   1.425 +// Going offline should not shut down Unix domain sockets.
   1.426 +function test_keep_when_offline()
   1.427 +{
   1.428 +  let log = '';
   1.429 +
   1.430 +  let socketName = do_get_tempdir();
   1.431 +  socketName.append('keep-when-offline');
   1.432 +
   1.433 +  // Create a listening socket.
   1.434 +  let listener = new UnixServerSocket(socketName, allPermissions, -1);
   1.435 +  listener.asyncListen({ onSocketAccepted: onAccepted, onStopListening: onStopListening });
   1.436 +
   1.437 +  // Connect a client socket to the listening socket.
   1.438 +  let client = socketTransportService.createUnixDomainTransport(socketName);
   1.439 +  let clientOutput = client.openOutputStream(0, 0, 0);
   1.440 +  let clientInput = client.openInputStream(0, 0, 0);
   1.441 +  clientInput.asyncWait(clientReady, 0, 0, threadManager.currentThread);
   1.442 +  let clientScriptableInput = new ScriptableInputStream(clientInput);
   1.443 +
   1.444 +  let server, serverInput, serverScriptableInput, serverOutput;
   1.445 +
   1.446 +  // How many times has the server invited the client to go first?
   1.447 +  let count = 0;
   1.448 +
   1.449 +  // The server accepted connection callback.
   1.450 +  function onAccepted(aListener, aServer) {
   1.451 +    do_print("test_keep_when_offline: onAccepted called");
   1.452 +    log += 'a';
   1.453 +    do_check_eq(aListener, listener);
   1.454 +    server = aServer;
   1.455 +
   1.456 +    // Prepare to receive messages from the client.
   1.457 +    serverInput = server.openInputStream(0, 0, 0);
   1.458 +    serverInput.asyncWait(serverReady, 0, 0, threadManager.currentThread);
   1.459 +    serverScriptableInput = new ScriptableInputStream(serverInput);
   1.460 +
   1.461 +    // Start a conversation with the client.
   1.462 +    serverOutput = server.openOutputStream(0, 0, 0);
   1.463 +    serverOutput.write("After you, Alphonse!", 20);
   1.464 +    count++;
   1.465 +  }
   1.466 +
   1.467 +  // The client has seen its end of the socket close.
   1.468 +  function clientReady(aStream) {
   1.469 +    log += 'c';
   1.470 +    do_print("test_keep_when_offline: clientReady called: " + log);
   1.471 +    do_check_eq(aStream, clientInput);
   1.472 +
   1.473 +    // If the connection has been closed, end the conversation and stop listening.
   1.474 +    let available;
   1.475 +    try {
   1.476 +      available = clientInput.available();
   1.477 +    } catch (ex) {
   1.478 +      do_check_instanceof(ex, Ci.nsIException);
   1.479 +      do_check_eq(ex.result, Cr.NS_BASE_STREAM_CLOSED);
   1.480 +
   1.481 +      do_print("client received end-of-stream; closing client output stream");
   1.482 +      log += ')';
   1.483 +
   1.484 +      client.close(Cr.NS_OK);
   1.485 +
   1.486 +      // Now both output streams have been closed, and both input streams
   1.487 +      // have received the close notification. Stop listening for
   1.488 +      // connections.
   1.489 +      listener.close();
   1.490 +    }
   1.491 +
   1.492 +    if (available) {
   1.493 +      // Check the message from the server.
   1.494 +      do_check_eq(clientScriptableInput.readBytes(20), "After you, Alphonse!");
   1.495 +
   1.496 +      // Write our response to the server.
   1.497 +      clientOutput.write("No, after you, Gaston!", 22);
   1.498 +
   1.499 +      // Ask to be called again, when more input arrives.
   1.500 +      clientInput.asyncWait(clientReady, 0, 0, threadManager.currentThread);
   1.501 +    }
   1.502 +  }
   1.503 +
   1.504 +  function serverReady(aStream) {
   1.505 +    log += 's';
   1.506 +    do_print("test_keep_when_offline: serverReady called: " + log);
   1.507 +    do_check_eq(aStream, serverInput);
   1.508 +
   1.509 +    // Check the message from the client.
   1.510 +    do_check_eq(serverScriptableInput.readBytes(22), "No, after you, Gaston!");
   1.511 +
   1.512 +    // This should not shut things down: Unix domain sockets should
   1.513 +    // remain open in offline mode.
   1.514 +    if (count == 5) {
   1.515 +      IOService.offline = true;
   1.516 +      log += 'o';
   1.517 +    }
   1.518 +
   1.519 +    if (count < 10) {
   1.520 +      // Insist.
   1.521 +      serverOutput.write("After you, Alphonse!", 20);
   1.522 +      count++;
   1.523 +
   1.524 +      // As long as the input stream is open, always ask to be called again
   1.525 +      // when more input arrives.
   1.526 +      serverInput.asyncWait(serverReady, 0, 0, threadManager.currentThread);
   1.527 +    } else if (count == 10) {
   1.528 +      // After sending ten times and receiving ten replies, we're not
   1.529 +      // going to send any more. Close the server's output stream; the
   1.530 +      // client's input stream should see this.
   1.531 +      do_print("closing server transport");
   1.532 +      server.close(Cr.NS_OK);
   1.533 +      log += '(';
   1.534 +    }
   1.535 +  }
   1.536 +
   1.537 +  // We have stopped listening.
   1.538 +  function onStopListening(aServ, aStatus) {
   1.539 +    do_print("test_keep_when_offline: onStopListening called");
   1.540 +    log += 'L';
   1.541 +    do_check_eq(log, 'acscscscscsocscscscscs(c)L');
   1.542 +
   1.543 +    do_check_eq(aServ, listener);
   1.544 +    do_check_eq(aStatus, Cr.NS_BINDING_ABORTED);
   1.545 +
   1.546 +    run_next_test();
   1.547 +  }
   1.548 +}

mercurial