@@ -75,12 +75,54 @@ class URLResponseExtensionsTests: XCTestCase {
7575 }
7676
7777 func testExceededLimit( ) {
78- let httpResponse = HTTPURLResponse ( url: URL ( string: " https://instructure.com " ) !, statusCode: 403 , httpVersion: " HTTP/2.0 " , headerFields: [ : ] ) !
79- let data = " 403 Forbidden (Rate Limit Exceeded) " . data ( using: . utf8)
78+ var httpResponse = HTTPURLResponse ( url: URL ( string: " https://instructure.com " ) !, statusCode: 403 , httpVersion: " HTTP/2.0 " , headerFields: [ : ] ) !
79+ var data = " 403 Forbidden (Rate Limit Exceeded) " . data ( using: . utf8)
80+ XCTAssertTrue ( httpResponse. exceededLimit ( responseData: data) )
8081
82+ httpResponse = HTTPURLResponse ( url: URL ( string: " https://instructure.com " ) !, statusCode: 429 , httpVersion: " HTTP/2.0 " , headerFields: [ : ] ) !
83+ data = " 429 Too Many Requests (Rate Limit Exceeded) " . data ( using: . utf8)
8184 XCTAssertTrue ( httpResponse. exceededLimit ( responseData: data) )
8285 }
8386
87+ func testRetrialTimeOnRateLimitExceeded( ) throws {
88+ // Given
89+ let httpResponse = HTTPURLResponse ( url: URL ( string: " https://instructure.com " ) !, statusCode: 429 , httpVersion: " HTTP/2.0 " , headerFields: [ : ] ) !
90+ let data = " 429 Too Many Requests (Rate Limit Exceeded) " . data ( using: . utf8)
91+
92+ let base = DispatchTime . now ( )
93+ let limit = base + . seconds( 1 ) + . milliseconds( 500 )
94+
95+ // When
96+ let retrialTimes = [
97+ try XCTUnwrap ( httpResponse. retrialTimeOnRateLimitExceeded ( responseData: data) ) ,
98+ try XCTUnwrap ( httpResponse. retrialTimeOnRateLimitExceeded ( responseData: data) ) ,
99+ try XCTUnwrap ( httpResponse. retrialTimeOnRateLimitExceeded ( responseData: data) ) ,
100+ try XCTUnwrap ( httpResponse. retrialTimeOnRateLimitExceeded ( responseData: data) )
101+ ]
102+
103+ // Then
104+ if case . nanoseconds( let interval) = base. distance ( to: limit) {
105+ for time in retrialTimes {
106+ if case . nanoseconds( let nanoseconds) = base. distance ( to: time) {
107+ XCTAssertTrue ( nanoseconds <= interval)
108+ } else {
109+ XCTFail ( " Time must be checked against limit " )
110+ }
111+ }
112+ } else {
113+ XCTFail ( " All times must be checked against limit " )
114+ }
115+
116+ for i in 0 ..< retrialTimes. count {
117+ let time = retrialTimes [ i]
118+
119+ for j in 0 ..< retrialTimes. count where j != i {
120+ let anotherTime = retrialTimes [ j]
121+ XCTAssertNotEqual ( time, anotherTime)
122+ }
123+ }
124+ }
125+
84126 func testExceededLimitWithoutData( ) {
85127 let httpResponse = HTTPURLResponse ( url: URL ( string: " https://instructure.com " ) !, statusCode: 403 , httpVersion: " HTTP/2.0 " , headerFields: [ : ] ) !
86128
@@ -89,15 +131,21 @@ class URLResponseExtensionsTests: XCTestCase {
89131
90132 func testExceededLimitWithMismatchingData( ) {
91133 let httpResponse = HTTPURLResponse ( url: URL ( string: " https://instructure.com " ) !, statusCode: 403 , httpVersion: " HTTP/2.0 " , headerFields: [ : ] ) !
92- let data = " 403 Forbidden " . data ( using: . utf8)
134+ var data = " 403 Forbidden " . data ( using: . utf8)
93135
94136 XCTAssertFalse ( httpResponse. exceededLimit ( responseData: data) )
137+
138+ data = " 429 Too Many Requests " . data ( using: . utf8)
139+ XCTAssertFalse ( httpResponse. exceededLimit ( responseData: data) )
95140 }
96141
97142 func testExceededLimitWithNonHTTPResponse( ) {
98143 let response = URLResponse ( url: URL ( string: " https://instructure.com " ) !, mimeType: nil , expectedContentLength: 0 , textEncodingName: nil )
99- let data = " 403 Forbidden (Rate Limit Exceeded) " . data ( using: . utf8)
100144
145+ var data = " 403 Forbidden (Rate Limit Exceeded) " . data ( using: . utf8)
146+ XCTAssertFalse ( response. exceededLimit ( responseData: data) )
147+
148+ data = " 429 Too Many Requests (Rate Limit Exceeded) " . data ( using: . utf8)
101149 XCTAssertFalse ( response. exceededLimit ( responseData: data) )
102150 }
103151}
0 commit comments