File: CommandLineSwitches_Tests.cs
Web Access
Project: ..\..\..\src\MSBuild.UnitTests\Microsoft.Build.CommandLine.UnitTests.csproj (Microsoft.Build.CommandLine.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Resources;
using Microsoft.Build.CommandLine;
using Microsoft.Build.Construction;
using Microsoft.Build.Execution;
using Microsoft.Build.Framework;
using Microsoft.Build.Graph;
using Microsoft.Build.Logging;
using Microsoft.Build.Shared;
using Shouldly;
using Xunit;
using Xunit.NetCore.Extensions;
 
#nullable disable
 
namespace Microsoft.Build.UnitTests
{
    public class CommandLineSwitchesTests
    {
        public CommandLineSwitchesTests()
        {
            // Make sure resources are initialized
            MSBuildApp.Initialize();
        }
 
        [Fact]
        public void BogusSwitchIdentificationTests()
        {
            CommandLineSwitches.ParameterlessSwitch parameterlessSwitch;
            string duplicateSwitchErrorMessage;
 
            CommandLineSwitches.IsParameterlessSwitch("bogus", out parameterlessSwitch, out duplicateSwitchErrorMessage).ShouldBeFalse();
            parameterlessSwitch.ShouldBe(CommandLineSwitches.ParameterlessSwitch.Invalid);
            duplicateSwitchErrorMessage.ShouldBeNull();
 
            CommandLineSwitches.ParameterizedSwitch parameterizedSwitch;
            bool multipleParametersAllowed;
            string missingParametersErrorMessage;
            bool unquoteParameters;
            bool emptyParametersAllowed;
 
            CommandLineSwitches.IsParameterizedSwitch("bogus", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed).ShouldBeFalse();
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.Invalid);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeFalse();
            missingParametersErrorMessage.ShouldBeNull();
            unquoteParameters.ShouldBeFalse();
        }
 
        [Theory]
        [InlineData("help")]
        [InlineData("HELP")]
        [InlineData("Help")]
        [InlineData("h")]
        [InlineData("H")]
        [InlineData("?")]
        public void HelpSwitchIdentificationTests(string help)
        {
            CommandLineSwitches.IsParameterlessSwitch(help, out CommandLineSwitches.ParameterlessSwitch parameterlessSwitch, out string duplicateSwitchErrorMessage).ShouldBeTrue();
            parameterlessSwitch.ShouldBe(CommandLineSwitches.ParameterlessSwitch.Help);
            duplicateSwitchErrorMessage.ShouldBeNull();
        }
 
        [Theory]
        [InlineData("version")]
        [InlineData("Version")]
        [InlineData("VERSION")]
        [InlineData("ver")]
        [InlineData("VER")]
        [InlineData("Ver")]
        public void VersionSwitchIdentificationTests(string version)
        {
            CommandLineSwitches.IsParameterlessSwitch(version, out CommandLineSwitches.ParameterlessSwitch parameterlessSwitch, out string duplicateSwitchErrorMessage).ShouldBeTrue();
            parameterlessSwitch.ShouldBe(CommandLineSwitches.ParameterlessSwitch.Version);
            duplicateSwitchErrorMessage.ShouldBeNull();
        }
 
        [Theory]
        [InlineData("nologo")]
        [InlineData("NOLOGO")]
        [InlineData("NoLogo")]
        public void NoLogoSwitchIdentificationTests(string nologo)
        {
            CommandLineSwitches.IsParameterlessSwitch(nologo, out CommandLineSwitches.ParameterlessSwitch parameterlessSwitch, out string duplicateSwitchErrorMessage).ShouldBeTrue();
            parameterlessSwitch.ShouldBe(CommandLineSwitches.ParameterlessSwitch.NoLogo);
            duplicateSwitchErrorMessage.ShouldBeNull();
        }
 
        [Theory]
        [InlineData("noautoresponse")]
        [InlineData("NOAUTORESPONSE")]
        [InlineData("NoAutoResponse")]
        [InlineData("noautorsp")]
        [InlineData("NOAUTORSP")]
        [InlineData("NoAutoRsp")]
        public void NoAutoResponseSwitchIdentificationTests(string noautoresponse)
        {
            CommandLineSwitches.IsParameterlessSwitch(noautoresponse, out CommandLineSwitches.ParameterlessSwitch parameterlessSwitch, out string duplicateSwitchErrorMessage).ShouldBeTrue();
            parameterlessSwitch.ShouldBe(CommandLineSwitches.ParameterlessSwitch.NoAutoResponse);
            duplicateSwitchErrorMessage.ShouldBeNull();
        }
 
        [Theory]
        [InlineData("noconsolelogger")]
        [InlineData("NOCONSOLELOGGER")]
        [InlineData("NoConsoleLogger")]
        [InlineData("noconlog")]
        [InlineData("NOCONLOG")]
        [InlineData("NoConLog")]
        public void NoConsoleLoggerSwitchIdentificationTests(string noconsolelogger)
        {
            CommandLineSwitches.ParameterlessSwitch parameterlessSwitch;
            string duplicateSwitchErrorMessage;
 
            CommandLineSwitches.IsParameterlessSwitch(noconsolelogger, out parameterlessSwitch, out duplicateSwitchErrorMessage).ShouldBeTrue();
            parameterlessSwitch.ShouldBe(CommandLineSwitches.ParameterlessSwitch.NoConsoleLogger);
            duplicateSwitchErrorMessage.ShouldBeNull();
        }
 
        [Theory]
        [InlineData("fileLogger")]
        [InlineData("FILELOGGER")]
        [InlineData("FileLogger")]
        [InlineData("fl")]
        [InlineData("FL")]
        public void FileLoggerSwitchIdentificationTests(string filelogger)
        {
            CommandLineSwitches.ParameterlessSwitch parameterlessSwitch;
            string duplicateSwitchErrorMessage;
 
            CommandLineSwitches.IsParameterlessSwitch(filelogger, out parameterlessSwitch, out duplicateSwitchErrorMessage).ShouldBeTrue();
            parameterlessSwitch.ShouldBe(CommandLineSwitches.ParameterlessSwitch.FileLogger);
            duplicateSwitchErrorMessage.ShouldBeNull();
        }
 
        [Theory]
        [InlineData("distributedfilelogger")]
        [InlineData("DISTRIBUTEDFILELOGGER")]
        [InlineData("DistributedFileLogger")]
        [InlineData("dfl")]
        [InlineData("DFL")]
        public void DistributedFileLoggerSwitchIdentificationTests(string distributedfilelogger)
        {
            CommandLineSwitches.ParameterlessSwitch parameterlessSwitch;
            string duplicateSwitchErrorMessage;
 
            CommandLineSwitches.IsParameterlessSwitch(distributedfilelogger, out parameterlessSwitch, out duplicateSwitchErrorMessage).ShouldBeTrue();
            parameterlessSwitch.ShouldBe(CommandLineSwitches.ParameterlessSwitch.DistributedFileLogger);
            duplicateSwitchErrorMessage.ShouldBeNull();
        }
 
        [Theory]
        [InlineData("ll")]
        [InlineData("LL")]
        [InlineData("livelogger")]
        [InlineData("LiveLogger")]
        [InlineData("LIVELOGGER")]
        [InlineData("tl")]
        [InlineData("TL")]
        [InlineData("terminallogger")]
        [InlineData("TerminalLogger")]
        [InlineData("TERMINALLOGGER")]
        public void TerminalLoggerSwitchIdentificationTests(string terminallogger)
        {
            CommandLineSwitches.ParameterizedSwitch parameterlessSwitch;
            string duplicateSwitchErrorMessage;
 
            CommandLineSwitches.IsParameterizedSwitch(terminallogger, out parameterlessSwitch, out duplicateSwitchErrorMessage, out bool multipleParametersAllowed, out string missingParametersErrorMessage, out bool unquoteParameters, out bool emptyParametersAllowed).ShouldBeTrue();
            parameterlessSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.TerminalLogger);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeTrue();
            missingParametersErrorMessage.ShouldBeNull();
            unquoteParameters.ShouldBeTrue();
            emptyParametersAllowed.ShouldBeTrue();
        }
 
        [Theory]
        [InlineData("flp")]
        [InlineData("FLP")]
        [InlineData("fileLoggerParameters")]
        [InlineData("FILELOGGERPARAMETERS")]
        public void FileLoggerParametersIdentificationTests(string fileloggerparameters)
        {
            CommandLineSwitches.ParameterizedSwitch parameterizedSwitch;
            string duplicateSwitchErrorMessage;
            bool multipleParametersAllowed;
            string missingParametersErrorMessage;
            bool unquoteParameters;
            bool emptyParametersAllowed;
 
            CommandLineSwitches.IsParameterizedSwitch(fileloggerparameters, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed).ShouldBeTrue();
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.FileLoggerParameters);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeFalse();
            missingParametersErrorMessage.ShouldNotBeNull();
            unquoteParameters.ShouldBeTrue();
        }
 
        [Theory]
        [InlineData("tlp")]
        [InlineData("TLP")]
        [InlineData("terminalLoggerParameters")]
        [InlineData("TERMINALLOGGERPARAMETERS")]
        public void TerminalLoggerParametersIdentificationTests(string terminalLoggerParameters)
        {
            CommandLineSwitches.ParameterizedSwitch parameterizedSwitch;
            string duplicateSwitchErrorMessage;
            bool multipleParametersAllowed;
            string missingParametersErrorMessage;
            bool unquoteParameters;
            bool emptyParametersAllowed;
 
            CommandLineSwitches.IsParameterizedSwitch(terminalLoggerParameters, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed).ShouldBeTrue();
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.TerminalLoggerParameters);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeFalse();
            missingParametersErrorMessage.ShouldNotBeNull();
            unquoteParameters.ShouldBeTrue();
        }
 
