Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit c20262c

Browse files
author
Geoff Kizer
committed
consolidate cookie tests
1 parent 15beaca commit c20262c

File tree

2 files changed

+104
-173
lines changed

2 files changed

+104
-173
lines changed

src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.cs

Lines changed: 0 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -978,66 +978,6 @@ public async Task GetAsync_CredentialIsCredentialCacheUriRedirect_StatusCodeOK(i
978978
}
979979
}
980980

981-
[OuterLoop] // TODO: Issue #11345
982-
[Fact]
983-
public async Task GetAsync_DefaultCoookieContainer_NoCookieSent()
984-
{
985-
using (HttpClient client = CreateHttpClient())
986-
{
987-
using (HttpResponseMessage httpResponse = await client.GetAsync(Configuration.Http.RemoteEchoServer))
988-
{
989-
string responseText = await httpResponse.Content.ReadAsStringAsync();
990-
_output.WriteLine(responseText);
991-
Assert.False(TestHelper.JsonMessageContainsKey(responseText, "Cookie"));
992-
}
993-
}
994-
}
995-
996-
[OuterLoop] // TODO: Issue #11345
997-
[Theory]
998-
[InlineData("cookieName1", "cookieValue1")]
999-
public async Task GetAsync_SetCookieContainer_CookieSent(string cookieName, string cookieValue)
1000-
{
1001-
HttpClientHandler handler = CreateHttpClientHandler();
1002-
var cookieContainer = new CookieContainer();
1003-
cookieContainer.Add(Configuration.Http.RemoteEchoServer, new Cookie(cookieName, cookieValue));
1004-
handler.CookieContainer = cookieContainer;
1005-
using (var client = new HttpClient(handler))
1006-
{
1007-
using (HttpResponseMessage httpResponse = await client.GetAsync(Configuration.Http.RemoteEchoServer))
1008-
{
1009-
Assert.Equal(HttpStatusCode.OK, httpResponse.StatusCode);
1010-
string responseText = await httpResponse.Content.ReadAsStringAsync();
1011-
_output.WriteLine(responseText);
1012-
Assert.True(TestHelper.JsonMessageContainsKeyValue(responseText, cookieName, cookieValue));
1013-
}
1014-
}
1015-
}
1016-
1017-
[OuterLoop] // TODO: Issue #11345
1018-
[Theory]
1019-
[InlineData("cookieName1", "cookieValue1")]
1020-
public async Task GetAsync_RedirectResponseHasCookie_CookieSentToFinalUri(string cookieName, string cookieValue)
1021-
{
1022-
Uri uri = Configuration.Http.RedirectUriForDestinationUri(
1023-
secure: false,
1024-
statusCode: 302,
1025-
destinationUri: Configuration.Http.RemoteEchoServer,
1026-
hops: 1);
1027-
using (HttpClient client = CreateHttpClient())
1028-
{
1029-
client.DefaultRequestHeaders.Add(
1030-
"X-SetCookie",
1031-
string.Format("{0}={1};Path=/", cookieName, cookieValue));
1032-
using (HttpResponseMessage httpResponse = await client.GetAsync(uri))
1033-
{
1034-
string responseText = await httpResponse.Content.ReadAsStringAsync();
1035-
_output.WriteLine(responseText);
1036-
Assert.True(TestHelper.JsonMessageContainsKeyValue(responseText, cookieName, cookieValue));
1037-
}
1038-
}
1039-
}
1040-
1041981
[OuterLoop] // TODO: Issue #11345
1042982
[ConditionalTheory(nameof(NotWindowsUAPOrBeforeVersion1709)), MemberData(nameof(HeaderWithEmptyValueAndUris))]
1043983
public async Task GetAsync_RequestHeadersAddCustomHeaders_HeaderAndEmptyValueSent(string name, string value, Uri uri)
@@ -1074,105 +1014,6 @@ public async Task GetAsync_RequestHeadersAddCustomHeaders_HeaderAndValueSent(str
10741014
}
10751015
}
10761016

