private string RunPluginInspector(string jarFilePath, string tempDir)
        {
            Debug.Assert(!string.IsNullOrEmpty(this.inspectorClassFilePath));

            string reportFilePath = Path.Combine(tempDir, "report.xml");

            IEnumerable <string> jarFiles = GetRuntimeDependencies();

            // Construct the class path argument
            StringBuilder sb = new StringBuilder();

            sb.AppendFormat("-cp \"{0}\"", Path.GetDirectoryName(this.inspectorClassFilePath));
            foreach (string dependencyFilePath in jarFiles)
            {
                sb.AppendFormat(";{0}", dependencyFilePath);
            }

            IList <string> cmdLineArgs = new List <string>();

            cmdLineArgs.Add(sb.ToString()); // options must preceed the name of the class to execute
            cmdLineArgs.Add(PluginInspectorFullClassName);
            cmdLineArgs.Add(jarFilePath);   // parameter(s) to pass to the class
            cmdLineArgs.Add(reportFilePath);

            ProcessRunnerArguments runnerArgs = new ProcessRunnerArguments(GetJavaExePath(), logger);

            runnerArgs.CmdLineArgs = cmdLineArgs;

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

            Assert.IsTrue(success, "Test error: failed to execute the PluginInspector");
            Assert.IsTrue(File.Exists(reportFilePath), "Test error: failed to create the PluginInspector report");
            return(reportFilePath);
        }
        public void ProcRunner_ArgumentQuotingForwardedByBatchScript()
        {
            // Checks arguments passed to a batch script which itself passes them on are correctly escaped
            var testDir   = TestUtils.CreateTestSpecificFolderWithSubPaths(TestContext);
            var batchName = TestUtils.WriteBatchFileForTest(TestContext, "\"" + LogArgsPath() + "\" %*");
            var runner    = new ProcessRunner(new TestLogger());
            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"
            };
            var args = new ProcessRunnerArguments(batchName, true)
            {
                CmdLineArgs = expected, WorkingDirectory = testDir
            };
            var success = runner.Execute(args);

            success.Should().BeTrue("Expecting the process to have succeeded");
            runner.ExitCode.Should().Be(0, "Unexpected exit code");
            // Check that the public and private arguments are passed to the child process
            AssertExpectedLogContents(testDir, expected);
        }
Beispiel #3
0
        public void ProcRunner_FailsOnTimeout()
        {
            // Arrange
            string exeName = TestUtils.WriteBatchFileForTest(TestContext,
                                                             @"TIMEOUT 2
@echo Hello world
");

            TestLogger             logger = new TestLogger();
            ProcessRunnerArguments args   = new ProcessRunnerArguments(exeName, logger)
            {
                TimeoutInMilliseconds = 100
            };
            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.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);
        }
Beispiel #4
0
        private void AppendKeyValue(string key, string value)
        {
            Debug.Assert(!ProcessRunnerArguments.ContainsSensitiveData(key) && !ProcessRunnerArguments.ContainsSensitiveData(value),
                         "Not expecting sensitive data to be written to the sonar-project properties file. Key: {0}", key);

            sb.Append(key).Append('=').AppendLine(Escape(value));
        }
        public void ProcRunner_FailsOnTimeout()
        {
            // Arrange
            string exeName = TestUtils.WriteBatchFileForTest(TestContext,
@"TIMEOUT 2
@echo Hello world
");

            TestLogger logger = new TestLogger();
            ProcessRunnerArguments args = new ProcessRunnerArguments(exeName, logger)
            {
                TimeoutInMilliseconds = 100
            };
            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.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);
        }
        public void ProcRunner_PassesEnvVariables()
        {
            // Arrange
            var logger = new TestLogger();
            var runner = new ProcessRunner(logger);

            var 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" }
            };

            var args = new ProcessRunnerArguments(exeName, true)
            {
                EnvironmentVariables = envVariables
            };

            // Act
            var 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");
        }
