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 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 |