Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(425)

Side by Side Diff: pkg/http/test/utils.dart

Issue 261763002: Rip out the last dart:io dependency from pkg/http. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: code review Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/http/test/streamed_request_test.dart ('k') | pkg/pkg.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, 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 library test_utils; 5 library test_utils;
6 6
7 import 'dart:async';
8 import 'dart:convert'; 7 import 'dart:convert';
9 import 'dart:io';
10 8
11 import 'package:http/http.dart'; 9 import 'package:http/http.dart' as http;
12 import 'package:http/src/utils.dart'; 10 import 'package:http_parser/http_parser.dart';
13 import 'package:unittest/unittest.dart'; 11 import 'package:unittest/unittest.dart';
14 12
15 /// The current server instance.
16 HttpServer _server;
17
18 /// The URL for the current server instance.
19 Uri get serverUrl => Uri.parse('http://localhost:${_server.port}');
20
21 /// A dummy URL for constructing requests that won't be sent. 13 /// A dummy URL for constructing requests that won't be sent.
22 Uri get dummyUrl => Uri.parse('http://dartlang.org/'); 14 Uri get dummyUrl => Uri.parse('http://dartlang.org/');
23 15
24 /// Starts a new HTTP server.
25 Future startServer() {
26 return HttpServer.bind("localhost", 0).then((s) {
27 _server = s;
28 s.listen((request) {
29 var path = request.uri.path;
30 var response = request.response;
31
32 if (path == '/error') {
33 response.statusCode = 400;
34 response.contentLength = 0;
35 response.close();
36 return;
37 }
38
39 if (path == '/loop') {
40 var n = int.parse(request.uri.query);
41 response.statusCode = 302;
42 response.headers.set('location',
43 serverUrl.resolve('/loop?${n + 1}').toString());
44 response.contentLength = 0;
45 response.close();
46 return;
47 }
48
49 if (path == '/redirect') {
50 response.statusCode = 302;
51 response.headers.set('location', serverUrl.resolve('/').toString());
52 response.contentLength = 0;
53 response.close();
54 return;
55 }
56
57 if (path == '/no-content-length') {
58 response.statusCode = 200;
59 response.contentLength = -1;
60 response.write('body');
61 response.close();
62 return;
63 }
64
65 new ByteStream(request).toBytes().then((requestBodyBytes) {
66 var outputEncoding;
67 var encodingName = request.uri.queryParameters['response-encoding'];
68 if (encodingName != null) {
69 outputEncoding = requiredEncodingForCharset(encodingName);
70 } else {
71 outputEncoding = ASCII;
72 }
73
74 response.headers.contentType =
75 new ContentType(
76 "application", "json", charset: outputEncoding.name);
77 response.headers.set('single', 'value');
78
79 var requestBody;
80 if (requestBodyBytes.isEmpty) {
81 requestBody = null;
82 } else if (request.headers.contentType != null &&
83 request.headers.contentType.charset != null) {
84 var encoding = requiredEncodingForCharset(
85 request.headers.contentType.charset);
86 requestBody = encoding.decode(requestBodyBytes);
87 } else {
88 requestBody = requestBodyBytes;
89 }
90
91 var content = {
92 'method': request.method,
93 'path': request.uri.path,
94 'headers': {}
95 };
96 if (requestBody != null) content['body'] = requestBody;
97 request.headers.forEach((name, values) {
98 // These headers are automatically generated by dart:io, so we don't
99 // want to test them here.
100 if (name == 'cookie' || name == 'host') return;
101
102 content['headers'][name] = values;
103 });
104
105 var body = JSON.encode(content);
106 response.contentLength = body.length;
107 response.write(body);
108 response.close();
109 });
110 });
111 });
112 }
113
114 /// Stops the current HTTP server.
115 void stopServer() {
116 if (_server != null) {
117 _server.close();
118 _server = null;
119 }
120 }
121
122 /// Removes eight spaces of leading indentation from a multiline string. 16 /// Removes eight spaces of leading indentation from a multiline string.
123 /// 17 ///
124 /// Note that this is very sensitive to how the literals are styled. They should 18 /// Note that this is very sensitive to how the literals are styled. They should
125 /// be: 19 /// be:
126 /// ''' 20 /// '''
127 /// Text starts on own line. Lines up with subsequent lines. 21 /// Text starts on own line. Lines up with subsequent lines.
128 /// Lines are indented exactly 8 characters from the left margin. 22 /// Lines are indented exactly 8 characters from the left margin.
129 /// Close is on the same line.''' 23 /// Close is on the same line.'''
130 /// 24 ///
131 /// This does nothing if text is only a single line. 25 /// This does nothing if text is only a single line.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 61
168 return _matcher.matches(parsed, matchState); 62 return _matcher.matches(parsed, matchState);
169 } 63 }
170 64
171 Description describe(Description description) { 65 Description describe(Description description) {
172 return description.add('parses to a value that ') 66 return description.add('parses to a value that ')
173 .addDescriptionOf(_matcher); 67 .addDescriptionOf(_matcher);
174 } 68 }
175 } 69 }
176 70
177 /// A matcher for functions that throw HttpException. 71 /// A matcher that validates the body of a multipart request after finalization.
178 Matcher get throwsClientException => 72 /// The string "{{boundary}}" in [pattern] will be replaced by the boundary
179 throwsA(new isInstanceOf<ClientException>()); 73 /// string for the request, and LF newlines will be replaced with CRLF.
74 /// Indentation will be normalized.
75 Matcher bodyMatches(String pattern) => new _BodyMatches(pattern);
180 76
181 /// A matcher for RedirectLimitExceededExceptions. 77 class _BodyMatches extends Matcher {
182 const isRedirectLimitExceededException = 78 final String _pattern;
183 const _RedirectLimitExceededException();
184 79
185 /// A matcher for functions that throw RedirectLimitExceededException. 80 _BodyMatches(this._pattern);
186 const Matcher throwsRedirectLimitExceededException =
187 const Throws(isRedirectLimitExceededException);
188 81
189 class _RedirectLimitExceededException extends TypeMatcher { 82 bool matches(item, Map matchState) {
190 const _RedirectLimitExceededException() : 83 if (item is! http.MultipartRequest) return false;
191 super("RedirectLimitExceededException");
192 84
193 bool matches(item, Map matchState) => 85 var future = item.finalize().toBytes().then((bodyBytes) {
194 item is RedirectException && item.message == "Redirect limit exceeded"; 86 var body = UTF8.decode(bodyBytes);
87 var contentType = new MediaType.parse(item.headers['content-type']);
88 var boundary = contentType.parameters['boundary'];
89 var expected = cleanUpLiteral(_pattern)
90 .replaceAll("\n", "\r\n")
91 .replaceAll("{{boundary}}", boundary);
92
93 expect(body, equals(expected));
94 expect(item.contentLength, equals(bodyBytes.length));
95 });
96
97 return completes.matches(future, matchState);
98 }
99
100 Description describe(Description description) {
101 return description.add('has a body that matches "$_pattern"');
102 }
195 } 103 }
196 104
197 /// A matcher for SocketExceptions. 105 /// A matcher that matches a [http.ClientException] with the given [message].
198 const isSocketException = const _SocketException(); 106 ///
107 /// [message] can be a String or a [Matcher].
108 Matcher isClientException(message) => predicate((error) {
109 expect(error, new isInstanceOf<http.ClientException>());
110 expect(error.message, message);
111 return true;
112 });
199 113
200 /// A matcher for functions that throw SocketException. 114 /// A matcher that matches function or future that throws a
201 const Matcher throwsSocketException = 115 /// [http.ClientException] with the given [message].
202 const Throws(isSocketException); 116 ///
203 117 /// [message] can be a String or a [Matcher].
204 class _SocketException extends TypeMatcher { 118 Matcher throwsClientException(message) => throwsA(isClientException(message));
205 const _SocketException() : super("SocketException");
206 bool matches(item, Map matchState) => item is SocketException;
207 }
OLDNEW
« no previous file with comments | « pkg/http/test/streamed_request_test.dart ('k') | pkg/pkg.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698