-
Notifications
You must be signed in to change notification settings - Fork 10.6k
Expand file tree
/
Copy pathRequestDelegateCreationTests.QueryParameters.cs
More file actions
229 lines (196 loc) · 9.24 KB
/
RequestDelegateCreationTests.QueryParameters.cs
File metadata and controls
229 lines (196 loc) · 9.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Text;
using Microsoft.AspNetCore.Http.RequestDelegateGenerator.StaticRouteHandlerModel;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNetCore.Http.Generators.Tests;
public abstract partial class RequestDelegateCreationTests
{
public static IEnumerable<object[]> QueryParamOptionalityData
{
get
{
return new List<object[]>
{
new object[] { @"(string name) => $""Hello {name}!""", "name", null, true, null},
new object[] { @"(string name) => $""Hello {name}!""", "name", "TestName", false, "Hello TestName!" },
new object[] { @"(string name = ""DefaultName"") => $""Hello {name}!""", "name", null, false, "Hello DefaultName!" },
new object[] { @"(string name = ""DefaultName"") => $""Hello {name}!""", "name", "TestName", false, "Hello TestName!" },
new object[] { @"(string? name) => $""Hello {name}!""", "name", null, false, "Hello !" },
new object[] { @"(string? name) => $""Hello {name}!""", "name", "TestName", false, "Hello TestName!"},
new object[] { @"(int age) => $""Age: {age}""", "age", null, true, null},
new object[] { @"(int age) => $""Age: {age}""", "age", "42", false, "Age: 42" },
new object[] { @"(int age = 12) => $""Age: {age}""", "age", null, false, "Age: 12" },
new object[] { @"(int age = 12) => $""Age: {age}""", "age", "42", false, "Age: 42" },
new object[] { @"(int? age) => $""Age: {age}""", "age", null, false, "Age: " },
new object[] { @"(int? age) => $""Age: {age}""", "age", "42", false, "Age: 42"},
};
}
}
[Theory]
[MemberData(nameof(QueryParamOptionalityData))]
public async Task RequestDelegateHandlesQueryParamOptionality(string innerSource, string paramName, string queryParam, bool isInvalid, string expectedResponse)
{
var source = $"""
string handler{innerSource};
app.MapGet("/", handler);
""";
var (_, compilation) = await RunGeneratorAsync(source);
var serviceProvider = CreateServiceProvider();
var endpoint = GetEndpointFromCompilation(compilation, serviceProvider: serviceProvider);
var httpContext = CreateHttpContext();
var responseBodyStream = new MemoryStream();
httpContext.Response.Body = responseBodyStream;
if (queryParam is not null)
{
httpContext.Request.Query = new QueryCollection(new Dictionary<string, StringValues>
{
[paramName] = queryParam
});
}
await endpoint.RequestDelegate(httpContext);
var logs = TestSink.Writes.ToArray();
if (isInvalid)
{
Assert.Equal(400, httpContext.Response.StatusCode);
var log = Assert.Single(logs);
Assert.Equal(LogLevel.Debug, log.LogLevel);
Assert.Equal(new EventId(4, "RequiredParameterNotProvided"), log.EventId);
var expectedType = paramName == "age" ? "int age" : $"string name";
var parameterSource = IsGeneratorEnabled ? "route or query string" : "query string";
Assert.Equal($@"Required parameter ""{expectedType}"" was not provided from {parameterSource}.", log.Message);
}
else
{
Assert.Equal(200, httpContext.Response.StatusCode);
Assert.False(httpContext.RequestAborted.IsCancellationRequested);
var decodedResponseBody = Encoding.UTF8.GetString(responseBodyStream.ToArray());
Assert.Equal(expectedResponse, decodedResponseBody);
}
}
[Fact]
public async Task MapAction_SingleNullableStringParam_WithEmptyQueryStringValueProvided_StringReturn()
{
var (results, compilation) = await RunGeneratorAsync("""
app.MapGet("/hello", ([FromQuery]string? p) => p == string.Empty ? "No value, but not null!" : "Was null!");
""");
var endpoint = GetEndpointFromCompilation(compilation);
VerifyStaticEndpointModel(results, endpointModel =>
{
Assert.Equal("MapGet", endpointModel.HttpMethod);
var p = Assert.Single(endpointModel.Parameters);
Assert.Equal(EndpointParameterSource.Query, p.Source);
Assert.Equal("p", p.SymbolName);
});
var httpContext = CreateHttpContext();
httpContext.Request.QueryString = new QueryString("?p=");
await endpoint.RequestDelegate(httpContext);
await VerifyResponseBodyAsync(httpContext, "No value, but not null!");
await VerifyAgainstBaselineUsingFile(compilation);
}
[Fact]
public async Task MapAction_MultipleStringParam_StringReturn()
{
var (results, compilation) = await RunGeneratorAsync("""
app.MapGet("/hello", ([FromQuery]string p1, [FromQuery]string p2) => $"{p1} {p2}");
""");
var endpoint = GetEndpointFromCompilation(compilation);
VerifyStaticEndpointModel(results, endpointModel =>
{
Assert.Equal("MapGet", endpointModel.HttpMethod);
});
var httpContext = CreateHttpContext();
httpContext.Request.QueryString = new QueryString("?p1=Hello&p2=world!");
await endpoint.RequestDelegate(httpContext);
await VerifyResponseBodyAsync(httpContext, "Hello world!");
await VerifyAgainstBaselineUsingFile(compilation);
}
[Fact]
public async Task MapAction_ExplicitParsableParameter_StringReturn()
{
var (results, compilation) = await RunGeneratorAsync("""
app.MapGet("/hello", ([FromQuery] int p1 = 10) => $"{p1}");
""");
var endpoint = GetEndpointFromCompilation(compilation);
var httpContext = CreateHttpContext();
await endpoint.RequestDelegate(httpContext);
await VerifyResponseBodyAsync(httpContext, "10");
}
[Theory]
[InlineData(null, "Id: 00000000-0000-0000-0000-000000000000")]
[InlineData("a0e1f2b3-c4d5-4e6f-7a8b-9c0d1e2f3a4b", "Id: a0e1f2b3-c4d5-4e6f-7a8b-9c0d1e2f3a4b")]
public async Task CanSetGuidParamAsOptionalWithDefaultValue(string queryValue, string expectedResponse)
{
var (_, compilation) = await RunGeneratorAsync("""
app.MapGet("/", ([FromQuery] Guid id = default) => $"Id: {id}");
""");
var endpoint = GetEndpointFromCompilation(compilation);
var httpContext = CreateHttpContext();
if (queryValue is not null)
{
httpContext.Request.Query = new QueryCollection(new Dictionary<string, StringValues>
{
["id"] = queryValue
});
}
await endpoint.RequestDelegate(httpContext);
await VerifyResponseBodyAsync(httpContext, expectedResponse);
}
[Theory]
[InlineData(null, "Date: 0001-01-01T00:00:00.0000000")]
[InlineData("2024-01-15", "Date: 2024-01-15T00:00:00.0000000")]
public async Task CanSetDateTimeParamAsOptionalWithDefaultValue(string queryValue, string expectedResponse)
{
var (_, compilation) = await RunGeneratorAsync("""
app.MapGet("/", ([FromQuery] DateTime date = default) => $"Date: {date:O}");
""");
var endpoint = GetEndpointFromCompilation(compilation);
var httpContext = CreateHttpContext();
if (queryValue is not null)
{
httpContext.Request.Query = new QueryCollection(new Dictionary<string, StringValues>
{
["date"] = queryValue
});
}
await endpoint.RequestDelegate(httpContext);
await VerifyResponseBodyAsync(httpContext, expectedResponse);
}
public static object[][] MapAction_ExplicitQueryParam_NameTest_Data
{
get
{
return new[]
{
new object[] { "name", "name" },
new object[] { "_", "_" },
new object[] { "123", "123" },
new object[] { "💩", "💩" },
new object[] { "\r", "\\r" },
new object[] { "\x00E7" , "\x00E7" },
new object[] { "!!" , "!!" },
new object[] { "\\" , "\\\\" },
new object[] { "\'" , "\'" },
};
}
}
[Theory]
[MemberData(nameof(MapAction_ExplicitQueryParam_NameTest_Data))]
public async Task MapAction_ExplicitQueryParam_NameTest(string name, string lookupName)
{
var (results, compilation) = await RunGeneratorAsync($"""app.MapGet("/", ([FromQuery(Name = @"{name}")] string queryValue) => queryValue);""");
var endpoint = GetEndpointFromCompilation(compilation);
VerifyStaticEndpointModel(results, (endpointModel) =>
{
Assert.Equal("MapGet", endpointModel.HttpMethod);
var p = Assert.Single(endpointModel.Parameters);
Assert.Equal(EndpointParameterSource.Query, p.Source);
Assert.Equal(lookupName, p.LookupName);
});
var httpContext = CreateHttpContext();
httpContext.Request.QueryString = new QueryString($"?{name}=test");
await endpoint.RequestDelegate(httpContext);
await VerifyResponseBodyAsync(httpContext, "test", 200);
}
}