Add test to frontend_server that mimics the flutter benchmarks
Change-Id: I1c968e5fb62fa42a38cf4e7d69683c6790385797
Reviewed-on: https://dart-review.googlesource.com/49902
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Aske Simon Christensen <askesc@google.com>
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 1ff41ca..0c49070 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -49,6 +49,7 @@
front_end/tool/incremental_perf_test: Slow, Pass
kernel/test/closures_test: Slow, Pass
kernel/testcases/*: Skip # These are not tests but input for tests.
+vm/test/frontend_server_test: Slow, Pass
vm/test/transformations/type_flow/transformer_test: Slow, Pass
vm/testcases/*: SkipByDesign # These are not tests but input for tests.
diff --git a/pkg/vm/test/frontend_server_test.dart b/pkg/vm/test/frontend_server_test.dart
index 997bdf9..7efa188 100644
--- a/pkg/vm/test/frontend_server_test.dart
+++ b/pkg/vm/test/frontend_server_test.dart
@@ -6,6 +6,8 @@
import 'package:args/src/arg_results.dart';
import 'package:kernel/binary/ast_to_binary.dart';
import 'package:kernel/ast.dart' show Component;
+import 'package:kernel/kernel.dart' show loadComponentFromBinary;
+import 'package:kernel/verifier.dart' show verifyComponent;
import 'package:mockito/mockito.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
@@ -786,6 +788,168 @@
expect(path.basename(depContentsParsed[0]), path.basename(dillFile.path));
expect(depContentsParsed[1], isNotEmpty);
});
+
+ test('mimic flutter benchmark', () async {
+ // This is based on what flutters "hot_mode_dev_cycle__benchmark" does.
+ var dillFile = new File('${tempDir.path}/full.dill');
+ var incrementalDillFile = new File('${tempDir.path}/incremental.dill');
+ expect(dillFile.existsSync(), equals(false));
+ final List<String> args = <String>[
+ '--sdk-root=${sdkRoot.toFilePath()}',
+ '--strong',
+ '--incremental',
+ '--platform=${platformKernel.path}',
+ '--output-dill=${dillFile.path}',
+ '--output-incremental-dill=${incrementalDillFile.path}'
+ ];
+ File dart2js = new File.fromUri(
+ Platform.script.resolve("../../../pkg/compiler/bin/dart2js.dart"));
+ expect(dart2js.existsSync(), equals(true));
+ File dart2jsOtherFile = new File.fromUri(Platform.script
+ .resolve("../../../pkg/compiler/lib/src/compiler.dart"));
+ expect(dart2jsOtherFile.existsSync(), equals(true));
+
+ int libraryCount = -1;
+ int sourceCount = -1;
+
+ for (int serverCloses = 0; serverCloses < 2; ++serverCloses) {
+ print("Restart #$serverCloses");
+ final StreamController<List<int>> streamController =
+ new StreamController<List<int>>();
+ final StreamController<List<int>> stdoutStreamController =
+ new StreamController<List<int>>();
+ final IOSink ioSink = new IOSink(stdoutStreamController.sink);
+ StreamController<String> receivedResults =
+ new StreamController<String>();
+
+ String boundaryKey;
+ stdoutStreamController.stream
+ .transform(utf8.decoder)
+ .transform(const LineSplitter())
+ .listen((String s) {
+ const String RESULT_OUTPUT_SPACE = 'result ';
+ if (boundaryKey == null) {
+ if (s.startsWith(RESULT_OUTPUT_SPACE)) {
+ boundaryKey = s.substring(RESULT_OUTPUT_SPACE.length);
+ }
+ } else {
+ if (s.startsWith(boundaryKey)) {
+ receivedResults.add(s.substring(boundaryKey.length + 1));
+ boundaryKey = null;
+ }
+ }
+ });
+
+ int exitcode =
+ await starter(args, input: streamController.stream, output: ioSink);
+ expect(exitcode, equals(0));
+ streamController.add('compile ${dart2js.path}\n'.codeUnits);
+ int count = 0;
+ Completer<bool> allDone = new Completer<bool>();
+ receivedResults.stream.listen((String outputFilenameAndErrorCount) {
+ int delim = outputFilenameAndErrorCount.lastIndexOf(' ');
+ expect(delim > 0, equals(true));
+ String outputFilename =
+ outputFilenameAndErrorCount.substring(0, delim);
+ print("$outputFilename -- count $count");
+ if (count == 0) {
+ // First request is to 'compile', which results in full kernel file.
+ expect(dillFile.existsSync(), equals(true));
+ expect(outputFilename, dillFile.path);
+
+ // Dill file can be loaded and includes data.
+ Component component = loadComponentFromBinary(dillFile.path);
+ if (serverCloses == 0) {
+ libraryCount = component.libraries.length;
+ sourceCount = component.uriToSource.length;
+ expect(libraryCount > 100, equals(true));
+ expect(sourceCount >= libraryCount, equals(true),
+ reason: "Expects >= source entries than libraries.");
+ } else {
+ expect(component.libraries.length, equals(libraryCount),
+ reason: "Expects the same number of libraries "
+ "when compiling after a restart");
+ expect(component.uriToSource.length, equals(sourceCount),
+ reason: "Expects the same number of sources "
+ "when compiling after a restart");
+ }
+
+ // Include platform and verify.
+ component = loadComponentFromBinary(platformKernel.path, component);
+ expect(component.mainMethod, isNotNull);
+ verifyComponent(component);
+
+ count += 1;
+
+ // Restart with no changes
+ streamController.add('accept\n'.codeUnits);
+ streamController.add('reset\n'.codeUnits);
+ streamController.add('recompile ${dart2js.path} x$count\n'
+ 'x$count\n'
+ .codeUnits);
+ } else if (count == 1) {
+ // Restart. Expect full kernel file.
+ expect(dillFile.existsSync(), equals(true));
+ expect(outputFilename, dillFile.path);
+
+ // Dill file can be loaded and includes data.
+ Component component = loadComponentFromBinary(dillFile.path);
+ expect(component.libraries.length, equals(libraryCount),
+ reason: "Expect the same number of libraries after a reset.");
+ expect(component.uriToSource.length, equals(sourceCount),
+ reason: "Expect the same number of sources after a reset.");
+
+ // Include platform and verify.
+ component = loadComponentFromBinary(platformKernel.path, component);
+ expect(component.mainMethod, isNotNull);
+ verifyComponent(component);
+
+ count += 1;
+
+ // Reload with no changes
+ streamController.add('accept\n'.codeUnits);
+ streamController.add('recompile ${dart2js.path} x$count\n'
+ 'x$count\n'
+ .codeUnits);
+ } else if (count == 2) {
+ // Partial file. Expect to be empty.
+ expect(incrementalDillFile.existsSync(), equals(true));
+ expect(outputFilename, incrementalDillFile.path);
+
+ // Dill file can be loaded and includes no data.
+ Component component =
+ loadComponentFromBinary(incrementalDillFile.path);
+ expect(component.libraries.length, equals(0));
+
+ count += 1;
+
+ // Reload with 1 change
+ streamController.add('accept\n'.codeUnits);
+ streamController.add('recompile ${dart2js.path} x$count\n'
+ '${dart2jsOtherFile.path}\n'
+ 'x$count\n'
+ .codeUnits);
+ } else if (count == 3) {
+ // Partial file. Expect to not be empty.
+ expect(incrementalDillFile.existsSync(), equals(true));
+ expect(outputFilename, incrementalDillFile.path);
+
+ // Dill file can be loaded and includes some data.
+ Component component =
+ loadComponentFromBinary(incrementalDillFile.path);
+ expect(component.libraries, isNotEmpty);
+ expect(component.uriToSource.length >= component.libraries.length,
+ equals(true),
+ reason: "Expects >= source entries than libraries.");
+
+ count += 1;
+
+ allDone.complete(true);
+ }
+ });
+ expect(await allDone.future, true);
+ }
+ }, timeout: new Timeout.factor(8));
});
return 0;
}