Files
UnrealEngineUWP/Engine/Source/Programs/AutomationTool/LowLevelTests/Tests/Gauntlet.LowLevelTestNode.cs
chris constantinescu bb62366170 FN Editor test fail due to it reusing local devices when spawning parallel tests instead of managing them per test session.
UnrealDeviceReservation is causing this because it's storing static device data.
Changed to non-static and associated a test session with a UnrealDeviceReservation instance 1:1

#jira UE-133981
#rb Jerome.Delattre, Josh.Engrebetson

#ROBOMERGE-AUTHOR: chris.constantinescu
#ROBOMERGE-SOURCE: CL 18108024 in //UE5/Main/...
#ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v889-18060218)
#ROBOMERGE[STARSHIP]: UE5-Release-Engine-Staging Release-5.0

[CL 18108080 by chris constantinescu in ue5-release-engine-test branch]
2021-11-09 12:47:22 -05:00

224 lines
5.3 KiB
C#

// Copyright Epic Games, Inc. All Rights Reserved.
using AutomationTool;
using Gauntlet;
using System;
using System.IO;
using System.Linq;
using UnrealBuildTool;
namespace LowLevelTests
{
public class LowLevelTests : BaseTest
{
private LowLevelTestContext Context;
private IAppInstance TestInstance;
private DateTime SessionStartTime = DateTime.MinValue;
private TestResult LowLevelTestResult;
public LowLevelTestsSession LowLevelTestsApp { get; private set; }
public LowLevelTests(LowLevelTestContext InContext)
{
Context = InContext;
MaxDuration = 60 * 5;
LowLevelTestResult = TestResult.Invalid;
}
public string DefaultCommandLine;
private string ArtifactPath;
public override string Name { get { return "LowLevelTest"; } }
public override float MaxDuration { protected set; get; }
public override bool IsReadyToStart()
{
if (LowLevelTestsApp == null)
{
LowLevelTestsApp = new LowLevelTestsSession(Context.BuildInfo);
}
return LowLevelTestsApp.TryReserveDevices();
}
public override string GetTestSummary()
{
return "Low Level Test";
}
public override TestResult GetTestResult()
{
return LowLevelTestResult;
}
public override void SetTestResult(TestResult testResult)
{
LowLevelTestResult = testResult;
}
public override bool StartTest(int Pass, int NumPasses)
{
if (LowLevelTestsApp == null)
{
throw new AutomationException("Node already has a null LowLevelTestsApp, was IsReadyToStart called?");
}
ArtifactPath = Path.Join(Context.Options.LogDir, Context.Options.TestApp);
Log.Info("LowLevelTestNode.StartTest Creating artifacts path at {0}", ArtifactPath);
Directory.CreateDirectory(ArtifactPath);
TestInstance = LowLevelTestsApp.InstallAndRunNativeTestApp();
if (TestInstance != null)
{
IDeviceUsageReporter.RecordComment(TestInstance.Device.Name, (UnrealTargetPlatform)TestInstance.Device.Platform, IDeviceUsageReporter.EventType.Device, Context.Options.JobDetails);
IDeviceUsageReporter.RecordComment(TestInstance.Device.Name, (UnrealTargetPlatform)TestInstance.Device.Platform, IDeviceUsageReporter.EventType.Test, this.GetType().Name);
}
if (SessionStartTime == DateTime.MinValue)
{
SessionStartTime = DateTime.Now;
}
if (TestInstance != null)
{
MarkTestStarted();
}
return TestInstance != null;
}
public override void TickTest()
{
if (TestInstance != null && TestInstance.HasExited)
{
if (TestInstance.WasKilled)
{
LowLevelTestResult = TestResult.Failed;
}
MarkTestComplete();
}
}
public override void StopTest(StopReason InReason)
{
base.StopTest(InReason);
if (TestInstance != null && !TestInstance.HasExited)
{
TestInstance.Kill();
}
string StdOut;
if (TestInstance is IWithUnfilteredStdOut)
{
StdOut = ((IWithUnfilteredStdOut)TestInstance).UnfilteredStdOut;
}
else
{
StdOut = TestInstance.StdOut;
}
if (StdOut == null || string.IsNullOrEmpty(StdOut.Trim()))
{
Log.Warning("No StdOut returned from low level test app.");
}
LowLevelTestsLogParser LowLevelTestsLogParser = new LowLevelTestsLogParser(StdOut);
UnrealProcessResult Result = GetExitCodeAndReason(
InReason,
LowLevelTestsLogParser.GetSummary(),
LowLevelTestsLogParser.GetCatchTestResults(),
out string ExitReason,
out int ExitCode);
if (ExitCode == 0)
{
LowLevelTestResult = TestResult.Passed;
}
else
{
if (Result == UnrealProcessResult.TimeOut)
{
LowLevelTestResult = TestResult.TimedOut;
}
else
{
LowLevelTestResult = TestResult.Failed;
}
Log.Info("Low level test exited with code {0} and reason: {1}", ExitCode, ExitReason);
}
}
public override void CleanupTest()
{
if (LowLevelTestsApp != null)
{
LowLevelTestsApp.Dispose();
LowLevelTestsApp = null;
}
}
protected virtual UnrealProcessResult GetExitCodeAndReason(StopReason InReason, UnrealLog InLog, LowLevelTestsLogParser.CatchTestResults InCatchResults, out string ExitReason, out int ExitCode)
{
if (TestInstance.WasKilled)
{
if (InReason == StopReason.MaxDuration)
{
ExitReason = "Process was killed by Gauntlet due to a timeout.";
ExitCode = -1;
return UnrealProcessResult.TimeOut;
}
else
{
ExitReason = "Process was killed by Gauntlet.";
ExitCode = 0;
return UnrealProcessResult.ExitOk;
}
}
// First we check for unreal specific issues.
// A successful test run must be free of these.
if (InLog.FatalError != null)
{
ExitReason = "Process encountered fatal error";
ExitCode = -1;
return UnrealProcessResult.EncounteredFatalError;
}
if (InLog.Ensures.Count() > 0)
{
ExitReason = string.Format("Process encountered {0} Ensures", InLog.Ensures.Count());
ExitCode = -1;
return UnrealProcessResult.EncounteredEnsure;
}
if (InLog.RequestedExit)
{
ExitReason = string.Format("Exit was requested: {0}", InLog.RequestedExitReason);
ExitCode = 0;
return UnrealProcessResult.ExitOk;
}
// Then we check for actual test results.
if (InCatchResults.Passed)
{
ExitReason = "All Catch2 tests passed.";
ExitCode = 0;
return UnrealProcessResult.ExitOk;
}
else
{
ExitReason = "Catch2 tests failed.";
ExitCode = -1;
return UnrealProcessResult.TestFailure;
}
}
}
}