testutil/TestBucket.cs (101 lines of code) (raw):

// Copyright(c) 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy of // the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations under // the License. using Google.Cloud.Storage.V1; using System; using System.Collections.Generic; using System.IO; using System.Threading; namespace GoogleCloudSamples { /// <summary> /// Creates a bucket with a random name for use in tests. Call Dispose() /// to delete the bucket. /// </summary> public class RandomBucketFixture : IDisposable { private readonly StorageClient _storage = StorageClient.Create(); public RandomBucketFixture() : this(Environment.GetEnvironmentVariable("GOOGLE_PROJECT_ID")) { } private RandomBucketFixture(string projectId) { BucketName = RandomBucketName(); _storage.CreateBucket(projectId, BucketName); } public void Dispose() { int retryDelayMs = 0; for (int errorCount = 0; errorCount < 4; ++errorCount) { Thread.Sleep(retryDelayMs); retryDelayMs = (retryDelayMs + 1000) * 2; try { _storage.DeleteBucket(BucketName, new DeleteBucketOptions() { DeleteObjects = true }); } catch (Google.GoogleApiException e) when (e.Error.Code == 404) { return; // Bucket does not exist. Ok. } catch (Google.GoogleApiException) { continue; // Try again. } } } private static string RandomBucketName() { return TestUtil.RandomName(); } public string BucketName { get; private set; } } /// <summary> /// Tracks objects in a Cloud Storage bucket for later clean up. /// Call Dispose() to clean up. /// </summary> public class BucketCollector : IDisposable { private readonly StorageClient _storage = StorageClient.Create(); private readonly string _bucketName; private readonly SortedDictionary<string, SortedSet<string>> _garbage = new SortedDictionary<string, SortedSet<string>>(); public BucketCollector(string bucketName) { _bucketName = bucketName; } /// <summary> /// Record the name of a Cloud Storage object for later clean up. /// </summary> /// <returns>The object name.</returns> public string Collect(string objectName) { return Collect(_bucketName, objectName); } /// <summary> /// Record the name of a Cloud Storage object for later clean up. /// </summary> /// <returns>The object name.</returns> public string Collect(string bucketName, string objectName) { if (!_garbage.TryGetValue(bucketName, out SortedSet<string> objectNames)) { objectNames = _garbage[bucketName] = new SortedSet<string>(); } objectNames.Add(objectName); return objectName; } /// <summary> /// Copies a local file to the Cloud Storage bucket and records its /// name for later clean up. /// </summary> /// <param name="localPath"></param> /// <param name="objectName"></param> public void CopyToBucket(string localPath, string objectName) { using (Stream m = new FileStream(localPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { _storage.UploadObject(_bucketName, objectName, null, m); Collect(objectName); } } public void Dispose() { RetryRobot robot = new RetryRobot() { MaxTryCount = 10, ShouldRetry = (e) => true, }; foreach (KeyValuePair<string, SortedSet<string>> bucket in _garbage) { foreach (string objectName in bucket.Value) { robot.Eventually(() => { _storage.DeleteObject(bucket.Key, objectName); }); } } _garbage.Clear(); } } }