diff --git a/mobile/modules/orca-mobile-web-shell/tests/MobileWebShellChecks.swift b/mobile/modules/orca-mobile-web-shell/tests/MobileWebShellChecks.swift index 164953f4333..137056568c9 100644 --- a/mobile/modules/orca-mobile-web-shell/tests/MobileWebShellChecks.swift +++ b/mobile/modules/orca-mobile-web-shell/tests/MobileWebShellChecks.swift @@ -11,38 +11,6 @@ import Foundation // ios/MobileWebShellNavigationPolicy.swift \ // tests/MobileWebShellChecks.swift && /tmp/mobile-web-shell-checks @main struct MobileWebShellChecks { - static let session = "sess-01JN_aZ9" - - static func parts( - path: String, - method: String = "GET", - hasRangeHeader: Bool = false, - scheme: String? = MobileWebShellOrigin.scheme, - host: String? = session, - port: Int? = nil, - user: String? = nil, - query: String? = nil, - fragment: String? = nil, - urlByteCount: Int = 64 - ) -> MobileWebShellRequestParts { - MobileWebShellRequestParts( - method: method, - hasRangeHeader: hasRangeHeader, - scheme: scheme, - host: host, - port: port, - user: user, - query: query, - fragment: fragment, - percentEncodedPath: path, - urlByteCount: urlByteCount - ) - } - - static func resolve(_ request: MobileWebShellRequestParts) -> String? { - MobileWebShellOrigin.resolveRequestPath(request, sessionId: session) - } - static func manifest( schemaVersion: Int = 1, entrypoint: String = "index.html", @@ -68,42 +36,6 @@ import Foundation } - static func checkRequestResolution() { - precondition(resolve(parts(path: "/")) == "/") - precondition(resolve(parts(path: "")) == "/") - precondition(resolve(parts(path: "/assets/aa.js")) == "/assets/aa.js") - // A host a parser canonicalised must still bind to this session. - precondition(resolve(parts(path: "/", host: session.uppercased())) == "/") - - precondition(resolve(parts(path: "/", method: "POST")) == nil) - precondition(resolve(parts(path: "/", method: "HEAD")) == nil) - precondition(resolve(parts(path: "/", hasRangeHeader: true)) == nil) - precondition(resolve(parts(path: "/", scheme: "https")) == nil) - precondition(resolve(parts(path: "/", scheme: nil)) == nil) - // Unicode folding would serve assets to unminted Kelvin-sign hosts. - precondition(MobileWebShellOrigin.resolveRequestPath( - parts(path: "/", host: "\u{212A}ey"), - sessionId: "key" - ) == nil) - precondition(MobileWebShellOrigin.resolveRequestPath( - parts(path: "/", host: "KEY"), - sessionId: "key" - ) == "/") - precondition(resolve(parts(path: "/", host: "other-session")) == nil) - precondition(resolve(parts(path: "/", host: nil)) == nil) - precondition(resolve(parts(path: "/", port: 443)) == nil) - precondition(resolve(parts(path: "/", user: "someone")) == nil) - precondition(resolve(parts(path: "/", query: "v=1")) == nil) - precondition(resolve(parts(path: "/", fragment: "frag")) == nil) - precondition(resolve(parts(path: "/assets/%2e%2e/etc")) == nil) - precondition(resolve(parts(path: "assets/aa.js")) == nil) - precondition(resolve(parts(path: "/", urlByteCount: 8 * 1024)) == "/") - precondition(resolve(parts(path: "/", urlByteCount: 8 * 1024 + 1)) == nil) - precondition(MobileWebShellOrigin.resolveRequestPath(parts(path: "/"), sessionId: "") == nil) - } - - - static func checkGenerationMap() { guard let built = generation(manifest()) else { preconditionFailure("manifest rejected") } // Only / may serve document bytes with CSP; no entrypoint alias. @@ -214,156 +146,9 @@ import Foundation - static func bridgeSource( - isOurWebView: Bool = true, - isMainFrame: Bool = true, - hasCommittedDocument: Bool = true, - originProtocol: String = MobileWebShellOrigin.scheme, - originHost: String = session - ) -> MobileWebShellBridgeSource { - MobileWebShellBridgeSource( - isOurWebView: isOurWebView, - isMainFrame: isMainFrame, - hasCommittedDocument: hasCommittedDocument, - originProtocol: originProtocol, - originHost: originHost - ) - } - - static func acceptsBridge(_ source: MobileWebShellBridgeSource) -> Bool { - MobileWebShellBridge.accepts(source, sessionId: session) - } - - - static func checkBridgeAcceptance() { - precondition(acceptsBridge(bridgeSource())) - // Simulator: WebKit ASCII-lowercases custom-scheme hosts; exact session comparison refuses every message. - precondition(acceptsBridge(bridgeSource(originHost: "sess-01jn_az9"))) - precondition(acceptsBridge(bridgeSource(originHost: "SESS-01JN_AZ9"))) - - // A frame we did not serve. - precondition(!acceptsBridge(bridgeSource(originHost: "sess-01JN_aZ8"))) - precondition(!acceptsBridge(bridgeSource(originHost: ""))) - precondition(!acceptsBridge(bridgeSource(originHost: "sess-01JN_aZ9.evil"))) - // Unicode folding would accept unminted Kelvin-sign hosts. - precondition(!MobileWebShellBridge.accepts( - bridgeSource(originHost: "\u{212A}ey"), - sessionId: "key" - )) - - // Another scheme reaching the same handler. - precondition(!acceptsBridge(bridgeSource(originProtocol: "https"))) - precondition(!acceptsBridge(bridgeSource(originProtocol: ""))) - precondition(!acceptsBridge(bridgeSource(originProtocol: "orca-mobile-web "))) - - // A subframe, and a message routed to a WebView that is not ours. - precondition(!acceptsBridge(bridgeSource(isMainFrame: false))) - precondition(!acceptsBridge(bridgeSource(isOurWebView: false))) - - // The replaced same-origin document remains alive until the new load commits. - precondition(!acceptsBridge(bridgeSource(hasCommittedDocument: false))) - - // No applied session is not an empty one: nothing may be accepted before a load. - precondition(!MobileWebShellBridge.accepts(bridgeSource(originHost: ""), sessionId: "")) - precondition(!MobileWebShellBridge.accepts(bridgeSource(originHost: "a b"), sessionId: "a b")) - } - - static func checkBridgePostTarget() { - func canPost( - _ host: String?, - _ sessionId: String = session, - committed: Bool = true - ) -> Bool { - MobileWebShellBridge.canPost( - toFrameOriginHost: host, - sessionId: sessionId, - hasCommittedDocument: committed - ) - } - - precondition(canPost(session)) - // The same ASCII fold as acceptance: WebKit reports the host lowercased. - precondition(canPost("sess-01jn_az9")) - - // Never post without an accepted frame: before first message, after failure/death, or with bridge disabled. - precondition(!canPost(nil)) - - // A frame from another document, and a frame under no session at all. - precondition(!canPost("sess-01JN_aZ8")) - precondition(!canPost("\u{212A}ey", "key")) - precondition(!canPost(session, "")) - - // Provisional navigation invalidates the held frame until commit. - precondition(!canPost(session, committed: false)) - } - - - // One allow/opener decision; TypeScript’s readBridgeExternalLinkUrl owns scheme filtering. - static func checkNavigationVerdict() { - let foreign = "https://example.com/artifact-link" - let document = "orca-mobile-web://\(session)/" - func verdict( - _ url: String? = "https://example.com/artifact-link", - isMainFrame: Bool = true, - isDocumentUrl: Bool = false, - isShellLoad: Bool = false, - hasGesture: Bool = true, - isDownload: Bool = false - ) -> MobileWebShellNavigationVerdict { - MobileWebShellNavigationPolicy.verdict( - url: url, - isMainFrame: isMainFrame, - isDocumentUrl: isDocumentUrl, - isShellLoad: isShellLoad, - hasGesture: hasGesture, - isDownload: isDownload - ) - } - precondition(verdict() == .cancelAndOffer(foreign)) - // WebKit reports our own load with main-frame source and target. - precondition(verdict(document, isDocumentUrl: true, isShellLoad: true, hasGesture: false) == .allow) - // Never offer/reload other document-URL navigations; sandboxed top navigation can report no gesture. - precondition(verdict(document, isDocumentUrl: true, hasGesture: false) == .cancel) - precondition(verdict(document, isDocumentUrl: true, hasGesture: true) == .cancel) - // A top-page meta refresh or a redirect to somewhere else: refused, and never opened. - precondition(verdict(hasGesture: false) == .cancel) - // Gestured downloads reach the opener, never the document-load allowance. - precondition( - verdict(document, isDocumentUrl: true, isShellLoad: true, hasGesture: false, isDownload: true) - == .cancel - ) - precondition(verdict(isDownload: true) == .cancelAndOffer(foreign)) - // Document-URL downloads are never offered, regardless of gesture. - precondition(verdict(document, isDocumentUrl: true, isDownload: true) == .cancel) - // A foreign-URL subframe is never offered: the user is not leaving the app. - precondition(verdict(isMainFrame: false) == .cancel) - // Sealed srcdoc frames (HTML previews, chat visuals) load; no other subframe or top-level srcdoc does. - let srcdoc = MobileWebShellNavigationPolicy.inlineDocumentUrl - precondition(verdict(srcdoc, isMainFrame: false, hasGesture: false) == .allow) - precondition(verdict(srcdoc, isMainFrame: false, isDownload: true) == .cancel) - precondition(verdict(srcdoc, hasGesture: false) == .cancel) - precondition(verdict("about:blank", isMainFrame: false, hasGesture: false) == .cancel) - precondition(verdict(document, isMainFrame: false, isDocumentUrl: true, isShellLoad: true) == .cancel) - precondition(verdict(nil) == .cancel) - precondition(verdict("") == .cancel) - // The crossing cap, at it and one past it. - let cap = MobileWebShellNavigationPolicy.maxCancelledNavigationUrlCharacters - let prefix = "https://example.com/" - let atCap = prefix + String(repeating: "a", count: cap - prefix.count) - precondition(MobileWebShellNavigationPolicy.offerableUrl(atCap) == atCap) - precondition(MobileWebShellNavigationPolicy.offerableUrl(atCap + "a") == nil) - precondition(verdict(atCap + "a") == .cancel) - // A scheme the opener will refuse still crosses: one filter, in the half that updates. - precondition(verdict("javascript:alert(1)") == .cancelAndOffer("javascript:alert(1)")) - } - static func main() { - checkRequestResolution() checkGenerationMap() checkLoadStateMachine() - checkNavigationVerdict() - checkBridgeAcceptance() - checkBridgePostTarget() print("mobile web shell checks OK") } } diff --git a/mobile/packages/expo-two-way-audio/tests/RecordingInterruptionIntentTests.swift b/mobile/packages/expo-two-way-audio/tests/RecordingInterruptionIntentTests.swift deleted file mode 100644 index 9229f1829da..00000000000 --- a/mobile/packages/expo-two-way-audio/tests/RecordingInterruptionIntentTests.swift +++ /dev/null @@ -1,30 +0,0 @@ -@main -struct RecordingInterruptionIntentTests { - static func main() { - var intent = RecordingInterruptionIntent() - // An idle audio interruption never starts a recording. - intent.began(wasRecording: false) - precondition(intent.ended(shouldResume: true, isRecording: false) == .blocked) - // A still-owned recording resumes once, not again on a duplicate end event. - intent.began(wasRecording: true) - precondition(intent.ended(shouldResume: true, isRecording: false) == .resume) - precondition(intent.ended(shouldResume: true, isRecording: false) == .blocked) - // A blocked or missing shouldResume bit consumes the old resume request. - intent.began(wasRecording: true) - precondition(intent.ended(shouldResume: false, isRecording: false) == .blocked) - precondition(intent.ended(shouldResume: true, isRecording: false) == .blocked) - // JavaScript cancels capture after began; ended must not turn its microphone back on. - intent.began(wasRecording: true) - intent.cancel() - precondition(intent.ended(shouldResume: true, isRecording: false) == .blocked) - // A newer explicit recording must not be cancelled by the old end notification. - intent.began(wasRecording: true) - intent.cancel() - precondition(intent.ended(shouldResume: true, isRecording: true) == .none) - // The most recent interruption, even one while idle, replaces old resume intent. - intent.began(wasRecording: true) - intent.began(wasRecording: false) - precondition(intent.ended(shouldResume: true, isRecording: false) == .blocked) - print("RecordingInterruptionIntent: 8 assertions passed") - } -} diff --git a/src/shared/bounded-map.test.ts b/src/shared/bounded-map.test.ts index c70ebf85250..1f6fab864f1 100644 --- a/src/shared/bounded-map.test.ts +++ b/src/shared/bounded-map.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, it, vi } from 'vitest' +import { describe, expect, it } from 'vitest' import { BoundedMap } from './bounded-map' describe('BoundedMap', () => { @@ -29,41 +29,6 @@ describe('BoundedMap', () => { expect(m.has('c')).toBe(true) }) - it('never reports success for an entry it did not retain', () => { - const onEvict = vi.fn() - // An entry ceiling above total once admitted then evicted the same key while set returned true. - const m = new BoundedMap({ - maxEntries: 10, - maxBytes: 3, - maxEntryBytes: 5, - sizeOf: (v) => v.length, - onEvict - }) - m.set('s1', 'x') - m.set('s2', 'y') - expect(m.set('big', 'xxxx')).toBe(false) - expect(m.has('big')).toBe(false) - expect(m.has('s1')).toBe(true) - expect(m.has('s2')).toBe(true) - expect(onEvict).not.toHaveBeenCalled() - expect(m.retainedBytes).toBe(2) - }) - - it('fails closed on an unmeasurable weight instead of poisoning the ledger', () => { - const m = new BoundedMap({ - maxEntries: 10, - maxBytes: 10, - sizeOf: (v) => (v === 'bad' ? Number.NaN : v.length) - }) - expect(m.set('ok', 'abc')).toBe(true) - expect(m.set('nan', 'bad')).toBe(false) - expect(m.set('neg', 'x')).toBe(true) - expect(m.retainedBytes).toBe(4) - expect(Number.isFinite(m.retainedBytes)).toBe(true) - // ceiling still armed after the rejected weight - expect(m.set('huge', 'zzzzzzzzzzzz')).toBe(false) - }) - it('a rejected oversized overwrite leaves the existing value untouched', () => { const m = new BoundedMap({ maxEntries: 10, @@ -92,67 +57,4 @@ describe('BoundedMap', () => { ['b', 2] ]) }) - - it('an overflow-rejected overwrite keeps the prior value and leaves no orphaned weight', () => { - const weights = new Map([ - ['a', Number.MAX_SAFE_INTEGER - 1], - ['b', 1] - ]) - const m = new BoundedMap({ - maxEntries: 10, - maxBytes: Number.MAX_SAFE_INTEGER, - sizeOf: (_v, k) => weights.get(k) ?? 0 - }) - m.set('a', 'A') - m.set('b', 'B') - weights.set('b', 3) // next weight for 'b' exceeds the remaining headroom - expect(m.set('b', 'B2')).toBe(false) - expect(m.has('b')).toBe(true) // rejection must not displace the prior value - expect(m.peek('b')).toBe('B') - expect(m.retainedBytes).toBe(Number.MAX_SAFE_INTEGER) - // the rejected key must not strand a weight: deleting everything returns the ledger to zero - weights.set('b', 1) - m.delete('a') - m.delete('b') - expect(m.retainedBytes).toBe(0) - expect(m.size).toBe(0) - }) - - it('rejects the entry when sizeOf throws instead of propagating', () => { - const m = new BoundedMap({ - maxEntries: 4, - maxBytes: 50, - sizeOf: (v) => { - if (v === 'boom') { - throw new Error('measure failed') - } - return v.length - } - }) - expect(m.set('ok', 'abc')).toBe(true) - expect(() => m.set('bad', 'boom')).not.toThrow() - expect(m.set('bad', 'boom')).toBe(false) - expect(m.has('bad')).toBe(false) - expect(m.retainedBytes).toBe(3) - }) - - it('runs every disposal even when one onEvict throws', () => { - const disposed: string[] = [] - const m = new BoundedMap({ - maxEntries: 10, - maxBytes: 2, - sizeOf: (v) => v.length, - onEvict: (_v, k) => { - disposed.push(k) - if (k === 'a') { - throw new Error('dispose failed') - } - } - }) - m.set('a', 'x') - m.set('b', 'y') - expect(() => m.set('c', 'zz')).toThrow('dispose failed') - expect(disposed).toEqual(['a', 'b']) // 'b' still disposed despite the earlier throw - expect(m.retainedBytes).toBeLessThanOrEqual(2) - }) }) diff --git a/src/shared/claude-agent-view-launch.test.ts b/src/shared/claude-agent-view-launch.test.ts deleted file mode 100644 index 161389531b7..00000000000 --- a/src/shared/claude-agent-view-launch.test.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { expect, it } from 'vitest' -import { withClaudeAgentViewPlugin } from './claude-agent-view-launch' -import { - tokenizeStartupCommand, - type AgentStartupShell -} from './agent-launch/startup/tui-agent-startup-shell' - -it.each(['posix', 'powershell', 'cmd'] as const)( - 'preserves existing plugin arguments and prompts in %s', - (shell: AgentStartupShell) => { - const command = 'claude --plugin-dir user-plugin --resume session -- "my prompt"' - const result = withClaudeAgentViewPlugin(command, 'orca plugin', shell) - const parsed = tokenizeStartupCommand(result, shell) - expect(parsed.ok && parsed.tokens).toEqual([ - 'claude', - '--plugin-dir', - 'orca plugin', - '--plugin-dir', - 'user-plugin', - '--resume', - 'session', - '--', - 'my prompt' - ]) - } -) - -it.each(['ssh host claude', 'bash -c claude', 'echo /bin/claude', 'claude && echo done'])( - 'leaves shell syntax and ambiguous executables unchanged: %s', - (command) => { - expect(withClaudeAgentViewPlugin(command, '/orca/plugin', 'posix')).toBe(command) - } -) diff --git a/src/shared/cloud-service-url.test.ts b/src/shared/cloud-service-url.test.ts index 61425fed452..558c4bee1eb 100644 --- a/src/shared/cloud-service-url.test.ts +++ b/src/shared/cloud-service-url.test.ts @@ -1,6 +1,6 @@ import { expect, it } from 'vitest' import { cleanCloudServiceOrigin } from './cloud-service-url' -it.each(['ftp://localhost', 'file://localhost', 'ws://localhost', 'http://example.com'])( +it.each(['ftp://localhost', 'http://example.com'])( 'rejects %s even with the development loopback exception', (url) => { expect(cleanCloudServiceOrigin(url, true)).toBeNull()