Unverified Commit d72eea53 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] precache and unpack updates for desktop release artifacts (#55510)

- Update windows precache to include placeholder profile/release artifacts
- Update Linux and windows unpack to account for the cpp_client_wrapper code to live separate from the engine binaries
- Cleanup testing in unpack_linux and remove test cases that are covered in build_system_test.dart
parent 0c4a659d
...@@ -49,8 +49,12 @@ enum Artifact { ...@@ -49,8 +49,12 @@ enum Artifact {
iproxy, iproxy,
/// The root of the Linux desktop sources. /// The root of the Linux desktop sources.
linuxDesktopPath, linuxDesktopPath,
// The root of the cpp client code for Linux desktop.
linuxCppClientWrapper,
/// The root of the Windows desktop sources. /// The root of the Windows desktop sources.
windowsDesktopPath, windowsDesktopPath,
/// The root of the cpp client code for Windows desktop.
windowsCppClientWrapper,
/// The root of the sky_engine package /// The root of the sky_engine package
skyEnginePath, skyEnginePath,
/// The location of the macOS engine podspec file. /// The location of the macOS engine podspec file.
...@@ -116,6 +120,10 @@ String _artifactToFileName(Artifact artifact, [ TargetPlatform platform, BuildMo ...@@ -116,6 +120,10 @@ String _artifactToFileName(Artifact artifact, [ TargetPlatform platform, BuildMo
return ''; return '';
case Artifact.windowsDesktopPath: case Artifact.windowsDesktopPath:
return ''; return '';
case Artifact.windowsCppClientWrapper:
return 'cpp_client_wrapper';
case Artifact.linuxCppClientWrapper:
return 'cpp_client_wrapper_glfw';
case Artifact.skyEnginePath: case Artifact.skyEnginePath:
return 'sky_engine'; return 'sky_engine';
case Artifact.flutterMacOSPodspec: case Artifact.flutterMacOSPodspec:
...@@ -357,6 +365,12 @@ class CachedArtifacts extends Artifacts { ...@@ -357,6 +365,12 @@ class CachedArtifacts extends Artifacts {
} }
final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path; final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path;
return _fileSystem.path.join(engineArtifactsPath, platformDirName, _artifactToFileName(artifact, platform, mode)); return _fileSystem.path.join(engineArtifactsPath, platformDirName, _artifactToFileName(artifact, platform, mode));
case Artifact.windowsCppClientWrapper:
final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path;
return _fileSystem.path.join(engineArtifactsPath, 'windows-x64', _artifactToFileName(artifact, platform, mode));
case Artifact.linuxCppClientWrapper:
final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path;
return _fileSystem.path.join(engineArtifactsPath, 'linux-x64', _artifactToFileName(artifact, platform, mode));
case Artifact.skyEnginePath: case Artifact.skyEnginePath:
final Directory dartPackageDirectory = _cache.getCacheDir('pkg'); final Directory dartPackageDirectory = _cache.getCacheDir('pkg');
return _fileSystem.path.join(dartPackageDirectory.path, _artifactToFileName(artifact)); return _fileSystem.path.join(dartPackageDirectory.path, _artifactToFileName(artifact));
...@@ -517,8 +531,12 @@ class LocalEngineArtifacts extends Artifacts { ...@@ -517,8 +531,12 @@ class LocalEngineArtifacts extends Artifacts {
return _cache.getArtifactDirectory('usbmuxd').childFile(artifactFileName).path; return _cache.getArtifactDirectory('usbmuxd').childFile(artifactFileName).path;
case Artifact.linuxDesktopPath: case Artifact.linuxDesktopPath:
return _fileSystem.path.join(_hostEngineOutPath, artifactFileName); return _fileSystem.path.join(_hostEngineOutPath, artifactFileName);
case Artifact.linuxCppClientWrapper:
return _fileSystem.path.join(_hostEngineOutPath, artifactFileName);
case Artifact.windowsDesktopPath: case Artifact.windowsDesktopPath:
return _fileSystem.path.join(_hostEngineOutPath, artifactFileName); return _fileSystem.path.join(_hostEngineOutPath, artifactFileName);
case Artifact.windowsCppClientWrapper:
return _fileSystem.path.join(_hostEngineOutPath, artifactFileName);
case Artifact.skyEnginePath: case Artifact.skyEnginePath:
return _fileSystem.path.join(_hostEngineOutPath, 'gen', 'dart-pkg', artifactFileName); return _fileSystem.path.join(_hostEngineOutPath, 'gen', 'dart-pkg', artifactFileName);
case Artifact.flutterMacOSPodspec: case Artifact.flutterMacOSPodspec:
......
...@@ -7,59 +7,67 @@ import 'package:meta/meta.dart'; ...@@ -7,59 +7,67 @@ import 'package:meta/meta.dart';
import '../../base/file_system.dart'; import '../../base/file_system.dart';
import '../depfile.dart'; import '../depfile.dart';
/// Unpack the artifact list [artifacts] from [artifactPath] into a directory /// Unpack the engine artifact list [artifacts] from [engineSourcePath] and
/// [outputDirectory], returning a [Depfile] including all copied files. /// [clientSourcePath] (if provided) into a directory [outputDirectory].
///
/// Returns a [Depfile] including all copied files.
///
/// Throws an [Exception] if [artifacts] includes missing files, directories,
/// or links.
Depfile unpackDesktopArtifacts({ Depfile unpackDesktopArtifacts({
@required FileSystem fileSystem, @required FileSystem fileSystem,
@required List<String> artifacts, @required List<String> artifacts,
@required Directory outputDirectory, @required Directory outputDirectory,
@required String artifactPath, @required String engineSourcePath,
String clientSourcePath,
}) { }) {
final List<File> inputs = <File>[]; final List<File> inputs = <File>[];
final List<File> outputs = <File>[]; final List<File> outputs = <File>[];
for (final String artifact in artifacts) { for (final String artifact in artifacts) {
final String entityPath = fileSystem.path.join(artifactPath, artifact); final String entityPath = fileSystem.path.join(engineSourcePath, artifact);
final FileSystemEntityType entityType = fileSystem.typeSync(entityPath); final FileSystemEntityType entityType = fileSystem.typeSync(entityPath);
if (entityType == FileSystemEntityType.notFound if (entityType == FileSystemEntityType.notFound
|| entityType == FileSystemEntityType.directory
|| entityType == FileSystemEntityType.link) { || entityType == FileSystemEntityType.link) {
throw Exception('Unsupported file type: $entityType'); throw Exception('Unsupported file type: $entityType');
} }
assert(entityType == FileSystemEntityType.file);
// If this artifact is a file then copy the source over. final String outputPath = fileSystem.path.join(
if (entityType == FileSystemEntityType.file) { outputDirectory.path,
final String outputPath = fileSystem.path.join( fileSystem.path.relative(entityPath, from: engineSourcePath),
outputDirectory.path, );
fileSystem.path.relative(entityPath, from: artifactPath), final File destinationFile = fileSystem.file(outputPath);
); if (!destinationFile.parent.existsSync()) {
final File destinationFile = fileSystem.file(outputPath); destinationFile.parent.createSync(recursive: true);
if (!destinationFile.parent.existsSync()) {
destinationFile.parent.createSync(recursive: true);
}
final File inputFile = fileSystem.file(entityPath);
inputFile.copySync(destinationFile.path);
inputs.add(inputFile);
outputs.add(destinationFile);
continue;
} }
final File inputFile = fileSystem.file(entityPath);
// If the artifact is a directory, recursively copy every file from it. inputFile.copySync(destinationFile.path);
for (final File input in fileSystem.directory(entityPath) inputs.add(inputFile);
.listSync(recursive: true) outputs.add(destinationFile);
.whereType<File>()) { }
final String outputPath = fileSystem.path.join( if (clientSourcePath == null) {
outputDirectory.path, return Depfile(inputs, outputs);
fileSystem.path.relative(input.path, from: artifactPath), }
); final Directory clientSourceDirectory = fileSystem.directory(clientSourcePath);
final File destinationFile = fileSystem.file(outputPath); if (!clientSourceDirectory.existsSync()) {
if (!destinationFile.parent.existsSync()) { throw Exception('Missing clientSourceDirectory: $clientSourcePath');
destinationFile.parent.createSync(recursive: true); }
} for (final File input in clientSourceDirectory
final File inputFile = fileSystem.file(input); .listSync(recursive: true)
inputFile.copySync(destinationFile.path); .whereType<File>()) {
inputs.add(inputFile); final String outputPath = fileSystem.path.join(
outputs.add(destinationFile); outputDirectory.path,
fileSystem.path.relative(input.path, from: clientSourceDirectory.parent.path),
);
final File destinationFile = fileSystem.file(outputPath);
if (!destinationFile.parent.existsSync()) {
destinationFile.parent.createSync(recursive: true);
} }
final File inputFile = fileSystem.file(input);
inputFile.copySync(destinationFile.path);
inputs.add(inputFile);
outputs.add(destinationFile);
} }
return Depfile(inputs, outputs); return Depfile(inputs, outputs);
} }
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
import '../../artifacts.dart'; import '../../artifacts.dart';
import '../../base/file_system.dart'; import '../../base/file_system.dart';
import '../../build_info.dart'; import '../../build_info.dart';
import '../../globals.dart' as globals;
import '../build_system.dart'; import '../build_system.dart';
import '../depfile.dart'; import '../depfile.dart';
import '../exceptions.dart'; import '../exceptions.dart';
...@@ -22,17 +21,16 @@ const List<String> _kLinuxArtifacts = <String>[ ...@@ -22,17 +21,16 @@ const List<String> _kLinuxArtifacts = <String>[
'flutter_plugin_registrar.h', 'flutter_plugin_registrar.h',
'flutter_glfw.h', 'flutter_glfw.h',
'icudtl.dat', 'icudtl.dat',
'cpp_client_wrapper_glfw/',
]; ];
const String _kLinuxDepfile = 'linux_engine_sources.d'; const String _kLinuxDepfile = 'linux_engine_sources.d';
/// Copies the Linux desktop embedding files to the copy directory. /// Copies the Linux desktop embedding files to the copy directory.
class UnpackLinuxDebug extends Target { class UnpackLinux extends Target {
const UnpackLinuxDebug(); const UnpackLinux();
@override @override
String get name => 'unpack_linux_debug'; String get name => 'unpack_linux';
@override @override
List<Source> get inputs => const <Source>[ List<Source> get inputs => const <Source>[
...@@ -50,7 +48,19 @@ class UnpackLinuxDebug extends Target { ...@@ -50,7 +48,19 @@ class UnpackLinuxDebug extends Target {
@override @override
Future<void> build(Environment environment) async { Future<void> build(Environment environment) async {
final String artifactPath = globals.artifacts.getArtifactPath(Artifact.linuxDesktopPath); final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
final String engineSourcePath = environment.artifacts
.getArtifactPath(
Artifact.linuxDesktopPath,
mode: buildMode,
platform: TargetPlatform.linux_x64,
);
final String clientSourcePath = environment.artifacts
.getArtifactPath(
Artifact.linuxCppClientWrapper,
mode: buildMode,
platform: TargetPlatform.linux_x64,
);
final Directory outputDirectory = environment.fileSystem.directory( final Directory outputDirectory = environment.fileSystem.directory(
environment.fileSystem.path.join( environment.fileSystem.path.join(
environment.projectDir.path, environment.projectDir.path,
...@@ -60,13 +70,14 @@ class UnpackLinuxDebug extends Target { ...@@ -60,13 +70,14 @@ class UnpackLinuxDebug extends Target {
)); ));
final Depfile depfile = unpackDesktopArtifacts( final Depfile depfile = unpackDesktopArtifacts(
fileSystem: environment.fileSystem, fileSystem: environment.fileSystem,
artifactPath: artifactPath, engineSourcePath: engineSourcePath,
outputDirectory: outputDirectory, outputDirectory: outputDirectory,
artifacts: _kLinuxArtifacts, artifacts: _kLinuxArtifacts,
clientSourcePath: clientSourcePath,
); );
final DepfileService depfileService = DepfileService( final DepfileService depfileService = DepfileService(
fileSystem: globals.fs, fileSystem: environment.fileSystem,
logger: globals.logger, logger: environment.logger,
); );
depfileService.writeToFile( depfileService.writeToFile(
depfile, depfile,
...@@ -85,7 +96,7 @@ class DebugBundleLinuxAssets extends Target { ...@@ -85,7 +96,7 @@ class DebugBundleLinuxAssets extends Target {
@override @override
List<Target> get dependencies => const <Target>[ List<Target> get dependencies => const <Target>[
KernelSnapshot(), KernelSnapshot(),
UnpackLinuxDebug(), UnpackLinux(),
]; ];
@override @override
...@@ -125,8 +136,8 @@ class DebugBundleLinuxAssets extends Target { ...@@ -125,8 +136,8 @@ class DebugBundleLinuxAssets extends Target {
} }
final Depfile depfile = await copyAssets(environment, outputDirectory); final Depfile depfile = await copyAssets(environment, outputDirectory);
final DepfileService depfileService = DepfileService( final DepfileService depfileService = DepfileService(
fileSystem: globals.fs, fileSystem: environment.fileSystem,
logger: globals.logger, logger: environment.logger,
); );
depfileService.writeToFile( depfileService.writeToFile(
depfile, depfile,
......
...@@ -24,7 +24,6 @@ const List<String> _kWindowsArtifacts = <String>[ ...@@ -24,7 +24,6 @@ const List<String> _kWindowsArtifacts = <String>[
'flutter_plugin_registrar.h', 'flutter_plugin_registrar.h',
'flutter_windows.h', 'flutter_windows.h',
'icudtl.dat', 'icudtl.dat',
'cpp_client_wrapper',
]; ];
const String _kWindowsDepfile = 'windows_engine_sources.d'; const String _kWindowsDepfile = 'windows_engine_sources.d';
...@@ -52,7 +51,19 @@ class UnpackWindows extends Target { ...@@ -52,7 +51,19 @@ class UnpackWindows extends Target {
@override @override
Future<void> build(Environment environment) async { Future<void> build(Environment environment) async {
final String artifactPath = environment.artifacts.getArtifactPath(Artifact.windowsDesktopPath); final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
final String engineSourcePath = environment.artifacts
.getArtifactPath(
Artifact.windowsDesktopPath,
platform: TargetPlatform.windows_x64,
mode: buildMode,
);
final String clientSourcePath = environment.artifacts
.getArtifactPath(
Artifact.windowsCppClientWrapper,
platform: TargetPlatform.windows_x64,
mode: buildMode,
);
final Directory outputDirectory = environment.fileSystem.directory( final Directory outputDirectory = environment.fileSystem.directory(
environment.fileSystem.path.join( environment.fileSystem.path.join(
environment.projectDir.path, environment.projectDir.path,
...@@ -64,8 +75,9 @@ class UnpackWindows extends Target { ...@@ -64,8 +75,9 @@ class UnpackWindows extends Target {
final Depfile depfile = unpackDesktopArtifacts( final Depfile depfile = unpackDesktopArtifacts(
fileSystem: environment.fileSystem, fileSystem: environment.fileSystem,
artifacts: _kWindowsArtifacts, artifacts: _kWindowsArtifacts,
artifactPath: artifactPath, engineSourcePath: engineSourcePath,
outputDirectory: outputDirectory, outputDirectory: outputDirectory,
clientSourcePath: clientSourcePath,
); );
final DepfileService depfileService = DepfileService( final DepfileService depfileService = DepfileService(
fileSystem: environment.fileSystem, fileSystem: environment.fileSystem,
......
...@@ -118,9 +118,9 @@ class Cache { ...@@ -118,9 +118,9 @@ class Cache {
_artifacts.add(IOSEngineArtifacts(this)); _artifacts.add(IOSEngineArtifacts(this));
_artifacts.add(FlutterWebSdk(this)); _artifacts.add(FlutterWebSdk(this));
_artifacts.add(FlutterSdk(this)); _artifacts.add(FlutterSdk(this));
_artifacts.add(WindowsEngineArtifacts(this)); _artifacts.add(WindowsEngineArtifacts(this, platform: _platform));
_artifacts.add(MacOSEngineArtifacts(this)); _artifacts.add(MacOSEngineArtifacts(this));
_artifacts.add(LinuxEngineArtifacts(this)); _artifacts.add(LinuxEngineArtifacts(this, platform: _platform));
_artifacts.add(LinuxFuchsiaSDKArtifacts(this)); _artifacts.add(LinuxFuchsiaSDKArtifacts(this));
_artifacts.add(MacOSFuchsiaSDKArtifacts(this)); _artifacts.add(MacOSFuchsiaSDKArtifacts(this));
_artifacts.add(FlutterRunnerSDKArtifacts(this)); _artifacts.add(FlutterRunnerSDKArtifacts(this));
...@@ -879,19 +879,25 @@ class MacOSEngineArtifacts extends EngineCachedArtifact { ...@@ -879,19 +879,25 @@ class MacOSEngineArtifacts extends EngineCachedArtifact {
List<String> getLicenseDirs() => const <String>[]; List<String> getLicenseDirs() => const <String>[];
} }
/// Artifacts required for desktop Windows builds.
class WindowsEngineArtifacts extends EngineCachedArtifact { class WindowsEngineArtifacts extends EngineCachedArtifact {
WindowsEngineArtifacts(Cache cache) : super( WindowsEngineArtifacts(Cache cache, {
'windows-sdk', @required Platform platform,
cache, }) : _platform = platform,
DevelopmentArtifact.windows, super(
); 'windows-sdk',
cache,
DevelopmentArtifact.windows,
);
final Platform _platform;
@override @override
List<String> getPackageDirs() => const <String>[]; List<String> getPackageDirs() => const <String>[];
@override @override
List<List<String>> getBinaryDirs() { List<List<String>> getBinaryDirs() {
if (globals.platform.isWindows || ignorePlatformFiltering) { if (_platform.isWindows || ignorePlatformFiltering) {
return _windowsDesktopBinaryDirs; return _windowsDesktopBinaryDirs;
} }
return const <List<String>>[]; return const <List<String>>[];
...@@ -901,19 +907,25 @@ class WindowsEngineArtifacts extends EngineCachedArtifact { ...@@ -901,19 +907,25 @@ class WindowsEngineArtifacts extends EngineCachedArtifact {
List<String> getLicenseDirs() => const <String>[]; List<String> getLicenseDirs() => const <String>[];
} }
/// Artifacts required for desktop Linux builds.
class LinuxEngineArtifacts extends EngineCachedArtifact { class LinuxEngineArtifacts extends EngineCachedArtifact {
LinuxEngineArtifacts(Cache cache) : super( LinuxEngineArtifacts(Cache cache, {
'linux-sdk', @required Platform platform
cache, }) : _platform = platform,
DevelopmentArtifact.linux, super(
); 'linux-sdk',
cache,
DevelopmentArtifact.linux,
);
final Platform _platform;
@override @override
List<String> getPackageDirs() => const <String>[]; List<String> getPackageDirs() => const <String>[];
@override @override
List<List<String>> getBinaryDirs() { List<List<String>> getBinaryDirs() {
if (globals.platform.isLinux || ignorePlatformFiltering) { if (_platform.isLinux || ignorePlatformFiltering) {
return _linuxDesktopBinaryDirs; return _linuxDesktopBinaryDirs;
} }
return const <List<String>>[]; return const <List<String>>[];
...@@ -1364,9 +1376,14 @@ void _ensureExists(Directory directory) { ...@@ -1364,9 +1376,14 @@ void _ensureExists(Directory directory) {
} }
} }
// TODO(jonahwilliams): upload debug desktop artifacts to host-debug and
// remove from existing host folder.
// https://github.com/flutter/flutter/issues/38935
const List<List<String>> _windowsDesktopBinaryDirs = <List<String>>[ const List<List<String>> _windowsDesktopBinaryDirs = <List<String>>[
<String>['windows-x64', 'windows-x64/windows-x64-flutter.zip'], <String>['windows-x64', 'windows-x64/windows-x64-flutter.zip'],
<String>['windows-x64', 'windows-x64/flutter-cpp-client-wrapper.zip'], <String>['windows-x64', 'windows-x64/flutter-cpp-client-wrapper.zip'],
<String>['windows-x64-profile', 'windows-x64-profile/windows-x64-flutter.zip'],
<String>['windows-x64-release', 'windows-x64-release/windows-x64-flutter.zip'],
]; ];
const List<List<String>> _linuxDesktopBinaryDirs = <List<String>>[ const List<List<String>> _linuxDesktopBinaryDirs = <List<String>>[
...@@ -1374,9 +1391,6 @@ const List<List<String>> _linuxDesktopBinaryDirs = <List<String>>[ ...@@ -1374,9 +1391,6 @@ const List<List<String>> _linuxDesktopBinaryDirs = <List<String>>[
<String>['linux-x64', 'linux-x64/flutter-cpp-client-wrapper-glfw.zip'], <String>['linux-x64', 'linux-x64/flutter-cpp-client-wrapper-glfw.zip'],
]; ];
// TODO(jonahwilliams): upload debug desktop artifacts to host-debug and
// remove from existing host folder.
// https://github.com/flutter/flutter/issues/38935
const List<List<String>> _macOSDesktopBinaryDirs = <List<String>>[ const List<List<String>> _macOSDesktopBinaryDirs = <List<String>>[
<String>['darwin-x64', 'darwin-x64/FlutterMacOS.framework.zip'], <String>['darwin-x64', 'darwin-x64/FlutterMacOS.framework.zip'],
<String>['darwin-x64-profile', 'darwin-x64-profile/FlutterMacOS.framework.zip'], <String>['darwin-x64-profile', 'darwin-x64-profile/FlutterMacOS.framework.zip'],
......
...@@ -17,19 +17,19 @@ void main() { ...@@ -17,19 +17,19 @@ void main() {
// Should be copied. // Should be copied.
fileSystem.file('inputs/a.txt').createSync(); fileSystem.file('inputs/a.txt').createSync();
fileSystem.file('inputs/b.txt').createSync(); fileSystem.file('inputs/b.txt').createSync();
fileSystem.file('inputs/foo/c.txt').createSync(); fileSystem.file('foo/c.txt').createSync(recursive: true);
// Sould not be copied. // Sould not be copied.
fileSystem.file('inputs/d.txt').createSync(); fileSystem.file('inputs/d.txt').createSync();
final Depfile depfile = unpackDesktopArtifacts( final Depfile depfile = unpackDesktopArtifacts(
fileSystem: fileSystem, fileSystem: fileSystem,
artifactPath: 'inputs', engineSourcePath: 'inputs',
outputDirectory: fileSystem.directory('outputs'), outputDirectory: fileSystem.directory('outputs'),
artifacts: <String>[ artifacts: <String>[
'a.txt', 'a.txt',
'b.txt', 'b.txt',
'foo/'
], ],
clientSourcePath: 'foo',
); );
// Files are copied // Files are copied
...@@ -42,7 +42,7 @@ void main() { ...@@ -42,7 +42,7 @@ void main() {
expect(depfile.inputs.map((File file) => file.path), unorderedEquals(<String>[ expect(depfile.inputs.map((File file) => file.path), unorderedEquals(<String>[
'inputs/a.txt', 'inputs/a.txt',
'inputs/b.txt', 'inputs/b.txt',
'inputs/foo/c.txt', 'foo/c.txt',
])); ]));
expect(depfile.outputs.map((File file) => file.path), unorderedEquals(<String>[ expect(depfile.outputs.map((File file) => file.path), unorderedEquals(<String>[
'outputs/a.txt', 'outputs/a.txt',
...@@ -56,11 +56,41 @@ void main() { ...@@ -56,11 +56,41 @@ void main() {
expect(() => unpackDesktopArtifacts( expect(() => unpackDesktopArtifacts(
fileSystem: fileSystem, fileSystem: fileSystem,
artifactPath: 'inputs', engineSourcePath: 'inputs',
outputDirectory: fileSystem.directory('outputs'), outputDirectory: fileSystem.directory('outputs'),
artifacts: <String>[ artifacts: <String>[
'a.txt', 'a.txt',
], ],
clientSourcePath: 'foo'
), throwsA(isA<Exception>())); ), throwsA(isA<Exception>()));
}); });
testWithoutContext('unpackDesktopArtifacts throws when attempting to copy missing directory', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
fileSystem.file('inputs/a.txt').createSync(recursive: true);
expect(() => unpackDesktopArtifacts(
fileSystem: fileSystem,
engineSourcePath: 'inputs',
outputDirectory: fileSystem.directory('outputs'),
artifacts: <String>[
'a.txt',
],
clientSourcePath: 'foo'
), throwsA(isA<Exception>()));
});
testWithoutContext('unpackDesktopArtifacts does not require a client source path', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
fileSystem.file('inputs/a.txt').createSync(recursive: true);
expect(() => unpackDesktopArtifacts(
fileSystem: fileSystem,
engineSourcePath: 'inputs',
outputDirectory: fileSystem.directory('outputs'),
artifacts: <String>[
'a.txt',
],
), returnsNormally);
});
} }
...@@ -2,118 +2,106 @@ ...@@ -2,118 +2,106 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:file/memory.dart';
import 'package:file_testing/file_testing.dart';
import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/artifacts.dart';
import 'package:platform/platform.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/build_system/targets/dart.dart'; import 'package:flutter_tools/src/build_system/targets/dart.dart';
import 'package:flutter_tools/src/build_system/targets/linux.dart'; import 'package:flutter_tools/src/build_system/targets/linux.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import '../../../src/common.dart'; import '../../../src/common.dart';
import '../../../src/context.dart'; import '../../../src/context.dart';
import '../../../src/testbed.dart';
void main() { void main() {
Testbed testbed; testWithoutContext('Copies files to correct cache directory, excluding unrelated code', () async {
BuildSystem buildSystem; final FileSystem fileSystem = MemoryFileSystem.test();
Environment environment; setUpCacheDirectory(fileSystem);
MockPlatform mockPlatform; final MockArtifacts mockArtifacts = MockArtifacts();
when(mockArtifacts.getArtifactPath(
setUpAll(() { Artifact.linuxDesktopPath,
Cache.disableLocking(); mode: anyNamed('mode'),
Cache.flutterRoot = ''; platform: anyNamed('platform'),
)).thenReturn('linux-x64');
when(mockArtifacts.getArtifactPath(
Artifact.linuxCppClientWrapper,
mode: anyNamed('mode'),
platform: anyNamed('platform'),
)).thenReturn('linux-x64/cpp_client_wrapper_glfw');
final Environment testEnvironment = Environment.test(
fileSystem.currentDirectory,
defines: <String, String>{
kBuildMode: 'debug',
},
artifacts: mockArtifacts,
processManager: FakeProcessManager.any(),
fileSystem: fileSystem,
logger: BufferLogger.test(),
);
testEnvironment.buildDir.createSync(recursive: true);
await const UnpackLinux().build(testEnvironment);
expect(fileSystem.file('linux/flutter/ephemeral/libflutter_linux_glfw.so'), exists);
expect(fileSystem.file('linux/flutter/ephemeral/flutter_export.h'), exists);
expect(fileSystem.file('linux/flutter/ephemeral/flutter_messenger.h'), exists);
expect(fileSystem.file('linux/flutter/ephemeral/flutter_plugin_registrar.h'), exists);
expect(fileSystem.file('linux/flutter/ephemeral/flutter_glfw.h'), exists);
expect(fileSystem.file('linux/flutter/ephemeral/icudtl.dat'), exists);
expect(fileSystem.file('linux/flutter/ephemeral/cpp_client_wrapper_glfw/foo'), exists);
expect(fileSystem.file('linux/flutter/ephemeral/unrelated-stuff'), isNot(exists));
}); });
// Only required for the test below that still depends on the context.
FileSystem fileSystem;
setUp(() { setUp(() {
mockPlatform = MockPlatform(); fileSystem = MemoryFileSystem.test();
when(mockPlatform.isWindows).thenReturn(false);
when(mockPlatform.isMacOS).thenReturn(false);
when(mockPlatform.isLinux).thenReturn(true);
when(mockPlatform.environment).thenReturn(Map<String, String>.unmodifiable(<String, String>{}));
testbed = Testbed(setup: () {
Cache.flutterRoot = '';
buildSystem = BuildSystem(
logger: globals.logger,
platform: globals.platform,
fileSystem: globals.fs,
);
environment = Environment.test(
globals.fs.currentDirectory,
defines: <String, String>{
kBuildMode: 'debug',
},
artifacts: MockArtifacts(),
processManager: FakeProcessManager.any(),
fileSystem: globals.fs,
logger: globals.logger,
);
globals.fs.file('bin/cache/artifacts/engine/linux-x64/unrelated-stuff').createSync(recursive: true);
globals.fs.file('bin/cache/artifacts/engine/linux-x64/libflutter_linux_glfw.so').createSync(recursive: true);
globals.fs.file('bin/cache/artifacts/engine/linux-x64/flutter_export.h').createSync();
globals.fs.file('bin/cache/artifacts/engine/linux-x64/flutter_messenger.h').createSync();
globals.fs.file('bin/cache/artifacts/engine/linux-x64/flutter_plugin_registrar.h').createSync();
globals.fs.file('bin/cache/artifacts/engine/linux-x64/flutter_glfw.h').createSync();
globals.fs.file('bin/cache/artifacts/engine/linux-x64/icudtl.dat').createSync();
globals.fs.file('bin/cache/artifacts/engine/linux-x64/cpp_client_wrapper_glfw/foo').createSync(recursive: true);
globals.fs.file('packages/flutter_tools/lib/src/build_system/targets/linux.dart').createSync(recursive: true);
globals.fs.directory('linux').createSync();
}, overrides: <Type, Generator>{
Platform: () => mockPlatform,
});
}); });
test('Copies files to correct cache directory, excluding unrelated code', () => testbed.run(() async { testUsingContext('DebugBundleLinuxAssets copies artifacts to out directory', () async {
final BuildResult result = await buildSystem.build(const UnpackLinuxDebug(), environment); final Environment testEnvironment = Environment.test(
fileSystem.currentDirectory,
expect(result.hasException, false); defines: <String, String>{
expect(globals.fs.file('linux/flutter/ephemeral/libflutter_linux_glfw.so').existsSync(), true); kBuildMode: 'debug',
expect(globals.fs.file('linux/flutter/ephemeral/flutter_export.h').existsSync(), true); },
expect(globals.fs.file('linux/flutter/ephemeral/flutter_messenger.h').existsSync(), true); artifacts: MockArtifacts(),
expect(globals.fs.file('linux/flutter/ephemeral/flutter_plugin_registrar.h').existsSync(), true); processManager: FakeProcessManager.any(),
expect(globals.fs.file('linux/flutter/ephemeral/flutter_glfw.h').existsSync(), true); fileSystem: fileSystem,
expect(globals.fs.file('linux/flutter/ephemeral/icudtl.dat').existsSync(), true); logger: BufferLogger.test(),
expect(globals.fs.file('linux/flutter/ephemeral/cpp_client_wrapper_glfw/foo').existsSync(), true); );
expect(globals.fs.file('linux/flutter/ephemeral/unrelated-stuff').existsSync(), false);
}));
test('Does not re-copy files unecessarily', () => testbed.run(() async {
await buildSystem.build(const UnpackLinuxDebug(), environment);
// Set a date in the far distant past to deal with the limited resolution
// of the windows filesystem.
final DateTime theDistantPast = DateTime(1991, 8, 23);
globals.fs.file('linux/flutter/ephemeral/libflutter_linux_glfw.so').setLastModifiedSync(theDistantPast);
await buildSystem.build(const UnpackLinuxDebug(), environment);
expect(globals.fs.file('linux/flutter/ephemeral/libflutter_linux_glfw.so').statSync().modified, equals(theDistantPast));
}));
test('Detects changes in input cache files', () => testbed.run(() async {
await buildSystem.build(const UnpackLinuxDebug(), environment);
globals.fs.file('bin/cache/artifacts/engine/linux-x64/libflutter_linux_glfw.so').writeAsStringSync('asd'); // modify cache.
await buildSystem.build(const UnpackLinuxDebug(), environment); testEnvironment.buildDir.createSync(recursive: true);
expect(globals.fs.file('linux/flutter/ephemeral/libflutter_linux_glfw.so').readAsStringSync(), 'asd');
}));
test('Copies artifacts to out directory', () => testbed.run(() async {
environment.buildDir.createSync(recursive: true);
// Create input files. // Create input files.
environment.buildDir.childFile('app.dill').createSync(); testEnvironment.buildDir.childFile('app.dill').createSync();
await const DebugBundleLinuxAssets().build(environment); await const DebugBundleLinuxAssets().build(testEnvironment);
final Directory output = environment.outputDir final Directory output = testEnvironment.outputDir
.childDirectory('flutter_assets'); .childDirectory('flutter_assets');
expect(output.childFile('kernel_blob.bin').existsSync(), true); expect(output.childFile('kernel_blob.bin'), exists);
expect(output.childFile('FontManifest.json').existsSync(), false); expect(output.childFile('AssetManifest.json'), exists);
expect(output.childFile('AssetManifest.json').existsSync(), true); // No bundled fonts
})); expect(output.childFile('FontManifest.json'), isNot(exists));
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(),
});
}
void setUpCacheDirectory(FileSystem fileSystem) {
fileSystem.file('linux-x64/unrelated-stuff').createSync(recursive: true);
fileSystem.file('linux-x64/libflutter_linux_glfw.so').createSync(recursive: true);
fileSystem.file('linux-x64/flutter_export.h').createSync();
fileSystem.file('linux-x64/flutter_messenger.h').createSync();
fileSystem.file('linux-x64/flutter_plugin_registrar.h').createSync();
fileSystem.file('linux-x64/flutter_glfw.h').createSync();
fileSystem.file('linux-x64/icudtl.dat').createSync();
fileSystem.file('linux-x64/cpp_client_wrapper_glfw/foo').createSync(recursive: true);
fileSystem.file('packages/flutter_tools/lib/src/build_system/targets/linux.dart').createSync(recursive: true);
} }
class MockPlatform extends Mock implements Platform {}
class MockArtifacts extends Mock implements Artifacts {} class MockArtifacts extends Mock implements Artifacts {}
...@@ -47,6 +47,9 @@ void main() { ...@@ -47,6 +47,9 @@ void main() {
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
fileSystem: fileSystem, fileSystem: fileSystem,
logger: BufferLogger.test(), logger: BufferLogger.test(),
defines: <String, String>{
kBuildMode: 'debug',
}
); );
final DepfileService depfileService = DepfileService( final DepfileService depfileService = DepfileService(
logger: BufferLogger.test(), logger: BufferLogger.test(),
...@@ -54,8 +57,16 @@ void main() { ...@@ -54,8 +57,16 @@ void main() {
); );
environment.buildDir.createSync(recursive: true); environment.buildDir.createSync(recursive: true);
when(artifacts.getArtifactPath(Artifact.windowsDesktopPath)) when(artifacts.getArtifactPath(
.thenReturn(r'C:\bin\cache\artifacts\engine\windows-x64\'); Artifact.windowsDesktopPath,
mode: anyNamed('mode'),
platform: anyNamed('platform')
)).thenReturn(r'C:\bin\cache\artifacts\engine\windows-x64\');
when(artifacts.getArtifactPath(
Artifact.windowsCppClientWrapper,
mode: anyNamed('mode'),
platform: anyNamed('platform')
)).thenReturn(r'C:\bin\cache\artifacts\engine\windows-x64\cpp_client_wrapper\');
for (final String path in kRequiredFiles) { for (final String path in kRequiredFiles) {
fileSystem.file(path).createSync(recursive: true); fileSystem.file(path).createSync(recursive: true);
} }
...@@ -117,8 +128,13 @@ void main() { ...@@ -117,8 +128,13 @@ void main() {
}); });
// AssetBundleFactory still uses context injection // AssetBundleFactory still uses context injection
FileSystem fileSystem;
setUp(() {
fileSystem = MemoryFileSystem.test(style: FileSystemStyle.windows);
});
testUsingContext('DebugBundleWindowsAssets creates correct bundle structure', () async { testUsingContext('DebugBundleWindowsAssets creates correct bundle structure', () async {
final FileSystem fileSystem = MemoryFileSystem.test(style: FileSystemStyle.windows);
final Environment environment = Environment.test( final Environment environment = Environment.test(
fileSystem.currentDirectory, fileSystem.currentDirectory,
artifacts: MockArtifacts(), artifacts: MockArtifacts(),
...@@ -137,6 +153,10 @@ void main() { ...@@ -137,6 +153,10 @@ void main() {
// Depfile is created and dill is copied. // Depfile is created and dill is copied.
expect(environment.buildDir.childFile('flutter_assets.d'), exists); expect(environment.buildDir.childFile('flutter_assets.d'), exists);
expect(fileSystem.file(r'C:\flutter_assets\kernel_blob.bin'), exists); expect(fileSystem.file(r'C:\flutter_assets\kernel_blob.bin'), exists);
expect(fileSystem.file(r'C:\flutter_assets\AssetManifest.json'), exists);
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(),
}); });
} }
......
...@@ -574,26 +574,41 @@ void main() { ...@@ -574,26 +574,41 @@ void main() {
Platform: () => FakePlatform(operatingSystem: 'linux'), Platform: () => FakePlatform(operatingSystem: 'linux'),
}); });
testUsingContext('Windows desktop artifacts ignore filtering when requested', () { testWithoutContext('Windows desktop artifacts ignore filtering when requested', () {
final MockCache mockCache = MockCache(); final MockCache mockCache = MockCache();
final WindowsEngineArtifacts artifacts = WindowsEngineArtifacts(mockCache); final WindowsEngineArtifacts artifacts = WindowsEngineArtifacts(
mockCache,
platform: FakePlatform(operatingSystem: 'linux'),
);
when(mockCache.includeAllPlatforms).thenReturn(false); when(mockCache.includeAllPlatforms).thenReturn(false);
when(mockCache.platformOverrideArtifacts).thenReturn(<String>{'windows'}); when(mockCache.platformOverrideArtifacts).thenReturn(<String>{'windows'});
expect(artifacts.getBinaryDirs(), isNotEmpty); expect(artifacts.getBinaryDirs(), isNotEmpty);
}, overrides: <Type, Generator> {
Platform: () => FakePlatform(operatingSystem: 'linux'),
}); });
testUsingContext('Linux desktop artifacts ignore filtering when requested', () { testWithoutContext('Windows desktop artifacts include profile and release artifacts', () {
final MockCache mockCache = MockCache(); final MockCache mockCache = MockCache();
final LinuxEngineArtifacts artifacts = LinuxEngineArtifacts(mockCache); final WindowsEngineArtifacts artifacts = WindowsEngineArtifacts(
mockCache,
platform: FakePlatform(operatingSystem: 'windows'),
);
expect(artifacts.getBinaryDirs(), containsAll(<Matcher>[
contains(contains('profile')),
contains(contains('release')),
]));
});
testWithoutContext('Linux desktop artifacts ignore filtering when requested', () {
final MockCache mockCache = MockCache();
final LinuxEngineArtifacts artifacts = LinuxEngineArtifacts(
mockCache,
platform: FakePlatform(operatingSystem: 'macos'),
);
when(mockCache.includeAllPlatforms).thenReturn(false); when(mockCache.includeAllPlatforms).thenReturn(false);
when(mockCache.platformOverrideArtifacts).thenReturn(<String>{'linux'}); when(mockCache.platformOverrideArtifacts).thenReturn(<String>{'linux'});
expect(artifacts.getBinaryDirs(), isNotEmpty); expect(artifacts.getBinaryDirs(), isNotEmpty);
}, overrides: <Type, Generator> {
Platform: () => FakePlatform(operatingSystem: 'macos'),
}); });
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment