| OLD | NEW |
| (Empty) |
| 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 // VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked | |
| 5 | |
| 6 library test_helper; | |
| 7 | |
| 8 import 'dart:async'; | |
| 9 import 'dart:convert'; | |
| 10 import 'dart:io'; | |
| 11 import 'package:observatory/service_io.dart'; | |
| 12 | |
| 13 // This invocation should set up the state being tested. | |
| 14 const String _TESTEE_MODE_FLAG = "--testee-mode"; | |
| 15 | |
| 16 class _TestLauncher { | |
| 17 Process process; | |
| 18 final List<String> args; | |
| 19 | |
| 20 _TestLauncher() : args = ['--enable-vm-service:0', | |
| 21 Platform.script.toFilePath(), | |
| 22 _TESTEE_MODE_FLAG] {} | |
| 23 | |
| 24 Future<int> launch(bool pause_on_exit) { | |
| 25 String dartExecutable = Platform.executable; | |
| 26 var fullArgs = []; | |
| 27 if (pause_on_exit == true) { | |
| 28 fullArgs.add('--pause-isolates-on-exit'); | |
| 29 } | |
| 30 fullArgs.addAll(Platform.executableArguments); | |
| 31 fullArgs.addAll(args); | |
| 32 print('** Launching $dartExecutable ${fullArgs.join(' ')}'); | |
| 33 return Process.start(dartExecutable, fullArgs).then((p) { | |
| 34 | |
| 35 Completer completer = new Completer(); | |
| 36 process = p; | |
| 37 var portNumber; | |
| 38 var blank; | |
| 39 var first = true; | |
| 40 process.stdout.transform(UTF8.decoder) | |
| 41 .transform(new LineSplitter()).listen((line) { | |
| 42 if (line.startsWith('Observatory listening on http://')) { | |
| 43 RegExp portExp = new RegExp(r"\d+.\d+.\d+.\d+:(\d+)"); | |
| 44 var port = portExp.firstMatch(line).group(1); | |
| 45 portNumber = int.parse(port); | |
| 46 } | |
| 47 if (line == '') { | |
| 48 // Received blank line. | |
| 49 blank = true; | |
| 50 } | |
| 51 if (portNumber != null && blank == true && first == true) { | |
| 52 completer.complete(portNumber); | |
| 53 // Stop repeat completions. | |
| 54 first = false; | |
| 55 print('** Signaled to run test queries on $portNumber'); | |
| 56 } | |
| 57 print(line); | |
| 58 }); | |
| 59 process.stderr.transform(UTF8.decoder) | |
| 60 .transform(new LineSplitter()).listen((line) { | |
| 61 print(line); | |
| 62 }); | |
| 63 process.exitCode.then((exitCode) { | |
| 64 print("** Process exited"); | |
| 65 }); | |
| 66 return completer.future; | |
| 67 }); | |
| 68 } | |
| 69 | |
| 70 void requestExit() { | |
| 71 print('** Killing script'); | |
| 72 process.kill(); | |
| 73 } | |
| 74 } | |
| 75 | |
| 76 typedef Future IsolateTest(Isolate isolate); | |
| 77 typedef Future VMTest(VM vm); | |
| 78 | |
| 79 /// Runs [tests] in sequence, each of which should take an [Isolate] and | |
| 80 /// return a [Future]. Code for setting up state can run before and/or | |
| 81 /// concurrently with the tests. Uses [mainArgs] to determine whether | |
| 82 /// to run tests or testee in this invokation of the script. | |
| 83 void runIsolateTests(List<String> mainArgs, | |
| 84 List<IsolateTest> tests, | |
| 85 {void testeeBefore(), | |
| 86 void testeeConcurrent(), | |
| 87 bool pause_on_exit}) { | |
| 88 if (mainArgs.contains(_TESTEE_MODE_FLAG)) { | |
| 89 if (testeeBefore != null) { | |
| 90 testeeBefore(); | |
| 91 } | |
| 92 print(''); // Print blank line to signal that we are ready. | |
| 93 if (testeeConcurrent != null) { | |
| 94 testeeConcurrent(); | |
| 95 } | |
| 96 // Wait around for the process to be killed. | |
| 97 stdin.first.then((_) => exit(0)); | |
| 98 } else { | |
| 99 var process = new _TestLauncher(); | |
| 100 process.launch(pause_on_exit).then((port) { | |
| 101 String addr = 'ws://localhost:$port/ws'; | |
| 102 var testIndex = 0; | |
| 103 var totalTests = tests.length - 1; | |
| 104 var name = Platform.script.pathSegments.last; | |
| 105 new WebSocketVM(new WebSocketVMTarget(addr)).load() | |
| 106 .then((VM vm) => vm.isolates.first.load()) | |
| 107 .then((Isolate isolate) => Future.forEach(tests, (test) { | |
| 108 print('Running $name [$testIndex/$totalTests]'); | |
| 109 testIndex++; | |
| 110 return test(isolate); | |
| 111 })).then((_) => process.requestExit()); | |
| 112 }); | |
| 113 } | |
| 114 } | |
| 115 | |
| 116 | |
| 117 // Cancel the subscription and complete the completer when finished processing | |
| 118 // events. | |
| 119 typedef void ServiceEventHandler(ServiceEvent event, | |
| 120 StreamSubscription subscription, | |
| 121 Completer completer); | |
| 122 | |
| 123 Future processServiceEvents(VM vm, ServiceEventHandler handler) { | |
| 124 Completer completer = new Completer(); | |
| 125 var subscription; | |
| 126 subscription = vm.events.stream.listen((ServiceEvent event) { | |
| 127 handler(event, subscription, completer); | |
| 128 }); | |
| 129 return completer.future; | |
| 130 } | |
| 131 | |
| 132 | |
| 133 /// Runs [tests] in sequence, each of which should take an [Isolate] and | |
| 134 /// return a [Future]. Code for setting up state can run before and/or | |
| 135 /// concurrently with the tests. Uses [mainArgs] to determine whether | |
| 136 /// to run tests or testee in this invokation of the script. | |
| 137 Future runVMTests(List<String> mainArgs, | |
| 138 List<VMTest> tests, | |
| 139 {Future testeeBefore(), | |
| 140 Future testeeConcurrent(), | |
| 141 bool pause_on_exit}) async { | |
| 142 if (mainArgs.contains(_TESTEE_MODE_FLAG)) { | |
| 143 if (testeeBefore != null) { | |
| 144 await testeeBefore(); | |
| 145 } | |
| 146 print(''); // Print blank line to signal that we are ready. | |
| 147 if (testeeConcurrent != null) { | |
| 148 await testeeConcurrent(); | |
| 149 } | |
| 150 // Wait around for the process to be killed. | |
| 151 stdin.first.then((_) => exit(0)); | |
| 152 } else { | |
| 153 var process = new _TestLauncher(); | |
| 154 process.launch(pause_on_exit).then((port) async { | |
| 155 String addr = 'ws://localhost:$port/ws'; | |
| 156 var testIndex = 0; | |
| 157 var totalTests = tests.length - 1; | |
| 158 var name = Platform.script.pathSegments.last; | |
| 159 new WebSocketVM(new WebSocketVMTarget(addr)).load() | |
| 160 .then((VM vm) => Future.forEach(tests, (test) { | |
| 161 print('Running $name [$testIndex/$totalTests]'); | |
| 162 testIndex++; | |
| 163 return test(vm); | |
| 164 })).then((_) => process.requestExit()); | |
| 165 }); | |
| 166 } | |
| 167 } | |
| OLD | NEW |