| Index: runtime/vm/service_test.cc
|
| ===================================================================
|
| --- runtime/vm/service_test.cc (revision 37949)
|
| +++ runtime/vm/service_test.cc (working copy)
|
| @@ -608,6 +608,119 @@
|
| }
|
|
|
|
|
| +TEST_CASE(Service_RetainingPath) {
|
| + const char* kScript =
|
| + "var port;\n" // Set to our mock port by C++.
|
| + "var id0;\n" // Set to an object id by C++.
|
| + "var id1;\n" // Ditto.
|
| + "var idElem;\n" // Ditto.
|
| + "class Foo {\n"
|
| + " String f0;\n"
|
| + " String f1;\n"
|
| + "}\n"
|
| + "Foo foo;\n"
|
| + "List<String> lst;\n"
|
| + "main() {\n"
|
| + " foo = new Foo();\n"
|
| + " lst = new List<String>(100);\n"
|
| + "}\n";
|
| + Isolate* isolate = Isolate::Current();
|
| + Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL);
|
| + EXPECT_VALID(h_lib);
|
| + Library& lib = Library::Handle();
|
| + lib ^= Api::UnwrapHandle(h_lib);
|
| + EXPECT(!lib.IsNull());
|
| + Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
|
| + EXPECT_VALID(result);
|
| + const Class& class_foo = Class::Handle(GetClass(lib, "Foo"));
|
| + EXPECT(!class_foo.IsNull());
|
| + Dart_Handle foo = Dart_GetField(h_lib, NewString("foo"));
|
| + Dart_Handle lst = Dart_GetField(h_lib, NewString("lst"));
|
| + const intptr_t kElemIndex = 42;
|
| + {
|
| + Dart_EnterScope();
|
| + ObjectIdRing* ring = isolate->object_id_ring();
|
| + {
|
| + const String& foo0 = String::Handle(String::New("foo0", Heap::kOld));
|
| + Dart_Handle h_foo0 = Api::NewHandle(isolate, foo0.raw());
|
| + EXPECT_VALID(Dart_SetField(foo, NewString("f0"), h_foo0));
|
| + Dart_Handle id0 = Dart_NewInteger(ring->GetIdForObject(foo0.raw()));
|
| + EXPECT_VALID(id0);
|
| + EXPECT_VALID(Dart_SetField(h_lib, NewString("id0"), id0));
|
| + }
|
| + {
|
| + const String& foo1 = String::Handle(String::New("foo1", Heap::kOld));
|
| + Dart_Handle h_foo1 = Api::NewHandle(isolate, foo1.raw());
|
| + EXPECT_VALID(Dart_SetField(foo, NewString("f1"), h_foo1));
|
| + Dart_Handle id1 = Dart_NewInteger(ring->GetIdForObject(foo1.raw()));
|
| + EXPECT_VALID(id1);
|
| + EXPECT_VALID(Dart_SetField(h_lib, NewString("id1"), id1));
|
| + }
|
| + {
|
| + const String& elem = String::Handle(String::New("elem", Heap::kOld));
|
| + Dart_Handle h_elem = Api::NewHandle(isolate, elem.raw());
|
| + EXPECT_VALID(Dart_ListSetAt(lst, kElemIndex, h_elem));
|
| + Dart_Handle idElem = Dart_NewInteger(ring->GetIdForObject(elem.raw()));
|
| + EXPECT_VALID(idElem);
|
| + EXPECT_VALID(Dart_SetField(h_lib, NewString("idElem"), idElem));
|
| + }
|
| + Dart_ExitScope();
|
| + }
|
| +
|
| + // Build a mock message handler and wrap it in a dart port.
|
| + ServiceTestMessageHandler handler;
|
| + Dart_Port port_id = PortMap::CreatePort(&handler);
|
| + Dart_Handle port = Api::NewHandle(isolate, SendPort::New(port_id));
|
| + EXPECT_VALID(port);
|
| + EXPECT_VALID(Dart_SetField(h_lib, NewString("port"), port));
|
| + Instance& service_msg = Instance::Handle();
|
| +
|
| + // Retaining path to 'foo0', limit 2.
|
| + service_msg = Eval(
|
| + h_lib,
|
| + "[0, port, ['objects', '$id0', 'retaining_path'], ['limit'], ['2']]");
|
| + Service::HandleIsolateMessage(isolate, service_msg);
|
| + handler.HandleNextMessage();
|
| + ExpectSubstringF(
|
| + handler.msg(),
|
| + "{\"type\":\"RetainingPath\",\"id\":\"retaining_path\",\"length\":2,"
|
| + "\"elements\":[{\"index\":0,\"value\":{\"type\":\"@String\"");
|
| + ExpectSubstringF(handler.msg(), "\"parentField\":{\"type\":\"@Field\"");
|
| + ExpectSubstringF(handler.msg(), "\"name\":\"f0\"");
|
| + ExpectSubstringF(handler.msg(),
|
| + "{\"index\":1,\"value\":{\"type\":\"@Instance\"");
|
| +
|
| + // Retaining path to 'foo1', limit 2.
|
| + service_msg = Eval(
|
| + h_lib,
|
| + "[0, port, ['objects', '$id1', 'retaining_path'], ['limit'], ['2']]");
|
| + Service::HandleIsolateMessage(isolate, service_msg);
|
| + handler.HandleNextMessage();
|
| + ExpectSubstringF(
|
| + handler.msg(),
|
| + "{\"type\":\"RetainingPath\",\"id\":\"retaining_path\",\"length\":2,"
|
| + "\"elements\":[{\"index\":0,\"value\":{\"type\":\"@String\"");
|
| + ExpectSubstringF(handler.msg(), "\"parentField\":{\"type\":\"@Field\"");
|
| + ExpectSubstringF(handler.msg(), "\"name\":\"f1\"");
|
| + ExpectSubstringF(handler.msg(),
|
| + "{\"index\":1,\"value\":{\"type\":\"@Instance\"");
|
| +
|
| + // Retaining path to 'elem', limit 2.
|
| + service_msg = Eval(
|
| + h_lib,
|
| + "[0, port, ['objects', '$idElem', 'retaining_path'], ['limit'], ['2']]");
|
| + Service::HandleIsolateMessage(isolate, service_msg);
|
| + handler.HandleNextMessage();
|
| + ExpectSubstringF(
|
| + handler.msg(),
|
| + "{\"type\":\"RetainingPath\",\"id\":\"retaining_path\",\"length\":2,"
|
| + "\"elements\":[{\"index\":0,\"value\":{\"type\":\"@String\"");
|
| + ExpectSubstringF(handler.msg(), "\"parentListIndex\":%" Pd, kElemIndex);
|
| + ExpectSubstringF(handler.msg(),
|
| + "{\"index\":1,\"value\":{\"type\":\"@Array\"");
|
| +}
|
| +
|
| +
|
| TEST_CASE(Service_Libraries) {
|
| const char* kScript =
|
| "var port;\n" // Set to our mock port by C++.
|
|
|