示例#1
0
        public void ProcRunner_PassesEnvVariables()
        {
            // Arrange
            TestLogger    logger = new TestLogger();
            ProcessRunner runner = new ProcessRunner();

            string exeName = TestUtils.WriteBatchFileForTest(TestContext,
                                                             @"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" }
            };

            ProcessScannerArguments args = new ProcessScannerArguments(exeName, true, logger)
            {
                EnvironmentVariables = envVariables
            };

            // Act
            bool success = runner.Execute(args);

            // 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");
        }
示例#2
0
        public void ProcRunner_PassesEnvVariables_OverrideExisting()
        {
            // Tests that existing environment variables will be overwritten successfully

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

            try
            {
                // It's possible the user won't be have permissions to set machine level variables
                // (e.g. when running on a build agent). Carry on with testing the other variables.
                SafeSetEnvironmentVariable("proc.runner.test.machine", "existing machine value", EnvironmentVariableTarget.Machine, logger);
                Environment.SetEnvironmentVariable("proc.runner.test.process", "existing process value", EnvironmentVariableTarget.Process);
                Environment.SetEnvironmentVariable("proc.runner.test.user", "existing user value", EnvironmentVariableTarget.User);

                string exeName = TestUtils.WriteBatchFileForTest(TestContext,
                                                                 @"@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" }
                };

                ProcessScannerArguments args = new ProcessScannerArguments(exeName, true, logger)
                {
                    EnvironmentVariables = envVariables
                };

                // Act
                bool success = runner.Execute(args);

                // Assert
                Assert.IsTrue(success, "Expecting the process to have succeeded");
                Assert.AreEqual(0, runner.ExitCode, "Unexpected exit code");
            }
            finally
            {
                SafeSetEnvironmentVariable("proc.runner.test.machine", null, EnvironmentVariableTarget.Machine, logger);
                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.AssertSingleDebugMessageExists("proc.runner.test.process", "existing process value", "process override");
        }
        private static void AppendKeyValue(StringBuilder sb, string key, string value)
        {
            Debug.Assert(!ProcessScannerArguments.ContainsSensitiveData(key) && !ProcessScannerArguments.ContainsSensitiveData(value),
                         "Not expecting sensitive data to be written to the sonar-project properties file. Key: {0}", key);

            sb.Append(key);
            sb.Append('=');
            sb.AppendLine(Escape(value));
        }
示例#4
0
        public void ProcRunner_ExecutionFailed()
        {
            // Arrange
            string exeName = TestUtils.WriteBatchFileForTest(TestContext, "exit -2");

            TestLogger logger              = new TestLogger();
            ProcessScannerArguments args   = new ProcessScannerArguments(exeName, true, logger);
            ProcessRunner           runner = new ProcessRunner();

            // Act
            bool success = runner.Execute(args);

            // Assert
            Assert.IsFalse(success, "Expecting the process to have failed");
            Assert.AreEqual(-2, runner.ExitCode, "Unexpected exit code");
        }
示例#5
0
        public void ProcRunner_ArgumentQuotingForwardedByBatchScript()
        {
            // Checks arguments passed to a batch script which itself passes them on are correctly escaped

            // Arrange
            string testDir = TestUtils.CreateTestSpecificFolder(this.TestContext);
            // Create a dummy exe that will produce a log file showing any input args
            string exeName = DummyExeHelper.CreateDummyPostProcessor(testDir, 0);

            string batchName = TestUtils.WriteBatchFileForTest(TestContext, "\"" + exeName + "\" %*");

            TestLogger logger            = new TestLogger();
            ProcessScannerArguments args = new ProcessScannerArguments(batchName, true, logger);

            var expected = new[] {
                "unquoted",
                "\"quoted\"",
                "\"quoted with spaces\"",
                "/test:\"quoted arg\"",
                "unquoted with spaces",
                "quote in \"the middle",
                "quotes \"& ampersands",
                "\"multiple \"\"\"      quotes \" ",
                "trailing backslash \\",
                "all special chars: \\ / : * ? \" < > | %",
                "injection \" > foo.txt",
                "injection \" & echo haha",
                "double escaping \\\" > foo.txt"
            };

            args.CmdLineArgs = expected;

            ProcessRunner runner = new ProcessRunner();

            // Act
            bool success = runner.Execute(args);

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

            // Check that the public and private arguments are passed to the child process
            string exeLogFile = DummyExeHelper.AssertDummyPostProcLogExists(testDir, this.TestContext);

            DummyExeHelper.AssertExpectedLogContents(exeLogFile, expected);
        }
