Beispiel #1
0
        public static void TakeMemoryDump(this Process process, string outputFolderPath, ITestOutputHelper output)
        {
            // this environment variable is set by Github Actions CI to `true` https://docs.github.com/en/actions/learn-github-actions/environment-variables
            string ciEnvVar = Environment.GetEnvironmentVariable("CI");

            if (!bool.TryParse(ciEnvVar, out var result) || !result)
            {
                output.WriteLine("^^^^^^^^^^^^^^^^^^^^^^ Currently not running in Github Actions CI. No memory dump will be taken.");
                return;
            }

            output.WriteLine($"^^^^^^^^^^^^^^^^^^^^^^ Taking memory dump of process Id {process.Id}...");

            using var processDump = new Process();

            if (EnvironmentHelper.IsRunningOnWindows())
            {
                // In Github Actions CI, we downloaded, extracted procdump. We also add its folder to the PATH
                processDump.StartInfo.FileName  = Environment.Is64BitProcess ? "procdump64.exe" : "procdump.exe";
                processDump.StartInfo.Arguments = $@"-ma {process.Id} -accepteula";
            }
            else
            {
                processDump.StartInfo.FileName  = "dotnet-dump";
                processDump.StartInfo.Arguments = $"collect --process-id {process.Id}";
            }

            processDump.StartInfo.UseShellExecute        = false;
            processDump.StartInfo.CreateNoWindow         = true;
            processDump.StartInfo.RedirectStandardOutput = true;
            processDump.StartInfo.RedirectStandardError  = true;
            processDump.StartInfo.RedirectStandardInput  = false;
            processDump.StartInfo.WorkingDirectory       = outputFolderPath;
            processDump.Start();

            using var helper = new ProcessHelper(processDump);

            bool ranToCompletion = processDump.WaitForExit(MemoryDumpDurationMs) && helper.Drain(MemoryDumpDurationMs / 2);

            if (!ranToCompletion)
            {
                output.WriteLine("   Failed to take a memory dump.");
                if (!processDump.HasExited)
                {
                    output.WriteLine($"   Dumping tool (Id {processDump.Id}) has not exited. Terminating it.");

                    try
                    {
                        processDump.KillTree();
                    }
                    catch
                    {
                        // do nothing
                    }
                }
            }
            else
            {
                output.WriteLine($"   Memory dump successfully taken for process {process.Id}");
            }

            var standardOutput = helper.StandardOutput;

            if (!string.IsNullOrWhiteSpace(standardOutput))
            {
                output.WriteLine($"   Memory dump tool output: {Environment.NewLine}{standardOutput}");
            }

            var errorOutput = helper.ErrorOutput;

            if (!string.IsNullOrWhiteSpace(errorOutput))
            {
                output.WriteLine($"   Memory dump tool error: {Environment.NewLine}{errorOutput}");
            }
        }
Beispiel #2
0
        private void RunTest(int agentPort)
        {
            (var executor, var arguments) = BuildTestCommandLine();

            using var process = new Process();

            SetEnvironmentVariables(process.StartInfo.EnvironmentVariables, agentPort);

            process.StartInfo.FileName               = executor;
            process.StartInfo.Arguments              = arguments;
            process.StartInfo.UseShellExecute        = false;
            process.StartInfo.CreateNoWindow         = true;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardError  = true;
            process.StartInfo.RedirectStandardInput  = false;
            process.Start();

            using var processHelper = new ProcessHelper(process);

            var ranToCompletion = process.WaitForExit((int)_maxTestRunDuration.TotalMilliseconds) && processHelper.Drain((int)_maxTestRunDuration.TotalMilliseconds / 2);

            var standardOutput = processHelper.StandardOutput;
            var errorOutput    = processHelper.ErrorOutput;

            if (!ranToCompletion)
            {
                if (!process.HasExited)
                {
                    process.GetAllThreadsStack(_testBaseOutputDir, _output);

                    process.TakeMemoryDump(_testBaseOutputDir, _output);

                    try
                    {
                        process.KillTree();
                    }
                    catch
                    {
                        // do nothing
                    }

                    _output.WriteLine($"The test {_appName} is running for too long (more than {_maxTestRunDuration.TotalSeconds} seconds) or was lost.");
                    _output.WriteLine(standardOutput);
                    _output.WriteLine(errorOutput);
                    throw new TimeoutException($"The test {_appName} is running for too long or was lost");
                }
            }

            if (!string.IsNullOrWhiteSpace(standardOutput))
            {
                _output.WriteLine($"[TestRunner] Standard output: {standardOutput}");
                Assert.False(standardOutput.Contains("[Error]"), "An error occured during the test. See the standard output above.");
            }

            if (!string.IsNullOrWhiteSpace(errorOutput))
            {
                _output.WriteLine($"[TestRunner] Error output: {errorOutput}");
                Assert.False(errorOutput.Contains("[Error]"), "An error occured during the test. See the error output above.");
            }

            Assert.True(
                0 == process.ExitCode,
                $"Exit code of \"{Path.GetFileName(process.StartInfo?.FileName ?? string.Empty)}\" should be 0 instead of {process.ExitCode} (= 0x{process.ExitCode.ToString("X")})");
        }