forked from BasedHardware/omi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRewindStorageTestIsolation.swift
More file actions
119 lines (105 loc) · 3.59 KB
/
Copy pathRewindStorageTestIsolation.swift
File metadata and controls
119 lines (105 loc) · 3.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import Foundation
@testable import Omi_Computer
private actor RewindStorageTestGate {
static let shared = RewindStorageTestGate()
private var isHeld = false
private var waiters: [CheckedContinuation<Void, Never>] = []
func acquire() async {
if !isHeld {
isHeld = true
return
}
await withCheckedContinuation { continuation in
waiters.append(continuation)
}
}
func release() {
guard !waiters.isEmpty else {
isHeld = false
return
}
waiters.removeFirst().resume()
}
}
/// Shared setup/teardown for XCTest suites that touch Rewind storage singletons.
///
/// Mirrors the lifecycle used by `StagedTaskSyncIntegrityTests`: close the database,
/// invalidate cached storage actors, configure a throwaway user, initialize, and on
/// teardown close again before deleting the user directory.
enum RewindStorageTestIsolation {
struct Fixture {
let testUserId: String
let userDir: URL
}
struct AuthSnapshot {
let isSignedIn: Bool
let userId: String?
}
static func setUp(userIdPrefix: String) async throws -> Fixture {
await RewindStorageTestGate.shared.acquire()
let testUserId = "\(userIdPrefix)-\(UUID().uuidString)"
let userDir = userDirectory(for: testUserId)
do {
await RewindDatabase.shared.close()
await invalidateAllStorageCaches()
RewindDatabase.currentUserId = testUserId
await RewindDatabase.shared.configure(userId: testUserId)
try await RewindDatabase.shared.initialize()
return Fixture(testUserId: testUserId, userDir: userDir)
} catch {
await RewindDatabase.shared.close()
await invalidateAllStorageCaches()
RewindDatabase.currentUserId = nil
try? FileManager.default.removeItem(at: userDir)
await RewindStorageTestGate.shared.release()
throw error
}
}
static func tearDown(userDir: URL?) async {
guard let userDir else { return }
await RewindDatabase.shared.close()
await invalidateAllStorageCaches()
RewindDatabase.currentUserId = nil
try? FileManager.default.removeItem(at: userDir)
await RewindStorageTestGate.shared.release()
}
@MainActor
static func captureAuthSnapshot() -> AuthSnapshot {
AuthSnapshot(
isSignedIn: AuthState.shared.isSignedIn,
userId: UserDefaults.standard.string(forKey: .authUserId)
)
}
@MainActor
static func signInForTests(userId: String) {
AuthState.shared.update(isSignedIn: true)
UserDefaults.standard.set(userId, forKey: .authUserId)
}
@MainActor
static func restoreAuthSnapshot(_ snapshot: AuthSnapshot) {
AuthState.shared.update(isSignedIn: snapshot.isSignedIn)
if let userId = snapshot.userId {
UserDefaults.standard.set(userId, forKey: .authUserId)
} else {
UserDefaults.standard.removeObject(forKey: .authUserId)
}
}
static func invalidateAllStorageCaches() async {
await MemoryStorage.shared.invalidateCache()
await ActionItemStorage.shared.invalidateCache()
await TranscriptionStorage.shared.invalidateCache()
await StagedTaskStorage.shared.invalidateCache()
await GoalStorage.shared.invalidateCache()
await ProactiveStorage.shared.invalidateCache()
await TaskChatMessageStorage.shared.invalidateCache()
}
static func userDirectory(for testUserId: String) -> URL {
let appSupport = FileManager.default
.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
return
appSupport
.appendingPathComponent("Omi", isDirectory: true)
.appendingPathComponent("users", isDirectory: true)
.appendingPathComponent(testUserId, isDirectory: true)
}
}