Skip to content

Commit 87a50e6

Browse files
remaining coverage
1 parent 3870fa1 commit 87a50e6

1 file changed

Lines changed: 210 additions & 0 deletions

File tree

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
/**
2+
* Copyright 2026 Arm Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import * as vscode from 'vscode';
18+
import { ComponentViewerTargetAccess } from '../component-viewer-target-access';
19+
import { debugSessionFactory } from '../../../__test__/vscode.factory';
20+
import { GDBTargetDebugSession } from '../../../debug-session';
21+
import { logger } from '../../../logger';
22+
23+
type DebugWithSession = {
24+
activeDebugSession: vscode.DebugSession | undefined;
25+
activeStackItem: vscode.DebugStackFrame | undefined;
26+
};
27+
28+
function setActiveStackItem(session: vscode.DebugSession | undefined, frameId: number | undefined) {
29+
(vscode.debug as unknown as DebugWithSession).activeStackItem = session
30+
? ({ session, threadId: 1, frameId } as unknown as vscode.DebugStackFrame)
31+
: undefined;
32+
}
33+
34+
describe('ComponentViewerTargetAccess coverage', () => {
35+
const defaultConfig = () => ({
36+
name: 'test-session',
37+
type: 'gdbtarget',
38+
request: 'launch',
39+
});
40+
41+
let debugSession: vscode.DebugSession;
42+
let gdbTargetSession: GDBTargetDebugSession;
43+
let targetAccess: ComponentViewerTargetAccess;
44+
45+
beforeEach(() => {
46+
debugSession = debugSessionFactory(defaultConfig());
47+
gdbTargetSession = new GDBTargetDebugSession(debugSession);
48+
targetAccess = new ComponentViewerTargetAccess();
49+
targetAccess.setActiveSession(gdbTargetSession);
50+
setActiveStackItem(undefined, undefined);
51+
});
52+
53+
afterEach(() => {
54+
setActiveStackItem(undefined, undefined);
55+
(vscode.debug as unknown as DebugWithSession).activeDebugSession = undefined;
56+
jest.restoreAllMocks();
57+
});
58+
59+
it('initializes session from vscode when available', () => {
60+
(vscode.debug as unknown as DebugWithSession).activeDebugSession = debugSession;
61+
62+
const instance = new ComponentViewerTargetAccess();
63+
64+
expect(instance._activeSession).toBeInstanceOf(GDBTargetDebugSession);
65+
expect(instance._activeSession?.session).toBe(debugSession);
66+
});
67+
68+
it('formats addresses consistently', () => {
69+
const formatAddress = (targetAccess as unknown as { formatAddress: (addr: string | number | bigint) => string })
70+
.formatAddress;
71+
72+
expect(formatAddress('')).toBe('');
73+
expect(formatAddress(' 0x1A ')).toBe('0x1A');
74+
expect(formatAddress('15')).toBe('0xf');
75+
expect(formatAddress(16)).toBe('0x10');
76+
expect(formatAddress(0x20n)).toBe('0x20');
77+
expect(formatAddress('not-a-number')).toBe('not-a-number');
78+
});
79+
80+
it('evaluates symbol address and handles failures', async () => {
81+
(debugSession.customRequest as jest.Mock).mockResolvedValueOnce({ result: '0x20000000 extra' });
82+
setActiveStackItem(debugSession, 9);
83+
84+
await expect(targetAccess.evaluateSymbolAddress('myVar')).resolves.toBe('0x20000000');
85+
86+
const debugSpy = jest.spyOn(logger, 'debug');
87+
(debugSession.customRequest as jest.Mock).mockRejectedValueOnce(new Error('bad'));
88+
89+
await expect(targetAccess.evaluateSymbolAddress('missing')).resolves.toBeUndefined();
90+
expect(debugSpy).toHaveBeenCalledWith(
91+
'Session \'test-session\': Failed to evaluate address \'missing\' - \'bad\''
92+
);
93+
});
94+
95+
it('evaluates symbol name with valid and missing results', async () => {
96+
(debugSession.customRequest as jest.Mock).mockResolvedValueOnce({ result: '0x20000000 <MySymbol>' });
97+
setActiveStackItem(debugSession, 1);
98+
99+
await expect(targetAccess.evaluateSymbolName(0x20000000)).resolves.toBe('MySymbol');
100+
101+
(debugSession.customRequest as jest.Mock).mockResolvedValueOnce({ result: '0x20000000 <Other>' });
102+
setActiveStackItem(undefined, undefined);
103+
await expect(targetAccess.evaluateSymbolName('0x20000000')).resolves.toBe('Other');
104+
expect(debugSession.customRequest).toHaveBeenLastCalledWith('evaluate', {
105+
expression: '(unsigned int*)0x20000000',
106+
frameId: 0,
107+
context: 'hover',
108+
});
109+
110+
(debugSession.customRequest as jest.Mock).mockResolvedValueOnce({ result: 'No symbol matches' });
111+
await expect(targetAccess.evaluateSymbolName('0x0')).resolves.toBeUndefined();
112+
113+
const debugSpy = jest.spyOn(logger, 'debug');
114+
(debugSession.customRequest as jest.Mock).mockRejectedValueOnce(new Error('oops'));
115+
await expect(targetAccess.evaluateSymbolName('0x1')).resolves.toBeUndefined();
116+
expect(debugSpy).toHaveBeenCalledWith(
117+
'Session \'test-session\': Failed to evaluate name \'0x1\' - \'oops\''
118+
);
119+
});
120+
121+
it('evaluates symbol context', async () => {
122+
(debugSession.customRequest as jest.Mock).mockResolvedValueOnce({ result: 'main.c:10' });
123+
await expect(targetAccess.evaluateSymbolContext('0x100')).resolves.toBe('main.c:10');
124+
125+
(debugSession.customRequest as jest.Mock).mockResolvedValueOnce({ result: 'No line information' });
126+
await expect(targetAccess.evaluateSymbolContext('0x100')).resolves.toBeUndefined();
127+
128+
const debugSpy = jest.spyOn(logger, 'debug');
129+
(debugSession.customRequest as jest.Mock).mockRejectedValueOnce(new Error('context fail'));
130+
await expect(targetAccess.evaluateSymbolContext('0x100')).resolves.toBeUndefined();
131+
expect(debugSpy).toHaveBeenCalledWith(
132+
'Session \'test-session\': Failed to evaluate context for \'0x100\' - \'context fail\''
133+
);
134+
});
135+
136+
it('evaluates symbol size', async () => {
137+
(debugSession.customRequest as jest.Mock).mockResolvedValueOnce({ result: '4' });
138+
await expect(targetAccess.evaluateSymbolSize('var')).resolves.toBe(4);
139+
140+
(debugSession.customRequest as jest.Mock).mockResolvedValueOnce({ result: 'nan' });
141+
await expect(targetAccess.evaluateSymbolSize('var')).resolves.toBeUndefined();
142+
143+
const debugSpy = jest.spyOn(logger, 'debug');
144+
(debugSession.customRequest as jest.Mock).mockRejectedValueOnce(new Error('size fail'));
145+
await expect(targetAccess.evaluateSymbolSize('var')).resolves.toBeUndefined();
146+
expect(debugSpy).toHaveBeenCalledWith(
147+
'Session \'test-session\': Failed to evaluate size of \'var\' - \'size fail\''
148+
);
149+
});
150+
151+
it('reads memory and handles errors', async () => {
152+
(debugSession.customRequest as jest.Mock).mockResolvedValueOnce({ data: 'AAAA' });
153+
await expect(targetAccess.evaluateMemory('16', 4, 0)).resolves.toBe('AAAA');
154+
155+
const debugSpy = jest.spyOn(logger, 'debug');
156+
(debugSession.customRequest as jest.Mock).mockRejectedValueOnce(new Error('custom request failed'));
157+
await expect(targetAccess.evaluateMemory('16', 4, 0)).resolves.toBe('No active session');
158+
expect(debugSpy).toHaveBeenCalledWith(
159+
'Session \'test-session\': Failed to read memory at address \'0x10\' - \'custom request failed\''
160+
);
161+
162+
(debugSession.customRequest as jest.Mock).mockRejectedValueOnce(new Error('bad read'));
163+
await expect(targetAccess.evaluateMemory('16', 4, 0)).resolves.toBe('bad read');
164+
expect(debugSpy).toHaveBeenCalledWith(
165+
'Session \'test-session\': Failed to read memory at address \'0x10\' - \'bad read\''
166+
);
167+
});
168+
169+
it('checks symbol existence', async () => {
170+
(debugSession.customRequest as jest.Mock).mockResolvedValueOnce({ result: '0x2000 mySymbol' });
171+
await expect(targetAccess.doesSymbolExist('mySymbol')).resolves.toBe(true);
172+
173+
(debugSession.customRequest as jest.Mock).mockResolvedValueOnce({ result: '0x2000 other' });
174+
await expect(targetAccess.doesSymbolExist('mySymbol')).resolves.toBe(false);
175+
176+
const debugSpy = jest.spyOn(logger, 'debug');
177+
(debugSession.customRequest as jest.Mock).mockRejectedValueOnce(new Error('exist fail'));
178+
await expect(targetAccess.doesSymbolExist('mySymbol')).resolves.toBe(false);
179+
expect(debugSpy).toHaveBeenCalledWith(
180+
'Session \'test-session\': Failed to know if symbol mySymbol exists - \'exist fail\''
181+
);
182+
});
183+
184+
it('evaluates number of array elements', async () => {
185+
(debugSession.customRequest as jest.Mock).mockResolvedValueOnce({ result: ' 3 ' });
186+
await expect(targetAccess.evaluateNumberOfArrayElements('arr')).resolves.toBe(3);
187+
188+
(debugSession.customRequest as jest.Mock).mockResolvedValueOnce({ result: 'NaN' });
189+
await expect(targetAccess.evaluateNumberOfArrayElements('arr')).resolves.toBeUndefined();
190+
191+
const debugSpy = jest.spyOn(logger, 'debug');
192+
(debugSession.customRequest as jest.Mock).mockRejectedValueOnce(new Error('count fail'));
193+
await expect(targetAccess.evaluateNumberOfArrayElements('arr')).resolves.toBeUndefined();
194+
expect(debugSpy).toHaveBeenCalledWith(
195+
'Session \'test-session\': Failed to evaluate number of elements for array \'arr\' - \'count fail\''
196+
);
197+
});
198+
199+
it('evaluates register values', async () => {
200+
(debugSession.customRequest as jest.Mock).mockResolvedValueOnce({ result: '0x1234' });
201+
await expect(targetAccess.evaluateRegisterValue('r0')).resolves.toBe('0x1234');
202+
203+
const debugSpy = jest.spyOn(logger, 'debug');
204+
(debugSession.customRequest as jest.Mock).mockRejectedValueOnce(new Error('reg fail'));
205+
await expect(targetAccess.evaluateRegisterValue('r1')).resolves.toBeUndefined();
206+
expect(debugSpy).toHaveBeenCalledWith(
207+
'Session \'test-session\': Failed to evaluate register value for \'r1\' - \'reg fail\''
208+
);
209+
});
210+
});

0 commit comments

Comments
 (0)