Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 56 additions & 56 deletions .github/ISSUE_TEMPLATE/30_api_proposal.md
Original file line number Diff line number Diff line change
@@ -1,56 +1,56 @@
---
name: API proposal
about: Propose a change to the public API surface
title: ''
labels: api-suggestion
assignees: ''
---
## Background and Motivation
<!--
We welcome API proposals! We have a process to evaluate the value and shape of new API. There is an overview of our process [here](https://github.com/dotnet/aspnetcore/blob/main/docs/APIReviewProcess.md). This template will help us gather the information we need to start the review process.
First, please describe the purpose and value of the new API here.
-->
## Proposed API
<!--
Please provide the specific public API signature diff that you are proposing. For example:
```diff
namespace Microsoft.AspNetCore.Http
{
public static class HttpResponseWritingExtensions
{
+ public Task WriteAsync(this HttpResponse response, StringBuilder builder);
}
}
```
You may find the [Framework Design Guidelines](https://github.com/dotnet/runtime/blob/master/docs/coding-guidelines/framework-design-guidelines-digest.md) helpful.
-->
## Usage Examples
<!--
Please provide code examples that highlight how the proposed API additions are meant to be consumed.
This will help suggest whether the API has the right shape to be functional, performant and useable.
You can use code blocks like this:
``` C#
// some lines of code here
```
-->
## Alternative Designs
<!--
Were there other options you considered, such as alternative API shapes?
How does this compare to analogous APIs in other ecosystems and libraries?
-->
## Risks
<!--
Please mention any risks that to your knowledge the API proposal might entail, such as breaking changes, performance regressions, etc.
-->
---
name: API proposal
about: Propose a change to the public API surface
title: ''
labels: api-suggestion
assignees: ''

---

## Background and Motivation

<!--
We welcome API proposals! We have a process to evaluate the value and shape of new API. There is an overview of our process [here](https://github.com/dotnet/aspnetcore/blob/main/docs/APIReviewProcess.md). This template will help us gather the information we need to start the review process.
First, please describe the purpose and value of the new API here.
-->

## Proposed API

<!--
Please provide the specific public API signature diff that you are proposing. For example:
```diff
namespace Microsoft.AspNetCore.Http
{
public static class HttpResponseWritingExtensions
{
+ public Task WriteAsync(this HttpResponse response, StringBuilder builder);
}
}
```
You may find the [Framework Design Guidelines](https://github.com/dotnet/runtime/blob/master/docs/coding-guidelines/framework-design-guidelines-digest.md) helpful.
-->

## Usage Examples

<!--
Please provide code examples that highlight how the proposed API additions are meant to be consumed.
This will help suggest whether the API has the right shape to be functional, performant and useable.
You can use code blocks like this:
``` C#
// some lines of code here
```
-->

## Alternative Designs

<!--
Were there other options you considered, such as alternative API shapes?
How does this compare to analogous APIs in other ecosystems and libraries?
-->

## Risks

<!--
Please mention any risks that to your knowledge the API proposal might entail, such as breaking changes, performance regressions, etc.
-->

10 changes: 10 additions & 0 deletions src/Testing/Testing.slnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"solution": {
"path": "..\\..\\AspNetCore.sln",
"projects": [
"src\\Analyzers\\Microsoft.AspNetCore.Analyzer.Testing\\src\\Microsoft.AspNetCore.Analyzer.Testing.csproj",
"src\\Testing\\src\\Microsoft.AspNetCore.Testing.csproj",
"src\\Testing\\test\\Microsoft.AspNetCore.Testing.Tests.csproj"
]
}
}
8 changes: 3 additions & 5 deletions src/Testing/src/AssemblyTestLog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,6 @@ public IServiceProvider CreateLoggerServices(ITestOutputHelper output, string cl
return serviceCollection.BuildServiceProvider();
}

// For back compat
public static AssemblyTestLog Create(string assemblyName, string baseDirectory)
=> Create(Assembly.Load(new AssemblyName(assemblyName)), baseDirectory);

public static AssemblyTestLog Create(Assembly assembly, string baseDirectory)
{
var logStart = DateTimeOffset.UtcNow;
Expand Down Expand Up @@ -229,7 +225,8 @@ public static AssemblyTestLog ForAssembly(Assembly assembly)

// Try to clear previous logs, continue if it fails.
var assemblyBaseDirectory = TestFileOutputContext.GetAssemblyBaseDirectory(assembly);
if (!string.IsNullOrEmpty(assemblyBaseDirectory) && !TestFileOutputContext.GetPreserveExistingLogsInOutput(assembly))
if (!string.IsNullOrEmpty(assemblyBaseDirectory) &&
!TestFileOutputContext.GetPreserveExistingLogsInOutput(assembly))
{
try
{
Expand Down Expand Up @@ -267,6 +264,7 @@ private static SerilogLoggerProvider ConfigureFileLogging(string fileName, DateT
.MinimumLevel.Verbose()
.WriteTo.File(fileName, outputTemplate: "[{TimestampOffset}] [{SourceContext}] [{Level}] {Message:l}{NewLine}{Exception}", flushToDiskInterval: TimeSpan.FromSeconds(1), shared: true)
.CreateLogger();

return new SerilogLoggerProvider(serilogger, dispose: true);
}

Expand Down
23 changes: 0 additions & 23 deletions src/Testing/src/LoggedTest/ILoggedTest.cs

This file was deleted.

2 changes: 1 addition & 1 deletion src/Testing/src/LoggedTest/LoggedTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

namespace Microsoft.AspNetCore.Testing;

public class LoggedTestBase : ILoggedTest, ITestMethodLifecycle
public abstract class LoggedTestBase : ITestMethodLifecycle, IDisposable
{
private ExceptionDispatchInfo _initializationException;

Expand Down
3 changes: 3 additions & 0 deletions src/Testing/startvs.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@ECHO OFF

%~dp0..\..\startvs.cmd %~dp0Testing.slnf
4 changes: 3 additions & 1 deletion src/Testing/test/AssemblyFixtureTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ namespace Microsoft.AspNetCore.Testing;
[TestCaseOrderer("Microsoft.AspNetCore.Testing.AlphabeticalOrderer", "Microsoft.AspNetCore.Testing.Tests")]
public class AssemblyFixtureTest
{
public AssemblyFixtureTest(TestAssemblyFixture assemblyFixture, TestCollectionFixture collectionFixture)
public AssemblyFixtureTest(
TestAssemblyFixture assemblyFixture,
TestCollectionFixture collectionFixture)
{
AssemblyFixture = assemblyFixture;
CollectionFixture = collectionFixture;
Expand Down
66 changes: 46 additions & 20 deletions src/Testing/test/AssemblyTestLogTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Testing;
Expand All @@ -17,7 +16,11 @@ public class AssemblyTestLogTests : LoggedTest
{
private static readonly Assembly ThisAssembly = typeof(AssemblyTestLogTests).GetTypeInfo().Assembly;
private static readonly string ThisAssemblyName = ThisAssembly.GetName().Name;
private static readonly string TFM = ThisAssembly.GetCustomAttributes().OfType<TestOutputDirectoryAttribute>().FirstOrDefault().TargetFramework;
private static readonly string TFM = ThisAssembly
.GetCustomAttributes()
.OfType<TestOutputDirectoryAttribute>()
.FirstOrDefault()
.TargetFramework;

[Fact]
public void FunctionalLogs_LogsPreservedFromNonQuarantinedTest()
Expand All @@ -43,8 +46,8 @@ public void ForAssembly_ReturnsSameInstanceForSameAssembly()
public void TestLogWritesToITestOutputHelper()
{
var output = new TestTestOutputHelper();
var assemblyLog = AssemblyTestLog.Create(ThisAssemblyName, baseDirectory: null);

using var assemblyLog = AssemblyTestLog.Create(ThisAssembly, baseDirectory: null);
using (assemblyLog.StartTestLog(output, "NonExistant.Test.Class", out var loggerFactory))
{
var logger = loggerFactory.CreateLogger("TestLogger");
Expand All @@ -69,11 +72,17 @@ public Task TestLogEscapesIllegalFileNames() =>
{
var illegalTestName = "T:e/s//t";
var escapedTestName = "T_e_s_t";
using (var testAssemblyLog = AssemblyTestLog.Create(ThisAssemblyName, baseDirectory: tempDir))
using (testAssemblyLog.StartTestLog(output: null, className: "FakeTestAssembly.FakeTestClass", loggerFactory: out var testLoggerFactory, minLogLevel: LogLevel.Trace, resolvedTestName: out var resolvedTestname, out var _, testName: illegalTestName))
{
Assert.Equal(escapedTestName, resolvedTestname);
}

using var testAssemblyLog = AssemblyTestLog.Create(ThisAssembly, baseDirectory: tempDir);
using var disposable = testAssemblyLog.StartTestLog(
output: null,
className: "FakeTestAssembly.FakeTestClass",
loggerFactory: out var testLoggerFactory,
minLogLevel: LogLevel.Trace,
resolvedTestName: out var resolvedTestname,
out var _,
testName: illegalTestName);
Assert.Equal(escapedTestName, resolvedTestname);
});

[Fact]
Expand All @@ -84,11 +93,16 @@ public Task TestLogWritesToGlobalLogFile() =>
// but it's also testing the test logging facility. So this is pretty meta ;)
var logger = LoggerFactory.CreateLogger("Test");

using (var testAssemblyLog = AssemblyTestLog.Create(ThisAssemblyName, tempDir))
using (var testAssemblyLog = AssemblyTestLog.Create(ThisAssembly, baseDirectory: tempDir))
{
logger.LogInformation("Created test log in {baseDirectory}", tempDir);

using (testAssemblyLog.StartTestLog(output: null, className: $"{ThisAssemblyName}.FakeTestClass", loggerFactory: out var testLoggerFactory, minLogLevel: LogLevel.Trace, testName: "FakeTestName"))
using (testAssemblyLog.StartTestLog(
output: null,
className: $"{ThisAssemblyName}.FakeTestClass",
loggerFactory: out var testLoggerFactory,
minLogLevel: LogLevel.Trace,
testName: "FakeTestName"))
{
var testLogger = testLoggerFactory.CreateLogger("TestLogger");
testLogger.LogInformation("Information!");
Expand Down Expand Up @@ -126,15 +140,21 @@ public Task TestLogTruncatesTestNameToAvoidLongPaths() =>
{
var longTestName = new string('0', 50) + new string('1', 50) + new string('2', 50) + new string('3', 50) + new string('4', 50);
var logger = LoggerFactory.CreateLogger("Test");
using (var testAssemblyLog = AssemblyTestLog.Create(ThisAssemblyName, tempDir))
using (var testAssemblyLog = AssemblyTestLog.Create(ThisAssembly, baseDirectory: tempDir))
{
logger.LogInformation("Created test log in {baseDirectory}", tempDir);

using (testAssemblyLog.StartTestLog(output: null, className: $"{ThisAssemblyName}.FakeTestClass", loggerFactory: out var testLoggerFactory, minLogLevel: LogLevel.Trace, testName: longTestName))
using (testAssemblyLog.StartTestLog(
output: null,
className: $"{ThisAssemblyName}.FakeTestClass",
loggerFactory: out var testLoggerFactory,
minLogLevel: LogLevel.Trace,
testName: longTestName))
{
testLoggerFactory.CreateLogger("TestLogger").LogInformation("Information!");
}
}

logger.LogInformation("Finished test log in {baseDirectory}", tempDir);

var testLogFiles = new DirectoryInfo(Path.Combine(tempDir, ThisAssemblyName, TFM, "FakeTestClass")).EnumerateFiles();
Expand All @@ -152,18 +172,24 @@ public Task TestLogEnumerateFilenamesToAvoidCollisions() =>
RunTestLogFunctionalTest((tempDir) =>
{
var logger = LoggerFactory.CreateLogger("Test");
using (var testAssemblyLog = AssemblyTestLog.Create(ThisAssemblyName, tempDir))
using (var testAssemblyLog = AssemblyTestLog.Create(ThisAssembly, baseDirectory: tempDir))
{
logger.LogInformation("Created test log in {baseDirectory}", tempDir);

for (var i = 0; i < 10; i++)
{
using (testAssemblyLog.StartTestLog(output: null, className: $"{ThisAssemblyName}.FakeTestClass", loggerFactory: out var testLoggerFactory, minLogLevel: LogLevel.Trace, testName: "FakeTestName"))
using (testAssemblyLog.StartTestLog(
output: null,
className: $"{ThisAssemblyName}.FakeTestClass",
loggerFactory: out var testLoggerFactory,
minLogLevel: LogLevel.Trace,
testName: "FakeTestName"))
{
testLoggerFactory.CreateLogger("TestLogger").LogInformation("Information!");
}
}
}

logger.LogInformation("Finished test log in {baseDirectory}", tempDir);

// The first log file exists
Expand All @@ -176,13 +202,13 @@ public Task TestLogEnumerateFilenamesToAvoidCollisions() =>
}
});

private static readonly Regex TimestampRegex = new Regex(@"\d+-\d+-\d+T\d+:\d+:\d+");
private static readonly Regex TimestampOffsetRegex = new Regex(@"\d+\.\d+s");
private static readonly Regex DurationRegex = new Regex(@"[^ ]+s$");
private static readonly Regex TimestampRegex = new(@"\d+-\d+-\d+T\d+:\d+:\d+");
private static readonly Regex TimestampOffsetRegex = new(@"\d+\.\d+s");
private static readonly Regex DurationRegex = new(@"[^ ]+s$");

private async Task RunTestLogFunctionalTest(Action<string> action, [CallerMemberName] string testName = null)
private static async Task RunTestLogFunctionalTest(Action<string> action)
{
var tempDir = Path.Combine(Path.GetTempPath(), $"TestLogging_{Guid.NewGuid().ToString("N")}");
var tempDir = Path.Combine(Path.GetTempPath(), $"TestLogging_{Guid.NewGuid():N}");
try
{
action(tempDir);
Expand All @@ -209,7 +235,7 @@ private static string MakeConsistent(string input)
return string.Join(Environment.NewLine, input.Split(new[] { Environment.NewLine }, StringSplitOptions.None)
.Select(line =>
{
var strippedPrefix = line.IndexOf('[') >= 0 ? line.Substring(line.IndexOf('[')) : line;
var strippedPrefix = line.Contains('[') ? line.Substring(line.IndexOf('[')) : line;

var strippedDuration = DurationRegex.Replace(strippedPrefix, "DURATION");
var strippedTimestamp = TimestampRegex.Replace(strippedDuration, "TIMESTAMP");
Expand Down
1 change: 0 additions & 1 deletion src/Testing/test/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Xunit;

[assembly: Repeat(1)]
[assembly: LogLevel(LogLevel.Trace)]
Expand Down