Unverified Commit b275e111 authored by chunhtai's avatar chunhtai Committed by GitHub

fix issue 12999: Make assets available during tests (#31207)

parent e69a8a15
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:typed_data';
import 'dart:ui' as ui; import 'dart:ui' as ui;
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
...@@ -16,6 +17,7 @@ import 'package:flutter/widgets.dart'; ...@@ -16,6 +17,7 @@ import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart' show TestWindow; import 'package:flutter_test/flutter_test.dart' show TestWindow;
import 'package:quiver/testing/async.dart'; import 'package:quiver/testing/async.dart';
import 'package:quiver/time.dart'; import 'package:quiver/time.dart';
import 'package:path/path.dart' as path;
import 'package:test_api/test_api.dart' as test_package; import 'package:test_api/test_api.dart' as test_package;
import 'package:stack_trace/stack_trace.dart' as stack_trace; import 'package:stack_trace/stack_trace.dart' as stack_trace;
import 'package:vector_math/vector_math_64.dart'; import 'package:vector_math/vector_math_64.dart';
...@@ -707,6 +709,7 @@ class AutomatedTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding { ...@@ -707,6 +709,7 @@ class AutomatedTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
super.initInstances(); super.initInstances();
window.onBeginFrame = null; window.onBeginFrame = null;
window.onDrawFrame = null; window.onDrawFrame = null;
_mockFlutterAssets();
} }
FakeAsync _currentFakeAsync; // set in runTest; cleared in postTest FakeAsync _currentFakeAsync; // set in runTest; cleared in postTest
...@@ -736,6 +739,40 @@ class AutomatedTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding { ...@@ -736,6 +739,40 @@ class AutomatedTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
@override @override
int get microtaskCount => _currentFakeAsync.microtaskCount; int get microtaskCount => _currentFakeAsync.microtaskCount;
static Set<String> _allowedKeys;
void _mockFlutterAssets() {
if (!Platform.environment.containsKey('UNIT_TEST_ASSETS')) {
return;
}
final String assetFolderPath = Platform.environment['UNIT_TEST_ASSETS'];
_ensureInitialized(assetFolderPath);
BinaryMessages.setMockMessageHandler('flutter/assets', (ByteData message) {
final String key = utf8.decode(message.buffer.asUint8List());
if (_allowedKeys.contains(key)) {
final File asset = File(path.join(assetFolderPath, key));
final Uint8List encoded = Uint8List.fromList(asset.readAsBytesSync());
return Future<ByteData>.value(encoded.buffer.asByteData());
}
});
}
void _ensureInitialized(String assetFolderPath) {
if (_allowedKeys == null) {
final File manifestFile = File(
path.join(assetFolderPath, 'AssetManifest.json'));
final Map<String, dynamic> manifest = json.decode(
manifestFile.readAsStringSync());
_allowedKeys = <String>{
'AssetManifest.json',
};
for (List<dynamic> value in manifest.values) {
final List<String> strList = List<String>.from(value);
_allowedKeys.addAll(strList);
}
}
}
@override @override
Future<void> pump([ Duration duration, EnginePhase newPhase = EnginePhase.sendSemanticsUpdate ]) { Future<void> pump([ Duration duration, EnginePhase newPhase = EnginePhase.sendSemanticsUpdate ]) {
return TestAsyncUtils.guard<void>(() { return TestAsyncUtils.guard<void>(() {
......
...@@ -5,9 +5,11 @@ ...@@ -5,9 +5,11 @@
import 'dart:async'; import 'dart:async';
import 'dart:math' as math; import 'dart:math' as math;
import '../asset.dart';
import '../base/common.dart'; import '../base/common.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../base/platform.dart'; import '../base/platform.dart';
import '../bundle.dart';
import '../cache.dart'; import '../cache.dart';
import '../codegen.dart'; import '../codegen.dart';
import '../dart/pub.dart'; import '../dart/pub.dart';
...@@ -18,7 +20,6 @@ import '../test/coverage_collector.dart'; ...@@ -18,7 +20,6 @@ import '../test/coverage_collector.dart';
import '../test/event_printer.dart'; import '../test/event_printer.dart';
import '../test/runner.dart'; import '../test/runner.dart';
import '../test/watcher.dart'; import '../test/watcher.dart';
class TestCommand extends FastFlutterCommand { class TestCommand extends FastFlutterCommand {
TestCommand({ bool verboseHelp = false }) { TestCommand({ bool verboseHelp = false }) {
requiresPubspecYaml(); requiresPubspecYaml();
...@@ -83,7 +84,14 @@ class TestCommand extends FastFlutterCommand { ...@@ -83,7 +84,14 @@ class TestCommand extends FastFlutterCommand {
abbr: 'j', abbr: 'j',
defaultsTo: math.max<int>(1, platform.numberOfProcessors - 2).toString(), defaultsTo: math.max<int>(1, platform.numberOfProcessors - 2).toString(),
help: 'The number of concurrent test processes to run.', help: 'The number of concurrent test processes to run.',
valueHelp: 'jobs'); valueHelp: 'jobs'
)
..addFlag('test-assets',
defaultsTo: true,
negatable: true,
help: 'Whether to build the assets bundle for testing.\n'
'Consider using --no-test-assets if assets are not required.',
);
} }
@override @override
...@@ -110,6 +118,10 @@ class TestCommand extends FastFlutterCommand { ...@@ -110,6 +118,10 @@ class TestCommand extends FastFlutterCommand {
if (shouldRunPub) { if (shouldRunPub) {
await pubGet(context: PubContext.getVerifyContext(name), skipPubspecYamlCheck: true); await pubGet(context: PubContext.getVerifyContext(name), skipPubspecYamlCheck: true);
} }
final bool buildTestAssets = argResults['test-assets'];
if (buildTestAssets) {
await _buildTestAsset();
}
final List<String> names = argResults['name']; final List<String> names = argResults['name'];
final List<String> plainNames = argResults['plain-name']; final List<String> plainNames = argResults['plain-name'];
final FlutterProject flutterProject = await FlutterProject.current(); final FlutterProject flutterProject = await FlutterProject.current();
...@@ -195,6 +207,7 @@ class TestCommand extends FastFlutterCommand { ...@@ -195,6 +207,7 @@ class TestCommand extends FastFlutterCommand {
trackWidgetCreation: argResults['track-widget-creation'], trackWidgetCreation: argResults['track-widget-creation'],
updateGoldens: argResults['update-goldens'], updateGoldens: argResults['update-goldens'],
concurrency: jobs, concurrency: jobs,
buildTestAssets: buildTestAssets,
flutterProject: flutterProject, flutterProject: flutterProject,
); );
...@@ -208,6 +221,15 @@ class TestCommand extends FastFlutterCommand { ...@@ -208,6 +221,15 @@ class TestCommand extends FastFlutterCommand {
throwToolExit(null); throwToolExit(null);
return const FlutterCommandResult(ExitStatus.success); return const FlutterCommandResult(ExitStatus.success);
} }
Future<void> _buildTestAsset() async {
final AssetBundle assetBundle = AssetBundleFactory.instance.createBundle();
final int build = await assetBundle.build();
if (build != 0) {
throwToolExit('Error: Failed to build asset bundle');
}
await writeBundle(fs.directory(fs.path.join('build', 'unit_test_assets')), assetBundle.entries);
}
} }
Iterable<String> _findTests(Directory directory) { Iterable<String> _findTests(Directory directory) {
......
...@@ -88,6 +88,7 @@ void installHook({ ...@@ -88,6 +88,7 @@ void installHook({
Map<String, String> precompiledDillFiles, Map<String, String> precompiledDillFiles,
bool trackWidgetCreation = false, bool trackWidgetCreation = false,
bool updateGoldens = false, bool updateGoldens = false,
bool buildTestAssets = false,
int observatoryPort, int observatoryPort,
InternetAddressType serverType = InternetAddressType.IPv4, InternetAddressType serverType = InternetAddressType.IPv4,
Uri projectRootDirectory, Uri projectRootDirectory,
...@@ -110,6 +111,7 @@ void installHook({ ...@@ -110,6 +111,7 @@ void installHook({
precompiledDillFiles: precompiledDillFiles, precompiledDillFiles: precompiledDillFiles,
trackWidgetCreation: trackWidgetCreation, trackWidgetCreation: trackWidgetCreation,
updateGoldens: updateGoldens, updateGoldens: updateGoldens,
buildTestAssets: buildTestAssets,
projectRootDirectory: projectRootDirectory, projectRootDirectory: projectRootDirectory,
flutterProject: flutterProject, flutterProject: flutterProject,
icudtlPath: icudtlPath, icudtlPath: icudtlPath,
...@@ -390,6 +392,7 @@ class _FlutterPlatform extends PlatformPlugin { ...@@ -390,6 +392,7 @@ class _FlutterPlatform extends PlatformPlugin {
this.precompiledDillFiles, this.precompiledDillFiles,
this.trackWidgetCreation, this.trackWidgetCreation,
this.updateGoldens, this.updateGoldens,
this.buildTestAssets,
this.projectRootDirectory, this.projectRootDirectory,
this.flutterProject, this.flutterProject,
this.icudtlPath, this.icudtlPath,
...@@ -407,6 +410,7 @@ class _FlutterPlatform extends PlatformPlugin { ...@@ -407,6 +410,7 @@ class _FlutterPlatform extends PlatformPlugin {
final Map<String, String> precompiledDillFiles; final Map<String, String> precompiledDillFiles;
final bool trackWidgetCreation; final bool trackWidgetCreation;
final bool updateGoldens; final bool updateGoldens;
final bool buildTestAssets;
final Uri projectRootDirectory; final Uri projectRootDirectory;
final FlutterProject flutterProject; final FlutterProject flutterProject;
final String icudtlPath; final String icudtlPath;
...@@ -977,6 +981,10 @@ class _FlutterPlatform extends PlatformPlugin { ...@@ -977,6 +981,10 @@ class _FlutterPlatform extends PlatformPlugin {
'FONTCONFIG_FILE': _fontConfigFile.path, 'FONTCONFIG_FILE': _fontConfigFile.path,
'SERVER_PORT': serverPort.toString(), 'SERVER_PORT': serverPort.toString(),
}; };
if (buildTestAssets) {
environment['UNIT_TEST_ASSETS'] = fs.path.join(
flutterProject.directory.path, 'build', 'unit_test_assets');
}
return processManager.start(command, environment: environment); return processManager.start(command, environment: environment);
} }
......
...@@ -35,6 +35,7 @@ Future<int> runTests( ...@@ -35,6 +35,7 @@ Future<int> runTests(
bool updateGoldens = false, bool updateGoldens = false,
TestWatcher watcher, TestWatcher watcher,
@required int concurrency, @required int concurrency,
bool buildTestAssets = false,
FlutterProject flutterProject, FlutterProject flutterProject,
String icudtlPath, String icudtlPath,
Directory coverageDirectory, Directory coverageDirectory,
...@@ -83,6 +84,7 @@ Future<int> runTests( ...@@ -83,6 +84,7 @@ Future<int> runTests(
precompiledDillFiles: precompiledDillFiles, precompiledDillFiles: precompiledDillFiles,
trackWidgetCreation: trackWidgetCreation, trackWidgetCreation: trackWidgetCreation,
updateGoldens: updateGoldens, updateGoldens: updateGoldens,
buildTestAssets: buildTestAssets,
projectRootDirectory: fs.currentDirectory.uri, projectRootDirectory: fs.currentDirectory.uri,
flutterProject: flutterProject, flutterProject: flutterProject,
icudtlPath: icudtlPath, icudtlPath: icudtlPath,
......
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