| 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.outputStream.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.headers.set("Content-Type", "text/html; charset=UTF-8"); |
| 116 response.outputStream.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 // Check the "Host" header. |
| 128 void _hostHandler(HttpRequest request, HttpResponse response) { |
| 129 Expect.equals(1, request.headers["Host"].length); |
| 130 Expect.equals("www.dartlang.org:1234", request.headers["Host"][0]); |
| 131 Expect.equals("www.dartlang.org", request.headers.host); |
| 132 Expect.equals(1234, request.headers.port); |
| 133 response.statusCode = HttpStatus.OK; |
| 134 response.outputStream.close(); |
| 135 } |
| 136 |
| 137 void main() { |
| 138 // Setup request handlers. |
| 139 _requestHandlers = new Map(); |
| 140 _requestHandlers["/echo"] = (HttpRequest request, HttpResponse response) { |
| 141 _echoHandler(request, response); |
| 142 }; |
| 143 _requestHandlers["/0123456789"] = |
| 144 (HttpRequest request, HttpResponse response) { |
| 145 _zeroToTenHandler(request, response); |
| 146 }; |
| 147 _requestHandlers["/reasonformoving"] = |
| 148 (HttpRequest request, HttpResponse response) { |
| 149 _reasonForMovingHandler(request, response); |
| 150 }; |
| 151 _requestHandlers["/host"] = |
| 152 (HttpRequest request, HttpResponse response) { |
| 153 _hostHandler(request, response); |
| 154 }; |
| 155 |
| 156 this.port.receive((var message, SendPort replyTo) { |
| 157 if (message.isStart) { |
| 158 _server = new HttpServer(); |
| 159 try { |
| 160 _server.listen("127.0.0.1", 0); |
| 161 _server.defaultRequestHandler = (HttpRequest req, HttpResponse rsp) { |
| 162 _requestReceivedHandler(req, rsp); |
| 163 }; |
| 164 replyTo.send(new TestServerStatus.started(_server.port), null); |
| 165 } catch (var e) { |
| 166 replyTo.send(new TestServerStatus.error(), null); |
| 167 } |
| 168 } else if (message.isStop) { |
| 169 _server.close(); |
| 170 this.port.close(); |
| 171 replyTo.send(new TestServerStatus.stopped(), null); |
| 172 } else if (message.isChunkedEncoding) { |
| 173 _chunkedEncoding = true; |
| 174 } |
| 175 }); |
| 176 } |
| 177 |
| 178 void _requestReceivedHandler(HttpRequest request, HttpResponse response) { |
| 179 var requestHandler =_requestHandlers[request.path]; |
| 180 if (requestHandler != null) { |
| 181 requestHandler(request, response); |
| 182 } else { |
| 183 _notFoundHandler(request, response); |
| 184 } |
| 185 } |
| 186 |
| 187 HttpServer _server; // HTTP server instance. |
| 188 Map _requestHandlers; |
| 189 bool _chunkedEncoding = false; |
| 190 } |
| 191 |
| 192 void testStartStop() { |
| 193 TestServerMain testServerMain = new TestServerMain(); |
| 194 testServerMain.setServerStartedHandler((int port) { |
| 195 testServerMain.shutdown(); |
| 196 }); |
| 197 testServerMain.start(); |
| 198 } |
| 199 |
| 200 void testGET() { |
| 201 TestServerMain testServerMain = new TestServerMain(); |
| 202 testServerMain.setServerStartedHandler((int port) { |
| 203 HttpClient httpClient = new HttpClient(); |
| 204 HttpClientConnection conn = |
| 205 httpClient.get("127.0.0.1", port, "/0123456789"); |
| 206 conn.onResponse = (HttpClientResponse response) { |
| 207 Expect.equals(HttpStatus.OK, response.statusCode); |
| 208 StringInputStream stream = new StringInputStream(response.inputStream); |
| 209 StringBuffer body = new StringBuffer(); |
| 210 stream.onData = () => body.add(stream.read()); |
| 211 stream.onClosed = () { |
| 212 Expect.equals("01234567890", body.toString()); |
| 213 httpClient.shutdown(); |
| 214 testServerMain.shutdown(); |
| 215 }; |
| 216 }; |
| 217 }); |
| 218 testServerMain.start(); |
| 219 } |
| 220 |
| 221 void testPOST(bool chunkedEncoding) { |
| 222 String data = "ABCDEFGHIJKLMONPQRSTUVWXYZ"; |
| 223 final int kMessageCount = 10; |
| 224 |
| 225 TestServerMain testServerMain = new TestServerMain(); |
| 226 |
| 227 void runTest(int port) { |
| 228 int count = 0; |
| 229 HttpClient httpClient = new HttpClient(); |
| 230 void sendRequest() { |
| 231 HttpClientConnection conn = |
| 232 httpClient.post("127.0.0.1", port, "/echo"); |
| 233 conn.onRequest = (HttpClientRequest request) { |
| 234 if (chunkedEncoding) { |
| 235 request.outputStream.writeString(data.substring(0, 10)); |
| 236 request.outputStream.writeString(data.substring(10, data.length)); |
| 237 } else { |
| 238 request.contentLength = data.length; |
| 239 request.outputStream.write(data.charCodes()); |
| 240 } |
| 241 request.outputStream.close(); |
| 242 }; |
| 243 conn.onResponse = (HttpClientResponse response) { |
| 244 Expect.equals(HttpStatus.OK, response.statusCode); |
| 245 StringInputStream stream = new StringInputStream(response.inputStream); |
| 246 StringBuffer body = new StringBuffer(); |
| 247 stream.onData = () => body.add(stream.read()); |
| 248 stream.onClosed = () { |
| 249 Expect.equals(data, body.toString()); |
| 250 count++; |
| 251 if (count < kMessageCount) { |
| 252 sendRequest(); |
| 253 } else { |
| 254 httpClient.shutdown(); |
| 255 testServerMain.shutdown(); |
| 256 } |
| 257 }; |
| 258 }; |
| 259 } |
| 260 |
| 261 sendRequest(); |
| 262 } |
| 263 |
| 264 testServerMain.setServerStartedHandler(runTest); |
| 265 if (chunkedEncoding) { |
| 266 testServerMain.chunkedEncoding(); |
| 267 } |
| 268 testServerMain.start(); |
| 269 } |
| 270 |
| 271 void test404() { |
| 272 TestServerMain testServerMain = new TestServerMain(); |
| 273 testServerMain.setServerStartedHandler((int port) { |
| 274 HttpClient httpClient = new HttpClient(); |
| 275 HttpClientConnection conn = |
| 276 httpClient.get("127.0.0.1", port, "/thisisnotfound"); |
| 277 conn.onResponse = (HttpClientResponse response) { |
| 278 Expect.equals(HttpStatus.NOT_FOUND, response.statusCode); |
| 279 httpClient.shutdown(); |
| 280 testServerMain.shutdown(); |
| 281 }; |
| 282 }); |
| 283 testServerMain.start(); |
| 284 } |
| 285 |
| 286 void testReasonPhrase() { |
| 287 TestServerMain testServerMain = new TestServerMain(); |
| 288 testServerMain.setServerStartedHandler((int port) { |
| 289 HttpClient httpClient = new HttpClient(); |
| 290 HttpClientConnection conn = |
| 291 httpClient.get("127.0.0.1", port, "/reasonformoving"); |
| 292 conn.followRedirects = false; |
| 293 conn.onResponse = (HttpClientResponse response) { |
| 294 Expect.equals(HttpStatus.MOVED_PERMANENTLY, response.statusCode); |
| 295 Expect.equals("Don't come looking here any more", response.reasonPhrase); |
| 296 httpClient.shutdown(); |
| 297 testServerMain.shutdown(); |
| 298 }; |
| 299 }); |
| 300 testServerMain.start(); |
| 301 } |
| 302 |
| 303 void main() { |
| 304 testStartStop(); |
| 305 testGET(); |
| 306 testPOST(true); |
| 307 testPOST(false); |
| 308 test404(); |
| 309 testReasonPhrase(); |
| 310 } |
| OLD | NEW |