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 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'; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 bool killedByTester = false; | 84 bool killedByTester = false; |
85 | 85 |
86 _ServiceTesteeLauncher() : | 86 _ServiceTesteeLauncher() : |
87 args = [Platform.script.toFilePath()] {} | 87 args = [Platform.script.toFilePath()] {} |
88 | 88 |
89 // Spawn the testee process. | 89 // Spawn the testee process. |
90 Future<Process> _spawnProcess(bool pause_on_start, | 90 Future<Process> _spawnProcess(bool pause_on_start, |
91 bool pause_on_exit, | 91 bool pause_on_exit, |
92 bool pause_on_unhandled_exceptions, | 92 bool pause_on_unhandled_exceptions, |
93 bool trace_service, | 93 bool trace_service, |
94 bool trace_compiler) { | 94 bool trace_compiler, |
| 95 bool testeeControlsServer) { |
95 assert(pause_on_start != null); | 96 assert(pause_on_start != null); |
96 assert(pause_on_exit != null); | 97 assert(pause_on_exit != null); |
97 assert(pause_on_unhandled_exceptions != null); | 98 assert(pause_on_unhandled_exceptions != null); |
98 assert(trace_service != null); | 99 assert(trace_service != null); |
99 assert(trace_compiler != null); | 100 assert(trace_compiler != null); |
| 101 assert(testeeControlsServer != null); |
100 | 102 |
101 if (_shouldLaunchSkyShell()) { | 103 if (_shouldLaunchSkyShell()) { |
102 return _spawnSkyProcess(pause_on_start, | 104 return _spawnSkyProcess(pause_on_start, |
103 pause_on_exit, | 105 pause_on_exit, |
104 pause_on_unhandled_exceptions, | 106 pause_on_unhandled_exceptions, |
105 trace_service, | 107 trace_service, |
106 trace_compiler); | 108 trace_compiler, |
| 109 testeeControlsServer); |
107 } else { | 110 } else { |
108 return _spawnDartProcess(pause_on_start, | 111 return _spawnDartProcess(pause_on_start, |
109 pause_on_exit, | 112 pause_on_exit, |
110 pause_on_unhandled_exceptions, | 113 pause_on_unhandled_exceptions, |
111 trace_service, | 114 trace_service, |
112 trace_compiler); | 115 trace_compiler, |
| 116 testeeControlsServer); |
113 } | 117 } |
114 } | 118 } |
115 | 119 |
116 Future<Process> _spawnDartProcess(bool pause_on_start, | 120 Future<Process> _spawnDartProcess(bool pause_on_start, |
117 bool pause_on_exit, | 121 bool pause_on_exit, |
118 bool pause_on_unhandled_exceptions, | 122 bool pause_on_unhandled_exceptions, |
119 bool trace_service, | 123 bool trace_service, |
120 bool trace_compiler) { | 124 bool trace_compiler, |
| 125 bool testeeControlsServer) { |
121 assert(!_shouldLaunchSkyShell()); | 126 assert(!_shouldLaunchSkyShell()); |
122 | 127 |
123 String dartExecutable = Platform.executable; | 128 String dartExecutable = Platform.executable; |
124 | 129 |
125 var fullArgs = []; | 130 var fullArgs = []; |
126 if (trace_service) { | 131 if (trace_service) { |
127 fullArgs.add('--trace-service'); | 132 fullArgs.add('--trace-service'); |
128 fullArgs.add('--trace-service-verbose'); | 133 fullArgs.add('--trace-service-verbose'); |
129 } | 134 } |
130 if (trace_compiler) { | 135 if (trace_compiler) { |
131 fullArgs.add('--trace-compiler'); | 136 fullArgs.add('--trace-compiler'); |
132 } | 137 } |
133 if (pause_on_start) { | 138 if (pause_on_start) { |
134 fullArgs.add('--pause-isolates-on-start'); | 139 fullArgs.add('--pause-isolates-on-start'); |
135 } | 140 } |
136 if (pause_on_exit) { | 141 if (pause_on_exit) { |
137 fullArgs.add('--pause-isolates-on-exit'); | 142 fullArgs.add('--pause-isolates-on-exit'); |
138 } | 143 } |
139 if (pause_on_unhandled_exceptions) { | 144 if (pause_on_unhandled_exceptions) { |
140 fullArgs.add('--pause-isolates-on-unhandled-exceptions'); | 145 fullArgs.add('--pause-isolates-on-unhandled-exceptions'); |
141 } | 146 } |
142 | 147 |
143 fullArgs.addAll(Platform.executableArguments); | 148 fullArgs.addAll(Platform.executableArguments); |
144 fullArgs.add('--enable-vm-service:0'); | 149 if (!testeeControlsServer) { |
| 150 fullArgs.add('--enable-vm-service:0'); |
| 151 } |
145 fullArgs.addAll(args); | 152 fullArgs.addAll(args); |
146 | 153 |
147 return _spawnCommon(dartExecutable, fullArgs); | 154 return _spawnCommon(dartExecutable, fullArgs); |
148 } | 155 } |
149 | 156 |
150 Future<Process> _spawnSkyProcess(bool pause_on_start, | 157 Future<Process> _spawnSkyProcess(bool pause_on_start, |
151 bool pause_on_exit, | 158 bool pause_on_exit, |
152 bool pause_on_unhandled_exceptions, | 159 bool pause_on_unhandled_exceptions, |
153 bool trace_service, | 160 bool trace_service, |
154 bool trace_compiler) { | 161 bool trace_compiler) { |
(...skipping 17 matching lines...) Expand all Loading... |
172 if (pause_on_exit) { | 179 if (pause_on_exit) { |
173 dartFlags.add('--pause_isolates_on_exit'); | 180 dartFlags.add('--pause_isolates_on_exit'); |
174 } | 181 } |
175 if (pause_on_unhandled_exceptions) { | 182 if (pause_on_unhandled_exceptions) { |
176 dartFlags.add('--pause_isolates_on_unhandled_exceptions'); | 183 dartFlags.add('--pause_isolates_on_unhandled_exceptions'); |
177 } | 184 } |
178 // Override mirrors. | 185 // Override mirrors. |
179 dartFlags.add('--enable_mirrors=true'); | 186 dartFlags.add('--enable_mirrors=true'); |
180 | 187 |
181 fullArgs.addAll(Platform.executableArguments); | 188 fullArgs.addAll(Platform.executableArguments); |
182 fullArgs.add('--observatory-port=0'); | 189 if (!testeeControlsServer) { |
| 190 fullArgs.add('--observatory-port=0'); |
| 191 } |
183 fullArgs.add('--dart-flags=${dartFlags.join(' ')}'); | 192 fullArgs.add('--dart-flags=${dartFlags.join(' ')}'); |
184 fullArgs.addAll(args); | 193 fullArgs.addAll(args); |
185 | 194 |
186 return _spawnCommon(dartExecutable, fullArgs); | 195 return _spawnCommon(dartExecutable, fullArgs); |
187 } | 196 } |
188 | 197 |
189 Future<Process> _spawnCommon(String executable, List<String> arguments) { | 198 Future<Process> _spawnCommon(String executable, List<String> arguments) { |
190 var environment = _TESTEE_SPAWN_ENV; | 199 var environment = _TESTEE_SPAWN_ENV; |
191 var bashEnvironment = new StringBuffer(); | 200 var bashEnvironment = new StringBuffer(); |
192 environment.forEach((k, v) => bashEnvironment.write("$k=$v ")); | 201 environment.forEach((k, v) => bashEnvironment.write("$k=$v ")); |
193 print('** Launching $bashEnvironment$executable ${arguments.join(' ')}'); | 202 print('** Launching $bashEnvironment$executable ${arguments.join(' ')}'); |
194 return Process.start(executable, arguments, environment: environment); | 203 return Process.start(executable, arguments, environment: environment); |
195 } | 204 } |
196 | 205 |
197 Future<int> launch(bool pause_on_start, | 206 Future<Uri> launch(bool pause_on_start, |
198 bool pause_on_exit, | 207 bool pause_on_exit, |
199 bool pause_on_unhandled_exceptions, | 208 bool pause_on_unhandled_exceptions, |
200 bool trace_service, | 209 bool trace_service, |
201 bool trace_compiler) { | 210 bool trace_compiler, |
| 211 bool testeeControlsServer) { |
202 return _spawnProcess(pause_on_start, | 212 return _spawnProcess(pause_on_start, |
203 pause_on_exit, | 213 pause_on_exit, |
204 pause_on_unhandled_exceptions, | 214 pause_on_unhandled_exceptions, |
205 trace_service, | 215 trace_service, |
206 trace_compiler).then((p) { | 216 trace_compiler, |
207 Completer completer = new Completer(); | 217 testeeControlsServer).then((p) { |
| 218 Completer<Uri> completer = new Completer<Uri>(); |
208 process = p; | 219 process = p; |
209 var portNumber; | 220 Uri uri; |
210 var blank; | 221 var blank; |
211 var first = true; | 222 var first = true; |
212 process.stdout.transform(UTF8.decoder) | 223 process.stdout.transform(UTF8.decoder) |
213 .transform(new LineSplitter()).listen((line) { | 224 .transform(new LineSplitter()).listen((line) { |
214 if (line.startsWith('Observatory listening on http://')) { | 225 const kObservatoryListening = 'Observatory listening on '; |
215 RegExp portExp = new RegExp(r"\d+.\d+.\d+.\d+:(\d+)"); | 226 if (line.startsWith(kObservatoryListening)) { |
216 var port = portExp.firstMatch(line).group(1); | 227 uri = Uri.parse(line.substring(kObservatoryListening.length)); |
217 portNumber = int.parse(port); | |
218 } | 228 } |
219 if (pause_on_start || line == '') { | 229 if (pause_on_start || line == '') { |
220 // Received blank line. | 230 // Received blank line. |
221 blank = true; | 231 blank = true; |
222 } | 232 } |
223 if (portNumber != null && blank == true && first == true) { | 233 if ((uri != null) && (blank == true) && (first == true)) { |
224 completer.complete(portNumber); | 234 completer.complete(uri); |
225 // Stop repeat completions. | 235 // Stop repeat completions. |
226 first = false; | 236 first = false; |
227 print('** Signaled to run test queries on $portNumber'); | 237 print('** Signaled to run test queries on $uri'); |
228 } | 238 } |
229 print('>testee>out> $line'); | 239 print('>testee>out> $line'); |
230 }); | 240 }); |
231 process.stderr.transform(UTF8.decoder) | 241 process.stderr.transform(UTF8.decoder) |
232 .transform(new LineSplitter()).listen((line) { | 242 .transform(new LineSplitter()).listen((line) { |
233 print('>testee>err> $line'); | 243 print('>testee>err> $line'); |
234 }); | 244 }); |
235 process.exitCode.then((exitCode) { | 245 process.exitCode.then((exitCode) { |
236 if ((exitCode != 0) && !killedByTester) { | 246 if ((exitCode != 0) && !killedByTester) { |
237 throw "Testee exited with $exitCode"; | 247 throw "Testee exited with $exitCode"; |
238 } | 248 } |
239 print("** Process exited"); | 249 print("** Process exited"); |
240 }); | 250 }); |
241 return completer.future; | 251 return completer.future; |
242 }); | 252 }); |
243 } | 253 } |
244 | 254 |
245 void requestExit() { | 255 void requestExit() { |
246 print('** Killing script'); | 256 print('** Killing script'); |
247 if (process.kill()) { | 257 if (process.kill()) { |
248 killedByTester = true; | 258 killedByTester = true; |
249 } | 259 } |
250 } | 260 } |
251 } | 261 } |
252 | 262 |
253 // A tester runner that doesn't spawn a process but instead connects to | 263 void setupAddresses(Uri serverAddress) { |
254 // an already running flutter application running on a device. Assumes | 264 serviceWebsocketAddress = |
255 // port 8100. This is only useful for debugging. | 265 'ws://${serverAddress.authority}${serverAddress.path}ws'; |
256 class _FlutterDeviceServiceTesterRunner { | 266 serviceHttpAddress = |
257 void run({List<String> mainArgs, | 267 'http://${serverAddress.authority}${serverAddress.path}'; |
258 List<VMTest> vmTests, | |
259 List<IsolateTest> isolateTests, | |
260 bool pause_on_start: false, | |
261 bool pause_on_exit: false, | |
262 bool trace_service: false, | |
263 bool trace_compiler: false, | |
264 bool verbose_vm: false, | |
265 bool pause_on_unhandled_exceptions: false}) { | |
266 var port = 8100; | |
267 serviceWebsocketAddress = 'ws://localhost:$port/ws'; | |
268 serviceHttpAddress = 'http://localhost:$port'; | |
269 var name = Platform.script.pathSegments.last; | |
270 Chain.capture(() async { | |
271 var vm = | |
272 new WebSocketVM(new WebSocketVMTarget(serviceWebsocketAddress)); | |
273 print('Loading VM...'); | |
274 await vm.load(); | |
275 print('Done loading VM'); | |
276 | |
277 // Run vm tests. | |
278 if (vmTests != null) { | |
279 var testIndex = 1; | |
280 var totalTests = vmTests.length; | |
281 for (var test in vmTests) { | |
282 vm.verbose = verbose_vm; | |
283 print('Running $name [$testIndex/$totalTests]'); | |
284 testIndex++; | |
285 await test(vm); | |
286 } | |
287 } | |
288 | |
289 // Run isolate tests. | |
290 if (isolateTests != null) { | |
291 var isolate = await vm.isolates.first.load(); | |
292 var testIndex = 1; | |
293 var totalTests = isolateTests.length; | |
294 for (var test in isolateTests) { | |
295 vm.verbose = verbose_vm; | |
296 print('Running $name [$testIndex/$totalTests]'); | |
297 testIndex++; | |
298 await test(isolate); | |
299 } | |
300 } | |
301 }, onError: (error, stackTrace) { | |
302 print('Unexpected exception in service tests: $error\n$stackTrace'); | |
303 }); | |
304 } | |
305 } | |
306 | |
307 void suppressWarning() { | |
308 new _FlutterDeviceServiceTesterRunner(); | |
309 } | 268 } |
310 | 269 |
311 class _ServiceTesterRunner { | 270 class _ServiceTesterRunner { |
312 void run({List<String> mainArgs, | 271 void run({List<String> mainArgs, |
313 List<VMTest> vmTests, | 272 List<VMTest> vmTests, |
314 List<IsolateTest> isolateTests, | 273 List<IsolateTest> isolateTests, |
315 bool pause_on_start: false, | 274 bool pause_on_start: false, |
316 bool pause_on_exit: false, | 275 bool pause_on_exit: false, |
317 bool trace_service: false, | 276 bool trace_service: false, |
318 bool trace_compiler: false, | 277 bool trace_compiler: false, |
319 bool verbose_vm: false, | 278 bool verbose_vm: false, |
320 bool pause_on_unhandled_exceptions: false}) { | 279 bool pause_on_unhandled_exceptions: false, |
| 280 bool testeeControlsServer: false}) { |
321 var process = new _ServiceTesteeLauncher(); | 281 var process = new _ServiceTesteeLauncher(); |
322 process.launch(pause_on_start, pause_on_exit, | 282 process.launch(pause_on_start, pause_on_exit, |
323 pause_on_unhandled_exceptions, | 283 pause_on_unhandled_exceptions, |
324 trace_service, trace_compiler).then((port) async { | 284 trace_service, trace_compiler, |
| 285 testeeControlsServer).then((Uri serverAddress) async { |
325 if (mainArgs.contains("--gdb")) { | 286 if (mainArgs.contains("--gdb")) { |
326 var pid = process.process.pid; | 287 var pid = process.process.pid; |
327 var wait = new Duration(seconds: 10); | 288 var wait = new Duration(seconds: 10); |
328 print("Testee has pid $pid, waiting $wait before continuing"); | 289 print("Testee has pid $pid, waiting $wait before continuing"); |
329 sleep(wait); | 290 sleep(wait); |
330 } | 291 } |
331 serviceWebsocketAddress = 'ws://localhost:$port/ws'; | 292 setupAddresses(serverAddress); |
332 serviceHttpAddress = 'http://localhost:$port'; | |
333 var name = Platform.script.pathSegments.last; | 293 var name = Platform.script.pathSegments.last; |
334 Chain.capture(() async { | 294 Chain.capture(() async { |
335 var vm = | 295 var vm = |
336 new WebSocketVM(new WebSocketVMTarget(serviceWebsocketAddress)); | 296 new WebSocketVM(new WebSocketVMTarget(serviceWebsocketAddress)); |
337 print('Loading VM...'); | 297 print('Loading VM...'); |
338 await vm.load(); | 298 await vm.load(); |
339 print('Done loading VM'); | 299 print('Done loading VM'); |
340 | 300 |
341 // Run vm tests. | 301 // Run vm tests. |
342 if (vmTests != null) { | 302 if (vmTests != null) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 /// to run tests or testee in this invokation of the script. | 339 /// to run tests or testee in this invokation of the script. |
380 Future runIsolateTests(List<String> mainArgs, | 340 Future runIsolateTests(List<String> mainArgs, |
381 List<IsolateTest> tests, | 341 List<IsolateTest> tests, |
382 {testeeBefore(), | 342 {testeeBefore(), |
383 testeeConcurrent(), | 343 testeeConcurrent(), |
384 bool pause_on_start: false, | 344 bool pause_on_start: false, |
385 bool pause_on_exit: false, | 345 bool pause_on_exit: false, |
386 bool trace_service: false, | 346 bool trace_service: false, |
387 bool trace_compiler: false, | 347 bool trace_compiler: false, |
388 bool verbose_vm: false, | 348 bool verbose_vm: false, |
389 bool pause_on_unhandled_exceptions: false}) async { | 349 bool pause_on_unhandled_exceptions: false, |
| 350 bool testeeControlsServer: false}) async { |
390 assert(!pause_on_start || testeeBefore == null); | 351 assert(!pause_on_start || testeeBefore == null); |
391 if (_isTestee()) { | 352 if (_isTestee()) { |
392 new _ServiceTesteeRunner().run(testeeBefore: testeeBefore, | 353 new _ServiceTesteeRunner().run(testeeBefore: testeeBefore, |
393 testeeConcurrent: testeeConcurrent, | 354 testeeConcurrent: testeeConcurrent, |
394 pause_on_start: pause_on_start, | 355 pause_on_start: pause_on_start, |
395 pause_on_exit: pause_on_exit); | 356 pause_on_exit: pause_on_exit); |
396 } else { | 357 } else { |
397 new _ServiceTesterRunner().run( | 358 new _ServiceTesterRunner().run( |
398 mainArgs: mainArgs, | 359 mainArgs: mainArgs, |
399 isolateTests: tests, | 360 isolateTests: tests, |
400 pause_on_start: pause_on_start, | 361 pause_on_start: pause_on_start, |
401 pause_on_exit: pause_on_exit, | 362 pause_on_exit: pause_on_exit, |
402 trace_service: trace_service, | 363 trace_service: trace_service, |
403 trace_compiler: trace_compiler, | 364 trace_compiler: trace_compiler, |
404 verbose_vm: verbose_vm, | 365 verbose_vm: verbose_vm, |
405 pause_on_unhandled_exceptions: pause_on_unhandled_exceptions); | 366 pause_on_unhandled_exceptions: pause_on_unhandled_exceptions, |
| 367 testeeControlsServer: testeeControlsServer); |
406 } | 368 } |
407 } | 369 } |
408 | 370 |
409 /// Runs [tests] in sequence, each of which should take an [Isolate] and | 371 /// Runs [tests] in sequence, each of which should take an [Isolate] and |
410 /// return a [Future]. Code for setting up state can run before and/or | 372 /// return a [Future]. Code for setting up state can run before and/or |
411 /// concurrently with the tests. Uses [mainArgs] to determine whether | 373 /// concurrently with the tests. Uses [mainArgs] to determine whether |
412 /// to run tests or testee in this invokation of the script. | 374 /// to run tests or testee in this invokation of the script. |
413 /// | 375 /// |
414 /// This is a special version of this test harness specifically for the | 376 /// This is a special version of this test harness specifically for the |
415 /// pause_on_unhandled_exceptions_test, which cannot properly function | 377 /// pause_on_unhandled_exceptions_test, which cannot properly function |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 mainArgs: mainArgs, | 431 mainArgs: mainArgs, |
470 vmTests: tests, | 432 vmTests: tests, |
471 pause_on_start: pause_on_start, | 433 pause_on_start: pause_on_start, |
472 pause_on_exit: pause_on_exit, | 434 pause_on_exit: pause_on_exit, |
473 trace_service: trace_service, | 435 trace_service: trace_service, |
474 trace_compiler: trace_compiler, | 436 trace_compiler: trace_compiler, |
475 verbose_vm: verbose_vm, | 437 verbose_vm: verbose_vm, |
476 pause_on_unhandled_exceptions: pause_on_unhandled_exceptions); | 438 pause_on_unhandled_exceptions: pause_on_unhandled_exceptions); |
477 } | 439 } |
478 } | 440 } |
OLD | NEW |