Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/dart_api_impl.h" | 5 #include "vm/dart_api_impl.h" |
| 6 #include "vm/dart_api_message.h" | |
| 6 #include "vm/debugger.h" | 7 #include "vm/debugger.h" |
| 8 #include "vm/message.h" | |
| 7 #include "vm/unit_test.h" | 9 #include "vm/unit_test.h" |
| 8 | 10 |
| 9 namespace dart { | 11 namespace dart { |
| 10 | 12 |
| 11 #ifndef PRODUCT | 13 #ifndef PRODUCT |
| 12 | 14 |
| 13 DECLARE_FLAG(bool, remove_script_timestamps_for_test); | 15 DECLARE_FLAG(bool, remove_script_timestamps_for_test); |
| 16 DECLARE_FLAG(bool, trace_rewind); | |
| 14 | 17 |
| 15 // Search for the formatted string in buffer. | 18 // Search for the formatted string in buffer. |
| 16 // | 19 // |
| 17 // TODO(turnidge): This function obscures the line number of failing | 20 // TODO(turnidge): This function obscures the line number of failing |
| 18 // EXPECTs. Rework this. | 21 // EXPECTs. Rework this. |
| 19 static void ExpectSubstringF(const char* buff, const char* fmt, ...) { | 22 static void ExpectSubstringF(const char* buff, const char* fmt, ...) { |
| 20 va_list args; | 23 va_list args; |
| 21 va_start(args, fmt); | 24 va_start(args, fmt); |
| 22 intptr_t len = OS::VSNPrint(NULL, 0, fmt, args); | 25 intptr_t len = OS::VSNPrint(NULL, 0, fmt, args); |
| 23 va_end(args); | 26 va_end(args); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 134 // Set a breakpoint and run. | 137 // Set a breakpoint and run. |
| 135 EXPECT_VALID(Dart_SetBreakpoint(NewString(TestCase::url()), 2)); | 138 EXPECT_VALID(Dart_SetBreakpoint(NewString(TestCase::url()), 2)); |
| 136 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 139 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
| 137 EXPECT_VALID(result); | 140 EXPECT_VALID(result); |
| 138 EXPECT(Dart_IsString(result)); | 141 EXPECT(Dart_IsString(result)); |
| 139 | 142 |
| 140 // We ran the code in InspectPausedEvent. | 143 // We ran the code in InspectPausedEvent. |
| 141 EXPECT(saw_paused_event); | 144 EXPECT(saw_paused_event); |
| 142 } | 145 } |
| 143 | 146 |
| 147 | |
| 148 static uint8_t* malloc_allocator(uint8_t* ptr, | |
| 149 intptr_t old_size, | |
| 150 intptr_t new_size) { | |
| 151 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); | |
| 152 return reinterpret_cast<uint8_t*>(new_ptr); | |
| 153 } | |
| 154 | |
| 155 | |
| 156 const char* rewind_frame_index = "-1"; | |
| 157 | |
| 158 | |
| 159 // Build and send a fake resume OOB message for testing purposes. | |
| 160 void SendResumeMessage(Isolate* isolate) { | |
| 161 // Format is: [ oob_type, port, seq, method_name, [keys], [values] ] | |
| 162 Dart_CObject msg; | |
| 163 Dart_CObject* list_values[6]; | |
| 164 msg.type = Dart_CObject_kArray; | |
| 165 msg.value.as_array.length = 6; | |
| 166 msg.value.as_array.values = list_values; | |
| 167 | |
| 168 Dart_CObject oob; | |
| 169 oob.type = Dart_CObject_kInt32; | |
| 170 oob.value.as_int32 = Message::kServiceOOBMsg; | |
| 171 list_values[0] = &oob; | |
| 172 | |
| 173 Dart_CObject reply_port; | |
| 174 reply_port.type = Dart_CObject_kNull; | |
| 175 list_values[1] = &reply_port; | |
| 176 | |
| 177 Dart_CObject seq; | |
| 178 seq.type = Dart_CObject_kNull; | |
| 179 list_values[2] = &seq; | |
| 180 | |
| 181 Dart_CObject method_name; | |
| 182 method_name.type = Dart_CObject_kString; | |
| 183 method_name.value.as_string = const_cast<char*>("resume"); | |
| 184 list_values[3] = &method_name; | |
| 185 | |
| 186 const int kParamCount = 3; | |
| 187 Dart_CObject param_keys; | |
| 188 Dart_CObject* param_keys_list[kParamCount]; | |
| 189 param_keys.type = Dart_CObject_kArray; | |
| 190 param_keys.value.as_array.values = param_keys_list; | |
| 191 param_keys.value.as_array.length = kParamCount; | |
| 192 list_values[4] = ¶m_keys; | |
| 193 | |
| 194 Dart_CObject param_values; | |
| 195 Dart_CObject* param_values_list[kParamCount]; | |
| 196 param_values.type = Dart_CObject_kArray; | |
| 197 param_values.value.as_array.values = param_values_list; | |
| 198 param_values.value.as_array.length = kParamCount; | |
| 199 list_values[5] = ¶m_values; | |
| 200 | |
| 201 Dart_CObject param0_name; | |
| 202 param0_name.type = Dart_CObject_kString; | |
| 203 param0_name.value.as_string = const_cast<char*>("isolateId"); | |
| 204 param_keys_list[0] = ¶m0_name; | |
| 205 | |
| 206 Dart_CObject param0_value; | |
| 207 param0_value.type = Dart_CObject_kString; | |
| 208 const char* isolate_id = Thread::Current()->zone()->PrintToString( | |
| 209 ISOLATE_SERVICE_ID_FORMAT_STRING, | |
| 210 static_cast<int64_t>(isolate->main_port())); | |
| 211 param0_value.value.as_string = const_cast<char*>(isolate_id); | |
| 212 param_values_list[0] = ¶m0_value; | |
| 213 | |
| 214 Dart_CObject param1_name; | |
| 215 param1_name.type = Dart_CObject_kString; | |
| 216 param1_name.value.as_string = const_cast<char*>("step"); | |
| 217 param_keys_list[1] = ¶m1_name; | |
| 218 | |
| 219 Dart_CObject param1_value; | |
| 220 param1_value.type = Dart_CObject_kString; | |
| 221 param1_value.value.as_string = const_cast<char*>("Rewind"); | |
| 222 param_values_list[1] = ¶m1_value; | |
| 223 | |
| 224 Dart_CObject param2_name; | |
| 225 param2_name.type = Dart_CObject_kString; | |
| 226 param2_name.value.as_string = const_cast<char*>("frameIndex"); | |
| 227 param_keys_list[2] = ¶m2_name; | |
| 228 | |
| 229 Dart_CObject param2_value; | |
| 230 param2_value.type = Dart_CObject_kString; | |
| 231 param2_value.value.as_string = const_cast<char*>(rewind_frame_index); | |
| 232 param_values_list[2] = ¶m2_value; | |
| 233 | |
| 234 { | |
| 235 uint8_t* buffer = NULL; | |
| 236 ApiMessageWriter writer(&buffer, &malloc_allocator); | |
| 237 bool success = writer.WriteCMessage(&msg); | |
| 238 ASSERT(success); | |
| 239 | |
| 240 // Post the message at the given port. | |
| 241 success = PortMap::PostMessage(new Message(isolate->main_port(), buffer, | |
| 242 writer.BytesWritten(), | |
| 243 Message::kOOBPriority)); | |
| 244 ASSERT(success); | |
| 245 } | |
| 246 } | |
| 247 | |
| 248 | |
| 249 static void RewindOnce(Dart_IsolateId isolate_id, | |
| 250 intptr_t bp_id, | |
| 251 const Dart_CodeLocation& loc) { | |
| 252 bool first_time = !saw_paused_event; | |
| 253 saw_paused_event = true; | |
| 254 if (first_time) { | |
| 255 Thread* T = Thread::Current(); | |
| 256 Isolate* I = T->isolate(); | |
| 257 I->set_is_runnable(true); | |
|
rmacnak
2017/01/31 19:21:00
Weird.
turnidge
2017/01/31 19:35:46
Added a TODO
| |
| 258 SendResumeMessage(I); | |
| 259 I->PauseEventHandler(); | |
| 260 } | |
| 261 } | |
| 262 | |
| 263 | |
| 264 TEST_CASE(Debugger_RewindOneFrame_Unoptimized) { | |
| 265 SetFlagScope<bool> sfs(&FLAG_trace_rewind, true); | |
| 266 saw_paused_event = false; | |
| 267 rewind_frame_index = "1"; | |
| 268 | |
| 269 const char* kScriptChars = | |
| 270 "import 'dart:developer';\n" | |
| 271 "\n" | |
| 272 "var msg = new StringBuffer();\n" | |
| 273 "\n" | |
| 274 "foo() {\n" | |
| 275 " msg.write('enter(foo) ');\n" | |
| 276 " debugger();\n" | |
| 277 " msg.write('exit(foo) ');\n" | |
| 278 "}\n" | |
| 279 "\n" | |
| 280 "main() {\n" | |
| 281 " msg.write('enter(main) ');\n" | |
| 282 " foo();\n" | |
| 283 " msg.write('exit(main) ');\n" | |
| 284 " return msg.toString();\n" | |
| 285 "}\n"; | |
| 286 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | |
| 287 EXPECT_VALID(lib); | |
| 288 | |
| 289 Dart_SetPausedEventHandler(RewindOnce); | |
| 290 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | |
| 291 const char* result_cstr; | |
| 292 EXPECT_VALID(result); | |
| 293 EXPECT(Dart_IsString(result)); | |
| 294 EXPECT_VALID(Dart_StringToCString(result, &result_cstr)); | |
| 295 EXPECT_STREQ("enter(main) enter(foo) enter(foo) exit(foo) exit(main) ", | |
| 296 result_cstr); | |
| 297 EXPECT(saw_paused_event); | |
| 298 } | |
| 299 | |
| 300 | |
| 301 TEST_CASE(Debugger_RewindTwoFrames_Unoptimized) { | |
| 302 SetFlagScope<bool> sfs(&FLAG_trace_rewind, true); | |
| 303 saw_paused_event = false; | |
| 304 rewind_frame_index = "2"; | |
| 305 | |
| 306 const char* kScriptChars = | |
| 307 "import 'dart:developer';\n" | |
| 308 "\n" | |
| 309 "var msg = new StringBuffer();\n" | |
| 310 "\n" | |
| 311 "foo() {\n" | |
| 312 " msg.write('enter(foo) ');\n" | |
| 313 " debugger();\n" | |
| 314 " msg.write('exit(foo) ');\n" | |
| 315 "}\n" | |
| 316 "\n" | |
| 317 "bar() {\n" | |
| 318 " msg.write('enter(bar) ');\n" | |
| 319 " foo();\n" | |
| 320 " msg.write('exit(bar) ');\n" | |
| 321 "}\n" | |
| 322 "\n" | |
| 323 "main() {\n" | |
| 324 " msg.write('enter(main) ');\n" | |
| 325 " bar();\n" | |
| 326 " msg.write('exit(main) ');\n" | |
| 327 " return msg.toString();\n" | |
| 328 "}\n"; | |
| 329 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | |
| 330 EXPECT_VALID(lib); | |
| 331 | |
| 332 Dart_SetPausedEventHandler(RewindOnce); | |
| 333 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | |
| 334 const char* result_cstr; | |
| 335 EXPECT_VALID(result); | |
| 336 EXPECT(Dart_IsString(result)); | |
| 337 EXPECT_VALID(Dart_StringToCString(result, &result_cstr)); | |
| 338 EXPECT_STREQ( | |
| 339 "enter(main) enter(bar) enter(foo) enter(bar) enter(foo) " | |
| 340 "exit(foo) exit(bar) exit(main) ", | |
| 341 result_cstr); | |
| 342 EXPECT(saw_paused_event); | |
| 343 } | |
| 344 | |
| 144 #endif // !PRODUCT | 345 #endif // !PRODUCT |
| 145 | 346 |
| 146 } // namespace dart | 347 } // namespace dart |
| OLD | NEW |