David McFarland b0fd9b0638 dotnet: add darwin.ICU dependency to AOT test
This dependency seems to have been removed accidentally along with the
framework dependencies in #398707, so the test has been broken since
then.

Fixes: dd0f03a56cf2be99f0904ff1f64e1cc5fb201d43
2025-05-22 18:21:35 -03:00

298 lines
8.8 KiB
Nix

{
stdenv,
stdenvNoCC,
lib,
writeText,
testers,
runCommand,
runCommandWith,
darwin,
expect,
curl,
installShellFiles,
callPackage,
zlib,
swiftPackages,
icu,
lndir,
replaceVars,
nugetPackageHook,
xmlstarlet,
}:
type: unwrapped:
stdenvNoCC.mkDerivation (finalAttrs: {
pname = "${unwrapped.pname}-wrapped";
inherit (unwrapped) version;
meta = {
description = "${unwrapped.meta.description or "dotnet"} (wrapper)";
mainProgram = "dotnet";
inherit (unwrapped.meta)
homepage
license
maintainers
platforms
;
};
src = unwrapped;
dontUnpack = true;
setupHooks =
[
./dotnet-setup-hook.sh
]
++ lib.optional (type == "sdk") (
replaceVars ./dotnet-sdk-setup-hook.sh {
inherit lndir xmlstarlet;
}
);
propagatedSandboxProfile = toString unwrapped.__propagatedSandboxProfile;
propagatedBuildInputs = lib.optional (type == "sdk") nugetPackageHook;
nativeBuildInputs = [ installShellFiles ];
outputs = [ "out" ] ++ lib.optional (unwrapped ? man) "man";
installPhase = ''
runHook preInstall
mkdir -p "$out"/bin "$out"/share
ln -s "$src"/bin/* "$out"/bin
ln -s "$src"/share/dotnet "$out"/share
runHook postInstall
'';
postInstall = ''
# completions snippets taken from https://learn.microsoft.com/en-us/dotnet/core/tools/enable-tab-autocomplete
installShellCompletion --cmd dotnet \
--bash ${./completions/dotnet.bash} \
--zsh ${./completions/dotnet.zsh} \
--fish ${./completions/dotnet.fish}
'';
doInstallCheck = true;
installCheckPhase = ''
runHook preInstallCheck
HOME=$(mktemp -d) $out/bin/dotnet --info
runHook postInstallCheck
'';
postFixup = lib.optionalString (unwrapped ? man) ''
ln -s ${unwrapped.man} "$man"
'';
passthru = unwrapped.passthru // {
inherit unwrapped;
tests =
let
mkDotnetTest =
{
name,
stdenv ? stdenvNoCC,
template,
lang ? null,
usePackageSource ? false,
build,
buildInputs ? [ ],
runtime ? finalAttrs.finalPackage.runtime,
runInputs ? [ ],
run ? null,
runAllowNetworking ? false,
}:
let
sdk = finalAttrs.finalPackage;
built = stdenv.mkDerivation {
name = "${sdk.name}-test-${name}";
buildInputs = [ sdk ] ++ buildInputs ++ lib.optional (usePackageSource) sdk.packages;
# make sure ICU works in a sandbox
propagatedSandboxProfile = toString sdk.__propagatedSandboxProfile;
unpackPhase =
let
unpackArgs =
[ template ]
++ lib.optionals (lang != null) [
"-lang"
lang
];
in
''
mkdir test
cd test
dotnet new ${lib.escapeShellArgs unpackArgs} -o . --no-restore
'';
buildPhase = build;
dontPatchELF = true;
};
in
# older SDKs don't include an embedded FSharp.Core package
if lang == "F#" && lib.versionOlder sdk.version "6.0.400" then
null
else if run == null then
built
else
runCommand "${built.name}-run"
(
{
src = built;
nativeBuildInputs = [ built ] ++ runInputs;
passthru = {
inherit built;
};
}
// lib.optionalAttrs (stdenv.hostPlatform.isDarwin && runAllowNetworking) {
sandboxProfile = ''
(allow network-inbound (local ip))
(allow mach-lookup (global-name "com.apple.FSEvents"))
'';
__darwinAllowLocalNetworking = true;
}
)
(
lib.optionalString (runtime != null) ''
export DOTNET_ROOT=${runtime}/share/dotnet
''
+ run
);
mkConsoleTests =
lang: suffix: output:
let
# Setting LANG to something other than 'C' forces the runtime to search
# for ICU, which will be required in most user environments.
checkConsoleOutput = command: ''
output="$(LANG=C.UTF-8 ${command})"
[[ "$output" =~ ${output} ]] && touch "$out"
'';
mkConsoleTest =
{ name, ... }@args:
mkDotnetTest (
args
// {
name = "console-${name}-${suffix}";
template = "console";
inherit lang;
}
);
in
lib.recurseIntoAttrs {
run = mkConsoleTest {
name = "run";
build = checkConsoleOutput "dotnet run";
};
publish = mkConsoleTest {
name = "publish";
build = "dotnet publish -o $out/bin";
run = checkConsoleOutput "$src/bin/test";
};
self-contained = mkConsoleTest {
name = "self-contained";
usePackageSource = true;
build = "dotnet publish --use-current-runtime --sc -o $out";
runtime = null;
run = checkConsoleOutput "$src/test";
};
single-file = mkConsoleTest {
name = "single-file";
usePackageSource = true;
build = "dotnet publish --use-current-runtime -p:PublishSingleFile=true -o $out/bin";
runtime = null;
run = checkConsoleOutput "$src/bin/test";
};
ready-to-run = mkConsoleTest {
name = "ready-to-run";
usePackageSource = true;
build = "dotnet publish --use-current-runtime -p:PublishReadyToRun=true -o $out/bin";
run = checkConsoleOutput "$src/bin/test";
};
}
// lib.optionalAttrs finalAttrs.finalPackage.hasILCompiler {
aot = mkConsoleTest {
name = "aot";
stdenv = if stdenv.hostPlatform.isDarwin then swiftPackages.stdenv else stdenv;
usePackageSource = true;
buildInputs =
[
zlib
]
++ lib.optional stdenv.hostPlatform.isDarwin [
swiftPackages.swift
darwin.ICU
];
build = ''
dotnet restore -p:PublishAot=true
dotnet publish -p:PublishAot=true -o $out/bin
'';
runtime = null;
run = checkConsoleOutput "$src/bin/test";
};
};
mkWebTest =
lang: suffix:
mkDotnetTest {
name = "web-${suffix}";
template = "web";
inherit lang;
build = "dotnet publish -o $out/bin";
runtime = finalAttrs.finalPackage.aspnetcore;
runInputs = [
expect
curl
];
run = ''
expect <<"EOF"
set status 1
spawn $env(src)/bin/test
proc abort { } { exit 2 }
expect_before default abort
expect -re {Now listening on: ([^\r]+)\r} {
set url $expect_out(1,string)
}
expect "Application started. Press Ctrl+C to shut down."
set output [exec curl -sSf $url]
if {$output != "Hello World!"} {
send_error "Unexpected output: $output\n"
exit 1
}
send \x03
expect_before timeout abort
expect eof
catch wait result
exit [lindex $result 3]
EOF
touch $out
'';
runAllowNetworking = true;
};
in
unwrapped.passthru.tests or { }
// {
version = testers.testVersion {
package = finalAttrs.finalPackage;
command = "HOME=$(mktemp -d) dotnet " + (if type == "sdk" then "--version" else "--info");
};
}
// lib.optionalAttrs (type == "sdk") ({
console = lib.recurseIntoAttrs {
# yes, older SDKs omit the comma
cs = mkConsoleTests "C#" "cs" "Hello,?\\ World!";
fs = mkConsoleTests "F#" "fs" "Hello\\ from\\ F#";
vb = mkConsoleTests "VB" "vb" "Hello,?\\ World!";
};
web = lib.recurseIntoAttrs {
cs = mkWebTest "C#" "cs";
fs = mkWebTest "F#" "fs";
};
});
};
})