/// <summary>
        /// set blob properties
        /// </summary>
        /// <param name="azureBlob">CloudBlob object</param>
        /// <param name="meta">blob properties hashtable</param>
        private async Task SetBlobProperties(IStorageBlobManagement localChannel, StorageBlob.CloudBlob blob, Hashtable properties)
        {
            if (properties == null)
            {
                return;
            }

            foreach (DictionaryEntry entry in properties)
            {
                string key   = entry.Key.ToString();
                string value = entry.Value.ToString();
                Action <StorageBlob.BlobProperties, string> action = validCloudBlobProperties[key];

                if (action != null)
                {
                    action(blob.Properties, value);
                }
            }

            AccessCondition accessCondition = null;

            StorageBlob.BlobRequestOptions requestOptions = RequestOptions;

            await Channel.SetBlobPropertiesAsync(blob, accessCondition, requestOptions, OperationContext, CmdletCancellationToken).ConfigureAwait(false);
        }
        /// <summary>
        /// set blob meta
        /// </summary>
        /// <param name="azureBlob">CloudBlob object</param>
        /// <param name="meta">meta data hashtable</param>
        private async Task SetBlobMeta(IStorageBlobManagement localChannel, StorageBlob.CloudBlob blob, Hashtable meta)
        {
            if (meta == null)
            {
                return;
            }

            foreach (DictionaryEntry entry in meta)
            {
                string key   = entry.Key.ToString();
                string value = entry.Value.ToString();

                if (blob.Metadata.ContainsKey(key))
                {
                    blob.Metadata[key] = value;
                }
                else
                {
                    blob.Metadata.Add(key, value);
                }
            }

            AccessCondition accessCondition = null;

            StorageBlob.BlobRequestOptions requestOptions = RequestOptions;

            await Channel.SetBlobMetadataAsync(blob, accessCondition, requestOptions, OperationContext, CmdletCancellationToken).ConfigureAwait(false);
        }
        /// <summary>
        /// On Task run successfully
        /// </summary>
        /// <param name="data">User data</param>
        protected override void OnTaskSuccessful(DataMovementUserData data)
        {
            StorageBlob.CloudBlob  blob         = data.Data as StorageBlob.CloudBlob;
            IStorageBlobManagement localChannel = data.Channel;

            if (blob != null)
            {
                AccessCondition accessCondition = null;
                StorageBlob.BlobRequestOptions requestOptions = RequestOptions;

                if (this.pageBlobTier != null || this.standardBlobTier != null)
                {
                    this.SetBlobTier(localChannel, blob, pageBlobTier, standardBlobTier).Wait();
                }

                try
                {
                    localChannel.FetchBlobAttributesAsync(blob, accessCondition, requestOptions, OperationContext, CmdletCancellationToken).Wait();
                }
                catch (AggregateException e)
                {
                    StorageException storageException = e.InnerException as StorageException;
                    //Handle the limited read permission.
                    if (storageException == null || !storageException.IsNotFoundException())
                    {
                        throw e.InnerException;
                    }
                }

                WriteCloudBlobObject(data.TaskId, localChannel, blob);
            }
        }
예제 #4
0
        /// <summary>
        /// set blob AccessTier
        /// </summary>
        /// <param name="azureBlob">CloudBlob object</param>
        /// <param name="blockBlobTier">Block Blob Tier</param>
        /// <param name="pageBlobTier">Page Blob Tier</param>
        private async Task SetBlobTier(IStorageBlobManagement localChannel, StorageBlob.CloudBlob blob, PremiumPageBlobTier?pageBlobTier)
        {
            if (pageBlobTier == null)
            {
                return;
            }

            StorageBlob.BlobRequestOptions requestOptions = RequestOptions;

            // The Blob Type and Blob Tier must match, since already checked they are match at the begin of ExecuteCmdlet().
            if (pageBlobTier != null)
            {
                await Channel.SetPageBlobTierAsync((CloudPageBlob)blob, pageBlobTier.Value, requestOptions, OperationContext, CmdletCancellationToken).ConfigureAwait(false);
            }
        }
예제 #5
0
        /// <summary>
        /// set blob properties to a blob object
        /// </summary>
        /// <param name="azureBlob">CloudBlob object</param>
        /// <param name="meta">blob properties hashtable</param>
        private void SetBlobProperties(StorageBlob.CloudBlob blob, Hashtable properties)
        {
            if (properties == null)
            {
                return;
            }

            foreach (DictionaryEntry entry in properties)
            {
                string key   = entry.Key.ToString();
                string value = entry.Value.ToString();
                Action <StorageBlob.BlobProperties, string> action = validCloudBlobProperties[key];

                if (action != null)
                {
                    action(blob.Properties, value);
                }
            }
        }
 public static void UploadFromByteArray(this StorageBlob.CloudBlob cloudBlob, byte[] randomData)
 {
     if (StorageBlob.BlobType.BlockBlob == cloudBlob.BlobType)
     {
         (cloudBlob as StorageBlob.CloudBlockBlob).UploadFromByteArray(randomData, 0, randomData.Length);
     }
     else if (StorageBlob.BlobType.PageBlob == cloudBlob.BlobType)
     {
         (cloudBlob as StorageBlob.CloudPageBlob).UploadFromByteArray(randomData, 0, randomData.Length);
     }
     else if (StorageBlob.BlobType.AppendBlob == cloudBlob.BlobType)
     {
         (cloudBlob as StorageBlob.CloudAppendBlob).UploadFromByteArray(randomData, 0, randomData.Length);
     }
     else
     {
         throw new InvalidOperationException(string.Format("Invalid blob type: {0}", cloudBlob.BlobType));
     }
 }
 public static void UploadFromStream(this StorageBlob.CloudBlob cloudBlob, Stream source)
 {
     if (StorageBlob.BlobType.BlockBlob == cloudBlob.BlobType)
     {
         (cloudBlob as StorageBlob.CloudBlockBlob).UploadFromStream(source);
     }
     else if (StorageBlob.BlobType.PageBlob == cloudBlob.BlobType)
     {
         (cloudBlob as StorageBlob.CloudPageBlob).UploadFromStream(source);
     }
     else if (StorageBlob.BlobType.AppendBlob == cloudBlob.BlobType)
     {
         (cloudBlob as StorageBlob.CloudAppendBlob).UploadFromStream(source);
     }
     else
     {
         throw new InvalidOperationException(string.Format("Invalid blob type: {0}", cloudBlob.BlobType));
     }
 }
