nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at python-updates 668 lines 21 kB view raw
1# To run these tests: 2# nix-build -A tests.stdenv 3 4{ 5 stdenv, 6 pkgs, 7 lib, 8 testers, 9}: 10 11let 12 # tests can be based on builtins.derivation and stage0 or bootstrapTools directly to minimize rebuilds 13 # see test 'make-symlinks-relative' in ./hooks.nix as an example. 14 initialBash = if stdenv ? stage0 then stdenv.stage0.bash else stdenv.bootstrapTools; 15 initialPath = if stdenv ? stage0 then stdenv.stage0.initialPath else [ stdenv.bootstrapTools ]; 16 # early enough not to rebuild gcc but late enough to have patchelf 17 earlyPkgs = stdenv.__bootPackages.stdenv.__bootPackages or pkgs; 18 earlierPkgs = 19 stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages 20 or earlyPkgs; 21 # use a early stdenv so when hacking on stdenv this test can be run quickly 22 bootStdenv = earlyPkgs.stdenv.__bootPackages.stdenv.__bootPackages.stdenv or earlyPkgs.stdenv; 23 pkgsStructured = import pkgs.path { 24 config = { 25 structuredAttrsByDefault = true; 26 }; 27 inherit (stdenv.hostPlatform) system; 28 }; 29 bootStdenvStructuredAttrsByDefault = 30 pkgsStructured.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv 31 or pkgsStructured.stdenv; 32 33 runCommand = earlierPkgs.runCommand; 34 35 ccWrapperSubstitutionsTest = 36 { 37 name, 38 stdenv', 39 extraAttrs ? { }, 40 }: 41 42 stdenv'.cc.overrideAttrs ( 43 previousAttrs: 44 ( 45 { 46 inherit name; 47 48 postFixup = previousAttrs.postFixup + '' 49 declare -p wrapperName 50 echo "env.wrapperName = $wrapperName" 51 [[ $wrapperName == "CC_WRAPPER" ]] || (echo "'\$wrapperName' was not 'CC_WRAPPER'" && false) 52 declare -p suffixSalt 53 echo "env.suffixSalt = $suffixSalt" 54 [[ $suffixSalt == "${stdenv'.cc.suffixSalt}" ]] || (echo "'\$suffxSalt' was not '${stdenv'.cc.suffixSalt}'" && false) 55 56 grep -q "@out@" $out/bin/cc || echo "@out@ in $out/bin/cc was substituted" 57 grep -q "@suffixSalt@" $out/bin/cc && (echo "$out/bin/cc contains unsubstituted variables" && false) 58 59 touch $out 60 ''; 61 } 62 // extraAttrs 63 ) 64 ); 65 66 testEnvAttrset = 67 { 68 name, 69 stdenv', 70 extraAttrs ? { }, 71 }: 72 stdenv'.mkDerivation ( 73 { 74 inherit name; 75 env = { 76 string = "testing-string"; 77 }; 78 79 passAsFile = [ "buildCommand" ]; 80 buildCommand = '' 81 declare -p string 82 echo "env.string = $string" 83 [[ $string == "testing-string" ]] || (echo "'\$string' was not 'testing-string'" && false) 84 [[ "$(declare -p string)" == 'declare -x string="testing-string"' ]] || (echo "'\$string' was not exported" && false) 85 touch $out 86 ''; 87 } 88 // extraAttrs 89 ); 90 91 testPrependAndAppendToVar = 92 { 93 name, 94 stdenv', 95 extraAttrs ? { }, 96 }: 97 stdenv'.mkDerivation ( 98 { 99 inherit name; 100 env = { 101 string = "testing-string"; 102 }; 103 104 passAsFile = [ "buildCommand" ] ++ lib.optionals (extraAttrs ? extraTest) [ "extraTest" ]; 105 buildCommand = '' 106 declare -p string 107 appendToVar string hello 108 # test that quoted strings work 109 prependToVar string "world" 110 declare -p string 111 112 declare -A associativeArray=(["X"]="Y") 113 [[ $(appendToVar associativeArray "fail" 2>&1) =~ "trying to use" ]] || (echo "appendToVar did not throw appending to associativeArray" && false) 114 [[ $(prependToVar associativeArray "fail" 2>&1) =~ "trying to use" ]] || (echo "prependToVar did not throw prepending associativeArray" && false) 115 116 [[ $string == "world testing-string hello" ]] || (echo "'\$string' was not 'world testing-string hello'" && false) 117 118 # test appending to a unset variable 119 appendToVar nonExistant created hello 120 declare -p nonExistant 121 if [[ -n $__structuredAttrs ]]; then 122 [[ "''${nonExistant[@]}" == "created hello" ]] 123 else 124 # there's a extra " " in front here and a extra " " in the end of prependToVar 125 # shouldn't matter because these functions will mostly be used for $*Flags and the Flag variable will in most cases already exist 126 [[ "$nonExistant" == " created hello" ]] 127 fi 128 129 eval "$extraTest" 130 131 touch $out 132 ''; 133 } 134 // extraAttrs 135 ); 136 137 testConcatTo = 138 { 139 name, 140 stdenv', 141 extraAttrs ? { }, 142 }: 143 stdenv'.mkDerivation ( 144 { 145 inherit name; 146 147 string = "a *"; 148 list = [ 149 "c" 150 "d" 151 ]; 152 153 passAsFile = [ "buildCommand" ] ++ lib.optionals (extraAttrs ? extraTest) [ "extraTest" ]; 154 buildCommand = '' 155 declare -A associativeArray=(["X"]="Y") 156 [[ $(concatTo nowhere associativeArray 2>&1) =~ "trying to use" ]] || (echo "concatTo did not throw concatenating associativeArray" && false) 157 158 empty_array=() 159 empty_string="" 160 161 declare -a flagsArray 162 concatTo flagsArray string list notset=e=f empty_array=g empty_string=h 163 declare -p flagsArray 164 [[ "''${flagsArray[0]}" == "a" ]] || (echo "'\$flagsArray[0]' was not 'a'" && false) 165 [[ "''${flagsArray[1]}" == "*" ]] || (echo "'\$flagsArray[1]' was not '*'" && false) 166 [[ "''${flagsArray[2]}" == "c" ]] || (echo "'\$flagsArray[2]' was not 'c'" && false) 167 [[ "''${flagsArray[3]}" == "d" ]] || (echo "'\$flagsArray[3]' was not 'd'" && false) 168 [[ "''${flagsArray[4]}" == "e=f" ]] || (echo "'\$flagsArray[4]' was not 'e=f'" && false) 169 [[ "''${flagsArray[5]}" == "g" ]] || (echo "'\$flagsArray[5]' was not 'g'" && false) 170 [[ "''${flagsArray[6]}" == "h" ]] || (echo "'\$flagsArray[6]' was not 'h'" && false) 171 172 # test concatenating to unset variable 173 concatTo nonExistant string list notset=e=f empty_array=g empty_string=h 174 declare -p nonExistant 175 [[ "''${nonExistant[0]}" == "a" ]] || (echo "'\$nonExistant[0]' was not 'a'" && false) 176 [[ "''${nonExistant[1]}" == "*" ]] || (echo "'\$nonExistant[1]' was not '*'" && false) 177 [[ "''${nonExistant[2]}" == "c" ]] || (echo "'\$nonExistant[2]' was not 'c'" && false) 178 [[ "''${nonExistant[3]}" == "d" ]] || (echo "'\$nonExistant[3]' was not 'd'" && false) 179 [[ "''${nonExistant[4]}" == "e=f" ]] || (echo "'\$nonExistant[4]' was not 'e=f'" && false) 180 [[ "''${nonExistant[5]}" == "g" ]] || (echo "'\$nonExistant[5]' was not 'g'" && false) 181 [[ "''${nonExistant[6]}" == "h" ]] || (echo "'\$nonExistant[6]' was not 'h'" && false) 182 183 eval "$extraTest" 184 185 touch $out 186 ''; 187 } 188 // extraAttrs 189 ); 190 191 testConcatStringsSep = 192 { name, stdenv' }: 193 stdenv'.mkDerivation { 194 inherit name; 195 196 # NOTE: Testing with "&" as separator is intentional, because unquoted 197 # "&" has a special meaning in the "${var//pattern/replacement}" syntax. 198 # Cf. https://github.com/NixOS/nixpkgs/pull/318614#discussion_r1706191919 199 passAsFile = [ "buildCommand" ]; 200 buildCommand = '' 201 declare -A associativeArray=(["X"]="Y") 202 [[ $(concatStringsSep ";" associativeArray 2>&1) =~ "trying to use" ]] || (echo "concatStringsSep did not throw concatenating associativeArray" && false) 203 204 string="lorem ipsum dolor sit amet" 205 stringWithSep="$(concatStringsSep "&" string)" 206 [[ "$stringWithSep" == "lorem&ipsum&dolor&sit&amet" ]] || (echo "'\$stringWithSep' was not 'lorem&ipsum&dolor&sit&amet'" && false) 207 208 array=("lorem ipsum" "dolor" "sit amet") 209 arrayWithSep="$(concatStringsSep "&" array)" 210 [[ "$arrayWithSep" == "lorem ipsum&dolor&sit amet" ]] || (echo "'\$arrayWithSep' was not 'lorem ipsum&dolor&sit amet'" && false) 211 212 array=("lorem ipsum" "dolor" "sit amet") 213 arrayWithSep="$(concatStringsSep "++" array)" 214 [[ "$arrayWithSep" == "lorem ipsum++dolor++sit amet" ]] || (echo "'\$arrayWithSep' was not 'lorem ipsum++dolor++sit amet'" && false) 215 216 array=("lorem ipsum" "dolor" "sit amet") 217 arrayWithSep="$(concatStringsSep " and " array)" 218 [[ "$arrayWithSep" == "lorem ipsum and dolor and sit amet" ]] || (echo "'\$arrayWithSep' was not 'lorem ipsum and dolor and sit amet'" && false) 219 220 touch $out 221 ''; 222 }; 223 224 testInputDerivationDep = stdenv.mkDerivation { 225 name = "test-input-derivation-dependency"; 226 buildCommand = "touch $out"; 227 }; 228 testInputDerivation = 229 attrs: 230 (stdenv.mkDerivation ( 231 attrs 232 // { 233 buildInputs = [ testInputDerivationDep ]; 234 } 235 )).inputDerivation 236 // { 237 meta = { }; 238 }; 239in 240 241{ 242 # tests for hooks in `stdenv.defaultNativeBuildInputs` 243 hooks = lib.recurseIntoAttrs ( 244 import ./hooks.nix { 245 stdenv = bootStdenv; 246 pkgs = earlyPkgs; 247 inherit initialPath initialBash lib; 248 } 249 ); 250 251 outputs-no-out = 252 runCommand "outputs-no-out-assert" 253 { 254 result = earlierPkgs.testers.testBuildFailure ( 255 bootStdenv.mkDerivation { 256 NIX_DEBUG = 1; 257 name = "outputs-no-out"; 258 outputs = [ "foo" ]; 259 buildPhase = ":"; 260 installPhase = '' 261 touch $foo 262 ''; 263 } 264 ); 265 266 # Assumption: the first output* variable to be configured is 267 # _overrideFirst outputDev "dev" "out" 268 expectedMsg = "error: _assignFirst: could not find a non-empty variable whose name to assign to outputDev.\n The following variables were all unset or empty:\n dev out"; 269 } 270 '' 271 grep -F "$expectedMsg" $result/testBuildFailure.log >/dev/null 272 touch $out 273 ''; 274 275 test-env-attrset = testEnvAttrset { 276 name = "test-env-attrset"; 277 stdenv' = bootStdenv; 278 }; 279 280 # Check that mkDerivation rejects MD5 hashes 281 rejectedHashes = lib.recurseIntoAttrs { 282 md5 = 283 let 284 drv = runCommand "md5 outputHash rejected" { 285 outputHash = "md5-fPt7dxVVP7ffY3MxkQdwVw=="; 286 } "true"; 287 in 288 assert !(builtins.tryEval drv).success; 289 { }; 290 }; 291 292 test-inputDerivation = 293 let 294 inherit 295 (stdenv.mkDerivation { 296 dep1 = derivation { 297 name = "dep1"; 298 builder = "/bin/sh"; 299 args = [ 300 "-c" 301 ": > $out" 302 ]; 303 inherit (stdenv.buildPlatform) system; 304 }; 305 dep2 = derivation { 306 name = "dep2"; 307 builder = "/bin/sh"; 308 args = [ 309 "-c" 310 ": > $out" 311 ]; 312 inherit (stdenv.buildPlatform) system; 313 }; 314 passAsFile = [ "dep2" ]; 315 }) 316 inputDerivation 317 ; 318 in 319 runCommand "test-inputDerivation" 320 { 321 exportReferencesGraph = [ 322 "graph" 323 inputDerivation 324 ]; 325 } 326 '' 327 grep ${inputDerivation.dep1} graph 328 grep ${inputDerivation.dep2} graph 329 touch $out 330 ''; 331 332 test-inputDerivation-fixed-output = 333 let 334 inherit 335 (stdenv.mkDerivation { 336 dep1 = derivation { 337 name = "dep1"; 338 builder = "/bin/sh"; 339 args = [ 340 "-c" 341 ": > $out" 342 ]; 343 inherit (stdenv.buildPlatform) system; 344 }; 345 dep2 = derivation { 346 name = "dep2"; 347 builder = "/bin/sh"; 348 args = [ 349 "-c" 350 ": > $out" 351 ]; 352 inherit (stdenv.buildPlatform) system; 353 }; 354 name = "meow"; 355 outputHash = "sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="; 356 outputHashMode = "flat"; 357 outputHashAlgo = "sha256"; 358 buildCommand = '' 359 touch $out 360 ''; 361 passAsFile = [ "dep2" ]; 362 }) 363 inputDerivation 364 ; 365 in 366 runCommand "test-inputDerivation" 367 { 368 exportReferencesGraph = [ 369 "graph" 370 inputDerivation 371 ]; 372 } 373 '' 374 grep ${inputDerivation.dep1} graph 375 grep ${inputDerivation.dep2} graph 376 touch $out 377 ''; 378 379 test-inputDerivation-structured = testInputDerivation { 380 name = "test-inDrv-structured"; 381 __structuredAttrs = true; 382 }; 383 384 test-inputDerivation-allowedReferences = testInputDerivation { 385 name = "test-inDrv-allowedReferences"; 386 allowedReferences = [ ]; 387 }; 388 389 test-inputDerivation-disallowedReferences = testInputDerivation { 390 name = "test-inDrv-disallowedReferences"; 391 disallowedReferences = [ "${testInputDerivationDep}" ]; 392 }; 393 394 test-inputDerivation-allowedRequisites = testInputDerivation { 395 name = "test-inDrv-allowedRequisites"; 396 allowedRequisites = [ ]; 397 }; 398 399 test-inputDerivation-disallowedRequisites = testInputDerivation { 400 name = "test-inDrv-disallowedRequisites"; 401 disallowedRequisites = [ "${testInputDerivationDep}" ]; 402 }; 403 404 test-inputDerivation-structured-allowedReferences = testInputDerivation { 405 name = "test-inDrv-structured-allowedReferences"; 406 __structuredAttrs = true; 407 outputChecks.out.allowedReferences = [ ]; 408 }; 409 410 test-inputDerivation-structured-disallowedReferences = testInputDerivation { 411 name = "test-inDrv-structured-disallowedReferences"; 412 __structuredAttrs = true; 413 outputChecks.out.disallowedReferences = [ "${testInputDerivationDep}" ]; 414 }; 415 416 test-inputDerivation-structured-allowedRequisites = testInputDerivation { 417 name = "test-inDrv-structured-allowedRequisites"; 418 __structuredAttrs = true; 419 outputChecks.out.allowedRequisites = [ ]; 420 }; 421 422 test-inputDerivation-structured-disallowedRequisites = testInputDerivation { 423 name = "test-inDrv-structured-disallowedRequisites"; 424 __structuredAttrs = true; 425 outputChecks.out.disallowedRequisites = [ "${testInputDerivationDep}" ]; 426 }; 427 428 test-prepend-append-to-var = testPrependAndAppendToVar { 429 name = "test-prepend-append-to-var"; 430 stdenv' = bootStdenv; 431 }; 432 433 test-concat-to = testConcatTo { 434 name = "test-concat-to"; 435 stdenv' = bootStdenv; 436 }; 437 438 test-concat-strings-sep = testConcatStringsSep { 439 name = "test-concat-strings-sep"; 440 stdenv' = bootStdenv; 441 }; 442 443 test-structured-env-attrset = testEnvAttrset { 444 name = "test-structured-env-attrset"; 445 stdenv' = bootStdenv; 446 extraAttrs = { 447 __structuredAttrs = true; 448 }; 449 }; 450 451 test-cc-wrapper-substitutions = ccWrapperSubstitutionsTest { 452 name = "test-cc-wrapper-substitutions"; 453 stdenv' = bootStdenv; 454 }; 455 456 tests-stdenv-gcc-stageCompare = pkgs.callPackage ./gcc-stageCompare.nix { }; 457 458 ensure-no-execve-in-setup-sh = 459 derivation { 460 name = "ensure-no-execve-in-setup-sh"; 461 inherit (stdenv.hostPlatform) system; 462 builder = "${initialBash}/bin/bash"; 463 PATH = "${pkgs.strace}/bin:${lib.strings.makeSearchPath "bin" initialPath}"; 464 initialPath = initialPath ++ [ 465 pkgs.strace 466 ]; 467 args = [ 468 "-c" 469 '' 470 countCall() { 471 echo "$stats" | tr -s ' ' | grep "$1" | cut -d ' ' -f5 472 } 473 474 # prevent setup.sh from running `nproc` when cores=0 475 # (this would mess up the syscall stats) 476 export NIX_BUILD_CORES=1 477 478 echo "Analyzing setup.sh with strace" 479 stats=$(strace -fc bash -c ". ${../../stdenv/generic/setup.sh}" 2>&1) 480 echo "$stats" | head -n15 481 482 # fail if execve calls is > 1 483 stats=$(strace -fc bash -c ". ${../../stdenv/generic/setup.sh}" 2>&1) 484 execveCalls=$(countCall execve) 485 if [ "$execveCalls" -gt 1 ]; then 486 echo "execve calls: $execveCalls; expected: 1" 487 echo "ERROR: setup.sh should not launch additional processes when being sourced" 488 exit 1 489 else 490 echo "setup.sh doesn't launch extra processes when sourcing, as expected" 491 fi 492 493 touch $out 494 '' 495 ]; 496 } 497 // { 498 meta = { }; 499 }; 500 501 structuredAttrsByDefault = lib.recurseIntoAttrs { 502 503 hooks = lib.recurseIntoAttrs ( 504 import ./hooks.nix { 505 stdenv = bootStdenvStructuredAttrsByDefault; 506 pkgs = earlyPkgs; 507 inherit initialBash initialPath lib; 508 } 509 ); 510 511 test-cc-wrapper-substitutions = ccWrapperSubstitutionsTest { 512 name = "test-cc-wrapper-substitutions-structuredAttrsByDefault"; 513 stdenv' = bootStdenvStructuredAttrsByDefault; 514 }; 515 516 test-structured-env-attrset = testEnvAttrset { 517 name = "test-structured-env-attrset-structuredAttrsByDefault"; 518 stdenv' = bootStdenvStructuredAttrsByDefault; 519 }; 520 521 test-prepend-append-to-var = testPrependAndAppendToVar { 522 name = "test-prepend-append-to-var-structuredAttrsByDefault"; 523 stdenv' = bootStdenvStructuredAttrsByDefault; 524 extraAttrs = { 525 # will be a bash indexed array in attrs.sh 526 # declare -a list=('a' 'b' ) 527 # and a json array in attrs.json 528 # "list":["a","b"] 529 list = [ 530 "a" 531 "b" 532 ]; 533 # will be a bash associative array(dictionary) in attrs.sh 534 # declare -A array=(['a']='1' ['b']='2' ) 535 # and a json object in attrs.json 536 # {"array":{"a":"1","b":"2"} 537 array = { 538 a = "1"; 539 b = "2"; 540 }; 541 extraTest = '' 542 declare -p array 543 array+=(["c"]="3") 544 declare -p array 545 546 [[ "''${array[c]}" == "3" ]] || (echo "c element of '\$array' was not '3'" && false) 547 548 declare -p list 549 prependToVar list hello 550 # test that quoted strings work 551 appendToVar list "world" 552 declare -p list 553 554 [[ "''${list[0]}" == "hello" ]] || (echo "first element of '\$list' was not 'hello'" && false) 555 [[ "''${list[1]}" == "a" ]] || (echo "first element of '\$list' was not 'a'" && false) 556 [[ "''${list[-1]}" == "world" ]] || (echo "last element of '\$list' was not 'world'" && false) 557 ''; 558 }; 559 }; 560 561 test-concat-to = testConcatTo { 562 name = "test-concat-to-structuredAttrsByDefault"; 563 stdenv' = bootStdenvStructuredAttrsByDefault; 564 extraAttrs = { 565 # test that whitespace is kept in the bash array for structuredAttrs 566 listWithSpaces = [ 567 "c c" 568 "d d" 569 ]; 570 extraTest = '' 571 declare -a flagsWithSpaces 572 concatTo flagsWithSpaces string listWithSpaces 573 declare -p flagsWithSpaces 574 [[ "''${flagsWithSpaces[0]}" == "a" ]] || (echo "'\$flagsWithSpaces[0]' was not 'a'" && false) 575 [[ "''${flagsWithSpaces[1]}" == "*" ]] || (echo "'\$flagsWithSpaces[1]' was not '*'" && false) 576 [[ "''${flagsWithSpaces[2]}" == "c c" ]] || (echo "'\$flagsWithSpaces[2]' was not 'c c'" && false) 577 [[ "''${flagsWithSpaces[3]}" == "d d" ]] || (echo "'\$flagsWithSpaces[3]' was not 'd d'" && false) 578 ''; 579 }; 580 }; 581 582 test-concat-strings-sep = testConcatStringsSep { 583 name = "test-concat-strings-sep-structuredAttrsByDefault"; 584 stdenv' = bootStdenvStructuredAttrsByDefault; 585 }; 586 587 test-golden-example-structuredAttrs = 588 let 589 goldenSh = earlyPkgs.writeText "goldenSh" '' 590 declare -A EXAMPLE_ATTRS=(['foo']='bar' ) 591 declare EXAMPLE_BOOL_FALSE= 592 declare EXAMPLE_BOOL_TRUE=1 593 declare EXAMPLE_INT=123 594 declare EXAMPLE_INT_NEG=-123 595 declare -a EXAMPLE_LIST=('foo' 'bar' ) 596 declare EXAMPLE_STR='foo bar' 597 ''; 598 goldenJson = earlyPkgs.writeText "goldenSh" '' 599 { 600 "EXAMPLE_ATTRS": { 601 "foo": "bar" 602 }, 603 "EXAMPLE_BOOL_FALSE": false, 604 "EXAMPLE_BOOL_TRUE": true, 605 "EXAMPLE_INT": 123, 606 "EXAMPLE_INT_NEG": -123, 607 "EXAMPLE_LIST": [ 608 "foo", 609 "bar" 610 ], 611 "EXAMPLE_NESTED_ATTRS": { 612 "foo": { 613 "bar": "baz" 614 } 615 }, 616 "EXAMPLE_NESTED_LIST": [ 617 [ 618 "foo", 619 "bar" 620 ], 621 [ 622 "baz" 623 ] 624 ], 625 "EXAMPLE_STR": "foo bar" 626 } 627 ''; 628 in 629 bootStdenvStructuredAttrsByDefault.mkDerivation { 630 name = "test-golden-example-structuredAttrsByDefault"; 631 nativeBuildInputs = [ earlyPkgs.jq ]; 632 633 EXAMPLE_BOOL_TRUE = true; 634 EXAMPLE_BOOL_FALSE = false; 635 EXAMPLE_INT = 123; 636 EXAMPLE_INT_NEG = -123; 637 EXAMPLE_STR = "foo bar"; 638 EXAMPLE_LIST = [ 639 "foo" 640 "bar" 641 ]; 642 EXAMPLE_NESTED_LIST = [ 643 [ 644 "foo" 645 "bar" 646 ] 647 [ "baz" ] 648 ]; 649 EXAMPLE_ATTRS = { 650 foo = "bar"; 651 }; 652 EXAMPLE_NESTED_ATTRS = { 653 foo.bar = "baz"; 654 }; 655 656 inherit goldenSh; 657 inherit goldenJson; 658 659 buildCommand = '' 660 mkdir -p $out 661 cat $NIX_ATTRS_SH_FILE | grep "EXAMPLE" | grep -v -E 'installPhase|jq' > $out/sh 662 jq 'with_entries(select(.key|match("EXAMPLE")))' $NIX_ATTRS_JSON_FILE > $out/json 663 diff $out/sh $goldenSh 664 diff $out/json $goldenJson 665 ''; 666 }; 667 }; 668}