示例#6
0
        public void ProcRunner_MissingExe()
        {
            // Tests attempting to launch a non-existent exe

            // Arrange
            TestLogger logger              = new TestLogger();
            ProcessScannerArguments args   = new ProcessScannerArguments("missingExe.foo", false, logger);
            ProcessRunner           runner = new ProcessRunner();

            // Act
            bool success = runner.Execute(args);

            // Assert
            Assert.IsFalse(success, "Expecting the process to have failed");
            Assert.AreEqual(ProcessRunner.ErrorCode, runner.ExitCode, "Unexpected exit code");
            logger.AssertSingleErrorExists("missingExe.foo");
        }
        public void V0_9Upgrade_CalledFromV0_9()
        {
            // Arrange
            TestLogger logger = new TestLogger();
            ProcessScannerArguments scannerArgs = new ProcessScannerArguments(typeof(V0_9UpgradeMessageExe.Program).Assembly.Location, false, logger)
            {
                WorkingDirectory = this.TestContext.DeploymentDirectory
            };

            // Act
            ProcessRunner runner  = new ProcessRunner();
            bool          success = runner.Execute(scannerArgs);

            // Assert
            Assert.IsFalse(success);
            logger.AssertSingleErrorExists(SonarQube.V0_9UpgradeMessageExe.Resources.UpgradeMessage);
            logger.AssertErrorsLogged(1);
        }
        private static int PreProcess(IBuildAgentUpdater updater, IBootstrapperSettings settings, ILogger logger)
        {
            string downloadBinPath = settings.DownloadDirectory;

            logger.LogInfo(Resources.MSG_PreparingDirectories);
            if (!Utilities.TryEnsureEmptyDirectories(logger,
                                                     settings.TempDirectory,
                                                     downloadBinPath))
            {
                return(ErrorCode);
            }

            string server = settings.SonarQubeUrl;

            Debug.Assert(!string.IsNullOrWhiteSpace(server), "Not expecting the server url to be null/empty");
            logger.LogDebug(Resources.MSG_ServerUrl, server);

            logger.LogInfo(Resources.MSG_CheckingForUpdates);
            if (!updater.TryUpdate(server, downloadBinPath, logger))
            {
                logger.LogError(Resources.ERROR_FailedToUpdateRunnerBinaries);
                return(ErrorCode);
            }

            if (!updater.CheckBootstrapperApiVersion(settings.SupportedBootstrapperVersionsFilePath, settings.BootstrapperVersion))
            {
                logger.LogError(Resources.ERROR_VersionMismatch);
                return(ErrorCode);
            }

            var preprocessorFilePath = settings.PreProcessorFilePath;

            ProcessScannerArguments runnerArgs = new ProcessScannerArguments(preprocessorFilePath, false, logger)
            {
                CmdLineArgs      = settings.ChildCmdLineArgs,
                WorkingDirectory = settings.TempDirectory,
            };
            ProcessRunner runner = new ProcessRunner();

            runner.Execute(runnerArgs);

            return(runner.ExitCode);
        }
        private static int PostProcess(IBootstrapperSettings settings, ILogger logger)
        {
            if (!File.Exists(settings.PostProcessorFilePath))
            {
                logger.LogError(Resources.ERROR_PostProcessExeNotFound, settings.PostProcessorFilePath);
                return(ErrorCode);
            }

            ProcessScannerArguments runnerArgs = new ProcessScannerArguments(settings.PostProcessorFilePath, false, logger)
            {
                CmdLineArgs      = settings.ChildCmdLineArgs,
                WorkingDirectory = settings.TempDirectory
            };

            ProcessRunner runner = new ProcessRunner();

            runner.Execute(runnerArgs);

            return(runner.ExitCode);
        }
