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

Side by Side Diff: pkg/gcloud/test/storage/storage_test.dart

Issue 804973002: Add appengine/gcloud/mustache dependencies. (Closed) Base URL: git@github.com:dart-lang/pub-dartlang-dart.git@master
Patch Set: Added AUTHORS/LICENSE/PATENTS files Created 6 years 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/gcloud/test/storage/e2e_test.dart ('k') | pkg/mustache/.gitignore » ('j') | 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) 2014, 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 gcloud.storage;
6
7 import 'dart:async';
8 import 'dart:convert';
9
10 import 'package:http/http.dart' as http;
11 import 'package:unittest/unittest.dart';
12
13 import 'package:gcloud/storage.dart';
14
15 import 'package:googleapis/storage/v1.dart' as storage;
16 import 'package:googleapis/common/common.dart' as common;
17
18 import '../common.dart';
19 import '../common_e2e.dart';
20
21
22 const String ROOT_PATH = '/storage/v1/';
23
24
25 http.Client mockClient() => new MockClient(ROOT_PATH);
26
27 withMockClient(function) {
28 var mock = mockClient();
29 function(mock, new Storage(mock, PROJECT));
30 }
31
32 main() {
33 group('bucket', () {
34 var bucketName = 'test-bucket';
35 var absoluteName = 'gs://test-bucket';
36
37 test('create', () {
38 withMockClient((mock, api) {
39 mock.register('POST', 'b', expectAsync((request) {
40 var requestBucket =
41 new storage.Bucket.fromJson(JSON.decode(request.body));
42 expect(requestBucket.name, bucketName);
43 return mock.respond(new storage.Bucket()..name = bucketName);
44 }));
45
46 expect(api.createBucket(bucketName), completion(isNull));
47 });
48 });
49
50 test('create-with-predefined-acl', () {
51 var predefined =
52 [[PredefinedAcl.authenticatedRead, 'authenticatedRead'],
53 [PredefinedAcl.private, 'private'],
54 [PredefinedAcl.projectPrivate, 'projectPrivate'],
55 [PredefinedAcl.publicRead, 'publicRead'],
56 [PredefinedAcl.publicReadWrite, 'publicReadWrite']];
57
58 withMockClient((mock, api) {
59 int count = 0;
60
61 mock.register('POST', 'b', expectAsync((request) {
62 var requestBucket =
63 new storage.Bucket.fromJson(JSON.decode(request.body));
64 expect(requestBucket.name, bucketName);
65 expect(requestBucket.acl, isNull);
66 expect(request.url.queryParameters['predefinedAcl'],
67 predefined[count++][1]);
68 return mock.respond(new storage.Bucket()..name = bucketName);
69 }, count: predefined.length));
70
71 var futures = [];
72 for (int i = 0; i < predefined.length; i++) {
73 futures.add(api.createBucket(bucketName,
74 predefinedAcl: predefined[i][0]));
75 }
76 return Future.wait(futures);
77 });
78 });
79
80 test('create-with-acl', () {
81 var acl1 = new Acl([
82 new AclEntry(new AccountScope('user@example.com'),
83 AclPermission.FULL_CONTROL),
84 ]);
85 var acl2 = new Acl([
86 new AclEntry(new AccountScope('user@example.com'),
87 AclPermission.FULL_CONTROL),
88 new AclEntry(new GroupScope('group@example.com'),
89 AclPermission.WRITE),
90 ]);
91 var acl3 = new Acl([
92 new AclEntry(new AccountScope('user@example.com'),
93 AclPermission.FULL_CONTROL),
94 new AclEntry(new GroupScope('group@example.com'),
95 AclPermission.WRITE),
96 new AclEntry(new DomainScope('example.com'),
97 AclPermission.READ),
98 ]);
99
100 var acls = [acl1, acl2, acl3];
101
102 withMockClient((mock, api) {
103 int count = 0;
104
105 mock.register('POST', 'b', expectAsync((request) {
106 var requestBucket =
107 new storage.Bucket.fromJson(JSON.decode(request.body));
108 expect(requestBucket.name, bucketName);
109 expect(request.url.queryParameters['predefinedAcl'], isNull);
110 expect(requestBucket.acl, isNotNull);
111 expect(requestBucket.acl.length, count + 1);
112 expect(requestBucket.acl[0].entity, 'user-user@example.com');
113 expect(requestBucket.acl[0].role, 'OWNER');
114 if (count > 0) {
115 expect(requestBucket.acl[1].entity, 'group-group@example.com');
116 expect(requestBucket.acl[1].role, 'WRITER');
117 }
118 if (count > 2) {
119 expect(requestBucket.acl[2].entity, 'domain-example.com');
120 expect(requestBucket.acl[2].role, 'READER');
121 }
122 count++;
123 return mock.respond(new storage.Bucket()..name = bucketName);
124 }, count: acls.length));
125
126 var futures = [];
127 for (int i = 0; i < acls.length; i++) {
128 futures.add(api.createBucket(bucketName, acl: acls[i]));
129 }
130 return Future.wait(futures);
131 });
132 });
133
134 test('create-with-acl-and-predefined-acl', () {
135 var predefined =
136 [[PredefinedAcl.authenticatedRead, 'authenticatedRead'],
137 [PredefinedAcl.private, 'private'],
138 [PredefinedAcl.projectPrivate, 'projectPrivate'],
139 [PredefinedAcl.publicRead, 'publicRead'],
140 [PredefinedAcl.publicReadWrite, 'publicReadWrite']];
141
142 var acl1 = new Acl([
143 new AclEntry(new AccountScope('user@example.com'),
144 AclPermission.FULL_CONTROL),
145 ]);
146 var acl2 = new Acl([
147 new AclEntry(new AccountScope('user@example.com'),
148 AclPermission.FULL_CONTROL),
149 new AclEntry(new GroupScope('group@example.com'),
150 AclPermission.WRITE),
151 ]);
152 var acl3 = new Acl([
153 new AclEntry(new AccountScope('user@example.com'),
154 AclPermission.FULL_CONTROL),
155 new AclEntry(new GroupScope('group@example.com'),
156 AclPermission.WRITE),
157 new AclEntry(new DomainScope('example.com'),
158 AclPermission.READ),
159 ]);
160
161 var acls = [acl1, acl2, acl3];
162
163 withMockClient((mock, api) {
164 int count = 0;
165
166 mock.register('POST', 'b', expectAsync((request) {
167 var requestBucket =
168 new storage.Bucket.fromJson(JSON.decode(request.body));
169 int predefinedIndex = count ~/ acls.length;
170 int aclIndex = count % acls.length;
171 expect(requestBucket.name, bucketName);
172 expect(request.url.queryParameters['predefinedAcl'],
173 predefined[predefinedIndex][1]);
174 expect(requestBucket.acl, isNotNull);
175 expect(requestBucket.acl.length, aclIndex + 1);
176 expect(requestBucket.acl[0].entity, 'user-user@example.com');
177 expect(requestBucket.acl[0].role, 'OWNER');
178 if (aclIndex > 0) {
179 expect(requestBucket.acl[1].entity, 'group-group@example.com');
180 expect(requestBucket.acl[1].role, 'WRITER');
181 }
182 if (aclIndex > 2) {
183 expect(requestBucket.acl[2].entity, 'domain-example.com');
184 expect(requestBucket.acl[2].role, 'READER');
185 }
186 count++;
187 return mock.respond(new storage.Bucket()..name = bucketName);
188 }, count: predefined.length * acls.length));
189
190 var futures = [];
191 for (int i = 0; i < predefined.length; i++) {
192 for (int j = 0; j < acls.length; j++) {
193 futures.add(api.createBucket(
194 bucketName, predefinedAcl: predefined[i][0], acl: acls[j]));
195 }
196 }
197 return Future.wait(futures);
198 });
199 });
200
201 test('delete', () {
202 withMockClient((mock, api) {
203 mock.register(
204 'DELETE', new RegExp(r'b/[a-z/-]*$'), expectAsync((request) {
205 expect(request.url.path, '${ROOT_PATH}b/$bucketName');
206 expect(request.body.length, 0);
207 return mock.respond(new storage.Bucket()..name = bucketName);
208 }));
209
210 expect(api.deleteBucket(bucketName), completion(isNull));
211 });
212 });
213
214 test('exists', () {
215 var exists = true;
216
217 withMockClient((mock, api) {
218 mock.register(
219 'GET', new RegExp(r'b/[a-z/-]*$'), expectAsync((request) {
220 expect(request.url.path, '${ROOT_PATH}b/$bucketName');
221 expect(request.body.length, 0);
222 if (exists) {
223 return mock.respond(new storage.Bucket()..name = bucketName);
224 } else {
225 return mock.respondError(404);
226 }
227 }, count: 2));
228
229 return api.bucketExists(bucketName).then(expectAsync((result) {
230 expect(result, isTrue);
231 exists = false;
232 expect(api.bucketExists(bucketName), completion(isFalse));
233 }));
234 });
235 });
236
237 test('stat', () {
238 withMockClient((mock, api) {
239 mock.register(
240 'GET', new RegExp(r'b/[a-z/-]*$'), expectAsync((request) {
241 expect(request.url.path, '${ROOT_PATH}b/$bucketName');
242 expect(request.body.length, 0);
243 return mock.respond(new storage.Bucket()
244 ..name = bucketName
245 ..timeCreated = new DateTime(2014));
246 }));
247
248 return api.bucketInfo(bucketName).then(expectAsync((result) {
249 expect(result.bucketName, bucketName);
250 expect(result.created, new DateTime(2014));
251 }));
252 });
253 });
254
255 group('list', () {
256 test('empty', () {
257 withMockClient((mock, api) {
258 mock.register('GET', 'b', expectAsync((request) {
259 expect(request.body.length, 0);
260 return mock.respond(new storage.Buckets());
261 }));
262
263 api.listBucketNames().listen(
264 (_) => throw 'Unexpected',
265 onDone: expectAsync(() => null));
266 });
267 });
268
269 test('immediate-cancel', () {
270 withMockClient((mock, api) {
271 api.listBucketNames().listen(
272 (_) => throw 'Unexpected',
273 onDone: () => throw 'Unexpected')
274 ..cancel();
275 });
276 });
277
278 test('list', () {
279 // TODO: Test list.
280 });
281
282 test('page', () {
283 // TODO: Test page.
284 });
285 });
286
287 test('copy', () {
288 withMockClient((mock, api) {
289 mock.register(
290 'POST',
291 'b/srcBucket/o/srcObject/copyTo/b/destBucket/o/destObject',
292 expectAsync((request) {
293 return mock.respond(new storage.Object()..name = 'destObject');
294 }));
295 expect(api.copyObject('gs://srcBucket/srcObject',
296 'gs://destBucket/destObject'),
297 completion(isNull));
298 });
299 });
300
301 test('copy-invalid-args', () {
302 withMockClient((mock, api) {
303 expect(() => api.copyObject('a', 'b'), throwsA(isFormatException));
304 expect(() => api.copyObject('a/b', 'c/d'), throwsA(isFormatException));
305 expect(() => api.copyObject('gs://a/b', 'gs://c/'),
306 throwsA(isFormatException));
307 expect(() => api.copyObject('gs://a/b', 'gs:///c'),
308 throwsA(isFormatException));
309 });
310 });
311 });
312
313 group('object', () {
314 var bucketName = 'test-bucket';
315 var objectName = 'test-object';
316
317 var bytesNormalUpload = [1, 2, 3];
318
319 // Generate a list just above the limit when changing to resumable upload.
320 const int MB = 1024 * 1024;
321 const int maxNormalUpload = 1 * MB;
322 const int minResumableUpload = maxNormalUpload + 1;
323 var bytesResumableUpload =
324 new List.generate(minResumableUpload, (e) => e & 255);
325
326 bool testArgumentError(e) => e is ArgumentError;
327 bool testApiError(e) => e is common.ApiRequestError;
328 bool testDetailedApiError(e) => e is common.DetailedApiRequestError;
329 Function expectStatus(status) => (e) => expect(e.status, status);
330 Function expectNotNull(status) => (o) => expect(o, isNotNull);
331
332 expectNormalUpload(mock, data, objectName) {
333 var bytes = data.fold([], (p, e) => p..addAll(e));
334 mock.registerUpload(
335 'POST', 'b/$bucketName/o', expectAsync((request) {
336 return mock.processNormalMediaUpload(request)
337 .then(expectAsync((mediaUpload) {
338 var object =
339 new storage.Object.fromJson(JSON.decode(mediaUpload.json));
340 expect(object.name, objectName);
341 expect(mediaUpload.bytes, bytes);
342 expect(mediaUpload.contentType, 'application/octet-stream');
343 return mock.respond(new storage.Object()..name = objectName);
344 }));
345 }));
346 }
347
348 expectResumableUpload(mock, data, objectName) {
349 var bytes = data.fold([], (p, e) => p..addAll(e));
350 expect(bytes.length, bytesResumableUpload.length);
351 int count = 0;
352 mock.registerResumableUpload(
353 'POST', 'b/$bucketName/o', expectAsync((request) {
354 var requestObject =
355 new storage.Object.fromJson(JSON.decode(request.body));
356 expect(requestObject.name, objectName);
357 return mock.respondInitiateResumableUpload(PROJECT);
358 }));
359 mock.registerResumableUpload(
360 'PUT', 'b/$PROJECT/o', expectAsync((request) {
361 count++;
362 if (count == 1) {
363 expect(request.bodyBytes.length, MB);
364 return mock.respondContinueResumableUpload();
365 } else {
366 expect(request.bodyBytes.length, 1);
367 return mock.respond(new storage.Object()..name = objectName);
368 }
369 }, count: 2));
370 }
371
372 checkResult(result) {
373 expect(result.name, objectName);
374 }
375
376 Future pipeToSink(sink, List<List<int>> data) {
377 sink.done.then(expectAsync(checkResult));
378 sink.done.catchError((e) => throw 'Unexpected $e');
379 return new Stream.fromIterable(data)
380 .pipe(sink)
381 .then(expectAsync(checkResult))
382 .catchError((e) => throw 'Unexpected $e');
383 }
384
385 Future addStreamToSink(sink, List<List<int>> data) {
386 sink.done.then(expectAsync(checkResult));
387 sink.done.catchError((e) => throw 'Unexpected $e');
388 return sink.addStream(new Stream.fromIterable(data))
389 .then((_) => sink.close())
390 .then(expectAsync(checkResult))
391 .catchError((e) => throw 'Unexpected $e');
392 }
393
394 Future addToSink(sink, List<List<int>> data) {
395 sink.done.then(expectAsync(checkResult));
396 sink.done.catchError((e) => throw 'Unexpected $e');
397 data.forEach((bytes) => sink.add(bytes));
398 return sink.close()
399 .then(expectAsync(checkResult))
400 .catchError((e) => throw 'Unexpected $e');
401 }
402
403 Future runTest(mock, api, data, length) {
404 var bucket = api.bucket(bucketName);
405
406 Future upload(fn, sendLength) {
407 mock.clear();
408 if (length <= maxNormalUpload) {
409 expectNormalUpload(mock, data, objectName);
410 } else {
411 expectResumableUpload(mock, data, objectName);
412 }
413 var sink;
414 if (sendLength) {
415 sink = bucket.write(objectName, length: length);
416 } else {
417 sink = bucket.write(objectName);
418 }
419 return fn(sink, data);
420 }
421
422 return upload(pipeToSink, true)
423 .then(expectAsync((_) => upload(pipeToSink, false)))
424 .then(expectAsync((_) => upload(addStreamToSink, true)))
425 .then(expectAsync((_) => upload(addStreamToSink, false)))
426 .then(expectAsync((_) => upload(addToSink, true)))
427 .then(expectAsync((_) => upload(addToSink, false)));
428 };
429
430 test('write-short-1', () {
431 withMockClient((mock, api) {
432 runTest(mock, api, [bytesNormalUpload], bytesNormalUpload.length);
433 });
434 });
435
436 test('write-short-2', () {
437 withMockClient((mock, api) {
438 runTest(mock,
439 api,
440 [bytesNormalUpload, bytesNormalUpload],
441 bytesNormalUpload.length * 2);
442 });
443 });
444
445 test('write-long', () {
446 withMockClient((mock, api) {
447 runTest(mock, api, [bytesResumableUpload], bytesResumableUpload.length);
448 });
449 });
450
451 test('write-short-error', () {
452 withMockClient((mock, api) {
453
454 Future test(length) {
455 mock.clear();
456 mock.registerUpload(
457 'POST', 'b/$bucketName/o', expectAsync((request) {
458 return mock.respondError(500);
459 }));
460
461 var bucket = api.bucket(bucketName);
462 var sink = bucket.write(bucketName, length: length);
463 sink.done
464 .then((_) => throw 'Unexpected')
465 .catchError(expectAsync(expectNotNull),
466 test: testDetailedApiError);
467 sink.done
468 .catchError(expectAsync(expectNotNull),
469 test: testDetailedApiError);
470 return new Stream.fromIterable([bytesNormalUpload])
471 .pipe(sink)
472 .then((_) => throw 'Unexpected')
473 .catchError(expectAsync(expectNotNull),
474 test: testDetailedApiError);
475 }
476
477 test(null) // Unknown length.
478 .then(expectAsync((_) => test(1)))
479 .then(expectAsync((_) => test(10)))
480 .then(expectAsync((_) => test(maxNormalUpload)));
481 });
482 });
483
484 // TODO: Mock the resumable upload timeout.
485 test('write-long-error', () {
486 withMockClient((mock, api) {
487
488 Future test(length) {
489 mock.clear();
490 mock.registerResumableUpload(
491 'POST', 'b/$bucketName/o', expectAsync((request) {
492 return mock.respondInitiateResumableUpload(PROJECT);
493 }));
494 mock.registerResumableUpload(
495 'PUT', 'b/$PROJECT/o', expectAsync((request) {
496 return mock.respondError(502);
497 }, count: 3)); // Default 3 retries in googleapis library.
498
499
500 var bucket = api.bucket(bucketName);
501 var sink = bucket.write(bucketName);
502 sink.done
503 .then((_) => throw 'Unexpected')
504 .catchError(expectAsync(expectNotNull),
505 test: testDetailedApiError);
506 return new Stream.fromIterable([bytesResumableUpload])
507 .pipe(sink)
508 .then((_) => throw 'Unexpected')
509 .catchError(expectAsync(expectNotNull),
510 test: testDetailedApiError);
511 }
512
513 test(null) // Unknown length.
514 .then(expectAsync((_) => test(minResumableUpload)));
515 });
516 });
517
518 test('write-long-wrong-length', () {
519 withMockClient((mock, api) {
520
521 Future test(data, length) {
522 mock.clear();
523 mock.registerResumableUpload(
524 'POST', 'b/$bucketName/o', expectAsync((request) {
525 return mock.respondInitiateResumableUpload(PROJECT);
526 }));
527 mock.registerResumableUpload(
528 'PUT', 'b/$PROJECT/o', expectAsync((request) {
529 return mock.respondContinueResumableUpload();
530 })); // Default 3 retries in googleapis library.
531
532 var bucket = api.bucket(bucketName);
533 var sink = bucket.write(bucketName, length: length);
534 sink.done
535 .then((_) => throw 'Unexpected')
536 .catchError(
537 expectAsync(expectNotNull),
538 test: (e) => e is String || e is common.ApiRequestError);
539 return new Stream.fromIterable(data)
540 .pipe(sink)
541 .then((_) => throw 'Unexpected')
542 .catchError(
543 expectAsync(expectNotNull),
544 test: (e) => e is String || e is common.ApiRequestError);
545 }
546
547 test([bytesResumableUpload], bytesResumableUpload.length + 1)
548 .then(expectAsync((_) => test([bytesResumableUpload, [1, 2]],
549 bytesResumableUpload.length + 1)));
550 });
551 });
552
553 test('write-add-error', () {
554 withMockClient((mock, api) {
555 var bucket = api.bucket(bucketName);
556 var controller = new StreamController(sync: true);
557 var sink = bucket.write(bucketName);
558 sink.done
559 .then((_) => throw 'Unexpected')
560 .catchError(expectAsync(expectNotNull), test: testArgumentError);
561 var stream = new Stream.fromIterable([[1, 2, 3]]);
562 sink.addStream(stream).then((_) {
563 sink.addError(new ArgumentError());
564 sink.close()
565 .catchError(expectAsync(expectNotNull), test: testArgumentError);
566 });
567 });
568 });
569
570 test('write-long-add-error', () {
571 int count = 0;
572 withMockClient((mock, api) {
573 mock.registerResumableUpload(
574 'POST', 'b/$bucketName/o', expectAsync((request) {
575 return mock.respondInitiateResumableUpload(PROJECT);
576 }));
577 // The resumable upload will buffer until either close or a full chunk,
578 // so when we add an error the last byte is never sent. Therefore this
579 // PUT is only called once.
580 mock.registerResumableUpload(
581 'PUT', 'b/$PROJECT/o', expectAsync((request) {
582 expect(request.bodyBytes.length, 1024 * 1024);
583 return mock.respondContinueResumableUpload();
584 }));
585
586 var bucket = api.bucket(bucketName);
587 var sink = bucket.write(bucketName);
588 sink.done
589 .then((_) => throw 'Unexpected')
590 .catchError(expectAsync(expectNotNull), test: testArgumentError);
591 var stream = new Stream.fromIterable([bytesResumableUpload]);
592 sink.addStream(stream).then((_) {
593 sink.addError(new ArgumentError());
594 sink.close()
595 .catchError(expectAsync(expectNotNull), test: testArgumentError);
596 });
597 });
598 });
599
600 test('write-with-metadata-short', () {
601 var metadata =
602 [new ObjectMetadata(contentType: 'mime/type'),
603 new ObjectMetadata(contentType: 'type/mime',
604 cacheControl: 'control-cache'),
605 new ObjectMetadata(cacheControl: 'control-cache'),
606 new ObjectMetadata(cacheControl: 'control-cache',
607 contentDisposition: 'disp-content'),
608 new ObjectMetadata(contentDisposition: 'disp-content',
609 contentEncoding: 'encoding',
610 contentLanguage: 'language'),
611 new ObjectMetadata(custom: {'x': 'y'}),
612 new ObjectMetadata(custom: {'a': 'b', 'x': 'y'})
613 ];
614
615 withMockClient((mock, api) {
616 int count = 0;
617 var bytes = [1, 2, 3];
618
619 mock.registerUpload(
620 'POST', 'b/$bucketName/o', expectAsync((request) {
621 return mock.processNormalMediaUpload(request)
622 .then(expectAsync((mediaUpload) {
623 var object =
624 new storage.Object.fromJson(JSON.decode(mediaUpload.json));
625 ObjectMetadata m = metadata[count];
626 expect(object.name, objectName);
627 expect(mediaUpload.bytes, bytes);
628 var contentType = m.contentType != null
629 ? m.contentType : 'application/octet-stream';
630 expect(mediaUpload.contentType, contentType);
631 expect(object.cacheControl, m.cacheControl);
632 expect(object.contentDisposition, m.contentDisposition);
633 expect(object.contentEncoding, m.contentEncoding);
634 expect(object.contentLanguage, m.contentLanguage);
635 expect(object.metadata, m.custom);
636 count++;
637 return mock.respond(new storage.Object()..name = objectName);
638 }));
639 }, count: metadata.length));
640
641 var bucket = api.bucket(bucketName);
642 var futures = [];
643 for (int i = 0; i < metadata.length; i++) {
644 futures.add(bucket.writeBytes(objectName, bytes,
645 metadata: metadata[i]));
646 }
647 return Future.wait(futures);
648 });
649 });
650
651 test('write-with-metadata-long', () {
652 var metadata =
653 [new ObjectMetadata(contentType: 'mime/type'),
654 new ObjectMetadata(contentType: 'type/mime',
655 cacheControl: 'control-cache'),
656 new ObjectMetadata(cacheControl: 'control-cache'),
657 new ObjectMetadata(cacheControl: 'control-cache',
658 contentDisposition: 'disp-content'),
659 new ObjectMetadata(contentDisposition: 'disp-content',
660 contentEncoding: 'encoding',
661 contentLanguage: 'language'),
662 new ObjectMetadata(custom: {'x': 'y'}),
663 new ObjectMetadata(custom: {'a': 'b', 'x': 'y'})
664 ];
665
666 withMockClient((mock, api) {
667 int countInitial = 0;
668 int countData = 0;
669
670 mock.registerResumableUpload(
671 'POST', 'b/$bucketName/o', expectAsync((request) {
672 var object = new storage.Object.fromJson(JSON.decode(request.body));
673 ObjectMetadata m = metadata[countInitial];
674 expect(object.name, objectName);
675 var contentType = m.contentType != null
676 ? m.contentType : 'application/octet-stream';
677 expect(object.cacheControl, m.cacheControl);
678 expect(object.contentDisposition, m.contentDisposition);
679 expect(object.contentEncoding, m.contentEncoding);
680 expect(object.contentLanguage, m.contentLanguage);
681 expect(object.metadata, m.custom);
682 countInitial++;
683 return mock.respondInitiateResumableUpload(PROJECT);
684 }, count: metadata.length));
685 mock.registerResumableUpload(
686 'PUT', 'b/$PROJECT/o', expectAsync((request) {
687 ObjectMetadata m = metadata[countData % metadata.length];
688 var contentType = m.contentType != null
689 ? m.contentType : 'application/octet-stream';
690 expect(request.headers['content-type'], contentType);
691 bool firstPart = countData < metadata.length;
692 countData++;
693 if (firstPart) {
694 expect(request.bodyBytes.length, MB);
695 return mock.respondContinueResumableUpload();
696 } else {
697 expect(request.bodyBytes.length, 1);
698 return mock.respond(new storage.Object()..name = objectName);
699 }
700 }, count: metadata.length * 2));
701
702 var bucket = api.bucket(bucketName);
703 var futures = [];
704 for (int i = 0; i < metadata.length; i++) {
705 futures.add(bucket.writeBytes(objectName, bytesResumableUpload,
706 metadata: metadata[i]));
707 }
708 return Future.wait(futures);
709 });
710 });
711
712 test('write-with-predefined-acl', () {
713 var predefined =
714 [[PredefinedAcl.authenticatedRead, 'authenticatedRead'],
715 [PredefinedAcl.private, 'private'],
716 [PredefinedAcl.projectPrivate, 'projectPrivate'],
717 [PredefinedAcl.publicRead, 'publicRead'],
718 [PredefinedAcl.bucketOwnerFullControl, 'bucketOwnerFullControl'],
719 [PredefinedAcl.bucketOwnerRead, 'bucketOwnerRead']];
720
721 withMockClient((mock, api) {
722 int count = 0;
723 var bytes = [1,2,3];
724
725 mock.registerUpload(
726 'POST', 'b/$bucketName/o', expectAsync((request) {
727 return mock.processNormalMediaUpload(request)
728 .then(expectAsync((mediaUpload) {
729 var object =
730 new storage.Object.fromJson(JSON.decode(mediaUpload.json));
731 expect(object.name, objectName);
732 expect(mediaUpload.bytes, bytes);
733 expect(mediaUpload.contentType, 'application/octet-stream');
734 expect(request.url.queryParameters['predefinedAcl'],
735 predefined[count++][1]);
736 expect(object.acl, isNull);
737 return mock.respond(new storage.Object()..name = objectName);
738 }));
739 }, count: predefined.length));
740
741 var bucket = api.bucket(bucketName);
742 var futures = [];
743 for (int i = 0; i < predefined.length; i++) {
744 futures.add(bucket.writeBytes(objectName, bytes,
745 predefinedAcl: predefined[i][0]));
746 }
747 return Future.wait(futures);
748 });
749 });
750
751 test('write-with-acl', () {
752 var acl1 = new Acl([
753 new AclEntry(new AccountScope('user@example.com'),
754 AclPermission.FULL_CONTROL),
755 ]);
756 var acl2 = new Acl([
757 new AclEntry(new AccountScope('user@example.com'),
758 AclPermission.FULL_CONTROL),
759 new AclEntry(new GroupScope('group@example.com'),
760 AclPermission.WRITE),
761 ]);
762 var acl3 = new Acl([
763 new AclEntry(new AccountScope('user@example.com'),
764 AclPermission.FULL_CONTROL),
765 new AclEntry(new GroupScope('group@example.com'),
766 AclPermission.WRITE),
767 new AclEntry(new DomainScope('example.com'),
768 AclPermission.READ),
769 ]);
770
771 var acls = [acl1, acl2, acl3];
772
773 withMockClient((mock, api) {
774 int count = 0;
775 var bytes = [1,2,3];
776
777 mock.registerUpload(
778 'POST', 'b/$bucketName/o', expectAsync((request) {
779 return mock.processNormalMediaUpload(request)
780 .then(expectAsync((mediaUpload) {
781 var object =
782 new storage.Object.fromJson(JSON.decode(mediaUpload.json));
783 expect(object.name, objectName);
784 expect(mediaUpload.bytes, bytes);
785 expect(mediaUpload.contentType, 'application/octet-stream');
786 expect(request.url.queryParameters['predefinedAcl'], isNull);
787 expect(object.acl, isNotNull);
788 expect(object.acl.length, count + 1);
789 expect(object.acl[0].entity, 'user-user@example.com');
790 expect(object.acl[0].role, 'OWNER');
791 if (count > 0) {
792 expect(object.acl[1].entity, 'group-group@example.com');
793 expect(object.acl[1].role, 'OWNER');
794 }
795 if (count > 2) {
796 expect(object.acl[2].entity, 'domain-example.com');
797 expect(object.acl[2].role, 'READER');
798 }
799 count++;
800 return mock.respond(new storage.Object()..name = objectName);
801 }));
802 }, count: acls.length));
803
804 var bucket = api.bucket(bucketName);
805 var futures = [];
806 for (int i = 0; i < acls.length; i++) {
807 futures.add(bucket.writeBytes(objectName, bytes, acl: acls[i]));
808 }
809 return Future.wait(futures);
810 });
811 });
812
813 test('write-with-acl-and-predefined-acl', () {
814 var predefined =
815 [[PredefinedAcl.authenticatedRead, 'authenticatedRead'],
816 [PredefinedAcl.private, 'private'],
817 [PredefinedAcl.projectPrivate, 'projectPrivate'],
818 [PredefinedAcl.publicRead, 'publicRead'],
819 [PredefinedAcl.bucketOwnerFullControl, 'bucketOwnerFullControl'],
820 [PredefinedAcl.bucketOwnerRead, 'bucketOwnerRead']];
821
822 var acl1 = new Acl([
823 new AclEntry(new AccountScope('user@example.com'),
824 AclPermission.FULL_CONTROL),
825 ]);
826 var acl2 = new Acl([
827 new AclEntry(new AccountScope('user@example.com'),
828 AclPermission.FULL_CONTROL),
829 new AclEntry(new GroupScope('group@example.com'),
830 AclPermission.WRITE),
831 ]);
832 var acl3 = new Acl([
833 new AclEntry(new AccountScope('user@example.com'),
834 AclPermission.FULL_CONTROL),
835 new AclEntry(new GroupScope('group@example.com'),
836 AclPermission.WRITE),
837 new AclEntry(new DomainScope('example.com'),
838 AclPermission.READ),
839 ]);
840
841 var acls = [acl1, acl2, acl3];
842
843 withMockClient((mock, api) {
844 int count = 0;
845 var bytes = [1,2,3];
846
847 mock.registerUpload(
848 'POST', 'b/$bucketName/o', expectAsync((request) {
849 return mock.processNormalMediaUpload(request)
850 .then(expectAsync((mediaUpload) {
851 int predefinedIndex = count ~/ acls.length;
852 int aclIndex = count % acls.length;
853 var object =
854 new storage.Object.fromJson(JSON.decode(mediaUpload.json));
855 expect(object.name, objectName);
856 expect(mediaUpload.bytes, bytes);
857 expect(mediaUpload.contentType, 'application/octet-stream');
858 expect(request.url.queryParameters['predefinedAcl'],
859 predefined[predefinedIndex][1]);
860 expect(object.acl, isNotNull);
861 expect(object.acl.length, aclIndex + 1);
862 expect(object.acl[0].entity, 'user-user@example.com');
863 expect(object.acl[0].role, 'OWNER');
864 if (aclIndex > 0) {
865 expect(object.acl[1].entity, 'group-group@example.com');
866 expect(object.acl[1].role, 'OWNER');
867 }
868 if (aclIndex > 2) {
869 expect(object.acl[2].entity, 'domain-example.com');
870 expect(object.acl[2].role, 'READER');
871 }
872 count++;
873 return mock.respond(new storage.Object()..name = objectName);
874 }));
875 }, count: predefined.length * acls.length));
876
877 var bucket = api.bucket(bucketName);
878 var futures = [];
879 for (int i = 0; i < predefined.length; i++) {
880 for (int j = 0; j < acls.length; j++) {
881 futures.add(bucket.writeBytes(
882 objectName, bytes,
883 acl: acls[j], predefinedAcl: predefined[i][0]));
884 }
885 }
886 return Future.wait(futures);
887 });
888 });
889
890
891
892 test('read', () {
893 var bytes = [1, 2, 3];
894 withMockClient((mock, api) {
895 mock.register(
896 'GET', 'b/$bucketName/o/$objectName', expectAsync((request) {
897 expect(request.url.queryParameters['alt'], 'media');
898 return mock.respondBytes(bytes);
899 }));
900
901 var bucket = api.bucket(bucketName);
902 var data = [];
903 bucket.read(objectName).listen(data.addAll).asFuture()
904 .then(expectAsync((_) => expect(data, bytes)));
905 });
906 });
907
908 test('stat', () {
909 withMockClient((mock, api) {
910 mock.register(
911 'GET', 'b/$bucketName/o/$objectName', expectAsync((request) {
912 expect(request.url.queryParameters['alt'], 'json');
913 return mock.respond(new storage.Object()
914 ..name = objectName
915 ..updated = new DateTime(2014)
916 ..contentType = 'mime/type');
917 }));
918
919 var api = new Storage(mock, PROJECT);
920 var bucket = api.bucket(bucketName);
921 bucket.info(objectName).then(expectAsync((stat) {
922 expect(stat.name, objectName);
923 expect(stat.updated, new DateTime(2014));
924 expect(stat.metadata.contentType, 'mime/type');
925 }));
926 });
927 });
928
929 test('stat-acl', () {
930 withMockClient((mock, api) {
931 mock.register(
932 'GET', 'b/$bucketName/o/$objectName', expectAsync((request) {
933 expect(request.url.queryParameters['alt'], 'json');
934 var acl1 = new storage.ObjectAccessControl();
935 acl1.entity = 'user-1234567890';
936 acl1.role = 'OWNER';
937 var acl2 = new storage.ObjectAccessControl();
938 acl2.entity = 'user-xxx@yyy.zzz';
939 acl2.role = 'OWNER';
940 var acl3 = new storage.ObjectAccessControl();
941 acl3.entity = 'xxx-1234567890';
942 acl3.role = 'OWNER';
943 return mock.respond(new storage.Object()
944 ..name = objectName
945 ..acl = [acl1, acl2, acl3]);
946 }));
947
948 var api = new Storage(mock, PROJECT);
949 var bucket = api.bucket(bucketName);
950 bucket.info(objectName).then(expectAsync((ObjectInfo info) {
951 expect(info.name, objectName);
952 expect(info.metadata.acl.entries.length, 3);
953 expect(info.metadata.acl.entries[0] is AclEntry, isTrue);
954 expect(info.metadata.acl.entries[0].scope is StorageIdScope, isTrue);
955 expect(info.metadata.acl.entries[1] is AclEntry, isTrue);
956 expect(info.metadata.acl.entries[1].scope is AccountScope, isTrue);
957 expect(info.metadata.acl.entries[2] is AclEntry, isTrue);
958 expect(info.metadata.acl.entries[2].scope is OpaqueScope, isTrue);
959 }));
960 });
961 });
962
963 group('list', () {
964 test('empty', () {
965 withMockClient((mock, api) {
966 mock.register('GET', 'b/$bucketName/o', expectAsync((request) {
967 expect(request.body.length, 0);
968 return mock.respond(new storage.Objects());
969 }));
970
971 var bucket = api.bucket(bucketName);
972 bucket.list().listen(
973 (_) => throw 'Unexpected',
974 onDone: expectAsync(() => null));
975 });
976 });
977
978 test('immediate-cancel', () {
979 withMockClient((mock, api) {
980 var bucket = api.bucket(bucketName);
981 bucket.list().listen(
982 (_) => throw 'Unexpected',
983 onDone: () => throw 'Unexpected')
984 ..cancel();
985 });
986 });
987
988 test('list', () {
989 // TODO: Test list.
990 });
991
992 test('page', () {
993 // TODO: Test page.
994 });
995 });
996 });
997
998 group('acl', () {
999 var id = new StorageIdScope('1234567890');
1000 var user = new AccountScope('sgjesse@google.com');
1001 var group = new GroupScope('dart');
1002 var domain = new DomainScope('dartlang.org');
1003
1004 var userRead = new AclEntry(user, AclPermission.READ);
1005 var groupWrite = new AclEntry(group, AclPermission.WRITE);
1006 var domainFullControl =
1007 new AclEntry(domain, AclPermission.FULL_CONTROL);
1008
1009 test('compare-scope', () {
1010 expect(id, new StorageIdScope('1234567890'));
1011 expect(user, new AccountScope('sgjesse@google.com'));
1012 expect(group, new GroupScope('dart'));
1013 expect(domain, new DomainScope('dartlang.org'));
1014 expect(AclScope.allAuthenticated, new AllAuthenticatedScope());
1015 expect(AclScope.allUsers, new AllUsersScope());
1016 });
1017
1018 test('compare-entries', () {
1019 expect(userRead, new AclEntry(user, AclPermission.READ));
1020 expect(groupWrite, new AclEntry(group, AclPermission.WRITE));
1021 expect(domainFullControl,
1022 new AclEntry(domain, AclPermission.FULL_CONTROL));
1023 });
1024
1025 test('compare-acls', () {
1026 var acl = new Acl([userRead, groupWrite, domainFullControl]);
1027 expect(acl, new Acl([new AclEntry(user, AclPermission.READ),
1028 new AclEntry(group, AclPermission.WRITE),
1029 new AclEntry(domain, AclPermission.FULL_CONTROL)]));
1030 expect(acl,
1031 isNot(equals(new Acl([new AclEntry(group, AclPermission.WRITE),
1032 new AclEntry(user, AclPermission.READ),
1033 new AclEntry(domain, AclPermission.FULL_CONTROL)]))));
1034 });
1035
1036
1037 test('compare-predefined-acls', () {
1038 expect(PredefinedAcl.private, PredefinedAcl.private);
1039 expect(PredefinedAcl.private, isNot(equals(PredefinedAcl.publicRead)));
1040 });
1041 });
1042 }
OLDNEW
« no previous file with comments | « pkg/gcloud/test/storage/e2e_test.dart ('k') | pkg/mustache/.gitignore » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698