#if FEATURE_NODE_REUSE
        [Theory]
        [InlineData("nr")]
        [InlineData("NR")]
        [InlineData("nodereuse")]
        [InlineData("NodeReuse")]
        public void NodeReuseParametersIdentificationTests(string nodereuse)
        {
            CommandLineSwitches.ParameterizedSwitch parameterizedSwitch;
            string duplicateSwitchErrorMessage;
            bool multipleParametersAllowed;
            string missingParametersErrorMessage;
            bool unquoteParameters;
            bool emptyParametersAllowed;
 
            CommandLineSwitches.IsParameterizedSwitch(nodereuse, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed).ShouldBeTrue();
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.NodeReuse);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeFalse();
            missingParametersErrorMessage.ShouldNotBeNull();
            unquoteParameters.ShouldBeTrue();
        }
#endif
 
        [Fact]
        public void ProjectSwitchIdentificationTests()
        {
            CommandLineSwitches.ParameterizedSwitch parameterizedSwitch;
            string duplicateSwitchErrorMessage;
            bool multipleParametersAllowed;
            string missingParametersErrorMessage;
            bool unquoteParameters;
            bool emptyParametersAllowed;
 
            Assert.True(CommandLineSwitches.IsParameterizedSwitch(null, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
            Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Project, parameterizedSwitch);
            Assert.NotNull(duplicateSwitchErrorMessage);
            Assert.False(multipleParametersAllowed);
            Assert.Null(missingParametersErrorMessage);
            Assert.True(unquoteParameters);
 
            // for the virtual project switch, we match on null, not empty string
            Assert.False(CommandLineSwitches.IsParameterizedSwitch(String.Empty, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
            Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Invalid, parameterizedSwitch);
            Assert.Null(duplicateSwitchErrorMessage);
            Assert.False(multipleParametersAllowed);
            Assert.Null(missingParametersErrorMessage);
            Assert.False(unquoteParameters);
        }
 
        [Theory]
        [InlineData("ignoreprojectextensions")]
        [InlineData("IgnoreProjectExtensions")]
        [InlineData("IGNOREPROJECTEXTENSIONS")]
        [InlineData("ignore")]
        [InlineData("IGNORE")]
        public void IgnoreProjectExtensionsSwitchIdentificationTests(string ignoreprojectextensions)
        {
            CommandLineSwitches.ParameterizedSwitch parameterizedSwitch;
            string duplicateSwitchErrorMessage;
            bool multipleParametersAllowed;
            string missingParametersErrorMessage;
            bool unquoteParameters;
            bool emptyParametersAllowed;
 
            CommandLineSwitches.IsParameterizedSwitch(ignoreprojectextensions, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed).ShouldBeTrue();
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.IgnoreProjectExtensions);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeTrue();
            missingParametersErrorMessage.ShouldNotBeNull();
            unquoteParameters.ShouldBeTrue();
        }
 
        [Theory]
        [InlineData("target")]
        [InlineData("TARGET")]
        [InlineData("Target")]
        [InlineData("t")]
        [InlineData("T")]
        public void TargetSwitchIdentificationTests(string target)
        {
            CommandLineSwitches.ParameterizedSwitch parameterizedSwitch;
            string duplicateSwitchErrorMessage;
            bool multipleParametersAllowed;
            string missingParametersErrorMessage;
            bool unquoteParameters;
            bool emptyParametersAllowed;
 
            CommandLineSwitches.IsParameterizedSwitch(target, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed).ShouldBeTrue();
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.Target);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeTrue();
            missingParametersErrorMessage.ShouldNotBeNull();
            unquoteParameters.ShouldBeTrue();
        }
 
        [Theory]
        [InlineData("property")]
        [InlineData("PROPERTY")]
        [InlineData("Property")]
        [InlineData("p")]
        [InlineData("P")]
        public void PropertySwitchIdentificationTests(string property)
        {
            CommandLineSwitches.ParameterizedSwitch parameterizedSwitch;
            string duplicateSwitchErrorMessage;
            bool multipleParametersAllowed;
            string missingParametersErrorMessage;
            bool unquoteParameters;
            bool emptyParametersAllowed;
 
            CommandLineSwitches.IsParameterizedSwitch(property, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed).ShouldBeTrue();
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.Property);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeTrue();
            missingParametersErrorMessage.ShouldNotBeNull();
            unquoteParameters.ShouldBeTrue();
        }
 
        [Theory]
        [InlineData("restoreproperty")]
        [InlineData("RESTOREPROPERTY")]
        [InlineData("RestoreProperty")]
        [InlineData("rp")]
        [InlineData("RP")]
        public void RestorePropertySwitchIdentificationTests(string property)
        {
            CommandLineSwitches.IsParameterizedSwitch(property, out CommandLineSwitches.ParameterizedSwitch parameterizedSwitch, out string duplicateSwitchErrorMessage, out bool multipleParametersAllowed, out string missingParametersErrorMessage, out bool unquoteParameters, out bool emptyParametersAllowed).ShouldBeTrue();
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.RestoreProperty);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeTrue();
            missingParametersErrorMessage.ShouldBe("MissingPropertyError");
            unquoteParameters.ShouldBeTrue();
        }
 
        [Theory]
        [InlineData("logger")]
        [InlineData("LOGGER")]
        [InlineData("Logger")]
        [InlineData("l")]
        [InlineData("L")]
        public void LoggerSwitchIdentificationTests(string logger)
        {
            CommandLineSwitches.ParameterizedSwitch parameterizedSwitch;
            string duplicateSwitchErrorMessage;
            bool multipleParametersAllowed;
            string missingParametersErrorMessage;
            bool unquoteParameters;
            bool emptyParametersAllowed;
 
            CommandLineSwitches.IsParameterizedSwitch(logger, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed).ShouldBeTrue();
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.Logger);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeFalse();
            missingParametersErrorMessage.ShouldNotBeNull();
            unquoteParameters.ShouldBeFalse();
        }
 
        [Theory]
        [InlineData("verbosity")]
        [InlineData("VERBOSITY")]
        [InlineData("Verbosity")]
        [InlineData("v")]
        [InlineData("V")]
        public void VerbositySwitchIdentificationTests(string verbosity)
        {
            CommandLineSwitches.ParameterizedSwitch parameterizedSwitch;
            string duplicateSwitchErrorMessage;
            bool multipleParametersAllowed;
            string missingParametersErrorMessage;
            bool unquoteParameters;
            bool emptyParametersAllowed;
 
            CommandLineSwitches.IsParameterizedSwitch(verbosity, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed).ShouldBeTrue();
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.Verbosity);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeFalse();
            missingParametersErrorMessage.ShouldNotBeNull();
            unquoteParameters.ShouldBeTrue();
        }
 
        [Theory]
        [InlineData("ds")]
        [InlineData("DS")]
        [InlineData("Ds")]
        [InlineData("detailedsummary")]
        [InlineData("DETAILEDSUMMARY")]
        [InlineData("DetailedSummary")]
        public void DetailedSummarySwitchIdentificationTests(string detailedsummary)
        {
            CommandLineSwitches.IsParameterizedSwitch(
                detailedsummary,
                out var parameterizedSwitch,
                out var duplicateSwitchErrorMessage,
                out var multipleParametersAllowed,
                out var missingParametersErrorMessage,
                out var unquoteParameters,
                out var emptyParametersAllowed).ShouldBeTrue();
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.DetailedSummary);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBe(false);
            missingParametersErrorMessage.ShouldBeNull();
            unquoteParameters.ShouldBe(true);
            emptyParametersAllowed.ShouldBe(false);
        }
 
        [Theory]
        [InlineData("m")]
        [InlineData("M")]
        [InlineData("maxcpucount")]
        [InlineData("MAXCPUCOUNT")]
        public void MaxCPUCountSwitchIdentificationTests(string maxcpucount)
        {
            CommandLineSwitches.ParameterizedSwitch parameterizedSwitch;
            string duplicateSwitchErrorMessage;
            bool multipleParametersAllowed;
            string missingParametersErrorMessage;
            bool unquoteParameters;
            bool emptyParametersAllowed;
 
            CommandLineSwitches.IsParameterizedSwitch(maxcpucount, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed).ShouldBeTrue();
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.MaxCPUCount);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeFalse();
            missingParametersErrorMessage.ShouldNotBeNull();
            unquoteParameters.ShouldBeTrue();
        }
 
