8000 updates · dotnet/command-line-api@c642816 · GitHub
[go: up one dir, main page]

Skip to content

Commit c642816

Browse files
committed
updates
1 parent 09edaf3 commit c642816

10 files changed

+944
-400
lines changed
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
// // Copyright (c) .NET Foundation and contributors. All rights reserved.
2+
// // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System.CommandLine.Binding;
5+
using System.CommandLine.Invocation;
6+
using System.CommandLine.IO;
7+
using System.IO;
8+
using System.Threading.Tasks;
9+
using FluentAssertions;
10+
using Xunit;
11+
12+
namespace System.CommandLine.Tests.Binding
13+
{
14+
public partial class ModelBindingCommandHandlerTests
15+
{
16+
public class BindingByName
17+
{
18+
[Theory]
19+
[InlineData(typeof(bool), "--value", true)]
20+
[InlineData(typeof(bool), "--value false", false)]
21+
[InlineData(typeof(string), "--value hello", "hello")]
22+
[InlineData(typeof(int), "--value 123", 123)]
23+
public async Task Option_arguments_are_bound_by_name_to_method_parameters(
24+
Type type,
25+
string commandLine,
26+
object expectedValue)
27+
{
28+
var targetType = typeof(ClassWithMethodHavingParameter<>).MakeGenericType(type);
29+
30+
var handlerMethod = targetType.GetMethod(nameof(ClassWithMethodHavingParameter<int>.HandleAsync));
31+
32+
var handler = HandlerDescriptor.FromMethodInfo(handlerMethod)
33+
.GetCommandHandler();
34+
35+
var command = new Command("the-command")
36+
{
37+
new Option("--value", argumentType: type)
38+
};
39+
40+
var console = new TestConsole();
41+
42+
await handler.InvokeAsync(
43+
new InvocationContext(command.Parse(commandLine), console));
44+
45+
console.Out.ToString().Should().Be(expectedValue.ToString());
46+
}
47+
48+
[Theory]
49+
[InlineData(typeof(bool), "--value", true)]
50+
[InlineData(typeof(bool), "--value false", false)]
51+
[InlineData(typeof(string), "--value hello", "hello")]
52+
[InlineData(typeof(int), "--value 123", 123)]
53+
public async Task Option_arguments_are_bound_by_name_to_the_properties_of_method_parameters(
54+
Type type,
55+
string commandLine,
56+
object expectedValue)
57+
{
58+
var complexParameterType = typeof(ClassWithSetter<>).MakeGenericType(type);
59+
60+
var handlerType = typeof(ClassWithMethodHavingParameter<>).MakeGenericType(complexParameterType);
61+
62+
var handlerMethod = handlerType.GetMethod("HandleAsync");
63+
64+
var handler = HandlerDescriptor.FromMethodInfo(handlerMethod)
65+
.GetCommandHandler();
66+
67+
var command = new Command("the-command")
68+
{
69+
new Option("--value", argumentType: type)
70+
};
71+
72+
var console = new TestConsole();
73+
74+
await handler.InvokeAsync(
75+
new InvocationContext(command.Parse(commandLine), console));
76+
77+
console.Out.ToString().Should().Be($"ClassWithSetter<{type.Name}>: {expectedValue}");
78+
}
79+
80+
[Theory]
81+
[InlineData(typeof(bool), "--value", true)]
82+
[InlineData(typeof(bool), "--value false", false)]
83+
[InlineData(typeof(string), "--value hello", "hello")]
84+
[InlineData(typeof(int), "--value 123", 123)]
85+
public async Task Option_arguments_are_bound_by_name_to_the_constructor_parameters_of_method_parameters(
86+
Type type,
87+
string commandLine,
88+
object expectedValue)
89+
{
90+
var complexParameterType = typeof(ClassWithCtorParameter<>).MakeGenericType(type);
91+
92+
var handlerType = typeof(ClassWithMethodHavingParameter<>).MakeGenericType(complexParameterType);
93+
94+
var handlerMethod = handlerType.GetMethod("HandleAsync");
95+
96+
var handler = HandlerDescriptor.FromMethodInfo(handlerMethod)
97+
.GetCommandHandler();
98+
99+
var command = new Command("the-command")
100+
{
101+
new Option("--value", argumentType: type)
102+
};
103+
104+
var console = new TestConsole();
105+
106+
await handler.InvokeAsync(
107+
new InvocationContext(command.Parse(commandLine), console));
108+
109+
console.Out.ToString().Should().Be($"ClassWithCtorParameter<{type.Name}>: {expectedValue}");
110+
}
111+
112+
[Theory]
113+
[InlineData(typeof(string), "hello", "hello")]
114+
[InlineData(typeof(int), "123", 123)]
115+
public async Task Command_arguments_are_bound_by_name_to_handler_method_parameters(
116+
Type type,
117+
string commandLine,
118+
object expectedValue)
119+
{
120+
var targetType = typeof(ClassWithMethodHavingParameter<>).MakeGenericType(type);
121+
122+
var handlerMethod = targetType.GetMethod(nameof(ClassWithMethodHavingParameter<int>.HandleAsync));
123+
124+
var handler = HandlerDescriptor.FromMethodInfo(handlerMethod)
125+
.GetCommandHandler();
126+
127+
var command = new Command("the-command")
128+
{
129+
new Argument
130+
{
131+
Name = "value",
132+
ArgumentType = type
133+
}
134+
};
135+
136+
var console = new TestConsole();
137+
138+
await handler.InvokeAsync(
139+
new InvocationContext(command.Parse(commandLine), console));
140+
141+
console.Out.ToString().Should().Be(expectedValue.ToString());
142+
}
143+
144+
[Fact]
145+
public void When_argument_type_is_more_specific_than_parameter_type_then_parameter_is_bound_correctly()
146+
{
147+
FileSystemInfo received = null;
148+
149+
var root = new RootCommand
150+
{
151+
new Option<DirectoryInfo>("-f")
152+
};
153+
root.Handler = CommandHandler.Create<FileSystemInfo>(f => received = f);
154+
var path = $"{Directory.GetCurrentDirectory()}{Path.DirectorySeparatorChar}";
155+
156+
root.Invoke($"-f {path}");
157+
158+
received.Should()
159+
.BeOfType<DirectoryInfo>()
160+
.Which
161+
.FullName
162+
.Should()
163+
.Be(path);
164+
}
165+
}
166+
}
167+
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System.Collections.Generic;
5+
using System.CommandLine.Invocation;
6+
using System.Linq;
7+
using FluentAssertions;
8+
using System.Threading.Tasks;
9+
using Xunit;
10+
11+
namespace System.CommandLine.Tests.Binding
12+
{
13+
public partial class ModelBindingCommandHandlerTests
14+
{
15+
public class BindingBySymbol
16+
{
17+
[Theory]
18+
[InlineData(1)]
19+
[InlineData(2)]
20+
[InlineData(3)]
21+
[InlineData(4)]
22+
[InlineData(5)]
23+
[InlineData(6)]
24+
[InlineData(7)]
25+
[InlineData(8)]
26+
[InlineData(9)]
27+
[InlineData(10)]
28+
[InlineData(11)]
29+
[InlineData(12)]
30+
[InlineData(13)]
31+
[InlineData(14)]
32+
[InlineData(15)]
33+
[InlineData(16)]
34+
public void Binding_is_correct_for_overload_having_arity_(int arity)
35+
{
36+
var command = new RootCommand();
37+
var commandLine = "";
38+
39+
for (var i = 1; i <= arity; i++)
40+
{
41+
command.AddArgument(new Argument<int>($"i{i}"));
42+
43+
commandLine += $" {i}";
44+
}
45+
46+
var receivedValues = new List<int>();
47+
Delegate handlerFunc = arity switch
48+
{
49+
1 => new Func<int, Task>(
50+
i1 =>
51+
Received(i1)),
52+
2 => new Func<int, int, Task>(
53+
(i1, i2) =>
54+
Received(i1, i2)),
55+
3 => new Func<int, int, int, Task>(
56+
(i1, i2, i3) =>
57+
Received(i1, i2, i3)),
58+
4 => new Func<int, int, int, int, Task>(
59+
(i1, i2, i3, i4) =>
60+
Received(i1, i2, i3, i4)),
61+
5 => new Func<int, int, int, int, int, Task>(
62+
(i1, i2, i3, i4, i5) =>
63+
Received(i1, i2, i3, i4, i5)),
64+
6 => new Func<int, int, int, int, int, int, Task>(
65+
(i1, i2, i3, i4, i5, i6) =>
66+
Received(i1, i2, i3, i4, i5, i6)),
67+
7 => new Func<int, int, int, int, int, int, int, Task>(
68+
(i1, i2, i3, i4, i5, i6, i7) =>
69+
Received(i1, i2, i3, i4, i5, i6, i7)),
70+
8 => new Func<int, int, int, int, int, int, int, int, Task>(
71+
(i1, i2, i3, i4, i5, i6, i7, i8) =>
72+
Received(i1, i2, i3, i4, i5, i6, i7, i8)),
73+
9 => new Func<int, int, int, int, int, int, int, int, int, Task>(
74+
(i1, i2, i3, i4, i5, i6, i7, i8, i9) =>
75+
Received(i1, i2, i3, i4, i5, i6, i7, i8, i9)),
76+
10 => new Func<int, int, int, int, int, int, int, int, int, int, Task>(
77+
(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10) =>
78+
Received(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10)),
79+
11 => new Func<int, int, int, int, int, int, int, int, int, int, int, Task>(
80+
(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11) =>
81+
Received(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11)),
82+
12 => new Func<int, int, int, int, int, int, int, int, int, int, int, int, Task>(
83+
(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12) =>
84+
Received(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12)),
85+
13 => new Func<int, int, int, int, int, int, int, int, int, int, int, int, int, Task>(
86+
(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13) =>
87+
Received(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13)),
88+
14 => new Func<int, int, int, int, int, int, int, int, int, int, int, int, int, int, Task>(
89+
(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14) =>
90+
Received(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14)),
91+
15 => new Func<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, Task>(
92+
(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15) =>
93+
Received(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15)),
94+
16 => new Func<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, Task>(
95+
96+
(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16) =>
97+
Received(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16)),
98+
99+
_ => throw new ArgumentOutOfRangeException()
100+
};
101+
102+
// build up the method invocation
103+
var genericMethodDef = typeof(CommandHandler)
104+
.GetMethods()
105+
.Where(m => m.Name == nameof(CommandHandler.Create))
106+
.Where(m => m.IsGenericMethod /* symbols + handler Func */)
107+
.Single(m => m.GetParameters().Length == arity + 1);
108+
109+
var genericParameterTypes = Enumerable.Range(1, arity)
110+
.Select(_ => typeof(int))
111+
.ToArray();
112+
113+
var createMethod = genericMethodDef.MakeGenericMethod(genericParameterTypes);
114+
115+
var parameters = new List<object>();
116+
117+
parameters.AddRange(command.Arguments);
118+
parameters.Add(handlerFunc);
119+
120+
var handler = (ICommandHandler) createMethod.Invoke(null, parameters.ToArray());
121+
122+
command.Handler = handler;
123+
124+
command.Invoke(commandLine);
125+
126+
receivedValues.Should().BeEquivalentTo(
127+
Enumerable.Range(1, arity),
128+
config => config.WithStrictOrdering());
129+
130+
Task Received(params int[] values)
131+
{
132+
receivedValues.AddRange(values);
133+
return Task.CompletedTask;
134+
}
135+
}
136+
}
137+
}
138+
}

0 commit comments

Comments
 (0)
0