Skip to content

Commit d379762

Browse files
authored
Run flutter tests in preview-dart-2 mode on travis flutter builds. (flutter#14728)
* Run flutter tests in preview-dart-2 mode on travis flutter builds. * Run dart2 tests on osx. Run dart tests in dart2. * Fix name camelCase * Default options to empty array, rather than null * Troubleshoot failures * More logging * Troubleshoot: run single test * Troubleshoot: run 15 tests * Troubleshoot: run 15 tests with fix * Try limit concurrency to 1 * Limit concurrency for preview-dart-2 tests to 4 * Move dart2 tests to allow_failures section * Reinstate tests_dart_2 shard * Raise concurrency to 8 * Reuse compiler across multiple test runs * Allow to switch entry points when recompiling. Actually use single compiler to incrementally recompile all tests executed by 'flutter test'. * Remove leftover commented code * Fix comment * Lints
1 parent e8d5667 commit d379762

File tree

4 files changed

+90
-26
lines changed

4 files changed

+90
-26
lines changed

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ osx_image: xcode9.2
66
env:
77
- SHARD=analyze
88
- SHARD=tests
9+
- SHARD=tests_dart2
910
- SHARD=docs
1011
- SHARD=build_and_deploy_gallery
1112
matrix:
@@ -14,6 +15,8 @@ matrix:
1415
env: SHARD=analyze
1516
- os: osx
1617
env: SHARD=docs
18+
allow_failures:
19+
- env: SHARD=tests_dart2
1720
sudo: false
1821
filter_secrets: false
1922

dev/bots/test.dart

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const Map<String, ShardRunner> _kShards = const <String, ShardRunner>{
2929
'docs': _generateDocs,
3030
'analyze': _analyzeRepo,
3131
'tests': _runTests,
32+
'tests_dart2': _runTestsDart2,
3233
'coverage': _runCoverage,
3334
};
3435

@@ -129,35 +130,50 @@ Future<Null> _analyzeRepo() async {
129130
print('${bold}DONE: Analysis successful.$reset');
130131
}
131132

132-
Future<Null> _runTests() async {
133+
Future<Null> _runTestsDart2() async {
134+
if (Platform.isWindows) {
135+
// AppVeyor platform is overloaded, won't be able to handle additional
136+
// load of dart2 testing.
137+
return;
138+
}
139+
_runTests(options: <String>['--preview-dart-2']);
140+
}
141+
142+
Future<Null> _runTests({List<String> options: const <String>[]}) async {
133143
// Verify that the tests actually return failure on failure and success on success.
134144
final String automatedTests = path.join(flutterRoot, 'dev', 'automated_tests');
135145
await _runFlutterTest(automatedTests,
136146
script: path.join('test_smoke_test', 'fail_test.dart'),
147+
options: options,
137148
expectFailure: true,
138149
printOutput: false,
139150
);
140151
await _runFlutterTest(automatedTests,
141152
script: path.join('test_smoke_test', 'pass_test.dart'),
153+
options: options,
142154
printOutput: false,
143155
);
144156
await _runFlutterTest(automatedTests,
145157
script: path.join('test_smoke_test', 'crash1_test.dart'),
158+
options: options,
146159
expectFailure: true,
147160
printOutput: false,
148161
);
149162
await _runFlutterTest(automatedTests,
150163
script: path.join('test_smoke_test', 'crash2_test.dart'),
164+
options: options,
151165
expectFailure: true,
152166
printOutput: false,
153167
);
154168
await _runFlutterTest(automatedTests,
155169
script: path.join('test_smoke_test', 'syntax_error_test.broken_dart'),
170+
options: options,
156171
expectFailure: true,
157172
printOutput: false,
158173
);
159174
await _runFlutterTest(automatedTests,
160175
script: path.join('test_smoke_test', 'missing_import_test.broken_dart'),
176+
options: options,
161177
expectFailure: true,
162178
printOutput: false,
163179
);
@@ -171,21 +187,21 @@ Future<Null> _runTests() async {
171187
await _verifyVersion(path.join(flutterRoot, 'version'));
172188

173189
// Run tests.
174-
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter'));
175-
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_localizations'));
176-
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_driver'));
177-
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_test'));
190+
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter'), options: options);
191+
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_localizations'), options: options);
192+
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_driver'), options: options);
193+
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_test'), options: options);
178194
await _pubRunTest(path.join(flutterRoot, 'packages', 'flutter_tools'));
179195
await _pubRunTest(path.join(flutterRoot, 'dev', 'bots'));
180196

181-
await _runAllDartTests(path.join(flutterRoot, 'dev', 'devicelab'));
182-
await _runFlutterTest(path.join(flutterRoot, 'dev', 'manual_tests'));
183-
await _runFlutterTest(path.join(flutterRoot, 'dev', 'tools', 'vitool'));
184-
await _runFlutterTest(path.join(flutterRoot, 'examples', 'hello_world'));
185-
await _runFlutterTest(path.join(flutterRoot, 'examples', 'layers'));
186-
await _runFlutterTest(path.join(flutterRoot, 'examples', 'stocks'));
187-
await _runFlutterTest(path.join(flutterRoot, 'examples', 'flutter_gallery'));
188-
await _runFlutterTest(path.join(flutterRoot, 'examples', 'catalog'));
197+
await _runAllDartTests(path.join(flutterRoot, 'dev', 'devicelab'), options: options);
198+
await _runFlutterTest(path.join(flutterRoot, 'dev', 'manual_tests'), options: options);
199+
await _runFlutterTest(path.join(flutterRoot, 'dev', 'tools', 'vitool'), options: options);
200+
await _runFlutterTest(path.join(flutterRoot, 'examples', 'hello_world'), options: options);
201+
await _runFlutterTest(path.join(flutterRoot, 'examples', 'layers'), options: options);
202+
await _runFlutterTest(path.join(flutterRoot, 'examples', 'stocks'), options: options);
203+
await _runFlutterTest(path.join(flutterRoot, 'examples', 'flutter_gallery'), options: options);
204+
await _runFlutterTest(path.join(flutterRoot, 'examples', 'catalog'), options: options);
189205

190206
print('${bold}DONE: All tests successful.$reset');
191207
}
@@ -356,8 +372,13 @@ Future<Null> _runFlutterTest(String workingDirectory, {
356372

357373
Future<Null> _runAllDartTests(String workingDirectory, {
358374
Map<String, String> environment,
375+
List<String> options,
359376
}) {
360-
final List<String> args = <String>['--checked', path.join('test', 'all.dart')];
377+
final List<String> args = <String>['--checked'];
378+
if (options != null) {
379+
args.addAll(options);
380+
}
381+
args.add(path.join('test', 'all.dart'));
361382
return _runCommand(dart, args,
362383
workingDirectory: workingDirectory,
363384
environment: environment,

packages/flutter_tools/lib/src/compile.dart

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,23 +125,27 @@ Future<String> compile(
125125
/// The wrapper is intended to stay resident in memory as user changes, reloads,
126126
/// restarts the Flutter app.
127127
class ResidentCompiler {
128-
ResidentCompiler(this._sdkRoot, {bool trackWidgetCreation: false})
128+
ResidentCompiler(this._sdkRoot, {bool trackWidgetCreation: false,
129+
String packagesPath})
129130
: assert(_sdkRoot != null),
130-
_trackWidgetCreation = trackWidgetCreation {
131+
_trackWidgetCreation = trackWidgetCreation,
132+
_packagesPath = packagesPath {
131133
// This is a URI, not a file path, so the forward slash is correct even on Windows.
132134
if (!_sdkRoot.endsWith('/'))
133135
_sdkRoot = '$_sdkRoot/';
134136
}
135137

136138
final bool _trackWidgetCreation;
139+
final String _packagesPath;
137140
String _sdkRoot;
138141
Process _server;
139142
final _StdoutHandler stdoutHandler = new _StdoutHandler();
140143

141144
/// If invoked for the first time, it compiles Dart script identified by
142145
/// [mainPath], [invalidatedFiles] list is ignored.
143-
/// Otherwise, [mainPath] is ignored, but [invalidatedFiles] is recompiled
144-
/// into new binary.
146+
/// On successive runs [invalidatedFiles] indicates which files need to be
147+
/// recompiled. If [mainPath] is [null], previously used [mainPath] entry
148+
/// point that is used for recompilation.
145149
/// Binary file name is returned if compilation was successful, otherwise
146150
/// null is returned.
147151
Future<String> recompile(String mainPath, List<String> invalidatedFiles,
@@ -154,7 +158,7 @@ class ResidentCompiler {
154158
return _compile(mainPath, outputPath);
155159

156160
final String inputKey = new Uuid().generateV4();
157-
_server.stdin.writeln('recompile $inputKey');
161+
_server.stdin.writeln('recompile ${mainPath != null ? mainPath + " ": ""}$inputKey');
158162
invalidatedFiles.forEach(_server.stdin.writeln);
159163
_server.stdin.writeln(inputKey);
160164

@@ -179,6 +183,9 @@ class ResidentCompiler {
179183
if (_trackWidgetCreation) {
180184
args.add('--track-widget-creation');
181185
}
186+
if (_packagesPath != null) {
187+
args.addAll(<String>['--packages', _packagesPath]);
188+
}
182189
_server = await processManager.start(args);
183190
_server.stdout
184191
.transform(UTF8.decoder)

packages/flutter_tools/lib/src/test/flutter_platform.dart

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@ enum _InitialResult { crashed, timedOut, connected }
8383
enum _TestResult { crashed, harnessBailed, testBailed }
8484
typedef Future<Null> _Finalizer();
8585

86+
class CompilationRequest {
87+
String path;
88+
Completer<String> result;
89+
90+
CompilationRequest(this.path, this.result);
91+
}
92+
8693
class _FlutterPlatform extends PlatformPlugin {
8794
_FlutterPlatform({
8895
@required this.shellPath,
@@ -93,7 +100,30 @@ class _FlutterPlatform extends PlatformPlugin {
93100
this.explicitObservatoryPort,
94101
this.host,
95102
this.previewDart2,
96-
}) : assert(shellPath != null);
103+
}) : assert(shellPath != null) {
104+
compilerController.stream.listen((CompilationRequest request) async {
105+
final bool isEmpty = compilationQueue.isEmpty;
106+
compilationQueue.add(request);
107+
// Only trigger processing if queue was empty - i.e. no other requests
108+
// are currently being processed. This effectively enforces "one
109+
// compilation request at a time".
110+
if (isEmpty) {
111+
while (compilationQueue.isNotEmpty) {
112+
final CompilationRequest request = compilationQueue.first;
113+
printTrace('Compiling ${request.path}');
114+
final String outputPath = await compiler.recompile(request.path,
115+
<String>[request.path]
116+
);
117+
print('Finished compilation of ${request.path} into $outputPath');
118+
compiler.accept();
119+
compiler.reset();
120+
request.result.complete(outputPath);
121+
// Only remove now when we finished processing the element
122+
compilationQueue.removeAt(0);
123+
}
124+
}
125+
});
126+
}
97127

98128
final String shellPath;
99129
final TestWatcher watcher;
@@ -103,6 +133,12 @@ class _FlutterPlatform extends PlatformPlugin {
103133
final int explicitObservatoryPort;
104134
final InternetAddress host;
105135
final bool previewDart2;
136+
final StreamController<CompilationRequest> compilerController =
137+
new StreamController<CompilationRequest>();
138+
ResidentCompiler compiler =
139+
new ResidentCompiler(artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
140+
packagesPath: PackageMap.globalPackagesPath);
141+
final List<CompilationRequest> compilationQueue = <CompilationRequest>[];
106142

107143
// Each time loadChannel() is called, we spin up a local WebSocket server,
108144
// then spin up the engine in a subprocess. We pass the engine a Dart file
@@ -203,12 +239,9 @@ class _FlutterPlatform extends PlatformPlugin {
203239
String bundlePath;
204240

205241
if (previewDart2) {
206-
mainDart = await compile(
207-
sdkRoot: artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
208-
mainPath: listenerFile.path,
209-
packagesPath: PackageMap.globalPackagesPath,
210-
linkPlatformKernelIn: true
211-
);
242+
final Completer<String> completer = new Completer<String>();
243+
compilerController.add(new CompilationRequest(listenerFile.path, completer));
244+
mainDart = await completer.future;
212245

213246
if (mainDart == null) {
214247
controller.sink.addError(_getErrorMessage('Compilation failed', testPath, shellPath));

0 commit comments

Comments
 (0)