| 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 | 47 |
| 48 static RawInstance* Eval(Dart_Handle lib, const char* expr) { | 48 static RawInstance* Eval(Dart_Handle lib, const char* expr) { |
| 49 Dart_Handle result = Dart_EvaluateExpr(lib, NewString(expr)); | 49 Dart_Handle result = Dart_EvaluateExpr(lib, NewString(expr)); |
| 50 EXPECT_VALID(result); | 50 EXPECT_VALID(result); |
| 51 Isolate* isolate = Isolate::Current(); | 51 Isolate* isolate = Isolate::Current(); |
| 52 const Instance& instance = Api::UnwrapInstanceHandle(isolate, result); | 52 const Instance& instance = Api::UnwrapInstanceHandle(isolate, result); |
| 53 return instance.raw(); | 53 return instance.raw(); |
| 54 } | 54 } |
| 55 | 55 |
| 56 | 56 |
| 57 static RawInstance* EvalF(Dart_Handle lib, const char* fmt, ...) { |
| 58 Isolate* isolate = Isolate::Current(); |
| 59 |
| 60 va_list args; |
| 61 va_start(args, fmt); |
| 62 intptr_t len = OS::VSNPrint(NULL, 0, fmt, args); |
| 63 va_end(args); |
| 64 |
| 65 char* buffer = isolate->current_zone()->Alloc<char>(len + 1); |
| 66 va_list args2; |
| 67 va_start(args2, fmt); |
| 68 OS::VSNPrint(buffer, (len + 1), fmt, args2); |
| 69 va_end(args2); |
| 70 |
| 71 return Eval(lib, buffer); |
| 72 } |
| 73 |
| 74 |
| 75 /* |
| 76 static RawFunction* GetFunction(const Class& cls, const char* name) { |
| 77 const Function& result = Function::Handle(cls.LookupDynamicFunction( |
| 78 String::Handle(String::New(name)))); |
| 79 EXPECT(!result.IsNull()); |
| 80 return result.raw(); |
| 81 } |
| 82 |
| 83 |
| 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) { |
| 102 const Class& cls = Class::Handle( |
| 103 lib.LookupClass(String::Handle(Symbols::New(name)))); |
| 104 EXPECT(!cls.IsNull()); // No ambiguity error expected. |
| 105 return cls.raw(); |
| 106 } |
| 107 |
| 108 |
| 57 TEST_CASE(Service_DebugBreakpoints) { | 109 TEST_CASE(Service_DebugBreakpoints) { |
| 58 const char* kScript = | 110 const char* kScript = |
| 59 "var port;\n" // Set to our mock port by C++. | 111 "var port;\n" // Set to our mock port by C++. |
| 60 "\n" | 112 "\n" |
| 61 "main() {\n" // We set breakpoint here. | 113 "main() {\n" // We set breakpoint here. |
| 62 "}"; | 114 "}"; |
| 63 | 115 |
| 64 Isolate* isolate = Isolate::Current(); | 116 Isolate* isolate = Isolate::Current(); |
| 65 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 117 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); |
| 66 EXPECT_VALID(lib); | 118 EXPECT_VALID(lib); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 service_msg = Eval(lib, "[port, ['debug', 'nosferatu'], [], []]"); | 191 service_msg = Eval(lib, "[port, ['debug', 'nosferatu'], [], []]"); |
| 140 Service::HandleServiceMessage(isolate, service_msg); | 192 Service::HandleServiceMessage(isolate, service_msg); |
| 141 handler.HandleNextMessage(); | 193 handler.HandleNextMessage(); |
| 142 EXPECT_STREQ("{\"type\":\"Error\"," | 194 EXPECT_STREQ("{\"type\":\"Error\"," |
| 143 "\"text\":\"Unrecognized subcommand 'nosferatu'\"," | 195 "\"text\":\"Unrecognized subcommand 'nosferatu'\"," |
| 144 "\"message\":{\"arguments\":[\"debug\",\"nosferatu\"]," | 196 "\"message\":{\"arguments\":[\"debug\",\"nosferatu\"]," |
| 145 "\"option_keys\":[],\"option_values\":[]}}", | 197 "\"option_keys\":[],\"option_values\":[]}}", |
| 146 handler.msg()); | 198 handler.msg()); |
| 147 } | 199 } |
| 148 | 200 |
| 201 |
| 202 TEST_CASE(Service_Classes) { |
| 203 const char* kScript = |
| 204 "var port;\n" // Set to our mock port by C++. |
| 205 "\n" |
| 206 "class A {\n" |
| 207 " var a;\n" |
| 208 " dynamic b() {}\n" |
| 209 " dynamic c() {\n" |
| 210 " var d = () { b(); };\n" |
| 211 " return d;\n" |
| 212 " }\n" |
| 213 "}\n" |
| 214 "main() {\n" |
| 215 " var z = new A();\n" |
| 216 " var x = z.c();\n" |
| 217 " x();\n" |
| 218 "}"; |
| 219 |
| 220 Isolate* isolate = Isolate::Current(); |
| 221 Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL); |
| 222 EXPECT_VALID(h_lib); |
| 223 Library& lib = Library::Handle(); |
| 224 lib ^= Api::UnwrapHandle(h_lib); |
| 225 EXPECT(!lib.IsNull()); |
| 226 Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL); |
| 227 EXPECT_VALID(result); |
| 228 const Class& class_a = Class::Handle(GetClass(lib, "A")); |
| 229 EXPECT(!class_a.IsNull()); |
| 230 intptr_t cid = class_a.id(); |
| 231 |
| 232 // Build a mock message handler and wrap it in a dart port. |
| 233 ServiceTestMessageHandler handler; |
| 234 Dart_Port port_id = PortMap::CreatePort(&handler); |
| 235 Dart_Handle port = |
| 236 Api::NewHandle(isolate, DartLibraryCalls::NewSendPort(port_id)); |
| 237 EXPECT_VALID(port); |
| 238 EXPECT_VALID(Dart_SetField(h_lib, NewString("port"), port)); |
| 239 |
| 240 Instance& service_msg = Instance::Handle(); |
| 241 |
| 242 // Request an invalid class id. |
| 243 service_msg = Eval(h_lib, "[port, ['classes', '999999'], [], []]"); |
| 244 Service::HandleServiceMessage(isolate, service_msg); |
| 245 handler.HandleNextMessage(); |
| 246 EXPECT_STREQ( |
| 247 "{\"type\":\"Error\",\"text\":\"999999 is not a valid class id.\"," |
| 248 "\"message\":{\"arguments\":[\"classes\",\"999999\"]," |
| 249 "\"option_keys\":[],\"option_values\":[]}}", handler.msg()); |
| 250 |
| 251 // Request the class A over the service. |
| 252 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "'], [], []]", cid); |
| 253 Service::HandleServiceMessage(isolate, service_msg); |
| 254 handler.HandleNextMessage(); |
| 255 EXPECT_STREQ( |
| 256 "{\"type\":\"Class\",\"id\":\"classes\\/1009\",\"name\":\"A\"," |
| 257 "\"user_name\":\"A\",\"implemented\":false,\"abstract\":false," |
| 258 "\"patch\":false,\"finalized\":true,\"const\":false,\"super\":" |
| 259 "{\"type\":\"@Class\",\"id\":\"classes\\/35\",\"name\":\"Object\"," |
| 260 "\"user_name\":\"Object\"},\"library\":{\"type\":\"@Library\",\"id\":" |
| 261 "\"libraries\\/12\",\"name\":\"\",\"user_name\":\"dart:test-lib\"}," |
| 262 "\"fields\":[{\"type\":\"@Field\",\"id\":\"classes\\/1009\\/fields\\/0\"," |
| 263 "\"name\":\"a\",\"user_name\":\"a\",\"owner\":{\"type\":\"@Class\"," |
| 264 "\"id\":\"classes\\/1009\",\"name\":\"A\",\"user_name\":\"A\"}," |
| 265 "\"declared_type\":{\"type\":\"@Class\",\"id\":\"classes\\/106\"," |
| 266 "\"name\":\"dynamic\",\"user_name\":\"dynamic\"},\"static\":false," |
| 267 "\"final\":false,\"const\":false}],\"functions\":[" |
| 268 "{\"type\":\"@Function\",\"id\":\"classes\\/1009\\/functions\\/0\"," |
| 269 "\"name\":\"get:a\",\"user_name\":\"A.a\"},{\"type\":\"@Function\"," |
| 270 "\"id\":\"classes\\/1009\\/functions\\/1\",\"name\":\"set:a\"," |
| 271 "\"user_name\":\"A.a=\"},{\"type\":\"@Function\",\"id\":" |
| 272 "\"classes\\/1009\\/functions\\/2\",\"name\":\"b\",\"user_name\":\"A.b\"}" |
| 273 ",{\"type\":\"@Function\",\"id\":\"classes\\/1009\\/functions\\/3\"," |
| 274 "\"name\":\"c\",\"user_name\":\"A.c\"},{\"type\":\"@Function\",\"id\":" |
| 275 "\"classes\\/1009\\/functions\\/4\",\"name\":\"A.\",\"user_name\":" |
| 276 "\"A.A\"}]}", |
| 277 handler.msg()); |
| 278 |
| 279 // Request function 0 from class A. |
| 280 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'functions', '0']," |
| 281 "[], []]", cid); |
| 282 Service::HandleServiceMessage(isolate, service_msg); |
| 283 handler.HandleNextMessage(); |
| 284 EXPECT_STREQ( |
| 285 "{\"type\":\"Function\",\"id\":\"classes\\/1009\\/functions\\/0\",\"name\":" |
| 286 "\"get:a\",\"user_name\":\"A.a\",\"is_static\":false,\"is_const\":false," |
| 287 "\"is_optimizable\":true,\"is_inlinable\":false,\"kind\":" |
| 288 "\"implicit getter\",\"unoptimized_code\":{\"type\":\"null\"}," |
| 289 "\"usage_counter\":0,\"optimized_call_site_count\":0,\"code\":" |
| 290 "{\"type\":\"null\"},\"deoptimizations\":0}", handler.msg()); |
| 291 |
| 292 // Request field 0 from class A. |
| 293 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'fields', '0']," |
| 294 "[], []]", cid); |
| 295 Service::HandleServiceMessage(isolate, service_msg); |
| 296 handler.HandleNextMessage(); |
| 297 EXPECT_STREQ( |
| 298 "{\"type\":\"Field\",\"id\":\"classes\\/1009\\/fields\\/0\",\"name\":\"a\"," |
| 299 "\"user_name\":\"a\",\"owner\":{\"type\":\"@Class\",\"id\":" |
| 300 "\"classes\\/1009\",\"name\":\"A\",\"user_name\":\"A\"},\"declared_type\":" |
| 301 "{\"type\":\"@Class\",\"id\":\"classes\\/106\",\"name\":\"dynamic\"," |
| 302 "\"user_name\":\"dynamic\"},\"static\":false,\"final\":false,\"const\":" |
| 303 "false,\"guard_nullable\":true,\"guard_class\":{\"type\":\"@Class\"," |
| 304 "\"id\":\"classes\\/105\",\"name\":\"Null\",\"user_name\":\"Null\"}," |
| 305 "\"guard_length\":\"variable\"}", handler.msg()); |
| 306 |
| 307 // Invalid sub command. |
| 308 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'huh', '0']," |
| 309 "[], []]", cid); |
| 310 Service::HandleServiceMessage(isolate, service_msg); |
| 311 handler.HandleNextMessage(); |
| 312 EXPECT_STREQ( |
| 313 "{\"type\":\"Error\",\"text\":\"Invalid sub collection huh\",\"message\":" |
| 314 "{\"arguments\":[\"classes\",\"1009\",\"huh\",\"0\"],\"option_keys\":[]," |
| 315 "\"option_values\":[]}}", handler.msg()); |
| 316 |
| 317 // Invalid field request. |
| 318 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'fields', '9']," |
| 319 "[], []]", cid); |
| 320 Service::HandleServiceMessage(isolate, service_msg); |
| 321 handler.HandleNextMessage(); |
| 322 EXPECT_STREQ( |
| 323 "{\"type\":\"Error\",\"text\":\"fields id (9) must be in [0, 1).\"," |
| 324 "\"message\":{\"arguments\":[\"classes\",\"1009\",\"fields\",\"9\"]," |
| 325 "\"option_keys\":[],\"option_values\":[]}}", handler.msg()); |
| 326 |
| 327 // Invalid function request. |
| 328 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'functions', '9']," |
| 329 "[], []]", cid); |
| 330 Service::HandleServiceMessage(isolate, service_msg); |
| 331 handler.HandleNextMessage(); |
| 332 EXPECT_STREQ( |
| 333 "{\"type\":\"Error\",\"text\":\"functions id (9) must be in [0, 5).\"," |
| 334 "\"message\":{\"arguments\":[\"classes\",\"1009\",\"functions\",\"9\"]," |
| 335 "\"option_keys\":[],\"option_values\":[]}}", handler.msg()); |
| 336 |
| 337 |
| 338 // Invalid field subcommand. |
| 339 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'fields', '9', 'x']" |
| 340 ",[], []]", cid); |
| 341 Service::HandleServiceMessage(isolate, service_msg); |
| 342 handler.HandleNextMessage(); |
| 343 EXPECT_STREQ( |
| 344 "{\"type\":\"Error\",\"text\":\"Command too long\",\"message\":" |
| 345 "{\"arguments\":[\"classes\",\"1009\",\"fields\",\"9\",\"x\"]," |
| 346 "\"option_keys\":[],\"option_values\":[]}}", |
| 347 handler.msg()); |
| 348 |
| 349 // Invalid function request. |
| 350 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'functions', '9'," |
| 351 "'x'], [], []]", cid); |
| 352 Service::HandleServiceMessage(isolate, service_msg); |
| 353 handler.HandleNextMessage(); |
| 354 EXPECT_STREQ( |
| 355 "{\"type\":\"Error\",\"text\":\"Command too long\",\"message\":" |
| 356 "{\"arguments\":[\"classes\",\"1009\",\"functions\",\"9\",\"x\"]," |
| 357 "\"option_keys\":[],\"option_values\":[]}}", |
| 358 handler.msg()); |
| 359 } |
| 360 |
| 149 } // namespace dart | 361 } // namespace dart |
| OLD | NEW |