示例#10
0
        public /* for test purposes */ static bool ExecuteJavaRunner(AnalysisConfig config, IEnumerable <string> userCmdLineArguments, ILogger logger, string exeFileName, string propertiesFileName)
        {
            Debug.Assert(File.Exists(exeFileName), "The specified exe file does not exist: " + exeFileName);
            Debug.Assert(File.Exists(propertiesFileName), "The specified properties file does not exist: " + propertiesFileName);

            IgnoreSonarScannerHome(logger);

            IEnumerable <string> allCmdLineArgs = GetAllCmdLineArgs(propertiesFileName, userCmdLineArguments, config);

            IDictionary <string, string> envVarsDictionary = GetAdditionalEnvVariables(logger);

            Debug.Assert(envVarsDictionary != null);

            logger.LogInfo(Resources.MSG_SonarScannerCalling);

            Debug.Assert(!String.IsNullOrWhiteSpace(config.SonarScannerWorkingDirectory), "The working dir should have been set in the analysis config");
            Debug.Assert(Directory.Exists(config.SonarScannerWorkingDirectory), "The working dir should exist");

            ProcessScannerArguments scannerArgs = new ProcessScannerArguments(exeFileName, true, logger)
            {
                CmdLineArgs          = allCmdLineArgs,
                WorkingDirectory     = config.SonarScannerWorkingDirectory,
                EnvironmentVariables = envVarsDictionary
            };

            ProcessRunner runner = new ProcessRunner();

            // SONARMSBRU-202 Note that the Sonar Scanner may write warnings to stderr so
            // we should only rely on the exit code when deciding if it ran successfully
            bool success = runner.Execute(scannerArgs);

            if (success)
            {
                logger.LogInfo(Resources.MSG_SonarScannerCompleted);
            }
            else
            {
                logger.LogError(Resources.ERR_SonarScannerExecutionFailed);
            }
            return(success);
        }
示例#11
0
        // was internal
        public static bool ConvertBinaryToXml(string converterExeFilePath, string inputBinaryFilePath, string outputXmlFilePath, ILogger logger)
        {
            Debug.Assert(!string.IsNullOrEmpty(converterExeFilePath), "Expecting the conversion tool path to have been set");
            Debug.Assert(File.Exists(converterExeFilePath), "Expecting the converter exe to exist: " + converterExeFilePath);
            Debug.Assert(Path.IsPathRooted(inputBinaryFilePath), "Expecting the input file name to be a full absolute path");
            Debug.Assert(File.Exists(inputBinaryFilePath), "Expecting the input file to exist: " + inputBinaryFilePath);
            Debug.Assert(Path.IsPathRooted(outputXmlFilePath), "Expecting the output file name to be a full absolute path");

            List <string> args = new List <string>();

            args.Add("analyze");
            args.Add(string.Format(System.Globalization.CultureInfo.InvariantCulture, @"/output:{0}", outputXmlFilePath));
            args.Add(inputBinaryFilePath);

            ProcessScannerArguments scannerArgs = new ProcessScannerArguments(converterExeFilePath, false, logger)
            {
                WorkingDirectory      = Path.GetDirectoryName(outputXmlFilePath),
                CmdLineArgs           = args,
                TimeoutInMilliseconds = ConversionTimeoutInMs
            };

            ProcessRunner runner  = new ProcessRunner();
            bool          success = runner.Execute(scannerArgs);

            if (success)
            {
                // Check the output file actually exists
                if (!File.Exists(outputXmlFilePath))
                {
                    logger.LogError(Resources.CONV_ERROR_OutputFileNotFound, outputXmlFilePath);
                    success = false;
                }
            }
            else
            {
                logger.LogError(Resources.CONV_ERROR_ConversionToolFailed, inputBinaryFilePath);
            }

            return(success);
        }
