mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-23 10:55:31 -06:00
0dbdf994b3
* feat(macos): isolate named app profiles * refactor(macos): isolate profile launch ownership * fix(macos): avoid overlapping approvals socket access * fix(macos): declare profile defaults concurrency ownership * fix(macos): return profiled node launch arguments * chore(i18n): refresh macOS profile source inventory * fix(macos): gate profile startup before services * test(macos): evaluate profile state before assertions * fix(daemon): skip absent launchd deactivation * fix(macos): fail closed on profile port conflicts * chore(i18n): refresh profile conflict inventory * fix(macos): ignore non-gateway launch agent claims * test(macos): stabilize profile lifecycle timing * fix(macos): remove stale dashboard URL * chore(macos): refresh native source baseline
73 lines
2.5 KiB
Swift
73 lines
2.5 KiB
Swift
import Foundation
|
|
import OpenClawKit
|
|
import Testing
|
|
@testable import OpenClaw
|
|
|
|
@Suite(.serialized)
|
|
@MainActor
|
|
struct NodesStoreTests {
|
|
@Test func `named profile keeps durable node service unavailability informational`() {
|
|
let store = NodesStore(
|
|
appProfile: AppProfile(environment: ["OPENCLAW_PROFILE": "work"]),
|
|
localNodeIdentityProfile: .node,
|
|
localNodeIDLoader: { _ in nil })
|
|
|
|
#expect(store.persistentServiceNotice ==
|
|
"Persistent Mac node service unavailable under app profile; runtime node remains available.")
|
|
#expect(store.lastError == nil)
|
|
store.statusMessage = "Refreshing devices…"
|
|
#expect(store.persistentServiceNotice != nil)
|
|
#expect(store.lastError == nil)
|
|
}
|
|
|
|
@Test func `local node identity is prepared once`() async {
|
|
let loader = LocalNodeIdentityLoader(results: ["node-id"])
|
|
let store = NodesStore(
|
|
localNodeIdentityProfile: .node,
|
|
localNodeIDLoader: loader.load)
|
|
|
|
async let first: Void = store.prepareLocalNodeIdentity()
|
|
async let second: Void = store.prepareLocalNodeIdentity()
|
|
_ = await (first, second)
|
|
await store.prepareLocalNodeIdentity()
|
|
|
|
#expect(store.localNodeIdentityState == .available("node-id"))
|
|
#expect(loader.loadedProfiles == [.node])
|
|
}
|
|
|
|
@Test func `unavailable local node identity can be retried`() async {
|
|
let loader = LocalNodeIdentityLoader(results: [nil, "node-id"])
|
|
let store = NodesStore(
|
|
localNodeIdentityProfile: .primary,
|
|
localNodeIDLoader: loader.load)
|
|
|
|
await store.prepareLocalNodeIdentity()
|
|
#expect(store.localNodeIdentityState == .unavailable)
|
|
|
|
await store.prepareLocalNodeIdentity()
|
|
#expect(store.localNodeIdentityState == .available("node-id"))
|
|
#expect(loader.loadedProfiles == [.primary, .primary])
|
|
}
|
|
}
|
|
|
|
private final class LocalNodeIdentityLoader: @unchecked Sendable {
|
|
private let lock = NSLock()
|
|
private var results: [String?]
|
|
private var profiles: [GatewayDeviceIdentityProfile] = []
|
|
|
|
init(results: [String?]) {
|
|
self.results = results
|
|
}
|
|
|
|
var loadedProfiles: [GatewayDeviceIdentityProfile] {
|
|
self.lock.withLock { self.profiles }
|
|
}
|
|
|
|
func load(profile: GatewayDeviceIdentityProfile) -> String? {
|
|
self.lock.withLock {
|
|
self.profiles.append(profile)
|
|
return self.results.isEmpty ? nil : self.results.removeFirst()
|
|
}
|
|
}
|
|
}
|