@@ -4,28 +4,77 @@ import Testing
|
4 | 4 | |
5 | 5 | @Suite(.serialized) |
6 | 6 | struct ExecApprovalsStoreRefactorTests { |
| 7 | +private var realTemporaryDirectory: URL { |
| 8 | +let path = FileManager().temporaryDirectory.path |
| 9 | +if path.hasPrefix("/var/") { |
| 10 | +return URL(fileURLWithPath: "/private\(path)", isDirectory: true) |
| 11 | +} |
| 12 | +return FileManager().temporaryDirectory.resolvingSymlinksInPath() |
| 13 | +} |
| 14 | + |
| 15 | +private func withLockedEnv( |
| 16 | + _ values: [String: String?], |
| 17 | + _ body: () async throws -> Void) async throws |
| 18 | +{ |
| 19 | +func restoreEnv(_ values: [String: String?]) { |
| 20 | +for (key, value) in values { |
| 21 | +if let value { |
| 22 | +setenv(key, value, 1) |
| 23 | +} else { |
| 24 | +unsetenv(key) |
| 25 | +} |
| 26 | +} |
| 27 | +} |
| 28 | + |
| 29 | +await TestIsolationLock.shared.acquire() |
| 30 | +var previousEnv: [String: String?] = [:] |
| 31 | +for (key, value) in values { |
| 32 | +previousEnv[key] = getenv(key).map { String(cString: $0) } |
| 33 | +if let value { |
| 34 | +setenv(key, value, 1) |
| 35 | +} else { |
| 36 | +unsetenv(key) |
| 37 | +} |
| 38 | +} |
| 39 | + |
| 40 | +do { |
| 41 | +try await body() |
| 42 | +restoreEnv(previousEnv) |
| 43 | +await TestIsolationLock.shared.release() |
| 44 | +} catch { |
| 45 | +restoreEnv(previousEnv) |
| 46 | +await TestIsolationLock.shared.release() |
| 47 | +throw error |
| 48 | +} |
| 49 | +} |
| 50 | + |
7 | 51 | private func withTempStateDir( |
8 | 52 | _ body: @escaping @Sendable (URL) async throws -> Void) async throws |
9 | 53 | { |
10 | | -let stateDir = FileManager().temporaryDirectory |
| 54 | +let root = self.realTemporaryDirectory |
11 | 55 | .appendingPathComponent("openclaw-state-\(UUID().uuidString)", isDirectory: true) |
12 | | -defer { try? FileManager().removeItem(at: stateDir) } |
| 56 | +let home = root.appendingPathComponent("home", isDirectory: true) |
| 57 | +let stateDir = root.appendingPathComponent("state", isDirectory: true) |
| 58 | +defer { try? FileManager().removeItem(at: root) } |
13 | 59 | |
14 | | -try await TestIsolation.withEnvValues(["OPENCLAW_STATE_DIR": stateDir.path]) { |
| 60 | +try await self.withLockedEnv([ |
| 61 | +"OPENCLAW_HOME": home.path, |
| 62 | +"OPENCLAW_STATE_DIR": stateDir.path, |
| 63 | +]) { |
15 | 64 | try await body(stateDir) |
16 | 65 | } |
17 | 66 | } |
18 | 67 | |
19 | 68 | private func withTempHomeAndStateDir( |
20 | 69 | _ body: @escaping @Sendable (URL, URL) async throws -> Void) async throws |
21 | 70 | { |
22 | | -let root = FileManager().temporaryDirectory |
| 71 | +let root = self.realTemporaryDirectory |
23 | 72 | .appendingPathComponent("openclaw-home-state-\(UUID().uuidString)", isDirectory: true) |
24 | 73 | let home = root.appendingPathComponent("home", isDirectory: true) |
25 | 74 | let stateDir = root.appendingPathComponent("state", isDirectory: true) |
26 | 75 | defer { try? FileManager().removeItem(at: root) } |
27 | 76 | |
28 | | -try await TestIsolation.withEnvValues([ |
| 77 | +try await self.withLockedEnv([ |
29 | 78 | "OPENCLAW_HOME": home.path, |
30 | 79 | "OPENCLAW_STATE_DIR": stateDir.path, |
31 | 80 | ]) { |
|