Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Tests/Segment-Tests/Storage_Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ class StorageTests: XCTestCase {
let analytics = Analytics(configuration: Configuration(writeKey: uniqueWriteKey())
.storageMode(.memory(10))
.trackApplicationLifecycleEvents(false)
// a slow real request keeps analytics alive past waitUntilFinished's timeout.
.httpSession(RestrictedHTTPSession())
)

analytics.waitUntilStarted()
Expand Down
7 changes: 4 additions & 3 deletions Tests/Segment-Tests/StressTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class StressTests: XCTestCase {
.errorHandler({ error in
XCTFail("Storage Error: \(error)")
})
.httpSession(RestrictedHTTPSession())
.httpSession(InstantHTTPSession())
)
analytics.purgeStorage()
analytics.storage.hardReset(doYouKnowHowToUseThis: true)
Expand Down Expand Up @@ -114,7 +114,7 @@ class StressTests: XCTestCase {
.errorHandler({ error in
XCTFail("Storage Error: \(error)")
})
.httpSession(RestrictedHTTPSession())
.httpSession(InstantHTTPSession())
)
analytics.purgeStorage()
analytics.storage.hardReset(doYouKnowHowToUseThis: true)
Expand Down Expand Up @@ -245,7 +245,8 @@ class StressTests: XCTestCase {
.storageMode(.memory(30_000))
.errorHandler({ error in
XCTFail("Storage Error: \(error)")
}))
})
.httpSession(InstantHTTPSession()))
analytics.storage.hardReset(doYouKnowHowToUseThis: true)

waitUntilStarted(analytics: analytics)
Expand Down
64 changes: 64 additions & 0 deletions Tests/Segment-Tests/Support/TestUtilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,70 @@ class RestrictedHTTPSession: HTTPSession {



// answers every request with a 200 without going through URLSession, so there are no request
// timers to expire on a slow runner. tasks follow URLSessionTask's lifecycle (nothing happens
// until resume, running until the completion is called) and file uploads still read the file.
class InstantHTTPSession: HTTPSession {
class Task: UploadTask, DataTask {
private let lock = NSLock()
private var _state: URLSessionTask.State = .suspended
private let queue: DispatchQueue
private let work: () -> (Data?, URLResponse?, (any Error)?)
private let completionHandler: @Sendable (Data?, URLResponse?, (any Error)?) -> Void

init(queue: DispatchQueue, work: @escaping () -> (Data?, URLResponse?, (any Error)?), completionHandler: @escaping @Sendable (Data?, URLResponse?, (any Error)?) -> Void) {
self.queue = queue
self.work = work
self.completionHandler = completionHandler
}

var state: URLSessionTask.State {
lock.lock(); defer { lock.unlock() }
return _state
}

func resume() {
lock.lock()
guard _state == .suspended else { lock.unlock(); return }
_state = .running
lock.unlock()
queue.async { [self] in
let (data, response, error) = work()
lock.lock(); _state = .completed; lock.unlock()
completionHandler(data, response, error)
}
}
}

// serial, like URLSession's delegate queue.
private let queue = DispatchQueue(label: "com.segment.test.instantHTTPSession")

func uploadTask(with request: URLRequest, fromFile file: URL, completionHandler: @escaping @Sendable (Data?, URLResponse?, (any Error)?) -> Void) -> Task {
return Task(queue: queue, work: {
do {
_ = try Data(contentsOf: file)
return (Data(), Self.ok(request), nil)
} catch {
return (nil, nil, error)
}
}, completionHandler: completionHandler)
}

func uploadTask(with request: URLRequest, from bodyData: Data?, completionHandler: @escaping @Sendable (Data?, URLResponse?, (any Error)?) -> Void) -> Task {
return Task(queue: queue, work: { (Data(), Self.ok(request), nil) }, completionHandler: completionHandler)
}

func dataTask(with request: URLRequest, completionHandler: @escaping @Sendable (Data?, URLResponse?, (any Error)?) -> Void) -> Task {
return Task(queue: queue, work: { (Data(), Self.ok(request), nil) }, completionHandler: completionHandler)
}

func finishTasksAndInvalidate() {}

private static func ok(_ request: URLRequest) -> HTTPURLResponse {
return HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: nil, headerFields: nil)!
}
}

class BlockNetworkCalls: URLProtocol {
var initialURL: URL? = nil
override class func canInit(with request: URLRequest) -> Bool {
Expand Down
Loading