in src/extensions/testframework/YamlTestCaseRunner.cs [164:265]
private static TestOutcome RunTestCase(bool skipOnFailure, string cli, string? command, string? script, bool scriptIsBash, string? @foreach, string? arguments, string? input, string? expectGpt, string? expectRegex, string? notExpectRegex, string? env, string workingDirectory, int timeout, out string stdOut, out string stdErr, out string errorMessage, out string stackTrace, out string additional, out string debugTrace)
{
var outcome = TestOutcome.None;
additional = $"START TIME: {DateTime.Now}";
debugTrace = "";
stackTrace = script ?? string.Empty;
List<string>? filesToDelete = null;
var sbOut = new StringBuilder();
var sbErr = new StringBuilder();
var sbMerged = new StringBuilder();
try
{
var kvs = KeyValuePairsFromJson(arguments, true);
kvs.AddRange(KeyValuePairsFromJson(@foreach, false));
stackTrace = UpdateStackTrace(stackTrace, command, kvs);
kvs = ConvertValuesToAtArgs(kvs, ref filesToDelete);
var useCmd = !scriptIsBash;
script = WriteTextToTempFile(script, useCmd ? "cmd" : null);
expectRegex = WriteTextToTempFile(expectRegex);
notExpectRegex = WriteTextToTempFile(notExpectRegex);
GetStartInfoArgs(out var startProcess, out var startArgs, cli, command, script, scriptIsBash, kvs, expectRegex, notExpectRegex, ref filesToDelete);
stackTrace = $"{startProcess} {startArgs}\n{stackTrace ?? string.Empty}";
Logger.Log($"Process.Start('{startProcess} {startArgs}')");
var startInfo = new ProcessStartInfo(startProcess, startArgs)
{
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardError = true,
RedirectStandardOutput = true,
WorkingDirectory = workingDirectory
};
UpdateEnvironment(startInfo, env);
UpdatePathEnvironment(startInfo);
var process = Process.Start(startInfo);
if (process == null) throw new Exception("Process.Start() returned null!");
process.StandardInput.WriteLine(input ?? string.Empty);
process.StandardInput.Close();
var outDoneSignal = new ManualResetEvent(false);
var errDoneSignal = new ManualResetEvent(false);
process.OutputDataReceived += (sender, e) => AppendLineOrSignal(e.Data, sbOut, sbMerged, outDoneSignal);
process.ErrorDataReceived += (sender, e) => AppendLineOrSignal(e.Data, sbErr, sbMerged, errDoneSignal);
process.BeginOutputReadLine();
process.BeginErrorReadLine();
var exitedNotKilled = WaitForExit(process, timeout);
outcome = exitedNotKilled && process.ExitCode == 0
? TestOutcome.Passed
: skipOnFailure
? TestOutcome.Skipped
: TestOutcome.Failed;
if (exitedNotKilled)
{
outDoneSignal.WaitOne();
errDoneSignal.WaitOne();
}
var exitCode = exitedNotKilled
? process.ExitCode.ToString()
: $"(did not exit; timedout; killed)";
var exitTime = exitedNotKilled
? process.ExitTime.ToString()
: DateTime.UtcNow.ToString();
errorMessage = $"EXIT CODE: {exitCode}";
additional = additional
+ $" STOP TIME: {exitTime}"
+ $" EXIT CODE: {exitCode}";
}
catch (Exception ex)
{
outcome = TestOutcome.Failed;
errorMessage = ex.Message;
debugTrace = ex.ToString();
stackTrace = $"{stackTrace}\n{ex.StackTrace}";
}
finally
{
if (script != null) File.Delete(script);
if (expectRegex != null) File.Delete(expectRegex);
if (notExpectRegex != null) File.Delete(notExpectRegex);
filesToDelete?.ForEach(x => File.Delete(x));
}
stdOut = sbOut.ToString();
stdErr = sbErr.ToString();
return outcome == TestOutcome.Passed && !string.IsNullOrEmpty(expectGpt)
? CheckExpectGptOutcome(sbMerged.ToString(), expectGpt, workingDirectory, ref stdOut, ref stdErr)
: outcome;
}