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 "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 the class A over the service. | |
| 243 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "'], [], []]", cid); | |
| 244 Service::HandleServiceMessage(isolate, service_msg); | |
| 245 handler.HandleNextMessage(); | |
| 246 EXPECT_STREQ( | |
| 247 "{\"type\":\"Class\",\"id\":\"classes\\/1009\",\"name\":\"A\"," | |
| 248 "\"user_name\":\"A\",\"implemented\":false,\"abstract\":false," | |
| 249 "\"patch\":false,\"finalized\":true,\"const\":false,\"super\":" | |
| 250 "{\"type\":\"@Class\",\"id\":\"classes\\/35\",\"name\":\"Object\"," | |
| 251 "\"user_name\":\"Object\"},\"library\":{\"type\":\"@Library\",\"id\":" | |
| 252 "\"libraries\\/12\",\"name\":\"\",\"user_name\":\"dart:test-lib\"}," | |
| 253 "\"fields\":[{\"type\":\"@Field\",\"id\":\"classes\\/1009\\/fields\\/0\"," | |
| 254 "\"name\":\"a\",\"user_name\":\"a\",\"owner\":{\"type\":\"@Class\"," | |
| 255 "\"id\":\"classes\\/1009\",\"name\":\"A\",\"user_name\":\"A\"}," | |
| 256 "\"declared_type\":{\"type\":\"@Class\",\"id\":\"classes\\/106\"," | |
| 257 "\"name\":\"dynamic\",\"user_name\":\"dynamic\"},\"static\":false," | |
| 258 "\"final\":false,\"const\":false}],\"functions\":[" | |
| 259 "{\"type\":\"@Function\",\"id\":\"classes\\/1009\\/functions\\/0\"," | |
| 260 "\"name\":\"get:a\",\"user_name\":\"A.a\"},{\"type\":\"@Function\"," | |
| 261 "\"id\":\"classes\\/1009\\/functions\\/1\",\"name\":\"set:a\"," | |
| 262 "\"user_name\":\"A.a=\"},{\"type\":\"@Function\",\"id\":" | |
| 263 "\"classes\\/1009\\/functions\\/2\",\"name\":\"b\",\"user_name\":\"A.b\"}" | |
| 264 ",{\"type\":\"@Function\",\"id\":\"classes\\/1009\\/functions\\/3\"," | |
| 265 "\"name\":\"c\",\"user_name\":\"A.c\"},{\"type\":\"@Function\",\"id\":" | |
| 266 "\"classes\\/1009\\/functions\\/4\",\"name\":\"A.\",\"user_name\":" | |
| 267 "\"A.A\"}]}", | |
| 268 handler.msg()); | |
|
turnidge
2013/12/20 17:44:45
Add test for invalid class.
Cutch
2013/12/20 18:23:46
Done.
| |
| 269 | |
| 270 // Request function 0 from class A. | |
| 271 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'functions', '0']," | |
| 272 "[], []]", cid); | |
| 273 Service::HandleServiceMessage(isolate, service_msg); | |
| 274 handler.HandleNextMessage(); | |
| 275 EXPECT_STREQ( | |
| 276 "{\"type\":\"Function\",\"id\":\"classes\\/1009\\/functions\\/0\",\"name\":" | |
| 277 "\"get:a\",\"user_name\":\"A.a\",\"is_static\":false,\"is_const\":false," | |
| 278 "\"is_optimizable\":true,\"is_inlinable\":false,\"kind\":" | |
| 279 "\"implicit getter\",\"unoptimized_code\":{\"type\":\"null\"}," | |
| 280 "\"usage_counter\":0,\"optimized_call_site_count\":0,\"code\":" | |
| 281 "{\"type\":\"null\"},\"deoptimizations\":0}", handler.msg()); | |
| 282 | |
| 283 // Request field 0 from class A. | |
| 284 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'fields', '0']," | |
| 285 "[], []]", cid); | |
| 286 Service::HandleServiceMessage(isolate, service_msg); | |
| 287 handler.HandleNextMessage(); | |
| 288 EXPECT_STREQ( | |
| 289 "{\"type\":\"Field\",\"id\":\"classes\\/1009\\/fields\\/0\",\"name\":\"a\"," | |
| 290 "\"user_name\":\"a\",\"owner\":{\"type\":\"@Class\",\"id\":" | |
| 291 "\"classes\\/1009\",\"name\":\"A\",\"user_name\":\"A\"},\"declared_type\":" | |
| 292 "{\"type\":\"@Class\",\"id\":\"classes\\/106\",\"name\":\"dynamic\"," | |
| 293 "\"user_name\":\"dynamic\"},\"static\":false,\"final\":false,\"const\":" | |
| 294 "false,\"guard_nullable\":true,\"guard_class\":{\"type\":\"@Class\"," | |
| 295 "\"id\":\"classes\\/105\",\"name\":\"Null\",\"user_name\":\"Null\"}," | |
| 296 "\"guard_length\":\"variable\"}", handler.msg()); | |
| 297 | |
| 298 // Invalid sub command. | |
| 299 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'huh', '0']," | |
| 300 "[], []]", cid); | |
| 301 Service::HandleServiceMessage(isolate, service_msg); | |
| 302 handler.HandleNextMessage(); | |
| 303 EXPECT_STREQ( | |
| 304 "{\"type\":\"Error\",\"text\":\"Invalid sub collection huh\",\"message\":" | |
| 305 "{\"arguments\":[\"classes\",\"1009\",\"huh\",\"0\"],\"option_keys\":[]," | |
| 306 "\"option_values\":[]}}", handler.msg()); | |
| 307 | |
| 308 // Invalid field request. | |
| 309 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'fields', '9']," | |
| 310 "[], []]", cid); | |
| 311 Service::HandleServiceMessage(isolate, service_msg); | |
| 312 handler.HandleNextMessage(); | |
| 313 EXPECT_STREQ( | |
| 314 "{\"type\":\"Error\",\"text\":\"fields id (9) must be in [0, 1).\"," | |
| 315 "\"message\":{\"arguments\":[\"classes\",\"1009\",\"fields\",\"9\"]," | |
| 316 "\"option_keys\":[],\"option_values\":[]}}", handler.msg()); | |
|
turnidge
2013/12/20 17:44:45
Add invalid subcommand access for field/function
Cutch
2013/12/20 18:23:46
Done.
| |
| 317 | |
| 318 // Invalid function request. | |
| 319 service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'functions', '9']," | |
| 320 "[], []]", cid); | |
| 321 Service::HandleServiceMessage(isolate, service_msg); | |
| 322 handler.HandleNextMessage(); | |
| 323 EXPECT_STREQ( | |
| 324 "{\"type\":\"Error\",\"text\":\"functions id (9) must be in [0, 5).\"," | |
| 325 "\"message\":{\"arguments\":[\"classes\",\"1009\",\"functions\",\"9\"]," | |
| 326 "\"option_keys\":[],\"option_values\":[]}}", handler.msg()); | |
| 327 } | |
| 328 | |
| 149 } // namespace dart | 329 } // namespace dart |
| OLD | NEW |