예제 #8
0
        /// <summary>
        /// set blob metadata to a blob object
        /// </summary>
        /// <param name="azureBlob">CloudBlob object</param>
        /// <param name="meta">meta data hashtable</param>
        private void SetBlobMeta(StorageBlob.CloudBlob blob, Hashtable meta)
        {
            if (meta == null)
            {
                return;
            }

            foreach (DictionaryEntry entry in meta)
            {
                string key   = entry.Key.ToString();
                string value = entry.Value.ToString();

                if (blob.Metadata.ContainsKey(key))
                {
                    blob.Metadata[key] = value;
                }
                else
                {
                    blob.Metadata.Add(key, value);
                }
            }
        }
 public static void UploadFromFile(this StorageBlob.CloudBlob cloudBlob,
                                   string path,
                                   AccessCondition accessCondition        = null,
                                   StorageBlob.BlobRequestOptions options = null,
                                   OperationContext operationContext      = null)
 {
     if (StorageBlob.BlobType.BlockBlob == cloudBlob.BlobType)
     {
         (cloudBlob as StorageBlob.CloudBlockBlob).UploadFromFile(path, accessCondition, options, operationContext);
     }
     else if (StorageBlob.BlobType.PageBlob == cloudBlob.BlobType)
     {
         (cloudBlob as StorageBlob.CloudPageBlob).UploadFromFile(path, accessCondition, options, operationContext);
     }
     else if (StorageBlob.BlobType.AppendBlob == cloudBlob.BlobType)
     {
         (cloudBlob as StorageBlob.CloudAppendBlob).UploadFromFile(path, accessCondition, options, operationContext);
     }
     else
     {
         throw new InvalidOperationException(string.Format("Invalid blob type: {0}", cloudBlob.BlobType));
     }
 }
