blob: ee08fe490fc226e080c928f6c807447f49a44803 [file] [log] [blame]
// Copyright (c) 2025, 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:convert';
import 'dart:io';
import 'package:code_assets/code_assets.dart';
import 'package:hooks/hooks.dart';
import 'package:native_test_helpers/native_test_helpers.dart';
import 'package:test/test.dart';
import '../hook/build.dart' as hook;
void main() {
test(
'build hook decodes percent-encoded package root paths',
() async {
final tempDir = await Directory.systemTemp.createTemp(
'objective_c_hook_path',
);
addTearDown(() => tempDir.delete(recursive: true));
final realPackageRoot = findPackageRoot('objective_c');
const rootDirName = 'pkg%47root';
final rootDir = Directory('${tempDir.path}/$rootDirName');
await rootDir.create();
final symlinkPath = '${rootDir.path}/objective_c';
await Link(symlinkPath).create(realPackageRoot.toFilePath());
final symlinkDir = Directory(symlinkPath);
final encodedPath = symlinkPath.replaceAll('%', '%25');
final encodedPackageRoot = Uri.parse(
'file:///${encodedPath.substring(1)}/',
);
expect(encodedPackageRoot.toString(), contains('%2547'));
final compilerLog = tempDir.uri.resolve('compiler_args.txt').toFilePath();
File(compilerLog).writeAsStringSync('');
final compilerScript = tempDir.uri.resolve('clang').toFilePath();
File(compilerScript).writeAsStringSync('''#!/bin/sh
if [ "\$1" = "--version" ]; then
echo "Apple clang version 15.0.0"
exit 0
fi
log="$compilerLog"
out=""
prev=""
for arg in "\$@"; do
if [ "\$prev" = "-o" ]; then
out="\$arg"
fi
prev="\$arg"
printf '%s\\n' "\$arg" >> "\$log"
done
if [ -n "\$out" ]; then
mkdir -p "\$(dirname "\$out")"
: > "\$out"
fi
exit 0
''');
Process.runSync('chmod', ['+x', compilerScript]);
final outputDirectoryShared = tempDir.uri.resolve('output_shared/');
await Directory.fromUri(outputDirectoryShared).create();
final outputFile = tempDir.uri.resolve('output.json');
final inputBuilder = BuildInputBuilder()
..setupShared(
packageRoot: encodedPackageRoot,
packageName: 'objective_c',
outputFile: outputFile,
outputDirectoryShared: outputDirectoryShared,
)
..setupBuildInput()
..config.setupBuild(linkingEnabled: false)
..addExtension(
CodeAssetExtension(
targetArchitecture: Architecture.current,
targetOS: OS.macOS,
linkModePreference: LinkModePreference.dynamic,
macOS: MacOSCodeConfig(targetVersion: 13),
cCompiler: CCompilerConfig(
compiler: Uri.file(compilerScript),
linker: Uri.file(compilerScript),
archiver: Uri.file(compilerScript),
),
),
);
final input = inputBuilder.build();
final inputFile = tempDir.uri.resolve('input.json');
File.fromUri(inputFile).writeAsStringSync(json.encode(input.json));
final originalCwd = Directory.current;
Directory.current = symlinkDir;
try {
await (hook.main as dynamic)(['--config=${inputFile.toFilePath()}']);
} finally {
Directory.current = originalCwd;
}
final logLines = File(compilerLog).readAsLinesSync();
final decodedUtil = '$symlinkPath/test/util.c';
expect(logLines, contains(decodedUtil));
expect(logLines.any((line) => line.contains('%2547')), isFalse);
},
skip: !Platform.isMacOS ? 'Requires macOS' : null,
);
}