88using System . Threading ;
99using System . Threading . Tasks ;
1010using Azure . Core . Pipeline ;
11+ using Azure . Core . TestFramework ;
1112using Microsoft . AspNetCore . Http ;
1213using NUnit . Framework ;
1314
1415namespace Azure . Core . Tests
1516{
16-
1717 [ TestFixture ( typeof ( HttpClientTransport ) , true ) ]
1818 [ TestFixture ( typeof ( HttpClientTransport ) , false ) ]
1919#if NETFRAMEWORK
@@ -158,6 +158,82 @@ public async Task NonBufferedFailedResponsesAreDisposedOf()
158158 Assert . Greater ( reqNum , requestCount ) ;
159159 }
160160
161+ [ Test ]
162+ public async Task Opens50ParallelConnections ( )
163+ {
164+ // Running 50 sync requests on the threadpool would cause starvation
165+ // and the test would take 20 sec to finish otherwise
166+ ThreadPool . SetMinThreads ( 100 , 100 ) ;
167+
168+ HttpPipeline httpPipeline = HttpPipelineBuilder . Build ( GetOptions ( ) ) ;
169+ int reqNum = 0 ;
170+
171+ TaskCompletionSource < object > requestsTcs = new TaskCompletionSource < object > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
172+
173+ using TestServer testServer = new TestServer (
174+ async context =>
175+ {
176+ if ( Interlocked . Increment ( ref reqNum ) == 50 )
177+ {
178+ requestsTcs . SetResult ( true ) ;
179+ }
180+
181+ await requestsTcs . Task ;
182+ } ) ;
183+
184+ var requestCount = 50 ;
185+ List < Task > requests = new List < Task > ( ) ;
186+ for ( int i = 0 ; i < requestCount ; i ++ )
187+ {
188+ HttpMessage message = httpPipeline . CreateMessage ( ) ;
189+ message . Request . Uri . Reset ( testServer . Address ) ;
190+
191+ requests . Add ( Task . Run ( ( ) => ExecuteRequest ( message , httpPipeline ) ) ) ;
192+ }
193+
194+ await Task . WhenAll ( requests ) ;
195+ }
196+
197+ [ Test ]
198+ [ Category ( "Live" ) ]
199+ public async Task Opens50ParallelConnectionsLive ( )
200+ {
201+ // Running 50 sync requests on the threadpool would cause starvation
202+ // and the test would take 20 sec to finish otherwise
203+ ThreadPool . SetMinThreads ( 100 , 100 ) ;
204+
205+ HttpPipeline httpPipeline = HttpPipelineBuilder . Build ( GetOptions ( ) ) ;
206+ int reqNum = 0 ;
207+
208+ TaskCompletionSource < object > requestsTcs = new TaskCompletionSource < object > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
209+
210+ async Task Connect ( )
211+ {
212+ using HttpMessage message = httpPipeline . CreateMessage ( ) ;
213+ message . Request . Uri . Reset ( new Uri ( "https://www.microsoft.com/" ) ) ;
214+ message . BufferResponse = false ;
215+
216+ await ExecuteRequest ( message , httpPipeline ) ;
217+
218+ if ( Interlocked . Increment ( ref reqNum ) == 50 )
219+ {
220+ requestsTcs . SetResult ( true ) ;
221+ }
222+
223+ await requestsTcs . Task ;
224+ }
225+
226+ var requestCount = 50 ;
227+ List < Task > requests = new List < Task > ( ) ;
228+ for ( int i = 0 ; i < requestCount ; i ++ )
229+ {
230+
231+ requests . Add ( Task . Run ( ( ) => Connect ( ) ) ) ;
232+ }
233+
234+ await Task . WhenAll ( requests ) ;
235+ }
236+
161237 [ Test ]
162238 public async Task BufferedResponsesReadableAfterMessageDisposed ( )
163239 {
@@ -176,7 +252,6 @@ public async Task BufferedResponsesReadableAfterMessageDisposed()
176252 }
177253 } ) ;
178254
179- // Make sure we dispose things correctly and not exhaust the connection pool
180255 var requestCount = 100 ;
181256 for ( int i = 0 ; i < requestCount ; i ++ )
182257 {
0 commit comments