From c83f004ab2c90c8d95690abb31a1415c89616832 Mon Sep 17 00:00:00 2001 From: Logan Bussell Date: Wed, 26 Feb 2025 10:57:25 -0800 Subject: [PATCH 1/3] Add retries to SDK download in VerifyDotnetFolderContents test --- .../SdkImageTests.cs | 48 ++++++++++++++----- .../TestScenarios/WebScenario.cs | 1 - 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/tests/Microsoft.DotNet.Docker.Tests/SdkImageTests.cs b/tests/Microsoft.DotNet.Docker.Tests/SdkImageTests.cs index d0587e3af6..fd20be7f15 100644 --- a/tests/Microsoft.DotNet.Docker.Tests/SdkImageTests.cs +++ b/tests/Microsoft.DotNet.Docker.Tests/SdkImageTests.cs @@ -12,11 +12,14 @@ using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; +using Polly; +using Polly.Retry; using SharpCompress.Common; using SharpCompress.Readers; using Xunit; using Xunit.Abstractions; +#nullable enable namespace Microsoft.DotNet.Docker.Tests { [Trait("Category", "sdk")] @@ -25,6 +28,21 @@ public class SdkImageTests : ProductImageTests private static readonly Dictionary> s_sdkContentsCache = new Dictionary>(); + private static readonly RetryStrategyOptions s_downloadRetryStrategy = + new() + { + BackoffType = DelayBackoffType.Exponential, + MaxRetryAttempts = 4, + Delay = TimeSpan.FromSeconds(3), + }; + + private static readonly ResiliencePipeline s_sdkDownloadPipeline = + new ResiliencePipelineBuilder() + .AddRetry(s_downloadRetryStrategy) + .Build(); + + private static readonly HttpClient s_httpClient = CreateHttpClient(); + public SdkImageTests(ITestOutputHelper outputHelper) : base(outputHelper) { @@ -276,21 +294,14 @@ private async Task> GetExpectedSdkContentsAsync( string sdkUrl = GetSdkUrl(imageData); OutputHelper.WriteLine("Downloading SDK archive: " + sdkUrl); - if (!s_sdkContentsCache.TryGetValue(sdkUrl, out IEnumerable files)) + if (!s_sdkContentsCache.TryGetValue(sdkUrl, out IEnumerable? files)) { string sdkFile = Path.GetTempFileName(); - using HttpClient httpClient = new(); - - if (Config.IsInternal) + await s_sdkDownloadPipeline.ExecuteAsync(async cancellationToken => { - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( - "Basic", - Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", "", - Config.InternalAccessToken)))); - } - - await httpClient.DownloadFileAsync(new Uri(sdkUrl), sdkFile); + await s_httpClient.DownloadFileAsync(new Uri(sdkUrl), sdkFile); + }); files = EnumerateArchiveContents(sdkFile) .OrderBy(file => file.Path) @@ -424,5 +435,20 @@ private static string NormalizePath(string path) .ToLower(); } } + + private static HttpClient CreateHttpClient() + { + var client = new HttpClient(); + + if (Config.IsInternal) + { + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( + "Basic", + Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", "", + Config.InternalAccessToken)))); + }; + + return client; + } } } diff --git a/tests/Microsoft.DotNet.Docker.Tests/TestScenarios/WebScenario.cs b/tests/Microsoft.DotNet.Docker.Tests/TestScenarios/WebScenario.cs index a69d73a267..1f2f35c07a 100644 --- a/tests/Microsoft.DotNet.Docker.Tests/TestScenarios/WebScenario.cs +++ b/tests/Microsoft.DotNet.Docker.Tests/TestScenarios/WebScenario.cs @@ -5,7 +5,6 @@ using System.Net.Http.Headers; using System.Threading.Tasks; using Polly; -using Polly.CircuitBreaker; using Polly.Retry; using Xunit.Abstractions; From 8100146da8cd894bd75a70c8c500ded7152650b9 Mon Sep 17 00:00:00 2001 From: Logan Bussell Date: Wed, 26 Feb 2025 11:23:10 -0800 Subject: [PATCH 2/3] Fix nullable annotations --- .../SdkImageTests.cs | 47 ++----------------- 1 file changed, 5 insertions(+), 42 deletions(-) diff --git a/tests/Microsoft.DotNet.Docker.Tests/SdkImageTests.cs b/tests/Microsoft.DotNet.Docker.Tests/SdkImageTests.cs index fd20be7f15..546c882f66 100644 --- a/tests/Microsoft.DotNet.Docker.Tests/SdkImageTests.cs +++ b/tests/Microsoft.DotNet.Docker.Tests/SdkImageTests.cs @@ -54,8 +54,6 @@ public static IEnumerable GetImageData() { return TestData.GetImageData(DotNetImageRepo.SDK) .Where(imageData => !imageData.IsDistroless) - // Filter the image data down to the distinct SDK OSes - .Distinct(new SdkImageDataEqualityComparer()) .Select(imageData => new object[] { imageData }); } @@ -136,7 +134,7 @@ public void VerifyEnvironmentVariables(ProductImageData imageData) [MemberData(nameof(GetImageData))] public void VerifyPowerShellScenario_DefaultUser(ProductImageData imageData) { - PowerShellScenario_Execute(imageData, null); + PowerShellScenario_Execute(imageData, string.Empty); } [DotNetTheory] @@ -358,7 +356,7 @@ private string GetSdkUrl(ProductImageData imageData) return url; } - private void PowerShellScenario_Execute(ProductImageData imageData, string optionalArgs) + private void PowerShellScenario_Execute(ProductImageData imageData, string? optionalArgs = null) { string image = imageData.GetImage(DotNetImageRepo.SDK, DockerHelper); @@ -379,52 +377,17 @@ private void PowerShellScenario_Execute(ProductImageData imageData, string optio Assert.Equal(output, bool.TrueString, ignoreCase: true); } - private class SdkImageDataEqualityComparer : IEqualityComparer + private record SdkContentFileInfo { - public bool Equals([AllowNull] ProductImageData x, [AllowNull] ProductImageData y) - { - if (x is null && y is null) - { - return true; - } + public string Path { get; init; } + public string Sha512 { get; init; } - if (x is null && !(y is null)) - { - return false; - } - - if (!(x is null) && y is null) - { - return false; - } - - return x.VersionString == y.VersionString && - x.SdkOS == y.SdkOS && - x.Arch == y.Arch; - } - - public int GetHashCode([DisallowNull] ProductImageData obj) - { - return $"{obj.VersionString}-{obj.SdkOS}-{obj.Arch}".GetHashCode(); - } - } - - private class SdkContentFileInfo : IComparable - { public SdkContentFileInfo(string path, string sha512) { Path = NormalizePath(path); Sha512 = sha512.ToLower(); } - public string Path { get; } - public string Sha512 { get; } - - public int CompareTo([AllowNull] SdkContentFileInfo other) - { - return (Path + Sha512).CompareTo(other.Path + other.Sha512); - } - private static string NormalizePath(string path) { return path From e260b5eacb91f9eeaab44915990b8483366c61b6 Mon Sep 17 00:00:00 2001 From: Logan Bussell Date: Wed, 26 Feb 2025 11:31:13 -0800 Subject: [PATCH 3/3] Use consistent name --- tests/Microsoft.DotNet.Docker.Tests/SdkImageTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Microsoft.DotNet.Docker.Tests/SdkImageTests.cs b/tests/Microsoft.DotNet.Docker.Tests/SdkImageTests.cs index 546c882f66..325e6cc1c3 100644 --- a/tests/Microsoft.DotNet.Docker.Tests/SdkImageTests.cs +++ b/tests/Microsoft.DotNet.Docker.Tests/SdkImageTests.cs @@ -28,7 +28,7 @@ public class SdkImageTests : ProductImageTests private static readonly Dictionary> s_sdkContentsCache = new Dictionary>(); - private static readonly RetryStrategyOptions s_downloadRetryStrategy = + private static readonly RetryStrategyOptions s_sdkDownloadRetryStrategy = new() { BackoffType = DelayBackoffType.Exponential, @@ -38,7 +38,7 @@ public class SdkImageTests : ProductImageTests private static readonly ResiliencePipeline s_sdkDownloadPipeline = new ResiliencePipelineBuilder() - .AddRetry(s_downloadRetryStrategy) + .AddRetry(s_sdkDownloadRetryStrategy) .Build(); private static readonly HttpClient s_httpClient = CreateHttpClient();