1077-
private static KeyValuePair<string, string> GenerateCookie(string name, char repeat, int overallHeaderValueLength)
1078-
{
1079-
string emptyHeaderValue = $"{name}=; Path=/";
1080-
1081-
Debug.Assert(overallHeaderValueLength > emptyHeaderValue.Length);
1082-
1083-
int valueCount = overallHeaderValueLength - emptyHeaderValue.Length;
1084-
string value = new string(repeat, valueCount);
1085-
1086-
return new KeyValuePair<string, string>(name, value);
1087-
}
1088-
1089-
public static IEnumerable<object[]> CookieNameValuesAndUseCookies()
1090-
{
1091-
foreach (bool useCookies in new[] { true, false })
1092-
{
1093-
// WinHttpHandler calls WinHttpQueryHeaders to iterate through multiple Set-Cookie header values,
1094-
// using an initial buffer size of 128 chars. If the buffer is not large enough, WinHttpQueryHeaders
1095-
// returns an insufficient buffer error, allowing WinHttpHandler to try again with a larger buffer.
1096-
// Sometimes when WinHttpQueryHeaders fails due to insufficient buffer, it still advances the
1097-
// iteration index, which would cause header values to be missed if not handled correctly.
1098-
//
1099-
// In particular, WinHttpQueryHeader behaves as follows for the following header value lengths:
1100-
// * 0-127 chars: succeeds, index advances from 0 to 1.
1101-
// * 128-255 chars: fails due to insufficient buffer, index advances from 0 to 1.
1102-
// * 256+ chars: fails due to insufficient buffer, index stays at 0.
1103-
//
1104-
// The below overall header value lengths were chosen to exercise reading header values at these
1105-
// edges, to ensure WinHttpHandler does not miss multiple Set-Cookie headers.
1106-
1107-
yield return new object[] { GenerateCookie(name: "foo", repeat: 'a', overallHeaderValueLength: 126), useCookies };
1108-
yield return new object[] { GenerateCookie(name: "foo", repeat: 'a', overallHeaderValueLength: 127), useCookies };
1109-
yield return new object[] { GenerateCookie(name: "foo", repeat: 'a', overallHeaderValueLength: 128), useCookies };
1110-
yield return new object[] { GenerateCookie(name: "foo", repeat: 'a', overallHeaderValueLength: 129), useCookies };
1111-
1112-
yield return new object[] { GenerateCookie(name: "foo", repeat: 'a', overallHeaderValueLength: 254), useCookies };
1113-
yield return new object[] { GenerateCookie(name: "foo", repeat: 'a', overallHeaderValueLength: 255), useCookies };
1114-
yield return new object[] { GenerateCookie(name: "foo", repeat: 'a', overallHeaderValueLength: 256), useCookies };
1115-
yield return new object[] { GenerateCookie(name: "foo", repeat: 'a', overallHeaderValueLength: 257), useCookies };
1116-
1117-
yield return new object[]
1118-
{
1119-
new KeyValuePair<string, string>(
1120-
".AspNetCore.Antiforgery.Xam7_OeLcN4",
1121-
"CfDJ8NGNxAt7CbdClq3UJ8_6w_4661wRQZT1aDtUOIUKshbcV4P0NdS8klCL5qGSN-PNBBV7w23G6MYpQ81t0PMmzIN4O04fqhZ0u1YPv66mixtkX3iTi291DgwT3o5kozfQhe08-RAExEmXpoCbueP_QYM"),
1122-
useCookies
1123-
};
1124-
}
1125-
}
1126-
1127-
[OuterLoop] // TODO: Issue #11345
1128-
[Theory]
1129-
[MemberData(nameof(CookieNameValuesAndUseCookies))]
1130-
public async Task GetAsync_ResponseWithSetCookieHeaders_AllCookiesRead(KeyValuePair<string, string> cookie1, bool useCookies)
1131-
{
1132-
var cookie2 = new KeyValuePair<string, string>(".AspNetCore.Session", "RAExEmXpoCbueP_QYM");
1133-
var cookie3 = new KeyValuePair<string, string>("name", "value");
1134-
1135-
await LoopbackServer.CreateServerAsync(async (server, url) =>
1136-
{
1137-
using (HttpClientHandler handler = CreateHttpClientHandler())
1138-
{
1139-
handler.UseCookies = useCookies;
1140-
1141-
using (var client = new HttpClient(handler))
1142-
{
1143-
Task<HttpResponseMessage> getResponseTask = client.GetAsync(url);
1144-
await TestHelper.WhenAllCompletedOrAnyFailed(
1145-
getResponseTask,
1146-
LoopbackServer.ReadRequestAndSendResponseAsync(server,
1147-
$"HTTP/1.1 200 OK\r\n" +
1148-
$"Date: {DateTimeOffset.UtcNow:R}\r\n" +
1149-
$"Set-Cookie: {cookie1.Key}={cookie1.Value}; Path=/\r\n" +
1150-
$"Set-Cookie : {cookie2.Key}={cookie2.Value}; Path=/\r\n" + // space before colon to verify header is trimmed and recognized
1151-
$"Set-Cookie: {cookie3.Key}={cookie3.Value}; Path=/\r\n" +
1152-
"\r\n"));
1153-
1154-
using (HttpResponseMessage response = await getResponseTask)
1155-
{
1156-
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
1157-
1158-
CookieCollection cookies = handler.CookieContainer.GetCookies(url);
1159-
if (useCookies)
1160-
{
1161-
Assert.Equal(3, cookies.Count);
1162-
Assert.Equal(cookie1.Value, cookies[cookie1.Key].Value);
1163-
Assert.Equal(cookie2.Value, cookies[cookie2.Key].Value);
1164-
Assert.Equal(cookie3.Value, cookies[cookie3.Key].Value);
1165-
}
1166-
else
1167-
{
1168-
Assert.Equal(0, cookies.Count);
1169-
}
1170-
}
1171-
}
1172-
}
1173-
});
1174-
}
1175-
11761017
[OuterLoop] // TODO: Issue #11345
11771018
[Theory]
11781019
[InlineData(false)]