示例#12
0
        public void ProcRunner_FailsOnTimeout()
        {
            // Arrange

            // Calling TIMEOUT can fail on some older OSes (e.g. Windows 7) with the error
            // "Input redirection is not supported, exiting the process immediately."
            // However, it works reliably on the CI machines. Alternatives such as
            // pinging a non-existent address with a timeout were not reliable.
            string exeName = TestUtils.WriteBatchFileForTest(TestContext,
                                                             @"TIMEOUT 1
@echo Hello world
");

            TestLogger logger            = new TestLogger();
            ProcessScannerArguments args = new ProcessScannerArguments(exeName, true, logger)
            {
                TimeoutInMilliseconds = 100
            };
            ProcessRunner runner = new ProcessRunner();

            Stopwatch timer = Stopwatch.StartNew();

            // Act
            bool success = runner.Execute(args);

            // Assert
            timer.Stop(); // Sanity check that the process actually timed out
            logger.LogInfo("Test output: test ran for {0}ms", timer.ElapsedMilliseconds);
            // TODO: the following line throws regularly on the CI machines (elapsed time is around 97ms);
            // Assert.IsTrue(timer.ElapsedMilliseconds >= 100, "Test error: batch process exited too early. Elapsed time(ms): {0}", timer.ElapsedMilliseconds);

            Assert.IsFalse(success, "Expecting the process to have failed");
            Assert.AreEqual(ProcessRunner.ErrorCode, runner.ExitCode, "Unexpected exit code");
            logger.AssertMessageNotLogged("Hello world");
            logger.AssertWarningsLogged(1); // expecting a warning about the timeout
            Assert.IsTrue(logger.Warnings.Single().Contains("has been terminated"));
        }
示例#13
0
        public void ProcRunner_ExecutionSucceeded()
        {
            // Arrange
            string exeName = TestUtils.WriteBatchFileForTest(TestContext,
                                                             @"@echo Hello world
xxx yyy
@echo Testing 1,2,3...
");

            TestLogger logger              = new TestLogger();
            ProcessScannerArguments args   = new ProcessScannerArguments(exeName, true, logger);
            ProcessRunner           runner = new ProcessRunner();

            // Act
            bool success = runner.Execute(args);

            // 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
        }
示例#14
0
        [WorkItem(126)] // Exclude secrets from log data: http://jira.sonarsource.com/browse/SONARMSBRU-126
        public void ProcRunner_DoNotLogSensitiveData()
        {
            // Arrange
            string testDir = TestUtils.CreateTestSpecificFolder(this.TestContext);
            // Create a dummy exe that will produce a log file showing any input args
            string exeName = DummyExeHelper.CreateDummyPostProcessor(testDir, 0);

            TestLogger logger = new TestLogger();

            // Public args - should appear in the log
            string[] publicArgs = new string[]
            {
                "public1",
                "public2",
                "/d:sonar.projectKey=my.key"
            };

            string[] sensitiveArgs = new string[] {
                // Public args - should appear in the log
                "public1", "public2", "/dmy.key=value",

                // Sensitive args - should not appear in the log
                "/d:sonar.password=secret data password",
                "/d:sonar.login=secret data login",
                "/d:sonar.jdbc.password=secret data db password",
                "/d:sonar.jdbc.username=secret data db user name",

                // Sensitive args - different cases -> exclude to be on the safe side
                "/d:SONAR.jdbc.password=secret data db password upper",
                "/d:sonar.PASSWORD=secret data password upper",

                // Sensitive args - parameter format is slightly incorrect -> exclude to be on the safe side
                "/dsonar.login =secret data key typo",
                "sonar.password=secret data password typo"
            };

            string[] allArgs = sensitiveArgs.Union(publicArgs).ToArray();

            ProcessScannerArguments runnerArgs = new ProcessScannerArguments(exeName, false, logger)
            {
                CmdLineArgs = allArgs
            };
            ProcessRunner runner = new ProcessRunner();

            // Act
            bool success = runner.Execute(runnerArgs);

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

            // Check public arguments are logged but private ones are not
            foreach (string arg in publicArgs)
            {
                logger.AssertSingleDebugMessageExists(arg);
            }

            logger.AssertSingleDebugMessageExists(SonarQube.Common.Resources.MSG_CmdLine_SensitiveCmdLineArgsAlternativeText);
            AssertTextDoesNotAppearInLog("secret", logger);

            // Check that the public and private arguments are passed to the child process
            string exeLogFile = DummyExeHelper.AssertDummyPostProcLogExists(testDir, this.TestContext);

            DummyExeHelper.AssertExpectedLogContents(exeLogFile, allArgs);
        }