Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at flake-libs 297 lines 9.0 kB view raw
1{ 2 stdenv, 3 stdenvNoCC, 4 lib, 5 writeText, 6 testers, 7 runCommand, 8 runCommandWith, 9 darwin, 10 expect, 11 curl, 12 installShellFiles, 13 callPackage, 14 zlib, 15 swiftPackages, 16 icu, 17 lndir, 18 replaceVars, 19 nugetPackageHook, 20 xmlstarlet, 21}: 22type: unwrapped: 23stdenvNoCC.mkDerivation (finalAttrs: { 24 pname = "${unwrapped.pname}-wrapped"; 25 inherit (unwrapped) version; 26 27 meta = { 28 description = "${unwrapped.meta.description or "dotnet"} (wrapper)"; 29 mainProgram = "dotnet"; 30 inherit (unwrapped.meta) 31 homepage 32 license 33 maintainers 34 platforms 35 ; 36 }; 37 38 src = unwrapped; 39 dontUnpack = true; 40 41 setupHooks = 42 [ 43 ./dotnet-setup-hook.sh 44 ] 45 ++ lib.optional (type == "sdk") ( 46 replaceVars ./dotnet-sdk-setup-hook.sh { 47 inherit lndir xmlstarlet; 48 } 49 ); 50 51 propagatedSandboxProfile = toString unwrapped.__propagatedSandboxProfile; 52 53 propagatedBuildInputs = lib.optional (type == "sdk") nugetPackageHook; 54 55 nativeBuildInputs = [ installShellFiles ]; 56 57 outputs = [ "out" ] ++ lib.optional (unwrapped ? man) "man"; 58 59 installPhase = '' 60 runHook preInstall 61 mkdir -p "$out"/bin "$out"/share 62 ln -s "$src"/bin/* "$out"/bin 63 ln -s "$src"/share/dotnet "$out"/share 64 runHook postInstall 65 ''; 66 67 postInstall = '' 68 # completions snippets taken from https://learn.microsoft.com/en-us/dotnet/core/tools/enable-tab-autocomplete 69 installShellCompletion --cmd dotnet \ 70 --bash ${./completions/dotnet.bash} \ 71 --zsh ${./completions/dotnet.zsh} \ 72 --fish ${./completions/dotnet.fish} 73 ''; 74 75 doInstallCheck = true; 76 77 installCheckPhase = '' 78 runHook preInstallCheck 79 HOME=$(mktemp -d) $out/bin/dotnet --info 80 runHook postInstallCheck 81 ''; 82 83 postFixup = lib.optionalString (unwrapped ? man) '' 84 ln -s ${unwrapped.man} "$man" 85 ''; 86 87 passthru = unwrapped.passthru // { 88 inherit unwrapped; 89 tests = 90 let 91 mkDotnetTest = 92 { 93 name, 94 stdenv ? stdenvNoCC, 95 template, 96 lang ? null, 97 usePackageSource ? false, 98 build, 99 buildInputs ? [ ], 100 runtime ? finalAttrs.finalPackage.runtime, 101 runInputs ? [ ], 102 run ? null, 103 runAllowNetworking ? false, 104 }: 105 let 106 sdk = finalAttrs.finalPackage; 107 built = stdenv.mkDerivation { 108 name = "${sdk.name}-test-${name}"; 109 buildInputs = [ sdk ] ++ buildInputs ++ lib.optional (usePackageSource) sdk.packages; 110 # make sure ICU works in a sandbox 111 propagatedSandboxProfile = toString sdk.__propagatedSandboxProfile; 112 unpackPhase = 113 let 114 unpackArgs = 115 [ template ] 116 ++ lib.optionals (lang != null) [ 117 "-lang" 118 lang 119 ]; 120 in 121 '' 122 mkdir test 123 cd test 124 dotnet new ${lib.escapeShellArgs unpackArgs} -o . --no-restore 125 ''; 126 buildPhase = build; 127 dontPatchELF = true; 128 }; 129 in 130 # older SDKs don't include an embedded FSharp.Core package 131 if lang == "F#" && lib.versionOlder sdk.version "6.0.400" then 132 null 133 else if run == null then 134 built 135 else 136 runCommand "${built.name}-run" 137 ( 138 { 139 src = built; 140 nativeBuildInputs = [ built ] ++ runInputs; 141 passthru = { 142 inherit built; 143 }; 144 } 145 // lib.optionalAttrs (stdenv.hostPlatform.isDarwin && runAllowNetworking) { 146 sandboxProfile = '' 147 (allow network-inbound (local ip)) 148 (allow mach-lookup (global-name "com.apple.FSEvents")) 149 ''; 150 __darwinAllowLocalNetworking = true; 151 } 152 ) 153 ( 154 lib.optionalString (runtime != null) '' 155 export DOTNET_ROOT=${runtime}/share/dotnet 156 '' 157 + run 158 ); 159 160 mkConsoleTests = 161 lang: suffix: output: 162 let 163 # Setting LANG to something other than 'C' forces the runtime to search 164 # for ICU, which will be required in most user environments. 165 checkConsoleOutput = command: '' 166 output="$(LANG=C.UTF-8 ${command})" 167 [[ "$output" =~ ${output} ]] && touch "$out" 168 ''; 169 170 mkConsoleTest = 171 { name, ... }@args: 172 mkDotnetTest ( 173 args 174 // { 175 name = "console-${name}-${suffix}"; 176 template = "console"; 177 inherit lang; 178 } 179 ); 180 in 181 lib.recurseIntoAttrs { 182 run = mkConsoleTest { 183 name = "run"; 184 build = checkConsoleOutput "dotnet run"; 185 }; 186 187 publish = mkConsoleTest { 188 name = "publish"; 189 build = "dotnet publish -o $out/bin"; 190 run = checkConsoleOutput "$src/bin/test"; 191 }; 192 193 self-contained = mkConsoleTest { 194 name = "self-contained"; 195 usePackageSource = true; 196 build = "dotnet publish --use-current-runtime --sc -o $out"; 197 runtime = null; 198 run = checkConsoleOutput "$src/test"; 199 }; 200 201 single-file = mkConsoleTest { 202 name = "single-file"; 203 usePackageSource = true; 204 build = "dotnet publish --use-current-runtime -p:PublishSingleFile=true -o $out/bin"; 205 runtime = null; 206 run = checkConsoleOutput "$src/bin/test"; 207 }; 208 209 ready-to-run = mkConsoleTest { 210 name = "ready-to-run"; 211 usePackageSource = true; 212 build = "dotnet publish --use-current-runtime -p:PublishReadyToRun=true -o $out/bin"; 213 run = checkConsoleOutput "$src/bin/test"; 214 }; 215 } 216 // lib.optionalAttrs finalAttrs.finalPackage.hasILCompiler { 217 aot = mkConsoleTest { 218 name = "aot"; 219 stdenv = if stdenv.hostPlatform.isDarwin then swiftPackages.stdenv else stdenv; 220 usePackageSource = true; 221 buildInputs = 222 [ 223 zlib 224 ] 225 ++ lib.optional stdenv.hostPlatform.isDarwin [ 226 swiftPackages.swift 227 darwin.ICU 228 ]; 229 build = '' 230 dotnet restore -p:PublishAot=true 231 dotnet publish -p:PublishAot=true -o $out/bin 232 ''; 233 runtime = null; 234 run = checkConsoleOutput "$src/bin/test"; 235 }; 236 }; 237 238 mkWebTest = 239 lang: suffix: 240 mkDotnetTest { 241 name = "web-${suffix}"; 242 template = "web"; 243 inherit lang; 244 build = "dotnet publish -o $out/bin"; 245 runtime = finalAttrs.finalPackage.aspnetcore; 246 runInputs = [ 247 expect 248 curl 249 ]; 250 run = '' 251 expect <<"EOF" 252 set status 1 253 spawn $env(src)/bin/test 254 proc abort { } { exit 2 } 255 expect_before default abort 256 expect -re {Now listening on: ([^\r]+)\r} { 257 set url $expect_out(1,string) 258 } 259 expect "Application started. Press Ctrl+C to shut down." 260 set output [exec curl -sSf $url] 261 if {$output != "Hello World!"} { 262 send_error "Unexpected output: $output\n" 263 exit 1 264 } 265 send \x03 266 expect_before timeout abort 267 expect eof 268 catch wait result 269 exit [lindex $result 3] 270 EOF 271 touch $out 272 ''; 273 runAllowNetworking = true; 274 }; 275 in 276 unwrapped.passthru.tests or { } 277 // { 278 version = testers.testVersion { 279 package = finalAttrs.finalPackage; 280 command = "HOME=$(mktemp -d) dotnet " + (if type == "sdk" then "--version" else "--info"); 281 }; 282 } 283 // lib.optionalAttrs (type == "sdk") ({ 284 console = lib.recurseIntoAttrs { 285 # yes, older SDKs omit the comma 286 cs = mkConsoleTests "C#" "cs" "Hello,?\\ World!"; 287 fs = mkConsoleTests "F#" "fs" "Hello\\ from\\ F#"; 288 vb = mkConsoleTests "VB" "vb" "Hello,?\\ World!"; 289 }; 290 291 web = lib.recurseIntoAttrs { 292 cs = mkWebTest "C#" "cs"; 293 fs = mkWebTest "F#" "fs"; 294 }; 295 }); 296 }; 297})