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

Side by Side Diff: generated/googleapis/test/common/common_internal_test.dart

Issue 1078053002: Roll of googleapis as of 4/7/2015. (Closed) Base URL: https://github.com/dart-lang/googleapis.git@master
Patch Set: Created 5 years, 8 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
OLDNEW
(Empty)
1 library googleapis.common_internal_test;
2 import 'dart:async';
3 import 'dart:convert';
4
5 import 'package:crypto/crypto.dart' as crypto;
6 import 'package:googleapis/common/common.dart';
7 import 'package:googleapis/src/common_internal.dart';
8 import 'package:http/http.dart' as http;
9 import 'package:unittest/unittest.dart';
10
11 class HttpServerMock extends http.BaseClient {
12 Function _callback;
13 bool _expectJson;
14
15 void register(Function callback, bool expectJson) {
16 _callback = callback;
17 _expectJson = expectJson;
18 }
19
20 Future<http.StreamedResponse> send(http.BaseRequest request) {
21 if (_expectJson) {
22 return request.finalize()
23 .transform(UTF8.decoder)
24 .join('')
25 .then((String jsonString) {
26 if (jsonString.isEmpty) {
27 return _callback(request, null);
28 } else {
29 return _callback(request, JSON.decode(jsonString));
30 }
31 });
32 } else {
33 var stream = request.finalize();
34 if (stream == null) {
35 return _callback(request, []);
36 } else {
37 return stream.toBytes().then((data) {
38 return _callback(request, data);
39 });
40 }
41 }
42 }
43 }
44
45 http.StreamedResponse stringResponse(int status, Map headers, String body) {
46 var stream = new Stream.fromIterable([UTF8.encode(body)]);
47 return new http.StreamedResponse(stream, status, headers: headers);
48 }
49
50 http.StreamedResponse binaryResponse(int status,
51 Map<String,String> headers,
52 List<int> bytes) {
53 var stream = new Stream.fromIterable([bytes]);
54 return new http.StreamedResponse(stream, status, headers: headers);
55 }
56
57 Stream<List<int>> byteStream(String s) {
58 var bodyController = new StreamController();
59 bodyController.add(UTF8.encode(s));
60 bodyController.close();
61 return bodyController.stream;
62 }
63
64 class _ApiRequestError extends TypeMatcher {
65 const _ApiRequestError() : super("ApiRequestError");
66 bool matches(item, Map matchState) => item is ApiRequestError;
67 }
68
69 class _DetailedApiRequestError extends TypeMatcher {
70 const _DetailedApiRequestError() : super("DetailedApiRequestError");
71 bool matches(item, Map matchState) => item is DetailedApiRequestError;
72 }
73
74 class TestError {}
75
76 class _TestError extends TypeMatcher {
77 const _TestError() : super("TestError");
78 bool matches(item, Map matchState) => item is TestError;
79 }
80
81 const isApiRequestError = const _ApiRequestError();
82 const isDetailedApiRequestError = const _DetailedApiRequestError();
83 const isTestError = const _TestError();
84
85
86 main() {
87 group('common-external', () {
88 test('escaper', () {
89 expect(Escaper.ecapePathComponent('a/b%c '), equals('a%2Fb%25c%20'));
90 expect(Escaper.ecapeVariable('a/b%c '), equals('a%2Fb%25c%20'));
91 expect(Escaper.ecapeVariableReserved('a/b%c+ '), equals('a/b%25c+%20'));
92 expect(Escaper.escapeQueryComponent('a/b%c '), equals('a%2Fb%25c%20'));
93 });
94
95 test('mapMap', () {
96 newTestMap() => {
97 's' : 'string',
98 'i' : 42,
99 };
100
101 var copy = mapMap(newTestMap());
102 expect(copy, hasLength(2));
103 expect(copy['s'], equals('string'));
104 expect(copy['i'], equals(42));
105
106
107 var mod = mapMap(newTestMap(), (x) => '$x foobar');
108 expect(mod, hasLength(2));
109 expect(mod['s'], equals('string foobar'));
110 expect(mod['i'], equals('42 foobar'));
111 });
112
113 test('base64-encoder', () {
114 var base64encoder = new Base64Encoder();
115
116 testString(String msg, String expectedBase64) {
117 var msgBytes = UTF8.encode(msg);
118
119 Stream singleByteStream(List<int> msgBytes) {
120 var controller = new StreamController();
121 for (var byte in msgBytes) {
122 controller.add([byte]);
123 }
124 controller.close();
125 return controller.stream;
126 }
127
128 Stream allByteStream(List<int> msgBytes) {
129 var controller = new StreamController();
130 controller.add(msgBytes);
131 controller.close();
132 return controller.stream;
133 }
134
135 singleByteStream(msgBytes)
136 .transform(base64encoder)
137 .join('')
138 .then(expectAsync((String result) {
139 expect(result, equals(expectedBase64));
140 }));
141
142 allByteStream(msgBytes)
143 .transform(base64encoder)
144 .join('')
145 .then(expectAsync((String result) {
146 expect(result, equals(expectedBase64));
147 }));
148
149 expect(Base64Encoder.lengthOfBase64Stream(msg.length),
150 equals(expectedBase64.length));
151 }
152
153 testString('pleasure.', 'cGxlYXN1cmUu');
154 testString('leasure.', 'bGVhc3VyZS4=');
155 testString('easure.', 'ZWFzdXJlLg==');
156 testString('asure.', 'YXN1cmUu');
157 testString('sure.', 'c3VyZS4=');
158 testString('', '');
159 });
160
161 group('chunk-stack', () {
162 var chunkSize = 9;
163
164 folded(List<List<int>> byteArrays) {
165 return byteArrays.fold([], (buf, e) => buf..addAll(e));
166 }
167
168 test('finalize', () {
169 var chunkStack = new ChunkStack(9);
170 chunkStack.finalize();
171 expect(() => chunkStack.addBytes([1]), throwsA(isStateError));
172 expect(() => chunkStack.finalize(), throwsA(isStateError));
173 });
174
175 test('empty', () {
176 var chunkStack = new ChunkStack(9);
177 expect(chunkStack.length, equals(0));
178 chunkStack.finalize();
179 expect(chunkStack.length, equals(0));
180 });
181
182 test('sub-chunk-size', () {
183 var bytes = [1, 2, 3];
184
185 var chunkStack = new ChunkStack(9);
186 chunkStack.addBytes(bytes);
187 expect(chunkStack.length, equals(0));
188 chunkStack.finalize();
189 expect(chunkStack.length, equals(1));
190 expect(chunkStack.totalByteLength, equals(bytes.length));
191
192 var chunks = chunkStack.removeSublist(0, chunkStack.length);
193 expect(chunkStack.length, equals(0));
194 expect(chunks, hasLength(1));
195
196 expect(folded(chunks.first.byteArrays), equals(bytes));
197 expect(chunks.first.offset, equals(0));
198 expect(chunks.first.length, equals(3));
199 expect(chunks.first.endOfChunk, equals(bytes.length));
200 });
201
202 test('exact-chunk-size', () {
203 var bytes = [1, 2, 3, 4, 5, 6, 7, 8, 9];
204
205 var chunkStack = new ChunkStack(9);
206 chunkStack.addBytes(bytes);
207 expect(chunkStack.length, equals(1));
208 chunkStack.finalize();
209 expect(chunkStack.length, equals(1));
210 expect(chunkStack.totalByteLength, equals(bytes.length));
211
212 var chunks = chunkStack.removeSublist(0, chunkStack.length);
213 expect(chunkStack.length, equals(0));
214 expect(chunks, hasLength(1));
215
216 expect(folded(chunks.first.byteArrays), equals(bytes));
217 expect(chunks.first.offset, equals(0));
218 expect(chunks.first.length, equals(bytes.length));
219 expect(chunks.first.endOfChunk, equals(bytes.length));
220 });
221
222 test('super-chunk-size', () {
223 var bytes0 = [1, 2, 3, 4];
224 var bytes1 = [1, 2, 3, 4];
225 var bytes2 = [5, 6, 7, 8, 9, 10, 11];
226 var bytes = folded([bytes0, bytes1, bytes2]);
227
228 var chunkStack = new ChunkStack(9);
229 chunkStack.addBytes(bytes0);
230 chunkStack.addBytes(bytes1);
231 chunkStack.addBytes(bytes2);
232 expect(chunkStack.length, equals(1));
233 chunkStack.finalize();
234 expect(chunkStack.length, equals(2));
235 expect(chunkStack.totalByteLength, equals(bytes.length));
236
237 var chunks = chunkStack.removeSublist(0, chunkStack.length);
238 expect(chunkStack.length, equals(0));
239 expect(chunks, hasLength(2));
240
241 expect(folded(chunks.first.byteArrays),
242 equals(bytes.sublist(0, chunkSize)));
243 expect(chunks.first.offset, equals(0));
244 expect(chunks.first.length, equals(chunkSize));
245 expect(chunks.first.endOfChunk, equals(chunkSize));
246
247 expect(folded(chunks.last.byteArrays),
248 equals(bytes.sublist(chunkSize)));
249 expect(chunks.last.offset, equals(chunkSize));
250 expect(chunks.last.length, equals(bytes.length - chunkSize));
251 expect(chunks.last.endOfChunk, equals(bytes.length));
252 });
253 });
254
255 test('media', () {
256 // Tests for [MediaRange]
257 var partialRange = new ByteRange(1, 100);
258 expect(partialRange.start, equals(1));
259 expect(partialRange.end, equals(100));
260
261 var fullRange = new ByteRange(0, -1);
262 expect(fullRange.start, equals(0));
263 expect(fullRange.end, equals(-1));
264
265 expect(() => new ByteRange(0, 0), throws);
266 expect(() => new ByteRange(-1, 0), throws);
267 expect(() => new ByteRange(-1, 1), throws);
268
269 // Tests for [DownloadOptions]
270 expect(DownloadOptions.Metadata.isMetadataDownload, isTrue);
271
272 expect(DownloadOptions.FullMedia.isFullDownload, isTrue);
273 expect(DownloadOptions.FullMedia.isMetadataDownload, isFalse);
274
275 // Tests for [Media]
276 var stream = new StreamController().stream;
277 expect(() => new Media(null, 0, contentType: 'foobar'),
278 throwsA(isArgumentError));
279 expect(() => new Media(stream, 0, contentType: null),
280 throwsA(isArgumentError));
281 expect(() => new Media(stream, -1, contentType: 'foobar'),
282 throwsA(isArgumentError));
283
284 var lengthUnknownMedia = new Media(stream, null);
285 expect(lengthUnknownMedia.stream, equals(stream));
286 expect(lengthUnknownMedia.length, equals(null));
287
288 var media = new Media(stream, 10, contentType: 'foobar');
289 expect(media.stream, equals(stream));
290 expect(media.length, equals(10));
291 expect(media.contentType, equals('foobar'));
292
293 // Tests for [ResumableUploadOptions]
294 expect(() => new ResumableUploadOptions(numberOfAttempts: 0),
295 throwsA(isArgumentError));
296 expect(() => new ResumableUploadOptions(chunkSize: 1),
297 throwsA(isArgumentError));
298 });
299
300 group('api-requester', () {
301 var httpMock, rootUrl, basePath;
302 ApiRequester requester;
303
304 var responseHeaders = {
305 'content-type' : 'application/json; charset=utf-8',
306 };
307
308 setUp(() {
309 httpMock = new HttpServerMock();
310 rootUrl = 'http://example.com/';
311 basePath = 'base/';
312 requester = new ApiRequester(httpMock, rootUrl, basePath);
313 });
314
315
316 // Tests for Request, Response
317
318 group('metadata-request-response', () {
319 test('empty-request-empty-response', () {
320 httpMock.register(expectAsync((http.BaseRequest request, json) {
321 expect(request.method, equals('GET'));
322 expect('${request.url}',
323 equals('http://example.com/base/abc?alt=json'));
324 return stringResponse(200, responseHeaders, '');
325 }), true);
326 requester.request('abc', 'GET').then(expectAsync((response) {
327 expect(response, isNull);
328 }));
329 });
330
331 test('json-map-request-json-map-response', () {
332 httpMock.register(expectAsync((http.BaseRequest request, json) {
333 expect(request.method, equals('GET'));
334 expect('${request.url}',
335 equals('http://example.com/base/abc?alt=json'));
336 expect(json is Map, isTrue);
337 expect(json, hasLength(1));
338 expect(json['foo'], equals('bar'));
339 return stringResponse(200, responseHeaders, '{"foo2" : "bar2"}');
340 }), true);
341 requester.request('abc',
342 'GET',
343 body: JSON.encode({'foo' : 'bar'})).then(
344 expectAsync((response) {
345 expect(response is Map, isTrue);
346 expect(response, hasLength(1));
347 expect(response['foo2'], equals('bar2'));
348 }));
349 });
350
351 test('json-list-request-json-list-response', () {
352 httpMock.register(expectAsync((http.BaseRequest request, json) {
353 expect(request.method, equals('GET'));
354 expect('${request.url}',
355 equals('http://example.com/base/abc?alt=json'));
356 expect(json is List, isTrue);
357 expect(json, hasLength(2));
358 expect(json[0], equals('a'));
359 expect(json[1], equals(1));
360 return stringResponse(200, responseHeaders, '["b", 2]');
361 }), true);
362 requester.request('abc',
363 'GET',
364 body: JSON.encode(['a', 1])).then(
365 expectAsync((response) {
366 expect(response is List, isTrue);
367 expect(response[0], equals('b'));
368 expect(response[1], equals(2));
369 }));
370 });
371 });
372
373 group('media-download', () {
374 test('media-download', () {
375 var data256 = new List.generate(256, (i) => i);
376 httpMock.register(expectAsync((http.BaseRequest request, data) {
377 expect(request.method, equals('GET'));
378 expect('${request.url}',
379 equals('http://example.com/base/abc?alt=media'));
380 expect(data, isEmpty);
381 var headers = {
382 'content-length' : '${data256.length}',
383 'content-type' : 'foobar',
384 };
385 return binaryResponse(200, headers, data256);
386 }), false);
387 requester.request('abc',
388 'GET',
389 body: '',
390 downloadOptions: DownloadOptions.FullMedia).then(
391 expectAsync((Media media) {
392 expect(media.contentType, equals('foobar'));
393 expect(media.length, equals(data256.length));
394 media.stream.fold([], (b, d) => b..addAll(d)).then(expectAsync((d) {
395 expect(d, equals(data256));
396 }));
397 }));
398 });
399
400 test('media-download-partial', () {
401 var data256 = new List.generate(256, (i) => i);
402 var data64 = data256.sublist(128, 128 + 64);
403
404 httpMock.register(expectAsync((http.BaseRequest request, data) {
405 expect(request.method, equals('GET'));
406 expect('${request.url}',
407 equals('http://example.com/base/abc?alt=media'));
408 expect(data, isEmpty);
409 expect(request.headers['range'],
410 equals('bytes=128-191'));
411 var headers = {
412 'content-length' : '${data64.length}',
413 'content-type' : 'foobar',
414 'content-range' : 'bytes 128-191/256',
415 };
416 return binaryResponse(200, headers, data64);
417 }), false);
418 var range = new ByteRange(128, 128 + 64 - 1);
419 var options = new PartialDownloadOptions(range);
420 requester.request('abc',
421 'GET',
422 body: '',
423 downloadOptions: options).then(
424 expectAsync((Media media) {
425 expect(media.contentType, equals('foobar'));
426 expect(media.length, equals(data64.length));
427 media.stream.fold([], (b, d) => b..addAll(d)).then(expectAsync((d) {
428 expect(d, equals(data64));
429 }));
430 }));
431 });
432
433 test('json-upload-media-download', () {
434 var data256 = new List.generate(256, (i) => i);
435 httpMock.register(expectAsync((http.BaseRequest request, json) {
436 expect(request.method, equals('GET'));
437 expect('${request.url}',
438 equals('http://example.com/base/abc?alt=media'));
439 expect(json is List, isTrue);
440 expect(json, hasLength(2));
441 expect(json[0], equals('a'));
442 expect(json[1], equals(1));
443
444 var headers = {
445 'content-length' : '${data256.length}',
446 'content-type' : 'foobar',
447 };
448 return binaryResponse(200, headers, data256);
449 }), true);
450 requester.request('abc',
451 'GET',
452 body: JSON.encode(['a', 1]),
453 downloadOptions: DownloadOptions.FullMedia).then(
454 expectAsync((Media media) {
455 expect(media.contentType, equals('foobar'));
456 expect(media.length, equals(data256.length));
457 media.stream.fold([], (b, d) => b..addAll(d)).then(expectAsync((d) {
458 expect(d, equals(data256));
459 }));
460 }));
461 });
462 });
463
464 // Tests for media uploads
465
466 group('media-upload', () {
467 Stream streamFromByteArrays(byteArrays) {
468 var controller = new StreamController();
469 for (var array in byteArrays) {
470 controller.add(array);
471 }
472 controller.close();
473 return controller.stream;
474 }
475 Media mediaFromByteArrays(byteArrays, {bool withLen: true}) {
476 int len = 0;
477 byteArrays.forEach((array) { len += array.length; });
478 if (!withLen) len = null;
479 return new Media(streamFromByteArrays(byteArrays),
480 len,
481 contentType: 'foobar');
482 }
483 validateServerRequest(e, http.BaseRequest request, List<int> data) {
484 return new Future.sync(() {
485 var h = e['headers'];
486 var r = e['response'];
487
488 expect(request.url.toString(), equals(e['url']));
489 expect(request.method, equals(e['method']));
490 h.forEach((k, v) {
491 expect(request.headers[k], equals(v));
492 });
493
494 expect(data, equals(e['data']));
495 return r;
496 });
497 }
498 serverRequestValidator(List expectations) {
499 int i = 0;
500 return (http.BaseRequest request, List<int> data) {
501 return validateServerRequest(expectations[i++], request, data);
502 };
503 }
504
505 test('simple', () {
506 var bytes = new List.generate(10 * 256 * 1024 + 1, (i) => i % 256);
507 var expectations = [
508 {
509 'url' : 'http://example.com/xyz?uploadType=media&alt=json',
510 'method' : 'POST',
511 'data' : bytes,
512 'headers' : {
513 'content-length' : '${bytes.length}',
514 'content-type' : 'foobar',
515 },
516 'response' : stringResponse(200, responseHeaders, '')
517 },
518 ];
519
520 httpMock.register(
521 expectAsync(serverRequestValidator(expectations)), false);
522 var media = mediaFromByteArrays([bytes]);
523 requester.request('/xyz',
524 'POST',
525 uploadMedia: media).then(
526 expectAsync((response) {}));
527 });
528
529 test('multipart-upload', () {
530 var bytes = new List.generate(10 * 256 * 1024 + 1, (i) => i % 256);
531 var contentBytes =
532 '--314159265358979323846\r\n'
533 'Content-Type: $CONTENT_TYPE_JSON_UTF8\r\n\r\n'
534 'BODY'
535 '\r\n--314159265358979323846\r\n'
536 'Content-Type: foobar\r\n'
537 'Content-Transfer-Encoding: base64\r\n\r\n'
538 '${crypto.CryptoUtils.bytesToBase64(bytes)}'
539 '\r\n--314159265358979323846--';
540
541 var expectations = [
542 {
543 'url' : 'http://example.com/xyz?uploadType=multipart&alt=json',
544 'method' : 'POST',
545 'data' : UTF8.encode('$contentBytes'),
546 'headers' : {
547 'content-length' : '${contentBytes.length}',
548 'content-type' :
549 'multipart/related; boundary="314159265358979323846"',
550 },
551 'response' : stringResponse(200, responseHeaders, '')
552 },
553 ];
554
555 httpMock.register(
556 expectAsync(serverRequestValidator(expectations)), false);
557 var media = mediaFromByteArrays([bytes]);
558 requester.request('/xyz',
559 'POST',
560 body: 'BODY',
561 uploadMedia: media).then(
562 expectAsync((response) {}));
563 });
564
565 group('resumable-upload', () {
566 // TODO: respect [stream]
567 buildExpectations(List<int> bytes, int chunkSize, bool stream,
568 {int numberOfServerErrors: 0}) {
569 int totalLength = bytes.length;
570 int numberOfChunks = totalLength ~/ chunkSize;
571 int numberOfBytesInLastChunk = totalLength % chunkSize;
572
573 if (numberOfBytesInLastChunk > 0) {
574 numberOfChunks++;
575 } else {
576 numberOfBytesInLastChunk = chunkSize;
577 }
578
579 var expectations = [];
580
581 // First request is making a POST and gets the upload URL.
582 expectations.add({
583 'url' : 'http://example.com/xyz?uploadType=resumable&alt=json',
584 'method' : 'POST',
585 'data' : [],
586 'headers' : {
587 'content-length' : '0',
588 'content-type' : 'application/json; charset=utf-8',
589 'x-upload-content-type' : 'foobar',
590 }..addAll(stream ? {} : {
591 'x-upload-content-length' : '$totalLength',
592 }),
593 'response' : stringResponse(
594 200, {'location' : 'http://upload.com/'}, '')
595 });
596
597 var lastEnd = 0;
598 for (int i = 0; i < numberOfChunks; i++) {
599 bool isLast = i == (numberOfChunks - 1);
600 var lengthMarker = stream && !isLast ? '*' : '$totalLength';
601
602 int bytesToExpect = chunkSize;
603 if (isLast) {
604 bytesToExpect = numberOfBytesInLastChunk;
605 }
606
607 var start = i * chunkSize;
608 var end = start + bytesToExpect;
609 var sublist = bytes.sublist(start, end);
610
611 var firstContentRange =
612 'bytes $start-${end-1}/$lengthMarker';
613 var firstRange =
614 'bytes=0-${end-1}';
615
616 // We issue [numberOfServerErrors] 503 errors first, and then a
617 // successfull response.
618 for (var j = 0; j < (numberOfServerErrors + 1); j++) {
619 bool successfullResponse = j == numberOfServerErrors;
620
621 var response;
622 if (successfullResponse) {
623 var headers = isLast
624 ? { 'content-type' : 'application/json; charset=utf-8' }
625 : {'range' : firstRange };
626 response = stringResponse(isLast ? 200 : 308, headers, '');
627 } else {
628 var headers = {};
629 response = stringResponse(503, headers, '');
630 }
631
632 expectations.add({
633 'url' : 'http://upload.com/',
634 'method' : 'PUT',
635 'data' : sublist,
636 'headers' : {
637 'content-length' : '${sublist.length}',
638 'content-range' : firstContentRange,
639 'content-type' : 'foobar',
640 },
641 'response' : response,
642 });
643 }
644 }
645 return expectations;
646 }
647
648 List<List<int>> makeParts(List<int> bytes, List<int> splits) {
649 var parts = [];
650 int lastEnd = 0;
651 for (int i = 0; i < splits.length; i++) {
652 parts.add(bytes.sublist(lastEnd, splits[i]));
653 lastEnd = splits[i];
654 }
655 return parts;
656 }
657
658 runTest(int chunkSizeInBlocks, int length, List splits, bool stream,
659 {int numberOfServerErrors: 0, resumableOptions,
660 int expectedErrorStatus, int messagesNrOfFailure}) {
661 int chunkSize = chunkSizeInBlocks * 256 * 1024;
662
663 int i = 0;
664 var bytes = new List.generate(length, (i) => i % 256);
665 var parts = makeParts(bytes, splits);
666
667 // Simulation of our server
668 var expectations = buildExpectations(
669 bytes, chunkSize, false,
670 numberOfServerErrors: numberOfServerErrors);
671 // If the server simulates 50X errors and the client resumes only
672 // a limited amount of time, we'll trunkate the number of requests
673 // the server expects.
674 // [The client will give up and if the server expects more, the test
675 // would timeout.]
676 if (expectedErrorStatus != null) {
677 expectations = expectations.sublist(0, messagesNrOfFailure);
678 }
679 httpMock.register(
680 expectAsync(serverRequestValidator(expectations),
681 count: expectations.length),
682 false);
683
684 // Our client
685 var media = mediaFromByteArrays(parts);
686 if (resumableOptions == null) {
687 resumableOptions =
688 new ResumableUploadOptions(chunkSize: chunkSize);
689 }
690 var result = requester.request('/xyz',
691 'POST',
692 uploadMedia: media,
693 uploadOptions: resumableOptions);
694 if (expectedErrorStatus != null) {
695 result.catchError(expectAsync((error) {
696 expect(error is DetailedApiRequestError, isTrue);
697 expect(error.status, equals(expectedErrorStatus));
698 }));
699 } else {
700 result.then(expectAsync((_) {}));
701 }
702 }
703
704 Function backoffWrapper(int callCount) {
705 return expectAsync((int failedAttempts) {
706 var exp = ResumableUploadOptions.ExponentialBackoff;
707 Duration duration = exp(failedAttempts);
708 expect(duration.inSeconds, equals(1 << (failedAttempts - 1)));
709 return const Duration(milliseconds: 1);
710 }, count: callCount);
711 }
712
713 test('length-small-block', () {
714 runTest(1, 10, [10], false);
715 });
716
717 test('length-small-block-parts', () {
718 runTest(1, 20, [1, 2, 3, 4, 5, 6, 7, 19, 20], false);
719 });
720
721 test('length-big-block', () {
722 runTest(1, 1024 * 1024, [1024*1024], false);
723 });
724
725 test('length-big-block-parts', () {
726 runTest(1, 1024 * 1024,
727 [1,
728 256*1024-1,
729 256*1024,
730 256*1024+1,
731 1024*1024-1,
732 1024*1024], false);
733 });
734
735 test('length-big-block-parts-non-divisible', () {
736 runTest(1, 1024 * 1024 + 1,
737 [1,
738 256*1024-1,
739 256*1024,
740 256*1024+1,
741 1024*1024-1,
742 1024*1024,
743 1024*1024+1], false);
744 });
745
746 test('stream-small-block', () {
747 runTest(1, 10, [10], true);
748 });
749
750 test('stream-small-block-parts', () {
751 runTest(1, 20, [1, 2, 3, 4, 5, 6, 7, 19, 20], true);
752 });
753
754 test('stream-big-block', () {
755 runTest(1, 1024 * 1024, [1024*1024], true);
756 });
757
758 test('stream-big-block-parts', () {
759 runTest(1, 1024 * 1024,
760 [1,
761 256*1024-1,
762 256*1024,
763 256*1024+1,
764 1024*1024-1,
765 1024*1024], true);
766 });
767
768 test('stream-big-block-parts--with-server-error-recovery', () {
769 var numFailedAttempts = 4 * 3;
770 var options = new ResumableUploadOptions(
771 chunkSize: 256 * 1024, numberOfAttempts: 4,
772 backoffFunction: backoffWrapper(numFailedAttempts));
773 runTest(1, 1024 * 1024,
774 [1,
775 256*1024-1,
776 256*1024,
777 256*1024+1,
778 1024*1024-1,
779 1024*1024],
780 true,
781 numberOfServerErrors: 3,
782 resumableOptions: options);
783 });
784
785 test('stream-big-block-parts--server-error', () {
786 var numFailedAttempts = 2;
787 var options = new ResumableUploadOptions(
788 chunkSize: 256 * 1024, numberOfAttempts: 3,
789 backoffFunction: backoffWrapper(numFailedAttempts));
790 runTest(1, 1024 * 1024,
791 [1,
792 256*1024-1,
793 256*1024,
794 256*1024+1,
795 1024*1024-1,
796 1024*1024],
797 true,
798 numberOfServerErrors: 3,
799 resumableOptions: options,
800 expectedErrorStatus: 503,
801 messagesNrOfFailure: 4);
802 });
803 });
804 });
805
806 // Tests for error responses
807 group('request-errors', () {
808 makeTestError() {
809 // All errors from the [http.Client] propagate through.
810 // We use [TestError] to simulate it.
811 httpMock.register(expectAsync((http.BaseRequest request, string) {
812 return new Future.error(new TestError());
813 }), false);
814 }
815
816 makeDetailed400Error() {
817 httpMock.register(expectAsync((http.BaseRequest request, string) {
818 return stringResponse(400,
819 responseHeaders,
820 '{"error" : {"code" : 42, "message": "foo"}}');
821 }), false);
822 }
823
824 makeNormal199Error() {
825 httpMock.register(expectAsync((http.BaseRequest request, string) {
826 return stringResponse(199, {}, '');
827 }), false);
828 }
829
830 makeInvalidContentTypeError() {
831 httpMock.register(expectAsync((http.BaseRequest request, string) {
832 var responseHeaders = { 'content-type' : 'image/png'};
833 return stringResponse(200, responseHeaders, '');
834 }), false);
835 }
836
837
838 test('normal-http-client', () {
839 makeTestError();
840 expect(requester.request('abc', 'GET'), throwsA(isTestError));
841 });
842
843 test('normal-detailed-400', () {
844 makeDetailed400Error();
845 requester.request('abc', 'GET')
846 .catchError(expectAsync((error, stack) {
847 expect(error, isDetailedApiRequestError);
848 DetailedApiRequestError e = error;
849 expect(e.status, equals(42));
850 expect(e.message, equals('foo'));
851 }));
852 });
853
854 test('normal-199', () {
855 makeNormal199Error();
856 expect(requester.request('abc', 'GET'), throwsA(isApiRequestError));
857 });
858
859 test('normal-invalid-content-type', () {
860 makeInvalidContentTypeError();
861 expect(requester.request('abc', 'GET'), throwsA(isApiRequestError));
862 });
863
864 var options = DownloadOptions.FullMedia;
865 test('media-http-client', () {
866 makeTestError();
867 expect(requester.request('abc', 'GET', downloadOptions: options),
868 throwsA(isTestError));
869 });
870
871 test('media-detailed-400', () {
872 makeDetailed400Error();
873 requester.request('abc', 'GET')
874 .catchError(expectAsync((error, stack) {
875 expect(error, isDetailedApiRequestError);
876 DetailedApiRequestError e = error;
877 expect(e.status, equals(42));
878 expect(e.message, equals('foo'));
879 }));
880 });
881
882 test('media-199', () {
883 makeNormal199Error();
884 expect(requester.request('abc', 'GET', downloadOptions: options),
885 throwsA(isApiRequestError));
886 });
887 });
888
889
890 // Tests for path/query parameters
891
892 test('request-parameters-query', () {
893 var queryParams = {
894 'a' : ['a1', 'a2'],
895 's' : ['s1']
896 };
897 httpMock.register(expectAsync((http.BaseRequest request, json) {
898 expect(request.method, equals('GET'));
899 expect('${request.url}',
900 equals('http://example.com/base/abc?a=a1&a=a2&s=s1&alt=json'));
901 return stringResponse(200, responseHeaders, '');
902 }), true);
903 requester.request('abc', 'GET', queryParams: queryParams)
904 .then(expectAsync((response) {
905 expect(response, isNull);
906 }));
907 });
908
909 test('request-parameters-path', () {
910 httpMock.register(expectAsync((http.BaseRequest request, json) {
911 expect(request.method, equals('GET'));
912 expect('${request.url}', equals(
913 'http://example.com/base/s/foo/a1/a2/bar/s1/e?alt=json'));
914 return stringResponse(200, responseHeaders, '');
915 }), true);
916 requester.request('s/foo/a1/a2/bar/s1/e', 'GET')
917 .then(expectAsync((response) {
918 expect(response, isNull);
919 }));
920 });
921 });
922 });
923 }
OLDNEW
« no previous file with comments | « generated/googleapis/test/cloudsearch/v1_test.dart ('k') | generated/googleapis/test/compute/v1_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698