@@ -1525,6 +1525,126 @@ const testAll = (isDlvDap: boolean) => {
1525
1525
} ) ;
1526
1526
} ) ;
1527
1527
1528
+ suite ( 'switch goroutine' , ( ) => {
1529
+ async function runSwitchGoroutineTest ( stepFunction : string ) {
1530
+ const PROGRAM = path . join ( DATA_ROOT , 'goroutineTest' ) ;
1531
+ const FILE = path . join ( PROGRAM , 'main.go' ) ;
1532
+ const BREAKPOINT_LINE = 14 ;
1533
+
1534
+ const config = {
1535
+ name : 'Launch' ,
1536
+ type : 'go' ,
1537
+ request : 'launch' ,
1538
+ mode : 'debug' ,
1539
+ program : PROGRAM
1540
+ } ;
1541
+ const debugConfig = await initializeDebugConfig ( config ) ;
1542
+ await dc . hitBreakpoint ( debugConfig , getBreakpointLocation ( FILE , BREAKPOINT_LINE ) ) ;
1543
+ // Clear breakpoints to make sure they do not interrupt the stepping.
1544
+ const breakpointsResult = await dc . setBreakpointsRequest ( {
1545
+ source : { path : FILE } ,
1546
+ breakpoints : [ ]
1547
+ } ) ;
1548
+ assert . ok ( breakpointsResult . success ) ;
1549
+
1550
+ const threadsResponse = await dc . threadsRequest ( ) ;
1551
+ assert . ok ( threadsResponse . success ) ;
1552
+ const run1Goroutine = threadsResponse . body . threads . find ( ( val ) => val . name . indexOf ( 'main.run1' ) >= 0 ) ;
1553
+ const run2Goroutine = threadsResponse . body . threads . find ( ( val ) => val . name . indexOf ( 'main.run2' ) >= 0 ) ;
1554
+
1555
+ // runStepFunction runs the necessary step function and resolves if it succeeded.
1556
+ async function runStepFunction (
1557
+ args : { threadId : number } ,
1558
+ resolve : ( value : void | PromiseLike < void > ) => void ,
1559
+ reject : ( reason ?: any ) => void
1560
+ ) {
1561
+ const callback = ( resp : any ) => {
1562
+ assert . ok ( resp . success ) ;
1563
+ resolve ( ) ;
1564
+ } ;
1565
+ switch ( stepFunction ) {
1566
+ case 'next' :
1567
+ callback ( await dc . nextRequest ( args ) ) ;
1568
+ break ;
1569
+ case 'step in' :
1570
+ callback ( await dc . stepInRequest ( args ) ) ;
1571
+ break ;
1572
+ case 'step out' :
1573
+ // TODO(suzmue): write a test for step out.
1574
+ reject ( new Error ( 'step out will never complete on this program' ) ) ;
1575
+ break ;
1576
+ default :
1577
+ reject ( new Error ( `not a valid step function ${ stepFunction } ` ) ) ;
1578
+ }
1579
+ }
1580
+
1581
+ // The program is currently stopped on the goroutine in main.run2.
1582
+ // Test switching go routines by stepping in:
1583
+ // 1. main.run2
1584
+ // 2. main.run1 (switch routine)
1585
+ // 3. main.run1
1586
+ // 4. main.run2 (switch routine)
1587
+
1588
+ // Next on the goroutine in main.run2
1589
+ await Promise . all ( [
1590
+ new Promise < void > ( ( resolve , reject ) => {
1591
+ const args = { threadId : run2Goroutine . id } ;
1592
+ return runStepFunction ( args , resolve , reject ) ;
1593
+ } ) ,
1594
+ dc . waitForEvent ( 'stopped' ) . then ( ( event ) => {
1595
+ assert . strictEqual ( event . body . reason , 'step' ) ;
1596
+ assert . strictEqual ( event . body . threadId , run2Goroutine . id ) ;
1597
+ } )
1598
+ ] ) ;
1599
+
1600
+ // Next on the goroutine in main.run1
1601
+ await Promise . all ( [
1602
+ new Promise < void > ( ( resolve , reject ) => {
1603
+ const args = { threadId : run1Goroutine . id } ;
1604
+ return runStepFunction ( args , resolve , reject ) ;
1605
+ } ) ,
1606
+ dc . waitForEvent ( 'stopped' ) . then ( ( event ) => {
1607
+ assert . strictEqual ( event . body . reason , 'step' ) ;
1608
+ assert . strictEqual ( event . body . threadId , run1Goroutine . id ) ;
1609
+ } )
1610
+ ] ) ;
1611
+
1612
+ // Next on the goroutine in main.run1
1613
+ await Promise . all ( [
1614
+ new Promise < void > ( ( resolve , reject ) => {
1615
+ const args = { threadId : run1Goroutine . id } ;
1616
+ return runStepFunction ( args , resolve , reject ) ;
1617
+ } ) ,
1618
+ dc . waitForEvent ( 'stopped' ) . then ( ( event ) => {
1619
+ assert . strictEqual ( event . body . reason , 'step' ) ;
1620
+ assert . strictEqual ( event . body . threadId , run1Goroutine . id ) ;
1621
+ } )
1622
+ ] ) ;
1623
+
1624
+ // Next on the goroutine in main.run2
1625
+ await Promise . all ( [
1626
+ new Promise < void > ( ( resolve , reject ) => {
1627
+ const args = { threadId : run2Goroutine . id } ;
1628
+ return runStepFunction ( args , resolve , reject ) ;
1629
+ } ) ,
1630
+ dc . waitForEvent ( 'stopped' ) . then ( ( event ) => {
1631
+ assert . strictEqual ( event . body . reason , 'step' ) ;
1632
+ assert . strictEqual ( event . body . threadId , run2Goroutine . id ) ;
1633
+ } )
1634
+ ] ) ;
1635
+ }
1636
+
1637
+ test . skip ( 'next' , async ( ) => {
1638
+ // neither debug adapter implements this behavior
1639
+ await runSwitchGoroutineTest ( 'next' ) ;
1640
+ } ) ;
1641
+
1642
+ test . skip ( 'step in' , async ( ) => {
1643
+ // neither debug adapter implements this behavior
1644
+ await runSwitchGoroutineTest ( 'step in' ) ;
1645
+ } ) ;
1646
+ } ) ;
1647
+
1528
1648
suite ( 'substitute path' , ( ) => {
1529
1649
// TODO(suzmue): add unit tests for substitutePath.
1530
1650
let tmpDir : string ;
0 commit comments