Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
VmServiceTest.java
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015, the Dart project authors.
3 *
4 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
12 * the License.
13 */
14package org.dartlang.vm.service;
15
16import com.google.gson.JsonObject;
17import org.dartlang.vm.service.consumer.*;
18import org.dartlang.vm.service.element.*;
19import org.dartlang.vm.service.logging.Logger;
20import org.dartlang.vm.service.logging.Logging;
21
22import java.io.File;
23import java.io.IOException;
24import java.util.ArrayList;
25import java.util.Collections;
26import java.util.HashSet;
27import java.util.List;
28
29public class VmServiceTest {
30 private static File dartVm;
31 private static File sampleDart;
32 private static File sampleDartWithException;
33 private static int vmPort = 7575;
34 private static Process process;
35 private static VmService vmService;
36 private static SampleOutPrinter sampleOut;
37 private static SampleOutPrinter sampleErr;
38 private static int actualVmServiceVersionMajor;
39
40 public static void main(String[] args) {
41 setupLogging();
42 parseArgs(args);
43
44 try {
45 echoDartVmVersion();
46 runSample();
47 runSampleWithException();
48 System.out.println("Test Complete");
49 } finally {
50 vmDisconnect();
51 stopSample();
52 }
53 }
54
55 private static void echoDartVmVersion() {
56 // Echo Dart VM version
57 List<String> processArgs = new ArrayList<>();
58 processArgs.add(dartVm.getAbsolutePath());
59 processArgs.add("--version");
60 ProcessBuilder processBuilder = new ProcessBuilder(processArgs);
61 try {
62 process = processBuilder.start();
63 } catch (IOException e) {
64 throw new RuntimeException("Failed to launch Dart VM", e);
65 }
66 new SampleOutPrinter("version output", process.getInputStream());
67 new SampleOutPrinter("version output", process.getErrorStream());
68 }
69
70 private static void finishExecution(SampleVmServiceListener vmListener, ElementList<IsolateRef> isolates) {
71 // Finish execution
72 vmResume(isolates.get(0), null);
73 vmListener.waitFor(VmService.DEBUG_STREAM_ID, EventKind.Resume);
74
75 // VM pauses on exit and must be resumed to cleanly terminate process
76 vmListener.waitFor(VmService.DEBUG_STREAM_ID, EventKind.PauseExit);
77 vmResume(isolates.get(0), null);
78 vmListener.waitFor(VmService.ISOLATE_STREAM_ID, EventKind.IsolateExit);
79 waitForProcessExit();
80
81 sampleOut.assertLastLine("exiting");
82 // TODO(devoncarew):
83 // vm-service: isolate(544050040) 'sample_main.dart:main()' has no debugger attached and is paused at start.
84 //sampleErr.assertLastLine(null);
85 process = null;
86 }
87
88 private static boolean isWindows() {
89 return System.getProperty("os.name").startsWith("Win");
90 }
91
92 private static void parseArgs(String[] args) {
93 if (args.length != 1) {
94 showErrorAndExit("Expected absolute path to Dart SDK");
95 }
96 File sdkDir = new File(args[0]);
97 if (!sdkDir.isDirectory()) {
98 showErrorAndExit("Specified directory does not exist: " + sdkDir);
99 }
100 File binDir = new File(sdkDir, "bin");
101 dartVm = new File(binDir, isWindows() ? "dart.exe" : "dart");
102 if (!dartVm.isFile()) {
103 showErrorAndExit("Cannot find Dart VM in SDK: " + dartVm);
104 }
105 File currentDir = new File(".").getAbsoluteFile();
106 File projDir = currentDir;
107 String projName = "vm_service";
108 while (!projDir.getName().equals(projName)) {
109 projDir = projDir.getParentFile();
110 if (projDir == null) {
111 showErrorAndExit("Cannot find project " + projName + " from " + currentDir);
112 return;
113 }
114 }
115 sampleDart = new File(projDir, "java/example/sample_main.dart".replace("/", File.separator));
116 if (!sampleDart.isFile()) {
117 showErrorAndExit("Cannot find sample: " + sampleDart);
118 }
119 sampleDartWithException = new File(projDir,
120 "java/example/sample_exception.dart".replace("/", File.separator));
121 if (!sampleDartWithException.isFile()) {
122 showErrorAndExit("Cannot find sample: " + sampleDartWithException);
123 }
124 System.out.println("Using Dart SDK: " + sdkDir);
125 }
126
127 /**
128 * Exercise VM service with "normal" sample.
129 */
130 private static void runSample() {
131 SampleVmServiceListener vmListener = startSampleAndConnect(sampleDart);
132 vmGetVersion();
133 ElementList<IsolateRef> isolates = vmGetVmIsolates();
134 Isolate sampleIsolate = vmGetIsolate(isolates.get(0));
135 Library rootLib = vmGetLibrary(sampleIsolate, sampleIsolate.getRootLib());
136 vmGetScript(sampleIsolate, rootLib.getScripts().get(0));
137 vmCallServiceExtension(sampleIsolate);
138
139 // Run to breakpoint on line "foo(1);"
140 vmAddBreakpoint(sampleIsolate, rootLib.getScripts().get(0), 25);
141 vmListener.waitFor(VmService.DEBUG_STREAM_ID, EventKind.BreakpointAdded);
142 vmResume(isolates.get(0), null);
143 vmListener.waitFor(VmService.DEBUG_STREAM_ID, EventKind.Resume);
144 vmListener.waitFor(VmService.DEBUG_STREAM_ID, EventKind.PauseBreakpoint);
145 sampleOut.assertLastLine("hello");
146
147 // Get stack trace
148 vmGetStack(sampleIsolate);
149
150 // Evaluate
151 vmEvaluateInFrame(sampleIsolate, 0, "deepList[0]");
152
153 // Get coverage information
154 vmGetSourceReport(sampleIsolate);
155
156 // Step over line "foo(1);"
157 vmResume(isolates.get(0), StepOption.Over);
158 vmListener.waitFor(VmService.DEBUG_STREAM_ID, EventKind.Resume);
159 vmListener.waitFor(VmService.DEBUG_STREAM_ID, EventKind.PauseBreakpoint);
160 sampleOut.assertLastLine("val: 1");
161
162 finishExecution(vmListener, isolates);
163 }
164
165 /**
166 * Exercise VM service with sample that throws exceptions.
167 */
168 private static void runSampleWithException() {
169 SampleVmServiceListener vmListener = startSampleAndConnect(sampleDartWithException);
170 ElementList<IsolateRef> isolates = vmGetVmIsolates();
171 Isolate sampleIsolate = vmGetIsolate(isolates.get(0));
172
173 // Run until exception occurs
174 vmPauseOnException(isolates.get(0), ExceptionPauseMode.All);
175 vmResume(isolates.get(0), null);
176 vmListener.waitFor(VmService.DEBUG_STREAM_ID, EventKind.Resume);
177 Event event = vmListener.waitFor(VmService.DEBUG_STREAM_ID, EventKind.PauseException);
178 InstanceRefToString convert = new InstanceRefToString(sampleIsolate, vmService, new OpLatch());
179 System.out.println("Received PauseException event");
180 System.out.println(" Exception: " + convert.toString(event.getException()));
181 System.out.println(" Top Frame:");
182 showFrame(convert, event.getTopFrame());
183 sampleOut.assertLastLine("hello");
184
185 finishExecution(vmListener, isolates);
186 }
187
188 private static void setupLogging() {
189 Logging.setLogger(new Logger() {
190 @Override
191 public void logError(String message) {
192 System.out.println("Log error: " + message);
193 }
194
195 @Override
196 public void logError(String message, Throwable exception) {
197 System.out.println("Log error: " + message);
198 if (exception != null) {
199 System.out.println("Log error exception: " + exception);
200 exception.printStackTrace();
201 }
202 }
203
204 @Override
205 public void logInformation(String message) {
206 System.out.println("Log info: " + message);
207 }
208
209 @Override
210 public void logInformation(String message, Throwable exception) {
211 System.out.println("Log info: " + message);
212 if (exception != null) {
213 System.out.println("Log info exception: " + exception);
214 exception.printStackTrace();
215 }
216 }
217 });
218 }
219
220 private static void showErrorAndExit(String errMsg) {
221 System.out.println(errMsg);
222 System.out.flush();
223 sleep(10);
224 System.out.println("Usage: VmServiceTest /path/to/Dart/SDK");
225 System.exit(1);
226 }
227
228 private static void showFrame(InstanceRefToString convert, Frame frame) {
229 System.out.println(" #" + frame.getIndex() + " " + frame.getFunction().getName() + " ("
230 + frame.getLocation().getScript().getUri() + ")");
231 for (BoundVariable var : frame.getVars()) {
232 InstanceRef instanceRef = (InstanceRef)var.getValue();
233 System.out.println(" " + var.getName() + " = " + convert.toString(instanceRef));
234 }
235 }
236
237 private static void showRPCError(RPCError error) {
238 System.out.println(">>> Received error response");
239 System.out.println(" Code: " + error.getCode());
240 System.out.println(" Message: " + error.getMessage());
241 System.out.println(" Details: " + error.getDetails());
242 System.out.println(" Request: " + error.getRequest());
243 }
244
245 private static void showSentinel(Sentinel sentinel) {
246 System.out.println(">>> Received sentinel response");
247 System.out.println(" Sentinel kind: " + sentinel.getKind());
248 System.out.println(" Sentinel value: " + sentinel.getValueAsString());
249 }
250
251 private static void sleep(int milliseconds) {
252 try {
253 Thread.sleep(milliseconds);
254 } catch (InterruptedException e) {
255 // ignored
256 }
257 }
258
259 private static void startSample(File dartFile) {
260 List<String> processArgs;
261 ProcessBuilder processBuilder;
262
263 // Use new port to prevent race conditions
264 // between one sample releasing a port
265 // and the next sample using it.
266 ++vmPort;
267
268 processArgs = new ArrayList<>();
269 processArgs.add(dartVm.getAbsolutePath());
270 processArgs.add("--pause_isolates_on_start");
271 processArgs.add("--observe");
272 processArgs.add("--enable-vm-service=" + vmPort);
273 processArgs.add("--disable-service-auth-codes");
274 processArgs.add(dartFile.getAbsolutePath());
275 processBuilder = new ProcessBuilder(processArgs);
276 System.out.println("=================================================");
277 System.out.println("Launching sample: " + dartFile);
278 try {
279 process = processBuilder.start();
280 } catch (IOException e) {
281 throw new RuntimeException("Failed to launch Dart sample", e);
282 }
283 // Echo sample application output to System.out
284 sampleOut = new SampleOutPrinter("stdout", process.getInputStream());
285 sampleErr = new SampleOutPrinter("stderr", process.getErrorStream());
286 System.out.println("Dart process started - port " + vmPort);
287 }
288
289 private static SampleVmServiceListener startSampleAndConnect(File dartFile) {
290 startSample(dartFile);
291 sleep(1000);
292 vmConnect();
293 SampleVmServiceListener vmListener = new SampleVmServiceListener(
294 new HashSet<>(Collections.singletonList(EventKind.BreakpointResolved)));
295 vmService.addVmServiceListener(vmListener);
296 vmStreamListen(VmService.DEBUG_STREAM_ID);
297 vmStreamListen(VmService.ISOLATE_STREAM_ID);
298 return vmListener;
299 }
300
301 private static void stopSample() {
302 if (process == null) {
303 return;
304 }
305 final Process processToStop = process;
306 process = null;
307 long endTime = System.currentTimeMillis() + 5000;
308 while (System.currentTimeMillis() < endTime) {
309 try {
310 int exit = processToStop.exitValue();
311 if (exit != 0) {
312 System.out.println("Sample exit code: " + exit);
313 }
314 return;
315 } catch (IllegalThreadStateException e) {
316 //$FALL-THROUGH$
317 }
318 try {
319 Thread.sleep(20);
320 } catch (InterruptedException e) {
321 //$FALL-THROUGH$
322 }
323 }
324 processToStop.destroy();
325 System.out.println("Terminated sample process");
326 }
327
328 @SuppressWarnings("SameParameterValue")
329 private static void vmAddBreakpoint(Isolate isolate, ScriptRef script, int lineNum) {
330 final OpLatch latch = new OpLatch();
331 vmService.addBreakpoint(isolate.getId(), script.getId(), lineNum, new AddBreakpointConsumer() {
332 @Override
333 public void onError(RPCError error) {
334 showRPCError(error);
335 }
336
337 @Override
338 public void received(Breakpoint response) {
339 System.out.println("Received Breakpoint response");
340 System.out.println(" BreakpointNumber:" + response.getBreakpointNumber());
341 latch.opComplete();
342 }
343
344 @Override
345 public void received(Sentinel response) {
346 showSentinel(response);
347 }
348 });
349 latch.waitAndAssertOpComplete();
350 }
351
352 private static void vmConnect() {
353 try {
354 vmService = VmService.localConnect(vmPort);
355 } catch (IOException e) {
356 throw new RuntimeException("Failed to connect to the VM vmService service", e);
357 }
358 }
359
360 private static void vmDisconnect() {
361 if (vmService != null) {
362 vmService.disconnect();
363 }
364 }
365
366 @SuppressWarnings("SameParameterValue")
367 private static void vmEvaluateInFrame(Isolate isolate, int frameIndex, String expression) {
368 System.out.println("Evaluating: " + expression);
369 final ResultLatch<InstanceRef> latch = new ResultLatch<>();
370 vmService.evaluateInFrame(isolate.getId(), frameIndex, expression, new EvaluateInFrameConsumer() {
371 @Override
372 public void onError(RPCError error) {
373 showRPCError(error);
374 }
375
376 @Override
377 public void received(ErrorRef response) {
378 showErrorAndExit(response.getMessage());
379 }
380
381 public void received(Sentinel response) {
382 System.out.println(response.getValueAsString());
383 }
384
385 @Override
386 public void received(InstanceRef response) {
387 System.out.println("Received InstanceRef response");
388 System.out.println(" Id: " + response.getId());
389 System.out.println(" Kind: " + response.getKind());
390 System.out.println(" Json: " + response.getJson());
391 latch.setValue(response);
392 }
393 });
394 InstanceRef instanceRef = latch.getValue();
395 InstanceRefToString convert = new InstanceRefToString(isolate, vmService, latch);
396 System.out.println("Result: " + convert.toString(instanceRef));
397 }
398
399 private static SourceReport vmGetSourceReport(Isolate isolate) {
400 System.out.println("Getting coverage information for " + isolate.getId());
401 final long startTime = System.currentTimeMillis();
402 final ResultLatch<SourceReport> latch = new ResultLatch<>();
403 vmService.getSourceReport(isolate.getId(), Collections.singletonList(SourceReportKind.Coverage), new GetSourceReportConsumer() {
404 @Override
405 public void onError(RPCError error) {
406 showRPCError(error);
407 }
408
409 @Override
410 public void received(SourceReport response) {
411 System.out.println("Received SourceReport response (" + (System.currentTimeMillis() - startTime) + "ms)");
412 System.out.println(" Script count: " + response.getScripts().size());
413 System.out.println(" Range count: " + response.getRanges().size());
414 latch.setValue(response);
415 }
416
417 @Override
418 public void received(Sentinel response) {
419 showSentinel(response);
420 }
421 });
422 return latch.getValue();
423 }
424
425 private static Isolate vmGetIsolate(IsolateRef isolate) {
426 final ResultLatch<Isolate> latch = new ResultLatch<>();
427 vmService.getIsolate(isolate.getId(), new GetIsolateConsumer() {
428 @Override
429 public void onError(RPCError error) {
430 showRPCError(error);
431 }
432
433 @Override
434 public void received(Isolate response) {
435 System.out.println("Received Isolate response");
436 System.out.println(" Id: " + response.getId());
437 System.out.println(" Name: " + response.getName());
438 System.out.println(" Number: " + response.getNumber());
439 System.out.println(" Start Time: " + response.getStartTime());
440 System.out.println(" RootLib Id: " + response.getRootLib().getId());
441 System.out.println(" RootLib Uri: " + response.getRootLib().getUri());
442 System.out.println(" RootLib Name: " + response.getRootLib().getName());
443 System.out.println(" RootLib Json: " + response.getRootLib().getJson());
444 System.out.println(" Isolate: " + response);
445 latch.setValue(response);
446 }
447
448 @Override
449 public void received(Sentinel response) {
450 showSentinel(response);
451 }
452 });
453 return latch.getValue();
454 }
455
456 private static Library vmGetLibrary(Isolate isolateId, LibraryRef library) {
457 final ResultLatch<Library> latch = new ResultLatch<>();
458 vmService.getLibrary(isolateId.getId(), library.getId(), new GetLibraryConsumer() {
459 @Override
460 public void onError(RPCError error) {
461 showRPCError(error);
462 }
463
464 @Override
465 public void received(Library response) {
466 System.out.println("Received GetLibrary library");
467 System.out.println(" uri: " + response.getUri());
468 latch.setValue(response);
469 }
470 });
471 return latch.getValue();
472 }
473
474 private static void vmGetScript(Isolate isolate, ScriptRef scriptRef) {
475 final ResultLatch<Script> latch = new ResultLatch<>();
476 vmService.getObject(isolate.getId(), scriptRef.getId(), new GetObjectConsumer() {
477 @Override
478 public void onError(RPCError error) {
479 showRPCError(error);
480 }
481
482 @Override
483 public void received(Obj response) {
484 if (response instanceof Script) {
485 latch.setValue((Script) response);
486 } else {
487 RPCError.unexpected("Script", response);
488 }
489 }
490
491 @Override
492 public void received(Sentinel response) {
493 RPCError.unexpected("Script", response);
494 }
495 });
496 Script script = latch.getValue();
497 System.out.println("Received Script");
498 System.out.println(" Id: " + script.getId());
499 System.out.println(" Uri: " + script.getUri());
500 System.out.println(" Source: " + script.getSource());
501 System.out.println(" TokenPosTable: " + script.getTokenPosTable());
502 if (script.getTokenPosTable() == null) {
503 showErrorAndExit("Expected TokenPosTable to be non-null");
504 }
505 }
506
507 private static void vmGetStack(Isolate isolate) {
508 final ResultLatch<Stack> latch = new ResultLatch<>();
509 vmService.getStack(isolate.getId(), new GetStackConsumer() {
510 @Override
511 public void onError(RPCError error) {
512 showRPCError(error);
513 }
514
515 @Override
516 public void received(Stack stack) {
517 latch.setValue(stack);
518 }
519
520 @Override
521 public void received(Sentinel response) {
522 showSentinel(response);
523 }
524 });
525 Stack stack = latch.getValue();
526 System.out.println("Received Stack response");
527 System.out.println(" Messages:");
528 for (Message message : stack.getMessages()) {
529 System.out.println(" " + message.getName());
530 }
531 System.out.println(" Frames:");
532 InstanceRefToString convert = new InstanceRefToString(isolate, vmService, latch);
533 for (Frame frame : stack.getFrames()) {
534 showFrame(convert, frame);
535 }
536 }
537
538 private static void vmGetVersion() {
539 final OpLatch latch = new OpLatch();
540 vmService.getVersion(new VersionConsumer() {
541 @Override
542 public void onError(RPCError error) {
543 showRPCError(error);
544 }
545
546 @Override
547 public void received(Version response) {
548 System.out.println("Received Version response");
549 actualVmServiceVersionMajor = response.getMajor();
550 System.out.println(" Major: " + actualVmServiceVersionMajor);
551 System.out.println(" Minor: " + response.getMinor());
552 System.out.println(response.getJson());
553 latch.opComplete();
554 }
555 });
556 latch.waitAndAssertOpComplete();
557 }
558
559 private static void vmCallServiceExtension(Isolate isolateId) {
560 final OpLatch latch = new OpLatch();
561 vmService.callServiceExtension(isolateId.getId(), "getIsolate", new ServiceExtensionConsumer() {
562 @Override
563 public void onError(RPCError error) {
564 showRPCError(error);
565 }
566
567 @Override
568 public void received(JsonObject result) {
569 System.out.println("Received response: " + result);
570 latch.opComplete();
571 }
572 });
573 latch.waitAndAssertOpComplete();
574 }
575
576 private static ElementList<IsolateRef> vmGetVmIsolates() {
577 final ResultLatch<ElementList<IsolateRef>> latch = new ResultLatch<>();
578 vmService.getVM(new VMConsumer() {
579 @Override
580 public void onError(RPCError error) {
581 showRPCError(error);
582 }
583
584 @Override
585 public void received(VM response) {
586 System.out.println("Received VM response");
587 System.out.println(" ArchitectureBits: " + response.getArchitectureBits());
588 System.out.println(" HostCPU: " + response.getHostCPU());
589 System.out.println(" TargetCPU: " + response.getTargetCPU());
590 System.out.println(" Pid: " + response.getPid());
591 System.out.println(" StartTime: " + response.getStartTime());
592 for (IsolateRef isolate : response.getIsolates()) {
593 System.out.println(" Isolate " + isolate.getNumber() + ", " + isolate.getId() + ", "
594 + isolate.getName());
595 }
596 latch.setValue(response.getIsolates());
597 }
598 });
599 return latch.getValue();
600 }
601
602 private static void vmPauseOnException(IsolateRef isolate, ExceptionPauseMode mode) {
603 System.out.println("Request pause on exception: " + mode);
604 final OpLatch latch = new OpLatch();
605 vmService.setIsolatePauseMode(isolate.getId(), mode, /*shouldPauseOnExit=*/true, new SetIsolatePauseModeConsumer() {
606 @Override
607 public void onError(RPCError error) {
608 showRPCError(error);
609 }
610
611 @Override
612 public void received(Success response) {
613 System.out.println("Successfully set pause on exception");
614 latch.opComplete();
615 }
616
617 @Override
618 public void received(Sentinel response) {
619 showSentinel(response);
620 }
621 });
622 latch.waitAndAssertOpComplete();
623 }
624
625 private static void vmResume(IsolateRef isolateRef, final StepOption step) {
626 final String id = isolateRef.getId();
627 vmService.resume(id, step, null, new ResumeConsumer() {
628 @Override
629 public void onError(RPCError error) {
630 showRPCError(error);
631 }
632
633 @Override
634 public void received(Success response) {
635 if (step == null) {
636 System.out.println("Resumed isolate " + id);
637 } else {
638 System.out.println("Step " + step + " isolate " + id);
639 }
640 }
641
642 @Override
643 public void received(Sentinel response) {
644 showSentinel(response);
645 }
646 });
647 // Do not wait for confirmation, but display error if it occurs
648 }
649
650 private static void vmStreamListen(String streamId) {
651 final OpLatch latch = new OpLatch();
652 vmService.streamListen(streamId, new SuccessConsumer() {
653 @Override
654 public void onError(RPCError error) {
655 showRPCError(error);
656 }
657
658 @Override
659 public void received(Success response) {
660 System.out.println("Subscribed to debug event stream");
661 latch.opComplete();
662 }
663 });
664 latch.waitAndAssertOpComplete();
665 }
666
667 private static void waitForProcessExit() {
668 if (actualVmServiceVersionMajor == 2) {
669 // Don't wait for VM 1.12 - protocol 2.1
670 return;
671 }
672 long end = System.currentTimeMillis() + 5000;
673 while (true) {
674 try {
675 System.out.println("Exit code: " + process.exitValue());
676 return;
677 } catch (IllegalThreadStateException e) {
678 // fall through to wait for exit
679 }
680 if (System.currentTimeMillis() >= end) {
681 throw new RuntimeException("Expected child process to finish");
682 }
683 sleep(10);
684 }
685 }
686}
static int step(int x, SkScalar min, SkScalar max)
Definition BlurTest.cpp:215
Version
void add(sk_sp< SkIDChangeListener > listener) SK_EXCLUDES(fMutex)
static void main(String[] args)
static Editor::Movement convert(skui::Key key)
double frame
Definition examples.cpp:31
glong glong end
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent * event
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
Win32Message message
exit(kErrorExitCode)