[CLI tool] in flutter test, consider --flavor when validating the cached asset bundle (#150461)

Fixes https://github.com/flutter/flutter/issues/150296

**Context.** `flutter test` has its own code path for writing flutter app [assets](https://docs.flutter.dev/ui/assets/assets-and-images). https://github.com/flutter/flutter/pull/132985 introduced [flavor-conditional asset bundling ](https://docs.flutter.dev/deployment/flavors#conditionally-bundling-assets-based-on-flavor), which lets users control which assets get bundled based on `--flavor`. `--flavor` is supported in `flutter test`.

**Bug and fix.** `--flavor` isn't considered when deciding whether we need to rebuild this asset bundle:

5e448f4ce5/packages/flutter_tools/lib/src/commands/test.dart (L709)

This PR address this by writing the value of `--flavor` to a file in the build directory and checking that when validating the cached asset bundle.
This commit is contained in:
Andrew Kolos 2024-06-20 10:45:09 -07:00 committed by GitHub
parent 0674f46e9f
commit 8e4f704abc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 81 additions and 5 deletions

View file

@ -695,7 +695,7 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
if (build != 0) {
throwToolExit('Error: Failed to build asset bundle');
}
if (_needRebuild(assetBundle.entries)) {
if (_needsRebuild(assetBundle.entries, flavor)) {
await writeBundle(
globals.fs.directory(globals.fs.path.join('build', 'unit_test_assets')),
assetBundle.entries,
@ -708,14 +708,25 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
projectDir: globals.fs.currentDirectory,
buildMode: buildMode,
);
final File cachedFlavorFile = globals.fs.file(
globals.fs.path.join('build', 'test_cache', 'flavor.txt'),
);
if (cachedFlavorFile.existsSync()) {
await cachedFlavorFile.delete();
}
if (flavor != null) {
cachedFlavorFile.createSync(recursive: true);
cachedFlavorFile.writeAsStringSync(flavor);
}
}
}
bool _needRebuild(Map<String, AssetBundleEntry> entries) {
bool _needsRebuild(Map<String, AssetBundleEntry> entries, String? flavor) {
// TODO(andrewkolos): This logic might fail in the future if we change the
// schema of the contents of the asset manifest file and the user does not
// perform a `flutter clean` after upgrading.
// See https://github.com/flutter/flutter/issues/128563.
// schema of the contents of the asset manifest file and the user does not
// perform a `flutter clean` after upgrading.
// See https://github.com/flutter/flutter/issues/128563.
final File manifest = globals.fs.file(globals.fs.path.join('build', 'unit_test_assets', 'AssetManifest.bin'));
if (!manifest.existsSync()) {
return true;
@ -736,6 +747,17 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
return true;
}
}
final File cachedFlavorFile = globals.fs.file(
globals.fs.path.join('build', 'test_cache', 'flavor.txt'),
);
final String? cachedFlavor = cachedFlavorFile.existsSync()
? cachedFlavorFile.readAsStringSync()
: null;
if (cachedFlavor != flavor) {
return true;
}
return false;
}
}

View file

@ -7,6 +7,7 @@ import 'dart:convert';
import 'package:args/command_runner.dart';
import 'package:file/memory.dart';
import 'package:file_testing/file_testing.dart';
import 'package:flutter_tools/src/base/async_guard.dart';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/file_system.dart';
@ -1178,6 +1179,59 @@ dev_dependencies:
DeviceManager: () => _FakeDeviceManager(<Device>[]),
});
testUsingContext('correctly considers --flavor when validating the cached asset bundle', () async {
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
fs.file('vanilla.txt').writeAsStringSync('vanilla');
fs.file('flavorless.txt').writeAsStringSync('flavorless');
fs.file('pubspec.yaml').writeAsStringSync('''
flutter:
assets:
- path: vanilla.txt
flavors:
- vanilla
- flavorless.txt
dev_dependencies:
flutter_test:
sdk: flutter
integration_test:
sdk: flutter''');
final TestCommand testCommand = TestCommand(testRunner: testRunner);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
const List<String> buildArgsFlavorless = <String>[
'test',
'--no-pub',
];
const List<String> buildArgsVanilla = <String>[
'test',
'--no-pub',
'--flavor',
'vanilla',
];
final File builtVanillaAssetFile = fs.file(
fs.path.join('build', 'unit_test_assets', 'vanilla.txt'),
);
final File builtFlavorlessAssetFile = fs.file(
fs.path.join('build', 'unit_test_assets', 'flavorless.txt'),
);
await commandRunner.run(buildArgsVanilla);
await commandRunner.run(buildArgsFlavorless);
expect(builtVanillaAssetFile, isNot(exists));
expect(builtFlavorlessAssetFile, exists);
await commandRunner.run(buildArgsVanilla);
expect(builtVanillaAssetFile, exists);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.empty(),
DeviceManager: () => _FakeDeviceManager(<Device>[]),
});
testUsingContext("Don't build the asset manifest if --no-test-assets if informed", () async {
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);