python312Packages.lottie: 0.7.0 -> 0.7.1 (#361686)
[NixPkgs.git] / pkgs / test / stdenv / default.nix
blobd8f11f98e9b8bdd57e1c72dbe26e8c4bbb35e8a0
1 # To run these tests:
2 # nix-build -A tests.stdenv
4 { stdenv
5 , pkgs
6 , lib
7 , testers
8 }:
10 let
11   # early enough not to rebuild gcc but late enough to have patchelf
12   earlyPkgs = stdenv.__bootPackages.stdenv.__bootPackages;
13   earlierPkgs = stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages;
14   # use a early stdenv so when hacking on stdenv this test can be run quickly
15   bootStdenv = stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv;
16   pkgsStructured = import pkgs.path { config = { structuredAttrsByDefault = true; }; inherit (stdenv.hostPlatform) system; };
17   bootStdenvStructuredAttrsByDefault = pkgsStructured.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv;
19   runCommand = earlierPkgs.runCommand;
22   ccWrapperSubstitutionsTest = { name, stdenv', extraAttrs ? { } }:
24     stdenv'.cc.overrideAttrs (previousAttrs: ({
25       inherit name;
27       postFixup = previousAttrs.postFixup + ''
28         declare -p wrapperName
29         echo "env.wrapperName = $wrapperName"
30         [[ $wrapperName == "CC_WRAPPER" ]] || (echo "'\$wrapperName' was not 'CC_WRAPPER'" && false)
31         declare -p suffixSalt
32         echo "env.suffixSalt = $suffixSalt"
33         [[ $suffixSalt == "${stdenv'.cc.suffixSalt}" ]] || (echo "'\$suffxSalt' was not '${stdenv'.cc.suffixSalt}'" && false)
35         grep -q "@out@" $out/bin/cc || echo "@out@ in $out/bin/cc was substituted"
36         grep -q "@suffixSalt@" $out/bin/cc && (echo "$out/bin/cc contains unsubstituted variables" && false)
38         touch $out
39       '';
40     } // extraAttrs));
42   testEnvAttrset = { name, stdenv', extraAttrs ? { } }:
43     stdenv'.mkDerivation
44       ({
45         inherit name;
46         env = {
47           string = "testing-string";
48         };
50         passAsFile = [ "buildCommand" ];
51         buildCommand = ''
52           declare -p string
53           echo "env.string = $string"
54           [[ $string == "testing-string" ]] || (echo "'\$string' was not 'testing-string'" && false)
55           [[ "$(declare -p string)" == 'declare -x string="testing-string"' ]] || (echo "'\$string' was not exported" && false)
56           touch $out
57         '';
58       } // extraAttrs);
60   testPrependAndAppendToVar = { name, stdenv', extraAttrs ? { } }:
61     stdenv'.mkDerivation
62       ({
63         inherit name;
64         env = {
65           string = "testing-string";
66         };
68         passAsFile = [ "buildCommand" ] ++ lib.optionals (extraAttrs ? extraTest) [ "extraTest" ];
69         buildCommand = ''
70           declare -p string
71           appendToVar string hello
72           # test that quoted strings work
73           prependToVar string "world"
74           declare -p string
76           declare -A associativeArray=(["X"]="Y")
77           [[ $(appendToVar associativeArray "fail" 2>&1) =~ "trying to use" ]] || (echo "appendToVar did not throw appending to associativeArray" && false)
78           [[ $(prependToVar associativeArray "fail" 2>&1) =~ "trying to use" ]] || (echo "prependToVar did not throw prepending associativeArray" && false)
80           [[ $string == "world testing-string hello" ]] || (echo "'\$string' was not 'world testing-string hello'" && false)
82           # test appending to a unset variable
83           appendToVar nonExistant created hello
84           declare -p nonExistant
85           if [[ -n $__structuredAttrs ]]; then
86             [[ "''${nonExistant[@]}" == "created hello" ]]
87           else
88             # there's a extra " " in front here and a extra " " in the end of prependToVar
89             # shouldn't matter because these functions will mostly be used for $*Flags and the Flag variable will in most cases already exist
90             [[ "$nonExistant" == " created hello" ]]
91           fi
93           eval "$extraTest"
95           touch $out
96         '';
97       } // extraAttrs);
99   testConcatTo = { name, stdenv', extraAttrs ? { } }:
100     stdenv'.mkDerivation
101       ({
102         inherit name;
104         string = "a *";
105         list = ["c" "d"];
107         passAsFile = [ "buildCommand" ] ++ lib.optionals (extraAttrs ? extraTest) [ "extraTest" ];
108         buildCommand = ''
109           declare -A associativeArray=(["X"]="Y")
110           [[ $(concatTo nowhere associativeArray 2>&1) =~ "trying to use" ]] || (echo "concatTo did not throw concatenating associativeArray" && false)
112           empty_array=()
113           empty_string=""
115           declare -a flagsArray
116           concatTo flagsArray string list notset=e=f empty_array=g empty_string=h
117           declare -p flagsArray
118           [[ "''${flagsArray[0]}" == "a" ]] || (echo "'\$flagsArray[0]' was not 'a'" && false)
119           [[ "''${flagsArray[1]}" == "*" ]] || (echo "'\$flagsArray[1]' was not '*'" && false)
120           [[ "''${flagsArray[2]}" == "c" ]] || (echo "'\$flagsArray[2]' was not 'c'" && false)
121           [[ "''${flagsArray[3]}" == "d" ]] || (echo "'\$flagsArray[3]' was not 'd'" && false)
122           [[ "''${flagsArray[4]}" == "e=f" ]] || (echo "'\$flagsArray[4]' was not 'e=f'" && false)
123           [[ "''${flagsArray[5]}" == "g" ]] || (echo "'\$flagsArray[5]' was not 'g'" && false)
124           [[ "''${flagsArray[6]}" == "h" ]] || (echo "'\$flagsArray[6]' was not 'h'" && false)
126           # test concatenating to unset variable
127           concatTo nonExistant string list notset=e=f empty_array=g empty_string=h
128           declare -p nonExistant
129           [[ "''${nonExistant[0]}" == "a" ]] || (echo "'\$nonExistant[0]' was not 'a'" && false)
130           [[ "''${nonExistant[1]}" == "*" ]] || (echo "'\$nonExistant[1]' was not '*'" && false)
131           [[ "''${nonExistant[2]}" == "c" ]] || (echo "'\$nonExistant[2]' was not 'c'" && false)
132           [[ "''${nonExistant[3]}" == "d" ]] || (echo "'\$nonExistant[3]' was not 'd'" && false)
133           [[ "''${nonExistant[4]}" == "e=f" ]] || (echo "'\$nonExistant[4]' was not 'e=f'" && false)
134           [[ "''${nonExistant[5]}" == "g" ]] || (echo "'\$nonExistant[5]' was not 'g'" && false)
135           [[ "''${nonExistant[6]}" == "h" ]] || (echo "'\$nonExistant[6]' was not 'h'" && false)
137           eval "$extraTest"
139           touch $out
140         '';
141       } // extraAttrs);
143   testConcatStringsSep = { name, stdenv' }:
144     stdenv'.mkDerivation
145       {
146         inherit name;
148         # NOTE: Testing with "&" as separator is intentional, because unquoted
149         # "&" has a special meaning in the "${var//pattern/replacement}" syntax.
150         # Cf. https://github.com/NixOS/nixpkgs/pull/318614#discussion_r1706191919
151         passAsFile = [ "buildCommand" ];
152         buildCommand = ''
153           declare -A associativeArray=(["X"]="Y")
154           [[ $(concatStringsSep ";" associativeArray 2>&1) =~ "trying to use" ]] || (echo "concatStringsSep did not throw concatenating associativeArray" && false)
156           string="lorem ipsum dolor sit amet"
157           stringWithSep="$(concatStringsSep "&" string)"
158           [[ "$stringWithSep" == "lorem&ipsum&dolor&sit&amet" ]] || (echo "'\$stringWithSep' was not 'lorem&ipsum&dolor&sit&amet'" && false)
160           array=("lorem ipsum" "dolor" "sit amet")
161           arrayWithSep="$(concatStringsSep "&" array)"
162           [[ "$arrayWithSep" == "lorem ipsum&dolor&sit amet" ]] || (echo "'\$arrayWithSep' was not 'lorem ipsum&dolor&sit amet'" && false)
164           touch $out
165         '';
166       };
170   # Disable on Darwin due to assumptions with __bootPackages
171   __attrsFailEvaluation = stdenv.hostPlatform.isDarwin;
173   # tests for hooks in `stdenv.defaultNativeBuildInputs`
174   hooks = lib.recurseIntoAttrs (import ./hooks.nix { stdenv = bootStdenv; pkgs = earlyPkgs; inherit lib; });
176   outputs-no-out = runCommand "outputs-no-out-assert" {
177     result = earlierPkgs.testers.testBuildFailure (bootStdenv.mkDerivation {
178       NIX_DEBUG = 1;
179       name = "outputs-no-out";
180       outputs = ["foo"];
181       buildPhase = ":";
182       installPhase = ''
183         touch $foo
184       '';
185     });
187     # Assumption: the first output* variable to be configured is
188     #   _overrideFirst outputDev "dev" "out"
189     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";
190   } ''
191     grep -F "$expectedMsg" $result/testBuildFailure.log >/dev/null
192     touch $out
193   '';
195   test-env-attrset = testEnvAttrset { name = "test-env-attrset"; stdenv' = bootStdenv; };
197   # Test compatibility with derivations using `env` as a regular variable.
198   test-env-derivation = bootStdenv.mkDerivation rec {
199     name = "test-env-derivation";
200     env = bootStdenv.mkDerivation {
201       name = "foo";
202       buildCommand = ''
203         mkdir "$out"
204         touch "$out/bar"
205       '';
206     };
208     passAsFile = [ "buildCommand" ];
209     buildCommand = ''
210       declare -p env
211       [[ $env == "${env}" ]]
212       touch "$out"
213     '';
214   };
216   # Check that mkDerivation rejects MD5 hashes
217   rejectedHashes = lib.recurseIntoAttrs {
218     md5 =
219       let drv = runCommand "md5 outputHash rejected" {
220         outputHash = "md5-fPt7dxVVP7ffY3MxkQdwVw==";
221       } "true";
222       in assert !(builtins.tryEval drv).success; {};
223   };
225   test-inputDerivation = let
226     inherit (stdenv.mkDerivation {
227       dep1 = derivation { name = "dep1"; builder = "/bin/sh"; args = [ "-c" ": > $out" ]; system = builtins.currentSystem; };
228       dep2 = derivation { name = "dep2"; builder = "/bin/sh"; args = [ "-c" ": > $out" ]; system = builtins.currentSystem; };
229       passAsFile = [ "dep2" ];
230     }) inputDerivation;
231   in
232     runCommand "test-inputDerivation" {
233       exportReferencesGraph = [ "graph" inputDerivation ];
234     } ''
235       grep ${inputDerivation.dep1} graph
236       grep ${inputDerivation.dep2} graph
237       touch $out
238     '';
240   test-inputDerivation-fixed-output = let
241     inherit (stdenv.mkDerivation {
242       dep1 = derivation { name = "dep1"; builder = "/bin/sh"; args = [ "-c" ": > $out" ]; system = builtins.currentSystem; };
243       dep2 = derivation { name = "dep2"; builder = "/bin/sh"; args = [ "-c" ": > $out" ]; system = builtins.currentSystem; };
244       name = "meow";
245       outputHash = "sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=";
246       outputHashMode = "flat";
247       outputHashAlgo = "sha256";
248       buildCommand = ''
249         touch $out
250       '';
251       passAsFile = [ "dep2" ];
252     }) inputDerivation;
253   in
254     runCommand "test-inputDerivation" {
255       exportReferencesGraph = [ "graph" inputDerivation ];
256     } ''
257       grep ${inputDerivation.dep1} graph
258       grep ${inputDerivation.dep2} graph
259       touch $out
260     '';
262   test-prepend-append-to-var = testPrependAndAppendToVar {
263     name = "test-prepend-append-to-var";
264     stdenv' = bootStdenv;
265   };
267   test-concat-to = testConcatTo {
268     name = "test-concat-to";
269     stdenv' = bootStdenv;
270   };
272   test-concat-strings-sep = testConcatStringsSep {
273     name = "test-concat-strings-sep";
274     stdenv' = bootStdenv;
275   };
277   test-structured-env-attrset = testEnvAttrset {
278     name = "test-structured-env-attrset";
279     stdenv' = bootStdenv;
280     extraAttrs = { __structuredAttrs = true; };
281   };
283   test-cc-wrapper-substitutions = ccWrapperSubstitutionsTest {
284     name = "test-cc-wrapper-substitutions";
285     stdenv' = bootStdenv;
286   };
288   structuredAttrsByDefault = lib.recurseIntoAttrs {
290     hooks = lib.recurseIntoAttrs (import ./hooks.nix { stdenv = bootStdenvStructuredAttrsByDefault; pkgs = earlyPkgs; inherit lib; });
292     test-cc-wrapper-substitutions = ccWrapperSubstitutionsTest {
293       name = "test-cc-wrapper-substitutions-structuredAttrsByDefault";
294       stdenv' = bootStdenvStructuredAttrsByDefault;
295     };
297     test-structured-env-attrset = testEnvAttrset {
298       name = "test-structured-env-attrset-structuredAttrsByDefault";
299       stdenv' = bootStdenvStructuredAttrsByDefault;
300     };
302     test-prepend-append-to-var = testPrependAndAppendToVar {
303       name = "test-prepend-append-to-var-structuredAttrsByDefault";
304       stdenv' = bootStdenvStructuredAttrsByDefault;
305       extraAttrs = {
306         # will be a bash indexed array in attrs.sh
307         # declare -a list=('a' 'b' )
308         # and a json array in attrs.json
309         # "list":["a","b"]
310         list = [ "a" "b" ];
311         # will be a bash associative array(dictionary) in attrs.sh
312         # declare -A array=(['a']='1' ['b']='2' )
313         # and a json object in attrs.json
314         # {"array":{"a":"1","b":"2"}
315         array = { a = "1"; b = "2"; };
316         extraTest = ''
317           declare -p array
318           array+=(["c"]="3")
319           declare -p array
321           [[ "''${array[c]}" == "3" ]] || (echo "c element of '\$array' was not '3'" && false)
323           declare -p list
324           prependToVar list hello
325           # test that quoted strings work
326           appendToVar list "world"
327           declare -p list
329           [[ "''${list[0]}" == "hello" ]] || (echo "first element of '\$list' was not 'hello'" && false)
330           [[ "''${list[1]}" == "a" ]] || (echo "first element of '\$list' was not 'a'" && false)
331           [[ "''${list[-1]}" == "world" ]] || (echo "last element of '\$list' was not 'world'" && false)
332         '';
333       };
334     };
336     test-concat-to = testConcatTo {
337       name = "test-concat-to-structuredAttrsByDefault";
338       stdenv' = bootStdenvStructuredAttrsByDefault;
339       extraAttrs = {
340         # test that whitespace is kept in the bash array for structuredAttrs
341         listWithSpaces = [ "c c" "d d" ];
342         extraTest = ''
343           declare -a flagsWithSpaces
344           concatTo flagsWithSpaces string listWithSpaces
345           declare -p flagsWithSpaces
346           [[ "''${flagsWithSpaces[0]}" == "a" ]] || (echo "'\$flagsWithSpaces[0]' was not 'a'" && false)
347           [[ "''${flagsWithSpaces[1]}" == "*" ]] || (echo "'\$flagsWithSpaces[1]' was not '*'" && false)
348           [[ "''${flagsWithSpaces[2]}" == "c c" ]] || (echo "'\$flagsWithSpaces[2]' was not 'c c'" && false)
349           [[ "''${flagsWithSpaces[3]}" == "d d" ]] || (echo "'\$flagsWithSpaces[3]' was not 'd d'" && false)
350         '';
351       };
352     };
354     test-concat-strings-sep = testConcatStringsSep {
355       name = "test-concat-strings-sep-structuredAttrsByDefault";
356       stdenv' = bootStdenvStructuredAttrsByDefault;
357     };
359     test-golden-example-structuredAttrs =
360       let
361         goldenSh = earlyPkgs.writeText "goldenSh" ''
362           declare -A EXAMPLE_ATTRS=(['foo']='bar' )
363           declare EXAMPLE_BOOL_FALSE=
364           declare EXAMPLE_BOOL_TRUE=1
365           declare EXAMPLE_INT=123
366           declare EXAMPLE_INT_NEG=-123
367           declare -a EXAMPLE_LIST=('foo' 'bar' )
368           declare EXAMPLE_STR='foo bar'
369         '';
370         goldenJson = earlyPkgs.writeText "goldenSh" ''
371           {
372             "EXAMPLE_ATTRS": {
373               "foo": "bar"
374             },
375             "EXAMPLE_BOOL_FALSE": false,
376             "EXAMPLE_BOOL_TRUE": true,
377             "EXAMPLE_INT": 123,
378             "EXAMPLE_INT_NEG": -123,
379             "EXAMPLE_LIST": [
380               "foo",
381               "bar"
382             ],
383             "EXAMPLE_NESTED_ATTRS": {
384               "foo": {
385                 "bar": "baz"
386               }
387             },
388             "EXAMPLE_NESTED_LIST": [
389               [
390                 "foo",
391                 "bar"
392               ],
393               [
394                 "baz"
395               ]
396             ],
397             "EXAMPLE_STR": "foo bar"
398           }
399         '';
400       in
401       bootStdenvStructuredAttrsByDefault.mkDerivation {
402         name = "test-golden-example-structuredAttrsByDefault";
403         nativeBuildInputs = [ earlyPkgs.jq ];
405         EXAMPLE_BOOL_TRUE = true;
406         EXAMPLE_BOOL_FALSE = false;
407         EXAMPLE_INT = 123;
408         EXAMPLE_INT_NEG = -123;
409         EXAMPLE_STR = "foo bar";
410         EXAMPLE_LIST = [ "foo" "bar" ];
411         EXAMPLE_NESTED_LIST = [ [ "foo" "bar" ] [ "baz" ] ];
412         EXAMPLE_ATTRS = { foo = "bar"; };
413         EXAMPLE_NESTED_ATTRS = { foo.bar = "baz"; };
415         inherit goldenSh;
416         inherit goldenJson;
418         buildCommand = ''
419           mkdir -p $out
420           cat $NIX_ATTRS_SH_FILE | grep "EXAMPLE" | grep -v -E 'installPhase|jq' > $out/sh
421           jq 'with_entries(select(.key|match("EXAMPLE")))' $NIX_ATTRS_JSON_FILE > $out/json
422           diff $out/sh $goldenSh
423           diff $out/json $goldenJson
424         '';
425       };
427   };