Beispiel #7
0
        public bool CompileSources(IEnumerable <string> args, ILogger logger)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }
            if (logger == null)
            {
                throw new ArgumentNullException("logger");
            }

            string exePath = TryFindJavaExe(JAVA_COMPILER_EXE);

            Debug.Assert(!string.IsNullOrEmpty(exePath), "Failed to locate the Java compiler exe, although the JDK appears to be installed");

            ProcessRunnerArguments runnerArgs = new ProcessRunnerArguments(exePath, logger)
            {
                CmdLineArgs = args
            };

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

            return(success);
        }
        public /* for test purposes */ static bool ExecuteProcessorRunner(AnalysisConfig config, ILogger logger, string exeFileName, IEnumerable <string> userCmdLineArguments, string propertiesFileName, IProcessRunner runner)
        {
            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);

            logger.LogInfo(Resources.MSG_TFSProcessorCalling);

            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");

            var converterArgs = new ProcessRunnerArguments(exeFileName, !PlatformHelper.IsWindows())
            {
                CmdLineArgs      = userCmdLineArguments,
                WorkingDirectory = config.SonarScannerWorkingDirectory,
            };

            var success = runner.Execute(converterArgs);

            if (success)
            {
                logger.LogInfo(Resources.MSG_TFSProcessorCompleted);
            }
            else
            {
                logger.LogError(Resources.ERR_TFSProcessorExecutionFailed);
            }
            return(success);
        }
        public void ProcRunner_PassesEnvVariables()
        {
            // Arrange
            var logger = new TestLogger();
            var runner = CreateProcessRunner(logger);

            var exeName = 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" }
            };

            var args = new ProcessRunnerArguments(exeName, true)
            {
                EnvironmentVariables = envVariables
            };
            var output = "";

            args.HandleOutputStream = reader => output = reader.ReadToEnd();
            // Act
            runner.Execute(args);

            // Assert
            runner.ExitCode.Should().Be(0, "Unexpected exit code");

            output.Should().Contain("PROCESS_VAR value");
            output.Should().Contain("PROCESS_VAR2 value");
            output.Should().Contain("PROCESS_VAR3 value");
        }
        public void ProcRunner_ExecutionSucceeded()
        {
            // Arrange
            var exeName = WriteBatchFileForTest(TestContext,
                                                @"@echo Hello world
@echo xxx yyy
@echo Testing 1,2,3...>&2
");

            var logger = new TestLogger();
            var args   = new ProcessRunnerArguments(exeName, true);
            var output = "";

            args.HandleOutputStream = reader => output = reader.ReadToEnd();
            var runner = CreateProcessRunner(logger);

            // Act
            runner.Execute(args);

            // Assert
            runner.ExitCode.Should().Be(0, "Unexpected exit code");

            output.Should().Contain("Hello world");
            output.Should().NotContain("Testing 1,2,3...");
        }
        public bool Execute(ProcessRunnerArguments runnerArgs)
        {
            runnerArgs.Should().NotBeNull();
            SuppliedArguments = runnerArgs;

            return(executeResult);
        }
        public void ProcRunner_PassesEnvVariables_OverrideExisting()
        {
            // Tests that existing environment variables will be overwritten successfully

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

            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);

                var 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" }
                };

                var args = new ProcessRunnerArguments(exeName, true)
                {
                    EnvironmentVariables = envVariables
                };

                // Act
                var 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");
        }
