Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
service_test.cc
Go to the documentation of this 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
3// BSD-style license that can be found in the LICENSE file.
4
5#include <memory>
6
7#include "platform/globals.h"
8
10#include "vm/dart_api_impl.h"
11#include "vm/dart_entry.h"
12#include "vm/debugger.h"
14#include "vm/globals.h"
15#include "vm/heap/safepoint.h"
16#include "vm/message_handler.h"
17#include "vm/message_snapshot.h"
18#include "vm/object_id_ring.h"
19#include "vm/os.h"
20#include "vm/port.h"
21#include "vm/profiler.h"
22#include "vm/resolver.h"
23#include "vm/service.h"
24#include "vm/unit_test.h"
25
26namespace dart {
27
28// This flag is used in the Service_Flags test below.
29DEFINE_FLAG(bool, service_testing_flag, false, "Comment");
30
31#ifndef PRODUCT
32
34 public:
35 ServiceTestMessageHandler() : _msg(nullptr) {}
36
39 free(_msg);
40 }
41
42 MessageStatus HandleMessage(std::unique_ptr<Message> message) {
43 if (_msg != nullptr) {
44 free(_msg);
45 _msg = nullptr;
46 }
47
48 // Parse the message.
49 Object& response_obj = Object::Handle();
50 if (message->IsRaw()) {
51 response_obj = message->raw_obj();
52 } else {
54 response_obj = ReadMessage(thread, message.get());
55 }
56 if (response_obj.IsString()) {
57 String& response = String::Handle();
58 response ^= response_obj.ptr();
59 _msg = Utils::StrDup(response.ToCString());
60 } else {
61 ASSERT(response_obj.IsArray());
62 Array& response_array = Array::Handle();
63 response_array ^= response_obj.ptr();
64 ASSERT(response_array.Length() == 1);
66 response ^= response_array.At(0);
67 _msg = Utils::StrDup(reinterpret_cast<char*>(response.DataAddr(0)));
68 }
69
70 return kOK;
71 }
72
73 const char* msg() const { return _msg; }
74
75 virtual Isolate* isolate() const { return Isolate::Current(); }
76
77 private:
78 char* _msg;
79};
80
81static ArrayPtr Eval(Dart_Handle lib, const char* expr) {
82 const String& dummy_isolate_id = String::Handle(String::New("isolateId"));
83 Dart_Handle expr_val;
84 {
86 expr_val = Dart_EvaluateStaticExpr(lib, NewString(expr));
87 EXPECT_VALID(expr_val);
88 }
89 Zone* zone = Thread::Current()->zone();
91 Api::UnwrapGrowableObjectArrayHandle(zone, expr_val);
94 growable ^= result.At(4);
95 // Append dummy isolate id to parameter values.
96 growable.Add(dummy_isolate_id);
97 Array& array = Array::Handle(Array::MakeFixedLength(growable));
98 result.SetAt(4, array);
99 growable ^= result.At(5);
100 // Append dummy isolate id to parameter values.
101 growable.Add(dummy_isolate_id);
102 array = Array::MakeFixedLength(growable);
103 result.SetAt(5, array);
104 return result.ptr();
105}
106
107static ArrayPtr EvalF(Dart_Handle lib, const char* fmt, ...) {
108 va_list measure_args;
109 va_start(measure_args, fmt);
110 intptr_t len = Utils::VSNPrint(nullptr, 0, fmt, measure_args);
111 va_end(measure_args);
112
113 char* buffer = Thread::Current()->zone()->Alloc<char>(len + 1);
114 va_list print_args;
115 va_start(print_args, fmt);
116 Utils::VSNPrint(buffer, (len + 1), fmt, print_args);
117 va_end(print_args);
118
119 return Eval(lib, buffer);
120}
121
122static FunctionPtr GetFunction(const Class& cls, const char* name) {
125 EXPECT(!result.IsNull());
126 return result.ptr();
127}
128
129static ClassPtr GetClass(const Library& lib, const char* name) {
130 const Class& cls = Class::Handle(
131 lib.LookupClass(String::Handle(Symbols::New(Thread::Current(), name))));
132 EXPECT(!cls.IsNull()); // No ambiguity error expected.
133 return cls.ptr();
134}
135
136static void HandleIsolateMessage(Isolate* isolate, const Array& msg) {
137 Service::HandleIsolateMessage(isolate, msg);
138}
139
143
144ISOLATE_UNIT_TEST_CASE(Service_IsolateStickyError) {
145 const char* kScript = "main() => throw 'HI THERE STICKY';\n";
146
147 Isolate* isolate = thread->isolate();
148 isolate->set_is_runnable(true);
150 {
151 TransitionVMToNative transition(thread);
152 Dart_Handle lib = TestCase::LoadTestScript(kScript, nullptr);
153 EXPECT_VALID(lib);
154 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
157 }
158 EXPECT(Thread::Current()->sticky_error() == Error::null());
159
160 {
161 JSONStream js;
162 isolate->PrintJSON(&js, false);
163 // No error property and no PauseExit state.
164 EXPECT_NOTSUBSTRING("\"error\":", js.ToCString());
165 EXPECT_NOTSUBSTRING("HI THERE STICKY", js.ToCString());
166 EXPECT_NOTSUBSTRING("PauseExit", js.ToCString());
167 }
168
169 {
170 // Set the sticky error.
171 TransitionVMToNative transition(thread);
175 }
176
177 {
178 JSONStream js;
179 isolate->PrintJSON(&js, false);
180 // Error and PauseExit set.
181 EXPECT_SUBSTRING("\"error\":", js.ToCString());
182 EXPECT_SUBSTRING("HI THERE STICKY", js.ToCString());
183 EXPECT_SUBSTRING("PauseExit", js.ToCString());
184 }
185}
186
187ISOLATE_UNIT_TEST_CASE(Service_IdZones) {
188 Zone* zone = thread->zone();
189 Isolate* isolate = thread->isolate();
190 ObjectIdRing* ring = isolate->EnsureObjectIdRing();
191
192 const String& test_a = String::Handle(zone, String::New("a"));
193 const String& test_b = String::Handle(zone, String::New("b"));
194 const String& test_c = String::Handle(zone, String::New("c"));
195 const String& test_d = String::Handle(zone, String::New("d"));
196
197 // Both RingServiceIdZones share the same backing store and id space.
198
199 // Always allocate a new id.
200 RingServiceIdZone always_new_zone;
201 always_new_zone.Init(ring, ObjectIdRing::kAllocateId);
202 EXPECT_STREQ("objects/0", always_new_zone.GetServiceId(test_a));
203 EXPECT_STREQ("objects/1", always_new_zone.GetServiceId(test_a));
204 EXPECT_STREQ("objects/2", always_new_zone.GetServiceId(test_a));
205 EXPECT_STREQ("objects/3", always_new_zone.GetServiceId(test_b));
206 EXPECT_STREQ("objects/4", always_new_zone.GetServiceId(test_c));
207
208 // Reuse an existing id or allocate a new id.
209 RingServiceIdZone reuse_zone;
210 reuse_zone.Init(ring, ObjectIdRing::kReuseId);
211 EXPECT_STREQ("objects/0", reuse_zone.GetServiceId(test_a));
212 EXPECT_STREQ("objects/0", reuse_zone.GetServiceId(test_a));
213 EXPECT_STREQ("objects/3", reuse_zone.GetServiceId(test_b));
214 EXPECT_STREQ("objects/3", reuse_zone.GetServiceId(test_b));
215 EXPECT_STREQ("objects/4", reuse_zone.GetServiceId(test_c));
216 EXPECT_STREQ("objects/4", reuse_zone.GetServiceId(test_c));
217 EXPECT_STREQ("objects/5", reuse_zone.GetServiceId(test_d));
218 EXPECT_STREQ("objects/5", reuse_zone.GetServiceId(test_d));
219}
220
222 const char* kScript =
223 "var port;\n" // Set to our mock port by C++.
224 "\n"
225 "class A {\n"
226 " var a;\n"
227 " dynamic b() {}\n"
228 " dynamic c() {\n"
229 " var d = () { b(); };\n"
230 " return d;\n"
231 " }\n"
232 "}\n"
233 "main() {\n"
234 " var z = new A();\n"
235 " var x = z.c();\n"
236 " x();\n"
237 "}";
238
239 Isolate* isolate = thread->isolate();
240 isolate->set_is_runnable(true);
241 Dart_Handle lib;
242 Library& vmlib = Library::Handle();
243 {
244 TransitionVMToNative transition(thread);
245 lib = TestCase::LoadTestScript(kScript, nullptr);
246 EXPECT_VALID(lib);
247 EXPECT(!Dart_IsNull(lib));
248 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
250 }
251 vmlib ^= Api::UnwrapHandle(lib);
252 EXPECT(!vmlib.IsNull());
253 const Class& class_a = Class::Handle(GetClass(vmlib, "A"));
254 EXPECT(!class_a.IsNull());
255 const Function& function_c = Function::Handle(GetFunction(class_a, "c"));
256 EXPECT(!function_c.IsNull());
257 const Code& code_c = Code::Handle(function_c.CurrentCode());
258 EXPECT(!code_c.IsNull());
259 // Use the entry of the code object as it's reference.
260 uword entry = code_c.PayloadStart();
261 int64_t compile_timestamp = code_c.compile_timestamp();
262 EXPECT_GT(code_c.Size(), 16u);
263 uword last = entry + code_c.Size();
264
265 // Build a mock message handler and wrap it in a dart port.
267 Dart_Port port_id = PortMap::CreatePort(&handler);
268 Dart_Handle port = Api::NewHandle(thread, SendPort::New(port_id));
269 {
270 TransitionVMToNative transition(thread);
271 EXPECT_VALID(port);
272 EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
273 }
274
275 Array& service_msg = Array::Handle();
276
277 // Request an invalid code object.
278 service_msg =
279 Eval(lib, "[0, port, '0', 'getObject', ['objectId'], ['code/0']]");
280 HandleIsolateMessage(isolate, service_msg);
281 EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
282 EXPECT_SUBSTRING("\"error\"", handler.msg());
283
284 // The following test checks that a code object can be found only
285 // at compile_timestamp()-code.EntryPoint().
286 service_msg = EvalF(lib,
287 "[0, port, '0', 'getObject', "
288 "['objectId'], ['code/%" Px64 "-%" Px "']]",
289 compile_timestamp, entry);
290 HandleIsolateMessage(isolate, service_msg);
291 EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
292 EXPECT_SUBSTRING("\"type\":\"Code\"", handler.msg());
293 {
294 // Only perform a partial match.
295 const intptr_t kBufferSize = 512;
296 char buffer[kBufferSize];
298 "\"fixedId\":true,\"id\":\"code\\/%" Px64 "-%" Px "\",",
299 compile_timestamp, entry);
300 EXPECT_SUBSTRING(buffer, handler.msg());
301 }
302
303 // Request code object at compile_timestamp-code.EntryPoint() + 16
304 // Expect this to fail because the address is not the entry point.
305 uintptr_t address = entry + 16;
306 service_msg = EvalF(lib,
307 "[0, port, '0', 'getObject', "
308 "['objectId'], ['code/%" Px64 "-%" Px "']]",
309 compile_timestamp, address);
310 HandleIsolateMessage(isolate, service_msg);
311 EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
312 EXPECT_SUBSTRING("\"error\"", handler.msg());
313
314 // Request code object at (compile_timestamp - 1)-code.EntryPoint()
315 // Expect this to fail because the timestamp is wrong.
316 address = entry;
317 service_msg = EvalF(lib,
318 "[0, port, '0', 'getObject', "
319 "['objectId'], ['code/%" Px64 "-%" Px "']]",
320 compile_timestamp - 1, address);
321 HandleIsolateMessage(isolate, service_msg);
322 EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
323 EXPECT_SUBSTRING("\"error\"", handler.msg());
324
325 // Request native code at address. Expect the null code object back.
326 address = last;
327 service_msg = EvalF(lib,
328 "[0, port, '0', 'getObject', "
329 "['objectId'], ['code/native-%" Px "']]",
330 address);
331 HandleIsolateMessage(isolate, service_msg);
332 EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
333 // TODO(turnidge): It is pretty broken to return an Instance here. Fix.
334 EXPECT_SUBSTRING("\"kind\":\"Null\"", handler.msg());
335
336 // Request malformed native code.
337 service_msg = EvalF(lib,
338 "[0, port, '0', 'getObject', ['objectId'], "
339 "['code/native%" Px "']]",
340 address);
341 HandleIsolateMessage(isolate, service_msg);
342 EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
343 EXPECT_SUBSTRING("\"error\"", handler.msg());
344}
345
346ISOLATE_UNIT_TEST_CASE(Service_PcDescriptors) {
347 const char* kScript =
348 "var port;\n" // Set to our mock port by C++.
349 "\n"
350 "class A {\n"
351 " var a;\n"
352 " dynamic b() {}\n"
353 " dynamic c() {\n"
354 " var d = () { b(); };\n"
355 " return d;\n"
356 " }\n"
357 "}\n"
358 "main() {\n"
359 " var z = new A();\n"
360 " var x = z.c();\n"
361 " x();\n"
362 "}";
363
364 Isolate* isolate = thread->isolate();
365 isolate->set_is_runnable(true);
366 Dart_Handle lib;
367 Library& vmlib = Library::Handle();
368 {
369 TransitionVMToNative transition(thread);
370 lib = TestCase::LoadTestScript(kScript, nullptr);
371 EXPECT_VALID(lib);
372 EXPECT(!Dart_IsNull(lib));
373 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
375 }
376 vmlib ^= Api::UnwrapHandle(lib);
377 EXPECT(!vmlib.IsNull());
378 const Class& class_a = Class::Handle(GetClass(vmlib, "A"));
379 EXPECT(!class_a.IsNull());
380 const Function& function_c = Function::Handle(GetFunction(class_a, "c"));
381 EXPECT(!function_c.IsNull());
382 const Code& code_c = Code::Handle(function_c.CurrentCode());
383 EXPECT(!code_c.IsNull());
384
385 const PcDescriptors& descriptors =
387 EXPECT(!descriptors.IsNull());
388 ObjectIdRing* ring = isolate->EnsureObjectIdRing();
389 intptr_t id = ring->GetIdForObject(descriptors.ptr());
390
391 // Build a mock message handler and wrap it in a dart port.
393 Dart_Port port_id = PortMap::CreatePort(&handler);
394 Dart_Handle port = Api::NewHandle(thread, SendPort::New(port_id));
395 {
396 TransitionVMToNative transition(thread);
397 EXPECT_VALID(port);
398 EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
399 }
400
401 Array& service_msg = Array::Handle();
402
403 // Fetch object.
404 service_msg = EvalF(lib,
405 "[0, port, '0', 'getObject', "
406 "['objectId'], ['objects/%" Pd "']]",
407 id);
408 HandleIsolateMessage(isolate, service_msg);
409 EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
410 // Check type.
411 EXPECT_SUBSTRING("\"type\":\"Object\"", handler.msg());
412 EXPECT_SUBSTRING("\"_vmType\":\"PcDescriptors\"", handler.msg());
413 // Check for members array.
414 EXPECT_SUBSTRING("\"members\":[", handler.msg());
415}
416
417ISOLATE_UNIT_TEST_CASE(Service_LocalVarDescriptors) {
418 const char* kScript =
419 "var port;\n" // Set to our mock port by C++.
420 "\n"
421 "class A {\n"
422 " var a;\n"
423 " dynamic b() {}\n"
424 " dynamic c() {\n"
425 " var d = () { b(); };\n"
426 " return d;\n"
427 " }\n"
428 "}\n"
429 "main() {\n"
430 " var z = new A();\n"
431 " var x = z.c();\n"
432 " x();\n"
433 "}";
434
435 Isolate* isolate = thread->isolate();
436 isolate->set_is_runnable(true);
437 Dart_Handle lib;
438 Library& vmlib = Library::Handle();
439 {
440 TransitionVMToNative transition(thread);
441 lib = TestCase::LoadTestScript(kScript, nullptr);
442 EXPECT_VALID(lib);
443 EXPECT(!Dart_IsNull(lib));
444 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
446 }
447 vmlib ^= Api::UnwrapHandle(lib);
448 EXPECT(!vmlib.IsNull());
449 const Class& class_a = Class::Handle(GetClass(vmlib, "A"));
450 EXPECT(!class_a.IsNull());
451 const Function& function_c = Function::Handle(GetFunction(class_a, "c"));
452 EXPECT(!function_c.IsNull());
453 const Code& code_c = Code::Handle(function_c.CurrentCode());
454 EXPECT(!code_c.IsNull());
455
456 const LocalVarDescriptors& descriptors =
458 // Generate an ID for this object.
459 ObjectIdRing* ring = isolate->EnsureObjectIdRing();
460 intptr_t id = ring->GetIdForObject(descriptors.ptr());
461
462 // Build a mock message handler and wrap it in a dart port.
464 Dart_Port port_id = PortMap::CreatePort(&handler);
465 Dart_Handle port = Api::NewHandle(thread, SendPort::New(port_id));
466 {
467 TransitionVMToNative transition(thread);
468 EXPECT_VALID(port);
469 EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
470 }
471
472 Array& service_msg = Array::Handle();
473
474 // Fetch object.
475 service_msg = EvalF(lib,
476 "[0, port, '0', 'getObject', "
477 "['objectId'], ['objects/%" Pd "']]",
478 id);
479 HandleIsolateMessage(isolate, service_msg);
480 EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
481 // Check type.
482 EXPECT_SUBSTRING("\"type\":\"Object\"", handler.msg());
483 EXPECT_SUBSTRING("\"_vmType\":\"LocalVarDescriptors\"", handler.msg());
484 // Check for members array.
485 EXPECT_SUBSTRING("\"members\":[", handler.msg());
486}
487
488static void WeakHandleFinalizer(void* isolate_callback_data, void* peer) {}
489
490ISOLATE_UNIT_TEST_CASE(Service_PersistentHandles) {
491 const char* kScript =
492 "var port;\n" // Set to our mock port by C++.
493 "\n"
494 "class A {\n"
495 " var a;\n"
496 "}\n"
497 "var global = new A();\n"
498 "main() {\n"
499 " return global;\n"
500 "}";
501
502 Isolate* isolate = thread->isolate();
503 isolate->set_is_runnable(true);
504
505 Dart_Handle lib;
506 Dart_PersistentHandle persistent_handle;
507 Dart_WeakPersistentHandle weak_persistent_handle;
508 {
509 TransitionVMToNative transition(thread);
510 lib = TestCase::LoadTestScript(kScript, nullptr);
511 EXPECT_VALID(lib);
512 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
514
515 // Create a persistent handle to global.
516 persistent_handle = Dart_NewPersistentHandle(result);
517
518 // Create a weak persistent handle to global.
519 weak_persistent_handle = Dart_NewWeakPersistentHandle(
520 result, reinterpret_cast<void*>(0xdeadbeef), 128, WeakHandleFinalizer);
521 }
522
523 // Build a mock message handler and wrap it in a dart port.
525 Dart_Port port_id = PortMap::CreatePort(&handler);
526 Dart_Handle port = Api::NewHandle(thread, SendPort::New(port_id));
527 {
528 TransitionVMToNative transition(thread);
529 EXPECT_VALID(port);
530 EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
531 }
532
533 Array& service_msg = Array::Handle();
534
535 // Get persistent handles.
536 service_msg = Eval(lib, "[0, port, '0', '_getPersistentHandles', [], []]");
537 HandleIsolateMessage(isolate, service_msg);
538 EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
539 // Look for a heart beat.
540 EXPECT_SUBSTRING("\"type\":\"_PersistentHandles\"", handler.msg());
541 EXPECT_SUBSTRING("\"peer\":\"0xdeadbeef\"", handler.msg());
542 EXPECT_SUBSTRING("\"name\":\"A\"", handler.msg());
543 EXPECT_SUBSTRING("\"externalSize\":\"128\"", handler.msg());
544
545 // Delete persistent handles.
546 {
547 TransitionVMToNative transition(thread);
548 Dart_DeletePersistentHandle(persistent_handle);
549 Dart_DeleteWeakPersistentHandle(weak_persistent_handle);
550 }
551
552 // Get persistent handles (again).
553 service_msg = Eval(lib, "[0, port, '0', '_getPersistentHandles', [], []]");
554 HandleIsolateMessage(isolate, service_msg);
555 EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
556 EXPECT_SUBSTRING("\"type\":\"_PersistentHandles\"", handler.msg());
557 // Verify that old persistent handles are not present.
558 EXPECT_NOTSUBSTRING("\"peer\":\"0xdeadbeef\"", handler.msg());
559 EXPECT_NOTSUBSTRING("\"name\":\"A\"", handler.msg());
560 EXPECT_NOTSUBSTRING("\"externalSize\":\"128\"", handler.msg());
561}
562
563static bool alpha_callback(const char* name,
564 const char** option_keys,
565 const char** option_values,
566 intptr_t num_options,
567 void* user_data,
568 const char** result) {
569 *result = Utils::StrDup("alpha");
570 return true;
571}
572
573static bool beta_callback(const char* name,
574 const char** option_keys,
575 const char** option_values,
576 intptr_t num_options,
577 void* user_data,
578 const char** result) {
579 *result = Utils::StrDup("beta");
580 return false;
581}
582
583ISOLATE_UNIT_TEST_CASE(Service_EmbedderRootHandler) {
584 const char* kScript =
585 "var port;\n" // Set to our mock port by C++.
586 "\n"
587 "var x = 7;\n"
588 "main() {\n"
589 " x = x * x;\n"
590 " x = (x / 13).floor();\n"
591 "}";
592
593 Dart_Handle lib;
594 {
595 TransitionVMToNative transition(thread);
596
599
600 lib = TestCase::LoadTestScript(kScript, nullptr);
601 EXPECT_VALID(lib);
602 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
604 }
605
606 // Build a mock message handler and wrap it in a dart port.
608 Dart_Port port_id = PortMap::CreatePort(&handler);
609 Dart_Handle port = Api::NewHandle(thread, SendPort::New(port_id));
610 {
611 TransitionVMToNative transition(thread);
612 EXPECT_VALID(port);
613 EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
614 }
615
616 Array& service_msg = Array::Handle();
617 service_msg = Eval(lib, "[0, port, '\"', 'alpha', [], []]");
618 HandleRootMessage(service_msg);
619 EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
620 EXPECT_STREQ("{\"jsonrpc\":\"2.0\", \"result\":alpha,\"id\":\"\\\"\"}",
621 handler.msg());
622 service_msg = Eval(lib, "[0, port, 1, 'beta', [], []]");
623 HandleRootMessage(service_msg);
624 EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
625 EXPECT_STREQ("{\"jsonrpc\":\"2.0\", \"error\":beta,\"id\":1}", handler.msg());
626}
627
628ISOLATE_UNIT_TEST_CASE(Service_EmbedderIsolateHandler) {
629 const char* kScript =
630 "var port;\n" // Set to our mock port by C++.
631 "\n"
632 "var x = 7;\n"
633 "main() {\n"
634 " x = x * x;\n"
635 " x = (x / 13).floor();\n"
636 "}";
637
638 Dart_Handle lib;
639 {
640 TransitionVMToNative transition(thread);
641
643 nullptr);
645
646 lib = TestCase::LoadTestScript(kScript, nullptr);
647 EXPECT_VALID(lib);
648 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
650 }
651
652 // Build a mock message handler and wrap it in a dart port.
654 Dart_Port port_id = PortMap::CreatePort(&handler);
655 Dart_Handle port = Api::NewHandle(thread, SendPort::New(port_id));
656 {
657 TransitionVMToNative transition(thread);
658 EXPECT_VALID(port);
659 EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
660 }
661
662 Isolate* isolate = thread->isolate();
663 Array& service_msg = Array::Handle();
664 service_msg = Eval(lib, "[0, port, '0', 'alpha', [], []]");
665 HandleIsolateMessage(isolate, service_msg);
666 EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
667 EXPECT_STREQ("{\"jsonrpc\":\"2.0\", \"result\":alpha,\"id\":\"0\"}",
668 handler.msg());
669 service_msg = Eval(lib, "[0, port, '0', 'beta', [], []]");
670 HandleIsolateMessage(isolate, service_msg);
671 EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
672 EXPECT_STREQ("{\"jsonrpc\":\"2.0\", \"error\":beta,\"id\":\"0\"}",
673 handler.msg());
674}
675
676// TODO(zra): Remove when tests are ready to enable.
677#if !defined(TARGET_ARCH_ARM64)
678
679static void EnableProfiler() {
680 if (!FLAG_profiler) {
681 FLAG_profiler = true;
683 }
684}
685
686ISOLATE_UNIT_TEST_CASE(Service_Profile) {
688 const char* kScript =
689 "var port;\n" // Set to our mock port by C++.
690 "\n"
691 "var x = 7;\n"
692 "main() {\n"
693 " x = x * x;\n"
694 " x = (x / 13).floor();\n"
695 "}";
696
697 Isolate* isolate = thread->isolate();
698 isolate->set_is_runnable(true);
699 Dart_Handle lib;
700 {
701 TransitionVMToNative transition(thread);
702
703 lib = TestCase::LoadTestScript(kScript, nullptr);
704 EXPECT_VALID(lib);
705 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
707 }
708
709 // Build a mock message handler and wrap it in a dart port.
711 Dart_Port port_id = PortMap::CreatePort(&handler);
712 Dart_Handle port = Api::NewHandle(thread, SendPort::New(port_id));
713 {
714 TransitionVMToNative transition(thread);
715 EXPECT_VALID(port);
716 EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
717 }
718
719 Array& service_msg = Array::Handle();
720 service_msg = Eval(lib, "[0, port, '0', 'getCpuSamples', [], []]");
721 HandleIsolateMessage(isolate, service_msg);
722 EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
723 // Expect profile
724 EXPECT_SUBSTRING("\"type\":\"CpuSamples\"", handler.msg());
725}
726
727#endif // !defined(TARGET_ARCH_ARM64)
728
729ISOLATE_UNIT_TEST_CASE(Service_ParseJSONArray) {
730 {
731 const auto& elements =
733 EXPECT_EQ(-1, ParseJSONArray(thread, "", elements));
734 EXPECT_EQ(-1, ParseJSONArray(thread, "[", elements));
735 }
736
737 {
738 const auto& elements =
740 EXPECT_EQ(0, ParseJSONArray(thread, "[]", elements));
741 EXPECT_EQ(0, elements.Length());
742 }
743
744 {
745 const auto& elements =
747 EXPECT_EQ(0, ParseJSONArray(thread, "[a]", elements));
748 EXPECT_EQ(1, elements.Length());
749 auto& element = String::Handle();
750 element ^= elements.At(0);
751 EXPECT(element.Equals("a"));
752 }
753
754 {
755 const auto& elements =
757 EXPECT_EQ(0, ParseJSONArray(thread, "[abc, def]", elements));
758 EXPECT_EQ(2, elements.Length());
759 auto& element = String::Handle();
760 element ^= elements.At(0);
761 EXPECT(element.Equals("abc"));
762 element ^= elements.At(1);
763 EXPECT(element.Equals("def"));
764 }
765
766 {
767 const auto& elements =
769 EXPECT_EQ(0, ParseJSONArray(thread, "[abc, def, ghi]", elements));
770 EXPECT_EQ(3, elements.Length());
771 auto& element = String::Handle();
772 element ^= elements.At(0);
773 EXPECT(element.Equals("abc"));
774 element ^= elements.At(1);
775 EXPECT(element.Equals("def"));
776 element ^= elements.At(2);
777 EXPECT(element.Equals("ghi"));
778 }
779
780 {
781 const auto& elements =
783 EXPECT_EQ(0, ParseJSONArray(thread, "[abc, , ghi]", elements));
784 EXPECT_EQ(3, elements.Length());
785 auto& element = String::Handle();
786 element ^= elements.At(0);
787 EXPECT(element.Equals("abc"));
788 element ^= elements.At(1);
789 EXPECT(element.Equals(""));
790 element ^= elements.At(2);
791 EXPECT(element.Equals("ghi"));
792 }
793}
794
795#endif // !PRODUCT
796
797} // namespace dart
static const size_t kBufferSize
Definition SkString.cpp:27
#define EXPECT(type, expectedAlignment, expectedSize)
static Dart_Handle NewHandle(Thread *thread, ObjectPtr raw)
static ObjectPtr UnwrapHandle(Dart_Handle object)
ObjectPtr At(intptr_t index) const
Definition object.h:10854
intptr_t Length() const
Definition object.h:10808
static ArrayPtr MakeFixedLength(const GrowableObjectArray &growable_array, bool unique=false)
Definition object.cc:25014
uword Size() const
Definition object.h:6876
PcDescriptorsPtr pc_descriptors() const
Definition object.h:6900
LocalVarDescriptorsPtr GetLocalVarDescriptors() const
Definition object.cc:17675
uword PayloadStart() const
Definition object.h:6823
int64_t compile_timestamp() const
Definition object.h:7201
CodePtr CurrentCode() const
Definition object.h:3157
void Add(const Object &value, Heap::Space space=Heap::kNew) const
Definition object.cc:25070
static GrowableObjectArrayPtr New(Heap::Space space=Heap::kNew)
Definition object.h:11118
ObjectPtr At(intptr_t index) const
Definition object.h:11059
static Isolate * Current()
Definition isolate.h:939
void PrintJSON(JSONStream *stream, bool ref=true)
Definition isolate.cc:3038
void set_is_runnable(bool value)
Definition isolate.h:1049
ObjectIdRing * EnsureObjectIdRing()
Definition isolate.cc:2968
Thread * thread() const
MessageStatus HandleNextMessage()
int32_t GetIdForObject(ObjectPtr raw_obj, IdPolicy policy=kAllocateId)
static ObjectPtr null()
Definition object.h:433
ObjectPtr ptr() const
Definition object.h:332
bool IsNull() const
Definition object.h:363
static Object & Handle()
Definition object.h:407
static void ClosePorts(MessageHandler *handler)
Definition port.cc:128
static Dart_Port CreatePort(MessageHandler *handler)
Definition port.cc:55
static void Init()
Definition profiler.cc:567
static FunctionPtr ResolveDynamicFunction(Zone *zone, const Class &receiver_class, const String &function_name)
Definition resolver.cc:189
void Init(ObjectIdRing *ring, ObjectIdRing::IdPolicy policy)
Definition service.cc:374
virtual char * GetServiceId(const Object &obj)
Definition service.cc:380
static SendPortPtr New(Dart_Port id, Heap::Space space=Heap::kNew)
Definition object.cc:25891
MessageStatus HandleMessage(std::unique_ptr< Message > message)
virtual Isolate * isolate() const
static ErrorPtr HandleRootMessage(const Array &message)
Definition service.cc:1059
static ErrorPtr HandleIsolateMessage(Isolate *isolate, const Array &message)
Definition service.cc:1069
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
Definition object.cc:23777
static const char * ToCString(Thread *thread, StringPtr ptr)
Definition object.cc:24205
static StringPtr New(Thread *thread, const char *cstr)
Definition symbols.h:722
static Dart_Handle LoadTestScript(const char *script, Dart_NativeEntryResolver resolver, const char *lib_uri=RESOLVED_USER_TEST_URI, bool finalize=true, bool allow_compile_errors=false)
Definition unit_test.cc:422
Zone * zone() const
static Thread * Current()
Definition thread.h:361
void * DataAddr(intptr_t byte_offset) const
Definition object.h:11545
static int SNPrint(char *str, size_t size, const char *format,...) PRINTF_ATTRIBUTE(3
static char * StrDup(const char *s)
static int static int VSNPrint(char *str, size_t size, const char *format, va_list args)
ElementType * Alloc(intptr_t length)
int64_t Dart_Port
Definition dart_api.h:1524
struct _Dart_Handle * Dart_Handle
Definition dart_api.h:258
Dart_Handle Dart_PersistentHandle
Definition dart_api.h:259
struct _Dart_WeakPersistentHandle * Dart_WeakPersistentHandle
Definition dart_api.h:260
#define ASSERT(E)
static const uint8_t buffer[]
uint8_t value
GAsyncResult * result
#define DEFINE_FLAG(type, name, default_value, comment)
Definition flags.h:16
Win32Message message
DART_EXPORT Dart_WeakPersistentHandle Dart_NewWeakPersistentHandle(Dart_Handle object, void *peer, intptr_t external_allocation_size, Dart_HandleFinalizer callback)
ObjectPtr ReadMessage(Thread *thread, Message *message)
static ArrayPtr EvalF(Dart_Handle lib, const char *fmt,...)
const char *const name
Dart_Handle Dart_EvaluateStaticExpr(Dart_Handle lib_handle, Dart_Handle expr_in)
static void HandleIsolateMessage(Isolate *isolate, const Array &msg)
DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target, Dart_Handle name, int number_of_arguments, Dart_Handle *arguments)
DART_EXPORT bool Dart_HasStickyError()
DART_EXPORT bool Dart_IsUnhandledExceptionError(Dart_Handle object)
static ArrayPtr Eval(Dart_Handle lib, const char *expr)
FunctionPtr GetFunction(const Library &lib, const char *name)
uintptr_t uword
Definition globals.h:501
DART_EXPORT void Dart_RegisterRootServiceRequestCallback(const char *name, Dart_ServiceRequestCallback callback, void *user_data)
DART_EXPORT void Dart_DeletePersistentHandle(Dart_PersistentHandle object)
DART_EXPORT void Dart_DeleteWeakPersistentHandle(Dart_WeakPersistentHandle object)
static void WeakHandleFinalizer(void *isolate_callback_data, void *peer)
static void EnableProfiler()
ClassPtr GetClass(const Library &lib, const char *name)
DART_EXPORT Dart_Handle Dart_SetField(Dart_Handle container, Dart_Handle name, Dart_Handle value)
Dart_Handle NewString(const char *str)
DART_EXPORT void Dart_SetPausedOnExit(bool paused)
DART_EXPORT bool Dart_IsNull(Dart_Handle object)
DART_EXPORT void Dart_SetStickyError(Dart_Handle error)
DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(const char *name, Dart_ServiceRequestCallback callback, void *user_data)
static bool beta_callback(const char *name, const char **option_keys, const char **option_values, intptr_t num_options, void *user_data, const char **result)
intptr_t ParseJSONArray(Thread *thread, const char *str, const GrowableObjectArray &elements)
Definition service.cc:3660
static bool alpha_callback(const char *name, const char **option_keys, const char **option_values, intptr_t num_options, void *user_data, const char **result)
static void HandleRootMessage(const Array &message)
DART_EXPORT Dart_PersistentHandle Dart_NewPersistentHandle(Dart_Handle object)
static SkString fmt(SkColor4f c)
Definition p3.cpp:43
#define Px
Definition globals.h:410
#define Px64
Definition globals.h:418
#define Pd
Definition globals.h:408
#define ISOLATE_UNIT_TEST_CASE(name)
Definition unit_test.h:64
#define EXPECT_VALID(handle)
Definition unit_test.h:650