src/System.Net.Http/tests/FunctionalTests/HttpCookieProtocolTests.cs

Lines changed: 104 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System.Collections.Generic;
6+
using System.Diagnostics;
67
using System.Linq;
78
using System.Net.Test.Common;
89
using System.Threading.Tasks;
@@ -15,6 +16,7 @@ public class HttpCookieProtocolTests : HttpClientTestBase
1516
private const string s_cookieName = "ABC";
1617
private const string s_cookieValue = "123";
1718
private const string s_expectedCookieHeaderValue = "ABC=123";
19+
1820
private const string s_customCookieHeaderValue = "CustomCookie=456";
1921

2022
private const string s_simpleContent = "Hello world!";
@@ -23,13 +25,18 @@ public class HttpCookieProtocolTests : HttpClientTestBase
2325
// Send cookie tests
2426
//
2527

26-
private static CookieContainer CreateSingleCookieContainer(Uri uri)
28+
private static CookieContainer CreateSingleCookieContainer(Uri uri) => CreateSingleCookieContainer(uri, s_cookieName, s_cookieValue);
29+
30+
private static CookieContainer CreateSingleCookieContainer(Uri uri, string cookieName, string cookieValue)
2731
{
2832
var container = new CookieContainer();
29-
container.Add(uri, new Cookie(s_cookieName, s_cookieValue));
33+
container.Add(uri, new Cookie(cookieName, cookieValue));
3034
return container;
3135
}
3236

37+
private static string GetCookieHeaderValue(string cookieName, string cookieValue) => $"{cookieName}={cookieValue}";
38+
39+
3340
[Fact]
3441
public async Task GetAsync_DefaultCoookieContainer_NoCookieSent()
3542
{
@@ -48,13 +55,15 @@ await LoopbackServer.CreateServerAsync(async (server, url) =>
4855
});
4956
}
5057

