Split transport-specific tests and general tests into distinct test projects (#1588).
* Rename EngineTests to LibuvTransportTests.
* Move libuv-specific tests into their own test project.
* Move LibuvOutputConsumerTests.AllocCommitCanBeCalledAfterConnectionClose to new OutputProducerTests class and rename it to WritesNoopAfterConnectionCloses.
* Remove TransportContext from TestServiceContext.
* Make KestrelTests depend on Kestrel.Core only.
* Rename Microsoft.AspNetCore.Server.Kestrel.KestrelTests to Microsoft.AspNetCore.Server.Kestrel.Core.Tests.
* Add Microsoft.AspNetCore.Server.Kestrel.Tests test project for WebHostBuilderKestrelExtensionsTests.
* Increase socket receive timeout in MaxRequestBufferSizeTests to mitigate flakiness.
* Anything using TestServer should be a functional test.
* Move out of LibuvTransportTests tests that are not specific to LibuvTransport.
- Move to RequestTests:
- Http11 (rename to Http11KeptAliveByDefault)
- Http10ContentLength (rename to Http10NotKeptAliveByDefault)
- Http10KeepAlive
- Http10KeepAliveNotUsedIfResponseContentLengthNotSet (rename to Http10KeepAliveNotHonoredIfResponseContentLengthNotSet)
- Http10ContentLengthKeepAlive (rename to Http10KeepAliveHonoredIfResponseContentLengthSet)
- Expect100ContinueForBody (rename to Expect100ContinueHonored)
- ZeroContentLengthAssumedOnNonKeepAliveRequestsWithoutContentLengthOrTransferEncodingHeader
- ConnectionClosesWhenFinReceivedBeforeRequestCompletes (test was actually not marked as Theory, and was incorrect)
- RequestsCanBeAbortedMidRead
- RequestHeadersAreResetOnEachRequest
- UpgradeRequestIsNotKeptAliveOrChunked
- HeadersAndStreamsAreReused (rename to HeadersAndStreamsAreReusedAcrossRequests)
- Move to ResponseTests:
- Http10RequestReceivesHttp11Response (rename to Http11ResponseSentToHttp10Request)
- ZeroContentLengthSetAutomaticallyAfterNoWrites
- ZeroContentLengthSetAutomaticallyForNonKeepAliveRequests
- ZeroContentLengthNotSetAutomaticallyForHeadRequests
- ZeroContentLengthNotSetAutomaticallyForCertainStatusCodes
- ConnectionClosedAfter101Response
- ThrowingResultsIn500Response
- ThrowingAfterWritingKillsConnection
- ThrowingAfterPartialWriteKillsConnection
- ThrowingInOnStartingResultsInFailedWritesAnd500Response
- ThrowingInOnCompletedIsLoggedAndClosesConnection
- FailedWritesResultInAbortedRequest
- NoErrorsLoggedWhenServerEndsConnectionBeforeClient
- NoResponseSentWhenConnectionIsClosedByServerBeforeClientFinishesSendingRequest
- ResponseHeadersAreResetOnEachRequest
- OnStartingCallbacksAreCalledInLastInFirstOutOrder
- OnCompletedCallbacksAreCalledInLastInFirstOutOrder
- Remove:
- RePathEscapeTests (theory data to HttpParsingData)
- ReDisconnectingClient (what was that testing?)
This commit is contained in:
parent
26bd01337d
commit
f253dbc0c0
|
|
@ -1,6 +1,6 @@
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 15.0.26327.1
|
VisualStudioVersion = 15.0.26405.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7972A5D6-3385-4127-9277-428506DD44FF}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7972A5D6-3385-4127-9277-428506DD44FF}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
|
@ -24,11 +24,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{0EF2AC
|
||||||
test\shared\HttpParsingData.cs = test\shared\HttpParsingData.cs
|
test\shared\HttpParsingData.cs = test\shared\HttpParsingData.cs
|
||||||
test\shared\KestrelTestLoggerFactory.cs = test\shared\KestrelTestLoggerFactory.cs
|
test\shared\KestrelTestLoggerFactory.cs = test\shared\KestrelTestLoggerFactory.cs
|
||||||
test\shared\LifetimeNotImplemented.cs = test\shared\LifetimeNotImplemented.cs
|
test\shared\LifetimeNotImplemented.cs = test\shared\LifetimeNotImplemented.cs
|
||||||
test\shared\MockConnection.cs = test\shared\MockConnection.cs
|
|
||||||
test\shared\MockFrameControl.cs = test\shared\MockFrameControl.cs
|
test\shared\MockFrameControl.cs = test\shared\MockFrameControl.cs
|
||||||
test\shared\MockSocketOutput.cs = test\shared\MockSocketOutput.cs
|
test\shared\MockSocketOutput.cs = test\shared\MockSocketOutput.cs
|
||||||
test\shared\MockSystemClock.cs = test\shared\MockSystemClock.cs
|
test\shared\MockSystemClock.cs = test\shared\MockSystemClock.cs
|
||||||
test\shared\SocketInputExtensions.cs = test\shared\SocketInputExtensions.cs
|
|
||||||
test\shared\StringExtensions.cs = test\shared\StringExtensions.cs
|
test\shared\StringExtensions.cs = test\shared\StringExtensions.cs
|
||||||
test\shared\TestApp.cs = test\shared\TestApp.cs
|
test\shared\TestApp.cs = test\shared\TestApp.cs
|
||||||
test\shared\TestApplicationErrorLogger.cs = test\shared\TestApplicationErrorLogger.cs
|
test\shared\TestApplicationErrorLogger.cs = test\shared\TestApplicationErrorLogger.cs
|
||||||
|
|
@ -36,13 +34,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{0EF2AC
|
||||||
test\shared\TestFrame.cs = test\shared\TestFrame.cs
|
test\shared\TestFrame.cs = test\shared\TestFrame.cs
|
||||||
test\shared\TestKestrelTrace.cs = test\shared\TestKestrelTrace.cs
|
test\shared\TestKestrelTrace.cs = test\shared\TestKestrelTrace.cs
|
||||||
test\shared\TestResources.cs = test\shared\TestResources.cs
|
test\shared\TestResources.cs = test\shared\TestResources.cs
|
||||||
test\shared\TestServer.cs = test\shared\TestServer.cs
|
|
||||||
test\shared\TestServiceContext.cs = test\shared\TestServiceContext.cs
|
test\shared\TestServiceContext.cs = test\shared\TestServiceContext.cs
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.Kestrel.Core", "src\Microsoft.AspNetCore.Server.Kestrel.Core\Microsoft.AspNetCore.Server.Kestrel.Core.csproj", "{F510611A-3BEE-4B88-A613-5F4A74ED82A1}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.Kestrel.Core", "src\Microsoft.AspNetCore.Server.Kestrel.Core\Microsoft.AspNetCore.Server.Kestrel.Core.csproj", "{F510611A-3BEE-4B88-A613-5F4A74ED82A1}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.KestrelTests", "test\Microsoft.AspNetCore.Server.KestrelTests\Microsoft.AspNetCore.Server.KestrelTests.csproj", "{37F3BFB2-6454-49E5-9D7F-581BF755CCFE}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.Kestrel.Core.Tests", "test\Microsoft.AspNetCore.Server.Kestrel.Core.Tests\Microsoft.AspNetCore.Server.Kestrel.Core.Tests.csproj", "{37F3BFB2-6454-49E5-9D7F-581BF755CCFE}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleApp", "samples\SampleApp\SampleApp.csproj", "{2C3CB3DC-EEBF-4F52-9E1C-4F2F972E76C3}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleApp", "samples\SampleApp\SampleApp.csproj", "{2C3CB3DC-EEBF-4F52-9E1C-4F2F972E76C3}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|
@ -67,6 +64,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions", "src\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.csproj", "{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions", "src\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.csproj", "{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests", "test\Microsoft.AspNetCore.Server.Transport.Libuv.Tests\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.csproj", "{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.Kestrel.Tests", "test\Microsoft.AspNetCore.Server.Kestrel.Tests\Microsoft.AspNetCore.Server.Kestrel.Tests.csproj", "{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -209,6 +210,30 @@ Global
|
||||||
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}.Release|x64.Build.0 = Release|Any CPU
|
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}.Release|x86.ActiveCfg = Release|Any CPU
|
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}.Release|x86.Build.0 = Release|Any CPU
|
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -227,5 +252,7 @@ Global
|
||||||
{A76B8C8C-0DC5-4DD3-9B1F-02E51A0915F4} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
|
{A76B8C8C-0DC5-4DD3-9B1F-02E51A0915F4} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
|
||||||
{56139957-5C29-4E7D-89BD-7D20598B4EAF} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
|
{56139957-5C29-4E7D-89BD-7D20598B4EAF} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
|
||||||
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
|
{2E9CB89D-EC8F-4DD9-A72B-08D5BABF752D} = {2D5D5227-4DBD-499A-96B1-76A36B03B750}
|
||||||
|
{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
|
||||||
|
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,6 @@
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.FunctionalTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.FunctionalTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.KestrelTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.Core.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.Performance, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.Performance, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||||
|
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Internal.System;
|
using Microsoft.AspNetCore.Server.Kestrel.Internal.System;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class AsciiDecodingTests
|
public class AsciiDecodingTests
|
||||||
{
|
{
|
||||||
|
|
@ -6,7 +6,7 @@ using System.Text;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class ChunkWriterTests
|
public class ChunkWriterTests
|
||||||
{
|
{
|
||||||
|
|
@ -5,7 +5,7 @@ using System.Net;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class CreateIPEndpointTests
|
public class CreateIPEndpointTests
|
||||||
{
|
{
|
||||||
|
|
@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class DateHeaderValueManagerTests
|
public class DateHeaderValueManagerTests
|
||||||
{
|
{
|
||||||
|
|
@ -8,7 +8,7 @@ using Microsoft.Extensions.Primitives;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class FrameHeadersTests
|
public class FrameHeadersTests
|
||||||
{
|
{
|
||||||
|
|
@ -10,7 +10,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class FrameRequestHeadersTests
|
public class FrameRequestHeadersTests
|
||||||
{
|
{
|
||||||
|
|
@ -8,7 +8,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class FrameRequestStreamTests
|
public class FrameRequestStreamTests
|
||||||
{
|
{
|
||||||
|
|
@ -11,7 +11,7 @@ using Microsoft.AspNetCore.Testing;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class FrameResponseHeadersTests
|
public class FrameResponseHeadersTests
|
||||||
{
|
{
|
||||||
|
|
@ -5,10 +5,10 @@ using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
using Microsoft.AspNetCore.Server.KestrelTests.TestHelpers;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Tests.TestHelpers;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class FrameResponseStreamTests
|
public class FrameResponseStreamTests
|
||||||
{
|
{
|
||||||
|
|
@ -26,7 +26,7 @@ using Microsoft.Extensions.Primitives;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class FrameTests : IDisposable
|
public class FrameTests : IDisposable
|
||||||
{
|
{
|
||||||
|
|
@ -16,7 +16,7 @@ using Microsoft.Extensions.Logging;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class HttpParserTests
|
public class HttpParserTests
|
||||||
{
|
{
|
||||||
|
|
@ -8,7 +8,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Internal.System;
|
using Microsoft.AspNetCore.Server.Kestrel.Internal.System;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class HttpUtilitiesTest
|
public class HttpUtilitiesTest
|
||||||
{
|
{
|
||||||
|
|
@ -7,7 +7,7 @@ using System.Reflection;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class KestrelEventSourceTests
|
public class KestrelEventSourceTests
|
||||||
{
|
{
|
||||||
|
|
@ -5,7 +5,7 @@ using System;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class KestrelServerLimitsTests
|
public class KestrelServerLimitsTests
|
||||||
{
|
{
|
||||||
|
|
@ -5,7 +5,7 @@ using System.Net;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class KestrelServerOptionsTests
|
public class KestrelServerOptionsTests
|
||||||
{
|
{
|
||||||
|
|
@ -16,7 +16,7 @@ using Microsoft.Extensions.Options;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class KestrelServerTests
|
public class KestrelServerTests
|
||||||
{
|
{
|
||||||
|
|
@ -8,7 +8,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class LoggingThreadPoolTests
|
public class LoggingThreadPoolTests
|
||||||
{
|
{
|
||||||
|
|
@ -16,7 +16,7 @@ using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Xunit.Sdk;
|
using Xunit.Sdk;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Summary description for MessageBodyTests
|
/// Summary description for MessageBodyTests
|
||||||
|
|
@ -22,12 +22,12 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Server.Kestrel\Microsoft.AspNetCore.Server.Kestrel.csproj" />
|
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Server.Kestrel.Core\Microsoft.AspNetCore.Server.Kestrel.Core.csproj" />
|
||||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Server.Kestrel.Https\Microsoft.AspNetCore.Server.Kestrel.Https.csproj" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Testing" Version="$(AspNetCoreVersion)" />
|
<PackageReference Include="Microsoft.AspNetCore.Testing" Version="$(AspNetCoreVersion)" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Http" Version="$(AspNetCoreVersion)" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
|
||||||
<PackageReference Include="Moq" Version="$(MoqVersion)" />
|
<PackageReference Include="Moq" Version="$(MoqVersion)" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitVersion)" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitVersion)" />
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
||||||
|
using Microsoft.AspNetCore.Testing;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
|
{
|
||||||
|
public class OutputProducerTests
|
||||||
|
{
|
||||||
|
private readonly PipeFactory _pipeFactory;
|
||||||
|
|
||||||
|
public OutputProducerTests()
|
||||||
|
{
|
||||||
|
_pipeFactory = new PipeFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_pipeFactory.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WritesNoopAfterConnectionCloses()
|
||||||
|
{
|
||||||
|
var pipeOptions = new PipeOptions
|
||||||
|
{
|
||||||
|
ReaderScheduler = Mock.Of<IScheduler>(),
|
||||||
|
};
|
||||||
|
|
||||||
|
using (var socketOutput = CreateOutputProducer(pipeOptions))
|
||||||
|
{
|
||||||
|
// Close
|
||||||
|
socketOutput.Dispose();
|
||||||
|
|
||||||
|
var called = false;
|
||||||
|
|
||||||
|
((ISocketOutput)socketOutput).Write<object>((buffer, state) =>
|
||||||
|
{
|
||||||
|
called = true;
|
||||||
|
},
|
||||||
|
null);
|
||||||
|
|
||||||
|
Assert.False(called);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private OutputProducer CreateOutputProducer(PipeOptions pipeOptions)
|
||||||
|
{
|
||||||
|
var pipe = _pipeFactory.Create(pipeOptions);
|
||||||
|
var serviceContext = new TestServiceContext();
|
||||||
|
var frame = new Frame<object>(null, new FrameContext { ServiceContext = serviceContext });
|
||||||
|
var socketOutput = new OutputProducer(pipe.Writer, frame, "0", serviceContext.Log);
|
||||||
|
|
||||||
|
return socketOutput;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Internal.System;
|
using Microsoft.AspNetCore.Server.Kestrel.Internal.System;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class PathNormalizerTests
|
public class PathNormalizerTests
|
||||||
{
|
{
|
||||||
|
|
@ -8,7 +8,7 @@ using Microsoft.AspNetCore.Testing;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class PipeOptionsTests
|
public class PipeOptionsTests
|
||||||
{
|
{
|
||||||
|
|
@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(10, 10, 10)]
|
[InlineData(10, 10, 10)]
|
||||||
[InlineData(null, 0, 0)]
|
[InlineData(null, 0, 0)]
|
||||||
public void LibuvInputPipeOptionsConfiguredCorrectly(long? maxRequestBufferSize, long expectedMaximumSizeLow, long expectedMaximumSizeHigh)
|
public void InputPipeOptionsConfiguredCorrectly(long? maxRequestBufferSize, long expectedMaximumSizeLow, long expectedMaximumSizeHigh)
|
||||||
{
|
{
|
||||||
var serviceContext = new TestServiceContext();
|
var serviceContext = new TestServiceContext();
|
||||||
serviceContext.ServerOptions.Limits.MaxRequestBufferSize = maxRequestBufferSize;
|
serviceContext.ServerOptions.Limits.MaxRequestBufferSize = maxRequestBufferSize;
|
||||||
|
|
@ -9,7 +9,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Internal.System;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class PipelineExtensionTests : IDisposable
|
public class PipelineExtensionTests : IDisposable
|
||||||
{
|
{
|
||||||
|
|
@ -5,7 +5,7 @@ using System;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class ServerAddressTests
|
public class ServerAddressTests
|
||||||
{
|
{
|
||||||
|
|
@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
public class StreamSocketOutputTests
|
public class StreamSocketOutputTests
|
||||||
{
|
{
|
||||||
|
|
@ -7,7 +7,7 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
using Microsoft.Extensions.Internal;
|
using Microsoft.Extensions.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests.TestHelpers
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests.TestHelpers
|
||||||
{
|
{
|
||||||
public class MockFrameControl : IFrameControl
|
public class MockFrameControl : IFrameControl
|
||||||
{
|
{
|
||||||
|
|
@ -11,7 +11,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Microsoft.Extensions.Internal;
|
using Microsoft.Extensions.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
||||||
{
|
{
|
||||||
class TestInput : ITimeoutControl, IFrameControl, IDisposable
|
class TestInput : ITimeoutControl, IFrameControl, IDisposable
|
||||||
{
|
{
|
||||||
|
|
@ -13,7 +13,7 @@ using Microsoft.AspNetCore.Testing;
|
||||||
using Microsoft.Extensions.Internal;
|
using Microsoft.Extensions.Internal;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
{
|
{
|
||||||
public class ChunkedRequestTests
|
public class ChunkedRequestTests
|
||||||
{
|
{
|
||||||
|
|
@ -11,7 +11,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
{
|
{
|
||||||
public class ChunkedResponseTests
|
public class ChunkedResponseTests
|
||||||
{
|
{
|
||||||
|
|
@ -12,7 +12,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
{
|
{
|
||||||
public class ConnectionAdapterTests
|
public class ConnectionAdapterTests
|
||||||
{
|
{
|
||||||
|
|
@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Testing;
|
||||||
using Microsoft.Extensions.Internal;
|
using Microsoft.Extensions.Internal;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
{
|
{
|
||||||
public class DefaultHeaderTests
|
public class DefaultHeaderTests
|
||||||
{
|
{
|
||||||
|
|
@ -20,7 +20,7 @@ using Microsoft.AspNetCore.Testing;
|
||||||
using Microsoft.Extensions.Internal;
|
using Microsoft.Extensions.Internal;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
{
|
{
|
||||||
public class HttpsConnectionAdapterTests
|
public class HttpsConnectionAdapterTests
|
||||||
{
|
{
|
||||||
|
|
@ -248,7 +248,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
|
|
||||||
// Timeouts large enough to prevent false positives, but small enough to fail quickly.
|
// Timeouts large enough to prevent false positives, but small enough to fail quickly.
|
||||||
socket.SendTimeout = 10 * 1000;
|
socket.SendTimeout = 10 * 1000;
|
||||||
socket.ReceiveTimeout = 10 * 1000;
|
socket.ReceiveTimeout = 30 * 1000;
|
||||||
|
|
||||||
socket.Connect(IPAddress.Loopback, port);
|
socket.Connect(IPAddress.Loopback, port);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
{
|
{
|
||||||
public class RequestTargetProcessingTests
|
public class RequestTargetProcessingTests
|
||||||
{
|
{
|
||||||
|
|
@ -5,6 +5,7 @@ using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
|
@ -15,6 +16,8 @@ using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Microsoft.AspNetCore.Testing.xunit;
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
|
|
@ -35,6 +38,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
private const int _connectionResetEventId = 19;
|
private const int _connectionResetEventId = 19;
|
||||||
private const int _semaphoreWaitTimeout = 2500;
|
private const int _semaphoreWaitTimeout = 2500;
|
||||||
|
|
||||||
|
public static TheoryData<ListenOptions> ConnectionAdapterData => new TheoryData<ListenOptions>
|
||||||
|
{
|
||||||
|
new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0)),
|
||||||
|
new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0))
|
||||||
|
{
|
||||||
|
ConnectionAdapters = { new PassThroughConnectionAdapter() }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(10 * 1024 * 1024, true)]
|
[InlineData(10 * 1024 * 1024, true)]
|
||||||
// In the following dataset, send at least 2GB.
|
// In the following dataset, send at least 2GB.
|
||||||
|
|
@ -633,6 +645,558 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task Http11KeptAliveByDefault(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
using (var server = new TestServer(TestApp.EchoAppChunked, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"Connection: close",
|
||||||
|
"Content-Length: 7",
|
||||||
|
"",
|
||||||
|
"Goodbye");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: close",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 7",
|
||||||
|
"",
|
||||||
|
"Goodbye");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task Http10NotKeptAliveByDefault(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
using (var server = new TestServer(TestApp.EchoApp, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.0",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveForcedEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: close",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"POST / HTTP/1.0",
|
||||||
|
"Content-Length: 11",
|
||||||
|
"",
|
||||||
|
"Hello World");
|
||||||
|
await connection.ReceiveForcedEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: close",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"",
|
||||||
|
"Hello World");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task Http10KeepAlive(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
using (var server = new TestServer(TestApp.EchoAppChunked, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.0",
|
||||||
|
"Connection: keep-alive",
|
||||||
|
"",
|
||||||
|
"POST / HTTP/1.0",
|
||||||
|
"Content-Length: 7",
|
||||||
|
"",
|
||||||
|
"Goodbye");
|
||||||
|
await connection.Receive(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: keep-alive",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"\r\n");
|
||||||
|
await connection.ReceiveForcedEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: close",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 7",
|
||||||
|
"",
|
||||||
|
"Goodbye");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task Http10KeepAliveNotHonoredIfResponseContentLengthNotSet(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
using (var server = new TestServer(TestApp.EchoApp, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.0",
|
||||||
|
"Connection: keep-alive",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
|
||||||
|
await connection.Receive(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: keep-alive",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"\r\n");
|
||||||
|
|
||||||
|
await connection.Send(
|
||||||
|
"POST / HTTP/1.0",
|
||||||
|
"Connection: keep-alive",
|
||||||
|
"Content-Length: 7",
|
||||||
|
"",
|
||||||
|
"Goodbye");
|
||||||
|
|
||||||
|
await connection.ReceiveForcedEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: close",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"",
|
||||||
|
"Goodbye");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task Http10KeepAliveHonoredIfResponseContentLengthSet(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
using (var server = new TestServer(TestApp.EchoAppChunked, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"POST / HTTP/1.0",
|
||||||
|
"Content-Length: 11",
|
||||||
|
"Connection: keep-alive",
|
||||||
|
"",
|
||||||
|
"Hello World");
|
||||||
|
|
||||||
|
await connection.Receive(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: keep-alive",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 11",
|
||||||
|
"",
|
||||||
|
"Hello World");
|
||||||
|
|
||||||
|
await connection.Send(
|
||||||
|
"POST / HTTP/1.0",
|
||||||
|
"Connection: keep-alive",
|
||||||
|
"Content-Length: 11",
|
||||||
|
"",
|
||||||
|
"Hello Again");
|
||||||
|
|
||||||
|
await connection.Receive(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: keep-alive",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 11",
|
||||||
|
"",
|
||||||
|
"Hello Again");
|
||||||
|
|
||||||
|
await connection.Send(
|
||||||
|
"POST / HTTP/1.0",
|
||||||
|
"Content-Length: 7",
|
||||||
|
"",
|
||||||
|
"Goodbye");
|
||||||
|
|
||||||
|
await connection.ReceiveForcedEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: close",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 7",
|
||||||
|
"",
|
||||||
|
"Goodbye");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task Expect100ContinueHonored(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
using (var server = new TestServer(TestApp.EchoAppChunked, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"POST / HTTP/1.1",
|
||||||
|
"Expect: 100-continue",
|
||||||
|
"Connection: close",
|
||||||
|
"Content-Length: 11",
|
||||||
|
"\r\n");
|
||||||
|
await connection.Receive(
|
||||||
|
"HTTP/1.1 100 Continue",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.Send("Hello World");
|
||||||
|
await connection.ReceiveForcedEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: close",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 11",
|
||||||
|
"",
|
||||||
|
"Hello World");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task ZeroContentLengthAssumedOnNonKeepAliveRequestsWithoutContentLengthOrTransferEncodingHeader(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
using (var server = new TestServer(async httpContext =>
|
||||||
|
{
|
||||||
|
// This will hang if 0 content length is not assumed by the server
|
||||||
|
Assert.Equal(0, await httpContext.Request.Body.ReadAsync(new byte[1], 0, 1).TimeoutAfter(TimeSpan.FromSeconds(10)));
|
||||||
|
}, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
// Use Send instead of SendEnd to ensure the connection will remain open while
|
||||||
|
// the app runs and reads 0 bytes from the body nonetheless. This checks that
|
||||||
|
// https://github.com/aspnet/KestrelHttpServer/issues/1104 is not regressing.
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"Connection: close",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveForcedEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: close",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.0",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveForcedEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: close",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task ConnectionClosesWhenFinReceivedBeforeRequestCompletes(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
using (var server = new TestServer(TestApp.EchoAppChunked, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"POST / HTTP/1.1");
|
||||||
|
connection.Shutdown(SocketShutdown.Send);
|
||||||
|
await connection.ReceiveForcedEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"POST / HTTP/1.1",
|
||||||
|
"Content-Length: 7");
|
||||||
|
connection.Shutdown(SocketShutdown.Send);
|
||||||
|
await connection.ReceiveForcedEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task RequestsCanBeAbortedMidRead(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
var readTcs = new TaskCompletionSource<object>();
|
||||||
|
var registrationTcs = new TaskCompletionSource<int>();
|
||||||
|
var requestId = 0;
|
||||||
|
|
||||||
|
using (var server = new TestServer(async httpContext =>
|
||||||
|
{
|
||||||
|
requestId++;
|
||||||
|
|
||||||
|
var response = httpContext.Response;
|
||||||
|
var request = httpContext.Request;
|
||||||
|
var lifetime = httpContext.Features.Get<IHttpRequestLifetimeFeature>();
|
||||||
|
|
||||||
|
lifetime.RequestAborted.Register(() => registrationTcs.TrySetResult(requestId));
|
||||||
|
|
||||||
|
if (requestId == 1)
|
||||||
|
{
|
||||||
|
response.Headers["Content-Length"] = new[] { "5" };
|
||||||
|
|
||||||
|
await response.WriteAsync("World");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var readTask = request.Body.CopyToAsync(Stream.Null);
|
||||||
|
|
||||||
|
lifetime.Abort();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await readTask;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
readTcs.SetException(ex);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
readTcs.SetException(new Exception("This shouldn't be reached."));
|
||||||
|
}
|
||||||
|
}, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
// Never send the body so CopyToAsync always fails.
|
||||||
|
await connection.Send(
|
||||||
|
"POST / HTTP/1.1",
|
||||||
|
"Content-Length: 5",
|
||||||
|
"",
|
||||||
|
"HelloPOST / HTTP/1.1",
|
||||||
|
"Content-Length: 5",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
|
||||||
|
await connection.ReceiveForcedEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 5",
|
||||||
|
"",
|
||||||
|
"World");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<TaskCanceledException>(async () => await readTcs.Task);
|
||||||
|
|
||||||
|
// The cancellation token for only the last request should be triggered.
|
||||||
|
var abortedRequestId = await registrationTcs.Task;
|
||||||
|
Assert.Equal(2, abortedRequestId);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task RequestHeadersAreResetOnEachRequest(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
IHeaderDictionary originalRequestHeaders = null;
|
||||||
|
var firstRequest = true;
|
||||||
|
|
||||||
|
using (var server = new TestServer(httpContext =>
|
||||||
|
{
|
||||||
|
var requestFeature = httpContext.Features.Get<IHttpRequestFeature>();
|
||||||
|
|
||||||
|
if (firstRequest)
|
||||||
|
{
|
||||||
|
originalRequestHeaders = requestFeature.Headers;
|
||||||
|
requestFeature.Headers = new FrameRequestHeaders();
|
||||||
|
firstRequest = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Same(originalRequestHeaders, requestFeature.Headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TaskCache.CompletedTask;
|
||||||
|
}, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task UpgradeRequestIsNotKeptAliveOrChunked(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
const string message = "Hello World";
|
||||||
|
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
using (var server = new TestServer(async context =>
|
||||||
|
{
|
||||||
|
var upgradeFeature = context.Features.Get<IHttpUpgradeFeature>();
|
||||||
|
var duplexStream = await upgradeFeature.UpgradeAsync();
|
||||||
|
|
||||||
|
var buffer = new byte[message.Length];
|
||||||
|
var read = 0;
|
||||||
|
while (read < message.Length)
|
||||||
|
{
|
||||||
|
read += await duplexStream.ReadAsync(buffer, read, buffer.Length - read).TimeoutAfter(TimeSpan.FromSeconds(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
await duplexStream.WriteAsync(buffer, 0, read);
|
||||||
|
}, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"Connection: Upgrade",
|
||||||
|
"",
|
||||||
|
message);
|
||||||
|
await connection.ReceiveForcedEnd(
|
||||||
|
"HTTP/1.1 101 Switching Protocols",
|
||||||
|
"Connection: Upgrade",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"",
|
||||||
|
message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task HeadersAndStreamsAreReusedAcrossRequests(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
var streamCount = 0;
|
||||||
|
var requestHeadersCount = 0;
|
||||||
|
var responseHeadersCount = 0;
|
||||||
|
var loopCount = 20;
|
||||||
|
Stream lastStream = null;
|
||||||
|
IHeaderDictionary lastRequestHeaders = null;
|
||||||
|
IHeaderDictionary lastResponseHeaders = null;
|
||||||
|
|
||||||
|
using (var server = new TestServer(async context =>
|
||||||
|
{
|
||||||
|
if (context.Request.Body != lastStream)
|
||||||
|
{
|
||||||
|
lastStream = context.Request.Body;
|
||||||
|
streamCount++;
|
||||||
|
}
|
||||||
|
if (context.Request.Headers != lastRequestHeaders)
|
||||||
|
{
|
||||||
|
lastRequestHeaders = context.Request.Headers;
|
||||||
|
requestHeadersCount++;
|
||||||
|
}
|
||||||
|
if (context.Response.Headers != lastResponseHeaders)
|
||||||
|
{
|
||||||
|
lastResponseHeaders = context.Response.Headers;
|
||||||
|
responseHeadersCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ms = new MemoryStream();
|
||||||
|
await context.Request.Body.CopyToAsync(ms);
|
||||||
|
var request = ms.ToArray();
|
||||||
|
|
||||||
|
context.Response.ContentLength = request.Length;
|
||||||
|
|
||||||
|
await context.Response.Body.WriteAsync(request, 0, request.Length);
|
||||||
|
}, testContext))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
var requestData =
|
||||||
|
Enumerable.Repeat("GET / HTTP/1.1\r\n", loopCount)
|
||||||
|
.Concat(new[] { "GET / HTTP/1.1\r\nContent-Length: 7\r\nConnection: close\r\n\r\nGoodbye" });
|
||||||
|
|
||||||
|
var response = string.Join("\r\n", new string[] {
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
""});
|
||||||
|
|
||||||
|
var lastResponse = string.Join("\r\n", new string[]
|
||||||
|
{
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: close",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 7",
|
||||||
|
"",
|
||||||
|
"Goodbye"
|
||||||
|
});
|
||||||
|
|
||||||
|
var responseData =
|
||||||
|
Enumerable.Repeat(response, loopCount)
|
||||||
|
.Concat(new[] { lastResponse });
|
||||||
|
|
||||||
|
await connection.Send(requestData.ToArray());
|
||||||
|
|
||||||
|
await connection.ReceiveEnd(responseData.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.Equal(1, streamCount);
|
||||||
|
Assert.Equal(1, requestHeadersCount);
|
||||||
|
Assert.Equal(1, responseHeadersCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task TestRemoteIPAddress(string registerAddress, string requestAddress, string expectAddress)
|
private async Task TestRemoteIPAddress(string registerAddress, string requestAddress, string expectAddress)
|
||||||
{
|
{
|
||||||
var builder = new WebHostBuilder()
|
var builder = new WebHostBuilder()
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
|
@ -14,6 +16,7 @@ using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
|
|
@ -27,6 +30,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
{
|
{
|
||||||
public class ResponseTests
|
public class ResponseTests
|
||||||
{
|
{
|
||||||
|
public static TheoryData<ListenOptions> ConnectionAdapterData => new TheoryData<ListenOptions>
|
||||||
|
{
|
||||||
|
new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0)),
|
||||||
|
new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0))
|
||||||
|
{
|
||||||
|
ConnectionAdapters = { new PassThroughConnectionAdapter() }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task LargeDownload()
|
public async Task LargeDownload()
|
||||||
{
|
{
|
||||||
|
|
@ -1529,6 +1541,751 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task Http11ResponseSentToHttp10Request(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var serviceContext = new TestServiceContext();
|
||||||
|
|
||||||
|
using (var server = new TestServer(TestApp.EchoApp, serviceContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"POST / HTTP/1.0",
|
||||||
|
"Content-Length: 11",
|
||||||
|
"",
|
||||||
|
"Hello World");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: close",
|
||||||
|
$"Date: {serviceContext.DateHeaderValue}",
|
||||||
|
"",
|
||||||
|
"Hello World");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task ZeroContentLengthSetAutomaticallyAfterNoWrites(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
using (var server = new TestServer(TestApp.EmptyApp, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"GET / HTTP/1.0",
|
||||||
|
"Connection: keep-alive",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: keep-alive",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task ZeroContentLengthSetAutomaticallyForNonKeepAliveRequests(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
using (var server = new TestServer(async httpContext =>
|
||||||
|
{
|
||||||
|
Assert.Equal(0, await httpContext.Request.Body.ReadAsync(new byte[1], 0, 1).TimeoutAfter(TimeSpan.FromSeconds(10)));
|
||||||
|
}, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"Connection: close",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: close",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.0",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: close",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task ZeroContentLengthNotSetAutomaticallyForHeadRequests(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
using (var server = new TestServer(TestApp.EmptyApp, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"HEAD / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task ZeroContentLengthNotSetAutomaticallyForCertainStatusCodes(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
using (var server = new TestServer(async httpContext =>
|
||||||
|
{
|
||||||
|
var request = httpContext.Request;
|
||||||
|
var response = httpContext.Response;
|
||||||
|
|
||||||
|
using (var reader = new StreamReader(request.Body, Encoding.ASCII))
|
||||||
|
{
|
||||||
|
var statusString = await reader.ReadLineAsync();
|
||||||
|
response.StatusCode = int.Parse(statusString);
|
||||||
|
}
|
||||||
|
}, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"POST / HTTP/1.1",
|
||||||
|
"Content-Length: 3",
|
||||||
|
"",
|
||||||
|
"204POST / HTTP/1.1",
|
||||||
|
"Content-Length: 3",
|
||||||
|
"",
|
||||||
|
"205POST / HTTP/1.1",
|
||||||
|
"Content-Length: 3",
|
||||||
|
"",
|
||||||
|
"304POST / HTTP/1.1",
|
||||||
|
"Content-Length: 3",
|
||||||
|
"",
|
||||||
|
"200");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 204 No Content",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"",
|
||||||
|
"HTTP/1.1 205 Reset Content",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"",
|
||||||
|
"HTTP/1.1 304 Not Modified",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"",
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task ConnectionClosedAfter101Response(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
using (var server = new TestServer(async httpContext =>
|
||||||
|
{
|
||||||
|
var request = httpContext.Request;
|
||||||
|
var stream = await httpContext.Features.Get<IHttpUpgradeFeature>().UpgradeAsync();
|
||||||
|
var response = Encoding.ASCII.GetBytes("hello, world");
|
||||||
|
await stream.WriteAsync(response, 0, response.Length);
|
||||||
|
}, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveForcedEnd(
|
||||||
|
"HTTP/1.1 101 Switching Protocols",
|
||||||
|
"Connection: Upgrade",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"",
|
||||||
|
"hello, world");
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.0",
|
||||||
|
"Connection: keep-alive",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveForcedEnd(
|
||||||
|
"HTTP/1.1 101 Switching Protocols",
|
||||||
|
"Connection: Upgrade",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"",
|
||||||
|
"hello, world");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task ThrowingResultsIn500Response(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
bool onStartingCalled = false;
|
||||||
|
|
||||||
|
var testLogger = new TestApplicationErrorLogger();
|
||||||
|
testContext.Log = new KestrelTrace(testLogger);
|
||||||
|
|
||||||
|
using (var server = new TestServer(httpContext =>
|
||||||
|
{
|
||||||
|
var response = httpContext.Response;
|
||||||
|
response.OnStarting(_ =>
|
||||||
|
{
|
||||||
|
onStartingCalled = true;
|
||||||
|
return TaskCache.CompletedTask;
|
||||||
|
}, null);
|
||||||
|
|
||||||
|
// Anything added to the ResponseHeaders dictionary is ignored
|
||||||
|
response.Headers["Content-Length"] = "11";
|
||||||
|
throw new Exception();
|
||||||
|
}, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"Connection: close",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveForcedEnd(
|
||||||
|
"HTTP/1.1 500 Internal Server Error",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"HTTP/1.1 500 Internal Server Error",
|
||||||
|
"Connection: close",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.False(onStartingCalled);
|
||||||
|
Assert.Equal(2, testLogger.ApplicationErrorsLogged);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task ThrowingInOnStartingResultsInFailedWritesAnd500Response(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var callback1Called = false;
|
||||||
|
var callback2CallCount = 0;
|
||||||
|
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
var testLogger = new TestApplicationErrorLogger();
|
||||||
|
testContext.Log = new KestrelTrace(testLogger);
|
||||||
|
|
||||||
|
using (var server = new TestServer(async httpContext =>
|
||||||
|
{
|
||||||
|
var onStartingException = new Exception();
|
||||||
|
|
||||||
|
var response = httpContext.Response;
|
||||||
|
response.OnStarting(_ =>
|
||||||
|
{
|
||||||
|
callback1Called = true;
|
||||||
|
throw onStartingException;
|
||||||
|
}, null);
|
||||||
|
response.OnStarting(_ =>
|
||||||
|
{
|
||||||
|
callback2CallCount++;
|
||||||
|
throw onStartingException;
|
||||||
|
}, null);
|
||||||
|
|
||||||
|
var writeException = await Assert.ThrowsAsync<ObjectDisposedException>(async () => await response.Body.FlushAsync());
|
||||||
|
Assert.Same(onStartingException, writeException.InnerException);
|
||||||
|
}, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 500 Internal Server Error",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"HTTP/1.1 500 Internal Server Error",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The first registered OnStarting callback should have been called,
|
||||||
|
// since they are called LIFO order and the other one failed.
|
||||||
|
Assert.False(callback1Called);
|
||||||
|
Assert.Equal(2, callback2CallCount);
|
||||||
|
Assert.Equal(2, testLogger.ApplicationErrorsLogged);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task ThrowingInOnCompletedIsLoggedAndClosesConnection(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
var onCompletedCalled1 = false;
|
||||||
|
var onCompletedCalled2 = false;
|
||||||
|
|
||||||
|
var testLogger = new TestApplicationErrorLogger();
|
||||||
|
testContext.Log = new KestrelTrace(testLogger);
|
||||||
|
|
||||||
|
using (var server = new TestServer(async httpContext =>
|
||||||
|
{
|
||||||
|
var response = httpContext.Response;
|
||||||
|
response.OnCompleted(_ =>
|
||||||
|
{
|
||||||
|
onCompletedCalled1 = true;
|
||||||
|
throw new Exception();
|
||||||
|
}, null);
|
||||||
|
response.OnCompleted(_ =>
|
||||||
|
{
|
||||||
|
onCompletedCalled2 = true;
|
||||||
|
throw new Exception();
|
||||||
|
}, null);
|
||||||
|
|
||||||
|
response.Headers["Content-Length"] = new[] { "11" };
|
||||||
|
|
||||||
|
await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello World"), 0, 11);
|
||||||
|
}, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveForcedEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 11",
|
||||||
|
"",
|
||||||
|
"Hello World");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All OnCompleted callbacks should be called even if they throw.
|
||||||
|
Assert.Equal(2, testLogger.ApplicationErrorsLogged);
|
||||||
|
Assert.True(onCompletedCalled1);
|
||||||
|
Assert.True(onCompletedCalled2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task ThrowingAfterWritingKillsConnection(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
bool onStartingCalled = false;
|
||||||
|
|
||||||
|
var testLogger = new TestApplicationErrorLogger();
|
||||||
|
testContext.Log = new KestrelTrace(testLogger);
|
||||||
|
|
||||||
|
using (var server = new TestServer(async httpContext =>
|
||||||
|
{
|
||||||
|
var response = httpContext.Response;
|
||||||
|
response.OnStarting(_ =>
|
||||||
|
{
|
||||||
|
onStartingCalled = true;
|
||||||
|
return Task.FromResult<object>(null);
|
||||||
|
}, null);
|
||||||
|
|
||||||
|
response.Headers["Content-Length"] = new[] { "11" };
|
||||||
|
await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello World"), 0, 11);
|
||||||
|
throw new Exception();
|
||||||
|
}, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveForcedEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 11",
|
||||||
|
"",
|
||||||
|
"Hello World");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.True(onStartingCalled);
|
||||||
|
Assert.Equal(1, testLogger.ApplicationErrorsLogged);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task ThrowingAfterPartialWriteKillsConnection(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
bool onStartingCalled = false;
|
||||||
|
|
||||||
|
var testLogger = new TestApplicationErrorLogger();
|
||||||
|
testContext.Log = new KestrelTrace(testLogger);
|
||||||
|
|
||||||
|
using (var server = new TestServer(async httpContext =>
|
||||||
|
{
|
||||||
|
var response = httpContext.Response;
|
||||||
|
response.OnStarting(_ =>
|
||||||
|
{
|
||||||
|
onStartingCalled = true;
|
||||||
|
return Task.FromResult<object>(null);
|
||||||
|
}, null);
|
||||||
|
|
||||||
|
response.Headers["Content-Length"] = new[] { "11" };
|
||||||
|
await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello"), 0, 5);
|
||||||
|
throw new Exception();
|
||||||
|
}, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveForcedEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 11",
|
||||||
|
"",
|
||||||
|
"Hello");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.True(onStartingCalled);
|
||||||
|
Assert.Equal(1, testLogger.ApplicationErrorsLogged);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task FailedWritesResultInAbortedRequest(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
// This should match _maxBytesPreCompleted in SocketOutput
|
||||||
|
var maxBytesPreCompleted = 65536;
|
||||||
|
// Ensure string is long enough to disable write-behind buffering
|
||||||
|
var largeString = new string('a', maxBytesPreCompleted + 1);
|
||||||
|
|
||||||
|
var writeTcs = new TaskCompletionSource<object>();
|
||||||
|
var registrationWh = new ManualResetEventSlim();
|
||||||
|
var connectionCloseWh = new ManualResetEventSlim();
|
||||||
|
|
||||||
|
using (var server = new TestServer(async httpContext =>
|
||||||
|
{
|
||||||
|
var response = httpContext.Response;
|
||||||
|
var request = httpContext.Request;
|
||||||
|
var lifetime = httpContext.Features.Get<IHttpRequestLifetimeFeature>();
|
||||||
|
|
||||||
|
lifetime.RequestAborted.Register(() => registrationWh.Set());
|
||||||
|
|
||||||
|
await request.Body.CopyToAsync(Stream.Null);
|
||||||
|
connectionCloseWh.Wait();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Ensure write is long enough to disable write-behind buffering
|
||||||
|
for (int i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
await response.WriteAsync(largeString, lifetime.RequestAborted);
|
||||||
|
registrationWh.Wait(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
writeTcs.SetException(ex);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeTcs.SetException(new Exception("This shouldn't be reached."));
|
||||||
|
}, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"POST / HTTP/1.1",
|
||||||
|
"Content-Length: 5",
|
||||||
|
"",
|
||||||
|
"Hello");
|
||||||
|
// Don't wait to receive the response. Just close the socket.
|
||||||
|
}
|
||||||
|
|
||||||
|
connectionCloseWh.Set();
|
||||||
|
|
||||||
|
// Write failed
|
||||||
|
await Assert.ThrowsAsync<TaskCanceledException>(async () => await writeTcs.Task);
|
||||||
|
// RequestAborted tripped
|
||||||
|
Assert.True(registrationWh.Wait(1000));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task NoErrorsLoggedWhenServerEndsConnectionBeforeClient(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
var testLogger = new TestApplicationErrorLogger();
|
||||||
|
testContext.Log = new KestrelTrace(testLogger);
|
||||||
|
|
||||||
|
using (var server = new TestServer(async httpContext =>
|
||||||
|
{
|
||||||
|
var response = httpContext.Response;
|
||||||
|
response.Headers["Content-Length"] = new[] { "11" };
|
||||||
|
await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello World"), 0, 11);
|
||||||
|
}, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.0",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveForcedEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: close",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 11",
|
||||||
|
"",
|
||||||
|
"Hello World");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.Equal(0, testLogger.TotalErrorsLogged);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task NoResponseSentWhenConnectionIsClosedByServerBeforeClientFinishesSendingRequest(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
using (var server = new TestServer(httpContext =>
|
||||||
|
{
|
||||||
|
httpContext.Abort();
|
||||||
|
return TaskCache.CompletedTask;
|
||||||
|
}, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"POST / HTTP/1.0",
|
||||||
|
"Content-Length: 1",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveForcedEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task ResponseHeadersAreResetOnEachRequest(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
IHeaderDictionary originalResponseHeaders = null;
|
||||||
|
var firstRequest = true;
|
||||||
|
|
||||||
|
using (var server = new TestServer(httpContext =>
|
||||||
|
{
|
||||||
|
var responseFeature = httpContext.Features.Get<IHttpResponseFeature>();
|
||||||
|
|
||||||
|
if (firstRequest)
|
||||||
|
{
|
||||||
|
originalResponseHeaders = responseFeature.Headers;
|
||||||
|
responseFeature.Headers = new FrameResponseHeaders();
|
||||||
|
firstRequest = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Same(originalResponseHeaders, responseFeature.Headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TaskCache.CompletedTask;
|
||||||
|
}, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task OnStartingCallbacksAreCalledInLastInFirstOutOrder(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
const string response = "hello, world";
|
||||||
|
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
var callOrder = new Stack<int>();
|
||||||
|
var onStartingTcs = new TaskCompletionSource<object>();
|
||||||
|
|
||||||
|
using (var server = new TestServer(async context =>
|
||||||
|
{
|
||||||
|
context.Response.OnStarting(_ =>
|
||||||
|
{
|
||||||
|
callOrder.Push(1);
|
||||||
|
onStartingTcs.SetResult(null);
|
||||||
|
return TaskCache.CompletedTask;
|
||||||
|
}, null);
|
||||||
|
context.Response.OnStarting(_ =>
|
||||||
|
{
|
||||||
|
callOrder.Push(2);
|
||||||
|
return TaskCache.CompletedTask;
|
||||||
|
}, null);
|
||||||
|
|
||||||
|
context.Response.ContentLength = response.Length;
|
||||||
|
await context.Response.WriteAsync(response);
|
||||||
|
}, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
$"Content-Length: {response.Length}",
|
||||||
|
"",
|
||||||
|
"hello, world");
|
||||||
|
|
||||||
|
// Wait for all callbacks to be called.
|
||||||
|
await onStartingTcs.Task.TimeoutAfter(TimeSpan.FromSeconds(10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.Equal(1, callOrder.Pop());
|
||||||
|
Assert.Equal(2, callOrder.Pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task OnCompletedCallbacksAreCalledInLastInFirstOutOrder(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
const string response = "hello, world";
|
||||||
|
|
||||||
|
var testContext = new TestServiceContext();
|
||||||
|
|
||||||
|
var callOrder = new Stack<int>();
|
||||||
|
var onCompletedTcs = new TaskCompletionSource<object>();
|
||||||
|
|
||||||
|
using (var server = new TestServer(async context =>
|
||||||
|
{
|
||||||
|
context.Response.OnCompleted(_ =>
|
||||||
|
{
|
||||||
|
callOrder.Push(1);
|
||||||
|
onCompletedTcs.SetResult(null);
|
||||||
|
return TaskCache.CompletedTask;
|
||||||
|
}, null);
|
||||||
|
context.Response.OnCompleted(_ =>
|
||||||
|
{
|
||||||
|
callOrder.Push(2);
|
||||||
|
return TaskCache.CompletedTask;
|
||||||
|
}, null);
|
||||||
|
|
||||||
|
context.Response.ContentLength = response.Length;
|
||||||
|
await context.Response.WriteAsync(response);
|
||||||
|
}, testContext, listenOptions))
|
||||||
|
{
|
||||||
|
using (var connection = server.CreateConnection())
|
||||||
|
{
|
||||||
|
await connection.Send(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
$"Date: {testContext.DateHeaderValue}",
|
||||||
|
$"Content-Length: {response.Length}",
|
||||||
|
"",
|
||||||
|
"hello, world");
|
||||||
|
|
||||||
|
// Wait for all callbacks to be called.
|
||||||
|
await onCompletedTcs.Task.TimeoutAfter(TimeSpan.FromSeconds(10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.Equal(1, callOrder.Pop());
|
||||||
|
Assert.Equal(2, callOrder.Pop());
|
||||||
|
}
|
||||||
|
|
||||||
public static TheoryData<string, StringValues, string> NullHeaderData
|
public static TheoryData<string, StringValues, string> NullHeaderData
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,10 @@ using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
||||||
|
using Microsoft.AspNetCore.Testing;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Testing
|
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Summary description for TestServer
|
/// Summary description for TestServer
|
||||||
|
|
@ -44,11 +46,21 @@ namespace Microsoft.AspNetCore.Testing
|
||||||
_listenOptions = listenOptions;
|
_listenOptions = listenOptions;
|
||||||
|
|
||||||
Context = context;
|
Context = context;
|
||||||
Context.TransportContext.ConnectionHandler = new ConnectionHandler<HttpContext>(listenOptions, Context, new DummyApplication(app, httpContextFactory));
|
TransportContext = new LibuvTransportContext()
|
||||||
|
{
|
||||||
|
AppLifetime = new LifetimeNotImplemented(),
|
||||||
|
ConnectionHandler = new ConnectionHandler<HttpContext>(listenOptions, Context, new DummyApplication(app, httpContextFactory)),
|
||||||
|
Log = new LibuvTrace(new TestApplicationErrorLogger()),
|
||||||
|
Options = new LibuvTransportOptions()
|
||||||
|
{
|
||||||
|
ThreadCount = 1,
|
||||||
|
ShutdownTimeout = TimeSpan.FromSeconds(5)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_transport = new LibuvTransport(context.TransportContext, _listenOptions);
|
_transport = new LibuvTransport(TransportContext, _listenOptions);
|
||||||
_transport.BindAsync().Wait();
|
_transport.BindAsync().Wait();
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
|
@ -64,6 +76,7 @@ namespace Microsoft.AspNetCore.Testing
|
||||||
public AddressFamily AddressFamily => _listenOptions.IPEndPoint.AddressFamily;
|
public AddressFamily AddressFamily => _listenOptions.IPEndPoint.AddressFamily;
|
||||||
|
|
||||||
public TestServiceContext Context { get; }
|
public TestServiceContext Context { get; }
|
||||||
|
public LibuvTransportContext TransportContext { get; }
|
||||||
|
|
||||||
public TestConnection CreateConnection()
|
public TestConnection CreateConnection()
|
||||||
{
|
{
|
||||||
|
|
@ -20,7 +20,6 @@
|
||||||
<Compile Include="..\shared\TestApplicationErrorLogger.cs" />
|
<Compile Include="..\shared\TestApplicationErrorLogger.cs" />
|
||||||
<Compile Include="..\shared\TestFrame.cs" />
|
<Compile Include="..\shared\TestFrame.cs" />
|
||||||
<Compile Include="..\shared\TestKestrelTrace.cs" />
|
<Compile Include="..\shared\TestKestrelTrace.cs" />
|
||||||
<Compile Include="..\shared\MockConnection.cs" />
|
|
||||||
<Compile Include="..\shared\MockSocketOutput.cs" />
|
<Compile Include="..\shared\MockSocketOutput.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<Import Project="..\..\build\common.props" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFrameworks>netcoreapp2.0;net46</TargetFrameworks>
|
||||||
|
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netcoreapp2.0</TargetFrameworks>
|
||||||
|
<PlatformTarget Condition="'$(TargetFramework)' == 'net46'">x64</PlatformTarget>
|
||||||
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
|
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="xunit.runner.json" CopyToOutputDirectory="PreserveNewest" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Server.Kestrel\Microsoft.AspNetCore.Server.Kestrel.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
|
||||||
|
<PackageReference Include="xunit" Version="$(XunitVersion)" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitVersion)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Tests
|
||||||
{
|
{
|
||||||
public class WebHostBuilderKestrelExtensionsTests
|
public class WebHostBuilderKestrelExtensionsTests
|
||||||
{
|
{
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json.schemastore.org/xunit.runner.schema",
|
||||||
|
"methodDisplay": "method",
|
||||||
|
"longRunningTestSeconds": 60
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -4,14 +4,12 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv;
|
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||||
using Microsoft.AspNetCore.Server.KestrelTests.TestHelpers;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers;
|
||||||
using Microsoft.AspNetCore.Testing;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
{
|
{
|
||||||
public class ConnectionTests
|
public class ConnectionTests
|
||||||
{
|
{
|
||||||
|
|
@ -21,10 +19,8 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
using (var mockConnectionHandler = new MockConnectionHandler())
|
using (var mockConnectionHandler = new MockConnectionHandler())
|
||||||
{
|
{
|
||||||
var mockLibuv = new MockLibuv();
|
var mockLibuv = new MockLibuv();
|
||||||
var serviceContext = new TestServiceContext();
|
var transportContext = new TestLibuvTransportContext() { ConnectionHandler = mockConnectionHandler };
|
||||||
serviceContext.TransportContext.ConnectionHandler = mockConnectionHandler;
|
var transport = new LibuvTransport(mockLibuv, transportContext, null);
|
||||||
|
|
||||||
var transport = new LibuvTransport(mockLibuv, serviceContext.TransportContext, null);
|
|
||||||
var thread = new LibuvThread(transport);
|
var thread = new LibuvThread(transport);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -32,11 +28,11 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
await thread.StartAsync();
|
await thread.StartAsync();
|
||||||
await thread.PostAsync(_ =>
|
await thread.PostAsync(_ =>
|
||||||
{
|
{
|
||||||
var listenerContext = new ListenerContext(serviceContext.TransportContext)
|
var listenerContext = new ListenerContext(transportContext)
|
||||||
{
|
{
|
||||||
Thread = thread
|
Thread = thread
|
||||||
};
|
};
|
||||||
var socket = new MockSocket(mockLibuv, Thread.CurrentThread.ManagedThreadId, serviceContext.TransportContext.Log);
|
var socket = new MockSocket(mockLibuv, Thread.CurrentThread.ManagedThreadId, transportContext.Log);
|
||||||
var connection = new LibuvConnection(listenerContext, socket);
|
var connection = new LibuvConnection(listenerContext, socket);
|
||||||
connection.Start();
|
connection.Start();
|
||||||
|
|
||||||
|
|
@ -7,14 +7,13 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv;
|
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
||||||
using Microsoft.AspNetCore.Server.KestrelTests.TestHelpers;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
{
|
{
|
||||||
public class LibuvOutputConsumerTests : IDisposable
|
public class LibuvOutputConsumerTests : IDisposable
|
||||||
{
|
{
|
||||||
|
|
@ -37,7 +36,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
_pipeFactory = new PipeFactory();
|
_pipeFactory = new PipeFactory();
|
||||||
_mockLibuv = new MockLibuv();
|
_mockLibuv = new MockLibuv();
|
||||||
|
|
||||||
var libuvTransport = new LibuvTransport(_mockLibuv, new TestServiceContext().TransportContext, new ListenOptions(0));
|
var libuvTransport = new LibuvTransport(_mockLibuv, new TestLibuvTransportContext(), new ListenOptions(0));
|
||||||
_libuvThread = new LibuvThread(libuvTransport, maxLoops: 1);
|
_libuvThread = new LibuvThread(libuvTransport, maxLoops: 1);
|
||||||
_libuvThread.StartAsync().Wait();
|
_libuvThread.StartAsync().Wait();
|
||||||
}
|
}
|
||||||
|
|
@ -65,7 +64,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
MaximumSizeLow = maxResponseBufferSize ?? 0,
|
MaximumSizeLow = maxResponseBufferSize ?? 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
using (var socketOutput = CreateSocketOutput(pipeOptions))
|
using (var socketOutput = CreateOutputProducer(pipeOptions))
|
||||||
{
|
{
|
||||||
// At least one run of this test should have a MaxResponseBufferSize < 1 MB.
|
// At least one run of this test should have a MaxResponseBufferSize < 1 MB.
|
||||||
var bufferSize = 1024 * 1024;
|
var bufferSize = 1024 * 1024;
|
||||||
|
|
@ -100,7 +99,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
MaximumSizeLow = 0,
|
MaximumSizeLow = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
using (var socketOutput = CreateSocketOutput(pipeOptions))
|
using (var socketOutput = CreateOutputProducer(pipeOptions))
|
||||||
{
|
{
|
||||||
// Don't want to allocate anything too huge for perf. This is at least larger than the default buffer.
|
// Don't want to allocate anything too huge for perf. This is at least larger than the default buffer.
|
||||||
var bufferSize = 1024 * 1024;
|
var bufferSize = 1024 * 1024;
|
||||||
|
|
@ -146,7 +145,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
MaximumSizeLow = 1,
|
MaximumSizeLow = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
using (var socketOutput = CreateSocketOutput(pipeOptions))
|
using (var socketOutput = CreateOutputProducer(pipeOptions))
|
||||||
{
|
{
|
||||||
var bufferSize = 1;
|
var bufferSize = 1;
|
||||||
var buffer = new ArraySegment<byte>(new byte[bufferSize], 0, bufferSize);
|
var buffer = new ArraySegment<byte>(new byte[bufferSize], 0, bufferSize);
|
||||||
|
|
@ -200,7 +199,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
MaximumSizeLow = maxResponseBufferSize,
|
MaximumSizeLow = maxResponseBufferSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
using (var socketOutput = CreateSocketOutput(pipeOptions))
|
using (var socketOutput = CreateOutputProducer(pipeOptions))
|
||||||
{
|
{
|
||||||
var bufferSize = maxResponseBufferSize - 1;
|
var bufferSize = maxResponseBufferSize - 1;
|
||||||
var buffer = new ArraySegment<byte>(new byte[bufferSize], 0, bufferSize);
|
var buffer = new ArraySegment<byte>(new byte[bufferSize], 0, bufferSize);
|
||||||
|
|
@ -260,7 +259,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
MaximumSizeLow = maxResponseBufferSize,
|
MaximumSizeLow = maxResponseBufferSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
using (var socketOutput = CreateSocketOutput(pipeOptions))
|
using (var socketOutput = CreateOutputProducer(pipeOptions))
|
||||||
{
|
{
|
||||||
var bufferSize = maxResponseBufferSize / 2;
|
var bufferSize = maxResponseBufferSize / 2;
|
||||||
var data = new byte[bufferSize];
|
var data = new byte[bufferSize];
|
||||||
|
|
@ -328,7 +327,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
MaximumSizeLow = maxResponseBufferSize,
|
MaximumSizeLow = maxResponseBufferSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
using (var socketOutput = CreateSocketOutput(pipeOptions, mockConnection))
|
using (var socketOutput = CreateOutputProducer(pipeOptions, mockConnection))
|
||||||
{
|
{
|
||||||
var bufferSize = maxResponseBufferSize - 1;
|
var bufferSize = maxResponseBufferSize - 1;
|
||||||
|
|
||||||
|
|
@ -400,7 +399,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
MaximumSizeLow = maxResponseBufferSize,
|
MaximumSizeLow = maxResponseBufferSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
using (var socketOutput = CreateSocketOutput(pipeOptions))
|
using (var socketOutput = CreateOutputProducer(pipeOptions))
|
||||||
{
|
{
|
||||||
var bufferSize = maxResponseBufferSize - 1;
|
var bufferSize = maxResponseBufferSize - 1;
|
||||||
var buffer = new ArraySegment<byte>(new byte[bufferSize], 0, bufferSize);
|
var buffer = new ArraySegment<byte>(new byte[bufferSize], 0, bufferSize);
|
||||||
|
|
@ -458,7 +457,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
MaximumSizeLow = maxResponseBufferSize ?? 0,
|
MaximumSizeLow = maxResponseBufferSize ?? 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
using (var socketOutput = CreateSocketOutput(pipeOptions))
|
using (var socketOutput = CreateOutputProducer(pipeOptions))
|
||||||
{
|
{
|
||||||
_mockLibuv.KestrelThreadBlocker.Reset();
|
_mockLibuv.KestrelThreadBlocker.Reset();
|
||||||
|
|
||||||
|
|
@ -487,46 +486,21 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task AllocCommitCanBeCalledAfterConnectionClose()
|
|
||||||
{
|
|
||||||
var pipeOptions = new PipeOptions
|
|
||||||
{
|
|
||||||
ReaderScheduler = _libuvThread,
|
|
||||||
};
|
|
||||||
|
|
||||||
using (var connection = new MockConnection())
|
|
||||||
{
|
|
||||||
var socketOutput = CreateSocketOutput(pipeOptions, connection);
|
|
||||||
// Close SocketOutput
|
|
||||||
socketOutput.Dispose();
|
|
||||||
|
|
||||||
await _mockLibuv.OnPostTask;
|
private OutputProducer CreateOutputProducer(PipeOptions pipeOptions, MockConnection connection = null)
|
||||||
|
|
||||||
Assert.Equal(TaskStatus.RanToCompletion, connection.SocketClosed.Status);
|
|
||||||
|
|
||||||
var called = false;
|
|
||||||
|
|
||||||
((ISocketOutput)socketOutput).Write<object>((buffer, state) =>
|
|
||||||
{
|
|
||||||
called = true;
|
|
||||||
},
|
|
||||||
null);
|
|
||||||
|
|
||||||
Assert.False(called);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private OutputProducer CreateSocketOutput(PipeOptions pipeOptions, MockConnection connection = null)
|
|
||||||
{
|
{
|
||||||
var pipe = _pipeFactory.Create(pipeOptions);
|
var pipe = _pipeFactory.Create(pipeOptions);
|
||||||
var serviceContext = new TestServiceContext();
|
|
||||||
|
var logger = new TestApplicationErrorLogger();
|
||||||
|
var serviceContext = new TestServiceContext() { Log = new TestKestrelTrace(logger) };
|
||||||
|
var transportContext = new TestLibuvTransportContext() { Log = new LibuvTrace(logger) };
|
||||||
|
|
||||||
var frame = new Frame<object>(null, new FrameContext { ServiceContext = serviceContext });
|
var frame = new Frame<object>(null, new FrameContext { ServiceContext = serviceContext });
|
||||||
|
|
||||||
var socket = new MockSocket(_mockLibuv, _libuvThread.Loop.ThreadId, serviceContext.TransportContext.Log);
|
var socket = new MockSocket(_mockLibuv, _libuvThread.Loop.ThreadId, transportContext.Log);
|
||||||
var socketOutput = new OutputProducer(pipe.Writer, frame, "0", serviceContext.Log);
|
var socketOutput = new OutputProducer(pipe.Writer, frame, "0", serviceContext.Log);
|
||||||
var consumer = new LibuvOutputConsumer(pipe.Reader, _libuvThread, socket, connection ?? new MockConnection(), "0", serviceContext.TransportContext.Log);
|
var consumer = new LibuvOutputConsumer(pipe.Reader, _libuvThread, socket, connection ?? new MockConnection(), "0", transportContext.Log);
|
||||||
var ignore = consumer.StartWrites();
|
var ignore = consumer.StartWrites();
|
||||||
|
|
||||||
return socketOutput;
|
return socketOutput;
|
||||||
|
|
@ -2,14 +2,13 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv;
|
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
{
|
{
|
||||||
public class LibuvTransportFactoryTests
|
public class LibuvTransportFactoryTests
|
||||||
{
|
{
|
||||||
|
|
@ -2,10 +2,9 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
{
|
{
|
||||||
public class LibuvTransportOptionsTests
|
public class LibuvTransportOptionsTests
|
||||||
{
|
{
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers;
|
||||||
|
using Microsoft.AspNetCore.Testing;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
|
{
|
||||||
|
public class LibuvTransportTests
|
||||||
|
{
|
||||||
|
public static TheoryData<ListenOptions> ConnectionAdapterData => new TheoryData<ListenOptions>
|
||||||
|
{
|
||||||
|
new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0)),
|
||||||
|
new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0))
|
||||||
|
{
|
||||||
|
ConnectionAdapters = { new PassThroughConnectionAdapter() }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task TransportCanBindAndStop()
|
||||||
|
{
|
||||||
|
var transportContext = new TestLibuvTransportContext();
|
||||||
|
var transport = new LibuvTransport(transportContext,
|
||||||
|
new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0)));
|
||||||
|
|
||||||
|
// The transport can no longer start threads without binding to an endpoint.
|
||||||
|
await transport.BindAsync();
|
||||||
|
await transport.StopAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task TransportCanBindUnbindAndStop(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var transportContext = new TestLibuvTransportContext();
|
||||||
|
var transport = new LibuvTransport(transportContext, listenOptions);
|
||||||
|
|
||||||
|
await transport.BindAsync();
|
||||||
|
await transport.UnbindAsync();
|
||||||
|
await transport.StopAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ConnectionAdapterData))]
|
||||||
|
public async Task ConnectionCanReadAndWrite(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
var transportContext = new TestLibuvTransportContext()
|
||||||
|
{
|
||||||
|
ConnectionHandler = new ConnectionHandler<HttpContext>(listenOptions, new TestServiceContext(), new DummyApplication(TestApp.EchoApp))
|
||||||
|
};
|
||||||
|
var transport = new LibuvTransport(transportContext, listenOptions);
|
||||||
|
|
||||||
|
await transport.BindAsync();
|
||||||
|
|
||||||
|
using (var socket = TestConnection.CreateConnectedLoopbackSocket(listenOptions.IPEndPoint.Port))
|
||||||
|
{
|
||||||
|
var data = "Hello World";
|
||||||
|
socket.Send(Encoding.ASCII.GetBytes($"POST / HTTP/1.0\r\nContent-Length: 11\r\n\r\n{data}"));
|
||||||
|
var buffer = new byte[data.Length];
|
||||||
|
var read = 0;
|
||||||
|
while (read < data.Length)
|
||||||
|
{
|
||||||
|
read += socket.Receive(buffer, read, buffer.Length - read, SocketFlags.None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await transport.UnbindAsync();
|
||||||
|
await transport.StopAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,15 +9,14 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv;
|
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||||
using Microsoft.AspNetCore.Server.KestrelTests.TestHelpers;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
{
|
{
|
||||||
public class ListenerPrimaryTests
|
public class ListenerPrimaryTests
|
||||||
{
|
{
|
||||||
|
|
@ -28,14 +27,16 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));
|
var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));
|
||||||
|
|
||||||
var serviceContextPrimary = new TestServiceContext();
|
var serviceContextPrimary = new TestServiceContext();
|
||||||
serviceContextPrimary.TransportContext.ConnectionHandler = new ConnectionHandler<HttpContext>(
|
var transportContextPrimary = new TestLibuvTransportContext();
|
||||||
|
transportContextPrimary.ConnectionHandler = new ConnectionHandler<HttpContext>(
|
||||||
listenOptions, serviceContextPrimary, new DummyApplication(c => c.Response.WriteAsync("Primary")));
|
listenOptions, serviceContextPrimary, new DummyApplication(c => c.Response.WriteAsync("Primary")));
|
||||||
|
|
||||||
var serviceContextSecondary = new TestServiceContext();
|
var serviceContextSecondary = new TestServiceContext();
|
||||||
serviceContextSecondary.TransportContext.ConnectionHandler = new ConnectionHandler<HttpContext>(
|
var transportContextSecondary = new TestLibuvTransportContext();
|
||||||
|
transportContextSecondary.ConnectionHandler = new ConnectionHandler<HttpContext>(
|
||||||
listenOptions, serviceContextSecondary, new DummyApplication(c => c.Response.WriteAsync("Secondary")));
|
listenOptions, serviceContextSecondary, new DummyApplication(c => c.Response.WriteAsync("Secondary")));
|
||||||
|
|
||||||
var libuvTransport = new LibuvTransport(libuv, serviceContextPrimary.TransportContext, listenOptions);
|
var libuvTransport = new LibuvTransport(libuv, transportContextPrimary, listenOptions);
|
||||||
|
|
||||||
var pipeName = (libuv.IsWindows ? @"\\.\pipe\kestrel_" : "/tmp/kestrel_") + Guid.NewGuid().ToString("n");
|
var pipeName = (libuv.IsWindows ? @"\\.\pipe\kestrel_" : "/tmp/kestrel_") + Guid.NewGuid().ToString("n");
|
||||||
var pipeMessage = Guid.NewGuid().ToByteArray();
|
var pipeMessage = Guid.NewGuid().ToByteArray();
|
||||||
|
|
@ -43,7 +44,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
// Start primary listener
|
// Start primary listener
|
||||||
var libuvThreadPrimary = new LibuvThread(libuvTransport);
|
var libuvThreadPrimary = new LibuvThread(libuvTransport);
|
||||||
await libuvThreadPrimary.StartAsync();
|
await libuvThreadPrimary.StartAsync();
|
||||||
var listenerPrimary = new ListenerPrimary(serviceContextPrimary.TransportContext);
|
var listenerPrimary = new ListenerPrimary(transportContextPrimary);
|
||||||
await listenerPrimary.StartAsync(pipeName, pipeMessage, listenOptions, libuvThreadPrimary);
|
await listenerPrimary.StartAsync(pipeName, pipeMessage, listenOptions, libuvThreadPrimary);
|
||||||
var address = listenOptions.ToString();
|
var address = listenOptions.ToString();
|
||||||
|
|
||||||
|
|
@ -54,7 +55,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
// Add secondary listener
|
// Add secondary listener
|
||||||
var libuvThreadSecondary = new LibuvThread(libuvTransport);
|
var libuvThreadSecondary = new LibuvThread(libuvTransport);
|
||||||
await libuvThreadSecondary.StartAsync();
|
await libuvThreadSecondary.StartAsync();
|
||||||
var listenerSecondary = new ListenerSecondary(serviceContextSecondary.TransportContext);
|
var listenerSecondary = new ListenerSecondary(transportContextSecondary);
|
||||||
await listenerSecondary.StartAsync(pipeName, pipeMessage, listenOptions, libuvThreadSecondary);
|
await listenerSecondary.StartAsync(pipeName, pipeMessage, listenOptions, libuvThreadSecondary);
|
||||||
|
|
||||||
// Once a secondary listener is added, TCP connections start getting dispatched to it
|
// Once a secondary listener is added, TCP connections start getting dispatched to it
|
||||||
|
|
@ -79,8 +80,11 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
var libuv = new LibuvFunctions();
|
var libuv = new LibuvFunctions();
|
||||||
var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));
|
var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));
|
||||||
|
|
||||||
|
var logger = new TestApplicationErrorLogger();
|
||||||
|
|
||||||
var serviceContextPrimary = new TestServiceContext();
|
var serviceContextPrimary = new TestServiceContext();
|
||||||
serviceContextPrimary.TransportContext.ConnectionHandler = new ConnectionHandler<HttpContext>(
|
var transportContextPrimary = new TestLibuvTransportContext() { Log = new LibuvTrace(logger) };
|
||||||
|
transportContextPrimary.ConnectionHandler = new ConnectionHandler<HttpContext>(
|
||||||
listenOptions, serviceContextPrimary, new DummyApplication(c => c.Response.WriteAsync("Primary")));
|
listenOptions, serviceContextPrimary, new DummyApplication(c => c.Response.WriteAsync("Primary")));
|
||||||
|
|
||||||
var serviceContextSecondary = new TestServiceContext
|
var serviceContextSecondary = new TestServiceContext
|
||||||
|
|
@ -90,10 +94,11 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
ThreadPool = serviceContextPrimary.ThreadPool,
|
ThreadPool = serviceContextPrimary.ThreadPool,
|
||||||
HttpParserFactory = serviceContextPrimary.HttpParserFactory,
|
HttpParserFactory = serviceContextPrimary.HttpParserFactory,
|
||||||
};
|
};
|
||||||
serviceContextSecondary.TransportContext.ConnectionHandler = new ConnectionHandler<HttpContext>(
|
var transportContextSecondary = new TestLibuvTransportContext();
|
||||||
|
transportContextSecondary.ConnectionHandler = new ConnectionHandler<HttpContext>(
|
||||||
listenOptions, serviceContextSecondary, new DummyApplication(c => c.Response.WriteAsync("Secondary")));
|
listenOptions, serviceContextSecondary, new DummyApplication(c => c.Response.WriteAsync("Secondary")));
|
||||||
|
|
||||||
var libuvTransport = new LibuvTransport(libuv, serviceContextPrimary.TransportContext, listenOptions);
|
var libuvTransport = new LibuvTransport(libuv, transportContextPrimary, listenOptions);
|
||||||
|
|
||||||
var pipeName = (libuv.IsWindows ? @"\\.\pipe\kestrel_" : "/tmp/kestrel_") + Guid.NewGuid().ToString("n");
|
var pipeName = (libuv.IsWindows ? @"\\.\pipe\kestrel_" : "/tmp/kestrel_") + Guid.NewGuid().ToString("n");
|
||||||
var pipeMessage = Guid.NewGuid().ToByteArray();
|
var pipeMessage = Guid.NewGuid().ToByteArray();
|
||||||
|
|
@ -101,14 +106,14 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
// Start primary listener
|
// Start primary listener
|
||||||
var libuvThreadPrimary = new LibuvThread(libuvTransport);
|
var libuvThreadPrimary = new LibuvThread(libuvTransport);
|
||||||
await libuvThreadPrimary.StartAsync();
|
await libuvThreadPrimary.StartAsync();
|
||||||
var listenerPrimary = new ListenerPrimary(serviceContextPrimary.TransportContext);
|
var listenerPrimary = new ListenerPrimary(transportContextPrimary);
|
||||||
await listenerPrimary.StartAsync(pipeName, pipeMessage, listenOptions, libuvThreadPrimary);
|
await listenerPrimary.StartAsync(pipeName, pipeMessage, listenOptions, libuvThreadPrimary);
|
||||||
var address = listenOptions.ToString();
|
var address = listenOptions.ToString();
|
||||||
|
|
||||||
// Add secondary listener
|
// Add secondary listener
|
||||||
var libuvThreadSecondary = new LibuvThread(libuvTransport);
|
var libuvThreadSecondary = new LibuvThread(libuvTransport);
|
||||||
await libuvThreadSecondary.StartAsync();
|
await libuvThreadSecondary.StartAsync();
|
||||||
var listenerSecondary = new ListenerSecondary(serviceContextSecondary.TransportContext);
|
var listenerSecondary = new ListenerSecondary(transportContextSecondary);
|
||||||
await listenerSecondary.StartAsync(pipeName, pipeMessage, listenOptions, libuvThreadSecondary);
|
await listenerSecondary.StartAsync(pipeName, pipeMessage, listenOptions, libuvThreadSecondary);
|
||||||
|
|
||||||
// TCP Connections get round-robined
|
// TCP Connections get round-robined
|
||||||
|
|
@ -155,10 +160,8 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
|
|
||||||
await libuvThreadPrimary.PostAsync(_ => pipe.Dispose(), (object)null);
|
await libuvThreadPrimary.PostAsync(_ => pipe.Dispose(), (object)null);
|
||||||
|
|
||||||
var primaryTrace = (TestKestrelTrace)serviceContextPrimary.Log;
|
|
||||||
|
|
||||||
// Wait up to 10 seconds for error to be logged
|
// Wait up to 10 seconds for error to be logged
|
||||||
for (var i = 0; i < 10 && primaryTrace.Logger.TotalErrorsLogged == 0; i++)
|
for (var i = 0; i < 10 && logger.TotalErrorsLogged == 0; i++)
|
||||||
{
|
{
|
||||||
await Task.Delay(100);
|
await Task.Delay(100);
|
||||||
}
|
}
|
||||||
|
|
@ -174,8 +177,8 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
await listenerPrimary.DisposeAsync();
|
await listenerPrimary.DisposeAsync();
|
||||||
await libuvThreadPrimary.StopAsync(TimeSpan.FromSeconds(1));
|
await libuvThreadPrimary.StopAsync(TimeSpan.FromSeconds(1));
|
||||||
|
|
||||||
Assert.Equal(1, primaryTrace.Logger.TotalErrorsLogged);
|
Assert.Equal(1, logger.TotalErrorsLogged);
|
||||||
var errorMessage = primaryTrace.Logger.Messages.First(m => m.LogLevel == LogLevel.Error);
|
var errorMessage = logger.Messages.First(m => m.LogLevel == LogLevel.Error);
|
||||||
Assert.Equal(TestConstants.EOF, Assert.IsType<UvException>(errorMessage.Exception).StatusCode);
|
Assert.Equal(TestConstants.EOF, Assert.IsType<UvException>(errorMessage.Exception).StatusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -186,8 +189,11 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
var libuv = new LibuvFunctions();
|
var libuv = new LibuvFunctions();
|
||||||
var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));
|
var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));
|
||||||
|
|
||||||
|
var logger = new TestApplicationErrorLogger();
|
||||||
|
|
||||||
var serviceContextPrimary = new TestServiceContext();
|
var serviceContextPrimary = new TestServiceContext();
|
||||||
serviceContextPrimary.TransportContext.ConnectionHandler = new ConnectionHandler<HttpContext>(
|
var transportContextPrimary = new TestLibuvTransportContext() { Log = new LibuvTrace(logger) };
|
||||||
|
transportContextPrimary.ConnectionHandler = new ConnectionHandler<HttpContext>(
|
||||||
listenOptions, serviceContextPrimary, new DummyApplication(c => c.Response.WriteAsync("Primary")));
|
listenOptions, serviceContextPrimary, new DummyApplication(c => c.Response.WriteAsync("Primary")));
|
||||||
|
|
||||||
var serviceContextSecondary = new TestServiceContext
|
var serviceContextSecondary = new TestServiceContext
|
||||||
|
|
@ -197,10 +203,11 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
ThreadPool = serviceContextPrimary.ThreadPool,
|
ThreadPool = serviceContextPrimary.ThreadPool,
|
||||||
HttpParserFactory = serviceContextPrimary.HttpParserFactory,
|
HttpParserFactory = serviceContextPrimary.HttpParserFactory,
|
||||||
};
|
};
|
||||||
serviceContextSecondary.TransportContext.ConnectionHandler = new ConnectionHandler<HttpContext>(
|
var transportContextSecondary = new TestLibuvTransportContext();
|
||||||
|
transportContextSecondary.ConnectionHandler = new ConnectionHandler<HttpContext>(
|
||||||
listenOptions, serviceContextSecondary, new DummyApplication(c => c.Response.WriteAsync("Secondary")));
|
listenOptions, serviceContextSecondary, new DummyApplication(c => c.Response.WriteAsync("Secondary")));
|
||||||
|
|
||||||
var libuvTransport = new LibuvTransport(libuv, serviceContextPrimary.TransportContext, listenOptions);
|
var libuvTransport = new LibuvTransport(libuv, transportContextPrimary, listenOptions);
|
||||||
|
|
||||||
var pipeName = (libuv.IsWindows ? @"\\.\pipe\kestrel_" : "/tmp/kestrel_") + Guid.NewGuid().ToString("n");
|
var pipeName = (libuv.IsWindows ? @"\\.\pipe\kestrel_" : "/tmp/kestrel_") + Guid.NewGuid().ToString("n");
|
||||||
var pipeMessage = Guid.NewGuid().ToByteArray();
|
var pipeMessage = Guid.NewGuid().ToByteArray();
|
||||||
|
|
@ -208,20 +215,18 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
// Start primary listener
|
// Start primary listener
|
||||||
var libuvThreadPrimary = new LibuvThread(libuvTransport);
|
var libuvThreadPrimary = new LibuvThread(libuvTransport);
|
||||||
await libuvThreadPrimary.StartAsync();
|
await libuvThreadPrimary.StartAsync();
|
||||||
var listenerPrimary = new ListenerPrimary(serviceContextPrimary.TransportContext);
|
var listenerPrimary = new ListenerPrimary(transportContextPrimary);
|
||||||
await listenerPrimary.StartAsync(pipeName, pipeMessage, listenOptions, libuvThreadPrimary);
|
await listenerPrimary.StartAsync(pipeName, pipeMessage, listenOptions, libuvThreadPrimary);
|
||||||
var address = listenOptions.ToString();
|
var address = listenOptions.ToString();
|
||||||
|
|
||||||
// Add secondary listener with wrong pipe message
|
// Add secondary listener with wrong pipe message
|
||||||
var libuvThreadSecondary = new LibuvThread(libuvTransport);
|
var libuvThreadSecondary = new LibuvThread(libuvTransport);
|
||||||
await libuvThreadSecondary.StartAsync();
|
await libuvThreadSecondary.StartAsync();
|
||||||
var listenerSecondary = new ListenerSecondary(serviceContextSecondary.TransportContext);
|
var listenerSecondary = new ListenerSecondary(transportContextSecondary);
|
||||||
await listenerSecondary.StartAsync(pipeName, Guid.NewGuid().ToByteArray(), listenOptions, libuvThreadSecondary);
|
await listenerSecondary.StartAsync(pipeName, Guid.NewGuid().ToByteArray(), listenOptions, libuvThreadSecondary);
|
||||||
|
|
||||||
var primaryTrace = (TestKestrelTrace)serviceContextPrimary.Log;
|
|
||||||
|
|
||||||
// Wait up to 10 seconds for error to be logged
|
// Wait up to 10 seconds for error to be logged
|
||||||
for (var i = 0; i < 10 && primaryTrace.Logger.TotalErrorsLogged == 0; i++)
|
for (var i = 0; i < 10 && logger.TotalErrorsLogged == 0; i++)
|
||||||
{
|
{
|
||||||
await Task.Delay(100);
|
await Task.Delay(100);
|
||||||
}
|
}
|
||||||
|
|
@ -237,8 +242,8 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
await listenerPrimary.DisposeAsync();
|
await listenerPrimary.DisposeAsync();
|
||||||
await libuvThreadPrimary.StopAsync(TimeSpan.FromSeconds(1));
|
await libuvThreadPrimary.StopAsync(TimeSpan.FromSeconds(1));
|
||||||
|
|
||||||
Assert.Equal(1, primaryTrace.Logger.TotalErrorsLogged);
|
Assert.Equal(1, logger.TotalErrorsLogged);
|
||||||
var errorMessage = primaryTrace.Logger.Messages.First(m => m.LogLevel == LogLevel.Error);
|
var errorMessage = logger.Messages.First(m => m.LogLevel == LogLevel.Error);
|
||||||
Assert.IsType<IOException>(errorMessage.Exception);
|
Assert.IsType<IOException>(errorMessage.Exception);
|
||||||
Assert.Contains("Bad data", errorMessage.Exception.ToString());
|
Assert.Contains("Bad data", errorMessage.Exception.ToString());
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<Import Project="..\..\build\common.props" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFrameworks>netcoreapp2.0;net46</TargetFrameworks>
|
||||||
|
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netcoreapp2.0</TargetFrameworks>
|
||||||
|
<PlatformTarget Condition="'$(TargetFramework)' == 'net46'">x64</PlatformTarget>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="..\shared\**\*.cs" />
|
||||||
|
<None Include="xunit.runner.json" CopyToOutputDirectory="PreserveNewest" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Server.Kestrel.Core\Microsoft.AspNetCore.Server.Kestrel.Core.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Http" Version="$(AspNetCoreVersion)" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Testing" Version="$(AspNetCoreVersion)" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
|
||||||
|
<PackageReference Include="Moq" Version="$(MoqVersion)" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitVersion)" />
|
||||||
|
<PackageReference Include="xunit" Version="$(XunitVersion)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -6,14 +6,14 @@ using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers;
|
||||||
using Microsoft.AspNetCore.Server.KestrelTests.TestHelpers;
|
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
{
|
{
|
||||||
public class MultipleLoopTests
|
public class MultipleLoopTests
|
||||||
{
|
{
|
||||||
|
|
@ -12,7 +12,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Summary description for NetworkingTests
|
/// Summary description for NetworkingTests
|
||||||
|
|
@ -4,11 +4,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
||||||
using Microsoft.Extensions.Internal;
|
using Microsoft.Extensions.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Testing
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
|
||||||
{
|
{
|
||||||
public class MockConnection : LibuvConnection, IDisposable
|
public class MockConnection : LibuvConnection, IDisposable
|
||||||
{
|
{
|
||||||
|
|
@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests.TestHelpers
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
|
||||||
{
|
{
|
||||||
public class MockConnectionHandler : IConnectionHandler, IDisposable
|
public class MockConnectionHandler : IConnectionHandler, IDisposable
|
||||||
{
|
{
|
||||||
|
|
@ -6,7 +6,7 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests.TestHelpers
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
|
||||||
{
|
{
|
||||||
public class MockLibuv : LibuvFunctions
|
public class MockLibuv : LibuvFunctions
|
||||||
{
|
{
|
||||||
|
|
@ -5,7 +5,7 @@ using System;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests.TestHelpers
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
|
||||||
{
|
{
|
||||||
class MockSocket : UvStreamHandle
|
class MockSocket : UvStreamHandle
|
||||||
{
|
{
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests.TestHelpers
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
|
||||||
{
|
{
|
||||||
public class TestConstants
|
public class TestConstants
|
||||||
{
|
{
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
||||||
|
using Microsoft.AspNetCore.Testing;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
|
||||||
|
{
|
||||||
|
public class TestLibuvTransportContext : LibuvTransportContext
|
||||||
|
{
|
||||||
|
public TestLibuvTransportContext()
|
||||||
|
{
|
||||||
|
var logger = new TestApplicationErrorLogger();
|
||||||
|
|
||||||
|
AppLifetime = new LifetimeNotImplemented();
|
||||||
|
ConnectionHandler = new MockConnectionHandler();
|
||||||
|
Log = new LibuvTrace(logger);
|
||||||
|
Options = new LibuvTransportOptions
|
||||||
|
{
|
||||||
|
ThreadCount = 1,
|
||||||
|
ShutdownTimeout = TimeSpan.FromSeconds(5)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,11 +3,11 @@
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||||
using Microsoft.AspNetCore.Server.KestrelTests.TestHelpers;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
{
|
{
|
||||||
public class UvStreamHandleTests
|
public class UvStreamHandleTests
|
||||||
{
|
{
|
||||||
|
|
@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
|
||||||
{
|
{
|
||||||
public class UvTimerHandleTests
|
public class UvTimerHandleTests
|
||||||
{
|
{
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json.schemastore.org/xunit.runner.schema",
|
||||||
|
"appDomain": "denied",
|
||||||
|
"methodDisplay": "method",
|
||||||
|
"longRunningTestSeconds": 60
|
||||||
|
}
|
||||||
|
|
@ -33,6 +33,8 @@ namespace Microsoft.AspNetCore.Testing
|
||||||
Tuple.Create("/a%C3%A5a", "/a\u00E5a"),
|
Tuple.Create("/a%C3%A5a", "/a\u00E5a"),
|
||||||
Tuple.Create("/%C3%A5/bc", "/\u00E5/bc"),
|
Tuple.Create("/%C3%A5/bc", "/\u00E5/bc"),
|
||||||
Tuple.Create("/%25", "/%"),
|
Tuple.Create("/%25", "/%"),
|
||||||
|
Tuple.Create("/%25%30%30", "/%00"),
|
||||||
|
Tuple.Create("/%%2000", "/% 00"),
|
||||||
Tuple.Create("/%2F", "/%2F"),
|
Tuple.Create("/%2F", "/%2F"),
|
||||||
Tuple.Create("http://host/abs/path", "/abs/path"),
|
Tuple.Create("http://host/abs/path", "/abs/path"),
|
||||||
Tuple.Create("http://host/abs/path/", "/abs/path/"),
|
Tuple.Create("http://host/abs/path/", "/abs/path/"),
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,10 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv;
|
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Testing
|
namespace Microsoft.AspNetCore.Testing
|
||||||
{
|
{
|
||||||
|
|
@ -26,21 +23,8 @@ namespace Microsoft.AspNetCore.Testing
|
||||||
{
|
{
|
||||||
AddServerHeader = false
|
AddServerHeader = false
|
||||||
};
|
};
|
||||||
|
|
||||||
TransportContext = new LibuvTransportContext
|
|
||||||
{
|
|
||||||
AppLifetime = new LifetimeNotImplemented(),
|
|
||||||
Log = new LibuvTrace(logger),
|
|
||||||
Options = new LibuvTransportOptions
|
|
||||||
{
|
|
||||||
ThreadCount = 1,
|
|
||||||
ShutdownTimeout = TimeSpan.FromSeconds(5)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string DateHeaderValue { get; }
|
public string DateHeaderValue { get; }
|
||||||
|
|
||||||
public LibuvTransportContext TransportContext { get; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue