4using System.Collections.Generic;
11using Microsoft.FSharp.Core;
16 public class UnParserExtensionsTests
19 [MemberData(nameof(UnParseData))]
20 public static void UnParsing_instance_returns_command_line(
Simple_Options options,
string result)
23 .FormatCommandLine(options)
24 .Should().BeEquivalentTo(result);
28 [MemberData(nameof(UnParseData))]
29 public static void UnParsing_instance_with_splitArgs_returns_same_option_class(
Simple_Options options,
string result)
32 .FormatCommandLineArgs(options)
33 .Should().BeEquivalentTo(result.SplitArgs());
38 [MemberData(nameof(UnParseFileDirectoryData))]
42 .FormatCommandLine(options)
43 .Should().BeEquivalentTo(result);
47 [MemberData(nameof(UnParseFileDirectoryData))]
48 public static void UnParsing_instance_by_splitArgs_returns_command_line_for_file_directory_paths(
Options_With_FileDirectoryInfo options,
string result)
51 .FormatCommandLineArgs(options)
52 .Should().BeEquivalentTo(result.SplitArgs());
55 [MemberData(nameof(UnParseDataVerbs))]
56 public static void UnParsing_instance_returns_command_line_for_verbs(
Add_Verb verb,
string result)
59 .FormatCommandLine(verb)
60 .Should().BeEquivalentTo(result);
64 [MemberData(nameof(UnParseDataVerbs))]
65 public static void UnParsing_instance_to_splitArgs_returns_command_line_for_verbs(
Add_Verb verb,
string result)
68 .FormatCommandLineArgs(verb)
69 .Should().BeEquivalentTo(result.SplitArgs());
73 [MemberData(nameof(UnParseDataImmutable))]
74 public static void UnParsing_immutable_instance_returns_command_line(
Immutable_Simple_Options options,
string result)
77 .FormatCommandLine(options)
78 .Should().BeEquivalentTo(result);
82 [MemberData(nameof(UnParseDataHidden))]
83 public static void Unparsing_hidden_option_returns_command_line(
Hidden_Option options,
bool showHidden,
string result)
86 .FormatCommandLine(options, config => config.ShowHidden = showHidden)
87 .Should().BeEquivalentTo(result);
92 [MemberData(nameof(UnParseDataFSharpOption))]
93 public static void UnParsing_instance_with_fsharp_option_returns_command_line(
Options_With_FSharpOption options,
string result)
96 .FormatCommandLine(options)
97 .Should().BeEquivalentTo(result);
102 public static void UnParsing_instance_with_group_switches_returns_command_line_with_switches_grouped()
104 var options =
new Options_With_Switches { InputFile =
"input.bin", HumanReadable =
true, IgnoreWarnings =
true };
106 .FormatCommandLine(options, config => config.GroupSwitches =
true)
107 .Should().BeEquivalentTo(
"-hi --input input.bin");
111 public static void UnParsing_instance_with_equal_token_returns_command_line_with_long_option_using_equal_sign()
113 var options =
new Simple_Options { BoolValue =
true, IntSequence =
new[] { 1, 2, 3 }, StringValue =
"nospaces", LongValue = 123456789 };
115 .FormatCommandLine(options, config => config.UseEqualToken =
true)
116 .Should().BeEquivalentTo(
"-i 1 2 3 --stringvalue=nospaces -x 123456789");
120 public static void UnParsing_instance_with_dash_in_value_and_dashdash_enabled_returns_command_line_with_value_prefixed_with_dash_dash()
123 new Parser((setting) => setting.EnableDashDash =
true)
124 .FormatCommandLine(options)
125 .Should().BeEquivalentTo(
"-- -something with dash");
129 public static void UnParsing_instance_with_no_values_and_dashdash_enabled_returns_command_line_without_dash_dash()
132 new Parser((setting) => setting.EnableDashDash =
true)
133 .FormatCommandLine(options)
134 .Should().BeEquivalentTo(
"");
138 public static void UnParsing_instance_with_dash_in_value_and_dashdash_disabled_returns_command_line_with_value()
142 .FormatCommandLine(options)
143 .Should().BeEquivalentTo(
"-something with dash");
148 public static void UnParsing_instance_with_TimeSpan_returns_the_value_unquoted_in_command_line()
152 .FormatCommandLine(options)
153 .Should().Be(
"--duration 00:01:00");
160 public static void UnParsing_instance_with_default_values_when_skip_default_is_false()
164 .FormatCommandLine(options)
165 .Should().BeEquivalentTo(
"--p1 99 --p2 xyz --p3 88 --p4 Square");
169 [InlineData(
true,
"--p2 xyz")]
170 [InlineData(
false,
"--p1 99 --p2 xyz --p3 88 --p4 Square")]
171 public static void UnParsing_instance_with_default_values_when_skip_default_is_true(
bool skipDefault,
string expected)
175 .FormatCommandLine(options, x => x.SkipDefault = skipDefault)
176 .Should().BeEquivalentTo(expected);
180 [InlineData(
true,
"--p2 xyz")]
181 [InlineData(
false,
"--p1 99 --p2 xyz --p3 88 --p4 Square")]
182 public static void UnParsing_instance_with_nullable_default_values_when_skip_default_is_true(
bool skipDefault,
string expected)
186 .FormatCommandLine(options, x => x.SkipDefault = skipDefault)
187 .Should().BeEquivalentTo(expected);
190 public static void UnParsing_instance_with_datetime()
192 var date =
new DateTime(2019, 5, 1);
193 var options =
new Options_Date { Start = date };
195 .FormatCommandLine(options)
196 .Should().MatchRegex(
"--start\\s\".+\"");
200 public static void UnParsing_instance_with_datetime_nullable()
202 var date =
new DateTime(2019, 5, 1);
203 var options =
new Options_Date_Nullable { Start = date };
205 .FormatCommandLine(options)
206 .Should().MatchRegex(
"--start\\s\".+\"");
210 public static void UnParsing_instance_with_datetime_offset()
212 DateTimeOffset date =
new DateTime(2019, 5, 1);
213 var options =
new Options_DateTimeOffset { Start = date };
215 .FormatCommandLine(options)
216 .Should().MatchRegex(
"--start\\s\".+\"");
220 public static void UnParsing_instance_with_timespan()
222 var ts =
new TimeSpan(1,2,3);
223 var options =
new Options_TimeSpan { Start = ts };
225 .FormatCommandLine(options)
226 .Should().BeEquivalentTo(
"--start 01:02:03");
230 [InlineData(
false, 0,
"")]
231 [InlineData(
false, 1,
"-v 1")]
232 [InlineData(
false, 2,
"-v 2")]
233 [InlineData(
true, 1,
"")]
234 public static void UnParsing_instance_with_int(
bool skipDefault,
int value,
string expected)
236 var options =
new Option_Int { VerboseLevel = value };
238 .FormatCommandLine(options, x => x.SkipDefault = skipDefault)
239 .Should().BeEquivalentTo(expected);
244 [InlineData(
false, 0,
"-v 0")]
245 [InlineData(
false, 1,
"-v 1")]
246 [InlineData(
false, 2,
"-v 2")]
247 [InlineData(
false,
null,
"")]
248 [InlineData(
true, 1,
"")]
249 public static void UnParsing_instance_with_int_nullable(
bool skipDefault,
int? value,
string expected)
251 var options =
new Option_Int_Nullable { VerboseLevel = value };
253 .FormatCommandLine(options, x => x.SkipDefault = skipDefault)
254 .Should().BeEquivalentTo(expected);
259 [InlineData(
false,
false, 0,
"")]
260 [InlineData(
false,
false, 1,
"-v")]
261 [InlineData(
false,
false, 2,
"-v -v")]
262 [InlineData(
false,
true, 2,
"-vv")]
263 [InlineData(
false,
false, 3,
"-v -v -v")]
264 [InlineData(
false,
true, 3,
"-vvv")]
265 [InlineData(
true,
false, 1,
"")]
266 public static void UnParsing_instance_with_flag_counter(
bool skipDefault,
bool groupSwitches,
int value,
string expected)
268 var options =
new Option_FlagCounter { VerboseLevel = value };
270 .FormatCommandLine(options, x => { x.SkipDefault = skipDefault; x.GroupSwitches = groupSwitches; })
271 .Should().BeEquivalentTo(expected);
275 [InlineData(
Shapes.Circle,
"--shape Circle")]
276 [InlineData(
Shapes.Square,
"--shape Square")]
277 [InlineData(
null,
"")]
278 public static void UnParsing_instance_with_nullable_enum(
Shapes? shape,
string expected)
280 var options =
new Option_Nullable_Enum { Shape = shape };
282 .FormatCommandLine(options)
283 .Should().BeEquivalentTo(expected);
287 [InlineData(
true,
"-v True")]
288 [InlineData(
false,
"-v False")]
289 [InlineData(
null,
"")]
290 public static void UnParsing_instance_with_nullable_bool(
bool? flag,
string expected)
292 var options =
new Option_Nullable_Bool { Verbose = flag };
294 .FormatCommandLine(options)
295 .Should().BeEquivalentTo(expected);
299 [InlineData(
"--shape Circle",
new[] {
"--shape",
"Circle" })]
300 [InlineData(
" --shape Circle ",
new[] {
"--shape",
"Circle" })]
301 [InlineData(
"-a --shape Circle",
new[] {
"-a",
"--shape",
"Circle" })]
302 [InlineData(
"-a --shape Circle -- -x1 -x2",
new[] {
"-a",
"--shape",
"Circle",
"--",
"-x1",
"-x2" })]
303 [InlineData(
"--name \"name with space and quote\" -x1",
new[] {
"--name",
"name with space and quote",
"-x1" })]
304 public static void Split_arguments(
string command,
string[] expectedArgs)
306 var args = command.SplitArgs();
307 args.Should().BeEquivalentTo(expectedArgs);
310 [InlineData(
"--shape Circle",
new[] {
"--shape",
"Circle" })]
311 [InlineData(
" --shape Circle ",
new[] {
"--shape",
"Circle" })]
312 [InlineData(
"-a --shape Circle",
new[] {
"-a",
"--shape",
"Circle" })]
313 [InlineData(
"-a --shape Circle -- -x1 -x2",
new[] {
"-a",
"--shape",
"Circle",
"--",
"-x1",
"-x2" })]
314 [InlineData(
"--name \"name with space and quote\" -x1",
new[] {
"--name",
"\"name with space and quote\"",
"-x1" })]
315 public static void Split_arguments_with_keep_quote(
string command,
string[] expectedArgs)
317 var args = command.SplitArgs(
true);
318 args.Should().BeEquivalentTo(expectedArgs);
321 class Option_Int_Nullable
323 [
Option(
'v', Default = 1)]
324 public int? VerboseLevel {
get;
set; }
328 [
Option(
'v', Default = 1)]
329 public int VerboseLevel {
get;
set; }
331 class Option_FlagCounter
333 [
Option(
'v', Default = 1, FlagCounter=
true)]
334 public int VerboseLevel {
get;
set; }
336 class Option_Nullable_Bool
339 public bool? Verbose {
get;
set; }
341 class Option_Nullable_Enum
344 public Shapes? Shape {
get;
set; }
349 public DateTime Start {
get;
set; }
351 class Options_Date_Nullable
354 public DateTime? Start {
get;
set; }
356 class Options_TimeSpan
359 public TimeSpan Start {
get;
set; }
361 class Options_DateTimeOffset
364 public DateTimeOffset Start {
get;
set; }
367 public static IEnumerable<object[]> UnParseData
372 yield
return new object[] {
new Simple_Options { BoolValue =
true },
"-x" };
373 yield
return new object[] {
new Simple_Options { IntSequence =
new[] { 1, 2, 3 } },
"-i 1 2 3" };
374 yield
return new object[] {
new Simple_Options { StringValue =
"nospaces" },
"--stringvalue nospaces" };
375 yield
return new object[] {
new Simple_Options { StringValue =
" with spaces " },
"--stringvalue \" with spaces \"" };
376 yield
return new object[] {
new Simple_Options { StringValue =
"with\"quote" },
"--stringvalue \"with\\\"quote\"" };
377 yield
return new object[] {
new Simple_Options { StringValue =
"with \"quotes\" spaced" },
"--stringvalue \"with \\\"quotes\\\" spaced\"" };
378 yield
return new object[] {
new Simple_Options { LongValue = 123456789 },
"123456789" };
379 yield
return new object[] {
new Simple_Options { BoolValue =
true, IntSequence =
new[] { 1, 2, 3 }, StringValue =
"nospaces", LongValue = 123456789 },
"-i 1 2 3 --stringvalue nospaces -x 123456789" };
380 yield
return new object[] {
new Simple_Options { BoolValue =
true, IntSequence =
new[] { 1, 2, 3 }, StringValue =
"with \"quotes\" spaced", LongValue = 123456789 },
"-i 1 2 3 --stringvalue \"with \\\"quotes\\\" spaced\" -x 123456789" };
384 public static IEnumerable<object[]> UnParseFileDirectoryData
389 yield
return new object[] {
new Options_With_FileDirectoryInfo { FilePath =
new FileInfo(
@"C:\my path\with spaces\file with spaces.txt"), DirectoryPath =
new DirectoryInfo(
@"C:\my path\with spaces\"), StringPath =
@"C:\my path\with spaces\file with spaces.txt" },
@"--directoryPath ""C:\my path\with spaces\"" --filePath ""C:\my path\with spaces\file with spaces.txt"" --stringPath ""C:\my path\with spaces\file with spaces.txt""" };
394 public static IEnumerable<object[]> UnParseDataVerbs
398 yield
return new object[] {
new Add_Verb(),
"add" };
399 yield
return new object[] {
new Add_Verb { Patch =
true, FileName =
"mysource.cs" },
"add --patch mysource.cs" };
400 yield
return new object[] {
new Add_Verb { Force =
true, FileName =
"mysource.fs" },
"add --force mysource.fs" };
404 public static IEnumerable<object[]> UnParseDataImmutable
408 yield
return new object[] {
new Immutable_Simple_Options(
"", Enumerable.Empty<
int>(),
default(
bool),
default(
long)),
"" };
410 yield
return new object[] {
new Immutable_Simple_Options(
"",
new[] { 1, 2, 3 },
default(
bool),
default(
long)),
"-i 1 2 3" };
411 yield
return new object[] {
new Immutable_Simple_Options(
"nospaces", Enumerable.Empty<
int>(),
default(
bool),
default(
long)),
"--stringvalue nospaces" };
412 yield
return new object[] {
new Immutable_Simple_Options(
" with spaces ", Enumerable.Empty<
int>(),
default(
bool),
default(
long)),
"--stringvalue \" with spaces \"" };
413 yield
return new object[] {
new Immutable_Simple_Options(
"with\"quote", Enumerable.Empty<
int>(),
default(
bool),
default(
long)),
"--stringvalue \"with\\\"quote\"" };
414 yield
return new object[] {
new Immutable_Simple_Options(
"with \"quotes\" spaced", Enumerable.Empty<
int>(),
default(
bool),
default(
long)),
"--stringvalue \"with \\\"quotes\\\" spaced\"" };
415 yield
return new object[] {
new Immutable_Simple_Options(
"", Enumerable.Empty<
int>(),
default(
bool), 123456789),
"123456789" };
416 yield
return new object[] {
new Immutable_Simple_Options(
"nospaces",
new[] { 1, 2, 3 },
true, 123456789),
"-i 1 2 3 --stringvalue nospaces -x 123456789" };
417 yield
return new object[] {
new Immutable_Simple_Options(
"with \"quotes\" spaced",
new[] { 1, 2, 3 },
true, 123456789),
"-i 1 2 3 --stringvalue \"with \\\"quotes\\\" spaced\" -x 123456789" };
421 public static IEnumerable<object[]> UnParseDataHidden
425 yield
return new object[] {
new Hidden_Option { HiddenOption =
"hidden" },
true,
"--hiddenOption hidden" };
426 yield
return new object[] {
new Hidden_Option { HiddenOption =
"hidden" },
false,
"" };
430 public static IEnumerable<object[]> UnParseDataFSharpOption
435 yield
return new object[] {
new Options_With_FSharpOption { FileName = FSharpOption<string>.Some(
"myfile.bin") },
"--filename myfile.bin" };
437 yield
return new object[] {
new Options_With_FSharpOption { FileName = FSharpOption<string>.Some(
"myfile.bin"), Offset = FSharpOption<int>.Some(123456789) },
"--filename myfile.bin 123456789" };
Provides methods to parse command line arguments.