< Summary

Class:Azure.Storage.Blobs.ChangeFeed.BlobChangeFeedExtensions
Assembly:Azure.Storage.Blobs.ChangeFeed
File(s):C:\Git\azure-sdk-for-net\sdk\storage\Azure.Storage.Blobs.ChangeFeed\src\BlobChangeFeedExtensions.cs
Covered lines:74
Uncovered lines:1
Coverable lines:75
Total lines:189
Line coverage:98.6% (74 of 75)
Covered branches:56
Total branches:64
Branch coverage:87.5% (56 of 64)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
GetChangeFeedClient(...)-100%100%
ToDateTimeOffset(...)-94.74%90%
RoundDownToNearestHour(...)-100%100%
RoundUpToNearestHour(...)-100%100%
RoundDownToNearestYear(...)-100%100%
GetSegmentsInYearInternal()-100%81.58%
MinDateTime(...)-100%100%
ComputeMD5(...)-100%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\storage\Azure.Storage.Blobs.ChangeFeed\src\BlobChangeFeedExtensions.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.Collections.Generic;
 6using System.Globalization;
 7using System.Threading;
 8using System.Threading.Tasks;
 9using Azure.Storage.Blobs.Models;
 10
 11namespace Azure.Storage.Blobs.ChangeFeed
 12{
 13    /// <summary>
 14    /// BlobChangeFeedExtensions.
 15    /// </summary>
 16    public static class BlobChangeFeedExtensions
 17    {
 18        /// <summary>
 19        /// GetChangeFeedClient.
 20        /// </summary>
 21        /// <param name="serviceClient"></param>
 22        /// <returns><see cref="BlobChangeFeedClient"/>.</returns>
 23        public static BlobChangeFeedClient GetChangeFeedClient(this BlobServiceClient serviceClient)
 24        {
 3225            return new BlobChangeFeedClient(serviceClient);
 26        }
 27
 28        /// <summary>
 29        /// Builds a DateTimeOffset from a segment path.
 30        /// </summary>
 31        internal static DateTimeOffset? ToDateTimeOffset(string segmentPath)
 32        {
 1026833            if (segmentPath == null)
 34            {
 435                return default;
 36            }
 1026437            string[] splitPath = segmentPath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
 38
 1026439            if (splitPath.Length < 3)
 40            {
 041                throw new ArgumentException($"{nameof(segmentPath)} is not a valid segment path.");
 42            }
 43
 1026444            return new DateTimeOffset(
 1026445                year: int.Parse(splitPath[2], CultureInfo.InvariantCulture),
 1026446                month: splitPath.Length >= 4
 1026447                    ? int.Parse(splitPath[3], CultureInfo.InvariantCulture)
 1026448                    : 1,
 1026449                day: splitPath.Length >= 5
 1026450                    ? int.Parse(splitPath[4], CultureInfo.InvariantCulture)
 1026451                    : 1,
 1026452                hour: splitPath.Length >= 6
 1026453                    ? int.Parse(splitPath[5], CultureInfo.InvariantCulture) / 100
 1026454                    : 0,
 1026455                minute: 0,
 1026456                second: 0,
 1026457                offset: TimeSpan.Zero);
 58        }
 59
 60        /// <summary>
 61        /// Rounds a DateTimeOffset down to the nearest hour.
 62        /// </summary>
 63        internal static DateTimeOffset? RoundDownToNearestHour(this DateTimeOffset? dateTimeOffset)
 64        {
 10065            if (dateTimeOffset == null)
 66            {
 867                return null;
 68            }
 69
 9270            return new DateTimeOffset(
 9271                year: dateTimeOffset.Value.Year,
 9272                month: dateTimeOffset.Value.Month,
 9273                day: dateTimeOffset.Value.Day,
 9274                hour: dateTimeOffset.Value.Hour,
 9275                minute: 0,
 9276                second: 0,
 9277                offset: dateTimeOffset.Value.Offset);
 78        }
 79
 80        /// <summary>
 81        /// Rounds a DateTimeOffset up to the nearest hour.
 82        /// </summary>
 83        internal static DateTimeOffset? RoundUpToNearestHour(this DateTimeOffset? dateTimeOffset)
 84        {
 6885            if (dateTimeOffset == null)
 86            {
 2487                return null;
 88            }
 89
 4490            if (dateTimeOffset.Value.Minute == 0 && dateTimeOffset.Value.Second == 0 && dateTimeOffset.Value.Millisecond
 91            {
 892                return dateTimeOffset;
 93            }
 94
 3695            DateTimeOffset? newDateTimeOffest = dateTimeOffset.RoundDownToNearestHour();
 96
 3697            return newDateTimeOffest.Value.AddHours(1);
 98        }
 99
 100        internal static DateTimeOffset? RoundDownToNearestYear(this DateTimeOffset? dateTimeOffset)
 101        {
 112102            if (dateTimeOffset == null)
 103            {
 4104                return null;
 105            }
 106
 108107            return new DateTimeOffset(
 108108                year: dateTimeOffset.Value.ToUniversalTime().Year,
 108109                month: 1,
 108110                day: 1,
 108111                hour: 0,
 108112                minute: 0,
 108113                second: 0,
 108114                offset: TimeSpan.Zero);
 115        }
 116
 117        internal static async Task<Queue<string>> GetSegmentsInYearInternal(
 118            BlobContainerClient containerClient,
 119            string yearPath,
 120            DateTimeOffset? startTime,
 121            DateTimeOffset? endTime,
 122            bool async,
 123            CancellationToken cancellationToken)
 124        {
 100125            List<string> list = new List<string>();
 126
 100127            if (async)
 128            {
 20008129                await foreach (BlobHierarchyItem blobHierarchyItem in containerClient.GetBlobsByHierarchyAsync(
 88130                    prefix: yearPath,
 88131                    cancellationToken: cancellationToken)
 88132                    .ConfigureAwait(false))
 133                {
 9916134                    if (blobHierarchyItem.IsPrefix)
 135                        continue;
 136
 9916137                    DateTimeOffset segmentDateTime = ToDateTimeOffset(blobHierarchyItem.Blob.Name).Value;
 9916138                    if (startTime.HasValue && segmentDateTime < startTime
 9916139                        || endTime.HasValue && segmentDateTime > endTime)
 140                        continue;
 141
 182142                    list.Add(blobHierarchyItem.Blob.Name);
 143                }
 144            }
 145            else
 146            {
 112147                foreach (BlobHierarchyItem blobHierarchyItem in containerClient.GetBlobsByHierarchy(
 12148                    prefix: yearPath,
 12149                    cancellationToken: cancellationToken))
 150                {
 44151                    if (blobHierarchyItem.IsPrefix)
 152                        continue;
 153
 44154                    DateTimeOffset segmentDateTime = ToDateTimeOffset(blobHierarchyItem.Blob.Name).Value;
 44155                    if (startTime.HasValue && segmentDateTime < startTime
 44156                        || endTime.HasValue && segmentDateTime > endTime)
 157                        continue;
 158
 34159                    list.Add(blobHierarchyItem.Blob.Name);
 160                }
 161            }
 162
 100163            return new Queue<string>(list);
 100164        }
 165
 166        internal static DateTimeOffset MinDateTime(DateTimeOffset lastConsumable, DateTimeOffset? endDate)
 167        {
 92168            if (endDate.HasValue && endDate.Value < lastConsumable)
 169            {
 60170                return endDate.Value;
 171            }
 172
 32173            return lastConsumable;
 174        }
 175
 176        internal static string ComputeMD5(string input)
 177        {
 178#pragma warning disable CA5351 // Do Not Use Broken Cryptographic Algorithms
 192179            using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
 180#pragma warning restore CA5351 // Do Not Use Broken Cryptographic Algorithms
 181            {
 192182                byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
 192183                byte[] hashBytes = md5.ComputeHash(inputBytes);
 184
 192185                return Convert.ToBase64String(hashBytes);
 186            }
 192187        }
 188    }
 189}