1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/test/unit/test_net_addr.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,199 @@ 1.4 +const CC = Components.Constructor; 1.5 + 1.6 +const ServerSocket = CC("@mozilla.org/network/server-socket;1", 1.7 + "nsIServerSocket", 1.8 + "init"); 1.9 + 1.10 +/** 1.11 + * TestServer: A single instance of this is created as |serv|. When created, 1.12 + * it starts listening on the loopback address on port |serv.port|. Tests will 1.13 + * connect to it after setting |serv.acceptCallback|, which is invoked after it 1.14 + * accepts a connection. 1.15 + * 1.16 + * Within |serv.acceptCallback|, various properties of |serv| can be used to 1.17 + * run checks. After the callback, the connection is closed, but the server 1.18 + * remains listening until |serv.stop| 1.19 + * 1.20 + * Note: TestServer can only handle a single connection at a time. Tests 1.21 + * should use run_next_test at the end of |serv.acceptCallback| to start the 1.22 + * following test which creates a connection. 1.23 + */ 1.24 +function TestServer() { 1.25 + this.reset(); 1.26 + 1.27 + // start server. 1.28 + // any port (-1), loopback only (true), default backlog (-1) 1.29 + this.listener = ServerSocket(-1, true, -1); 1.30 + this.port = this.listener.port; 1.31 + do_print('server: listening on', this.port); 1.32 + this.listener.asyncListen(this); 1.33 +} 1.34 + 1.35 +TestServer.prototype = { 1.36 + onSocketAccepted: function(socket, trans) { 1.37 + do_print('server: got client connection'); 1.38 + 1.39 + // one connection at a time. 1.40 + if (this.input !== null) { 1.41 + try { socket.close(); } catch(ignore) {} 1.42 + do_throw("Test written to handle one connection at a time."); 1.43 + } 1.44 + 1.45 + try { 1.46 + this.input = trans.openInputStream(0, 0, 0); 1.47 + this.output = trans.openOutputStream(0, 0, 0); 1.48 + this.selfAddr = trans.getScriptableSelfAddr(); 1.49 + this.peerAddr = trans.getScriptablePeerAddr(); 1.50 + 1.51 + this.acceptCallback(); 1.52 + } catch(e) { 1.53 + /* In a native callback such as onSocketAccepted, exceptions might not 1.54 + * get output correctly or logged to test output. Send them through 1.55 + * do_throw, which fails the test immediately. */ 1.56 + do_report_unexpected_exception(e, "in TestServer.onSocketAccepted"); 1.57 + } 1.58 + 1.59 + this.reset(); 1.60 + } , 1.61 + 1.62 + onStopListening: function(socket) {} , 1.63 + 1.64 + /** 1.65 + * Called to close a connection and clean up properties. 1.66 + */ 1.67 + reset: function() { 1.68 + if (this.input) 1.69 + try { this.input.close(); } catch(ignore) {} 1.70 + if (this.output) 1.71 + try { this.output.close(); } catch(ignore) {} 1.72 + 1.73 + this.input = null; 1.74 + this.output = null; 1.75 + this.acceptCallback = null; 1.76 + this.selfAddr = null; 1.77 + this.peerAddr = null; 1.78 + } , 1.79 + 1.80 + /** 1.81 + * Cleanup for TestServer and this test case. 1.82 + */ 1.83 + stop: function() { 1.84 + this.reset(); 1.85 + try { this.listener.close(); } catch(ignore) {} 1.86 + } 1.87 +}; 1.88 + 1.89 + 1.90 +/** 1.91 + * Helper function. 1.92 + * Compares two nsINetAddr objects and ensures they are logically equivalent. 1.93 + */ 1.94 +function checkAddrEqual(lhs, rhs) { 1.95 + do_check_eq(lhs.family, rhs.family); 1.96 + 1.97 + if (lhs.family === Ci.nsINetAddr.FAMILY_INET) { 1.98 + do_check_eq(lhs.address, rhs.address); 1.99 + do_check_eq(lhs.port, rhs.port); 1.100 + } 1.101 + 1.102 + /* TODO: fully support ipv6 and local */ 1.103 +} 1.104 + 1.105 + 1.106 +/** 1.107 + * An instance of SocketTransportService, used to create connections. 1.108 + */ 1.109 +var sts; 1.110 + 1.111 +/** 1.112 + * Single instance of TestServer 1.113 + */ 1.114 +var serv; 1.115 + 1.116 +/** 1.117 + * Connections have 5 seconds to be made, or a timeout function fails this 1.118 + * test. This prevents the test from hanging and bringing down the entire 1.119 + * xpcshell test chain. 1.120 + */ 1.121 +var connectTimeout = 5*1000; 1.122 + 1.123 +/** 1.124 + * A place for individual tests to place Objects of importance for access 1.125 + * throughout asynchronous testing. Particularly important for any output or 1.126 + * input streams opened, as cleanup of those objects (by the garbage collector) 1.127 + * causes the stream to close and may have other side effects. 1.128 + */ 1.129 +var testDataStore = null; 1.130 + 1.131 +/** 1.132 + * IPv4 test. 1.133 + */ 1.134 +function testIpv4() { 1.135 + testDataStore = { 1.136 + transport : null , 1.137 + ouput : null 1.138 + } 1.139 + 1.140 + serv.acceptCallback = function() { 1.141 + // disable the timeoutCallback 1.142 + serv.timeoutCallback = function(){}; 1.143 + 1.144 + var selfAddr = testDataStore.transport.getScriptableSelfAddr(); 1.145 + var peerAddr = testDataStore.transport.getScriptablePeerAddr(); 1.146 + 1.147 + // check peerAddr against expected values 1.148 + do_check_eq(peerAddr.family, Ci.nsINetAddr.FAMILY_INET); 1.149 + do_check_eq(peerAddr.port, testDataStore.transport.port); 1.150 + do_check_eq(peerAddr.port, serv.port); 1.151 + do_check_eq(peerAddr.address, "127.0.0.1"); 1.152 + 1.153 + // check selfAddr against expected values 1.154 + do_check_eq(selfAddr.family, Ci.nsINetAddr.FAMILY_INET); 1.155 + do_check_eq(selfAddr.address, "127.0.0.1"); 1.156 + 1.157 + // check that selfAddr = server.peerAddr and vice versa. 1.158 + checkAddrEqual(selfAddr, serv.peerAddr); 1.159 + checkAddrEqual(peerAddr, serv.selfAddr); 1.160 + 1.161 + testDataStore = null; 1.162 + do_execute_soon(run_next_test); 1.163 + }; 1.164 + 1.165 + // Useful timeout for debugging test hangs 1.166 + /*serv.timeoutCallback = function(tname) { 1.167 + if (tname === 'testIpv4') 1.168 + do_throw('testIpv4 never completed a connection to TestServ'); 1.169 + }; 1.170 + do_timeout(connectTimeout, function(){ serv.timeoutCallback('testIpv4'); });*/ 1.171 + 1.172 + testDataStore.transport = sts.createTransport(null, 0, '127.0.0.1', serv.port, null); 1.173 + /* 1.174 + * Need to hold |output| so that the output stream doesn't close itself and 1.175 + * the associated connection. 1.176 + */ 1.177 + testDataStore.output = testDataStore.transport.openOutputStream(Ci.nsITransport.OPEN_BLOCKING,0,0); 1.178 + 1.179 + /* NEXT: 1.180 + * openOutputStream -> onSocketAccepted -> acceptedCallback -> run_next_test 1.181 + * OR (if the above timeout is uncommented) 1.182 + * <connectTimeout lapses> -> timeoutCallback -> do_throw 1.183 + */ 1.184 +} 1.185 + 1.186 + 1.187 +/** 1.188 + * Running the tests. 1.189 + */ 1.190 +function run_test() { 1.191 + sts = Cc["@mozilla.org/network/socket-transport-service;1"] 1.192 + .getService(Ci.nsISocketTransportService); 1.193 + serv = new TestServer(); 1.194 + 1.195 + do_register_cleanup(function(){ serv.stop(); }); 1.196 + 1.197 + add_test(testIpv4); 1.198 + /* TODO: testIpv6 */ 1.199 + /* TODO: testLocal */ 1.200 + 1.201 + run_next_test(); 1.202 +}