Beispiel #13
0
        public static BuildLog BuildTargets(TestContext testContext, string projectFile, bool buildShouldSucceed, params string[] targets)
        {
            // TODO: support 14.0?
            const string msBuildVersion = "15.0";

            // Expecting a path like "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\msbuild.exe"
            var exePath = MSBuildLocator.GetMSBuildPath(msBuildVersion, testContext);

            exePath.Should().NotBeNull($"Test setup failure - failed to locate MSBuild.exe for version {msBuildVersion}");
            File.Exists(exePath).Should().BeTrue($"expecting the returned msbuild.exe file to exist. File path: {exePath}");
            Path.GetFileName(exePath).Should().Be("msbuild.exe");
            Path.GetDirectoryName(exePath).Split(new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar })
            .Should().Contain(msBuildVersion);

            // The build is being run in a separate process so we can't directly
            // capture the property values or which tasks/targets were executed.
            // Instead, we add a custom logger that will record that information
            // in a structured form that we can check later.
            var logPath     = projectFile + ".log";
            var msbuildArgs = new List <string>();
            var loggerType  = typeof(SimpleXmlLogger);

            msbuildArgs.Add($"/logger:{loggerType.FullName},{loggerType.Assembly.Location};{logPath}");
            msbuildArgs.Add(projectFile);

            // Ask MSBuild to create a detailed binary log (not used by the tests,
            // but it simplifies manual investigation of failures)
            var projectDir    = Path.GetDirectoryName(projectFile);
            var binaryLogPath = Path.Combine(projectDir, "buildlog.binlog");

            msbuildArgs.Add("/bl:" + binaryLogPath);
            System.Console.WriteLine("Project Directory: " + projectDir);

            // Specify the targets to be executed, if any
            if (targets?.Length > 0)
            {
                msbuildArgs.Add($"/t:" + string.Join(";", targets.ToArray()));
            }

            // Run the build
            var args = new ProcessRunnerArguments(exePath, false)
            {
                CmdLineArgs = msbuildArgs
            };
            var runner  = new ProcessRunner(new ConsoleLogger(true));
            var success = runner.Execute(args);

            File.Exists(logPath).Should().BeTrue();
            testContext.AddResultFile(logPath);

            success.Should().Be(buildShouldSucceed);

            return(BuildLog.Load(logPath));
        }
        private static int PostProcess(IBootstrapperSettings settings, ILogger logger)
        {
            ProcessRunnerArguments runnerArgs = new ProcessRunnerArguments(settings.PostProcessorFilePath, logger)
            {
                CmdLineArgs      = settings.ChildCmdLineArgs,
                WorkingDirectory = settings.TempDirectory
            };

            ProcessRunner runner = new ProcessRunner();

            runner.Execute(runnerArgs);

            return(runner.ExitCode);
        }
        [WorkItem(126)] // Exclude secrets from log data: http://jira.sonarsource.com/browse/SONARMSBRU-126
        public void ProcRunner_DoNotLogSensitiveData()
        {
            var testDir = TestUtils.CreateTestSpecificFolderWithSubPaths(TestContext);
            var logger  = new TestLogger();
            var runner  = new ProcessRunner(logger);
            // Public args - should appear in the log
            var publicArgs = new string[]
            {
                "public1",
                "public2",
                "/d:sonar.projectKey=my.key"
            };
            var 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"
            };
            var allArgs    = sensitiveArgs.Union(publicArgs).ToArray();
            var runnerArgs = new ProcessRunnerArguments(LogArgsPath(), false)
            {
                CmdLineArgs = allArgs, WorkingDirectory = testDir
            };
            var success = runner.Execute(runnerArgs);

            success.Should().BeTrue("Expecting the process to have succeeded");
            runner.ExitCode.Should().Be(0, "Unexpected exit code");
            // Check public arguments are logged but private ones are not
            foreach (var arg in publicArgs)
            {
                logger.AssertSingleDebugMessageExists(arg);
            }
            logger.AssertSingleDebugMessageExists("<sensitive data removed>");
            AssertTextDoesNotAppearInLog("secret", logger);
            // Check that the public and private arguments are passed to the child process
            AssertExpectedLogContents(testDir, allArgs);
        }
