Skip to content

Commit

Permalink
UBF: Addet testcase for breaking double-start behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
maerki committed May 9, 2024
1 parent c5896ec commit b80e8bb
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 10 deletions.
3 changes: 2 additions & 1 deletion Sources/UBFoundation/Networking/UBURLDataTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public final class UBURLDataTask: UBURLSessionTask, CustomStringConvertible, Cus
}

/// The underlaying data task
private var dataTask: URLSessionDataTask?
private(set) var dataTask: URLSessionDataTask?

/// The callback queue where all callbacks take place
private(set) var callbackQueue: OperationQueue
Expand Down Expand Up @@ -447,6 +447,7 @@ public final class UBURLDataTask: UBURLSessionTask, CustomStringConvertible, Cus
}
set {
stateDispatchQueue.sync {
print("new state", _state, newValue)
_state = newValue
}
}
Expand Down
19 changes: 10 additions & 9 deletions Sources/UBFoundation/Networking/UBURLSession+Delegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,6 @@ class UBURLSessionDelegate: NSObject, URLSessionTaskDelegate, URLSessionDataDele
/// :nodoc:
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
assert(session == urlSession, "The sessions are not matching")
defer {
// Clear the collected data
serialQueue.sync {
tasksData.removeObject(forKey: task)
tasks.removeObject(forKey: task)
}
}

var _ubDataTask: UBURLDataTask?
var _collectedData: UBURLSessionDelegate.DataHolder?
Expand All @@ -66,10 +59,18 @@ class UBURLSessionDelegate: NSObject, URLSessionTaskDelegate, URLSessionDataDele
_collectedData = tasksData.object(forKey: task)
}

guard let ubDataTask = _ubDataTask else {
guard let ubDataTask = _ubDataTask, ubDataTask.dataTask == task else {
return
}

defer {
// Clear the collected data
serialQueue.sync {
tasksData.removeObject(forKey: task)
tasks.removeObject(forKey: task)
}
}

guard let collectedData = _collectedData else {
ubDataTask.dataTaskCompleted(data: nil, response: nil, error: error, info: nil)
return
Expand Down Expand Up @@ -176,7 +177,7 @@ class UBURLSessionDelegate: NSObject, URLSessionTaskDelegate, URLSessionDataDele
_collectedData = tasksData.object(forKey: dataTask)
}

guard let ubDataTask = _ubDataTask, let dataHolder = _collectedData else {
guard let ubDataTask = _ubDataTask, ubDataTask.dataTask == dataTask, let dataHolder = _collectedData else {
completionHandler(.cancel)
return
}
Expand Down
51 changes: 51 additions & 0 deletions Tests/UBFoundationTests/Networking/TaskAutoRefreshLogicTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,57 @@ class TaskAutoRefreshLogicTests: XCTestCase {
dataTask3.start()
wait(for: [ex3], timeout: 10000)
}

func testDoubleStart() {
// Load Request that changes cached header
let url = URL(string: "https://example.com/file.json")!

let initialResponse = try! BasicResponseProvider(rule: url.absoluteString, body: "Hello, World!", header: BasicResponseProvider.Header(statusCode: 200, headerFields: [
"cache-control": "max-age=10000",
"etag": "0x8DB4542835F84A7",
"Date": UBBaseCachingLogic().dateFormatter.string(from: Date()),
]), timing: .init(headerResponseDelay: 1, bodyResponseDelay: 1))

initialResponse.addToLocalServer()

defer {
LocalServer.pauseLocalServer()
}

let conf = UBURLSessionConfiguration()
conf.sessionConfiguration.urlCache = URLCache(memoryCapacity: 1024 * 1024 * 4, diskCapacity: 1024 * 1024 * 10, diskPath: nil)
conf.sessionConfiguration.protocolClasses = [LocalServerURLProtocol.self]
let session = UBURLSession(configuration: conf)

// load request to fill cache

let dataTask = UBURLDataTask(url: url, session: session)

let ex = expectation(description: "s")
dataTask.addCompletionHandler(decoder: .passthrough) { _, _, _, _ in

ex.fulfill()
}
dataTask.start()
wait(for: [ex], timeout: 60)

// load request again

let dataTask2 = UBURLDataTask(url: url, session: session)

let ex2 = expectation(description: "s2")
ex2.expectedFulfillmentCount = 2
dataTask2.addCompletionHandler(decoder: .passthrough) { _, _, info, _ in

XCTAssertNotNil(info)
XCTAssert(info!.cacheHit)

ex2.fulfill()
}
dataTask2.start()
dataTask2.start() // start request again
wait(for: [ex2], timeout: 60)
}
}

@available(iOS 15.0.0, *)
Expand Down

0 comments on commit b80e8bb

Please sign in to comment.