#if FEATURE_XML_SCHEMA_VALIDATION
        [Theory]
        [InlineData("validate")]
        [InlineData("VALIDATE")]
        [InlineData("Validate")]
        [InlineData("val")]
        [InlineData("VAL")]
        [InlineData("Val")]
        public void ValidateSwitchIdentificationTests(string validate)
        {
            CommandLineSwitches.ParameterizedSwitch parameterizedSwitch;
            string duplicateSwitchErrorMessage;
            bool multipleParametersAllowed;
            string missingParametersErrorMessage;
            bool unquoteParameters;
            bool emptyParametersAllowed;
 
            CommandLineSwitches.IsParameterizedSwitch(validate, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed).ShouldBeTrue();
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.Validate);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeFalse();
            missingParametersErrorMessage.ShouldBeNull();
            unquoteParameters.ShouldBeTrue();
        }
#endif
 
        [Theory]
        [InlineData("preprocess")]
        [InlineData("pp")]
        public void PreprocessSwitchIdentificationTests(string preprocess)
        {
            CommandLineSwitches.ParameterizedSwitch parameterizedSwitch;
            string duplicateSwitchErrorMessage;
            bool multipleParametersAllowed;
            string missingParametersErrorMessage;
            bool unquoteParameters;
            bool emptyParametersAllowed;
 
            CommandLineSwitches.IsParameterizedSwitch(preprocess, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed).ShouldBeTrue();
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.Preprocess);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeFalse();
            missingParametersErrorMessage.ShouldBeNull();
            unquoteParameters.ShouldBeTrue();
        }
 
        [Fact]
        public void GetPropertySwitchIdentificationTest()
        {
            CommandLineSwitches.IsParameterizedSwitch(
                "getProperty",
                out CommandLineSwitches.ParameterizedSwitch parameterizedSwitch,
                out string duplicateSwitchErrorMessage,
                out bool multipleParametersAllowed,
                out string missingParametersErrorMessage,
                out _,
                out _);
 
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.GetProperty);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeTrue();
            missingParametersErrorMessage.ShouldNotBeNullOrEmpty();
        }
 
        [Fact]
        public void GetItemSwitchIdentificationTest()
        {
            CommandLineSwitches.IsParameterizedSwitch(
                "getItem",
                out CommandLineSwitches.ParameterizedSwitch parameterizedSwitch,
                out string duplicateSwitchErrorMessage,
                out bool multipleParametersAllowed,
                out string missingParametersErrorMessage,
                out _,
                out _);
 
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.GetItem);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeTrue();
            missingParametersErrorMessage.ShouldNotBeNullOrEmpty();
        }
 
        [Fact]
        public void GetTargetResultSwitchIdentificationTest()
        {
            CommandLineSwitches.IsParameterizedSwitch(
                "getTargetResult",
                out CommandLineSwitches.ParameterizedSwitch parameterizedSwitch,
                out string duplicateSwitchErrorMessage,
                out bool multipleParametersAllowed,
                out string missingParametersErrorMessage,
                out _,
                out _);
 
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.GetTargetResult);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeTrue();
            missingParametersErrorMessage.ShouldNotBeNullOrEmpty();
        }
 
        [Theory]
        [InlineData("targets")]
        [InlineData("tArGeTs")]
        [InlineData("ts")]
        public void TargetsSwitchIdentificationTests(string @switch)
        {
            CommandLineSwitches.IsParameterizedSwitch(
                @switch,
                out var parameterizedSwitch,
                out var duplicateSwitchErrorMessage,
                out var multipleParametersAllowed,
                out var missingParametersErrorMessage,
                out var unquoteParameters,
                out var emptyParametersAllowed).ShouldBeTrue();
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.Targets);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeFalse();
            missingParametersErrorMessage.ShouldBeNull();
            unquoteParameters.ShouldBeTrue();
            emptyParametersAllowed.ShouldBeFalse();
        }
 
        [Theory]
        [InlineData("featureavailability")]
        [InlineData("fa")]
        public void FeatureAvailibilitySwitchIdentificationTest(string switchName)
        {
            CommandLineSwitches.IsParameterizedSwitch(
                switchName,
                out CommandLineSwitches.ParameterizedSwitch parameterizedSwitch,
                out string duplicateSwitchErrorMessage,
                out bool multipleParametersAllowed,
                out string missingParametersErrorMessage,
                out _,
                out _);
 
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.FeatureAvailability);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeTrue();
            missingParametersErrorMessage.ShouldNotBeNullOrEmpty();
        }
 
        [Fact]
        public void TargetsSwitchParameter()
        {
            CommandLineSwitches switches = new CommandLineSwitches();
            MSBuildApp.GatherCommandLineSwitches(new List<string>() { "/targets:targets.txt" }, switches);
 
            switches.HaveErrors().ShouldBeFalse();
            switches[CommandLineSwitches.ParameterizedSwitch.Targets].ShouldBe(new[] { "targets.txt" });
        }
 
        [Fact]
        public void TargetsSwitchDoesNotSupportMultipleOccurrences()
        {
            CommandLineSwitches switches = new CommandLineSwitches();
            MSBuildApp.GatherCommandLineSwitches(new List<string>() { "/targets /targets" }, switches);
 
            switches.HaveErrors().ShouldBeTrue();
        }
 
        [Theory]
        [InlineData("isolate")]
        [InlineData("ISOLATE")]
        [InlineData("isolateprojects")]
        [InlineData("isolateProjects")]
        public void IsolateProjectsSwitchIdentificationTests(string isolateprojects)
        {
            CommandLineSwitches.ParameterizedSwitch parameterizedSwitch;
            string duplicateSwitchErrorMessage;
            bool multipleParametersAllowed;
            string missingParametersErrorMessage;
            bool unquoteParameters;
            bool emptyParametersAllowed;
 
            CommandLineSwitches.IsParameterizedSwitch(isolateprojects, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed).ShouldBeTrue();
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.IsolateProjects);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeFalse();
            missingParametersErrorMessage.ShouldBeNull();
            unquoteParameters.ShouldBeTrue();
            emptyParametersAllowed.ShouldBeFalse();
        }
 
        [Theory]
        [InlineData("graph")]
        [InlineData("GRAPH")]
        [InlineData("graphbuild")]
        [InlineData("graphBuild")]
        public void GraphBuildSwitchIdentificationTests(string graph)
        {
            CommandLineSwitches.ParameterizedSwitch parameterizedSwitch;
            string duplicateSwitchErrorMessage;
            bool multipleParametersAllowed;
            string missingParametersErrorMessage;
            bool unquoteParameters;
            bool emptyParametersAllowed;
 
            CommandLineSwitches.IsParameterizedSwitch(graph, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed).ShouldBeTrue();
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.GraphBuild);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeTrue();
            missingParametersErrorMessage.ShouldBeNull();
            unquoteParameters.ShouldBeTrue();
            emptyParametersAllowed.ShouldBeFalse();
        }
 
        [Theory]
        [InlineData("low")]
        [InlineData("LOW")]
        [InlineData("lowpriority")]
        [InlineData("lowPriority")]
        public void LowPrioritySwitchIdentificationTests(string lowpriority)
        {
            CommandLineSwitches.IsParameterizedSwitch(lowpriority,
                out CommandLineSwitches.ParameterizedSwitch parameterizedSwitch,
                out string duplicateSwitchErrorMessage,
                out bool multipleParametersAllowed,
                out string missingParametersErrorMessage,
                out bool unquoteParameters,
                out bool emptyParametersAllowed).ShouldBeTrue();
            parameterizedSwitch.ShouldBe(CommandLineSwitches.ParameterizedSwitch.LowPriority);
            duplicateSwitchErrorMessage.ShouldBeNull();
            multipleParametersAllowed.ShouldBeFalse();
            missingParametersErrorMessage.ShouldBeNull();
            unquoteParameters.ShouldBeTrue();
            emptyParametersAllowed.ShouldBeFalse();
        }
 
        [Fact]
        public void GraphBuildSwitchCanHaveParameters()
        {
            CommandLineSwitches switches = new CommandLineSwitches();
 
            MSBuildApp.GatherCommandLineSwitches(new List<string> { "/graph", "/graph:true;  NoBuild  ;;  ;", "/graph:foo" }, switches);
 
            switches[CommandLineSwitches.ParameterizedSwitch.GraphBuild].ShouldBe(new[] { "true", "  NoBuild  ", "  ", "foo" });
 
            switches.HaveErrors().ShouldBeFalse();
        }
 
        [Fact]
        public void GraphBuildSwitchCanBeParameterless()
        {
            CommandLineSwitches switches = new CommandLineSwitches();
 
            MSBuildApp.GatherCommandLineSwitches(new List<string> { "/graph" }, switches);
 
            switches[CommandLineSwitches.ParameterizedSwitch.GraphBuild].ShouldBe(Array.Empty<string>());
 
            switches.HaveErrors().ShouldBeFalse();
        }
 
        [Fact]
        public void InputResultsCachesSupportsMultipleOccurrence()
        {
            CommandLineSwitches switches = new CommandLineSwitches();
 
            MSBuildApp.GatherCommandLineSwitches(new List<string>() { "/irc", "/irc:a;b", "/irc:c;d" }, switches);
 
            switches[CommandLineSwitches.ParameterizedSwitch.InputResultsCaches].ShouldBe(new[] { null, "a", "b", "c", "d" });
 
            switches.HaveErrors().ShouldBeFalse();
        }
 
        [Fact]
        public void OutputResultsCache()
        {
            CommandLineSwitches switches = new CommandLineSwitches();
 
            MSBuildApp.GatherCommandLineSwitches(new List<string>() { "/orc:a" }, switches);
 
            switches[CommandLineSwitches.ParameterizedSwitch.OutputResultsCache].ShouldBe(new[] { "a" });
 
            switches.HaveErrors().ShouldBeFalse();
        }
 
        [Fact]
        public void OutputResultsCachesDoesNotSupportMultipleOccurrences()
        {
            CommandLineSwitches switches = new CommandLineSwitches();
 
            MSBuildApp.GatherCommandLineSwitches(new List<string>() { "/orc:a", "/orc:b" }, switches);
 
            switches.HaveErrors().ShouldBeTrue();
        }
 
        [Fact]
        public void SetParameterlessSwitchTests()
        {
            CommandLineSwitches switches = new CommandLineSwitches();
 
            switches.SetParameterlessSwitch(CommandLineSwitches.ParameterlessSwitch.NoLogo, "/nologo");
 
            Assert.Equal("/nologo", switches.GetParameterlessSwitchCommandLineArg(CommandLineSwitches.ParameterlessSwitch.NoLogo));
            Assert.True(switches.IsParameterlessSwitchSet(CommandLineSwitches.ParameterlessSwitch.NoLogo));
            Assert.True(switches[CommandLineSwitches.ParameterlessSwitch.NoLogo]);
 
            // set it again
            switches.SetParameterlessSwitch(CommandLineSwitches.ParameterlessSwitch.NoLogo, "-NOLOGO");
 
            Assert.Equal("-NOLOGO", switches.GetParameterlessSwitchCommandLineArg(CommandLineSwitches.ParameterlessSwitch.NoLogo));
            Assert.True(switches.IsParameterlessSwitchSet(CommandLineSwitches.ParameterlessSwitch.NoLogo));
            Assert.True(switches[CommandLineSwitches.ParameterlessSwitch.NoLogo]);
 
            // we didn't set this switch
            Assert.Null(switches.GetParameterlessSwitchCommandLineArg(CommandLineSwitches.ParameterlessSwitch.Version));
            Assert.False(switches.IsParameterlessSwitchSet(CommandLineSwitches.ParameterlessSwitch.Version));
            Assert.False(switches[CommandLineSwitches.ParameterlessSwitch.Version]);
        }
 
        [Fact]
        public void SetParameterizedSwitchTests1()
        {
            CommandLineSwitches switches = new CommandLineSwitches();
 
            Assert.True(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Verbosity, "/v:q", "q", false, true, false));
 
            Assert.Equal("/v:q", switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Verbosity));
            Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Verbosity));
 
            string[] parameters = switches[CommandLineSwitches.ParameterizedSwitch.Verbosity];
 
            Assert.NotNull(parameters);
            Assert.Single(parameters);
            Assert.Equal("q", parameters[0]);
 
            // set it again -- this is bogus, because the /verbosity switch doesn't allow multiple parameters, but for the
            // purposes of testing the SetParameterizedSwitch() method, it doesn't matter
            Assert.True(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Verbosity, "/verbosity:\"diag\";minimal", "\"diag\";minimal", true, true, false));
 
            Assert.Equal("/v:q /verbosity:\"diag\";minimal", switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Verbosity));
            Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Verbosity));
 
            parameters = switches[CommandLineSwitches.ParameterizedSwitch.Verbosity];
 
            Assert.NotNull(parameters);
            Assert.Equal(3, parameters.Length);
            Assert.Equal("q", parameters[0]);
            Assert.Equal("diag", parameters[1]);
            Assert.Equal("minimal", parameters[2]);
        }
 
        [Fact]
        public void SetParameterizedSwitchTests2()
        {
            CommandLineSwitches switches = new CommandLineSwitches();
 
            // we haven't set this switch yet
            Assert.Null(switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Target));
            Assert.False(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));
 
            string[] parameters = switches[CommandLineSwitches.ParameterizedSwitch.Target];
 
            Assert.NotNull(parameters);
            Assert.Empty(parameters);
 
            // fake/missing parameters -- this is bogus because the /target switch allows multiple parameters but we're turning
            // that off here just for testing purposes
            Assert.False(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/t:\"", "\"", false, true, false));
 
            // switch has been set
            Assert.Equal("/t:\"", switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Target));
            Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));
 
            parameters = switches[CommandLineSwitches.ParameterizedSwitch.Target];
 
            // but no parameters
            Assert.NotNull(parameters);
            Assert.Empty(parameters);
 
            // more fake/missing parameters
            Assert.False(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/t:A,\"\";B", "A,\"\";B", true, true, false));
 
            Assert.Equal("/t:\" /t:A,\"\";B", switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Target));
            Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));
 
            parameters = switches[CommandLineSwitches.ParameterizedSwitch.Target];
 
            // now we have some parameters
            Assert.NotNull(parameters);
            Assert.Equal(2, parameters.Length);
            Assert.Equal("A", parameters[0]);
            Assert.Equal("B", parameters[1]);
        }
 
        [Fact]
        public void SetParameterizedSwitchTests3()
        {
            CommandLineSwitches switches = new CommandLineSwitches();
 
            // we haven't set this switch yet
            Assert.Null(switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Logger));
            Assert.False(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Logger));
 
            string[] parameters = switches[CommandLineSwitches.ParameterizedSwitch.Logger];
 
            Assert.NotNull(parameters);
            Assert.Empty(parameters);
 
            // don't unquote fake/missing parameters
            Assert.True(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Logger, "/l:\"", "\"", false, false, false));
 
            Assert.Equal("/l:\"", switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Logger));
            Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Logger));
 
            parameters = switches[CommandLineSwitches.ParameterizedSwitch.Logger];
 
            Assert.NotNull(parameters);
            Assert.Single(parameters);
            Assert.Equal("\"", parameters[0]);
 
            // don't unquote multiple fake/missing parameters -- this is bogus because the /logger switch does not take multiple
            // parameters, but for testing purposes this is fine
            Assert.True(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Logger, "/LOGGER:\"\",asm;\"p,a;r\"", "\"\",asm;\"p,a;r\"", true, false, false));
 
            Assert.Equal("/l:\" /LOGGER:\"\",asm;\"p,a;r\"", switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Logger));
            Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Logger));
 
            parameters = switches[CommandLineSwitches.ParameterizedSwitch.Logger];
 
            Assert.NotNull(parameters);
            Assert.Equal(4, parameters.Length);
            Assert.Equal("\"", parameters[0]);
            Assert.Equal("\"\"", parameters[1]);
            Assert.Equal("asm", parameters[2]);
            Assert.Equal("\"p,a;r\"", parameters[3]);
        }
 
        [Fact]
        public void SetParameterizedSwitchTestsAllowEmpty()
        {
            CommandLineSwitches switches = new CommandLineSwitches();
 
            Assert.True(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.WarningsAsErrors, "/warnaserror", "", multipleParametersAllowed: true, unquoteParameters: false, emptyParametersAllowed: true));
 
            Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.WarningsAsErrors));
 
            string[] parameters = switches[CommandLineSwitches.ParameterizedSwitch.WarningsAsErrors];
 
            Assert.NotNull(parameters);
 
            Assert.True(parameters.Length > 0);
 
            Assert.Null(parameters.Last());
        }
 
        [Fact]
        public void AppendErrorTests1()
        {
            CommandLineSwitches switchesLeft = new CommandLineSwitches();
            CommandLineSwitches switchesRight = new CommandLineSwitches();
 
            Assert.False(switchesLeft.HaveErrors());
            Assert.False(switchesRight.HaveErrors());
 
            switchesLeft.Append(switchesRight);
 
            Assert.False(switchesLeft.HaveErrors());
            Assert.False(switchesRight.HaveErrors());
 
            switchesLeft.SetUnknownSwitchError("/bogus");
 
            Assert.True(switchesLeft.HaveErrors());
            Assert.False(switchesRight.HaveErrors());
 
            switchesLeft.Append(switchesRight);
 
            Assert.True(switchesLeft.HaveErrors());
            Assert.False(switchesRight.HaveErrors());
 
            VerifySwitchError(switchesLeft, "/bogus");
 
            switchesRight.Append(switchesLeft);
 
            Assert.True(switchesLeft.HaveErrors());
            Assert.True(switchesRight.HaveErrors());
 
            VerifySwitchError(switchesLeft, "/bogus");
            VerifySwitchError(switchesRight, "/bogus");
        }
 
        [Fact]
        public void AppendErrorTests2()
        {
            CommandLineSwitches switchesLeft = new CommandLineSwitches();
            CommandLineSwitches switchesRight = new CommandLineSwitches();
 
            Assert.False(switchesLeft.HaveErrors());
            Assert.False(switchesRight.HaveErrors());
 
            switchesLeft.SetUnknownSwitchError("/bogus");
            switchesRight.SetUnexpectedParametersError("/nologo:foo");
 
            Assert.True(switchesLeft.HaveErrors());
            Assert.True(switchesRight.HaveErrors());
 
            VerifySwitchError(switchesLeft, "/bogus");
            VerifySwitchError(switchesRight, "/nologo:foo");
 
            switchesLeft.Append(switchesRight);
 
            VerifySwitchError(switchesLeft, "/bogus");
            VerifySwitchError(switchesRight, "/nologo:foo");
        }
 
        [Fact]
        public void AppendParameterlessSwitchesTests()
        {
            CommandLineSwitches switchesLeft = new CommandLineSwitches();
 
            switchesLeft.SetParameterlessSwitch(CommandLineSwitches.ParameterlessSwitch.Help, "/?");
 
            Assert.True(switchesLeft.IsParameterlessSwitchSet(CommandLineSwitches.ParameterlessSwitch.Help));
            Assert.False(switchesLeft.IsParameterlessSwitchSet(CommandLineSwitches.ParameterlessSwitch.NoConsoleLogger));
 
            CommandLineSwitches switchesRight1 = new CommandLineSwitches();
 
            switchesRight1.SetParameterlessSwitch(CommandLineSwitches.ParameterlessSwitch.NoConsoleLogger, "/noconlog");
 
            Assert.False(switchesRight1.IsParameterlessSwitchSet(CommandLineSwitches.ParameterlessSwitch.Help));
            Assert.True(switchesRight1.IsParameterlessSwitchSet(CommandLineSwitches.ParameterlessSwitch.NoConsoleLogger));
 
            switchesLeft.Append(switchesRight1);
 
            Assert.Equal("/noconlog", switchesLeft.GetParameterlessSwitchCommandLineArg(CommandLineSwitches.ParameterlessSwitch.NoConsoleLogger));
            Assert.True(switchesLeft.IsParameterlessSwitchSet(CommandLineSwitches.ParameterlessSwitch.NoConsoleLogger));
            Assert.True(switchesLeft[CommandLineSwitches.ParameterlessSwitch.NoConsoleLogger]);
 
            // this switch is not affected
            Assert.Equal("/?", switchesLeft.GetParameterlessSwitchCommandLineArg(CommandLineSwitches.ParameterlessSwitch.Help));
            Assert.True(switchesLeft.IsParameterlessSwitchSet(CommandLineSwitches.ParameterlessSwitch.Help));
            Assert.True(switchesLeft[CommandLineSwitches.ParameterlessSwitch.Help]);
 
            CommandLineSwitches switchesRight2 = new CommandLineSwitches();
 
            switchesRight2.SetParameterlessSwitch(CommandLineSwitches.ParameterlessSwitch.NoConsoleLogger, "/NOCONSOLELOGGER");
 
            Assert.False(switchesRight2.IsParameterlessSwitchSet(CommandLineSwitches.ParameterlessSwitch.Help));
            Assert.True(switchesRight2.IsParameterlessSwitchSet(CommandLineSwitches.ParameterlessSwitch.NoConsoleLogger));
 
            switchesLeft.Append(switchesRight2);
 
            Assert.Equal("/NOCONSOLELOGGER", switchesLeft.GetParameterlessSwitchCommandLineArg(CommandLineSwitches.ParameterlessSwitch.NoConsoleLogger));
            Assert.True(switchesLeft.IsParameterlessSwitchSet(CommandLineSwitches.ParameterlessSwitch.NoConsoleLogger));
            Assert.True(switchesLeft[CommandLineSwitches.ParameterlessSwitch.NoConsoleLogger]);
 
            Assert.Equal("/?", switchesLeft.GetParameterlessSwitchCommandLineArg(CommandLineSwitches.ParameterlessSwitch.Help));
            Assert.True(switchesLeft.IsParameterlessSwitchSet(CommandLineSwitches.ParameterlessSwitch.Help));
            Assert.True(switchesLeft[CommandLineSwitches.ParameterlessSwitch.Help]);
 
            Assert.False(switchesLeft.HaveErrors());
        }
 
        [Fact]
        public void AppendParameterizedSwitchesTests1()
        {
            CommandLineSwitches switchesLeft = new CommandLineSwitches();
 
            switchesLeft.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Project, "tempproject.proj", "tempproject.proj", false, true, false);
 
            Assert.True(switchesLeft.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Project));
            Assert.False(switchesLeft.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));
 
            CommandLineSwitches switchesRight = new CommandLineSwitches();
 
            switchesRight.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/t:build", "build", true, true, false);
 
            Assert.False(switchesRight.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Project));
            Assert.True(switchesRight.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));
 
            switchesLeft.Append(switchesRight);
 
            Assert.Equal("tempproject.proj", switchesLeft.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Project));
            Assert.True(switchesLeft.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Project));
 
            string[] parameters = switchesLeft[CommandLineSwitches.ParameterizedSwitch.Project];
 
            Assert.NotNull(parameters);
            Assert.Single(parameters);
            Assert.Equal("tempproject.proj", parameters[0]);
 
            Assert.Equal("/t:build", switchesLeft.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Target));
            Assert.True(switchesLeft.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));
 
            parameters = switchesLeft[CommandLineSwitches.ParameterizedSwitch.Target];
 
            Assert.NotNull(parameters);
            Assert.Single(parameters);
            Assert.Equal("build", parameters[0]);
        }
 
        [Fact]
        public void AppendParameterizedSwitchesTests2()
        {
            CommandLineSwitches switchesLeft = new CommandLineSwitches();
 
            switchesLeft.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/target:Clean", "Clean", true, true, false);
 
            Assert.True(switchesLeft.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));
 
            CommandLineSwitches switchesRight = new CommandLineSwitches();
 
            switchesRight.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/t:\"RESOURCES\";build", "\"RESOURCES\";build", true, true, false);
 
            Assert.True(switchesRight.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));
 
            switchesLeft.Append(switchesRight);
 
            Assert.Equal("/t:\"RESOURCES\";build", switchesLeft.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Target));
            Assert.True(switchesLeft.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));
 
            string[] parameters = switchesLeft[CommandLineSwitches.ParameterizedSwitch.Target];
 
            Assert.NotNull(parameters);
            Assert.Equal(3, parameters.Length);
            Assert.Equal("Clean", parameters[0]);
            Assert.Equal("RESOURCES", parameters[1]);
            Assert.Equal("build", parameters[2]);
        }
 
        /// <summary>
        /// Verifies that the Target property is unquoted and parsed properly.
        /// This will remove the possibility to have the ';' in the target name. 
        /// </summary>
        [Theory]
        [InlineData("/t:Clean;Build", "\"Clean;Build\"")]
        [InlineData("/t:Clean;Build", "Clean;Build")]
        public void ParameterizedSwitchTargetQuotedTest(string commandLineArg, string switchParameters)
        {
            CommandLineSwitches switches = new CommandLineSwitches();
            switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, commandLineArg, switchParameters, true, true, false);
            switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target).ShouldBeTrue();
 
            switches[CommandLineSwitches.ParameterizedSwitch.Target].Length.ShouldBe(2);
            switches[CommandLineSwitches.ParameterizedSwitch.Target][0].ShouldBe("Clean");
            switches[CommandLineSwitches.ParameterizedSwitch.Target][1].ShouldBe("Build");
            switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Target).ShouldBe(commandLineArg);
        }
 
        /// <summary>
        /// Verifies that the parsing behavior of quoted target properties is not changed when ChangeWave configured.
        /// </summary>
        [Fact]
        public void ParameterizedSwitchTargetQuotedChangeWaveTest()
        {
            using (TestEnvironment env = TestEnvironment.Create())
            {
                env.SetEnvironmentVariable("MSBUILDDISABLEFEATURESFROMVERSION", "17.10");
 
                CommandLineSwitches switches = new CommandLineSwitches();
                switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/t:Clean;Build", "\"Clean;Build\"", true, true, false);
                switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target).ShouldBeTrue();
 
                switches[CommandLineSwitches.ParameterizedSwitch.Target].Length.ShouldBe(1);
                switches[CommandLineSwitches.ParameterizedSwitch.Target][0].ShouldBe("Clean;Build");
            }
        }
 
        [Fact]
        public void AppendParameterizedSwitchesTests3()
        {
            CommandLineSwitches switchesLeft = new CommandLineSwitches();
 
            switchesLeft.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Project, "tempproject.proj", "tempproject.proj", false, true, false);
 
            Assert.True(switchesLeft.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Project));
 
            CommandLineSwitches switchesRight = new CommandLineSwitches();
 
            switchesRight.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Project, "Rhubarb.proj", "Rhubarb.proj", false, true, false);
 
            Assert.True(switchesRight.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Project));
 
            switchesLeft.Append(switchesRight);
 
            Assert.Equal("tempproject.proj", switchesLeft.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Project));
            Assert.True(switchesLeft.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Project));
 
            string[] parameters = switchesLeft[CommandLineSwitches.ParameterizedSwitch.Project];
 
            Assert.NotNull(parameters);
            Assert.Single(parameters);
            Assert.Equal("tempproject.proj", parameters[0]);
 
            Assert.True(switchesLeft.HaveErrors());
 
            VerifySwitchError(switchesLeft, "Rhubarb.proj");
        }
 
        [Fact]
        public void InvalidToolsVersionErrors()
        {
            Assert.Throws<InitializationException>(() =>
            {
                string filename = null;
                try
                {
                    filename = FileUtilities.GetTemporaryFileName();
                    ProjectRootElement project = ProjectRootElement.Create();
                    project.Save(filename);
                    BuildResult buildResult = null;
                    MSBuildApp.BuildProject(
                                        filename,
                                        null,
                                        "ScoobyDoo",
                                        new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase),
                                        new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase),
                                        Array.Empty<ILogger>(),
                                        LoggerVerbosity.Normal,
                                        Array.Empty<DistributedLoggerRecord>(),
#if FEATURE_XML_SCHEMA_VALIDATION
                                        false,
                                        null,
#endif
                                        1,
                                        true,
                                        new StringWriter(),
                                        new StringWriter(),
                                        false,
                                        warningsAsErrors: null,
                                        warningsNotAsErrors: null,
                                        warningsAsMessages: null,
                                        enableRestore: false,
                                        profilerLogger: null,
                                        enableProfiler: false,
                                        interactive: false,
                                        isolateProjects: ProjectIsolationMode.False,
                                        graphBuildOptions: null,
                                        lowPriority: false,
                                        question: false,
                                        isBuildCheckEnabled: false,
                                        inputResultsCaches: null,
                                        outputResultsCache: null,
                                        saveProjectResult: false,
                                        ref buildResult,
#if FEATURE_REPORTFILEACCESSES
                                        reportFileAccesses: false,
#endif
                                        commandLine: null);
                }
                finally
                {
                    if (File.Exists(filename))
                    {
                        File.Delete(filename);
                    }
                }
            });
        }
        [Fact]
        public void TestHaveAnySwitchesBeenSet()
        {
            // Check if method works with parameterized switch
            CommandLineSwitches switches = new CommandLineSwitches();
            Assert.False(switches.HaveAnySwitchesBeenSet());
            switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Verbosity, "/v:q", "q", false, true, false);
            Assert.True(switches.HaveAnySwitchesBeenSet());
 
            // Check if method works with parameterless switches
            switches = new CommandLineSwitches();
            Assert.False(switches.HaveAnySwitchesBeenSet());
            switches.SetParameterlessSwitch(CommandLineSwitches.ParameterlessSwitch.Help, "/?");
            Assert.True(switches.HaveAnySwitchesBeenSet());
        }
 
