From 563a488f3b38395d0a2c8db8e5e40e99d190825a Mon Sep 17 00:00:00 2001 From: Mikael Mengistu Date: Tue, 5 Mar 2019 15:50:25 -0800 Subject: [PATCH] Add baseline test (#7988) - mostly matching what's in `release/2.2` --- .../Framework.UnitTests/ConsoleReporter.cs | 71 +++++++++++++++++++ .../Framework.UnitTests.csproj | 9 +++ .../Framework.UnitTests/RetryHelper.cs | 65 +++++++++++++++++ .../Framework.UnitTests/SharedFxTests.cs | 66 +++++++++++++++++ src/Framework/Framework.UnitTests/TestData.cs | 2 + 5 files changed, 213 insertions(+) create mode 100644 src/Framework/Framework.UnitTests/ConsoleReporter.cs create mode 100644 src/Framework/Framework.UnitTests/RetryHelper.cs diff --git a/src/Framework/Framework.UnitTests/ConsoleReporter.cs b/src/Framework/Framework.UnitTests/ConsoleReporter.cs new file mode 100644 index 0000000000..190e805dc2 --- /dev/null +++ b/src/Framework/Framework.UnitTests/ConsoleReporter.cs @@ -0,0 +1,71 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using McMaster.Extensions.CommandLineUtils; + +namespace Microsoft.Extensions.Tools.Internal +{ + public class ConsoleReporter : IReporter + { + private object _writeLock = new object(); + + public ConsoleReporter(IConsole console) + : this(console, verbose: false, quiet: false) + { } + + public ConsoleReporter(IConsole console, bool verbose, bool quiet) + { + Console = console; + IsVerbose = verbose; + IsQuiet = quiet; + } + + protected IConsole Console { get; } + public bool IsVerbose { get; } + public bool IsQuiet { get; } + + protected virtual void WriteLine(TextWriter writer, string message, ConsoleColor? color) + { + lock (_writeLock) + { + if (color.HasValue) + { + Console.ForegroundColor = color.Value; + } + + writer.WriteLine(message); + + if (color.HasValue) + { + Console.ResetColor(); + } + } + } + + public virtual void Error(string message) + => WriteLine(Console.Error, message, ConsoleColor.Red); + public virtual void Warn(string message) + => WriteLine(Console.Out, message, ConsoleColor.Yellow); + + public virtual void Output(string message) + { + if (IsQuiet) + { + return; + } + WriteLine(Console.Out, message, color: null); + } + + public virtual void Verbose(string message) + { + if (!IsVerbose) + { + return; + } + + WriteLine(Console.Out, message, ConsoleColor.DarkGray); + } + } +} diff --git a/src/Framework/Framework.UnitTests/Framework.UnitTests.csproj b/src/Framework/Framework.UnitTests/Framework.UnitTests.csproj index f1eb186b64..c69b8ddbd1 100644 --- a/src/Framework/Framework.UnitTests/Framework.UnitTests.csproj +++ b/src/Framework/Framework.UnitTests/Framework.UnitTests.csproj @@ -23,10 +23,15 @@ <_Parameter1>MicrosoftNETCoreAppPackageVersion <_Parameter2>$(RuntimeFrameworkVersion) + + <_Parameter1>PreviousAspNetCoreReleaseVersion + <_Parameter2>$(PreviousAspNetCoreReleaseVersion) + + @@ -42,6 +47,10 @@ <_Parameter1>SharedFxMetadataOutput:%(_ResolvedFrameworkReference.SharedFxName) <_Parameter2>%(_ResolvedFrameworkReference.MetadataOutputPath) + + <_Parameter1>RuntimeAssetsOutputPath:%(_ResolvedFrameworkReference.SharedFxName) + <_Parameter2>%(_ResolvedFrameworkReference.RuntimeAssetsOutputPath) + diff --git a/src/Framework/Framework.UnitTests/RetryHelper.cs b/src/Framework/Framework.UnitTests/RetryHelper.cs new file mode 100644 index 0000000000..2d92113e36 --- /dev/null +++ b/src/Framework/Framework.UnitTests/RetryHelper.cs @@ -0,0 +1,65 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Threading.Tasks; +using McMaster.Extensions.CommandLineUtils; + +namespace TriageBuildFailures +{ + internal static class RetryHelpers + { + /// + /// Constrain the exponential back-off to this many minutes. + /// + private const int MaxRetryMinutes = 15; + + private static int TotalRetriesUsed; + + public static int GetTotalRetriesUsed() + { + return TotalRetriesUsed; + } + + public static async Task RetryAsync(Func action, IReporter reporter) + { + await RetryAsync( + async () => + { + await action(); + return null; + }, + reporter); + } + + public static async Task RetryAsync(Func> action, IReporter reporter) + { + Exception firstException = null; + + var retriesRemaining = 10; + var retryDelayInMinutes = 1; + + while (retriesRemaining > 0) + { + try + { + return await action(); + } + catch (Exception e) + { + firstException = firstException ?? e; + reporter.Output($"Exception thrown! {e.Message}"); + reporter.Output($"Waiting {retryDelayInMinutes} minute(s) to retry ({retriesRemaining} left)..."); + await Task.Delay(retryDelayInMinutes * 60 * 1000); + + // Do exponential back-off, but limit it (1, 2, 4, 8, 15, 15, 15, ...) + // With MaxRetryMinutes=15 and MaxRetries=10, this will delay a maximum of 105 minutes + retryDelayInMinutes = Math.Min(2 * retryDelayInMinutes, MaxRetryMinutes); + retriesRemaining--; + TotalRetriesUsed++; + } + } + throw new InvalidOperationException("Max exception retries reached, giving up.", firstException); + } + } +} diff --git a/src/Framework/Framework.UnitTests/SharedFxTests.cs b/src/Framework/Framework.UnitTests/SharedFxTests.cs index 28deb9a2ad..a541302b83 100644 --- a/src/Framework/Framework.UnitTests/SharedFxTests.cs +++ b/src/Framework/Framework.UnitTests/SharedFxTests.cs @@ -1,14 +1,80 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; +using System.Collections.Generic; using System.IO; +using System.IO.Compression; +using System.Net; +using System.Reflection; +using System.Threading.Tasks; +using McMaster.Extensions.CommandLineUtils; using Newtonsoft.Json.Linq; +using TriageBuildFailures; using Xunit; namespace Microsoft.AspNetCore { public class SharedFxTests { + [Theory] + [MemberData(nameof(GetSharedFxConfig))] + public async Task BaselineTest(SharedFxConfig config) + { + var previousVersion = TestData.GetPreviousAspNetCoreReleaseVersion(); + var url = new Uri($"https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/" + previousVersion + "/aspnetcore-runtime-internal-" + previousVersion + "-win-x64.zip"); + var zipName = "assemblies.zip"; + var nugetAssemblyVersions = new Dictionary(); + var dir = TestData.GetTestDataValue($"RuntimeAssetsOutputPath:{config.Name}"); + + using (var testClient = new WebClient()) + { + var reporter = new ConsoleReporter(PhysicalConsole.Singleton); + await RetryHelpers.RetryAsync(async () => await testClient.DownloadFileTaskAsync(url, zipName), reporter); + } + + var zipPath = Path.Combine(AppContext.BaseDirectory, zipName); + var tempDirectoryPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + try + { + Directory.CreateDirectory(tempDirectoryPath); + ZipFile.ExtractToDirectory(zipPath, tempDirectoryPath); + var nugetAssembliesPath = Path.Combine(tempDirectoryPath, "shared", config.Name, previousVersion); + + + var files = Directory.GetFiles(nugetAssembliesPath, "*.dll"); + foreach (var file in files) + { + try + { + var assemblyVersion = AssemblyName.GetAssemblyName(file).Version; + var dllName = Path.GetFileName(file); + nugetAssemblyVersions.Add(dllName, assemblyVersion); + } + catch (BadImageFormatException) { } + } + + files = Directory.GetFiles(dir, "*.dll"); + + Assert.All(files, file => + { + try + { + var localAssemblyVersion = AssemblyName.GetAssemblyName(file).Version; + var dllName = Path.GetFileName(file); + Assert.Contains(dllName, nugetAssemblyVersions.Keys); + Assert.InRange(localAssemblyVersion.CompareTo(nugetAssemblyVersions[dllName]), 0, int.MaxValue); + } + catch (BadImageFormatException) { } + + }); + } + finally + { + Directory.Delete(tempDirectoryPath, true); + } + } + [Theory] [MemberData(nameof(GetSharedFxConfig))] public void ItContainsValidRuntimeConfigFile(SharedFxConfig config) diff --git a/src/Framework/Framework.UnitTests/TestData.cs b/src/Framework/Framework.UnitTests/TestData.cs index a33613aff8..0814904168 100644 --- a/src/Framework/Framework.UnitTests/TestData.cs +++ b/src/Framework/Framework.UnitTests/TestData.cs @@ -10,6 +10,8 @@ namespace Microsoft.AspNetCore { public static string GetPackageVersion() => GetTestDataValue("PackageVersion"); + public static string GetPreviousAspNetCoreReleaseVersion() => GetTestDataValue("PreviousAspNetCoreReleaseVersion"); + public static string GetMicrosoftNETCoreAppPackageVersion() => GetTestDataValue("MicrosoftNETCoreAppPackageVersion"); public static string GetRepositoryCommit() => GetTestDataValue("RepositoryCommit");