Merge branch 'release/3.1' => 'master' (#2382)
This commit is contained in:
commit
b760a9da55
|
|
@ -9,6 +9,7 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Serilog;
|
||||
using Serilog.Core;
|
||||
|
|
@ -23,14 +24,6 @@ namespace Microsoft.Extensions.Logging.Testing
|
|||
private static readonly string MaxPathLengthEnvironmentVariableName = "ASPNETCORE_TEST_LOG_MAXPATH";
|
||||
private static readonly string LogFileExtension = ".log";
|
||||
private static readonly int MaxPathLength = GetMaxPathLength();
|
||||
private static char[] InvalidFileChars = new char[]
|
||||
{
|
||||
'\"', '<', '>', '|', '\0',
|
||||
(char)1, (char)2, (char)3, (char)4, (char)5, (char)6, (char)7, (char)8, (char)9, (char)10,
|
||||
(char)11, (char)12, (char)13, (char)14, (char)15, (char)16, (char)17, (char)18, (char)19, (char)20,
|
||||
(char)21, (char)22, (char)23, (char)24, (char)25, (char)26, (char)27, (char)28, (char)29, (char)30,
|
||||
(char)31, ':', '*', '?', '\\', '/', ' ', (char)127
|
||||
};
|
||||
|
||||
private static readonly object _lock = new object();
|
||||
private static readonly Dictionary<Assembly, AssemblyTestLog> _logs = new Dictionary<Assembly, AssemblyTestLog>();
|
||||
|
|
@ -113,8 +106,8 @@ namespace Microsoft.Extensions.Logging.Testing
|
|||
SerilogLoggerProvider serilogLoggerProvider = null;
|
||||
if (!string.IsNullOrEmpty(_baseDirectory))
|
||||
{
|
||||
logOutputDirectory = Path.Combine(GetAssemblyBaseDirectory(_baseDirectory, _assembly), className);
|
||||
testName = RemoveIllegalFileChars(testName);
|
||||
logOutputDirectory = Path.Combine(_baseDirectory, className);
|
||||
testName = TestFileOutputContext.RemoveIllegalFileChars(testName);
|
||||
|
||||
if (logOutputDirectory.Length + testName.Length + LogFileExtension.Length >= MaxPathLength)
|
||||
{
|
||||
|
|
@ -184,10 +177,10 @@ namespace Microsoft.Extensions.Logging.Testing
|
|||
{
|
||||
var logStart = DateTimeOffset.UtcNow;
|
||||
SerilogLoggerProvider serilogLoggerProvider = null;
|
||||
var globalLogDirectory = GetAssemblyBaseDirectory(baseDirectory, assembly);
|
||||
if (!string.IsNullOrEmpty(globalLogDirectory))
|
||||
if (!string.IsNullOrEmpty(baseDirectory))
|
||||
{
|
||||
var globalLogFileName = Path.Combine(globalLogDirectory, "global.log");
|
||||
baseDirectory = TestFileOutputContext.GetAssemblyBaseDirectory(assembly, baseDirectory);
|
||||
var globalLogFileName = Path.Combine(baseDirectory, "global.log");
|
||||
serilogLoggerProvider = ConfigureFileLogging(globalLogFileName, logStart);
|
||||
}
|
||||
|
||||
|
|
@ -222,31 +215,26 @@ namespace Microsoft.Extensions.Logging.Testing
|
|||
{
|
||||
if (!_logs.TryGetValue(assembly, out var log))
|
||||
{
|
||||
var baseDirectory = GetFileLoggerAttribute(assembly).BaseDirectory;
|
||||
var baseDirectory = TestFileOutputContext.GetOutputDirectory(assembly);
|
||||
|
||||
log = Create(assembly, baseDirectory);
|
||||
_logs[assembly] = log;
|
||||
|
||||
// Try to clear previous logs
|
||||
var assemblyBaseDirectory = GetAssemblyBaseDirectory(baseDirectory, assembly);
|
||||
if (Directory.Exists(assemblyBaseDirectory))
|
||||
// Try to clear previous logs, continue if it fails.
|
||||
var assemblyBaseDirectory = TestFileOutputContext.GetAssemblyBaseDirectory(assembly);
|
||||
if (!string.IsNullOrEmpty(assemblyBaseDirectory))
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(assemblyBaseDirectory, recursive: true);
|
||||
}
|
||||
catch {}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
return log;
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetAssemblyBaseDirectory(string baseDirectory, Assembly assembly)
|
||||
=> string.IsNullOrEmpty(baseDirectory)
|
||||
? string.Empty
|
||||
: Path.Combine(baseDirectory, assembly.GetName().Name, GetFileLoggerAttribute(assembly).TFM);
|
||||
|
||||
private static TestFrameworkFileLoggerAttribute GetFileLoggerAttribute(Assembly assembly)
|
||||
=> assembly.GetCustomAttribute<TestFrameworkFileLoggerAttribute>()
|
||||
?? throw new InvalidOperationException($"No {nameof(TestFrameworkFileLoggerAttribute)} found on the assembly {assembly.GetName().Name}. "
|
||||
|
|
@ -275,27 +263,6 @@ namespace Microsoft.Extensions.Logging.Testing
|
|||
return new SerilogLoggerProvider(serilogger, dispose: true);
|
||||
}
|
||||
|
||||
private static string RemoveIllegalFileChars(string s)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
foreach (var c in s)
|
||||
{
|
||||
if (InvalidFileChars.Contains(c))
|
||||
{
|
||||
if (sb.Length > 0 && sb[sb.Length - 1] != '_')
|
||||
{
|
||||
sb.Append('_');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(c);
|
||||
}
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
(_serviceProvider as IDisposable)?.Dispose();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
|
|
@ -12,7 +17,23 @@ namespace Microsoft.Extensions.Logging.Testing
|
|||
/// This currently only works in Windows environments
|
||||
/// </remarks>
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
||||
public class CollectDumpAttribute : Attribute
|
||||
public class CollectDumpAttribute : Attribute, ITestMethodLifecycle
|
||||
{
|
||||
public Task OnTestStartAsync(TestContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task OnTestEndAsync(TestContext context, Exception exception, CancellationToken cancellationToken)
|
||||
{
|
||||
if (exception != null)
|
||||
{
|
||||
var path = Path.Combine(context.FileOutput.TestClassOutputDirectory, context.FileOutput.GetUniqueFileName(context.FileOutput.TestName, ".dmp"));
|
||||
var process = Process.GetCurrentProcess();
|
||||
DumpCollector.Collect(process, path);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
|
|
@ -18,6 +19,6 @@ namespace Microsoft.Extensions.Logging.Testing
|
|||
// For back compat
|
||||
IDisposable StartLog(out ILoggerFactory loggerFactory, LogLevel minLogLevel, string testName);
|
||||
|
||||
void Initialize(MethodInfo methodInfo, object[] testMethodArguments, ITestOutputHelper testOutputHelper);
|
||||
void Initialize(TestContext context, MethodInfo methodInfo, object[] testMethodArguments, ITestOutputHelper testOutputHelper);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
|
|
@ -13,9 +14,9 @@ namespace Microsoft.Extensions.Logging.Testing
|
|||
|
||||
public ITestSink TestSink { get; set; }
|
||||
|
||||
public override void Initialize(MethodInfo methodInfo, object[] testMethodArguments, ITestOutputHelper testOutputHelper)
|
||||
public override void Initialize(TestContext context, MethodInfo methodInfo, object[] testMethodArguments, ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
base.Initialize(methodInfo, testMethodArguments, testOutputHelper);
|
||||
base.Initialize(context, methodInfo, testMethodArguments, testOutputHelper);
|
||||
|
||||
TestSink = new TestSink();
|
||||
LoggerFactory.AddProvider(new TestLoggerProvider(TestSink));
|
||||
|
|
|
|||
|
|
@ -6,12 +6,16 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Serilog;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class LoggedTestBase : ILoggedTest
|
||||
public class LoggedTestBase : ILoggedTest, ITestMethodLifecycle
|
||||
{
|
||||
private ExceptionDispatchInfo _initializationException;
|
||||
|
||||
|
|
@ -23,11 +27,11 @@ namespace Microsoft.Extensions.Logging.Testing
|
|||
TestOutputHelper = output;
|
||||
}
|
||||
|
||||
protected TestContext Context { get; private set; }
|
||||
|
||||
// Internal for testing
|
||||
internal string ResolvedTestClassName { get; set; }
|
||||
|
||||
internal RepeatContext RepeatContext { get; set; }
|
||||
|
||||
public string ResolvedLogOutputDirectory { get; set; }
|
||||
|
||||
public string ResolvedTestMethodName { get; set; }
|
||||
|
|
@ -49,7 +53,7 @@ namespace Microsoft.Extensions.Logging.Testing
|
|||
return AssemblyTestLog.ForAssembly(GetType().GetTypeInfo().Assembly).StartTestLog(TestOutputHelper, GetType().FullName, out loggerFactory, minLogLevel, testName);
|
||||
}
|
||||
|
||||
public virtual void Initialize(MethodInfo methodInfo, object[] testMethodArguments, ITestOutputHelper testOutputHelper)
|
||||
public virtual void Initialize(TestContext context, MethodInfo methodInfo, object[] testMethodArguments, ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -59,25 +63,22 @@ namespace Microsoft.Extensions.Logging.Testing
|
|||
var logLevelAttribute = methodInfo.GetCustomAttribute<LogLevelAttribute>()
|
||||
?? methodInfo.DeclaringType.GetCustomAttribute<LogLevelAttribute>()
|
||||
?? methodInfo.DeclaringType.Assembly.GetCustomAttribute<LogLevelAttribute>();
|
||||
var testName = testMethodArguments.Aggregate(methodInfo.Name, (a, b) => $"{a}-{(b ?? "null")}");
|
||||
|
||||
var useShortClassName = methodInfo.DeclaringType.GetCustomAttribute<ShortClassNameAttribute>()
|
||||
?? methodInfo.DeclaringType.Assembly.GetCustomAttribute<ShortClassNameAttribute>();
|
||||
// internal for testing
|
||||
ResolvedTestClassName = useShortClassName == null ? classType.FullName : classType.Name;
|
||||
ResolvedTestClassName = context.FileOutput.TestClassName;
|
||||
|
||||
_testLog = AssemblyTestLog
|
||||
.ForAssembly(classType.GetTypeInfo().Assembly)
|
||||
.StartTestLog(
|
||||
TestOutputHelper,
|
||||
ResolvedTestClassName,
|
||||
context.FileOutput.TestClassName,
|
||||
out var loggerFactory,
|
||||
logLevelAttribute?.LogLevel ?? LogLevel.Debug,
|
||||
out var resolvedTestName,
|
||||
out var logOutputDirectory,
|
||||
testName);
|
||||
out var logDirectory,
|
||||
context.FileOutput.TestName);
|
||||
|
||||
ResolvedLogOutputDirectory = logOutputDirectory;
|
||||
ResolvedLogOutputDirectory = logDirectory;
|
||||
ResolvedTestMethodName = resolvedTestName;
|
||||
|
||||
LoggerFactory = loggerFactory;
|
||||
|
|
@ -91,7 +92,7 @@ namespace Microsoft.Extensions.Logging.Testing
|
|||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
if(_testLog == null)
|
||||
if (_testLog == null)
|
||||
{
|
||||
// It seems like sometimes the MSBuild goop that adds the test framework can end up in a bad state and not actually add it
|
||||
// Not sure yet why that happens but the exception isn't clear so I'm adding this error so we can detect it better.
|
||||
|
|
@ -102,5 +103,19 @@ namespace Microsoft.Extensions.Logging.Testing
|
|||
_initializationException?.Throw();
|
||||
_testLog.Dispose();
|
||||
}
|
||||
|
||||
Task ITestMethodLifecycle.OnTestStartAsync(TestContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
Context = context;
|
||||
|
||||
Initialize(context, context.TestMethod, context.MethodArguments, context.Output);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
Task ITestMethodLifecycle.OnTestEndAsync(TestContext context, Exception exception, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class RepeatContext
|
||||
{
|
||||
internal int Limit { get; set; }
|
||||
|
||||
internal int CurrentIteration { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = false)]
|
||||
public class ShortClassNameAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +1,17 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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 Microsoft.AspNetCore.Testing;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
|
||||
public class TestFrameworkFileLoggerAttribute : Attribute
|
||||
public class TestFrameworkFileLoggerAttribute : TestOutputDirectoryAttribute
|
||||
{
|
||||
public TestFrameworkFileLoggerAttribute(string tfm, string baseDirectory = null)
|
||||
: base(tfm, baseDirectory)
|
||||
{
|
||||
TFM = tfm;
|
||||
BaseDirectory = baseDirectory;
|
||||
}
|
||||
|
||||
public string TFM { get; }
|
||||
public string BaseDirectory { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
// 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 Microsoft.AspNetCore.Testing;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class LoggedConditionalFactDiscoverer : LoggedFactDiscoverer
|
||||
{
|
||||
private readonly IMessageSink _diagnosticMessageSink;
|
||||
|
||||
public LoggedConditionalFactDiscoverer(IMessageSink diagnosticMessageSink) : base(diagnosticMessageSink)
|
||||
{
|
||||
_diagnosticMessageSink = diagnosticMessageSink;
|
||||
}
|
||||
|
||||
protected override IXunitTestCase CreateTestCase(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo factAttribute)
|
||||
{
|
||||
var skipReason = testMethod.EvaluateSkipConditions();
|
||||
return skipReason != null
|
||||
? new SkippedTestCase(skipReason, _diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), TestMethodDisplayOptions.None, testMethod)
|
||||
: base.CreateTestCase(discoveryOptions, testMethod, factAttribute);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
// 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.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class LoggedConditionalTheoryDiscoverer : LoggedTheoryDiscoverer
|
||||
{
|
||||
public LoggedConditionalTheoryDiscoverer(IMessageSink diagnosticMessageSink)
|
||||
: base(diagnosticMessageSink)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IEnumerable<IXunitTestCase> CreateTestCasesForTheory(
|
||||
ITestFrameworkDiscoveryOptions discoveryOptions,
|
||||
ITestMethod testMethod,
|
||||
IAttributeInfo theoryAttribute)
|
||||
{
|
||||
var skipReason = testMethod.EvaluateSkipConditions();
|
||||
return skipReason != null
|
||||
? new[] { new SkippedTestCase(skipReason, DiagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), TestMethodDisplayOptions.None, testMethod) }
|
||||
: base.CreateTestCasesForTheory(discoveryOptions, testMethod, theoryAttribute);
|
||||
}
|
||||
|
||||
protected override IEnumerable<IXunitTestCase> CreateTestCasesForDataRow(
|
||||
ITestFrameworkDiscoveryOptions discoveryOptions,
|
||||
ITestMethod testMethod, IAttributeInfo theoryAttribute,
|
||||
object[] dataRow)
|
||||
{
|
||||
var skipReason = testMethod.EvaluateSkipConditions();
|
||||
if (skipReason == null && dataRow?.Length > 0)
|
||||
{
|
||||
var obj = dataRow[0];
|
||||
if (obj != null)
|
||||
{
|
||||
var type = obj.GetType();
|
||||
var property = type.GetProperty("Skip");
|
||||
if (property != null && property.PropertyType.Equals(typeof(string)))
|
||||
{
|
||||
skipReason = property.GetValue(obj) as string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return skipReason != null
|
||||
? base.CreateTestCasesForSkippedDataRow(discoveryOptions, testMethod, theoryAttribute, dataRow, skipReason)
|
||||
: base.CreateTestCasesForDataRow(discoveryOptions, testMethod, theoryAttribute, dataRow);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
// 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 Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class LoggedFactDiscoverer : FactDiscoverer
|
||||
{
|
||||
public LoggedFactDiscoverer(IMessageSink diagnosticMessageSink) : base(diagnosticMessageSink)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IXunitTestCase CreateTestCase(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo factAttribute)
|
||||
=> new LoggedTestCase(DiagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), TestMethodDisplayOptions.None, testMethod);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class LoggedTestAssemblyRunner : XunitTestAssemblyRunner
|
||||
{
|
||||
public LoggedTestAssemblyRunner(
|
||||
ITestAssembly testAssembly,
|
||||
IEnumerable<IXunitTestCase> testCases,
|
||||
IMessageSink diagnosticMessageSink,
|
||||
IMessageSink executionMessageSink,
|
||||
ITestFrameworkExecutionOptions executionOptions)
|
||||
: base(testAssembly, testCases, diagnosticMessageSink, executionMessageSink, executionOptions)
|
||||
{
|
||||
}
|
||||
|
||||
protected override Task<RunSummary> RunTestCollectionAsync(
|
||||
IMessageBus messageBus,
|
||||
ITestCollection testCollection,
|
||||
IEnumerable<IXunitTestCase> testCases,
|
||||
CancellationTokenSource cancellationTokenSource)
|
||||
=> new LoggedTestCollectionRunner(testCollection, testCases, DiagnosticMessageSink, messageBus, TestCaseOrderer, new ExceptionAggregator(Aggregator), cancellationTokenSource).RunAsync();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
// 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;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class LoggedTestCase : XunitTestCase
|
||||
{
|
||||
[Obsolete("Called by the de-serializer; should only be called by deriving classes for de-serialization purposes")]
|
||||
public LoggedTestCase() : base()
|
||||
{
|
||||
}
|
||||
|
||||
public LoggedTestCase(
|
||||
IMessageSink diagnosticMessageSink,
|
||||
TestMethodDisplay defaultMethodDisplay,
|
||||
TestMethodDisplayOptions defaultMethodDisplayOptions,
|
||||
ITestMethod testMethod,
|
||||
object[] testMethodArguments = null)
|
||||
: base(diagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, testMethod, testMethodArguments)
|
||||
{
|
||||
}
|
||||
|
||||
public override Task<RunSummary> RunAsync(
|
||||
IMessageSink diagnosticMessageSink,
|
||||
IMessageBus messageBus,
|
||||
object[] constructorArguments,
|
||||
ExceptionAggregator aggregator,
|
||||
CancellationTokenSource cancellationTokenSource)
|
||||
=> new LoggedTestCaseRunner(this, DisplayName, SkipReason, constructorArguments, TestMethodArguments, messageBus, aggregator, cancellationTokenSource).RunAsync();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
// 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.Reflection;
|
||||
using System.Threading;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class LoggedTestCaseRunner : XunitTestCaseRunner
|
||||
{
|
||||
public LoggedTestCaseRunner(
|
||||
IXunitTestCase testCase,
|
||||
string displayName,
|
||||
string skipReason,
|
||||
object[] constructorArguments,
|
||||
object[] testMethodArguments,
|
||||
IMessageBus messageBus,
|
||||
ExceptionAggregator aggregator,
|
||||
CancellationTokenSource cancellationTokenSource)
|
||||
: base(testCase, displayName, skipReason, constructorArguments, testMethodArguments, messageBus, aggregator, cancellationTokenSource)
|
||||
{
|
||||
}
|
||||
|
||||
protected override XunitTestRunner CreateTestRunner(
|
||||
ITest test,
|
||||
IMessageBus messageBus,
|
||||
Type testClass,
|
||||
object[] constructorArguments,
|
||||
MethodInfo testMethod,
|
||||
object[] testMethodArguments,
|
||||
string skipReason,
|
||||
IReadOnlyList<BeforeAfterTestAttribute> beforeAfterAttributes,
|
||||
ExceptionAggregator aggregator,
|
||||
CancellationTokenSource cancellationTokenSource)
|
||||
=> new LoggedTestRunner(test, messageBus, testClass, constructorArguments, testMethod, testMethodArguments,
|
||||
skipReason, beforeAfterAttributes, new ExceptionAggregator(aggregator), cancellationTokenSource);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
// 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.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class LoggedTestClassRunner : XunitTestClassRunner
|
||||
{
|
||||
public LoggedTestClassRunner(
|
||||
ITestClass testClass,
|
||||
IReflectionTypeInfo @class,
|
||||
IEnumerable<IXunitTestCase> testCases,
|
||||
IMessageSink diagnosticMessageSink,
|
||||
IMessageBus messageBus,
|
||||
ITestCaseOrderer testCaseOrderer,
|
||||
ExceptionAggregator aggregator,
|
||||
CancellationTokenSource cancellationTokenSource,
|
||||
IDictionary<Type, object> collectionFixtureMappings)
|
||||
: base(testClass, @class, testCases, diagnosticMessageSink, messageBus, testCaseOrderer, aggregator, cancellationTokenSource, collectionFixtureMappings)
|
||||
{
|
||||
}
|
||||
|
||||
protected override Task<RunSummary> RunTestMethodAsync(
|
||||
ITestMethod testMethod,
|
||||
IReflectionMethodInfo method,
|
||||
IEnumerable<IXunitTestCase> testCases,
|
||||
object[] constructorArguments)
|
||||
=> new LoggedTestMethodRunner(testMethod, Class, method, testCases, DiagnosticMessageSink, MessageBus, new ExceptionAggregator(Aggregator), CancellationTokenSource, constructorArguments).RunAsync();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class LoggedTestCollectionRunner : XunitTestCollectionRunner
|
||||
{
|
||||
private readonly IMessageSink _diagnosticMessageSink;
|
||||
|
||||
public LoggedTestCollectionRunner(
|
||||
ITestCollection testCollection,
|
||||
IEnumerable<IXunitTestCase> testCases,
|
||||
IMessageSink diagnosticMessageSink,
|
||||
IMessageBus messageBus,
|
||||
ITestCaseOrderer testCaseOrderer,
|
||||
ExceptionAggregator aggregator,
|
||||
CancellationTokenSource cancellationTokenSource)
|
||||
: base(testCollection, testCases, diagnosticMessageSink, messageBus, testCaseOrderer, aggregator, cancellationTokenSource)
|
||||
{
|
||||
// Base class doesn't expose this, so capture it here.
|
||||
_diagnosticMessageSink = diagnosticMessageSink;
|
||||
}
|
||||
|
||||
protected override Task<RunSummary> RunTestClassAsync(ITestClass testClass, IReflectionTypeInfo @class, IEnumerable<IXunitTestCase> testCases)
|
||||
=> new LoggedTestClassRunner(testClass, @class, testCases, _diagnosticMessageSink, MessageBus, TestCaseOrderer, new ExceptionAggregator(Aggregator), CancellationTokenSource, CollectionFixtureMappings).RunAsync();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
// 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.Reflection;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class LoggedTestFramework : XunitTestFramework
|
||||
{
|
||||
public LoggedTestFramework(IMessageSink messageSink) : base(messageSink)
|
||||
{
|
||||
}
|
||||
|
||||
protected override ITestFrameworkDiscoverer CreateDiscoverer(IAssemblyInfo assemblyInfo)
|
||||
{
|
||||
return new LoggedTestFrameworkDiscoverer(assemblyInfo, SourceInformationProvider, DiagnosticMessageSink);
|
||||
}
|
||||
|
||||
protected override ITestFrameworkExecutor CreateExecutor(AssemblyName assemblyName)
|
||||
{
|
||||
return new LoggedTestFrameworkExecutor(assemblyName, SourceInformationProvider, DiagnosticMessageSink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
// 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.Linq;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class LoggedTestFrameworkDiscoverer : XunitTestFrameworkDiscoverer
|
||||
{
|
||||
private IDictionary<Type, IXunitTestCaseDiscoverer> Discoverers { get; }
|
||||
|
||||
public LoggedTestFrameworkDiscoverer(
|
||||
IAssemblyInfo assemblyInfo,
|
||||
ISourceInformationProvider sourceProvider,
|
||||
IMessageSink diagnosticMessageSink,
|
||||
IXunitTestCollectionFactory collectionFactory = null)
|
||||
: base(assemblyInfo, sourceProvider, diagnosticMessageSink, collectionFactory)
|
||||
{
|
||||
Discoverers = new Dictionary<Type, IXunitTestCaseDiscoverer>()
|
||||
{
|
||||
{ typeof(ConditionalTheoryAttribute), new LoggedConditionalTheoryDiscoverer(diagnosticMessageSink) },
|
||||
{ typeof(ConditionalFactAttribute), new LoggedConditionalFactDiscoverer(diagnosticMessageSink) },
|
||||
{ typeof(TheoryAttribute), new LoggedTheoryDiscoverer(diagnosticMessageSink) },
|
||||
{ typeof(FactAttribute), new LoggedFactDiscoverer(diagnosticMessageSink) }
|
||||
};
|
||||
}
|
||||
|
||||
protected override bool FindTestsForMethod(
|
||||
ITestMethod testMethod,
|
||||
bool includeSourceInformation,
|
||||
IMessageBus messageBus,
|
||||
ITestFrameworkDiscoveryOptions discoveryOptions)
|
||||
{
|
||||
if (typeof(ILoggedTest).IsAssignableFrom(testMethod.TestClass.Class.ToRuntimeType()))
|
||||
{
|
||||
var factAttributes = testMethod.Method.GetCustomAttributes(typeof(FactAttribute));
|
||||
if (factAttributes.Count() > 1)
|
||||
{
|
||||
var message = $"Test method '{testMethod.TestClass.Class.Name}.{testMethod.Method.Name}' has multiple [Fact]-derived attributes";
|
||||
var testCase = new ExecutionErrorTestCase(DiagnosticMessageSink, TestMethodDisplay.ClassAndMethod, TestMethodDisplayOptions.None, testMethod, message);
|
||||
return ReportDiscoveredTestCase(testCase, includeSourceInformation, messageBus);
|
||||
}
|
||||
|
||||
var factAttribute = factAttributes.FirstOrDefault();
|
||||
if (factAttribute == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var factAttributeType = (factAttribute as IReflectionAttributeInfo)?.Attribute.GetType();
|
||||
if (!Discoverers.TryGetValue(factAttributeType, out var discoverer))
|
||||
{
|
||||
return base.FindTestsForMethod(testMethod, includeSourceInformation, messageBus, discoveryOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var testCase in discoverer.Discover(discoveryOptions, testMethod, factAttribute))
|
||||
{
|
||||
if (!ReportDiscoveredTestCase(testCase, includeSourceInformation, messageBus))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return base.FindTestsForMethod(testMethod, includeSourceInformation, messageBus, discoveryOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class LoggedTestFrameworkExecutor : XunitTestFrameworkExecutor
|
||||
{
|
||||
public LoggedTestFrameworkExecutor(AssemblyName assemblyName, ISourceInformationProvider sourceInformationProvider, IMessageSink diagnosticMessageSink)
|
||||
: base(assemblyName, sourceInformationProvider, diagnosticMessageSink)
|
||||
{
|
||||
}
|
||||
|
||||
protected override async void RunTestCases(IEnumerable<IXunitTestCase> testCases, IMessageSink executionMessageSink, ITestFrameworkExecutionOptions executionOptions)
|
||||
{
|
||||
using (var assemblyRunner = new LoggedTestAssemblyRunner(TestAssembly, testCases, DiagnosticMessageSink, executionMessageSink, executionOptions))
|
||||
{
|
||||
await assemblyRunner.RunAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
// 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.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class LoggedTestInvoker : XunitTestInvoker
|
||||
{
|
||||
private readonly ITestOutputHelper _output;
|
||||
private readonly RepeatContext _repeatContext;
|
||||
private readonly bool _collectDumpOnFailure;
|
||||
|
||||
public LoggedTestInvoker(
|
||||
ITest test,
|
||||
IMessageBus messageBus,
|
||||
Type testClass,
|
||||
object[] constructorArguments,
|
||||
MethodInfo testMethod,
|
||||
object[] testMethodArguments,
|
||||
IReadOnlyList<BeforeAfterTestAttribute> beforeAfterAttributes,
|
||||
ExceptionAggregator aggregator,
|
||||
CancellationTokenSource cancellationTokenSource,
|
||||
ITestOutputHelper output,
|
||||
RepeatContext repeatContext,
|
||||
bool collectDumpOnFailure)
|
||||
: base(test, messageBus, testClass, constructorArguments, testMethod, testMethodArguments, beforeAfterAttributes, aggregator, cancellationTokenSource)
|
||||
{
|
||||
_output = output;
|
||||
_repeatContext = repeatContext;
|
||||
_collectDumpOnFailure = collectDumpOnFailure;
|
||||
}
|
||||
|
||||
protected override object CreateTestClass()
|
||||
{
|
||||
var testClass = base.CreateTestClass();
|
||||
|
||||
(testClass as ILoggedTest).Initialize(
|
||||
TestMethod,
|
||||
TestMethodArguments,
|
||||
_output ?? ConstructorArguments.SingleOrDefault(a => typeof(ITestOutputHelper).IsAssignableFrom(a.GetType())) as ITestOutputHelper);
|
||||
|
||||
if (testClass is LoggedTestBase loggedTestBase)
|
||||
{
|
||||
// Used for testing
|
||||
loggedTestBase.RepeatContext = _repeatContext;
|
||||
}
|
||||
|
||||
return testClass;
|
||||
}
|
||||
|
||||
protected override object CallTestMethod(object testClassInstance)
|
||||
{
|
||||
try
|
||||
{
|
||||
return base.CallTestMethod(testClassInstance);
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (_collectDumpOnFailure && testClassInstance is LoggedTestBase loggedTestBase)
|
||||
{
|
||||
var path = Path.Combine(loggedTestBase.ResolvedLogOutputDirectory, loggedTestBase.ResolvedTestMethodName + ".dmp");
|
||||
var process = Process.GetCurrentProcess();
|
||||
|
||||
DumpCollector.Collect(process, path);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class LoggedTestMethodRunner : XunitTestMethodRunner
|
||||
{
|
||||
private IMessageSink DiagnosticMessageSink { get; }
|
||||
private object[] ConstructorArguments { get; }
|
||||
|
||||
public LoggedTestMethodRunner(
|
||||
ITestMethod testMethod,
|
||||
IReflectionTypeInfo @class,
|
||||
IReflectionMethodInfo method,
|
||||
IEnumerable<IXunitTestCase> testCases,
|
||||
IMessageSink diagnosticMessageSink,
|
||||
IMessageBus messageBus,
|
||||
ExceptionAggregator aggregator,
|
||||
CancellationTokenSource cancellationTokenSource,
|
||||
object[] constructorArguments)
|
||||
: base(testMethod, @class, method, testCases, diagnosticMessageSink, messageBus, aggregator, cancellationTokenSource, constructorArguments)
|
||||
{
|
||||
DiagnosticMessageSink = diagnosticMessageSink;
|
||||
ConstructorArguments = constructorArguments;
|
||||
}
|
||||
|
||||
protected override Task<RunSummary> RunTestCaseAsync(IXunitTestCase testCase)
|
||||
=> testCase.RunAsync(DiagnosticMessageSink, MessageBus, ConstructorArguments, new ExceptionAggregator(Aggregator), CancellationTokenSource);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
// 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.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class LoggedTestRunner : XunitTestRunner
|
||||
{
|
||||
public LoggedTestRunner(
|
||||
ITest test,
|
||||
IMessageBus messageBus,
|
||||
Type testClass,
|
||||
object[] constructorArguments,
|
||||
MethodInfo testMethod, object[]
|
||||
testMethodArguments, string skipReason,
|
||||
IReadOnlyList<BeforeAfterTestAttribute> beforeAfterAttributes,
|
||||
ExceptionAggregator aggregator,
|
||||
CancellationTokenSource cancellationTokenSource)
|
||||
: base(test, messageBus, testClass, constructorArguments, testMethod, testMethodArguments, skipReason, beforeAfterAttributes, aggregator, cancellationTokenSource)
|
||||
{
|
||||
}
|
||||
|
||||
protected async override Task<Tuple<decimal, string>> InvokeTestAsync(ExceptionAggregator aggregator)
|
||||
{
|
||||
var testOutputHelper = ConstructorArguments.SingleOrDefault(a => typeof(TestOutputHelper).IsAssignableFrom(a.GetType())) as TestOutputHelper
|
||||
?? new TestOutputHelper();
|
||||
testOutputHelper.Initialize(MessageBus, Test);
|
||||
|
||||
var executionTime = await InvokeTestMethodAsync(aggregator, testOutputHelper);
|
||||
|
||||
var output = testOutputHelper.Output;
|
||||
testOutputHelper.Uninitialize();
|
||||
|
||||
return Tuple.Create(executionTime, output);
|
||||
}
|
||||
|
||||
protected override Task<decimal> InvokeTestMethodAsync(ExceptionAggregator aggregator)
|
||||
=> InvokeTestMethodAsync(aggregator, null);
|
||||
|
||||
private async Task<decimal> InvokeTestMethodAsync(ExceptionAggregator aggregator, ITestOutputHelper output)
|
||||
{
|
||||
var collectDump = TestMethod.GetCustomAttribute<CollectDumpAttribute>() != null;
|
||||
var repeatAttribute = GetRepeatAttribute(TestMethod);
|
||||
|
||||
if (!typeof(LoggedTestBase).IsAssignableFrom(TestClass) || repeatAttribute == null)
|
||||
{
|
||||
return await new LoggedTestInvoker(Test, MessageBus, TestClass, ConstructorArguments, TestMethod, TestMethodArguments, BeforeAfterAttributes, aggregator, CancellationTokenSource, output, null, collectDump).RunAsync();
|
||||
}
|
||||
|
||||
return await RunRepeatTestInvoker(aggregator, output, collectDump, repeatAttribute);
|
||||
}
|
||||
|
||||
private async Task<decimal> RunRepeatTestInvoker(ExceptionAggregator aggregator, ITestOutputHelper output, bool collectDump, RepeatAttribute repeatAttribute)
|
||||
{
|
||||
var repeatContext = new RepeatContext
|
||||
{
|
||||
Limit = repeatAttribute.RunCount
|
||||
};
|
||||
|
||||
var timeTaken = 0.0M;
|
||||
var testLogger = new LoggedTestInvoker(
|
||||
Test,
|
||||
MessageBus,
|
||||
TestClass,
|
||||
ConstructorArguments,
|
||||
TestMethod,
|
||||
TestMethodArguments,
|
||||
BeforeAfterAttributes,
|
||||
aggregator,
|
||||
CancellationTokenSource,
|
||||
output,
|
||||
repeatContext,
|
||||
collectDump);
|
||||
|
||||
for (repeatContext.CurrentIteration = 0; repeatContext.CurrentIteration < repeatContext.Limit; repeatContext.CurrentIteration++)
|
||||
{
|
||||
timeTaken = await testLogger.RunAsync();
|
||||
if (aggregator.HasExceptions)
|
||||
{
|
||||
return timeTaken;
|
||||
}
|
||||
}
|
||||
|
||||
return timeTaken;
|
||||
}
|
||||
|
||||
private RepeatAttribute GetRepeatAttribute(MethodInfo methodInfo)
|
||||
{
|
||||
var attributeCandidate = methodInfo.GetCustomAttribute<RepeatAttribute>();
|
||||
if (attributeCandidate != null)
|
||||
{
|
||||
return attributeCandidate;
|
||||
}
|
||||
|
||||
attributeCandidate = methodInfo.DeclaringType.GetCustomAttribute<RepeatAttribute>();
|
||||
if (attributeCandidate != null)
|
||||
{
|
||||
return attributeCandidate;
|
||||
}
|
||||
|
||||
return methodInfo.DeclaringType.Assembly.GetCustomAttribute<RepeatAttribute>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
// 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.Collections.Generic;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class LoggedTheoryDiscoverer : TheoryDiscoverer
|
||||
{
|
||||
public LoggedTheoryDiscoverer(IMessageSink diagnosticMessageSink) : base(diagnosticMessageSink)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IEnumerable<IXunitTestCase> CreateTestCasesForDataRow(
|
||||
ITestFrameworkDiscoveryOptions discoveryOptions,
|
||||
ITestMethod testMethod,
|
||||
IAttributeInfo theoryAttribute,
|
||||
object[] dataRow)
|
||||
=> new[] { new LoggedTestCase(DiagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), TestMethodDisplayOptions.None, testMethod, dataRow) };
|
||||
|
||||
protected override IEnumerable<IXunitTestCase> CreateTestCasesForTheory(
|
||||
ITestFrameworkDiscoveryOptions discoveryOptions,
|
||||
ITestMethod testMethod,
|
||||
IAttributeInfo theoryAttribute)
|
||||
=> new[] { new LoggedTheoryTestCase(DiagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), TestMethodDisplayOptions.None, testMethod) };
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
// 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;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class LoggedTheoryTestCase : XunitTheoryTestCase
|
||||
{
|
||||
[Obsolete("Called by the de-serializer; should only be called by deriving classes for de-serialization purposes")]
|
||||
public LoggedTheoryTestCase() : base()
|
||||
{
|
||||
}
|
||||
|
||||
public LoggedTheoryTestCase(
|
||||
IMessageSink diagnosticMessageSink,
|
||||
TestMethodDisplay defaultMethodDisplay,
|
||||
TestMethodDisplayOptions defaultMethodDisplayOptions,
|
||||
ITestMethod testMethod)
|
||||
: base(diagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, testMethod)
|
||||
{
|
||||
}
|
||||
|
||||
public override Task<RunSummary> RunAsync(
|
||||
IMessageSink diagnosticMessageSink,
|
||||
IMessageBus messageBus,
|
||||
object[] constructorArguments,
|
||||
ExceptionAggregator aggregator,
|
||||
CancellationTokenSource cancellationTokenSource)
|
||||
=> new LoggedTheoryTestCaseRunner(this, DisplayName, SkipReason, constructorArguments, diagnosticMessageSink, messageBus, aggregator, cancellationTokenSource).RunAsync();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
// 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.Reflection;
|
||||
using System.Threading;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
public class LoggedTheoryTestCaseRunner : XunitTheoryTestCaseRunner
|
||||
{
|
||||
public LoggedTheoryTestCaseRunner(
|
||||
IXunitTestCase testCase,
|
||||
string displayName,
|
||||
string skipReason,
|
||||
object[] constructorArguments,
|
||||
IMessageSink diagnosticMessageSink,
|
||||
IMessageBus messageBus,
|
||||
ExceptionAggregator aggregator,
|
||||
CancellationTokenSource cancellationTokenSource)
|
||||
: base(testCase, displayName, skipReason, constructorArguments, diagnosticMessageSink, messageBus, aggregator, cancellationTokenSource)
|
||||
{
|
||||
}
|
||||
|
||||
protected override XunitTestRunner CreateTestRunner(
|
||||
ITest test,
|
||||
IMessageBus messageBus,
|
||||
Type testClass,
|
||||
object[] constructorArguments,
|
||||
MethodInfo testMethod,
|
||||
object[] testMethodArguments,
|
||||
string skipReason,
|
||||
IReadOnlyList<BeforeAfterTestAttribute> beforeAfterAttributes,
|
||||
ExceptionAggregator aggregator,
|
||||
CancellationTokenSource cancellationTokenSource)
|
||||
=> new LoggedTestRunner(test, messageBus, testClass, constructorArguments, testMethod, testMethodArguments, skipReason, beforeAfterAttributes, new ExceptionAggregator(aggregator), cancellationTokenSource);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
// 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.ComponentModel;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing
|
||||
{
|
||||
/// <summary>
|
||||
/// Runs a test multiple times to stress flaky tests that are believed to be fixed.
|
||||
/// This can be used on an assembly, class, or method name.
|
||||
/// Requires using <see cref="LoggedTest"/> to run.
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = false)]
|
||||
public class RepeatAttribute : Attribute
|
||||
{
|
||||
public RepeatAttribute(int runCount = 10)
|
||||
{
|
||||
RunCount = runCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The number of times to run a test.
|
||||
/// </summary>
|
||||
public int RunCount { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -11,8 +11,8 @@
|
|||
Condition="'$(GenerateLoggingTestingAssemblyAttributes)' != 'false'">
|
||||
<ItemGroup>
|
||||
<AssemblyAttribute Include="Xunit.TestFramework">
|
||||
<_Parameter1>Microsoft.Extensions.Logging.Testing.LoggedTestFramework</_Parameter1>
|
||||
<_Parameter2>Microsoft.Extensions.Logging.Testing</_Parameter2>
|
||||
<_Parameter1>Microsoft.AspNetCore.Testing.AspNetTestFramework</_Parameter1>
|
||||
<_Parameter2>Microsoft.AspNetCore.Testing</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="Microsoft.Extensions.Logging.Testing.TestFrameworkFileLoggerAttribute">
|
||||
|
|
|
|||
|
|
@ -18,12 +18,6 @@ namespace Microsoft.Extensions.Logging.Testing.Tests
|
|||
private static readonly string ThisAssemblyName = ThisAssembly.GetName().Name;
|
||||
private static readonly string TFM = new DirectoryInfo(AppContext.BaseDirectory).Name;
|
||||
|
||||
[Fact]
|
||||
public void FullClassNameUsedWhenShortClassNameAttributeNotSpecified()
|
||||
{
|
||||
Assert.Equal(GetType().FullName, ResolvedTestClassName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ForAssembly_ReturnsSameInstanceForSameAssembly()
|
||||
{
|
||||
|
|
@ -57,7 +51,7 @@ namespace Microsoft.Extensions.Logging.Testing.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
private Task TestLogEscapesIllegalFileNames() =>
|
||||
public Task TestLogEscapesIllegalFileNames() =>
|
||||
RunTestLogFunctionalTest((tempDir) =>
|
||||
{
|
||||
var illegalTestName = "T:e/s//t";
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
// 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 Xunit;
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Testing.Tests
|
||||
{
|
||||
[Repeat]
|
||||
public class LoggedTestXunitRepeatTests : LoggedTest
|
||||
{
|
||||
public static int _runCount = 0;
|
||||
|
||||
[Fact]
|
||||
[Repeat(5)]
|
||||
public void RepeatLimitIsSetCorrectly()
|
||||
{
|
||||
Assert.Equal(5, RepeatContext.Limit);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Repeat(5)]
|
||||
public void RepeatRunsTestSpecifiedNumberOfTimes()
|
||||
{
|
||||
Assert.Equal(RepeatContext.CurrentIteration, _runCount);
|
||||
_runCount++;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RepeatCanBeSetOnClass()
|
||||
{
|
||||
Assert.Equal(10, RepeatContext.Limit);
|
||||
}
|
||||
}
|
||||
|
||||
public class LoggedTestXunitRepeatAssemblyTests : LoggedTest
|
||||
{
|
||||
[Fact]
|
||||
public void RepeatCanBeSetOnAssembly()
|
||||
{
|
||||
Assert.Equal(1, RepeatContext.Limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,18 +21,6 @@ namespace Microsoft.Extensions.Logging.Testing.Tests
|
|||
_output = output;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShortClassNameUsedWhenShortClassNameAttributeSpecified()
|
||||
{
|
||||
Assert.Equal(GetType().Name, ResolvedTestClassName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LoggedTestTestOutputHelperSameInstanceAsInjectedConstructorArg()
|
||||
{
|
||||
Assert.Same(_output, TestOutputHelper);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LoggedFactInitializesLoggedTestProperties()
|
||||
{
|
||||
|
|
@ -189,9 +177,9 @@ namespace Microsoft.Extensions.Logging.Testing.Tests
|
|||
public bool SetupInvoked { get; private set; } = false;
|
||||
public bool ITestOutputHelperIsInitialized { get; private set; } = false;
|
||||
|
||||
public override void Initialize(MethodInfo methodInfo, object[] testMethodArguments, ITestOutputHelper testOutputHelper)
|
||||
public override void Initialize(TestContext context, MethodInfo methodInfo, object[] testMethodArguments, ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
base.Initialize(methodInfo, testMethodArguments, testOutputHelper);
|
||||
base.Initialize(context, methodInfo, testMethodArguments, testOutputHelper);
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,4 +2,3 @@ using Microsoft.Extensions.Logging;
|
|||
using Microsoft.Extensions.Logging.Testing;
|
||||
|
||||
[assembly: LogLevel(LogLevel.Trace)]
|
||||
[assembly: Repeat(1)]
|
||||
|
|
|
|||
Loading…
Reference in New Issue