| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 // | |
| 5 // VMOptions= | |
| 6 // VMOptions=--short_socket_read | |
| 7 // VMOptions=--short_socket_write | |
| 8 // VMOptions=--short_socket_read --short_socket_write | |
| 9 | |
| 10 #import("dart:isolate"); | |
| 11 #import("dart:io"); | |
| 12 | |
| 13 class TestServerMain { | |
| 14 TestServerMain() | |
| 15 : _statusPort = new ReceivePort(), | |
| 16 _serverPort = null { | |
| 17 new TestServer().spawn().then((SendPort port) { | |
| 18 _serverPort = port; | |
| 19 }); | |
| 20 } | |
| 21 | |
| 22 void setServerStartedHandler(void startedCallback(int port)) { | |
| 23 _startedCallback = startedCallback; | |
| 24 } | |
| 25 | |
| 26 void start() { | |
| 27 // Handle status messages from the server. | |
| 28 _statusPort.receive((var status, SendPort replyTo) { | |
| 29 if (status.isStarted) { | |
| 30 _startedCallback(status.port); | |
| 31 } | |
| 32 }); | |
| 33 | |
| 34 // Send server start message to the server. | |
| 35 var command = new TestServerCommand.start(); | |
| 36 _serverPort.send(command, _statusPort.toSendPort()); | |
| 37 } | |
| 38 | |
| 39 void shutdown() { | |
| 40 // Send server stop message to the server. | |
| 41 _serverPort.send(new TestServerCommand.stop(), _statusPort.toSendPort()); | |
| 42 _statusPort.close(); | |
| 43 } | |
| 44 | |
| 45 void chunkedEncoding() { | |
| 46 // Send chunked encoding message to the server. | |
| 47 _serverPort.send( | |
| 48 new TestServerCommand.chunkedEncoding(), _statusPort.toSendPort()); | |
| 49 } | |
| 50 | |
| 51 ReceivePort _statusPort; // Port for receiving messages from the server. | |
| 52 SendPort _serverPort; // Port for sending messages to the server. | |
| 53 var _startedCallback; | |
| 54 } | |
| 55 | |
| 56 | |
| 57 class TestServerCommand { | |
| 58 static final START = 0; | |
| 59 static final STOP = 1; | |
| 60 static final CHUNKED_ENCODING = 2; | |
| 61 | |
| 62 TestServerCommand.start() : _command = START; | |
| 63 TestServerCommand.stop() : _command = STOP; | |
| 64 TestServerCommand.chunkedEncoding() : _command = CHUNKED_ENCODING; | |
| 65 | |
| 66 bool get isStart() => _command == START; | |
| 67 bool get isStop() => _command == STOP; | |
| 68 bool get isChunkedEncoding() => _command == CHUNKED_ENCODING; | |
| 69 | |
| 70 int _command; | |
| 71 } | |
| 72 | |
| 73 | |
| 74 class TestServerStatus { | |
| 75 static final STARTED = 0; | |
| 76 static final STOPPED = 1; | |
| 77 static final ERROR = 2; | |
| 78 | |
| 79 TestServerStatus.started(this._port) : _state = STARTED; | |
| 80 TestServerStatus.stopped() : _state = STOPPED; | |
| 81 TestServerStatus.error() : _state = ERROR; | |
| 82 | |
| 83 bool get isStarted() => _state == STARTED; | |
| 84 bool get isStopped() => _state == STOPPED; | |
| 85 bool get isError() => _state == ERROR; | |
| 86 | |
| 87 int get port() => _port; | |
| 88 | |
| 89 int _state; | |
| 90 int _port; | |
| 91 } | |
| 92 | |
| 93 | |
| 94 class TestServer extends Isolate { | |
| 95 // Echo the request content back to the response. | |
| 96 void _echoHandler(HttpRequest request, HttpResponse response) { | |
| 97 Expect.equals("POST", request.method); | |
| 98 response.contentLength = request.contentLength; | |
| 99 request.inputStream.pipe(response.outputStream); | |
| 100 } | |
| 101 | |
| 102 // Echo the request content back to the response. | |
| 103 void _zeroToTenHandler(HttpRequest request, HttpResponse response) { | |
| 104 Expect.equals("GET", request.method); | |
| 105 request.inputStream.onData = () {}; | |
| 106 request.inputStream.onClosed = () { | |
| 107 response.writeString("01234567890"); | |
| 108 response.outputStream.close(); | |
| 109 }; | |
| 110 } | |
| 111 | |
| 112 // Return a 404. | |
| 113 void _notFoundHandler(HttpRequest request, HttpResponse response) { | |
| 114 response.statusCode = HttpStatus.NOT_FOUND; | |
| 115 response.setHeader("Content-Type", "text/html; charset=UTF-8"); | |
| 116 response.writeString("Page not found"); | |
| 117 response.outputStream.close(); | |
| 118 } | |
| 119 | |
| 120 // Return a 301 with a custom reason phrase. | |
| 121 void _reasonForMovingHandler(HttpRequest request, HttpResponse response) { | |
| 122 response.statusCode = HttpStatus.MOVED_PERMANENTLY; | |
| 123 response.reasonPhrase = "Don't come looking here any more"; | |
| 124 response.outputStream.close(); | |
| 125 } | |
| 126 | |
| 127 void main() { | |
| 128 // Setup request handlers. | |
| 129 _requestHandlers = new Map(); | |
| 130 _requestHandlers["/echo"] = (HttpRequest request, HttpResponse response) { | |
| 131 _echoHandler(request, response); | |
| 132 }; | |
| 133 _requestHandlers["/0123456789"] = | |
| 134 (HttpRequest request, HttpResponse response) { | |
| 135 _zeroToTenHandler(request, response); | |
| 136 }; | |
| 137 _requestHandlers["/reasonformoving"] = | |
| 138 (HttpRequest request, HttpResponse response) { | |
| 139 _reasonForMovingHandler(request, response); | |
| 140 }; | |
| 141 | |
| 142 this.port.receive((var message, SendPort replyTo) { | |
| 143 if (message.isStart) { | |
| 144 _server = new HttpServer(); | |
| 145 try { | |
| 146 _server.listen("127.0.0.1", 0); | |
| 147 _server.onRequest = (HttpRequest req, HttpResponse rsp) { | |
| 148 _requestReceivedHandler(req, rsp); | |
| 149 }; | |
| 150 replyTo.send(new TestServerStatus.started(_server.port), null); | |
| 151 } catch (var e) { | |
| 152 replyTo.send(new TestServerStatus.error(), null); | |
| 153 } | |
| 154 } else if (message.isStop) { | |
| 155 _server.close(); | |
| 156 this.port.close(); | |
| 157 replyTo.send(new TestServerStatus.stopped(), null); | |
| 158 } else if (message.isChunkedEncoding) { | |
| 159 _chunkedEncoding = true; | |
| 160 } | |
| 161 }); | |
| 162 } | |
| 163 | |
| 164 void _requestReceivedHandler(HttpRequest request, HttpResponse response) { | |
| 165 var requestHandler =_requestHandlers[request.path]; | |
| 166 if (requestHandler != null) { | |
| 167 requestHandler(request, response); | |
| 168 } else { | |
| 169 _notFoundHandler(request, response); | |
| 170 } | |
| 171 } | |
| 172 | |
| 173 HttpServer _server; // HTTP server instance. | |
| 174 Map _requestHandlers; | |
| 175 bool _chunkedEncoding = false; | |
| 176 } | |
| 177 | |
| 178 | |
| 179 void testStartStop() { | |
| 180 TestServerMain testServerMain = new TestServerMain(); | |
| 181 testServerMain.setServerStartedHandler((int port) { | |
| 182 testServerMain.shutdown(); | |
| 183 }); | |
| 184 testServerMain.start(); | |
| 185 } | |
| 186 | |
| 187 | |
| 188 void testGET() { | |
| 189 TestServerMain testServerMain = new TestServerMain(); | |
| 190 testServerMain.setServerStartedHandler((int port) { | |
| 191 HttpClient httpClient = new HttpClient(); | |
| 192 HttpClientConnection conn = | |
| 193 httpClient.get("127.0.0.1", port, "/0123456789"); | |
| 194 conn.onResponse = (HttpClientResponse response) { | |
| 195 Expect.equals(HttpStatus.OK, response.statusCode); | |
| 196 StringInputStream stream = new StringInputStream(response.inputStream); | |
| 197 StringBuffer body = new StringBuffer(); | |
| 198 stream.onData = () => body.add(stream.read()); | |
| 199 stream.onClosed = () { | |
| 200 Expect.equals("01234567890", body.toString()); | |
| 201 httpClient.shutdown(); | |
| 202 testServerMain.shutdown(); | |
| 203 }; | |
| 204 }; | |
| 205 }); | |
| 206 testServerMain.start(); | |
| 207 } | |
| 208 | |
| 209 | |
| 210 void testPOST(bool chunkedEncoding) { | |
| 211 String data = "ABCDEFGHIJKLMONPQRSTUVWXYZ"; | |
| 212 final int kMessageCount = 10; | |
| 213 | |
| 214 TestServerMain testServerMain = new TestServerMain(); | |
| 215 | |
| 216 void runTest(int port) { | |
| 217 int count = 0; | |
| 218 HttpClient httpClient = new HttpClient(); | |
| 219 void sendRequest() { | |
| 220 HttpClientConnection conn = | |
| 221 httpClient.post("127.0.0.1", port, "/echo"); | |
| 222 conn.onRequest = (HttpClientRequest request) { | |
| 223 if (chunkedEncoding) { | |
| 224 request.writeString(data.substring(0, 10)); | |
| 225 request.writeString(data.substring(10, data.length)); | |
| 226 } else { | |
| 227 request.contentLength = data.length; | |
| 228 request.outputStream.write(data.charCodes()); | |
| 229 } | |
| 230 request.outputStream.close(); | |
| 231 }; | |
| 232 conn.onResponse = (HttpClientResponse response) { | |
| 233 Expect.equals(HttpStatus.OK, response.statusCode); | |
| 234 StringInputStream stream = new StringInputStream(response.inputStream); | |
| 235 StringBuffer body = new StringBuffer(); | |
| 236 stream.onData = () => body.add(stream.read()); | |
| 237 stream.onClosed = () { | |
| 238 Expect.equals(data, body.toString()); | |
| 239 count++; | |
| 240 if (count < kMessageCount) { | |
| 241 sendRequest(); | |
| 242 } else { | |
| 243 httpClient.shutdown(); | |
| 244 testServerMain.shutdown(); | |
| 245 } | |
| 246 }; | |
| 247 }; | |
| 248 } | |
| 249 | |
| 250 sendRequest(); | |
| 251 } | |
| 252 | |
| 253 testServerMain.setServerStartedHandler(runTest); | |
| 254 if (chunkedEncoding) { | |
| 255 testServerMain.chunkedEncoding(); | |
| 256 } | |
| 257 testServerMain.start(); | |
| 258 } | |
| 259 | |
| 260 | |
| 261 void testReadInto(bool chunkedEncoding) { | |
| 262 String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | |
| 263 final int kMessageCount = 10; | |
| 264 | |
| 265 TestServerMain testServerMain = new TestServerMain(); | |
| 266 | |
| 267 void runTest(int port) { | |
| 268 int count = 0; | |
| 269 HttpClient httpClient = new HttpClient(); | |
| 270 void sendRequest() { | |
| 271 HttpClientConnection conn = | |
| 272 httpClient.post("127.0.0.1", port, "/echo"); | |
| 273 conn.onRequest = (HttpClientRequest request) { | |
| 274 if (chunkedEncoding) { | |
| 275 request.writeString(data.substring(0, 10)); | |
| 276 request.writeString(data.substring(10, data.length)); | |
| 277 } else { | |
| 278 request.contentLength = data.length; | |
| 279 request.outputStream.write(data.charCodes()); | |
| 280 } | |
| 281 request.outputStream.close(); | |
| 282 }; | |
| 283 conn.onResponse = (HttpClientResponse response) { | |
| 284 Expect.equals(HttpStatus.OK, response.statusCode); | |
| 285 InputStream stream = response.inputStream; | |
| 286 List<int> body = new List<int>(); | |
| 287 stream.onData = () { | |
| 288 List tmp = new List(3); | |
| 289 int bytes = stream.readInto(tmp); | |
| 290 body.addAll(tmp.getRange(0, bytes)); | |
| 291 }; | |
| 292 stream.onClosed = () { | |
| 293 Expect.equals(data, new String.fromCharCodes(body)); | |
| 294 count++; | |
| 295 if (count < kMessageCount) { | |
| 296 sendRequest(); | |
| 297 } else { | |
| 298 httpClient.shutdown(); | |
| 299 testServerMain.shutdown(); | |
| 300 } | |
| 301 }; | |
| 302 }; | |
| 303 } | |
| 304 | |
| 305 sendRequest(); | |
| 306 } | |
| 307 | |
| 308 testServerMain.setServerStartedHandler(runTest); | |
| 309 if (chunkedEncoding) { | |
| 310 testServerMain.chunkedEncoding(); | |
| 311 } | |
| 312 testServerMain.start(); | |
| 313 } | |
| 314 | |
| 315 | |
| 316 void testReadShort(bool chunkedEncoding) { | |
| 317 String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | |
| 318 final int kMessageCount = 10; | |
| 319 | |
| 320 TestServerMain testServerMain = new TestServerMain(); | |
| 321 | |
| 322 void runTest(int port) { | |
| 323 int count = 0; | |
| 324 HttpClient httpClient = new HttpClient(); | |
| 325 void sendRequest() { | |
| 326 HttpClientConnection conn = | |
| 327 httpClient.post("127.0.0.1", port, "/echo"); | |
| 328 conn.onRequest = (HttpClientRequest request) { | |
| 329 if (chunkedEncoding) { | |
| 330 request.writeString(data.substring(0, 10)); | |
| 331 request.writeString(data.substring(10, data.length)); | |
| 332 } else { | |
| 333 request.contentLength = data.length; | |
| 334 request.outputStream.write(data.charCodes()); | |
| 335 } | |
| 336 request.outputStream.close(); | |
| 337 }; | |
| 338 conn.onResponse = (HttpClientResponse response) { | |
| 339 Expect.equals(HttpStatus.OK, response.statusCode); | |
| 340 InputStream stream = response.inputStream; | |
| 341 List<int> body = new List<int>(); | |
| 342 stream.onData = () { | |
| 343 List tmp = stream.read(2); | |
| 344 body.addAll(tmp); | |
| 345 }; | |
| 346 stream.onClosed = () { | |
| 347 Expect.equals(data, new String.fromCharCodes(body)); | |
| 348 count++; | |
| 349 if (count < kMessageCount) { | |
| 350 sendRequest(); | |
| 351 } else { | |
| 352 httpClient.shutdown(); | |
| 353 testServerMain.shutdown(); | |
| 354 } | |
| 355 }; | |
| 356 }; | |
| 357 } | |
| 358 | |
| 359 sendRequest(); | |
| 360 } | |
| 361 | |
| 362 testServerMain.setServerStartedHandler(runTest); | |
| 363 if (chunkedEncoding) { | |
| 364 testServerMain.chunkedEncoding(); | |
| 365 } | |
| 366 testServerMain.start(); | |
| 367 } | |
| 368 | |
| 369 | |
| 370 void test404() { | |
| 371 TestServerMain testServerMain = new TestServerMain(); | |
| 372 testServerMain.setServerStartedHandler((int port) { | |
| 373 HttpClient httpClient = new HttpClient(); | |
| 374 HttpClientConnection conn = | |
| 375 httpClient.get("127.0.0.1", port, "/thisisnotfound"); | |
| 376 conn.onResponse = (HttpClientResponse response) { | |
| 377 Expect.equals(HttpStatus.NOT_FOUND, response.statusCode); | |
| 378 httpClient.shutdown(); | |
| 379 testServerMain.shutdown(); | |
| 380 }; | |
| 381 }); | |
| 382 testServerMain.start(); | |
| 383 } | |
| 384 | |
| 385 | |
| 386 void testReasonPhrase() { | |
| 387 TestServerMain testServerMain = new TestServerMain(); | |
| 388 testServerMain.setServerStartedHandler((int port) { | |
| 389 HttpClient httpClient = new HttpClient(); | |
| 390 HttpClientConnection conn = | |
| 391 httpClient.get("127.0.0.1", port, "/reasonformoving"); | |
| 392 conn.onResponse = (HttpClientResponse response) { | |
| 393 Expect.equals(HttpStatus.MOVED_PERMANENTLY, response.statusCode); | |
| 394 Expect.equals("Don't come looking here any more", response.reasonPhrase); | |
| 395 httpClient.shutdown(); | |
| 396 testServerMain.shutdown(); | |
| 397 }; | |
| 398 }); | |
| 399 testServerMain.start(); | |
| 400 } | |
| 401 | |
| 402 | |
| 403 void main() { | |
| 404 testStartStop(); | |
| 405 testGET(); | |
| 406 testPOST(true); | |
| 407 testPOST(false); | |
| 408 testReadInto(true); | |
| 409 testReadInto(false); | |
| 410 testReadShort(true); | |
| 411 testReadShort(false); | |
| 412 test404(); | |
| 413 testReasonPhrase(); | |
| 414 } | |
| OLD | NEW |