| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 // | 4 // |
| 5 // VMOptions= | 5 // VMOptions= |
| 6 // VMOptions=--short_socket_read | 6 // VMOptions=--short_socket_read |
| 7 // VMOptions=--short_socket_write | 7 // VMOptions=--short_socket_write |
| 8 // VMOptions=--short_socket_read --short_socket_write | 8 // VMOptions=--short_socket_read --short_socket_write |
| 9 | 9 |
| 10 import "dart:isolate"; | 10 import "dart:isolate"; |
| 11 import "dart:io"; | 11 import "dart:io"; |
| 12 | 12 |
| 13 class TestServerMain { | 13 class IsolatedHttpServer { |
| 14 TestServerMain() | 14 IsolatedHttpServer() |
| 15 : _statusPort = new ReceivePort(), | 15 : _statusPort = new ReceivePort(), |
| 16 _serverPort = null { | 16 _serverPort = null { |
| 17 _serverPort = spawnFunction(startTestServer); | 17 _serverPort = spawnFunction(startIsolatedHttpServer); |
| 18 } | 18 } |
| 19 | 19 |
| 20 void setServerStartedHandler(void startedCallback(int port)) { | 20 void setServerStartedHandler(void startedCallback(int port)) { |
| 21 _startedCallback = startedCallback; | 21 _startedCallback = startedCallback; |
| 22 } | 22 } |
| 23 | 23 |
| 24 void start() { | 24 void start() { |
| 25 // Handle status messages from the server. | 25 // Handle status messages from the server. |
| 26 _statusPort.receive((var status, SendPort replyTo) { | 26 _statusPort.receive((var status, SendPort replyTo) { |
| 27 if (status.isStarted) { | 27 if (status.isStarted) { |
| 28 _startedCallback(status.port); | 28 _startedCallback(status.port); |
| 29 } | 29 } |
| 30 }); | 30 }); |
| 31 | 31 |
| 32 // Send server start message to the server. | 32 // Send server start message to the server. |
| 33 var command = new TestServerCommand.start(); | 33 var command = new IsolatedHttpServerCommand.start(); |
| 34 _serverPort.send(command, _statusPort.toSendPort()); | 34 _serverPort.send(command, _statusPort.toSendPort()); |
| 35 } | 35 } |
| 36 | 36 |
| 37 void shutdown() { | 37 void shutdown() { |
| 38 // Send server stop message to the server. | 38 // Send server stop message to the server. |
| 39 _serverPort.send(new TestServerCommand.stop(), _statusPort.toSendPort()); | 39 _serverPort.send(new IsolatedHttpServerCommand.stop(), |
| 40 _statusPort.toSendPort()); |
| 40 _statusPort.close(); | 41 _statusPort.close(); |
| 41 } | 42 } |
| 42 | 43 |
| 43 void chunkedEncoding() { | 44 void chunkedEncoding() { |
| 44 // Send chunked encoding message to the server. | 45 // Send chunked encoding message to the server. |
| 45 _serverPort.send( | 46 _serverPort.send( |
| 46 new TestServerCommand.chunkedEncoding(), _statusPort.toSendPort()); | 47 new IsolatedHttpServerCommand.chunkedEncoding(), |
| 48 _statusPort.toSendPort()); |
| 47 } | 49 } |
| 48 | 50 |
| 49 ReceivePort _statusPort; // Port for receiving messages from the server. | 51 ReceivePort _statusPort; // Port for receiving messages from the server. |
| 50 SendPort _serverPort; // Port for sending messages to the server. | 52 SendPort _serverPort; // Port for sending messages to the server. |
| 51 var _startedCallback; | 53 var _startedCallback; |
| 52 } | 54 } |
| 53 | 55 |
| 54 | 56 |
| 55 class TestServerCommand { | 57 class IsolatedHttpServerCommand { |
| 56 static const START = 0; | 58 static const START = 0; |
| 57 static const STOP = 1; | 59 static const STOP = 1; |
| 58 static const CHUNKED_ENCODING = 2; | 60 static const CHUNKED_ENCODING = 2; |
| 59 | 61 |
| 60 TestServerCommand.start() : _command = START; | 62 IsolatedHttpServerCommand.start() : _command = START; |
| 61 TestServerCommand.stop() : _command = STOP; | 63 IsolatedHttpServerCommand.stop() : _command = STOP; |
| 62 TestServerCommand.chunkedEncoding() : _command = CHUNKED_ENCODING; | 64 IsolatedHttpServerCommand.chunkedEncoding() : _command = CHUNKED_ENCODING; |
| 63 | 65 |
| 64 bool get isStart => _command == START; | 66 bool get isStart => _command == START; |
| 65 bool get isStop => _command == STOP; | 67 bool get isStop => _command == STOP; |
| 66 bool get isChunkedEncoding => _command == CHUNKED_ENCODING; | 68 bool get isChunkedEncoding => _command == CHUNKED_ENCODING; |
| 67 | 69 |
| 68 int _command; | 70 int _command; |
| 69 } | 71 } |
| 70 | 72 |
| 71 | 73 |
| 72 class TestServerStatus { | 74 class IsolatedHttpServerStatus { |
| 73 static const STARTED = 0; | 75 static const STARTED = 0; |
| 74 static const STOPPED = 1; | 76 static const STOPPED = 1; |
| 75 static const ERROR = 2; | 77 static const ERROR = 2; |
| 76 | 78 |
| 77 TestServerStatus.started(this._port) : _state = STARTED; | 79 IsolatedHttpServerStatus.started(this._port) : _state = STARTED; |
| 78 TestServerStatus.stopped() : _state = STOPPED; | 80 IsolatedHttpServerStatus.stopped() : _state = STOPPED; |
| 79 TestServerStatus.error() : _state = ERROR; | 81 IsolatedHttpServerStatus.error() : _state = ERROR; |
| 80 | 82 |
| 81 bool get isStarted => _state == STARTED; | 83 bool get isStarted => _state == STARTED; |
| 82 bool get isStopped => _state == STOPPED; | 84 bool get isStopped => _state == STOPPED; |
| 83 bool get isError => _state == ERROR; | 85 bool get isError => _state == ERROR; |
| 84 | 86 |
| 85 int get port => _port; | 87 int get port => _port; |
| 86 | 88 |
| 87 int _state; | 89 int _state; |
| 88 int _port; | 90 int _port; |
| 89 } | 91 } |
| 90 | 92 |
| 91 | 93 |
| 92 void startTestServer() { | 94 void startIsolatedHttpServer() { |
| 93 var server = new TestServer(); | 95 var server = new TestServer(); |
| 94 server.init(); | 96 server.init(); |
| 95 port.receive(server.dispatch); | 97 port.receive(server.dispatch); |
| 96 } | 98 } |
| 97 | 99 |
| 98 class TestServer { | 100 class TestServer { |
| 99 // Echo the request content back to the response. | 101 // Echo the request content back to the response. |
| 100 void _echoHandler(HttpRequest request, HttpResponse response) { | 102 void _echoHandler(HttpRequest request) { |
| 103 var response = request.response; |
| 101 Expect.equals("POST", request.method); | 104 Expect.equals("POST", request.method); |
| 102 response.contentLength = request.contentLength; | 105 response.contentLength = request.contentLength; |
| 103 request.inputStream.pipe(response.outputStream); | 106 request.pipe(response); |
| 104 } | 107 } |
| 105 | 108 |
| 106 // Return a 404. | 109 // Return a 404. |
| 107 void _notFoundHandler(HttpRequest request, HttpResponse response) { | 110 void _notFoundHandler(HttpRequest request) { |
| 111 var response = request.response; |
| 108 response.statusCode = HttpStatus.NOT_FOUND; | 112 response.statusCode = HttpStatus.NOT_FOUND; |
| 109 response.headers.set("Content-Type", "text/html; charset=UTF-8"); | 113 response.headers.set("Content-Type", "text/html; charset=UTF-8"); |
| 110 response.outputStream.writeString("Page not found"); | 114 response.addString("Page not found"); |
| 111 response.outputStream.close(); | 115 response.close(); |
| 112 } | 116 } |
| 113 | 117 |
| 114 | 118 |
| 115 void init() { | 119 void init() { |
| 116 // Setup request handlers. | 120 // Setup request handlers. |
| 117 _requestHandlers = new Map(); | 121 _requestHandlers = new Map(); |
| 118 _requestHandlers["/echo"] = (HttpRequest request, HttpResponse response) { | 122 _requestHandlers["/echo"] = _echoHandler; |
| 119 _echoHandler(request, response); | |
| 120 }; | |
| 121 } | 123 } |
| 122 | 124 |
| 123 void dispatch(message, SendPort replyTo) { | 125 void dispatch(message, SendPort replyTo) { |
| 124 if (message.isStart) { | 126 if (message.isStart) { |
| 125 _server = new HttpServer(); | |
| 126 try { | 127 try { |
| 127 _server.listen("127.0.0.1", 0); | 128 HttpServer.bind().then((server) { |
| 128 _server.defaultRequestHandler = (HttpRequest req, HttpResponse rsp) { | 129 _server = server; |
| 129 _requestReceivedHandler(req, rsp); | 130 _server.listen(_requestReceivedHandler); |
| 130 }; | 131 replyTo.send( |
| 131 replyTo.send(new TestServerStatus.started(_server.port), null); | 132 new IsolatedHttpServerStatus.started(_server.port), null); |
| 133 }); |
| 132 } catch (e) { | 134 } catch (e) { |
| 133 replyTo.send(new TestServerStatus.error(), null); | 135 replyTo.send(new IsolatedHttpServerStatus.error(), null); |
| 134 } | 136 } |
| 135 } else if (message.isStop) { | 137 } else if (message.isStop) { |
| 136 _server.close(); | 138 _server.close(); |
| 137 port.close(); | 139 port.close(); |
| 138 replyTo.send(new TestServerStatus.stopped(), null); | 140 replyTo.send(new IsolatedHttpServerStatus.stopped(), null); |
| 139 } else if (message.isChunkedEncoding) { | 141 } else if (message.isChunkedEncoding) { |
| 140 _chunkedEncoding = true; | 142 _chunkedEncoding = true; |
| 141 } | 143 } |
| 142 } | 144 } |
| 143 | 145 |
| 144 void _requestReceivedHandler(HttpRequest request, HttpResponse response) { | 146 void _requestReceivedHandler(HttpRequest request) { |
| 145 var requestHandler =_requestHandlers[request.path]; | 147 var requestHandler =_requestHandlers[request.uri.path]; |
| 146 if (requestHandler != null) { | 148 if (requestHandler != null) { |
| 147 requestHandler(request, response); | 149 requestHandler(request); |
| 148 } else { | 150 } else { |
| 149 _notFoundHandler(request, response); | 151 _notFoundHandler(request); |
| 150 } | 152 } |
| 151 } | 153 } |
| 152 | 154 |
| 153 HttpServer _server; // HTTP server instance. | 155 HttpServer _server; // HTTP server instance. |
| 154 Map _requestHandlers; | 156 Map _requestHandlers; |
| 155 bool _chunkedEncoding = false; | 157 bool _chunkedEncoding = false; |
| 156 } | 158 } |
| 157 | 159 |
| 158 void testReadInto(bool chunkedEncoding) { | 160 void testRead(bool chunkedEncoding) { |
| 159 String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | 161 String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
| 160 final int kMessageCount = 10; | 162 final int kMessageCount = 10; |
| 161 | 163 |
| 162 TestServerMain testServerMain = new TestServerMain(); | 164 IsolatedHttpServer server = new IsolatedHttpServer(); |
| 163 | 165 |
| 164 void runTest(int port) { | 166 void runTest(int port) { |
| 165 int count = 0; | 167 int count = 0; |
| 166 HttpClient httpClient = new HttpClient(); | 168 HttpClient httpClient = new HttpClient(); |
| 167 void sendRequest() { | 169 void sendRequest() { |
| 168 HttpClientConnection conn = | 170 httpClient.post("127.0.0.1", port, "/echo") |
| 169 httpClient.post("127.0.0.1", port, "/echo"); | 171 .then((request) { |
| 170 conn.onRequest = (HttpClientRequest request) { | 172 if (chunkedEncoding) { |
| 171 if (chunkedEncoding) { | 173 request.addString(data.substring(0, 10)); |
| 172 request.outputStream.writeString(data.substring(0, 10)); | 174 request.addString(data.substring(10, data.length)); |
| 173 request.outputStream.writeString(data.substring(10, data.length)); | 175 } else { |
| 174 } else { | 176 request.contentLength = data.length; |
| 175 request.contentLength = data.length; | 177 request.add(data.charCodes); |
| 176 request.outputStream.write(data.charCodes); | 178 } |
| 177 } | 179 return request.close(); |
| 178 request.outputStream.close(); | 180 }) |
| 179 }; | 181 .then((response) { |
| 180 conn.onResponse = (HttpClientResponse response) { | 182 Expect.equals(HttpStatus.OK, response.statusCode); |
| 181 Expect.equals(HttpStatus.OK, response.statusCode); | 183 List<int> body = new List<int>(); |
| 182 InputStream stream = response.inputStream; | 184 response.listen( |
| 183 List<int> body = new List<int>(); | 185 body.addAll, |
| 184 stream.onData = () { | 186 onDone: () { |
| 185 List tmp = new List.fixedLength(3); | 187 Expect.equals(data, new String.fromCharCodes(body)); |
| 186 int bytes = stream.readInto(tmp); | 188 count++; |
| 187 body.addAll(tmp.getRange(0, bytes)); | 189 if (count < kMessageCount) { |
| 188 }; | 190 sendRequest(); |
| 189 stream.onClosed = () { | 191 } else { |
| 190 Expect.equals(data, new String.fromCharCodes(body)); | 192 httpClient.close(); |
| 191 count++; | 193 server.shutdown(); |
| 192 if (count < kMessageCount) { | 194 } |
| 193 sendRequest(); | 195 }); |
| 194 } else { | 196 }); |
| 195 httpClient.shutdown(); | |
| 196 testServerMain.shutdown(); | |
| 197 } | |
| 198 }; | |
| 199 }; | |
| 200 } | 197 } |
| 201 | |
| 202 sendRequest(); | 198 sendRequest(); |
| 203 } | 199 } |
| 204 | 200 |
| 205 testServerMain.setServerStartedHandler(runTest); | 201 server.setServerStartedHandler(runTest); |
| 206 if (chunkedEncoding) { | 202 if (chunkedEncoding) { |
| 207 testServerMain.chunkedEncoding(); | 203 server.chunkedEncoding(); |
| 208 } | 204 } |
| 209 testServerMain.start(); | 205 server.start(); |
| 210 } | |
| 211 | |
| 212 void testReadShort(bool chunkedEncoding) { | |
| 213 String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | |
| 214 final int kMessageCount = 10; | |
| 215 | |
| 216 TestServerMain testServerMain = new TestServerMain(); | |
| 217 | |
| 218 void runTest(int port) { | |
| 219 int count = 0; | |
| 220 HttpClient httpClient = new HttpClient(); | |
| 221 void sendRequest() { | |
| 222 HttpClientConnection conn = | |
| 223 httpClient.post("127.0.0.1", port, "/echo"); | |
| 224 conn.onRequest = (HttpClientRequest request) { | |
| 225 if (chunkedEncoding) { | |
| 226 request.outputStream.writeString(data.substring(0, 10)); | |
| 227 request.outputStream.writeString(data.substring(10, data.length)); | |
| 228 } else { | |
| 229 request.contentLength = data.length; | |
| 230 request.outputStream.write(data.charCodes); | |
| 231 } | |
| 232 request.outputStream.close(); | |
| 233 }; | |
| 234 conn.onResponse = (HttpClientResponse response) { | |
| 235 Expect.equals(HttpStatus.OK, response.statusCode); | |
| 236 InputStream stream = response.inputStream; | |
| 237 List<int> body = new List<int>(); | |
| 238 stream.onData = () { | |
| 239 List tmp = stream.read(2); | |
| 240 body.addAll(tmp); | |
| 241 }; | |
| 242 stream.onClosed = () { | |
| 243 Expect.equals(data, new String.fromCharCodes(body)); | |
| 244 count++; | |
| 245 if (count < kMessageCount) { | |
| 246 sendRequest(); | |
| 247 } else { | |
| 248 httpClient.shutdown(); | |
| 249 testServerMain.shutdown(); | |
| 250 } | |
| 251 }; | |
| 252 }; | |
| 253 } | |
| 254 | |
| 255 sendRequest(); | |
| 256 } | |
| 257 | |
| 258 testServerMain.setServerStartedHandler(runTest); | |
| 259 if (chunkedEncoding) { | |
| 260 testServerMain.chunkedEncoding(); | |
| 261 } | |
| 262 testServerMain.start(); | |
| 263 } | 206 } |
| 264 | 207 |
| 265 void main() { | 208 void main() { |
| 266 testReadInto(true); | 209 testRead(true); |
| 267 testReadInto(false); | 210 testRead(false); |
| 268 testReadShort(true); | |
| 269 testReadShort(false); | |
| 270 } | 211 } |
| OLD | NEW |