@@ -495,21 +495,101 @@ class TestURLSession: LoopbackServerTest {
495
495
waitForExpectations ( timeout: 30 )
496
496
}
497
497
498
- func test_timeoutInterval ( ) {
498
+ func test_httpTimeout ( ) {
499
499
let config = URLSessionConfiguration . default
500
500
config. timeoutIntervalForRequest = 10
501
- let urlString = " http://127.0.0.1:-1 /Peru "
501
+ let urlString = " http://127.0.0.1: \( TestURLSession . serverPort ) /Peru "
502
502
let session = URLSession ( configuration: config, delegate: nil , delegateQueue: nil )
503
503
let expect = expectation ( description: " GET \( urlString) : will timeout " )
504
- var req = URLRequest ( url: URL ( string: " http://127.0.0.1:-1/Peru " ) !)
504
+ var req = URLRequest ( url: URL ( string: urlString) !)
505
+ req. setValue ( " 3 " , forHTTPHeaderField: " x-pause " )
505
506
req. timeoutInterval = 1
506
507
let task = session. dataTask ( with: req) { ( data, _, error) -> Void in
507
508
defer { expect. fulfill ( ) }
508
- XCTAssertNotNil ( error)
509
+ XCTAssertEqual ( ( error as? URLError ) ? . code , . timedOut , " Task should fail with URLError.timedOut error " )
509
510
}
510
511
task. resume ( )
512
+ waitForExpectations ( timeout: 30 )
513
+ }
514
+
515
+ func test_connectTimeout( ) {
516
+ // Reconfigure http server for this specific scenario:
517
+ // a slow request keeps web server busy, while other
518
+ // request times out on connection attempt.
519
+ Self . stopServer ( )
520
+ Self . options = Options ( serverBacklog: 1 , isAsynchronous: false )
521
+ Self . startServer ( )
522
+
523
+ let config = URLSessionConfiguration . default
524
+ let slowUrlString = " http://127.0.0.1: \( TestURLSession . serverPort) /Peru "
525
+ let fastUrlString = " http://127.0.0.1: \( TestURLSession . serverPort) /Italy "
526
+ let session = URLSession ( configuration: config, delegate: nil , delegateQueue: nil )
527
+ let slowReqExpect = expectation ( description: " GET \( slowUrlString) : will complete " )
528
+ let fastReqExpect = expectation ( description: " GET \( fastUrlString) : will timeout " )
529
+
530
+ var slowReq = URLRequest ( url: URL ( string: slowUrlString) !)
531
+ slowReq. setValue ( " 3 " , forHTTPHeaderField: " x-pause " )
532
+
533
+ var fastReq = URLRequest ( url: URL ( string: fastUrlString) !)
534
+ fastReq. timeoutInterval = 1
535
+
536
+ let slowTask = session. dataTask ( with: slowReq) { ( data, _, error) -> Void in
537
+ slowReqExpect. fulfill ( )
538
+ }
539
+ let fastTask = session. dataTask ( with: fastReq) { ( data, _, error) -> Void in
540
+ defer { fastReqExpect. fulfill ( ) }
541
+ XCTAssertEqual ( ( error as? URLError ) ? . code, . timedOut, " Task should fail with URLError.timedOut error " )
542
+ }
543
+ slowTask. resume ( )
544
+ Thread . sleep ( forTimeInterval: 0.1 ) // Give slow task some time to start
545
+ fastTask. resume ( )
511
546
512
547
waitForExpectations ( timeout: 30 )
548
+
549
+ // Reconfigure http server back to default settings
550
+ Self . stopServer ( )
551
+ Self . options = . default
552
+ Self . startServer ( )
553
+ }
554
+
555
+ func test_repeatedRequestsStress( ) throws {
556
+ let config = URLSessionConfiguration . default
557
+ let urlString = " http://127.0.0.1: \( TestURLSession . serverPort) /Peru "
558
+ let session = URLSession ( configuration: config, delegate: nil , delegateQueue: nil )
559
+ let req = URLRequest ( url: URL ( string: urlString) !)
560
+
561
+ var requestsLeft = 3000
562
+ let expect = expectation ( description: " \( requestsLeft) x GET \( urlString) " )
563
+
564
+ func doRequest( completion: @escaping ( ) -> Void ) {
565
+ // We only care about completion of one of the tasks,
566
+ // so we could move to next cycle.
567
+ // Some overlapping would happen and that's what we
568
+ // want actually to provoke issue with socket reuse
569
+ // on Windows.
570
+ let task = session. dataTask ( with: req) { ( _, _, _) -> Void in
571
+ }
572
+ task. resume ( )
573
+ let task2 = session. dataTask ( with: req) { ( _, _, _) -> Void in
574
+ }
575
+ task2. resume ( )
576
+ let task3 = session. dataTask ( with: req) { ( _, _, _) -> Void in
577
+ completion ( )
578
+ }
579
+ task3. resume ( )
580
+ }
581
+
582
+ func requestCompletion( ) {
583
+ requestsLeft -= 1
584
+ guard requestsLeft > 0 else {
585
+ expect. fulfill ( )
586
+ return
587
+ }
588
+ doRequest ( completion: requestCompletion)
589
+ }
590
+ doRequest ( completion: requestCompletion)
591
+
592
+ waitForExpectations ( timeout: 30 )
513
593
}
514
594
515
595
func test_httpRedirectionWithCode300( ) throws {
@@ -2049,7 +2129,6 @@ class TestURLSession: LoopbackServerTest {
2049
2129
( " test_taskTimeout " , test_taskTimeout) ,
2050
2130
( " test_verifyRequestHeaders " , test_verifyRequestHeaders) ,
2051
2131
( " test_verifyHttpAdditionalHeaders " , test_verifyHttpAdditionalHeaders) ,
2052
- ( " test_timeoutInterval " , test_timeoutInterval) ,
2053
2132
( " test_httpRedirectionWithCode300 " , test_httpRedirectionWithCode300) ,
2054
2133
( " test_httpRedirectionWithCode301_302 " , test_httpRedirectionWithCode301_302) ,
2055
2134
( " test_httpRedirectionWithCode303 " , test_httpRedirectionWithCode303) ,
@@ -2098,6 +2177,7 @@ class TestURLSession: LoopbackServerTest {
2098
2177
/* ⚠️ */ testExpectedToFail ( test_noDoubleCallbackWhenCancellingAndProtocolFailsFast, " This test crashes nondeterministically: https://bugs.swift.org/browse/SR-11310 " ) ) ,
2099
2178
/* ⚠️ */ ( " test_cancelledTasksCannotBeResumed " , testExpectedToFail ( test_cancelledTasksCannotBeResumed, " Breaks on Ubuntu 18.04 " ) ) ,
2100
2179
]
2180
+ #if NS_FOUNDATION_ALLOWS_TESTABLE_IMPORT
2101
2181
if #available( macOS 12 . 0 , * ) {
2102
2182
retVal. append ( contentsOf: [
2103
2183
( " test_webSocket " , asyncTest ( test_webSocket) ) ,
@@ -2106,6 +2186,19 @@ class TestURLSession: LoopbackServerTest {
2106
2186
( " test_webSocketSemiAbruptClose " , asyncTest ( test_webSocketSemiAbruptClose) ) ,
2107
2187
] )
2108
2188
}
2189
+ #endif
2190
+ #if os(Windows)
2191
+ retVal. append ( contentsOf: [
2192
+ ( " test_httpTimeout " , testExpectedToFail ( test_httpTimeout, " Crashes: https://github.com/apple/swift-corelibs-foundation/issues/4791 " ) ) ,
2193
+ ( " test_connectTimeout " , testExpectedToFail ( test_connectTimeout, " Crashes: https://github.com/apple/swift-corelibs-foundation/issues/4791 " ) ) ,
2194
+ ( " test_repeatedRequestsStress " , testExpectedToFail ( test_repeatedRequestsStress, " Crashes: https://github.com/apple/swift-corelibs-foundation/issues/4791 " ) ) ,
2195
+ ] )
2196
+ #else
2197
+ retVal. append ( contentsOf: [
2198
+ ( " test_httpTimeout " , test_httpTimeout) ,
2199
+ ( " test_connectTimeout " , test_connectTimeout) ,
2200
+ ] )
2201
+ #endif
2109
2202
return retVal
2110
2203
}
2111
2204
0 commit comments