- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / test / data / extensions / api_test / socket / api / background.js
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.
4
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.
8 //
9 // The response is based on the request but obfuscated using a random key.
10 const request = "0100000005320000005hello";
11 var expectedResponsePattern = /0100000005320000005.{11}/;
12
13 const socket = chrome.socket;
14 var address;
15 var bytesWritten = 0;
16 var dataAsString;
17 var dataRead = [];
18 var port = -1;
19 var protocol = "none";
20 var socketId = 0;
21 var succeeded = false;
22 var waitCount = 0;
23
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);
31   };
32   f.readAsArrayBuffer(blob);
33 }
34
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);
40   };
41   f.readAsText(blob);
42 }
43
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 + "\".");
49 }
50
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);
56
57       if (info.peerAddress || info.peerPort) {
58         chrome.test.fail('Unconnected socket should not have peer');
59       }
60       if (info.localAddress || info.localPort) {
61         chrome.test.fail('Unconnected socket should not have local binding');
62       }
63
64       socket.destroy(socketInfo.socketId);
65       socket.getInfo(socketInfo.socketId, function(info) {
66         chrome.test.assertEq(undefined, info);
67         chrome.test.succeed();
68       });
69     }
70
71     chrome.test.assertTrue(socketInfo.socketId > 0);
72
73     // Obtaining socket information before a connect() call should be safe, but
74     // return empty values.
75     socket.getInfo(socketInfo.socketId, onGetInfo);
76   }
77
78   socket.create(protocol, {}, onCreate);
79 };
80
81
82 var testGetInfo = function() {
83 };
84
85 function onDataRead(readInfo) {
86   if (readInfo.resultCode > 0 || readInfo.data.byteLength > 0) {
87     chrome.test.assertEq(readInfo.resultCode, readInfo.data.byteLength);
88   }
89
90   arrayBuffer2String(readInfo.data, function(s) {
91     dataAsString = s;  // save this for error reporting
92     assertDataMatch(expectedResponsePattern, dataAsString);
93     succeeded = true;
94     chrome.test.succeed();
95   });
96 }
97
98 function onWriteOrSendToComplete(writeInfo) {
99   bytesWritten += writeInfo.bytesWritten;
100   if (bytesWritten == request.length) {
101     if (protocol == "tcp")
102       socket.read(socketId, onDataRead);
103     else
104       socket.recvFrom(socketId, onDataRead);
105   }
106 }
107
108 function onSetKeepAlive(result) {
109   if (protocol == "tcp")
110     chrome.test.assertTrue(result, "setKeepAlive failed for TCP.");
111   else
112     chrome.test.assertFalse(result, "setKeepAlive did not fail for UDP.");
113
114   string2ArrayBuffer(request, function(arrayBuffer) {
115       if (protocol == "tcp")
116         socket.write(socketId, arrayBuffer, onWriteOrSendToComplete);
117       else
118         socket.sendTo(socketId, arrayBuffer, address, port,
119                       onWriteOrSendToComplete);
120     });
121 }
122
123 function onSetNoDelay(result) {
124   if (protocol == "tcp")
125     chrome.test.assertTrue(result, "setNoDelay failed for TCP.");
126   else
127     chrome.test.assertFalse(result, "setNoDelay did not fail for UDP.");
128   socket.setKeepAlive(socketId, true, 1000, onSetKeepAlive);
129 }
130
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");
137
138   if (protocol == "tcp") {
139     // NOTE: We're always called with 'localhost', but getInfo will only return
140     // IPs, not names.
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");
146   } else {
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");
152   }
153
154   socket.setNoDelay(socketId, true, onSetNoDelay);
155 }
156
157 function onConnectOrBindComplete(result) {
158   chrome.test.assertEq(0, result,
159                        "Connect or bind failed with error " + result);
160   if (result == 0) {
161     socket.getInfo(socketId, onGetInfo);
162   }
163 }
164
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);
170   else
171     socket.bind(socketId, "0.0.0.0", 0, onConnectOrBindComplete);
172 }
173
174 function waitForBlockingOperation() {
175   if (++waitCount < 10) {
176     setTimeout(waitForBlockingOperation, 1000);
177   } else {
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 + ">.");
181   }
182 }
183
184 var testSending = function() {
185   dataRead = "";
186   succeeded = false;
187   waitCount = 0;
188
189   setTimeout(waitForBlockingOperation, 1000);
190   socket.create(protocol, {}, onCreate);
191 };
192
193 // Tests listening on a socket and sending/receiving from accepted sockets.
194 var testSocketListening = function() {
195   var tmpSocketId = 0;
196
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);
203         succeeded = true;
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();
210           });
211         }, 500);
212       });
213     });
214   }
215
216   function onListen(result) {
217     chrome.test.assertEq(0, result, "Listen failed.");
218     socket.accept(socketId, onServerSocketAccept);
219
220     // Trying to schedule a second accept callback should fail.
221     socket.accept(socketId, function(acceptInfo) {
222       chrome.test.assertEq(-2, acceptInfo.resultCode);
223     });
224
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,
229         function(result) {
230           chrome.test.assertEq(0, result, "Connect failed");
231
232           // Write.
233           string2ArrayBuffer(request, function(buf) {
234             socket.write(tmpSocketId, buf, function() {
235               socket.disconnect(tmpSocketId);
236             });
237           });
238         });
239     });
240   }
241
242   function onServerSocketCreate(socketInfo) {
243     socketId = socketInfo.socketId;
244     socket.listen(socketId, address, port, onListen);
245   }
246
247   socket.create('tcp', {}, onServerSocketCreate);
248 };
249
250 var testPendingCallback = function() {
251   dataRead = "";
252   succeeded = false;
253   waitCount = 0;
254
255   console.log("calling create");
256   chrome.socket.create(protocol, null, onCreate);
257
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);
264     else
265       chrome.socket.bind(socketId, "0.0.0.0", 0, onConnect1);
266   }
267
268   function onConnect1(result) {
269     chrome.test.assertEq(0, result, "failed to connect");
270     console.log("Socket connect: result=" + result, chrome.runtime.lastError);
271
272     console.log("calling read with readCB2 callback");
273     if (protocol == "tcp")
274       chrome.socket.read(socketId, readCB1);
275     else
276       chrome.socket.recvFrom(socketId, readCB1);
277
278     console.log("calling disconnect");
279     chrome.socket.disconnect(socketId);
280
281     console.log("calling connect");
282     if (protocol == "tcp")
283       chrome.socket.connect(socketId, address, port, onConnect2);
284     else
285       chrome.socket.bind(socketId, "0.0.0.0", 0, onConnect2);
286   }
287
288   function onConnect2(result) {
289     chrome.test.assertEq(0, result, "failed to connect");
290     console.log("Socket connect: result=" + result, chrome.runtime.lastError);
291
292     console.log("calling read with readCB1 callback");
293     if (protocol == "tcp")
294       chrome.socket.read(socketId, readCB2);
295     else
296       chrome.socket.recvFrom(socketId, readCB2);
297
298     string2ArrayBuffer(request, function (arrayBuffer) {
299       if (protocol == "tcp")
300         chrome.socket.write(socketId, arrayBuffer, onWriteComplete);
301       else
302         chrome.socket.sendTo(
303             socketId, arrayBuffer, address, port, onWriteComplete);
304     });
305   }
306
307   function onWriteComplete(res) {
308     console.log("write callback: bytesWritten=" + res.bytesWritten);
309   }
310
311   // Callback 1 for initial read call
312   function readCB1(readInfo) {
313     console.log("Socket read CB1: result=" + readInfo.resultCode,
314         chrome.runtime.lastError);
315
316     if (readInfo.resultCode < 0) {
317       chrome.test.fail("Error reading from socket: " + readInfo.resultCode);
318     }
319   }
320
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);
329     }
330     else {
331       arrayBuffer2String(readInfo.data, function (s) {
332         assertDataMatch(expectedResponsePattern, s);
333         console.log("Success!");
334         succeeded = true;
335         chrome.test.succeed();
336       });
337     }
338   }
339 }
340
341 var onMessageReply = function(message) {
342   var parts = message.split(":");
343   var test_type = parts[0];
344   address = parts[1];
345   port = parseInt(parts[2]);
346   console.log("Running tests, protocol " + protocol + ", echo server " +
347               address + ":" + port);
348   if (test_type == 'tcp_server') {
349     chrome.test.runTests([ testSocketListening ]);
350   } else if (test_type == 'multicast') {
351     console.log("Running multicast tests");
352     chrome.test.runTests([ testMulticast ]);
353   } else {
354     protocol = test_type;
355     chrome.test.runTests(
356         [testSocketCreation, testSending, testPendingCallback]);
357   }
358 };
359
360 // Find out which protocol we're supposed to test, and which echo server we
361 // should be using, then kick off the tests.
362 chrome.test.sendMessage("info_please", onMessageReply);