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++;
                }
            }
        }
Beispiel #4
0
        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++;
                }
            }
        }
Beispiel #5
0
        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());
        }
Beispiel #6
0
        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 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);
        }
Beispiel #11
0
        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));
        }
Beispiel #13
0
        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);
        }
Beispiel #14
0
        private void GenerateTestSources(LoadTestInfo loadTest, IEnumerable <ISourceFileGenerator> sourceFileGenerators)
        {
            Directory.CreateDirectory(loadTest.SourceDirectory);

            CopyUnitTestAssemblyRefs(loadTest);

            foreach (var sourceGen in sourceFileGenerators)
            {
                sourceGen.GenerateSourceFile(loadTest);
            }
        }
Beispiel #15
0
        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);
        }
Beispiel #20
0
        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 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 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);
            }
        }
Beispiel #23
0
        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());
        }
Beispiel #26
0
        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));
        }
        // 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);
        }
Beispiel #31
0
        /*
         * 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;
        }