<commit_before>﻿//-----------------------------------------------------------------------
// <copyright file="ProcessRunnerTests.cs" company="SonarSource SA and Microsoft Corporation">
//   Copyright (c) SonarSource SA and Microsoft Corporation.  All rights reserved.
//   Licensed under the MIT License. See License.txt in the project root for license information.
// </copyright>
//-----------------------------------------------------------------------


using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.IO;
using TestUtilities;

namespace SonarQube.Common.UnitTests
{
    [TestClass]
    public class ProcessRunnerTests
    {
        public TestContext TestContext { get; set; }

        #region Tests

        [TestMethod]
        public void ProcRunner_ExecutionFailed()
        {
            // Arrange
            string exeName = WriteBatchFileForTest("exit -2");

            TestLogger logger = new TestLogger();
            ProcessRunner runner = new ProcessRunner();

            // Act
            bool success = runner.Execute(exeName, null, null, 5000, logger);

            // Assert
            Assert.IsFalse(success, "Expecting the process to have failed");
            Assert.AreEqual(-2, runner.ExitCode, "Unexpected exit code");
        }

        [TestMethod]
        public void ProcRunner_ExecutionSucceeded()
        {
            // Arrange
            string exeName = WriteBatchFileForTest(
@"@echo Hello world
xxx yyy
@echo Testing 1,2,3...
");

            TestLogger logger = new TestLogger();
            ProcessRunner runner = new ProcessRunner();

            // Act
            bool success = runner.Execute(exeName, null, null, 1000, logger);

            // Assert
            Assert.IsTrue(success, "Expecting the process to have succeeded");
            Assert.AreEqual(0, runner.ExitCode, "Unexpected exit code");

            logger.AssertMessageLogged("Hello world"); // Check output message are passed to the logger
            logger.AssertMessageLogged("Testing 1,2,3...");
            logger.AssertErrorLogged("'xxx' is not recognized as an internal or external command,"); // Check error messages are passed to the logger
        }

        [TestMethod]
        public void ProcRunner_FailsOnTimeout()
        {
            // Arrange
            string exeName = WriteBatchFileForTest(
@"TIMEOUT 1
@echo Hello world
");

            TestLogger logger = new TestLogger();
            ProcessRunner runner = new ProcessRunner();

            // Act
            bool success = runner.Execute(exeName, null, null, 100, logger);

            // Assert
            Assert.IsFalse(success, "Expecting the process to have failed");
            Assert.AreEqual(0, runner.ExitCode, "Unexpected exit code");
            logger.AssertMessageNotLogged("Hello world");

            // Give the spawned process a chance to terminate.
            // This isn't essential (and having a Sleep in the test isn't ideal), but it stops
            // the test framework outputting this warning which appears in the TeamBuild summary:
            // "System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain. This can happen 
            // if the test(s) started a thread but did not stop it. Make sure that all the threads started by 
            // the test(s) are stopped before completion."
            System.Threading.Thread.Sleep(1100);
        }

        [TestMethod]
        public void ProcRunner_PassesEnvVariables()
        {
            // Arrange
            TestLogger logger = new TestLogger();
            ProcessRunner runner = new ProcessRunner();

            string exeName = WriteBatchFileForTest(
@"echo %PROCESS_VAR%
@echo %PROCESS_VAR2%
@echo %PROCESS_VAR3%
");
            var envVariables = new Dictionary<string, string>() {
                { "PROCESS_VAR", "PROCESS_VAR value" },
                { "PROCESS_VAR2", "PROCESS_VAR2 value" },
                { "PROCESS_VAR3", "PROCESS_VAR3 value" } };

            // Act
            bool success = runner.Execute(exeName, null, null, 150, envVariables, logger);

            // Assert
            Assert.IsTrue(success, "Expecting the process to have succeeded");
            Assert.AreEqual(0, runner.ExitCode, "Unexpected exit code");

            logger.AssertMessageLogged("PROCESS_VAR value");
            logger.AssertMessageLogged("PROCESS_VAR2 value");
            logger.AssertMessageLogged("PROCESS_VAR3 value");
        }

        [TestMethod]
        public void ProcRunner_PassesEnvVariables_OverrideExisting()
        {
            // Tests that existing environment variables will be overwritten successfully

            // Arrange
            TestLogger logger = new TestLogger();
            ProcessRunner runner = new ProcessRunner();

            // We can't set machine-level variables from the test so use the PATH
            string existingPath = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine);
            Assert.IsFalse(string.IsNullOrWhiteSpace(existingPath), "Test setup error: %PATH% should not be null");

            try
            {
                Environment.SetEnvironmentVariable("proc.runner.test.process", "existing process value", EnvironmentVariableTarget.Process);
                Environment.SetEnvironmentVariable("proc.runner.test.user", "existing user value", EnvironmentVariableTarget.User);

                string exeName = WriteBatchFileForTest(
@"@echo file: %PATH%
@echo file: %proc.runner.test.process%
@echo file: %proc.runner.test.user%
");

                var envVariables = new Dictionary<string, string>() {
                    { "PATH", "path override" },
                    { "proc.runner.test.process", "process override" },
                    { "proc.runner.test.user", "user override" } };
  
                // Act
                bool success = runner.Execute(exeName, null, null, 150, envVariables, logger);

                // Assert
                Assert.IsTrue(success, "Expecting the process to have succeeded");
                Assert.AreEqual(0, runner.ExitCode, "Unexpected exit code");
            }
            finally
            {
                Environment.SetEnvironmentVariable("proc.runner.test.process", null, EnvironmentVariableTarget.Process);
                Environment.SetEnvironmentVariable("proc.runner.test.user", null, EnvironmentVariableTarget.User);
            }

            // Check the child process used expected values
            logger.AssertMessageLogged("file: path override");
            logger.AssertMessageLogged("file: process override");
            logger.AssertMessageLogged("file: user override");

            // Check the runner reported it was overwriting existing variables
            // Note: the existing value won't be visible to the child process unless
            // it was set *before* the test host launched, which won't be the case.
            // Consequently, the log won't show the user variable as being overwritten.
            logger.AssertSingleMessageExists("PATH", existingPath, "path override");
            logger.AssertSingleMessageExists("proc.runner.test.process", "existing process value", "process override");
        }

        #endregion


        #region Private methods

        /// <summary>
        /// Creates a batch file with the name of the current test
        /// </summary>
        /// <returns>Returns the full file name of the new file</returns>
        private string WriteBatchFileForTest(string content)
        {
            string fileName = Path.Combine(this.TestContext.DeploymentDirectory, this.TestContext.TestName + ".bat");
            Assert.IsFalse(File.Exists(fileName), "Not expecting a batch file to already exist: {0}", fileName);
            File.WriteAllText(fileName, content);
            return fileName;
        }

        #endregion
    }
}<commit_msg>Fix process runner test on CI machine<commit_after>﻿//-----------------------------------------------------------------------
// <copyright file="ProcessRunnerTests.cs" company="SonarSource SA and Microsoft Corporation">
//   Copyright (c) SonarSource SA and Microsoft Corporation.  All rights reserved.
//   Licensed under the MIT License. See License.txt in the project root for license information.
// </copyright>
//-----------------------------------------------------------------------


using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.IO;
using TestUtilities;

namespace SonarQube.Common.UnitTests
{
    [TestClass]
    public class ProcessRunnerTests
    {
        public TestContext TestContext { get; set; }

        #region Tests

        [TestMethod]
        public void ProcRunner_ExecutionFailed()
        {
            // Arrange
            string exeName = WriteBatchFileForTest("exit -2");

            TestLogger logger = new TestLogger();
            ProcessRunner runner = new ProcessRunner();

            // Act
            bool success = runner.Execute(exeName, null, null, 5000, logger);

            // Assert
            Assert.IsFalse(success, "Expecting the process to have failed");
            Assert.AreEqual(-2, runner.ExitCode, "Unexpected exit code");
        }

        [TestMethod]
        public void ProcRunner_ExecutionSucceeded()
        {
            // Arrange
            string exeName = WriteBatchFileForTest(
@"@echo Hello world
xxx yyy
@echo Testing 1,2,3...
");

            TestLogger logger = new TestLogger();
            ProcessRunner runner = new ProcessRunner();

            // Act
            bool success = runner.Execute(exeName, null, null, 1000, logger);

            // Assert
            Assert.IsTrue(success, "Expecting the process to have succeeded");
            Assert.AreEqual(0, runner.ExitCode, "Unexpected exit code");

            logger.AssertMessageLogged("Hello world"); // Check output message are passed to the logger
            logger.AssertMessageLogged("Testing 1,2,3...");
            logger.AssertErrorLogged("'xxx' is not recognized as an internal or external command,"); // Check error messages are passed to the logger
        }

        [TestMethod]
        public void ProcRunner_FailsOnTimeout()
        {
            // Arrange
            string exeName = WriteBatchFileForTest(
@"TIMEOUT 1
@echo Hello world
");

            TestLogger logger = new TestLogger();
            ProcessRunner runner = new ProcessRunner();

            // Act
            bool success = runner.Execute(exeName, null, null, 100, logger);

            // Assert
            Assert.IsFalse(success, "Expecting the process to have failed");
            Assert.AreEqual(0, runner.ExitCode, "Unexpected exit code");
            logger.AssertMessageNotLogged("Hello world");

            // Give the spawned process a chance to terminate.
            // This isn't essential (and having a Sleep in the test isn't ideal), but it stops
            // the test framework outputting this warning which appears in the TeamBuild summary:
            // "System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain. This can happen 
            // if the test(s) started a thread but did not stop it. Make sure that all the threads started by 
            // the test(s) are stopped before completion."
            System.Threading.Thread.Sleep(1100);
        }

        [TestMethod]
        public void ProcRunner_PassesEnvVariables()
        {
            // Arrange
            TestLogger logger = new TestLogger();
            ProcessRunner runner = new ProcessRunner();

            string exeName = WriteBatchFileForTest(
@"echo %PROCESS_VAR%
@echo %PROCESS_VAR2%
@echo %PROCESS_VAR3%
");
            var envVariables = new Dictionary<string, string>() {
                { "PROCESS_VAR", "PROCESS_VAR value" },
                { "PROCESS_VAR2", "PROCESS_VAR2 value" },
                { "PROCESS_VAR3", "PROCESS_VAR3 value" } };

            // Act
            bool success = runner.Execute(exeName, null, null, 150, envVariables, logger);

            // Assert
            Assert.IsTrue(success, "Expecting the process to have succeeded");
            Assert.AreEqual(0, runner.ExitCode, "Unexpected exit code");

            logger.AssertMessageLogged("PROCESS_VAR value");
            logger.AssertMessageLogged("PROCESS_VAR2 value");
            logger.AssertMessageLogged("PROCESS_VAR3 value");
        }

        [TestMethod]
        public void ProcRunner_PassesEnvVariables_OverrideExisting()
        {
            // Tests that existing environment variables will be overwritten successfully

            // Arrange
            TestLogger logger = new TestLogger();
            ProcessRunner runner = new ProcessRunner();

            try
            {
                Environment.SetEnvironmentVariable("proc.runner.test.machine", "existing machine value", EnvironmentVariableTarget.Machine);
                Environment.SetEnvironmentVariable("proc.runner.test.process", "existing process value", EnvironmentVariableTarget.Process);
                Environment.SetEnvironmentVariable("proc.runner.test.user", "existing user value", EnvironmentVariableTarget.User);

                string exeName = WriteBatchFileForTest(
@"@echo file: %proc.runner.test.machine%
@echo file: %proc.runner.test.process%
@echo file: %proc.runner.test.user%
");

                var envVariables = new Dictionary<string, string>() {
                    { "proc.runner.test.machine", "machine override" },
                    { "proc.runner.test.process", "process override" },
                    { "proc.runner.test.user", "user override" } };
  
                // Act
                bool success = runner.Execute(exeName, null, null, 200, envVariables, logger);

                // Assert
                Assert.IsTrue(success, "Expecting the process to have succeeded");
                Assert.AreEqual(0, runner.ExitCode, "Unexpected exit code");
            }
            finally
            {
                Environment.SetEnvironmentVariable("proc.runner.test.machine", null, EnvironmentVariableTarget.Machine);
                Environment.SetEnvironmentVariable("proc.runner.test.process", null, EnvironmentVariableTarget.Process);
                Environment.SetEnvironmentVariable("proc.runner.test.user", null, EnvironmentVariableTarget.User);
            }

            // Check the child process used expected values
            logger.AssertMessageLogged("file: machine override");
            logger.AssertMessageLogged("file: process override");
            logger.AssertMessageLogged("file: user override");

            // Check the runner reported it was overwriting existing variables
            // Note: the existing non-process values won't be visible to the child process
            // unless they were set *before* the test host launched, which won't be the case.
            logger.AssertSingleMessageExists("proc.runner.test.process", "existing process value", "process override");
        }

        #endregion


        #region Private methods

        /// <summary>
        /// Creates a batch file with the name of the current test
        /// </summary>
        /// <returns>Returns the full file name of the new file</returns>
        private string WriteBatchFileForTest(string content)
        {
            string fileName = Path.Combine(this.TestContext.DeploymentDirectory, this.TestContext.TestName + ".bat");
            Assert.IsFalse(File.Exists(fileName), "Not expecting a batch file to already exist: {0}", fileName);
            File.WriteAllText(fileName, content);
            return fileName;
        }

        #endregion
    }
}
{'fraction_non_alphanumeric': 0.10990682639285035, 'fraction_numerical': 0.005450972935285542, 'mean_word_length': 2.1010220125786163, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3430851', 'n_tokens_mistral': 3841, 'n_tokens_neox': 3654, 'n_words': 1141}