зеркало из https://github.com/aspnet/Stress.git
Add stress reporting infrastructure to conditionally output stress results.
- The default reporting mechanisms do not output stress data. - Can be overridden by configuration file `stressConfig.json` and running the tests with a `-stressconfig` option. - Updated runner to pass through metric information. - Updated `.gitignore` with `TestOutput`
This commit is contained in:
Родитель
9801e861fe
Коммит
c9999cd9df
|
@ -7,6 +7,7 @@ _ReSharper.*/
|
|||
packages/
|
||||
artifacts/
|
||||
PublishProfiles/
|
||||
TestOutput/
|
||||
*.user
|
||||
*.suo
|
||||
*.cache
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNet.StressFramework.Collectors
|
||||
{
|
||||
|
|
|
@ -6,13 +6,14 @@ namespace Microsoft.AspNet.StressFramework.Collectors
|
|||
{
|
||||
public class MetricsRecordedMessage : IMessageSinkMessage
|
||||
{
|
||||
private ITest Test { get; }
|
||||
private IReadOnlyList<Metric> Metrics { get; }
|
||||
|
||||
public MetricsRecordedMessage(ITest test, IEnumerable<Metric> metrics)
|
||||
{
|
||||
Test = test;
|
||||
Metrics = metrics.ToList().AsReadOnly();
|
||||
}
|
||||
|
||||
public ITest Test { get; }
|
||||
|
||||
public IReadOnlyList<Metric> Metrics { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using Microsoft.AspNet.StressFramework.Collectors;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNet.StressFramework
|
||||
{
|
||||
public abstract class DefaultStressTestMessageVisitor : DefaultRunnerReporterMessageHandler
|
||||
{
|
||||
public DefaultStressTestMessageVisitor(IRunnerLogger logger)
|
||||
: base(logger)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool OnMessage(IMessageSinkMessage message)
|
||||
{
|
||||
return DoVisit<MetricsRecordedMessage>(message, (t, m) => t.Visit(m)) &&
|
||||
base.OnMessage(message);
|
||||
}
|
||||
|
||||
protected virtual bool Visit(MetricsRecordedMessage metric)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DoVisit<TMessage>(IMessageSinkMessage message, Func<DefaultStressTestMessageVisitor, TMessage, bool> callback)
|
||||
where TMessage : class, IMessageSinkMessage
|
||||
{
|
||||
var castMessage = message as TMessage;
|
||||
if (castMessage != null)
|
||||
{
|
||||
return callback(this, castMessage);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNet.StressFramework
|
||||
{
|
||||
public class DefaultStressTestRunnerReporter : DefaultRunnerReporter
|
||||
{
|
||||
public override string RunnerSwitch => "stress";
|
||||
|
||||
public override string Description => "doesn't output stress test results.";
|
||||
|
||||
public override IMessageSink CreateMessageHandler(IRunnerLogger logger)
|
||||
{
|
||||
return new DefaultRunnerReporterMessageHandler(new ConsoleRunnerLogger(useColors: true));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -49,7 +49,7 @@ namespace Microsoft.AspNet.StressFramework
|
|||
DisplayName = suppliedDisplayName ?? BaseDisplayName;
|
||||
Iterations = iterations;
|
||||
WarmupIterations = warmupIterations;
|
||||
|
||||
|
||||
TestMethodArguments = testMethodArguments?.ToArray();
|
||||
}
|
||||
|
||||
|
|
|
@ -13,10 +13,6 @@ namespace Microsoft.AspNet.StressFramework
|
|||
private readonly IMessageBus _bus;
|
||||
private readonly Process _me;
|
||||
|
||||
private MemoryUsage _startMemory;
|
||||
private MemoryUsage _endMemory;
|
||||
private CpuTime _startCpu;
|
||||
|
||||
public IReadOnlyList<Metric> Recordings { get; }
|
||||
public int Iteration { get; }
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ using Xunit.Abstractions;
|
|||
using Xunit.Sdk;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.StressFramework.Collectors;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
#if DNXCORE50 || DNX451
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.StressFramework.Collectors;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNet.StressFramework
|
||||
{
|
||||
public class StressTestRunnerCSVReporter : DefaultRunnerReporter
|
||||
{
|
||||
public override string RunnerSwitch => "stresscsv";
|
||||
|
||||
public override string Description => "output stress test results to CSV files. 1 CSV file per test.";
|
||||
|
||||
public override IMessageSink CreateMessageHandler(IRunnerLogger logger)
|
||||
{
|
||||
return new CSVRunnerReporterMessageHandler(new ConsoleRunnerLogger(useColors: true));
|
||||
}
|
||||
|
||||
private class CSVRunnerReporterMessageHandler : DefaultStressTestMessageVisitor
|
||||
{
|
||||
public CSVRunnerReporterMessageHandler(IRunnerLogger logger)
|
||||
: base(logger)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool Visit(MetricsRecordedMessage metricsRecordedMessage)
|
||||
{
|
||||
Debug.Assert(metricsRecordedMessage.Test.TestCase is StressTestCase);
|
||||
|
||||
WriteCSV(metricsRecordedMessage);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void WriteCSV(MetricsRecordedMessage metricsRecordedMessage)
|
||||
{
|
||||
var test = metricsRecordedMessage.Test;
|
||||
var metrics = metricsRecordedMessage.Metrics;
|
||||
var testOutputDir = Path.Combine(Directory.GetCurrentDirectory(), "TestOutput");
|
||||
if (!Directory.Exists(testOutputDir))
|
||||
{
|
||||
Directory.CreateDirectory(testOutputDir);
|
||||
}
|
||||
|
||||
var outputFile = Path.Combine(testOutputDir, $"{test.TestCase.DisplayName}.{test.TestCase.UniqueID}.metrics.csv");
|
||||
|
||||
using (var writer = new StreamWriter(new FileStream(outputFile, FileMode.Create)))
|
||||
{
|
||||
writer.WriteLine("Iteration,Heap,WorkingSet,PrivateBytes,ElapsedTicks");
|
||||
|
||||
foreach (var iteration in metrics.GroupBy(g => g.Iteration).OrderBy(g => g.Key))
|
||||
{
|
||||
var elapsed = (ElapsedTime)iteration.Single(m => m.Value is ElapsedTime).Value;
|
||||
var mem = (MemoryUsage)iteration.Single(m => m.Value is MemoryUsage).Value;
|
||||
writer.WriteLine($"{iteration.Key},{mem.HeapMemoryBytes},{mem.WorkingSet},{mem.PrivateBytes},{elapsed.Elapsed.Ticks}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.Framework.Configuration;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNet.StressFramework
|
||||
{
|
||||
public class StressTestRunnerConfigReporter : DefaultRunnerReporter
|
||||
{
|
||||
private const string StressConfigFileName = "stressConfig.json";
|
||||
private const string StressOutputReporterConfigName = "StressOutputReporter";
|
||||
private static readonly Lazy<IRunnerReporter> _defaultReporter = new Lazy<IRunnerReporter>(
|
||||
() => new DefaultStressTestRunnerReporter());
|
||||
private static readonly Lazy<IRunnerReporter> _csvReporter = new Lazy<IRunnerReporter>(
|
||||
() => new StressTestRunnerCSVReporter());
|
||||
private IRunnerReporter _activeReporter;
|
||||
|
||||
private IRunnerReporter DefaultReporter => _defaultReporter.Value;
|
||||
private IRunnerReporter CSVReporter => _csvReporter.Value;
|
||||
|
||||
public override string RunnerSwitch => "stressconfig";
|
||||
|
||||
public override string Description => "determine stress output mechanism based on ";
|
||||
|
||||
public override IMessageSink CreateMessageHandler(IRunnerLogger logger)
|
||||
{
|
||||
if (_activeReporter == null)
|
||||
{
|
||||
var stressConfigFile = new FileInfo(StressConfigFileName);
|
||||
if (!stressConfigFile.Exists)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Cannot determine stress configuration. {StressConfigFileName} does not exist.");
|
||||
}
|
||||
|
||||
var config = new ConfigurationBuilder(".")
|
||||
.AddJsonFile(StressConfigFileName)
|
||||
.Build();
|
||||
var stressTestOutputReporterName = config[StressOutputReporterConfigName];
|
||||
|
||||
if (!string.IsNullOrEmpty(stressTestOutputReporterName) ||
|
||||
string.Equals(
|
||||
stressTestOutputReporterName,
|
||||
DefaultReporter.RunnerSwitch,
|
||||
StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_activeReporter = DefaultReporter;
|
||||
}
|
||||
else if (string.Equals(
|
||||
stressTestOutputReporterName,
|
||||
CSVReporter.RunnerSwitch,
|
||||
StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_activeReporter = CSVReporter;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Unknown {StressOutputReporterConfigName} value in {StressConfigFileName}.");
|
||||
}
|
||||
}
|
||||
|
||||
return _activeReporter.CreateMessageHandler(logger);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,17 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"dependencies": {
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
"Microsoft.Framework.Configuration.Json": "1.0.0-*",
|
||||
"xunit.assert": "2.1.0-*",
|
||||
"xunit.core": "2.1.0-*",
|
||||
"xunit.runner.dnx": "2.1.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnx451": { },
|
||||
"dnx451": {
|
||||
"frameworkAssemblies": {
|
||||
"System.Reflection": "4.0.0.0"
|
||||
}
|
||||
},
|
||||
"dnxcore50": {
|
||||
"dependencies": {
|
||||
"System.Runtime": "4.0.21-beta-*"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"commands": {
|
||||
"test": "xunit.runner.aspnet"
|
||||
"test": "xunit.runner.dnx"
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.StressFramework": "",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"commands": {
|
||||
"test": "xunit.runner.aspnet"
|
||||
"test": "xunit.runner.dnx"
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.StressFramework": "",
|
||||
|
|
Загрузка…
Ссылка в новой задаче