public void ProcRunner_ArgumentQuotingForwardedByBatchScript()
        {
            // Checks arguments passed to a batch script which itself passes them on are correctly escaped

            // 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 batchName = 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 = 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);
        }
        [WorkItem(126)] // Exclude secrets from log data: http://jira.sonarsource.com/browse/SONARMSBRU-126
        public void ProcRunner_DoNotLogSensitiveData()
        {
            // 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();

            // 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(exeName, false)
            {
                CmdLineArgs = allArgs,

                // Specify the arguments we consider to be sensitive.
                // Note: this is a change from the S4MSB which has a hard-coded set of sensitive keys.
                SensitivePropertyKeys = new string[]
                {
                    "sonar.password", "sonar.login", "sonar.jdbc.password", "sonar.jdbc.username"
                }
            };

            var runner = CreateProcessRunner(logger);

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

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

            DummyExeHelper.AssertExpectedLogContents(exeLogFile, allArgs);
        }