aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.dap/scopes.exp
blob: aa3bb688c0e85f0492b578b40f3d235a1a4fb95f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# Copyright 2023-2024 Free Software Foundation, Inc.

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# Test "scopes" and "variables".

require allow_dap_tests

load_lib dap-support.exp

standard_testfile

if {[build_executable ${testfile}.exp $testfile] == -1} {
    return
}

if {[dap_initialize] == ""} {
    return
}

set line [gdb_get_line_number "BREAK"]
set obj [dap_check_request_and_response "set breakpoint by line number" \
	     setBreakpoints \
	     [format {o source [o path [%s]] breakpoints [a [o line [i %d]]]} \
		  [list s $srcfile] $line]]
set line_bpno [dap_get_breakpoint_number $obj]

dap_check_request_and_response "configurationDone" configurationDone

if {[dap_launch $testfile] == ""} {
    return
}
dap_wait_for_event_and_check "inferior started" thread "body reason" started

dap_wait_for_event_and_check "stopped at line breakpoint" stopped \
    "body reason" breakpoint \
    "body hitBreakpointIds" $line_bpno

set bt [lindex [dap_check_request_and_response "backtrace" stackTrace \
		    {o threadId [i 1]}] \
	    0]
set frame_id [dict get [lindex [dict get $bt body stackFrames] 0] id]

set scopes [dap_check_request_and_response "get scopes" scopes \
		[format {o frameId [i %d]} $frame_id]]
set scopes [dict get [lindex $scopes 0] body scopes]

# Request the scopes twice, and verify that the results are identical.
# GDB previously had a bug where it would return new scopes each time.
set scopes2 [dap_check_request_and_response "get scopes again" scopes \
		 [format {o frameId [i %d]} $frame_id]]
set scopes2 [dict get [lindex $scopes2 0] body scopes]
gdb_assert {$scopes2 == $scopes} "identical scopes requests yield same body"

gdb_assert {[llength $scopes] == 2} "two scopes"

lassign $scopes scope reg_scope
gdb_assert {[dict get $scope name] == "Locals"} "scope is locals"
gdb_assert {[dict get $scope presentationHint] == "locals"} \
    "locals presentation hint"
gdb_assert {[dict get $scope namedVariables] == 3} "three vars in scope"

gdb_assert {[dict get $reg_scope name] == "Registers"} \
    "second scope is registers"
gdb_assert {[dict get $reg_scope presentationHint] == "registers"} \
    "registers presentation hint"
gdb_assert {[dict get $reg_scope namedVariables] > 0} "at least one register"

set num [dict get $scope variablesReference]
# Send two requests and combine them, to verify that using a range
# works.
set refs1 [lindex [dap_check_request_and_response "fetch variables 0,1" \
		       "variables" \
		       [format {o variablesReference [i %d] count [i 2]} \
			    $num]] \
	       0]
set refs2 [lindex [dap_check_request_and_response "fetch variables 2" \
		       "variables" \
		       [format {o variablesReference [i %d] \
				    start [i 2] count [i 1]} \
			    $num]] \
	       0]

set vars [concat [dict get $refs1 body variables] \
	      [dict get $refs2 body variables]]
foreach var $vars {
    set name [dict get $var name]

    if {$name != "dei"} {
	gdb_assert {[dict get $var variablesReference] == 0} \
	    "$name has no structure"
    }

    switch $name {
	"inner" {
	    gdb_assert {[string match "*inner block*" [dict get $var value]]} \
		"check value of inner"
	}
	"dei" {
	    gdb_assert {[dict get $var value] == ""} "check value of dei"
	    set dei_ref [dict get $var variablesReference]
	}
	"scalar" {
	    gdb_assert {[dict get $var value] == 23} "check value of scalar"
	}
	default {
	    fail "unknown variable $name"
	}
    }
}

set refs [lindex [dap_check_request_and_response "fetch contents of dei" \
		      "variables" \
		      [format {o variablesReference [i %d]} $dei_ref]] \
	      0]
set deivals [dict get $refs body variables]
gdb_assert {[llength $deivals] == 2} "dei has two members"

set num [dict get $reg_scope variablesReference]
# The request succeeding is sufficient.
set val [dap_check_request_and_response "fetch first register" \
	     "variables" \
	     [format {o variablesReference [i %d] count [i 1]} $num]]

# Try setting the value to something else.
set val [dict get [lindex $val 0] body variables]
set name [dict get [lindex $val 0] name]
set val [dict get [lindex $val 0] value]
# Just make sure it is different from the original value.
set val [expr {$val ^ 7}]

# setVariable isn't implemented yet, so use the register name.  Note
# that we sneak the "$" into the name, written in a slightly funny way
# to work around apparent TON limitations.
set response [dap_check_request_and_response "set first register" \
		  setExpression \
		  [format {o expression [s \$%s] value [s %d] frameId [i %d]} \
		       $name $val $frame_id]]
set response [lindex $response 0]

gdb_assert {[dict get $response body value] == $val} \
    "setting register yields updated value"

dap_shutdown