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