@@ -25,15 +25,21 @@ import { debugSessionFactory } from '../../../../__test__/vscode.factory';
2525import { GDBTargetDebugSession } from '../../../../debug-session' ;
2626import { componentViewerLogger } from '../../../../logger' ;
2727
28- type DebugWithSession = {
29- activeDebugSession : vscode . DebugSession | undefined ;
30- activeStackItem : vscode . DebugStackFrame | undefined ;
31- } ;
32-
3328function setActiveStackItem ( session : vscode . DebugSession | undefined , frameId : number | undefined ) {
34- ( vscode . debug as unknown as DebugWithSession ) . activeStackItem = session
35- ? ( { session, threadId : 1 , frameId } as unknown as vscode . DebugStackFrame )
36- : undefined ;
29+ const value = session ? { session, threadId : 1 , frameId } : undefined ;
30+ Object . defineProperty ( vscode . debug , 'activeStackItem' , {
31+ value,
32+ configurable : true ,
33+ writable : true ,
34+ } ) ;
35+ }
36+
37+ function setActiveDebugSession ( session : vscode . DebugSession | undefined ) {
38+ Object . defineProperty ( vscode . debug , 'activeDebugSession' , {
39+ value : session ,
40+ configurable : true ,
41+ writable : true ,
42+ } ) ;
3743}
3844
3945describe ( 'ComponentViewerTargetAccess' , ( ) => {
@@ -53,24 +59,42 @@ describe('ComponentViewerTargetAccess', () => {
5359 targetAccess = new ComponentViewerTargetAccess ( ) ;
5460 targetAccess . setActiveSession ( gdbTargetSession ) ;
5561 setActiveStackItem ( debugSession , 1 ) ;
62+ setActiveDebugSession ( debugSession ) ;
5663 } ) ;
5764
5865 afterEach ( ( ) => {
5966 setActiveStackItem ( undefined , undefined ) ;
60- ( vscode . debug as unknown as DebugWithSession ) . activeDebugSession = undefined ;
67+ setActiveDebugSession ( undefined ) ;
6168 jest . restoreAllMocks ( ) ;
6269 } ) ;
6370
64- it ( 'formats addresses consistently' , ( ) => {
65- const formatAddress = ( targetAccess as unknown as { formatAddress : ( addr : string | number | bigint ) => string } )
66- . formatAddress ;
71+ it ( 'formats addresses consistently for symbol lookups' , async ( ) => {
72+ setActiveStackItem ( debugSession , 7 ) ;
73+
74+ const cases = [
75+ { input : '' , expected : '(unsigned int*)' } ,
76+ { input : ' 0x1A ' , expected : '(unsigned int*)0x1A' } ,
77+ { input : '15' , expected : '(unsigned int*)0xf' } ,
78+ { input : 16 , expected : '(unsigned int*)0x10' } ,
79+ { input : 0x20n , expected : '(unsigned int*)0x20' } ,
80+ { input : 'not-a-number' , expected : '(unsigned int*)not-a-number' } ,
81+ ] ;
82+
83+ const expectedExpressions = cases . map ( ( { expected } ) => expected ) ;
84+ ( debugSession . customRequest as jest . Mock ) . mockImplementation ( async ( _command , args ) => {
85+ const expectedExpression = expectedExpressions . shift ( ) ;
86+ expect ( args ) . toEqual ( {
87+ expression : expectedExpression ?? '' ,
88+ frameId : 7 ,
89+ context : 'hover' ,
90+ } ) ;
91+ return { result : '0x0 <Sym>' } ;
92+ } ) ;
6793
68- expect ( formatAddress ( '' ) ) . toBe ( '' ) ;
69- expect ( formatAddress ( ' 0x1A ' ) ) . toBe ( '0x1A' ) ;
70- expect ( formatAddress ( '15' ) ) . toBe ( '0xf' ) ;
71- expect ( formatAddress ( 16 ) ) . toBe ( '0x10' ) ;
72- expect ( formatAddress ( 0x20n ) ) . toBe ( '0x20' ) ;
73- expect ( formatAddress ( 'not-a-number' ) ) . toBe ( 'not-a-number' ) ;
94+ for ( const { input } of cases ) {
95+ await expect ( targetAccess . evaluateSymbolName ( input ) ) . resolves . toBe ( 'Sym' ) ;
96+ }
97+ expect ( expectedExpressions ) . toHaveLength ( 0 ) ;
7498 } ) ;
7599
76100 it ( 'evaluates symbol address and handles failures' , async ( ) => {
@@ -91,6 +115,14 @@ describe('ComponentViewerTargetAccess', () => {
91115 ) ;
92116 } ) ;
93117
118+ it ( 'returns undefined without logging when exist check fails' , async ( ) => {
119+ const debugSpy = jest . spyOn ( componentViewerLogger , 'debug' ) ;
120+ ( debugSession . customRequest as jest . Mock ) . mockRejectedValueOnce ( new Error ( 'probe failed' ) ) ;
121+
122+ await expect ( targetAccess . evaluateSymbolAddress ( 'missing' , 'hover' , true ) ) . resolves . toBeUndefined ( ) ;
123+ expect ( debugSpy ) . not . toHaveBeenCalled ( ) ;
124+ } ) ;
125+
94126 it ( 'evaluates symbol name with valid and missing results' , async ( ) => {
95127 ( debugSession . customRequest as jest . Mock ) . mockResolvedValueOnce ( { result : '0x20000000 <MySymbol>' } ) ;
96128 setActiveStackItem ( debugSession , 1 ) ;
@@ -109,6 +141,9 @@ describe('ComponentViewerTargetAccess', () => {
109141 ( debugSession . customRequest as jest . Mock ) . mockResolvedValueOnce ( { result : 'No symbol matches' } ) ;
110142 await expect ( targetAccess . evaluateSymbolName ( '0x0' ) ) . resolves . toBeUndefined ( ) ;
111143
144+ ( debugSession . customRequest as jest . Mock ) . mockResolvedValueOnce ( { result : '0x20000000 Symbol' } ) ;
145+ await expect ( targetAccess . evaluateSymbolName ( '0x20000000' ) ) . resolves . toBeUndefined ( ) ;
146+
112147 const debugSpy = jest . spyOn ( componentViewerLogger , 'debug' ) ;
113148 ( debugSession . customRequest as jest . Mock ) . mockRejectedValueOnce ( new Error ( 'oops' ) ) ;
114149 await expect ( targetAccess . evaluateSymbolName ( '0x1' ) ) . resolves . toBeUndefined ( ) ;
@@ -124,6 +159,9 @@ describe('ComponentViewerTargetAccess', () => {
124159 ( debugSession . customRequest as jest . Mock ) . mockResolvedValueOnce ( { result : 'No line information' } ) ;
125160 await expect ( targetAccess . evaluateSymbolContext ( '0x100' ) ) . resolves . toBeUndefined ( ) ;
126161
162+ ( debugSession . customRequest as jest . Mock ) . mockResolvedValueOnce ( { result : '' } ) ;
163+ await expect ( targetAccess . evaluateSymbolContext ( '0x100' ) ) . resolves . toBeUndefined ( ) ;
164+
127165 const debugSpy = jest . spyOn ( componentViewerLogger , 'debug' ) ;
128166 ( debugSession . customRequest as jest . Mock ) . mockRejectedValueOnce ( new Error ( 'context fail' ) ) ;
129167 await expect ( targetAccess . evaluateSymbolContext ( '0x100' ) ) . resolves . toBeUndefined ( ) ;
0 commit comments