11// Licensed to the .NET Foundation under one or more agreements.
22// The .NET Foundation licenses this file to you under the MIT license.
33
4- using System ;
4+ using System . Diagnostics ;
55using System . Globalization ;
6- using System . Linq ;
76using System . Net . Http ;
87using System . Net . Sockets ;
98using System . Net . WebSockets ;
109using System . Text ;
11- using System . Threading ;
12- using System . Threading . Tasks ;
13- using Microsoft . AspNetCore . Server . IIS . FunctionalTests ;
1410using Microsoft . AspNetCore . InternalTesting ;
15- using Xunit ;
11+ using Microsoft . AspNetCore . Server . IntegrationTesting ;
12+ using Microsoft . AspNetCore . Server . IntegrationTesting . IIS ;
13+ using Xunit . Abstractions ;
14+
15+ #if ! IIS_FUNCTIONALS
16+ using Microsoft . AspNetCore . Server . IIS . FunctionalTests ;
1617
18+ #if IISEXPRESS_FUNCTIONALS
1719namespace Microsoft . AspNetCore . Server . IIS . IISExpress . FunctionalTests ;
20+ #elif NEWHANDLER_FUNCTIONALS
21+ namespace Microsoft . AspNetCore . Server . IIS . NewHandler . FunctionalTests ;
22+ #elif NEWSHIM_FUNCTIONALS
23+ namespace Microsoft . AspNetCore . Server . IIS . NewShim . FunctionalTests ;
24+ #endif
25+ #else
1826
19- [ Collection ( IISTestSiteCollection . Name ) ]
20- [ MinimumOSVersion ( OperatingSystems . Windows , WindowsVersions . Win8 , SkipReason = "No WebSocket supported on Win7" ) ]
21- [ SkipOnHelix ( "Unsupported queue" , Queues = "Windows.Amd64.VS2022.Pre.Open;" ) ]
22- public class WebSocketsTests
27+ namespace Microsoft . AspNetCore . Server . IIS . FunctionalTests ;
28+ #endif
29+
30+ public abstract class WebSocketsTests : FunctionalTestsBase
2331{
24- private readonly string _requestUri ;
25- private readonly string _webSocketUri ;
32+ public IISTestSiteFixture Fixture { get ; }
2633
27- public WebSocketsTests ( IISTestSiteFixture fixture )
34+ public WebSocketsTests ( IISTestSiteFixture fixture , ITestOutputHelper testOutput ) : base ( testOutput )
2835 {
29- _requestUri = fixture . DeploymentResult . ApplicationBaseUri ;
30- _webSocketUri = _requestUri . Replace ( "http:" , "ws:" ) ;
36+ Fixture = fixture ;
3137 }
3238
3339 [ ConditionalFact ]
3440 public async Task RequestWithBody_NotUpgradable ( )
3541 {
3642 using var client = new HttpClient ( ) { Timeout = TimeSpan . FromSeconds ( 200 ) } ;
37- using var response = await client . PostAsync ( _requestUri + "WebSocketNotUpgradable" , new StringContent ( "Hello World" ) ) ;
43+ using var response = await client . PostAsync ( Fixture . DeploymentResult . ApplicationBaseUri + "WebSocketNotUpgradable" , new StringContent ( "Hello World" ) ) ;
3844 response . EnsureSuccessStatusCode ( ) ;
3945 }
4046
4147 [ ConditionalFact ]
4248 public async Task RequestWithoutBody_Upgradable ( )
4349 {
50+ if ( Fixture . DeploymentParameters . HostingModel == HostingModel . OutOfProcess )
51+ {
52+ // OutOfProcess doesn't support upgrade requests without the "Upgrade": "websocket" header.
53+ return ;
54+ }
55+
4456 using var client = new HttpClient ( ) { Timeout = TimeSpan . FromSeconds ( 200 ) } ;
4557 // POST with Content-Length: 0 counts as not having a body.
46- using var response = await client . PostAsync ( _requestUri + "WebSocketUpgradable" , new StringContent ( "" ) ) ;
58+ using var response = await client . PostAsync ( Fixture . DeploymentResult . ApplicationBaseUri + "WebSocketUpgradable" , new StringContent ( "" ) ) ;
4759 response . EnsureSuccessStatusCode ( ) ;
4860 }
4961
5062 [ ConditionalFact ]
5163 public async Task OnStartedCalledForWebSocket ( )
5264 {
53- var cws = new ClientWebSocket ( ) ;
54- await cws . ConnectAsync ( new Uri ( _webSocketUri + "WebSocketLifetimeEvents" ) , default ) ;
65+ var webSocketUri = Fixture . DeploymentResult . ApplicationBaseUri ;
66+ webSocketUri = webSocketUri . Replace ( "http:" , "ws:" ) ;
67+
68+ using var cws = new ClientWebSocket ( ) ;
69+ await cws . ConnectAsync ( new Uri ( webSocketUri + "WebSocketLifetimeEvents" ) , default ) ;
5570
5671 await ReceiveMessage ( cws , "OnStarting" ) ;
5772 await ReceiveMessage ( cws , "Upgraded" ) ;
@@ -60,17 +75,23 @@ public async Task OnStartedCalledForWebSocket()
6075 [ ConditionalFact ]
6176 public async Task WebReadBeforeUpgrade ( )
6277 {
63- var cws = new ClientWebSocket ( ) ;
64- await cws . ConnectAsync ( new Uri ( _webSocketUri + "WebSocketReadBeforeUpgrade" ) , default ) ;
78+ var webSocketUri = Fixture . DeploymentResult . ApplicationBaseUri ;
79+ webSocketUri = webSocketUri . Replace ( "http:" , "ws:" ) ;
80+
81+ using var cws = new ClientWebSocket ( ) ;
82+ await cws . ConnectAsync ( new Uri ( webSocketUri + "WebSocketReadBeforeUpgrade" ) , default ) ;
6583
6684 await ReceiveMessage ( cws , "Yay" ) ;
6785 }
6886
6987 [ ConditionalFact ]
7088 public async Task CanSendAndReceieveData ( )
7189 {
72- var cws = new ClientWebSocket ( ) ;
73- await cws . ConnectAsync ( new Uri ( _webSocketUri + "WebSocketEcho" ) , default ) ;
90+ var webSocketUri = Fixture . DeploymentResult . ApplicationBaseUri ;
91+ webSocketUri = webSocketUri . Replace ( "http:" , "ws:" ) ;
92+
93+ using var cws = new ClientWebSocket ( ) ;
94+ await cws . ConnectAsync ( new Uri ( webSocketUri + "WebSocketEcho" ) , default ) ;
7495
7596 for ( int i = 0 ; i < 1000 ; i ++ )
7697 {
@@ -80,10 +101,33 @@ public async Task CanSendAndReceieveData()
80101 }
81102 }
82103
104+ [ ConditionalFact ]
105+ public async Task AttemptCompressionWorks ( )
106+ {
107+ var webSocketUri = Fixture . DeploymentResult . ApplicationBaseUri ;
108+ webSocketUri = webSocketUri . Replace ( "http:" , "ws:" ) ;
109+
110+ using var cws = new ClientWebSocket ( ) ;
111+ cws . Options . DangerousDeflateOptions = new WebSocketDeflateOptions ( ) ;
112+ await cws . ConnectAsync ( new Uri ( webSocketUri + "WebSocketAllowCompression" ) , default ) ;
113+
114+ // Compression doesn't work with OutOfProcess, let's make sure the websocket extensions aren't forwarded and the connection still works
115+ var expected = Fixture . DeploymentParameters . HostingModel == HostingModel . InProcess
116+ ? "permessage-deflate; client_max_window_bits=15" : "None" ;
117+ await ReceiveMessage ( cws , expected ) ;
118+
119+ for ( int i = 0 ; i < 1000 ; i ++ )
120+ {
121+ var message = i . ToString ( CultureInfo . InvariantCulture ) ;
122+ await SendMessage ( cws , message ) ;
123+ await ReceiveMessage ( cws , message ) ;
124+ }
125+ }
126+
83127 [ ConditionalFact ]
84128 public async Task Http1_0_Request_NotUpgradable ( )
85129 {
86- Uri uri = new Uri ( _requestUri + "WebSocketNotUpgradable" ) ;
130+ Uri uri = new Uri ( Fixture . DeploymentResult . ApplicationBaseUri + "WebSocketNotUpgradable" ) ;
87131 using TcpClient client = new TcpClient ( ) ;
88132
89133 await client . ConnectAsync ( uri . Host , uri . Port ) ;
@@ -103,7 +147,7 @@ public async Task Http1_0_Request_NotUpgradable()
103147 [ ConditionalFact ]
104148 public async Task Http1_0_Request_UpgradeErrors ( )
105149 {
106- Uri uri = new Uri ( _requestUri + "WebSocketUpgradeFails" ) ;
150+ Uri uri = new Uri ( Fixture . DeploymentResult . ApplicationBaseUri + "WebSocketUpgradeFails" ) ;
107151 using TcpClient client = new TcpClient ( ) ;
108152
109153 await client . ConnectAsync ( uri . Host , uri . Port ) ;
@@ -148,6 +192,7 @@ private async Task SendMessage(ClientWebSocket webSocket, string message)
148192
149193 private async Task ReceiveMessage ( ClientWebSocket webSocket , string expectedMessage )
150194 {
195+ Debug . Assert ( expectedMessage . Length > 0 ) ;
151196 var received = new byte [ expectedMessage . Length ] ;
152197
153198 var offset = 0 ;
@@ -156,7 +201,7 @@ private async Task ReceiveMessage(ClientWebSocket webSocket, string expectedMess
156201 {
157202 result = await webSocket . ReceiveAsync ( new ArraySegment < byte > ( received , offset , received . Length - offset ) , default ) ;
158203 offset += result . Count ;
159- } while ( ! result . EndOfMessage ) ;
204+ } while ( ! result . EndOfMessage && result . CloseStatus is null && received . Length - offset > 0 ) ;
160205
161206 Assert . Equal ( expectedMessage , Encoding . ASCII . GetString ( received ) ) ;
162207 }
0 commit comments