Index: pkg/gcloud/test/storage/e2e_test.dart |
diff --git a/pkg/gcloud/test/storage/e2e_test.dart b/pkg/gcloud/test/storage/e2e_test.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..fabbf48dff7b3d2b7f77c4ec33f45dd7f28f1d61 |
--- /dev/null |
+++ b/pkg/gcloud/test/storage/e2e_test.dart |
@@ -0,0 +1,271 @@ |
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+library gcloud.storage; |
+ |
+import 'dart:async'; |
+ |
+import 'package:gcloud/storage.dart'; |
+import 'package:googleapis/common/common.dart' as common; |
+import 'package:unittest/unittest.dart'; |
+ |
+import '../common_e2e.dart'; |
+ |
+String generateBucketName() { |
+ var id = new DateTime.now().millisecondsSinceEpoch; |
+ return 'dart-e2e-test-$id'; |
+} |
+ |
+bool testDetailedApiError(e) => e is common.DetailedApiRequestError; |
+ |
+// Generate a list just above the limit when changing to resumable upload. |
+const int MB = 1024 * 1024; |
+const int maxNormalUpload = 1 * MB; |
+const int minResumableUpload = maxNormalUpload + 1; |
+var bytesResumableUpload = |
+ new List.generate(minResumableUpload, (e) => e & 255); |
+ |
+runTests(Storage storage, Bucket testBucket) { |
+ group('bucket', () { |
+ test('create-info-delete', () { |
+ var bucketName = generateBucketName(); |
+ return storage.createBucket(bucketName).then(expectAsync((result) { |
+ expect(result, isNull); |
+ return storage.bucketInfo(bucketName).then(expectAsync((info) { |
+ expect(info.bucketName, bucketName); |
+ expect(info.etag, isNotNull); |
+ expect(info.created is DateTime, isTrue); |
+ expect(info.id, isNotNull); |
+ return storage.deleteBucket(bucketName) |
+ .then(expectAsync((result) { |
+ expect(result, isNull); |
+ })); |
+ })); |
+ })); |
+ }); |
+ |
+ test('create-with-predefined-acl-delete', () { |
+ Future<Acl> test(predefinedAcl, expectedLength) { |
+ var bucketName = generateBucketName(); |
+ return storage.createBucket(bucketName, predefinedAcl: predefinedAcl) |
+ .then(expectAsync((result) { |
+ expect(result, isNull); |
+ return storage.bucketInfo(bucketName).then(expectAsync((info) { |
+ var acl = info.acl; |
+ expect(info.bucketName, bucketName); |
+ expect(acl.entries.length, expectedLength); |
+ return storage.deleteBucket(bucketName) |
+ .then(expectAsync((result) { |
+ expect(result, isNull); |
+ })); |
+ })); |
+ })); |
+ } |
+ |
+ return Future.forEach([ |
+ // TODO: Figure out why some returned ACLs are empty. |
+ () => test(PredefinedAcl.authenticatedRead, 0), |
+ // [test, [PredefinedAcl.private, 0]], // TODO: Cannot delete. |
+ () => test(PredefinedAcl.projectPrivate, 3), |
+ () => test(PredefinedAcl.publicRead, 0), |
+ () => test(PredefinedAcl.publicReadWrite, 0) |
+ ], (f) => f().then(expectAsync((_) {}))); |
+ }); |
+ |
+ test('create-error', () { |
+ var bucketName = generateBucketName(); |
+ |
+ storage.createBucket('goog-reserved').catchError(expectAsync((e) { |
+ expect(e, isNotNull); |
+ }), test: testDetailedApiError); |
+ }); |
+ }); |
+ |
+ // TODO: Remove solo_ here when the rate-limit issue have been resolved. |
+ solo_group('object', () { |
+ // Run all object tests in the same bucket to try to avoid the rate-limit |
+ // for creating and deleting buckets while testing. |
+ Future withTestBucket(function) { |
+ return function(testBucket).whenComplete(() { |
+ // TODO: Clean the bucket. |
+ }); |
+ } |
+ |
+ test('create-read-delete', () { |
+ Future test(name, bytes) { |
+ return withTestBucket((Bucket bucket) { |
+ return bucket.writeBytes('test', bytes).then(expectAsync((info) { |
+ expect(info, isNotNull); |
+ return bucket.read('test') |
+ .fold([], (p, e) => p..addAll(e)) |
+ .then(expectAsync((result) { |
+ expect(result, bytes); |
+ return bucket.delete('test').then(expectAsync((result) { |
+ expect(result, isNull); |
+ })); |
+ })); |
+ })); |
+ }); |
+ } |
+ |
+ return Future.forEach([ |
+ () => test('test-1', [1, 2, 3]), |
+ () => test('test-2', bytesResumableUpload) |
+ ], (f) => f().then(expectAsync((_) {}))); |
+ }); |
+ |
+ test('create-with-predefined-acl-delete', () { |
+ return withTestBucket((Bucket bucket) { |
+ Future test(objectName, predefinedAcl, expectedLength) { |
+ var bucketName = generateBucketName(); |
+ return bucket.writeBytes( |
+ objectName, [1, 2, 3], predefinedAcl: predefinedAcl) |
+ .then(expectAsync((result) { |
+ expect(result, isNotNull); |
+ return bucket.info(objectName).then(expectAsync((info) { |
+ var acl = info.metadata.acl; |
+ expect(info.name, objectName); |
+ expect(info.etag, isNotNull); |
+ expect(acl.entries.length, expectedLength); |
+ return bucket.delete(objectName).then(expectAsync((result) { |
+ expect(result, isNull); |
+ })); |
+ })); |
+ })); |
+ } |
+ |
+ return Future.forEach([ |
+ () => test('test-1', PredefinedAcl.authenticatedRead, 2), |
+ () => test('test-2', PredefinedAcl.private, 1), |
+ () => test('test-3', PredefinedAcl.projectPrivate, 4), |
+ () => test('test-4', PredefinedAcl.publicRead, 2), |
+ () => test('test-5', PredefinedAcl.bucketOwnerFullControl, 2), |
+ () => test('test-6', PredefinedAcl.bucketOwnerRead, 2) |
+ ], (f) => f().then(expectAsync((_) {}))); |
+ }); |
+ }); |
+ |
+ test('create-with-acl-delete', () { |
+ return withTestBucket((Bucket bucket) { |
+ Future test(objectName, acl, expectedLength) { |
+ var bucketName = generateBucketName(); |
+ return bucket.writeBytes(objectName, [1, 2, 3], acl: acl) |
+ .then(expectAsync((result) { |
+ expect(result, isNotNull); |
+ return bucket.info(objectName).then(expectAsync((info) { |
+ var acl = info.metadata.acl; |
+ expect(info.name, objectName); |
+ expect(info.etag, isNotNull); |
+ expect(acl.entries.length, expectedLength); |
+ return bucket.delete(objectName).then(expectAsync((result) { |
+ expect(result, isNull); |
+ })); |
+ })); |
+ })); |
+ } |
+ |
+ Acl acl1 = new Acl( |
+ [new AclEntry(AclScope.allAuthenticated, AclPermission.WRITE)]); |
+ Acl acl2 = new Acl( |
+ [new AclEntry(AclScope.allUsers, AclPermission.WRITE), |
+ new AclEntry(new AccountScope('sgjesse@google.com'), |
+ AclPermission.WRITE)]); |
+ Acl acl3 = new Acl( |
+ [new AclEntry(AclScope.allUsers, AclPermission.WRITE), |
+ new AclEntry(new AccountScope('sgjesse@google.com'), |
+ AclPermission.WRITE), |
+ new AclEntry(new AccountScope('misc@dartlang.org'), |
+ AclPermission.READ)]); |
+ Acl acl4 = new Acl( |
+ [new AclEntry(AclScope.allUsers, AclPermission.WRITE), |
+ new AclEntry(new AccountScope('sgjesse@google.com'), |
+ AclPermission.WRITE), |
+ new AclEntry(new GroupScope('misc@dartlang.org'), |
+ AclPermission.READ), |
+ new AclEntry(new DomainScope('dartlang.org'), |
+ AclPermission.FULL_CONTROL)]); |
+ |
+ return Future.forEach([ |
+ () => test('test-1', acl1, 1), |
+ () => test('test-2', acl2, 2), |
+ () => test('test-3', acl3, 3), |
+ () => test('test-4', acl4, 4) |
+ ], (f) => f().then(expectAsync((_) {}))); |
+ }); |
+ }); |
+ |
+ test('create-with-metadata-delete', () { |
+ return withTestBucket((Bucket bucket) { |
+ Future test(objectName, metadata, bytes) { |
+ var bucketName = generateBucketName(); |
+ return bucket.writeBytes(objectName, bytes, metadata: metadata) |
+ .then(expectAsync((result) { |
+ expect(result, isNotNull); |
+ return bucket.info(objectName).then(expectAsync((info) { |
+ var acl = info.metadata.acl; |
+ expect(info.name, objectName); |
+ expect(info.length, bytes.length); |
+ expect(info.updated is DateTime, isTrue); |
+ expect(info.md5Hash, isNotNull); |
+ expect(info.crc32CChecksum, isNotNull); |
+ expect(info.downloadLink is Uri, isTrue); |
+ expect(info.generation.objectGeneration, isNotNull); |
+ expect(info.generation.metaGeneration, 1); |
+ expect(info.metadata.contentType, metadata.contentType); |
+ expect(info.metadata.cacheControl, metadata.cacheControl); |
+ expect(info.metadata.contentDisposition, |
+ metadata.contentDisposition); |
+ expect(info.metadata.contentEncoding, |
+ metadata.contentEncoding); |
+ expect(info.metadata.contentLanguage, |
+ metadata.contentLanguage); |
+ expect(info.metadata.custom, metadata.custom); |
+ return bucket.delete(objectName).then(expectAsync((result) { |
+ expect(result, isNull); |
+ })); |
+ })); |
+ })); |
+ } |
+ |
+ var metadata1 = new ObjectMetadata(contentType: 'text/plain'); |
+ var metadata2 = new ObjectMetadata( |
+ contentType: 'text/plain', |
+ cacheControl: 'no-cache', |
+ contentDisposition: 'attachment; filename="test.txt"', |
+ contentEncoding: 'gzip', |
+ contentLanguage: 'da', |
+ custom: {'a': 'b', 'c': 'd'}); |
+ |
+ return Future.forEach([ |
+ () => test('test-1', metadata1, [65, 66, 67]), |
+ () => test('test-2', metadata2, [65, 66, 67]), |
+ () => test('test-3', metadata1, bytesResumableUpload), |
+ () => test('test-4', metadata2, bytesResumableUpload) |
+ ], (f) => f().then(expectAsync((_) {}))); |
+ }); |
+ }); |
+ }); |
+} |
+ |
+main() { |
+ withAuthClient(Storage.SCOPES, (String project, httpClient) { |
+ var testBucket = generateBucketName(); |
+ |
+ // Share the same storage connection for all tests. |
+ var storage = new Storage(httpClient, project); |
+ |
+ // Create a shared bucket for all object tests. |
+ return storage.createBucket(testBucket).then((_) { |
+ return runE2EUnittest(() { |
+ runTests(storage, storage.bucket(testBucket)); |
+ }).whenComplete(() { |
+ // Deleting a bucket relies on eventually consistent behaviour, hence |
+ // the delay in attempt to prevent test flakiness. |
+ return new Future.delayed(STORAGE_LIST_DELAY, () { |
+ return storage.deleteBucket(testBucket); |
+ }); |
+ }); |
+ }); |
+ }); |
+} |