51-
[Fact]
52-
public async Task GetAsync_SetCookieContainer_CookieSent()
58+
[Theory]
59+
[MemberData(nameof(CookieNamesValuesAndUseCookies))]
60+
public async Task GetAsync_SetCookieContainer_CookieSent(string cookieName, string cookieValue, bool useCookies)
5361
{
5462
await LoopbackServer.CreateServerAsync(async (server, url) =>
5563
{
5664
HttpClientHandler handler = CreateHttpClientHandler();
57-
handler.CookieContainer = CreateSingleCookieContainer(url);
65+
handler.UseCookies = useCookies;
66+
handler.CookieContainer = CreateSingleCookieContainer(url, cookieName, cookieValue);
5867

5968
using (HttpClient client = new HttpClient(handler))
6069
{
@@ -64,8 +73,15 @@ await LoopbackServer.CreateServerAsync(async (server, url) =>
6473

6574
List<string> requestLines = await serverTask;
6675

67-
Assert.Contains($"Cookie: {s_expectedCookieHeaderValue}", requestLines);
68-
Assert.Equal(1, requestLines.Count(s => s.StartsWith("Cookie:")));
76+
if (useCookies)
77+
{
78+
Assert.Contains($"Cookie: {GetCookieHeaderValue(cookieName, cookieValue)}", requestLines);
79+
Assert.Equal(1, requestLines.Count(s => s.StartsWith("Cookie:")));
80+
}
81+
else
82+
{
83+
Assert.Equal(0, requestLines.Count(s => s.StartsWith("Cookie:")));
84+
}
6985
}
7086
});
7187
}
@@ -323,24 +339,34 @@ await LoopbackServer.CreateServerAndClientAsync(async url =>
323339
// Receive cookie tests
324340
//
325341

326-
[Fact]
327-
public async Task GetAsync_ReceiveSetCookieHeader_CookieAdded()
342+
[Theory]
343+
[MemberData(nameof(CookieNamesValuesAndUseCookies))]
344+
public async Task GetAsync_ReceiveSetCookieHeader_CookieAdded(string cookieName, string cookieValue, bool useCookies)
328345
{
329346
await LoopbackServer.CreateServerAsync(async (server, url) =>
330347
{
331348
HttpClientHandler handler = CreateHttpClientHandler();
349+
handler.UseCookies = useCookies;
332350

333351
using (HttpClient client = new HttpClient(handler))
334352
{
335353
Task<HttpResponseMessage> getResponseTask = client.GetAsync(url);
336354
Task<List<string>> serverTask = LoopbackServer.ReadRequestAndSendResponseAsync(server,
337-
$"HTTP/1.1 200 Ok\r\nContent-Length: {s_simpleContent.Length}\r\nSet-Cookie: {s_expectedCookieHeaderValue}\r\n\r\n{s_simpleContent}");
355+
$"HTTP/1.1 200 Ok\r\nContent-Length: {s_simpleContent.Length}\r\nSet-Cookie: {GetCookieHeaderValue(cookieName, cookieValue)}\r\n\r\n{s_simpleContent}");
338356
await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask);
339357

340358
CookieCollection collection = handler.CookieContainer.GetCookies(url);
341-
Assert.Equal(1, collection.Count);
342-
Assert.Equal(s_cookieName, collection[0].Name);
343-
Assert.Equal(s_cookieValue, collection[0].Value);
359+
360+
if (useCookies)
361+
{
362+
Assert.Equal(1, collection.Count);
363+
Assert.Equal(cookieName, collection[0].Name);
364+
Assert.Equal(cookieValue, collection[0].Value);
365+
}
366+
else
367+
{
368+
Assert.Equal(0, collection.Count);
369+
}
344370
}
345371
});
346372
}
@@ -356,7 +382,14 @@ await LoopbackServer.CreateServerAsync(async (server, url) =>
356382
{
357383
Task<HttpResponseMessage> getResponseTask = client.GetAsync(url);
358384
Task<List<string>> serverTask = LoopbackServer.ReadRequestAndSendResponseAsync(server,
359-
$"HTTP/1.1 200 Ok\r\nContent-Length: {s_simpleContent.Length}\r\nSet-Cookie: A=1\r\nSet-Cookie: B=2\r\nSet-Cookie: C=3\r\n\r\n{s_simpleContent}");
385+
$"HTTP/1.1 200 OK\r\n" +
386+
$"Date: {DateTimeOffset.UtcNow:R}\r\n" +
387+
$"Set-Cookie: A=1; Path=/\r\n" +
388+
$"Set-Cookie : B=2; Path=/\r\n" + // space before colon to verify header is trimmed and recognized
389+
$"Set-Cookie: C=3; Path=/\r\n" +
390+
$"Content-Length: {s_simpleContent.Length}\r\n" +
391+
$"\r\n" +
392+
$"{s_simpleContent}");
360393
await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask);
361394

