diff --git a/packages/shared/tests/unit/adapter-policy-cpp.test.ts b/packages/shared/tests/unit/adapter-policy-cpp.test.ts index c18ae8b8..79c2c168 100644 --- a/packages/shared/tests/unit/adapter-policy-cpp.test.ts +++ b/packages/shared/tests/unit/adapter-policy-cpp.test.ts @@ -156,6 +156,12 @@ describe('CppAdapterPolicy', () => { const env = (config as { env?: NodeJS.ProcessEnv }).env; expect(env?.LLDB_USE_NATIVE_PDB_READER).toBe('1'); }); + + it('defaults platform/arch to the host when omitted', () => { + const config = CppAdapterPolicy.getAdapterSpawnConfig!(payload); + expect((config as { command: string }).command).toBeTruthy(); + expect((config as { args: string[] }).args).toEqual(['--port', '4711']); + }); }); describe('matchesAdapter', () => { @@ -170,6 +176,48 @@ describe('CppAdapterPolicy', () => { expect(CppAdapterPolicy.isSessionReady!(SessionState.RUNNING)).toBe(false); }); + it('throws when building child session args', () => { + expect(() => CppAdapterPolicy.buildChildStartArgs!('pending-1', {})).toThrow( + 'CppAdapterPolicy does not support child sessions' + ); + }); + + it("treats only 'initialized' as the child-ready event", () => { + const event = (name: string): DebugProtocol.Event => ({ seq: 1, type: 'event', event: name }); + expect(CppAdapterPolicy.isChildReadyEvent!(event('initialized'))).toBe(true); + expect(CppAdapterPolicy.isChildReadyEvent!(event('stopped'))).toBe(false); + }); + + it('reads locals from the shared LLDB scope names', () => { + expect(CppAdapterPolicy.getLocalScopeName!()).toEqual(['Local', 'Locals']); + }); + + it('resolves executable path from inputs only, deferring to the adapter otherwise', () => { + expect(CppAdapterPolicy.resolveExecutablePath!('/custom/codelldb')).toBe('/custom/codelldb'); + // CODELLDB_PATH env var is handled in codelldb-resolver.ts, not here + expect(CppAdapterPolicy.resolveExecutablePath!()).toBeUndefined(); + }); + + it('reports CodeLLDB debugger capabilities', () => { + expect(CppAdapterPolicy.getDebuggerConfiguration!()).toEqual({ + requiresStrictHandshake: false, + skipConfigurationDone: false, + supportsVariableType: true, + supportsValueFormat: true, + supportsMemoryReferences: true + }); + }); + + it('never queues commands', () => { + expect(CppAdapterPolicy.requiresCommandQueueing!()).toBe(false); + const handling = CppAdapterPolicy.shouldQueueCommand!('next', CppAdapterPolicy.createInitialState!()); + expect(handling).toEqual({ + shouldQueue: false, + shouldDefer: false, + reason: 'C++/CodeLLDB adapter does not queue commands' + }); + }); + it('tracks initialization state via the shared LLDB state helpers', () => { const state = CppAdapterPolicy.createInitialState!(); expect(CppAdapterPolicy.isInitialized!(state)).toBe(false); diff --git a/packages/shared/tests/unit/adapter-policy-rust.test.ts b/packages/shared/tests/unit/adapter-policy-rust.test.ts index 31768974..d07a5500 100644 --- a/packages/shared/tests/unit/adapter-policy-rust.test.ts +++ b/packages/shared/tests/unit/adapter-policy-rust.test.ts @@ -365,11 +365,36 @@ describe('RustAdapterPolicy', () => { }); it('never queues commands', () => { + expect(RustAdapterPolicy.requiresCommandQueueing!()).toBe(false); const result = RustAdapterPolicy.shouldQueueCommand!(); expect(result.shouldQueue).toBe(false); expect(result.shouldDefer).toBe(false); }); + it("treats only 'initialized' as the child-ready event", () => { + const event = (name: string): DebugProtocol.Event => ({ seq: 1, type: 'event', event: name }); + expect(RustAdapterPolicy.isChildReadyEvent!(event('initialized'))).toBe(true); + expect(RustAdapterPolicy.isChildReadyEvent!(event('stopped'))).toBe(false); + }); + + it('reads locals from the shared LLDB scope names', () => { + expect(RustAdapterPolicy.getLocalScopeName!()).toEqual(['Local', 'Locals']); + }); + + it('uses the CodeLLDB adapter type', () => { + expect(RustAdapterPolicy.getDapAdapterConfiguration!()).toEqual({ type: 'lldb' }); + }); + + it('reports CodeLLDB debugger capabilities', () => { + expect(RustAdapterPolicy.getDebuggerConfiguration!()).toEqual({ + requiresStrictHandshake: false, + skipConfigurationDone: false, + supportsVariableType: true, + supportsValueFormat: true, + supportsMemoryReferences: true + }); + }); + it('matches CodeLLDB adapter invocations', () => { const match = RustAdapterPolicy.matchesAdapter!({ command: '/opt/codelldb/adapter/codelldb', diff --git a/packages/shared/tests/unit/resolve-exception-filters.test.ts b/packages/shared/tests/unit/resolve-exception-filters.test.ts index f3e26f58..891bafd2 100644 --- a/packages/shared/tests/unit/resolve-exception-filters.test.ts +++ b/packages/shared/tests/unit/resolve-exception-filters.test.ts @@ -15,6 +15,7 @@ import { DotnetAdapterPolicy, RubyAdapterPolicy, RustAdapterPolicy, + CppAdapterPolicy, MockAdapterPolicy } from '../../src/index.js'; @@ -37,6 +38,10 @@ const EXPECTATIONS: PolicyExpectation[] = [ // Ruby: no uncaught-only filter in rdbg → no launch default; crashes run to termination { name: 'ruby', policy: RubyAdapterPolicy, uncaught: [], all: ['any'], defaultMode: undefined }, { name: 'rust', policy: RustAdapterPolicy, uncaught: ['rust_panic'], all: ['rust_panic', 'cpp_throw'], defaultMode: 'uncaught' }, + // Cpp: LLDB has no uncaught-only C++ filter — cpp_throw fires on every throw, + // and uncaught exceptions reach std::terminate -> SIGABRT, which LLDB stops + // on natively. So 'uncaught' maps to NO filters (issue #244 default). + { name: 'cpp', policy: CppAdapterPolicy, uncaught: [], all: ['cpp_throw'], defaultMode: 'uncaught' }, { name: 'mock', policy: MockAdapterPolicy, uncaught: ['uncaught'], all: ['all'], defaultMode: 'uncaught' } ];