1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // net/tools/testserver/testserver.py is picky about the format of what it
6 // calls its "echo" messages. One might go so far as to mutter to oneself that
7 // it isn't an echo server at all.
9 // The response is based on the request but obfuscated using a random key.
10 const request = "0100000005320000005hello";
11 var expectedResponsePattern = /0100000005320000005.{11}/;
13 const socket = chrome.socket;
19 var protocol = "none";
21 var succeeded = false;
24 // Many thanks to Dennis for his StackOverflow answer: http://goo.gl/UDanx
25 // Since amended to handle BlobBuilder deprecation.
26 function string2ArrayBuffer(string, callback) {
27 var blob = new Blob([string]);
28 var f = new FileReader();
29 f.onload = function(e) {
30 callback(e.target.result);
32 f.readAsArrayBuffer(blob);
35 function arrayBuffer2String(buf, callback) {
36 var blob = new Blob([new Uint8Array(buf)]);
37 var f = new FileReader();
38 f.onload = function(e) {
39 callback(e.target.result);
44 function assertDataMatch(expecterDataPattern, data) {
45 var match = !!data.match(expecterDataPattern);
46 chrome.test.assertTrue(match, "Received data does not match. " +
47 "Expected pattern: \"" + expecterDataPattern + "\" - " +
48 "Data received: \"" + data + "\".");
51 var testSocketCreation = function() {
52 function onCreate(socketInfo) {
53 function onGetInfo(info) {
54 chrome.test.assertEq(info.socketType, protocol);
55 chrome.test.assertFalse(info.connected);
57 if (info.peerAddress || info.peerPort) {
58 chrome.test.fail('Unconnected socket should not have peer');
60 if (info.localAddress || info.localPort) {
61 chrome.test.fail('Unconnected socket should not have local binding');
64 socket.destroy(socketInfo.socketId);
65 socket.getInfo(socketInfo.socketId, function(info) {
66 chrome.test.assertEq(undefined, info);
67 chrome.test.succeed();
71 chrome.test.assertTrue(socketInfo.socketId > 0);
73 // Obtaining socket information before a connect() call should be safe, but
74 // return empty values.
75 socket.getInfo(socketInfo.socketId, onGetInfo);
78 socket.create(protocol, {}, onCreate);
82 var testGetInfo = function() {
85 function onDataRead(readInfo) {
86 if (readInfo.resultCode > 0 || readInfo.data.byteLength > 0) {
87 chrome.test.assertEq(readInfo.resultCode, readInfo.data.byteLength);
90 arrayBuffer2String(readInfo.data, function(s) {
91 dataAsString = s; // save this for error reporting
92 assertDataMatch(expectedResponsePattern, dataAsString);
94 chrome.test.succeed();
98 function onWriteOrSendToComplete(writeInfo) {
99 bytesWritten += writeInfo.bytesWritten;
100 if (bytesWritten == request.length) {
101 if (protocol == "tcp")
102 socket.read(socketId, onDataRead);
104 socket.recvFrom(socketId, onDataRead);
108 function onSetKeepAlive(result) {
109 if (protocol == "tcp")
110 chrome.test.assertTrue(result, "setKeepAlive failed for TCP.");
112 chrome.test.assertFalse(result, "setKeepAlive did not fail for UDP.");
114 string2ArrayBuffer(request, function(arrayBuffer) {
115 if (protocol == "tcp")
116 socket.write(socketId, arrayBuffer, onWriteOrSendToComplete);
118 socket.sendTo(socketId, arrayBuffer, address, port,
119 onWriteOrSendToComplete);
123 function onSetNoDelay(result) {
124 if (protocol == "tcp")
125 chrome.test.assertTrue(result, "setNoDelay failed for TCP.");
127 chrome.test.assertFalse(result, "setNoDelay did not fail for UDP.");
128 socket.setKeepAlive(socketId, true, 1000, onSetKeepAlive);
131 function onGetInfo(result) {
132 chrome.test.assertTrue(!!result.localAddress,
133 "Bound socket should always have local address");
134 chrome.test.assertTrue(!!result.localPort,
135 "Bound socket should always have local port");
136 chrome.test.assertEq(result.socketType, protocol, "Unexpected socketType");
138 if (protocol == "tcp") {
139 // NOTE: We're always called with 'localhost', but getInfo will only return
141 chrome.test.assertEq(result.peerAddress, "127.0.0.1",
142 "Peer addresss should be the listen server");
143 chrome.test.assertEq(result.peerPort, port,
144 "Peer port should be the listen server");
145 chrome.test.assertTrue(result.connected, "Socket should be connected");
147 chrome.test.assertFalse(result.connected, "UDP socket was not connected");
148 chrome.test.assertTrue(!result.peerAddress,
149 "Unconnected UDP socket should not have peer address");
150 chrome.test.assertTrue(!result.peerPort,
151 "Unconnected UDP socket should not have peer port");
154 socket.setNoDelay(socketId, true, onSetNoDelay);
157 function onConnectOrBindComplete(result) {
158 chrome.test.assertEq(0, result,
159 "Connect or bind failed with error " + result);
161 socket.getInfo(socketId, onGetInfo);
165 function onCreate(socketInfo) {
166 socketId = socketInfo.socketId;
167 chrome.test.assertTrue(socketId > 0, "failed to create socket");
168 if (protocol == "tcp")
169 socket.connect(socketId, address, port, onConnectOrBindComplete);
171 socket.bind(socketId, "0.0.0.0", 0, onConnectOrBindComplete);
174 function waitForBlockingOperation() {
175 if (++waitCount < 10) {
176 setTimeout(waitForBlockingOperation, 1000);
178 // We weren't able to succeed in the given time.
179 chrome.test.fail("Operations didn't complete after " + waitCount + " " +
180 "seconds. Response so far was <" + dataAsString + ">.");
184 var testSending = function() {
189 setTimeout(waitForBlockingOperation, 1000);
190 socket.create(protocol, {}, onCreate);
193 // Tests listening on a socket and sending/receiving from accepted sockets.
194 var testSocketListening = function() {
197 function onServerSocketAccept(acceptInfo) {
198 chrome.test.assertEq(0, acceptInfo.resultCode);
199 var acceptedSocketId = acceptInfo.socketId;
200 socket.read(acceptedSocketId, function(readInfo) {
201 arrayBuffer2String(readInfo.data, function (s) {
202 assertDataMatch(request, s);
204 // Test whether socket.getInfo correctly reflects the connection status
205 // if the peer has closed the connection.
206 setTimeout(function() {
207 socket.getInfo(acceptedSocketId, function(info) {
208 chrome.test.assertFalse(info.connected);
209 chrome.test.succeed();
216 function onListen(result) {
217 chrome.test.assertEq(0, result, "Listen failed.");
218 socket.accept(socketId, onServerSocketAccept);
220 // Trying to schedule a second accept callback should fail.
221 socket.accept(socketId, function(acceptInfo) {
222 chrome.test.assertEq(-2, acceptInfo.resultCode);
225 // Create a new socket to connect to the TCP server.
226 socket.create('tcp', {}, function(socketInfo) {
227 tmpSocketId = socketInfo.socketId;
228 socket.connect(tmpSocketId, address, port,
230 chrome.test.assertEq(0, result, "Connect failed");
233 string2ArrayBuffer(request, function(buf) {
234 socket.write(tmpSocketId, buf, function() {
235 socket.disconnect(tmpSocketId);
242 function onServerSocketCreate(socketInfo) {
243 socketId = socketInfo.socketId;
244 socket.listen(socketId, address, port, onListen);
247 socket.create('tcp', {}, onServerSocketCreate);
250 var testPendingCallback = function() {
255 console.log("calling create");
256 chrome.socket.create(protocol, null, onCreate);
258 function onCreate(createInfo) {
259 chrome.test.assertTrue(createInfo.socketId > 0, "failed to create socket");
260 socketId = createInfo.socketId;
261 console.log("calling connect");
262 if (protocol == "tcp")
263 chrome.socket.connect(socketId, address, port, onConnect1);
265 chrome.socket.bind(socketId, "0.0.0.0", 0, onConnect1);
268 function onConnect1(result) {
269 chrome.test.assertEq(0, result, "failed to connect");
270 console.log("Socket connect: result=" + result, chrome.runtime.lastError);
272 console.log("calling read with readCB2 callback");
273 if (protocol == "tcp")
274 chrome.socket.read(socketId, readCB1);
276 chrome.socket.recvFrom(socketId, readCB1);
278 console.log("calling disconnect");
279 chrome.socket.disconnect(socketId);
281 console.log("calling connect");
282 if (protocol == "tcp")
283 chrome.socket.connect(socketId, address, port, onConnect2);
285 chrome.socket.bind(socketId, "0.0.0.0", 0, onConnect2);
288 function onConnect2(result) {
289 chrome.test.assertEq(0, result, "failed to connect");
290 console.log("Socket connect: result=" + result, chrome.runtime.lastError);
292 console.log("calling read with readCB1 callback");
293 if (protocol == "tcp")
294 chrome.socket.read(socketId, readCB2);
296 chrome.socket.recvFrom(socketId, readCB2);
298 string2ArrayBuffer(request, function (arrayBuffer) {
299 if (protocol == "tcp")
300 chrome.socket.write(socketId, arrayBuffer, onWriteComplete);
302 chrome.socket.sendTo(
303 socketId, arrayBuffer, address, port, onWriteComplete);
307 function onWriteComplete(res) {
308 console.log("write callback: bytesWritten=" + res.bytesWritten);
311 // Callback 1 for initial read call
312 function readCB1(readInfo) {
313 console.log("Socket read CB1: result=" + readInfo.resultCode,
314 chrome.runtime.lastError);
316 if (readInfo.resultCode < 0) {
317 chrome.test.fail("Error reading from socket: " + readInfo.resultCode);
321 // Second callback, for read call after re-connect
322 function readCB2(readInfo) {
323 console.log("Socket read CB2: result=" + readInfo.resultCode,
324 chrome.runtime.lastError);
325 if (readInfo.resultCode === -1) {
326 chrome.test.fail("Unable to register a read 2nd callback on the socket!");
327 } else if (readInfo.resultCode < 0) {
328 chrome.test.fail("Error reading from socket: " + readInfo.resultCode);
331 arrayBuffer2String(readInfo.data, function (s) {
332 assertDataMatch(expectedResponsePattern, s);
333 console.log("Success!");
335 chrome.test.succeed();
341 // See http://crbug.com/418229.
342 var testUsingTCPSocketOnUDPMethods = function() {
343 if (protocol == "udp") {
344 socket.create("tcp", function(createInfo) {
345 socket.recvFrom(createInfo.socketId, 256, function(recvFromInfo) {
346 chrome.test.assertTrue(recvFromInfo.resultCode < 0);
347 chrome.test.succeed();
351 function onSendToComplete(writeInfo) {
352 chrome.test.assertTrue(writeInfo.bytesWritten < 0);
353 chrome.test.succeed();
356 string2ArrayBuffer(request, function(arrayBuffer) {
357 socket.create("tcp", function(createInfo) {
358 socket.sendTo(createInfo.socketId, arrayBuffer, address, port,
363 // We only run this test when the protocol is UDP to
364 // avoid running it multiple times unnecessarily.
365 chrome.test.succeed();
369 var onMessageReply = function(message) {
370 var parts = message.split(":");
371 var test_type = parts[0];
373 port = parseInt(parts[2]);
374 console.log("Running tests, protocol " + protocol + ", echo server " +
375 address + ":" + port);
376 if (test_type == 'tcp_server') {
377 chrome.test.runTests([ testSocketListening ]);
378 } else if (test_type == 'multicast') {
379 console.log("Running multicast tests");
380 chrome.test.runTests([ testMulticast ]);
382 protocol = test_type;
383 chrome.test.runTests([
387 testUsingTCPSocketOnUDPMethods]);
391 // Find out which protocol we're supposed to test, and which echo server we
392 // should be using, then kick off the tests.
393 chrome.test.sendMessage("info_please", onMessageReply);