blob: df1782c15068be4d9fae9f7cb98038ee561e9b41 [file] [log] [blame] [edit]
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. 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:io';
import 'package:meta/meta.dart' show isTest;
import 'package:test/test.dart';
import 'package:yaml/yaml.dart';
import '../architecture.dart';
import '../build_mode.dart';
import '../c_compiler_config.dart';
import '../code_assets/code_asset.dart';
import '../data_assets/data_asset.dart';
import '../ios_sdk.dart';
import '../link_mode_preference.dart';
import '../os.dart';
import 'build_config.dart';
import 'build_output.dart';
@isTest
Future<void> testBuildHook({
required String description,
// ignore: inference_failure_on_function_return_type
required Function(List<String> arguments) mainMethod,
required void Function(BuildConfig config, BuildOutput output) check,
BuildMode? buildMode,
Architecture? targetArchitecture,
OS? targetOS,
IOSSdk? targetIOSSdk,
int? targetIOSVersion,
int? targetMacOSVersion,
int? targetAndroidNdkApi,
CCompilerConfig? cCompiler,
LinkModePreference? linkModePreference,
required Iterable<String> supportedAssetTypes,
bool? linkingEnabled,
}) async {
test(
description,
() async {
final tempDir = await _tempDirForTest();
final outputDirectory = tempDir.resolve('output/');
await Directory.fromUri(outputDirectory).create();
final outputDirectoryShared = tempDir.resolve('output_shared/');
await Directory.fromUri(outputDirectory).create();
final buildConfig = BuildConfig.build(
outputDirectory: outputDirectory,
outputDirectoryShared: outputDirectoryShared,
packageName: await _packageName(),
packageRoot: Directory.current.uri,
buildMode: buildMode ?? BuildMode.release,
targetArchitecture: targetArchitecture ?? Architecture.current,
targetOS: targetOS ?? OS.current,
linkModePreference: linkModePreference ?? LinkModePreference.dynamic,
linkingEnabled: linkingEnabled ?? true,
cCompiler: cCompiler,
supportedAssetTypes: supportedAssetTypes,
targetAndroidNdkApi: targetAndroidNdkApi,
targetIOSSdk: targetIOSSdk,
targetIOSVersion: targetIOSVersion,
targetMacOSVersion: targetMacOSVersion,
) as BuildConfigImpl;
final buildConfigUri = tempDir.resolve('build_config.json');
await _writeBuildConfig(buildConfigUri, buildConfig);
await mainMethod(['--config=${buildConfigUri.toFilePath()}']);
final hookOutput = await _readOutput(buildConfig) as BuildOutput;
check(buildConfig, hookOutput);
final allEncodedAssets = [
...hookOutput.encodedAssets,
...hookOutput.encodedAssetsForLinking.values.expand((e) => e)
];
for (final asset in allEncodedAssets) {
expect(buildConfig.supportedAssetTypes, contains(asset.type));
}
for (final asset in hookOutput.dataAssets.all) {
final file = File.fromUri(asset.file);
expect(await file.exists(), true);
}
for (final asset in hookOutput.codeAssets.all) {
if (asset.file != null) {
final file = File.fromUri(asset.file!);
expect(await file.exists(), true);
}
}
},
);
}
Future<void> _writeBuildConfig(
Uri buildConfigUri,
BuildConfigImpl buildConfig,
) async {
final file = File.fromUri(buildConfigUri);
await file.create();
file.writeAsStringSync(buildConfig.toJsonString());
}
Future<HookOutputImpl> _readOutput(BuildConfigImpl buildConfig) async {
final hookOutput = HookOutputImpl.fromJsonString(
await File.fromUri(buildConfig.outputFile).readAsString());
return hookOutput;
}
Future<String> _packageName() async {
final uri = Directory.current.uri.resolve('pubspec.yaml');
final readAsString = await File.fromUri(uri).readAsString();
final yaml = loadYaml(readAsString) as YamlMap;
return yaml['name'] as String;
}
const keepTempKey = 'KEEP_TEMPORARY_DIRECTORIES';
Future<Uri> _tempDirForTest({String? prefix, bool keepTemp = false}) async {
final tempDir = await Directory.systemTemp.createTemp(prefix);
// Deal with Windows temp folder aliases.
final tempUri =
Directory(await tempDir.resolveSymbolicLinks()).uri.normalizePath();
if ((!Platform.environment.containsKey(keepTempKey) ||
Platform.environment[keepTempKey]!.isEmpty) &&
!keepTemp) {
addTearDown(() => tempDir.delete(recursive: true));
}
return tempUri;
}