@@ -1894,9 +1894,17 @@ class TestURLSession: LoopbackServerTest {
1894
1894
}
1895
1895
1896
1896
try await task. sendPing ( )
1897
-
1897
+
1898
1898
wait ( for: [ delegate. expectation] , timeout: 50 )
1899
1899
1900
+ do {
1901
+ _ = try await task. receive ( )
1902
+ XCTFail ( " Expected to throw when receiving on closed task " )
1903
+ } catch {
1904
+ let urlError = try XCTUnwrap ( error as? URLError )
1905
+ XCTAssertEqual ( urlError. _nsError. code, NSURLErrorNetworkConnectionLost)
1906
+ }
1907
+
1900
1908
let callbacks = [ " urlSession(_:webSocketTask:didOpenWithProtocol:) " ,
1901
1909
" urlSession(_:webSocketTask:didCloseWith:reason:) " ,
1902
1910
" urlSession(_:task:didCompleteWithError:) " ]
@@ -1925,15 +1933,98 @@ class TestURLSession: LoopbackServerTest {
1925
1933
wait ( for: [ delegate. expectation] , timeout: 50 )
1926
1934
1927
1935
let callbacks = [ " urlSession(_:webSocketTask:didOpenWithProtocol:) " ,
1936
+ " urlSession(_:webSocketTask:didCloseWith:reason:) " ,
1928
1937
" urlSession(_:task:didCompleteWithError:) " ]
1929
1938
XCTAssertEqual ( delegate. callbacks. count, callbacks. count)
1930
1939
XCTAssertEqual ( delegate. callbacks, callbacks, " Callbacks for \( #function) " )
1931
1940
1932
1941
XCTAssertEqual ( task. closeCode, . normalClosure)
1933
1942
XCTAssertEqual ( task. closeReason, " BuhBye " . data ( using: . utf8) )
1934
1943
}
1935
- #endif
1936
1944
1945
+ func test_webSocketAbruptClose( ) async throws {
1946
+ guard #available( macOS 10 . 15 , iOS 13 . 0 , watchOS 6 . 0 , tvOS 13 . 0 , * ) else { return }
1947
+ guard URLSessionWebSocketTask . supportsWebSockets else {
1948
+ print ( " libcurl lacks WebSockets support, skipping \( #function) " )
1949
+ return
1950
+ }
1951
+
1952
+ let urlString = " ws://127.0.0.1: \( TestURLSession . serverPort) /web-socket/abrupt-close "
1953
+ let url = try XCTUnwrap ( URL ( string: urlString) )
1954
+ let request = URLRequest ( url: url)
1955
+
1956
+ let delegate = SessionDelegate ( with: expectation ( description: " \( urlString) : Connect " ) )
1957
+ let task = delegate. runWebSocketTask ( with: request, timeoutInterval: 4 )
1958
+
1959
+ do {
1960
+ _ = try await task. receive ( )
1961
+ XCTFail ( " Expected to throw when server closes connection " )
1962
+ } catch {
1963
+ let urlError = try XCTUnwrap ( error as? URLError )
1964
+ XCTAssertEqual ( urlError. _nsError. code, NSURLErrorBadServerResponse)
1965
+ }
1966
+
1967
+ wait ( for: [ delegate. expectation] , timeout: 50 )
1968
+
1969
+ do {
1970
+ _ = try await task. receive ( )
1971
+ XCTFail ( " Expected to throw when receiving on closed connection " )
1972
+ } catch {
1973
+ let urlError = try XCTUnwrap ( error as? URLError )
1974
+ XCTAssertEqual ( urlError. _nsError. code, NSURLErrorBadServerResponse)
1975
+ }
1976
+
1977
+ let callbacks = [ " urlSession(_:task:didCompleteWithError:) " ]
1978
+ XCTAssertEqual ( delegate. callbacks. count, callbacks. count)
1979
+ XCTAssertEqual ( delegate. callbacks, callbacks, " Callbacks for \( #function) " )
1980
+
1981
+ XCTAssertEqual ( task. closeCode, . invalid)
1982
+ XCTAssertEqual ( task. closeReason, nil )
1983
+ }
1984
+
1985
+ func test_webSocketSemiAbruptClose( ) async throws {
1986
+ guard #available( macOS 10 . 15 , iOS 13 . 0 , watchOS 6 . 0 , tvOS 13 . 0 , * ) else { return }
1987
+ guard URLSessionWebSocketTask . supportsWebSockets else {
1988
+ print ( " libcurl lacks WebSockets support, skipping \( #function) " )
1989
+ return
1990
+ }
1991
+
1992
+ let urlString = " ws://127.0.0.1: \( TestURLSession . serverPort) /web-socket/semi-abrupt-close "
1993
+ let url = try XCTUnwrap ( URL ( string: urlString) )
1994
+ let request = URLRequest ( url: url)
1995
+
1996
+ let delegate = SessionDelegate ( with: expectation ( description: " \( urlString) : Connect " ) )
1997
+ let task = delegate. runWebSocketTask ( with: request, timeoutInterval: 4 )
1998
+
1999
+ do {
2000
+ _ = try await task. receive ( )
2001
+ XCTFail ( " Expected to throw when server closes connection " )
2002
+ } catch {
2003
+ let urlError = try XCTUnwrap ( error as? URLError )
2004
+ XCTAssertEqual ( urlError. _nsError. code, NSURLErrorNetworkConnectionLost)
2005
+ }
2006
+
2007
+ wait ( for: [ delegate. expectation] , timeout: 50 )
2008
+
2009
+ do {
2010
+ _ = try await task. receive ( )
2011
+ XCTFail ( " Expected to throw when receiving on closed connection " )
2012
+ } catch {
2013
+ let urlError = try XCTUnwrap ( error as? URLError )
2014
+ XCTAssertEqual ( urlError. _nsError. code, NSURLErrorNetworkConnectionLost)
2015
+ }
2016
+
2017
+ let callbacks = [ " urlSession(_:webSocketTask:didOpenWithProtocol:) " ,
2018
+ " urlSession(_:webSocketTask:didCloseWith:reason:) " ,
2019
+ " urlSession(_:task:didCompleteWithError:) " ]
2020
+ XCTAssertEqual ( delegate. callbacks. count, callbacks. count)
2021
+ XCTAssertEqual ( delegate. callbacks, callbacks, " Callbacks for \( #function) " )
2022
+
2023
+ XCTAssertEqual ( task. closeCode, . normalClosure)
2024
+ XCTAssertEqual ( task. closeReason, nil )
2025
+ }
2026
+ #endif
2027
+
1937
2028
static var allTests : [ ( String , ( TestURLSession ) -> ( ) throws -> Void ) ] {
1938
2029
var retVal = [
1939
2030
( " test_dataTaskWithURL " , test_dataTaskWithURL) ,
@@ -2011,6 +2102,8 @@ class TestURLSession: LoopbackServerTest {
2011
2102
retVal. append ( contentsOf: [
2012
2103
( " test_webSocket " , asyncTest ( test_webSocket) ) ,
2013
2104
( " test_webSocketSpecificProtocol " , asyncTest ( test_webSocketSpecificProtocol) ) ,
2105
+ ( " test_webSocketAbruptClose " , asyncTest ( test_webSocketAbruptClose) ) ,
2106
+ ( " test_webSocketSemiAbruptClose " , asyncTest ( test_webSocketSemiAbruptClose) ) ,
2014
2107
] )
2015
2108
}
2016
2109
return retVal
0 commit comments