flutter/packages/flutter_tools/test/commands.shard/hermetic/precache_test.dart
Jonah Williams 3e838da96a
[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
2020-09-17 15:22:06 -07:00

430 lines
14 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 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/precache.dart';
import 'package:flutter_tools/src/runner/flutter_command.dart';
import 'package:mockito/mockito.dart';
import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/mocks.dart';
import '../../src/testbed.dart';
void main() {
MockCache cache;
Set<DevelopmentArtifact> artifacts;
setUp(() {
cache = MockCache();
// Release lock between test cases.
Cache.releaseLock();
when(cache.isUpToDate()).thenAnswer((Invocation _) => Future<bool>.value(false));
when(cache.updateAll(any)).thenAnswer((Invocation invocation) {
artifacts = invocation.positionalArguments.first as Set<DevelopmentArtifact>;
return Future<void>.value(null);
});
});
testUsingContext('precache should acquire lock', () async {
final Platform platform = FakePlatform(environment: <String, String>{});
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
platform: platform,
featureFlags: TestFeatureFlags(),
);
applyMocksToCommand(command);
await createTestCommandRunner(command).run(const <String>['precache']);
expect(Cache.isLocked(), isTrue);
// Do not throw StateError, lock is acquired.
expect(() => Cache.checkLockAcquired(platform), returnsNormally);
});
testUsingContext('precache should not re-entrantly acquire lock', () async {
final Platform platform = FakePlatform(
operatingSystem: 'windows',
environment: <String, String>{
'FLUTTER_ROOT': 'flutter',
'FLUTTER_ALREADY_LOCKED': 'true',
},
);
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
featureFlags: TestFeatureFlags(),
platform: platform,
);
applyMocksToCommand(command);
await createTestCommandRunner(command).run(const <String>['precache']);
expect(Cache.isLocked(), isFalse);
// Do not throw StateError, acquired reentrantly with FLUTTER_ALREADY_LOCKED.
expect(() => Cache.checkLockAcquired(platform), returnsNormally);
});
testUsingContext('precache downloads web artifacts on dev branch when feature is enabled.', () async {
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
featureFlags: TestFeatureFlags(isWebEnabled: true),
platform: FakePlatform(environment: <String, String>{}),
);
applyMocksToCommand(command);
await createTestCommandRunner(command).run(const <String>['precache', '--web', '--no-android', '--no-ios']);
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.web,
}));
});
testUsingContext('precache does not download web artifacts on dev branch when feature is enabled.', () async {
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
featureFlags: TestFeatureFlags(isWebEnabled: false),
platform: FakePlatform(environment: <String, String>{}),
);
applyMocksToCommand(command);
await createTestCommandRunner(command).run(const <String>['precache', '--web', '--no-android', '--no-ios']);
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
}));
});
testUsingContext('precache downloads macOS artifacts on dev branch when macOS is enabled.', () async {
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
featureFlags: TestFeatureFlags(isMacOSEnabled: true),
platform: FakePlatform(environment: <String, String>{}),
);
applyMocksToCommand(command);
await createTestCommandRunner(command).run(const <String>['precache', '--macos', '--no-android', '--no-ios']);
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.macOS,
}));
});
testUsingContext('precache does not download macOS artifacts on dev branch when feature is enabled.', () async {
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
featureFlags: TestFeatureFlags(isMacOSEnabled: false),
platform: FakePlatform(environment: <String, String>{}),
);
applyMocksToCommand(command);
await createTestCommandRunner(command).run(const <String>['precache', '--macos', '--no-android', '--no-ios']);
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
}));
});
testUsingContext('precache downloads Windows artifacts on dev branch when feature is enabled.', () async {
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
featureFlags: TestFeatureFlags(isWindowsEnabled: true),
platform: FakePlatform(environment: <String, String>{}),
);
applyMocksToCommand(command);
await createTestCommandRunner(command).run(const <String>['precache', '--windows', '--no-android', '--no-ios']);
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.windows,
}));
});
testUsingContext('precache does not download Windows artifacts on dev branch when feature is enabled.', () async {
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
featureFlags: TestFeatureFlags(isWindowsEnabled: false),
platform: FakePlatform(environment: <String, String>{}),
);
applyMocksToCommand(command);
await createTestCommandRunner(command).run(const <String>['precache', '--windows', '--no-android', '--no-ios']);
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
}));
});
testUsingContext('precache downloads Linux artifacts on dev branch when feature is enabled.', () async {
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
featureFlags: TestFeatureFlags(isLinuxEnabled: true),
platform: FakePlatform(environment: <String, String>{}),
);
applyMocksToCommand(command);
await createTestCommandRunner(command).run(const <String>['precache', '--linux', '--no-android', '--no-ios']);
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.linux,
}));
});
testUsingContext('precache does not download Linux artifacts on dev branch when feature is enabled.', () async {
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
featureFlags: TestFeatureFlags(isLinuxEnabled: false),
platform: FakePlatform(environment: <String, String>{}),
);
applyMocksToCommand(command);
await createTestCommandRunner(command).run(const <String>['precache', '--linux', '--no-android', '--no-ios']);
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
}));
});
testUsingContext('precache exits if requesting mismatched artifacts.', () async {
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
featureFlags: TestFeatureFlags(isWebEnabled: false),
platform: FakePlatform(environment: <String, String>{}),
);
applyMocksToCommand(command);
expect(createTestCommandRunner(command).run(const <String>['precache',
'--no-android',
'--android_gen_snapshot',
]), throwsToolExit(message: '--android_gen_snapshot requires --android'));
});
testUsingContext('precache adds artifact flags to requested artifacts', () async {
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
featureFlags: TestFeatureFlags(
isWebEnabled: true,
isLinuxEnabled: true,
isMacOSEnabled: true,
isWindowsEnabled: true,
isFuchsiaEnabled: true,
),
platform: FakePlatform(environment: <String, String>{}),
);
applyMocksToCommand(command);
await createTestCommandRunner(command).run(
const <String>[
'precache',
'--ios',
'--android',
'--web',
'--macos',
'--linux',
'--windows',
'--fuchsia',
'--flutter_runner',
],
);
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.iOS,
DevelopmentArtifact.androidGenSnapshot,
DevelopmentArtifact.androidMaven,
DevelopmentArtifact.androidInternalBuild,
DevelopmentArtifact.web,
DevelopmentArtifact.macOS,
DevelopmentArtifact.linux,
DevelopmentArtifact.windows,
DevelopmentArtifact.fuchsia,
DevelopmentArtifact.flutterRunner,
}));
});
testUsingContext('precache expands android artifacts when the android flag is used', () async {
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
featureFlags: TestFeatureFlags(),
platform: FakePlatform(environment: <String, String>{}),
);
applyMocksToCommand(command);
await createTestCommandRunner(command).run(
const <String>[
'precache',
'--no-ios',
'--android',
],
);
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.androidGenSnapshot,
DevelopmentArtifact.androidMaven,
DevelopmentArtifact.androidInternalBuild,
}));
});
testUsingContext('precache adds artifact flags to requested android artifacts', () async {
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
featureFlags: TestFeatureFlags(),
platform: FakePlatform(environment: <String, String>{}),
);
applyMocksToCommand(command);
await createTestCommandRunner(command).run(
const <String>[
'precache',
'--no-ios',
'--android_gen_snapshot',
'--android_maven',
'--android_internal_build',
],
);
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.androidGenSnapshot,
DevelopmentArtifact.androidMaven,
DevelopmentArtifact.androidInternalBuild,
}));
});
testUsingContext('precache downloads iOS and Android artifacts by default', () async {
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
featureFlags: TestFeatureFlags(),
platform: FakePlatform(environment: <String, String>{}),
);
applyMocksToCommand(command);
await createTestCommandRunner(command).run(
const <String>[
'precache',
],
);
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.iOS,
DevelopmentArtifact.androidGenSnapshot,
DevelopmentArtifact.androidMaven,
DevelopmentArtifact.androidInternalBuild,
}));
});
testUsingContext('precache --all-platforms gets all artifacts', () async {
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
featureFlags: TestFeatureFlags(
isWebEnabled: true,
isLinuxEnabled: true,
isMacOSEnabled: true,
isWindowsEnabled: true,
isFuchsiaEnabled: true,
),
platform: FakePlatform(environment: <String, String>{}),
);
applyMocksToCommand(command);
await createTestCommandRunner(command).run(
const <String>[
'precache',
'--all-platforms',
],
);
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.iOS,
DevelopmentArtifact.androidGenSnapshot,
DevelopmentArtifact.androidMaven,
DevelopmentArtifact.androidInternalBuild,
DevelopmentArtifact.web,
DevelopmentArtifact.macOS,
DevelopmentArtifact.linux,
DevelopmentArtifact.windows,
DevelopmentArtifact.fuchsia,
DevelopmentArtifact.flutterRunner,
}));
});
testUsingContext('precache with default artifacts does not override platform filtering', () async {
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
featureFlags: TestFeatureFlags(),
platform: FakePlatform(environment: <String, String>{}),
);
applyMocksToCommand(command);
await createTestCommandRunner(command).run(
const <String>[
'precache',
],
);
verify(cache.platformOverrideArtifacts = <String>{});
});
testUsingContext('precache with explicit artifact options overrides platform filtering', () async {
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
featureFlags: TestFeatureFlags(
isMacOSEnabled: true,
),
platform: FakePlatform(
operatingSystem: 'windows',
environment: <String, String>{
'FLUTTER_ROOT': 'flutter',
'FLUTTER_ALREADY_LOCKED': 'true',
},
),
);
applyMocksToCommand(command);
await createTestCommandRunner(command).run(
const <String>[
'precache',
'--no-ios',
'--no-android',
'--macos',
],
);
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.macOS,
}));
verify(cache.platformOverrideArtifacts = <String>{'macos'});
});
testUsingContext('precache deletes artifact stampfiles when --force is provided', () async {
when(cache.isUpToDate()).thenAnswer((Invocation _) => Future<bool>.value(true));
final PrecacheCommand command = PrecacheCommand(
cache: cache,
logger: BufferLogger.test(),
featureFlags: TestFeatureFlags(
isMacOSEnabled: true,
),
platform: FakePlatform(environment: <String, String>{}),
);
applyMocksToCommand(command);
await createTestCommandRunner(command).run(const <String>['precache', '--force']);
verify(cache.clearStampFiles()).called(1);
});
}
class MockCache extends Mock implements Cache {}