Sei sulla pagina 1di 6

using

using
using
using
using

System.Collections.Generic;
System.IO;
System.Linq;
System.Reflection;
CommandLineParser.Arguments;

namespace CodingChallange1_800
{
public class Arguments : IArgumentsConfig<IArgumentsValues>, IArgumentsValue
s
{
private const char InputFileShortName = 'I';
private const char DictionaryShortName = 'D';
internal const string InputFileLongName = "input-file";
internal const string DictionaryLongName = "dictionary-file";
private readonly FileArgument _inputFile;
private readonly FileArgument _dictionaryFile;
public Arguments()
{
_inputFile = new FileArgument(InputFileShortName, InputFileLongName,
Help.InputFileArgument);
_dictionaryFile = new FileArgument(DictionaryShortName, DictionaryLo
ngName,
Help.DictionaryFileArgument)
{
DefaultValue = new FileInfo("defaultDictionary")
};
}
public IEnumerable<Argument> All
{
get
{
return GetType().GetFields(BindingFlags.Instance | BindingFlags.
NonPublic)
.Select(field => field.GetValue(this)).OfType<Argument>().To
List();
}
}
public FileInfo InputFile
{
get { return _inputFile.Value; }
}
public FileInfo DictionaryFile
{
get { return _dictionaryFile.Value; }
}
public IArgumentsValues AsOutput()
{
return this;
}
}
[TestFixture]
public class ArgumentsTest

{
private Arguments _arguments;
[SetUp]
public void SetUp()
{
_arguments = new Arguments();
}
[Test]
public void AllCollectsAllArguments()
{
AssertArgument<FileArgument>(Arguments.InputFileLongName);
AssertArgument<FileArgument>(Arguments.DictionaryLongName);
}
private void AssertArgument<T>(string longName) where T : Argument
{
var argument = FindArgument(longName);
Assert.IsNotNull(argument, "there should be an argument " + longName
);
Assert.IsInstanceOf(typeof(T), argument, "argument " + longName);
}
private Argument FindArgument(string longName)
{
return _arguments.All.First(x => x.LongName == longName);
}
[Test]
public void AllArgumentsShouldHaveDifferentShortNames()
{
var shortNames = _arguments.All.Select(x => x.ShortName).Where(x =>
x != ' ');
Assert.AreEqual(shortNames, shortNames.Distinct(), "distinct short n
ames");
}
[Test]
public void AllArgumentsShouldHaveDifferentLongNames()
{
var longNames = _arguments.All.Select(x => x.LongName);
Assert.AreEqual(longNames, longNames.Distinct(), "distinct long name
s");
}
[Test]
public void PropertiesHaveTheValueOfTheCorrespondingArguments()
{
InputFileArgument.Value = new FileInfo("inputFileName");
Assert.AreEqual(InputFileArgument.Value, _arguments.InputFile, "Argu
ments.InputFileName");
DictionaryFileArgument.Value = new FileInfo("dictionaryFileName");
Assert.AreEqual(DictionaryFileArgument.Value, _arguments.DictionaryF
ile,
"Arguments.DictionaryFileName");
}
[Test]
public void DictionaryArgumentIsDefaultDictionaryByDedfault()
{
Assert.AreEqual(new FileInfo("defaultDictionary").FullName, Dictiona
ryFileArgument.DefaultValue.FullName,
"DictionaryFileArgument default value");
}
[Test]
public void ReturnsItselfAsOutput()
{

Assert.AreSame(_arguments, _arguments.AsOutput(), "Arguments.AsOutpu


t");
}
private FileArgument DictionaryFileArgument
{
get { return (FileArgument)FindArgument(Arguments.DictionaryLongName
); }
}
private FileArgument InputFileArgument
{
get { return (FileArgument)FindArgument(Arguments.InputFileLongName)
; }
}
}
public static class Help
{
internal static readonly string InputFileArgument = Format(
"Input file argument");
internal static readonly string DictionaryFileArgument = Format(
"Dictionary file argument");
private static string Format(params string[] lines)
{
return String.Join("\r\n\t\t", lines);
}
}
public interface IArgumentsConfig<T>
{
IEnumerable<Argument> All { get; }
T AsOutput();
}
public interface IArgumentsValues
{
FileInfo InputFile { get; }
FileInfo DictionaryFile { get; }
}
public interface ICommandLine
{
string CommandLine { get; }
}
public interface IParser<T> : ICommandLine
{
string Usage { get; }
bool UsageShouldBeDisplayed { get; }
void ReadArgs(string[] args);
T Parse();
}
public class Parser<T> : IParser<T>
{
public const int SuccessExitCode = 0;
public const int FailureExitCode = -1;
private readonly CommandLineParser.CommandLineParser _parser;
private readonly IArgumentsConfig<T> _arguments;

private string[] _args = new string[0];


internal Parser(IArgumentsConfig<T> arguments)
{
_arguments = arguments;
_parser = new CommandLineParser.CommandLineParser();
_parser.IgnoreCase = true;
_parser.Arguments.AddRange(_arguments.All);
}
public string Usage
{
get
{
TextWriter str = new StringWriter();
_parser.PrintUsage(str);
return str.ToString().Trim();
}
}
public string CommandLine
{
get { return String.Join(" ", _args); }
}
public T Parse()
{
_parser.ParseCommandLine(_args);
return _arguments.AsOutput();
}
public void ReadArgs(string[] args)
{
_args = args;
}
public bool UsageShouldBeDisplayed
{
get { return (_args.Contains("--help") || _args.Contains("/help") ||
_args.Contains("/?")); }
}
}
[TestFixture]
public class ParserTest
{
private Parser<object> _parser;
private TestArguments _arguments;
[SetUp]
public void SetUp()
{
_arguments = new TestArguments();
_parser = null;
}
[Test]
public void PublishesTheUsageString()
{
GivenANewParser();
AssertIsUsage(_parser.Usage);
}
[Test]
public void ShowsUsageWithHelpArgs()
{
GivenANewParser();

_parser.ReadArgs(new [] { "--help"});
Assert.IsTrue(_parser.UsageShouldBeDisplayed, "Parser.UsageShouldBeD
isplayed");
}
[Test]
public void DoesNotShowUsageWithValidArgs()
{
ParseArgumentsWithUser();
Assert.IsFalse(_parser.UsageShouldBeDisplayed, "Parser.UsageShouldBe
Displayed");
}
[Test]
public void ByDefaultCommandLineIsEmpty()
{
GivenANewParser();
Assert.AreEqual("", _parser.CommandLine, "Command Line");
}
[Test]
public void KnowsTheActualCommandLineTextAfterAParsing()
{
var args = new[] {TestArguments.UserShortArg, "spoke", TestArguments
.NumberShortArg, "42"};
ParseArguments(args);
Assert.AreEqual(string.Join(" ", args), _parser.CommandLine, "Comman
d line");
}
[Test]
public void ActuallyParsesTheCommandLine()
{
const string User = "Bob";
const int Number = 12;
ParseArguments(TestArguments.UserShortArg, User, TestArguments.Numbe
rShortArg, Number.ToString());
Assert.AreEqual(User, _arguments.User.Value, "Parsed user argument")
;
Assert.AreEqual(Number, _arguments.Number.Value, "Parsed number argu
ment");
}
[Test, ExpectedException(typeof(InvalidConversionException))]
public void ThrowsWhenAParsingErrorOccurs()
{
ParseArgumentsWithUser(TestArguments.NumberShortArg, "malformed numb
er ...");
}
[Test]
public void CreatesTheOutputOnSuccessfulParsing()
{
Assert.AreEqual(_arguments.Output, ParseArgumentsWithUser(), "Output
built by the parser");
}
[Test]
public void HandlesUperCaseArguments()
{
const string User = "Client";
ParseArguments("--" + TestArguments.UserLongName.ToUpper(), User);
Assert.AreEqual(User, _arguments.User.Value, "User specified with up
case argument name");
}
private object ParseArgumentsWithUser(params string[] extraArgs)
{

var allArgs = new List<string> { TestArguments.UserShortArg, "Jimmy"


};
allArgs.AddRange(extraArgs);
return ParseArguments(allArgs.ToArray());
}
private object ParseArguments(params string[] args)
{
GivenANewParser();
_parser.ReadArgs(args);
return _parser.Parse();
}
private void GivenANewParser()
{
_parser = new Parser<object>(_arguments);
}
private static void AssertIsUsage(string text)
{
Assert.That(text, Is.StringStarting("Usage:"), "Command line usage")
;
Assert.That(text, Is.StringContaining(TestArguments.UserShortArg), "
Command line usage");
Assert.That(text, Is.StringContaining(TestArguments.NumberShortArg),
"Command line usage");
}
}
public class TestArguments : IArgumentsConfig<object>
{
internal const char UserShortName = 'U';
internal const string UserLongName = "user";
internal static readonly string UserShortArg = "-" + UserShortName;
internal const char NumberShortName = 'N';
internal static readonly string NumberShortArg = "-" + NumberShortName;
internal readonly ValueArgument<string> User = new ValueArgument<string>
(UserShortName, UserLongName)
{
Optional = false
};
internal readonly ValueArgument<int> Number = new ValueArgument<int>(Num
berShortName, "number");
public IEnumerable<Argument> All
{
get { return new Argument[] {User, Number}; }
}
internal readonly object Output = new object();
public object AsOutput()
{
return Output;
}
}