Skip to content

Add create test suite command to gc infra. #4803

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
OutputFolder: Q:\output-data_sync_checkin

EnableStressMode: false

CoreRoot: Q:\runtime\artifacts\tests\coreclr\windows.x64.Checked\Tests\Core_Root
ReliabilityFrameworkDll: Q:\runtime\artifacts\tests\coreclr\windows.x64.Release\GC\Stress\Framework\ReliabilityFramework\ReliabilityFramework.dll
GCPerfSimDll: Q:\performance\artifacts\bin\GCPerfSim\Release\net7.0\GCPerfSim.dll
TestFolder: Q:\runtime\artifacts\tests\coreclr\windows.x64.Release\GC\Stress\Framework\ReliabilityFramework\Tests




Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
using System.Xml.Linq;

namespace GC.Infrastructure.Core.Configurations
{
public static class ReliabilityFrameworkTestSuiteCreator
{
public static void CreateTestingAssets(string ReliabilityFrameworkDll,
string GCPerfSimDll,
string outputFolder,
string TestFolder)
{
try
{
Console.WriteLine($"====== Copy ReliabilityFramework.dll and Tests to `outputFolder` ======");
Utilities.CopyFile(ReliabilityFrameworkDll, outputFolder);
DirectoryInfo testDir = Directory.CreateDirectory(Path.Combine(outputFolder, "Tests"));
string testfolderPath = testDir.FullName;
Utilities.CopyFilesRecursively(TestFolder, testfolderPath);

Console.WriteLine($"====== Copy gcperfsim.dll to Tests ======");
string destTestsFolder = Path.Combine(outputFolder, "Tests");
Utilities.CopyFile(GCPerfSimDll, destTestsFolder);
}
catch (Exception ex)
{
throw new Exception($"{nameof(ReliabilityFrameworkTestSuiteCreator)}: Fail to generate test assets: {ex}");
}
}

public static void GenerateTestScript(string rid,
string baseSuiteFolder,
string coreRoot,
string configPath,
string gcMode,
string outputRoot,
string scriptPath)
{
string scriptFoler = Path.GetDirectoryName(scriptPath);
string osName = rid.Split("-")
.FirstOrDefault("");

string configName = Path.GetFileName(configPath).Split("-")
.FirstOrDefault("");

(string DOTNET_gcServer, string DOTNET_GCDynamicAdaptationMode) =
gcMode switch
{
"Datas" => ("1", "1"),
"Server" => ("1", "0"),
"Workstation" => ("0", "0"),
_ => throw new Exception($"{nameof(ReliabilityFrameworkTestSuiteCreator)}: Unknow GC mode: {gcMode}")
};

string scriptSettingSegment;
string scriptBaseContent;

if (osName == "win")
{
scriptSettingSegment =
$"""
########## setting start ##########
$Env:DOTNET_gcServer={DOTNET_gcServer}
$Env:DOTNET_GCDynamicAdaptationMode={DOTNET_GCDynamicAdaptationMode}

$OutputRoot="{outputRoot}"
$CORE_ROOT="{coreRoot}"

# set config path
$config_path=Join-Path -Path $PSScriptRoot -ChildPath "{Path.GetRelativePath(scriptFoler, configPath)}"

# set test folder
$test_folder=Join-Path -Path $OutputRoot -ChildPath "Tests"

# set ReliabilityFramework.dll path
$reliability_framework_dll=Join-Path -Path $OutputRoot -ChildPath "ReliabilityFramework.dll"

# set output folder
$output_folder=$PSScriptRoot
########## setting end ##########
""";
string baseScriptPath = Path.Combine(baseSuiteFolder, "TestingScript.ps1.txt");
scriptBaseContent = File.ReadAllText(baseScriptPath);
}
else
{
scriptSettingSegment =
$"""
#!/bin/bash

script_root=$(dirname $(realpath $0))
########## setting start ##########
# set gc mode
export DOTNET_gcServer={DOTNET_gcServer}
export DOTNET_GCDynamicAdaptationMode={DOTNET_GCDynamicAdaptationMode}

# set core_root
Output_Root={outputRoot}
CORE_ROOT={coreRoot}

# set config path
config_path=$script_root/{Path.GetRelativePath(scriptFoler, configPath)}

# set test folder
test_folder=$Output_Root/Tests

# set ReliabilityFramework.dll path
reliability_framework_dll=$Output_Root/ReliabilityFramework.dll

# set output folder
output_folder=$script_root

########## setting end ##########
""";
string baseScriptPath = Path.Combine(baseSuiteFolder, "TestingScript.sh.txt");
scriptBaseContent = File.ReadAllText(baseScriptPath);
}

string content = $"{scriptSettingSegment}\n\n{scriptBaseContent}";
File.WriteAllText(scriptPath, content);
}

public static void GenerateTestConfig(string rid, string baseSuiteFolder, string configName, bool enableStress, string gcMode, string configPath)
{
try
{
string osName = rid.Split("-")
.FirstOrDefault("");

string maximumWaitTime =
(osName, enableStress) switch
{
("win", false) => Windows[configName][gcMode],
("win", true) => WindowsStress[configName][gcMode],
("linux", false) => Linux[configName][gcMode],
("linux", true) => LinuxStress[configName][gcMode],
_ => throw new Exception($"{nameof(ReliabilityFrameworkTestSuiteCreator)}: Unknown OS {osName}")
};

string baseConfigPath = Path.Combine(baseSuiteFolder, $"{configName}.config");
string baseConfigContent = File.ReadAllText(baseConfigPath);
XElement config = XElement.Parse(baseConfigContent);
config.SetAttributeValue("maximumWaitTime", maximumWaitTime);
config.SetAttributeValue("maximumExecutionTime", "24:00:00");
config.SetAttributeValue("maximumTestRuns", "-1");

config.Save(configPath, SaveOptions.OmitDuplicateNamespaces);
}
catch (Exception e)
{
throw new Exception($"{nameof(ReliabilityFrameworkTestSuiteCreator)}: Fail to generate test config: {e.Message}");
}
}

private static Dictionary<string, Dictionary<string, string>> Windows { get; } = new()
{
{ "loh", new() { { "Server", "00:10:00"}, { "Workstation", "01:45:00"}, { "Datas", "00:10:00"} } },
{ "poh", new() { { "Server", "00:05:00"}, { "Workstation", "00:50:00" }, { "Datas", "00:05:00" } } },
{ "non_induced", new() { { "Server", "00:30:00"}, { "Workstation", "03:30:00"}, { "Datas", "00:20:00"} } },
{ "finalization", new() { { "Server", "00:05:00"}, { "Workstation", "00:50:00"}, { "Datas", "00:15:00" } } }
};
private static Dictionary<string, Dictionary<string, string>> WindowsStress { get; } = new()
{
{ "loh", new() { { "Server", "00:02:00"}, { "Workstation", "00:10:00"}, { "Datas", "00:05:00"} } },
{ "poh", new() { { "Server", "00:02:00"}, { "Workstation", "00:10:00" }, { "Datas", "00:05:00" } } },
{ "non_induced", new() { { "Server", "00:25:00"}, { "Workstation", "04:00:00"}, { "Datas", "00:35:00"} } },
{ "finalization", new() { { "Server", "00:05:00"}, { "Workstation", "00:40:00"}, { "Datas", "01:40:00" } } }
};
private static Dictionary<string, Dictionary<string, string>> Linux { get; } = new()
{
{ "loh", new() { { "Server", "00:25:00"}, { "Workstation", "00:20:00"}, { "Datas", "00:20:00"} } },
{ "poh", new() { { "Server", "00:10:00"}, { "Workstation", "00:10:00" }, { "Datas", "00:10:00" } } },
{ "non_induced", new() { { "Server", "00:25:00"}, { "Workstation", "00:55:00"}, { "Datas", "00:15:00"} } },
{ "finalization", new() { { "Server", "00:20:00"}, { "Workstation", "01:30:00"}, { "Datas", "00:25:00" } } }
};
private static Dictionary<string, Dictionary<string, string>> LinuxStress { get; } = new()
{
{ "loh", new() { { "Server", "00:10:00"}, { "Workstation", "00:25:00"}, { "Datas", "00:08:00"} } },
{ "poh", new() { { "Server", "00:05:00"}, { "Workstation", "00:15:00" }, { "Datas", "00:05:00" } } },
{ "non_induced", new() { { "Server", "00:25:00"}, { "Workstation", "01:10:00"}, { "Datas", "00:30:00"} } },
{ "finalization", new() { { "Server", "00:20:00"}, { "Workstation", "00:50:00"}, { "Datas", "04:00:00" } } }
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using YamlDotNet.Serialization;

namespace GC.Infrastructure.Core.Configurations
{
public sealed class ReliabilityFrameworkTestCreateTestSuiteConfiguration
{
public string OutputFolder { get; set; }
public string CoreRoot { get; set; }
public string ReliabilityFrameworkDll { get; set; }
public bool EnableStressMode { get; set; }
public string GCPerfSimDll { get; set; }
public string TestFolder { get; set; }
}

public static class ReliabilityFrameworkTestCreateTestSuiteConfigurationParser
{
private static readonly IDeserializer _deserializer =
new DeserializerBuilder().IgnoreUnmatchedProperties().Build();

public static ReliabilityFrameworkTestCreateTestSuiteConfiguration Parse(string path)
{
// Preconditions.
ConfigurationChecker.VerifyFile(path, nameof(ReliabilityFrameworkTestCreateTestSuiteConfigurationParser));

string serializedConfiguration = File.ReadAllText(path);
ReliabilityFrameworkTestCreateTestSuiteConfiguration? configuration = null;

// This try catch is here because the exception from the YamlDotNet isn't helpful and must be imbued with more details.
try
{
configuration = _deserializer.Deserialize<ReliabilityFrameworkTestCreateTestSuiteConfiguration>(serializedConfiguration);
}

catch (Exception ex)
{
throw new ArgumentException($"{nameof(ReliabilityFrameworkTestCreateTestSuiteConfiguration)}: Unable to parse the yaml file because of an error in the syntax. Exception: {ex.Message} \n Call Stack: {ex.StackTrace}");
}

if (string.IsNullOrEmpty(configuration.OutputFolder))
{
throw new ArgumentException($"{nameof(ReliabilityFrameworkTestCreateTestSuiteConfiguration)}: Please specify output folder");
}

if (string.IsNullOrEmpty(configuration.ReliabilityFrameworkDll) )
{
throw new ArgumentException($"{nameof(ReliabilityFrameworkTestCreateTestSuiteConfiguration)}: Please specify ReliabilityFrameworkDll");
}

if (!Path.Exists(configuration.CoreRoot))
{
throw new ArgumentException($"{nameof(ReliabilityFrameworkTestCreateTestSuiteConfiguration)}: Given CoreRoot path is not valid");
}

if (string.IsNullOrEmpty(configuration.GCPerfSimDll))
{
throw new ArgumentException($"{nameof(ReliabilityFrameworkTestCreateTestSuiteConfiguration)}: Please specify GCPerfSimDll");
}

if (!Path.Exists(configuration.TestFolder))
{
throw new ArgumentException($"{nameof(ReliabilityFrameworkTestCreateTestSuiteConfiguration)}: Given TestFolder path is not valid");
}

return configuration;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,24 @@ public static class Utilities
{
public static void CopyFilesRecursively(string sourcePath, string targetPath)
{
string targetPathAsDirectory = targetPath + "\\";
sourcePath = Path.GetFullPath(sourcePath).TrimEnd(Path.DirectorySeparatorChar);
targetPath = Path.GetFullPath(targetPath).TrimEnd(Path.DirectorySeparatorChar);

Directory.CreateDirectory(targetPath);

foreach (string dirPath in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories))
{
Directory.CreateDirectory(dirPath.Replace(sourcePath, targetPathAsDirectory));
string relativePath = Path.GetRelativePath(sourcePath, dirPath);
string newDirPath = Path.Combine(targetPath, relativePath);
Directory.CreateDirectory(newDirPath);
}

foreach (string newPath in Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories))
foreach (string filePath in Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories))
{
File.Copy(newPath, newPath.Replace(sourcePath, targetPathAsDirectory), true);
string relativePath = Path.GetRelativePath(sourcePath, filePath);
string newFilePath = Path.Combine(targetPath, relativePath);
Directory.CreateDirectory(Path.GetDirectoryName(newFilePath));
File.Copy(filePath, newFilePath, true);
}
}

Expand Down Expand Up @@ -49,5 +58,22 @@ public static bool TryCopyFile(string sourcePath, string destinationPath)
return false;
}
}

public static void CopyFile(string srcPath, string dstPath)
{
string realDestPath = String.Empty;
if (Directory.Exists(dstPath))
{
// Copy file to a directory
string fileName = Path.GetFileName(srcPath);
realDestPath = Path.Combine(dstPath, fileName);
}
else
{
realDestPath = dstPath;
}

File.Copy(srcPath, realDestPath);
}
}
}
Loading