nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{
2 lib,
3 pkgs,
4 stdenvNoCC,
5}:
6
7let
8 tests =
9 tests-stdenv
10 // test-extendMkDerivation
11 // tests-fetchhg
12 // tests-fetchurl
13 // tests-go
14 // tests-python;
15
16 tests-stdenv =
17 let
18 addEntangled =
19 origOverrideAttrs: f:
20 origOverrideAttrs (
21 lib.composeExtensions f (
22 self: super: {
23 passthru = super.passthru // {
24 entangled = super.passthru.entangled.overrideAttrs f;
25 overrideAttrs = addEntangled self.overrideAttrs;
26 };
27 }
28 )
29 );
30
31 entangle =
32 pkg1: pkg2:
33 pkg1.overrideAttrs (
34 self: super: {
35 passthru = super.passthru // {
36 entangled = pkg2;
37 overrideAttrs = addEntangled self.overrideAttrs;
38 };
39 }
40 );
41
42 example = entangle pkgs.hello pkgs.figlet;
43
44 overrides1 = example.overrideAttrs (_: super: { pname = "a-better-${super.pname}"; });
45
46 repeatedOverrides = overrides1.overrideAttrs (
47 _: super: { pname = "${super.pname}-with-blackjack"; }
48 );
49 in
50 {
51 repeatedOverrides-pname = {
52 expr = repeatedOverrides.pname;
53 expected = "a-better-hello-with-blackjack";
54 };
55 repeatedOverrides-entangled-pname = {
56 expr = repeatedOverrides.entangled.pname;
57 expected = "a-better-figlet-with-blackjack";
58 };
59 overriding-using-only-attrset = {
60 expr = (pkgs.hello.overrideAttrs { pname = "hello-overriden"; }).pname;
61 expected = "hello-overriden";
62 };
63 overriding-using-only-attrset-no-final-attrs = {
64 name = "overriding-using-only-attrset-no-final-attrs";
65 expr =
66 ((stdenvNoCC.mkDerivation { pname = "hello-no-final-attrs"; }).overrideAttrs {
67 pname = "hello-no-final-attrs-overridden";
68 }).pname;
69 expected = "hello-no-final-attrs-overridden";
70 };
71 };
72
73 test-extendMkDerivation =
74 let
75 mkLocalDerivation = lib.extendMkDerivation {
76 constructDrv = pkgs.stdenv.mkDerivation;
77 excludeDrvArgNames = [
78 "specialArg"
79 ];
80 extendDrvArgs =
81 finalAttrs:
82 {
83 preferLocalBuild ? true,
84 allowSubstitute ? false,
85 specialArg ? (_: false),
86 ...
87 }@args:
88 {
89 inherit preferLocalBuild allowSubstitute;
90 passthru = args.passthru or { } // {
91 greeting = if specialArg "Hi!" then "Hi!" else "Hello!";
92 };
93 };
94 };
95
96 helloLocalPlainAttrs = {
97 inherit (pkgs.hello) pname version src;
98 specialArg = throw "specialArg is broken.";
99 };
100
101 helloLocalPlain = mkLocalDerivation helloLocalPlainAttrs;
102
103 helloLocal = mkLocalDerivation (
104 finalAttrs:
105 helloLocalPlainAttrs
106 // {
107 passthru = pkgs.hello.passthru or { } // {
108 foo = "a";
109 bar = "${finalAttrs.passthru.foo}b";
110 };
111 }
112 );
113
114 hiLocal = mkLocalDerivation (
115 helloLocalPlainAttrs
116 // {
117 specialArg = s: lib.stringLength s == 3;
118 }
119 );
120 in
121 {
122 extendMkDerivation-helloLocal-imp-arguments = {
123 expr = helloLocal.preferLocalBuild;
124 expected = true;
125 };
126 extendMkDerivation-helloLocal-plain-equivalence = {
127 expr = helloLocal.drvPath;
128 expected = helloLocalPlain.drvPath;
129 };
130 extendMkDerivation-helloLocal-finalAttrs = {
131 expr = helloLocal.bar;
132 expected = "ab";
133 };
134 extendMkDerivation-helloLocal-specialArg = {
135 expr = hiLocal.greeting;
136 expected = "Hi!";
137 };
138 };
139
140 tests-fetchgit =
141 let
142 src-with-sha256 = pkgs.fetchgit {
143 url = "https://example.com/source.git";
144 sha256 = lib.fakeSha256;
145 };
146 in
147 {
148 test-fetchgit-hash-compat = {
149 expr = {
150 inherit (src-with-sha256)
151 outputHash
152 outputHashAlgo
153 ;
154 };
155 expected = {
156 outputHash = lib.fakeSha256;
157 outputHashAlgo = "sha256";
158 };
159 };
160 test-fetchgit-overrideAttrs-hash = {
161 expr = {
162 inherit (src-with-sha256.overrideAttrs { hash = pkgs.nix.src.hash; })
163 outputHash
164 outputHashAlgo
165 ;
166 };
167 expected = {
168 outputHash = pkgs.nix.src.hash;
169 outputHashAlgo = null;
170 };
171 };
172 test-fetchurl-overrideAttrs-hash-empty = {
173 expr = {
174 inherit (src-with-sha256.overrideAttrs { hash = ""; })
175 outputHash
176 outputHashAlgo
177 ;
178 };
179 expected = {
180 outputHash = lib.fakeHash;
181 outputHashAlgo = null;
182 };
183 };
184 };
185
186 tests-fetchurl =
187 let
188 src-with-sha256 = pkgs.fetchurl {
189 url = "https://example.com/source.tar.gz";
190 sha256 = lib.fakeSha256;
191 };
192 in
193 {
194 test-fetchurl-hash-compat = {
195 expr = {
196 inherit (src-with-sha256)
197 outputHash
198 outputHashAlgo
199 ;
200 };
201 expected = {
202 outputHash = lib.fakeSha256;
203 outputHashAlgo = "sha256";
204 };
205 };
206 test-fetchurl-overrideAttrs-hash = {
207 expr = {
208 inherit (src-with-sha256.overrideAttrs { hash = pkgs.hello.src.hash; })
209 outputHash
210 outputHashAlgo
211 ;
212 };
213 expected = {
214 outputHash = pkgs.hello.src.hash;
215 outputHashAlgo = null;
216 };
217 };
218 test-fetchurl-overrideAttrs-hash-empty = {
219 expr = {
220 inherit (src-with-sha256.overrideAttrs { hash = ""; })
221 outputHash
222 outputHashAlgo
223 ;
224 };
225 expected = {
226 outputHash = lib.fakeHash;
227 outputHashAlgo = null;
228 };
229 };
230 };
231
232 tests-fetchhg =
233 let
234 ruamel_0_18_14-hash = "sha256-HDkPPp1xI3uoGYlS9mwPp1ZjG2gKvx6vog0Blj6tBuI=";
235 ruamel_0_18_14-src = pkgs.fetchhg {
236 url = "http://hg.code.sf.net/p/ruamel-yaml/code";
237 rev = "0.18.14";
238 hash = ruamel_0_18_14-hash;
239 };
240 ruamel_0_17_21-hash = "sha256-6PV0NyPQfd+4RBqoj5vJaOHShx+TJVHD2IamRinU0VU=";
241 ruamel_0_17_21-src = pkgs.fetchhg {
242 url = "http://hg.code.sf.net/p/ruamel-yaml/code";
243 rev = "0.17.21";
244 hash = ruamel_0_17_21-hash;
245 };
246 ruamel_0_17_21-src-by-overriding = ruamel_0_18_14-src.overrideAttrs {
247 rev = "0.17.21";
248 hash = ruamel_0_17_21-hash;
249 };
250 in
251 {
252 hash-outputHash-equivalence = {
253 expr = ruamel_0_17_21-src.outputHash;
254 expected = ruamel_0_17_21-hash;
255 };
256
257 hash-overridability-outputHash = {
258 expr = ruamel_0_17_21-src-by-overriding.outputHash;
259 expected = ruamel_0_17_21-hash;
260 };
261
262 hash-overridability-drvPath = {
263 expr = [
264 (lib.isString ruamel_0_17_21-src-by-overriding.drvPath)
265 ruamel_0_17_21-src-by-overriding.drvPath
266 ];
267 expected = [
268 true
269 ruamel_0_17_21-src.drvPath
270 ];
271 };
272
273 hash-overridability-outPath = {
274 expr = [
275 (lib.isString ruamel_0_17_21-src-by-overriding.outPath)
276 ruamel_0_17_21-src-by-overriding.outPath
277 ];
278 expected = [
279 true
280 ruamel_0_17_21-src.outPath
281 ];
282 };
283 };
284
285 tests-go =
286 let
287 pet_0_3_4 = pkgs.buildGoModule rec {
288 pname = "pet";
289 version = "0.3.4";
290
291 src = pkgs.fetchFromGitHub {
292 owner = "knqyf263";
293 repo = "pet";
294 rev = "v${version}";
295 hash = "sha256-Gjw1dRrgM8D3G7v6WIM2+50r4HmTXvx0Xxme2fH9TlQ=";
296 };
297
298 vendorHash = "sha256-ciBIR+a1oaYH+H1PcC8cD8ncfJczk1IiJ8iYNM+R6aA=";
299
300 meta = {
301 description = "Simple command-line snippet manager, written in Go";
302 homepage = "https://github.com/knqyf263/pet";
303 license = lib.licenses.mit;
304 maintainers = with lib.maintainers; [ kalbasit ];
305 };
306 };
307
308 pet_0_4_0 = pkgs.buildGoModule rec {
309 pname = "pet";
310 version = "0.4.0";
311
312 src = pkgs.fetchFromGitHub {
313 owner = "knqyf263";
314 repo = "pet";
315 rev = "v${version}";
316 hash = "sha256-gVTpzmXekQxGMucDKskGi+e+34nJwwsXwvQTjRO6Gdg=";
317 };
318
319 vendorHash = "sha256-dUvp7FEW09V0xMuhewPGw3TuAic/sD7xyXEYviZ2Ivs=";
320
321 meta = {
322 description = "Simple command-line snippet manager, written in Go";
323 homepage = "https://github.com/knqyf263/pet";
324 license = lib.licenses.mit;
325 maintainers = with lib.maintainers; [ kalbasit ];
326 };
327 };
328
329 pet_0_4_0-overridden = pet_0_3_4.overrideAttrs (
330 finalAttrs: previousAttrs: {
331 version = "0.4.0";
332
333 src = pkgs.fetchFromGitHub {
334 inherit (previousAttrs.src) owner repo;
335 rev = "v${finalAttrs.version}";
336 hash = "sha256-gVTpzmXekQxGMucDKskGi+e+34nJwwsXwvQTjRO6Gdg=";
337 };
338
339 vendorHash = "sha256-dUvp7FEW09V0xMuhewPGw3TuAic/sD7xyXEYviZ2Ivs=";
340 }
341 );
342
343 pet-foo = pet_0_3_4.overrideAttrs (
344 finalAttrs: previousAttrs: {
345 passthru = previousAttrs.passthru // {
346 overrideModAttrs = lib.composeExtensions previousAttrs.passthru.overrideModAttrs (
347 finalModAttrs: previousModAttrs: {
348 FOO = "foo";
349 }
350 );
351 };
352 }
353 );
354
355 pet-vendored = pet-foo.overrideAttrs { vendorHash = null; };
356 in
357 {
358 buildGoModule-overrideAttrs =
359 let
360 getComparingAttrs = p: {
361 inherit (p)
362 drvPath
363 name
364 pname
365 version
366 vendorHash
367 ;
368 goModules = {
369 inherit (p.goModules)
370 drvPath
371 name
372 outPath
373 ;
374 };
375 };
376 in
377 {
378 expr = getComparingAttrs pet_0_4_0-overridden;
379 expected = getComparingAttrs pet_0_4_0;
380 };
381 buildGoModule-goModules-overrideAttrs = {
382 expr = pet-foo.goModules.FOO;
383 expected = "foo";
384 };
385 buildGoModule-goModules-overrideAttrs-vendored = {
386 expr = lib.isString pet-vendored.drvPath;
387 expected = true;
388 };
389 };
390
391 tests-python =
392 let
393 package-stub = pkgs.python3Packages.callPackage (
394 {
395 buildPythonPackage,
396 emptyDirectory,
397 }:
398 buildPythonPackage {
399 pname = "python-package-stub";
400 version = "0.1.0";
401 pyproject = true;
402 src = emptyDirectory;
403 }
404 ) { };
405
406 package-stub-gcc = package-stub.override (previousArgs: {
407 buildPythonPackage = previousArgs.buildPythonPackage.override {
408 stdenv = pkgs.gccStdenv;
409 };
410 });
411 package-stub-clang = package-stub-gcc.override (previousArgs: {
412 buildPythonPackage = previousArgs.buildPythonPackage.override {
413 stdenv = pkgs.clangStdenv;
414 };
415 });
416 package-stub-libcxx = package-stub-clang.override (previousArgs: {
417 buildPythonPackage = previousArgs.buildPythonPackage.override {
418 stdenv = pkgs.libcxxStdenv;
419 };
420 });
421
422 applyOverridePythonAttrs =
423 p:
424 p.overridePythonAttrs (previousAttrs: {
425 overridePythonAttrsFlag = previousAttrs.overridePythonAttrsFlag or 0 + 1;
426 });
427 overrideAttrsFooBar =
428 drv:
429 drv.overrideAttrs (
430 finalAttrs: previousAttrs: {
431 FOO = "a";
432 BAR = finalAttrs.FOO;
433 }
434 );
435 in
436 {
437 buildPythonPackage-override-gccStdenv = {
438 expr = package-stub-gcc.stdenv;
439 expected = pkgs.gccStdenv;
440 };
441 buildPythonPackage-override-clangStdenv = {
442 expr = package-stub-clang.stdenv;
443 expected = pkgs.clangStdenv;
444 };
445 buildPythonPackage-override-libcxxStdenv = {
446 expr = package-stub-libcxx.stdenv;
447 expected = pkgs.libcxxStdenv;
448 };
449
450 overridePythonAttrs = {
451 expr = (applyOverridePythonAttrs package-stub).overridePythonAttrsFlag;
452 expected = 1;
453 };
454 overridePythonAttrs-nested = {
455 expr = (applyOverridePythonAttrs (applyOverridePythonAttrs package-stub)).overridePythonAttrsFlag;
456 expected = 2;
457 };
458 overrideAttrs-overridePythonAttrs-test-overrideAttrs = {
459 expr = {
460 inherit (applyOverridePythonAttrs (overrideAttrsFooBar package-stub))
461 FOO
462 BAR
463 ;
464 };
465 expected = {
466 FOO = "a";
467 BAR = "a";
468 };
469 };
470 overrideAttrs-overridePythonAttrs-test-overridePythonAttrs = {
471 expr = (applyOverridePythonAttrs (overrideAttrsFooBar package-stub)) ? overridePythonAttrsFlag;
472 expected = true;
473 };
474 overrideAttrs-overridePythonAttrs-test-commutation = {
475 expr = overrideAttrsFooBar (applyOverridePythonAttrs package-stub);
476 expected = applyOverridePythonAttrs (overrideAttrsFooBar package-stub);
477 };
478 chain-of-overrides = rec {
479 expr = lib.pipe package-stub [
480 (p: p.overrideAttrs { inherit (expected) a; })
481 (p: p.overridePythonAttrs { inherit (expected) b; })
482 (p: p.overrideAttrs { inherit (expected) c; })
483 (p: p.overridePythonAttrs { inherit (expected) d; })
484 (builtins.intersectAttrs expected)
485 ];
486 expected = lib.genAttrs [ "a" "b" "c" "d" ] lib.id;
487 };
488 };
489
490in
491
492stdenvNoCC.mkDerivation (finalAttrs: {
493 __structuredAttrs = true;
494 name = "test-overriding";
495 passthru = {
496 inherit tests;
497 failures = lib.runTests (finalAttrs.passthru.tests // { tests = lib.attrNames tests; });
498 };
499 testResults = lib.mapAttrs (testName: test: test.expr == test.expected) finalAttrs.passthru.tests;
500 buildCommand = ''
501 touch $out
502 for testName in "''${!testResults[@]}"; do
503 if [[ -n "''${testResults[$testName]}" ]]; then
504 echo "$testName success"
505 else
506 echo "$testName fail"
507 fi
508 done
509 ''
510 + lib.optionalString (lib.any (v: !v) (lib.attrValues finalAttrs.testResults)) ''
511 {
512 echo "ERROR: tests.overriding: Encountering failed tests."
513 for testName in "''${!testResults[@]}"; do
514 if [[ -z "''${testResults[$testName]}" ]]; then
515 echo "- $testName"
516 fi
517 done
518 echo "To inspect the expected and actual result, "
519 echo ' evaluate `tests.overriding.tests.''${testName}`.'
520 } >&2
521 exit 1
522 '';
523})