#if FEATURE_NODE_REUSE
        /// <summary>
        /// /nodereuse:false /nodereuse:true should result in "true"
        /// </summary>
        [Fact]
        public void ProcessNodeReuseSwitchTrueLast()
        {
            bool nodeReuse = MSBuildApp.ProcessNodeReuseSwitch(new string[] { "false", "true" });
 
            Assert.True(nodeReuse);
        }
 
        /// <summary>
        /// /nodereuse:true /nodereuse:false should result in "false"
        /// </summary>
        [Fact]
        public void ProcessNodeReuseSwitchFalseLast()
        {
            bool nodeReuse = MSBuildApp.ProcessNodeReuseSwitch(new string[] { "true", "false" });
 
            Assert.False(nodeReuse);
        }
#endif
 
        /// <summary>
        /// Regress DDB #143341:
        ///     msbuild /clp:v=quiet /clp:v=diag /m:2
        /// gave console logger in quiet verbosity; expected diagnostic
        /// </summary>
        [Fact]
        public void ExtractAnyLoggerParameterPickLast()
        {
            string result = MSBuildApp.ExtractAnyLoggerParameter("v=diag;v=q", new string[] { "v", "verbosity" });
 
            Assert.Equal("v=q", result);
        }
 
        /// <summary>
        /// Verifies that when the /warnaserror switch is not specified, the set of warnings is null.
        /// </summary>
        [Fact]
        public void ProcessWarnAsErrorSwitchNotSpecified()
        {
            CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
 
            MSBuildApp.GatherCommandLineSwitches(new List<string>(new[] { "" }), commandLineSwitches);
 
            Assert.Null(MSBuildApp.ProcessWarnAsErrorSwitch(commandLineSwitches));
        }
 
        /// <summary>
        /// Verifies that the /warnaserror switch is parsed properly when codes are specified.
        /// </summary>
        [Fact]
        public void ProcessWarnAsErrorSwitchWithCodes()
        {
            ISet<string> expectedWarningsAsErrors = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "a", "B", "c", "D", "e" };
 
            CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
 
            MSBuildApp.GatherCommandLineSwitches(new List<string>(new[]
            {
                "\"/warnaserror: a,B ; c \"", // Leading, trailing, leading and trailing whitespace
                "/warnaserror:A,b,C",         // Repeats of different case
                "\"/warnaserror:,    ,,\"",   // Empty items
                "/err:D,d;E,e",               // A different source with new items and uses the short form
                "/warnaserror:a",             // A different source with a single duplicate
                "/warnaserror:a,b",           // A different source with  multiple duplicates
            }), commandLineSwitches);
 
            ISet<string> actualWarningsAsErrors = MSBuildApp.ProcessWarnAsErrorSwitch(commandLineSwitches);
 
            Assert.NotNull(actualWarningsAsErrors);
 
            Assert.Equal(expectedWarningsAsErrors, actualWarningsAsErrors, StringComparer.OrdinalIgnoreCase);
        }
 
        /// <summary>
        /// Verifies that an empty /warnaserror switch clears the list of codes.
        /// </summary>
        [Fact]
        public void ProcessWarnAsErrorSwitchEmptySwitchClearsSet()
        {
            CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
 
            MSBuildApp.GatherCommandLineSwitches(new List<string>(new[]
            {
                "/warnaserror:a;b;c",
                "/warnaserror",
            }), commandLineSwitches);
 
            ISet<string> actualWarningsAsErrors = MSBuildApp.ProcessWarnAsErrorSwitch(commandLineSwitches);
 
            Assert.NotNull(actualWarningsAsErrors);
 
            Assert.Empty(actualWarningsAsErrors);
        }
 
        /// <summary>
        /// Verifies that when values are specified after an empty /warnaserror switch that they are added to the cleared list.
        /// </summary>
        [Fact]
        public void ProcessWarnAsErrorSwitchValuesAfterEmptyAddOn()
        {
            ISet<string> expectedWarningsAsErors = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "e", "f", "g" };
 
            CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
 
            MSBuildApp.GatherCommandLineSwitches(new List<string>(new[]
            {
                "/warnaserror:a;b;c",
                "/warnaserror",
                "/warnaserror:e;f;g",
            }), commandLineSwitches);
 
            ISet<string> actualWarningsAsErrors = MSBuildApp.ProcessWarnAsErrorSwitch(commandLineSwitches);
 
            Assert.NotNull(actualWarningsAsErrors);
 
            Assert.Equal(expectedWarningsAsErors, actualWarningsAsErrors, StringComparer.OrdinalIgnoreCase);
        }
 
        /// <summary>
        /// Verifies that the /warnaserror switch is parsed properly when no codes are specified.
        /// </summary>
        [Fact]
        public void ProcessWarnAsErrorSwitchEmpty()
        {
            CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
 
            MSBuildApp.GatherCommandLineSwitches(new List<string>(new[] { "/warnaserror" }), commandLineSwitches);
 
            ISet<string> actualWarningsAsErrors = MSBuildApp.ProcessWarnAsErrorSwitch(commandLineSwitches);
 
            Assert.NotNull(actualWarningsAsErrors);
 
            Assert.Empty(actualWarningsAsErrors);
        }
 
        /// <summary>
        /// Verifies that when the /warnasmessage switch is used with no values that an error is shown.
        /// </summary>
        [Fact]
        public void ProcessWarnAsMessageSwitchEmpty()
        {
            CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
 
            // Set "expanded" content to match the placeholder so the verify can use the exact resource string as "expected."
            string command = "{0}";
            MSBuildApp.GatherCommandLineSwitches(new List<string>(new[] { "/warnasmessage" }), commandLineSwitches, command);
 
            VerifySwitchError(commandLineSwitches, "/warnasmessage", AssemblyResources.GetString("MissingWarnAsMessageParameterError"));
        }
 
        /// <summary>
        /// Verify that environment variables cannot be passed in as command line switches.
        /// Also verifies that the full command line is properly passed when a switch error occurs.
        /// </summary>
        [Fact]
        public void ProcessEnvironmentVariableSwitch()
        {
            using (TestEnvironment env = TestEnvironment.Create())
            {
                env.SetEnvironmentVariable("ENVIRONMENTVARIABLE", string.Empty);
 
                CommandLineSwitches commandLineSwitches = new();
                string fullCommandLine = "msbuild validProject.csproj %ENVIRONMENTVARIABLE%";
                MSBuildApp.GatherCommandLineSwitches(new List<string>() { "validProject.csproj", "%ENVIRONMENTVARIABLE%" }, commandLineSwitches, fullCommandLine);
                VerifySwitchError(commandLineSwitches, "%ENVIRONMENTVARIABLE%", String.Format(AssemblyResources.GetString("EnvironmentVariableAsSwitch"), fullCommandLine));
 
                commandLineSwitches = new();
                fullCommandLine = "msbuild %ENVIRONMENTVARIABLE% validProject.csproj";
                MSBuildApp.GatherCommandLineSwitches(new List<string>() { "%ENVIRONMENTVARIABLE%", "validProject.csproj" }, commandLineSwitches, fullCommandLine);
                VerifySwitchError(commandLineSwitches, "%ENVIRONMENTVARIABLE%", String.Format(AssemblyResources.GetString("EnvironmentVariableAsSwitch"), fullCommandLine));
            }
        }
 
        /// <summary>
        /// Verifies that the /warnasmessage switch is parsed properly when codes are specified.
        /// </summary>
        [Fact]
        public void ProcessWarnAsMessageSwitchWithCodes()
        {
            ISet<string> expectedWarningsAsMessages = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "a", "B", "c", "D", "e" };
 
            CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
 
            MSBuildApp.GatherCommandLineSwitches(new List<string>(new[]
            {
                "\"/warnasmessage: a,B ; c \"", // Leading, trailing, leading and trailing whitespace
                "/warnasmessage:A,b,C",         // Repeats of different case
                "\"/warnasmessage:,    ,,\"",   // Empty items
                "/nowarn:D,d;E,e",              // A different source with new items and uses the short form
                "/warnasmessage:a",             // A different source with a single duplicate
                "/warnasmessage:a,b",           // A different source with  multiple duplicates
            }), commandLineSwitches);
 
            ISet<string> actualWarningsAsMessages = MSBuildApp.ProcessWarnAsMessageSwitch(commandLineSwitches);
 
            Assert.NotNull(actualWarningsAsMessages);
 
            Assert.Equal(expectedWarningsAsMessages, actualWarningsAsMessages, StringComparer.OrdinalIgnoreCase);
        }
 
        /// <summary>
        /// Verifies that when the /profileevaluation switch is used with no values "no-file" is specified.
        /// </summary>
        [Fact]
        public void ProcessProfileEvaluationEmpty()
        {
            CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
 
            MSBuildApp.GatherCommandLineSwitches(new List<string>(new[] { "/profileevaluation" }), commandLineSwitches);
            commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.ProfileEvaluation][0].ShouldBe("no-file");
        }
 
        [Fact]
        public void ProcessBooleanSwitchTest()
        {
            MSBuildApp.ProcessBooleanSwitch(Array.Empty<string>(), defaultValue: true, resourceName: null).ShouldBeTrue();
 
            MSBuildApp.ProcessBooleanSwitch(Array.Empty<string>(), defaultValue: false, resourceName: null).ShouldBeFalse();
 
            MSBuildApp.ProcessBooleanSwitch(new[] { "true" }, defaultValue: false, resourceName: null).ShouldBeTrue();
 
            MSBuildApp.ProcessBooleanSwitch(new[] { "false" }, defaultValue: true, resourceName: null).ShouldBeFalse();
 
            Should.Throw<CommandLineSwitchException>(() => MSBuildApp.ProcessBooleanSwitch(new[] { "invalid" }, defaultValue: true, resourceName: "InvalidRestoreValue"));
        }
 
        public static IEnumerable<object[]> ProcessGraphBuildSwitchData()
        {
            var emptyOptions = new GraphBuildOptions();
            var noBuildOptions = new GraphBuildOptions { Build = false };
 
            yield return new object[] { Array.Empty<string>(), emptyOptions, null };
 
            yield return new object[] { new[] { "true" }, emptyOptions, null };
 
            yield return new object[] { new[] { "false" }, null, null };
 
            yield return new object[] { new[] { "  ", "  " }, emptyOptions, null };
 
            yield return new object[] { new[] { "NoBuild" }, noBuildOptions, null };
 
            yield return new object[] { new[] { "noBUILD" }, noBuildOptions, null };
 
            yield return new object[] { new[] { "noBUILD     " }, noBuildOptions, null };
 
            yield return new object[] { new[] { "false", "true" }, null, new[] { "false" } };
 
            yield return new object[] { new[] { "nobuild", "true" }, noBuildOptions, new[] { "true" } };
 
            yield return new object[] { new[] { "false", "nobuild" }, null, new[] { "false" } };
 
            yield return new object[] { new[] { "nobuild", "invalid" }, null, new[] { "invalid" } };
        }
 
        [Theory]
        [MemberData(nameof(ProcessGraphBuildSwitchData))]
        public void ProcessGraphBuildSwitch(string[] parameters, GraphBuildOptions expectedOptions, string[] expectedWordsInException)
        {
            CommandLineSwitchException exception = null;
 
            try
            {
                var graphBuildOptions = MSBuildApp.ProcessGraphBuildSwitch(parameters);
                graphBuildOptions.ShouldBe(expectedOptions);
            }
            catch (CommandLineSwitchException e)
            {
                exception = e;
            }
 
            if (expectedWordsInException != null)
            {
                exception.ShouldNotBeNull();
 
                exception.Message.ShouldContain("Graph build value is not valid");
 
                foreach (var expectedWord in expectedWordsInException)
                {
                    exception.Message.ShouldContain(expectedWord);
                }
            }
            else
            {
                exception.ShouldBeNull();
            }
        }
 
        /// <summary>
        /// Verifies that the /target switch is parsed properly with invalid characters.
        /// </summary>
        [Fact]
        public void ProcessInvalidTargetSwitch()
        {
            string projectContent = """
                <Project>
                </Project>
                """;
            using TestEnvironment testEnvironment = TestEnvironment.Create();
            string project = testEnvironment.CreateTestProjectWithFiles("project.proj", projectContent).ProjectFile;
 
#if FEATURE_GET_COMMANDLINE
            MSBuildApp.Execute(@"msbuild.exe " + project + " /t:foo.bar").ShouldBe(MSBuildApp.ExitType.SwitchError);
#else
            MSBuildApp.Execute(new[] { @"msbuild.exe", project, "/t:foo.bar" }).ShouldBe(MSBuildApp.ExitType.SwitchError);
#endif
        }
 
        /// <summary>
        /// Verifies that help messages are correctly formed with the right width and leading spaces.
        /// </summary>
        [Fact]
        public void HelpMessagesAreValid()
        {
            ResourceManager resourceManager = new ResourceManager("MSBuild.Strings", typeof(AssemblyResources).Assembly);
 
            const string switchLeadingSpaces = "  ";
            const string otherLineLeadingSpaces = "                     ";
            const string examplesLeadingSpaces = "        ";
 
            foreach (KeyValuePair<string, string> item in resourceManager.GetResourceSet(CultureInfo.CurrentUICulture, createIfNotExists: true, tryParents: true)
                .Cast<DictionaryEntry>().Where(i => i.Key is string && ((string)i.Key).StartsWith("HelpMessage_"))
                .Select(i => new KeyValuePair<string, string>((string)i.Key, (string)i.Value)))
            {
                string[] helpMessageLines = item.Value.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
 
                for (int i = 0; i < helpMessageLines.Length; i++)
                {
                    // All lines should be 80 characters or less
                    Assert.True(helpMessageLines[i].Length <= 80, $"Line {i + 1} of '{item.Key}' should be no longer than 80 characters.");
 
                    string trimmedLine = helpMessageLines[i].Trim();
 
                    if (i == 0)
                    {
                        if (trimmedLine.StartsWith("-") || trimmedLine.StartsWith("@"))
                        {
                            // If the first line in a switch it needs a certain amount of leading spaces
                            Assert.StartsWith(switchLeadingSpaces, helpMessageLines[i]);
                        }
                        else
                        {
                            // Otherwise it should have no leading spaces because it's a section
                            Assert.False(helpMessageLines[i].StartsWith(" "));
                        }
                    }
                    else
                    {
                        // Ignore empty lines
                        if (!String.IsNullOrWhiteSpace(helpMessageLines[i]))
                        {
                            if (item.Key.Contains("Examples"))
                            {
                                // Examples require a certain number of leading spaces
                                Assert.StartsWith(examplesLeadingSpaces, helpMessageLines[i]);
                            }
                            else if (trimmedLine.StartsWith("-") || trimmedLine.StartsWith("@"))
                            {
                                // Switches require a certain number of leading spaces
                                Assert.StartsWith(switchLeadingSpaces, helpMessageLines[i]);
                            }
                            else
                            {
                                // All other lines require a certain number of leading spaces
                                Assert.StartsWith(otherLineLeadingSpaces, helpMessageLines[i]);
                            }
                        }
                    }
                }
            }
        }
 
        /// <summary>
        /// Verifies that a switch collection has an error registered for the given command line arg.
        /// </summary>
        private void VerifySwitchError(CommandLineSwitches switches, string badCommandLineArg, string expectedMessage = null)
        {
            bool caughtError = false;
 
            try
            {
                switches.ThrowErrors();
            }
            catch (CommandLineSwitchException e)
            {
                Assert.Equal(badCommandLineArg, e.CommandLineArg);
 
                caughtError = true;
 
                if (expectedMessage != null)
                {
                    Assert.Contains(expectedMessage, e.Message);
                }
 
                // so I can see the message in NUnit's "Standard Out" window
                Console.WriteLine(e.Message);
            }
            finally
            {
                Assert.True(caughtError);
            }
        }
    }
}