@@ -18,6 +18,7 @@ import {
1818import { CdtDebugClient } from './debugClient' ;
1919import {
2020 fillDefaults ,
21+ gdbAsync ,
2122 gdbNonStop ,
2223 isRemoteTest ,
2324 standardBeforeEach ,
@@ -33,6 +34,7 @@ describe('launch', function () {
3334 const unicodeProgram = path . join ( testProgramsDir , 'bug275-测试' ) ;
3435 // the name of this file is short enough to work around https://sourceware.org/bugzilla/show_bug.cgi?id=30618
3536 const unicodeSrc = path . join ( testProgramsDir , 'bug275-测试.c' ) ;
37+ const loopForeverProgram = path . join ( testProgramsDir , 'loopforever' ) ;
3638
3739 beforeEach ( async function ( ) {
3840 dc = await standardBeforeEach ( ) ;
@@ -54,6 +56,63 @@ describe('launch', function () {
5456 ) ;
5557 } ) ;
5658
59+ function makeRunArgTest ( runArg : string ) {
60+ return async function ( this : Mocha . Context ) {
61+ // This tests both local and remote cases and does not need to be
62+ // duplicated in launchRemote.spec.ts (beforeEach and afterEach are
63+ // similar enough here and there).
64+ if (
65+ ( ! gdbAsync || ( isRemoteTest && ! gdbNonStop ) ) &&
66+ runArg === 'always'
67+ ) {
68+ // in sync mode when all threads are running we can't ask '-thread-info'
69+ // (remote needs non-stop to be really async)
70+ this . skip ( ) ;
71+ }
72+
73+ const launchArgs = fillDefaults ( this . test , {
74+ program : loopForeverProgram ,
75+ run : runArg ,
76+ } as LaunchRequestArguments ) ;
77+
78+ await Promise . all ( [
79+ dc
80+ . waitForEvent ( 'initialized' )
81+ . then ( ( ) => dc . configurationDoneRequest ( ) ) ,
82+ dc . initializeRequest ( ) . then ( ( ) => dc . launchRequest ( launchArgs ) ) ,
83+ ] ) ;
84+
85+ const threadInfo = JSON . parse (
86+ (
87+ await dc . evaluateRequest ( {
88+ expression : '>-thread-info' ,
89+ context : 'repl' ,
90+ } )
91+ ) . body . result
92+ ) ;
93+ const threadStates = threadInfo . threads . map ( ( t : any ) => t . state ) ;
94+ if ( runArg === 'always' ) {
95+ expect ( threadStates ) . to . contain ( 'running' ) ;
96+ expect ( threadStates ) . not . to . contain ( 'stopped' ) ;
97+ } else if ( runArg === 'preserve' ) {
98+ if ( isRemoteTest ) {
99+ // GDBTargetDebugSession interprets "launch" as "launch
100+ // gdbserver", not "launch the program", so this case actually
101+ // behaves like an attach, not like a launch.
102+ expect ( threadStates ) . to . contain ( 'stopped' ) ;
103+ } else {
104+ // GDBDebugSessionBase implements "launch" as expected.
105+ expect ( threadStates ) . to . be . an ( 'array' ) . that . is . empty ;
106+ }
107+ } else {
108+ expect ( runArg ) . to . be . oneOf ( [ 'always' , 'preserve' ] ) ;
109+ }
110+ } ;
111+ }
112+
113+ it ( 'can launch and run' , makeRunArgTest ( 'always' ) ) ;
114+ it ( 'can launch without running' , makeRunArgTest ( 'preserve' ) ) ;
115+
57116 it ( 'receives an error when no port is provided nor a suitable regex' , async function ( ) {
58117 if ( ! isRemoteTest ) {
59118 this . skip ( ) ;
0 commit comments