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

Side by Side Diff: pkg/pubserver/test/shelf_pubserver_test.dart

Issue 917793002: Use pub_server package (Closed) Base URL: git@github.com:dart-lang/pub-dartlang-dart.git@master
Patch Set: Created 5 years, 10 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
« no previous file with comments | « pkg/pubserver/pubspec.yaml ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2015, 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 library pubserver.shelf_pubserver_test;
6
7 import 'dart:async';
8 import 'dart:convert';
9
10 import 'package:shelf/shelf.dart' as shelf;
11 import 'package:pubserver/repository.dart';
12 import 'package:pubserver/shelf_pubserver.dart';
13 import 'package:unittest/unittest.dart';
14
15 class RepositoryMock implements PackageRepository {
16 final Function downloadFun;
17 final Function downloadUrlFun;
18 final Function finishAsyncUploadFun;
19 final Function lookupVersionFun;
20 final Function startAsyncUploadFun;
21 final Function uploadFun;
22 final Function versionsFun;
23
24 RepositoryMock(
25 {this.downloadFun, this.downloadUrlFun, this.finishAsyncUploadFun,
26 this.lookupVersionFun, this.startAsyncUploadFun, this.uploadFun,
27 this.versionsFun, this.supportsAsyncUpload: false,
28 this.supportsDownloadUrl: false, this.supportsUpload: false});
29
30 Future<Stream> download(String package, String version) async {
31 if (downloadFun != null) return downloadFun(package, version);
32 throw 'download';
33 }
34
35 Future<Uri> downloadUrl(String package, String version) async {
36 if (downloadUrlFun != null) return downloadUrlFun(package, version);
37 throw 'downloadUrl';
38 }
39
40 Future finishAsyncUpload(Uri uri) async {
41 if (finishAsyncUploadFun != null) return finishAsyncUploadFun(uri);
42 throw 'finishAsyncUpload';
43 }
44
45 Future<PackageVersion> lookupVersion(String package, String version) async {
46 if (lookupVersionFun != null) return lookupVersionFun(package, version);
47 throw 'lookupVersion';
48 }
49
50 Future<AsyncUploadInfo> startAsyncUpload(Uri redirectUrl) async {
51 if (startAsyncUploadFun != null) {
52 return startAsyncUploadFun(redirectUrl);
53 }
54 throw 'startAsyncUpload';
55 }
56
57 final bool supportsAsyncUpload;
58
59 final bool supportsDownloadUrl;
60
61 final bool supportsUpload;
62
63 Future upload(Stream<List<int>> data) {
64 if (uploadFun != null) return uploadFun(data);
65 throw 'upload';
66 }
67
68 Stream<PackageVersion> versions(String package) {
69 if (versionsFun != null) return versionsFun(package);
70 return new Stream.fromFuture(new Future.error('versions'));
71 }
72 }
73
74 Uri getUri(String path) => Uri.parse('http://www.example.com$path');
75
76 shelf.Request getRequest(String path) {
77 var url = getUri(path);
78 return new shelf.Request('GET', url);
79 }
80
81 shelf.Request multipartRequest(Uri uri, List<int> bytes) {
82 var requestBytes = [];
83 String boundary = 'testboundary';
84
85 requestBytes.addAll(ASCII.encode('--$boundary\r\n'));
86 requestBytes.addAll(
87 ASCII.encode('Content-Type: application/octet-stream\r\n'));
88 requestBytes.addAll(ASCII.encode('Content-Length: ${bytes.length}\r\n'));
89 requestBytes.addAll(ASCII.encode('Content-Disposition: '
90 'form-data; name="file"; '
91 'filename="package.tar.gz"\r\n\r\n'));
92 requestBytes.addAll(bytes);
93 requestBytes.addAll(ASCII.encode('\r\n--$boundary--\r\n'));
94
95 var headers = {
96 'Content-Type' : 'multipart/form-data; boundary="$boundary"',
97 'Content-Length' : '${requestBytes.length}',
98 };
99
100 var body = new Stream.fromIterable([requestBytes]);
101 return new shelf.Request('POST', uri, headers: headers, body: body);
102 }
103
104 main() {
105 group('shelf_pubserver', () {
106 test('invalid endpoint', () async {
107 var mock = new RepositoryMock();
108 var server = new ShelfPubServer(mock);
109
110 testInvalidUrl(String path) async {
111 var request = getRequest(path);
112 var response = await server.requestHandler(request);
113 await response.read().drain();
114 expect(response.statusCode, equals(404));
115 }
116
117 await testInvalidUrl('/foobar');
118 await testInvalidUrl('/api');
119 await testInvalidUrl('/api/');
120 await testInvalidUrl('/api/packages/analyzer/0.1.0');
121 });
122
123 group('/api/packages/<package>', () {
124 test('does not exist', () async {
125 var mock =
126 new RepositoryMock(versionsFun: (_) => new Stream.fromIterable([]));
127 var server = new ShelfPubServer(mock);
128 var request = getRequest('/api/packages/analyzer');
129
130 var response = await server.requestHandler(request);
131 await response.read().drain();
132 expect(response.statusCode, equals(404));
133 });
134
135 test('success full retrieval of version', () async {
136 var mock = new RepositoryMock(versionsFun: (String package) {
137 // The pubspec is invalid, but that is irrelevant for this test.
138 var pubspec = JSON.encode({'foo': 1});
139 var analyzer = new PackageVersion('analyzer', '0.1.0', pubspec);
140 return new Stream.fromIterable([analyzer]);
141 });
142 var server = new ShelfPubServer(mock);
143 var request = getRequest('/api/packages/analyzer');
144 var response = await server.requestHandler(request);
145 var body = await response.readAsString();
146
147 var expectedVersionJson = {
148 'pubspec': {'foo': 1},
149 'version': '0.1.0',
150 'archive_url':
151 '${getUri('/packages/analyzer/versions/0.1.0.tar.gz')}',
152 };
153 var expectedJson = {
154 'name': 'analyzer',
155 'latest': expectedVersionJson,
156 'versions': [expectedVersionJson],
157 };
158
159 expect(response.mimeType, equals('application/json'));
160 expect(response.statusCode, equals(200));
161 expect(JSON.decode(body), equals(expectedJson));
162 });
163 });
164
165 group('/api/packages/<package>/versions/<version>', () {
166 test('does not exist', () async {
167 var mock = new RepositoryMock(lookupVersionFun: (_, __) => null);
168 var server = new ShelfPubServer(mock);
169 var request = getRequest('/api/packages/analyzer/versions/0.1.0');
170
171 var response = await server.requestHandler(request);
172 await response.read().drain();
173 expect(response.statusCode, equals(404));
174 });
175
176 test('success full retrieval of version', () async {
177 var mock = new RepositoryMock(
178 lookupVersionFun: (String package, String version) {
179 // The pubspec is invalid, but that is irrelevant for this test.
180 var pubspec = JSON.encode({'foo': 1});
181 return new PackageVersion(package, version, pubspec);
182 });
183 var server = new ShelfPubServer(mock);
184 var request = getRequest('/api/packages/analyzer/versions/0.1.0');
185 var response = await server.requestHandler(request);
186 var body = await response.readAsString();
187
188 var expectedJson = {
189 'pubspec': {'foo': 1},
190 'version': '0.1.0',
191 'archive_url':
192 '${getUri('/packages/analyzer/versions/0.1.0.tar.gz')}',
193 };
194
195 expect(response.mimeType, equals('application/json'));
196 expect(response.statusCode, equals(200));
197 expect(JSON.decode(body), equals(expectedJson));
198 });
199 });
200
201 group('/packages/<package>/versions/<version>.tar.gz', () {
202 group('download', () {
203 test('successfull redirect', () async {
204 var mock = new RepositoryMock(
205 downloadFun: (String package, String version) {
206 return new Stream.fromIterable([[1, 2, 3]]);
207 });
208 var server = new ShelfPubServer(mock);
209 var request = getRequest('/packages/analyzer/versions/0.1.0.tar.gz');
210 var response = await server.requestHandler(request);
211 var body = await response.read().fold([], (b, d) => b..addAll(d));
212
213 expect(response.statusCode, equals(200));
214 expect(body, equals([1, 2, 3]));
215 });
216 });
217
218 group('download url', () {
219 test('successfull redirect', () async {
220 var expectedUrl =
221 Uri.parse('https://blobs.com/analyzer-0.1.0.tar.gz');
222 var mock = new RepositoryMock(supportsDownloadUrl: true,
223 downloadUrlFun: (String package, String version) {
224 return expectedUrl;
225 });
226 var server = new ShelfPubServer(mock);
227 var request = getRequest('/packages/analyzer/versions/0.1.0.tar.gz');
228 var response = await server.requestHandler(request);
229 var body = await response.readAsString();
230
231 expect(response.statusCode, equals(303));
232 expect(response.headers['location'], equals('$expectedUrl'));
233 });
234 });
235 });
236
237 group('/api/packages/versions/new', () {
238 test('async successfull', () async {
239 var expectedUrl = Uri.parse('https://storage.googleapis.com');
240 var foobarUrl = Uri.parse('https://foobar.com/package/done');
241 var newUrl = getUri('/api/packages/versions/new');
242 var finishUrl = getUri('/api/packages/versions/newUploadFinish');
243 var mock = new RepositoryMock(
244 supportsUpload: true,
245 supportsAsyncUpload: true,
246 startAsyncUploadFun: (Uri redirectUri) {
247 expect(redirectUri, equals(finishUrl));
248 return new Future.value(
249 new AsyncUploadInfo(expectedUrl, {'a' : '$foobarUrl'}));
250 }, finishAsyncUploadFun: (Uri uri) {
251 expect('$uri', equals('$finishUrl'));
252 });
253 var server = new ShelfPubServer(mock);
254
255 // Start upload
256 var request = new shelf.Request('GET', newUrl);
257 var response = await server.requestHandler(request);
258
259 expect(response.statusCode, equals(200));
260 expect(response.headers['content-type'], equals('application/json'));
261
262 var jsonBody = JSON.decode(await response.readAsString());
263 expect(jsonBody, equals({
264 'url' : '$expectedUrl',
265 'fields' : {
266 'a' : '$foobarUrl',
267 },
268 }));
269
270 // We would do now a multipart POST to `expectedUrl` which would
271 // redirect us back to the pub.dartlang.org app via `finishUrl`.
272
273 // Call the `finishUrl`.
274 request = new shelf.Request('GET', finishUrl);
275 response = await server.requestHandler(request);
276 jsonBody = JSON.decode(await response.readAsString());
277 expect(jsonBody, equals({
278 'success' : {
279 'message' : 'Successfully uploaded package.'
280 },
281 }));
282 });
283
284 test('sync successfull', () async {
285 var tarballBytes = const [1, 2, 3];
286 var newUrl = getUri('/api/packages/versions/new');
287 var uploadUrl = getUri('/api/packages/versions/newUpload');
288 var finishUrl = getUri('/api/packages/versions/newUploadFinish');
289 var mock = new RepositoryMock(
290 supportsUpload: true,
291 uploadFun: (Stream<List<int>> stream) {
292 return stream.fold([], (b, d) => b..addAll(d)).then((List<int> data) {
293 expect(data, equals(tarballBytes));
294 });
295 });
296 var server = new ShelfPubServer(mock);
297
298 // Start upload
299 var request = new shelf.Request('GET', newUrl);
300 var response = await server.requestHandler(request);
301 expect(response.statusCode, equals(200));
302 expect(response.headers['content-type'], equals('application/json'));
303 var jsonBody = JSON.decode(await response.readAsString());
304 expect(jsonBody, equals({
305 'url' : '$uploadUrl',
306 'fields' : {},
307 }));
308
309 // Post data via a multipart request.
310 request = multipartRequest(uploadUrl, tarballBytes);
311 response = await server.requestHandler(request);
312 await response.read();
313 expect(response.statusCode, equals(302));
314 expect(response.headers['location'], equals('$finishUrl'));
315
316 // Call the `finishUrl`.
317 request = new shelf.Request('GET', finishUrl);
318 response = await server.requestHandler(request);
319 jsonBody = JSON.decode(await response.readAsString());
320 expect(jsonBody, equals({
321 'success' : {
322 'message' : 'Successfully uploaded package.'
323 },
324 }));
325 });
326
327 test('sync failure', () async {
328 var tarballBytes = const [1, 2, 3];
329 var newUrl = getUri('/api/packages/versions/new');
330 var uploadUrl = getUri('/api/packages/versions/newUpload');
331 var finishUrl =
332 getUri('/api/packages/versions/newUploadFinish?error=abc');
333 var mock = new RepositoryMock(
334 supportsUpload: true,
335 uploadFun: (Stream<List<int>> stream) {
336 return new Future.error('abc');
337 });
338 var server = new ShelfPubServer(mock);
339
340 // Start upload - would happen here.
341
342 // Post data via a multipart request.
343 var request = multipartRequest(uploadUrl, tarballBytes);
344 var response = await server.requestHandler(request);
345 await response.read();
346 expect(response.statusCode, equals(302));
347 expect(response.headers['location'], equals('$finishUrl'));
348
349 // Call the `finishUrl`.
350 request = new shelf.Request('GET', finishUrl);
351 response = await server.requestHandler(request);
352 var jsonBody = JSON.decode(await response.readAsString());
353 expect(jsonBody, equals({
354 'error' : {
355 'message' : 'abc'
356 },
357 }));
358 });
359
360 test('unsupported', () async {
361 var newUrl = getUri('/api/packages/versions/new');
362 var mock = new RepositoryMock();
363 var server = new ShelfPubServer(mock);
364 var request = new shelf.Request('GET', newUrl);
365 var response = await server.requestHandler(request);
366
367 expect(response.statusCode, equals(404));
368 });
369 });
370 });
371 }
OLDNEW
« no previous file with comments | « pkg/pubserver/pubspec.yaml ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698