Beispiel #16
0
            public void Execute(ProcessRunnerArguments runnerArgs)
            {
                ExecuteCalled = true;

                runnerArgs.Should().NotBeNull();

                // Expecting a single file name as input
                runnerArgs.CmdLineArgs.Count().Should().Be(1);

                using (var stream = new MemoryStream(responseToReturn))
                    using (var streamReader = new StreamReader(stream))
                    {
                        runnerArgs.HandleOutputStream(streamReader);
                    }
            }
        public void ProcRunner_ExecutionFailed()
        {
            // Arrange
            var exeName = WriteBatchFileForTest(TestContext, "exit -2");

            var logger = new TestLogger();
            var args   = new ProcessRunnerArguments(exeName, true);
            var runner = CreateProcessRunner(logger);

            // Act
            runner.Execute(args);

            // Assert
            runner.ExitCode.Should().Be(-2, "Unexpected exit code");
        }
        public void ProcRunner_MissingExe()
        {
            // Tests attempting to launch a non-existent exe

            // Arrange
            var logger = new TestLogger();
            var args   = new ProcessRunnerArguments("missingExe.foo", false);
            var runner = CreateProcessRunner(logger);

            // Act
            runner.Execute(args);

            // Assert
            runner.ExitCode.Should().Be(ProcessRunner.ErrorCode, "Unexpected exit code");
            logger.AssertSingleErrorExists("missingExe.foo");
        }
        public void ProcRunner_ExecutionFailed()
        {
            // Arrange
            var exeName = TestUtils.WriteBatchFileForTest(TestContext, "exit -2");

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

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

            // Assert
            Assert.IsFalse(success, "Expecting the process to have failed");
            Assert.AreEqual(-2, runner.ExitCode, "Unexpected exit code");
        }
        public void ProcRunner_ExecutionFailed()
        {
            // Arrange
            string exeName = TestUtils.WriteBatchFileForTest(TestContext, "exit -2");

            TestLogger logger = new TestLogger();
            ProcessRunnerArguments args = new ProcessRunnerArguments(exeName, 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");
        }
        public void ProcRunner_ArgumentQuotingForwardedByBatchScript()
        {
            // Checks arguments passed to a batch script which itself passes them on are correctly escaped

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

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

            var logger = new TestLogger();
            var args   = new ProcessRunnerArguments(batchName, true);

            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;

            var runner = new ProcessRunner(logger);

            // Act
            var 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
            var exeLogFile = DummyExeHelper.AssertDummyPostProcLogExists(testDir, TestContext);

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

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

            // Act
            var 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 ProcRunner_ArgumentQuoting()
        {
            // Checks arguments passed to the child process are correctly quoted

            // 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();
            ProcessRunnerArguments args   = new ProcessRunnerArguments(exeName, logger);

            args.CmdLineArgs = new string[] {
                "unquoted",
                "\"quoted\"",
                "\"quoted with spaces\"",
                "/test:\"quoted arg\"",
                "unquoted with spaces",
                "quote in \"the middle",
                "quotes \"& ampersands",
                "\"multiple \"\"\"      quotes \" "
            };

            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,
                                                     "unquoted",
                                                     "\"quoted\"",
                                                     "\"quoted with spaces\"",
                                                     "/test:\"quoted arg\"",
                                                     "unquoted with spaces",
                                                     "quote in \"the middle",
                                                     "quotes \"& ampersands",
                                                     "\"multiple \"\"\"      quotes \" ");
        }
        public void V0_9Upgrade_CalledFromV0_9()
        {
            // Arrange
            TestLogger             logger     = new TestLogger();
            ProcessRunnerArguments runnerArgs = new ProcessRunnerArguments(typeof(V0_9UpgradeMessageExe.Program).Assembly.Location, logger)
            {
                WorkingDirectory = this.TestContext.DeploymentDirectory
            };

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

            // Assert
            Assert.IsFalse(success);
            logger.AssertSingleErrorExists(SonarQube.V0_9UpgradeMessageExe.Resources.UpgradeMessage);
            logger.AssertErrorsLogged(1);
        }
Beispiel #25
0
            public bool Execute(ProcessRunnerArguments runnerArgs)
            {
                ExecuteCalled = true;

                runnerArgs.Should().NotBeNull();

                // Expecting a single file name as input
                runnerArgs.CmdLineArgs.Count().Should().Be(1);
                ExchangeFileName = runnerArgs.CmdLineArgs.First();
                File.Exists(ExchangeFileName).Should().BeTrue();

                // Replace the file with the response
                File.Delete(ExchangeFileName);

                WriteResponse(ExchangeFileName, responseToReturn);

                return(successCodeToReturn);
            }
        public void ProcRunner_ArgumentQuoting()
        {
            // Checks arguments passed to the child process are correctly quoted

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

            var logger = new TestLogger();
            var args   = new ProcessRunnerArguments(exeName, false);

            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;

            var runner = CreateProcessRunner(logger);

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

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

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

            DummyExeHelper.AssertExpectedLogContents(exeLogFile, expected);
        }
Beispiel #27
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();
            ProcessRunnerArguments args   = new ProcessRunnerArguments(exeName, 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

            // 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);
        }
        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;

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

            runner.Execute(runnerArgs);

            return(runner.ExitCode);
        }
        public void Execute_CancellationTokenCancelledMidway_ProcessKilled()
        {
            var testFolder     = CreateTestSpecificFolder(TestContext);
            var signalFileName = $"{testFolder}\\signal-{Guid.NewGuid():N}.txt";

            var exeName = WriteBatchFileForTest(TestContext,
                                                $@"
echo test > ""{signalFileName}"" 
waitfor /t 10 {Guid.NewGuid():N}
@echo Done!
");

            using var processCancellationTokenSource = new CancellationTokenSource();
            var logger = new TestLogger(true, true);
            var args   = new ProcessRunnerArguments(exeName, true)
            {
                TimeoutInMilliseconds = 12000,
                CancellationToken     = processCancellationTokenSource.Token
            };

            var runner = CreateProcessRunner(logger);

            bool?result      = null;
            var  processTask = Task.Run(() => { result = runner.Execute(args); });

            var taskCancellationTokenSource = new CancellationTokenSource();
            var cancellationTask            = Task.Run(() =>
            {
                while (!taskCancellationTokenSource.IsCancellationRequested && !File.Exists(signalFileName))
                {
                    Thread.Sleep(millisecondsTimeout: 10);
                }
                processCancellationTokenSource.Cancel();
            }, taskCancellationTokenSource.Token);

            Task.WaitAll(new[] { processTask, cancellationTask }, TimeSpan.FromSeconds(15));
            taskCancellationTokenSource.Cancel();

            result.Should().BeFalse("Expecting the process to have failed");
            runner.ExitCode.Should().Be(-1, "Unexpected exit code");
            processCancellationTokenSource.IsCancellationRequested.Should().BeTrue();
            logger.AssertPartialOutputStringDoesNotExist("Done!");
        }
Beispiel #30
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");

            var args = new List <string>
            {
                "analyze",
                string.Format(CultureInfo.InvariantCulture, @"/output:{0}", outputXmlFilePath),
                inputBinaryFilePath
            };

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

            var runner  = new ProcessRunner();
            var 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);
        }
        private static int PostProcess(IBootstrapperSettings settings, ILogger logger)
        {
            if (!File.Exists(settings.PostProcessorFilePath))
            {
                logger.LogError(Resources.ERROR_PostProcessExeNotFound, settings.PostProcessorFilePath);
                return(ErrorCode);
            }

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

            ProcessRunner runner = new ProcessRunner();

            runner.Execute(runnerArgs);

            return(runner.ExitCode);
        }
        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");

            ProcessRunnerArguments scannerArgs = new ProcessRunnerArguments(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);
        }
        public void ProcRunner_ExecutionSucceeded()
        {
            // Arrange
            string exeName = TestUtils.WriteBatchFileForTest(TestContext,
@"@echo Hello world
xxx yyy
@echo Testing 1,2,3...
");

            TestLogger logger = new TestLogger();
            ProcessRunnerArguments args = new ProcessRunnerArguments(exeName, 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
        }
        public void ProcRunner_ArgumentQuoting()
        {
            // Checks arguments passed to the child process are correctly quoted

            // 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();
            ProcessRunnerArguments args = new ProcessRunnerArguments(exeName, logger);
            args.CmdLineArgs = new string[] {
                "unquoted",
                "\"quoted\"",
                "\"quoted with spaces\"",
                "/test:\"quoted arg\"",
                "unquoted with spaces" };

            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,
                "unquoted",
                "quoted",
                "quoted with spaces",
                "/test:quoted arg",
                "unquoted with spaces");
        }
        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" } };

            ProcessRunnerArguments args = new ProcessRunnerArguments(exeName, 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");
        }
        public void ProcRunner_MissingExe()
        {
            // Tests attempting to launch a non-existent exe

            // Arrange
            TestLogger logger = new TestLogger();
            ProcessRunnerArguments args = new ProcessRunnerArguments("missingExe.foo", 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 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" } };

                ProcessRunnerArguments args = new ProcessRunnerArguments(exeName, 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");
        }
        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();

            ProcessRunnerArguments runnerArgs = new ProcessRunnerArguments(exeName, 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);
        }