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. Load more
import Foundation import 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")