flutter/packages/flutter_tools/test/general.shard/resident_runner_helpers.dart
Daco Harkes 4e70bfae2b
Reland "Move native assets to isolated/ directory" (#143055)
Reland of https://github.com/flutter/flutter/pull/142709.

The revert of the revert is in the first commit, the fix in the commit on top.

The move of the fakes for packages/flutter_tools/test/general.shard/resident_runner_test.dart was erroneous before, as it was trying to use setters instead of a private field. This PR changes the private `_devFS` field in the fake to be a public `fakeDevFS` in line with other fakes.

## Original PR description

Native assets in other build systems are not built with `package:native_assets_builder` invoking `build.dart` scripts. Instead all packages have their own blaze rules. Therefore we'd like to not depend on `package:native_assets_builder` from flutter tools in g3 at all.

This PR aims to move the imports of `native_assets_builder` and `native_assets_cli` into the `isolated/` directory and into the files with a `main` function that are not used in with other build systems.

In order to be able to remove all imports in files used by other build systems, two new interfaces are added `HotRunnerNativeAssetsBuilder` and `TestCompilerNativeAssetsBuilder`. New parameters are then piped all the way through from the entry points:

* bin/fuchsia_tester.dart
* lib/executable.dart

The build_system/targets dir is already excluded in other build systems.

So, after this PR only the two above files and build_system/targets import from `isolated/native_assets/` and only `isolated/native_assets/` import `package:native_assets_cli` and `package:native_assets_builder`.

Context:

* https://github.com/flutter/flutter/issues/142041
2024-02-08 17:49:48 +00:00

530 lines
13 KiB
Dart

// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:dds/dds.dart' as dds;
import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/asset.dart';
import 'package:flutter_tools/src/base/dds.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/build_system/tools/scene_importer.dart';
import 'package:flutter_tools/src/build_system/tools/shader_compiler.dart';
import 'package:flutter_tools/src/compile.dart';
import 'package:flutter_tools/src/devfs.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/device_port_forwarder.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/resident_runner.dart';
import 'package:flutter_tools/src/run_cold.dart';
import 'package:flutter_tools/src/run_hot.dart';
import 'package:flutter_tools/src/vmservice.dart';
import 'package:package_config/package_config.dart';
import 'package:test/fake.dart';
import 'package:vm_service/vm_service.dart' as vm_service;
import '../src/fake_vm_services.dart';
final vm_service.Event fakeUnpausedEvent = vm_service.Event(
kind: vm_service.EventKind.kResume,
timestamp: 0
);
final vm_service.Event fakePausedEvent = vm_service.Event(
kind: vm_service.EventKind.kPauseException,
timestamp: 0
);
final vm_service.Isolate fakeUnpausedIsolate = vm_service.Isolate(
id: '1',
pauseEvent: fakeUnpausedEvent,
breakpoints: <vm_service.Breakpoint>[],
extensionRPCs: <String>[],
libraries: <vm_service.LibraryRef>[
vm_service.LibraryRef(
id: '1',
uri: 'file:///hello_world/main.dart',
name: '',
),
],
livePorts: 0,
name: 'test',
number: '1',
pauseOnExit: false,
runnable: true,
startTime: 0,
isSystemIsolate: false,
isolateFlags: <vm_service.IsolateFlag>[],
);
final vm_service.Isolate fakePausedIsolate = vm_service.Isolate(
id: '1',
pauseEvent: fakePausedEvent,
breakpoints: <vm_service.Breakpoint>[
vm_service.Breakpoint(
breakpointNumber: 123,
id: 'test-breakpoint',
location: vm_service.SourceLocation(
tokenPos: 0,
script: vm_service.ScriptRef(id: 'test-script', uri: 'foo.dart'),
),
enabled: true,
resolved: true,
),
],
libraries: <vm_service.LibraryRef>[],
livePorts: 0,
name: 'test',
number: '1',
pauseOnExit: false,
runnable: true,
startTime: 0,
isSystemIsolate: false,
isolateFlags: <vm_service.IsolateFlag>[],
);
final vm_service.VM fakeVM = vm_service.VM(
isolates: <vm_service.IsolateRef>[fakeUnpausedIsolate],
pid: 1,
hostCPU: '',
isolateGroups: <vm_service.IsolateGroupRef>[],
targetCPU: '',
startTime: 0,
name: 'dart',
architectureBits: 64,
operatingSystem: '',
version: '',
systemIsolateGroups: <vm_service.IsolateGroupRef>[],
systemIsolates: <vm_service.IsolateRef>[],
);
final FlutterView fakeFlutterView = FlutterView(
id: 'a',
uiIsolate: fakeUnpausedIsolate,
);
final FakeVmServiceRequest listViews = FakeVmServiceRequest(
method: kListViewsMethod,
jsonResponse: <String, Object>{
'views': <Object>[
fakeFlutterView.toJson(),
],
},
);
const FakeVmServiceRequest setAssetBundlePath = FakeVmServiceRequest(
method: '_flutter.setAssetBundlePath',
args: <String, Object>{
'viewId': 'a',
'assetDirectory': 'build/flutter_assets',
'isolateId': '1',
}
);
const FakeVmServiceRequest evict = FakeVmServiceRequest(
method: 'ext.flutter.evict',
args: <String, Object>{
'value': 'asset',
'isolateId': '1',
}
);
const FakeVmServiceRequest evictShader = FakeVmServiceRequest(
method: 'ext.ui.window.reinitializeShader',
args: <String, Object>{
'assetKey': 'foo.frag',
'isolateId': '1',
}
);
final Uri testUri = Uri.parse('foo://bar');
// This implements [dds.DartDevelopmentService], not the [DartDevelopmentService]
// interface from package:flutter_tools.
class FakeDartDevelopmentService extends Fake implements dds.DartDevelopmentService {
@override
Future<void> get done => Future<void>.value();
@override
Uri? get uri => null;
}
class FakeDartDevelopmentServiceException implements dds.DartDevelopmentServiceException {
FakeDartDevelopmentServiceException({this.message = defaultMessage});
@override
final int errorCode = dds.DartDevelopmentServiceException.existingDdsInstanceError;
@override
final String message;
static const String defaultMessage = 'A DDS instance is already connected at http://localhost:8181';
}
class TestFlutterDevice extends FlutterDevice {
TestFlutterDevice(super.device, { Stream<Uri>? vmServiceUris })
: _vmServiceUris = vmServiceUris, super(buildInfo: BuildInfo.debug, developmentShaderCompiler: const FakeShaderCompiler());
final Stream<Uri>? _vmServiceUris;
@override
Stream<Uri> get vmServiceUris => _vmServiceUris!;
}
class ThrowingForwardingFileSystem extends ForwardingFileSystem {
ThrowingForwardingFileSystem(super.delegate);
@override
File file(dynamic path) {
if (path == 'foo') {
throw const FileSystemException();
}
return delegate.file(path);
}
}
class FakeFlutterDevice extends Fake implements FlutterDevice {
FakeVmServiceHost? Function()? vmServiceHost;
Uri? testUri;
UpdateFSReport report = UpdateFSReport(
success: true,
invalidatedSourcesCount: 1,
);
Exception? reportError;
Exception? runColdError;
int runHotCode = 0;
int runColdCode = 0;
@override
ResidentCompiler? generator;
@override
DevelopmentShaderCompiler get developmentShaderCompiler => const FakeShaderCompiler();
@override
TargetPlatform targetPlatform = TargetPlatform.android;
@override
Stream<Uri?> get vmServiceUris => Stream<Uri?>.value(testUri);
@override
FlutterVmService? get vmService => vmServiceHost?.call()?.vmService;
DevFS? fakeDevFS;
@override
DevFS? get devFS => fakeDevFS;
@override
set devFS(DevFS? value) { }
@override
Device? device;
@override
Future<void> stopEchoingDeviceLog() async { }
@override
Future<void> initLogReader() async { }
@override
Future<Uri> setupDevFS(String fsName, Directory rootDirectory) async {
return testUri!;
}
@override
Future<int> runHot({required HotRunner hotRunner, String? route}) async {
return runHotCode;
}
@override
Future<int> runCold({required ColdRunner coldRunner, String? route}) async {
if (runColdError != null) {
throw runColdError!;
}
return runColdCode;
}
@override
Future<void> connect({
ReloadSources? reloadSources,
Restart? restart,
CompileExpression? compileExpression,
GetSkSLMethod? getSkSLMethod,
FlutterProject? flutterProject,
PrintStructuredErrorLogMethod? printStructuredErrorLogMethod,
int? hostVmServicePort,
int? ddsPort,
bool disableServiceAuthCodes = false,
bool enableDds = true,
bool cacheStartupProfile = false,
required bool allowExistingDdsInstance,
bool ipv6 = false,
}) async { }
@override
Future<UpdateFSReport> updateDevFS({
required Uri mainUri,
String? target,
AssetBundle? bundle,
DateTime? firstBuildTime,
bool bundleFirstUpload = false,
bool bundleDirty = false,
bool fullRestart = false,
String? projectRootPath,
required String pathToReload,
required String dillOutputPath,
required List<Uri> invalidatedFiles,
required PackageConfig packageConfig,
}) async {
if (reportError != null) {
throw reportError!;
}
return report;
}
@override
Future<void> updateReloadStatus(bool wasReloadSuccessful) async { }
}
class FakeDelegateFlutterDevice extends FlutterDevice {
FakeDelegateFlutterDevice(
super.device,
BuildInfo buildInfo,
ResidentCompiler residentCompiler,
this.fakeDevFS,
) : super(buildInfo: buildInfo, generator: residentCompiler, developmentShaderCompiler: const FakeShaderCompiler());
@override
Future<void> connect({
ReloadSources? reloadSources,
Restart? restart,
bool enableDds = true,
bool cacheStartupProfile = false,
bool disableServiceAuthCodes = false,
bool ipv6 = false,
CompileExpression? compileExpression,
GetSkSLMethod? getSkSLMethod,
FlutterProject? flutterProject,
int? hostVmServicePort,
int? ddsPort,
PrintStructuredErrorLogMethod? printStructuredErrorLogMethod,
bool allowExistingDdsInstance = false,
}) async { }
final DevFS fakeDevFS;
@override
DevFS? get devFS => fakeDevFS;
@override
set devFS(DevFS? value) {}
}
class FakeResidentCompiler extends Fake implements ResidentCompiler {
CompilerOutput? nextOutput;
bool didSuppressErrors = false;
Uri? receivedNativeAssetsYaml;
bool recompileCalled = false;
@override
Future<CompilerOutput?> recompile(
Uri mainUri,
List<Uri>? invalidatedFiles, {
required String outputPath,
required PackageConfig packageConfig,
String? projectRootPath,
required FileSystem fs,
bool suppressErrors = false,
bool checkDartPluginRegistry = false,
File? dartPluginRegistrant,
Uri? nativeAssetsYaml,
}) async {
recompileCalled = true;
receivedNativeAssetsYaml = nativeAssetsYaml;
didSuppressErrors = suppressErrors;
return nextOutput ?? const CompilerOutput('foo.dill', 0, <Uri>[]);
}
@override
void accept() { }
@override
void reset() { }
}
class FakeProjectFileInvalidator extends Fake implements ProjectFileInvalidator {
@override
Future<InvalidationResult> findInvalidated({
required DateTime? lastCompiled,
required List<Uri> urisToMonitor,
required String packagesPath,
required PackageConfig packageConfig,
bool asyncScanning = false,
}) async {
return InvalidationResult(
packageConfig: packageConfig,
uris: <Uri>[Uri.parse('file:///hello_world/main.dart'),
]);
}
}
class FakeDevice extends Fake implements Device {
FakeDevice({
String sdkNameAndVersion = 'Android',
TargetPlatform targetPlatform = TargetPlatform.android_arm,
bool isLocalEmulator = false,
this.supportsHotRestart = true,
this.supportsScreenshot = true,
this.supportsFlutterExit = true,
}) : _isLocalEmulator = isLocalEmulator,
_targetPlatform = targetPlatform,
_sdkNameAndVersion = sdkNameAndVersion;
final bool _isLocalEmulator;
final TargetPlatform _targetPlatform;
final String _sdkNameAndVersion;
bool disposed = false;
bool appStopped = false;
bool failScreenshot = false;
@override
bool supportsHotRestart;
@override
bool supportsScreenshot;
@override
bool supportsFlutterExit;
@override
PlatformType get platformType => _targetPlatform == TargetPlatform.web_javascript
? PlatformType.web
: PlatformType.android;
@override
Future<String> get sdkNameAndVersion async => _sdkNameAndVersion;
@override
Future<TargetPlatform> get targetPlatform async => _targetPlatform;
@override
Future<bool> get isLocalEmulator async => _isLocalEmulator;
@override
String get name => 'FakeDevice';
@override
late DartDevelopmentService dds;
@override
Future<void> dispose() async {
disposed = true;
}
@override
Future<bool> stopApp(ApplicationPackage? app, {String? userIdentifier}) async {
appStopped = true;
return true;
}
@override
Future<void> takeScreenshot(File outputFile) async {
if (failScreenshot) {
throw Exception();
}
outputFile.writeAsBytesSync(List<int>.generate(1024, (int i) => i));
}
@override
FutureOr<DeviceLogReader> getLogReader({
ApplicationPackage? app,
bool includePastLogs = false,
}) => NoOpDeviceLogReader(name);
@override
DevicePortForwarder portForwarder = const NoOpDevicePortForwarder();
}
class FakeDevFS extends Fake implements DevFS {
@override
DateTime? lastCompiled = DateTime(2000);
@override
PackageConfig? lastPackageConfig = PackageConfig.empty;
@override
List<Uri> sources = <Uri>[];
@override
Uri baseUri = Uri();
@override
Future<void> destroy() async { }
@override
Set<String> assetPathsToEvict = <String>{};
@override
Set<String> shaderPathsToEvict = <String>{};
@override
Set<String> scenePathsToEvict = <String>{};
@override
bool didUpdateFontManifest = false;
UpdateFSReport nextUpdateReport = UpdateFSReport(success: true);
@override
bool hasSetAssetDirectory = false;
@override
Future<Uri> create() async {
return Uri();
}
@override
void resetLastCompiled() {
lastCompiled = null;
}
@override
Future<UpdateFSReport> update({
required Uri mainUri,
required ResidentCompiler generator,
required bool trackWidgetCreation,
required String pathToReload,
required List<Uri> invalidatedFiles,
required PackageConfig packageConfig,
required String dillOutputPath,
required DevelopmentShaderCompiler shaderCompiler,
DevelopmentSceneImporter? sceneImporter,
DevFSWriter? devFSWriter,
String? target,
AssetBundle? bundle,
DateTime? firstBuildTime,
bool bundleFirstUpload = false,
bool fullRestart = false,
String? projectRootPath,
File? dartPluginRegistrant,
}) async {
return nextUpdateReport;
}
}
class FakeShaderCompiler implements DevelopmentShaderCompiler {
const FakeShaderCompiler();
@override
void configureCompiler(TargetPlatform? platform) { }
@override
Future<DevFSContent> recompileShader(DevFSContent inputShader) {
throw UnimplementedError();
}
}