提交 881089ed 编写于 作者: J Jared Parsons

Merge pull request #11397 from jaredpar/json

Minor updates to the test runner
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RestSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace RunTests.Cache
{
internal partial class WebDataStorage
{
internal sealed class TestResultData
{
[JsonProperty(Required = Required.Always)]
public int ExitCode { get; set; }
[JsonProperty(Required = Required.Always)]
public string OutputStandard { get; set; }
[JsonProperty(Required = Required.AllowNull)]
public string OutputError { get; set; }
public string ResultsFileName { get; set; }
[JsonProperty(Required = Required.AllowNull)]
public string ResultsFileContent { get; set; }
public int ElapsedSeconds { get; set; }
public int TestPassed { get; set; }
public int TestFailed { get; set; }
public int TestSkipped { get; set; }
}
internal sealed class TestSourceData
{
public string MachineName { get; set; }
public string EnlistmentRoot { get; set; }
public string AssemblyName { get; set; }
public string Source { get; set; }
public bool IsJenkins { get; set; }
}
internal sealed class TestCacheData
{
public TestResultData TestResultData { get; set; }
public TestSourceData TestSourceData { get; set; }
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RestSharp;
using System;
......@@ -13,18 +14,8 @@
namespace RunTests.Cache
{
internal sealed class WebDataStorage : IDataStorage
internal sealed partial class WebDataStorage : IDataStorage
{
private const string NameExitCode = "exitCode";
private const string NameOutputStandard = "outputStandard";
private const string NameOutputError = "outputError";
private const string NameResultsFileName = "resultsFileName";
private const string NameResultsFileContent = "resultsFileContent";
private const string NameElapsedSeconds = "elapsedSeconds";
private const string NameTestPassed = "testPassed";
private const string NameTestFailed = "testFailed";
private const string NameTestSkipped = "testSkipped";
private readonly RestClient _restClient = new RestClient(Constants.DashboardUriString);
public string Name => "web";
......@@ -33,14 +24,11 @@ public async Task AddCachedTestResult(AssemblyInfo assemblyInfo, ContentFile con
{
try
{
var obj = new JObject();
obj["TestResultData"] = CreateTestResultData(assemblyInfo.ResultsFileName, testResult);
obj["TestSourceData"] = CreateTestSourceData(assemblyInfo);
var request = new RestRequest($"api/testcache/{contentFile.Checksum}");
var testCacheData = CreateTestCacheData(assemblyInfo, assemblyInfo.ResultsFileName, testResult);
var request = new RestRequest($"api/testData/cache/{contentFile.Checksum}");
request.Method = Method.PUT;
request.RequestFormat = DataFormat.Json;
request.AddParameter("text/json", obj.ToString(), ParameterType.RequestBody);
request.AddParameter("text/json", JsonConvert.SerializeObject(testCacheData), ParameterType.RequestBody);
var response = await _restClient.ExecuteTaskAsync(request);
if (response.StatusCode != HttpStatusCode.NoContent)
......@@ -58,7 +46,7 @@ public async Task AddCachedTestResult(AssemblyInfo assemblyInfo, ContentFile con
{
try
{
var request = new RestRequest($"api/testcache/{checksum}");
var request = new RestRequest($"api/testData/cache/{checksum}");
// Add query parameters the web service uses for additional tracking
request.AddParameter("machineName", Environment.MachineName, ParameterType.QueryString);
......@@ -75,13 +63,13 @@ public async Task AddCachedTestResult(AssemblyInfo assemblyInfo, ContentFile con
return null;
}
var obj = JObject.Parse(response.Content);
var testCacheData = JsonConvert.DeserializeObject<TestResultData>(response.Content);
var result = new CachedTestResult(
exitCode: obj.Value<int>(NameExitCode),
standardOutput: obj.Value<string>(NameOutputStandard),
errorOutput: obj.Value<string>(NameOutputError),
resultsFileContent: obj.Value<string>(NameResultsFileContent),
elapsed: TimeSpan.FromSeconds(obj.Value<int>(NameElapsedSeconds)));
exitCode: testCacheData.ExitCode,
standardOutput: testCacheData.OutputStandard,
errorOutput: testCacheData.OutputError,
resultsFileContent: testCacheData.ResultsFileName,
elapsed: TimeSpan.FromSeconds(testCacheData.ElapsedSeconds));
return result;
}
catch (Exception ex)
......@@ -91,31 +79,41 @@ public async Task AddCachedTestResult(AssemblyInfo assemblyInfo, ContentFile con
}
}
private static JObject CreateTestResultData(string resultsFileName, CachedTestResult testResult)
private static TestCacheData CreateTestCacheData(AssemblyInfo assemblyInfo, string resultsFileName, CachedTestResult testResult)
{
var numbers = GetTestNumbers(resultsFileName, testResult) ?? Tuple.Create(-1, -1, -1);
var obj = new JObject();
obj[NameExitCode] = testResult.ExitCode;
obj[NameOutputStandard] = testResult.StandardOutput;
obj[NameOutputError] = testResult.ErrorOutput;
obj[NameResultsFileName] = resultsFileName;
obj[NameResultsFileContent] = testResult.ResultsFileContent;
obj[NameElapsedSeconds] = (int)testResult.Elapsed.TotalSeconds;
obj[NameTestPassed] = numbers.Item1;
obj[NameTestFailed] = numbers.Item2;
obj[NameTestSkipped] = numbers.Item3;
return new TestCacheData()
{
TestResultData = CreateTestResultData(resultsFileName, testResult),
TestSourceData = CreateTestSourceData(assemblyInfo)
};
}
return obj;
private static TestResultData CreateTestResultData(string resultsFileName, CachedTestResult testResult)
{
var numbers = GetTestNumbers(resultsFileName, testResult) ?? Tuple.Create(-1, -1, -1);
return new TestResultData()
{
ExitCode = testResult.ExitCode,
OutputStandard = testResult.StandardOutput,
OutputError = testResult.ErrorOutput,
ResultsFileName = resultsFileName,
ResultsFileContent = testResult.ResultsFileContent,
ElapsedSeconds = (int)testResult.Elapsed.TotalSeconds,
TestPassed = numbers.Item1,
TestFailed = numbers.Item2,
TestSkipped = numbers.Item3
};
}
private JObject CreateTestSourceData(AssemblyInfo assemblyInfo)
private static TestSourceData CreateTestSourceData(AssemblyInfo assemblyInfo)
{
var obj = new JObject();
obj["MachineName"] = Environment.MachineName;
obj["TestRoot"] = "";
obj["AssemblyName"] = assemblyInfo.DisplayName;
obj["IsJenkins"] = Constants.IsJenkinsRun;
return obj;
return new TestSourceData()
{
MachineName = Environment.MachineName,
EnlistmentRoot = Constants.EnlistmentRoot,
AssemblyName = assemblyInfo.DisplayName,
IsJenkins = Constants.IsJenkinsRun
};
}
private static Tuple<int, int, int> GetTestNumbers(string resultsFileName, CachedTestResult testResult)
......@@ -128,7 +126,7 @@ private JObject CreateTestSourceData(AssemblyInfo assemblyInfo)
try
{
using (var reader = new StringReader(testResult.ResultsFileContent))
{
{
var document = XDocument.Load(reader);
var assembly = document.Element("assemblies").Element("assembly");
var passed = int.Parse(assembly.Attribute("passed").Value);
......
......@@ -121,8 +121,8 @@ public async Task<TestResult> RunTestAsync(AssemblyInfo assemblyInfo, Cancellati
var commandLine = GetCommandLine(assemblyInfo);
Logger.Log($"Command line {assemblyInfo.DisplayName}: {commandLine}");
var standardOutput = string.Join(Environment.NewLine, processOutput.OutputLines);
var errorOutput = string.Join(Environment.NewLine, processOutput.ErrorLines);
var standardOutput = string.Join(Environment.NewLine, processOutput.OutputLines) ?? "";
var errorOutput = string.Join(Environment.NewLine, processOutput.ErrorLines) ?? "";
return new TestResult(
exitCode: processOutput.ExitCode,
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RunTests
{
internal partial class Program
{
internal sealed class TestRunData
{
public string Cache { get; set; }
public int ElapsedSeconds { get; set; }
public bool Succeeded { get; set; }
public bool IsJenkins { get; set; }
public bool Is32Bit { get; set; }
public int AssemblyCount { get; set; }
public int CacheCount { get; set; }
public int ChunkCount { get; set; }
}
}
}
......@@ -12,10 +12,11 @@
using Newtonsoft.Json.Linq;
using RestSharp;
using System.Collections.Immutable;
using Newtonsoft.Json;
namespace RunTests
{
internal sealed class Program
internal sealed partial class Program
{
internal const int ExitSuccess = 0;
internal const int ExitFailure = 1;
......@@ -213,24 +214,21 @@ private static IOrderedEnumerable<string> OrderAssemblyList(IEnumerable<string>
private static async Task SendRunStats(Options options, IDataStorage dataStorage, TimeSpan elapsed, RunAllResult result, int partitionCount, CancellationToken cancellationToken)
{
var obj = new JObject();
obj["Cache"] = dataStorage.Name;
obj["ElapsedSeconds"] = (int)elapsed.TotalSeconds;
obj["IsJenkins"] = Constants.IsJenkinsRun;
obj["Is32Bit"] = !options.Test64;
obj["AssemblyCount"] = options.Assemblies.Count;
obj["CacheCount"] = result.CacheCount;
obj["ChunkCount"] = partitionCount;
obj["PartitionCount"] = partitionCount;
obj["Succeeded"] = result.Succeeded;
// During the transition from ellapsed to elapsed the client needs to provide both
// spellings for the server.
obj["EllapsedSeconds"] = (int)elapsed.TotalSeconds;
var request = new RestRequest("api/testrun", Method.POST);
var testRunData = new TestRunData()
{
Cache = dataStorage.Name,
ElapsedSeconds = (int)elapsed.TotalSeconds,
IsJenkins = Constants.IsJenkinsRun,
Is32Bit = !options.Test64,
AssemblyCount = options.Assemblies.Count,
ChunkCount = partitionCount,
CacheCount = result.CacheCount,
Succeeded = result.Succeeded
};
var request = new RestRequest("api/testData/run", Method.POST);
request.RequestFormat = DataFormat.Json;
request.AddParameter("text/json", obj.ToString(), ParameterType.RequestBody);
request.AddParameter("text/json", JsonConvert.SerializeObject(testRunData), ParameterType.RequestBody);
try
{
......
......@@ -32,6 +32,7 @@
<Compile Include="Cache\CachingTestExecutor.cs" />
<Compile Include="Cache\ContentFile.cs" />
<Compile Include="Cache\EmptyDataStorage.cs" />
<Compile Include="Cache\WebDataStorage.Json.cs" />
<Compile Include="Cache\WebDataStorage.cs" />
<Compile Include="Constants.cs" />
<Compile Include="CrashDumps.cs" />
......@@ -48,6 +49,7 @@
<Compile Include="ConsoleUtil.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program..Json.cs" />
<None Include="project.json" />
</ItemGroup>
<ItemGroup>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册