179 lines
5.7 KiB
C#
179 lines
5.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using System.Xml.Linq;
|
|
using Unity.PerformanceTesting.Data;
|
|
using UnityEngine;
|
|
|
|
namespace Unity.PerformanceTesting.Editor
|
|
{
|
|
/// <summary>
|
|
/// Helper class to parse test runs into performance test runs.
|
|
/// </summary>
|
|
public class TestResultXmlParser
|
|
{
|
|
/// <summary>
|
|
/// Parses performance test run from test run result xml.
|
|
/// </summary>
|
|
/// <param name="resultXmlFileName">Path to test results xml file.</param>
|
|
/// <returns></returns>
|
|
public Run GetPerformanceTestRunFromXml(string resultXmlFileName)
|
|
{
|
|
ValidateInput(resultXmlFileName);
|
|
var xmlDocument = TryLoadResultXmlFile(resultXmlFileName);
|
|
var performanceTestRun = TryParseXmlToPerformanceTestRun(xmlDocument);
|
|
return performanceTestRun;
|
|
}
|
|
|
|
private void ValidateInput(string resultXmlFileName)
|
|
{
|
|
if (string.IsNullOrEmpty(resultXmlFileName))
|
|
{
|
|
Debug.LogWarning($"Test results path is null or empty.");
|
|
}
|
|
|
|
if (!File.Exists(resultXmlFileName))
|
|
{
|
|
Debug.LogWarning($"Test results file does not exists at path: {resultXmlFileName}");
|
|
}
|
|
}
|
|
|
|
private XDocument TryLoadResultXmlFile(string resultXmlFileName)
|
|
{
|
|
try
|
|
{
|
|
return XDocument.Load(resultXmlFileName);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var errMsg = $"Failed to load xml result file: {resultXmlFileName}";
|
|
Debug.LogWarning($"{errMsg}\r\nException: {e.Message}\r\n{e.StackTrace}");
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private Run TryParseXmlToPerformanceTestRun(XContainer xmlDocument)
|
|
{
|
|
var output = xmlDocument.Descendants("output").ToArray();
|
|
if (!output.Any())
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var run = DeserializeMetadata(output);
|
|
DeserializeTestResults(output, run);
|
|
return run;
|
|
}
|
|
|
|
private void DeserializeTestResults(IEnumerable<XElement> output, Run run)
|
|
{
|
|
foreach (var element in output)
|
|
{
|
|
foreach (var line in element.Value.Split('\n'))
|
|
{
|
|
var json = GetJsonFromHashtag("performancetestresult2", line);
|
|
if (json == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var result = TryDeserializePerformanceTestResultJsonObject(json);
|
|
if (result != null)
|
|
{
|
|
run.Results.Add(result);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private Run DeserializeMetadata(IEnumerable<XElement> output)
|
|
{
|
|
foreach (var element in output)
|
|
{
|
|
var pattern = @"##performancetestruninfo2:(.+)\n";
|
|
var regex = new Regex(pattern);
|
|
var matches = regex.Match(element.Value);
|
|
if (matches.Groups.Count == 0) continue;
|
|
if (matches.Captures.Count == 0) continue;
|
|
|
|
if (matches.Groups[1].Captures.Count > 1)
|
|
{
|
|
Debug.LogError("Performance test run had multiple hardware and player settings, there should only be one.");
|
|
return null;
|
|
}
|
|
|
|
var json = matches.Groups[1].Value;
|
|
if (string.IsNullOrEmpty(json))
|
|
{
|
|
Debug.LogError("Performance test run has incomplete hardware and player settings.");
|
|
return null;
|
|
}
|
|
|
|
var result = TryDeserializePerformanceTestRunJsonObject(json);
|
|
return result;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private PerformanceTestResult TryDeserializePerformanceTestResultJsonObject(string json)
|
|
{
|
|
try
|
|
{
|
|
return JsonUtility.FromJson<PerformanceTestResult>(json);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var errMsg = $"Exception thrown while deserializing json string to PerformanceTestResult: {json}";
|
|
Debug.LogWarning($"{errMsg}\r\nException: {e.Message}\r\n{e.StackTrace}");
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private Run TryDeserializePerformanceTestRunJsonObject(string json)
|
|
{
|
|
try
|
|
{
|
|
return JsonUtility.FromJson<Run>(json);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var errMsg = $"Exception thrown while deserializing json string to PerformanceTestRun: {json}";
|
|
Debug.LogWarning($"{errMsg}\r\nException: {e.Message}\r\n{e.StackTrace}");
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private 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);
|
|
}
|
|
}
|
|
}
|