362395
CookieCollection collection = handler.CookieContainer.GetCookies(url);
@@ -512,5 +545,62 @@ await LoopbackServer.AcceptSocketAsync(server, async (_, stream, reader, writer)
512545
});
513546
});
514547
}
548+
549+
//
550+
// MemberData stuff
551+
//
552+
553+
private static string GenerateCookie(string name, char repeat, int overallHeaderValueLength)
554+
{
555+
string emptyHeaderValue = $"{name}=; Path=/";
556+
557+
Debug.Assert(overallHeaderValueLength > emptyHeaderValue.Length);
558+
559+
int valueCount = overallHeaderValueLength - emptyHeaderValue.Length;
560+
return new string(repeat, valueCount);
561+
}
562+
563+
public static IEnumerable<object[]> CookieNamesValuesAndUseCookies()
564+
{
565+
foreach (bool useCookies in new[] { true, false })
566+
{
567+
yield return new object[] { "ABC", "123", useCookies };
568+
yield return new object[] { "Hello", "World", useCookies };
569+
yield return new object[] { "foo", "bar", useCookies };
570+
571+
yield return new object[] { ".AspNetCore.Session", "RAExEmXpoCbueP_QYM", useCookies };
572+
573+
yield return new object[]
574+
{
575+
".AspNetCore.Antiforgery.Xam7_OeLcN4",
576+
"CfDJ8NGNxAt7CbdClq3UJ8_6w_4661wRQZT1aDtUOIUKshbcV4P0NdS8klCL5qGSN-PNBBV7w23G6MYpQ81t0PMmzIN4O04fqhZ0u1YPv66mixtkX3iTi291DgwT3o5kozfQhe08-RAExEmXpoCbueP_QYM",
577+
useCookies
578+
};
579+
580+
// WinHttpHandler calls WinHttpQueryHeaders to iterate through multiple Set-Cookie header values,
581+
// using an initial buffer size of 128 chars. If the buffer is not large enough, WinHttpQueryHeaders
582+
// returns an insufficient buffer error, allowing WinHttpHandler to try again with a larger buffer.
583+
// Sometimes when WinHttpQueryHeaders fails due to insufficient buffer, it still advances the
584+
// iteration index, which would cause header values to be missed if not handled correctly.
585+
//
586+
// In particular, WinHttpQueryHeader behaves as follows for the following header value lengths:
587+
// * 0-127 chars: succeeds, index advances from 0 to 1.
588+
// * 128-255 chars: fails due to insufficient buffer, index advances from 0 to 1.
589+
// * 256+ chars: fails due to insufficient buffer, index stays at 0.
590+
//
591+
// The below overall header value lengths were chosen to exercise reading header values at these
592+
// edges, to ensure WinHttpHandler does not miss multiple Set-Cookie headers.
593+
594+
yield return new object[] { "foo", GenerateCookie(name: "foo", repeat: 'a', overallHeaderValueLength: 126), useCookies };
595+
yield return new object[] { "foo", GenerateCookie(name: "foo", repeat: 'a', overallHeaderValueLength: 127), useCookies };
596+
yield return new object[] { "foo", GenerateCookie(name: "foo", repeat: 'a', overallHeaderValueLength: 128), useCookies };
597+
yield return new object[] { "foo", GenerateCookie(name: "foo", repeat: 'a', overallHeaderValueLength: 129), useCookies };
598+
599+
yield return new object[] { "foo", GenerateCookie(name: "foo", repeat: 'a', overallHeaderValueLength: 254), useCookies };
600+
yield return new object[] { "foo", GenerateCookie(name: "foo", repeat: 'a', overallHeaderValueLength: 255), useCookies };
601+
yield return new object[] { "foo", GenerateCookie(name: "foo", repeat: 'a', overallHeaderValueLength: 256), useCookies };
602+
yield return new object[] { "foo", GenerateCookie(name: "foo", repeat: 'a', overallHeaderValueLength: 257), useCookies };
603+
}
604+
}
515605
}
516606
}

0 commit comments

Comments
 (0)