private static string GenerateSourceFileItemsSnippet(LoadTestInfo loadTest) { StringBuilder snippet = new StringBuilder(); foreach (var file in loadTest.SourceFiles) { string itemSnippet = string.Empty; if (file.SourceFileAction == SourceFileAction.Compile) { itemSnippet = $@" <Compile Include='{Path.GetFileName(file.FileName)}'/>"; } else if (file.SourceFileAction == SourceFileAction.Binplace) { itemSnippet = $@" <None Include='{Path.GetFileName(file.FileName)}'> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> "; } snippet.Append(itemSnippet); } return snippet.ToString(); }
public void GenerateSourceFile(LoadTestInfo loadTest) { string sourceCode = $@" using System; using System.Threading; using System.Threading.Tasks; using stress.execution; namespace stress.generated {{ public static class Program {{ public static void Main(string[] args) {{ TimeSpan duration = TimeSpan.Parse(""{loadTest.Duration.ToString()}""); CancellationTokenSource tokenSource = new CancellationTokenSource(duration); LoadTestClass.LoadTestMethod(tokenSource.Token); }} }} }} "; string srcFilePath = Path.Combine(loadTest.SourceDirectory, "Program.cs"); File.WriteAllText(srcFilePath, sourceCode); loadTest.SourceFiles.Add(new SourceFileInfo(srcFilePath, SourceFileAction.Compile)); }
public void GenerateSuite(int seed, string suiteName, string outputPath, string[] testPaths, string[] searchPatterns, string[] hintPaths, LoadSuiteConfig config) { int suiteTestCount = 0; _unitTestSelector = new UnitTestSelector(); _unitTestSelector.Initialize(seed, testPaths, searchPatterns, hintPaths); foreach (var loadTestConfig in config.LoadTestConfigs) { for (int i = 0; i < loadTestConfig.TestCount; i++) { var loadTestInfo = new LoadTestInfo() { TestName = suiteName + "_" + suiteTestCount.ToString("X4"), Duration = loadTestConfig.Duration, LoadPatternType = Type.GetType(loadTestConfig.LoadPattern), TestPatternType = Type.GetType(loadTestConfig.TestPattern), WorkerStrategyType = Type.GetType(loadTestConfig.WorkerStrategy), WorkerCount = loadTestConfig.NumWorkers, EnvironmentVariables = loadTestConfig.EnvironmentVariables, SuiteConfig = config, }; loadTestInfo.SourceDirectory = Path.Combine(outputPath, loadTestInfo.TestName); loadTestInfo.UnitTests = _unitTestSelector.NextUnitTests(loadTestConfig.NumTests).ToArray(); this.GenerateTestSources(loadTestInfo); CodeGenOutput.Info($"Generated Load Test: {loadTestInfo.TestName}"); suiteTestCount++; } } }
public void GenerateSuite(int seed, string suiteName, string outputPath, string[] testPaths, string[] searchPatterns, string[] hintPaths, LoadSuiteConfig config, string cachePath = null, bool legacyProject = false, string globalPackageConfig = null) { Random rand = new Random(seed); int suiteTestCount = 0; _unitTestSelector = new UnitTestSelector(); _unitTestSelector.Initialize(seed, testPaths, searchPatterns, hintPaths, cachePath); for (int iConfig = 0; iConfig < config.LoadTestConfigs.Count; iConfig++) { var loadTestConfig = config.LoadTestConfigs[iConfig]; for (int i = 0; i < loadTestConfig.TestCount; i++) { var loadTestInfo = new LoadTestInfo(globalPackageConfig) { TestName = suiteName + "_" + suiteTestCount.ToString("X4"), Duration = loadTestConfig.Duration, LoadPatternType = typeof(StaticLoadPattern), //Type.GetType(loadTestConfig.LoadPattern), TestPatternType = typeof(RandomTestPattern), //Type.GetType(loadTestConfig.TestPattern), WorkerStrategyType = typeof(DedicatedThreadWorkerStrategy), //Type.GetType(loadTestConfig.WorkerStrategy), WorkerCount = loadTestConfig.NumWorkers, SelfDestruct = loadTestConfig.SelfDestruct, EnvironmentVariables = loadTestConfig.EnvironmentVariables, SuiteConfig = config, Seed = rand.Next(), }; loadTestInfo.SourceDirectory = Path.Combine(outputPath, iConfig.ToString("00") + "_" + loadTestInfo.Duration.TotalHours.ToString("00.##") + "hr", loadTestInfo.TestName); loadTestInfo.UnitTests = _unitTestSelector.NextUnitTests(loadTestConfig.NumTests).ToArray(); //build a list of all the sources files to generate for the load test var generators = new List <ISourceFileGenerator>() { new LoadTestSourceFileGenerator(), new ProgramSourceFileGenerator(), new ExecutionFileGeneratorWindows(), new ExecutionFileGeneratorLinux(), }; //if we want to generate a legacy project file (i.e. ToF project file) use HelixToFProjectFileGenerator otherwise use LoadTestProjectFileGenerator var projectFileGenerator = legacyProject ? (ISourceFileGenerator) new HelixToFProjectFileGenerator() : (ISourceFileGenerator) new LoadTestProjectFileGenerator(); if (!legacyProject) { generators.Add(new LoadTestProjectJsonFileGenerator()); } //I believe the project file generator must be last, becuase it depends on discovering all the other source files //however the ordering beyond that should not matter generators.Add(projectFileGenerator); this.GenerateTestSources(loadTestInfo, generators); CodeGenOutput.Info($"Generated Load Test: {loadTestInfo.TestName}"); suiteTestCount++; } } }
private static string GenerateSourceFileItemsSnippet(LoadTestInfo loadTest) { StringBuilder snippet = new StringBuilder(); foreach (var file in loadTest.SourceFiles) { string itemSnippet = string.Empty; if (file.SourceFileAction == SourceFileAction.Compile) { itemSnippet = $@" <Compile Include='{Path.GetFileName(file.RelativePath)}'/>"; } else if (file.SourceFileAction == SourceFileAction.Binplace) { itemSnippet = $@" <None Include='{Path.GetFileName(file.RelativePath)}'> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> "; } snippet.Append(itemSnippet); } return(snippet.ToString()); }
public void GenerateSourceFile(LoadTestInfo testInfo) { this.LoadTest = testInfo; string unitTestInitSnippet = this.BuildUnitTestInitSnippet(); string externAliasSnippet = this.BuildExternAliasSnippet(); string testSnippet = this.BuildTestSnippet(); string source = $@" {externAliasSnippet} using System; using System.Threading; using stress.execution; namespace stress.generated {{ public static class LoadTestClass {{ {unitTestInitSnippet} {testSnippet} }} }} "; string srcFilePath = Path.Combine(this.LoadTest.SourceDirectory, "LoadTest.cs"); File.WriteAllText(srcFilePath, source); testInfo.SourceFiles.Add(new SourceFileInfo(srcFilePath, SourceFileAction.Compile)); }
public void GenerateSuite(int seed, string suiteName, string outputPath, string[] testPaths, string[] searchPatterns, string[] hintPaths, LoadSuiteConfig config, string cachePath = null) { int suiteTestCount = 0; _unitTestSelector = new UnitTestSelector(); _unitTestSelector.Initialize(seed, testPaths, searchPatterns, hintPaths, cachePath); for (int iConfig = 0; iConfig < config.LoadTestConfigs.Count; iConfig++) { var loadTestConfig = config.LoadTestConfigs[iConfig]; for (int i = 0; i < loadTestConfig.TestCount; i++) { var loadTestInfo = new LoadTestInfo() { TestName = suiteName + "_" + suiteTestCount.ToString("X4"), Duration = loadTestConfig.Duration, LoadPatternType = typeof(StaticLoadPattern), //Type.GetType(loadTestConfig.LoadPattern), TestPatternType = typeof(RandomTestPattern), //Type.GetType(loadTestConfig.TestPattern), WorkerStrategyType = typeof(DedicatedThreadWorkerStrategy), //Type.GetType(loadTestConfig.WorkerStrategy), WorkerCount = loadTestConfig.NumWorkers, EnvironmentVariables = loadTestConfig.EnvironmentVariables, SuiteConfig = config, }; loadTestInfo.SourceDirectory = Path.Combine(outputPath, iConfig.ToString("00") + "_" + loadTestInfo.Duration.TotalHours.ToString("00.##") + "hr", loadTestInfo.TestName); loadTestInfo.UnitTests = _unitTestSelector.NextUnitTests(loadTestConfig.NumTests).ToArray(); this.GenerateTestSources(loadTestInfo); CodeGenOutput.Info($"Generated Load Test: {loadTestInfo.TestName}"); suiteTestCount++; } } }
public void GenerateSourceFile(LoadTestInfo loadTestInfo)// (string scriptName, string testName, Dictionary<string, string> envVars, string host = null) { string batchScriptPath = Path.Combine(loadTestInfo.SourceDirectory, STRESS_SCRIPT_NAME); using (TextWriter stressScript = new StreamWriter(batchScriptPath, false)) { stressScript.WriteLine("@echo off"); stressScript.WriteLine("REM stress script for " + loadTestInfo.TestName); stressScript.WriteLine(); stressScript.WriteLine(); stressScript.WriteLine("REM environment section"); // first take care of the environment variables foreach (KeyValuePair <string, string> kvp in loadTestInfo.EnvironmentVariables) { stressScript.WriteLine("set {0}={1}", kvp.Key, kvp.Value); } stressScript.WriteLine(); stressScript.WriteLine(); // Prepare the test execution line string testCommandLine = loadTestInfo.TestName + ".exe"; // If there is a host then prepend it to the test command line if (!String.IsNullOrEmpty(loadTestInfo.SuiteConfig.Host)) { testCommandLine = loadTestInfo.SuiteConfig.Host + " " + testCommandLine; } stressScript.WriteLine("REM test execution"); stressScript.WriteLine("echo calling [{0}]", testCommandLine); stressScript.WriteLine(testCommandLine); // Save off the exit code stressScript.WriteLine("set _EXITCODE=%ERRORLEVEL%"); stressScript.WriteLine("echo test exited with ExitCode: %_EXITCODE%"); stressScript.WriteLine(); stressScript.WriteLine(); // // Check the return code // stressScript.WriteLine("if %_EXITCODE% EQU 0 goto :REPORT_PASS"); // stressScript.WriteLine("REM error processing"); // stressScript.WriteLine("echo JRS - Test Failed. Report the failure, call to do the initial dump analysis, zip up the directory and return that along with an event"); // stressScript.WriteLine("goto :END"); // stressScript.WriteLine(); // stressScript.WriteLine(); // // stressScript.WriteLine(":REPORT_PASS"); // stressScript.WriteLine("echo JRS - Test Passed. Report the pass."); // stressScript.WriteLine(); // stressScript.WriteLine(); // exit the script with the exit code from the process stressScript.WriteLine(":END"); stressScript.WriteLine("exit /b %_EXITCODE%"); } // Add the batch script to the source files loadTestInfo.SourceFiles.Add(new SourceFileInfo(STRESS_SCRIPT_NAME, SourceFileAction.Binplace)); }
public static void GenerateProjectFile(LoadTestInfo loadTest) { string refSnippet = GenerateReferencesSnippet(loadTest); string fxSnippet = GenerateFrameworkReferencesSnippet(loadTest); string itemSnippet = GenerateSourceFileItemsSnippet(loadTest); string projFileContent = string.Format(PROJECT_TEMPLATE, refSnippet, itemSnippet); //, fxSnippet); File.WriteAllText(Path.Combine(loadTest.SourceDirectory, loadTest.TestName + ".csproj"), projFileContent); }
public void GenerateSourceFile(LoadTestInfo loadTest) { var loadTestRefInfo = loadTest.PackageInfo; var srcFilePath = Path.Combine(loadTest.SourceDirectory, "project.json"); loadTestRefInfo.ToFile(srcFilePath); loadTest.SourceFiles.Add(new SourceFileInfo("project.json", SourceFileAction.None)); }
private static string GenerateTestPropertiesSnippet(LoadTestInfo loadTest) { //timeout = test duration + 5 minutes for dump processing ect. string timeoutInSeconds = Convert.ToInt32((loadTest.Duration + TimeSpan.FromMinutes(5)).TotalSeconds).ToString(); string propertyString = $@" <TimeoutInSeconds>{timeoutInSeconds}</TimeoutInSeconds>"; return(propertyString); }
private void GenerateTestSources(LoadTestInfo loadTest, IEnumerable <ISourceFileGenerator> sourceFileGenerators) { Directory.CreateDirectory(loadTest.SourceDirectory); CopyUnitTestAssemblyRefs(loadTest); foreach (var sourceGen in sourceFileGenerators) { sourceGen.GenerateSourceFile(loadTest); } }
public void GenerateSourceFile(LoadTestInfo loadTest) { string refSnippet = GenerateTestReferencesSnippet(loadTest); string itemSnippet = GenerateSourceFileItemsSnippet(loadTest); string propertySnippet = GenerateTestPropertiesSnippet(loadTest); //format the project template {0} source files, {1} test references, {2} test properties string projFileContent = string.Format(PROJECT_TEMPLATE, itemSnippet, refSnippet, propertySnippet); File.WriteAllText(Path.Combine(loadTest.SourceDirectory, loadTest.TestName + ".csproj"), projFileContent); }
private static string GenerateFrameworkReferencesSnippet(LoadTestInfo loadTest) { HashSet<string> uniqueAssemblies = new HashSet<string>(); StringBuilder snippet = new StringBuilder(); foreach (var fxref in loadTest.UnitTests.SelectMany(t => t.ReferenceInfo.FrameworkReferences).Union(s_systemRefs).Distinct()) { string refSnippet = $@" <CLRTestContractReference Include='{fxref}' />"; snippet.Append(refSnippet); } return snippet.ToString(); }
public void GenerateSourceFile(LoadTestInfo loadTest) { string refSnippet = GenerateTestReferencesSnippet(loadTest); string fxSnippet = GenerateFrameworkReferencesSnippet(loadTest); string itemSnippet = GenerateSourceFileItemsSnippet(loadTest); string propertySnippet = GenerateTestPropertiesSnippet(loadTest); //format the project template {0} source files, {1} framework references, {2} test references, {3} test properties string projFileContent = string.Format(PROJECT_TEMPLATE, itemSnippet, fxSnippet, refSnippet, propertySnippet); File.WriteAllText(Path.Combine(loadTest.SourceDirectory, loadTest.TestName + ".csproj"), projFileContent); }
public void GenerateSourceFile(LoadTestInfo testInfo) { this.LoadTest = testInfo; string unitTestsClassContentSnippet = this.BuildUnitTestsClassContentSnippet(); string unitTestInitSnippet = this.BuildUnitTestInitSnippet(); string externAliasSnippet = this.BuildExternAliasSnippet(); string testSnippet = this.BuildTestSnippet(); string source = $@" {externAliasSnippet} using System; using System.Collections.Generic; using System.Linq; using System.Threading; using stress.execution; using Xunit; namespace stress.generated {{ public static class UnitTests {{ {unitTestsClassContentSnippet} private static object s_lock = new object(); private static Random s_rand = new Random({testInfo.Seed}); }} public static class LoadTestClass {{ {unitTestInitSnippet} {testSnippet} }} }} "; string srcFilePath = Path.Combine(this.LoadTest.SourceDirectory, "LoadTest.cs"); File.WriteAllText(srcFilePath, source); testInfo.SourceFiles.Add(new SourceFileInfo("LoadTest.cs", SourceFileAction.Compile)); }
private void GenerateTestSources(LoadTestInfo loadTest) { Directory.CreateDirectory(loadTest.SourceDirectory); CopyUnitTestAssemblyRefsAsync(loadTest); new LoadTestSourceFileGenerator().GenerateSourceFile(loadTest); new ProgramSourceFileGenerator().GenerateSourceFile(loadTest); // Check whether Linux/Mac or Windows...we don't actually want to do both here. new ExecutionFileGeneratorWindows().GenerateSourceFile(loadTest); new ExecutionFileGeneratorLinux().GenerateSourceFile(loadTest); HelixProjectFileGenerator.GenerateProjectFile(loadTest); }
private void CopyUnitTestAssemblyRefs(LoadTestInfo loadTest) { string refDir = Path.Combine(loadTest.SourceDirectory, "refs"); Directory.CreateDirectory(refDir); foreach (var assmPath in loadTest.UnitTests.Select(t => t.AssemblyPath).Union(loadTest.UnitTests.SelectMany(t => t.ReferenceInfo.ReferencedAssemblies.Select(ra => ra.Path)))) { string destPath = Path.Combine(refDir, Path.GetFileName(assmPath)); if (!File.Exists(destPath)) { File.Copy(assmPath, destPath); } } }
private void CopyUnitTestAssemblyRefsAsync(LoadTestInfo loadTest) { string refDir = Path.Combine(loadTest.SourceDirectory, "refs"); Directory.CreateDirectory(refDir); foreach (var assmPath in loadTest.UnitTests.Select(t => t.AssemblyPath).Union(loadTest.UnitTests.SelectMany(t => t.ReferenceInfo.ReferencedAssemblies.Select(ra => ra.Path)))) { string destPath = Path.Combine(refDir, Path.GetFileName(assmPath)); if (!File.Exists(destPath)) { File.Copy(assmPath, destPath); } //await FileUtils.CopyDirAsync(Path.GetDirectoryName(assmPath), refDir); } }
private static string GenerateTestReferencesSnippet(LoadTestInfo loadTest) { HashSet <string> uniqueAssemblies = new HashSet <string>(); var packageInfo = loadTest.PackageInfo; StringBuilder snippet = new StringBuilder(); foreach (var test in loadTest.UnitTests) { if (uniqueAssemblies.Add(test.AssemblyName)) { string refSnippet = $@" <Reference Include='{test.AssemblyName}'> <HintPath>$(MSBuildThisFileDirectory)\refs\{test.AssemblyName}</HintPath> <Aliases>{UnitTestInfo.GetAssemblyAlias(test.AssemblyName)}</Aliases> </Reference>"; snippet.Append(refSnippet); } foreach (var assmref in test.ReferenceInfo.ReferencedAssemblies) { if (uniqueAssemblies.Add(assmref.Name) && packageInfo.dependencies[Path.GetFileNameWithoutExtension(assmref.Name)] == null) { string refSnippet = $@" <Reference Include='{assmref.Name}'> <HintPath>$(MSBuildThisFileDirectory)\refs\{assmref.Name}</HintPath> <Aliases>{UnitTestInfo.GetAssemblyAlias(assmref.Name)}</Aliases> </Reference>"; snippet.Append(refSnippet); } } } string stressexecutionsnippet = $@" <Reference Include='stress.execution.dll'> <HintPath>{typeof(stress.execution.UnitTest).Assembly.Location}</HintPath> </Reference>"; snippet.Append(stressexecutionsnippet); return(snippet.ToString()); }
private static string GenerateFrameworkReferencesSnippet(LoadTestInfo loadTest) { HashSet<string> uniqueAssemblies = new HashSet<string>(); StringBuilder snippet = new StringBuilder(); AssemblyReferenceSet fxRefSet = new AssemblyReferenceSet(); fxRefSet.UnionWith(s_infraFxRefs); foreach (var testfxRefs in loadTest.UnitTests.Select(t => t.ReferenceInfo.FrameworkReferences)) { fxRefSet.UnionWith(testfxRefs); } foreach (var fxref in fxRefSet) { string refSnippet; if (fxref.Version.StartsWith("4.0")) { refSnippet = $@" <CLRTestContractReference Include='{Path.GetFileNameWithoutExtension(fxref.Name)}'/>"; } else { refSnippet = $@" <CLRTestContractReference Include='{Path.GetFileNameWithoutExtension(fxref.Name)}'> <Version>{fxref.Version}</Version> </CLRTestContractReference>"; } snippet.Append(refSnippet); } snippet.Append(@" <CLRTestContractReference Include='Microsoft.DotNet.stress.execution'> <SkipSupportVerification>true</SkipSupportVerification> <Version>1.0.0-alpha-00037</Version> </CLRTestContractReference>"); return snippet.ToString(); }
private static string GenerateFrameworkReferencesSnippet(LoadTestInfo loadTest) { HashSet <string> uniqueAssemblies = new HashSet <string>(); StringBuilder snippet = new StringBuilder(); AssemblyReferenceSet fxRefSet = new AssemblyReferenceSet(); fxRefSet.UnionWith(s_infraFxRefs); foreach (var testfxRefs in loadTest.UnitTests.Select(t => t.ReferenceInfo.FrameworkReferences)) { fxRefSet.UnionWith(testfxRefs); } foreach (var fxref in fxRefSet) { string refSnippet; if (fxref.Version.StartsWith("4.0")) { refSnippet = $@" <CLRTestContractReference Include='{Path.GetFileNameWithoutExtension(fxref.Name)}'/>"; } else { refSnippet = $@" <CLRTestContractReference Include='{Path.GetFileNameWithoutExtension(fxref.Name)}'> <Version>{fxref.Version}</Version> </CLRTestContractReference>"; } snippet.Append(refSnippet); } snippet.Append(@" <CLRTestContractReference Include='Microsoft.DotNet.stress.execution'> <SkipSupportVerification>true</SkipSupportVerification> <Version>1.0.0-alpha-00031</Version> </CLRTestContractReference>"); return(snippet.ToString()); }
private static string GenerateReferencesSnippet(LoadTestInfo loadTest) { HashSet <string> uniqueAssemblies = new HashSet <string>(); StringBuilder snippet = new StringBuilder(); foreach (var test in loadTest.UnitTests) { if (uniqueAssemblies.Add(test.AssemblyPath)) { string refSnippet = $@" <Reference Include='{test.AssemblyName}'> <HintPath>$(MSBuildThisFileDirectory)\refs\{test.AssemblyName}</HintPath> <Aliases>{UnitTestInfo.GetAssemblyAlias(test.AssemblyPath)}</Aliases> <NotForTests>true</NotForTests> </Reference>"; snippet.Append(refSnippet); } foreach (var assmref in test.ReferenceInfo.ReferencedAssemblies) { if (uniqueAssemblies.Add(assmref.Path)) { string refSnippet = $@" <Reference Include='{assmref.Name}'> <HintPath>$(MSBuildThisFileDirectory)\refs\{assmref.Name}</HintPath> <Aliases>{UnitTestInfo.GetAssemblyAlias(assmref.Path)}</Aliases> <NotForTests>true</NotForTests> </Reference>"; snippet.Append(refSnippet); } } } return(snippet.ToString()); }
private static string GenerateReferencesSnippet(LoadTestInfo loadTest) { HashSet<string> uniqueAssemblies = new HashSet<string>(); StringBuilder snippet = new StringBuilder(); foreach (var test in loadTest.UnitTests) { if (uniqueAssemblies.Add(test.AssemblyPath)) { string refSnippet = $@" <Reference Include='{test.AssemblyName}'> <HintPath>$(MSBuildThisFileDirectory)\refs\{test.AssemblyName}</HintPath> <Aliases>{UnitTestInfo.GetAssemblyAlias(test.AssemblyPath)}</Aliases> <NotForTests>true</NotForTests> </Reference>"; snippet.Append(refSnippet); } foreach (var assmref in test.ReferenceInfo.ReferencedAssemblies) { if (uniqueAssemblies.Add(assmref.Path)) { string refSnippet = $@" <Reference Include='{assmref.Name}'> <HintPath>$(MSBuildThisFileDirectory)\refs\{assmref.Name}</HintPath> <Aliases>{UnitTestInfo.GetAssemblyAlias(assmref.Path)}</Aliases> <NotForTests>true</NotForTests> </Reference>"; snippet.Append(refSnippet); } } } return snippet.ToString(); }
// The reason for the spacing and begin/end blocks is that python relies on whitespace instead of things // like being/ends each nested block increases the spaces by 2 public void GenerateLLDBPythonScript(string scriptName, LoadTestInfo loadTestInfo) { // If the application is hosted then the debuggee is the host, otherwise it is the test exe string debuggee = String.IsNullOrEmpty(loadTestInfo.SuiteConfig.Host) ? loadTestInfo.TestName + ".exe" : loadTestInfo.SuiteConfig.Host; // the name of the core file (should be in the current directory) string coreFileName = "core"; // LastEvent.txt will contain the ClrStack, native callstack and last exception (if I can get it) string lastEventFile = "LastEvent.txt"; // LLDBError.txt will contain any error messages from failures to LLDB string lldbErrorFile = "LLDBError.txt"; // Threads.txt will contain full native callstacks for each threads (equivalent of bt all) string threadsFile = "Threads.txt"; string scriptNameWithPath = Path.Combine(loadTestInfo.SourceDirectory, scriptName); using (TextWriter lldbScript = new StreamWriter(scriptNameWithPath, false)) { // set the line ending for linux/mac lldbScript.NewLine = "\n"; lldbScript.WriteLine("import lldb"); // Create the debugger object lldbScript.WriteLine("debugger = lldb.SBDebugger.Create()"); // Create the return object. This contains the return informaton (success/failure, output or error text etc) from the debugger call lldbScript.WriteLine("retobj = lldb.SBCommandReturnObject()"); // Load the SOS plugin lldbScript.WriteLine("debugger.GetCommandInterpreter().HandleCommand(\"plugin load libsosplugin.so\", retobj)"); // Create the target lldbScript.WriteLine("target = debugger.CreateTarget('{0}')", debuggee); // If the target was created successfully lldbScript.WriteLine("if target:"); { // Load the core lldbScript.WriteLine(" process = target.LoadCore('{0}')", coreFileName); { // lldbScript.WriteLine(" debugger.GetCommandInterpreter().HandleCommand(\"sos ClrStack\", retobj)"); lldbScript.WriteLine(" if retobj.Succeeded():"); { lldbScript.WriteLine(" LastEventFile = open('{0}', 'w')", lastEventFile); lldbScript.WriteLine(" LastEventFile.write(retobj.GetOutput())"); lldbScript.WriteLine(" thread = process.GetSelectedThread()"); lldbScript.WriteLine(@" LastEventFile.write('\n'.join(str(frame) for frame in thread))"); lldbScript.WriteLine(" LastEventFile.close()"); } lldbScript.WriteLine(" else:"); { lldbScript.WriteLine(" LLDBErrorFile = open('{0}', 'w')", lldbErrorFile); lldbScript.WriteLine(" LLDBErrorFile.write(retobj.GetError())"); lldbScript.WriteLine(" LLDBErrorFile.close()"); } lldbScript.WriteLine(" ThreadsFile = open('{0}', 'w')", threadsFile); lldbScript.WriteLine(" for thread in process:"); { lldbScript.WriteLine(@" ThreadsFile.write('Thread %s:\n' % str(thread.GetThreadID()))"); lldbScript.WriteLine(" for frame in thread:"); { lldbScript.WriteLine(@" ThreadsFile.write(str(frame)+'\n')"); } } lldbScript.WriteLine(" ThreadsFile.close()"); } } } // Add the python script to the source files loadTestInfo.SourceFiles.Add(new SourceFileInfo(scriptNameWithPath, SourceFileAction.Binplace)); }
/* * scriptName - name of the script to be generated, this should include the path * testName - the name of the test executable * arguments - arguments to be passed to the test executable * envVars - dictionary of environment variables and their values * host (optional) - needed for hosted runtimes */ public void GenerateSourceFile(LoadTestInfo loadTestInfo) { string lldbInspectionFileName = "inspectCoreWithLLDB.py"; string shellScriptPath = Path.Combine(loadTestInfo.SourceDirectory, "stress.sh"); using (TextWriter stressScript = new StreamWriter(shellScriptPath, false)) { // set the line ending for shell scripts stressScript.NewLine = "\n"; stressScript.WriteLine("# stress script for {0}", loadTestInfo.TestName); stressScript.WriteLine(); stressScript.WriteLine(); stressScript.WriteLine("# environment section"); // first take care of the environment variables foreach (KeyValuePair<string, string> kvp in loadTestInfo.EnvironmentVariables) { stressScript.WriteLine("export {0}={1}", kvp.Key, kvp.Value); } stressScript.WriteLine(); stressScript.WriteLine(); // The default limit for coredumps on Linux and Mac is 0 and needs to be reset to allow core dumps to be created stressScript.WriteLine("# The default limit for coredumps on Linux and Mac is 0 and this needs to be reset to allow core dumps to be created"); stressScript.WriteLine("echo calling [ulimit -c unlimited]"); stressScript.WriteLine("ulimit -c unlimited"); // report the current limits (in theory this should get into the test log) stressScript.WriteLine("echo calling [ulimit -a]"); stressScript.WriteLine("ulimit -a"); stressScript.WriteLine(); stressScript.WriteLine(); // Prepare the test execution line string testCommandLine = loadTestInfo.TestName + ".exe"; // If there is a host then prepend it to the test command line if (!String.IsNullOrEmpty(loadTestInfo.SuiteConfig.Host)) { testCommandLine = loadTestInfo.SuiteConfig.Host + " " + testCommandLine; // If the command line isn't a full path or ./ for current directory then add it to ensure we're using the host in the current directory if ((!loadTestInfo.SuiteConfig.Host.StartsWith("/")) && (!loadTestInfo.SuiteConfig.Host.StartsWith("./"))) { testCommandLine = "./" + testCommandLine; } } stressScript.WriteLine("# test execution"); stressScript.WriteLine("echo calling [{0}]", testCommandLine); stressScript.WriteLine(testCommandLine); // Save off the exit code stressScript.WriteLine("export _EXITCODE=$?"); stressScript.WriteLine("echo test exited with ExitCode: $_EXITCODE"); // Check the return code stressScript.WriteLine("if [ $_EXITCODE != 0 ]"); stressScript.WriteLine("then"); // stressScript.WriteLine(" echo JRS - Test Failed. Report the failure, call to do the initial dump analysis, zip up the directory and return that along with an event"); stressScript.WriteLine(" if [-f core]"); stressScript.WriteLine(" then"); stressScript.WriteLine(" python {0}", lldbInspectionFileName); stressScript.WriteLine(" fi"); // stressScript.WriteLine("zip -r {0}.zip .", testName); // stressScript.WriteLine("else"); // stressScript.WriteLine(" echo JRS - Test Passed. Report the pass."); stressScript.WriteLine("fi"); stressScript.WriteLine(); stressScript.WriteLine(); // exit the script with the return code stressScript.WriteLine("exit $_EXITCODE"); } // Add the shell script to the source files loadTestInfo.SourceFiles.Add(new SourceFileInfo(shellScriptPath, SourceFileAction.Binplace)); // Generate the python script, figure out if the run script is being generated into // a specific directory, if so then generate the LLDB python script there as well GenerateLLDBPythonScript(lldbInspectionFileName, loadTestInfo); }
/* * scriptName - name of the script to be generated, this should include the path * testName - the name of the test executable * arguments - arguments to be passed to the test executable * envVars - dictionary of environment variables and their values * host (optional) - needed for hosted runtimes */ public void GenerateSourceFile(LoadTestInfo loadTestInfo) { string shellScriptPath = Path.Combine(loadTestInfo.SourceDirectory, STRESS_SCRIPT_NAME); using (TextWriter stressScript = new StreamWriter(shellScriptPath, false)) { // set the line ending for shell scripts stressScript.NewLine = "\n"; stressScript.WriteLine("#!/bin/sh"); stressScript.WriteLine(); stressScript.WriteLine(); stressScript.WriteLine("# stress script for {0}", loadTestInfo.TestName); stressScript.WriteLine(); stressScript.WriteLine(); stressScript.WriteLine("# environment section"); // first take care of the environment variables //if the environment variable "DUMPLING_PROPERTIES" already exists remove it //this is needed because multiple LoadTestInfo objects use the same environment dictionary instance if (loadTestInfo.EnvironmentVariables.ContainsKey("DUMPLING_PROPERTIES")) { loadTestInfo.EnvironmentVariables.Remove("DUMPLING_PROPERTIES"); } // add environment variables STRESS_TESTID, STRESS_BUILDID loadTestInfo.EnvironmentVariables["STRESS_TESTID"] = loadTestInfo.TestName; loadTestInfo.EnvironmentVariables["STRESS_BUILDID"] = loadTestInfo.TestName.Split('_')[0]; // build a string of all the env var pairs to be passed as properties to dumpling StringBuilder envVarPropertiesBuilder = new StringBuilder(); foreach (var kvp in loadTestInfo.EnvironmentVariables) { envVarPropertiesBuilder.Append(kvp.Key + "=" + kvp.Value + " "); } // add this string to the env vars as DUMPLING_PROPERTIES trimming the last space loadTestInfo.EnvironmentVariables["DUMPLING_PROPERTIES"] = "\"" + envVarPropertiesBuilder.ToString().TrimEnd(' ') + "\""; //write commands to setup environment environment foreach (KeyValuePair <string, string> kvp in loadTestInfo.EnvironmentVariables) { stressScript.WriteLine("export {0}={1}", kvp.Key, kvp.Value); } stressScript.WriteLine(); stressScript.WriteLine(); // Prepare the test execution line string testCommandLine = loadTestInfo.TestName + ".exe"; stressScript.WriteLine("chmod +x runstress.sh"); // If there is a host then prepend it to the test command line if (!String.IsNullOrEmpty(loadTestInfo.SuiteConfig.Host)) { stressScript.WriteLine($"chmod +x {loadTestInfo.SuiteConfig.Host}"); testCommandLine = loadTestInfo.SuiteConfig.Host + " " + testCommandLine; // If the command line isn't a full path or ./ for current directory then add it to ensure we're using the host in the current directory if ((!loadTestInfo.SuiteConfig.Host.StartsWith("/")) && (!loadTestInfo.SuiteConfig.Host.StartsWith("./"))) { testCommandLine = "./" + testCommandLine; } } testCommandLine = "./runstress.sh " + testCommandLine; stressScript.WriteLine("#test execution"); stressScript.WriteLine("echo executing [{0}]", testCommandLine); stressScript.WriteLine(testCommandLine); // Save off the exit code stressScript.WriteLine("export _EXITCODE=$?"); // exit the script with the return code stressScript.WriteLine("exit $_EXITCODE"); } // Add the shell script to the source files loadTestInfo.SourceFiles.Add(new SourceFileInfo(STRESS_SCRIPT_NAME, SourceFileAction.Binplace)); //add runstress.sh to the source directory as well var runstressPath = Path.Combine(loadTestInfo.SourceDirectory, "runstress.sh"); string unixContent = Encoding.UTF8.GetString(Resources.runstress).Replace("\r\n", "\n"); File.WriteAllText(runstressPath, unixContent); //add runstress.sh to the source files loadTestInfo.SourceFiles.Add(new SourceFileInfo("runstress.sh", SourceFileAction.Binplace)); }
/* * scriptName - name of the script to be generated, this should include the path * testName - the name of the test executable * arguments - arguments to be passed to the test executable * envVars - dictionary of environment variables and their values * host (optional) - needed for hosted runtimes */ public void GenerateSourceFile(LoadTestInfo loadTestInfo) { string lldbInspectionFileName = "inspectCoreWithLLDB.py"; string shellScriptPath = Path.Combine(loadTestInfo.SourceDirectory, "stress.sh"); using (TextWriter stressScript = new StreamWriter(shellScriptPath, false)) { // set the line ending for shell scripts stressScript.NewLine = "\n"; stressScript.WriteLine("!# /bin/sh"); stressScript.WriteLine(); stressScript.WriteLine(); stressScript.WriteLine("# stress script for {0}", loadTestInfo.TestName); stressScript.WriteLine(); stressScript.WriteLine(); stressScript.WriteLine("# environment section"); // first take care of the environment variables foreach (KeyValuePair <string, string> kvp in loadTestInfo.EnvironmentVariables) { stressScript.WriteLine("export {0}={1}", kvp.Key, kvp.Value); } stressScript.WriteLine(); stressScript.WriteLine(); // The default limit for coredumps on Linux and Mac is 0 and needs to be reset to allow core dumps to be created stressScript.WriteLine("# The default limit for coredumps on Linux and Mac is 0 and this needs to be reset to allow core dumps to be created"); stressScript.WriteLine("echo calling [ulimit -c unlimited]"); stressScript.WriteLine("ulimit -c unlimited"); // report the current limits (in theory this should get into the test log) stressScript.WriteLine("echo calling [ulimit -a]"); stressScript.WriteLine("ulimit -a"); stressScript.WriteLine(); stressScript.WriteLine(); // Prepare the test execution line string testCommandLine = loadTestInfo.TestName + ".exe"; // If there is a host then prepend it to the test command line if (!String.IsNullOrEmpty(loadTestInfo.SuiteConfig.Host)) { testCommandLine = loadTestInfo.SuiteConfig.Host + " " + testCommandLine; // If the command line isn't a full path or ./ for current directory then add it to ensure we're using the host in the current directory if ((!loadTestInfo.SuiteConfig.Host.StartsWith("/")) && (!loadTestInfo.SuiteConfig.Host.StartsWith("./"))) { testCommandLine = "./" + testCommandLine; } } stressScript.WriteLine("# test execution"); stressScript.WriteLine("echo calling [{0}]", testCommandLine); stressScript.WriteLine(testCommandLine); // Save off the exit code stressScript.WriteLine("export _EXITCODE=$?"); stressScript.WriteLine("echo test exited with ExitCode: $_EXITCODE"); // Check the return code stressScript.WriteLine("if [ $_EXITCODE != 0 ]"); stressScript.WriteLine("then"); //This is a temporary hack workaround for the fact that the process exits before the coredump file is completely written //We need to replace this with a more hardened way to guaruntee that we don't zip and upload before the coredump is available stressScript.WriteLine(" echo Work item failed waiting for coredump..."); stressScript.WriteLine(" sleep 2m"); stressScript.WriteLine(" echo zipping work item data for coredump analysis"); stressScript.WriteLine($" echo EXEC: $HELIX_PYTHONPATH $HELIX_SCRIPT_ROOT/zip_script.py $HELIX_WORKITEM_ROOT/../{loadTestInfo.TestName}.zip $HELIX_WORKITEM_ROOT $HELIX_WORKITEM_ROOT/execution $HELIX_WORKITEM_ROOT/core_root"); stressScript.WriteLine($" $HELIX_PYTHONPATH $HELIX_SCRIPT_ROOT/zip_script.py -zipFile $HELIX_WORKITEM_ROOT/../{loadTestInfo.TestName}.zip $HELIX_WORKITEM_ROOT $HELIX_WORKITEM_ROOT/execution $HELIX_WORKITEM_ROOT/core_root"); stressScript.WriteLine($" echo uploading coredump zip to $HELIX_RESULTS_CONTAINER_URI{loadTestInfo.TestName}.zip analysis"); stressScript.WriteLine($" echo EXEC: $HELIX_PYTHONPATH $HELIX_SCRIPT_ROOT/upload_result.py -result $HELIX_WORKITEM_ROOT/../{loadTestInfo.TestName}.zip -result_name {loadTestInfo.TestName}.zip -upload_client_type Blob"); stressScript.WriteLine($" $HELIX_PYTHONPATH $HELIX_SCRIPT_ROOT/upload_result.py -result $HELIX_WORKITEM_ROOT/../{loadTestInfo.TestName}.zip -result_name {loadTestInfo.TestName}.zip -upload_client_type Blob"); stressScript.WriteLine("fi"); //// stressScript.WriteLine("zip -r {0}.zip .", testName); //// stressScript.WriteLine("else"); //// stressScript.WriteLine(" echo JRS - Test Passed. Report the pass."); //stressScript.WriteLine("fi"); //stressScript.WriteLine(); //stressScript.WriteLine(); // exit the script with the return code stressScript.WriteLine("exit $_EXITCODE"); } // Add the shell script to the source files loadTestInfo.SourceFiles.Add(new SourceFileInfo(shellScriptPath, SourceFileAction.Binplace)); var shimAssmPath = Assembly.GetAssembly(typeof(StressTestShim)).Location; var shimAssm = Path.GetFileName(shimAssmPath); string shimRefPath = Path.Combine(loadTestInfo.SourceDirectory, shimAssm); File.Copy(shimAssmPath, shimRefPath); loadTestInfo.SourceFiles.Add(new SourceFileInfo(shimAssmPath, SourceFileAction.Binplace)); // Generate the python script, figure out if the run script is being generated into // a specific directory, if so then generate the LLDB python script there as well GenerateLLDBPythonScript(lldbInspectionFileName, loadTestInfo); }
// (string scriptName, string testName, Dictionary<string, string> envVars, string host = null) public void GenerateSourceFile(LoadTestInfo loadTestInfo) { string batchScriptPath = Path.Combine(loadTestInfo.SourceDirectory, STRESS_SCRIPT_NAME); using (TextWriter stressScript = new StreamWriter(batchScriptPath, false)) { stressScript.WriteLine("@echo off"); stressScript.WriteLine("REM stress script for " + loadTestInfo.TestName); stressScript.WriteLine(); stressScript.WriteLine(); stressScript.WriteLine("REM environment section"); // first take care of the environment variables foreach (KeyValuePair<string, string> kvp in loadTestInfo.EnvironmentVariables) { stressScript.WriteLine("set {0}={1}", kvp.Key, kvp.Value); } stressScript.WriteLine(); stressScript.WriteLine(); // Prepare the test execution line string testCommandLine = loadTestInfo.TestName + ".exe"; // If there is a host then prepend it to the test command line if (!String.IsNullOrEmpty(loadTestInfo.SuiteConfig.Host)) { testCommandLine = loadTestInfo.SuiteConfig.Host + " " + testCommandLine; } stressScript.WriteLine("REM test execution"); stressScript.WriteLine("echo calling [{0}]", testCommandLine); stressScript.WriteLine(testCommandLine); // Save off the exit code stressScript.WriteLine("set _EXITCODE=%ERRORLEVEL%"); stressScript.WriteLine("echo test exited with ExitCode: %_EXITCODE%"); stressScript.WriteLine(); stressScript.WriteLine(); // // Check the return code // stressScript.WriteLine("if %_EXITCODE% EQU 0 goto :REPORT_PASS"); // stressScript.WriteLine("REM error processing"); // stressScript.WriteLine("echo JRS - Test Failed. Report the failure, call to do the initial dump analysis, zip up the directory and return that along with an event"); // stressScript.WriteLine("goto :END"); // stressScript.WriteLine(); // stressScript.WriteLine(); // // stressScript.WriteLine(":REPORT_PASS"); // stressScript.WriteLine("echo JRS - Test Passed. Report the pass."); // stressScript.WriteLine(); // stressScript.WriteLine(); // exit the script with the exit code from the process stressScript.WriteLine(":END"); stressScript.WriteLine("exit /b %_EXITCODE%"); } // Add the batch script to the source files loadTestInfo.SourceFiles.Add(new SourceFileInfo(STRESS_SCRIPT_NAME, SourceFileAction.Binplace)); }
/* * scriptName - name of the script to be generated, this should include the path * testName - the name of the test executable * arguments - arguments to be passed to the test executable * envVars - dictionary of environment variables and their values * host (optional) - needed for hosted runtimes */ public void GenerateSourceFile(LoadTestInfo loadTestInfo) { string shellScriptPath = Path.Combine(loadTestInfo.SourceDirectory, STRESS_SCRIPT_NAME); using (TextWriter stressScript = new StreamWriter(shellScriptPath, false)) { // set the line ending for shell scripts stressScript.NewLine = "\n"; stressScript.WriteLine("#! /bin/sh"); stressScript.WriteLine(); stressScript.WriteLine(); stressScript.WriteLine("# stress script for {0}", loadTestInfo.TestName); stressScript.WriteLine(); stressScript.WriteLine(); stressScript.WriteLine("# environment section"); // first take care of the environment variables foreach (KeyValuePair<string, string> kvp in loadTestInfo.EnvironmentVariables) { stressScript.WriteLine("export {0}={1}", kvp.Key, kvp.Value); } stressScript.WriteLine(); stressScript.WriteLine(); // The default limit for coredumps on Linux and Mac is 0 and needs to be reset to allow core dumps to be created stressScript.WriteLine("# The default limit for coredumps on Linux and Mac is 0 and this needs to be reset to allow core dumps to be created"); stressScript.WriteLine("echo calling [ulimit -c unlimited]"); stressScript.WriteLine("ulimit -c unlimited"); // report the current limits (in theory this should get into the test log) stressScript.WriteLine("echo calling [ulimit -a]"); stressScript.WriteLine("ulimit -a"); //update the coredump collection filter stressScript.WriteLine("echo 0x3F > /proc/self/coredump_filter"); stressScript.WriteLine(); stressScript.WriteLine(); // Prepare the test execution line string testCommandLine = loadTestInfo.TestName + ".exe"; // If there is a host then prepend it to the test command line if (!String.IsNullOrEmpty(loadTestInfo.SuiteConfig.Host)) { testCommandLine = loadTestInfo.SuiteConfig.Host + " " + testCommandLine; // If the command line isn't a full path or ./ for current directory then add it to ensure we're using the host in the current directory if ((!loadTestInfo.SuiteConfig.Host.StartsWith("/")) && (!loadTestInfo.SuiteConfig.Host.StartsWith("./"))) { testCommandLine = "./" + testCommandLine; } } stressScript.WriteLine("# test execution"); stressScript.WriteLine("echo calling [{0}]", testCommandLine); stressScript.WriteLine(testCommandLine); // Save off the exit code stressScript.WriteLine("export _EXITCODE=$?"); stressScript.WriteLine("echo test exited with ExitCode: $_EXITCODE"); // Check the return code stressScript.WriteLine("if [ $_EXITCODE != 0 ]"); stressScript.WriteLine("then"); //This is a temporary hack workaround for the fact that the process exits before the coredump file is completely written //We need to replace this with a more hardened way to guaruntee that we don't zip and upload before the coredump is available stressScript.WriteLine(" echo Work item failed waiting for coredump..."); stressScript.WriteLine(" sleep 2m"); //test if the core file was created. //this condition makes the assumption that the file will be name either 'core' or 'core.*' which is true all the distros tested so far //ideally this would be constrained more by setting /proc/sys/kernel/core_pattern to a specific file to look for //however we don't have root permissions from this script when executing in helix so this would have to depend on machine setup stressScript.WriteLine(@" _corefile=$(ls $HELIX_WORKITEM_ROOT/execution | grep -E --max-count=1 '^core(\..*)?$')"); stressScript.WriteLine(" if [ -n '$_corefile' ]"); stressScript.WriteLine(" then"); //if the file core file was produced upload it to the dumpling service stressScript.WriteLine(" echo zipping and uploading core to dumpling service"); stressScript.WriteLine($" echo EXEC: $HELIX_PYTHONPATH ./dumpling.py upload --corefile $HELIX_WORKITEM_ROOT/execution/$_corefile --zipfile $HELIX_WORKITEM_ROOT/{loadTestInfo.TestName}.zip --addpaths $HELIX_WORKITEM_ROOT/execution"); stressScript.WriteLine($" $HELIX_PYTHONPATH ./dumpling.py upload --corefile $_corefile --zipfile $HELIX_WORKITEM_ROOT/{loadTestInfo.TestName}.zip --addpaths $HELIX_WORKITEM_ROOT/execution"); stressScript.WriteLine(" else"); //if the core file was not stressScript.WriteLine(" echo no coredump file '$HELIX_WORKITEM_ROOT/execution/core' was found"); stressScript.WriteLine(" fi"); //the following code zips and uploads the entire execution directory to the helix results store //it is here as a backup source of dump file storage until we are satisfied that the uploading dumps to //the dumpling service is solid and complete. After that this can be removed as it is redundant stressScript.WriteLine(" echo zipping work item data for coredump analysis"); stressScript.WriteLine($" echo EXEC: $HELIX_PYTHONPATH $HELIX_SCRIPT_ROOT/zip_script.py $HELIX_WORKITEM_ROOT/{loadTestInfo.TestName}.zip $HELIX_WORKITEM_ROOT/execution"); stressScript.WriteLine($" $HELIX_PYTHONPATH $HELIX_SCRIPT_ROOT/zip_script.py -zipFile $HELIX_WORKITEM_ROOT/{loadTestInfo.TestName}.zip $HELIX_WORKITEM_ROOT/execution"); stressScript.WriteLine($" echo uploading coredump zip to $HELIX_RESULTS_CONTAINER_URI{loadTestInfo.TestName}.zip analysis"); stressScript.WriteLine($" echo EXEC: $HELIX_PYTHONPATH $HELIX_SCRIPT_ROOT/upload_result.py -result $HELIX_WORKITEM_ROOT/{loadTestInfo.TestName}.zip -result_name {loadTestInfo.TestName}.zip -upload_client_type Blob"); stressScript.WriteLine($" $HELIX_PYTHONPATH $HELIX_SCRIPT_ROOT/upload_result.py -result $HELIX_WORKITEM_ROOT/{loadTestInfo.TestName}.zip -result_name {loadTestInfo.TestName}.zip -upload_client_type Blob"); stressScript.WriteLine("fi"); // exit the script with the return code stressScript.WriteLine("exit $_EXITCODE"); } // Add the shell script to the source files loadTestInfo.SourceFiles.Add(new SourceFileInfo(STRESS_SCRIPT_NAME, SourceFileAction.Binplace)); //this script also depends on dumpling.py so add this to the source files loadTestInfo.SourceFiles.Add(new SourceFileInfo(@"$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Build.cmd))\src\triage.python\dumpling.py", SourceFileAction.Binplace)); }
private static string GenerateFrameworkReferencesSnippet(LoadTestInfo loadTest) { HashSet<string> uniqueAssemblies = new HashSet<string>(); StringBuilder snippet = new StringBuilder(); foreach (var fxref in loadTest.UnitTests.SelectMany(t => t.ReferenceInfo.FrameworkReferences).Union(s_systemRefs).Distinct()) { string refSnippet = $@" <CLRTestContractReference Include='{fxref}' />"; snippet.Append(refSnippet); } snippet.Append(@" <CLRTestContractReference Include='Microsoft.DotNet.stress.execution'> <SkipSupportVerification>true</SkipSupportVerification> <Version>1.0.0-alpha-00003</Version> </CLRTestContractReference>"); return snippet.ToString(); }
/* * scriptName - name of the script to be generated, this should include the path * testName - the name of the test executable * arguments - arguments to be passed to the test executable * envVars - dictionary of environment variables and their values * host (optional) - needed for hosted runtimes */ public void GenerateSourceFile(LoadTestInfo loadTestInfo) { string shellScriptPath = Path.Combine(loadTestInfo.SourceDirectory, STRESS_SCRIPT_NAME); using (TextWriter stressScript = new StreamWriter(shellScriptPath, false)) { // set the line ending for shell scripts stressScript.NewLine = "\n"; stressScript.WriteLine("#! /bin/sh"); stressScript.WriteLine(); stressScript.WriteLine(); stressScript.WriteLine("# stress script for {0}", loadTestInfo.TestName); stressScript.WriteLine(); stressScript.WriteLine(); stressScript.WriteLine("# environment section"); // first take care of the environment variables foreach (KeyValuePair <string, string> kvp in loadTestInfo.EnvironmentVariables) { stressScript.WriteLine("export {0}={1}", kvp.Key, kvp.Value); } stressScript.WriteLine(); stressScript.WriteLine(); // The default limit for coredumps on Linux and Mac is 0 and needs to be reset to allow core dumps to be created stressScript.WriteLine("# The default limit for coredumps on Linux and Mac is 0 and this needs to be reset to allow core dumps to be created"); stressScript.WriteLine("echo calling [ulimit -c unlimited]"); stressScript.WriteLine("ulimit -c unlimited"); // report the current limits (in theory this should get into the test log) stressScript.WriteLine("echo calling [ulimit -a]"); stressScript.WriteLine("ulimit -a"); //update the coredump collection filter stressScript.WriteLine("echo 0x3F > /proc/self/coredump_filter"); stressScript.WriteLine(); stressScript.WriteLine(); // Prepare the test execution line string testCommandLine = loadTestInfo.TestName + ".exe"; // If there is a host then prepend it to the test command line if (!String.IsNullOrEmpty(loadTestInfo.SuiteConfig.Host)) { testCommandLine = loadTestInfo.SuiteConfig.Host + " " + testCommandLine; // If the command line isn't a full path or ./ for current directory then add it to ensure we're using the host in the current directory if ((!loadTestInfo.SuiteConfig.Host.StartsWith("/")) && (!loadTestInfo.SuiteConfig.Host.StartsWith("./"))) { testCommandLine = "./" + testCommandLine; } } stressScript.WriteLine("# test execution"); stressScript.WriteLine("echo calling [{0}]", testCommandLine); stressScript.WriteLine(testCommandLine); // Save off the exit code stressScript.WriteLine("export _EXITCODE=$?"); stressScript.WriteLine("echo test exited with ExitCode: $_EXITCODE"); // Check the return code stressScript.WriteLine("if [ $_EXITCODE != 0 ]"); stressScript.WriteLine("then"); //This is a temporary hack workaround for the fact that the process exits before the coredump file is completely written //We need to replace this with a more hardened way to guaruntee that we don't zip and upload before the coredump is available stressScript.WriteLine(" echo Work item failed waiting for coredump..."); stressScript.WriteLine(" sleep 2m"); //test if the core file was created. //this condition makes the assumption that the file will be name either 'core' or 'core.*' which is true all the distros tested so far //ideally this would be constrained more by setting /proc/sys/kernel/core_pattern to a specific file to look for //however we don't have root permissions from this script when executing in helix so this would have to depend on machine setup stressScript.WriteLine(@" _corefile=$(ls $HELIX_WORKITEM_ROOT/execution | grep -E --max-count=1 '^core(\..*)?$')"); stressScript.WriteLine(" if [ -n '$_corefile' ]"); stressScript.WriteLine(" then"); //if the file core file was produced upload it to the dumpling service stressScript.WriteLine(" echo zipping and uploading core to dumpling service"); stressScript.WriteLine($" echo EXEC: $HELIX_PYTHONPATH ./dumpling.py upload --corefile $HELIX_WORKITEM_ROOT/execution/$_corefile --zipfile $HELIX_WORKITEM_ROOT/{loadTestInfo.TestName}.zip --addpaths $HELIX_WORKITEM_ROOT/execution"); stressScript.WriteLine($" $HELIX_PYTHONPATH ./dumpling.py upload --corefile $_corefile --zipfile $HELIX_WORKITEM_ROOT/{loadTestInfo.TestName}.zip --addpaths $HELIX_WORKITEM_ROOT/execution"); stressScript.WriteLine(" else"); //if the core file was not stressScript.WriteLine(" echo no coredump file '$HELIX_WORKITEM_ROOT/execution/core' was found"); stressScript.WriteLine(" fi"); //the following code zips and uploads the entire execution directory to the helix results store //it is here as a backup source of dump file storage until we are satisfied that the uploading dumps to //the dumpling service is solid and complete. After that this can be removed as it is redundant stressScript.WriteLine(" echo zipping work item data for coredump analysis"); stressScript.WriteLine($" echo EXEC: $HELIX_PYTHONPATH $HELIX_SCRIPT_ROOT/zip_script.py $HELIX_WORKITEM_ROOT/{loadTestInfo.TestName}.zip $HELIX_WORKITEM_ROOT/execution"); stressScript.WriteLine($" $HELIX_PYTHONPATH $HELIX_SCRIPT_ROOT/zip_script.py -zipFile $HELIX_WORKITEM_ROOT/{loadTestInfo.TestName}.zip $HELIX_WORKITEM_ROOT/execution"); stressScript.WriteLine($" echo uploading coredump zip to $HELIX_RESULTS_CONTAINER_URI{loadTestInfo.TestName}.zip analysis"); stressScript.WriteLine($" echo EXEC: $HELIX_PYTHONPATH $HELIX_SCRIPT_ROOT/upload_result.py -result $HELIX_WORKITEM_ROOT/{loadTestInfo.TestName}.zip -result_name {loadTestInfo.TestName}.zip -upload_client_type Blob"); stressScript.WriteLine($" $HELIX_PYTHONPATH $HELIX_SCRIPT_ROOT/upload_result.py -result $HELIX_WORKITEM_ROOT/{loadTestInfo.TestName}.zip -result_name {loadTestInfo.TestName}.zip -upload_client_type Blob"); stressScript.WriteLine("fi"); // exit the script with the return code stressScript.WriteLine("exit $_EXITCODE"); } // Add the shell script to the source files loadTestInfo.SourceFiles.Add(new SourceFileInfo(STRESS_SCRIPT_NAME, SourceFileAction.Binplace)); //this script also depends on dumpling.py so add this to the source files loadTestInfo.SourceFiles.Add(new SourceFileInfo(@"$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Build.cmd))\src\triage.python\dumpling.py", SourceFileAction.Binplace)); }
private static string GenerateTestPropertiesSnippet(LoadTestInfo loadTest) { //timeout = test duration + 5 minutes for dump processing ect. string timeoutInSeconds = Convert.ToInt32((loadTest.Duration + TimeSpan.FromMinutes(5)).TotalSeconds).ToString(); string propertyString = $@" <TestAssembly>stress.execution</TestAssembly> <TimeoutInSeconds>{timeoutInSeconds}</TimeoutInSeconds>"; return propertyString; }