/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Test/Perf/Utilities/TestUtilities.cs
248 строк
8 KB
Cyrus Najmabadi
Use coalesce expressions
29 июн 2022, 00:40
29 июн 2022, 00:40
9182ac5
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System; using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; namespace Roslyn.Test.Performance.Utilities { /// <summary> /// Global statics shared between the runner and tests. /// </summary> public static class RuntimeSettings { /// <summary> /// Used as a pseudo-return value for tests to send test objects /// back to the runner. /// </summary> public static PerfTest[] ResultTests = null; /// <summary> /// The logger that is being used by the process. /// </summary> public static ILogger Logger = new ConsoleAndFileLogger(); /// <summary> /// True if the logger should be verbose. /// </summary> public static bool IsVerbose = true; /// <summary> /// True if a runner is orchestrating the test runs. /// </summary> public static bool IsRunnerAttached = false; } public static class TestUtilities { /// <returns> /// Returns the path to CPC /// </returns> public static string GetCPCDirectoryPath() { return Environment.ExpandEnvironmentVariables(@"%SYSTEMDRIVE%\CPC"); } /// <returns> /// The path to the ViBenchToJson executable. /// </returns> public static string GetViBenchToJsonExeFilePath() { return Path.Combine(GetCPCDirectoryPath(), "ViBenchToJson.exe"); } // // Process spawning and error handling. // /// <summary> /// The result of a ShellOut completing. /// </summary> public class ProcessResult { /// <summary> /// The path to the executable that was run. /// </summary> public string ExecutablePath { get; set; } /// <summary> /// The arguments that were passed to the process. /// </summary> public string Args { get; set; } /// <summary> /// The exit code of the process. /// </summary> public int Code { get; set; } /// <summary> /// The entire standard-out of the process. /// </summary> public string StdOut { get; set; } /// <summary> /// The entire standard-error of the process. /// </summary> public string StdErr { get; set; } /// <summary> /// True if the command returned an exit code other /// than zero. /// </summary> public bool Failed => Code != 0; /// <summary> /// True if the command returned an exit code of 0. /// </summary> public bool Succeeded => !Failed; } /// <summary> /// Shells out, and if the process fails, log the error and quit the script. /// </summary> public static void ShellOutVital( string file, string args, string workingDirectory = null, CancellationToken cancellationToken = default(CancellationToken)) { var result = ShellOut(file, args, workingDirectory, cancellationToken); if (result.Failed) { LogProcessResult(result); throw new System.Exception("ShellOutVital Failed"); } } /// <summary> /// Shells out, blocks, and returns the ProcessResult. /// </summary> public static ProcessResult ShellOut( string file, string args, string workingDirectory = null, CancellationToken cancellationToken = default(CancellationToken)) { workingDirectory ??= AppDomain.CurrentDomain.BaseDirectory; var tcs = new TaskCompletionSource<ProcessResult>(); var startInfo = new ProcessStartInfo(file, args); startInfo.RedirectStandardOutput = true; startInfo.RedirectStandardError = true; startInfo.UseShellExecute = false; startInfo.WorkingDirectory = workingDirectory; var process = new Process { StartInfo = startInfo, EnableRaisingEvents = true, }; if (cancellationToken != default(CancellationToken)) { cancellationToken.Register(() => process.Kill()); } if (RuntimeSettings.IsVerbose) { Log($"running \"{file}\" with arguments \"{args}\" from directory {workingDirectory}"); } process.Start(); var output = new StringWriter(); var error = new StringWriter(); process.OutputDataReceived += (s, e) => { if (!String.IsNullOrEmpty(e.Data)) { output.WriteLine(e.Data); } }; process.ErrorDataReceived += (s, e) => { if (!String.IsNullOrEmpty(e.Data)) { error.WriteLine(e.Data); } }; process.BeginOutputReadLine(); process.BeginErrorReadLine(); process.WaitForExit(); return new ProcessResult { ExecutablePath = file, Args = args, Code = process.ExitCode, StdOut = output.ToString(), StdErr = error.ToString(), }; } /// <summary> /// Shells out and returns the string gathered from the stdout of the /// executing process. /// /// Throws an exception if the process fails. /// </summary> public static string StdoutFrom(string program, string args = "", string workingDirectory = null) { var result = ShellOut(program, args, workingDirectory); if (result.Failed) { LogProcessResult(result); throw new Exception("Shelling out failed"); } return result.StdOut.Trim(); } /// <summary> /// Logs a message. /// /// The actual implementation of this method may change depending on /// if the script is being run standalone or through the test runner. /// </summary> public static void Log(string info) { RuntimeSettings.Logger.Log(info); RuntimeSettings.Logger.Flush(); } /// <summary> /// Logs the result of a finished process /// </summary> public static void LogProcessResult(ProcessResult result) { RuntimeSettings.Logger.Log(String.Format("The process \"{0}\" {1} with code {2}", $"{result.ExecutablePath} {result.Args}", result.Failed ? "failed" : "succeeded", result.Code)); RuntimeSettings.Logger.Log($"Standard Out:\n{result.StdOut}"); RuntimeSettings.Logger.Log($"\nStandard Error:\n{result.StdErr}"); } /// <summary> /// Either runs the provided tests, or schedules them to be run by the /// runner. /// </summary> public static void TestThisPlease(params PerfTest[] tests) { if (RuntimeSettings.IsRunnerAttached) { RuntimeSettings.ResultTests = tests; } else { foreach (var test in tests) { test.Setup(); for (int i = 0; i < test.Iterations; i++) { test.Test(); } } } } } }