BadScript 2
Loading...
Searching...
No Matches
UnParserExtensionsTests.cs
Go to the documentation of this file.
1// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information.
2
3using System;
4using System.Collections.Generic;
5using System.IO;
6using System.Linq;
7using Xunit;
8using FluentAssertions;
10#if !SKIP_FSHARP
11using Microsoft.FSharp.Core;
12#endif
13
15{
16 public class UnParserExtensionsTests
17 {
18 [Theory]
19 [MemberData(nameof(UnParseData))]
20 public static void UnParsing_instance_returns_command_line(Simple_Options options, string result)
21 {
22 new Parser()
23 .FormatCommandLine(options)
24 .Should().BeEquivalentTo(result);
25 }
26
27 [Theory]
28 [MemberData(nameof(UnParseData))]
29 public static void UnParsing_instance_with_splitArgs_returns_same_option_class(Simple_Options options, string result)
30 {
31 new Parser()
32 .FormatCommandLineArgs(options)
33 .Should().BeEquivalentTo(result.SplitArgs());
34
35 }
36
37 [Theory]
38 [MemberData(nameof(UnParseFileDirectoryData))]
39 public static void UnParsing_instance_returns_command_line_for_file_directory_paths(Options_With_FileDirectoryInfo options, string result)
40 {
41 new Parser()
42 .FormatCommandLine(options)
43 .Should().BeEquivalentTo(result);
44 }
45
46 [Theory]
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)
49 {
50 new Parser()
51 .FormatCommandLineArgs(options)
52 .Should().BeEquivalentTo(result.SplitArgs());
53 }
54 [Theory]
55 [MemberData(nameof(UnParseDataVerbs))]
56 public static void UnParsing_instance_returns_command_line_for_verbs(Add_Verb verb, string result)
57 {
58 new Parser()
59 .FormatCommandLine(verb)
60 .Should().BeEquivalentTo(result);
61 }
62
63 [Theory]
64 [MemberData(nameof(UnParseDataVerbs))]
65 public static void UnParsing_instance_to_splitArgs_returns_command_line_for_verbs(Add_Verb verb, string result)
66 {
67 new Parser()
68 .FormatCommandLineArgs(verb)
69 .Should().BeEquivalentTo(result.SplitArgs());
70 }
71
72 [Theory]
73 [MemberData(nameof(UnParseDataImmutable))]
74 public static void UnParsing_immutable_instance_returns_command_line(Immutable_Simple_Options options, string result)
75 {
76 new Parser()
77 .FormatCommandLine(options)
78 .Should().BeEquivalentTo(result);
79 }
80
81 [Theory]
82 [MemberData(nameof(UnParseDataHidden))]
83 public static void Unparsing_hidden_option_returns_command_line(Hidden_Option options, bool showHidden, string result)
84 {
85 new Parser()
86 .FormatCommandLine(options, config => config.ShowHidden = showHidden)
87 .Should().BeEquivalentTo(result);
88 }
89
90#if !SKIP_FSHARP
91 [Theory]
92 [MemberData(nameof(UnParseDataFSharpOption))]
93 public static void UnParsing_instance_with_fsharp_option_returns_command_line(Options_With_FSharpOption options, string result)
94 {
95 new Parser()
96 .FormatCommandLine(options)
97 .Should().BeEquivalentTo(result);
98 }
99#endif
100
101 [Fact]
102 public static void UnParsing_instance_with_group_switches_returns_command_line_with_switches_grouped()
103 {
104 var options = new Options_With_Switches { InputFile = "input.bin", HumanReadable = true, IgnoreWarnings = true };
105 new Parser()
106 .FormatCommandLine(options, config => config.GroupSwitches = true)
107 .Should().BeEquivalentTo("-hi --input input.bin");
108 }
109
110 [Fact]
111 public static void UnParsing_instance_with_equal_token_returns_command_line_with_long_option_using_equal_sign()
112 {
113 var options = new Simple_Options { BoolValue = true, IntSequence = new[] { 1, 2, 3 }, StringValue = "nospaces", LongValue = 123456789 };
114 new Parser()
115 .FormatCommandLine(options, config => config.UseEqualToken = true)
116 .Should().BeEquivalentTo("-i 1 2 3 --stringvalue=nospaces -x 123456789");
117 }
118
119 [Fact]
120 public static void UnParsing_instance_with_dash_in_value_and_dashdash_enabled_returns_command_line_with_value_prefixed_with_dash_dash()
121 {
122 var options = new Simple_Options_With_Values { StringSequence = new List<string> { "-something", "with", "dash" } };
123 new Parser((setting) => setting.EnableDashDash = true)
124 .FormatCommandLine(options)
125 .Should().BeEquivalentTo("-- -something with dash");
126 }
127
128 [Fact]
129 public static void UnParsing_instance_with_no_values_and_dashdash_enabled_returns_command_line_without_dash_dash()
130 {
131 var options = new Simple_Options_With_Values();
132 new Parser((setting) => setting.EnableDashDash = true)
133 .FormatCommandLine(options)
134 .Should().BeEquivalentTo("");
135 }
136
137 [Fact]
138 public static void UnParsing_instance_with_dash_in_value_and_dashdash_disabled_returns_command_line_with_value()
139 {
140 var options = new Simple_Options_With_Values { StringSequence = new List<string> { "-something", "with", "dash" } };
141 new Parser()
142 .FormatCommandLine(options)
143 .Should().BeEquivalentTo("-something with dash");
144 }
145
146 #region Issue 579
147 [Fact]
148 public static void UnParsing_instance_with_TimeSpan_returns_the_value_unquoted_in_command_line()
149 {
150 var options = new Options_With_TimeSpan { Duration = TimeSpan.FromMinutes(1) };
151 new Parser()
152 .FormatCommandLine(options)
153 .Should().Be("--duration 00:01:00");
154 }
155 #endregion
156
157 #region PR 550
158
159 [Fact]
160 public static void UnParsing_instance_with_default_values_when_skip_default_is_false()
161 {
162 var options = new Options_With_Defaults { P2 = "xyz", P1 = 99, P3 = 88, P4 = Shapes.Square };
163 new Parser()
164 .FormatCommandLine(options)
165 .Should().BeEquivalentTo("--p1 99 --p2 xyz --p3 88 --p4 Square");
166 }
167
168 [Theory]
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)
172 {
173 var options = new Options_With_Defaults { P2 = "xyz", P1 = 99, P3 = 88, P4 = Shapes.Square };
174 new Parser()
175 .FormatCommandLine(options, x => x.SkipDefault = skipDefault)
176 .Should().BeEquivalentTo(expected);
177 }
178
179 [Theory]
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)
183 {
184 var options = new Nuulable_Options_With_Defaults { P2 = "xyz", P1 = 99, P3 = 88, P4 = Shapes.Square };
185 new Parser()
186 .FormatCommandLine(options, x => x.SkipDefault = skipDefault)
187 .Should().BeEquivalentTo(expected);
188 }
189 [Fact]
190 public static void UnParsing_instance_with_datetime()
191 {
192 var date = new DateTime(2019, 5, 1);
193 var options = new Options_Date { Start = date };
194 var result = new Parser()
195 .FormatCommandLine(options)
196 .Should().MatchRegex("--start\\s\".+\"");
197 }
198
199 [Fact]
200 public static void UnParsing_instance_with_datetime_nullable()
201 {
202 var date = new DateTime(2019, 5, 1);
203 var options = new Options_Date_Nullable { Start = date };
204 var result = new Parser()
205 .FormatCommandLine(options)
206 .Should().MatchRegex("--start\\s\".+\"");
207 }
208
209 [Fact]
210 public static void UnParsing_instance_with_datetime_offset()
211 {
212 DateTimeOffset date = new DateTime(2019, 5, 1);
213 var options = new Options_DateTimeOffset { Start = date };
214 var result = new Parser()
215 .FormatCommandLine(options)
216 .Should().MatchRegex("--start\\s\".+\"");
217 }
218
219 [Fact]
220 public static void UnParsing_instance_with_timespan()
221 {
222 var ts = new TimeSpan(1,2,3);
223 var options = new Options_TimeSpan { Start = ts };
224 var result = new Parser()
225 .FormatCommandLine(options)
226 .Should().BeEquivalentTo("--start 01:02:03"); //changed for issue 579
227 }
228
229 [Theory]
230 [InlineData(false, 0, "")] //default behaviour based on type
231 [InlineData(false, 1, "-v 1")] //default skip=false
232 [InlineData(false, 2, "-v 2")]
233 [InlineData(true, 1, "")] //default skip=true
234 public static void UnParsing_instance_with_int(bool skipDefault, int value, string expected)
235 {
236 var options = new Option_Int { VerboseLevel = value };
237 var result = new Parser()
238 .FormatCommandLine(options, x => x.SkipDefault = skipDefault)
239 .Should().BeEquivalentTo(expected);
240
241 }
242
243 [Theory]
244 [InlineData(false, 0, "-v 0")]
245 [InlineData(false, 1, "-v 1")] //default
246 [InlineData(false, 2, "-v 2")]
247 [InlineData(false, null, "")]
248 [InlineData(true, 1, "")] //default
249 public static void UnParsing_instance_with_int_nullable(bool skipDefault, int? value, string expected)
250 {
251 var options = new Option_Int_Nullable { VerboseLevel = value };
252 var result = new Parser()
253 .FormatCommandLine(options, x => x.SkipDefault = skipDefault)
254 .Should().BeEquivalentTo(expected);
255
256 }
257
258 [Theory]
259 [InlineData(false, false, 0, "")]
260 [InlineData(false, false, 1, "-v")] // default but not skipped
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, "")] // default, skipped
266 public static void UnParsing_instance_with_flag_counter(bool skipDefault, bool groupSwitches, int value, string expected)
267 {
268 var options = new Option_FlagCounter { VerboseLevel = value };
269 var result = new Parser()
270 .FormatCommandLine(options, x => { x.SkipDefault = skipDefault; x.GroupSwitches = groupSwitches; })
271 .Should().BeEquivalentTo(expected);
272 }
273
274 [Theory]
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)
279 {
280 var options = new Option_Nullable_Enum { Shape = shape };
281 var result = new Parser()
282 .FormatCommandLine(options)
283 .Should().BeEquivalentTo(expected);
284 }
285
286 [Theory]
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)
291 {
292 var options = new Option_Nullable_Bool { Verbose = flag };
293 var result = new Parser()
294 .FormatCommandLine(options)
295 .Should().BeEquivalentTo(expected);
296 }
297 #region SplitArgs
298 [Theory]
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)
305 {
306 var args = command.SplitArgs();
307 args.Should().BeEquivalentTo(expectedArgs);
308 }
309 [Theory]
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)
316 {
317 var args = command.SplitArgs(true);
318 args.Should().BeEquivalentTo(expectedArgs);
319 }
320 #endregion
321 class Option_Int_Nullable
322 {
323 [Option('v', Default = 1)]
324 public int? VerboseLevel { get; set; }
325 }
326 class Option_Int
327 {
328 [Option('v', Default = 1)]
329 public int VerboseLevel { get; set; }
330 }
331 class Option_FlagCounter
332 {
333 [Option('v', Default = 1, FlagCounter=true)]
334 public int VerboseLevel { get; set; }
335 }
336 class Option_Nullable_Bool
337 {
338 [Option('v')]
339 public bool? Verbose { get; set; }
340 }
341 class Option_Nullable_Enum
342 {
343 [Option]
344 public Shapes? Shape { get; set; }
345 }
346 class Options_Date
347 {
348 [Option]
349 public DateTime Start { get; set; }
350 }
351 class Options_Date_Nullable
352 {
353 [Option]
354 public DateTime? Start { get; set; }
355 }
356 class Options_TimeSpan
357 {
358 [Option]
359 public TimeSpan Start { get; set; }
360 }
361 class Options_DateTimeOffset
362 {
363 [Option]
364 public DateTimeOffset Start { get; set; }
365 }
366 #endregion
367 public static IEnumerable<object[]> UnParseData
368 {
369 get
370 {
371 yield return new object[] { new Simple_Options(), "" };
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" };
381 }
382 }
383
384 public static IEnumerable<object[]> UnParseFileDirectoryData
385 {
386 get
387 {
388 yield return new object[] { new Options_With_FileDirectoryInfo(), "" };
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""" };
390 }
391 }
392
393
394 public static IEnumerable<object[]> UnParseDataVerbs
395 {
396 get
397 {
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" };
401 }
402 }
403
404 public static IEnumerable<object[]> UnParseDataImmutable
405 {
406 get
407 {
408 yield return new object[] { new Immutable_Simple_Options("", Enumerable.Empty<int>(), default(bool), default(long)), "" };
409 yield return new object[] { new Immutable_Simple_Options("", Enumerable.Empty<int>(), true, default(long)), "-x" };
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" };
418 }
419 }
420
421 public static IEnumerable<object[]> UnParseDataHidden
422 {
423 get
424 {
425 yield return new object[] { new Hidden_Option { HiddenOption = "hidden" }, true, "--hiddenOption hidden" };
426 yield return new object[] { new Hidden_Option { HiddenOption = "hidden" }, false, "" };
427 }
428 }
429#if !SKIP_FSHARP
430 public static IEnumerable<object[]> UnParseDataFSharpOption
431 {
432 get
433 {
434 yield return new object[] { new Options_With_FSharpOption(), "" };
435 yield return new object[] { new Options_With_FSharpOption { FileName = FSharpOption<string>.Some("myfile.bin") }, "--filename myfile.bin" };
436 yield return new object[] { new Options_With_FSharpOption { Offset = FSharpOption<int>.Some(123456789) }, "123456789" };
437 yield return new object[] { new Options_With_FSharpOption { FileName = FSharpOption<string>.Some("myfile.bin"), Offset = FSharpOption<int>.Some(123456789) }, "--filename myfile.bin 123456789" };
438 }
439 }
440#endif
441 }
442}
Provides methods to parse command line arguments.
Definition Parser.cs:21