Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Auth] Remove AuthDispatcher singleton, prefer DI #14122

Merged
merged 1 commit into from
Nov 14, 2024
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
8 changes: 6 additions & 2 deletions FirebaseAuth/Sources/Swift/Auth/Auth.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1616,7 +1616,8 @@ extension Auth: AuthInterop {

init(app: FirebaseApp,
keychainStorageProvider: AuthKeychainStorage = AuthKeychainStorageReal(),
backend: AuthBackend = AuthBackend(rpcIssuer: AuthBackendRPCIssuer())) {
backend: AuthBackend = .init(rpcIssuer: AuthBackendRPCIssuer()),
authDispatcher: AuthDispatcher = .init()) {
Auth.setKeychainServiceNameForApp(app)
self.app = app
mainBundleUrlTypes = Bundle.main
Expand All @@ -1642,6 +1643,7 @@ extension Auth: AuthInterop {
heartbeatLogger: app.heartbeatLogger,
appCheck: appCheck)
self.backend = backend
self.authDispatcher = authDispatcher
super.init()
requestConfiguration.auth = self

Expand Down Expand Up @@ -1902,7 +1904,7 @@ extension Auth: AuthInterop {
}
autoRefreshScheduled = true
weak var weakSelf = self
AuthDispatcher.shared.dispatch(afterDelay: delay, queue: kAuthGlobalWorkQueue) {
authDispatcher.dispatch(afterDelay: delay, queue: kAuthGlobalWorkQueue) {
guard let strongSelf = weakSelf else {
return
}
Expand Down Expand Up @@ -2361,6 +2363,8 @@ extension Auth: AuthInterop {
/// The Firebase app name.
private let firebaseAppName: String

private let authDispatcher: AuthDispatcher

/// The keychain service.
private var keychainServices: AuthKeychainServices!

Expand Down
12 changes: 8 additions & 4 deletions FirebaseAuth/Sources/Swift/Auth/AuthDispatcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@
import Foundation

/// A utility class used to facilitate scheduling tasks to be executed in the future.
class AuthDispatcher {
static let shared = AuthDispatcher()

struct AuthDispatcher {
/// Allows custom implementation of dispatchAfterDelay:queue:callback:.
///
/// Set to nil to restore default implementation.
var dispatchAfterImplementation: ((TimeInterval, DispatchQueue, @escaping () -> Void) -> Void)?
private let dispatchAfterImplementation: ((TimeInterval, DispatchQueue, @escaping () -> Void)
-> Void)?

init(dispatchAfterImplementation: ((TimeInterval, DispatchQueue, @escaping () -> Void) -> Void)? =
nil) {
self.dispatchAfterImplementation = dispatchAfterImplementation
}

/// Schedules task in the future after a specified delay.
/// - Parameter delay: The delay in seconds after which the task will be scheduled to execute.
Expand Down
16 changes: 2 additions & 14 deletions FirebaseAuth/Tests/Unit/AuthDispatcherTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,15 @@ class AuthDispatcherTests: XCTestCase {
let kTestDelay = 0.1
let kMaxDifferenceBetweenTimeIntervals = 0.4

/** @fn testSharedInstance
@brief Tests @c sharedInstance returns the same object.
*/
func testSharedInstance() {
let instance1 = AuthDispatcher.shared
let instance2 = AuthDispatcher.shared
XCTAssert(instance1 === instance2)
}

/** @fn testDispatchAfterDelay
@brief Tests @c dispatchAfterDelay indeed dispatches the specified task after the provided
delay.
*/
func testDispatchAfterDelay() {
let dispatcher = AuthDispatcher.shared
let dispatcher = AuthDispatcher()
let testWorkQueue = DispatchQueue(label: "test.work.queue")
let expectation = self.expectation(description: #function)
let dateBeforeDispatch = Date()
dispatcher.dispatchAfterImplementation = nil
dispatcher.dispatch(afterDelay: kTestDelay, queue: testWorkQueue) { [self] in
let timeSinceDispatch = fabs(dateBeforeDispatch.timeIntervalSinceNow - self.kTestDelay)
XCTAssertLessThan(timeSinceDispatch, kMaxDifferenceBetweenTimeIntervals)
Expand All @@ -54,15 +44,13 @@ class AuthDispatcherTests: XCTestCase {
@c dispatchAfterDelay.
*/
func testSetDispatchAfterImplementation() {
let dispatcher = AuthDispatcher.shared
let testWorkQueue = DispatchQueue(label: "test.work.queue")
let expectation = self.expectation(description: #function)
dispatcher.dispatchAfterImplementation = { delay, queue, task in
let dispatcher = AuthDispatcher { delay, queue, task in
XCTAssertEqual(self.kTestDelay, delay)
XCTAssertEqual(testWorkQueue, queue)
expectation.fulfill()
}

dispatcher.dispatch(afterDelay: kTestDelay, queue: testWorkQueue) {
// Fail to ensure this code is never executed.
XCTFail("Should not execute this code")
Expand Down
16 changes: 8 additions & 8 deletions FirebaseAuth/Tests/Unit/AuthTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,20 @@ class AuthTests: RPCBaseTests {
#else
let keychainStorageProvider = AuthKeychainStorageReal()
#endif // (os(macOS) && !FIREBASE_AUTH_TESTING_USE_MACOS_KEYCHAIN) || SWIFT_PACKAGE
auth = Auth(
app: FirebaseApp.app(name: name)!,
keychainStorageProvider: keychainStorageProvider,
backend: authBackend
)

// Set authDispatcherCallback implementation in order to save the token refresh task for later
// execution.
AuthDispatcher.shared.dispatchAfterImplementation = { delay, queue, task in
// Stub the implementation to save the token refresh task for later execution.
let authDispatcher = AuthDispatcher { delay, queue, task in
XCTAssertNotNil(task)
XCTAssertGreaterThan(delay, 0)
XCTAssertEqual(kAuthGlobalWorkQueue, queue)
self.authDispatcherCallback = task
}
auth = Auth(
app: FirebaseApp.app(name: name)!,
keychainStorageProvider: keychainStorageProvider,
backend: authBackend,
authDispatcher: authDispatcher
)
// Wait until Auth initialization completes
waitForAuthGlobalWorkQueueDrain()
}
Expand Down
Loading