1""" 2Test lldb-dap completions request 3""" 4 5import re 6 7import lldbdap_testcase 8import dap_server 9from lldbsuite.test import lldbutil 10from lldbsuite.test.decorators import * 11from lldbsuite.test.lldbtest import * 12 13 14class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase): 15 def assertEvaluate(self, expression, regex): 16 self.assertRegex( 17 self.dap_server.request_evaluate(expression, context=self.context)["body"][ 18 "result" 19 ], 20 regex, 21 ) 22 23 def assertEvaluateFailure(self, expression): 24 self.assertNotIn( 25 "result", 26 self.dap_server.request_evaluate(expression, context=self.context)["body"], 27 ) 28 29 def isResultExpandedDescription(self): 30 return self.context == "repl" 31 32 def isExpressionParsedExpected(self): 33 return self.context != "hover" 34 35 def run_test_evaluate_expressions( 36 self, context=None, enableAutoVariableSummaries=False 37 ): 38 """ 39 Tests the evaluate expression request at different breakpoints 40 """ 41 self.context = context 42 program = self.getBuildArtifact("a.out") 43 self.build_and_launch( 44 program, enableAutoVariableSummaries=enableAutoVariableSummaries 45 ) 46 source = "main.cpp" 47 self.set_source_breakpoints( 48 source, 49 [ 50 line_number(source, "// breakpoint 1"), 51 line_number(source, "// breakpoint 2"), 52 line_number(source, "// breakpoint 3"), 53 line_number(source, "// breakpoint 4"), 54 line_number(source, "// breakpoint 5"), 55 line_number(source, "// breakpoint 6"), 56 line_number(source, "// breakpoint 7"), 57 line_number(source, "// breakpoint 8"), 58 ], 59 ) 60 self.continue_to_next_stop() 61 62 # Expressions at breakpoint 1, which is in main 63 self.assertEvaluate("var1", "20") 64 # Empty expression should equate to the previous expression. 65 if context == "repl": 66 self.assertEvaluate("", "20") 67 else: 68 self.assertEvaluateFailure("") 69 self.assertEvaluate("var2", "21") 70 if context == "repl": 71 self.assertEvaluate("", "21") 72 self.assertEvaluate("", "21") 73 self.assertEvaluate("static_int", "42") 74 self.assertEvaluate("non_static_int", "43") 75 self.assertEvaluate("struct1.foo", "15") 76 self.assertEvaluate("struct2->foo", "16") 77 78 if self.isResultExpandedDescription(): 79 self.assertEvaluate( 80 "struct1", 81 r"\(my_struct\) (struct1|\$\d+) = \(foo = 15\)", 82 ) 83 self.assertEvaluate("struct2", r"\(my_struct \*\) (struct2|\$\d+) = 0x.*") 84 self.assertEvaluate( 85 "struct3", r"\(my_struct \*\) (struct3|\$\d+) = nullptr" 86 ) 87 else: 88 self.assertEvaluate( 89 "struct1", 90 ( 91 re.escape("{foo:15}") 92 if enableAutoVariableSummaries 93 else "my_struct @ 0x" 94 ), 95 ) 96 self.assertEvaluate( 97 "struct2", "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*" 98 ) 99 self.assertEvaluate("struct3", "0x.*0") 100 101 if context == "repl": 102 # In the repl context expressions may be interpreted as lldb 103 # commands since no variables have the same name as the command. 104 self.assertEvaluate("list", r"\(lldb\) list\n.*") 105 else: 106 self.assertEvaluateFailure("list") # local variable of a_function 107 108 self.assertEvaluateFailure("my_struct") # type name 109 self.assertEvaluateFailure("int") # type name 110 self.assertEvaluateFailure("foo") # member of my_struct 111 112 if self.isExpressionParsedExpected(): 113 self.assertEvaluate("a_function", "0x.*a.out`a_function.*") 114 self.assertEvaluate("a_function(1)", "1") 115 self.assertEvaluate("var2 + struct1.foo", "36") 116 self.assertEvaluate("foo_func", "0x.*a.out`foo_func.*") 117 self.assertEvaluate("foo_var", "44") 118 else: 119 self.assertEvaluateFailure("a_function") 120 self.assertEvaluateFailure("a_function(1)") 121 self.assertEvaluateFailure("var2 + struct1.foo") 122 self.assertEvaluateFailure("foo_func") 123 self.assertEvaluateFailure("foo_var") 124 125 # Expressions at breakpoint 2, which is an anonymous block 126 self.continue_to_next_stop() 127 self.assertEvaluate("var1", "20") 128 self.assertEvaluate("var2", "2") # different variable with the same name 129 self.assertEvaluate("static_int", "42") 130 self.assertEvaluate( 131 "non_static_int", "10" 132 ) # different variable with the same name 133 if self.isResultExpandedDescription(): 134 self.assertEvaluate( 135 "struct1", 136 r"\(my_struct\) (struct1|\$\d+) = \(foo = 15\)", 137 ) 138 else: 139 self.assertEvaluate( 140 "struct1", 141 ( 142 re.escape("{foo:15}") 143 if enableAutoVariableSummaries 144 else "my_struct @ 0x" 145 ), 146 ) 147 self.assertEvaluate("struct1.foo", "15") 148 self.assertEvaluate("struct2->foo", "16") 149 150 if self.isExpressionParsedExpected(): 151 self.assertEvaluate("a_function", "0x.*a.out`a_function.*") 152 self.assertEvaluate("a_function(1)", "1") 153 self.assertEvaluate("var2 + struct1.foo", "17") 154 self.assertEvaluate("foo_func", "0x.*a.out`foo_func.*") 155 self.assertEvaluate("foo_var", "44") 156 else: 157 self.assertEvaluateFailure("a_function") 158 self.assertEvaluateFailure("a_function(1)") 159 self.assertEvaluateFailure("var2 + struct1.foo") 160 self.assertEvaluateFailure("foo_func") 161 self.assertEvaluateFailure("foo_var") 162 163 # Expressions at breakpoint 3, which is inside a_function 164 self.continue_to_next_stop() 165 self.assertEvaluate("list", "42") 166 self.assertEvaluate("static_int", "42") 167 self.assertEvaluate("non_static_int", "43") 168 169 self.assertEvaluateFailure("var1") 170 self.assertEvaluateFailure("var2") 171 self.assertEvaluateFailure("struct1") 172 self.assertEvaluateFailure("struct1.foo") 173 self.assertEvaluateFailure("struct2->foo") 174 self.assertEvaluateFailure("var2 + struct1.foo") 175 176 if self.isExpressionParsedExpected(): 177 self.assertEvaluate("a_function", "0x.*a.out`a_function.*") 178 self.assertEvaluate("a_function(1)", "1") 179 self.assertEvaluate("list + 1", "43") 180 self.assertEvaluate("foo_func", "0x.*a.out`foo_func.*") 181 self.assertEvaluate("foo_var", "44") 182 else: 183 self.assertEvaluateFailure("a_function") 184 self.assertEvaluateFailure("a_function(1)") 185 self.assertEvaluateFailure("list + 1") 186 self.assertEvaluateFailure("foo_func") 187 self.assertEvaluateFailure("foo_var") 188 189 # Now we check that values are updated after stepping 190 self.continue_to_next_stop() 191 self.assertEvaluate("my_vec", "size=2") 192 self.continue_to_next_stop() 193 self.assertEvaluate("my_vec", "size=3") 194 195 self.assertEvaluate("my_map", "size=2") 196 self.continue_to_next_stop() 197 self.assertEvaluate("my_map", "size=3") 198 199 self.assertEvaluate("my_bool_vec", "size=1") 200 self.continue_to_next_stop() 201 self.assertEvaluate("my_bool_vec", "size=2") 202 203 # Test memory read, especially with 'empty' repeat commands. 204 if context == "repl": 205 self.continue_to_next_stop() 206 self.assertEvaluate("memory read -c 1 &my_ints", ".* 05 .*\n") 207 self.assertEvaluate("", ".* 0a .*\n") 208 self.assertEvaluate("", ".* 0f .*\n") 209 self.assertEvaluate("", ".* 14 .*\n") 210 self.assertEvaluate("", ".* 19 .*\n") 211 212 @skipIfWindows 213 def test_generic_evaluate_expressions(self): 214 # Tests context-less expression evaluations 215 self.run_test_evaluate_expressions(enableAutoVariableSummaries=False) 216 217 @skipIfWindows 218 def test_repl_evaluate_expressions(self): 219 # Tests expression evaluations that are triggered from the Debug Console 220 self.run_test_evaluate_expressions("repl", enableAutoVariableSummaries=False) 221 222 @skipIfWindows 223 def test_watch_evaluate_expressions(self): 224 # Tests expression evaluations that are triggered from a watch expression 225 self.run_test_evaluate_expressions("watch", enableAutoVariableSummaries=True) 226 227 @skipIfWindows 228 def test_hover_evaluate_expressions(self): 229 # Tests expression evaluations that are triggered when hovering on the editor 230 self.run_test_evaluate_expressions("hover", enableAutoVariableSummaries=False) 231 232 @skipIfWindows 233 def test_variable_evaluate_expressions(self): 234 # Tests expression evaluations that are triggered in the variable explorer 235 self.run_test_evaluate_expressions("variable", enableAutoVariableSummaries=True) 236