1683 lines · 66.3 KB · Swift
RawDownload
import Foundationimport Testing@testable import CodexBarCore private final class AntigravityAttemptRecorder: @unchecked Sendable {    private let lock = NSLock()    private var endpoints: [AntigravityStatusProbe.AntigravityConnectionEndpoint] = []     func append(_ endpoint: AntigravityStatusProbe.AntigravityConnectionEndpoint) {        self.lock.lock()        self.endpoints.append(endpoint)        self.lock.unlock()    }     func snapshot() -> [AntigravityStatusProbe.AntigravityConnectionEndpoint] {        self.lock.lock()        let snapshot = self.endpoints        self.lock.unlock()        return snapshot    }} struct AntigravityStatusProbeTests {    @Test    func `process detection accepts antigravity 2 unsuffixed language server`() {        let command = """        /Applications/Antigravity.app/Contents/Resources/bin/language_server --standalone \        --override_ide_name antigravity --override_ide_version 2.0.0 \        --csrf_token token --app_data_dir antigravity        """         #expect(AntigravityStatusProbe.isAntigravityLanguageServerCommandLine(command))    }     @Test    func `process detection accepts antigravity language server paths with spaces`() {        let command = """        /Applications/Google Antigravity.app/Contents/Resources/bin/language_server --standalone \        --override_ide_name antigravity --csrf_token token --app_data_dir antigravity        """         #expect(AntigravityStatusProbe.isAntigravityLanguageServerCommandLine(command))    }     @Test    func `process detection accepts hyphenated language server from app bundle`() throws {        let command = """        /Applications/Google Antigravity.app/Contents/Resources/bin/language-server --standalone \        --csrf_token token --extension_server_port 64123        """         #expect(AntigravityStatusProbe.isAntigravityLanguageServerCommandLine(command))         let result = try AntigravityStatusProbe.processInfo(fromProcessListOutput: "  321 \(command)")        #expect(result.pid == 321)        #expect(result.csrfToken == "token")        #expect(result.extensionPort == 64123)    }     @Test    func `process detection keeps ignoring non language server antigravity helpers`() {        let helper = """        /Applications/Antigravity.app/Contents/Frameworks/Antigravity Helper.app/Contents/MacOS/Antigravity Helper \        --type=renderer --user-data-dir=/Users/test/Library/Application Support/Antigravity        """         #expect(!AntigravityStatusProbe.isAntigravityLanguageServerCommandLine(helper))    }     @Test    func `process detection still accepts legacy antigravity language server`() {        let command = """        /Applications/Antigravity.app/Contents/Resources/bin/language_server_macos \        --csrf_token token --app_data_dir antigravity        """         #expect(AntigravityStatusProbe.isAntigravityLanguageServerCommandLine(command))    }     @Test    func `process detection accepts platform suffixed antigravity language server`() throws {        let output = """          101 /Applications/Antigravity.app/Contents/Resources/bin/language_server_macos_arm \          --csrf_token ide-token --app_data_dir antigravity --extension_server_port 54977        """         let result = try AntigravityStatusProbe.processInfo(fromProcessListOutput: output, scope: .appOnly)         #expect(result.pid == 101)        #expect(result.csrfToken == "ide-token")        #expect(result.extensionPort == 54977)    }     @Test    func `process detection accepts antigravity cli without csrf token`() {        // The CLI launches its language server without a `--csrf_token` flag.        let node = """        node /Users/test/.gemini/antigravity-cli/build/mcp-server.cjs \        --app_data_dir /Users/test/.gemini/antigravity        """        #expect(AntigravityStatusProbe.isAntigravityLanguageServerCommandLine(node))         let agy = "/Users/test/.local/bin/agy -p hello"        #expect(AntigravityStatusProbe.isAntigravityLanguageServerCommandLine(agy))         let agyUnderscore = "/usr/local/bin/agy --app_data_dir /Users/test/.gemini/antigravity_cli"        #expect(AntigravityStatusProbe.isAntigravityLanguageServerCommandLine(agyUnderscore))    }     @Test    func `process detection ignores unrelated binaries containing agy substring`() {        // "agy" must be path-anchored so unrelated commands do not match.        #expect(!AntigravityStatusProbe.isAntigravityLanguageServerCommandLine("/usr/bin/legacy --run"))        #expect(!AntigravityStatusProbe.isAntigravityLanguageServerCommandLine("/opt/imagymagic/bin/tool"))    }     @Test    func `process detection ignores cli names outside explicit cli path segments`() {        #expect(            !AntigravityStatusProbe.isAntigravityLanguageServerCommandLine(                "/usr/bin/node /tmp/not-antigravity-cli/build/server.js"))        #expect(            !AntigravityStatusProbe.isAntigravityLanguageServerCommandLine(                "/usr/bin/helper --workspace antigravity-cli"))    }     @Test    func `process kind distinguishes app ide language server and cli`() {        let app = """        /Applications/Antigravity.app/Contents/Resources/bin/language_server \        --csrf_token token --app_data_dir antigravity        """        let ide = """        /Applications/Antigravity IDE.app/Contents/Resources/app/extensions/antigravity/bin/language_server_macos_arm \        --csrf_token token --app_data_dir antigravity-ide        """        #expect(AntigravityStatusProbe.antigravityProcessKind(app) == .app)        #expect(AntigravityStatusProbe.antigravityProcessKind(ide) == .ide)        #expect(AntigravityStatusProbe.antigravityProcessKind("/Users/test/.local/bin/agy -p hi") == .cli)        #expect(            AntigravityStatusProbe.antigravityProcessKind(                "node /x/.gemini/antigravity-cli/build/mcp-server.cjs --app_data_dir /x/.gemini/antigravity") == .cli)        #expect(AntigravityStatusProbe.antigravityProcessKind("/usr/bin/legacy --run") == nil)    }     @Test    func `csrf token stays required for ide but optional for cli`() {        // Desktop app/IDE with a token returns it.        let appWithToken = """        /Applications/Antigravity.app/Contents/Resources/bin/language_server \        --csrf_token ide-token --app_data_dir antigravity        """        #expect(AntigravityStatusProbe.resolvedCSRFToken(forKind: .app, command: appWithToken) == "ide-token")         // Tokenless desktop app is skipped (nil) so detection keeps scanning for a valid        // server and preserves the missing-token diagnostic - no empty-token probe.        let appNoToken = """        /Applications/Antigravity.app/Contents/Resources/bin/language_server \        --app_data_dir antigravity        """        #expect(AntigravityStatusProbe.resolvedCSRFToken(forKind: .app, command: appNoToken) == nil)         // CLI without a token resolves to an empty token (its server needs none).        #expect(            AntigravityStatusProbe.resolvedCSRFToken(                forKind: .cli, command: "/Users/test/.local/bin/agy -p hi")?.isEmpty == true)         // A CLI that does carry a token still uses it.        #expect(            AntigravityStatusProbe.resolvedCSRFToken(                forKind: .cli, command: "/Users/test/.local/bin/agy --csrf_token cli-token") == "cli-token")    }     @Test    func `process scan skips tokenless ide before later valid ide`() throws {        let tokenlessIDE =            "  100 /Applications/Antigravity.app/Contents/Resources/bin/language_server --app_data_dir antigravity"        let validIDE = "  101 /Applications/Antigravity.app/Contents/Resources/bin/language_server " +            "--csrf_token ide-token --app_data_dir antigravity " +            "--extension_server_port 64432 --extension_server_csrf_token extension-token"        let output = [tokenlessIDE, validIDE].joined(separator: "\n")         let result = try AntigravityStatusProbe.processInfo(fromProcessListOutput: output)         #expect(result.pid == 101)        #expect(result.csrfToken == "ide-token")        #expect(result.extensionPort == 64432)        #expect(result.extensionServerCSRFToken == "extension-token")    }     @Test    func `process scan returns all valid app candidates`() throws {        let firstApp = "  101 /Applications/Antigravity.app/Contents/Resources/bin/language_server " +            "--csrf_token first-token --app_data_dir antigravity"        let secondApp = "  102 /Applications/Antigravity.app/Contents/Resources/bin/language_server " +            "--csrf_token second-token --app_data_dir antigravity " +            "--extension_server_port 64432 --extension_server_csrf_token extension-token"        let output = [firstApp, secondApp].joined(separator: "\n")         let results = try AntigravityStatusProbe.processInfos(fromProcessListOutput: output, scope: .appOnly)         #expect(results.map(\.pid) == [101, 102])        #expect(results.map(\.csrfToken) == ["first-token", "second-token"])        #expect(results.last?.extensionPort == 64432)        #expect(results.last?.extensionServerCSRFToken == "extension-token")    }     @Test    func `local snapshot score prefers quota summary over legacy model quotas`() {        let legacy = AntigravityStatusSnapshot(            modelQuotas: [                AntigravityModelQuota(                    label: "Gemini 3 Pro Low",                    modelId: "gemini-3-pro-low",                    remainingFraction: 0.9,                    resetTime: Date(timeIntervalSince1970: 1_700_000_000),                    resetDescription: nil),                AntigravityModelQuota(                    label: "Claude Sonnet",                    modelId: "claude-sonnet",                    remainingFraction: 0.5,                    resetTime: Date(timeIntervalSince1970: 1_700_000_000),                    resetDescription: nil),            ],            accountEmail: "user@example.com",            accountPlan: "Pro",            source: .local)        let summary = AntigravityStatusSnapshot(            quotaSummary: AntigravityQuotaSummary(                description: nil,                groups: [                    AntigravityQuotaSummaryGroup(                        displayName: "Gemini Models",                        description: nil,                        buckets: [                            AntigravityQuotaSummaryBucket(                                bucketId: "gemini-5h",                                displayName: "Five Hour Limit",                                remainingFraction: 0.9,                                resetDescription: nil,                                disabled: false),                            AntigravityQuotaSummaryBucket(                                bucketId: "gemini-weekly",                                displayName: "Weekly Limit",                                remainingFraction: 0.8,                                resetDescription: nil,                                disabled: false),                        ]),                    AntigravityQuotaSummaryGroup(                        displayName: "Claude and GPT models",                        description: nil,                        buckets: [                            AntigravityQuotaSummaryBucket(                                bucketId: "3p-5h",                                displayName: "Five Hour Limit",                                remainingFraction: 0.7,                                resetDescription: nil,                                disabled: false),                            AntigravityQuotaSummaryBucket(                                bucketId: "3p-weekly",                                displayName: "Weekly Limit",                                remainingFraction: 0.6,                                resetDescription: nil,                                disabled: false),                        ]),                ]),            accountEmail: "user@example.com",            accountPlan: "Pro",            source: .local)         #expect(AntigravityStatusProbe.localSnapshotScore(summary) > AntigravityStatusProbe.localSnapshotScore(legacy))    }     @Test    func `process scan reports missing csrf when only tokenless ide matches`() {        let output = """          100 /Applications/Antigravity.app/Contents/Resources/bin/language_server --app_data_dir antigravity        """         #expect(throws: AntigravityStatusProbeError.missingCSRFToken) {            try AntigravityStatusProbe.processInfo(fromProcessListOutput: output)        }    }     @Test    func `process scan allows empty csrf only for explicit cli match`() throws {        let output = """          200 /Users/test/.local/bin/agy -p hello        """         let result = try AntigravityStatusProbe.processInfo(fromProcessListOutput: output)         #expect(result.pid == 200)        #expect(result.csrfToken.isEmpty)        #expect(result.commandLine == "/Users/test/.local/bin/agy -p hello")    }     @Test    func `ideOnly scope skips app and cli processes and reports not running`() {        let output = "  200 /Users/test/.local/bin/agy -p hello"         #expect(throws: AntigravityStatusProbeError.notRunning) {            try AntigravityStatusProbe.processInfo(fromProcessListOutput: output, scope: .ideOnly)        }         let app = "  101 /Applications/Antigravity.app/Contents/Resources/bin/language_server " +            "--csrf_token app-token --app_data_dir antigravity"        #expect(throws: AntigravityStatusProbeError.notRunning) {            try AntigravityStatusProbe.processInfo(fromProcessListOutput: app, scope: .ideOnly)        }    }     @Test    func `ideOnly scope still matches ide server listed after cli and app processes`() throws {        let cli = "  200 /Users/test/.local/bin/agy -p hello"        let app = "  101 /Applications/Antigravity.app/Contents/Resources/bin/language_server " +            "--csrf_token app-token --app_data_dir antigravity"        let ide = "  102 /Applications/Antigravity IDE.app/Contents/Resources/app/extensions/antigravity/bin/" +            "language_server_macos_arm " +            "--csrf_token ide-token --app_data_dir antigravity"        let output = cli + "\n" + app + "\n" + ide         let result = try AntigravityStatusProbe.processInfo(fromProcessListOutput: output, scope: .ideOnly)         #expect(result.pid == 102)        #expect(result.csrfToken == "ide-token")    }     @Test    func `appOnly scope skips ide and cli processes`() throws {        let cli = "  200 /Users/test/.local/bin/agy -p hello"        let ide = "  102 /Applications/Antigravity IDE.app/Contents/Resources/app/extensions/antigravity/bin/" +            "language_server_macos_arm --csrf_token ide-token --app_data_dir antigravity-ide"        let app = "  101 /Applications/Antigravity.app/Contents/Resources/bin/language_server " +            "--csrf_token app-token --app_data_dir antigravity"        let output = cli + "\n" + ide + "\n" + app         let result = try AntigravityStatusProbe.processInfo(fromProcessListOutput: output, scope: .appOnly)         #expect(result.pid == 101)        #expect(result.csrfToken == "app-token")    }} extension AntigravityStatusProbeTests {    @Test    func `localhost trust policy only accepts local server trust challenges`() {        #expect(            LocalhostTrustPolicy.shouldAcceptServerTrust(                host: "127.0.0.1",                authenticationMethod: NSURLAuthenticationMethodServerTrust,                hasServerTrust: true))        #expect(            LocalhostTrustPolicy.shouldAcceptServerTrust(                host: "LOCALHOST",                authenticationMethod: NSURLAuthenticationMethodServerTrust,                hasServerTrust: true))         #expect(            !LocalhostTrustPolicy.shouldAcceptServerTrust(                host: "cursor.com",                authenticationMethod: NSURLAuthenticationMethodServerTrust,                hasServerTrust: true))        #expect(            !LocalhostTrustPolicy.shouldAcceptServerTrust(                host: "127.0.0.1",                authenticationMethod: NSURLAuthenticationMethodHTTPBasic,                hasServerTrust: true))        #expect(            !LocalhostTrustPolicy.shouldAcceptServerTrust(                host: "127.0.0.1",                authenticationMethod: NSURLAuthenticationMethodServerTrust,                hasServerTrust: false))    }     @Test    func `localhost trust policy rejects non loopback hostnames that contain localhost`() {        #expect(            !LocalhostTrustPolicy.shouldAcceptServerTrust(                host: "localhost.example.com",                authenticationMethod: NSURLAuthenticationMethodServerTrust,                hasServerTrust: true))    }     @Test    func `connection candidates preserve scheme order and endpoint tokens`() {        let candidates = AntigravityStatusProbe.connectionCandidates(            listeningPorts: [64440],            languageServerCSRFToken: "language-token",            extensionServerPort: 64432,            extensionServerCSRFToken: "extension-token")         #expect(            candidates == [                AntigravityStatusProbe.AntigravityConnectionEndpoint(                    scheme: "https",                    port: 64440,                    csrfToken: "language-token",                    source: .languageServer),                AntigravityStatusProbe.AntigravityConnectionEndpoint(                    scheme: "http",                    port: 64432,                    csrfToken: "extension-token",                    source: .extensionServer),                AntigravityStatusProbe.AntigravityConnectionEndpoint(                    scheme: "http",                    port: 64432,                    csrfToken: "language-token",                    source: .extensionServer),            ])    }     @Test    func `connection candidates restrict plain http probing to the declared extension port`() {        let candidates = AntigravityStatusProbe.connectionCandidates(            listeningPorts: [64440, 64441],            languageServerCSRFToken: "language-token",            extensionServerPort: 64432,            extensionServerCSRFToken: nil)         #expect(            candidates == [                AntigravityStatusProbe.AntigravityConnectionEndpoint(                    scheme: "https",                    port: 64440,                    csrfToken: "language-token",                    source: .languageServer),                AntigravityStatusProbe.AntigravityConnectionEndpoint(                    scheme: "https",                    port: 64441,                    csrfToken: "language-token",                    source: .languageServer),                AntigravityStatusProbe.AntigravityConnectionEndpoint(                    scheme: "http",                    port: 64432,                    csrfToken: "language-token",                    source: .extensionServer),            ])    }     @Test    func `connection candidates preserve extension fallback when extension token is unavailable`() {        let candidates = AntigravityStatusProbe.connectionCandidates(            listeningPorts: [64440],            languageServerCSRFToken: "language-token",            extensionServerPort: 64432,            extensionServerCSRFToken: nil)         #expect(            candidates == [                AntigravityStatusProbe.AntigravityConnectionEndpoint(                    scheme: "https",                    port: 64440,                    csrfToken: "language-token",                    source: .languageServer),                AntigravityStatusProbe.AntigravityConnectionEndpoint(                    scheme: "http",                    port: 64432,                    csrfToken: "language-token",                    source: .extensionServer),            ])    }     @Test    func `connection candidates do not duplicate the same http target when ports overlap`() {        let candidates = AntigravityStatusProbe.connectionCandidates(            listeningPorts: [64432],            languageServerCSRFToken: "language-token",            extensionServerPort: 64432,            extensionServerCSRFToken: nil)         #expect(            candidates == [                AntigravityStatusProbe.AntigravityConnectionEndpoint(                    scheme: "https",                    port: 64432,                    csrfToken: "language-token",                    source: .languageServer),                AntigravityStatusProbe.AntigravityConnectionEndpoint(                    scheme: "http",                    port: 64432,                    csrfToken: "language-token",                    source: .extensionServer),            ])    }     @Test    func `request endpoints retry extension server after language server success`() {        let resolvedEndpoint = AntigravityStatusProbe.AntigravityConnectionEndpoint(            scheme: "https",            port: 64440,            csrfToken: "language-token",            source: .languageServer)         let endpoints = AntigravityStatusProbe.requestEndpoints(            resolvedEndpoint: resolvedEndpoint,            listeningPorts: [64440],            languageServerCSRFToken: "language-token",            extensionServerPort: 64432,            extensionServerCSRFToken: "extension-token")

Lines 1–500 of 1683.