1
1
// Licensed to the .NET Foundation under one or more agreements.
2
2
// The .NET Foundation licenses this file to you under the MIT license.
3
3
4
- using System ;
4
+ using System . Diagnostics ;
5
5
using System . Globalization ;
6
- using System . Linq ;
7
6
using System . Net . Http ;
8
7
using System . Net . Sockets ;
9
8
using System . Net . WebSockets ;
10
9
using System . Text ;
11
- using System . Threading ;
12
- using System . Threading . Tasks ;
13
- using Microsoft . AspNetCore . Server . IIS . FunctionalTests ;
14
10
using 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 ;
16
17
18
+ #if IISEXPRESS_FUNCTIONALS
17
19
namespace 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
18
26
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
23
31
{
24
- private readonly string _requestUri ;
25
- private readonly string _webSocketUri ;
32
+ public IISTestSiteFixture Fixture { get ; }
26
33
27
- public WebSocketsTests ( IISTestSiteFixture fixture )
34
+ public WebSocketsTests ( IISTestSiteFixture fixture , ITestOutputHelper testOutput ) : base ( testOutput )
28
35
{
29
- _requestUri = fixture . DeploymentResult . ApplicationBaseUri ;
30
- _webSocketUri = _requestUri . Replace ( "http:" , "ws:" ) ;
36
+ Fixture = fixture ;
31
37
}
32
38
33
39
[ ConditionalFact ]
34
40
public async Task RequestWithBody_NotUpgradable ( )
35
41
{
36
42
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" ) ) ;
38
44
response . EnsureSuccessStatusCode ( ) ;
39
45
}
40
46
41
47
[ ConditionalFact ]
42
48
public async Task RequestWithoutBody_Upgradable ( )
43
49
{
50
+ if ( Fixture . DeploymentParameters . HostingModel == HostingModel . OutOfProcess )
51
+ {
52
+ // OutOfProcess doesn't support upgrade requests without the "Upgrade": "websocket" header.
53
+ return ;
54
+ }
55
+
44
56
using var client = new HttpClient ( ) { Timeout = TimeSpan . FromSeconds ( 200 ) } ;
45
57
// 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 ( "" ) ) ;
47
59
response . EnsureSuccessStatusCode ( ) ;
48
60
}
49
61
50
62
[ ConditionalFact ]
51
63
public async Task OnStartedCalledForWebSocket ( )
52
64
{
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 ) ;
55
70
56
71
await ReceiveMessage ( cws , "OnStarting" ) ;
57
72
await ReceiveMessage ( cws , "Upgraded" ) ;
@@ -60,17 +75,23 @@ public async Task OnStartedCalledForWebSocket()
60
75
[ ConditionalFact ]
61
76
public async Task WebReadBeforeUpgrade ( )
62
77
{
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 ) ;
65
83
66
84
await ReceiveMessage ( cws , "Yay" ) ;
67
85
}
68
86
69
87
[ ConditionalFact ]
70
88
public async Task CanSendAndReceieveData ( )
71
89
{
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 ) ;
74
95
75
96
for ( int i = 0 ; i < 1000 ; i ++ )
76
97
{
@@ -80,10 +101,33 @@ public async Task CanSendAndReceieveData()
80
101
}
81
102
}
82
103
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
+
83
127
[ ConditionalFact ]
84
128
public async Task Http1_0_Request_NotUpgradable ( )
85
129
{
86
- Uri uri = new Uri ( _requestUri + "WebSocketNotUpgradable" ) ;
130
+ Uri uri = new Uri ( Fixture . DeploymentResult . ApplicationBaseUri + "WebSocketNotUpgradable" ) ;
87
131
using TcpClient client = new TcpClient ( ) ;
88
132
89
133
await client . ConnectAsync ( uri . Host , uri . Port ) ;
@@ -103,7 +147,7 @@ public async Task Http1_0_Request_NotUpgradable()
103
147
[ ConditionalFact ]
104
148
public async Task Http1_0_Request_UpgradeErrors ( )
105
149
{
106
- Uri uri = new Uri ( _requestUri + "WebSocketUpgradeFails" ) ;
150
+ Uri uri = new Uri ( Fixture . DeploymentResult . ApplicationBaseUri + "WebSocketUpgradeFails" ) ;
107
151
using TcpClient client = new TcpClient ( ) ;
108
152
109
153
await client . ConnectAsync ( uri . Host , uri . Port ) ;
@@ -148,6 +192,7 @@ private async Task SendMessage(ClientWebSocket webSocket, string message)
148
192
149
193
private async Task ReceiveMessage ( ClientWebSocket webSocket , string expectedMessage )
150
194
{
195
+ Debug . Assert ( expectedMessage . Length > 0 ) ;
151
196
var received = new byte [ expectedMessage . Length ] ;
152
197
153
198
var offset = 0 ;
@@ -156,7 +201,7 @@ private async Task ReceiveMessage(ClientWebSocket webSocket, string expectedMess
156
201
{
157
202
result = await webSocket . ReceiveAsync ( new ArraySegment < byte > ( received , offset , received . Length - offset ) , default ) ;
158
203
offset += result . Count ;
159
- } while ( ! result . EndOfMessage ) ;
204
+ } while ( ! result . EndOfMessage && result . CloseStatus is null && received . Length - offset > 0 ) ;
160
205
161
206
Assert . Equal ( expectedMessage , Encoding . ASCII . GetString ( received ) ) ;
162
207
}
0 commit comments