Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: runtime/observatory/tests/service/test_helper.dart

Issue 1726773002: Refactor service tests in preparation of running on sky_shell (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 library test_helper; 5 library test_helper;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:convert'; 8 import 'dart:convert';
9 import 'dart:io'; 9 import 'dart:io';
10 import 'package:observatory/service_io.dart'; 10 import 'package:observatory/service_io.dart';
11 import 'package:unittest/unittest.dart'; 11 import 'service_test_common.dart';
12
13 /// Will be set to the http address of the VM's service protocol before
14 /// any tests are invoked.
15 String serviceHttpAddress;
16 String serviceWebsocketAddress;
12 17
13 bool _isWebSocketDisconnect(e) { 18 bool _isWebSocketDisconnect(e) {
14 return e is NetworkRpcException; 19 return e is NetworkRpcException;
15 } 20 }
16 21
17 // This invocation should set up the state being tested. 22 const String _TESTEE_ENV_KEY = 'SERVICE_TEST_TESTEE';
18 const String _TESTEE_MODE_FLAG = "--testee-mode"; 23 const Map<String, String> _TESTEE_SPAWN_ENV = const {
24 _TESTEE_ENV_KEY: 'true'
25 };
26 bool _isTestee() {
27 return Platform.environment.containsKey(_TESTEE_ENV_KEY);
28 }
19 29
20 class _TestLauncher { 30 class _SerivceTesteeRunner {
31 Future run({Future testeeBefore(): null,
32 Future testeeConcurrent(): null,
33 bool pause_on_start: false,
34 bool pause_on_exit: false}) async {
35 if (!pause_on_start) {
36 if (testeeBefore != null) {
37 var result = testeeBefore();
38 if (result is Future) {
39 await result;
40 }
41 }
42 print(''); // Print blank line to signal that testeeBefore has run.
43 }
44 if (testeeConcurrent != null) {
45 var result = testeeConcurrent();
46 if (result is Future) {
47 await result;
48 }
49 }
50 if (!pause_on_exit) {
51 // Wait around for the process to be killed.
52 stdin.first.then((_) => exit(0));
53 }
54 }
55
56 void runSync({void testeeBeforeSync(): null,
57 void testeeConcurrentSync(): null,
58 bool pause_on_start: false,
59 bool pause_on_exit: false}) {
60 if (!pause_on_start) {
61 if (testeeBeforeSync != null) {
62 testeeBeforeSync();
63 }
64 print(''); // Print blank line to signal that testeeBefore has run.
65 }
66 if (testeeConcurrentSync != null) {
67 testeeConcurrentSync();
68 }
69 if (!pause_on_exit) {
70 // Wait around for the process to be killed.
71 stdin.first.then((_) => exit(0));
72 }
73 }
74 }
75
76 class _ServiceTesteeLauncher {
21 Process process; 77 Process process;
22 final List<String> args; 78 final List<String> args;
23 bool killedByTester = false; 79 bool killedByTester = false;
24 80
25 _TestLauncher() : args = ['--enable-vm-service:0', 81 _ServiceTesteeLauncher() :
26 Platform.script.toFilePath(), 82 args = ['--enable-vm-service:0',
27 _TESTEE_MODE_FLAG] {} 83 Platform.script.toFilePath()] {}
28 84
29 Future<int> launch(bool pause_on_start, 85 String get executablePath => Platform.executable;
30 bool pause_on_exit, 86
31 bool pause_on_unhandled_exceptions, 87 // Spawn the testee process.
32 bool trace_service, 88 Future<Process> _spawnProcess(bool pause_on_start,
33 bool trace_compiler) { 89 bool pause_on_exit,
90 bool pause_on_unhandled_exceptions,
91 bool trace_service,
92 bool trace_compiler) {
34 assert(pause_on_start != null); 93 assert(pause_on_start != null);
35 assert(pause_on_exit != null); 94 assert(pause_on_exit != null);
36 assert(trace_service != null); 95 assert(trace_service != null);
37 // TODO(turnidge): I have temporarily turned on service tracing for 96 // TODO(turnidge): I have temporarily turned on service tracing for
38 // all tests to help diagnose flaky tests. 97 // all tests to help diagnose flaky tests.
39 trace_service = true; 98 trace_service = true;
40 String dartExecutable = Platform.executable; 99 String dartExecutable = Platform.executable;
41 var fullArgs = []; 100 var fullArgs = [];
42 if (trace_service) { 101 if (trace_service) {
43 fullArgs.add('--trace-service'); 102 fullArgs.add('--trace-service');
44 fullArgs.add('--trace-service-verbose'); 103 fullArgs.add('--trace-service-verbose');
45 } 104 }
46 if (trace_compiler) { 105 if (trace_compiler) {
47 fullArgs.add('--trace-compiler'); 106 fullArgs.add('--trace-compiler');
48 } 107 }
49 if (pause_on_start) { 108 if (pause_on_start) {
50 fullArgs.add('--pause-isolates-on-start'); 109 fullArgs.add('--pause-isolates-on-start');
51 } 110 }
52 if (pause_on_exit) { 111 if (pause_on_exit) {
53 fullArgs.add('--pause-isolates-on-exit'); 112 fullArgs.add('--pause-isolates-on-exit');
54 } 113 }
55 if (pause_on_unhandled_exceptions) { 114 if (pause_on_unhandled_exceptions) {
56 fullArgs.add('--pause-isolates-on-unhandled-exceptions'); 115 fullArgs.add('--pause-isolates-on-unhandled-exceptions');
57 } 116 }
58 fullArgs.addAll(Platform.executableArguments); 117 fullArgs.addAll(Platform.executableArguments);
59 fullArgs.addAll(args); 118 fullArgs.addAll(args);
60 print('** Launching $dartExecutable ${fullArgs.join(' ')}'); 119 print('** Launching $dartExecutable ${fullArgs.join(' ')}');
61 return Process.start(dartExecutable, fullArgs).then((p) { 120 return Process.start(dartExecutable,
121 fullArgs,
122 environment: _TESTEE_SPAWN_ENV);
123 }
62 124
125 Future<int> launch(bool pause_on_start,
126 bool pause_on_exit,
127 bool pause_on_unhandled_exceptions,
128 bool trace_service,
129 bool trace_compiler) {
130 return _spawnProcess(pause_on_start,
131 pause_on_exit,
132 pause_on_unhandled_exceptions,
133 trace_service,
134 trace_compiler).then((p) {
63 Completer completer = new Completer(); 135 Completer completer = new Completer();
64 process = p; 136 process = p;
65 var portNumber; 137 var portNumber;
66 var blank; 138 var blank;
67 var first = true; 139 var first = true;
68 process.stdout.transform(UTF8.decoder) 140 process.stdout.transform(UTF8.decoder)
69 .transform(new LineSplitter()).listen((line) { 141 .transform(new LineSplitter()).listen((line) {
70 if (line.startsWith('Observatory listening on http://')) { 142 if (line.startsWith('Observatory listening on http://')) {
71 RegExp portExp = new RegExp(r"\d+.\d+.\d+.\d+:(\d+)"); 143 RegExp portExp = new RegExp(r"\d+.\d+.\d+.\d+:(\d+)");
72 var port = portExp.firstMatch(line).group(1); 144 var port = portExp.firstMatch(line).group(1);
(...skipping 26 matching lines...) Expand all
99 } 171 }
100 172
101 void requestExit() { 173 void requestExit() {
102 print('** Killing script'); 174 print('** Killing script');
103 if (process.kill()) { 175 if (process.kill()) {
104 killedByTester = true; 176 killedByTester = true;
105 } 177 }
106 } 178 }
107 } 179 }
108 180
109 typedef Future IsolateTest(Isolate isolate); 181 class _ServiceTesterRunner {
110 typedef Future VMTest(VM vm); 182 void run({List<String> mainArgs,
111 183 List<VMTest> vmTests,
112 /// Will be set to the http address of the VM's service protocol before 184 List<IsolateTest> isolateTests,
113 /// any tests are invoked. 185 bool pause_on_start: false,
114 String serviceHttpAddress; 186 bool pause_on_exit: false,
115 187 bool trace_service: false,
116 /// Runs [tests] in sequence, each of which should take an [Isolate] and 188 bool trace_compiler: false,
117 /// return a [Future]. Code for setting up state can run before and/or 189 bool verbose_vm: false,
118 /// concurrently with the tests. Uses [mainArgs] to determine whether 190 bool pause_on_unhandled_exceptions: false}) {
119 /// to run tests or testee in this invokation of the script. 191 var process = new _ServiceTesteeLauncher();
120 Future runIsolateTests(List<String> mainArgs,
121 List<IsolateTest> tests,
122 {testeeBefore(),
123 void testeeConcurrent(),
124 bool pause_on_start: false,
125 bool pause_on_exit: false,
126 bool trace_service: false,
127 bool trace_compiler: false,
128 bool verbose_vm: false,
129 bool pause_on_unhandled_exceptions: false}) async {
130 assert(!pause_on_start || testeeBefore == null);
131 if (mainArgs.contains(_TESTEE_MODE_FLAG)) {
132 if (!pause_on_start) {
133 if (testeeBefore != null) {
134 var result = testeeBefore();
135 if (result is Future) {
136 await result;
137 }
138 }
139 print(''); // Print blank line to signal that we are ready.
140 }
141 if (testeeConcurrent != null) {
142 testeeConcurrent();
143 }
144 if (!pause_on_exit) {
145 // Wait around for the process to be killed.
146 stdin.first.then((_) => exit(0));
147 }
148 } else {
149 var process = new _TestLauncher();
150 process.launch(pause_on_start, pause_on_exit, 192 process.launch(pause_on_start, pause_on_exit,
151 pause_on_unhandled_exceptions, 193 pause_on_unhandled_exceptions,
152 trace_service, trace_compiler).then((port) { 194 trace_service, trace_compiler).then((port) async {
153 if (mainArgs.contains("--gdb")) { 195 if (mainArgs.contains("--gdb")) {
154 port = 8181; 196 port = 8181;
155 } 197 }
156 String addr = 'ws://localhost:$port/ws'; 198 serviceWebsocketAddress = 'ws://localhost:$port/ws';
157 serviceHttpAddress = 'http://localhost:$port'; 199 serviceHttpAddress = 'http://localhost:$port';
158 var testIndex = 1;
159 var totalTests = tests.length;
160 var name = Platform.script.pathSegments.last; 200 var name = Platform.script.pathSegments.last;
161 runZoned(() { 201 runZoned(() {
162 new WebSocketVM(new WebSocketVMTarget(addr)).load() 202 new WebSocketVM(new WebSocketVMTarget(serviceWebsocketAddress)).load()
163 .then((VM vm) => vm.isolates.first.load()) 203 .then((VM vm) async {
164 .then((Isolate isolate) => Future.forEach(tests, (test) { 204
165 isolate.vm.verbose = verbose_vm; 205 // Run vm tests.
166 print('Running $name [$testIndex/$totalTests]'); 206 if (vmTests != null) {
167 testIndex++; 207 var testIndex = 1;
168 return test(isolate); 208 var totalTests = vmTests.length;
169 })).then((_) => process.requestExit()); 209 for (var test in vmTests) {
210 vm.verbose = verbose_vm;
211 print('Running $name [$testIndex/$totalTests]');
212 testIndex++;
213 await test(vm);
214 }
215 }
216
217 // Run isolate tests.
218 if (isolateTests != null) {
219 var isolate = await vm.isolates.first.load();
220 var testIndex = 1;
221 var totalTests = isolateTests.length;
222 for (var test in isolateTests) {
223 vm.verbose = verbose_vm;
224 print('Running $name [$testIndex/$totalTests]');
225 testIndex++;
226 await test(isolate);
227 }
228 }
229
230 await process.requestExit();
231 });
170 }, onError: (e, st) { 232 }, onError: (e, st) {
171 process.requestExit(); 233 process.requestExit();
172 if (!_isWebSocketDisconnect(e)) { 234 if (!_isWebSocketDisconnect(e)) {
173 print('Unexpected exception in service tests: $e $st'); 235 print('Unexpected exception in service tests: $e $st');
174 throw e; 236 throw e;
175 } 237 }
176 }); 238 });
177 }); 239 });
178 } 240 }
179 } 241 }
180 242
181 /// Runs [tests] in sequence, each of which should take an [Isolate] and 243 /// Runs [tests] in sequence, each of which should take an [Isolate] and
182 /// return a [Future]. Code for setting up state can run before and/or 244 /// return a [Future]. Code for setting up state can run before and/or
183 /// concurrently with the tests. Uses [mainArgs] to determine whether 245 /// concurrently with the tests. Uses [mainArgs] to determine whether
184 /// to run tests or testee in this invokation of the script. 246 /// to run tests or testee in this invokation of the script.
247 Future runIsolateTests(List<String> mainArgs,
248 List<IsolateTest> tests,
249 {testeeBefore(),
250 testeeConcurrent(),
251 bool pause_on_start: false,
252 bool pause_on_exit: false,
253 bool trace_service: false,
254 bool trace_compiler: false,
255 bool verbose_vm: false,
256 bool pause_on_unhandled_exceptions: false}) async {
257 assert(!pause_on_start || testeeBefore == null);
258 if (_isTestee()) {
259 new _SerivceTesteeRunner().run(testeeBefore: testeeBefore,
260 testeeConcurrent: testeeConcurrent,
261 pause_on_start: pause_on_start,
262 pause_on_exit: pause_on_exit);
263 } else {
264 new _ServiceTesterRunner().run(
265 mainArgs: mainArgs,
266 isolateTests: tests,
267 pause_on_start: pause_on_start,
268 pause_on_exit: pause_on_exit,
269 trace_service: trace_service,
270 trace_compiler: trace_compiler,
271 verbose_vm: verbose_vm,
272 pause_on_unhandled_exceptions: pause_on_unhandled_exceptions);
273 }
274 }
275
276 /// Runs [tests] in sequence, each of which should take an [Isolate] and
277 /// return a [Future]. Code for setting up state can run before and/or
278 /// concurrently with the tests. Uses [mainArgs] to determine whether
279 /// to run tests or testee in this invokation of the script.
185 /// 280 ///
186 /// This is a special version of this test harness specifically for the 281 /// This is a special version of this test harness specifically for the
187 /// pause_on_unhandled_exceptions_test, which cannot properly function 282 /// pause_on_unhandled_exceptions_test, which cannot properly function
188 /// in an async context (because exceptions are *always* handled in async 283 /// in an async context (because exceptions are *always* handled in async
189 /// functions). 284 /// functions).
190 ///
191 /// TODO(johnmccutchan): Don't use the shared harness for the
192 /// pause_on_unhandled_exceptions_test.
193 void runIsolateTestsSynchronous(List<String> mainArgs, 285 void runIsolateTestsSynchronous(List<String> mainArgs,
194 List<IsolateTest> tests, 286 List<IsolateTest> tests,
195 {void testeeBefore(), 287 {void testeeBefore(),
196 void testeeConcurrent(), 288 void testeeConcurrent(),
197 bool pause_on_start: false, 289 bool pause_on_start: false,
198 bool pause_on_exit: false, 290 bool pause_on_exit: false,
199 bool trace_service: false, 291 bool trace_service: false,
200 bool trace_compiler: false, 292 bool trace_compiler: false,
201 bool verbose_vm: false, 293 bool verbose_vm: false,
202 bool pause_on_unhandled_exceptions: false}) { 294 bool pause_on_unhandled_exceptions: false}) {
203 assert(!pause_on_start || testeeBefore == null); 295 assert(!pause_on_start || testeeBefore == null);
204 if (mainArgs.contains(_TESTEE_MODE_FLAG)) { 296 if (_isTestee()) {
205 if (!pause_on_start) { 297 new _SerivceTesteeRunner().runSync(testeeBeforeSync: testeeBefore,
206 if (testeeBefore != null) { 298 testeeConcurrentSync: testeeConcurrent,
207 testeeBefore(); 299 pause_on_start: pause_on_start,
208 } 300 pause_on_exit: pause_on_exit);
209 print(''); // Print blank line to signal that we are ready.
210 }
211 if (testeeConcurrent != null) {
212 testeeConcurrent();
213 }
214 if (!pause_on_exit) {
215 // Wait around for the process to be killed.
216 stdin.first.then((_) => exit(0));
217 }
218 } else { 301 } else {
219 var process = new _TestLauncher(); 302 new _ServiceTesterRunner().run(
220 process.launch(pause_on_start, pause_on_exit, 303 mainArgs: mainArgs,
221 pause_on_unhandled_exceptions, 304 isolateTests: tests,
222 trace_service, trace_compiler).then((port) { 305 pause_on_start: pause_on_start,
223 if (mainArgs.contains("--gdb")) { 306 pause_on_exit: pause_on_exit,
224 port = 8181; 307 trace_service: trace_service,
225 } 308 trace_compiler: trace_compiler,
226 String addr = 'ws://localhost:$port/ws'; 309 verbose_vm: verbose_vm,
227 serviceHttpAddress = 'http://localhost:$port'; 310 pause_on_unhandled_exceptions: pause_on_unhandled_exceptions);
228 var testIndex = 1;
229 var totalTests = tests.length;
230 var name = Platform.script.pathSegments.last;
231 runZoned(() {
232 new WebSocketVM(new WebSocketVMTarget(addr)).load()
233 .then((VM vm) => vm.isolates.first.load())
234 .then((Isolate isolate) => Future.forEach(tests, (test) {
235 isolate.vm.verbose = verbose_vm;
236 print('Running $name [$testIndex/$totalTests]');
237 testIndex++;
238 return test(isolate);
239 })).then((_) => process.requestExit());
240 }, onError: (e, st) {
241 process.requestExit();
242 if (!_isWebSocketDisconnect(e)) {
243 print('Unexpected exception in service tests: $e $st');
244 throw e;
245 }
246 });
247 });
248 } 311 }
249 } 312 }
250 313
251 Future asyncStepOver(Isolate isolate) async {
252 final Completer pausedAtSyntheticBreakpoint = new Completer();
253 StreamSubscription subscription;
254 314
255 // Cancel the subscription.
256 cancelSubscription() {
257 if (subscription != null) {
258 subscription.cancel();
259 subscription = null;
260 }
261 }
262
263 // Complete futures with with error.
264 completeError(error) {
265 if (!pausedAtSyntheticBreakpoint.isCompleted) {
266 pausedAtSyntheticBreakpoint.completeError(error);
267 }
268 }
269
270 // Subscribe to the debugger event stream.
271 Stream stream;
272 try {
273 stream = await isolate.vm.getEventStream(VM.kDebugStream);
274 } catch (e) {
275 completeError(e);
276 return pausedAtSyntheticBreakpoint.future;
277 }
278
279 Breakpoint syntheticBreakpoint;
280
281 subscription = stream.listen((ServiceEvent event) async {
282 // Synthetic breakpoint add event. This is the first event we will
283 // receive.
284 bool isAdd = (event.kind == ServiceEvent.kBreakpointAdded) &&
285 (event.breakpoint.isSyntheticAsyncContinuation) &&
286 (event.owner == isolate);
287 // Resume after synthetic breakpoint added. This is the second event
288 // we will recieve.
289 bool isResume = (event.kind == ServiceEvent.kResume) &&
290 (syntheticBreakpoint != null) &&
291 (event.owner == isolate);
292 // Paused at synthetic breakpoint. This is the third event we will
293 // receive.
294 bool isPaused = (event.kind == ServiceEvent.kPauseBreakpoint) &&
295 (syntheticBreakpoint != null) &&
296 (event.breakpoint == syntheticBreakpoint);
297 if (isAdd) {
298 syntheticBreakpoint = event.breakpoint;
299 } else if (isResume) {
300 } else if (isPaused) {
301 pausedAtSyntheticBreakpoint.complete(isolate);
302 syntheticBreakpoint = null;
303 cancelSubscription();
304 }
305 });
306
307 // Issue the step OverAwait command.
308 try {
309 await isolate.stepOverAsyncSuspension();
310 } catch (e) {
311 // This can fail when another client issued the same resume command
312 // or another client has moved the isolate forward.
313 cancelSubscription();
314 completeError(e);
315 }
316
317 return pausedAtSyntheticBreakpoint.future;
318 }
319
320
321 Future<Isolate> hasPausedFor(Isolate isolate, String kind) {
322 // Set up a listener to wait for breakpoint events.
323 Completer completer = new Completer();
324 isolate.vm.getEventStream(VM.kDebugStream).then((stream) {
325 var subscription;
326 subscription = stream.listen((ServiceEvent event) {
327 if (event.kind == kind) {
328 print('Paused with $kind');
329 subscription.cancel();
330 if (completer != null) {
331 // Reload to update isolate.pauseEvent.
332 completer.complete(isolate.reload());
333 completer = null;
334 }
335 }
336 });
337
338 // Pause may have happened before we subscribed.
339 isolate.reload().then((_) {
340 if ((isolate.pauseEvent != null) &&
341 (isolate.pauseEvent.kind == kind)) {
342 // Already waiting at a breakpoint.
343 print('Paused with $kind');
344 subscription.cancel();
345 if (completer != null) {
346 completer.complete(isolate);
347 completer = null;
348 }
349 }
350 });
351 });
352
353 return completer.future; // Will complete when breakpoint hit.
354 }
355
356 Future<Isolate> hasStoppedAtBreakpoint(Isolate isolate) {
357 return hasPausedFor(isolate, ServiceEvent.kPauseBreakpoint);
358 }
359
360 Future<Isolate> hasStoppedWithUnhandledException(Isolate isolate) {
361 return hasPausedFor(isolate, ServiceEvent.kPauseException);
362 }
363
364 Future<Isolate> hasPausedAtStart(Isolate isolate) {
365 return hasPausedFor(isolate, ServiceEvent.kPauseStart);
366 }
367
368 // Currying is your friend.
369 IsolateTest setBreakpointAtLine(int line) {
370 return (Isolate isolate) async {
371 print("Setting breakpoint for line $line");
372 Library lib = await isolate.rootLibrary.load();
373 Script script = lib.scripts.single;
374
375 Breakpoint bpt = await isolate.addBreakpoint(script, line);
376 print("Breakpoint is $bpt");
377 expect(bpt, isNotNull);
378 expect(bpt is Breakpoint, isTrue);
379 };
380 }
381
382 IsolateTest stoppedAtLine(int line) {
383 return (Isolate isolate) async {
384 print("Checking we are at line $line");
385
386 ServiceMap stack = await isolate.getStack();
387 expect(stack.type, equals('Stack'));
388
389 List<Frame> frames = stack['frames'];
390 expect(frames.length, greaterThanOrEqualTo(1));
391
392 Frame top = frames[0];
393 Script script = await top.location.script.load();
394 int actualLine = script.tokenToLine(top.location.tokenPos);
395 if (actualLine != line) {
396 var sb = new StringBuffer();
397 sb.write("Expected to be at line $line but actually at line $actualLine");
398 sb.write("\nFull stack trace:\n");
399 for (Frame f in stack['frames']) {
400 sb.write(" $f [${await f.location.getLine()}]\n");
401 }
402 throw sb.toString();
403 }
404 };
405 }
406
407
408 Future<Isolate> resumeIsolate(Isolate isolate) {
409 Completer completer = new Completer();
410 isolate.vm.getEventStream(VM.kDebugStream).then((stream) {
411 var subscription;
412 subscription = stream.listen((ServiceEvent event) {
413 if (event.kind == ServiceEvent.kResume) {
414 subscription.cancel();
415 completer.complete();
416 }
417 });
418 });
419 isolate.resume();
420 return completer.future;
421 }
422
423
424 Future resumeAndAwaitEvent(Isolate isolate, stream, onEvent) async {
425 Completer completer = new Completer();
426 var sub;
427 sub = await isolate.vm.listenEventStream(
428 stream,
429 (ServiceEvent event) {
430 var r = onEvent(event);
431 if (r is! Future) {
432 r = new Future.value(r);
433 }
434 r.then((x) => sub.cancel().then((_) {
435 completer.complete();
436 }));
437 });
438 await isolate.resume();
439 return completer.future;
440 }
441
442 IsolateTest resumeIsolateAndAwaitEvent(stream, onEvent) {
443 return (Isolate isolate) async =>
444 resumeAndAwaitEvent(isolate, stream, onEvent);
445 }
446
447
448 Future<Isolate> stepOver(Isolate isolate) async {
449 await isolate.stepOver();
450 return hasStoppedAtBreakpoint(isolate);
451 }
452
453 Future<Class> getClassFromRootLib(Isolate isolate, String className) async {
454 Library rootLib = await isolate.rootLibrary.load();
455 for (var i = 0; i < rootLib.classes.length; i++) {
456 Class cls = rootLib.classes[i];
457 if (cls.name == className) {
458 return cls;
459 }
460 }
461 return null;
462 }
463
464
465 Future<Instance> rootLibraryFieldValue(Isolate isolate,
466 String fieldName) async {
467 Library rootLib = await isolate.rootLibrary.load();
468 Field field = rootLib.variables.singleWhere((v) => v.name == fieldName);
469 await field.load();
470 Instance value = field.staticValue;
471 await value.load();
472 return value;
473 }
474
475
476 /// Runs [tests] in sequence, each of which should take an [Isolate] and 315 /// Runs [tests] in sequence, each of which should take an [Isolate] and
477 /// return a [Future]. Code for setting up state can run before and/or 316 /// return a [Future]. Code for setting up state can run before and/or
478 /// concurrently with the tests. Uses [mainArgs] to determine whether 317 /// concurrently with the tests. Uses [mainArgs] to determine whether
479 /// to run tests or testee in this invokation of the script. 318 /// to run tests or testee in this invokation of the script.
480 Future runVMTests(List<String> mainArgs, 319 Future runVMTests(List<String> mainArgs,
481 List<VMTest> tests, 320 List<VMTest> tests,
482 {Future testeeBefore(), 321 {testeeBefore(),
483 Future testeeConcurrent(), 322 testeeConcurrent(),
484 bool pause_on_start: false, 323 bool pause_on_start: false,
485 bool pause_on_exit: false, 324 bool pause_on_exit: false,
486 bool trace_service: false, 325 bool trace_service: false,
487 bool trace_compiler: false, 326 bool trace_compiler: false,
488 bool verbose_vm: false, 327 bool verbose_vm: false,
489 bool pause_on_unhandled_exceptions: false}) async { 328 bool pause_on_unhandled_exceptions: false}) async {
490 if (mainArgs.contains(_TESTEE_MODE_FLAG)) { 329 if (_isTestee()) {
491 if (!pause_on_start) { 330 new _SerivceTesteeRunner().run(testeeBefore: testeeBefore,
492 if (testeeBefore != null) { 331 testeeConcurrent: testeeConcurrent,
493 await testeeBefore(); 332 pause_on_start: pause_on_start,
494 } 333 pause_on_exit: pause_on_exit);
495 print(''); // Print blank line to signal that we are ready.
496 }
497 if (testeeConcurrent != null) {
498 await testeeConcurrent();
499 }
500 if (!pause_on_exit) {
501 // Wait around for the process to be killed.
502 stdin.first.then((_) => exit(0));
503 }
504 } else { 334 } else {
505 var process = new _TestLauncher(); 335 new _ServiceTesterRunner().run(
506 process.launch(pause_on_start, 336 mainArgs: mainArgs,
507 pause_on_exit, 337 vmTests: tests,
508 pause_on_unhandled_exceptions, 338 pause_on_start: pause_on_start,
509 trace_service, trace_compiler).then((port) async { 339 pause_on_exit: pause_on_exit,
510 if (mainArgs.contains("--gdb")) { 340 trace_service: trace_service,
511 port = 8181; 341 trace_compiler: trace_compiler,
512 } 342 verbose_vm: verbose_vm,
513 String addr = 'ws://localhost:$port/ws'; 343 pause_on_unhandled_exceptions: pause_on_unhandled_exceptions);
514 serviceHttpAddress = 'http://localhost:$port';
515 var testIndex = 1;
516 var totalTests = tests.length;
517 var name = Platform.script.pathSegments.last;
518 runZoned(() {
519 new WebSocketVM(new WebSocketVMTarget(addr)).load()
520 .then((VM vm) => Future.forEach(tests, (test) {
521 vm.verbose = verbose_vm;
522 print('Running $name [$testIndex/$totalTests]');
523 testIndex++;
524 return test(vm);
525 })).then((_) => process.requestExit());
526 }, onError: (e, st) {
527 process.requestExit();
528 if (!_isWebSocketDisconnect(e)) {
529 print('Unexpected exception in service tests: $e $st');
530 throw e;
531 }
532 });
533 });
534 } 344 }
535 } 345 }
OLDNEW
« no previous file with comments | « runtime/observatory/tests/service/step_over_await_test.dart ('k') | runtime/observatory/tests/service/vm_restart_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698