@@ -392,4 +392,131 @@ describe('multithread', async function () {
392392 }
393393 }
394394 } ) ;
395+
396+ it ( 'gets and sets register values at different frames for different threads' , async function ( ) {
397+ if ( ! gdbNonStop ) {
398+ // This test is covering only gdb-non-stop on
399+ this . skip ( ) ;
400+ }
401+
402+ await dc . launchRequest (
403+ fillDefaults ( this . test , {
404+ program,
405+ } )
406+ ) ;
407+ await dc . setBreakpointsRequest ( {
408+ source : {
409+ path : source ,
410+ } ,
411+ breakpoints : [
412+ {
413+ line : lineTags [ 'LINE_MAIN_ALL_THREADS_STARTED' ] ,
414+ } ,
415+ {
416+ line : lineTags [ 'LINE_THREAD_INNER' ] ,
417+ } ,
418+ ] ,
419+ } ) ;
420+
421+ const waitForStop = dc . waitForEvent ( 'stopped' ) ;
422+ await dc . configurationDoneRequest ( ) ;
423+ await waitForStop ;
424+
425+ // make sure that all the threads have stopped
426+ // TODO instead of a sleep, wait until all threads have stopped
427+ await new Promise ( ( f ) => setTimeout ( f , 1000 ) ) ;
428+ const threads = await dc . threadsRequest ( ) ;
429+ const runningThreads = threads . body . threads . filter (
430+ ( t ) => ( t as unknown as { running ?: boolean } ) . running
431+ ) ;
432+ expect ( runningThreads ) . to . be . an ( 'array' ) . that . is . empty ;
433+ const nameToId = new Map (
434+ threads . body . threads . map ( ( thread ) => [ thread . name , thread . id ] )
435+ ) ;
436+
437+ // check that each thread can be communicated with individually
438+ for ( const [ name , idInProgram ] of Object . entries ( threadNames ) ) {
439+ // There are multiple ids/indexes.
440+ // idInProgram cooresponds to the variable thread_id in the C++ source
441+ // threadId is the id of the thread in DAP
442+ const threadId = nameToId . get ( name ) ;
443+ if ( threadId === undefined ) {
444+ // unreachable because of expect above
445+ fail ( 'unreachable' ) ;
446+ }
447+
448+ const stack = await dc . stackTraceRequest ( { threadId } ) ;
449+
450+ // Iterate through stack frames:
451+ // Stack frame 0 is the inner method
452+ // Stack frames 1 to id + 1 are the recursive method
453+ // Stack frame id + 2 is PrintHello
454+ for ( let i = 0 ; i < idInProgram + 3 ; i ++ ) {
455+ if ( i == 0 ) {
456+ expect ( stack . body . stackFrames [ i ] . name ) . to . eq (
457+ 'inner_method'
458+ ) ;
459+ } else if ( i == idInProgram + 2 ) {
460+ expect ( stack . body . stackFrames [ i ] . name ) . to . eq ( 'PrintHello' ) ;
461+ } else {
462+ expect ( stack . body . stackFrames [ i ] . name ) . to . eq ( 'recursive' ) ;
463+ }
464+
465+ const scopes = await dc . scopesRequest ( {
466+ frameId : stack . body . stackFrames [ i ] . id ,
467+ } ) ;
468+ const vr = scopes . body . scopes [ 1 ] . variablesReference ;
469+ const vars = await dc . variablesRequest ( {
470+ variablesReference : vr ,
471+ } ) ;
472+
473+ const regPC = vars . body . variables . find (
474+ ( v ) => v . name === 'pc' || v . name === 'rip'
475+ ) ;
476+ expect ( regPC ) . to . exist ;
477+ const reg0 = vars . body . variables [ 0 ] ;
478+
479+ const setRegPC = await dc . setVariableRequest ( {
480+ name : regPC ! . name ,
481+ value : '0x200' ,
482+ variablesReference : vr ,
483+ } ) ;
484+ expect ( setRegPC . body . value ) . to . equal ( '0x200' ) ;
485+
486+ const setReg0 = await dc . setVariableRequest ( {
487+ name : reg0 . name ,
488+ value : '0x55555' ,
489+ variablesReference : vr ,
490+ } ) ;
491+ expect ( setReg0 . body . value ) . to . equal ( '0x55555' ) ;
492+
493+ const vars1 = await dc . variablesRequest ( {
494+ variablesReference : vr ,
495+ } ) ;
496+ expect ( vars1 . body . variables . length ) . to . equal (
497+ vars . body . variables . length
498+ ) ;
499+
500+ const varnameToValue1 = new Map (
501+ vars1 . body . variables . map ( ( variable ) => [
502+ variable . name ,
503+ variable . value ,
504+ ] )
505+ ) ;
506+ expect ( varnameToValue1 . get ( regPC ! . name ) ) . to . equal ( '0x200' ) ;
507+ expect ( varnameToValue1 . get ( reg0 . name ) ) . to . equal ( '0x55555' ) ;
508+
509+ await dc . setVariableRequest ( {
510+ name : regPC ! . name ,
511+ value : regPC ! . value ,
512+ variablesReference : vr ,
513+ } ) ;
514+ await dc . setVariableRequest ( {
515+ name : reg0 . name ,
516+ value : reg0 . value ,
517+ variablesReference : vr ,
518+ } ) ;
519+ }
520+ }
521+ } ) ;
395522} ) ;
0 commit comments