mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Rollback patch that broke microbenchmarks (#11616)
* Revert "Extract snapshotting logic to Snapshotter class (#11591)" This reverts commit 309a2d78fbcd735b7594e3f65df809f52d46b23e. * Revert "Minor whitespace formatting fix (#11590)" This reverts commit bf69c3c69bde95779252e0deb3e288c8120aa1ec. * Revert "Avoid rebuilding snapshots if no change to source (#11551)" This reverts commit 74835db563b7c31b4c883eeea15e689a1bdbd303.
This commit is contained in:
parent
946a28580c
commit
70fe6f4c23
@ -2,48 +2,11 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert' show JSON;
|
||||
|
||||
import 'package:crypto/crypto.dart' show md5;
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import '../artifacts.dart';
|
||||
import '../build_info.dart';
|
||||
import '../globals.dart';
|
||||
import 'context.dart';
|
||||
import 'file_system.dart';
|
||||
import 'process.dart';
|
||||
|
||||
GenSnapshot get genSnapshot => context.putIfAbsent(GenSnapshot, () => const GenSnapshot());
|
||||
|
||||
class GenSnapshot {
|
||||
const GenSnapshot();
|
||||
|
||||
Future<int> run({
|
||||
@required TargetPlatform targetPlatform,
|
||||
@required BuildMode buildMode,
|
||||
@required String packagesPath,
|
||||
@required String depfilePath,
|
||||
Iterable<String> additionalArgs: const <String>[],
|
||||
}) {
|
||||
final String vmSnapshotData = artifacts.getArtifactPath(Artifact.vmSnapshotData);
|
||||
final String isolateSnapshotData = artifacts.getArtifactPath(Artifact.isolateSnapshotData);
|
||||
final List<String> args = <String>[
|
||||
'--assert_initializer',
|
||||
'--await_is_keyword',
|
||||
'--causal_async_stacks',
|
||||
'--vm_snapshot_data=$vmSnapshotData',
|
||||
'--isolate_snapshot_data=$isolateSnapshotData',
|
||||
'--packages=$packagesPath',
|
||||
'--dependencies=$depfilePath',
|
||||
'--print_snapshot_sizes',
|
||||
]..addAll(additionalArgs);
|
||||
|
||||
final String snapshotterPath = artifacts.getArtifactPath(Artifact.genSnapshot, targetPlatform, buildMode);
|
||||
return runCommandAndStreamOutput(<String>[snapshotterPath]..addAll(args));
|
||||
}
|
||||
}
|
||||
|
||||
/// A collection of checksums for a set of input files.
|
||||
///
|
||||
@ -79,134 +42,3 @@ class Checksum {
|
||||
@override
|
||||
int get hashCode => _checksums.hashCode;
|
||||
}
|
||||
|
||||
final RegExp _separatorExpr = new RegExp(r'([^\\]) ');
|
||||
final RegExp _escapeExpr = new RegExp(r'\\(.)');
|
||||
|
||||
/// Parses a VM snapshot dependency file.
|
||||
///
|
||||
/// Snapshot dependency files are a single line mapping the output snapshot to a
|
||||
/// space-separated list of input files used to generate that output. Spaces and
|
||||
/// backslashes are escaped with a backslash. e.g,
|
||||
///
|
||||
/// outfile : file1.dart fil\\e2.dart fil\ e3.dart
|
||||
///
|
||||
/// will return a set containing: 'file1.dart', 'fil\e2.dart', 'fil e3.dart'.
|
||||
Future<Set<String>> readDepfile(String depfilePath) async {
|
||||
// Depfile format:
|
||||
// outfile1 outfile2 : file1.dart file2.dart file3.dart
|
||||
final String contents = await fs.file(depfilePath).readAsString();
|
||||
final String dependencies = contents.split(': ')[1];
|
||||
return dependencies
|
||||
.replaceAllMapped(_separatorExpr, (Match match) => '${match.group(1)}\n')
|
||||
.split('\n')
|
||||
.map((String path) => path.replaceAllMapped(_escapeExpr, (Match match) => match.group(1)).trim())
|
||||
.where((String path) => path.isNotEmpty)
|
||||
.toSet();
|
||||
}
|
||||
|
||||
/// Dart snapshot builder.
|
||||
///
|
||||
/// Builds Dart snapshots in one of three modes:
|
||||
/// * Script snapshot: architecture-independent snapshot of a Dart script core
|
||||
/// libraries.
|
||||
/// * AOT snapshot: architecture-specific ahead-of-time compiled snapshot
|
||||
/// suitable for loading with `mmap`.
|
||||
/// * Assembly AOT snapshot: architecture-specific ahead-of-time compile to
|
||||
/// assembly suitable for compilation as a static or dynamic library.
|
||||
class Snapshotter {
|
||||
/// Builds an architecture-independent snapshot of the specified script.
|
||||
Future<int> buildScriptSnapshot({
|
||||
@required String mainPath,
|
||||
@required String snapshotPath,
|
||||
@required String depfilePath,
|
||||
@required String packagesPath
|
||||
}) async {
|
||||
final List<String> args = <String>[
|
||||
'--snapshot_kind=script',
|
||||
'--script_snapshot=$snapshotPath',
|
||||
mainPath,
|
||||
];
|
||||
|
||||
final String checksumsPath = '$depfilePath.checksums';
|
||||
final int exitCode = await _build(
|
||||
outputSnapshotPath: snapshotPath,
|
||||
packagesPath: packagesPath,
|
||||
snapshotArgs: args,
|
||||
depfilePath: depfilePath,
|
||||
mainPath: mainPath,
|
||||
checksumsPath: checksumsPath,
|
||||
);
|
||||
if (exitCode != 0)
|
||||
return exitCode;
|
||||
await _writeChecksum(snapshotPath, depfilePath, mainPath, checksumsPath);
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/// Builds an architecture-specific ahead-of-time compiled snapshot of the specified script.
|
||||
Future<Null> buildAotSnapshot() async {
|
||||
throw new UnimplementedError('AOT snapshotting not yet implemented');
|
||||
}
|
||||
|
||||
Future<int> _build({
|
||||
@required List<String> snapshotArgs,
|
||||
@required String outputSnapshotPath,
|
||||
@required String packagesPath,
|
||||
@required String depfilePath,
|
||||
@required String mainPath,
|
||||
@required String checksumsPath,
|
||||
}) async {
|
||||
if (!await _isBuildRequired(outputSnapshotPath, depfilePath, mainPath, checksumsPath)) {
|
||||
printTrace('Skipping snapshot build. Checksums match.');
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Build the snapshot.
|
||||
final int exitCode = await genSnapshot.run(
|
||||
targetPlatform: null,
|
||||
buildMode: BuildMode.debug,
|
||||
packagesPath: packagesPath,
|
||||
depfilePath: depfilePath,
|
||||
additionalArgs: snapshotArgs,
|
||||
);
|
||||
if (exitCode != 0)
|
||||
return exitCode;
|
||||
|
||||
_writeChecksum(outputSnapshotPath, depfilePath, mainPath, checksumsPath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Future<bool> _isBuildRequired(String outputSnapshotPath, String depfilePath, String mainPath, String checksumsPath) async {
|
||||
final File checksumFile = fs.file(checksumsPath);
|
||||
final File outputSnapshotFile = fs.file(outputSnapshotPath);
|
||||
final File depfile = fs.file(depfilePath);
|
||||
if (!outputSnapshotFile.existsSync() || !depfile.existsSync() || !checksumFile.existsSync())
|
||||
return true;
|
||||
|
||||
try {
|
||||
if (checksumFile.existsSync()) {
|
||||
final Checksum oldChecksum = new Checksum.fromJson(await checksumFile.readAsString());
|
||||
final Set<String> checksumPaths = await readDepfile(depfilePath)
|
||||
..addAll(<String>[outputSnapshotPath, mainPath]);
|
||||
final Checksum newChecksum = new Checksum.fromFiles(checksumPaths);
|
||||
return oldChecksum != newChecksum;
|
||||
}
|
||||
} catch (e, s) {
|
||||
// Log exception and continue, this step is a performance improvement only.
|
||||
printTrace('Error during snapshot checksum output: $e\n$s');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<Null> _writeChecksum(String outputSnapshotPath, String depfilePath, String mainPath, String checksumsPath) async {
|
||||
try {
|
||||
final Set<String> checksumPaths = await readDepfile(depfilePath)
|
||||
..addAll(<String>[outputSnapshotPath, mainPath]);
|
||||
final Checksum checksum = new Checksum.fromFiles(checksumPaths);
|
||||
await fs.file(checksumsPath).writeAsString(checksum.toJson());
|
||||
} catch (e, s) {
|
||||
// Log exception and continue, this step is a performance improvement only.
|
||||
print('Error during snapshot checksum output: $e\n$s');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
import 'dart:async';
|
||||
|
||||
import '../artifacts.dart';
|
||||
import '../base/build.dart';
|
||||
import '../base/common.dart';
|
||||
import '../base/file_system.dart';
|
||||
import '../base/logger.dart';
|
||||
@ -150,16 +149,13 @@ Future<String> _buildAotSnapshot(
|
||||
final String uiPath = fs.path.join(skyEnginePkg, 'lib', 'ui', 'ui.dart');
|
||||
final String vmServicePath = fs.path.join(skyEnginePkg, 'sdk_ext', 'vmservice_io.dart');
|
||||
|
||||
final List<String> inputPaths = <String>[
|
||||
final List<String> filePaths = <String>[
|
||||
vmEntryPoints,
|
||||
ioEntryPoints,
|
||||
uiPath,
|
||||
vmServicePath,
|
||||
mainPath,
|
||||
];
|
||||
|
||||
final Set<String> outputPaths = new Set<String>();
|
||||
|
||||
// These paths are used only on iOS.
|
||||
String snapshotDartIOS;
|
||||
String assembly;
|
||||
@ -168,15 +164,13 @@ Future<String> _buildAotSnapshot(
|
||||
case TargetPlatform.android_arm:
|
||||
case TargetPlatform.android_x64:
|
||||
case TargetPlatform.android_x86:
|
||||
outputPaths.addAll(<String>[
|
||||
vmSnapshotData,
|
||||
isolateSnapshotData,
|
||||
]);
|
||||
break;
|
||||
case TargetPlatform.ios:
|
||||
snapshotDartIOS = artifacts.getArtifactPath(Artifact.snapshotDart, platform, buildMode);
|
||||
assembly = fs.path.join(outputDir.path, 'snapshot_assembly.S');
|
||||
inputPaths.add(snapshotDartIOS);
|
||||
filePaths.addAll(<String>[
|
||||
snapshotDartIOS,
|
||||
]);
|
||||
break;
|
||||
case TargetPlatform.darwin_x64:
|
||||
case TargetPlatform.linux_x64:
|
||||
@ -185,9 +179,9 @@ Future<String> _buildAotSnapshot(
|
||||
assert(false);
|
||||
}
|
||||
|
||||
final Iterable<String> missingInputs = inputPaths.where((String p) => !fs.isFileSync(p));
|
||||
if (missingInputs.isNotEmpty) {
|
||||
printError('Missing input files: $missingInputs');
|
||||
final List<String> missingFiles = filePaths.where((String p) => !fs.isFileSync(p)).toList();
|
||||
if (missingFiles.isNotEmpty) {
|
||||
printError('Missing files: $missingFiles');
|
||||
return null;
|
||||
}
|
||||
if (!processManager.canRun(genSnapshot)) {
|
||||
@ -214,17 +208,6 @@ Future<String> _buildAotSnapshot(
|
||||
genSnapshotCmd.add('--embedder_entry_points_manifest=$ioEntryPoints');
|
||||
}
|
||||
|
||||
// iOS symbols used to load snapshot data in the engine.
|
||||
const String kVmSnapshotData = 'kDartVmSnapshotData';
|
||||
const String kIsolateSnapshotData = 'kDartIsolateSnapshotData';
|
||||
|
||||
// iOS snapshot generated files, compiled object files.
|
||||
final String kVmSnapshotDataC = fs.path.join(outputDir.path, '$kVmSnapshotData.c');
|
||||
final String kIsolateSnapshotDataC = fs.path.join(outputDir.path, '$kIsolateSnapshotData.c');
|
||||
final String kVmSnapshotDataO = fs.path.join(outputDir.path, '$kVmSnapshotData.o');
|
||||
final String kIsolateSnapshotDataO = fs.path.join(outputDir.path, '$kIsolateSnapshotData.o');
|
||||
final String assemblyO = fs.path.join(outputDir.path, 'snapshot_assembly.o');
|
||||
|
||||
switch (platform) {
|
||||
case TargetPlatform.android_arm:
|
||||
case TargetPlatform.android_x64:
|
||||
@ -241,14 +224,9 @@ Future<String> _buildAotSnapshot(
|
||||
if (interpreter) {
|
||||
genSnapshotCmd.add('--snapshot_kind=core');
|
||||
genSnapshotCmd.add(snapshotDartIOS);
|
||||
outputPaths.addAll(<String>[
|
||||
kVmSnapshotDataO,
|
||||
kIsolateSnapshotDataO,
|
||||
]);
|
||||
} else {
|
||||
genSnapshotCmd.add('--snapshot_kind=app-aot-assembly');
|
||||
genSnapshotCmd.add('--assembly=$assembly');
|
||||
outputPaths.add(assemblyO);
|
||||
}
|
||||
break;
|
||||
case TargetPlatform.darwin_x64:
|
||||
@ -267,27 +245,6 @@ Future<String> _buildAotSnapshot(
|
||||
|
||||
genSnapshotCmd.add(mainPath);
|
||||
|
||||
final File checksumFile = fs.file('$dependencies.checksum');
|
||||
final List<File> checksumFiles = <File>[checksumFile, fs.file(dependencies)]
|
||||
..addAll(inputPaths.map(fs.file))
|
||||
..addAll(outputPaths.map(fs.file));
|
||||
if (checksumFiles.every((File file) => file.existsSync())) {
|
||||
try {
|
||||
final String json = await checksumFile.readAsString();
|
||||
final Checksum oldChecksum = new Checksum.fromJson(json);
|
||||
final Set<String> snapshotInputPaths = await readDepfile(dependencies);
|
||||
snapshotInputPaths.addAll(outputPaths);
|
||||
final Checksum newChecksum = new Checksum.fromFiles(snapshotInputPaths);
|
||||
if (oldChecksum == newChecksum) {
|
||||
printTrace('Skipping AOT snapshot build. Checksums match.');
|
||||
return outputPath;
|
||||
}
|
||||
} catch (e, s) {
|
||||
// Log exception and continue, this step is a performance improvement only.
|
||||
printTrace('Error during AOT snapshot checksum check: $e\n$s');
|
||||
}
|
||||
}
|
||||
|
||||
final RunResult results = await runAsync(genSnapshotCmd);
|
||||
if (results.exitCode != 0) {
|
||||
printError('Dart snapshot generator failed with exit code ${results.exitCode}');
|
||||
@ -304,6 +261,16 @@ Future<String> _buildAotSnapshot(
|
||||
if (platform == TargetPlatform.ios) {
|
||||
printStatus('Building App.framework...');
|
||||
|
||||
// These names are known to from the engine.
|
||||
const String kVmSnapshotData = 'kDartVmSnapshotData';
|
||||
const String kIsolateSnapshotData = 'kDartIsolateSnapshotData';
|
||||
|
||||
final String kVmSnapshotDataC = fs.path.join(outputDir.path, '$kVmSnapshotData.c');
|
||||
final String kIsolateSnapshotDataC = fs.path.join(outputDir.path, '$kIsolateSnapshotData.c');
|
||||
final String kVmSnapshotDataO = fs.path.join(outputDir.path, '$kVmSnapshotData.o');
|
||||
final String kIsolateSnapshotDataO = fs.path.join(outputDir.path, '$kIsolateSnapshotData.o');
|
||||
final String assemblyO = fs.path.join(outputDir.path, 'snapshot_assembly.o');
|
||||
|
||||
final List<String> commonBuildOptions = <String>['-arch', 'arm64', '-miphoneos-version-min=8.0'];
|
||||
|
||||
if (interpreter) {
|
||||
@ -350,16 +317,5 @@ Future<String> _buildAotSnapshot(
|
||||
await runCheckedAsync(linkCommand);
|
||||
}
|
||||
|
||||
// Compute and record checksums.
|
||||
try {
|
||||
final Set<String> snapshotInputPaths = await readDepfile(dependencies);
|
||||
snapshotInputPaths..addAll(outputPaths);
|
||||
final Checksum checksum = new Checksum.fromFiles(snapshotInputPaths);
|
||||
await checksumFile.writeAsString(checksum.toJson());
|
||||
} catch (e, s) {
|
||||
// Log exception and continue, this step is a performance improvement only.
|
||||
printTrace('Error during AOT snapshot checksum output: $e\n$s');
|
||||
}
|
||||
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
@ -4,10 +4,14 @@
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:meta/meta.dart' show required;
|
||||
|
||||
import 'artifacts.dart';
|
||||
import 'asset.dart';
|
||||
import 'base/build.dart';
|
||||
import 'base/common.dart';
|
||||
import 'base/file_system.dart';
|
||||
import 'base/process.dart';
|
||||
import 'build_info.dart';
|
||||
import 'dart/package_map.dart';
|
||||
import 'devfs.dart';
|
||||
@ -26,6 +30,90 @@ const String _kKernelKey = 'kernel_blob.bin';
|
||||
const String _kSnapshotKey = 'snapshot_blob.bin';
|
||||
const String _kDylibKey = 'libapp.so';
|
||||
|
||||
Future<int> _createSnapshot({
|
||||
@required String mainPath,
|
||||
@required String snapshotPath,
|
||||
@required String depfilePath,
|
||||
@required String packages
|
||||
}) async {
|
||||
assert(mainPath != null);
|
||||
assert(snapshotPath != null);
|
||||
assert(depfilePath != null);
|
||||
assert(packages != null);
|
||||
final String snapshotterPath = artifacts.getArtifactPath(Artifact.genSnapshot, null, BuildMode.debug);
|
||||
final String vmSnapshotData = artifacts.getArtifactPath(Artifact.vmSnapshotData);
|
||||
final String isolateSnapshotData = artifacts.getArtifactPath(Artifact.isolateSnapshotData);
|
||||
|
||||
final List<String> args = <String>[
|
||||
snapshotterPath,
|
||||
'--snapshot_kind=script',
|
||||
'--vm_snapshot_data=$vmSnapshotData',
|
||||
'--isolate_snapshot_data=$isolateSnapshotData',
|
||||
'--packages=$packages',
|
||||
'--script_snapshot=$snapshotPath',
|
||||
'--dependencies=$depfilePath',
|
||||
mainPath,
|
||||
];
|
||||
|
||||
// Write the depfile path to disk.
|
||||
fs.file(depfilePath).parent.childFile('gen_snapshot.d').writeAsString('$depfilePath: $snapshotterPath\n');
|
||||
|
||||
final File checksumFile = fs.file('$depfilePath.checksums');
|
||||
final File snapshotFile = fs.file(snapshotPath);
|
||||
final File depfile = fs.file(depfilePath);
|
||||
if (snapshotFile.existsSync() && depfile.existsSync() && checksumFile.existsSync()) {
|
||||
try {
|
||||
final String json = await checksumFile.readAsString();
|
||||
final Checksum oldChecksum = new Checksum.fromJson(json);
|
||||
final Set<String> inputPaths = await _readDepfile(depfilePath);
|
||||
inputPaths.add(snapshotPath);
|
||||
final Checksum newChecksum = new Checksum.fromFiles(inputPaths);
|
||||
if (oldChecksum == newChecksum) {
|
||||
printTrace('Skipping snapshot build. Checksums match.');
|
||||
return 0;
|
||||
}
|
||||
} catch (e, s) {
|
||||
// Log exception and continue, this step is a performance improvement only.
|
||||
printTrace('Error during snapshot checksum check: $e\n$s');
|
||||
}
|
||||
}
|
||||
|
||||
// Build the snapshot.
|
||||
final int exitCode = await runCommandAndStreamOutput(args);
|
||||
if (exitCode != 0)
|
||||
return exitCode;
|
||||
|
||||
// Compute and record input file checksums.
|
||||
try {
|
||||
final Set<String> inputPaths = await _readDepfile(depfilePath);
|
||||
inputPaths.add(snapshotPath);
|
||||
final Checksum checksum = new Checksum.fromFiles(inputPaths);
|
||||
await checksumFile.writeAsString(checksum.toJson());
|
||||
} catch (e, s) {
|
||||
// Log exception and continue, this step is a performance improvement only.
|
||||
printTrace('Error during snapshot checksum output: $e\n$s');
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Parses a VM snapshot dependency file.
|
||||
///
|
||||
/// Snapshot dependency files are a single line mapping the output snapshot to a
|
||||
/// space-separated list of input files used to generate that output. e.g,
|
||||
///
|
||||
/// outfile : file1.dart file2.dart file3.dart
|
||||
Future<Set<String>> _readDepfile(String depfilePath) async {
|
||||
// Depfile format:
|
||||
// outfile : file1.dart file2.dart file3.dart
|
||||
final String contents = await fs.file(depfilePath).readAsString();
|
||||
final String dependencies = contents.split(': ')[1];
|
||||
return dependencies
|
||||
.split(' ')
|
||||
.map((String path) => path.trim())
|
||||
.where((String path) => path.isNotEmpty)
|
||||
.toSet();
|
||||
}
|
||||
|
||||
Future<Null> build({
|
||||
String mainPath: defaultMainPath,
|
||||
String manifestPath: defaultManifestPath,
|
||||
@ -51,12 +139,11 @@ Future<Null> build({
|
||||
|
||||
// In a precompiled snapshot, the instruction buffer contains script
|
||||
// content equivalents
|
||||
final Snapshotter snapshotter = new Snapshotter();
|
||||
final int result = await snapshotter.buildScriptSnapshot(
|
||||
final int result = await _createSnapshot(
|
||||
mainPath: mainPath,
|
||||
snapshotPath: snapshotPath,
|
||||
depfilePath: depfilePath,
|
||||
packagesPath: packagesPath,
|
||||
packages: packagesPath
|
||||
);
|
||||
if (result != 0)
|
||||
throwToolExit('Failed to run the Flutter compiler. Exit code: $result', exitCode: result);
|
||||
|
||||
@ -2,54 +2,13 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert' show JSON;
|
||||
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/base/build.dart';
|
||||
import 'package:flutter_tools/src/base/context.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../src/context.dart';
|
||||
|
||||
class _FakeGenSnapshot implements GenSnapshot {
|
||||
_FakeGenSnapshot({
|
||||
this.succeed: true,
|
||||
this.snapshotPath: 'output.snapshot',
|
||||
this.snapshotContent: '',
|
||||
this.depfilePath: 'output.snapshot.d',
|
||||
this.depfileContent: 'output.snapshot.d : main.dart',
|
||||
});
|
||||
|
||||
final bool succeed;
|
||||
final String snapshotPath;
|
||||
final String snapshotContent;
|
||||
final String depfilePath;
|
||||
final String depfileContent;
|
||||
int _callCount = 0;
|
||||
|
||||
int get callCount => _callCount;
|
||||
|
||||
@override
|
||||
Future<int> run({
|
||||
TargetPlatform targetPlatform,
|
||||
BuildMode buildMode,
|
||||
String packagesPath,
|
||||
String depfilePath,
|
||||
Iterable<String> additionalArgs,
|
||||
}) async {
|
||||
_callCount += 1;
|
||||
|
||||
if (!succeed)
|
||||
return 1;
|
||||
await fs.file(snapshotPath).writeAsString(snapshotContent);
|
||||
await fs.file(depfilePath).writeAsString(depfileContent);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
group('Checksum', () {
|
||||
group('fromFiles', () {
|
||||
@ -105,185 +64,4 @@ void main() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
group('readDepfile', () {
|
||||
MemoryFileSystem fs;
|
||||
|
||||
setUp(() {
|
||||
fs = new MemoryFileSystem();
|
||||
});
|
||||
|
||||
testUsingContext('returns one file if only one is listed', () async {
|
||||
await fs.file('a.d').writeAsString('snapshot.d: /foo/a.dart');
|
||||
expect(await readDepfile('a.d'), unorderedEquals(<String>['/foo/a.dart']));
|
||||
}, overrides: <Type, Generator>{ FileSystem: () => fs });
|
||||
|
||||
testUsingContext('returns multiple files', () async {
|
||||
await fs.file('a.d').writeAsString('snapshot.d: /foo/a.dart /foo/b.dart');
|
||||
expect(await readDepfile('a.d'), unorderedEquals(<String>[
|
||||
'/foo/a.dart',
|
||||
'/foo/b.dart',
|
||||
]));
|
||||
}, overrides: <Type, Generator>{ FileSystem: () => fs});
|
||||
|
||||
testUsingContext('trims extra spaces between files', () async {
|
||||
await fs.file('a.d').writeAsString('snapshot.d: /foo/a.dart /foo/b.dart /foo/c.dart');
|
||||
expect(await readDepfile('a.d'), unorderedEquals(<String>[
|
||||
'/foo/a.dart',
|
||||
'/foo/b.dart',
|
||||
'/foo/c.dart',
|
||||
]));
|
||||
}, overrides: <Type, Generator>{ FileSystem: () => fs });
|
||||
|
||||
testUsingContext('returns files with spaces and backslashes', () async {
|
||||
await fs.file('a.d').writeAsString(r'snapshot.d: /foo/a\ a.dart /foo/b\\b.dart /foo/c\\ c.dart');
|
||||
expect(await readDepfile('a.d'), unorderedEquals(<String>[
|
||||
r'/foo/a a.dart',
|
||||
r'/foo/b\b.dart',
|
||||
r'/foo/c\ c.dart',
|
||||
]));
|
||||
}, overrides: <Type, Generator>{ FileSystem: () => fs });
|
||||
});
|
||||
|
||||
group('Snapshotter', () {
|
||||
_FakeGenSnapshot genSnapshot;
|
||||
MemoryFileSystem fs;
|
||||
Snapshotter snapshotter;
|
||||
|
||||
setUp(() {
|
||||
fs = new MemoryFileSystem();
|
||||
genSnapshot = new _FakeGenSnapshot();
|
||||
snapshotter = new Snapshotter();
|
||||
});
|
||||
|
||||
testUsingContext('builds snapshot and checksums when no checksums are present', () async {
|
||||
await fs.file('main.dart').writeAsString('void main() {}');
|
||||
await fs.file('output.snapshot').create();
|
||||
await fs.file('output.snapshot.d').writeAsString('snapshot : main.dart');
|
||||
await snapshotter.buildScriptSnapshot(
|
||||
mainPath: 'main.dart',
|
||||
snapshotPath: 'output.snapshot',
|
||||
depfilePath: 'output.snapshot.d',
|
||||
packagesPath: '.packages',
|
||||
);
|
||||
|
||||
expect(genSnapshot.callCount, 1);
|
||||
|
||||
final Map<String, dynamic> json = JSON.decode(await fs.file('output.snapshot.d.checksums').readAsString());
|
||||
expect(json, hasLength(2));
|
||||
expect(json['main.dart'], '27f5ebf0f8c559b2af9419d190299a5e');
|
||||
expect(json['output.snapshot'], 'd41d8cd98f00b204e9800998ecf8427e');
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
GenSnapshot: () => genSnapshot,
|
||||
});
|
||||
|
||||
testUsingContext('builds snapshot and checksums when checksums differ', () async {
|
||||
await fs.file('main.dart').writeAsString('void main() {}');
|
||||
await fs.file('output.snapshot').create();
|
||||
await fs.file('output.snapshot.d').writeAsString('output.snapshot : main.dart');
|
||||
await fs.file('output.snapshot.d.checksums').writeAsString(JSON.encode(<String, dynamic>{
|
||||
'main.dart': '27f5ebf0f8c559b2af9419d190299a5e',
|
||||
'output.snapshot': 'deadbeef01234567890abcdef0123456',
|
||||
}));
|
||||
await snapshotter.buildScriptSnapshot(
|
||||
mainPath: 'main.dart',
|
||||
snapshotPath: 'output.snapshot',
|
||||
depfilePath: 'output.snapshot.d',
|
||||
packagesPath: '.packages',
|
||||
);
|
||||
|
||||
expect(genSnapshot.callCount, 1);
|
||||
|
||||
final Map<String, dynamic> json = JSON.decode(await fs.file('output.snapshot.d.checksums').readAsString());
|
||||
expect(json, hasLength(2));
|
||||
expect(json['main.dart'], '27f5ebf0f8c559b2af9419d190299a5e');
|
||||
expect(json['output.snapshot'], 'd41d8cd98f00b204e9800998ecf8427e');
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
GenSnapshot: () => genSnapshot,
|
||||
});
|
||||
|
||||
testUsingContext('builds snapshot and checksums when checksums match but previous snapshot not present', () async {
|
||||
await fs.file('main.dart').writeAsString('void main() {}');
|
||||
await fs.file('output.snapshot.d').writeAsString('output.snapshot : main.dart');
|
||||
await fs.file('output.snapshot.d.checksums').writeAsString(JSON.encode(<String, dynamic>{
|
||||
'main.dart': '27f5ebf0f8c559b2af9419d190299a5e',
|
||||
'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e',
|
||||
}));
|
||||
await snapshotter.buildScriptSnapshot(
|
||||
mainPath: 'main.dart',
|
||||
snapshotPath: 'output.snapshot',
|
||||
depfilePath: 'output.snapshot.d',
|
||||
packagesPath: '.packages',
|
||||
);
|
||||
|
||||
expect(genSnapshot.callCount, 1);
|
||||
|
||||
final Map<String, dynamic> json = JSON.decode(await fs.file('output.snapshot.d.checksums').readAsString());
|
||||
expect(json, hasLength(2));
|
||||
expect(json['main.dart'], '27f5ebf0f8c559b2af9419d190299a5e');
|
||||
expect(json['output.snapshot'], 'd41d8cd98f00b204e9800998ecf8427e');
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
GenSnapshot: () => genSnapshot,
|
||||
});
|
||||
|
||||
testUsingContext('builds snapshot and checksums when main entry point changes', () async {
|
||||
final _FakeGenSnapshot genSnapshot = new _FakeGenSnapshot(
|
||||
snapshotPath: 'output.snapshot',
|
||||
depfilePath: 'output.snapshot.d',
|
||||
depfileContent: 'output.snapshot : other.dart',
|
||||
);
|
||||
context.setVariable(GenSnapshot, genSnapshot);
|
||||
|
||||
await fs.file('main.dart').writeAsString('void main() {}');
|
||||
await fs.file('other.dart').writeAsString('void main() { print("Kanpai ima kimi wa jinsei no ookina ookina butai ni tachi"); }');
|
||||
await fs.file('output.snapshot.d').writeAsString('output.snapshot : main.dart');
|
||||
await fs.file('output.snapshot.d.checksums').writeAsString(JSON.encode(<String, dynamic>{
|
||||
'main.dart': '27f5ebf0f8c559b2af9419d190299a5e',
|
||||
'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e',
|
||||
}));
|
||||
await snapshotter.buildScriptSnapshot(
|
||||
mainPath: 'other.dart',
|
||||
snapshotPath: 'output.snapshot',
|
||||
depfilePath: 'output.snapshot.d',
|
||||
packagesPath: '.packages',
|
||||
);
|
||||
|
||||
expect(genSnapshot.callCount, 1);
|
||||
final Map<String, dynamic> json = JSON.decode(await fs.file('output.snapshot.d.checksums').readAsString());
|
||||
expect(json, hasLength(2));
|
||||
expect(json['other.dart'], '3238d0ae341339b1731d3c2e195ad177');
|
||||
expect(json['output.snapshot'], 'd41d8cd98f00b204e9800998ecf8427e');
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
});
|
||||
|
||||
testUsingContext('skips snapshot when checksums match and previous snapshot is present', () async {
|
||||
await fs.file('main.dart').writeAsString('void main() {}');
|
||||
await fs.file('output.snapshot').create();
|
||||
await fs.file('output.snapshot.d').writeAsString('output.snapshot : main.dart');
|
||||
await fs.file('output.snapshot.d.checksums').writeAsString(JSON.encode(<String, dynamic>{
|
||||
'main.dart': '27f5ebf0f8c559b2af9419d190299a5e',
|
||||
'output.snapshot': 'd41d8cd98f00b204e9800998ecf8427e',
|
||||
}));
|
||||
await snapshotter.buildScriptSnapshot(
|
||||
mainPath: 'main.dart',
|
||||
snapshotPath: 'output.snapshot',
|
||||
depfilePath: 'output.snapshot.d',
|
||||
packagesPath: '.packages',
|
||||
);
|
||||
|
||||
expect(genSnapshot.callCount, 0);
|
||||
|
||||
final Map<String, dynamic> json = JSON.decode(await fs.file('output.snapshot.d.checksums').readAsString());
|
||||
expect(json, hasLength(2));
|
||||
expect(json['main.dart'], '27f5ebf0f8c559b2af9419d190299a5e');
|
||||
expect(json['output.snapshot'], 'd41d8cd98f00b204e9800998ecf8427e');
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
GenSnapshot: () => genSnapshot,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user