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 . IIS . FunctionalTests ;
12
+ using Microsoft . AspNetCore . Server . IntegrationTesting ;
13
+ using Microsoft . AspNetCore . Server . IntegrationTesting . IIS ;
14
+ using Xunit . Abstractions ;
15
+
16
+ #if ! IIS_FUNCTIONALS
17
+ using Microsoft . AspNetCore . Server . IIS . FunctionalTests ;
16
18
19
+ #if IISEXPRESS_FUNCTIONALS
17
20
namespace Microsoft . AspNetCore . Server . IIS . IISExpress . FunctionalTests ;
21
+ #elif NEWHANDLER_FUNCTIONALS
22
+ namespace Microsoft . AspNetCore . Server . IIS . NewHandler . FunctionalTests ;
23
+ #elif NEWSHIM_FUNCTIONALS
24
+ namespace Microsoft . AspNetCore . Server . IIS . NewShim . FunctionalTests ;
25
+ #endif
26
+ #else
27
+
28
+ namespace Microsoft . AspNetCore . Server . IIS . FunctionalTests ;
29
+ #endif
18
30
19
- [ Collection ( IISTestSiteCollection . Name ) ]
20
31
[ MinimumOSVersion ( OperatingSystems . Windows , WindowsVersions . Win8 , SkipReason = "No WebSocket supported on Win7" ) ]
21
32
[ SkipOnHelix ( "Unsupported queue" , Queues = "Windows.Amd64.VS2022.Pre.Open;" ) ]
22
- public class WebSocketsTests
33
+ public abstract class WebSocketsTests : FunctionalTestsBase
23
34
{
24
- private readonly string _requestUri ;
25
- private readonly string _webSocketUri ;
35
+ public IISTestSiteFixture Fixture { get ; }
26
36
27
- public WebSocketsTests ( IISTestSiteFixture fixture )
37
+ public WebSocketsTests ( IISTestSiteFixture fixture , ITestOutputHelper testOutput ) : base ( testOutput )
28
38
{
29
- _requestUri = fixture . DeploymentResult . ApplicationBaseUri ;
30
- _webSocketUri = _requestUri . Replace ( "http:" , "ws: ") ;
39
+ Fixture = fixture ;
40
+ Fixture . DeploymentParameters . EnableLogging ( "C:/github/aspnetcore/artifacts/log ") ;
31
41
}
32
42
33
43
[ ConditionalFact ]
34
44
public async Task RequestWithBody_NotUpgradable ( )
35
45
{
36
46
using var client = new HttpClient ( ) { Timeout = TimeSpan . FromSeconds ( 200 ) } ;
37
- using var response = await client . PostAsync ( _requestUri + "WebSocketNotUpgradable" , new StringContent ( "Hello World" ) ) ;
47
+ using var response = await client . PostAsync ( Fixture . DeploymentResult . ApplicationBaseUri + "WebSocketNotUpgradable" , new StringContent ( "Hello World" ) ) ;
38
48
response . EnsureSuccessStatusCode ( ) ;
39
49
}
40
50
41
51
[ ConditionalFact ]
42
52
public async Task RequestWithoutBody_Upgradable ( )
43
53
{
54
+ if ( Fixture . DeploymentParameters . HostingModel == HostingModel . OutOfProcess )
55
+ {
56
+ // OutOfProcess doesn't support upgrade requests without the "Upgrade": "websocket" header.
57
+ return ;
58
+ }
59
+
44
60
using var client = new HttpClient ( ) { Timeout = TimeSpan . FromSeconds ( 200 ) } ;
45
61
// POST with Content-Length: 0 counts as not having a body.
46
- using var response = await client . PostAsync ( _requestUri + "WebSocketUpgradable" , new StringContent ( "" ) ) ;
62
+ using var response = await client . PostAsync ( Fixture . DeploymentResult . ApplicationBaseUri + "WebSocketUpgradable" , new StringContent ( "" ) ) ;
47
63
response . EnsureSuccessStatusCode ( ) ;
48
64
}
49
65
50
66
[ ConditionalFact ]
51
67
public async Task OnStartedCalledForWebSocket ( )
52
68
{
53
- var cws = new ClientWebSocket ( ) ;
54
- await cws . ConnectAsync ( new Uri ( _webSocketUri + "WebSocketLifetimeEvents" ) , default ) ;
69
+ var webSocketUri = Fixture . DeploymentResult . ApplicationBaseUri ;
70
+ webSocketUri = webSocketUri . Replace ( "http:" , "ws:" ) ;
71
+
72
+ using var cws = new ClientWebSocket ( ) ;
73
+ await cws . ConnectAsync ( new Uri ( webSocketUri + "WebSocketLifetimeEvents" ) , default ) ;
55
74
56
75
await ReceiveMessage ( cws , "OnStarting" ) ;
57
76
await ReceiveMessage ( cws , "Upgraded" ) ;
@@ -60,17 +79,23 @@ public async Task OnStartedCalledForWebSocket()
60
79
[ ConditionalFact ]
61
80
public async Task WebReadBeforeUpgrade ( )
62
81
{
63
- var cws = new ClientWebSocket ( ) ;
64
- await cws . ConnectAsync ( new Uri ( _webSocketUri + "WebSocketReadBeforeUpgrade" ) , default ) ;
82
+ var webSocketUri = Fixture . DeploymentResult . ApplicationBaseUri ;
83
+ webSocketUri = webSocketUri . Replace ( "http:" , "ws:" ) ;
84
+
85
+ using var cws = new ClientWebSocket ( ) ;
86
+ await cws . ConnectAsync ( new Uri ( webSocketUri + "WebSocketReadBeforeUpgrade" ) , default ) ;
65
87
66
88
await ReceiveMessage ( cws , "Yay" ) ;
67
89
}
68
90
69
91
[ ConditionalFact ]
70
92
public async Task CanSendAndReceieveData ( )
71
93
{
72
- var cws = new ClientWebSocket ( ) ;
73
- await cws . ConnectAsync ( new Uri ( _webSocketUri + "WebSocketEcho" ) , default ) ;
94
+ var webSocketUri = Fixture . DeploymentResult . ApplicationBaseUri ;
95
+ webSocketUri = webSocketUri . Replace ( "http:" , "ws:" ) ;
96
+
97
+ using var cws = new ClientWebSocket ( ) ;
98
+ await cws . ConnectAsync ( new Uri ( webSocketUri + "WebSocketEcho" ) , default ) ;
74
99
75
100
for ( int i = 0 ; i < 1000 ; i ++ )
76
101
{
@@ -80,10 +105,33 @@ public async Task CanSendAndReceieveData()
80
105
}
81
106
}
82
107
108
+ [ ConditionalFact ]
109
+ public async Task AttemptCompressionWorks ( )
110
+ {
111
+ var webSocketUri = Fixture . DeploymentResult . ApplicationBaseUri ;
112
+ webSocketUri = webSocketUri . Replace ( "http:" , "ws:" ) ;
113
+
114
+ using var cws = new ClientWebSocket ( ) ;
115
+ cws . Options . DangerousDeflateOptions = new WebSocketDeflateOptions ( ) ;
116
+ await cws . ConnectAsync ( new Uri ( webSocketUri + "WebSocketAllowCompression" ) , default ) ;
117
+
118
+ // Compression doesn't work with OutOfProcess, let's make sure the websocket extensions aren't forwarded and the connection still works
119
+ var expected = Fixture . DeploymentParameters . HostingModel == HostingModel . InProcess
120
+ ? "permessage-deflate; client_max_window_bits=15" : "None" ;
121
+ await ReceiveMessage ( cws , expected ) ;
122
+
123
+ for ( int i = 0 ; i < 1000 ; i ++ )
124
+ {
125
+ var message = i . ToString ( CultureInfo . InvariantCulture ) ;
126
+ await SendMessage ( cws , message ) ;
127
+ await ReceiveMessage ( cws , message ) ;
128
+ }
129
+ }
130
+
83
131
[ ConditionalFact ]
84
132
public async Task Http1_0_Request_NotUpgradable ( )
85
133
{
86
- Uri uri = new Uri ( _requestUri + "WebSocketNotUpgradable" ) ;
134
+ Uri uri = new Uri ( Fixture . DeploymentResult . ApplicationBaseUri + "WebSocketNotUpgradable" ) ;
87
135
using TcpClient client = new TcpClient ( ) ;
88
136
89
137
await client . ConnectAsync ( uri . Host , uri . Port ) ;
@@ -103,7 +151,7 @@ public async Task Http1_0_Request_NotUpgradable()
103
151
[ ConditionalFact ]
104
152
public async Task Http1_0_Request_UpgradeErrors ( )
105
153
{
106
- Uri uri = new Uri ( _requestUri + "WebSocketUpgradeFails" ) ;
154
+ Uri uri = new Uri ( Fixture . DeploymentResult . ApplicationBaseUri + "WebSocketUpgradeFails" ) ;
107
155
using TcpClient client = new TcpClient ( ) ;
108
156
109
157
await client . ConnectAsync ( uri . Host , uri . Port ) ;
@@ -148,6 +196,7 @@ private async Task SendMessage(ClientWebSocket webSocket, string message)
148
196
149
197
private async Task ReceiveMessage ( ClientWebSocket webSocket , string expectedMessage )
150
198
{
199
+ Debug . Assert ( expectedMessage . Length > 0 ) ;
151
200
var received = new byte [ expectedMessage . Length ] ;
152
201
153
202
var offset = 0 ;
@@ -156,7 +205,7 @@ private async Task ReceiveMessage(ClientWebSocket webSocket, string expectedMess
156
205
{
157
206
result = await webSocket . ReceiveAsync ( new ArraySegment < byte > ( received , offset , received . Length - offset ) , default ) ;
158
207
offset += result . Count ;
159
- } while ( ! result . EndOfMessage ) ;
208
+ } while ( ! result . EndOfMessage && result . CloseStatus is null && received . Length - offset > 0 ) ;
160
209
161
210
Assert . Equal ( expectedMessage , Encoding . ASCII . GetString ( received ) ) ;
162
211
}
0 commit comments