| 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 "platform/globals.h" | 5 #include "platform/globals.h" | 
| 6 | 6 | 
| 7 #include "include/dart_tools_api.h" | 7 #include "include/dart_tools_api.h" | 
| 8 #include "vm/dart_api_impl.h" | 8 #include "vm/dart_api_impl.h" | 
| 9 #include "vm/dart_entry.h" | 9 #include "vm/dart_entry.h" | 
| 10 #include "vm/debugger.h" | 10 #include "vm/debugger.h" | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 21 | 21 | 
| 22 // This flag is used in the Service_Flags test below. | 22 // This flag is used in the Service_Flags test below. | 
| 23 DEFINE_FLAG(bool, service_testing_flag, false, "Comment"); | 23 DEFINE_FLAG(bool, service_testing_flag, false, "Comment"); | 
| 24 | 24 | 
| 25 #ifndef PRODUCT | 25 #ifndef PRODUCT | 
| 26 | 26 | 
| 27 class ServiceTestMessageHandler : public MessageHandler { | 27 class ServiceTestMessageHandler : public MessageHandler { | 
| 28  public: | 28  public: | 
| 29   ServiceTestMessageHandler() : _msg(NULL) {} | 29   ServiceTestMessageHandler() : _msg(NULL) {} | 
| 30 | 30 | 
| 31   ~ServiceTestMessageHandler() { | 31   ~ServiceTestMessageHandler() { free(_msg); } | 
| 32     free(_msg); |  | 
| 33   } |  | 
| 34 | 32 | 
| 35   MessageStatus HandleMessage(Message* message) { | 33   MessageStatus HandleMessage(Message* message) { | 
| 36     if (_msg != NULL) { | 34     if (_msg != NULL) { | 
| 37       free(_msg); | 35       free(_msg); | 
| 38     } | 36     } | 
| 39 | 37 | 
| 40     // Parse the message. | 38     // Parse the message. | 
| 41     Object& response_obj = Object::Handle(); | 39     Object& response_obj = Object::Handle(); | 
| 42     if (message->IsRaw()) { | 40     if (message->IsRaw()) { | 
| 43       response_obj = message->raw_obj(); | 41       response_obj = message->raw_obj(); | 
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 105   va_list args2; | 103   va_list args2; | 
| 106   va_start(args2, fmt); | 104   va_start(args2, fmt); | 
| 107   OS::VSNPrint(buffer, (len + 1), fmt, args2); | 105   OS::VSNPrint(buffer, (len + 1), fmt, args2); | 
| 108   va_end(args2); | 106   va_end(args2); | 
| 109 | 107 | 
| 110   return Eval(lib, buffer); | 108   return Eval(lib, buffer); | 
| 111 } | 109 } | 
| 112 | 110 | 
| 113 | 111 | 
| 114 static RawFunction* GetFunction(const Class& cls, const char* name) { | 112 static RawFunction* GetFunction(const Class& cls, const char* name) { | 
| 115   const Function& result = Function::Handle(cls.LookupDynamicFunction( | 113   const Function& result = Function::Handle( | 
| 116       String::Handle(String::New(name)))); | 114       cls.LookupDynamicFunction(String::Handle(String::New(name)))); | 
| 117   EXPECT(!result.IsNull()); | 115   EXPECT(!result.IsNull()); | 
| 118   return result.raw(); | 116   return result.raw(); | 
| 119 } | 117 } | 
| 120 | 118 | 
| 121 | 119 | 
| 122 static RawClass* GetClass(const Library& lib, const char* name) { | 120 static RawClass* GetClass(const Library& lib, const char* name) { | 
| 123   const Class& cls = Class::Handle( | 121   const Class& cls = Class::Handle( | 
| 124       lib.LookupClass(String::Handle(Symbols::New(Thread::Current(), name)))); | 122       lib.LookupClass(String::Handle(Symbols::New(Thread::Current(), name)))); | 
| 125   EXPECT(!cls.IsNull());  // No ambiguity error expected. | 123   EXPECT(!cls.IsNull());  // No ambiguity error expected. | 
| 126   return cls.raw(); | 124   return cls.raw(); | 
| 127 } | 125 } | 
| 128 | 126 | 
| 129 | 127 | 
| 130 static void HandleIsolateMessage(Isolate* isolate, const Array& msg) { | 128 static void HandleIsolateMessage(Isolate* isolate, const Array& msg) { | 
| 131   TransitionNativeToVM transition(Thread::Current()); | 129   TransitionNativeToVM transition(Thread::Current()); | 
| 132   Service::HandleIsolateMessage(isolate, msg); | 130   Service::HandleIsolateMessage(isolate, msg); | 
| 133 } | 131 } | 
| 134 | 132 | 
| 135 | 133 | 
| 136 static void HandleRootMessage(const Array& message) { | 134 static void HandleRootMessage(const Array& message) { | 
| 137   TransitionNativeToVM transition(Thread::Current()); | 135   TransitionNativeToVM transition(Thread::Current()); | 
| 138   Service::HandleRootMessage(message); | 136   Service::HandleRootMessage(message); | 
| 139 } | 137 } | 
| 140 | 138 | 
| 141 | 139 | 
| 142 TEST_CASE(Service_IsolateStickyError) { | 140 TEST_CASE(Service_IsolateStickyError) { | 
| 143   const char* kScript = | 141   const char* kScript = "main() => throw 'HI THERE STICKY';\n"; | 
| 144       "main() => throw 'HI THERE STICKY';\n"; |  | 
| 145 | 142 | 
| 146   Isolate* isolate = thread->isolate(); | 143   Isolate* isolate = thread->isolate(); | 
| 147   isolate->set_is_runnable(true); | 144   isolate->set_is_runnable(true); | 
| 148   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 145   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 
| 149   EXPECT_VALID(lib); | 146   EXPECT_VALID(lib); | 
| 150   Library& vmlib = Library::Handle(); | 147   Library& vmlib = Library::Handle(); | 
| 151   vmlib ^= Api::UnwrapHandle(lib); | 148   vmlib ^= Api::UnwrapHandle(lib); | 
| 152   EXPECT(!vmlib.IsNull()); | 149   EXPECT(!vmlib.IsNull()); | 
| 153   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 150   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 
| 154   EXPECT(Dart_IsUnhandledExceptionError(result)); | 151   EXPECT(Dart_IsUnhandledExceptionError(result)); | 
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 269 | 266 | 
| 270   // Request an invalid code object. | 267   // Request an invalid code object. | 
| 271   service_msg = | 268   service_msg = | 
| 272       Eval(lib, "[0, port, '0', 'getObject', ['objectId'], ['code/0']]"); | 269       Eval(lib, "[0, port, '0', 'getObject', ['objectId'], ['code/0']]"); | 
| 273   HandleIsolateMessage(isolate, service_msg); | 270   HandleIsolateMessage(isolate, service_msg); | 
| 274   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 271   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 
| 275   EXPECT_SUBSTRING("\"error\"", handler.msg()); | 272   EXPECT_SUBSTRING("\"error\"", handler.msg()); | 
| 276 | 273 | 
| 277   // The following test checks that a code object can be found only | 274   // The following test checks that a code object can be found only | 
| 278   // at compile_timestamp()-code.EntryPoint(). | 275   // at compile_timestamp()-code.EntryPoint(). | 
| 279   service_msg = EvalF(lib, "[0, port, '0', 'getObject', " | 276   service_msg = EvalF(lib, | 
| 280                       "['objectId'], ['code/%" Px64"-%" Px "']]", | 277                       "[0, port, '0', 'getObject', " | 
| 281                       compile_timestamp, | 278                       "['objectId'], ['code/%" Px64 "-%" Px "']]", | 
| 282                       entry); | 279                       compile_timestamp, entry); | 
| 283   HandleIsolateMessage(isolate, service_msg); | 280   HandleIsolateMessage(isolate, service_msg); | 
| 284   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 281   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 
| 285   EXPECT_SUBSTRING("\"type\":\"Code\"", handler.msg()); | 282   EXPECT_SUBSTRING("\"type\":\"Code\"", handler.msg()); | 
| 286   { | 283   { | 
| 287     // Only perform a partial match. | 284     // Only perform a partial match. | 
| 288     const intptr_t kBufferSize = 512; | 285     const intptr_t kBufferSize = 512; | 
| 289     char buffer[kBufferSize]; | 286     char buffer[kBufferSize]; | 
| 290     OS::SNPrint(buffer, kBufferSize-1, | 287     OS::SNPrint(buffer, kBufferSize - 1, | 
| 291                 "\"fixedId\":true,\"id\":\"code\\/%" Px64 "-%" Px "\",", | 288                 "\"fixedId\":true,\"id\":\"code\\/%" Px64 "-%" Px "\",", | 
| 292                 compile_timestamp, | 289                 compile_timestamp, entry); | 
| 293                 entry); |  | 
| 294     EXPECT_SUBSTRING(buffer, handler.msg()); | 290     EXPECT_SUBSTRING(buffer, handler.msg()); | 
| 295   } | 291   } | 
| 296 | 292 | 
| 297   // Request code object at compile_timestamp-code.EntryPoint() + 16 | 293   // Request code object at compile_timestamp-code.EntryPoint() + 16 | 
| 298   // Expect this to fail because the address is not the entry point. | 294   // Expect this to fail because the address is not the entry point. | 
| 299   uintptr_t address = entry + 16; | 295   uintptr_t address = entry + 16; | 
| 300   service_msg = EvalF(lib, "[0, port, '0', 'getObject', " | 296   service_msg = EvalF(lib, | 
| 301                       "['objectId'], ['code/%" Px64"-%" Px "']]", | 297                       "[0, port, '0', 'getObject', " | 
| 302                       compile_timestamp, | 298                       "['objectId'], ['code/%" Px64 "-%" Px "']]", | 
| 303                       address); | 299                       compile_timestamp, address); | 
| 304   HandleIsolateMessage(isolate, service_msg); | 300   HandleIsolateMessage(isolate, service_msg); | 
| 305   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 301   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 
| 306   EXPECT_SUBSTRING("\"error\"", handler.msg()); | 302   EXPECT_SUBSTRING("\"error\"", handler.msg()); | 
| 307 | 303 | 
| 308   // Request code object at (compile_timestamp - 1)-code.EntryPoint() | 304   // Request code object at (compile_timestamp - 1)-code.EntryPoint() | 
| 309   // Expect this to fail because the timestamp is wrong. | 305   // Expect this to fail because the timestamp is wrong. | 
| 310   address = entry; | 306   address = entry; | 
| 311   service_msg = EvalF(lib, "[0, port, '0', 'getObject', " | 307   service_msg = EvalF(lib, | 
| 312                       "['objectId'], ['code/%" Px64"-%" Px "']]", | 308                       "[0, port, '0', 'getObject', " | 
| 313                       compile_timestamp - 1, | 309                       "['objectId'], ['code/%" Px64 "-%" Px "']]", | 
| 314                       address); | 310                       compile_timestamp - 1, address); | 
| 315   HandleIsolateMessage(isolate, service_msg); | 311   HandleIsolateMessage(isolate, service_msg); | 
| 316   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 312   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 
| 317   EXPECT_SUBSTRING("\"error\"", handler.msg()); | 313   EXPECT_SUBSTRING("\"error\"", handler.msg()); | 
| 318 | 314 | 
| 319   // Request native code at address. Expect the null code object back. | 315   // Request native code at address. Expect the null code object back. | 
| 320   address = last; | 316   address = last; | 
| 321   service_msg = EvalF(lib, "[0, port, '0', 'getObject', " | 317   service_msg = EvalF(lib, | 
|  | 318                       "[0, port, '0', 'getObject', " | 
| 322                       "['objectId'], ['code/native-%" Px "']]", | 319                       "['objectId'], ['code/native-%" Px "']]", | 
| 323                       address); | 320                       address); | 
| 324   HandleIsolateMessage(isolate, service_msg); | 321   HandleIsolateMessage(isolate, service_msg); | 
| 325   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 322   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 
| 326   // TODO(turnidge): It is pretty broken to return an Instance here.  Fix. | 323   // TODO(turnidge): It is pretty broken to return an Instance here.  Fix. | 
| 327   EXPECT_SUBSTRING("\"kind\":\"Null\"", | 324   EXPECT_SUBSTRING("\"kind\":\"Null\"", handler.msg()); | 
| 328                    handler.msg()); |  | 
| 329 | 325 | 
| 330   // Request malformed native code. | 326   // Request malformed native code. | 
| 331   service_msg = EvalF(lib, "[0, port, '0', 'getObject', ['objectId'], " | 327   service_msg = EvalF(lib, | 
|  | 328                       "[0, port, '0', 'getObject', ['objectId'], " | 
| 332                       "['code/native%" Px "']]", | 329                       "['code/native%" Px "']]", | 
| 333                       address); | 330                       address); | 
| 334   HandleIsolateMessage(isolate, service_msg); | 331   HandleIsolateMessage(isolate, service_msg); | 
| 335   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 332   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 
| 336   EXPECT_SUBSTRING("\"error\"", handler.msg()); | 333   EXPECT_SUBSTRING("\"error\"", handler.msg()); | 
| 337 } | 334 } | 
| 338 | 335 | 
| 339 | 336 | 
| 340 TEST_CASE(Service_TokenStream) { | 337 TEST_CASE(Service_TokenStream) { | 
| 341   const char* kScript = | 338   const char* kScript = | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
| 365   // Build a mock message handler and wrap it in a dart port. | 362   // Build a mock message handler and wrap it in a dart port. | 
| 366   ServiceTestMessageHandler handler; | 363   ServiceTestMessageHandler handler; | 
| 367   Dart_Port port_id = PortMap::CreatePort(&handler); | 364   Dart_Port port_id = PortMap::CreatePort(&handler); | 
| 368   Dart_Handle port = Api::NewHandle(thread, SendPort::New(port_id)); | 365   Dart_Handle port = Api::NewHandle(thread, SendPort::New(port_id)); | 
| 369   EXPECT_VALID(port); | 366   EXPECT_VALID(port); | 
| 370   EXPECT_VALID(Dart_SetField(lib, NewString("port"), port)); | 367   EXPECT_VALID(Dart_SetField(lib, NewString("port"), port)); | 
| 371 | 368 | 
| 372   Array& service_msg = Array::Handle(); | 369   Array& service_msg = Array::Handle(); | 
| 373 | 370 | 
| 374   // Fetch object. | 371   // Fetch object. | 
| 375   service_msg = EvalF(lib, "[0, port, '0', 'getObject', " | 372   service_msg = EvalF(lib, | 
| 376                       "['objectId'], ['objects/%" Pd "']]", id); | 373                       "[0, port, '0', 'getObject', " | 
|  | 374                       "['objectId'], ['objects/%" Pd "']]", | 
|  | 375                       id); | 
| 377   HandleIsolateMessage(isolate, service_msg); | 376   HandleIsolateMessage(isolate, service_msg); | 
| 378   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 377   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 
| 379 | 378 | 
| 380   // Check type. | 379   // Check type. | 
| 381   EXPECT_SUBSTRING("\"type\":\"Object\"", handler.msg()); | 380   EXPECT_SUBSTRING("\"type\":\"Object\"", handler.msg()); | 
| 382   EXPECT_SUBSTRING("\"_vmType\":\"TokenStream\"", handler.msg()); | 381   EXPECT_SUBSTRING("\"_vmType\":\"TokenStream\"", handler.msg()); | 
| 383   // Check for members array. | 382   // Check for members array. | 
| 384   EXPECT_SUBSTRING("\"members\":[", handler.msg()); | 383   EXPECT_SUBSTRING("\"members\":[", handler.msg()); | 
| 385 } | 384 } | 
| 386 | 385 | 
| 387 | 386 | 
| 388 TEST_CASE(Service_PcDescriptors) { | 387 TEST_CASE(Service_PcDescriptors) { | 
| 389   const char* kScript = | 388   const char* kScript = | 
| 390     "var port;\n"  // Set to our mock port by C++. | 389       "var port;\n"  // Set to our mock port by C++. | 
| 391     "\n" | 390       "\n" | 
| 392     "class A {\n" | 391       "class A {\n" | 
| 393     "  var a;\n" | 392       "  var a;\n" | 
| 394     "  dynamic b() {}\n" | 393       "  dynamic b() {}\n" | 
| 395     "  dynamic c() {\n" | 394       "  dynamic c() {\n" | 
| 396     "    var d = () { b(); };\n" | 395       "    var d = () { b(); };\n" | 
| 397     "    return d;\n" | 396       "    return d;\n" | 
| 398     "  }\n" | 397       "  }\n" | 
| 399     "}\n" | 398       "}\n" | 
| 400     "main() {\n" | 399       "main() {\n" | 
| 401     "  var z = new A();\n" | 400       "  var z = new A();\n" | 
| 402     "  var x = z.c();\n" | 401       "  var x = z.c();\n" | 
| 403     "  x();\n" | 402       "  x();\n" | 
| 404     "}"; | 403       "}"; | 
| 405 | 404 | 
| 406   Isolate* isolate = thread->isolate(); | 405   Isolate* isolate = thread->isolate(); | 
| 407   isolate->set_is_runnable(true); | 406   isolate->set_is_runnable(true); | 
| 408   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 407   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 
| 409   EXPECT_VALID(lib); | 408   EXPECT_VALID(lib); | 
| 410   Library& vmlib = Library::Handle(); | 409   Library& vmlib = Library::Handle(); | 
| 411   vmlib ^= Api::UnwrapHandle(lib); | 410   vmlib ^= Api::UnwrapHandle(lib); | 
| 412   EXPECT(!vmlib.IsNull()); | 411   EXPECT(!vmlib.IsNull()); | 
| 413   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 412   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 
| 414   EXPECT_VALID(result); | 413   EXPECT_VALID(result); | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 428   // Build a mock message handler and wrap it in a dart port. | 427   // Build a mock message handler and wrap it in a dart port. | 
| 429   ServiceTestMessageHandler handler; | 428   ServiceTestMessageHandler handler; | 
| 430   Dart_Port port_id = PortMap::CreatePort(&handler); | 429   Dart_Port port_id = PortMap::CreatePort(&handler); | 
| 431   Dart_Handle port = Api::NewHandle(thread, SendPort::New(port_id)); | 430   Dart_Handle port = Api::NewHandle(thread, SendPort::New(port_id)); | 
| 432   EXPECT_VALID(port); | 431   EXPECT_VALID(port); | 
| 433   EXPECT_VALID(Dart_SetField(lib, NewString("port"), port)); | 432   EXPECT_VALID(Dart_SetField(lib, NewString("port"), port)); | 
| 434 | 433 | 
| 435   Array& service_msg = Array::Handle(); | 434   Array& service_msg = Array::Handle(); | 
| 436 | 435 | 
| 437   // Fetch object. | 436   // Fetch object. | 
| 438   service_msg = EvalF(lib, "[0, port, '0', 'getObject', " | 437   service_msg = EvalF(lib, | 
| 439                       "['objectId'], ['objects/%" Pd "']]", id); | 438                       "[0, port, '0', 'getObject', " | 
|  | 439                       "['objectId'], ['objects/%" Pd "']]", | 
|  | 440                       id); | 
| 440   HandleIsolateMessage(isolate, service_msg); | 441   HandleIsolateMessage(isolate, service_msg); | 
| 441   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 442   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 
| 442   // Check type. | 443   // Check type. | 
| 443   EXPECT_SUBSTRING("\"type\":\"Object\"", handler.msg()); | 444   EXPECT_SUBSTRING("\"type\":\"Object\"", handler.msg()); | 
| 444   EXPECT_SUBSTRING("\"_vmType\":\"PcDescriptors\"", handler.msg()); | 445   EXPECT_SUBSTRING("\"_vmType\":\"PcDescriptors\"", handler.msg()); | 
| 445   // Check for members array. | 446   // Check for members array. | 
| 446   EXPECT_SUBSTRING("\"members\":[", handler.msg()); | 447   EXPECT_SUBSTRING("\"members\":[", handler.msg()); | 
| 447 } | 448 } | 
| 448 | 449 | 
| 449 | 450 | 
| 450 TEST_CASE(Service_LocalVarDescriptors) { | 451 TEST_CASE(Service_LocalVarDescriptors) { | 
| 451   const char* kScript = | 452   const char* kScript = | 
| 452     "var port;\n"  // Set to our mock port by C++. | 453       "var port;\n"  // Set to our mock port by C++. | 
| 453     "\n" | 454       "\n" | 
| 454     "class A {\n" | 455       "class A {\n" | 
| 455     "  var a;\n" | 456       "  var a;\n" | 
| 456     "  dynamic b() {}\n" | 457       "  dynamic b() {}\n" | 
| 457     "  dynamic c() {\n" | 458       "  dynamic c() {\n" | 
| 458     "    var d = () { b(); };\n" | 459       "    var d = () { b(); };\n" | 
| 459     "    return d;\n" | 460       "    return d;\n" | 
| 460     "  }\n" | 461       "  }\n" | 
| 461     "}\n" | 462       "}\n" | 
| 462     "main() {\n" | 463       "main() {\n" | 
| 463     "  var z = new A();\n" | 464       "  var z = new A();\n" | 
| 464     "  var x = z.c();\n" | 465       "  var x = z.c();\n" | 
| 465     "  x();\n" | 466       "  x();\n" | 
| 466     "}"; | 467       "}"; | 
| 467 | 468 | 
| 468   Isolate* isolate = thread->isolate(); | 469   Isolate* isolate = thread->isolate(); | 
| 469   isolate->set_is_runnable(true); | 470   isolate->set_is_runnable(true); | 
| 470   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 471   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 
| 471   EXPECT_VALID(lib); | 472   EXPECT_VALID(lib); | 
| 472   Library& vmlib = Library::Handle(); | 473   Library& vmlib = Library::Handle(); | 
| 473   vmlib ^= Api::UnwrapHandle(lib); | 474   vmlib ^= Api::UnwrapHandle(lib); | 
| 474   EXPECT(!vmlib.IsNull()); | 475   EXPECT(!vmlib.IsNull()); | 
| 475   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 476   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 
| 476   EXPECT_VALID(result); | 477   EXPECT_VALID(result); | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 490   // Build a mock message handler and wrap it in a dart port. | 491   // Build a mock message handler and wrap it in a dart port. | 
| 491   ServiceTestMessageHandler handler; | 492   ServiceTestMessageHandler handler; | 
| 492   Dart_Port port_id = PortMap::CreatePort(&handler); | 493   Dart_Port port_id = PortMap::CreatePort(&handler); | 
| 493   Dart_Handle port = Api::NewHandle(thread, SendPort::New(port_id)); | 494   Dart_Handle port = Api::NewHandle(thread, SendPort::New(port_id)); | 
| 494   EXPECT_VALID(port); | 495   EXPECT_VALID(port); | 
| 495   EXPECT_VALID(Dart_SetField(lib, NewString("port"), port)); | 496   EXPECT_VALID(Dart_SetField(lib, NewString("port"), port)); | 
| 496 | 497 | 
| 497   Array& service_msg = Array::Handle(); | 498   Array& service_msg = Array::Handle(); | 
| 498 | 499 | 
| 499   // Fetch object. | 500   // Fetch object. | 
| 500   service_msg = EvalF(lib, "[0, port, '0', 'getObject', " | 501   service_msg = EvalF(lib, | 
| 501                       "['objectId'], ['objects/%" Pd "']]", id); | 502                       "[0, port, '0', 'getObject', " | 
|  | 503                       "['objectId'], ['objects/%" Pd "']]", | 
|  | 504                       id); | 
| 502   HandleIsolateMessage(isolate, service_msg); | 505   HandleIsolateMessage(isolate, service_msg); | 
| 503   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 506   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 
| 504   // Check type. | 507   // Check type. | 
| 505   EXPECT_SUBSTRING("\"type\":\"Object\"", handler.msg()); | 508   EXPECT_SUBSTRING("\"type\":\"Object\"", handler.msg()); | 
| 506   EXPECT_SUBSTRING("\"_vmType\":\"LocalVarDescriptors\"", handler.msg()); | 509   EXPECT_SUBSTRING("\"_vmType\":\"LocalVarDescriptors\"", handler.msg()); | 
| 507   // Check for members array. | 510   // Check for members array. | 
| 508   EXPECT_SUBSTRING("\"members\":[", handler.msg()); | 511   EXPECT_SUBSTRING("\"members\":[", handler.msg()); | 
| 509 } | 512 } | 
| 510 | 513 | 
| 511 | 514 | 
| 512 |  | 
| 513 static void WeakHandleFinalizer(void* isolate_callback_data, | 515 static void WeakHandleFinalizer(void* isolate_callback_data, | 
| 514                                 Dart_WeakPersistentHandle handle, | 516                                 Dart_WeakPersistentHandle handle, | 
| 515                                 void* peer) { | 517                                 void* peer) {} | 
| 516 } |  | 
| 517 | 518 | 
| 518 | 519 | 
| 519 TEST_CASE(Service_PersistentHandles) { | 520 TEST_CASE(Service_PersistentHandles) { | 
| 520   const char* kScript = | 521   const char* kScript = | 
| 521     "var port;\n"  // Set to our mock port by C++. | 522       "var port;\n"  // Set to our mock port by C++. | 
| 522     "\n" | 523       "\n" | 
| 523     "class A {\n" | 524       "class A {\n" | 
| 524     "  var a;\n" | 525       "  var a;\n" | 
| 525     "}\n" | 526       "}\n" | 
| 526     "var global = new A();\n" | 527       "var global = new A();\n" | 
| 527     "main() {\n" | 528       "main() {\n" | 
| 528     "  return global;\n" | 529       "  return global;\n" | 
| 529     "}"; | 530       "}"; | 
| 530 | 531 | 
| 531   Isolate* isolate = thread->isolate(); | 532   Isolate* isolate = thread->isolate(); | 
| 532   isolate->set_is_runnable(true); | 533   isolate->set_is_runnable(true); | 
| 533   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 534   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 
| 534   EXPECT_VALID(lib); | 535   EXPECT_VALID(lib); | 
| 535   Library& vmlib = Library::Handle(); | 536   Library& vmlib = Library::Handle(); | 
| 536   vmlib ^= Api::UnwrapHandle(lib); | 537   vmlib ^= Api::UnwrapHandle(lib); | 
| 537   EXPECT(!vmlib.IsNull()); | 538   EXPECT(!vmlib.IsNull()); | 
| 538   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 539   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 
| 539   EXPECT_VALID(result); | 540   EXPECT_VALID(result); | 
| 540 | 541 | 
| 541   // Create a persistent handle to global. | 542   // Create a persistent handle to global. | 
| 542   Dart_PersistentHandle persistent_handle = Dart_NewPersistentHandle(result); | 543   Dart_PersistentHandle persistent_handle = Dart_NewPersistentHandle(result); | 
| 543 | 544 | 
| 544   // Create a weak persistent handle to global. | 545   // Create a weak persistent handle to global. | 
| 545   Dart_WeakPersistentHandle weak_persistent_handle = | 546   Dart_WeakPersistentHandle weak_persistent_handle = | 
| 546       Dart_NewWeakPersistentHandle(result, | 547       Dart_NewWeakPersistentHandle(result, reinterpret_cast<void*>(0xdeadbeef), | 
| 547                                    reinterpret_cast<void*>(0xdeadbeef), | 548                                    128, WeakHandleFinalizer); | 
| 548                                    128, |  | 
| 549                                    WeakHandleFinalizer); |  | 
| 550 | 549 | 
| 551   // Build a mock message handler and wrap it in a dart port. | 550   // Build a mock message handler and wrap it in a dart port. | 
| 552   ServiceTestMessageHandler handler; | 551   ServiceTestMessageHandler handler; | 
| 553   Dart_Port port_id = PortMap::CreatePort(&handler); | 552   Dart_Port port_id = PortMap::CreatePort(&handler); | 
| 554   Dart_Handle port = Api::NewHandle(thread, SendPort::New(port_id)); | 553   Dart_Handle port = Api::NewHandle(thread, SendPort::New(port_id)); | 
| 555   EXPECT_VALID(port); | 554   EXPECT_VALID(port); | 
| 556   EXPECT_VALID(Dart_SetField(lib, NewString("port"), port)); | 555   EXPECT_VALID(Dart_SetField(lib, NewString("port"), port)); | 
| 557 | 556 | 
| 558   Array& service_msg = Array::Handle(); | 557   Array& service_msg = Array::Handle(); | 
| 559 | 558 | 
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 606   const String& str = String::Handle(String::New("foobar", Heap::kOld)); | 605   const String& str = String::Handle(String::New("foobar", Heap::kOld)); | 
| 607   Array& service_msg = Array::Handle(); | 606   Array& service_msg = Array::Handle(); | 
| 608   // Note: If we ever introduce old space compaction, this test might fail. | 607   // Note: If we ever introduce old space compaction, this test might fail. | 
| 609   uword start_addr = RawObject::ToAddr(str.raw()); | 608   uword start_addr = RawObject::ToAddr(str.raw()); | 
| 610   // Expect to find 'str', also from internal addresses. | 609   // Expect to find 'str', also from internal addresses. | 
| 611   for (int offset = 0; offset < kObjectAlignment; ++offset) { | 610   for (int offset = 0; offset < kObjectAlignment; ++offset) { | 
| 612     uword addr = start_addr + offset; | 611     uword addr = start_addr + offset; | 
| 613     char buf[1024]; | 612     char buf[1024]; | 
| 614     bool ref = offset % 2 == 0; | 613     bool ref = offset % 2 == 0; | 
| 615     OS::SNPrint(buf, sizeof(buf), | 614     OS::SNPrint(buf, sizeof(buf), | 
| 616                 (ref | 615                 (ref ? "[0, port, '0', '_getObjectByAddress', " | 
| 617                  ? "[0, port, '0', '_getObjectByAddress', " | 616                        "['address', 'ref'], ['%" Px "', 'true']]" | 
| 618                    "['address', 'ref'], ['%" Px "', 'true']]" | 617                      : "[0, port, '0', '_getObjectByAddress', " | 
| 619                  : "[0, port, '0', '_getObjectByAddress', " | 618                        "['address'], ['%" Px "']]"), | 
| 620                    "['address'], ['%" Px "']]"), |  | 
| 621                 addr); | 619                 addr); | 
| 622     service_msg = Eval(lib, buf); | 620     service_msg = Eval(lib, buf); | 
| 623     HandleIsolateMessage(isolate, service_msg); | 621     HandleIsolateMessage(isolate, service_msg); | 
| 624     EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 622     EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 
| 625     EXPECT_SUBSTRING(ref ? "\"type\":\"@Instance\"" : | 623     EXPECT_SUBSTRING(ref ? "\"type\":\"@Instance\"" : "\"type\":\"Instance\"", | 
| 626                            "\"type\":\"Instance\"", |  | 
| 627                      handler.msg()); | 624                      handler.msg()); | 
| 628     EXPECT_SUBSTRING("\"kind\":\"String\"", handler.msg()); | 625     EXPECT_SUBSTRING("\"kind\":\"String\"", handler.msg()); | 
| 629     EXPECT_SUBSTRING("foobar", handler.msg()); | 626     EXPECT_SUBSTRING("foobar", handler.msg()); | 
| 630   } | 627   } | 
| 631   // Expect null when no object is found. | 628   // Expect null when no object is found. | 
| 632   service_msg = Eval(lib, "[0, port, '0', '_getObjectByAddress', " | 629   service_msg = Eval(lib, | 
|  | 630                      "[0, port, '0', '_getObjectByAddress', " | 
| 633                      "['address'], ['7']]"); | 631                      "['address'], ['7']]"); | 
| 634   HandleIsolateMessage(isolate, service_msg); | 632   HandleIsolateMessage(isolate, service_msg); | 
| 635   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 633   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 
| 636   // TODO(turnidge): Should this be a ServiceException instead? | 634   // TODO(turnidge): Should this be a ServiceException instead? | 
| 637   EXPECT_SUBSTRING("{\"type\":\"Sentinel\",\"kind\":\"Free\"," | 635   EXPECT_SUBSTRING( | 
| 638                    "\"valueAsString\":\"<free>\"", | 636       "{\"type\":\"Sentinel\",\"kind\":\"Free\"," | 
| 639                handler.msg()); | 637       "\"valueAsString\":\"<free>\"", | 
|  | 638       handler.msg()); | 
| 640 } | 639 } | 
| 641 | 640 | 
| 642 | 641 | 
| 643 static bool alpha_callback( | 642 static bool alpha_callback(const char* name, | 
| 644     const char* name, | 643                            const char** option_keys, | 
| 645     const char** option_keys, | 644                            const char** option_values, | 
| 646     const char** option_values, | 645                            intptr_t num_options, | 
| 647     intptr_t num_options, | 646                            void* user_data, | 
| 648     void* user_data, | 647                            const char** result) { | 
| 649     const char** result) { |  | 
| 650   *result = strdup("alpha"); | 648   *result = strdup("alpha"); | 
| 651   return true; | 649   return true; | 
| 652 } | 650 } | 
| 653 | 651 | 
| 654 | 652 | 
| 655 static bool beta_callback( | 653 static bool beta_callback(const char* name, | 
| 656     const char* name, | 654                           const char** option_keys, | 
| 657     const char** option_keys, | 655                           const char** option_values, | 
| 658     const char** option_values, | 656                           intptr_t num_options, | 
| 659     intptr_t num_options, | 657                           void* user_data, | 
| 660     void* user_data, | 658                           const char** result) { | 
| 661     const char** result) { |  | 
| 662   *result = strdup("beta"); | 659   *result = strdup("beta"); | 
| 663   return false; | 660   return false; | 
| 664 } | 661 } | 
| 665 | 662 | 
| 666 | 663 | 
| 667 TEST_CASE(Service_EmbedderRootHandler) { | 664 TEST_CASE(Service_EmbedderRootHandler) { | 
| 668   const char* kScript = | 665   const char* kScript = | 
| 669     "var port;\n"  // Set to our mock port by C++. | 666       "var port;\n"  // Set to our mock port by C++. | 
| 670     "\n" | 667       "\n" | 
| 671     "var x = 7;\n" | 668       "var x = 7;\n" | 
| 672     "main() {\n" | 669       "main() {\n" | 
| 673     "  x = x * x;\n" | 670       "  x = x * x;\n" | 
| 674     "  x = x / 13;\n" | 671       "  x = x / 13;\n" | 
| 675     "}"; | 672       "}"; | 
| 676 | 673 | 
| 677   Dart_RegisterRootServiceRequestCallback("alpha", alpha_callback, NULL); | 674   Dart_RegisterRootServiceRequestCallback("alpha", alpha_callback, NULL); | 
| 678   Dart_RegisterRootServiceRequestCallback("beta", beta_callback, NULL); | 675   Dart_RegisterRootServiceRequestCallback("beta", beta_callback, NULL); | 
| 679 | 676 | 
| 680   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 677   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 
| 681   EXPECT_VALID(lib); | 678   EXPECT_VALID(lib); | 
| 682   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 679   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 
| 683   EXPECT_VALID(result); | 680   EXPECT_VALID(result); | 
| 684 | 681 | 
| 685   // Build a mock message handler and wrap it in a dart port. | 682   // Build a mock message handler and wrap it in a dart port. | 
| 686   ServiceTestMessageHandler handler; | 683   ServiceTestMessageHandler handler; | 
| 687   Dart_Port port_id = PortMap::CreatePort(&handler); | 684   Dart_Port port_id = PortMap::CreatePort(&handler); | 
| 688   Dart_Handle port = Api::NewHandle(thread, SendPort::New(port_id)); | 685   Dart_Handle port = Api::NewHandle(thread, SendPort::New(port_id)); | 
| 689   EXPECT_VALID(port); | 686   EXPECT_VALID(port); | 
| 690   EXPECT_VALID(Dart_SetField(lib, NewString("port"), port)); | 687   EXPECT_VALID(Dart_SetField(lib, NewString("port"), port)); | 
| 691 | 688 | 
| 692 | 689 | 
| 693   Array& service_msg = Array::Handle(); | 690   Array& service_msg = Array::Handle(); | 
| 694   service_msg = Eval(lib, "[0, port, '\"', 'alpha', [], []]"); | 691   service_msg = Eval(lib, "[0, port, '\"', 'alpha', [], []]"); | 
| 695   HandleRootMessage(service_msg); | 692   HandleRootMessage(service_msg); | 
| 696   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 693   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 
| 697   EXPECT_STREQ("{\"jsonrpc\":\"2.0\", \"result\":alpha,\"id\":\"\\\"\"}", | 694   EXPECT_STREQ("{\"jsonrpc\":\"2.0\", \"result\":alpha,\"id\":\"\\\"\"}", | 
| 698                handler.msg()); | 695                handler.msg()); | 
| 699   service_msg = Eval(lib, "[0, port, 1, 'beta', [], []]"); | 696   service_msg = Eval(lib, "[0, port, 1, 'beta', [], []]"); | 
| 700   HandleRootMessage(service_msg); | 697   HandleRootMessage(service_msg); | 
| 701   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 698   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 
| 702   EXPECT_STREQ("{\"jsonrpc\":\"2.0\", \"error\":beta,\"id\":1}", | 699   EXPECT_STREQ("{\"jsonrpc\":\"2.0\", \"error\":beta,\"id\":1}", handler.msg()); | 
| 703                handler.msg()); |  | 
| 704 } | 700 } | 
| 705 | 701 | 
| 706 | 702 | 
| 707 TEST_CASE(Service_EmbedderIsolateHandler) { | 703 TEST_CASE(Service_EmbedderIsolateHandler) { | 
| 708   const char* kScript = | 704   const char* kScript = | 
| 709     "var port;\n"  // Set to our mock port by C++. | 705       "var port;\n"  // Set to our mock port by C++. | 
| 710     "\n" | 706       "\n" | 
| 711     "var x = 7;\n" | 707       "var x = 7;\n" | 
| 712     "main() {\n" | 708       "main() {\n" | 
| 713     "  x = x * x;\n" | 709       "  x = x * x;\n" | 
| 714     "  x = x / 13;\n" | 710       "  x = x / 13;\n" | 
| 715     "}"; | 711       "}"; | 
| 716 | 712 | 
| 717   Dart_RegisterIsolateServiceRequestCallback("alpha", alpha_callback, NULL); | 713   Dart_RegisterIsolateServiceRequestCallback("alpha", alpha_callback, NULL); | 
| 718   Dart_RegisterIsolateServiceRequestCallback("beta", beta_callback, NULL); | 714   Dart_RegisterIsolateServiceRequestCallback("beta", beta_callback, NULL); | 
| 719 | 715 | 
| 720   Isolate* isolate = thread->isolate(); | 716   Isolate* isolate = thread->isolate(); | 
| 721   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 717   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 
| 722   EXPECT_VALID(lib); | 718   EXPECT_VALID(lib); | 
| 723   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 719   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 
| 724   EXPECT_VALID(result); | 720   EXPECT_VALID(result); | 
| 725 | 721 | 
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 790   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 786   EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage()); | 
| 791   // Expect error. | 787   // Expect error. | 
| 792   EXPECT_SUBSTRING("\"error\"", handler.msg()); | 788   EXPECT_SUBSTRING("\"error\"", handler.msg()); | 
| 793 } | 789 } | 
| 794 | 790 | 
| 795 #endif  // !defined(TARGET_ARCH_ARM64) | 791 #endif  // !defined(TARGET_ARCH_ARM64) | 
| 796 | 792 | 
| 797 #endif  // !PRODUCT | 793 #endif  // !PRODUCT | 
| 798 | 794 | 
| 799 }  // namespace dart | 795 }  // namespace dart | 
| OLD | NEW | 
|---|