/
githubmirror
/
aspnetcore
Обзор
Документация
Войти
/
githubmirror
/
aspnetcore
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Mvc/test/Mvc.FunctionalTests/Infrastructure/ResourceFile.cs
264 строки
12 KB
Alexander Köplinger
Upgrade xunit version to 2.9.0 (#57303)
23 авг 2024, 20:27
Не верифицирован
23 авг 2024, 20:27
9209724
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Globalization; using System.Reflection; using System.Text; using Microsoft.AspNetCore.InternalTesting; namespace Microsoft.AspNetCore.Mvc; /// <summary> /// Reader and, if GenerateBaselines is set to true, writer for files compiled into an assembly as resources. /// </summary> /// <remarks>Inspired by Razor's BaselineWriter and TestFile test classes.</remarks> public static class ResourceFile { /// <summary> /// Set this to true to cause baseline files to becompiled into an assembly as resources. /// </summary> public static readonly bool GenerateBaselines = false; private static readonly object writeLock = new object(); public static void UpdateOrVerify(Assembly assembly, string outputFile, string expectedContent, string responseContent, string token = null) { if (GenerateBaselines) { // Reverse usual substitution and insert a format item into the new file content. if (token != null) { responseContent = responseContent.Replace(token, "{0}"); } UpdateFile(assembly, outputFile, expectedContent, responseContent); } else { if (token != null) { expectedContent = string.Format(CultureInfo.InvariantCulture, expectedContent, token); } Assert.Equal(expectedContent, responseContent, ignoreLineEndingDifferences: true); } } /// <summary> /// Return <see cref="Stream"/> for <paramref name="resourceName"/> from <paramref name="assembly"/>'s /// manifest. /// </summary> /// <param name="assembly">The <see cref="Assembly"/> containing <paramref name="resourceName"/>.</param> /// <param name="resourceName"> /// Name of the manifest resource in <paramref name="assembly"/>. A path relative to the test project /// directory. /// </param> /// <param name="sourceFile"> /// If <c>true</c> <paramref name="resourceName"/> is used as a source file and must exist. Otherwise /// <paramref name="resourceName"/> is an output file and, if <c>GENERATE_BASELINES</c> is defined, it will /// soon be generated if missing. /// </param> /// <returns> /// <see cref="Stream"/> for <paramref name="resourceName"/> from <paramref name="assembly"/>'s /// manifest. <c>null</c> if <c>GENERATE_BASELINES</c> is defined, <paramref name="sourceFile"/> is /// <c>false</c>, and <paramref name="resourceName"/> is not found in <paramref name="assembly"/>. /// </returns> /// <exception cref="Xunit.Sdk.TrueException"> /// Thrown if <c>GENERATE_BASELINES</c> is not defined or <paramref name="sourceFile"/> is <c>true</c> and /// <paramref name="resourceName"/> is not found in <paramref name="assembly"/>. /// </exception> public static Stream GetResourceStream(Assembly assembly, string resourceName, bool sourceFile) { var fullName = $"{ assembly.GetName().Name }.{ resourceName.Replace('/', '.') }"; if (!Exists(assembly, fullName)) { if (GenerateBaselines) { if (sourceFile) { // Even when generating baselines, a missing source file is a serious problem. Assert.Fail($"Manifest resource: { fullName } not found."); } } else { // When not generating baselines, a missing source or output file is always an error. Assert.Fail($"Manifest resource '{ fullName }' not found."); } return null; } var stream = assembly.GetManifestResourceStream(fullName); if (sourceFile) { // Normalize line endings to '\r\n' (CRLF). This removes core.autocrlf, core.eol, core.safecrlf, and // .gitattributes from the equation and treats "\r\n" and "\n" as equivalent. Does not handle // some line endings like "\r" but otherwise ensures checksums and line mappings are consistent. string text; using (var streamReader = new StreamReader(stream)) { text = streamReader.ReadToEnd().Replace("\r", "").Replace("\n", "\r\n"); } var bytes = Encoding.UTF8.GetBytes(text); stream = new MemoryStream(bytes); } return stream; } /// <summary> /// Return <see cref="string"/> content of <paramref name="resourceName"/> from <paramref name="assembly"/>'s /// manifest. /// </summary> /// <param name="assembly">The <see cref="Assembly"/> containing <paramref name="resourceName"/>.</param> /// <param name="resourceName"> /// Name of the manifest resource in <paramref name="assembly"/>. A path relative to the test project /// directory. /// </param> /// <param name="sourceFile"> /// If <c>true</c> <paramref name="resourceName"/> is used as a source file and must exist. Otherwise /// <paramref name="resourceName"/> is an output file and, if <c>GENERATE_BASELINES</c> is defined, it will /// soon be generated if missing. /// </param> /// <returns> /// A <see cref="Task{string}"/> which on completion returns the <see cref="string"/> content of /// <paramref name="resourceName"/> from <paramref name="assembly"/>'s manifest. <c>null</c> if /// <c>GENERATE_BASELINES</c> is defined, <paramref name="sourceFile"/> is <c>false</c>, and /// <paramref name="resourceName"/> is not found in <paramref name="assembly"/>. /// </returns> /// <exception cref="Xunit.Sdk.TrueException"> /// Thrown if <c>GENERATE_BASELINES</c> is not defined or <paramref name="sourceFile"/> is <c>true</c> and /// <paramref name="resourceName"/> is not found in <paramref name="assembly"/>. /// </exception> /// <remarks>Normalizes line endings to <see cref="Environment.NewLine"/>.</remarks> public static async Task<string> ReadResourceAsync(Assembly assembly, string resourceName, bool sourceFile) { using (var stream = GetResourceStream(assembly, resourceName, sourceFile)) { if (stream == null) { return null; } using (var streamReader = new StreamReader(stream)) { return await streamReader.ReadToEndAsync(); } } } /// <summary> /// Return <see cref="string"/> content of <paramref name="resourceName"/> from <paramref name="assembly"/>'s /// manifest. /// </summary> /// <param name="assembly">The <see cref="Assembly"/> containing <paramref name="resourceName"/>.</param> /// <param name="resourceName"> /// Name of the manifest resource in <paramref name="assembly"/>. A path relative to the test project /// directory. /// </param> /// <param name="sourceFile"> /// If <c>true</c> <paramref name="resourceName"/> is used as a source file and must exist. Otherwise /// <paramref name="resourceName"/> is an output file and, if <c>GENERATE_BASELINES</c> is defined, it will /// soon be generated if missing. /// </param> /// <returns> /// The <see cref="string"/> content of <paramref name="resourceName"/> from <paramref name="assembly"/>'s /// manifest. <c>null</c> if <c>GENERATE_BASELINES</c> is defined, <paramref name="sourceFile"/> is /// <c>false</c>, and <paramref name="resourceName"/> is not found in <paramref name="assembly"/>. /// </returns> /// <exception cref="Xunit.Sdk.TrueException"> /// Thrown if <c>GENERATE_BASELINES</c> is not defined or <paramref name="sourceFile"/> is <c>true</c> and /// <paramref name="resourceName"/> is not found in <paramref name="assembly"/>. /// </exception> /// <remarks>Normalizes line endings to <see cref="Environment.NewLine"/>.</remarks> public static string ReadResource(Assembly assembly, string resourceName, bool sourceFile) { using (var stream = GetResourceStream(assembly, resourceName, sourceFile)) { if (stream == null) { return null; } using (var streamReader = new StreamReader(stream)) { return streamReader.ReadToEnd(); } } } /// <summary> /// Write <paramref name="content"/> to file that will become <paramref name="resourceName"/> in /// <paramref name="assembly"/> the next time the project is built. Does nothing if /// <paramref name="previousContent"/> and <paramref name="content"/> already match. /// </summary> /// <param name="assembly">The <see cref="Assembly"/> containing <paramref name="resourceName"/>.</param> /// <param name="resourceName"> /// Name of the manifest resource in <paramref name="assembly"/>. A path relative to the test project /// directory. /// </param> /// <param name="previousContent"> /// Current content of <paramref name="resourceName"/>. <c>null</c> if <paramref name="resourceName"/> does /// not currently exist in <paramref name="assembly"/>. /// </param> /// <param name="content"> /// New content of <paramref name="resourceName"/> in <paramref name="assembly"/>. /// </param> private static void UpdateFile(Assembly assembly, string resourceName, string previousContent, string content) { if (!GenerateBaselines) { throw new NotSupportedException("Calling UpdateFile is not supported when GenerateBaselines=false"); } // Normalize line endings to '\r\n' for comparison. This removes Environment.NewLine from the equation. Not // worth updating files just because we generate baselines on a different system. var normalizedPreviousContent = previousContent?.Replace("\r", "").Replace("\n", "\r\n"); var normalizedContent = content.Replace("\r", "").Replace("\n", "\r\n"); if (!string.Equals(normalizedPreviousContent, normalizedContent, StringComparison.Ordinal)) { // The build system compiles every file under the resources folder as a resource available at runtime // with the same name as the file name. Need to update this file on disc. // https://github.com/dotnet/aspnetcore/issues/10423 #pragma warning disable 0618 var solutionPath = TestPathUtilities.GetSolutionRootDirectory("Mvc"); #pragma warning restore 0618 var projectPath = Path.Combine(solutionPath, "test", assembly.GetName().Name); var fullPath = Path.Combine(projectPath, resourceName); WriteFile(fullPath, content); } } private static bool Exists(Assembly assembly, string fullName) { var resourceNames = assembly.GetManifestResourceNames(); foreach (var resourceName in resourceNames) { // Resource names are case-sensitive. if (string.Equals(fullName, resourceName, StringComparison.Ordinal)) { return true; } } return false; } private static void WriteFile(string fullPath, string content) { // Serialize writes to minimize contention for file handles and directory access. lock (writeLock) { // Write content to the file, creating it if necessary. using (var stream = File.Open(fullPath, FileMode.Create, FileAccess.Write)) { using (var writer = new StreamWriter(stream)) { writer.Write(content); } } } } }