11// Copyright (c) .NET Foundation and contributors. All rights reserved.
22// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33
4+ using System . CommandLine . Parsing ;
5+ using System . CommandLine . Tests . Utility ;
46using FluentAssertions ;
57using System . Linq ;
68using Xunit ;
9+ using Xunit . Abstractions ;
710
811namespace System . CommandLine . Tests
912{
@@ -13,6 +16,13 @@ public class MultipleArgumentsPerToken
1316 {
1417 public class Allowed
1518 {
19+ private readonly ITestOutputHelper _output ;
20+
21+ public Allowed ( ITestOutputHelper output )
22+ {
23+ _output = output ;
24+ }
25+
1626 [ Fact ]
1727 public void When_option_is_not_respecified_but_limit_is_not_reached_then_the_following_token_is_used_as_value ( )
1828 {
@@ -86,6 +96,77 @@ public void When_option_is_not_respecified_and_limit_is_reached_then_the_followi
8696 . Should ( )
8797 . BeEquivalentTo ( "some-arg" ) ;
8898 }
99+
100+ [ Theory ]
101+ [ InlineData ( "--option 1 --option 2" ) ]
102+ [ InlineData ( "xyz --option 1 --option 2" ) ]
103+ [ InlineData ( "--option 1 xyz --option 2" ) ]
104+ [ InlineData ( "--option 1 --option 2 xyz" ) ]
105+ public void When_max_arity_is_1_then_subsequent_option_args_overwrite_previous_ones ( string commandLine )
106+ {
107+ var option = new Option < string > ( "--option" )
108+ {
109+ AllowMultipleArgumentsPerToken = true
110+ } ;
111+ var command = new Command ( "the-command" )
112+ {
113+ option ,
114+ new Argument < string > ( )
115+ } ;
116+
117+ var result = command . Parse ( commandLine ) ;
118+
119+ var value = result . ValueForOption ( option ) ;
120+
121+ value . Should ( ) . Be ( "2" ) ;
122+ }
123+
124+ [ Fact ]
125+ public void All_consumed_tokens_are_present_in_option_result ( )
126+ {
127+ var option = new Option < int > ( "-x" )
128+ {
129+ AllowMultipleArgumentsPerToken = true
130+ } ;
131+
132+ var result = option . Parse ( "-x 1 -x 2 -x 3 -x 4" ) ;
133+
134+ _output . WriteLine ( result . Diagram ( ) ) ;
135+
136+ var optionResult = result . FindResultFor ( option ) ;
137+
138+ optionResult
139+ . Tokens
140+ . Select ( t => t . Value )
141+ . Should ( ) . BeEquivalentSequenceTo ( "1" , "2" , "3" , "4" ) ;
142+ }
143+
144+ [ Fact ]
145+ public void Multiple_option_arguments_that_match_single_arity_option_aliases_are_parsed_correctly ( )
146+ {
147+ var optionX = new Option < string > ( "-x" )
148+ {
149+ AllowMultipleArgumentsPerToken = true
150+ } ;
151+ var optionY = new Option < string > ( "-y" )
152+ {
153+ AllowMultipleArgumentsPerToken = true
154+ } ;
155+
156+ var command = new RootCommand
157+ {
158+ optionX ,
159+ optionY
160+ } ;
161+
162+ var result = command . Parse ( "-x -x -x -y -y -x -y -y -y -x -x -y" ) ;
163+
164+ _output . WriteLine ( result . Diagram ( ) ) ;
165+
166+ result . Errors . Should ( ) . BeEmpty ( ) ;
167+ result . ValueForOption ( optionY ) . Should ( ) . Be ( "-x" ) ;
168+ result . ValueForOption ( optionX ) . Should ( ) . Be ( "-y" ) ;
169+ }
89170 }
90171
91172 public class Disallowed
@@ -101,39 +182,32 @@ public void Single_option_arg_is_matched()
101182 var value = result . ValueForOption ( option ) ;
102183
103184 value . Should ( ) . BeEquivalentTo ( new [ ] { "1" } ) ;
104- result . UnmatchedTokens . Should ( ) . BeEquivalentTo ( new [ ] { "2" } ) ;
105185 }
106186
107187 [ Fact ]
108- public void When_max_arity_is_greater_than_1_then_multiple_option_args_are_matched ( )
188+ public void Subsequent_matched_arguments_result_in_errors ( )
109189 {
110190 var option = new Option < string [ ] > ( "--option" ) { AllowMultipleArgumentsPerToken = false } ;
111191 var command = new Command ( "the-command" ) { option } ;
112192
113- var result = command . Parse ( "--option 1 --option 2" ) ;
114-
115- var value = result . ValueForOption ( option ) ;
193+ var result = command . Parse ( "--option 1 2" ) ;
116194
117- value . Should ( ) . BeEquivalentTo ( new [ ] { "1" , "2" } ) ;
195+ result . UnmatchedTokens . Should ( ) . BeEquivalentTo ( new [ ] { "2" } ) ;
196+ result . Errors . Should ( ) . Contain ( e => e . Message == Resources . Instance . UnrecognizedCommandOrArgument ( "2" ) ) ;
118197 }
119198
120- [ Theory ]
121- [ InlineData ( "--option 1 --option 2" ) ]
122- [ InlineData ( "xyz --option 1 --option 2" ) ]
123- [ InlineData ( "--option 1 xyz --option 2" ) ]
124- public void When_max_arity_is_1_then_subsequent_option_args_overwrite_its_value ( string commandLine )
199+ [ Fact ]
200+ public void When_max_arity_is_greater_than_1_then_multiple_option_args_are_matched ( )
125201 {
126- var option = new Option < string > ( "--option" ) { AllowMultipleArgumentsPerToken = false } ;
127- var command = new Command ( "the-command" ) {
128- option ,
129- new Argument < string > ( )
130- } ;
202+ var option = new Option < string [ ] > ( "--option" ) { AllowMultipleArgumentsPerToken = false } ;
203+ var command = new Command ( "the-command" ) { option } ;
131204
132- var result = command . Parse ( commandLine ) ;
205+ var result = command . Parse ( "--option 1 --option 2" ) ;
133206
134207 var value = result . ValueForOption ( option ) ;
135208
136- value . Should ( ) . Be ( "2" ) ;
209+ value . Should ( ) . BeEquivalentTo ( new [ ] { "1" , "2" } ) ;
210+ result . Errors . Should ( ) . BeEmpty ( ) ;
137211 }
138212 }
139213 }
0 commit comments