@@ -597,24 +597,32 @@ func TestPreSetBreakpoint(t *testing.T) {
597
597
})
598
598
}
599
599
600
- // checkStackFrames is a helper for verifying the values within StackTraceResponse.
600
+ // checkStackFramesExact is a helper for verifying the values within StackTraceResponse.
601
601
// wantStartName - name of the first returned frame (ignored if "")
602
602
// wantStartLine - file line of the first returned frame (ignored if <0).
603
603
// wantStartID - id of the first frame returned (ignored if wantFrames is 0).
604
604
// wantFrames - number of frames returned (length of StackTraceResponse.Body.StackFrames array).
605
605
// wantTotalFrames - total number of stack frames available (StackTraceResponse.Body.TotalFrames).
606
- func checkStackFrames (t * testing.T , got * dap.StackTraceResponse ,
606
+ func checkStackFramesExact (t * testing.T , got * dap.StackTraceResponse ,
607
607
wantStartName string , wantStartLine , wantStartID , wantFrames , wantTotalFrames int ) {
608
608
t .Helper ()
609
- checkStackFramesNamed ("" , t , got , wantStartName , wantStartLine , wantStartID , wantFrames , wantTotalFrames )
609
+ checkStackFramesNamed ("" , t , got , wantStartName , wantStartLine , wantStartID , wantFrames , wantTotalFrames , true )
610
610
}
611
611
612
- func checkStackFramesNamed ( testName string , t * testing.T , got * dap.StackTraceResponse ,
612
+ func checkStackFramesHasMore ( t * testing.T , got * dap.StackTraceResponse ,
613
613
wantStartName string , wantStartLine , wantStartID , wantFrames , wantTotalFrames int ) {
614
614
t .Helper ()
615
- if got .Body .TotalFrames != wantTotalFrames {
615
+ checkStackFramesNamed ("" , t , got , wantStartName , wantStartLine , wantStartID , wantFrames , wantTotalFrames , false )
616
+ }
617
+ func checkStackFramesNamed (testName string , t * testing.T , got * dap.StackTraceResponse ,
618
+ wantStartName string , wantStartLine , wantStartID , wantFrames , wantTotalFrames int , totalExact bool ) {
619
+ t .Helper ()
620
+ if totalExact && got .Body .TotalFrames != wantTotalFrames {
616
621
t .Errorf ("%s\n got %#v\n want TotalFrames=%d" , testName , got .Body .TotalFrames , wantTotalFrames )
622
+ } else if ! totalExact && got .Body .TotalFrames < wantTotalFrames {
623
+ t .Errorf ("%s\n got %#v\n want TotalFrames>=%d" , testName , got .Body .TotalFrames , wantTotalFrames )
617
624
}
625
+
618
626
if len (got .Body .StackFrames ) != wantFrames {
619
627
t .Errorf ("%s\n got len(StackFrames)=%d\n want %d" , testName , len (got .Body .StackFrames ), wantFrames )
620
628
} else {
@@ -812,10 +820,9 @@ func TestStackTraceRequest(t *testing.T) {
812
820
// repeated requests at the same breakpoint
813
821
// would assign next block of unique ids to them each time.
814
822
const NumFrames = 6
815
- reqIndex := - 1
816
- frameID := func (frameIndex int ) int {
817
- reqIndex ++
818
- return startHandle + NumFrames * reqIndex + frameIndex
823
+ reqIndex := 0
824
+ frameID := func () int {
825
+ return startHandle + reqIndex
819
826
}
820
827
821
828
tests := map [string ]struct {
@@ -826,24 +833,102 @@ func TestStackTraceRequest(t *testing.T) {
826
833
wantStartFrame int
827
834
wantFramesReturned int
828
835
wantFramesAvailable int
836
+ exact bool
829
837
}{
830
- "all frame levels from 0 to NumFrames" : {0 , NumFrames , "main.Increment" , 8 , 0 , NumFrames , NumFrames },
831
- "subset of frames from 1 to -1" : {1 , NumFrames - 1 , "main.Increment" , 11 , 1 , NumFrames - 1 , NumFrames },
832
- "load stack in pages: first half" : {0 , NumFrames / 2 , "main.Increment" , 8 , 0 , NumFrames / 2 , NumFrames },
833
- "load stack in pages: second half" : {NumFrames / 2 , NumFrames , "main.main" , 17 , NumFrames / 2 , NumFrames / 2 , NumFrames },
834
- "zero levels means all levels" : {0 , 0 , "main.Increment" , 8 , 0 , NumFrames , NumFrames },
835
- "zero levels means all remaining levels" : {NumFrames / 2 , 0 , "main.main" , 17 , NumFrames / 2 , NumFrames / 2 , NumFrames },
836
- "negative levels treated as 0 (all)" : {0 , - 10 , "main.Increment" , 8 , 0 , NumFrames , NumFrames },
837
- "OOB levels is capped at available len" : {0 , NumFrames + 1 , "main.Increment" , 8 , 0 , NumFrames , NumFrames },
838
- "OOB levels is capped at available len 1" : {1 , NumFrames + 1 , "main.Increment" , 11 , 1 , NumFrames - 1 , NumFrames },
839
- "negative startFrame treated as 0" : {- 10 , 0 , "main.Increment" , 8 , 0 , NumFrames , NumFrames },
840
- "OOB startFrame returns empty trace" : {NumFrames , 0 , "main.Increment" , - 1 , - 1 , 0 , NumFrames },
838
+ "all frame levels from 0 to NumFrames" : {0 , NumFrames , "main.Increment" , 8 , 0 , NumFrames , NumFrames , true },
839
+ "subset of frames from 1 to -1" : {1 , NumFrames - 1 , "main.Increment" , 11 , 1 , NumFrames - 1 , NumFrames , true },
840
+ "load stack in pages: first half" : {0 , NumFrames / 2 , "main.Increment" , 8 , 0 , NumFrames / 2 , NumFrames , false },
841
+ "load stack in pages: second half" : {NumFrames / 2 , NumFrames , "main.main" , 17 , NumFrames / 2 , NumFrames / 2 , NumFrames , true },
842
+ "zero levels means all levels" : {0 , 0 , "main.Increment" , 8 , 0 , NumFrames , NumFrames , true },
843
+ "zero levels means all remaining levels" : {NumFrames / 2 , 0 , "main.main" , 17 , NumFrames / 2 , NumFrames / 2 , NumFrames , true },
844
+ "negative levels treated as 0 (all)" : {0 , - 10 , "main.Increment" , 8 , 0 , NumFrames , NumFrames , true },
845
+ "OOB levels is capped at available len" : {0 , NumFrames + 1 , "main.Increment" , 8 , 0 , NumFrames , NumFrames , true },
846
+ "OOB levels is capped at available len 1" : {1 , NumFrames + 1 , "main.Increment" , 11 , 1 , NumFrames - 1 , NumFrames , true },
847
+ "negative startFrame treated as 0" : {- 10 , 0 , "main.Increment" , 8 , 0 , NumFrames , NumFrames , true },
848
+ "OOB startFrame returns empty trace" : {NumFrames , 0 , "main.Increment" , - 1 , - 1 , 0 , NumFrames , true },
841
849
}
842
850
for name , tc := range tests {
843
851
client .StackTraceRequest (1 , tc .startFrame , tc .levels )
844
852
stResp = client .ExpectStackTraceResponse (t )
845
853
checkStackFramesNamed (name , t , stResp ,
846
- tc .wantStartName , tc .wantStartLine , frameID (tc .wantStartFrame ), tc .wantFramesReturned , tc .wantFramesAvailable )
854
+ tc .wantStartName , tc .wantStartLine , frameID (), tc .wantFramesReturned , tc .wantFramesAvailable , tc .exact )
855
+ reqIndex += len (stResp .Body .StackFrames )
856
+ }
857
+ },
858
+ disconnect : false ,
859
+ }, {
860
+ // Stop at line 18
861
+ execute : func () {
862
+ // Frame ids get reset at each breakpoint.
863
+ client .StackTraceRequest (1 , 0 , 0 )
864
+ stResp = client .ExpectStackTraceResponse (t )
865
+ checkStackFramesExact (t , stResp , "main.main" , 18 , startHandle , 3 , 3 )
866
+ },
867
+ disconnect : false ,
868
+ }})
869
+ })
870
+ runTest (t , "increment" , func (client * daptest.Client , fixture protest.Fixture ) {
871
+ var stResp * dap.StackTraceResponse
872
+ runDebugSessionWithBPs (t , client , "launch" ,
873
+ // Launch
874
+ func () {
875
+ client .LaunchRequest ("exec" , fixture .Path , ! stopOnEntry )
876
+ },
877
+ // Set breakpoints
878
+ fixture .Source , []int {8 , 18 },
879
+ []onBreakpoint {{
880
+ // Stop at line 8
881
+ execute : func () {
882
+ // Even though the stack frames do not change,
883
+ // repeated requests at the same breakpoint
884
+ // would assign next block of unique ids to them each time.
885
+ const NumFrames = 6
886
+
887
+ var frames []dap.StackFrame
888
+
889
+ for start , levels := 0 , 1 ; start < NumFrames ; {
890
+ client .StackTraceRequest (1 , start , levels )
891
+ stResp = client .ExpectStackTraceResponse (t )
892
+ frames = append (frames , stResp .Body .StackFrames ... )
893
+ if stResp .Body .TotalFrames < NumFrames {
894
+ t .Errorf ("got %#v\n want TotalFrames>=%d\n " , stResp .Body .TotalFrames , NumFrames )
895
+ }
896
+
897
+ if len (stResp .Body .StackFrames ) < levels {
898
+ t .Errorf ("got len(StackFrames)=%d\n want >=%d\n " , len (stResp .Body .StackFrames ), levels )
899
+ }
900
+
901
+ start += len (stResp .Body .StackFrames )
902
+ }
903
+
904
+ // TODO check all the frames.
905
+ want := []struct {
906
+ wantName string
907
+ wantLine int
908
+ }{
909
+ {"main.Increment" , 8 },
910
+ {"main.Increment" , 11 },
911
+ {"main.Increment" , 11 },
912
+ {"main.main" , 17 },
913
+ {"runtime.main" , 0 },
914
+ {"runtime.goexit" , 0 },
915
+ }
916
+ for i , frame := range frames {
917
+ frameId := startHandle + i
918
+ if frame .Id != frameId {
919
+ t .Errorf ("got %#v\n want Id=%d\n " , frame , frameId )
920
+ }
921
+
922
+ // Verify the name and line corresponding to the first returned frame (if any).
923
+ // This is useful when the first frame is the frame corresponding to the breakpoint at
924
+ // a predefined line. Line values < 0 are a signal to skip the check (which can be useful
925
+ // for frames in the third-party code, where we do not control the lines).
926
+ if want [i ].wantLine > 0 && frame .Line != want [i ].wantLine {
927
+ t .Errorf ("got Line=%d\n want %d\n " , frame .Line , want [i ].wantLine )
928
+ }
929
+ if want [i ].wantName != "" && frame .Name != want [i ].wantName {
930
+ t .Errorf ("got Name=%s\n want %s\n " , frame .Name , want [i ].wantName )
931
+ }
847
932
}
848
933
},
849
934
disconnect : false ,
@@ -853,7 +938,7 @@ func TestStackTraceRequest(t *testing.T) {
853
938
// Frame ids get reset at each breakpoint.
854
939
client .StackTraceRequest (1 , 0 , 0 )
855
940
stResp = client .ExpectStackTraceResponse (t )
856
- checkStackFrames (t , stResp , "main.main" , 18 , startHandle , 3 , 3 )
941
+ checkStackFramesExact (t , stResp , "main.main" , 18 , startHandle , 3 , 3 )
857
942
},
858
943
disconnect : false ,
859
944
}})
@@ -887,7 +972,7 @@ func TestScopesAndVariablesRequests(t *testing.T) {
887
972
startLineno = - 1
888
973
}
889
974
890
- checkStackFrames (t , stack , "main.foobar" , startLineno , 1000 , 4 , 4 )
975
+ checkStackFramesExact (t , stack , "main.foobar" , startLineno , 1000 , 4 , 4 )
891
976
892
977
client .ScopesRequest (1000 )
893
978
scopes := client .ExpectScopesResponse (t )
@@ -1101,7 +1186,7 @@ func TestScopesAndVariablesRequests(t *testing.T) {
1101
1186
// Frame ids get reset at each breakpoint.
1102
1187
client .StackTraceRequest (1 , 0 , 20 )
1103
1188
stack := client .ExpectStackTraceResponse (t )
1104
- checkStackFrames (t , stack , "main.barfoo" , 27 , 1000 , 5 , 5 )
1189
+ checkStackFramesExact (t , stack , "main.barfoo" , 27 , 1000 , 5 , 5 )
1105
1190
1106
1191
client .ScopesRequest (1000 )
1107
1192
scopes := client .ExpectScopesResponse (t )
@@ -1154,7 +1239,7 @@ func TestScopesAndVariablesRequests2(t *testing.T) {
1154
1239
execute : func () {
1155
1240
client .StackTraceRequest (1 , 0 , 20 )
1156
1241
stack := client .ExpectStackTraceResponse (t )
1157
- checkStackFrames (t , stack , "main.main" , - 1 , 1000 , 3 , 3 )
1242
+ checkStackFramesExact (t , stack , "main.main" , - 1 , 1000 , 3 , 3 )
1158
1243
1159
1244
client .ScopesRequest (1000 )
1160
1245
scopes := client .ExpectScopesResponse (t )
@@ -1166,7 +1251,7 @@ func TestScopesAndVariablesRequests2(t *testing.T) {
1166
1251
execute : func () {
1167
1252
client .StackTraceRequest (1 , 0 , 20 )
1168
1253
stack := client .ExpectStackTraceResponse (t )
1169
- checkStackFrames (t , stack , "main.main" , - 1 , 1000 , 3 , 3 )
1254
+ checkStackFramesExact (t , stack , "main.main" , - 1 , 1000 , 3 , 3 )
1170
1255
1171
1256
client .ScopesRequest (1000 )
1172
1257
scopes := client .ExpectScopesResponse (t )
@@ -1439,7 +1524,7 @@ func TestScopesRequestsOptimized(t *testing.T) {
1439
1524
startLineno = - 1
1440
1525
}
1441
1526
1442
- checkStackFrames (t , stack , "main.foobar" , startLineno , 1000 , 4 , 4 )
1527
+ checkStackFramesExact (t , stack , "main.foobar" , startLineno , 1000 , 4 , 4 )
1443
1528
1444
1529
client .ScopesRequest (1000 )
1445
1530
scopes := client .ExpectScopesResponse (t )
@@ -1454,7 +1539,7 @@ func TestScopesRequestsOptimized(t *testing.T) {
1454
1539
// Frame ids get reset at each breakpoint.
1455
1540
client .StackTraceRequest (1 , 0 , 20 )
1456
1541
stack := client .ExpectStackTraceResponse (t )
1457
- checkStackFrames (t , stack , "main.barfoo" , 27 , 1000 , 5 , 5 )
1542
+ checkStackFramesExact (t , stack , "main.barfoo" , 27 , 1000 , 5 , 5 )
1458
1543
1459
1544
client .ScopesRequest (1000 )
1460
1545
scopes := client .ExpectScopesResponse (t )
@@ -1904,7 +1989,7 @@ func TestGlobalScopeAndVariables(t *testing.T) {
1904
1989
execute : func () {
1905
1990
client .StackTraceRequest (1 , 0 , 20 )
1906
1991
stack := client .ExpectStackTraceResponse (t )
1907
- checkStackFrames (t , stack , "main.main" , 36 , 1000 , 3 , 3 )
1992
+ checkStackFramesExact (t , stack , "main.main" , 36 , 1000 , 3 , 3 )
1908
1993
1909
1994
client .ScopesRequest (1000 )
1910
1995
scopes := client .ExpectScopesResponse (t )
@@ -1926,7 +2011,7 @@ func TestGlobalScopeAndVariables(t *testing.T) {
1926
2011
1927
2012
client .StackTraceRequest (1 , 0 , 20 )
1928
2013
stack = client .ExpectStackTraceResponse (t )
1929
- checkStackFrames (t , stack , "" , 13 , 1000 , 4 , 4 )
2014
+ checkStackFramesExact (t , stack , "" , 13 , 1000 , 4 , 4 )
1930
2015
1931
2016
client .ScopesRequest (1000 )
1932
2017
scopes = client .ExpectScopesResponse (t )
@@ -1970,7 +2055,7 @@ func TestShadowedVariables(t *testing.T) {
1970
2055
execute : func () {
1971
2056
client .StackTraceRequest (1 , 0 , 20 )
1972
2057
stack := client .ExpectStackTraceResponse (t )
1973
- checkStackFrames (t , stack , "main.main" , 13 , 1000 , 3 , 3 )
2058
+ checkStackFramesExact (t , stack , "main.main" , 13 , 1000 , 3 , 3 )
1974
2059
1975
2060
client .ScopesRequest (1000 )
1976
2061
scopes := client .ExpectScopesResponse (t )
@@ -2010,7 +2095,7 @@ func TestLaunchRequestWithStackTraceDepth(t *testing.T) {
2010
2095
execute : func () {
2011
2096
client .StackTraceRequest (1 , 0 , 0 )
2012
2097
stResp = client .ExpectStackTraceResponse (t )
2013
- checkStackFrames (t , stResp , "main.Increment" , 8 , 1000 , 2 /*returned*/ , 2 /*available*/ )
2098
+ checkStackFramesHasMore (t , stResp , "main.Increment" , 8 , 1000 , 1 /*returned*/ , 2 /*available*/ )
2014
2099
},
2015
2100
disconnect : false ,
2016
2101
}})
0 commit comments