From 3e838da96a872a226a58b7dfb544532486237d2a Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Thu, 17 Sep 2020 15:22:06 -0700 Subject: [PATCH] [flutter_tools] use flutter tool handler for dwds resources and precache tool pub dependencies (#65814) If the tool is downloaded from a precompiled snapshot, or if the backing source files in the pub cache are deleted, the dwds debugging functionality will break as the client.js file cannot be located. Instead use the PackageConfig to verify that package location, downloading if it is missing. Override the dwds middleware to avoid Isolate.resolvePackageUri Fixes #53644 Fixes #65475 --- .../lib/src/build_runner/devfs_web.dart | 34 ++++++- .../src/build_runner/resident_web_runner.dart | 11 --- packages/flutter_tools/lib/src/cache.dart | 89 +++++++++++++++++- .../lib/src/commands/precache.dart | 2 +- .../flutter_tools/lib/src/context_runner.dart | 3 +- packages/flutter_tools/lib/src/dart/pub.dart | 14 +-- packages/flutter_tools/lib/src/template.dart | 27 +----- .../hermetic/analyze_continuously_test.dart | 2 +- .../hermetic/precache_test.dart | 4 +- .../test/general.shard/cache_test.dart | 93 ++++++++++++++++--- .../resident_web_runner_test.dart | 6 -- packages/flutter_tools/test/src/testbed.dart | 2 +- 12 files changed, 210 insertions(+), 77 deletions(-) diff --git a/packages/flutter_tools/lib/src/build_runner/devfs_web.dart b/packages/flutter_tools/lib/src/build_runner/devfs_web.dart index 90e982631d..2bb3f7ebb0 100644 --- a/packages/flutter_tools/lib/src/build_runner/devfs_web.dart +++ b/packages/flutter_tools/lib/src/build_runner/devfs_web.dart @@ -7,7 +7,7 @@ import 'dart:typed_data'; import 'package:dwds/data/build_result.dart'; import 'package:dwds/dwds.dart'; -import 'package:logging/logging.dart'; +import 'package:logging/logging.dart' as logging; import 'package:meta/meta.dart'; import 'package:mime/mime.dart' as mime; import 'package:package_config/package_config.dart'; @@ -19,6 +19,7 @@ import '../asset.dart'; import '../base/common.dart'; import '../base/file_system.dart'; import '../base/io.dart'; +import '../base/logger.dart'; import '../base/net.dart'; import '../base/platform.dart'; import '../base/utils.dart'; @@ -45,7 +46,7 @@ typedef DwdsLauncher = Future Function({ bool useSseForDebugProxy, bool useSseForDebugBackend, bool serveDevTools, - void Function(Level, String) logWriter, + void Function(logging.Level, String) logWriter, bool verbose, UrlEncoder urlEncoder, bool useFileProvider, @@ -227,6 +228,21 @@ class WebAssetServer implements AssetReader { } return null; } + // Ensure dwds is present and provide middleware to avoid trying to + // load the through the isolate APIs. + final Directory directory = await _loadDwdsDirectory(globals.fs, globals.logger); + final shelf.Middleware middleware = (FutureOr Function(shelf.Request) innerHandler) { + return (shelf.Request request) async { + if (request.url.path.endsWith('dwds/src/injected/client.js')) { + final Uri uri = directory.uri.resolve('src/injected/client.js'); + final String result = await globals.fs.file(uri.toFilePath()).readAsString(); + return shelf.Response.ok(result, headers: { + HttpHeaders.contentTypeHeader: 'application/javascript' + }); + } + return innerHandler(request); + }; + }; // In debug builds, spin up DWDS and the full asset server. final Dwds dwds = await dwdsLauncher( @@ -243,7 +259,7 @@ class WebAssetServer implements AssetReader { useSseForDebugProxy: useSseForDebugProxy, useSseForDebugBackend: useSseForDebugBackend, serveDevTools: false, - logWriter: (Level logLevel, String message) => globals.printTrace(message), + logWriter: (logging.Level logLevel, String message) => globals.printTrace(message), loadStrategy: RequireStrategy( ReloadConfiguration.none, '.lib.js', @@ -258,6 +274,7 @@ class WebAssetServer implements AssetReader { ); shelf.Pipeline pipeline = const shelf.Pipeline(); if (enableDwds) { + pipeline = pipeline.addMiddleware(middleware); pipeline = pipeline.addMiddleware(dwds.middleware); } final shelf.Handler dwdsHandler = pipeline.addHandler(server.handleRequest); @@ -946,3 +963,14 @@ class ReleaseAssetServer { return shelf.Response.notFound(''); } } + +Future _loadDwdsDirectory(FileSystem fileSystem, Logger logger) async { + final String toolPackagePath = fileSystem.path.join( + Cache.flutterRoot, 'packages', 'flutter_tools'); + final String packageFilePath = fileSystem.path.join(toolPackagePath, kPackagesFileName); + final PackageConfig packageConfig = await loadPackageConfigWithLogging( + fileSystem.file(packageFilePath), + logger: logger, + ); + return fileSystem.directory(packageConfig['dwds'].packageUriRoot); +} diff --git a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart index 88f3690bf7..89a8b57d37 100644 --- a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart +++ b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart @@ -22,9 +22,7 @@ import '../base/terminal.dart'; import '../base/utils.dart'; import '../build_info.dart'; import '../build_system/targets/web.dart'; -import '../cache.dart'; import '../dart/language_version.dart'; -import '../dart/pub.dart'; import '../devfs.dart'; import '../device.dart'; import '../features.dart'; @@ -444,15 +442,6 @@ class _ResidentWebRunner extends ResidentWebRunner { try { return await asyncGuard(() async { - // Ensure dwds resources are cached. If the .packages file is missing then - // the client.js script cannot be located by the injected handler in dwds. - // This will result in a NoSuchMethodError thrown by injected_handler.darts - await pub.get( - context: PubContext.pubGet, - directory: globals.fs.path.join(Cache.flutterRoot, 'packages', 'flutter_tools'), - generateSyntheticPackage: false, - ); - final ExpressionCompiler expressionCompiler = debuggingOptions.webEnableExpressionEvaluation ? WebExpressionCompiler(device.generator) diff --git a/packages/flutter_tools/lib/src/cache.dart b/packages/flutter_tools/lib/src/cache.dart index 898c601fe2..b752f047e4 100644 --- a/packages/flutter_tools/lib/src/cache.dart +++ b/packages/flutter_tools/lib/src/cache.dart @@ -4,6 +4,7 @@ import 'package:archive/archive.dart'; import 'package:meta/meta.dart'; +import 'package:package_config/package_config.dart'; import 'android/gradle_utils.dart'; import 'base/common.dart'; @@ -14,8 +15,11 @@ import 'base/net.dart'; import 'base/os.dart' show OperatingSystemUtils; import 'base/platform.dart'; import 'base/process.dart'; +import 'dart/package_map.dart'; +import 'dart/pub.dart'; import 'features.dart'; import 'globals.dart' as globals; +import 'runner/flutter_command.dart'; /// A tag for a set of development artifacts that need to be cached. class DevelopmentArtifact { @@ -126,6 +130,14 @@ class Cache { _artifacts.add(IosUsbArtifacts(artifactName, this)); } _artifacts.add(FontSubsetArtifacts(this)); + _artifacts.add(PubDependencies( + fileSystem: _fileSystem, + logger: _logger, + // flutter root and pub must be lazily initialized to avoid accessing + // before the version is determined. + flutterRoot: () => flutterRoot, + pub: () => pub, + )); } else { _artifacts.addAll(artifacts); } @@ -432,7 +444,14 @@ class Cache { ); } - bool isUpToDate() => _artifacts.every((ArtifactSet artifact) => artifact.isUpToDate()); + Future isUpToDate() async { + for (final ArtifactSet artifact in _artifacts) { + if (!await artifact.isUpToDate()) { + return false; + } + } + return true; + } /// Update the cache to contain all `requiredArtifacts`. Future updateAll(Set requiredArtifacts) async { @@ -444,7 +463,7 @@ class Cache { _logger.printTrace('Artifact $artifact is not required, skipping update.'); continue; } - if (artifact.isUpToDate()) { + if (await artifact.isUpToDate()) { continue; } try { @@ -502,7 +521,7 @@ abstract class ArtifactSet { final DevelopmentArtifact developmentArtifact; /// [true] if the artifact is up to date. - bool isUpToDate(); + Future isUpToDate(); /// The environment variables (if any) required to consume the artifacts. Map get environment { @@ -546,7 +565,7 @@ abstract class CachedArtifact extends ArtifactSet { } @override - bool isUpToDate() { + Future isUpToDate() async { if (!location.existsSync()) { return false; } @@ -592,6 +611,66 @@ abstract class CachedArtifact extends ArtifactSet { Uri _toStorageUri(String path) => Uri.parse('${cache.storageBaseUrl}/$path'); } +/// Ensures that the source files for all of the dependencies for the +/// flutter_tool are present. +/// +/// This does not handle cases wheere the source files are modified or the +/// directory contents are incomplete. +class PubDependencies extends ArtifactSet { + PubDependencies({ + // Needs to be lazy to avoid reading from the cache before the root is initialized. + @required String Function() flutterRoot, + @required FileSystem fileSystem, + @required Logger logger, + @required Pub Function() pub, + }) : _logger = logger, + _fileSystem = fileSystem, + _flutterRoot = flutterRoot, + _pub = pub, + super(DevelopmentArtifact.universal); + + final String Function() _flutterRoot; + final FileSystem _fileSystem; + final Logger _logger; + final Pub Function() _pub; + + @override + Future isUpToDate() async { + final File toolPackageConfig = _fileSystem.file( + _fileSystem.path.join(_flutterRoot(), 'packages', 'flutter_tools', kPackagesFileName), + ); + if (!toolPackageConfig.existsSync()) { + return false; + } + final PackageConfig packageConfig = await loadPackageConfigWithLogging( + toolPackageConfig, + logger: _logger, + throwOnError: false, + ); + if (packageConfig == null || packageConfig == PackageConfig.empty ) { + return false; + } + for (final Package package in packageConfig.packages) { + if (!_fileSystem.directory(package.packageUriRoot).existsSync()) { + return false; + } + } + return true; + } + + @override + String get name => 'pub_dependencies'; + + @override + Future update(ArtifactUpdater artifactUpdater) async { + await _pub().get( + context: PubContext.pubGet, + directory: _fileSystem.path.join(_flutterRoot(), 'packages', 'flutter_tools'), + generateSyntheticPackage: false, + ); + } +} + /// A cached artifact containing fonts used for Material Design. class MaterialFonts extends CachedArtifact { MaterialFonts(Cache cache) : super( @@ -979,7 +1058,7 @@ class AndroidMavenArtifacts extends ArtifactSet { } @override - bool isUpToDate() { + Future isUpToDate() async { // The dependencies are downloaded and cached by Gradle. // The tool doesn't know if the dependencies are already cached at this point. // Therefore, call Gradle to figure this out. diff --git a/packages/flutter_tools/lib/src/commands/precache.dart b/packages/flutter_tools/lib/src/commands/precache.dart index d21c814939..78a5c911e4 100644 --- a/packages/flutter_tools/lib/src/commands/precache.dart +++ b/packages/flutter_tools/lib/src/commands/precache.dart @@ -156,7 +156,7 @@ class PrecacheCommand extends FlutterCommand { requiredArtifacts.add(artifact); } } - if (!_cache.isUpToDate()) { + if (!await _cache.isUpToDate()) { await _cache.updateAll(requiredArtifacts); } else { _logger.printStatus('Already up-to-date.'); diff --git a/packages/flutter_tools/lib/src/context_runner.dart b/packages/flutter_tools/lib/src/context_runner.dart index a8eb4ff903..4bd5da0d64 100644 --- a/packages/flutter_tools/lib/src/context_runner.dart +++ b/packages/flutter_tools/lib/src/context_runner.dart @@ -232,7 +232,8 @@ Future runInContext( botDetector: globals.botDetector, platform: globals.platform, usage: globals.flutterUsage, - toolStampFile: globals.cache.getStampFileFor('flutter_tools'), + // Avoid a circular dependency by making this access lazy. + toolStampFile: () => globals.cache.getStampFileFor('flutter_tools'), ), ShutdownHooks: () => ShutdownHooks(logger: globals.logger), Stdio: () => Stdio(), diff --git a/packages/flutter_tools/lib/src/dart/pub.dart b/packages/flutter_tools/lib/src/dart/pub.dart index ce7d328b80..9bff641361 100644 --- a/packages/flutter_tools/lib/src/dart/pub.dart +++ b/packages/flutter_tools/lib/src/dart/pub.dart @@ -80,7 +80,7 @@ abstract class Pub { @required Platform platform, @required BotDetector botDetector, @required Usage usage, - File toolStampFile, + File Function() toolStampFile, }) = _DefaultPub; /// Runs `pub get`. @@ -141,7 +141,7 @@ class _DefaultPub implements Pub { @required Platform platform, @required BotDetector botDetector, @required Usage usage, - File toolStampFile, + File Function() toolStampFile, }) : _toolStampFile = toolStampFile, _fileSystem = fileSystem, _logger = logger, @@ -159,7 +159,7 @@ class _DefaultPub implements Pub { final Platform _platform; final BotDetector _botDetector; final Usage _usage; - final File _toolStampFile; + final File Function() _toolStampFile; @override Future get({ @@ -399,10 +399,10 @@ class _DefaultPub implements Pub { if (pubSpecYaml.lastModifiedSync().isAfter(dotPackagesLastModified)) { return true; } - - if (_toolStampFile != null && - _toolStampFile.existsSync() && - _toolStampFile.lastModifiedSync().isAfter(dotPackagesLastModified)) { + final File toolStampFile = _toolStampFile != null ? _toolStampFile() : null; + if (toolStampFile != null && + toolStampFile.existsSync() && + toolStampFile.lastModifiedSync().isAfter(dotPackagesLastModified)) { return true; } return false; diff --git a/packages/flutter_tools/lib/src/template.dart b/packages/flutter_tools/lib/src/template.dart index 094321b417..dcbc6ff728 100644 --- a/packages/flutter_tools/lib/src/template.dart +++ b/packages/flutter_tools/lib/src/template.dart @@ -291,36 +291,13 @@ Future _templateImageDirectory(String name, FileSystem fileSystem, Lo final String toolPackagePath = fileSystem.path.join( Cache.flutterRoot, 'packages', 'flutter_tools'); final String packageFilePath = fileSystem.path.join(toolPackagePath, kPackagesFileName); - // Ensure that .packgaes is present. - if (!fileSystem.file(packageFilePath).existsSync()) { - await _ensurePackageDependencies(toolPackagePath, pub); - } - PackageConfig packageConfig = await loadPackageConfigWithLogging( + final PackageConfig packageConfig = await loadPackageConfigWithLogging( fileSystem.file(packageFilePath), logger: logger, ); - Uri imagePackageLibDir = packageConfig['flutter_template_images']?.packageUriRoot; - // Ensure that the template image package is present. - if (imagePackageLibDir == null || !fileSystem.directory(imagePackageLibDir).existsSync()) { - await _ensurePackageDependencies(toolPackagePath, pub); - packageConfig = await loadPackageConfigWithLogging( - fileSystem.file(packageFilePath), - logger: logger, - ); - imagePackageLibDir = packageConfig['flutter_template_images']?.packageUriRoot; - } + final Uri imagePackageLibDir = packageConfig['flutter_template_images']?.packageUriRoot; return fileSystem.directory(imagePackageLibDir) .parent .childDirectory('templates') .childDirectory(name); } - -// Runs 'pub get' for the given path to ensure that .packages is created and -// all dependencies are present. -Future _ensurePackageDependencies(String packagePath, Pub pub) async { - await pub.get( - context: PubContext.pubGet, - directory: packagePath, - generateSyntheticPackage: false, - ); -} diff --git a/packages/flutter_tools/test/commands.shard/hermetic/analyze_continuously_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/analyze_continuously_test.dart index 06dd6aeb71..badc6932cb 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/analyze_continuously_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/analyze_continuously_test.dart @@ -117,7 +117,7 @@ void main() { platform: const LocalPlatform(), usage: globals.flutterUsage, botDetector: globals.botDetector, - toolStampFile: globals.fs.file('test'), + toolStampFile: () => globals.fs.file('test'), ); await pub.get( context: PubContext.flutterTests, diff --git a/packages/flutter_tools/test/commands.shard/hermetic/precache_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/precache_test.dart index b4dcd818fe..9b79ff0724 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/precache_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/precache_test.dart @@ -23,7 +23,7 @@ void main() { // Release lock between test cases. Cache.releaseLock(); - when(cache.isUpToDate()).thenReturn(false); + when(cache.isUpToDate()).thenAnswer((Invocation _) => Future.value(false)); when(cache.updateAll(any)).thenAnswer((Invocation invocation) { artifacts = invocation.positionalArguments.first as Set; return Future.value(null); @@ -410,7 +410,7 @@ void main() { }); testUsingContext('precache deletes artifact stampfiles when --force is provided', () async { - when(cache.isUpToDate()).thenReturn(true); + when(cache.isUpToDate()).thenAnswer((Invocation _) => Future.value(true)); final PrecacheCommand command = PrecacheCommand( cache: cache, logger: BufferLogger.test(), diff --git a/packages/flutter_tools/test/general.shard/cache_test.dart b/packages/flutter_tools/test/general.shard/cache_test.dart index 111bdc4cb2..427f14c16e 100644 --- a/packages/flutter_tools/test/general.shard/cache_test.dart +++ b/packages/flutter_tools/test/general.shard/cache_test.dart @@ -13,6 +13,7 @@ import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/cache.dart'; +import 'package:flutter_tools/src/dart/pub.dart'; import 'package:flutter_tools/src/globals.dart' as globals; import 'package:meta/meta.dart'; import 'package:mockito/mockito.dart'; @@ -137,25 +138,25 @@ void main() { ProcessManager: () => FakeProcessManager.any(), }); - testUsingContext('should not be up to date, if some cached artifact is not', () { + testUsingContext('should not be up to date, if some cached artifact is not', () async { final CachedArtifact artifact1 = MockCachedArtifact(); final CachedArtifact artifact2 = MockCachedArtifact(); - when(artifact1.isUpToDate()).thenReturn(true); - when(artifact2.isUpToDate()).thenReturn(false); + when(artifact1.isUpToDate()).thenAnswer((Invocation _) => Future.value(true)); + when(artifact2.isUpToDate()).thenAnswer((Invocation _) => Future.value(false)); final Cache cache = Cache(artifacts: [artifact1, artifact2]); - expect(cache.isUpToDate(), isFalse); + expect(await cache.isUpToDate(), isFalse); }, overrides: { ProcessManager: () => FakeProcessManager.any(), FileSystem: () => MemoryFileSystem.test(), }); - testUsingContext('should be up to date, if all cached artifacts are', () { + testUsingContext('should be up to date, if all cached artifacts are', () async { final CachedArtifact artifact1 = MockCachedArtifact(); final CachedArtifact artifact2 = MockCachedArtifact(); - when(artifact1.isUpToDate()).thenReturn(true); - when(artifact2.isUpToDate()).thenReturn(true); + when(artifact1.isUpToDate()).thenAnswer((Invocation _) => Future.value(true)); + when(artifact2.isUpToDate()).thenAnswer((Invocation _) => Future.value(true)); final Cache cache = Cache(artifacts: [artifact1, artifact2]); - expect(cache.isUpToDate(), isTrue); + expect(await cache.isUpToDate(), isTrue); }, overrides: { ProcessManager: () => FakeProcessManager.any(), FileSystem: () => MemoryFileSystem.test(), @@ -164,8 +165,8 @@ void main() { testUsingContext('should update cached artifacts which are not up to date', () async { final CachedArtifact artifact1 = MockCachedArtifact(); final CachedArtifact artifact2 = MockCachedArtifact(); - when(artifact1.isUpToDate()).thenReturn(true); - when(artifact2.isUpToDate()).thenReturn(false); + when(artifact1.isUpToDate()).thenAnswer((Invocation _) => Future.value(true)); + when(artifact2.isUpToDate()).thenAnswer((Invocation _) => Future.value(false)); final Cache cache = Cache(artifacts: [artifact1, artifact2]); await cache.updateAll({ null, @@ -206,8 +207,8 @@ void main() { testUsingContext('failed storage.googleapis.com download shows China warning', () async { final CachedArtifact artifact1 = MockCachedArtifact(); final CachedArtifact artifact2 = MockCachedArtifact(); - when(artifact1.isUpToDate()).thenReturn(false); - when(artifact2.isUpToDate()).thenReturn(false); + when(artifact1.isUpToDate()).thenAnswer((Invocation _) => Future.value(false)); + when(artifact2.isUpToDate()).thenAnswer((Invocation _) => Future.value(false)); final MockInternetAddress address = MockInternetAddress(); when(address.host).thenReturn('storage.googleapis.com'); when(artifact1.update(any)).thenThrow(SocketException( @@ -317,7 +318,7 @@ void main() { ..createSync(recursive: true); when(mockCache.getRoot()).thenReturn(cacheRoot); final AndroidMavenArtifacts mavenArtifacts = AndroidMavenArtifacts(mockCache); - expect(mavenArtifacts.isUpToDate(), isFalse); + expect(await mavenArtifacts.isUpToDate(), isFalse); final Directory gradleWrapperDir = globals.fs.systemTempDirectory.createTempSync('flutter_cache_test_gradle_wrapper.'); when(mockCache.getArtifactDirectory('gradle_wrapper')).thenReturn(gradleWrapperDir); @@ -340,7 +341,7 @@ void main() { await mavenArtifacts.update(MockArtifactUpdater()); - expect(mavenArtifacts.isUpToDate(), isFalse); + expect(await mavenArtifacts.isUpToDate(), isFalse); }, overrides: { Cache: () => mockCache, FileSystem: () => memoryFileSystem, @@ -660,6 +661,69 @@ void main() { expect(cache.getStampFor('foo'), 'ABC'); }); + + testWithoutContext('PubDependencies needs to be updated if the package config' + ' file or the source directories are missing', () async { + final BufferLogger logger = BufferLogger.test(); + final MemoryFileSystem fileSystem = MemoryFileSystem.test(); + final PubDependencies pubDependencies = PubDependencies( + flutterRoot: () => '', + fileSystem: fileSystem, + logger: logger, + pub: () => MockPub(), + ); + + expect(await pubDependencies.isUpToDate(), false); // no package config + + fileSystem.file('packages/flutter_tools/.packages') + ..createSync(recursive: true) + ..writeAsStringSync('\n'); + fileSystem.file('packages/flutter_tools/.dart_tool/package_config.json') + ..createSync(recursive: true) + ..writeAsStringSync(''' +{ + "configVersion": 2, + "packages": [ + { + "name": "example", + "rootUri": "file:///.pub-cache/hosted/pub.dartlang.org/example-7.0.0", + "packageUri": "lib/", + "languageVersion": "2.7" + } + ], + "generated": "2020-09-15T20:29:20.691147Z", + "generator": "pub", + "generatorVersion": "2.10.0-121.0.dev" +} +'''); + + expect(await pubDependencies.isUpToDate(), false); // dependencies are missing. + + fileSystem.file('.pub-cache/hosted/pub.dartlang.org/example-7.0.0/lib/foo.dart') + .createSync(recursive: true); + + expect(await pubDependencies.isUpToDate(), true); + }); + + testWithoutContext('PubDependencies updates via pub get', () async { + final BufferLogger logger = BufferLogger.test(); + final MemoryFileSystem fileSystem = MemoryFileSystem.test(); + final MockPub pub = MockPub(); + final PubDependencies pubDependencies = PubDependencies( + flutterRoot: () => '', + fileSystem: fileSystem, + logger: logger, + pub: () => pub, + ); + + await pubDependencies.update(MockArtifactUpdater()); + + verify(pub.get( + context: PubContext.pubGet, + directory: 'packages/flutter_tools', + generateSyntheticPackage: false, + )).called(1); + }); } class FakeCachedArtifact extends EngineCachedArtifact { @@ -724,6 +788,7 @@ class MockInternetAddress extends Mock implements InternetAddress {} class MockCache extends Mock implements Cache {} class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {} class MockVersionedPackageResolver extends Mock implements VersionedPackageResolver {} +class MockPub extends Mock implements Pub {} class FakeCache extends Cache { FakeCache({ @required Logger logger, diff --git a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart index 78494a4183..b902c7c205 100644 --- a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart +++ b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart @@ -294,12 +294,6 @@ void main() { verify(mockAppConnection.runMain()).called(1); verify(status.stop()).called(1); - verify(pub.get( - context: PubContext.pubGet, - directory: anyNamed('directory'), - generateSyntheticPackage: false, - )).called(1); - expect(bufferLogger.statusText, contains('Debug service listening on ws://127.0.0.1/abcd/')); expect(debugConnectionInfo.wsUri.toString(), 'ws://127.0.0.1/abcd/'); }, overrides: { diff --git a/packages/flutter_tools/test/src/testbed.dart b/packages/flutter_tools/test/src/testbed.dart index 0914900a23..4a4e2a9bfe 100644 --- a/packages/flutter_tools/test/src/testbed.dart +++ b/packages/flutter_tools/test/src/testbed.dart @@ -931,7 +931,7 @@ class FakeCache implements Cache { } @override - bool isUpToDate() { + Future isUpToDate() async { return true; }