From 26298bc6295be9cddfa185f9d1dc8e99a5c92278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20P=C3=ADchov=C3=A1?= Date: Tue, 21 Jan 2020 19:55:08 +0100 Subject: [PATCH] WinHttpHandler tests are back (#1676) The tests used by PlatformHandlerTest moved to Common/tests in order to share them between System.Net.Http and System.Net.Http.WinHttpHandler. The added conditions correspond to the state before WinHttpHandler removal. They're just based on IsWinHttpHandler instead of UseSocketHandler. Some of the code must be conditionally compiled since there is no usable common base class for HttpClientHandler and WinHttpHandler. Other issues solved by introducing WinHttpClientHandler for testing purposes. It corresponds to HttpClientHandler.Windows.cs code from before its removal. --- .../System/Net/Http}/ByteAtATimeContent.cs | 0 .../Net/Http}/ChannelBindingAwareContent.cs | 0 .../tests/System/Net/Http}/CustomContent.cs | 0 .../Net/Http}/DefaultCredentialsTest.cs | 4 + .../tests/System/Net/Http}/DribbleStream.cs | 0 .../Net/Http}/HttpClient.SelectedSitesTest.cs | 0 .../System/Net/Http}/HttpClientEKUTest.cs | 4 + .../HttpClientHandlerTest.AcceptAllCerts.cs | 8 +- .../Http}/HttpClientHandlerTest.Asynchrony.cs | 0 .../HttpClientHandlerTest.Authentication.cs | 16 ++ .../HttpClientHandlerTest.AutoRedirect.cs | 72 ++++++- .../HttpClientHandlerTest.Cancellation.cs | 4 + ...ttpClientHandlerTest.ClientCertificates.cs | 4 + .../Http}/HttpClientHandlerTest.Cookies.cs | 11 ++ .../HttpClientHandlerTest.Decompression.cs | 18 +- ...ientHandlerTest.DefaultProxyCredentials.cs | 6 + ...ientHandlerTest.MaxConnectionsPerServer.cs | 4 + ...entHandlerTest.MaxResponseHeadersLength.cs | 14 +- .../Net/Http}/HttpClientHandlerTest.Proxy.cs | 14 +- ...ttpClientHandlerTest.ServerCertificates.cs | 10 + .../HttpClientHandlerTest.SslProtocols.cs | 17 +- .../System/Net/Http}/HttpClientHandlerTest.cs | 55 +++++- .../Net/Http}/HttpClientHandlerTestBase.cs | 37 +--- .../System/Net/Http}/HttpProtocolTests.cs | 58 +++++- .../Net/Http}/HttpRetryProtocolTests.cs | 12 ++ .../System/Net/Http}/IdnaProtocolTests.cs | 4 + .../System/Net/Http}/PostScenarioTest.cs | 4 + .../System/Net/Http}/RepeatedFlushContent.cs | 0 .../System/Net/Http}/ResponseStreamTest.cs | 27 ++- .../Net/Http}/SchSendAuxRecordHttpTest.cs | 6 +- .../System/Net/Http}/SyncBlockingContent.cs | 0 .../tests/System/Net/Http}/TestHelper.cs | 6 +- ...ttpClientHandlerTestBase.WinHttpHandler.cs | 30 +++ .../FunctionalTests/PlatformHandlerTest.cs | 67 +------ ...ttp.WinHttpHandler.Functional.Tests.csproj | 178 +++++++++++++++++ .../FunctionalTests/WinHttpClientHandler.cs | 184 ++++++++++++++++++ ...lientHandlerTestBase.SocketsHttpHandler.cs | 38 ++++ .../FunctionalTests/PostScenarioUWPTest.cs | 148 -------------- .../System.Net.Http.Functional.Tests.csproj | 130 +++++++++---- 39 files changed, 873 insertions(+), 317 deletions(-) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/ByteAtATimeContent.cs (100%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/ChannelBindingAwareContent.cs (100%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/CustomContent.cs (100%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/DefaultCredentialsTest.cs (99%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/DribbleStream.cs (100%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpClient.SelectedSitesTest.cs (100%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpClientEKUTest.cs (98%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpClientHandlerTest.AcceptAllCerts.cs (96%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpClientHandlerTest.Asynchrony.cs (100%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpClientHandlerTest.Authentication.cs (98%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpClientHandlerTest.AutoRedirect.cs (89%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpClientHandlerTest.Cancellation.cs (99%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpClientHandlerTest.ClientCertificates.cs (98%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpClientHandlerTest.Cookies.cs (98%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpClientHandlerTest.Decompression.cs (95%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpClientHandlerTest.DefaultProxyCredentials.cs (98%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpClientHandlerTest.MaxConnectionsPerServer.cs (97%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpClientHandlerTest.MaxResponseHeadersLength.cs (94%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpClientHandlerTest.Proxy.cs (97%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpClientHandlerTest.ServerCertificates.cs (98%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpClientHandlerTest.SslProtocols.cs (94%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpClientHandlerTest.cs (98%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpClientHandlerTestBase.cs (74%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpProtocolTests.cs (91%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/HttpRetryProtocolTests.cs (94%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/IdnaProtocolTests.cs (98%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/PostScenarioTest.cs (99%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/RepeatedFlushContent.cs (100%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/ResponseStreamTest.cs (93%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/SchSendAuxRecordHttpTest.cs (96%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/SyncBlockingContent.cs (100%) rename src/libraries/{System.Net.Http/tests/FunctionalTests => Common/tests/System/Net/Http}/TestHelper.cs (97%) create mode 100644 src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/HttpClientHandlerTestBase.WinHttpHandler.cs rename src/libraries/{System.Net.Http => System.Net.Http.WinHttpHandler}/tests/FunctionalTests/PlatformHandlerTest.cs (68%) create mode 100644 src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/WinHttpClientHandler.cs create mode 100644 src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs delete mode 100644 src/libraries/System.Net.Http/tests/FunctionalTests/PostScenarioUWPTest.cs diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/ByteAtATimeContent.cs b/src/libraries/Common/tests/System/Net/Http/ByteAtATimeContent.cs similarity index 100% rename from src/libraries/System.Net.Http/tests/FunctionalTests/ByteAtATimeContent.cs rename to src/libraries/Common/tests/System/Net/Http/ByteAtATimeContent.cs diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/ChannelBindingAwareContent.cs b/src/libraries/Common/tests/System/Net/Http/ChannelBindingAwareContent.cs similarity index 100% rename from src/libraries/System.Net.Http/tests/FunctionalTests/ChannelBindingAwareContent.cs rename to src/libraries/Common/tests/System/Net/Http/ChannelBindingAwareContent.cs diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/CustomContent.cs b/src/libraries/Common/tests/System/Net/Http/CustomContent.cs similarity index 100% rename from src/libraries/System.Net.Http/tests/FunctionalTests/CustomContent.cs rename to src/libraries/Common/tests/System/Net/Http/CustomContent.cs diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/DefaultCredentialsTest.cs b/src/libraries/Common/tests/System/Net/Http/DefaultCredentialsTest.cs similarity index 99% rename from src/libraries/System.Net.Http/tests/FunctionalTests/DefaultCredentialsTest.cs rename to src/libraries/Common/tests/System/Net/Http/DefaultCredentialsTest.cs index 667e82b91dbfb..11f9d8397721b 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/DefaultCredentialsTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/DefaultCredentialsTest.cs @@ -13,6 +13,10 @@ namespace System.Net.Http.Functional.Tests { using Configuration = System.Net.Test.Common.Configuration; +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + [PlatformSpecific(TestPlatforms.Windows)] public abstract class DefaultCredentialsTest : HttpClientHandlerTestBase { diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/DribbleStream.cs b/src/libraries/Common/tests/System/Net/Http/DribbleStream.cs similarity index 100% rename from src/libraries/System.Net.Http/tests/FunctionalTests/DribbleStream.cs rename to src/libraries/Common/tests/System/Net/Http/DribbleStream.cs diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClient.SelectedSitesTest.cs b/src/libraries/Common/tests/System/Net/Http/HttpClient.SelectedSitesTest.cs similarity index 100% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpClient.SelectedSitesTest.cs rename to src/libraries/Common/tests/System/Net/Http/HttpClient.SelectedSitesTest.cs diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientEKUTest.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientEKUTest.cs similarity index 98% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientEKUTest.cs rename to src/libraries/Common/tests/System/Net/Http/HttpClientEKUTest.cs index 31e1c97f8e53c..c57b6f718b411 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientEKUTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientEKUTest.cs @@ -16,6 +16,10 @@ namespace System.Net.Http.Functional.Tests { using Configuration = System.Net.Test.Common.Configuration; +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + public abstract class HttpClientEKUTest : HttpClientHandlerTestBase { private static bool CanTestCertificates => diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.AcceptAllCerts.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.AcceptAllCerts.cs similarity index 96% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.AcceptAllCerts.cs rename to src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.AcceptAllCerts.cs index b9f4dedb4a784..53d45add78b83 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.AcceptAllCerts.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.AcceptAllCerts.cs @@ -14,12 +14,17 @@ namespace System.Net.Http.Functional.Tests { using Configuration = System.Net.Test.Common.Configuration; +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + public abstract class HttpClientHandler_DangerousAcceptAllCertificatesValidator_Test : HttpClientHandlerTestBase { private static bool ClientSupportsDHECipherSuites => (!PlatformDetection.IsWindows || PlatformDetection.IsWindows10Version1607OrGreater); public HttpClientHandler_DangerousAcceptAllCertificatesValidator_Test(ITestOutputHelper output) : base(output) { } +#if !WINHTTPHANDLER_TEST [Fact] public void SingletonReturnsTrue() { @@ -27,8 +32,9 @@ public void SingletonReturnsTrue() Assert.Same(HttpClientHandler.DangerousAcceptAnyServerCertificateValidator, HttpClientHandler.DangerousAcceptAnyServerCertificateValidator); Assert.True(HttpClientHandler.DangerousAcceptAnyServerCertificateValidator(null, null, null, SslPolicyErrors.None)); } +#endif - [ConditionalTheory] + [Theory] [InlineData(SslProtocols.Tls, false)] // try various protocols to ensure we correctly set versions even when accepting all certs [InlineData(SslProtocols.Tls, true)] [InlineData(SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls, false)] diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Asynchrony.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Asynchrony.cs similarity index 100% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Asynchrony.cs rename to src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Asynchrony.cs diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Authentication.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Authentication.cs similarity index 98% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Authentication.cs rename to src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Authentication.cs index 174b95336ed44..14768ad849f93 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Authentication.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Authentication.cs @@ -18,6 +18,10 @@ namespace System.Net.Http.Functional.Tests { using Configuration = System.Net.Test.Common.Configuration; +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + public abstract class HttpClientHandler_Authentication_Test : HttpClientHandlerTestBase { private const string Username = "testusername"; @@ -70,6 +74,12 @@ await TestHelper.WhenAllCompletedOrAnyFailedWithTimeout(TestHelper.PassingTestTi [InlineData("WWW-Authenticate: Digest realm=\"hello1\", nonce=\"hello\", algorithm=MD5\r\nWWW-Authenticate: Digest realm=\"hello\", nonce=\"hello\", algorithm=MD5\r\n")] public async Task HttpClientHandler_MultipleAuthenticateHeaders_WithSameAuth_Succeeds(string authenticateHeader) { + if (IsWinHttpHandler) + { + // TODO: https://github.com/dotnet/corefx/issues/28065: Fix failing authentication test cases on different httpclienthandlers. + return; + } + await HttpClientHandler_MultipleAuthenticateHeaders_Succeeds(authenticateHeader); } @@ -413,6 +423,12 @@ await LoopbackServer.CreateClientAndServerAsync(async uri => [Fact] public async Task PreAuthenticate_SuccessfulBasic_ThenDigestChallenged() { + if (IsWinHttpHandler) + { + // WinHttpHandler fails with Unauthorized after the basic preauth fails. + return; + } + await LoopbackServer.CreateClientAndServerAsync(async uri => { using (HttpClientHandler handler = CreateHttpClientHandler()) diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.AutoRedirect.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.AutoRedirect.cs similarity index 89% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.AutoRedirect.cs rename to src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.AutoRedirect.cs index 3b298703785f8..625ff1e2ddfe1 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.AutoRedirect.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.AutoRedirect.cs @@ -15,6 +15,10 @@ namespace System.Net.Http.Functional.Tests { using Configuration = System.Net.Test.Common.Configuration; +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + public abstract class HttpClientHandlerTest_AutoRedirect : HttpClientHandlerTestBase { private const string ExpectedContent = "Test content"; @@ -68,6 +72,12 @@ public HttpClientHandlerTest_AutoRedirect(ITestOutputHelper output) : base(outpu [Theory, MemberData(nameof(RemoteServersAndRedirectStatusCodes))] public async Task GetAsync_AllowAutoRedirectFalse_RedirectFromHttpToHttp_StatusCodeRedirect(Configuration.Http.RemoteServer remoteServer, int statusCode) { + if (statusCode == 308 && (IsWinHttpHandler && PlatformDetection.WindowsVersion < 10)) + { + // 308 redirects are not supported on old versions of WinHttp, or on .NET Framework. + return; + } + HttpClientHandler handler = CreateHttpClientHandler(); handler.AllowAutoRedirect = false; using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler)) @@ -89,6 +99,12 @@ public async Task GetAsync_AllowAutoRedirectFalse_RedirectFromHttpToHttp_StatusC public async Task AllowAutoRedirect_True_ValidateNewMethodUsedOnRedirection( int statusCode, string oldMethod, string newMethod) { + if (statusCode == 308 && (IsWinHttpHandler && PlatformDetection.WindowsVersion < 10)) + { + // 308 redirects are not supported on old versions of WinHttp, or on .NET Framework. + return; + } + HttpClientHandler handler = CreateHttpClientHandler(); using (HttpClient client = CreateHttpClient(handler)) { @@ -191,6 +207,12 @@ await LoopbackServer.CreateServerAsync(async (redirServer, redirUrl) => [Theory, MemberData(nameof(RemoteServersAndRedirectStatusCodes))] public async Task GetAsync_AllowAutoRedirectTrue_RedirectFromHttpToHttp_StatusCodeOK(Configuration.Http.RemoteServer remoteServer, int statusCode) { + if (statusCode == 308 && (IsWinHttpHandler && PlatformDetection.WindowsVersion < 10)) + { + // 308 redirects are not supported on old versions of WinHttp, or on .NET Framework. + return; + } + HttpClientHandler handler = CreateHttpClientHandler(); handler.AllowAutoRedirect = true; using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler)) @@ -254,6 +276,12 @@ public async Task GetAsync_AllowAutoRedirectTrue_RedirectFromHttpsToHttp_StatusC [Fact] public async Task GetAsync_AllowAutoRedirectTrue_RedirectWithoutLocation_ReturnsOriginalResponse() { + // [ActiveIssue("https://github.com/dotnet/corefx/issues/24819", TestPlatforms.Windows)] + if (IsWinHttpHandler) + { + return; + } + HttpClientHandler handler = CreateHttpClientHandler(); handler.AllowAutoRedirect = true; using (HttpClient client = CreateHttpClient(handler)) @@ -301,6 +329,13 @@ public async Task GetAsync_AllowAutoRedirectTrue_RedirectToUriWithParams_Request [InlineData(3, 4)] public async Task GetAsync_MaxAutomaticRedirectionsNServerHops_ThrowsIfTooMany(int maxHops, int hops) { + if (IsWinHttpHandler && !PlatformDetection.IsWindows10Version1703OrGreater) + { + // Skip this test if using WinHttpHandler but on a release prior to Windows 10 Creators Update. + _output.WriteLine("Skipping test due to Windows 10 version prior to Version 1703."); + return; + } + HttpClientHandler handler = CreateHttpClientHandler(); handler.MaxAutomaticRedirections = maxHops; using (HttpClient client = CreateHttpClient(handler)) @@ -320,9 +355,16 @@ public async Task GetAsync_MaxAutomaticRedirectionsNServerHops_ThrowsIfTooMany(i } else { - using (HttpResponseMessage response = await t) + if (!IsWinHttpHandler) + { + using (HttpResponseMessage response = await t) + { + Assert.Equal(HttpStatusCode.Redirect, response.StatusCode); + } + } + else { - Assert.Equal(HttpStatusCode.Redirect, response.StatusCode); + await Assert.ThrowsAsync(() => t); } } } @@ -394,6 +436,20 @@ await TestHelper.WhenAllCompletedOrAnyFailed( public async Task GetAsync_AllowAutoRedirectTrue_RetainsOriginalFragmentIfAppropriate( string origFragment, string redirFragment, string expectedFragment, bool useRelativeRedirect) { + if (IsWinHttpHandler) + { + // According to https://tools.ietf.org/html/rfc7231#section-7.1.2, + // "If the Location value provided in a 3xx (Redirection) response does + // not have a fragment component, a user agent MUST process the + // redirection as if the value inherits the fragment component of the + // URI reference used to generate the request target(i.e., the + // redirection inherits the original reference's fragment, if any)." + // WINHTTP is not doing this, and thus neither is WinHttpHandler. + // It also sometimes doesn't include the fragments for redirects + // even in other cases. + return; + } + HttpClientHandler handler = CreateHttpClientHandler(); handler.AllowAutoRedirect = true; using (HttpClient client = CreateHttpClient(handler)) @@ -482,6 +538,12 @@ public async Task HttpClientHandler_CredentialIsNotCredentialCacheAfterRedirect_ [Theory, MemberData(nameof(RemoteServersAndRedirectStatusCodes))] public async Task GetAsync_CredentialIsCredentialCacheUriRedirect_StatusCodeOK(Configuration.Http.RemoteServer remoteServer, int statusCode) { + if (statusCode == 308 && (IsWinHttpHandler && PlatformDetection.WindowsVersion < 10)) + { + // 308 redirects are not supported on old versions of WinHttp, or on .NET Framework. + return; + } + Uri uri = remoteServer.BasicAuthUriForCreds(userName: Username, password: Password); Uri redirectUri = remoteServer.RedirectUriForCreds( statusCode: statusCode, @@ -508,6 +570,12 @@ public async Task GetAsync_CredentialIsCredentialCacheUriRedirect_StatusCodeOK(C [Theory, MemberData(nameof(RemoteServersAndRedirectStatusCodes))] public async Task DefaultHeaders_SetCredentials_ClearedOnRedirect(Configuration.Http.RemoteServer remoteServer, int statusCode) { + if (statusCode == 308 && (IsWinHttpHandler && PlatformDetection.WindowsVersion < 10)) + { + // 308 redirects are not supported on old versions of WinHttp, or on .NET Framework. + return; + } + HttpClientHandler handler = CreateHttpClientHandler(); using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler)) { diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Cancellation.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs similarity index 99% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Cancellation.cs rename to src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs index ee4c5ed4b45ac..8dc8f8b690494 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Cancellation.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs @@ -20,6 +20,10 @@ namespace System.Net.Http.Functional.Tests { +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + public abstract class HttpClientHandler_Cancellation_Test : HttpClientHandlerTestBase { public HttpClientHandler_Cancellation_Test(ITestOutputHelper output) : base(output) { } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ClientCertificates.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ClientCertificates.cs similarity index 98% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ClientCertificates.cs rename to src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ClientCertificates.cs index d71cb40e7a747..346681abd9ad4 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ClientCertificates.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ClientCertificates.cs @@ -17,6 +17,10 @@ namespace System.Net.Http.Functional.Tests { using Configuration = System.Net.Test.Common.Configuration; +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + public abstract class HttpClientHandler_ClientCertificates_Test : HttpClientHandlerTestBase { public HttpClientHandler_ClientCertificates_Test(ITestOutputHelper output) : base(output) { } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Cookies.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cookies.cs similarity index 98% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Cookies.cs rename to src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cookies.cs index de9993b269dc1..306e886fcc971 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Cookies.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cookies.cs @@ -13,6 +13,10 @@ namespace System.Net.Http.Functional.Tests { +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + public abstract class HttpClientHandlerTest_Cookies : HttpClientHandlerTestBase { private const string s_cookieName = "ABC"; @@ -526,6 +530,13 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async url => [Fact] public async Task GetAsyncWithBasicAuth_ReceiveSetCookie_CookieSent() { + if (IsWinHttpHandler) + { + // Issue https://github.com/dotnet/corefx/issues/26986 + // WinHttpHandler does not process the cookie. + return; + } + await LoopbackServerFactory.CreateClientAndServerAsync(async url => { HttpClientHandler handler = CreateHttpClientHandler(); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Decompression.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs similarity index 95% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Decompression.cs rename to src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs index 2da1fd95c088f..0fb03c3e612b8 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Decompression.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs @@ -16,6 +16,10 @@ namespace System.Net.Http.Functional.Tests { using Configuration = System.Net.Test.Common.Configuration; +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + public abstract class HttpClientHandler_Decompression_Test : HttpClientHandlerTestBase { public HttpClientHandler_Decompression_Test(ITestOutputHelper output) : base(output) { } @@ -59,6 +63,12 @@ public static IEnumerable DecompressedResponse_MethodSpecified_Decompr public async Task DecompressedResponse_MethodSpecified_DecompressedContentReturned( string encodingName, Func compress, DecompressionMethods methods) { + // Brotli only supported on SocketsHttpHandler. + if (IsWinHttpHandler && encodingName == "br") + { + return; + } + var expectedContent = new byte[12345]; new Random(42).NextBytes(expectedContent); @@ -179,12 +189,10 @@ public async Task GetAsync_SetAutomaticDecompression_HeadersRemoved(Configuratio } [Theory] -#if NETCOREAPP [InlineData(DecompressionMethods.Brotli, "br", "")] [InlineData(DecompressionMethods.Brotli, "br", "br")] [InlineData(DecompressionMethods.Brotli, "br", "gzip")] [InlineData(DecompressionMethods.Brotli, "br", "gzip, deflate")] -#endif [InlineData(DecompressionMethods.GZip, "gzip", "")] [InlineData(DecompressionMethods.Deflate, "deflate", "")] [InlineData(DecompressionMethods.GZip | DecompressionMethods.Deflate, "gzip, deflate", "")] @@ -200,6 +208,12 @@ public async Task GetAsync_SetAutomaticDecompression_AcceptEncodingHeaderSentWit string encodings, string manualAcceptEncodingHeaderValues) { + // Brotli only supported on SocketsHttpHandler. + if (IsWinHttpHandler && (encodings.Contains("br") || manualAcceptEncodingHeaderValues.Contains("br"))) + { + return; + } + await LoopbackServer.CreateServerAsync(async (server, url) => { HttpClientHandler handler = CreateHttpClientHandler(); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.DefaultProxyCredentials.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.DefaultProxyCredentials.cs similarity index 98% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.DefaultProxyCredentials.cs rename to src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.DefaultProxyCredentials.cs index 090d471348bff..b648c77c32dea 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.DefaultProxyCredentials.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.DefaultProxyCredentials.cs @@ -16,6 +16,10 @@ namespace System.Net.Http.Functional.Tests { using Configuration = System.Net.Test.Common.Configuration; +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + public abstract class HttpClientHandler_DefaultProxyCredentials_Test : HttpClientHandlerTestBase { public HttpClientHandler_DefaultProxyCredentials_Test(ITestOutputHelper output) : base(output) { } @@ -76,6 +80,7 @@ await server.AcceptConnectionSendResponseAndCloseAsync( }); } +#if !WINHTTPHANDLER_TEST [ActiveIssue("https://github.com/dotnet/corefx/issues/42323")] [OuterLoop("Uses external server")] [PlatformSpecific(TestPlatforms.AnyUnix)] // The default proxy is resolved via WinINet on Windows. @@ -122,6 +127,7 @@ await LoopbackServer.CreateServerAsync(async (proxyServer, proxyUri) => } }, options); } +#endif // The purpose of this test is mainly to validate the .NET Framework OOB System.Net.Http implementation // since it has an underlying dependency to WebRequest. While .NET Core implementations of System.Net.Http diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.MaxConnectionsPerServer.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.MaxConnectionsPerServer.cs similarity index 97% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.MaxConnectionsPerServer.cs rename to src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.MaxConnectionsPerServer.cs index 87f06778fcc04..8549d38943c1b 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.MaxConnectionsPerServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.MaxConnectionsPerServer.cs @@ -15,6 +15,10 @@ namespace System.Net.Http.Functional.Tests { using Configuration = System.Net.Test.Common.Configuration; +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + public abstract class HttpClientHandler_MaxConnectionsPerServer_Test : HttpClientHandlerTestBase { public HttpClientHandler_MaxConnectionsPerServer_Test(ITestOutputHelper output) : base(output) { } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.MaxResponseHeadersLength.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.MaxResponseHeadersLength.cs similarity index 94% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.MaxResponseHeadersLength.cs rename to src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.MaxResponseHeadersLength.cs index 350b8a9d34a9f..7c6db382a0686 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.MaxResponseHeadersLength.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.MaxResponseHeadersLength.cs @@ -14,6 +14,10 @@ namespace System.Net.Http.Functional.Tests { using Configuration = System.Net.Test.Common.Configuration; +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + public abstract class HttpClientHandler_MaxResponseHeadersLength_Test : HttpClientHandlerTestBase { public HttpClientHandler_MaxResponseHeadersLength_Test(ITestOutputHelper output) : base(output) { } @@ -86,7 +90,10 @@ await server.AcceptConnectionAsync(async connection => Exception e = await Assert.ThrowsAsync(() => getAsync); cts.Cancel(); - Assert.Contains((handler.MaxResponseHeadersLength * 1024).ToString(), e.ToString()); + if (!IsWinHttpHandler) + { + Assert.Contains((handler.MaxResponseHeadersLength * 1024).ToString(), e.ToString()); + } await serverTask; }); } @@ -120,7 +127,10 @@ await server.AcceptConnectionAsync(async connection => else { Exception e = await Assert.ThrowsAsync(() => getAsync); - Assert.Contains((handler.MaxResponseHeadersLength * 1024).ToString(), e.ToString()); + if (!IsWinHttpHandler) + { + Assert.Contains((handler.MaxResponseHeadersLength * 1024).ToString(), e.ToString()); + } try { await serverTask; } catch { } } }); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Proxy.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Proxy.cs similarity index 97% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Proxy.cs rename to src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Proxy.cs index 3cbe378ef9c36..cc49d76129b24 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Proxy.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Proxy.cs @@ -18,6 +18,10 @@ namespace System.Net.Http.Functional.Tests { using Configuration = System.Net.Test.Common.Configuration; +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + public abstract class HttpClientHandler_Proxy_Test : HttpClientHandlerTestBase { public HttpClientHandler_Proxy_Test(ITestOutputHelper output) : base(output) { } @@ -224,7 +228,9 @@ public async Task Proxy_SslProxyUnsupported_Throws() { handler.Proxy = new WebProxy("https://" + Guid.NewGuid().ToString("N")); - await Assert.ThrowsAsync(() => client.GetAsync("http://" + Guid.NewGuid().ToString("N"))); + Type expectedType = IsWinHttpHandler ? typeof(HttpRequestException) : typeof(NotSupportedException); + + await Assert.ThrowsAsync(expectedType, () => client.GetAsync("http://" + Guid.NewGuid().ToString("N"))); } } @@ -288,6 +294,12 @@ await LoopbackServer.CreateServerAsync(async (proxyServer, proxyUrl) => [PlatformSpecific(TestPlatforms.Windows)] public async Task MultiProxy_PAC_Failover_Succeeds() { + if (IsWinHttpHandler) + { + // PAC-based failover is only supported on Windows/SocketsHttpHandler + return; + } + // Create our failing proxy server. // Bind a port to reserve it, but don't start listening yet. The first Connect() should fail and cause a fail-over. using Socket failingProxyServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ServerCertificates.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs similarity index 98% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ServerCertificates.cs rename to src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs index 13393b3cf8fc2..09bc7547c73a1 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ServerCertificates.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs @@ -20,6 +20,10 @@ namespace System.Net.Http.Functional.Tests { using Configuration = System.Net.Test.Common.Configuration; +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + public abstract partial class HttpClientHandler_ServerCertificates_Test : HttpClientHandlerTestBase { private static bool ClientSupportsDHECipherSuites => (!PlatformDetection.IsWindows || PlatformDetection.IsWindows10Version1607OrGreater); @@ -78,6 +82,12 @@ public async Task NoCallback_ValidCertificate_SuccessAndExpectedPropertyBehavior [Fact] public async Task UseCallback_HaveCredsAndUseAuthenticatedCustomProxyAndPostToSecureServer_Success() { + if (IsWinHttpHandler && PlatformDetection.IsWindows7) + { + // Issue https://github.com/dotnet/corefx/issues/27612 + return; + } + var options = new LoopbackProxyServer.Options { AuthenticationSchemes = AuthenticationSchemes.Basic, ConnectionCloseAfter407 = true diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.SslProtocols.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.SslProtocols.cs similarity index 94% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.SslProtocols.cs rename to src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.SslProtocols.cs index 08920e556c869..104f920f2531d 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.SslProtocols.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.SslProtocols.cs @@ -17,6 +17,10 @@ namespace System.Net.Http.Functional.Tests { using Configuration = System.Net.Test.Common.Configuration; +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + public abstract partial class HttpClientHandler_SslProtocols_Test : HttpClientHandlerTestBase { public HttpClientHandler_SslProtocols_Test(ITestOutputHelper output) : base(output) { } @@ -101,7 +105,7 @@ public static IEnumerable GetAsync_AllowedSSLVersion_Succeeds_MemberDa } } - [ConditionalTheory] + [Theory] [MemberData(nameof(GetAsync_AllowedSSLVersion_Succeeds_MemberData))] public async Task GetAsync_AllowedSSLVersion_Succeeds(SslProtocols acceptedProtocol, bool requestOnlyThisProtocol) { @@ -240,6 +244,17 @@ await TestHelper.WhenAllCompletedOrAnyFailed( public async Task GetAsync_AllowedClientSslVersionDiffersFromServer_ThrowsException( SslProtocols allowedClientProtocols, SslProtocols acceptedServerProtocols) { + if (IsWinHttpHandler && + allowedClientProtocols == (SslProtocols.Tls11 | SslProtocols.Tls12) && + acceptedServerProtocols == SslProtocols.Tls) + { + // Native WinHTTP sometimes uses multiple TCP connections to try other TLS protocols when + // getting TLS protocol failures as part of its TLS fallback algorithm. The loopback server + // doesn't expect this and stops listening for more connections. This causes unexpected test + // failures. See dotnet/corefx https://github.com/dotnet/corefx/issues/8538. + return; + } + using (HttpClientHandler handler = CreateHttpClientHandler()) using (HttpClient client = CreateHttpClient(handler)) { diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs similarity index 98% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.cs rename to src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs index 35b8720206e56..9b65dbe084c0b 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs @@ -24,6 +24,10 @@ namespace System.Net.Http.Functional.Tests { using Configuration = System.Net.Test.Common.Configuration; +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + // Note: Disposing the HttpClient object automatically disposes the handler within. So, it is not necessary // to separately Dispose (or have a 'using' statement) for the handler. public abstract class HttpClientHandlerTest : HttpClientHandlerTestBase @@ -141,6 +145,7 @@ public void MaxAutomaticRedirections_InvalidValue_Throws(int redirects) } } +#if !WINHTTPHANDLER_TEST [Theory] [InlineData(-1)] [InlineData((long)int.MaxValue + (long)1)] @@ -151,6 +156,7 @@ public void MaxRequestContentBufferSize_SetInvalidValue_ThrowsArgumentOutOfRange Assert.Throws(() => handler.MaxRequestContentBufferSize = value); } } +#endif [OuterLoop("Uses external servers")] [Theory] @@ -419,6 +425,11 @@ await LoopbackServer.CreateClientAndServerAsync(async proxyUri => [OuterLoop("Uses external server")] public async Task ProxyTunnelRequest_UserAgentHeaderAdded(bool addUserAgentHeader) { + if (IsWinHttpHandler) + { + return; // Skip test since the fix is only in SocketsHttpHandler. + } + string addressUri = $"https://{Configuration.Http.SecureHost}/"; bool connectionAccepted = false; @@ -574,6 +585,11 @@ await LoopbackServerFactory.CreateServerAsync(async (server, url) => [MemberData(nameof(RemoteServersAndHeaderEchoUrisMemberData))] public async Task GetAsync_RequestHeadersAddCustomHeaders_HeaderAndEmptyValueSent(Configuration.Http.RemoteServer remoteServer, Uri uri) { + if (IsWinHttpHandler && !PlatformDetection.IsWindows10Version1709OrGreater) + { + return; + } + string name = "X-Cust-Header-NoValue"; string value = ""; using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer)) @@ -699,6 +715,12 @@ await LoopbackServer.CreateClientAndServerAsync(async uri => [InlineData(true, true)] public async Task GetAsync_IncompleteData_ThrowsHttpRequestException(bool failDuringHeaders, bool getString) { + if (IsWinHttpHandler) + { + // [ActiveIssue("https://github.com/dotnet/corefx/issues/39136")] + return; + } + await LoopbackServer.CreateClientAndServerAsync(async uri => { using (HttpClient client = CreateHttpClient()) @@ -1799,14 +1821,17 @@ public async Task PostAsync_ExpectContinue_Success(bool? expectContinue, string { Assert.Equal(HttpStatusCode.OK, response.StatusCode); - const string ExpectedReqHeader = "\"Expect\": \"100-continue\""; - if (expectContinue == true && (version == "1.1" || version == "2.0")) - { - Assert.Contains(ExpectedReqHeader, await response.Content.ReadAsStringAsync()); - } - else + if (!IsWinHttpHandler) { - Assert.DoesNotContain(ExpectedReqHeader, await response.Content.ReadAsStringAsync()); + const string ExpectedReqHeader = "\"Expect\": \"100-continue\""; + if (expectContinue == true && (version == "1.1" || version == "2.0")) + { + Assert.Contains(ExpectedReqHeader, await response.Content.ReadAsStringAsync()); + } + else + { + Assert.DoesNotContain(ExpectedReqHeader, await response.Content.ReadAsStringAsync()); + } } } } @@ -2037,6 +2062,13 @@ await server.AcceptConnectionAsync(async connection => [ConditionalFact] public async Task SendAsync_101SwitchingProtocolsResponse_Success() { + // WinHttpHandler and CurlHandler will hang, waiting for additional response. + // Other handlers will accept 101 as a final response. + if (IsWinHttpHandler) + { + return; + } + if (LoopbackServerFactory.IsHttp2) { throw new SkipTestException("Upgrade is not supported on HTTP/2"); @@ -2369,9 +2401,14 @@ public async Task SendAsync_RequestVersion11_ServerReceivesVersion11Request() [OuterLoop("Uses external server")] [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public async Task SendAsync_RequestVersionNotSpecified_ServerReceivesVersion11Request() { + // SocketsHttpHandler treats 0.0 as a bad version, and throws. + if (!IsWinHttpHandler) + { + return; + } + // The default value for HttpRequestMessage.Version is Version(1,1). // So, we need to set something different (0,0), to test the "unknown" version. Version receivedRequestVersion = await SendRequestAndGetRequestVersionAsync(new Version(0, 0)); @@ -2379,7 +2416,7 @@ public async Task SendAsync_RequestVersionNotSpecified_ServerReceivesVersion11Re } [OuterLoop("Uses external server")] - [ConditionalTheory] + [Theory] [MemberData(nameof(Http2Servers))] public async Task SendAsync_RequestVersion20_ResponseVersion20IfHttp2Supported(Uri server) { diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTestBase.cs similarity index 74% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.cs rename to src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTestBase.cs index 8f56613816c73..66cd3726ea3ed 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTestBase.cs @@ -3,20 +3,21 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Net.Test.Common; -using System.Reflection; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.PlatformAbstractions; using Xunit.Abstractions; namespace System.Net.Http.Functional.Tests { using Configuration = System.Net.Test.Common.Configuration; - public abstract class HttpClientHandlerTestBase : FileCleanupTestBase +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + + public abstract partial class HttpClientHandlerTestBase : FileCleanupTestBase { public readonly ITestOutputHelper _output; @@ -42,30 +43,6 @@ protected static HttpClient CreateHttpClient(string useHttp2String) => protected static HttpClient CreateHttpClient(HttpMessageHandler handler, string useHttp2String) => new HttpClient(handler) { DefaultRequestVersion = GetVersion(bool.Parse(useHttp2String)) }; - protected HttpClientHandler CreateHttpClientHandler() => CreateHttpClientHandler(UseHttp2); - - protected static HttpClientHandler CreateHttpClientHandler(string useHttp2LoopbackServerString) => - CreateHttpClientHandler(bool.Parse(useHttp2LoopbackServerString)); - - protected static HttpClientHandler CreateHttpClientHandler(bool useHttp2LoopbackServer = false) - { - HttpClientHandler handler = new HttpClientHandler(); - - if (useHttp2LoopbackServer) - { - TestHelper.EnableUnencryptedHttp2IfNecessary(handler); - handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates; - } - - return handler; - } - - protected static object GetUnderlyingSocketsHttpHandler(HttpClientHandler handler) - { - FieldInfo field = typeof(HttpClientHandler).GetField("_socketsHttpHandler", BindingFlags.Instance | BindingFlags.NonPublic); - return field?.GetValue(handler); - } - protected LoopbackServerFactory LoopbackServerFactory => #if NETCOREAPP UseHttp2 ? @@ -82,13 +59,13 @@ protected HttpClient CreateHttpClientForRemoteServer(Configuration.Http.RemoteSe return CreateHttpClientForRemoteServer(remoteServer, CreateHttpClientHandler()); } - protected HttpClient CreateHttpClientForRemoteServer(Configuration.Http.RemoteServer remoteServer, HttpClientHandler httpClientHandler) + protected HttpClient CreateHttpClientForRemoteServer(Configuration.Http.RemoteServer remoteServer, HttpMessageHandler httpClientHandler) { HttpMessageHandler wrappedHandler = httpClientHandler; // WinHttpHandler will downgrade to 1.1 if you set Transfer-Encoding: chunked. // So, skip this verification if we're not using SocketsHttpHandler. - if (PlatformDetection.SupportsAlpn) + if (PlatformDetection.SupportsAlpn && !IsWinHttpHandler) { wrappedHandler = new VersionCheckerHttpHandler(httpClientHandler, remoteServer.HttpVersion); } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpProtocolTests.cs b/src/libraries/Common/tests/System/Net/Http/HttpProtocolTests.cs similarity index 91% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpProtocolTests.cs rename to src/libraries/Common/tests/System/Net/Http/HttpProtocolTests.cs index 76211456d3871..5e5047a45becc 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpProtocolTests.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpProtocolTests.cs @@ -77,7 +77,17 @@ await LoopbackServer.CreateServerAsync(async (server, url) => Task getResponseTask = client.SendAsync(request); Task> serverTask = server.AcceptConnectionSendResponseAndCloseAsync(); - await Assert.ThrowsAsync(() => TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask)); + + if (IsWinHttpHandler) + { + await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); + var requestLines = await serverTask; + Assert.Equal($"GET {url.PathAndQuery} HTTP/1.1", requestLines[0]); + } + else + { + await Assert.ThrowsAsync(() => TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask)); + } } }, new LoopbackServer.Options { StreamWrapper = GetStream_ClientDisconnectOk}); } @@ -166,9 +176,17 @@ await LoopbackServer.CreateServerAsync(async (server, url) => await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); using (HttpResponseMessage response = await getResponseTask) - { - Assert.Equal(1, response.Version.Major); - Assert.Equal(responseMinorVersion, response.Version.Minor); + { + if (IsWinHttpHandler) + { + Assert.Equal(0, response.Version.Major); + Assert.Equal(0, response.Version.Minor); + } + else + { + Assert.Equal(1, response.Version.Major); + Assert.Equal(responseMinorVersion, response.Version.Minor); + } } } }, new LoopbackServer.Options { StreamWrapper = GetStream }); @@ -251,16 +269,29 @@ await LoopbackServer.CreateServerAsync(async (server, url) => [InlineData("HTTP/1.1 600 still valid", 600, "still valid")] public async Task GetAsync_ExpectedStatusCodeAndReason_Success(string statusLine, int expectedStatusCode, string expectedReason) { + if (IsWinHttpHandler) + { + return; + } + await GetAsyncSuccessHelper(statusLine, expectedStatusCode, expectedReason); } [Theory] [InlineData("HTTP/1.1 200 ", 200, " ")] [InlineData("HTTP/1.1 200 Something", 200, " Something")] - public async Task GetAsync_ExpectedStatusCodeAndReason_PlatformBehaviorTest(string statusLine, int expectedStatusCode, string reasonWithSpace) + public async Task GetAsync_ExpectedStatusCodeAndReason_PlatformBehaviorTest(string statusLine, int expectedStatusCode, string reason) { - // SocketsHttpHandler and .NET Framework will keep the space characters. - await GetAsyncSuccessHelper(statusLine, expectedStatusCode, reasonWithSpace); + if (IsWinHttpHandler) + { + // WinHttpHandler will trim space characters. + await GetAsyncSuccessHelper(statusLine, expectedStatusCode, reason.Trim()); + } + else + { + // SocketsHttpHandler and .NET Framework will keep the space characters. + await GetAsyncSuccessHelper(statusLine, expectedStatusCode, reason); + } } [Theory] @@ -351,8 +382,12 @@ public async Task GetAsync_ReasonPhraseHasLF_BehaviorDifference() [InlineData("HTTP/1.1 200\t")] public async Task GetAsync_InvalidStatusLine_ThrowsExceptionOnSocketsHttpHandler(string responseString) { - // SocketsHttpHandler and .NET Framework will throw HttpRequestException. - await GetAsyncThrowsExceptionHelper(responseString); + if (!IsWinHttpHandler) + { + // SocketsHttpHandler and .NET Framework will throw HttpRequestException. + await GetAsyncThrowsExceptionHelper(responseString); + } + // WinHttpHandler will succeed. } private async Task GetAsyncThrowsExceptionHelper(string responseString) @@ -407,6 +442,11 @@ public static IEnumerable GetAsync_Chunked_VaryingSizeChunks_ReceivedC [MemberData(nameof(GetAsync_Chunked_VaryingSizeChunks_ReceivedCorrectly_MemberData))] public async Task GetAsync_Chunked_VaryingSizeChunks_ReceivedCorrectly(int maxChunkSize, string lineEnding, bool useCopyToAsync) { + if (IsWinHttpHandler) + { + return; + } + var rand = new Random(42); byte[] expectedData = new byte[100_000]; rand.NextBytes(expectedData); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpRetryProtocolTests.cs b/src/libraries/Common/tests/System/Net/Http/HttpRetryProtocolTests.cs similarity index 94% rename from src/libraries/System.Net.Http/tests/FunctionalTests/HttpRetryProtocolTests.cs rename to src/libraries/Common/tests/System/Net/Http/HttpRetryProtocolTests.cs index 230eb33221321..36f6e826f199c 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpRetryProtocolTests.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpRetryProtocolTests.cs @@ -22,6 +22,12 @@ public HttpRetryProtocolTests(ITestOutputHelper output) : base(output) { } [Fact] public async Task GetAsync_RetryOnConnectionClosed_Success() { + if (IsWinHttpHandler) + { + // WinHttpHandler does not support Expect: 100-continue. + return; + } + await LoopbackServer.CreateClientAndServerAsync(async url => { using (HttpClient client = CreateHttpClient()) @@ -58,6 +64,12 @@ await server.AcceptConnectionAsync(async connection => [Fact] public async Task PostAsyncExpect100Continue_FailsAfterContentSendStarted_Throws() { + if (IsWinHttpHandler) + { + // WinHttpHandler does not support Expect: 100-continue. + return; + } + var contentSending = new TaskCompletionSource(); var connectionClosed = new TaskCompletionSource(); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/IdnaProtocolTests.cs b/src/libraries/Common/tests/System/Net/Http/IdnaProtocolTests.cs similarity index 98% rename from src/libraries/System.Net.Http/tests/FunctionalTests/IdnaProtocolTests.cs rename to src/libraries/Common/tests/System/Net/Http/IdnaProtocolTests.cs index 713e0c03d63f8..b745c946e649b 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/IdnaProtocolTests.cs +++ b/src/libraries/Common/tests/System/Net/Http/IdnaProtocolTests.cs @@ -10,6 +10,10 @@ namespace System.Net.Http.Functional.Tests { +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + public abstract class IdnaProtocolTests : HttpClientHandlerTestBase { protected abstract bool SupportsIdna { get; } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/PostScenarioTest.cs b/src/libraries/Common/tests/System/Net/Http/PostScenarioTest.cs similarity index 99% rename from src/libraries/System.Net.Http/tests/FunctionalTests/PostScenarioTest.cs rename to src/libraries/Common/tests/System/Net/Http/PostScenarioTest.cs index fd8542d76cc34..c7c343e3b7d37 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/PostScenarioTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/PostScenarioTest.cs @@ -14,6 +14,10 @@ namespace System.Net.Http.Functional.Tests { using Configuration = System.Net.Test.Common.Configuration; +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + // Note: Disposing the HttpClient object automatically disposes the handler within. So, it is not necessary // to separately Dispose (or have a 'using' statement) for the handler. public abstract class PostScenarioTest : HttpClientHandlerTestBase diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/RepeatedFlushContent.cs b/src/libraries/Common/tests/System/Net/Http/RepeatedFlushContent.cs similarity index 100% rename from src/libraries/System.Net.Http/tests/FunctionalTests/RepeatedFlushContent.cs rename to src/libraries/Common/tests/System/Net/Http/RepeatedFlushContent.cs diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/ResponseStreamTest.cs b/src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs similarity index 93% rename from src/libraries/System.Net.Http/tests/FunctionalTests/ResponseStreamTest.cs rename to src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs index c48eae28b97d2..8df08a7282145 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/ResponseStreamTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs @@ -196,16 +196,29 @@ await client.GetAsync(remoteServer.EchoUri, HttpCompletionOption.ResponseHeaders // Verify that the task completed. Assert.True(((IAsyncResult)task).AsyncWaitHandle.WaitOne(new TimeSpan(0, 5, 0))); Assert.True(task.IsCompleted, "Task was not yet completed"); - - if (task.IsFaulted) + + // Verify that the task completed successfully or is canceled. + if (IsWinHttpHandler) { - // Propagate exception for debugging - task.GetAwaiter().GetResult(); + // With WinHttpHandler, we may fault because canceling the task destroys the request handle + // which may randomly cause an ObjectDisposedException (or other exception). + Assert.True( + task.Status == TaskStatus.RanToCompletion || + task.Status == TaskStatus.Canceled || + task.Status == TaskStatus.Faulted); } + else + { + if (task.IsFaulted) + { + // Propagate exception for debugging + task.GetAwaiter().GetResult(); + } - Assert.True( - task.Status == TaskStatus.RanToCompletion || - task.Status == TaskStatus.Canceled); + Assert.True( + task.Status == TaskStatus.RanToCompletion || + task.Status == TaskStatus.Canceled); + } } } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SchSendAuxRecordHttpTest.cs b/src/libraries/Common/tests/System/Net/Http/SchSendAuxRecordHttpTest.cs similarity index 96% rename from src/libraries/System.Net.Http/tests/FunctionalTests/SchSendAuxRecordHttpTest.cs rename to src/libraries/Common/tests/System/Net/Http/SchSendAuxRecordHttpTest.cs index 51d64ca43708d..cd5b1790662e3 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/SchSendAuxRecordHttpTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/SchSendAuxRecordHttpTest.cs @@ -10,7 +10,11 @@ using Xunit.Abstractions; namespace System.Net.Http.Functional.Tests -{ +{ +#if WINHTTPHANDLER_TEST + using HttpClientHandler = System.Net.Http.WinHttpClientHandler; +#endif + [ActiveIssue("https://github.com/dotnet/corefx/issues/26539")] // Flaky test public abstract class SchSendAuxRecordHttpTest : HttpClientHandlerTestBase { diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SyncBlockingContent.cs b/src/libraries/Common/tests/System/Net/Http/SyncBlockingContent.cs similarity index 100% rename from src/libraries/System.Net.Http/tests/FunctionalTests/SyncBlockingContent.cs rename to src/libraries/Common/tests/System/Net/Http/SyncBlockingContent.cs diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/TestHelper.cs b/src/libraries/Common/tests/System/Net/Http/TestHelper.cs similarity index 97% rename from src/libraries/System.Net.Http/tests/FunctionalTests/TestHelper.cs rename to src/libraries/Common/tests/System/Net/Http/TestHelper.cs index 97ea7c7f94a06..4805ccd18554a 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/TestHelper.cs +++ b/src/libraries/Common/tests/System/Net/Http/TestHelper.cs @@ -128,11 +128,7 @@ public static void EnableUnencryptedHttp2IfNecessary(HttpClientHandler handler) } object socketsHttpHandler = socketsHttpHandlerField.GetValue(handler); - if (socketsHttpHandler == null) - { - // Not using SocketsHttpHandler, e.g. using WinHttpHandler. - return; - } + Assert.NotNull(socketsHttpHandler); // Get HttpConnectionSettings object from SocketsHttpHandler. Type socketsHttpHandlerType = typeof(HttpClientHandler).Assembly.GetType("System.Net.Http.SocketsHttpHandler"); diff --git a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/HttpClientHandlerTestBase.WinHttpHandler.cs b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/HttpClientHandlerTestBase.WinHttpHandler.cs new file mode 100644 index 0000000000000..367ad2e73232c --- /dev/null +++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/HttpClientHandlerTestBase.WinHttpHandler.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.IO; + +namespace System.Net.Http.Functional.Tests +{ + public abstract partial class HttpClientHandlerTestBase : FileCleanupTestBase + { + protected static bool IsWinHttpHandler => true; + + protected WinHttpClientHandler CreateHttpClientHandler() => CreateHttpClientHandler(UseHttp2); + + protected static WinHttpClientHandler CreateHttpClientHandler(string useHttp2LoopbackServerString) => + CreateHttpClientHandler(bool.Parse(useHttp2LoopbackServerString)); + + protected static WinHttpClientHandler CreateHttpClientHandler(bool useHttp2LoopbackServer = false) + { + WinHttpClientHandler handler = new WinHttpClientHandler(); + + if (useHttp2LoopbackServer) + { + handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates; + } + + return handler; + } + } +} \ No newline at end of file diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/PlatformHandlerTest.cs b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/PlatformHandlerTest.cs similarity index 68% rename from src/libraries/System.Net.Http/tests/FunctionalTests/PlatformHandlerTest.cs rename to src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/PlatformHandlerTest.cs index 874d227e6dc2e..499ba9bf5ae98 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/PlatformHandlerTest.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/PlatformHandlerTest.cs @@ -10,8 +10,6 @@ namespace System.Net.Http.Functional.Tests { - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public class PlatformHandler_HttpClientHandler : HttpClientHandlerTestBase { public PlatformHandler_HttpClientHandler(ITestOutputHelper output) : base(output) { } @@ -23,7 +21,7 @@ public async Task GetAsync_TrailingHeaders_Ignored(bool includeTrailerHeader) { await LoopbackServer.CreateServerAsync(async (server, url) => { - using (HttpClient client = CreateHttpClient()) + using (HttpClient client = CreateHttpClient(new WinHttpHandler())) { Task getResponseTask = client.GetAsync(url); await TestHelper.WhenAllCompletedOrAnyFailed( @@ -59,150 +57,103 @@ await TestHelper.WhenAllCompletedOrAnyFailed( } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_HttpClientHandler_Asynchrony_Test : HttpClientHandler_Asynchrony_Test { public PlatformHandler_HttpClientHandler_Asynchrony_Test(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_HttpProtocolTests : HttpProtocolTests { public PlatformHandler_HttpProtocolTests(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_HttpProtocolTests_Dribble : HttpProtocolTests_Dribble { public PlatformHandler_HttpProtocolTests_Dribble(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] - public sealed class PlatformHandler_DiagnosticsTest : DiagnosticsTest - { - public PlatformHandler_DiagnosticsTest(ITestOutputHelper output) : base(output) { } - } - - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_HttpClient_SelectedSites_Test : HttpClient_SelectedSites_Test { public PlatformHandler_HttpClient_SelectedSites_Test(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_HttpClientEKUTest : HttpClientEKUTest { public PlatformHandler_HttpClientEKUTest(ITestOutputHelper output) : base(output) { } } #if NETCOREAPP - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_HttpClientHandler_Decompression_Tests : HttpClientHandler_Decompression_Test { public PlatformHandler_HttpClientHandler_Decompression_Tests(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_HttpClientHandler_DangerousAcceptAllCertificatesValidator_Test : HttpClientHandler_DangerousAcceptAllCertificatesValidator_Test { public PlatformHandler_HttpClientHandler_DangerousAcceptAllCertificatesValidator_Test(ITestOutputHelper output) : base(output) { } } #endif - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_HttpClientHandler_ClientCertificates_Test : HttpClientHandler_ClientCertificates_Test { public PlatformHandler_HttpClientHandler_ClientCertificates_Test(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_HttpClientHandler_DefaultProxyCredentials_Test : HttpClientHandler_DefaultProxyCredentials_Test { public PlatformHandler_HttpClientHandler_DefaultProxyCredentials_Test(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_HttpClientHandler_MaxConnectionsPerServer_Test : HttpClientHandler_MaxConnectionsPerServer_Test { public PlatformHandler_HttpClientHandler_MaxConnectionsPerServer_Test(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_HttpClientHandler_ServerCertificates_Test : HttpClientHandler_ServerCertificates_Test { public PlatformHandler_HttpClientHandler_ServerCertificates_Test(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_PostScenarioTest : PostScenarioTest { public PlatformHandler_PostScenarioTest(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_ResponseStreamTest : ResponseStreamTest { public PlatformHandler_ResponseStreamTest(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_HttpClientHandler_SslProtocols_Test : HttpClientHandler_SslProtocols_Test { public PlatformHandler_HttpClientHandler_SslProtocols_Test(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_HttpClientHandler_Proxy_Test : HttpClientHandler_Proxy_Test { public PlatformHandler_HttpClientHandler_Proxy_Test(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_SchSendAuxRecordHttpTest : SchSendAuxRecordHttpTest { public PlatformHandler_SchSendAuxRecordHttpTest(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_HttpClientHandlerTest : HttpClientHandlerTest { public PlatformHandler_HttpClientHandlerTest(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandlerTest_AutoRedirect : HttpClientHandlerTest_AutoRedirect { public PlatformHandlerTest_AutoRedirect(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_DefaultCredentialsTest : DefaultCredentialsTest { public PlatformHandler_DefaultCredentialsTest(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_IdnaProtocolTests : IdnaProtocolTests { public PlatformHandler_IdnaProtocolTests(ITestOutputHelper output) : base(output) { } @@ -210,43 +161,31 @@ public PlatformHandler_IdnaProtocolTests(ITestOutputHelper output) : base(output protected override bool SupportsIdna => !PlatformDetection.IsWindows7; } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_HttpRetryProtocolTests : HttpRetryProtocolTests { public PlatformHandler_HttpRetryProtocolTests(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandlerTest_Cookies : HttpClientHandlerTest_Cookies { public PlatformHandlerTest_Cookies(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandlerTest_Cookies_Http11 : HttpClientHandlerTest_Cookies_Http11 { public PlatformHandlerTest_Cookies_Http11(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_HttpClientHandler_MaxResponseHeadersLength_Test : HttpClientHandler_MaxResponseHeadersLength_Test { public PlatformHandler_HttpClientHandler_MaxResponseHeadersLength_Test(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_HttpClientHandler_Cancellation_Test : HttpClientHandler_Cancellation_Test { public PlatformHandler_HttpClientHandler_Cancellation_Test(ITestOutputHelper output) : base(output) { } } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandler_HttpClientHandler_Authentication_Test : HttpClientHandler_Authentication_Test { public PlatformHandler_HttpClientHandler_Authentication_Test(ITestOutputHelper output) : base(output) { } @@ -254,14 +193,10 @@ public PlatformHandler_HttpClientHandler_Authentication_Test(ITestOutputHelper o // Enable this to run HTTP2 tests on platform handler #if PLATFORM_HANDLER_HTTP2_TESTS - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] public sealed class PlatformHandlerTest_Http2 : HttpClientHandlerTest_Http2 { } - // Test only WinHttpHandler since the CurlHandler was removed - [ActiveIssue("https://github.com/dotnet/runtime/issues/339")] [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.SupportsAlpn))] public sealed class PlatformHandlerTest_Cookies_Http2 : HttpClientHandlerTest_Cookies { diff --git a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/System.Net.Http.WinHttpHandler.Functional.Tests.csproj b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/System.Net.Http.WinHttpHandler.Functional.Tests.csproj index 68941aa696d33..a88721597b0f6 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/System.Net.Http.WinHttpHandler.Functional.Tests.csproj +++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/System.Net.Http.WinHttpHandler.Functional.Tests.csproj @@ -1,6 +1,8 @@ $(NetCoreAppCurrent)-Windows_NT-Debug;$(NetCoreAppCurrent)-Windows_NT-Release;$(NetFrameworkCurrent)-Windows_NT-Debug;$(NetFrameworkCurrent)-Windows_NT-Release + true + $(DefineConstants);WINHTTPHANDLER_TEST @@ -12,5 +14,181 @@ + + + + Common\System\Net\Http\HttpHandlerDefaults.cs + + + Common\System\IO\DelegateStream.cs + + + Common\System\Net\Configuration.Certificates.cs + + + Common\System\Net\Configuration.Security.cs + + + Common\System\Net\Configuration.Sockets.cs + + + Common\System\Net\Capability.Security.cs + + + Common\System\Net\Capability.Security.Windows.cs + + + Common\System\Net\EventSourceTestLogging.cs + + + Common\System\Net\HttpsTestServer.cs + + + Common\System\Net\RemoteServerQuery.cs + + + Common\System\Net\VerboseTestLogging.cs + + + Common\System\Net\TestWebProxies.cs + + + Common\System\Net\Http\ByteAtATimeContent.cs + + + Common\System\Net\Http\ChannelBindingAwareContent.cs + + + Common\System\Net\Http\CustomContent.cs + + + Common\System\Net\Http\DefaultCredentialsTest.cs + + + Common\System\Net\Http\DribbleStream.cs + + + Common\System\Net\Http\GenericLoopbackServer.cs + + + Common\System\Net\Http\HttpClientHandlerTestBase.cs + + + Common\System\Net\Http\Http2Frames.cs + + + Common\System\Net\Http\HPackEncoder.cs + + + Common\System\Net\Http\Http2LoopbackServer.cs + + + Common\System\Net\Http\Http2LoopbackConnection.cs + + + Common\System\Net\Http\HuffmanDecoder.cs + + + Common\System\Net\Http\HuffmanEncoder.cs + + + Common\System\Net\Http\HttpClientHandlerTest.cs + + + Common\System\Net\Http\HttpClientHandlerTest.AcceptAllCerts.cs + + + Common\System\Net\Http\HttpClientHandlerTest.Asynchrony.cs + + + Common\System\Net\Http\HttpClientHandlerTest.Authentication.cs + + + Common\System\Net\Http\HttpClientHandlerTest.AutoRedirect.cs + + + Common\System\Net\Http\HttpClientHandlerTest.Cancellation.cs + + + Common\System\Net\Http\HttpClientHandlerTest.ClientCertificates.cs + + + Common\System\Net\Http\HttpClientHandlerTest.Cookies.cs + + + Common\System\Net\Http\HttpClientHandlerTest.Decompression.cs + + + Common\System\Net\Http\HttpClientHandlerTest.DefaultProxyCredentials.cs + + + Common\System\Net\Http\HttpClientHandlerTest.MaxConnectionsPerServer.cs + + + Common\System\Net\Http\HttpClientHandlerTest.MaxResponseHeadersLength.cs + + + Common\System\Net\Http\HttpClientHandlerTest.Proxy.cs + + + Common\System\Net\Http\HttpClientHandlerTest.ServerCertificates.cs + + + Common\System\Net\Http\HttpClientHandlerTest.SslProtocols.cs + + + Common\System\Net\Http\HttpProtocolTests.cs + + + Common\System\Net\Http\HttpClient.SelectedSitesTest.cs + + + Common\System\Net\Http\HttpClientEKUTest.cs + + + Common\System\Net\Http\HttpRetryProtocolTests.cs + + + Common\System\Net\Http\IdnaProtocolTests.cs + + + Common\System\Net\Http\LoopbackProxyServer.cs + + + Common\System\Net\Http\LoopbackServer.cs + + + Common\System\Net\Http\LoopbackServer.AuthenticationHelpers.cs + + + Common\System\Net\Http\TestHelper.cs + + + Common\System\Net\Http\PostScenarioTest.cs + + + Common\System\Net\Http\RepeatedFlushContent.cs + + + Common\System\Net\Http\ResponseStreamTest.cs + + + Common\System\Net\Http\SchSendAuxRecordHttpTest.cs + + + Common\System\Net\Http\SyncBlockingContent.cs + + + Common\System\Threading\Tasks\TaskTimeoutExtensions.cs + + + Common\System\Threading\TrackingSynchronizationContext.cs + + + + + + + \ No newline at end of file diff --git a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/WinHttpClientHandler.cs b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/WinHttpClientHandler.cs new file mode 100644 index 0000000000000..2f8ccd311a3d0 --- /dev/null +++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/WinHttpClientHandler.cs @@ -0,0 +1,184 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Net.Security; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Http +{ + // Only for testing purposes. + // Contains HttpClientHandler.Windows.cs code from before its System.Net.Http removal. + // Follows HttpClientHandler contract so that its tests can be easily reused for WinHttpHandler. + // The only difference is in removal of DiagnosticsHandler since it's internal to System.Net.Http. + public class WinHttpClientHandler : WinHttpHandler + { + private bool _useProxy; + + public WinHttpClientHandler() + { + // Adjust defaults to match current .NET Desktop HttpClientHandler (based on HWR stack). + AllowAutoRedirect = true; + AutomaticDecompression = HttpHandlerDefaults.DefaultAutomaticDecompression; + UseProxy = true; + UseCookies = true; + CookieContainer = new CookieContainer(); + DefaultProxyCredentials = null; + ServerCredentials = null; + + // The existing .NET Desktop HttpClientHandler based on the HWR stack uses only WinINet registry + // settings for the proxy. This also includes supporting the "Automatic Detect a proxy" using + // WPAD protocol and PAC file. So, for app-compat, we will do the same for the default proxy setting. + WindowsProxyUsePolicy = WindowsProxyUsePolicy.UseWinInetProxy; + Proxy = null; + + // Since the granular WinHttpHandler timeout properties are not exposed via the HttpClientHandler API, + // we need to set them to infinite and allow the HttpClient.Timeout property to have precedence. + ReceiveHeadersTimeout = Timeout.InfiniteTimeSpan; + ReceiveDataTimeout = Timeout.InfiniteTimeSpan; + SendTimeout = Timeout.InfiniteTimeSpan; + } + + public virtual bool SupportsAutomaticDecompression => true; + public virtual bool SupportsProxy => true; + public virtual bool SupportsRedirectConfiguration => true; + + public bool UseCookies + { + get => CookieUsePolicy == CookieUsePolicy.UseSpecifiedCookieContainer; + set => CookieUsePolicy = value ? CookieUsePolicy.UseSpecifiedCookieContainer : CookieUsePolicy.IgnoreCookies; + } + + public new CookieContainer CookieContainer + { + get => base.CookieContainer; + set + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + base.CookieContainer = value; + } + } + + public bool UseProxy + { + get => _useProxy; + set => _useProxy = value; + } + + public bool UseDefaultCredentials + { + // WinHttpHandler doesn't have a separate UseDefaultCredentials property. There + // is just a ServerCredentials property. So, we need to map the behavior. + // Do the same for SocketsHttpHandler.Credentials. + // + // This property only affect .ServerCredentials and not .DefaultProxyCredentials. + get => ServerCredentials == CredentialCache.DefaultCredentials; + set + { + if (value) + { + ServerCredentials = CredentialCache.DefaultCredentials; + } + else + { + if (ServerCredentials == CredentialCache.DefaultCredentials) + { + // Only clear out the ServerCredentials property if it was a DefaultCredentials. + ServerCredentials = null; + } + } + } + } + + public ICredentials Credentials + { + get => ServerCredentials; + set => ServerCredentials = value; + } + + public bool AllowAutoRedirect + { + get => AutomaticRedirection; + set => AutomaticRedirection = value; + } + + public long MaxRequestContentBufferSize + { + // This property is not supported. In the .NET Framework it was only used when the handler needed to + // automatically buffer the request content. That only happened if neither 'Content-Length' nor + // 'Transfer-Encoding: chunked' request headers were specified. So, the handler thus needed to buffer + // in the request content to determine its length and then would choose 'Content-Length' semantics when + // POST'ing. In .NET Core, the handler will resolve the ambiguity by always choosing + // 'Transfer-Encoding: chunked'. The handler will never automatically buffer in the request content. + get + { + return 0; // Returning zero is appropriate since in .NET Framework it means no limit. + } + + set + { + if (value < 0 || value > int.MaxValue) + { + throw new ArgumentOutOfRangeException(nameof(value)); + } + + // No-op on property setter. + } + } + + public ClientCertificateOption ClientCertificateOptions + { + get => ClientCertificateOption; + set => ClientCertificateOption = value; + } + + public Func ServerCertificateCustomValidationCallback + { + get => ServerCertificateValidationCallback; + set => ServerCertificateValidationCallback = value; + } + + public static Func DangerousAcceptAnyServerCertificateValidator { get; } = delegate { return true; }; + + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + // Get current value of WindowsProxyUsePolicy. Only call its WinHttpHandler + // property setter if the value needs to change. + var oldProxyUsePolicy = base.WindowsProxyUsePolicy; + + if (_useProxy) + { + if (base.Proxy == null) + { + if (oldProxyUsePolicy != WindowsProxyUsePolicy.UseWinInetProxy) + { + base.WindowsProxyUsePolicy = WindowsProxyUsePolicy.UseWinInetProxy; + } + } + else + { + if (oldProxyUsePolicy != WindowsProxyUsePolicy.UseCustomProxy) + { + base.WindowsProxyUsePolicy = WindowsProxyUsePolicy.UseCustomProxy; + } + } + } + else + { + if (oldProxyUsePolicy != WindowsProxyUsePolicy.DoNotUseProxy) + { + base.WindowsProxyUsePolicy = WindowsProxyUsePolicy.DoNotUseProxy; + } + } + + return base.SendAsync(request, cancellationToken); + } + } +} diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs new file mode 100644 index 0000000000000..d57b9e6f19aba --- /dev/null +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.IO; +using System.Reflection; + +namespace System.Net.Http.Functional.Tests +{ + public abstract partial class HttpClientHandlerTestBase : FileCleanupTestBase + { + protected static bool IsWinHttpHandler => false; + + protected HttpClientHandler CreateHttpClientHandler() => CreateHttpClientHandler(UseHttp2); + + protected static HttpClientHandler CreateHttpClientHandler(string useHttp2LoopbackServerString) => + CreateHttpClientHandler(bool.Parse(useHttp2LoopbackServerString)); + + protected static HttpClientHandler CreateHttpClientHandler(bool useHttp2LoopbackServer = false) + { + HttpClientHandler handler = new HttpClientHandler(); + + if (useHttp2LoopbackServer) + { + TestHelper.EnableUnencryptedHttp2IfNecessary(handler); + handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates; + } + + return handler; + } + + protected static object GetUnderlyingSocketsHttpHandler(HttpClientHandler handler) + { + FieldInfo field = typeof(HttpClientHandler).GetField("_socketsHttpHandler", BindingFlags.Instance | BindingFlags.NonPublic); + return field?.GetValue(handler); + } + } +} diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/PostScenarioUWPTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/PostScenarioUWPTest.cs deleted file mode 100644 index 347ad9a158e00..0000000000000 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/PostScenarioUWPTest.cs +++ /dev/null @@ -1,148 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics; -using System.IO; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using Microsoft.DotNet.RemoteExecutor; -using Xunit; -using Xunit.Abstractions; - -namespace System.Net.Http.Functional.Tests -{ - using Configuration = System.Net.Test.Common.Configuration; - - public abstract class PostScenarioUWPTest : HttpClientHandlerTestBase - { - public PostScenarioUWPTest(ITestOutputHelper output) : base(output) { } - - [Fact] - public void Authentication_UseStreamContent_Throws() - { - RemoteExecutor.Invoke(async (useHttp2String) => - { - // This test validates the current limitation of CoreFx's NetFxToWinRtStreamAdapter - // which throws exceptions when trying to rewind a .NET Stream when it needs to be - // re-POST'd to the server. - string username = "testuser"; - string password = "password"; - Uri uri = Configuration.Http.RemoteHttp11Server.BasicAuthUriForCreds(userName: username, password: password); - HttpClientHandler handler = CreateHttpClientHandler(useHttp2String); - handler.Credentials = new NetworkCredential(username, password); - - using (HttpClient client = CreateHttpClient(handler, useHttp2String)) - { - byte[] postData = Encoding.UTF8.GetBytes("This is data to post."); - var stream = new MemoryStream(postData, false); - var content = new StreamContent(stream); - - await Assert.ThrowsAsync(() => client.PostAsync(uri, content)); - } - }, UseHttp2.ToString()).Dispose(); - } - - [Fact] - public void Authentication_UseMultiInterfaceNonRewindableStreamContent_Throws() - { - RemoteExecutor.Invoke(async (useHttp2String) => - { - string username = "testuser"; - string password = "password"; - Uri uri = Configuration.Http.RemoteHttp11Server.BasicAuthUriForCreds(userName: username, password: password); - HttpClientHandler handler = CreateHttpClientHandler(useHttp2String); - handler.Credentials = new NetworkCredential(username, password); - - using (HttpClient client = CreateHttpClient(handler, useHttp2String)) - { - byte[] postData = Encoding.UTF8.GetBytes("This is data to post."); - var stream = new MultiInterfaceNonRewindableReadOnlyStream(postData); - var content = new MultiInterfaceStreamContent(stream); - - await Assert.ThrowsAsync(() => client.PostAsync(uri, content)); - } - }, UseHttp2.ToString()).Dispose(); - } - - [Fact] - public void Authentication_UseMultiInterfaceStreamContent_Success() - { - RemoteExecutor.Invoke(async (useHttp2String) => - { - string username = "testuser"; - string password = "password"; - Uri uri = Configuration.Http.RemoteHttp11Server.BasicAuthUriForCreds(userName: username, password: password); - HttpClientHandler handler = CreateHttpClientHandler(useHttp2String); - handler.Credentials = new NetworkCredential(username, password); - - using (HttpClient client = CreateHttpClient(handler, useHttp2String)) - { - byte[] postData = Encoding.UTF8.GetBytes("This is data to post."); - var stream = new MultiInterfaceReadOnlyStream(postData); - var content = new MultiInterfaceStreamContent(stream); - - using (HttpResponseMessage response = await client.PostAsync(uri, content)) - { - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - string responseContent = await response.Content.ReadAsStringAsync(); - } - } - }, UseHttp2.ToString()).Dispose(); - } - - [Fact] - public void Authentication_UseMemoryStreamVisibleBufferContent_Success() - { - RemoteExecutor.Invoke(async (useHttp2String) => - { - string username = "testuser"; - string password = "password"; - Uri uri = Configuration.Http.RemoteHttp11Server.BasicAuthUriForCreds(userName: username, password: password); - HttpClientHandler handler = CreateHttpClientHandler(useHttp2String); - handler.Credentials = new NetworkCredential(username, password); - - using (HttpClient client = CreateHttpClient(handler, useHttp2String)) - { - byte[] postData = Encoding.UTF8.GetBytes("This is data to post."); - var stream = new MemoryStream(postData, 0, postData.Length, false, true); - var content = new MultiInterfaceStreamContent(stream); - - using (HttpResponseMessage response = await client.PostAsync(uri, content)) - { - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - string responseContent = await response.Content.ReadAsStringAsync(); - } - } - }, UseHttp2.ToString()).Dispose(); - } - - [Fact] - public void Authentication_UseMemoryStreamNotVisibleBufferContent_Success() - { - RemoteExecutor.Invoke(async (useHttp2String) => - { - string username = "testuser"; - string password = "password"; - Uri uri = Configuration.Http.RemoteHttp11Server.BasicAuthUriForCreds(userName: username, password: password); - HttpClientHandler handler = CreateHttpClientHandler(useHttp2String); - handler.Credentials = new NetworkCredential(username, password); - - using (HttpClient client = CreateHttpClient(handler, useHttp2String)) - { - byte[] postData = Encoding.UTF8.GetBytes("This is data to post."); - var stream = new MemoryStream(postData, 0, postData.Length, false, false); - var content = new MultiInterfaceStreamContent(stream); - - using (HttpResponseMessage response = await client.PostAsync(uri, content)) - { - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - string responseContent = await response.Content.ReadAsStringAsync(); - } - } - }, UseHttp2.ToString()).Dispose(); - } - } -} diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj index 0b68363a2fea0..75d2181b9cde6 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj @@ -76,6 +76,12 @@ Common\System\Net\Http\GenericLoopbackServer.cs + + Common\System\Net\Http\HttpClientHandlerTestBase.cs + + + Common\System\Net\Http\TestHelper.cs + Common\System\Threading\TrackingSynchronizationContext.cs @@ -87,56 +93,110 @@ - - - + + Common\System\Net\Http\ChannelBindingAwareContent.cs + + + Common\System\Net\Http\DribbleStream.cs + + + Common\System\Net\Http\CustomContent.cs + - - - - - - - - - + + Common\System\Net\Http\ByteAtATimeContent.cs + + + Common\System\Net\Http\HttpClientHandlerTest.cs + + + Common\System\Net\Http\HttpClientHandlerTest.Asynchrony.cs + + + Common\System\Net\Http\HttpClientHandlerTest.Authentication.cs + + + Common\System\Net\Http\HttpClientHandlerTest.AutoRedirect.cs + + + Common\System\Net\Http\HttpClientHandlerTest.Cancellation.cs + + + Common\System\Net\Http\HttpClientHandlerTest.ClientCertificates.cs + + + Common\System\Net\Http\HttpClientHandlerTest.Cookies.cs + + + Common\System\Net\Http\HttpClientHandlerTest.DefaultProxyCredentials.cs + - - - + + Common\System\Net\Http\HttpClientHandlerTest.MaxConnectionsPerServer.cs + + + Common\System\Net\Http\HttpClientHandlerTest.MaxResponseHeadersLength.cs + + + Common\System\Net\Http\HttpClientHandlerTest.Proxy.cs + - - + + Common\System\Net\Http\HttpClientHandlerTest.ServerCertificates.cs + + + Common\System\Net\Http\HttpClientHandlerTest.SslProtocols.cs + + - - - + + Common\System\Net\Http\HttpClientEKUTest.cs + + + Common\System\Net\Http\HttpClient.SelectedSitesTest.cs + - - - + + Common\System\Net\Http\HttpRetryProtocolTests.cs + + + Common\System\Net\Http\IdnaProtocolTests.cs + + + Common\System\Net\Http\HttpProtocolTests.cs + - - - - - + + Common\System\Net\Http\PostScenarioTest.cs + + + Common\System\Net\Http\RepeatedFlushContent.cs + + + Common\System\Net\Http\ResponseStreamTest.cs + + + Common\System\Net\Http\SchSendAuxRecordHttpTest.cs + - - - + + Common\System\Net\Http\SyncBlockingContent.cs + + + Common\System\Net\Http\DefaultCredentialsTest.cs + @@ -145,8 +205,12 @@ - - + + Common\System\Net\Http\HttpClientHandlerTest.AcceptAllCerts.cs + + + Common\System\Net\Http\HttpClientHandlerTest.Decompression.cs +