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 "include/dart_debugger_api.h" | 5 #include "include/dart_debugger_api.h" |
6 #include "vm/dart_api_impl.h" | 6 #include "vm/dart_api_impl.h" |
7 #include "vm/dart_entry.h" | 7 #include "vm/dart_entry.h" |
8 #include "vm/debugger.h" | 8 #include "vm/debugger.h" |
9 #include "vm/globals.h" | 9 #include "vm/globals.h" |
10 #include "vm/message_handler.h" | 10 #include "vm/message_handler.h" |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 char* buffer = isolate->current_zone()->Alloc<char>(len + 1); | 65 char* buffer = isolate->current_zone()->Alloc<char>(len + 1); |
66 va_list args2; | 66 va_list args2; |
67 va_start(args2, fmt); | 67 va_start(args2, fmt); |
68 OS::VSNPrint(buffer, (len + 1), fmt, args2); | 68 OS::VSNPrint(buffer, (len + 1), fmt, args2); |
69 va_end(args2); | 69 va_end(args2); |
70 | 70 |
71 return Eval(lib, buffer); | 71 return Eval(lib, buffer); |
72 } | 72 } |
73 | 73 |
74 | 74 |
75 /* | |
76 static RawFunction* GetFunction(const Class& cls, const char* name) { | 75 static RawFunction* GetFunction(const Class& cls, const char* name) { |
77 const Function& result = Function::Handle(cls.LookupDynamicFunction( | 76 const Function& result = Function::Handle(cls.LookupDynamicFunction( |
78 String::Handle(String::New(name)))); | 77 String::Handle(String::New(name)))); |
79 EXPECT(!result.IsNull()); | 78 EXPECT(!result.IsNull()); |
80 return result.raw(); | 79 return result.raw(); |
81 } | 80 } |
82 | 81 |
83 | 82 |
84 static RawFunction* GetStaticFunction(const Class& cls, const char* name) { | |
85 const Function& result = Function::Handle(cls.LookupStaticFunction( | |
86 String::Handle(String::New(name)))); | |
87 EXPECT(!result.IsNull()); | |
88 return result.raw(); | |
89 } | |
90 | |
91 | |
92 static RawField* GetField(const Class& cls, const char* name) { | |
93 const Field& field = | |
94 Field::Handle(cls.LookupField(String::Handle(String::New(name)))); | |
95 EXPECT(!field.IsNull()); | |
96 return field.raw(); | |
97 } | |
98 */ | |
99 | |
100 | |
101 static RawClass* GetClass(const Library& lib, const char* name) { | 83 static RawClass* GetClass(const Library& lib, const char* name) { |
102 const Class& cls = Class::Handle( | 84 const Class& cls = Class::Handle( |
103 lib.LookupClass(String::Handle(Symbols::New(name)))); | 85 lib.LookupClass(String::Handle(Symbols::New(name)))); |
104 EXPECT(!cls.IsNull()); // No ambiguity error expected. | 86 EXPECT(!cls.IsNull()); // No ambiguity error expected. |
105 return cls.raw(); | 87 return cls.raw(); |
106 } | 88 } |
107 | 89 |
108 | 90 |
109 TEST_CASE(Service_DebugBreakpoints) { | 91 TEST_CASE(Service_DebugBreakpoints) { |
110 const char* kScript = | 92 const char* kScript = |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 | 260 |
279 // Request function 0 from class A. | 261 // Request function 0 from class A. |
280 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'functions', '0']," | 262 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'functions', '0']," |
281 "[], []]", cid); | 263 "[], []]", cid); |
282 Service::HandleServiceMessage(isolate, service_msg); | 264 Service::HandleServiceMessage(isolate, service_msg); |
283 handler.HandleNextMessage(); | 265 handler.HandleNextMessage(); |
284 EXPECT_STREQ( | 266 EXPECT_STREQ( |
285 "{\"type\":\"Function\",\"id\":\"classes\\/1009\\/functions\\/0\",\"name\":" | 267 "{\"type\":\"Function\",\"id\":\"classes\\/1009\\/functions\\/0\",\"name\":" |
286 "\"get:a\",\"user_name\":\"A.a\",\"is_static\":false,\"is_const\":false," | 268 "\"get:a\",\"user_name\":\"A.a\",\"is_static\":false,\"is_const\":false," |
287 "\"is_optimizable\":true,\"is_inlinable\":false,\"kind\":" | 269 "\"is_optimizable\":true,\"is_inlinable\":false,\"kind\":" |
288 "\"implicit getter\",\"unoptimized_code\":{\"type\":\"null\"}," | 270 "\"kImplicitGetter\",\"unoptimized_code\":{\"type\":\"null\"}," |
289 "\"usage_counter\":0,\"optimized_call_site_count\":0,\"code\":" | 271 "\"usage_counter\":0,\"optimized_call_site_count\":0,\"code\":" |
290 "{\"type\":\"null\"},\"deoptimizations\":0}", handler.msg()); | 272 "{\"type\":\"null\"},\"deoptimizations\":0}", handler.msg()); |
291 | 273 |
292 // Request field 0 from class A. | 274 // Request field 0 from class A. |
293 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'fields', '0']," | 275 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'fields', '0']," |
294 "[], []]", cid); | 276 "[], []]", cid); |
295 Service::HandleServiceMessage(isolate, service_msg); | 277 Service::HandleServiceMessage(isolate, service_msg); |
296 handler.HandleNextMessage(); | 278 handler.HandleNextMessage(); |
297 EXPECT_STREQ( | 279 EXPECT_STREQ( |
298 "{\"type\":\"Field\",\"id\":\"classes\\/1009\\/fields\\/0\",\"name\":\"a\"," | 280 "{\"type\":\"Field\",\"id\":\"classes\\/1009\\/fields\\/0\",\"name\":\"a\"," |
(...skipping 14 matching lines...) Expand all Loading... |
313 "{\"type\":\"Error\",\"text\":\"Invalid sub collection huh\",\"message\":" | 295 "{\"type\":\"Error\",\"text\":\"Invalid sub collection huh\",\"message\":" |
314 "{\"arguments\":[\"classes\",\"1009\",\"huh\",\"0\"],\"option_keys\":[]," | 296 "{\"arguments\":[\"classes\",\"1009\",\"huh\",\"0\"],\"option_keys\":[]," |
315 "\"option_values\":[]}}", handler.msg()); | 297 "\"option_values\":[]}}", handler.msg()); |
316 | 298 |
317 // Invalid field request. | 299 // Invalid field request. |
318 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'fields', '9']," | 300 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'fields', '9']," |
319 "[], []]", cid); | 301 "[], []]", cid); |
320 Service::HandleServiceMessage(isolate, service_msg); | 302 Service::HandleServiceMessage(isolate, service_msg); |
321 handler.HandleNextMessage(); | 303 handler.HandleNextMessage(); |
322 EXPECT_STREQ( | 304 EXPECT_STREQ( |
323 "{\"type\":\"Error\",\"text\":\"fields id (9) must be in [0, 1).\"," | 305 "{\"type\":\"Error\",\"text\":\"Field 9 not found\"," |
324 "\"message\":{\"arguments\":[\"classes\",\"1009\",\"fields\",\"9\"]," | 306 "\"message\":{\"arguments\":[\"classes\",\"1009\",\"fields\",\"9\"]," |
325 "\"option_keys\":[],\"option_values\":[]}}", handler.msg()); | 307 "\"option_keys\":[],\"option_values\":[]}}", handler.msg()); |
326 | 308 |
327 // Invalid function request. | 309 // Invalid function request. |
328 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'functions', '9']," | 310 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'functions', '9']," |
329 "[], []]", cid); | 311 "[], []]", cid); |
330 Service::HandleServiceMessage(isolate, service_msg); | 312 Service::HandleServiceMessage(isolate, service_msg); |
331 handler.HandleNextMessage(); | 313 handler.HandleNextMessage(); |
332 EXPECT_STREQ( | 314 EXPECT_STREQ( |
333 "{\"type\":\"Error\",\"text\":\"functions id (9) must be in [0, 5).\"," | 315 "{\"type\":\"Error\",\"text\":\"Function 9 not found\"," |
334 "\"message\":{\"arguments\":[\"classes\",\"1009\",\"functions\",\"9\"]," | 316 "\"message\":{\"arguments\":[\"classes\",\"1009\",\"functions\",\"9\"]," |
335 "\"option_keys\":[],\"option_values\":[]}}", handler.msg()); | 317 "\"option_keys\":[],\"option_values\":[]}}", handler.msg()); |
336 | 318 |
337 | 319 |
338 // Invalid field subcommand. | 320 // Invalid field subcommand. |
339 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'fields', '9', 'x']" | 321 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'fields', '9', 'x']" |
340 ",[], []]", cid); | 322 ",[], []]", cid); |
341 Service::HandleServiceMessage(isolate, service_msg); | 323 Service::HandleServiceMessage(isolate, service_msg); |
342 handler.HandleNextMessage(); | 324 handler.HandleNextMessage(); |
343 EXPECT_STREQ( | 325 EXPECT_STREQ( |
344 "{\"type\":\"Error\",\"text\":\"Command too long\",\"message\":" | 326 "{\"type\":\"Error\",\"text\":\"Command too long\",\"message\":" |
345 "{\"arguments\":[\"classes\",\"1009\",\"fields\",\"9\",\"x\"]," | 327 "{\"arguments\":[\"classes\",\"1009\",\"fields\",\"9\",\"x\"]," |
346 "\"option_keys\":[],\"option_values\":[]}}", | 328 "\"option_keys\":[],\"option_values\":[]}}", |
347 handler.msg()); | 329 handler.msg()); |
348 | 330 |
349 // Invalid function request. | 331 // Invalid function request. |
350 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'functions', '9'," | 332 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'functions', '9'," |
351 "'x'], [], []]", cid); | 333 "'x'], [], []]", cid); |
352 Service::HandleServiceMessage(isolate, service_msg); | 334 Service::HandleServiceMessage(isolate, service_msg); |
353 handler.HandleNextMessage(); | 335 handler.HandleNextMessage(); |
354 EXPECT_STREQ( | 336 EXPECT_STREQ( |
355 "{\"type\":\"Error\",\"text\":\"Command too long\",\"message\":" | 337 "{\"type\":\"Error\",\"text\":\"Command too long\",\"message\":" |
356 "{\"arguments\":[\"classes\",\"1009\",\"functions\",\"9\",\"x\"]," | 338 "{\"arguments\":[\"classes\",\"1009\",\"functions\",\"9\",\"x\"]," |
357 "\"option_keys\":[],\"option_values\":[]}}", | 339 "\"option_keys\":[],\"option_values\":[]}}", |
358 handler.msg()); | 340 handler.msg()); |
359 } | 341 } |
360 | 342 |
| 343 |
| 344 TEST_CASE(Service_Code) { |
| 345 const char* kScript = |
| 346 "var port;\n" // Set to our mock port by C++. |
| 347 "\n" |
| 348 "class A {\n" |
| 349 " var a;\n" |
| 350 " dynamic b() {}\n" |
| 351 " dynamic c() {\n" |
| 352 " var d = () { b(); };\n" |
| 353 " return d;\n" |
| 354 " }\n" |
| 355 "}\n" |
| 356 "main() {\n" |
| 357 " var z = new A();\n" |
| 358 " var x = z.c();\n" |
| 359 " x();\n" |
| 360 "}"; |
| 361 |
| 362 Isolate* isolate = Isolate::Current(); |
| 363 Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL); |
| 364 EXPECT_VALID(h_lib); |
| 365 Library& lib = Library::Handle(); |
| 366 lib ^= Api::UnwrapHandle(h_lib); |
| 367 EXPECT(!lib.IsNull()); |
| 368 Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL); |
| 369 EXPECT_VALID(result); |
| 370 const Class& class_a = Class::Handle(GetClass(lib, "A")); |
| 371 EXPECT(!class_a.IsNull()); |
| 372 const Function& function_c = Function::Handle(GetFunction(class_a, "c")); |
| 373 EXPECT(!function_c.IsNull()); |
| 374 const Code& code_c = Code::Handle(function_c.CurrentCode()); |
| 375 EXPECT(!code_c.IsNull()); |
| 376 // Use the entry of the code object as it's reference. |
| 377 uword entry = code_c.EntryPoint(); |
| 378 EXPECT_GT(code_c.Size(), 16); |
| 379 uword last = entry + code_c.Size(); |
| 380 |
| 381 // Build a mock message handler and wrap it in a dart port. |
| 382 ServiceTestMessageHandler handler; |
| 383 Dart_Port port_id = PortMap::CreatePort(&handler); |
| 384 Dart_Handle port = |
| 385 Api::NewHandle(isolate, DartLibraryCalls::NewSendPort(port_id)); |
| 386 EXPECT_VALID(port); |
| 387 EXPECT_VALID(Dart_SetField(h_lib, NewString("port"), port)); |
| 388 |
| 389 Instance& service_msg = Instance::Handle(); |
| 390 |
| 391 // Request an invalid code object. |
| 392 service_msg = Eval(h_lib, "[port, ['code', '0'], [], []]"); |
| 393 Service::HandleServiceMessage(isolate, service_msg); |
| 394 handler.HandleNextMessage(); |
| 395 EXPECT_STREQ( |
| 396 "{\"type\":\"Error\",\"text\":\"Could not find code at 0\",\"message\":" |
| 397 "{\"arguments\":[\"code\",\"0\"]," |
| 398 "\"option_keys\":[],\"option_values\":[]}}", handler.msg()); |
| 399 |
| 400 // The following four tests check that a code object can be found |
| 401 // inside the range: [code.EntryPoint(), code.EntryPoint() + code.Size()). |
| 402 // Request code object at code.EntryPoint() |
| 403 // Expect this to succeed as it is inside [entry, entry + size). |
| 404 service_msg = EvalF(h_lib, "[port, ['code', '%" Px "'], [], []]", entry); |
| 405 Service::HandleServiceMessage(isolate, service_msg); |
| 406 handler.HandleNextMessage(); |
| 407 { |
| 408 // Only perform a partial match. |
| 409 const intptr_t kBufferSize = 512; |
| 410 char buffer[kBufferSize]; |
| 411 OS::SNPrint(buffer, kBufferSize-1, |
| 412 "{\"type\":\"Code\",\"id\":\"code\\/%" Px "\",", entry); |
| 413 EXPECT_SUBSTRING(buffer, handler.msg()); |
| 414 } |
| 415 |
| 416 // Request code object at code.EntryPoint() + 16. |
| 417 // Expect this to succeed as it is inside [entry, entry + size). |
| 418 uintptr_t address = entry + 16; |
| 419 service_msg = EvalF(h_lib, "[port, ['code', '%" Px "'], [], []]", address); |
| 420 Service::HandleServiceMessage(isolate, service_msg); |
| 421 handler.HandleNextMessage(); |
| 422 { |
| 423 // Only perform a partial match. |
| 424 const intptr_t kBufferSize = 512; |
| 425 char buffer[kBufferSize]; |
| 426 OS::SNPrint(buffer, kBufferSize-1, |
| 427 "{\"type\":\"Code\",\"id\":\"code\\/%" Px "\",", entry); |
| 428 EXPECT_SUBSTRING(buffer, handler.msg()); |
| 429 } |
| 430 |
| 431 // Request code object at code.EntryPoint() + code.Size() - 1. |
| 432 // Expect this to succeed as it is inside [entry, entry + size). |
| 433 address = last - 1; |
| 434 service_msg = EvalF(h_lib, "[port, ['code', '%" Px "'], [], []]", address); |
| 435 Service::HandleServiceMessage(isolate, service_msg); |
| 436 handler.HandleNextMessage(); |
| 437 { |
| 438 // Only perform a partial match. |
| 439 const intptr_t kBufferSize = 512; |
| 440 char buffer[kBufferSize]; |
| 441 OS::SNPrint(buffer, kBufferSize-1, |
| 442 "{\"type\":\"Code\",\"id\":\"code\\/%" Px "\",", entry); |
| 443 EXPECT_SUBSTRING(buffer, handler.msg()); |
| 444 } |
| 445 |
| 446 // Request code object at code.EntryPoint() + code.Size(). Expect this |
| 447 // to fail as it's outside of [entry, entry + size). |
| 448 address = last; |
| 449 service_msg = EvalF(h_lib, "[port, ['code', '%" Px "'], [], []]", address); |
| 450 Service::HandleServiceMessage(isolate, service_msg); |
| 451 handler.HandleNextMessage(); |
| 452 { |
| 453 const intptr_t kBufferSize = 1024; |
| 454 char buffer[kBufferSize]; |
| 455 OS::SNPrint(buffer, kBufferSize-1, |
| 456 "{\"type\":\"Error\",\"text\":\"Could not find code at %" Px "\"," |
| 457 "\"message\":{\"arguments\":[\"code\",\"%" Px "\"]," |
| 458 "\"option_keys\":[],\"option_values\":[]}}", address, address); |
| 459 EXPECT_STREQ(buffer, handler.msg()); |
| 460 } |
| 461 } |
| 462 |
361 } // namespace dart | 463 } // namespace dart |
OLD | NEW |