212 lines
6.4 KiB
C#
212 lines
6.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using System.Xml.Linq;
|
|
using Unity.PerformanceTesting.Data;
|
|
using UnityEditor.TestTools.TestRunner.Api;
|
|
using UnityEngine;
|
|
|
|
namespace Unity.PerformanceTesting.Editor
|
|
{
|
|
static class TestResultsParser
|
|
{
|
|
internal static Run GetPerformanceTestRunData(ITestResultAdaptor testResults)
|
|
{
|
|
var testOutputs = GetTestOutputsRecursively(testResults);
|
|
return ExtractPerformanceRunData(testOutputs);
|
|
}
|
|
|
|
internal static Run GetPerformanceTestRunDataFromXmlFile(string xmlResultsPath)
|
|
{
|
|
try
|
|
{
|
|
var xmlDocument = XDocument.Load(xmlResultsPath);
|
|
return GetPerformanceTestRunData(xmlDocument);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.LogWarning("Failed to load performance test results from XML.\n" +
|
|
$"{e.GetType()}: {e.Message}\n" +
|
|
$"{e.StackTrace}");
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
static Run GetPerformanceTestRunData(XDocument testResults)
|
|
{
|
|
var testOutputs = testResults.Descendants("output")
|
|
.Select(outputElement => outputElement.Value)
|
|
.ToArray();
|
|
|
|
return ExtractPerformanceRunData(testOutputs);
|
|
}
|
|
|
|
static string[] GetTestOutputsRecursively(ITestResultAdaptor testResults)
|
|
{
|
|
var res = new List<string>();
|
|
if (testResults != null)
|
|
{
|
|
AccumulateTestRunOutputRecursively(testResults, res);
|
|
}
|
|
|
|
return res.ToArray();
|
|
}
|
|
|
|
static void AccumulateTestRunOutputRecursively(ITestResultAdaptor parentResult, List<string> outputs)
|
|
{
|
|
var children = parentResult.Children;
|
|
foreach (var child in children)
|
|
{
|
|
AccumulateTestRunOutputRecursively(child, outputs);
|
|
}
|
|
|
|
var currentTestOutput = parentResult.Output;
|
|
if (!string.IsNullOrEmpty(currentTestOutput))
|
|
{
|
|
outputs.Add(currentTestOutput);
|
|
}
|
|
}
|
|
|
|
internal static Run ExtractPerformanceRunData(string[] testOutputs)
|
|
{
|
|
if (testOutputs == null || testOutputs.Length == 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
try
|
|
{
|
|
var run = ExtractPerformanceTestRunInfo(testOutputs);
|
|
if (run != null)
|
|
{
|
|
DeserializeTestResults(testOutputs, run);
|
|
}
|
|
|
|
return run;
|
|
}
|
|
catch (FormatException fe)
|
|
{
|
|
Debug.LogError($"Invalid performance test results format: {fe.Message}");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.LogError($"Unexpected exception while reading performance test results: {e.Message}");
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
static Run ExtractPerformanceTestRunInfo(string[] testOutputs)
|
|
{
|
|
foreach (var output in testOutputs)
|
|
{
|
|
const string pattern = @"##performancetestruninfo2:(.+)\n";
|
|
var regex = new Regex(pattern);
|
|
var matches = regex.Match(output);
|
|
if (matches.Groups.Count == 0 || matches.Captures.Count == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (matches.Groups[1].Captures.Count > 1)
|
|
{
|
|
throw new FormatException("Multiple execution metadata instances found.");
|
|
}
|
|
|
|
var json = matches.Groups[1].Value;
|
|
if (string.IsNullOrEmpty(json))
|
|
{
|
|
throw new FormatException("No execution metadata found.");
|
|
}
|
|
|
|
return ReadPerformanceTestRunJsonObject(json);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
static Run ReadPerformanceTestRunJsonObject(string json)
|
|
{
|
|
try
|
|
{
|
|
return JsonUtility.FromJson<Run>(json);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
throw new FormatException($"Failed to read performance execution metadata from json string: '{json}'.\n" +
|
|
$"Exception: {e.Message}\n" +
|
|
$"{e.StackTrace}");
|
|
}
|
|
}
|
|
|
|
static void DeserializeTestResults(string[] testOutputs, Run run)
|
|
{
|
|
foreach (var output in testOutputs)
|
|
{
|
|
foreach (var line in output.Split('\n'))
|
|
{
|
|
var json = GetJsonFromHashtag("performancetestresult2", line);
|
|
if (json == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var result = ReadPerformanceTestResultJsonObject(json);
|
|
if (result != null)
|
|
{
|
|
run.Results.Add(result);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static PerformanceTestResult ReadPerformanceTestResultJsonObject(string json)
|
|
{
|
|
try
|
|
{
|
|
return JsonUtility.FromJson<PerformanceTestResult>(json);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.LogWarning($"Failed to read performance results from json string: '{json}'.\n" +
|
|
$"Exception: {e.Message}\n" +
|
|
$"{e.StackTrace}");
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
static string GetJsonFromHashtag(string tag, string line)
|
|
{
|
|
if (!line.Contains($"##{tag}:"))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var jsonStart = line.IndexOf('{');
|
|
var openBrackets = 0;
|
|
var stringIndex = jsonStart;
|
|
while (openBrackets > 0 || stringIndex == jsonStart)
|
|
{
|
|
var character = line[stringIndex];
|
|
switch (character)
|
|
{
|
|
case '{':
|
|
openBrackets++;
|
|
break;
|
|
case '}':
|
|
openBrackets--;
|
|
break;
|
|
}
|
|
|
|
stringIndex++;
|
|
}
|
|
|
|
var jsonEnd = stringIndex;
|
|
return line.Substring(jsonStart, jsonEnd - jsonStart);
|
|
}
|
|
}
|
|
}
|