3 var CC = Components.Constructor;
5 const ServerSocket = CC(
6 "@mozilla.org/network/server-socket;1",
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.
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|
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.
25 function TestServer() {
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);
36 TestServer.prototype = {
37 onSocketAccepted(socket, trans) {
38 info("server: got client connection");
40 // one connection at a time.
41 if (this.input !== null) {
45 do_throw("Test written to handle one connection at a time.");
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();
54 this.acceptCallback();
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");
65 onStopListening(socket) {},
68 * Called to close a connection and clean up properties.
84 this.acceptCallback = null;
90 * Cleanup for TestServer and this test case.
95 this.listener.close();
102 * Compares two nsINetAddr objects and ensures they are logically equivalent.
104 function checkAddrEqual(lhs, rhs) {
105 Assert.equal(lhs.family, rhs.family);
107 if (lhs.family === Ci.nsINetAddr.FAMILY_INET) {
108 Assert.equal(lhs.address, rhs.address);
109 Assert.equal(lhs.port, rhs.port);
112 /* TODO: fully support ipv6 and local */
116 * An instance of SocketTransportService, used to create connections.
121 * Single instance of TestServer
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.
131 var testDataStore = null;
136 function testIpv4() {
142 serv.acceptCallback = function() {
143 // disable the timeoutCallback
144 serv.timeoutCallback = function() {};
146 var selfAddr = testDataStore.transport.getScriptableSelfAddr();
147 var peerAddr = testDataStore.transport.getScriptablePeerAddr();
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");
155 // check selfAddr against expected values
156 Assert.equal(selfAddr.family, Ci.nsINetAddr.FAMILY_INET);
157 Assert.equal(selfAddr.address, "127.0.0.1");
159 // check that selfAddr = server.peerAddr and vice versa.
160 checkAddrEqual(selfAddr, serv.peerAddr);
161 checkAddrEqual(peerAddr, serv.selfAddr);
163 testDataStore = null;
164 executeSoon(run_next_test);
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');
172 do_timeout(connectTimeout, function(){ serv.timeoutCallback('testIpv4'); });*/
174 testDataStore.transport = sts.createTransport(
182 * Need to hold |output| so that the output stream doesn't close itself and
183 * the associated connection.
185 testDataStore.output = testDataStore.transport.openOutputStream(
186 Ci.nsITransport.OPEN_BLOCKING,
192 * openOutputStream -> onSocketAccepted -> acceptedCallback -> run_next_test
193 * OR (if the above timeout is uncommented)
194 * <connectTimeout lapses> -> timeoutCallback -> do_throw
201 function run_test() {
202 sts = Cc["@mozilla.org/network/socket-transport-service;1"].getService(
203 Ci.nsISocketTransportService
205 serv = new TestServer();
207 registerCleanupFunction(function() {
213 /* TODO: testLocal */