예제 #10
0
        public void CloudBlobSoftDeleteNoSnapshotAPM()
        {
            CloudBlobContainer container = GetRandomContainerReference();

            try
            {
                //Enables a delete retention policy on the blob with 1 day of default retention days
                container.ServiceClient.EnableSoftDelete();
                container.Create();

                // Upload some data to the blob.
                MemoryStream    originalData = new MemoryStream(GetRandomBuffer(1024));
                CloudAppendBlob appendBlob   = container.GetAppendBlobReference(BlobName);
                appendBlob.CreateOrReplace();
                appendBlob.AppendBlock(originalData, null);


                CloudBlob blob = container.GetBlobReference(BlobName);
                Assert.IsFalse(blob.IsDeleted);

                IAsyncResult result;
                using (AutoResetEvent waitHandle = new AutoResetEvent(false))
                {
                    result = blob.BeginDelete(DeleteSnapshotsOption.None, null, null, null, ar => waitHandle.Set(), null);
                    waitHandle.WaitOne();
                    blob.EndDelete(result);
                }

                Assert.IsFalse(blob.Exists());

                int blobCount = 0;
                foreach (IListBlobItem item in container.ListBlobs(null, true, BlobListingDetails.All))
                {
                    CloudAppendBlob blobItem = (CloudAppendBlob)item;
                    Assert.AreEqual(blobItem.Name, BlobName);
                    Assert.IsTrue(blobItem.IsDeleted);
                    Assert.IsNotNull(blobItem.Properties.DeletedTime);
                    Assert.AreEqual(blobItem.Properties.RemainingDaysBeforePermanentDelete, 0);
                    blobCount++;
                }

                Assert.AreEqual(1, blobCount);

                using (AutoResetEvent waitHandle = new AutoResetEvent(false))
                {
                    result = blob.BeginUndelete(ar => waitHandle.Set(), null);
                    waitHandle.WaitOne();
                    blob.EndUndelete(result);
                }

                blob.FetchAttributes();
                Assert.IsFalse(blob.IsDeleted);
                Assert.IsNull(blob.Properties.DeletedTime);
                Assert.IsNull(blob.Properties.RemainingDaysBeforePermanentDelete);

                blobCount = 0;
                foreach (IListBlobItem item in container.ListBlobs(null, true, BlobListingDetails.All))
                {
                    CloudAppendBlob blobItem = (CloudAppendBlob)item;
                    Assert.AreEqual(blobItem.Name, BlobName);
                    Assert.IsFalse(blobItem.IsDeleted);
                    Assert.IsNull(blobItem.Properties.DeletedTime);
                    Assert.IsNull(blobItem.Properties.RemainingDaysBeforePermanentDelete);
                    blobCount++;
                }

                Assert.AreEqual(blobCount, 1);
            }
            finally
            {
                container.ServiceClient.DisableSoftDelete();
                container.DeleteIfExists();
            }
        }
        /// <summary>
        /// Upload File to blob with storage Client library API
        /// </summary>
        internal virtual async Task UploadBlobwithSdk(long taskId, IStorageBlobManagement localChannel, string filePath, StorageBlob.CloudBlob blob)
        {
            BlobClientOptions options = null;

            if (this.Force.IsPresent ||
                !blob.Exists() ||
                ShouldContinue(string.Format(Resources.OverwriteConfirmation, blob.Uri), null))
            {
                // Prepare blob Properties, MetaData, accessTier
                BlobHttpHeaders blobHttpHeaders       = CreateBlobHttpHeaders(BlobProperties);
                IDictionary <string, string> metadata = new Dictionary <string, string>();
                SetBlobMeta_Track2(metadata, this.Metadata);
                AccessTier?accesstier = GetAccessTier_Track2(this.standardBlobTier, this.pageBlobTier);

                //Prepare progress handler
                long             fileSize        = new FileInfo(ResolvedFileName).Length;
                string           activity        = String.Format(Resources.SendAzureBlobActivity, this.File, blob.Name, blob.Container.Name);
                string           status          = Resources.PrepareUploadingBlob;
                ProgressRecord   pr              = new ProgressRecord(OutputStream.GetProgressId(taskId), activity, status);
                IProgress <long> progressHandler = new Progress <long>((finishedBytes) =>
                {
                    if (pr != null)
                    {
                        // Size of the source file might be 0, when it is, directly treat the progress as 100 percent.
                        pr.PercentComplete   = 0 == fileSize ? 100 : (int)(finishedBytes * 100 / fileSize);
                        pr.StatusDescription = string.Format(CultureInfo.CurrentCulture, Resources.FileTransmitStatus, pr.PercentComplete);
                        Console.WriteLine(finishedBytes);
                        this.OutputStream.WriteProgress(pr);
                    }
                });

                using (FileStream stream = System.IO.File.OpenRead(ResolvedFileName))
                {
                    //block blob
                    if (string.Equals(blobType, BlockBlobType, StringComparison.InvariantCultureIgnoreCase))
                    {
                        BlobClient             blobClient     = GetTrack2BlobClient(blob, localChannel.StorageContext, options);
                        StorageTransferOptions trasnferOption = new StorageTransferOptions()
                        {
                            MaximumConcurrency = this.GetCmdletConcurrency()
                        };
                        BlobUploadOptions uploadOptions = new BlobUploadOptions();

                        uploadOptions.Metadata        = metadata;
                        uploadOptions.HttpHeaders     = blobHttpHeaders;
                        uploadOptions.Conditions      = this.BlobRequestConditions;
                        uploadOptions.AccessTier      = accesstier;
                        uploadOptions.ProgressHandler = progressHandler;
                        uploadOptions.TransferOptions = trasnferOption;

                        await blobClient.UploadAsync(stream, uploadOptions, CmdletCancellationToken).ConfigureAwait(false);
                    }
                    //Page or append blob
                    else if (string.Equals(blobType, PageBlobType, StringComparison.InvariantCultureIgnoreCase) ||
                             string.Equals(blobType, AppendBlobType, StringComparison.InvariantCultureIgnoreCase))
                    {
                        PageBlobClient   pageblobClient   = null;
                        AppendBlobClient appendblobClient = null;

                        //Create Blob
                        if (string.Equals(blobType, PageBlobType, StringComparison.InvariantCultureIgnoreCase)) //page
                        {
                            if (fileSize % 512 != 0)
                            {
                                throw new ArgumentException(String.Format("File size {0} Bytes is invalid for PageBlob, must be a multiple of 512 bytes.", fileSize.ToString()));
                            }
                            pageblobClient = GetTrack2PageBlobClient(blob, localChannel.StorageContext, options);
                            PageBlobCreateOptions createOptions = new PageBlobCreateOptions();

                            createOptions.Metadata    = metadata;
                            createOptions.HttpHeaders = blobHttpHeaders;
                            createOptions.Conditions  = this.PageBlobRequestConditions;
                            Response <BlobContentInfo> blobInfo = await pageblobClient.CreateAsync(fileSize, createOptions, CmdletCancellationToken).ConfigureAwait(false);
                        }
                        else //append
                        {
                            appendblobClient = GetTrack2AppendBlobClient(blob, localChannel.StorageContext, options);
                            AppendBlobCreateOptions createOptions = new AppendBlobCreateOptions();

                            createOptions.Metadata    = metadata;
                            createOptions.HttpHeaders = blobHttpHeaders;
                            createOptions.Conditions  = this.AppendBlobRequestConditions;
                            Response <BlobContentInfo> blobInfo = await appendblobClient.CreateAsync(createOptions, CmdletCancellationToken).ConfigureAwait(false);
                        }

                        // Upload blob content
                        byte[] uploadcache4MB = null;
                        byte[] uploadcache    = null;
                        progressHandler.Report(0);
                        long offset = 0;
                        while (offset < fileSize)
                        {
                            // Get chunk size and prepare cache
                            int chunksize = size4MB;
                            if (chunksize <= (fileSize - offset)) // Chunk size will be 4MB
                            {
                                if (uploadcache4MB == null)
                                {
                                    uploadcache4MB = new byte[size4MB];
                                }
                                uploadcache = uploadcache4MB;
                            }
                            else // last chunk can < 4MB
                            {
                                chunksize = (int)(fileSize - offset);
                                if (uploadcache4MB == null)
                                {
                                    uploadcache = new byte[chunksize];
                                }
                                else
                                {
                                    uploadcache = uploadcache4MB;
                                }
                            }

                            //Get content to upload for the chunk
                            int readoutcount = await stream.ReadAsync(uploadcache, 0, (int)chunksize).ConfigureAwait(false);

                            MemoryStream chunkContent = new MemoryStream(uploadcache, 0, readoutcount);

                            //Upload content
                            if (string.Equals(blobType, PageBlobType, StringComparison.InvariantCultureIgnoreCase)) //page
                            {
                                Response <PageInfo> pageInfo = await pageblobClient.UploadPagesAsync(chunkContent, offset, null, null, null, CmdletCancellationToken).ConfigureAwait(false);
                            }
                            else //append
                            {
                                Response <BlobAppendInfo> pageInfo = await appendblobClient.AppendBlockAsync(chunkContent, null, null, null, CmdletCancellationToken).ConfigureAwait(false);
                            }

                            // Update progress
                            offset += readoutcount;
                            progressHandler.Report(offset);
                        }
                        if (string.Equals(blobType, PageBlobType, StringComparison.InvariantCultureIgnoreCase) && accesstier != null)
                        {
                            await pageblobClient.SetAccessTierAsync(accesstier.Value, cancellationToken : CmdletCancellationToken).ConfigureAwait(false);
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException(string.Format(
                                                                CultureInfo.CurrentCulture,
                                                                Resources.InvalidBlobType,
                                                                blobType,
                                                                BlobName));
                    }
                }

                WriteCloudBlobObject(taskId, localChannel, blob);
            }
        }
        /// <summary>
        /// upload file to azure blob
        /// </summary>
        /// <param name="taskId">Task id</param>
        /// <param name="filePath">local file path</param>
        /// <param name="blob">destination azure blob object</param>
        internal virtual async Task Upload2Blob(long taskId, IStorageBlobManagement localChannel, string filePath, StorageBlob.CloudBlob blob)
        {
            string         activity = String.Format(Resources.SendAzureBlobActivity, filePath, blob.Name, blob.Container.Name);
            string         status   = Resources.PrepareUploadingBlob;
            ProgressRecord pr       = new ProgressRecord(OutputStream.GetProgressId(taskId), activity, status);

            FileInfo fileInfo = new FileInfo(filePath);

            DataMovementUserData data = new DataMovementUserData()
            {
                Data      = blob,
                TaskId    = taskId,
                Channel   = localChannel,
                Record    = pr,
                TotalSize = fileInfo.Length
            };

            SingleTransferContext transferContext = this.GetTransferContext(data);

#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
            transferContext.SetAttributesCallbackAsync = async(destination) =>
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
            {
                CloudBlob destBlob = destination as CloudBlob;
                SetBlobProperties(destBlob, this.BlobProperties);
                SetBlobMeta(destBlob, this.BlobMetadata);
            };

            await DataMovementTransferHelper.DoTransfer(() =>
            {
                return(this.TransferManager.UploadAsync(filePath,
                                                        blob,
                                                        null,
                                                        transferContext,
                                                        this.CmdletCancellationToken));
            },
                                                        data.Record,
                                                        this.OutputStream).ConfigureAwait(false);

            if (this.pageBlobTier != null || this.standardBlobTier != null)
            {
                await this.SetBlobTier(localChannel, blob, pageBlobTier, standardBlobTier).ConfigureAwait(false);
            }

            try
            {
                await localChannel.FetchBlobAttributesAsync(
                    blob,
                    AccessCondition.GenerateEmptyCondition(),
                    this.RequestOptions,
                    this.OperationContext,
                    this.CmdletCancellationToken).ConfigureAwait(false);
            }
            catch (StorageException e)
            {
                //Handle the limited read permission, and handle the upload with write only permission
                if (!e.IsNotFoundException() && !e.IsForbiddenException())
                {
                    throw;
                }
            }

            WriteCloudBlobObject(data.TaskId, localChannel, blob);
        }
예제 #13
0
        private static async Task TestAccessAsync(BlobContainerPublicAccessType accessType, CloudBlobContainer container, CloudBlob inputBlob)
        {
            StorageCredentials credentials = new StorageCredentials();

            container = new CloudBlobContainer(container.Uri, credentials);
            CloudPageBlob      blob    = new CloudPageBlob(inputBlob.Uri, credentials);
            OperationContext   context = new OperationContext();
            BlobRequestOptions options = new BlobRequestOptions();


            if (accessType.Equals(BlobContainerPublicAccessType.Container))
            {
                await blob.FetchAttributesAsync();

                await container.ListBlobsSegmentedAsync(null, true, BlobListingDetails.All, null, null, options, context);

                await container.FetchAttributesAsync();
            }
            else if (accessType.Equals(BlobContainerPublicAccessType.Blob))
            {
                await blob.FetchAttributesAsync();

                await TestHelper.ExpectedExceptionAsync(
                    async() => await container.ListBlobsSegmentedAsync(null, true, BlobListingDetails.All, null, null, options, context),
                    context,
                    "List blobs while public access does not allow for listing",
                    HttpStatusCode.NotFound);

                await TestHelper.ExpectedExceptionAsync(
                    async() => await container.FetchAttributesAsync(null, options, context),
                    context,
                    "Fetch container attributes while public access does not allow",
                    HttpStatusCode.NotFound);
            }
            else
            {
                await TestHelper.ExpectedExceptionAsync(
                    async() => await blob.FetchAttributesAsync(null, options, context),
                    context,
                    "Fetch blob attributes while public access does not allow",
                    HttpStatusCode.NotFound);

                await TestHelper.ExpectedExceptionAsync(
                    async() => await container.ListBlobsSegmentedAsync(null, true, BlobListingDetails.All, null, null, options, context),
                    context,
                    "List blobs while public access does not allow for listing",
                    HttpStatusCode.NotFound);

                await TestHelper.ExpectedExceptionAsync(
                    async() => await container.FetchAttributesAsync(null, options, context),
                    context,
                    "Fetch container attributes while public access does not allow",
                    HttpStatusCode.NotFound);
            }
        }
예제 #14
0
        private static async Task TestAccessAsync(string sasToken, SharedAccessBlobPermissions permissions, SharedAccessBlobHeaders headers, CloudBlobContainer container, CloudBlob blob, HttpStatusCode setBlobMetadataWhileSasExpectedStatusCode = HttpStatusCode.Forbidden, HttpStatusCode deleteBlobWhileSasExpectedStatusCode = HttpStatusCode.Forbidden, HttpStatusCode listBlobWhileSasExpectedStatusCode = HttpStatusCode.Forbidden)
        {
            OperationContext   operationContext = new OperationContext();
            StorageCredentials credentials      = string.IsNullOrEmpty(sasToken) ?
                                                  new StorageCredentials() :
                                                  new StorageCredentials(sasToken);

            if (container != null)
            {
                container = new CloudBlobContainer(container.Uri, credentials);
                if (blob.BlobType == BlobType.BlockBlob)
                {
                    blob = container.GetBlockBlobReference(blob.Name);
                }
                else
                {
                    blob = container.GetPageBlobReference(blob.Name);
                }
            }
            else
            {
                if (blob.BlobType == BlobType.BlockBlob)
                {
                    blob = new CloudBlockBlob(blob.Uri, credentials);
                }
                else
                {
#if !FACADE_NETCORE
                    blob = new CloudPageBlob(blob.Uri, credentials);
#else
                    blob = new CloudPageBlob(blob.Uri, null, credentials);
#endif
                }
            }

            if (container != null)
            {
                if ((permissions & SharedAccessBlobPermissions.List) == SharedAccessBlobPermissions.List)
                {
                    await container.ListBlobsSegmentedAsync(null);
                }
                else
                {
                    await TestHelper.ExpectedExceptionAsync(
                        async() => await container.ListBlobsSegmentedAsync(null, true, BlobListingDetails.None, null, null, null, operationContext),
                        operationContext,
                        "List blobs while SAS does not allow for listing",
                        listBlobWhileSasExpectedStatusCode);
                }
            }

            if ((permissions & SharedAccessBlobPermissions.Read) == SharedAccessBlobPermissions.Read)
            {
                await blob.FetchAttributesAsync();

                // Test headers
                if (headers != null)
                {
                    if (headers.CacheControl != null)
                    {
                        Assert.AreEqual(headers.CacheControl, blob.Properties.CacheControl);
                    }

                    if (headers.ContentDisposition != null)
                    {
                        Assert.AreEqual(headers.ContentDisposition, blob.Properties.ContentDisposition);
                    }

                    if (headers.ContentEncoding != null)
                    {
                        Assert.AreEqual(headers.ContentEncoding, blob.Properties.ContentEncoding);
                    }

                    if (headers.ContentLanguage != null)
                    {
                        Assert.AreEqual(headers.ContentLanguage, blob.Properties.ContentLanguage);
                    }

                    if (headers.ContentType != null)
                    {
                        Assert.AreEqual(headers.ContentType, blob.Properties.ContentType);
                    }
                }
            }
            else
            {
                await TestHelper.ExpectedExceptionAsync(
                    async() => await blob.FetchAttributesAsync(null, null, operationContext),
                    operationContext,
                    "Fetch blob attributes while SAS does not allow for reading",
                    HttpStatusCode.Forbidden);
            }

            if ((permissions & SharedAccessBlobPermissions.Write) == SharedAccessBlobPermissions.Write)
            {
                await blob.SetMetadataAsync();
            }
            else
            {
                await TestHelper.ExpectedExceptionAsync(
                    async() => await blob.SetMetadataAsync(null, null, operationContext),
                    operationContext,
                    "Set blob metadata while SAS does not allow for writing",
                    setBlobMetadataWhileSasExpectedStatusCode);
            }

            if ((permissions & SharedAccessBlobPermissions.Delete) == SharedAccessBlobPermissions.Delete)
            {
                await blob.DeleteAsync();
            }
            else
            {
                await TestHelper.ExpectedExceptionAsync(
                    async() => await blob.DeleteAsync(DeleteSnapshotsOption.None, null, null, operationContext),
                    operationContext,
                    "Delete blob while SAS does not allow for deleting",
                    deleteBlobWhileSasExpectedStatusCode);
            }
        }
예제 #15
0
        public void CloudBlobSoftDeleteSnapshotTask()
        {
            CloudBlobContainer container = GetRandomContainerReference();

            try
            {
                //Enables a delete retention policy on the blob with 1 day of default retention days
                container.ServiceClient.EnableSoftDelete();
                container.Create();

                // Upload some data to the blob.
                MemoryStream    originalData = new MemoryStream(GetRandomBuffer(1024));
                CloudAppendBlob appendBlob   = container.GetAppendBlobReference(BlobName);
                appendBlob.UploadFromStream(originalData);

                CloudBlob blob = container.GetBlobReference(BlobName);

                //create snapshot via api
                CloudBlob snapshot = blob.Snapshot();
                //create snapshot via write protection
                appendBlob.UploadFromStream(originalData);

                //we should have 2 snapshots 1 regular and 1 deleted: there is no way to get only the deleted snapshots but the below listing will get both snapshot types
                int blobCount            = 0;
                int deletedSnapshotCount = 0;
                int snapShotCount        = 0;
                BlobContinuationToken ct = null;

                do
                {
                    Task <BlobResultSegment> resultSegments = container.ListBlobsSegmentedAsync
                                                                  (null, true, BlobListingDetails.Snapshots | BlobListingDetails.Deleted, null, ct, null, null);
                    List <IListBlobItem> blobs = resultSegments.Result
                                                 .Results
                                                 .ToList();
                    ct = resultSegments.Result.ContinuationToken;

                    foreach (IListBlobItem item in blobs)
                    {
                        CloudAppendBlob blobItem = (CloudAppendBlob)item;
                        Assert.AreEqual(blobItem.Name, BlobName);
                        if (blobItem.IsSnapshot)
                        {
                            snapShotCount++;
                        }
                        if (blobItem.IsDeleted)
                        {
                            Assert.IsNotNull(blobItem.Properties.DeletedTime);
                            Assert.AreEqual(blobItem.Properties.RemainingDaysBeforePermanentDelete, 0);
                            deletedSnapshotCount++;
                        }
                        blobCount++;
                    }
                } while (ct != null);

                Assert.AreEqual(3, blobCount);
                Assert.AreEqual(deletedSnapshotCount, 1);
                Assert.AreEqual(snapShotCount, 2);

                blobCount = 0;
                ct        = null;
                do
                {
                    foreach (IListBlobItem item in container.ListBlobsSegmentedAsync
                                 (null, true, BlobListingDetails.Snapshots, null, ct, null, null)
                             .Result
                             .Results
                             .ToList())
                    {
                        CloudAppendBlob blobItem = (CloudAppendBlob)item;
                        Assert.AreEqual(blobItem.Name, BlobName);
                        Assert.IsFalse(blobItem.IsDeleted);
                        Assert.IsNull(blobItem.Properties.DeletedTime);
                        Assert.IsNull(blobItem.Properties.RemainingDaysBeforePermanentDelete);
                        blobCount++;
                    }
                } while (ct != null);

                Assert.AreEqual(blobCount, 2);

                //Delete Blob and snapshots
                blob.Delete(DeleteSnapshotsOption.IncludeSnapshots);
                Assert.IsFalse(blob.Exists());
                Assert.IsFalse(snapshot.Exists());

                blobCount = 0;
                ct        = null;
                do
                {
                    foreach (IListBlobItem item in container.ListBlobsSegmentedAsync
                                 (null, true, BlobListingDetails.All, null, ct, null, null)
                             .Result
                             .Results
                             .ToList())
                    {
                        CloudAppendBlob blobItem = (CloudAppendBlob)item;
                        Assert.AreEqual(blobItem.Name, BlobName);
                        Assert.IsTrue(blobItem.IsDeleted);
                        Assert.IsNotNull(blobItem.Properties.DeletedTime);
                        Assert.AreEqual(blobItem.Properties.RemainingDaysBeforePermanentDelete, 0);
                        blobCount++;
                    }
                }while(ct != null);

                Assert.AreEqual(blobCount, 3);

                blob.Undelete();

                blob.FetchAttributes();
                Assert.IsFalse(blob.IsDeleted);
                Assert.IsNull(blob.Properties.DeletedTime);
                Assert.IsNull(blob.Properties.RemainingDaysBeforePermanentDelete);

                blobCount = 0;
                ct        = null;
                do
                {
                    foreach (IListBlobItem item in container.ListBlobsSegmentedAsync
                                 (null, true, BlobListingDetails.All, null, ct, null, null)
                             .Result
                             .Results
                             .ToList())
                    {
                        CloudAppendBlob blobItem = (CloudAppendBlob)item;
                        Assert.AreEqual(blobItem.Name, BlobName);
                        Assert.IsFalse(blobItem.IsDeleted);
                        Assert.IsNull(blobItem.Properties.DeletedTime);
                        Assert.IsNull(blobItem.Properties.RemainingDaysBeforePermanentDelete);
                        blobCount++;
                    }
                }while(ct != null);

                Assert.AreEqual(blobCount, 3);
            }
            finally
            {
                container.ServiceClient.DisableSoftDelete();
                container.DeleteIfExists();
            }
        }
예제 #16
0
        public void CloudBlobSoftDeleteNoSnapshotTask()
        {
            CloudBlobContainer container = GetRandomContainerReference();

            try
            {
                //Enables a delete retention policy on the blob with 1 day of default retention days
                container.ServiceClient.EnableSoftDelete();
                container.CreateAsync().Wait();

                // Upload some data to the blob.
                MemoryStream    originalData = new MemoryStream(GetRandomBuffer(1024));
                CloudAppendBlob appendBlob   = container.GetAppendBlobReference(BlobName);
                appendBlob.CreateOrReplaceAsync().Wait();
                appendBlob.AppendBlockAsync(originalData, null).Wait();


                CloudBlob blob = container.GetBlobReference(BlobName);
                Assert.IsTrue(blob.ExistsAsync().Result);
                Assert.IsFalse(blob.IsDeleted);

                blob.DeleteAsync().Wait();
                Assert.IsFalse(blob.ExistsAsync().Result);

                int blobCount            = 0;
                BlobContinuationToken ct = null;
                do
                {
                    foreach (IListBlobItem item in container.ListBlobsSegmentedAsync
                                 (null, true, BlobListingDetails.All, null, ct, null, null)
                             .Result
                             .Results
                             .ToList())
                    {
                        CloudAppendBlob blobItem = (CloudAppendBlob)item;
                        Assert.AreEqual(blobItem.Name, BlobName);
                        Assert.IsTrue(blobItem.IsDeleted);
                        Assert.IsNotNull(blobItem.Properties.DeletedTime);
                        Assert.AreEqual(blobItem.Properties.RemainingDaysBeforePermanentDelete, 0);
                        blobCount++;
                    }
                } while (ct != null);

                Assert.AreEqual(blobCount, 1);

                blob.UndeleteAsync().Wait();

                blob.FetchAttributes();
                Assert.IsFalse(blob.IsDeleted);
                Assert.IsNull(blob.Properties.DeletedTime);
                Assert.IsNull(blob.Properties.RemainingDaysBeforePermanentDelete);

                blobCount = 0;
                ct        = null;
                do
                {
                    foreach (IListBlobItem item in container.ListBlobsSegmentedAsync
                                 (null, true, BlobListingDetails.All, null, ct, null, null)
                             .Result
                             .Results
                             .ToList())
                    {
                        CloudAppendBlob blobItem = (CloudAppendBlob)item;
                        Assert.AreEqual(blobItem.Name, BlobName);
                        Assert.IsFalse(blobItem.IsDeleted);
                        Assert.IsNull(blobItem.Properties.DeletedTime);
                        Assert.IsNull(blobItem.Properties.RemainingDaysBeforePermanentDelete);
                        blobCount++;
                    }
                } while (ct != null);
                Assert.AreEqual(blobCount, 1);
            }
            finally
            {
                container.ServiceClient.DisableSoftDelete();
                container.DeleteIfExists();
            }
        }
예제 #17
0
        public void CloudBlobSnapshot()
        {
            CloudBlobContainer container = GetRandomContainerReference();

            try
            {
                container.Create();

                // Upload some data to the blob.
                MemoryStream    originalData = new MemoryStream(GetRandomBuffer(1024));
                CloudAppendBlob appendBlob   = container.GetAppendBlobReference(BlobName);
                appendBlob.CreateOrReplace();
                appendBlob.AppendBlock(originalData, null);

                CloudBlob blob = container.GetBlobReference(BlobName);
                blob.FetchAttributes();
                Assert.IsFalse(blob.IsSnapshot);
                Assert.IsNull(blob.SnapshotTime, "Root blob has SnapshotTime set");
                Assert.IsFalse(blob.SnapshotQualifiedUri.Query.Contains("snapshot"));
                Assert.AreEqual(blob.Uri, blob.SnapshotQualifiedUri);

                CloudBlob snapshot1 = blob.Snapshot();
                Assert.AreEqual(blob.Properties.ETag, snapshot1.Properties.ETag);
                Assert.AreEqual(blob.Properties.LastModified, snapshot1.Properties.LastModified);
                Assert.IsTrue(snapshot1.IsSnapshot);
                Assert.IsNotNull(snapshot1.SnapshotTime, "Snapshot does not have SnapshotTime set");
                Assert.AreEqual(blob.Uri, snapshot1.Uri);
                Assert.AreNotEqual(blob.SnapshotQualifiedUri, snapshot1.SnapshotQualifiedUri);
                Assert.AreNotEqual(snapshot1.Uri, snapshot1.SnapshotQualifiedUri);
                Assert.IsTrue(snapshot1.SnapshotQualifiedUri.Query.Contains("snapshot"));

                CloudBlob snapshot2 = blob.Snapshot();
                Assert.IsTrue(snapshot2.SnapshotTime.Value > snapshot1.SnapshotTime.Value);

                snapshot1.FetchAttributes();
                snapshot2.FetchAttributes();
                blob.FetchAttributes();
                AssertAreEqual(snapshot1.Properties, blob.Properties, false);

                CloudBlob snapshot1Clone = new CloudBlob(new Uri(blob.Uri + "?snapshot=" + snapshot1.SnapshotTime.Value.ToString("O")), blob.ServiceClient.Credentials);
                Assert.IsNotNull(snapshot1Clone.SnapshotTime, "Snapshot clone does not have SnapshotTime set");
                Assert.AreEqual(snapshot1.SnapshotTime.Value, snapshot1Clone.SnapshotTime.Value);
                snapshot1Clone.FetchAttributes();
                AssertAreEqual(snapshot1.Properties, snapshot1Clone.Properties, false);

                // The query parser should not be case sensitive in detecting a snapshot in the query string
                CloudBlob snapshotParseVerifier = new CloudBlob(new Uri(blob.Uri + "?sNapshOt=" + snapshot1.SnapshotTime.Value.ToString("O")), blob.ServiceClient.Credentials);
                Assert.IsNotNull(snapshotParseVerifier.SnapshotTime, "Snapshot parse verifier did not successfully detect the snapshot time");
                Assert.AreEqual(snapshot1.SnapshotTime.Value, snapshotParseVerifier.SnapshotTime.Value);

                CloudBlob snapshotCopy = container.GetBlobReference("blob2");
                snapshotCopy.StartCopy(TestHelper.Defiddler(snapshot1.Uri));
                WaitForCopy(snapshotCopy);
                Assert.AreEqual(CopyStatus.Success, snapshotCopy.CopyState.Status);

                using (Stream snapshotStream = snapshot1.OpenRead())
                {
                    snapshotStream.Seek(0, SeekOrigin.End);
                    TestHelper.AssertStreamsAreEqual(originalData, snapshotStream);
                }

                //overwriting the blob and creating the 5th snapshot
                appendBlob.CreateOrReplace();
                blob.FetchAttributes();

                using (Stream snapshotStream = snapshot1.OpenRead())
                {
                    snapshotStream.Seek(0, SeekOrigin.End);
                    TestHelper.AssertStreamsAreEqual(originalData, snapshotStream);
                }

                List <IListBlobItem> blobs = container.ListBlobs(null, true, BlobListingDetails.All, null, null).ToList();
                Assert.AreEqual(4, blobs.Count);
                AssertAreEqual(snapshot1, (CloudBlob)blobs[0]);
                AssertAreEqual(snapshot2, (CloudBlob)blobs[1]);
                AssertAreEqual(blob, (CloudBlob)blobs[2]);
                AssertAreEqual(snapshotCopy, (CloudBlob)blobs[3]);
            }
            finally
            {
                container.DeleteIfExists();
            }
        }
예제 #18
0
        public void CloudBlobSoftDeleteNoSnapshot()
        {
            CloudBlobContainer container = GetRandomContainerReference();

            try
            {
                //Enables a delete retention policy on the blob with 1 day of default retention days
                container.ServiceClient.EnableSoftDelete();
                Shared.Protocol.ServiceProperties props = container.ServiceClient.GetServiceProperties();
                container.Create();
                // Upload some data to the blob.
                MemoryStream    originalData = new MemoryStream(GetRandomBuffer(1024));
                CloudAppendBlob appendBlob   = container.GetAppendBlobReference(BlobName);
                appendBlob.CreateOrReplace();
                appendBlob.AppendBlock(originalData, null);


                CloudBlob blob = container.GetBlobReference(BlobName);

                Assert.IsTrue(blob.Exists());
                Assert.IsFalse(blob.IsDeleted);

                blob.Delete();
                Assert.IsFalse(blob.Exists());

                int blobCount = 0;
                foreach (IListBlobItem item in container.ListBlobs(null, true, BlobListingDetails.Snapshots | BlobListingDetails.Deleted))
                {
                    CloudAppendBlob blobItem = (CloudAppendBlob)item;
                    Assert.AreEqual(blobItem.Name, BlobName);
                    Assert.IsTrue(blobItem.IsDeleted);
                    Assert.IsNotNull(blobItem.Properties.DeletedTime);
                    Assert.AreEqual(blobItem.Properties.RemainingDaysBeforePermanentDelete, 0);
                    blobCount++;
                }

                Assert.AreEqual(blobCount, 1);

                blob.Undelete();

                blob.FetchAttributes();
                Assert.IsFalse(blob.IsDeleted);
                Assert.IsNull(blob.Properties.DeletedTime);
                Assert.IsNull(blob.Properties.RemainingDaysBeforePermanentDelete);

                blobCount = 0;
                foreach (IListBlobItem item in container.ListBlobs(null, true, BlobListingDetails.All))
                {
                    CloudAppendBlob blobItem = (CloudAppendBlob)item;
                    Assert.AreEqual(blobItem.Name, BlobName);
                    Assert.IsFalse(blobItem.IsDeleted);
                    Assert.IsNull(blobItem.Properties.DeletedTime);
                    Assert.IsNull(blobItem.Properties.RemainingDaysBeforePermanentDelete);
                    blobCount++;
                }

                Assert.AreEqual(blobCount, 1);
            }
            finally
            {
                container.ServiceClient.DisableSoftDelete();
                container.DeleteIfExists();
            }
        }
예제 #19
0
        public async Task CloudBlobSnapshotTask()
        {
            CloudBlobContainer container = GetRandomContainerReference();

            try
            {
                await container.CreateAsync();

                MemoryStream    originalData = new MemoryStream(GetRandomBuffer(1024));
                CloudAppendBlob appendBlob   = container.GetAppendBlobReference(BlobName);
                await appendBlob.CreateOrReplaceAsync();

                await appendBlob.AppendBlockAsync(originalData, null);

                CloudBlob blob = container.GetBlobReference(BlobName);
                await blob.FetchAttributesAsync();

                CloudBlob snapshot1 = await blob.SnapshotAsync();

                Assert.AreEqual(blob.Properties.ETag, snapshot1.Properties.ETag);
                Assert.AreEqual(blob.Properties.LastModified, snapshot1.Properties.LastModified);
                Assert.IsTrue(snapshot1.IsSnapshot);
                Assert.IsNotNull(snapshot1.SnapshotTime, "Snapshot does not have SnapshotTime set");
                Assert.AreEqual(blob.Uri, snapshot1.Uri);
                Assert.AreNotEqual(blob.SnapshotQualifiedUri, snapshot1.SnapshotQualifiedUri);
                Assert.AreNotEqual(snapshot1.Uri, snapshot1.SnapshotQualifiedUri);
                Assert.IsTrue(snapshot1.SnapshotQualifiedUri.Query.Contains("snapshot"));

                CloudBlob snapshot2 = await blob.SnapshotAsync();

                Assert.IsTrue(snapshot2.SnapshotTime.Value > snapshot1.SnapshotTime.Value);

                await snapshot1.FetchAttributesAsync();

                await snapshot2.FetchAttributesAsync();

                await blob.FetchAttributesAsync();

                AssertAreEqual(snapshot1.Properties, blob.Properties);

                CloudBlob snapshot1Clone = new CloudBlob(new Uri(blob.Uri + "?snapshot=" + snapshot1.SnapshotTime.Value.ToString("O")), blob.ServiceClient.Credentials);
                Assert.IsNotNull(snapshot1Clone.SnapshotTime, "Snapshot clone does not have SnapshotTime set");
                Assert.AreEqual(snapshot1.SnapshotTime.Value, snapshot1Clone.SnapshotTime.Value);
                await snapshot1Clone.FetchAttributesAsync();

                AssertAreEqual(snapshot1.Properties, snapshot1Clone.Properties);

                CloudBlob snapshotCopy = container.GetBlobReference("blob2");
                await snapshotCopy.StartCopyAsync(snapshot1.Uri, null, null, null, null);
                await WaitForCopyAsync(snapshotCopy);

                Assert.AreEqual(CopyStatus.Success, snapshotCopy.CopyState.Status);

                using (Stream snapshotStream = await snapshot1.OpenReadAsync())
                {
                    snapshotStream.Seek(0, SeekOrigin.End);
                    TestHelper.AssertStreamsAreEqual(originalData, snapshotStream);
                }

                //overwriting will create another snapshot
                await appendBlob.CreateOrReplaceAsync();

                await blob.FetchAttributesAsync();

                using (Stream snapshotStream = await snapshot1.OpenReadAsync())
                {
                    snapshotStream.Seek(0, SeekOrigin.End);
                    TestHelper.AssertStreamsAreEqual(originalData, snapshotStream);
                }

                List <IListBlobItem> blobs =
                    (await container.ListBlobsSegmentedAsync(null, true, BlobListingDetails.All, null, null, null, null))
                    .Results
                    .ToList();
                Assert.AreEqual(5, blobs.Count);
                AssertAreEqual(snapshot1, (CloudBlob)blobs[0]);
                AssertAreEqual(snapshot2, (CloudBlob)blobs[1]);
                Assert.IsTrue(((CloudBlob)blobs[2]).IsDeleted);
                AssertAreEqual(blob, (CloudBlob)blobs[3]);
                AssertAreEqual(snapshotCopy, (CloudBlob)blobs[4]);
            }
            finally
            {
                await container.DeleteIfExistsAsync();
            }
        }
예제 #20
0
        public void CloudBlobSnapshotAPM()
        {
            CloudBlobContainer container = GetRandomContainerReference();

            try
            {
                container.Create();

                MemoryStream    originalData = new MemoryStream(GetRandomBuffer(1024));
                CloudAppendBlob appendBlob   = container.GetAppendBlobReference(BlobName);
                appendBlob.CreateOrReplace();
                appendBlob.AppendBlock(originalData, null);

                CloudBlob blob = container.GetBlobReference(BlobName);
                blob.FetchAttributes();
                IAsyncResult result;
                using (AutoResetEvent waitHandle = new AutoResetEvent(false))
                {
                    result = blob.BeginSnapshot(ar => waitHandle.Set(), null);
                    waitHandle.WaitOne();
                    CloudBlob snapshot1 = blob.EndSnapshot(result);
                    Assert.AreEqual(blob.Properties.ETag, snapshot1.Properties.ETag);
                    Assert.AreEqual(blob.Properties.LastModified, snapshot1.Properties.LastModified);
                    Assert.IsTrue(snapshot1.IsSnapshot);
                    Assert.IsNotNull(snapshot1.SnapshotTime, "Snapshot does not have SnapshotTime set");
                    Assert.AreEqual(blob.Uri, snapshot1.Uri);
                    Assert.AreNotEqual(blob.SnapshotQualifiedUri, snapshot1.SnapshotQualifiedUri);
                    Assert.AreNotEqual(snapshot1.Uri, snapshot1.SnapshotQualifiedUri);
                    Assert.IsTrue(snapshot1.SnapshotQualifiedUri.Query.Contains("snapshot"));

                    result = blob.BeginSnapshot(ar => waitHandle.Set(), null);
                    waitHandle.WaitOne();
                    CloudBlob snapshot2 = blob.EndSnapshot(result);
                    Assert.IsTrue(snapshot2.SnapshotTime.Value > snapshot1.SnapshotTime.Value);

                    snapshot1.FetchAttributes();
                    snapshot2.FetchAttributes();
                    blob.FetchAttributes();
                    AssertAreEqual(snapshot1.Properties, blob.Properties);

                    CloudBlob snapshotCopy = container.GetBlobReference("blob2");
                    result = snapshotCopy.BeginStartCopy(snapshot1.Uri, null, null, null, null, ar => waitHandle.Set(), null);
                    waitHandle.WaitOne();
                    snapshotCopy.EndStartCopy(result);
                    WaitForCopy(snapshotCopy);
                    Assert.AreEqual(CopyStatus.Success, snapshotCopy.CopyState.Status);

                    result = snapshot1.BeginOpenRead(ar => waitHandle.Set(), null);
                    waitHandle.WaitOne();
                    using (Stream snapshotStream = snapshot1.EndOpenRead(result))
                    {
                        snapshotStream.Seek(0, SeekOrigin.End);
                        TestHelper.AssertStreamsAreEqual(originalData, snapshotStream);
                    }

                    result = appendBlob.BeginCreateOrReplace(ar => waitHandle.Set(), null);
                    waitHandle.WaitOne();
                    appendBlob.EndCreateOrReplace(result);
                    result = blob.BeginFetchAttributes(ar => waitHandle.Set(), null);
                    waitHandle.WaitOne();
                    blob.EndFetchAttributes(result);

                    result = snapshot1.BeginOpenRead(ar => waitHandle.Set(), null);
                    waitHandle.WaitOne();
                    using (Stream snapshotStream = snapshot1.EndOpenRead(result))
                    {
                        snapshotStream.Seek(0, SeekOrigin.End);
                        TestHelper.AssertStreamsAreEqual(originalData, snapshotStream);
                    }

                    List <IListBlobItem> blobs = container.ListBlobs(null, true, BlobListingDetails.All, null, null).ToList();
                    Assert.AreEqual(4, blobs.Count);
                    AssertAreEqual(snapshot1, (CloudBlob)blobs[0]);
                    AssertAreEqual(snapshot2, (CloudBlob)blobs[1]);
                    AssertAreEqual(blob, (CloudBlob)blobs[2]);
                    AssertAreEqual(snapshotCopy, (CloudBlob)blobs[3]);
                }
            }
            finally
            {
                container.DeleteIfExists();
            }
        }
예제 #21
0
        public async Task CloudBlobSnapshotAsync()
        {
            CloudBlobContainer container = GetRandomContainerReference();

            try
            {
                await container.CreateAsync();

                MemoryStream   originalData = new MemoryStream(GetRandomBuffer(1024));
                CloudBlockBlob blockBlob    = container.GetBlockBlobReference(BlobName);
                await blockBlob.UploadFromStreamAsync(originalData);

                CloudBlob blob = container.GetBlobReference(BlobName);
                await blob.FetchAttributesAsync();

                Assert.IsFalse(blob.IsSnapshot);
                Assert.IsNull(blob.SnapshotTime, "Root blob has SnapshotTime set");
                Assert.IsFalse(blob.SnapshotQualifiedUri.Query.Contains("snapshot"));
                Assert.AreEqual(blob.Uri, blob.SnapshotQualifiedUri);

                CloudBlob snapshot1 = await blob.SnapshotAsync();

                Assert.AreEqual(blob.Properties.ETag, snapshot1.Properties.ETag);
                Assert.AreEqual(blob.Properties.LastModified, snapshot1.Properties.LastModified);
                Assert.IsTrue(snapshot1.IsSnapshot);
                Assert.IsNotNull(snapshot1.SnapshotTime, "Snapshot does not have SnapshotTime set");
                Assert.AreEqual(blob.Uri, snapshot1.Uri);
                Assert.AreNotEqual(blob.SnapshotQualifiedUri, snapshot1.SnapshotQualifiedUri);
                Assert.AreNotEqual(snapshot1.Uri, snapshot1.SnapshotQualifiedUri);
                Assert.IsTrue(snapshot1.SnapshotQualifiedUri.Query.Contains("snapshot"));

                CloudBlob snapshot2 = await blob.SnapshotAsync();

                Assert.IsTrue(snapshot2.SnapshotTime.Value > snapshot1.SnapshotTime.Value);

                await snapshot1.FetchAttributesAsync();

                await snapshot2.FetchAttributesAsync();

                await blob.FetchAttributesAsync();

                AssertAreEqual(snapshot1.Properties, blob.Properties);

                CloudBlob snapshot1Clone = new CloudBlob(new Uri(blob.Uri + "?snapshot=" + snapshot1.SnapshotTime.Value.ToString("O")), blob.ServiceClient.Credentials);
                Assert.IsNotNull(snapshot1Clone.SnapshotTime, "Snapshot clone does not have SnapshotTime set");
                Assert.AreEqual(snapshot1.SnapshotTime.Value, snapshot1Clone.SnapshotTime.Value);
                await snapshot1Clone.FetchAttributesAsync();

                AssertAreEqual(snapshot1.Properties, snapshot1Clone.Properties);

                // The query parser should not be case sensitive in detecting a snapshot in the query string
                CloudBlob snapshotParseVerifier = new CloudBlob(new Uri(blob.Uri + "?sNapshOt=" + snapshot1.SnapshotTime.Value.ToString("O")), blob.ServiceClient.Credentials);
                Assert.IsNotNull(snapshotParseVerifier.SnapshotTime, "Snapshot parse verifier did not successfully detect the snapshot time");
                Assert.AreEqual(snapshot1.SnapshotTime.Value, snapshotParseVerifier.SnapshotTime.Value);

                CloudBlob snapshotCopy = container.GetBlobReference("blob2");
                await snapshotCopy.StartCopyAsync(TestHelper.Defiddler(snapshot1.Uri));
                await WaitForCopyAsync(snapshotCopy);

                Assert.AreEqual(CopyStatus.Success, snapshotCopy.CopyState.Status);

                using (Stream snapshotStream = (await snapshot1.OpenReadAsync()))
                {
                    snapshotStream.Seek(0, SeekOrigin.End);
                    TestHelper.AssertStreamsAreEqual(originalData, snapshotStream);
                }

                await blockBlob.PutBlockListAsync(new List <string>());

                await blob.FetchAttributesAsync();

                using (Stream snapshotStream = (await snapshot1.OpenReadAsync()))
                {
                    snapshotStream.Seek(0, SeekOrigin.End);
                    TestHelper.AssertStreamsAreEqual(originalData, snapshotStream);
                }

                BlobResultSegment resultSegment = await container.ListBlobsSegmentedAsync(null, true, BlobListingDetails.All, null, null, null, null);

                List <IListBlobItem> blobs = resultSegment.Results.ToList();
                Assert.AreEqual(4, blobs.Count);
                AssertAreEqual(snapshot1, (CloudBlob)blobs[0]);
                AssertAreEqual(snapshot2, (CloudBlob)blobs[1]);
                AssertAreEqual(blob, (CloudBlob)blobs[2]);
                AssertAreEqual(snapshotCopy, (CloudBlob)blobs[3]);
            }
            finally
            {
                container.DeleteIfExistsAsync().Wait();
            }
        }