From 30dcc19d1f30fc203be460134c4578509cce704f Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 5 Oct 2023 12:12:18 -0400 Subject: Put functional tests in `tests/functional` I think it is bad for these reasons when `tests/` contains a mix of functional and integration tests - Concepts is harder to understand, the documentation makes a good unit vs functional vs integration distinction, but when the integration tests are just two subdirs within `tests/` this is not clear. - Source filtering in the `flake.nix` is more complex. We need to filter out some of the dirs from `tests/`, rather than simply pick the dirs we want and take all of them. This is a good sign the structure of what we are trying to do is not matching the structure of the files. With this change we have a clean: ```shell-session $ git show 'HEAD:tests' tree HEAD:tests functional/ installer/ nixos/ ``` (cherry picked from commit 68c81c737571794f7246db53fb4774e94fcf4b7e) --- .github/labeler.yml | 2 +- .gitignore | 36 +- CONTRIBUTING.md | 2 +- Makefile | 10 +- doc/manual/src/contributing/testing.md | 32 +- flake.nix | 52 +-- mk/common-test.sh | 8 +- src/libstore/gc.cc | 2 +- src/libutil/url-parts.hh | 2 +- tests/add.sh | 28 -- tests/bad.tar.xz | Bin 228 -> 0 bytes tests/bash-profile.sh | 9 - tests/big-derivation-attr.nix | 13 - tests/binary-cache-build-remote.sh | 16 - tests/binary-cache.sh | 286 ------------ tests/brotli.sh | 21 - tests/build-delete.sh | 54 --- tests/build-dry.sh | 67 --- tests/build-hook-ca-fixed.nix | 58 --- tests/build-hook-ca-floating.nix | 6 - tests/build-hook.nix | 59 --- tests/build-remote-content-addressed-fixed.sh | 5 - tests/build-remote-content-addressed-floating.sh | 9 - tests/build-remote-input-addressed.sh | 33 -- tests/build-remote-trustless-after.sh | 2 - tests/build-remote-trustless-should-fail-0.sh | 29 -- tests/build-remote-trustless-should-pass-0.sh | 9 - tests/build-remote-trustless-should-pass-1.sh | 9 - tests/build-remote-trustless-should-pass-2.sh | 13 - tests/build-remote-trustless-should-pass-3.sh | 14 - tests/build-remote-trustless.sh | 14 - tests/build-remote.sh | 84 ---- tests/build.sh | 135 ------ tests/ca-shell.nix | 1 - tests/ca/build-cache.sh | 51 -- tests/ca/build-dry.sh | 6 - tests/ca/build-with-garbage-path.sh | 21 - tests/ca/build.sh | 67 --- tests/ca/common.sh | 5 - tests/ca/concurrent-builds.sh | 18 - tests/ca/config.nix.in | 1 - tests/ca/content-addressed.nix | 100 ---- tests/ca/derivation-json.sh | 29 -- tests/ca/duplicate-realisation-in-closure.sh | 26 -- tests/ca/flake.nix | 3 - tests/ca/gc.sh | 10 - tests/ca/import-derivation.sh | 6 - tests/ca/local.mk | 28 -- tests/ca/new-build-cmd.sh | 5 - tests/ca/nix-copy.sh | 31 -- tests/ca/nix-run.sh | 7 - tests/ca/nix-shell.sh | 8 - tests/ca/nondeterministic.nix | 35 -- tests/ca/post-hook.sh | 11 - tests/ca/racy.nix | 15 - tests/ca/recursive.sh | 9 - tests/ca/repl.sh | 5 - tests/ca/selfref-gc.sh | 11 - tests/ca/signatures.sh | 36 -- tests/ca/substitute.sh | 71 --- tests/ca/why-depends.sh | 5 - tests/case-hack.sh | 19 - tests/case.nar | Bin 2416 -> 0 bytes tests/check-refs.nix | 77 ---- tests/check-refs.sh | 53 --- tests/check-reqs.nix | 57 --- tests/check-reqs.sh | 16 - tests/check.nix | 55 --- tests/check.sh | 91 ---- tests/common.sh | 12 - tests/common/vars-and-functions.sh.in | 276 ----------- tests/completions.sh | 68 --- tests/compression-levels.sh | 22 - tests/compute-levels.sh | 7 - tests/config.nix.in | 27 -- tests/config.sh | 58 --- tests/config/nix-with-substituters.conf | 2 - tests/db-migration.sh | 28 -- tests/dependencies.builder0.sh | 16 - tests/dependencies.nix | 48 -- tests/dependencies.sh | 72 --- tests/derivation-json.sh | 12 - tests/dummy | 1 - tests/dump-db.sh | 22 - tests/dyn-drv/build-built-drv.sh | 21 - tests/dyn-drv/common.sh | 8 - tests/dyn-drv/config.nix.in | 1 - tests/dyn-drv/dep-built-drv.sh | 11 - tests/dyn-drv/eval-outputOf.sh | 80 ---- tests/dyn-drv/local.mk | 15 - tests/dyn-drv/old-daemon-error-hack.nix | 20 - tests/dyn-drv/old-daemon-error-hack.sh | 11 - tests/dyn-drv/recursive-mod-json.nix | 33 -- tests/dyn-drv/recursive-mod-json.sh | 27 -- tests/dyn-drv/text-hashed-output.nix | 33 -- tests/dyn-drv/text-hashed-output.sh | 26 -- tests/eval-store.sh | 30 -- tests/eval.nix | 5 - tests/eval.sh | 43 -- tests/experimental-features.sh | 86 ---- tests/export-graph.nix | 29 -- tests/export-graph.sh | 30 -- tests/export.sh | 36 -- tests/failing.nix | 22 - tests/fetchClosure.sh | 150 ------ tests/fetchGit.sh | 256 ----------- tests/fetchGitRefs.sh | 108 ----- tests/fetchGitSubmodules.sh | 128 ------ tests/fetchMercurial.sh | 106 ----- tests/fetchPath.sh | 6 - tests/fetchTree-file.sh | 117 ----- tests/fetchurl.sh | 80 ---- tests/filter-source.nix | 12 - tests/filter-source.sh | 25 - tests/fixed.builder1.sh | 3 - tests/fixed.builder2.sh | 6 - tests/fixed.nix | 58 --- tests/fixed.sh | 58 --- tests/flakes/absolute-paths.sh | 17 - tests/flakes/build-paths.sh | 96 ---- tests/flakes/bundle.sh | 32 -- tests/flakes/check.sh | 91 ---- tests/flakes/circular.sh | 49 -- tests/flakes/common.sh | 70 --- tests/flakes/config.sh | 42 -- tests/flakes/flake-in-submodule.sh | 52 --- tests/flakes/flakes.sh | 511 --------------------- tests/flakes/follow-paths.sh | 232 ---------- tests/flakes/init.sh | 87 ---- tests/flakes/inputs.sh | 80 ---- tests/flakes/mercurial.sh | 43 -- tests/flakes/run.sh | 29 -- tests/flakes/search-root.sh | 50 -- tests/flakes/show.sh | 87 ---- tests/flakes/unlocked-override.sh | 30 -- tests/fmt.sh | 33 -- tests/fmt.simple.sh | 1 - tests/function-trace.sh | 67 --- tests/functional/add.sh | 28 ++ tests/functional/bad.tar.xz | Bin 0 -> 228 bytes tests/functional/bash-profile.sh | 9 + tests/functional/big-derivation-attr.nix | 13 + tests/functional/binary-cache-build-remote.sh | 16 + tests/functional/binary-cache.sh | 286 ++++++++++++ tests/functional/brotli.sh | 21 + tests/functional/build-delete.sh | 54 +++ tests/functional/build-dry.sh | 67 +++ tests/functional/build-hook-ca-fixed.nix | 58 +++ tests/functional/build-hook-ca-floating.nix | 6 + tests/functional/build-hook.nix | 59 +++ .../build-remote-content-addressed-fixed.sh | 5 + .../build-remote-content-addressed-floating.sh | 9 + tests/functional/build-remote-input-addressed.sh | 33 ++ tests/functional/build-remote-trustless-after.sh | 2 + .../build-remote-trustless-should-fail-0.sh | 29 ++ .../build-remote-trustless-should-pass-0.sh | 9 + .../build-remote-trustless-should-pass-1.sh | 9 + .../build-remote-trustless-should-pass-2.sh | 13 + .../build-remote-trustless-should-pass-3.sh | 14 + tests/functional/build-remote-trustless.sh | 14 + tests/functional/build-remote.sh | 84 ++++ tests/functional/build.sh | 135 ++++++ tests/functional/ca-shell.nix | 1 + tests/functional/ca/build-cache.sh | 51 ++ tests/functional/ca/build-dry.sh | 6 + tests/functional/ca/build-with-garbage-path.sh | 21 + tests/functional/ca/build.sh | 67 +++ tests/functional/ca/common.sh | 5 + tests/functional/ca/concurrent-builds.sh | 18 + tests/functional/ca/config.nix.in | 1 + tests/functional/ca/content-addressed.nix | 100 ++++ tests/functional/ca/derivation-json.sh | 29 ++ .../ca/duplicate-realisation-in-closure.sh | 26 ++ tests/functional/ca/flake.nix | 3 + tests/functional/ca/gc.sh | 10 + tests/functional/ca/import-derivation.sh | 6 + tests/functional/ca/local.mk | 28 ++ tests/functional/ca/new-build-cmd.sh | 5 + tests/functional/ca/nix-copy.sh | 31 ++ tests/functional/ca/nix-run.sh | 7 + tests/functional/ca/nix-shell.sh | 8 + tests/functional/ca/nondeterministic.nix | 35 ++ tests/functional/ca/post-hook.sh | 11 + tests/functional/ca/racy.nix | 15 + tests/functional/ca/recursive.sh | 9 + tests/functional/ca/repl.sh | 5 + tests/functional/ca/selfref-gc.sh | 11 + tests/functional/ca/signatures.sh | 36 ++ tests/functional/ca/substitute.sh | 71 +++ tests/functional/ca/why-depends.sh | 5 + tests/functional/case-hack.sh | 19 + tests/functional/case.nar | Bin 0 -> 2416 bytes tests/functional/check-refs.nix | 77 ++++ tests/functional/check-refs.sh | 53 +++ tests/functional/check-reqs.nix | 57 +++ tests/functional/check-reqs.sh | 16 + tests/functional/check.nix | 55 +++ tests/functional/check.sh | 91 ++++ tests/functional/common.sh | 12 + tests/functional/common/vars-and-functions.sh.in | 276 +++++++++++ tests/functional/completions.sh | 68 +++ tests/functional/compression-levels.sh | 22 + tests/functional/compute-levels.sh | 7 + tests/functional/config.nix.in | 27 ++ tests/functional/config.sh | 58 +++ tests/functional/config/nix-with-substituters.conf | 2 + tests/functional/db-migration.sh | 28 ++ tests/functional/dependencies.builder0.sh | 16 + tests/functional/dependencies.nix | 48 ++ tests/functional/dependencies.sh | 72 +++ tests/functional/derivation-json.sh | 12 + tests/functional/dummy | 1 + tests/functional/dump-db.sh | 22 + tests/functional/dyn-drv/build-built-drv.sh | 21 + tests/functional/dyn-drv/common.sh | 8 + tests/functional/dyn-drv/config.nix.in | 1 + tests/functional/dyn-drv/dep-built-drv.sh | 11 + tests/functional/dyn-drv/eval-outputOf.sh | 80 ++++ tests/functional/dyn-drv/local.mk | 15 + tests/functional/dyn-drv/old-daemon-error-hack.nix | 20 + tests/functional/dyn-drv/old-daemon-error-hack.sh | 11 + tests/functional/dyn-drv/recursive-mod-json.nix | 33 ++ tests/functional/dyn-drv/recursive-mod-json.sh | 27 ++ tests/functional/dyn-drv/text-hashed-output.nix | 33 ++ tests/functional/dyn-drv/text-hashed-output.sh | 26 ++ tests/functional/eval-store.sh | 30 ++ tests/functional/eval.nix | 5 + tests/functional/eval.sh | 43 ++ tests/functional/experimental-features.sh | 86 ++++ tests/functional/export-graph.nix | 29 ++ tests/functional/export-graph.sh | 30 ++ tests/functional/export.sh | 36 ++ tests/functional/failing.nix | 22 + tests/functional/fetchClosure.sh | 150 ++++++ tests/functional/fetchGit.sh | 256 +++++++++++ tests/functional/fetchGitRefs.sh | 108 +++++ tests/functional/fetchGitSubmodules.sh | 128 ++++++ tests/functional/fetchMercurial.sh | 106 +++++ tests/functional/fetchPath.sh | 6 + tests/functional/fetchTree-file.sh | 117 +++++ tests/functional/fetchurl.sh | 80 ++++ tests/functional/filter-source.nix | 12 + tests/functional/filter-source.sh | 25 + tests/functional/fixed.builder1.sh | 3 + tests/functional/fixed.builder2.sh | 6 + tests/functional/fixed.nix | 58 +++ tests/functional/fixed.sh | 58 +++ tests/functional/flakes/absolute-paths.sh | 17 + tests/functional/flakes/build-paths.sh | 96 ++++ tests/functional/flakes/bundle.sh | 32 ++ tests/functional/flakes/check.sh | 91 ++++ tests/functional/flakes/circular.sh | 49 ++ tests/functional/flakes/common.sh | 70 +++ tests/functional/flakes/config.sh | 42 ++ tests/functional/flakes/flake-in-submodule.sh | 52 +++ tests/functional/flakes/flakes.sh | 511 +++++++++++++++++++++ tests/functional/flakes/follow-paths.sh | 232 ++++++++++ tests/functional/flakes/init.sh | 87 ++++ tests/functional/flakes/inputs.sh | 80 ++++ tests/functional/flakes/mercurial.sh | 43 ++ tests/functional/flakes/run.sh | 29 ++ tests/functional/flakes/search-root.sh | 50 ++ tests/functional/flakes/show.sh | 87 ++++ tests/functional/flakes/unlocked-override.sh | 30 ++ tests/functional/fmt.sh | 33 ++ tests/functional/fmt.simple.sh | 1 + tests/functional/function-trace.sh | 67 +++ tests/functional/gc-auto.sh | 81 ++++ tests/functional/gc-concurrent.builder.sh | 16 + tests/functional/gc-concurrent.nix | 30 ++ tests/functional/gc-concurrent.sh | 59 +++ tests/functional/gc-concurrent2.builder.sh | 5 + tests/functional/gc-non-blocking.sh | 33 ++ tests/functional/gc-runtime.nix | 17 + tests/functional/gc-runtime.sh | 38 ++ tests/functional/gc.sh | 52 +++ tests/functional/hash-check.nix | 29 ++ tests/functional/hash.sh | 107 +++++ tests/functional/hermetic.nix | 56 +++ tests/functional/import-derivation.nix | 26 ++ tests/functional/import-derivation.sh | 12 + tests/functional/impure-derivations.nix | 63 +++ tests/functional/impure-derivations.sh | 65 +++ tests/functional/init.sh | 41 ++ tests/functional/install-darwin.sh | 96 ++++ tests/functional/lang-test-infra.sh | 86 ++++ tests/functional/lang.sh | 146 ++++++ tests/functional/lang/binary-data | Bin 0 -> 1024 bytes tests/functional/lang/data | 1 + tests/functional/lang/dir1/a.nix | 1 + tests/functional/lang/dir2/a.nix | 1 + tests/functional/lang/dir2/b.nix | 1 + tests/functional/lang/dir3/a.nix | 1 + tests/functional/lang/dir3/b.nix | 1 + tests/functional/lang/dir3/c.nix | 1 + tests/functional/lang/dir4/a.nix | 1 + tests/functional/lang/dir4/c.nix | 1 + tests/functional/lang/empty.exp | 0 tests/functional/lang/eval-fail-abort.err.exp | 10 + tests/functional/lang/eval-fail-abort.nix | 1 + .../lang/eval-fail-antiquoted-path.err.exp | 1 + tests/functional/lang/eval-fail-assert.err.exp | 36 ++ tests/functional/lang/eval-fail-assert.nix | 5 + .../lang/eval-fail-bad-antiquote-1.err.exp | 10 + .../lang/eval-fail-bad-antiquote-2.err.exp | 1 + .../lang/eval-fail-bad-antiquote-3.err.exp | 10 + .../eval-fail-bad-string-interpolation-1.err.exp | 10 + .../lang/eval-fail-bad-string-interpolation-1.nix | 1 + .../eval-fail-bad-string-interpolation-2.err.exp | 1 + .../lang/eval-fail-bad-string-interpolation-2.nix | 1 + .../eval-fail-bad-string-interpolation-3.err.exp | 10 + .../lang/eval-fail-bad-string-interpolation-3.nix | 1 + tests/functional/lang/eval-fail-blackhole.err.exp | 18 + tests/functional/lang/eval-fail-blackhole.nix | 5 + tests/functional/lang/eval-fail-deepseq.err.exp | 26 ++ tests/functional/lang/eval-fail-deepseq.nix | 1 + .../lang/eval-fail-dup-dynamic-attrs.err.exp | 8 + .../lang/eval-fail-dup-dynamic-attrs.nix | 4 + ...-fail-foldlStrict-strict-op-application.err.exp | 38 ++ ...eval-fail-foldlStrict-strict-op-application.nix | 5 + .../lang/eval-fail-fromTOML-timestamps.err.exp | 12 + .../lang/eval-fail-fromTOML-timestamps.nix | 130 ++++++ .../lang/eval-fail-hashfile-missing.err.exp | 19 + .../functional/lang/eval-fail-hashfile-missing.nix | 5 + tests/functional/lang/eval-fail-list.err.exp | 10 + tests/functional/lang/eval-fail-list.nix | 1 + .../functional/lang/eval-fail-missing-arg.err.exp | 16 + tests/functional/lang/eval-fail-missing-arg.nix | 1 + .../lang/eval-fail-nonexist-path.err.exp | 1 + tests/functional/lang/eval-fail-nonexist-path.nix | 4 + tests/functional/lang/eval-fail-path-slash.err.exp | 8 + tests/functional/lang/eval-fail-path-slash.nix | 6 + tests/functional/lang/eval-fail-recursion.err.exp | 16 + tests/functional/lang/eval-fail-recursion.nix | 1 + tests/functional/lang/eval-fail-remove.err.exp | 19 + tests/functional/lang/eval-fail-remove.nix | 5 + tests/functional/lang/eval-fail-scope-5.err.exp | 36 ++ tests/functional/lang/eval-fail-scope-5.nix | 10 + tests/functional/lang/eval-fail-seq.err.exp | 18 + tests/functional/lang/eval-fail-seq.nix | 1 + .../functional/lang/eval-fail-set-override.err.exp | 6 + tests/functional/lang/eval-fail-set-override.nix | 1 + tests/functional/lang/eval-fail-set.err.exp | 7 + tests/functional/lang/eval-fail-set.nix | 1 + tests/functional/lang/eval-fail-substring.err.exp | 12 + tests/functional/lang/eval-fail-substring.nix | 1 + tests/functional/lang/eval-fail-to-path.err.exp | 14 + tests/functional/lang/eval-fail-to-path.nix | 1 + tests/functional/lang/eval-fail-toJSON.err.exp | 57 +++ tests/functional/lang/eval-fail-toJSON.nix | 10 + .../lang/eval-fail-undeclared-arg.err.exp | 17 + tests/functional/lang/eval-fail-undeclared-arg.nix | 1 + tests/functional/lang/eval-okay-any-all.exp | 1 + tests/functional/lang/eval-okay-any-all.nix | 11 + tests/functional/lang/eval-okay-arithmetic.exp | 1 + tests/functional/lang/eval-okay-arithmetic.nix | 59 +++ tests/functional/lang/eval-okay-attrnames.exp | 1 + tests/functional/lang/eval-okay-attrnames.nix | 11 + tests/functional/lang/eval-okay-attrs.exp | 1 + tests/functional/lang/eval-okay-attrs.nix | 5 + tests/functional/lang/eval-okay-attrs2.exp | 1 + tests/functional/lang/eval-okay-attrs2.nix | 10 + tests/functional/lang/eval-okay-attrs3.exp | 1 + tests/functional/lang/eval-okay-attrs3.nix | 22 + tests/functional/lang/eval-okay-attrs4.exp | 1 + tests/functional/lang/eval-okay-attrs4.nix | 7 + tests/functional/lang/eval-okay-attrs5.exp | 1 + tests/functional/lang/eval-okay-attrs5.nix | 21 + tests/functional/lang/eval-okay-attrs6.exp | 1 + tests/functional/lang/eval-okay-attrs6.nix | 4 + tests/functional/lang/eval-okay-autoargs.exp | 1 + tests/functional/lang/eval-okay-autoargs.flags | 1 + tests/functional/lang/eval-okay-autoargs.nix | 15 + .../lang/eval-okay-backslash-newline-1.exp | 1 + .../lang/eval-okay-backslash-newline-1.nix | 2 + .../lang/eval-okay-backslash-newline-2.exp | 1 + .../lang/eval-okay-backslash-newline-2.nix | 2 + tests/functional/lang/eval-okay-builtins-add.exp | 1 + tests/functional/lang/eval-okay-builtins-add.nix | 8 + tests/functional/lang/eval-okay-builtins.exp | 1 + tests/functional/lang/eval-okay-builtins.nix | 12 + tests/functional/lang/eval-okay-callable-attrs.exp | 1 + tests/functional/lang/eval-okay-callable-attrs.nix | 1 + tests/functional/lang/eval-okay-catattrs.exp | 1 + tests/functional/lang/eval-okay-catattrs.nix | 1 + tests/functional/lang/eval-okay-closure.exp | 1 + tests/functional/lang/eval-okay-closure.exp.xml | 343 ++++++++++++++ tests/functional/lang/eval-okay-closure.nix | 13 + tests/functional/lang/eval-okay-comments.exp | 1 + tests/functional/lang/eval-okay-comments.nix | 59 +++ tests/functional/lang/eval-okay-concat.exp | 1 + tests/functional/lang/eval-okay-concat.nix | 1 + tests/functional/lang/eval-okay-concatmap.exp | 1 + tests/functional/lang/eval-okay-concatmap.nix | 5 + .../functional/lang/eval-okay-concatstringssep.exp | 1 + .../functional/lang/eval-okay-concatstringssep.nix | 8 + .../lang/eval-okay-context-introspection.exp | 1 + .../lang/eval-okay-context-introspection.nix | 41 ++ tests/functional/lang/eval-okay-context.exp | 1 + tests/functional/lang/eval-okay-context.nix | 6 + tests/functional/lang/eval-okay-curpos.exp | 1 + tests/functional/lang/eval-okay-curpos.nix | 5 + tests/functional/lang/eval-okay-deepseq.exp | 1 + tests/functional/lang/eval-okay-deepseq.nix | 1 + .../lang/eval-okay-delayed-with-inherit.exp | 1 + .../lang/eval-okay-delayed-with-inherit.nix | 24 + tests/functional/lang/eval-okay-delayed-with.exp | 1 + tests/functional/lang/eval-okay-delayed-with.nix | 29 ++ .../functional/lang/eval-okay-dynamic-attrs-2.exp | 1 + .../functional/lang/eval-okay-dynamic-attrs-2.nix | 1 + .../lang/eval-okay-dynamic-attrs-bare.exp | 1 + .../lang/eval-okay-dynamic-attrs-bare.nix | 17 + tests/functional/lang/eval-okay-dynamic-attrs.exp | 1 + tests/functional/lang/eval-okay-dynamic-attrs.nix | 17 + tests/functional/lang/eval-okay-elem.exp | 1 + tests/functional/lang/eval-okay-elem.nix | 6 + tests/functional/lang/eval-okay-empty-args.exp | 1 + tests/functional/lang/eval-okay-empty-args.nix | 1 + tests/functional/lang/eval-okay-eq-derivations.exp | 1 + tests/functional/lang/eval-okay-eq-derivations.nix | 10 + tests/functional/lang/eval-okay-eq.exp | 1 + tests/functional/lang/eval-okay-eq.nix | 3 + tests/functional/lang/eval-okay-filter.exp | 1 + tests/functional/lang/eval-okay-filter.nix | 5 + .../lang/eval-okay-flake-ref-to-string.exp | 1 + .../lang/eval-okay-flake-ref-to-string.nix | 7 + tests/functional/lang/eval-okay-flatten.exp | 1 + tests/functional/lang/eval-okay-flatten.nix | 8 + tests/functional/lang/eval-okay-float.exp | 1 + tests/functional/lang/eval-okay-float.nix | 6 + tests/functional/lang/eval-okay-floor-ceil.exp | 1 + tests/functional/lang/eval-okay-floor-ceil.nix | 9 + .../lang/eval-okay-foldlStrict-lazy-elements.exp | 1 + .../lang/eval-okay-foldlStrict-lazy-elements.nix | 9 + ...l-okay-foldlStrict-lazy-initial-accumulator.exp | 1 + ...l-okay-foldlStrict-lazy-initial-accumulator.nix | 6 + tests/functional/lang/eval-okay-foldlStrict.exp | 1 + tests/functional/lang/eval-okay-foldlStrict.nix | 3 + .../lang/eval-okay-fromTOML-timestamps.exp | 1 + .../lang/eval-okay-fromTOML-timestamps.flags | 1 + .../lang/eval-okay-fromTOML-timestamps.nix | 130 ++++++ tests/functional/lang/eval-okay-fromTOML.exp | 1 + tests/functional/lang/eval-okay-fromTOML.nix | 208 +++++++++ .../functional/lang/eval-okay-fromjson-escapes.exp | 1 + .../functional/lang/eval-okay-fromjson-escapes.nix | 3 + tests/functional/lang/eval-okay-fromjson.exp | 1 + tests/functional/lang/eval-okay-fromjson.nix | 41 ++ tests/functional/lang/eval-okay-functionargs.exp | 1 + .../functional/lang/eval-okay-functionargs.exp.xml | 15 + tests/functional/lang/eval-okay-functionargs.nix | 80 ++++ .../lang/eval-okay-getattrpos-functionargs.exp | 1 + .../lang/eval-okay-getattrpos-functionargs.nix | 4 + .../lang/eval-okay-getattrpos-undefined.exp | 1 + .../lang/eval-okay-getattrpos-undefined.nix | 1 + tests/functional/lang/eval-okay-getattrpos.exp | 1 + tests/functional/lang/eval-okay-getattrpos.nix | 6 + tests/functional/lang/eval-okay-getenv.exp | 1 + tests/functional/lang/eval-okay-getenv.nix | 1 + tests/functional/lang/eval-okay-groupBy.exp | 1 + tests/functional/lang/eval-okay-groupBy.nix | 5 + tests/functional/lang/eval-okay-hash.exp | 0 tests/functional/lang/eval-okay-hashfile.exp | 1 + tests/functional/lang/eval-okay-hashfile.nix | 4 + tests/functional/lang/eval-okay-hashstring.exp | 1 + tests/functional/lang/eval-okay-hashstring.nix | 4 + tests/functional/lang/eval-okay-if.exp | 1 + tests/functional/lang/eval-okay-if.nix | 1 + tests/functional/lang/eval-okay-import.exp | 1 + tests/functional/lang/eval-okay-import.nix | 11 + tests/functional/lang/eval-okay-ind-string.exp | 1 + tests/functional/lang/eval-okay-ind-string.nix | 128 ++++++ tests/functional/lang/eval-okay-intersectAttrs.exp | 1 + tests/functional/lang/eval-okay-intersectAttrs.nix | 50 ++ tests/functional/lang/eval-okay-let.exp | 1 + tests/functional/lang/eval-okay-let.nix | 5 + tests/functional/lang/eval-okay-list.exp | 1 + tests/functional/lang/eval-okay-list.nix | 7 + tests/functional/lang/eval-okay-listtoattrs.exp | 1 + tests/functional/lang/eval-okay-listtoattrs.nix | 11 + tests/functional/lang/eval-okay-logic.exp | 1 + tests/functional/lang/eval-okay-logic.nix | 1 + tests/functional/lang/eval-okay-map.exp | 1 + tests/functional/lang/eval-okay-map.nix | 3 + tests/functional/lang/eval-okay-mapattrs.exp | 1 + tests/functional/lang/eval-okay-mapattrs.nix | 3 + .../lang/eval-okay-merge-dynamic-attrs.exp | 1 + .../lang/eval-okay-merge-dynamic-attrs.nix | 13 + tests/functional/lang/eval-okay-nested-with.exp | 1 + tests/functional/lang/eval-okay-nested-with.nix | 3 + tests/functional/lang/eval-okay-new-let.exp | 1 + tests/functional/lang/eval-okay-new-let.nix | 14 + .../lang/eval-okay-null-dynamic-attrs.exp | 1 + .../lang/eval-okay-null-dynamic-attrs.nix | 1 + tests/functional/lang/eval-okay-overrides.exp | 1 + tests/functional/lang/eval-okay-overrides.nix | 9 + .../functional/lang/eval-okay-parse-flake-ref.exp | 1 + .../functional/lang/eval-okay-parse-flake-ref.nix | 1 + tests/functional/lang/eval-okay-partition.exp | 1 + tests/functional/lang/eval-okay-partition.nix | 5 + .../lang/eval-okay-path-string-interpolation.exp | 1 + .../lang/eval-okay-path-string-interpolation.nix | 12 + tests/functional/lang/eval-okay-path.exp | 1 + tests/functional/lang/eval-okay-path.nix | 7 + tests/functional/lang/eval-okay-pathexists.exp | 1 + tests/functional/lang/eval-okay-pathexists.nix | 29 ++ tests/functional/lang/eval-okay-patterns.exp | 1 + tests/functional/lang/eval-okay-patterns.nix | 16 + tests/functional/lang/eval-okay-print.err.exp | 1 + tests/functional/lang/eval-okay-print.exp | 1 + tests/functional/lang/eval-okay-print.nix | 1 + tests/functional/lang/eval-okay-readDir.exp | 1 + tests/functional/lang/eval-okay-readDir.nix | 1 + tests/functional/lang/eval-okay-readFileType.exp | 1 + tests/functional/lang/eval-okay-readFileType.nix | 6 + tests/functional/lang/eval-okay-readfile.exp | 1 + tests/functional/lang/eval-okay-readfile.nix | 1 + .../functional/lang/eval-okay-redefine-builtin.exp | 1 + .../functional/lang/eval-okay-redefine-builtin.nix | 3 + tests/functional/lang/eval-okay-regex-match.exp | 1 + tests/functional/lang/eval-okay-regex-match.nix | 29 ++ tests/functional/lang/eval-okay-regex-split.exp | 1 + tests/functional/lang/eval-okay-regex-split.nix | 48 ++ .../lang/eval-okay-regression-20220122.exp | 1 + .../lang/eval-okay-regression-20220122.nix | 1 + .../lang/eval-okay-regression-20220125.exp | 1 + .../lang/eval-okay-regression-20220125.nix | 2 + tests/functional/lang/eval-okay-remove.exp | 1 + tests/functional/lang/eval-okay-remove.nix | 5 + tests/functional/lang/eval-okay-replacestrings.exp | 1 + tests/functional/lang/eval-okay-replacestrings.nix | 12 + tests/functional/lang/eval-okay-scope-1.exp | 1 + tests/functional/lang/eval-okay-scope-1.nix | 6 + tests/functional/lang/eval-okay-scope-2.exp | 1 + tests/functional/lang/eval-okay-scope-2.nix | 6 + tests/functional/lang/eval-okay-scope-3.exp | 1 + tests/functional/lang/eval-okay-scope-3.nix | 6 + tests/functional/lang/eval-okay-scope-4.exp | 1 + tests/functional/lang/eval-okay-scope-4.nix | 10 + tests/functional/lang/eval-okay-scope-6.exp | 1 + tests/functional/lang/eval-okay-scope-6.nix | 7 + tests/functional/lang/eval-okay-scope-7.exp | 1 + tests/functional/lang/eval-okay-scope-7.nix | 6 + tests/functional/lang/eval-okay-search-path.exp | 1 + tests/functional/lang/eval-okay-search-path.flags | 1 + tests/functional/lang/eval-okay-search-path.nix | 10 + tests/functional/lang/eval-okay-seq.exp | 1 + tests/functional/lang/eval-okay-seq.nix | 1 + tests/functional/lang/eval-okay-sort.exp | 1 + tests/functional/lang/eval-okay-sort.nix | 20 + tests/functional/lang/eval-okay-splitversion.exp | 1 + tests/functional/lang/eval-okay-splitversion.nix | 1 + tests/functional/lang/eval-okay-string.exp | 1 + tests/functional/lang/eval-okay-string.nix | 12 + .../lang/eval-okay-strings-as-attrs-names.exp | 1 + .../lang/eval-okay-strings-as-attrs-names.nix | 20 + tests/functional/lang/eval-okay-substring.exp | 1 + tests/functional/lang/eval-okay-substring.nix | 21 + .../lang/eval-okay-tail-call-1.exp-disabled | 1 + tests/functional/lang/eval-okay-tail-call-1.nix | 3 + tests/functional/lang/eval-okay-tojson.exp | 1 + tests/functional/lang/eval-okay-tojson.nix | 13 + tests/functional/lang/eval-okay-toxml.exp | 1 + tests/functional/lang/eval-okay-toxml.nix | 3 + tests/functional/lang/eval-okay-toxml2.exp | 1 + tests/functional/lang/eval-okay-toxml2.nix | 1 + tests/functional/lang/eval-okay-tryeval.exp | 1 + tests/functional/lang/eval-okay-tryeval.nix | 5 + tests/functional/lang/eval-okay-types.exp | 1 + tests/functional/lang/eval-okay-types.nix | 37 ++ tests/functional/lang/eval-okay-versions.exp | 1 + tests/functional/lang/eval-okay-versions.nix | 43 ++ tests/functional/lang/eval-okay-with.exp | 1 + tests/functional/lang/eval-okay-with.nix | 19 + tests/functional/lang/eval-okay-xml.exp.xml | 52 +++ tests/functional/lang/eval-okay-xml.nix | 21 + tests/functional/lang/eval-okay-zipAttrsWith.exp | 1 + tests/functional/lang/eval-okay-zipAttrsWith.nix | 9 + tests/functional/lang/framework.sh | 33 ++ tests/functional/lang/imported.nix | 3 + tests/functional/lang/imported2.nix | 1 + tests/functional/lang/lib.nix | 61 +++ .../functional/lang/parse-fail-dup-attrs-1.err.exp | 7 + tests/functional/lang/parse-fail-dup-attrs-1.nix | 4 + .../functional/lang/parse-fail-dup-attrs-2.err.exp | 7 + tests/functional/lang/parse-fail-dup-attrs-2.nix | 13 + .../functional/lang/parse-fail-dup-attrs-3.err.exp | 7 + tests/functional/lang/parse-fail-dup-attrs-3.nix | 13 + .../functional/lang/parse-fail-dup-attrs-4.err.exp | 7 + tests/functional/lang/parse-fail-dup-attrs-4.nix | 4 + .../functional/lang/parse-fail-dup-attrs-6.err.exp | 1 + .../functional/lang/parse-fail-dup-attrs-7.err.exp | 7 + tests/functional/lang/parse-fail-dup-attrs-7.nix | 9 + .../functional/lang/parse-fail-dup-formals.err.exp | 6 + tests/functional/lang/parse-fail-dup-formals.nix | 1 + .../lang/parse-fail-eof-in-string.err.exp | 7 + tests/functional/lang/parse-fail-eof-in-string.nix | 3 + .../lang/parse-fail-mixed-nested-attrs1.err.exp | 8 + .../lang/parse-fail-mixed-nested-attrs1.nix | 4 + .../lang/parse-fail-mixed-nested-attrs2.err.exp | 8 + .../lang/parse-fail-mixed-nested-attrs2.nix | 4 + .../functional/lang/parse-fail-patterns-1.err.exp | 7 + tests/functional/lang/parse-fail-patterns-1.nix | 1 + .../lang/parse-fail-regression-20060610.err.exp | 8 + .../lang/parse-fail-regression-20060610.nix | 11 + .../functional/lang/parse-fail-undef-var-2.err.exp | 7 + tests/functional/lang/parse-fail-undef-var-2.nix | 7 + tests/functional/lang/parse-fail-undef-var.err.exp | 7 + tests/functional/lang/parse-fail-undef-var.nix | 1 + tests/functional/lang/parse-fail-utf8.err.exp | 6 + tests/functional/lang/parse-fail-utf8.nix | 1 + tests/functional/lang/parse-okay-1.exp | 1 + tests/functional/lang/parse-okay-1.nix | 1 + tests/functional/lang/parse-okay-crlf.exp | 1 + tests/functional/lang/parse-okay-crlf.nix | 17 + tests/functional/lang/parse-okay-dup-attrs-5.exp | 1 + tests/functional/lang/parse-okay-dup-attrs-5.nix | 4 + tests/functional/lang/parse-okay-dup-attrs-6.exp | 1 + tests/functional/lang/parse-okay-dup-attrs-6.nix | 4 + .../lang/parse-okay-mixed-nested-attrs-1.exp | 1 + .../lang/parse-okay-mixed-nested-attrs-1.nix | 4 + .../lang/parse-okay-mixed-nested-attrs-2.exp | 1 + .../lang/parse-okay-mixed-nested-attrs-2.nix | 4 + .../lang/parse-okay-mixed-nested-attrs-3.exp | 1 + .../lang/parse-okay-mixed-nested-attrs-3.nix | 7 + .../lang/parse-okay-regression-20041027.exp | 1 + .../lang/parse-okay-regression-20041027.nix | 11 + .../functional/lang/parse-okay-regression-751.exp | 1 + .../functional/lang/parse-okay-regression-751.nix | 2 + tests/functional/lang/parse-okay-subversion.exp | 1 + tests/functional/lang/parse-okay-subversion.nix | 43 ++ tests/functional/lang/parse-okay-url.exp | 1 + tests/functional/lang/parse-okay-url.nix | 8 + tests/functional/lang/readDir/bar | 0 .../lang/readDir/foo/git-hates-directories | 0 tests/functional/lang/readDir/ldir | 1 + tests/functional/lang/readDir/linked | 1 + tests/functional/legacy-ssh-store.sh | 4 + tests/functional/linux-sandbox-cert-test.nix | 30 ++ tests/functional/linux-sandbox.sh | 75 +++ tests/functional/local-store.sh | 22 + tests/functional/local.mk | 146 ++++++ tests/functional/logging.sh | 26 ++ tests/functional/misc.sh | 32 ++ tests/functional/multiple-outputs.nix | 130 ++++++ tests/functional/multiple-outputs.sh | 88 ++++ tests/functional/nar-access.nix | 23 + tests/functional/nar-access.sh | 56 +++ tests/functional/nested-sandboxing.sh | 11 + tests/functional/nested-sandboxing/command.sh | 29 ++ tests/functional/nested-sandboxing/runner.nix | 24 + tests/functional/nix-build-examples.nix | 33 ++ tests/functional/nix-build.sh | 43 ++ tests/functional/nix-channel.sh | 66 +++ tests/functional/nix-collect-garbage-d.sh | 40 ++ tests/functional/nix-copy-ssh-ng.sh | 18 + tests/functional/nix-copy-ssh.sh | 20 + tests/functional/nix-daemon-untrusting.sh | 3 + tests/functional/nix-profile.sh | 187 ++++++++ tests/functional/nix-shell.sh | 147 ++++++ tests/functional/nix_path.sh | 14 + tests/functional/optimise-store.sh | 44 ++ tests/functional/output-normalization.sh | 9 + tests/functional/parallel.builder.sh | 29 ++ tests/functional/parallel.nix | 19 + tests/functional/parallel.sh | 56 +++ tests/functional/pass-as-file.sh | 18 + tests/functional/path-from-hash-part.sh | 10 + tests/functional/path.nix | 14 + tests/functional/placeholders.sh | 20 + tests/functional/plugins.sh | 9 + tests/functional/plugins/local.mk | 11 + tests/functional/plugins/plugintest.cc | 28 ++ tests/functional/post-hook.sh | 31 ++ tests/functional/pure-eval.nix | 3 + tests/functional/pure-eval.sh | 34 ++ tests/functional/push-to-store-old.sh | 14 + tests/functional/push-to-store.sh | 14 + tests/functional/read-only-store.sh | 42 ++ tests/functional/readfile-context.nix | 28 ++ tests/functional/readfile-context.sh | 16 + tests/functional/recursive.nix | 56 +++ tests/functional/recursive.sh | 19 + tests/functional/referrers.sh | 38 ++ tests/functional/remote-store.sh | 43 ++ tests/functional/repair.sh | 123 +++++ tests/functional/repl.sh | 179 ++++++++ tests/functional/restricted.nix | 1 + tests/functional/restricted.sh | 53 +++ tests/functional/search.nix | 25 + tests/functional/search.sh | 46 ++ tests/functional/secure-drv-outputs.nix | 23 + tests/functional/secure-drv-outputs.sh | 36 ++ tests/functional/selfref-gc.sh | 30 ++ tests/functional/shell-hello.nix | 26 ++ tests/functional/shell.nix | 90 ++++ tests/functional/shell.sh | 32 ++ tests/functional/shell.shebang.rb | 7 + tests/functional/shell.shebang.sh | 4 + tests/functional/signing.sh | 109 +++++ tests/functional/simple-failing.nix | 12 + tests/functional/simple.builder.sh | 11 + tests/functional/simple.nix | 8 + tests/functional/simple.sh | 33 ++ tests/functional/ssh-relay.sh | 16 + tests/functional/store-ping.sh | 17 + tests/functional/structured-attrs-shell.nix | 21 + tests/functional/structured-attrs.nix | 70 +++ tests/functional/structured-attrs.sh | 23 + tests/functional/substitute-with-invalid-ca.sh | 38 ++ tests/functional/suggestions.sh | 44 ++ tests/functional/supplementary-groups.sh | 37 ++ tests/functional/tarball.sh | 64 +++ tests/functional/test-infra.sh | 85 ++++ tests/functional/test-libstoreconsumer.sh | 6 + tests/functional/test-libstoreconsumer/README.md | 6 + tests/functional/test-libstoreconsumer/local.mk | 15 + tests/functional/test-libstoreconsumer/main.cc | 45 ++ tests/functional/timeout.nix | 31 ++ tests/functional/timeout.sh | 39 ++ tests/functional/toString-path.sh | 8 + tests/functional/undefined-variable.nix | 1 + tests/functional/user-envs-migration.sh | 35 ++ tests/functional/user-envs.builder.sh | 5 + tests/functional/user-envs.nix | 34 ++ tests/functional/user-envs.sh | 190 ++++++++ tests/functional/why-depends.sh | 29 ++ tests/functional/zstd.sh | 28 ++ tests/gc-auto.sh | 81 ---- tests/gc-concurrent.builder.sh | 16 - tests/gc-concurrent.nix | 30 -- tests/gc-concurrent.sh | 59 --- tests/gc-concurrent2.builder.sh | 5 - tests/gc-non-blocking.sh | 33 -- tests/gc-runtime.nix | 17 - tests/gc-runtime.sh | 38 -- tests/gc.sh | 52 --- tests/hash-check.nix | 29 -- tests/hash.sh | 107 ----- tests/hermetic.nix | 56 --- tests/import-derivation.nix | 26 -- tests/import-derivation.sh | 12 - tests/impure-derivations.nix | 63 --- tests/impure-derivations.sh | 65 --- tests/init.sh | 41 -- tests/install-darwin.sh | 96 ---- tests/lang-test-infra.sh | 86 ---- tests/lang.sh | 146 ------ tests/lang/binary-data | Bin 1024 -> 0 bytes tests/lang/data | 1 - tests/lang/dir1/a.nix | 1 - tests/lang/dir2/a.nix | 1 - tests/lang/dir2/b.nix | 1 - tests/lang/dir3/a.nix | 1 - tests/lang/dir3/b.nix | 1 - tests/lang/dir3/c.nix | 1 - tests/lang/dir4/a.nix | 1 - tests/lang/dir4/c.nix | 1 - tests/lang/empty.exp | 0 tests/lang/eval-fail-abort.err.exp | 10 - tests/lang/eval-fail-abort.nix | 1 - tests/lang/eval-fail-antiquoted-path.err.exp | 1 - tests/lang/eval-fail-assert.err.exp | 36 -- tests/lang/eval-fail-assert.nix | 5 - tests/lang/eval-fail-bad-antiquote-1.err.exp | 10 - tests/lang/eval-fail-bad-antiquote-2.err.exp | 1 - tests/lang/eval-fail-bad-antiquote-3.err.exp | 10 - .../eval-fail-bad-string-interpolation-1.err.exp | 10 - .../lang/eval-fail-bad-string-interpolation-1.nix | 1 - .../eval-fail-bad-string-interpolation-2.err.exp | 1 - .../lang/eval-fail-bad-string-interpolation-2.nix | 1 - .../eval-fail-bad-string-interpolation-3.err.exp | 10 - .../lang/eval-fail-bad-string-interpolation-3.nix | 1 - tests/lang/eval-fail-blackhole.err.exp | 18 - tests/lang/eval-fail-blackhole.nix | 5 - tests/lang/eval-fail-deepseq.err.exp | 26 -- tests/lang/eval-fail-deepseq.nix | 1 - tests/lang/eval-fail-dup-dynamic-attrs.err.exp | 8 - tests/lang/eval-fail-dup-dynamic-attrs.nix | 4 - ...-fail-foldlStrict-strict-op-application.err.exp | 38 -- ...eval-fail-foldlStrict-strict-op-application.nix | 5 - tests/lang/eval-fail-fromTOML-timestamps.err.exp | 12 - tests/lang/eval-fail-fromTOML-timestamps.nix | 130 ------ tests/lang/eval-fail-hashfile-missing.err.exp | 19 - tests/lang/eval-fail-hashfile-missing.nix | 5 - tests/lang/eval-fail-list.err.exp | 10 - tests/lang/eval-fail-list.nix | 1 - tests/lang/eval-fail-missing-arg.err.exp | 16 - tests/lang/eval-fail-missing-arg.nix | 1 - tests/lang/eval-fail-nonexist-path.err.exp | 1 - tests/lang/eval-fail-nonexist-path.nix | 4 - tests/lang/eval-fail-path-slash.err.exp | 8 - tests/lang/eval-fail-path-slash.nix | 6 - tests/lang/eval-fail-recursion.err.exp | 16 - tests/lang/eval-fail-recursion.nix | 1 - tests/lang/eval-fail-remove.err.exp | 19 - tests/lang/eval-fail-remove.nix | 5 - tests/lang/eval-fail-scope-5.err.exp | 36 -- tests/lang/eval-fail-scope-5.nix | 10 - tests/lang/eval-fail-seq.err.exp | 18 - tests/lang/eval-fail-seq.nix | 1 - tests/lang/eval-fail-set-override.err.exp | 6 - tests/lang/eval-fail-set-override.nix | 1 - tests/lang/eval-fail-set.err.exp | 7 - tests/lang/eval-fail-set.nix | 1 - tests/lang/eval-fail-substring.err.exp | 12 - tests/lang/eval-fail-substring.nix | 1 - tests/lang/eval-fail-to-path.err.exp | 14 - tests/lang/eval-fail-to-path.nix | 1 - tests/lang/eval-fail-toJSON.err.exp | 57 --- tests/lang/eval-fail-toJSON.nix | 10 - tests/lang/eval-fail-undeclared-arg.err.exp | 17 - tests/lang/eval-fail-undeclared-arg.nix | 1 - tests/lang/eval-okay-any-all.exp | 1 - tests/lang/eval-okay-any-all.nix | 11 - tests/lang/eval-okay-arithmetic.exp | 1 - tests/lang/eval-okay-arithmetic.nix | 59 --- tests/lang/eval-okay-attrnames.exp | 1 - tests/lang/eval-okay-attrnames.nix | 11 - tests/lang/eval-okay-attrs.exp | 1 - tests/lang/eval-okay-attrs.nix | 5 - tests/lang/eval-okay-attrs2.exp | 1 - tests/lang/eval-okay-attrs2.nix | 10 - tests/lang/eval-okay-attrs3.exp | 1 - tests/lang/eval-okay-attrs3.nix | 22 - tests/lang/eval-okay-attrs4.exp | 1 - tests/lang/eval-okay-attrs4.nix | 7 - tests/lang/eval-okay-attrs5.exp | 1 - tests/lang/eval-okay-attrs5.nix | 21 - tests/lang/eval-okay-attrs6.exp | 1 - tests/lang/eval-okay-attrs6.nix | 4 - tests/lang/eval-okay-autoargs.exp | 1 - tests/lang/eval-okay-autoargs.flags | 1 - tests/lang/eval-okay-autoargs.nix | 15 - tests/lang/eval-okay-backslash-newline-1.exp | 1 - tests/lang/eval-okay-backslash-newline-1.nix | 2 - tests/lang/eval-okay-backslash-newline-2.exp | 1 - tests/lang/eval-okay-backslash-newline-2.nix | 2 - tests/lang/eval-okay-builtins-add.exp | 1 - tests/lang/eval-okay-builtins-add.nix | 8 - tests/lang/eval-okay-builtins.exp | 1 - tests/lang/eval-okay-builtins.nix | 12 - tests/lang/eval-okay-callable-attrs.exp | 1 - tests/lang/eval-okay-callable-attrs.nix | 1 - tests/lang/eval-okay-catattrs.exp | 1 - tests/lang/eval-okay-catattrs.nix | 1 - tests/lang/eval-okay-closure.exp | 1 - tests/lang/eval-okay-closure.exp.xml | 343 -------------- tests/lang/eval-okay-closure.nix | 13 - tests/lang/eval-okay-comments.exp | 1 - tests/lang/eval-okay-comments.nix | 59 --- tests/lang/eval-okay-concat.exp | 1 - tests/lang/eval-okay-concat.nix | 1 - tests/lang/eval-okay-concatmap.exp | 1 - tests/lang/eval-okay-concatmap.nix | 5 - tests/lang/eval-okay-concatstringssep.exp | 1 - tests/lang/eval-okay-concatstringssep.nix | 8 - tests/lang/eval-okay-context-introspection.exp | 1 - tests/lang/eval-okay-context-introspection.nix | 41 -- tests/lang/eval-okay-context.exp | 1 - tests/lang/eval-okay-context.nix | 6 - tests/lang/eval-okay-curpos.exp | 1 - tests/lang/eval-okay-curpos.nix | 5 - tests/lang/eval-okay-deepseq.exp | 1 - tests/lang/eval-okay-deepseq.nix | 1 - tests/lang/eval-okay-delayed-with-inherit.exp | 1 - tests/lang/eval-okay-delayed-with-inherit.nix | 24 - tests/lang/eval-okay-delayed-with.exp | 1 - tests/lang/eval-okay-delayed-with.nix | 29 -- tests/lang/eval-okay-dynamic-attrs-2.exp | 1 - tests/lang/eval-okay-dynamic-attrs-2.nix | 1 - tests/lang/eval-okay-dynamic-attrs-bare.exp | 1 - tests/lang/eval-okay-dynamic-attrs-bare.nix | 17 - tests/lang/eval-okay-dynamic-attrs.exp | 1 - tests/lang/eval-okay-dynamic-attrs.nix | 17 - tests/lang/eval-okay-elem.exp | 1 - tests/lang/eval-okay-elem.nix | 6 - tests/lang/eval-okay-empty-args.exp | 1 - tests/lang/eval-okay-empty-args.nix | 1 - tests/lang/eval-okay-eq-derivations.exp | 1 - tests/lang/eval-okay-eq-derivations.nix | 10 - tests/lang/eval-okay-eq.exp | 1 - tests/lang/eval-okay-eq.nix | 3 - tests/lang/eval-okay-filter.exp | 1 - tests/lang/eval-okay-filter.nix | 5 - tests/lang/eval-okay-flake-ref-to-string.exp | 1 - tests/lang/eval-okay-flake-ref-to-string.nix | 7 - tests/lang/eval-okay-flatten.exp | 1 - tests/lang/eval-okay-flatten.nix | 8 - tests/lang/eval-okay-float.exp | 1 - tests/lang/eval-okay-float.nix | 6 - tests/lang/eval-okay-floor-ceil.exp | 1 - tests/lang/eval-okay-floor-ceil.nix | 9 - tests/lang/eval-okay-foldlStrict-lazy-elements.exp | 1 - tests/lang/eval-okay-foldlStrict-lazy-elements.nix | 9 - ...l-okay-foldlStrict-lazy-initial-accumulator.exp | 1 - ...l-okay-foldlStrict-lazy-initial-accumulator.nix | 6 - tests/lang/eval-okay-foldlStrict.exp | 1 - tests/lang/eval-okay-foldlStrict.nix | 3 - tests/lang/eval-okay-fromTOML-timestamps.exp | 1 - tests/lang/eval-okay-fromTOML-timestamps.flags | 1 - tests/lang/eval-okay-fromTOML-timestamps.nix | 130 ------ tests/lang/eval-okay-fromTOML.exp | 1 - tests/lang/eval-okay-fromTOML.nix | 208 --------- tests/lang/eval-okay-fromjson-escapes.exp | 1 - tests/lang/eval-okay-fromjson-escapes.nix | 3 - tests/lang/eval-okay-fromjson.exp | 1 - tests/lang/eval-okay-fromjson.nix | 41 -- tests/lang/eval-okay-functionargs.exp | 1 - tests/lang/eval-okay-functionargs.exp.xml | 15 - tests/lang/eval-okay-functionargs.nix | 80 ---- tests/lang/eval-okay-getattrpos-functionargs.exp | 1 - tests/lang/eval-okay-getattrpos-functionargs.nix | 4 - tests/lang/eval-okay-getattrpos-undefined.exp | 1 - tests/lang/eval-okay-getattrpos-undefined.nix | 1 - tests/lang/eval-okay-getattrpos.exp | 1 - tests/lang/eval-okay-getattrpos.nix | 6 - tests/lang/eval-okay-getenv.exp | 1 - tests/lang/eval-okay-getenv.nix | 1 - tests/lang/eval-okay-groupBy.exp | 1 - tests/lang/eval-okay-groupBy.nix | 5 - tests/lang/eval-okay-hash.exp | 0 tests/lang/eval-okay-hashfile.exp | 1 - tests/lang/eval-okay-hashfile.nix | 4 - tests/lang/eval-okay-hashstring.exp | 1 - tests/lang/eval-okay-hashstring.nix | 4 - tests/lang/eval-okay-if.exp | 1 - tests/lang/eval-okay-if.nix | 1 - tests/lang/eval-okay-import.exp | 1 - tests/lang/eval-okay-import.nix | 11 - tests/lang/eval-okay-ind-string.exp | 1 - tests/lang/eval-okay-ind-string.nix | 128 ------ tests/lang/eval-okay-intersectAttrs.exp | 1 - tests/lang/eval-okay-intersectAttrs.nix | 50 -- tests/lang/eval-okay-let.exp | 1 - tests/lang/eval-okay-let.nix | 5 - tests/lang/eval-okay-list.exp | 1 - tests/lang/eval-okay-list.nix | 7 - tests/lang/eval-okay-listtoattrs.exp | 1 - tests/lang/eval-okay-listtoattrs.nix | 11 - tests/lang/eval-okay-logic.exp | 1 - tests/lang/eval-okay-logic.nix | 1 - tests/lang/eval-okay-map.exp | 1 - tests/lang/eval-okay-map.nix | 3 - tests/lang/eval-okay-mapattrs.exp | 1 - tests/lang/eval-okay-mapattrs.nix | 3 - tests/lang/eval-okay-merge-dynamic-attrs.exp | 1 - tests/lang/eval-okay-merge-dynamic-attrs.nix | 13 - tests/lang/eval-okay-nested-with.exp | 1 - tests/lang/eval-okay-nested-with.nix | 3 - tests/lang/eval-okay-new-let.exp | 1 - tests/lang/eval-okay-new-let.nix | 14 - tests/lang/eval-okay-null-dynamic-attrs.exp | 1 - tests/lang/eval-okay-null-dynamic-attrs.nix | 1 - tests/lang/eval-okay-overrides.exp | 1 - tests/lang/eval-okay-overrides.nix | 9 - tests/lang/eval-okay-parse-flake-ref.exp | 1 - tests/lang/eval-okay-parse-flake-ref.nix | 1 - tests/lang/eval-okay-partition.exp | 1 - tests/lang/eval-okay-partition.nix | 5 - tests/lang/eval-okay-path-string-interpolation.exp | 1 - tests/lang/eval-okay-path-string-interpolation.nix | 12 - tests/lang/eval-okay-path.exp | 1 - tests/lang/eval-okay-path.nix | 7 - tests/lang/eval-okay-pathexists.exp | 1 - tests/lang/eval-okay-pathexists.nix | 29 -- tests/lang/eval-okay-patterns.exp | 1 - tests/lang/eval-okay-patterns.nix | 16 - tests/lang/eval-okay-print.err.exp | 1 - tests/lang/eval-okay-print.exp | 1 - tests/lang/eval-okay-print.nix | 1 - tests/lang/eval-okay-readDir.exp | 1 - tests/lang/eval-okay-readDir.nix | 1 - tests/lang/eval-okay-readFileType.exp | 1 - tests/lang/eval-okay-readFileType.nix | 6 - tests/lang/eval-okay-readfile.exp | 1 - tests/lang/eval-okay-readfile.nix | 1 - tests/lang/eval-okay-redefine-builtin.exp | 1 - tests/lang/eval-okay-redefine-builtin.nix | 3 - tests/lang/eval-okay-regex-match.exp | 1 - tests/lang/eval-okay-regex-match.nix | 29 -- tests/lang/eval-okay-regex-split.exp | 1 - tests/lang/eval-okay-regex-split.nix | 48 -- tests/lang/eval-okay-regression-20220122.exp | 1 - tests/lang/eval-okay-regression-20220122.nix | 1 - tests/lang/eval-okay-regression-20220125.exp | 1 - tests/lang/eval-okay-regression-20220125.nix | 2 - tests/lang/eval-okay-remove.exp | 1 - tests/lang/eval-okay-remove.nix | 5 - tests/lang/eval-okay-replacestrings.exp | 1 - tests/lang/eval-okay-replacestrings.nix | 12 - tests/lang/eval-okay-scope-1.exp | 1 - tests/lang/eval-okay-scope-1.nix | 6 - tests/lang/eval-okay-scope-2.exp | 1 - tests/lang/eval-okay-scope-2.nix | 6 - tests/lang/eval-okay-scope-3.exp | 1 - tests/lang/eval-okay-scope-3.nix | 6 - tests/lang/eval-okay-scope-4.exp | 1 - tests/lang/eval-okay-scope-4.nix | 10 - tests/lang/eval-okay-scope-6.exp | 1 - tests/lang/eval-okay-scope-6.nix | 7 - tests/lang/eval-okay-scope-7.exp | 1 - tests/lang/eval-okay-scope-7.nix | 6 - tests/lang/eval-okay-search-path.exp | 1 - tests/lang/eval-okay-search-path.flags | 1 - tests/lang/eval-okay-search-path.nix | 10 - tests/lang/eval-okay-seq.exp | 1 - tests/lang/eval-okay-seq.nix | 1 - tests/lang/eval-okay-sort.exp | 1 - tests/lang/eval-okay-sort.nix | 20 - tests/lang/eval-okay-splitversion.exp | 1 - tests/lang/eval-okay-splitversion.nix | 1 - tests/lang/eval-okay-string.exp | 1 - tests/lang/eval-okay-string.nix | 12 - tests/lang/eval-okay-strings-as-attrs-names.exp | 1 - tests/lang/eval-okay-strings-as-attrs-names.nix | 20 - tests/lang/eval-okay-substring.exp | 1 - tests/lang/eval-okay-substring.nix | 21 - tests/lang/eval-okay-tail-call-1.exp-disabled | 1 - tests/lang/eval-okay-tail-call-1.nix | 3 - tests/lang/eval-okay-tojson.exp | 1 - tests/lang/eval-okay-tojson.nix | 13 - tests/lang/eval-okay-toxml.exp | 1 - tests/lang/eval-okay-toxml.nix | 3 - tests/lang/eval-okay-toxml2.exp | 1 - tests/lang/eval-okay-toxml2.nix | 1 - tests/lang/eval-okay-tryeval.exp | 1 - tests/lang/eval-okay-tryeval.nix | 5 - tests/lang/eval-okay-types.exp | 1 - tests/lang/eval-okay-types.nix | 37 -- tests/lang/eval-okay-versions.exp | 1 - tests/lang/eval-okay-versions.nix | 43 -- tests/lang/eval-okay-with.exp | 1 - tests/lang/eval-okay-with.nix | 19 - tests/lang/eval-okay-xml.exp.xml | 52 --- tests/lang/eval-okay-xml.nix | 21 - tests/lang/eval-okay-zipAttrsWith.exp | 1 - tests/lang/eval-okay-zipAttrsWith.nix | 9 - tests/lang/framework.sh | 33 -- tests/lang/imported.nix | 3 - tests/lang/imported2.nix | 1 - tests/lang/lib.nix | 61 --- tests/lang/parse-fail-dup-attrs-1.err.exp | 7 - tests/lang/parse-fail-dup-attrs-1.nix | 4 - tests/lang/parse-fail-dup-attrs-2.err.exp | 7 - tests/lang/parse-fail-dup-attrs-2.nix | 13 - tests/lang/parse-fail-dup-attrs-3.err.exp | 7 - tests/lang/parse-fail-dup-attrs-3.nix | 13 - tests/lang/parse-fail-dup-attrs-4.err.exp | 7 - tests/lang/parse-fail-dup-attrs-4.nix | 4 - tests/lang/parse-fail-dup-attrs-6.err.exp | 1 - tests/lang/parse-fail-dup-attrs-7.err.exp | 7 - tests/lang/parse-fail-dup-attrs-7.nix | 9 - tests/lang/parse-fail-dup-formals.err.exp | 6 - tests/lang/parse-fail-dup-formals.nix | 1 - tests/lang/parse-fail-eof-in-string.err.exp | 7 - tests/lang/parse-fail-eof-in-string.nix | 3 - tests/lang/parse-fail-mixed-nested-attrs1.err.exp | 8 - tests/lang/parse-fail-mixed-nested-attrs1.nix | 4 - tests/lang/parse-fail-mixed-nested-attrs2.err.exp | 8 - tests/lang/parse-fail-mixed-nested-attrs2.nix | 4 - tests/lang/parse-fail-patterns-1.err.exp | 7 - tests/lang/parse-fail-patterns-1.nix | 1 - tests/lang/parse-fail-regression-20060610.err.exp | 8 - tests/lang/parse-fail-regression-20060610.nix | 11 - tests/lang/parse-fail-undef-var-2.err.exp | 7 - tests/lang/parse-fail-undef-var-2.nix | 7 - tests/lang/parse-fail-undef-var.err.exp | 7 - tests/lang/parse-fail-undef-var.nix | 1 - tests/lang/parse-fail-utf8.err.exp | 6 - tests/lang/parse-fail-utf8.nix | 1 - tests/lang/parse-okay-1.exp | 1 - tests/lang/parse-okay-1.nix | 1 - tests/lang/parse-okay-crlf.exp | 1 - tests/lang/parse-okay-crlf.nix | 17 - tests/lang/parse-okay-dup-attrs-5.exp | 1 - tests/lang/parse-okay-dup-attrs-5.nix | 4 - tests/lang/parse-okay-dup-attrs-6.exp | 1 - tests/lang/parse-okay-dup-attrs-6.nix | 4 - tests/lang/parse-okay-mixed-nested-attrs-1.exp | 1 - tests/lang/parse-okay-mixed-nested-attrs-1.nix | 4 - tests/lang/parse-okay-mixed-nested-attrs-2.exp | 1 - tests/lang/parse-okay-mixed-nested-attrs-2.nix | 4 - tests/lang/parse-okay-mixed-nested-attrs-3.exp | 1 - tests/lang/parse-okay-mixed-nested-attrs-3.nix | 7 - tests/lang/parse-okay-regression-20041027.exp | 1 - tests/lang/parse-okay-regression-20041027.nix | 11 - tests/lang/parse-okay-regression-751.exp | 1 - tests/lang/parse-okay-regression-751.nix | 2 - tests/lang/parse-okay-subversion.exp | 1 - tests/lang/parse-okay-subversion.nix | 43 -- tests/lang/parse-okay-url.exp | 1 - tests/lang/parse-okay-url.nix | 8 - tests/lang/readDir/bar | 0 tests/lang/readDir/foo/git-hates-directories | 0 tests/lang/readDir/ldir | 1 - tests/lang/readDir/linked | 1 - tests/legacy-ssh-store.sh | 4 - tests/linux-sandbox-cert-test.nix | 30 -- tests/linux-sandbox.sh | 75 --- tests/local-store.sh | 22 - tests/local.mk | 144 ------ tests/logging.sh | 26 -- tests/misc.sh | 32 -- tests/multiple-outputs.nix | 130 ------ tests/multiple-outputs.sh | 88 ---- tests/nar-access.nix | 23 - tests/nar-access.sh | 56 --- tests/nested-sandboxing.sh | 11 - tests/nested-sandboxing/command.sh | 29 -- tests/nested-sandboxing/runner.nix | 24 - tests/nix-build-examples.nix | 33 -- tests/nix-build.sh | 43 -- tests/nix-channel.sh | 66 --- tests/nix-collect-garbage-d.sh | 40 -- tests/nix-copy-ssh-ng.sh | 18 - tests/nix-copy-ssh.sh | 20 - tests/nix-daemon-untrusting.sh | 3 - tests/nix-profile.sh | 187 -------- tests/nix-shell.sh | 147 ------ tests/nix_path.sh | 14 - tests/optimise-store.sh | 44 -- tests/output-normalization.sh | 9 - tests/parallel.builder.sh | 29 -- tests/parallel.nix | 19 - tests/parallel.sh | 56 --- tests/pass-as-file.sh | 18 - tests/path-from-hash-part.sh | 10 - tests/path.nix | 14 - tests/placeholders.sh | 20 - tests/plugins.sh | 9 - tests/plugins/local.mk | 11 - tests/plugins/plugintest.cc | 28 -- tests/post-hook.sh | 31 -- tests/pure-eval.nix | 3 - tests/pure-eval.sh | 34 -- tests/push-to-store-old.sh | 14 - tests/push-to-store.sh | 14 - tests/read-only-store.sh | 42 -- tests/readfile-context.nix | 28 -- tests/readfile-context.sh | 16 - tests/recursive.nix | 56 --- tests/recursive.sh | 19 - tests/referrers.sh | 38 -- tests/remote-store.sh | 43 -- tests/repair.sh | 123 ----- tests/repl.sh | 179 -------- tests/restricted.nix | 1 - tests/restricted.sh | 53 --- tests/search.nix | 25 - tests/search.sh | 46 -- tests/secure-drv-outputs.nix | 23 - tests/secure-drv-outputs.sh | 36 -- tests/selfref-gc.sh | 30 -- tests/shell-hello.nix | 26 -- tests/shell.nix | 90 ---- tests/shell.sh | 32 -- tests/shell.shebang.rb | 7 - tests/shell.shebang.sh | 4 - tests/signing.sh | 109 ----- tests/simple-failing.nix | 12 - tests/simple.builder.sh | 11 - tests/simple.nix | 8 - tests/simple.sh | 33 -- tests/ssh-relay.sh | 16 - tests/store-ping.sh | 17 - tests/structured-attrs-shell.nix | 21 - tests/structured-attrs.nix | 70 --- tests/structured-attrs.sh | 23 - tests/substitute-with-invalid-ca.sh | 38 -- tests/suggestions.sh | 44 -- tests/supplementary-groups.sh | 37 -- tests/tarball.sh | 64 --- tests/test-infra.sh | 85 ---- tests/test-libstoreconsumer.sh | 6 - tests/test-libstoreconsumer/README.md | 6 - tests/test-libstoreconsumer/local.mk | 15 - tests/test-libstoreconsumer/main.cc | 45 -- tests/timeout.nix | 31 -- tests/timeout.sh | 39 -- tests/toString-path.sh | 8 - tests/undefined-variable.nix | 1 - tests/user-envs-migration.sh | 35 -- tests/user-envs.builder.sh | 5 - tests/user-envs.nix | 34 -- tests/user-envs.sh | 190 -------- tests/why-depends.sh | 29 -- tests/zstd.sh | 28 -- 1187 files changed, 14019 insertions(+), 14019 deletions(-) delete mode 100644 tests/add.sh delete mode 100644 tests/bad.tar.xz delete mode 100644 tests/bash-profile.sh delete mode 100644 tests/big-derivation-attr.nix delete mode 100644 tests/binary-cache-build-remote.sh delete mode 100644 tests/binary-cache.sh delete mode 100644 tests/brotli.sh delete mode 100644 tests/build-delete.sh delete mode 100644 tests/build-dry.sh delete mode 100644 tests/build-hook-ca-fixed.nix delete mode 100644 tests/build-hook-ca-floating.nix delete mode 100644 tests/build-hook.nix delete mode 100644 tests/build-remote-content-addressed-fixed.sh delete mode 100644 tests/build-remote-content-addressed-floating.sh delete mode 100644 tests/build-remote-input-addressed.sh delete mode 100644 tests/build-remote-trustless-after.sh delete mode 100644 tests/build-remote-trustless-should-fail-0.sh delete mode 100644 tests/build-remote-trustless-should-pass-0.sh delete mode 100644 tests/build-remote-trustless-should-pass-1.sh delete mode 100644 tests/build-remote-trustless-should-pass-2.sh delete mode 100644 tests/build-remote-trustless-should-pass-3.sh delete mode 100644 tests/build-remote-trustless.sh delete mode 100644 tests/build-remote.sh delete mode 100644 tests/build.sh delete mode 100644 tests/ca-shell.nix delete mode 100644 tests/ca/build-cache.sh delete mode 100644 tests/ca/build-dry.sh delete mode 100755 tests/ca/build-with-garbage-path.sh delete mode 100644 tests/ca/build.sh delete mode 100644 tests/ca/common.sh delete mode 100755 tests/ca/concurrent-builds.sh delete mode 120000 tests/ca/config.nix.in delete mode 100644 tests/ca/content-addressed.nix delete mode 100644 tests/ca/derivation-json.sh delete mode 100644 tests/ca/duplicate-realisation-in-closure.sh delete mode 100644 tests/ca/flake.nix delete mode 100755 tests/ca/gc.sh delete mode 100644 tests/ca/import-derivation.sh delete mode 100644 tests/ca/local.mk delete mode 100644 tests/ca/new-build-cmd.sh delete mode 100755 tests/ca/nix-copy.sh delete mode 100755 tests/ca/nix-run.sh delete mode 100755 tests/ca/nix-shell.sh delete mode 100644 tests/ca/nondeterministic.nix delete mode 100755 tests/ca/post-hook.sh delete mode 100644 tests/ca/racy.nix delete mode 100755 tests/ca/recursive.sh delete mode 100644 tests/ca/repl.sh delete mode 100755 tests/ca/selfref-gc.sh delete mode 100644 tests/ca/signatures.sh delete mode 100644 tests/ca/substitute.sh delete mode 100644 tests/ca/why-depends.sh delete mode 100644 tests/case-hack.sh delete mode 100644 tests/case.nar delete mode 100644 tests/check-refs.nix delete mode 100644 tests/check-refs.sh delete mode 100644 tests/check-reqs.nix delete mode 100644 tests/check-reqs.sh delete mode 100644 tests/check.nix delete mode 100644 tests/check.sh delete mode 100644 tests/common.sh delete mode 100644 tests/common/vars-and-functions.sh.in delete mode 100644 tests/completions.sh delete mode 100644 tests/compression-levels.sh delete mode 100644 tests/compute-levels.sh delete mode 100644 tests/config.nix.in delete mode 100644 tests/config.sh delete mode 100644 tests/config/nix-with-substituters.conf delete mode 100644 tests/db-migration.sh delete mode 100644 tests/dependencies.builder0.sh delete mode 100644 tests/dependencies.nix delete mode 100644 tests/dependencies.sh delete mode 100644 tests/derivation-json.sh delete mode 100644 tests/dummy delete mode 100644 tests/dump-db.sh delete mode 100644 tests/dyn-drv/build-built-drv.sh delete mode 100644 tests/dyn-drv/common.sh delete mode 120000 tests/dyn-drv/config.nix.in delete mode 100644 tests/dyn-drv/dep-built-drv.sh delete mode 100644 tests/dyn-drv/eval-outputOf.sh delete mode 100644 tests/dyn-drv/local.mk delete mode 100644 tests/dyn-drv/old-daemon-error-hack.nix delete mode 100644 tests/dyn-drv/old-daemon-error-hack.sh delete mode 100644 tests/dyn-drv/recursive-mod-json.nix delete mode 100644 tests/dyn-drv/recursive-mod-json.sh delete mode 100644 tests/dyn-drv/text-hashed-output.nix delete mode 100644 tests/dyn-drv/text-hashed-output.sh delete mode 100644 tests/eval-store.sh delete mode 100644 tests/eval.nix delete mode 100644 tests/eval.sh delete mode 100644 tests/experimental-features.sh delete mode 100644 tests/export-graph.nix delete mode 100644 tests/export-graph.sh delete mode 100644 tests/export.sh delete mode 100644 tests/failing.nix delete mode 100644 tests/fetchClosure.sh delete mode 100644 tests/fetchGit.sh delete mode 100644 tests/fetchGitRefs.sh delete mode 100644 tests/fetchGitSubmodules.sh delete mode 100644 tests/fetchMercurial.sh delete mode 100644 tests/fetchPath.sh delete mode 100644 tests/fetchTree-file.sh delete mode 100644 tests/fetchurl.sh delete mode 100644 tests/filter-source.nix delete mode 100644 tests/filter-source.sh delete mode 100644 tests/fixed.builder1.sh delete mode 100644 tests/fixed.builder2.sh delete mode 100644 tests/fixed.nix delete mode 100644 tests/fixed.sh delete mode 100644 tests/flakes/absolute-paths.sh delete mode 100644 tests/flakes/build-paths.sh delete mode 100644 tests/flakes/bundle.sh delete mode 100644 tests/flakes/check.sh delete mode 100644 tests/flakes/circular.sh delete mode 100644 tests/flakes/common.sh delete mode 100644 tests/flakes/config.sh delete mode 100644 tests/flakes/flake-in-submodule.sh delete mode 100644 tests/flakes/flakes.sh delete mode 100644 tests/flakes/follow-paths.sh delete mode 100644 tests/flakes/init.sh delete mode 100644 tests/flakes/inputs.sh delete mode 100644 tests/flakes/mercurial.sh delete mode 100644 tests/flakes/run.sh delete mode 100644 tests/flakes/search-root.sh delete mode 100644 tests/flakes/show.sh delete mode 100644 tests/flakes/unlocked-override.sh delete mode 100644 tests/fmt.sh delete mode 100755 tests/fmt.simple.sh delete mode 100755 tests/function-trace.sh create mode 100644 tests/functional/add.sh create mode 100644 tests/functional/bad.tar.xz create mode 100644 tests/functional/bash-profile.sh create mode 100644 tests/functional/big-derivation-attr.nix create mode 100644 tests/functional/binary-cache-build-remote.sh create mode 100644 tests/functional/binary-cache.sh create mode 100644 tests/functional/brotli.sh create mode 100644 tests/functional/build-delete.sh create mode 100644 tests/functional/build-dry.sh create mode 100644 tests/functional/build-hook-ca-fixed.nix create mode 100644 tests/functional/build-hook-ca-floating.nix create mode 100644 tests/functional/build-hook.nix create mode 100644 tests/functional/build-remote-content-addressed-fixed.sh create mode 100644 tests/functional/build-remote-content-addressed-floating.sh create mode 100644 tests/functional/build-remote-input-addressed.sh create mode 100644 tests/functional/build-remote-trustless-after.sh create mode 100644 tests/functional/build-remote-trustless-should-fail-0.sh create mode 100644 tests/functional/build-remote-trustless-should-pass-0.sh create mode 100644 tests/functional/build-remote-trustless-should-pass-1.sh create mode 100644 tests/functional/build-remote-trustless-should-pass-2.sh create mode 100644 tests/functional/build-remote-trustless-should-pass-3.sh create mode 100644 tests/functional/build-remote-trustless.sh create mode 100644 tests/functional/build-remote.sh create mode 100644 tests/functional/build.sh create mode 100644 tests/functional/ca-shell.nix create mode 100644 tests/functional/ca/build-cache.sh create mode 100644 tests/functional/ca/build-dry.sh create mode 100755 tests/functional/ca/build-with-garbage-path.sh create mode 100644 tests/functional/ca/build.sh create mode 100644 tests/functional/ca/common.sh create mode 100755 tests/functional/ca/concurrent-builds.sh create mode 120000 tests/functional/ca/config.nix.in create mode 100644 tests/functional/ca/content-addressed.nix create mode 100644 tests/functional/ca/derivation-json.sh create mode 100644 tests/functional/ca/duplicate-realisation-in-closure.sh create mode 100644 tests/functional/ca/flake.nix create mode 100755 tests/functional/ca/gc.sh create mode 100644 tests/functional/ca/import-derivation.sh create mode 100644 tests/functional/ca/local.mk create mode 100644 tests/functional/ca/new-build-cmd.sh create mode 100755 tests/functional/ca/nix-copy.sh create mode 100755 tests/functional/ca/nix-run.sh create mode 100755 tests/functional/ca/nix-shell.sh create mode 100644 tests/functional/ca/nondeterministic.nix create mode 100755 tests/functional/ca/post-hook.sh create mode 100644 tests/functional/ca/racy.nix create mode 100755 tests/functional/ca/recursive.sh create mode 100644 tests/functional/ca/repl.sh create mode 100755 tests/functional/ca/selfref-gc.sh create mode 100644 tests/functional/ca/signatures.sh create mode 100644 tests/functional/ca/substitute.sh create mode 100644 tests/functional/ca/why-depends.sh create mode 100644 tests/functional/case-hack.sh create mode 100644 tests/functional/case.nar create mode 100644 tests/functional/check-refs.nix create mode 100644 tests/functional/check-refs.sh create mode 100644 tests/functional/check-reqs.nix create mode 100644 tests/functional/check-reqs.sh create mode 100644 tests/functional/check.nix create mode 100644 tests/functional/check.sh create mode 100644 tests/functional/common.sh create mode 100644 tests/functional/common/vars-and-functions.sh.in create mode 100644 tests/functional/completions.sh create mode 100644 tests/functional/compression-levels.sh create mode 100644 tests/functional/compute-levels.sh create mode 100644 tests/functional/config.nix.in create mode 100644 tests/functional/config.sh create mode 100644 tests/functional/config/nix-with-substituters.conf create mode 100644 tests/functional/db-migration.sh create mode 100644 tests/functional/dependencies.builder0.sh create mode 100644 tests/functional/dependencies.nix create mode 100644 tests/functional/dependencies.sh create mode 100644 tests/functional/derivation-json.sh create mode 100644 tests/functional/dummy create mode 100644 tests/functional/dump-db.sh create mode 100644 tests/functional/dyn-drv/build-built-drv.sh create mode 100644 tests/functional/dyn-drv/common.sh create mode 120000 tests/functional/dyn-drv/config.nix.in create mode 100644 tests/functional/dyn-drv/dep-built-drv.sh create mode 100644 tests/functional/dyn-drv/eval-outputOf.sh create mode 100644 tests/functional/dyn-drv/local.mk create mode 100644 tests/functional/dyn-drv/old-daemon-error-hack.nix create mode 100644 tests/functional/dyn-drv/old-daemon-error-hack.sh create mode 100644 tests/functional/dyn-drv/recursive-mod-json.nix create mode 100644 tests/functional/dyn-drv/recursive-mod-json.sh create mode 100644 tests/functional/dyn-drv/text-hashed-output.nix create mode 100644 tests/functional/dyn-drv/text-hashed-output.sh create mode 100644 tests/functional/eval-store.sh create mode 100644 tests/functional/eval.nix create mode 100644 tests/functional/eval.sh create mode 100644 tests/functional/experimental-features.sh create mode 100644 tests/functional/export-graph.nix create mode 100644 tests/functional/export-graph.sh create mode 100644 tests/functional/export.sh create mode 100644 tests/functional/failing.nix create mode 100644 tests/functional/fetchClosure.sh create mode 100644 tests/functional/fetchGit.sh create mode 100644 tests/functional/fetchGitRefs.sh create mode 100644 tests/functional/fetchGitSubmodules.sh create mode 100644 tests/functional/fetchMercurial.sh create mode 100644 tests/functional/fetchPath.sh create mode 100644 tests/functional/fetchTree-file.sh create mode 100644 tests/functional/fetchurl.sh create mode 100644 tests/functional/filter-source.nix create mode 100644 tests/functional/filter-source.sh create mode 100644 tests/functional/fixed.builder1.sh create mode 100644 tests/functional/fixed.builder2.sh create mode 100644 tests/functional/fixed.nix create mode 100644 tests/functional/fixed.sh create mode 100644 tests/functional/flakes/absolute-paths.sh create mode 100644 tests/functional/flakes/build-paths.sh create mode 100644 tests/functional/flakes/bundle.sh create mode 100644 tests/functional/flakes/check.sh create mode 100644 tests/functional/flakes/circular.sh create mode 100644 tests/functional/flakes/common.sh create mode 100644 tests/functional/flakes/config.sh create mode 100644 tests/functional/flakes/flake-in-submodule.sh create mode 100644 tests/functional/flakes/flakes.sh create mode 100644 tests/functional/flakes/follow-paths.sh create mode 100644 tests/functional/flakes/init.sh create mode 100644 tests/functional/flakes/inputs.sh create mode 100644 tests/functional/flakes/mercurial.sh create mode 100644 tests/functional/flakes/run.sh create mode 100644 tests/functional/flakes/search-root.sh create mode 100644 tests/functional/flakes/show.sh create mode 100644 tests/functional/flakes/unlocked-override.sh create mode 100644 tests/functional/fmt.sh create mode 100755 tests/functional/fmt.simple.sh create mode 100755 tests/functional/function-trace.sh create mode 100644 tests/functional/gc-auto.sh create mode 100644 tests/functional/gc-concurrent.builder.sh create mode 100644 tests/functional/gc-concurrent.nix create mode 100644 tests/functional/gc-concurrent.sh create mode 100644 tests/functional/gc-concurrent2.builder.sh create mode 100644 tests/functional/gc-non-blocking.sh create mode 100644 tests/functional/gc-runtime.nix create mode 100644 tests/functional/gc-runtime.sh create mode 100644 tests/functional/gc.sh create mode 100644 tests/functional/hash-check.nix create mode 100644 tests/functional/hash.sh create mode 100644 tests/functional/hermetic.nix create mode 100644 tests/functional/import-derivation.nix create mode 100644 tests/functional/import-derivation.sh create mode 100644 tests/functional/impure-derivations.nix create mode 100644 tests/functional/impure-derivations.sh create mode 100755 tests/functional/init.sh create mode 100755 tests/functional/install-darwin.sh create mode 100644 tests/functional/lang-test-infra.sh create mode 100755 tests/functional/lang.sh create mode 100644 tests/functional/lang/binary-data create mode 100644 tests/functional/lang/data create mode 100644 tests/functional/lang/dir1/a.nix create mode 100644 tests/functional/lang/dir2/a.nix create mode 100644 tests/functional/lang/dir2/b.nix create mode 100644 tests/functional/lang/dir3/a.nix create mode 100644 tests/functional/lang/dir3/b.nix create mode 100644 tests/functional/lang/dir3/c.nix create mode 100644 tests/functional/lang/dir4/a.nix create mode 100644 tests/functional/lang/dir4/c.nix create mode 100644 tests/functional/lang/empty.exp create mode 100644 tests/functional/lang/eval-fail-abort.err.exp create mode 100644 tests/functional/lang/eval-fail-abort.nix create mode 100644 tests/functional/lang/eval-fail-antiquoted-path.err.exp create mode 100644 tests/functional/lang/eval-fail-assert.err.exp create mode 100644 tests/functional/lang/eval-fail-assert.nix create mode 100644 tests/functional/lang/eval-fail-bad-antiquote-1.err.exp create mode 100644 tests/functional/lang/eval-fail-bad-antiquote-2.err.exp create mode 100644 tests/functional/lang/eval-fail-bad-antiquote-3.err.exp create mode 100644 tests/functional/lang/eval-fail-bad-string-interpolation-1.err.exp create mode 100644 tests/functional/lang/eval-fail-bad-string-interpolation-1.nix create mode 100644 tests/functional/lang/eval-fail-bad-string-interpolation-2.err.exp create mode 100644 tests/functional/lang/eval-fail-bad-string-interpolation-2.nix create mode 100644 tests/functional/lang/eval-fail-bad-string-interpolation-3.err.exp create mode 100644 tests/functional/lang/eval-fail-bad-string-interpolation-3.nix create mode 100644 tests/functional/lang/eval-fail-blackhole.err.exp create mode 100644 tests/functional/lang/eval-fail-blackhole.nix create mode 100644 tests/functional/lang/eval-fail-deepseq.err.exp create mode 100644 tests/functional/lang/eval-fail-deepseq.nix create mode 100644 tests/functional/lang/eval-fail-dup-dynamic-attrs.err.exp create mode 100644 tests/functional/lang/eval-fail-dup-dynamic-attrs.nix create mode 100644 tests/functional/lang/eval-fail-foldlStrict-strict-op-application.err.exp create mode 100644 tests/functional/lang/eval-fail-foldlStrict-strict-op-application.nix create mode 100644 tests/functional/lang/eval-fail-fromTOML-timestamps.err.exp create mode 100644 tests/functional/lang/eval-fail-fromTOML-timestamps.nix create mode 100644 tests/functional/lang/eval-fail-hashfile-missing.err.exp create mode 100644 tests/functional/lang/eval-fail-hashfile-missing.nix create mode 100644 tests/functional/lang/eval-fail-list.err.exp create mode 100644 tests/functional/lang/eval-fail-list.nix create mode 100644 tests/functional/lang/eval-fail-missing-arg.err.exp create mode 100644 tests/functional/lang/eval-fail-missing-arg.nix create mode 100644 tests/functional/lang/eval-fail-nonexist-path.err.exp create mode 100644 tests/functional/lang/eval-fail-nonexist-path.nix create mode 100644 tests/functional/lang/eval-fail-path-slash.err.exp create mode 100644 tests/functional/lang/eval-fail-path-slash.nix create mode 100644 tests/functional/lang/eval-fail-recursion.err.exp create mode 100644 tests/functional/lang/eval-fail-recursion.nix create mode 100644 tests/functional/lang/eval-fail-remove.err.exp create mode 100644 tests/functional/lang/eval-fail-remove.nix create mode 100644 tests/functional/lang/eval-fail-scope-5.err.exp create mode 100644 tests/functional/lang/eval-fail-scope-5.nix create mode 100644 tests/functional/lang/eval-fail-seq.err.exp create mode 100644 tests/functional/lang/eval-fail-seq.nix create mode 100644 tests/functional/lang/eval-fail-set-override.err.exp create mode 100644 tests/functional/lang/eval-fail-set-override.nix create mode 100644 tests/functional/lang/eval-fail-set.err.exp create mode 100644 tests/functional/lang/eval-fail-set.nix create mode 100644 tests/functional/lang/eval-fail-substring.err.exp create mode 100644 tests/functional/lang/eval-fail-substring.nix create mode 100644 tests/functional/lang/eval-fail-to-path.err.exp create mode 100644 tests/functional/lang/eval-fail-to-path.nix create mode 100644 tests/functional/lang/eval-fail-toJSON.err.exp create mode 100644 tests/functional/lang/eval-fail-toJSON.nix create mode 100644 tests/functional/lang/eval-fail-undeclared-arg.err.exp create mode 100644 tests/functional/lang/eval-fail-undeclared-arg.nix create mode 100644 tests/functional/lang/eval-okay-any-all.exp create mode 100644 tests/functional/lang/eval-okay-any-all.nix create mode 100644 tests/functional/lang/eval-okay-arithmetic.exp create mode 100644 tests/functional/lang/eval-okay-arithmetic.nix create mode 100644 tests/functional/lang/eval-okay-attrnames.exp create mode 100644 tests/functional/lang/eval-okay-attrnames.nix create mode 100644 tests/functional/lang/eval-okay-attrs.exp create mode 100644 tests/functional/lang/eval-okay-attrs.nix create mode 100644 tests/functional/lang/eval-okay-attrs2.exp create mode 100644 tests/functional/lang/eval-okay-attrs2.nix create mode 100644 tests/functional/lang/eval-okay-attrs3.exp create mode 100644 tests/functional/lang/eval-okay-attrs3.nix create mode 100644 tests/functional/lang/eval-okay-attrs4.exp create mode 100644 tests/functional/lang/eval-okay-attrs4.nix create mode 100644 tests/functional/lang/eval-okay-attrs5.exp create mode 100644 tests/functional/lang/eval-okay-attrs5.nix create mode 100644 tests/functional/lang/eval-okay-attrs6.exp create mode 100644 tests/functional/lang/eval-okay-attrs6.nix create mode 100644 tests/functional/lang/eval-okay-autoargs.exp create mode 100644 tests/functional/lang/eval-okay-autoargs.flags create mode 100644 tests/functional/lang/eval-okay-autoargs.nix create mode 100644 tests/functional/lang/eval-okay-backslash-newline-1.exp create mode 100644 tests/functional/lang/eval-okay-backslash-newline-1.nix create mode 100644 tests/functional/lang/eval-okay-backslash-newline-2.exp create mode 100644 tests/functional/lang/eval-okay-backslash-newline-2.nix create mode 100644 tests/functional/lang/eval-okay-builtins-add.exp create mode 100644 tests/functional/lang/eval-okay-builtins-add.nix create mode 100644 tests/functional/lang/eval-okay-builtins.exp create mode 100644 tests/functional/lang/eval-okay-builtins.nix create mode 100644 tests/functional/lang/eval-okay-callable-attrs.exp create mode 100644 tests/functional/lang/eval-okay-callable-attrs.nix create mode 100644 tests/functional/lang/eval-okay-catattrs.exp create mode 100644 tests/functional/lang/eval-okay-catattrs.nix create mode 100644 tests/functional/lang/eval-okay-closure.exp create mode 100644 tests/functional/lang/eval-okay-closure.exp.xml create mode 100644 tests/functional/lang/eval-okay-closure.nix create mode 100644 tests/functional/lang/eval-okay-comments.exp create mode 100644 tests/functional/lang/eval-okay-comments.nix create mode 100644 tests/functional/lang/eval-okay-concat.exp create mode 100644 tests/functional/lang/eval-okay-concat.nix create mode 100644 tests/functional/lang/eval-okay-concatmap.exp create mode 100644 tests/functional/lang/eval-okay-concatmap.nix create mode 100644 tests/functional/lang/eval-okay-concatstringssep.exp create mode 100644 tests/functional/lang/eval-okay-concatstringssep.nix create mode 100644 tests/functional/lang/eval-okay-context-introspection.exp create mode 100644 tests/functional/lang/eval-okay-context-introspection.nix create mode 100644 tests/functional/lang/eval-okay-context.exp create mode 100644 tests/functional/lang/eval-okay-context.nix create mode 100644 tests/functional/lang/eval-okay-curpos.exp create mode 100644 tests/functional/lang/eval-okay-curpos.nix create mode 100644 tests/functional/lang/eval-okay-deepseq.exp create mode 100644 tests/functional/lang/eval-okay-deepseq.nix create mode 100644 tests/functional/lang/eval-okay-delayed-with-inherit.exp create mode 100644 tests/functional/lang/eval-okay-delayed-with-inherit.nix create mode 100644 tests/functional/lang/eval-okay-delayed-with.exp create mode 100644 tests/functional/lang/eval-okay-delayed-with.nix create mode 100644 tests/functional/lang/eval-okay-dynamic-attrs-2.exp create mode 100644 tests/functional/lang/eval-okay-dynamic-attrs-2.nix create mode 100644 tests/functional/lang/eval-okay-dynamic-attrs-bare.exp create mode 100644 tests/functional/lang/eval-okay-dynamic-attrs-bare.nix create mode 100644 tests/functional/lang/eval-okay-dynamic-attrs.exp create mode 100644 tests/functional/lang/eval-okay-dynamic-attrs.nix create mode 100644 tests/functional/lang/eval-okay-elem.exp create mode 100644 tests/functional/lang/eval-okay-elem.nix create mode 100644 tests/functional/lang/eval-okay-empty-args.exp create mode 100644 tests/functional/lang/eval-okay-empty-args.nix create mode 100644 tests/functional/lang/eval-okay-eq-derivations.exp create mode 100644 tests/functional/lang/eval-okay-eq-derivations.nix create mode 100644 tests/functional/lang/eval-okay-eq.exp create mode 100644 tests/functional/lang/eval-okay-eq.nix create mode 100644 tests/functional/lang/eval-okay-filter.exp create mode 100644 tests/functional/lang/eval-okay-filter.nix create mode 100644 tests/functional/lang/eval-okay-flake-ref-to-string.exp create mode 100644 tests/functional/lang/eval-okay-flake-ref-to-string.nix create mode 100644 tests/functional/lang/eval-okay-flatten.exp create mode 100644 tests/functional/lang/eval-okay-flatten.nix create mode 100644 tests/functional/lang/eval-okay-float.exp create mode 100644 tests/functional/lang/eval-okay-float.nix create mode 100644 tests/functional/lang/eval-okay-floor-ceil.exp create mode 100644 tests/functional/lang/eval-okay-floor-ceil.nix create mode 100644 tests/functional/lang/eval-okay-foldlStrict-lazy-elements.exp create mode 100644 tests/functional/lang/eval-okay-foldlStrict-lazy-elements.nix create mode 100644 tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.exp create mode 100644 tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.nix create mode 100644 tests/functional/lang/eval-okay-foldlStrict.exp create mode 100644 tests/functional/lang/eval-okay-foldlStrict.nix create mode 100644 tests/functional/lang/eval-okay-fromTOML-timestamps.exp create mode 100644 tests/functional/lang/eval-okay-fromTOML-timestamps.flags create mode 100644 tests/functional/lang/eval-okay-fromTOML-timestamps.nix create mode 100644 tests/functional/lang/eval-okay-fromTOML.exp create mode 100644 tests/functional/lang/eval-okay-fromTOML.nix create mode 100644 tests/functional/lang/eval-okay-fromjson-escapes.exp create mode 100644 tests/functional/lang/eval-okay-fromjson-escapes.nix create mode 100644 tests/functional/lang/eval-okay-fromjson.exp create mode 100644 tests/functional/lang/eval-okay-fromjson.nix create mode 100644 tests/functional/lang/eval-okay-functionargs.exp create mode 100644 tests/functional/lang/eval-okay-functionargs.exp.xml create mode 100644 tests/functional/lang/eval-okay-functionargs.nix create mode 100644 tests/functional/lang/eval-okay-getattrpos-functionargs.exp create mode 100644 tests/functional/lang/eval-okay-getattrpos-functionargs.nix create mode 100644 tests/functional/lang/eval-okay-getattrpos-undefined.exp create mode 100644 tests/functional/lang/eval-okay-getattrpos-undefined.nix create mode 100644 tests/functional/lang/eval-okay-getattrpos.exp create mode 100644 tests/functional/lang/eval-okay-getattrpos.nix create mode 100644 tests/functional/lang/eval-okay-getenv.exp create mode 100644 tests/functional/lang/eval-okay-getenv.nix create mode 100644 tests/functional/lang/eval-okay-groupBy.exp create mode 100644 tests/functional/lang/eval-okay-groupBy.nix create mode 100644 tests/functional/lang/eval-okay-hash.exp create mode 100644 tests/functional/lang/eval-okay-hashfile.exp create mode 100644 tests/functional/lang/eval-okay-hashfile.nix create mode 100644 tests/functional/lang/eval-okay-hashstring.exp create mode 100644 tests/functional/lang/eval-okay-hashstring.nix create mode 100644 tests/functional/lang/eval-okay-if.exp create mode 100644 tests/functional/lang/eval-okay-if.nix create mode 100644 tests/functional/lang/eval-okay-import.exp create mode 100644 tests/functional/lang/eval-okay-import.nix create mode 100644 tests/functional/lang/eval-okay-ind-string.exp create mode 100644 tests/functional/lang/eval-okay-ind-string.nix create mode 100644 tests/functional/lang/eval-okay-intersectAttrs.exp create mode 100644 tests/functional/lang/eval-okay-intersectAttrs.nix create mode 100644 tests/functional/lang/eval-okay-let.exp create mode 100644 tests/functional/lang/eval-okay-let.nix create mode 100644 tests/functional/lang/eval-okay-list.exp create mode 100644 tests/functional/lang/eval-okay-list.nix create mode 100644 tests/functional/lang/eval-okay-listtoattrs.exp create mode 100644 tests/functional/lang/eval-okay-listtoattrs.nix create mode 100644 tests/functional/lang/eval-okay-logic.exp create mode 100644 tests/functional/lang/eval-okay-logic.nix create mode 100644 tests/functional/lang/eval-okay-map.exp create mode 100644 tests/functional/lang/eval-okay-map.nix create mode 100644 tests/functional/lang/eval-okay-mapattrs.exp create mode 100644 tests/functional/lang/eval-okay-mapattrs.nix create mode 100644 tests/functional/lang/eval-okay-merge-dynamic-attrs.exp create mode 100644 tests/functional/lang/eval-okay-merge-dynamic-attrs.nix create mode 100644 tests/functional/lang/eval-okay-nested-with.exp create mode 100644 tests/functional/lang/eval-okay-nested-with.nix create mode 100644 tests/functional/lang/eval-okay-new-let.exp create mode 100644 tests/functional/lang/eval-okay-new-let.nix create mode 100644 tests/functional/lang/eval-okay-null-dynamic-attrs.exp create mode 100644 tests/functional/lang/eval-okay-null-dynamic-attrs.nix create mode 100644 tests/functional/lang/eval-okay-overrides.exp create mode 100644 tests/functional/lang/eval-okay-overrides.nix create mode 100644 tests/functional/lang/eval-okay-parse-flake-ref.exp create mode 100644 tests/functional/lang/eval-okay-parse-flake-ref.nix create mode 100644 tests/functional/lang/eval-okay-partition.exp create mode 100644 tests/functional/lang/eval-okay-partition.nix create mode 100644 tests/functional/lang/eval-okay-path-string-interpolation.exp create mode 100644 tests/functional/lang/eval-okay-path-string-interpolation.nix create mode 100644 tests/functional/lang/eval-okay-path.exp create mode 100644 tests/functional/lang/eval-okay-path.nix create mode 100644 tests/functional/lang/eval-okay-pathexists.exp create mode 100644 tests/functional/lang/eval-okay-pathexists.nix create mode 100644 tests/functional/lang/eval-okay-patterns.exp create mode 100644 tests/functional/lang/eval-okay-patterns.nix create mode 100644 tests/functional/lang/eval-okay-print.err.exp create mode 100644 tests/functional/lang/eval-okay-print.exp create mode 100644 tests/functional/lang/eval-okay-print.nix create mode 100644 tests/functional/lang/eval-okay-readDir.exp create mode 100644 tests/functional/lang/eval-okay-readDir.nix create mode 100644 tests/functional/lang/eval-okay-readFileType.exp create mode 100644 tests/functional/lang/eval-okay-readFileType.nix create mode 100644 tests/functional/lang/eval-okay-readfile.exp create mode 100644 tests/functional/lang/eval-okay-readfile.nix create mode 100644 tests/functional/lang/eval-okay-redefine-builtin.exp create mode 100644 tests/functional/lang/eval-okay-redefine-builtin.nix create mode 100644 tests/functional/lang/eval-okay-regex-match.exp create mode 100644 tests/functional/lang/eval-okay-regex-match.nix create mode 100644 tests/functional/lang/eval-okay-regex-split.exp create mode 100644 tests/functional/lang/eval-okay-regex-split.nix create mode 100644 tests/functional/lang/eval-okay-regression-20220122.exp create mode 100644 tests/functional/lang/eval-okay-regression-20220122.nix create mode 100644 tests/functional/lang/eval-okay-regression-20220125.exp create mode 100644 tests/functional/lang/eval-okay-regression-20220125.nix create mode 100644 tests/functional/lang/eval-okay-remove.exp create mode 100644 tests/functional/lang/eval-okay-remove.nix create mode 100644 tests/functional/lang/eval-okay-replacestrings.exp create mode 100644 tests/functional/lang/eval-okay-replacestrings.nix create mode 100644 tests/functional/lang/eval-okay-scope-1.exp create mode 100644 tests/functional/lang/eval-okay-scope-1.nix create mode 100644 tests/functional/lang/eval-okay-scope-2.exp create mode 100644 tests/functional/lang/eval-okay-scope-2.nix create mode 100644 tests/functional/lang/eval-okay-scope-3.exp create mode 100644 tests/functional/lang/eval-okay-scope-3.nix create mode 100644 tests/functional/lang/eval-okay-scope-4.exp create mode 100644 tests/functional/lang/eval-okay-scope-4.nix create mode 100644 tests/functional/lang/eval-okay-scope-6.exp create mode 100644 tests/functional/lang/eval-okay-scope-6.nix create mode 100644 tests/functional/lang/eval-okay-scope-7.exp create mode 100644 tests/functional/lang/eval-okay-scope-7.nix create mode 100644 tests/functional/lang/eval-okay-search-path.exp create mode 100644 tests/functional/lang/eval-okay-search-path.flags create mode 100644 tests/functional/lang/eval-okay-search-path.nix create mode 100644 tests/functional/lang/eval-okay-seq.exp create mode 100644 tests/functional/lang/eval-okay-seq.nix create mode 100644 tests/functional/lang/eval-okay-sort.exp create mode 100644 tests/functional/lang/eval-okay-sort.nix create mode 100644 tests/functional/lang/eval-okay-splitversion.exp create mode 100644 tests/functional/lang/eval-okay-splitversion.nix create mode 100644 tests/functional/lang/eval-okay-string.exp create mode 100644 tests/functional/lang/eval-okay-string.nix create mode 100644 tests/functional/lang/eval-okay-strings-as-attrs-names.exp create mode 100644 tests/functional/lang/eval-okay-strings-as-attrs-names.nix create mode 100644 tests/functional/lang/eval-okay-substring.exp create mode 100644 tests/functional/lang/eval-okay-substring.nix create mode 100644 tests/functional/lang/eval-okay-tail-call-1.exp-disabled create mode 100644 tests/functional/lang/eval-okay-tail-call-1.nix create mode 100644 tests/functional/lang/eval-okay-tojson.exp create mode 100644 tests/functional/lang/eval-okay-tojson.nix create mode 100644 tests/functional/lang/eval-okay-toxml.exp create mode 100644 tests/functional/lang/eval-okay-toxml.nix create mode 100644 tests/functional/lang/eval-okay-toxml2.exp create mode 100644 tests/functional/lang/eval-okay-toxml2.nix create mode 100644 tests/functional/lang/eval-okay-tryeval.exp create mode 100644 tests/functional/lang/eval-okay-tryeval.nix create mode 100644 tests/functional/lang/eval-okay-types.exp create mode 100644 tests/functional/lang/eval-okay-types.nix create mode 100644 tests/functional/lang/eval-okay-versions.exp create mode 100644 tests/functional/lang/eval-okay-versions.nix create mode 100644 tests/functional/lang/eval-okay-with.exp create mode 100644 tests/functional/lang/eval-okay-with.nix create mode 100644 tests/functional/lang/eval-okay-xml.exp.xml create mode 100644 tests/functional/lang/eval-okay-xml.nix create mode 100644 tests/functional/lang/eval-okay-zipAttrsWith.exp create mode 100644 tests/functional/lang/eval-okay-zipAttrsWith.nix create mode 100644 tests/functional/lang/framework.sh create mode 100644 tests/functional/lang/imported.nix create mode 100644 tests/functional/lang/imported2.nix create mode 100644 tests/functional/lang/lib.nix create mode 100644 tests/functional/lang/parse-fail-dup-attrs-1.err.exp create mode 100644 tests/functional/lang/parse-fail-dup-attrs-1.nix create mode 100644 tests/functional/lang/parse-fail-dup-attrs-2.err.exp create mode 100644 tests/functional/lang/parse-fail-dup-attrs-2.nix create mode 100644 tests/functional/lang/parse-fail-dup-attrs-3.err.exp create mode 100644 tests/functional/lang/parse-fail-dup-attrs-3.nix create mode 100644 tests/functional/lang/parse-fail-dup-attrs-4.err.exp create mode 100644 tests/functional/lang/parse-fail-dup-attrs-4.nix create mode 100644 tests/functional/lang/parse-fail-dup-attrs-6.err.exp create mode 100644 tests/functional/lang/parse-fail-dup-attrs-7.err.exp create mode 100644 tests/functional/lang/parse-fail-dup-attrs-7.nix create mode 100644 tests/functional/lang/parse-fail-dup-formals.err.exp create mode 100644 tests/functional/lang/parse-fail-dup-formals.nix create mode 100644 tests/functional/lang/parse-fail-eof-in-string.err.exp create mode 100644 tests/functional/lang/parse-fail-eof-in-string.nix create mode 100644 tests/functional/lang/parse-fail-mixed-nested-attrs1.err.exp create mode 100644 tests/functional/lang/parse-fail-mixed-nested-attrs1.nix create mode 100644 tests/functional/lang/parse-fail-mixed-nested-attrs2.err.exp create mode 100644 tests/functional/lang/parse-fail-mixed-nested-attrs2.nix create mode 100644 tests/functional/lang/parse-fail-patterns-1.err.exp create mode 100644 tests/functional/lang/parse-fail-patterns-1.nix create mode 100644 tests/functional/lang/parse-fail-regression-20060610.err.exp create mode 100644 tests/functional/lang/parse-fail-regression-20060610.nix create mode 100644 tests/functional/lang/parse-fail-undef-var-2.err.exp create mode 100644 tests/functional/lang/parse-fail-undef-var-2.nix create mode 100644 tests/functional/lang/parse-fail-undef-var.err.exp create mode 100644 tests/functional/lang/parse-fail-undef-var.nix create mode 100644 tests/functional/lang/parse-fail-utf8.err.exp create mode 100644 tests/functional/lang/parse-fail-utf8.nix create mode 100644 tests/functional/lang/parse-okay-1.exp create mode 100644 tests/functional/lang/parse-okay-1.nix create mode 100644 tests/functional/lang/parse-okay-crlf.exp create mode 100644 tests/functional/lang/parse-okay-crlf.nix create mode 100644 tests/functional/lang/parse-okay-dup-attrs-5.exp create mode 100644 tests/functional/lang/parse-okay-dup-attrs-5.nix create mode 100644 tests/functional/lang/parse-okay-dup-attrs-6.exp create mode 100644 tests/functional/lang/parse-okay-dup-attrs-6.nix create mode 100644 tests/functional/lang/parse-okay-mixed-nested-attrs-1.exp create mode 100644 tests/functional/lang/parse-okay-mixed-nested-attrs-1.nix create mode 100644 tests/functional/lang/parse-okay-mixed-nested-attrs-2.exp create mode 100644 tests/functional/lang/parse-okay-mixed-nested-attrs-2.nix create mode 100644 tests/functional/lang/parse-okay-mixed-nested-attrs-3.exp create mode 100644 tests/functional/lang/parse-okay-mixed-nested-attrs-3.nix create mode 100644 tests/functional/lang/parse-okay-regression-20041027.exp create mode 100644 tests/functional/lang/parse-okay-regression-20041027.nix create mode 100644 tests/functional/lang/parse-okay-regression-751.exp create mode 100644 tests/functional/lang/parse-okay-regression-751.nix create mode 100644 tests/functional/lang/parse-okay-subversion.exp create mode 100644 tests/functional/lang/parse-okay-subversion.nix create mode 100644 tests/functional/lang/parse-okay-url.exp create mode 100644 tests/functional/lang/parse-okay-url.nix create mode 100644 tests/functional/lang/readDir/bar create mode 100644 tests/functional/lang/readDir/foo/git-hates-directories create mode 120000 tests/functional/lang/readDir/ldir create mode 120000 tests/functional/lang/readDir/linked create mode 100644 tests/functional/legacy-ssh-store.sh create mode 100644 tests/functional/linux-sandbox-cert-test.nix create mode 100644 tests/functional/linux-sandbox.sh create mode 100644 tests/functional/local-store.sh create mode 100644 tests/functional/local.mk create mode 100644 tests/functional/logging.sh create mode 100644 tests/functional/misc.sh create mode 100644 tests/functional/multiple-outputs.nix create mode 100644 tests/functional/multiple-outputs.sh create mode 100644 tests/functional/nar-access.nix create mode 100644 tests/functional/nar-access.sh create mode 100644 tests/functional/nested-sandboxing.sh create mode 100644 tests/functional/nested-sandboxing/command.sh create mode 100644 tests/functional/nested-sandboxing/runner.nix create mode 100644 tests/functional/nix-build-examples.nix create mode 100644 tests/functional/nix-build.sh create mode 100644 tests/functional/nix-channel.sh create mode 100644 tests/functional/nix-collect-garbage-d.sh create mode 100644 tests/functional/nix-copy-ssh-ng.sh create mode 100644 tests/functional/nix-copy-ssh.sh create mode 100755 tests/functional/nix-daemon-untrusting.sh create mode 100644 tests/functional/nix-profile.sh create mode 100644 tests/functional/nix-shell.sh create mode 100644 tests/functional/nix_path.sh create mode 100644 tests/functional/optimise-store.sh create mode 100644 tests/functional/output-normalization.sh create mode 100644 tests/functional/parallel.builder.sh create mode 100644 tests/functional/parallel.nix create mode 100644 tests/functional/parallel.sh create mode 100644 tests/functional/pass-as-file.sh create mode 100644 tests/functional/path-from-hash-part.sh create mode 100644 tests/functional/path.nix create mode 100644 tests/functional/placeholders.sh create mode 100644 tests/functional/plugins.sh create mode 100644 tests/functional/plugins/local.mk create mode 100644 tests/functional/plugins/plugintest.cc create mode 100644 tests/functional/post-hook.sh create mode 100644 tests/functional/pure-eval.nix create mode 100644 tests/functional/pure-eval.sh create mode 100755 tests/functional/push-to-store-old.sh create mode 100755 tests/functional/push-to-store.sh create mode 100644 tests/functional/read-only-store.sh create mode 100644 tests/functional/readfile-context.nix create mode 100644 tests/functional/readfile-context.sh create mode 100644 tests/functional/recursive.nix create mode 100644 tests/functional/recursive.sh create mode 100644 tests/functional/referrers.sh create mode 100644 tests/functional/remote-store.sh create mode 100644 tests/functional/repair.sh create mode 100644 tests/functional/repl.sh create mode 100644 tests/functional/restricted.nix create mode 100644 tests/functional/restricted.sh create mode 100644 tests/functional/search.nix create mode 100644 tests/functional/search.sh create mode 100644 tests/functional/secure-drv-outputs.nix create mode 100644 tests/functional/secure-drv-outputs.sh create mode 100644 tests/functional/selfref-gc.sh create mode 100644 tests/functional/shell-hello.nix create mode 100644 tests/functional/shell.nix create mode 100644 tests/functional/shell.sh create mode 100644 tests/functional/shell.shebang.rb create mode 100755 tests/functional/shell.shebang.sh create mode 100644 tests/functional/signing.sh create mode 100644 tests/functional/simple-failing.nix create mode 100644 tests/functional/simple.builder.sh create mode 100644 tests/functional/simple.nix create mode 100644 tests/functional/simple.sh create mode 100644 tests/functional/ssh-relay.sh create mode 100644 tests/functional/store-ping.sh create mode 100644 tests/functional/structured-attrs-shell.nix create mode 100644 tests/functional/structured-attrs.nix create mode 100644 tests/functional/structured-attrs.sh create mode 100644 tests/functional/substitute-with-invalid-ca.sh create mode 100644 tests/functional/suggestions.sh create mode 100644 tests/functional/supplementary-groups.sh create mode 100644 tests/functional/tarball.sh create mode 100644 tests/functional/test-infra.sh create mode 100644 tests/functional/test-libstoreconsumer.sh create mode 100644 tests/functional/test-libstoreconsumer/README.md create mode 100644 tests/functional/test-libstoreconsumer/local.mk create mode 100644 tests/functional/test-libstoreconsumer/main.cc create mode 100644 tests/functional/timeout.nix create mode 100644 tests/functional/timeout.sh create mode 100644 tests/functional/toString-path.sh create mode 100644 tests/functional/undefined-variable.nix create mode 100644 tests/functional/user-envs-migration.sh create mode 100644 tests/functional/user-envs.builder.sh create mode 100644 tests/functional/user-envs.nix create mode 100644 tests/functional/user-envs.sh create mode 100644 tests/functional/why-depends.sh create mode 100644 tests/functional/zstd.sh delete mode 100644 tests/gc-auto.sh delete mode 100644 tests/gc-concurrent.builder.sh delete mode 100644 tests/gc-concurrent.nix delete mode 100644 tests/gc-concurrent.sh delete mode 100644 tests/gc-concurrent2.builder.sh delete mode 100644 tests/gc-non-blocking.sh delete mode 100644 tests/gc-runtime.nix delete mode 100644 tests/gc-runtime.sh delete mode 100644 tests/gc.sh delete mode 100644 tests/hash-check.nix delete mode 100644 tests/hash.sh delete mode 100644 tests/hermetic.nix delete mode 100644 tests/import-derivation.nix delete mode 100644 tests/import-derivation.sh delete mode 100644 tests/impure-derivations.nix delete mode 100644 tests/impure-derivations.sh delete mode 100755 tests/init.sh delete mode 100755 tests/install-darwin.sh delete mode 100644 tests/lang-test-infra.sh delete mode 100755 tests/lang.sh delete mode 100644 tests/lang/binary-data delete mode 100644 tests/lang/data delete mode 100644 tests/lang/dir1/a.nix delete mode 100644 tests/lang/dir2/a.nix delete mode 100644 tests/lang/dir2/b.nix delete mode 100644 tests/lang/dir3/a.nix delete mode 100644 tests/lang/dir3/b.nix delete mode 100644 tests/lang/dir3/c.nix delete mode 100644 tests/lang/dir4/a.nix delete mode 100644 tests/lang/dir4/c.nix delete mode 100644 tests/lang/empty.exp delete mode 100644 tests/lang/eval-fail-abort.err.exp delete mode 100644 tests/lang/eval-fail-abort.nix delete mode 100644 tests/lang/eval-fail-antiquoted-path.err.exp delete mode 100644 tests/lang/eval-fail-assert.err.exp delete mode 100644 tests/lang/eval-fail-assert.nix delete mode 100644 tests/lang/eval-fail-bad-antiquote-1.err.exp delete mode 100644 tests/lang/eval-fail-bad-antiquote-2.err.exp delete mode 100644 tests/lang/eval-fail-bad-antiquote-3.err.exp delete mode 100644 tests/lang/eval-fail-bad-string-interpolation-1.err.exp delete mode 100644 tests/lang/eval-fail-bad-string-interpolation-1.nix delete mode 100644 tests/lang/eval-fail-bad-string-interpolation-2.err.exp delete mode 100644 tests/lang/eval-fail-bad-string-interpolation-2.nix delete mode 100644 tests/lang/eval-fail-bad-string-interpolation-3.err.exp delete mode 100644 tests/lang/eval-fail-bad-string-interpolation-3.nix delete mode 100644 tests/lang/eval-fail-blackhole.err.exp delete mode 100644 tests/lang/eval-fail-blackhole.nix delete mode 100644 tests/lang/eval-fail-deepseq.err.exp delete mode 100644 tests/lang/eval-fail-deepseq.nix delete mode 100644 tests/lang/eval-fail-dup-dynamic-attrs.err.exp delete mode 100644 tests/lang/eval-fail-dup-dynamic-attrs.nix delete mode 100644 tests/lang/eval-fail-foldlStrict-strict-op-application.err.exp delete mode 100644 tests/lang/eval-fail-foldlStrict-strict-op-application.nix delete mode 100644 tests/lang/eval-fail-fromTOML-timestamps.err.exp delete mode 100644 tests/lang/eval-fail-fromTOML-timestamps.nix delete mode 100644 tests/lang/eval-fail-hashfile-missing.err.exp delete mode 100644 tests/lang/eval-fail-hashfile-missing.nix delete mode 100644 tests/lang/eval-fail-list.err.exp delete mode 100644 tests/lang/eval-fail-list.nix delete mode 100644 tests/lang/eval-fail-missing-arg.err.exp delete mode 100644 tests/lang/eval-fail-missing-arg.nix delete mode 100644 tests/lang/eval-fail-nonexist-path.err.exp delete mode 100644 tests/lang/eval-fail-nonexist-path.nix delete mode 100644 tests/lang/eval-fail-path-slash.err.exp delete mode 100644 tests/lang/eval-fail-path-slash.nix delete mode 100644 tests/lang/eval-fail-recursion.err.exp delete mode 100644 tests/lang/eval-fail-recursion.nix delete mode 100644 tests/lang/eval-fail-remove.err.exp delete mode 100644 tests/lang/eval-fail-remove.nix delete mode 100644 tests/lang/eval-fail-scope-5.err.exp delete mode 100644 tests/lang/eval-fail-scope-5.nix delete mode 100644 tests/lang/eval-fail-seq.err.exp delete mode 100644 tests/lang/eval-fail-seq.nix delete mode 100644 tests/lang/eval-fail-set-override.err.exp delete mode 100644 tests/lang/eval-fail-set-override.nix delete mode 100644 tests/lang/eval-fail-set.err.exp delete mode 100644 tests/lang/eval-fail-set.nix delete mode 100644 tests/lang/eval-fail-substring.err.exp delete mode 100644 tests/lang/eval-fail-substring.nix delete mode 100644 tests/lang/eval-fail-to-path.err.exp delete mode 100644 tests/lang/eval-fail-to-path.nix delete mode 100644 tests/lang/eval-fail-toJSON.err.exp delete mode 100644 tests/lang/eval-fail-toJSON.nix delete mode 100644 tests/lang/eval-fail-undeclared-arg.err.exp delete mode 100644 tests/lang/eval-fail-undeclared-arg.nix delete mode 100644 tests/lang/eval-okay-any-all.exp delete mode 100644 tests/lang/eval-okay-any-all.nix delete mode 100644 tests/lang/eval-okay-arithmetic.exp delete mode 100644 tests/lang/eval-okay-arithmetic.nix delete mode 100644 tests/lang/eval-okay-attrnames.exp delete mode 100644 tests/lang/eval-okay-attrnames.nix delete mode 100644 tests/lang/eval-okay-attrs.exp delete mode 100644 tests/lang/eval-okay-attrs.nix delete mode 100644 tests/lang/eval-okay-attrs2.exp delete mode 100644 tests/lang/eval-okay-attrs2.nix delete mode 100644 tests/lang/eval-okay-attrs3.exp delete mode 100644 tests/lang/eval-okay-attrs3.nix delete mode 100644 tests/lang/eval-okay-attrs4.exp delete mode 100644 tests/lang/eval-okay-attrs4.nix delete mode 100644 tests/lang/eval-okay-attrs5.exp delete mode 100644 tests/lang/eval-okay-attrs5.nix delete mode 100644 tests/lang/eval-okay-attrs6.exp delete mode 100644 tests/lang/eval-okay-attrs6.nix delete mode 100644 tests/lang/eval-okay-autoargs.exp delete mode 100644 tests/lang/eval-okay-autoargs.flags delete mode 100644 tests/lang/eval-okay-autoargs.nix delete mode 100644 tests/lang/eval-okay-backslash-newline-1.exp delete mode 100644 tests/lang/eval-okay-backslash-newline-1.nix delete mode 100644 tests/lang/eval-okay-backslash-newline-2.exp delete mode 100644 tests/lang/eval-okay-backslash-newline-2.nix delete mode 100644 tests/lang/eval-okay-builtins-add.exp delete mode 100644 tests/lang/eval-okay-builtins-add.nix delete mode 100644 tests/lang/eval-okay-builtins.exp delete mode 100644 tests/lang/eval-okay-builtins.nix delete mode 100644 tests/lang/eval-okay-callable-attrs.exp delete mode 100644 tests/lang/eval-okay-callable-attrs.nix delete mode 100644 tests/lang/eval-okay-catattrs.exp delete mode 100644 tests/lang/eval-okay-catattrs.nix delete mode 100644 tests/lang/eval-okay-closure.exp delete mode 100644 tests/lang/eval-okay-closure.exp.xml delete mode 100644 tests/lang/eval-okay-closure.nix delete mode 100644 tests/lang/eval-okay-comments.exp delete mode 100644 tests/lang/eval-okay-comments.nix delete mode 100644 tests/lang/eval-okay-concat.exp delete mode 100644 tests/lang/eval-okay-concat.nix delete mode 100644 tests/lang/eval-okay-concatmap.exp delete mode 100644 tests/lang/eval-okay-concatmap.nix delete mode 100644 tests/lang/eval-okay-concatstringssep.exp delete mode 100644 tests/lang/eval-okay-concatstringssep.nix delete mode 100644 tests/lang/eval-okay-context-introspection.exp delete mode 100644 tests/lang/eval-okay-context-introspection.nix delete mode 100644 tests/lang/eval-okay-context.exp delete mode 100644 tests/lang/eval-okay-context.nix delete mode 100644 tests/lang/eval-okay-curpos.exp delete mode 100644 tests/lang/eval-okay-curpos.nix delete mode 100644 tests/lang/eval-okay-deepseq.exp delete mode 100644 tests/lang/eval-okay-deepseq.nix delete mode 100644 tests/lang/eval-okay-delayed-with-inherit.exp delete mode 100644 tests/lang/eval-okay-delayed-with-inherit.nix delete mode 100644 tests/lang/eval-okay-delayed-with.exp delete mode 100644 tests/lang/eval-okay-delayed-with.nix delete mode 100644 tests/lang/eval-okay-dynamic-attrs-2.exp delete mode 100644 tests/lang/eval-okay-dynamic-attrs-2.nix delete mode 100644 tests/lang/eval-okay-dynamic-attrs-bare.exp delete mode 100644 tests/lang/eval-okay-dynamic-attrs-bare.nix delete mode 100644 tests/lang/eval-okay-dynamic-attrs.exp delete mode 100644 tests/lang/eval-okay-dynamic-attrs.nix delete mode 100644 tests/lang/eval-okay-elem.exp delete mode 100644 tests/lang/eval-okay-elem.nix delete mode 100644 tests/lang/eval-okay-empty-args.exp delete mode 100644 tests/lang/eval-okay-empty-args.nix delete mode 100644 tests/lang/eval-okay-eq-derivations.exp delete mode 100644 tests/lang/eval-okay-eq-derivations.nix delete mode 100644 tests/lang/eval-okay-eq.exp delete mode 100644 tests/lang/eval-okay-eq.nix delete mode 100644 tests/lang/eval-okay-filter.exp delete mode 100644 tests/lang/eval-okay-filter.nix delete mode 100644 tests/lang/eval-okay-flake-ref-to-string.exp delete mode 100644 tests/lang/eval-okay-flake-ref-to-string.nix delete mode 100644 tests/lang/eval-okay-flatten.exp delete mode 100644 tests/lang/eval-okay-flatten.nix delete mode 100644 tests/lang/eval-okay-float.exp delete mode 100644 tests/lang/eval-okay-float.nix delete mode 100644 tests/lang/eval-okay-floor-ceil.exp delete mode 100644 tests/lang/eval-okay-floor-ceil.nix delete mode 100644 tests/lang/eval-okay-foldlStrict-lazy-elements.exp delete mode 100644 tests/lang/eval-okay-foldlStrict-lazy-elements.nix delete mode 100644 tests/lang/eval-okay-foldlStrict-lazy-initial-accumulator.exp delete mode 100644 tests/lang/eval-okay-foldlStrict-lazy-initial-accumulator.nix delete mode 100644 tests/lang/eval-okay-foldlStrict.exp delete mode 100644 tests/lang/eval-okay-foldlStrict.nix delete mode 100644 tests/lang/eval-okay-fromTOML-timestamps.exp delete mode 100644 tests/lang/eval-okay-fromTOML-timestamps.flags delete mode 100644 tests/lang/eval-okay-fromTOML-timestamps.nix delete mode 100644 tests/lang/eval-okay-fromTOML.exp delete mode 100644 tests/lang/eval-okay-fromTOML.nix delete mode 100644 tests/lang/eval-okay-fromjson-escapes.exp delete mode 100644 tests/lang/eval-okay-fromjson-escapes.nix delete mode 100644 tests/lang/eval-okay-fromjson.exp delete mode 100644 tests/lang/eval-okay-fromjson.nix delete mode 100644 tests/lang/eval-okay-functionargs.exp delete mode 100644 tests/lang/eval-okay-functionargs.exp.xml delete mode 100644 tests/lang/eval-okay-functionargs.nix delete mode 100644 tests/lang/eval-okay-getattrpos-functionargs.exp delete mode 100644 tests/lang/eval-okay-getattrpos-functionargs.nix delete mode 100644 tests/lang/eval-okay-getattrpos-undefined.exp delete mode 100644 tests/lang/eval-okay-getattrpos-undefined.nix delete mode 100644 tests/lang/eval-okay-getattrpos.exp delete mode 100644 tests/lang/eval-okay-getattrpos.nix delete mode 100644 tests/lang/eval-okay-getenv.exp delete mode 100644 tests/lang/eval-okay-getenv.nix delete mode 100644 tests/lang/eval-okay-groupBy.exp delete mode 100644 tests/lang/eval-okay-groupBy.nix delete mode 100644 tests/lang/eval-okay-hash.exp delete mode 100644 tests/lang/eval-okay-hashfile.exp delete mode 100644 tests/lang/eval-okay-hashfile.nix delete mode 100644 tests/lang/eval-okay-hashstring.exp delete mode 100644 tests/lang/eval-okay-hashstring.nix delete mode 100644 tests/lang/eval-okay-if.exp delete mode 100644 tests/lang/eval-okay-if.nix delete mode 100644 tests/lang/eval-okay-import.exp delete mode 100644 tests/lang/eval-okay-import.nix delete mode 100644 tests/lang/eval-okay-ind-string.exp delete mode 100644 tests/lang/eval-okay-ind-string.nix delete mode 100644 tests/lang/eval-okay-intersectAttrs.exp delete mode 100644 tests/lang/eval-okay-intersectAttrs.nix delete mode 100644 tests/lang/eval-okay-let.exp delete mode 100644 tests/lang/eval-okay-let.nix delete mode 100644 tests/lang/eval-okay-list.exp delete mode 100644 tests/lang/eval-okay-list.nix delete mode 100644 tests/lang/eval-okay-listtoattrs.exp delete mode 100644 tests/lang/eval-okay-listtoattrs.nix delete mode 100644 tests/lang/eval-okay-logic.exp delete mode 100644 tests/lang/eval-okay-logic.nix delete mode 100644 tests/lang/eval-okay-map.exp delete mode 100644 tests/lang/eval-okay-map.nix delete mode 100644 tests/lang/eval-okay-mapattrs.exp delete mode 100644 tests/lang/eval-okay-mapattrs.nix delete mode 100644 tests/lang/eval-okay-merge-dynamic-attrs.exp delete mode 100644 tests/lang/eval-okay-merge-dynamic-attrs.nix delete mode 100644 tests/lang/eval-okay-nested-with.exp delete mode 100644 tests/lang/eval-okay-nested-with.nix delete mode 100644 tests/lang/eval-okay-new-let.exp delete mode 100644 tests/lang/eval-okay-new-let.nix delete mode 100644 tests/lang/eval-okay-null-dynamic-attrs.exp delete mode 100644 tests/lang/eval-okay-null-dynamic-attrs.nix delete mode 100644 tests/lang/eval-okay-overrides.exp delete mode 100644 tests/lang/eval-okay-overrides.nix delete mode 100644 tests/lang/eval-okay-parse-flake-ref.exp delete mode 100644 tests/lang/eval-okay-parse-flake-ref.nix delete mode 100644 tests/lang/eval-okay-partition.exp delete mode 100644 tests/lang/eval-okay-partition.nix delete mode 100644 tests/lang/eval-okay-path-string-interpolation.exp delete mode 100644 tests/lang/eval-okay-path-string-interpolation.nix delete mode 100644 tests/lang/eval-okay-path.exp delete mode 100644 tests/lang/eval-okay-path.nix delete mode 100644 tests/lang/eval-okay-pathexists.exp delete mode 100644 tests/lang/eval-okay-pathexists.nix delete mode 100644 tests/lang/eval-okay-patterns.exp delete mode 100644 tests/lang/eval-okay-patterns.nix delete mode 100644 tests/lang/eval-okay-print.err.exp delete mode 100644 tests/lang/eval-okay-print.exp delete mode 100644 tests/lang/eval-okay-print.nix delete mode 100644 tests/lang/eval-okay-readDir.exp delete mode 100644 tests/lang/eval-okay-readDir.nix delete mode 100644 tests/lang/eval-okay-readFileType.exp delete mode 100644 tests/lang/eval-okay-readFileType.nix delete mode 100644 tests/lang/eval-okay-readfile.exp delete mode 100644 tests/lang/eval-okay-readfile.nix delete mode 100644 tests/lang/eval-okay-redefine-builtin.exp delete mode 100644 tests/lang/eval-okay-redefine-builtin.nix delete mode 100644 tests/lang/eval-okay-regex-match.exp delete mode 100644 tests/lang/eval-okay-regex-match.nix delete mode 100644 tests/lang/eval-okay-regex-split.exp delete mode 100644 tests/lang/eval-okay-regex-split.nix delete mode 100644 tests/lang/eval-okay-regression-20220122.exp delete mode 100644 tests/lang/eval-okay-regression-20220122.nix delete mode 100644 tests/lang/eval-okay-regression-20220125.exp delete mode 100644 tests/lang/eval-okay-regression-20220125.nix delete mode 100644 tests/lang/eval-okay-remove.exp delete mode 100644 tests/lang/eval-okay-remove.nix delete mode 100644 tests/lang/eval-okay-replacestrings.exp delete mode 100644 tests/lang/eval-okay-replacestrings.nix delete mode 100644 tests/lang/eval-okay-scope-1.exp delete mode 100644 tests/lang/eval-okay-scope-1.nix delete mode 100644 tests/lang/eval-okay-scope-2.exp delete mode 100644 tests/lang/eval-okay-scope-2.nix delete mode 100644 tests/lang/eval-okay-scope-3.exp delete mode 100644 tests/lang/eval-okay-scope-3.nix delete mode 100644 tests/lang/eval-okay-scope-4.exp delete mode 100644 tests/lang/eval-okay-scope-4.nix delete mode 100644 tests/lang/eval-okay-scope-6.exp delete mode 100644 tests/lang/eval-okay-scope-6.nix delete mode 100644 tests/lang/eval-okay-scope-7.exp delete mode 100644 tests/lang/eval-okay-scope-7.nix delete mode 100644 tests/lang/eval-okay-search-path.exp delete mode 100644 tests/lang/eval-okay-search-path.flags delete mode 100644 tests/lang/eval-okay-search-path.nix delete mode 100644 tests/lang/eval-okay-seq.exp delete mode 100644 tests/lang/eval-okay-seq.nix delete mode 100644 tests/lang/eval-okay-sort.exp delete mode 100644 tests/lang/eval-okay-sort.nix delete mode 100644 tests/lang/eval-okay-splitversion.exp delete mode 100644 tests/lang/eval-okay-splitversion.nix delete mode 100644 tests/lang/eval-okay-string.exp delete mode 100644 tests/lang/eval-okay-string.nix delete mode 100644 tests/lang/eval-okay-strings-as-attrs-names.exp delete mode 100644 tests/lang/eval-okay-strings-as-attrs-names.nix delete mode 100644 tests/lang/eval-okay-substring.exp delete mode 100644 tests/lang/eval-okay-substring.nix delete mode 100644 tests/lang/eval-okay-tail-call-1.exp-disabled delete mode 100644 tests/lang/eval-okay-tail-call-1.nix delete mode 100644 tests/lang/eval-okay-tojson.exp delete mode 100644 tests/lang/eval-okay-tojson.nix delete mode 100644 tests/lang/eval-okay-toxml.exp delete mode 100644 tests/lang/eval-okay-toxml.nix delete mode 100644 tests/lang/eval-okay-toxml2.exp delete mode 100644 tests/lang/eval-okay-toxml2.nix delete mode 100644 tests/lang/eval-okay-tryeval.exp delete mode 100644 tests/lang/eval-okay-tryeval.nix delete mode 100644 tests/lang/eval-okay-types.exp delete mode 100644 tests/lang/eval-okay-types.nix delete mode 100644 tests/lang/eval-okay-versions.exp delete mode 100644 tests/lang/eval-okay-versions.nix delete mode 100644 tests/lang/eval-okay-with.exp delete mode 100644 tests/lang/eval-okay-with.nix delete mode 100644 tests/lang/eval-okay-xml.exp.xml delete mode 100644 tests/lang/eval-okay-xml.nix delete mode 100644 tests/lang/eval-okay-zipAttrsWith.exp delete mode 100644 tests/lang/eval-okay-zipAttrsWith.nix delete mode 100644 tests/lang/framework.sh delete mode 100644 tests/lang/imported.nix delete mode 100644 tests/lang/imported2.nix delete mode 100644 tests/lang/lib.nix delete mode 100644 tests/lang/parse-fail-dup-attrs-1.err.exp delete mode 100644 tests/lang/parse-fail-dup-attrs-1.nix delete mode 100644 tests/lang/parse-fail-dup-attrs-2.err.exp delete mode 100644 tests/lang/parse-fail-dup-attrs-2.nix delete mode 100644 tests/lang/parse-fail-dup-attrs-3.err.exp delete mode 100644 tests/lang/parse-fail-dup-attrs-3.nix delete mode 100644 tests/lang/parse-fail-dup-attrs-4.err.exp delete mode 100644 tests/lang/parse-fail-dup-attrs-4.nix delete mode 100644 tests/lang/parse-fail-dup-attrs-6.err.exp delete mode 100644 tests/lang/parse-fail-dup-attrs-7.err.exp delete mode 100644 tests/lang/parse-fail-dup-attrs-7.nix delete mode 100644 tests/lang/parse-fail-dup-formals.err.exp delete mode 100644 tests/lang/parse-fail-dup-formals.nix delete mode 100644 tests/lang/parse-fail-eof-in-string.err.exp delete mode 100644 tests/lang/parse-fail-eof-in-string.nix delete mode 100644 tests/lang/parse-fail-mixed-nested-attrs1.err.exp delete mode 100644 tests/lang/parse-fail-mixed-nested-attrs1.nix delete mode 100644 tests/lang/parse-fail-mixed-nested-attrs2.err.exp delete mode 100644 tests/lang/parse-fail-mixed-nested-attrs2.nix delete mode 100644 tests/lang/parse-fail-patterns-1.err.exp delete mode 100644 tests/lang/parse-fail-patterns-1.nix delete mode 100644 tests/lang/parse-fail-regression-20060610.err.exp delete mode 100644 tests/lang/parse-fail-regression-20060610.nix delete mode 100644 tests/lang/parse-fail-undef-var-2.err.exp delete mode 100644 tests/lang/parse-fail-undef-var-2.nix delete mode 100644 tests/lang/parse-fail-undef-var.err.exp delete mode 100644 tests/lang/parse-fail-undef-var.nix delete mode 100644 tests/lang/parse-fail-utf8.err.exp delete mode 100644 tests/lang/parse-fail-utf8.nix delete mode 100644 tests/lang/parse-okay-1.exp delete mode 100644 tests/lang/parse-okay-1.nix delete mode 100644 tests/lang/parse-okay-crlf.exp delete mode 100644 tests/lang/parse-okay-crlf.nix delete mode 100644 tests/lang/parse-okay-dup-attrs-5.exp delete mode 100644 tests/lang/parse-okay-dup-attrs-5.nix delete mode 100644 tests/lang/parse-okay-dup-attrs-6.exp delete mode 100644 tests/lang/parse-okay-dup-attrs-6.nix delete mode 100644 tests/lang/parse-okay-mixed-nested-attrs-1.exp delete mode 100644 tests/lang/parse-okay-mixed-nested-attrs-1.nix delete mode 100644 tests/lang/parse-okay-mixed-nested-attrs-2.exp delete mode 100644 tests/lang/parse-okay-mixed-nested-attrs-2.nix delete mode 100644 tests/lang/parse-okay-mixed-nested-attrs-3.exp delete mode 100644 tests/lang/parse-okay-mixed-nested-attrs-3.nix delete mode 100644 tests/lang/parse-okay-regression-20041027.exp delete mode 100644 tests/lang/parse-okay-regression-20041027.nix delete mode 100644 tests/lang/parse-okay-regression-751.exp delete mode 100644 tests/lang/parse-okay-regression-751.nix delete mode 100644 tests/lang/parse-okay-subversion.exp delete mode 100644 tests/lang/parse-okay-subversion.nix delete mode 100644 tests/lang/parse-okay-url.exp delete mode 100644 tests/lang/parse-okay-url.nix delete mode 100644 tests/lang/readDir/bar delete mode 100644 tests/lang/readDir/foo/git-hates-directories delete mode 120000 tests/lang/readDir/ldir delete mode 120000 tests/lang/readDir/linked delete mode 100644 tests/legacy-ssh-store.sh delete mode 100644 tests/linux-sandbox-cert-test.nix delete mode 100644 tests/linux-sandbox.sh delete mode 100644 tests/local-store.sh delete mode 100644 tests/local.mk delete mode 100644 tests/logging.sh delete mode 100644 tests/misc.sh delete mode 100644 tests/multiple-outputs.nix delete mode 100644 tests/multiple-outputs.sh delete mode 100644 tests/nar-access.nix delete mode 100644 tests/nar-access.sh delete mode 100644 tests/nested-sandboxing.sh delete mode 100644 tests/nested-sandboxing/command.sh delete mode 100644 tests/nested-sandboxing/runner.nix delete mode 100644 tests/nix-build-examples.nix delete mode 100644 tests/nix-build.sh delete mode 100644 tests/nix-channel.sh delete mode 100644 tests/nix-collect-garbage-d.sh delete mode 100644 tests/nix-copy-ssh-ng.sh delete mode 100644 tests/nix-copy-ssh.sh delete mode 100755 tests/nix-daemon-untrusting.sh delete mode 100644 tests/nix-profile.sh delete mode 100644 tests/nix-shell.sh delete mode 100644 tests/nix_path.sh delete mode 100644 tests/optimise-store.sh delete mode 100644 tests/output-normalization.sh delete mode 100644 tests/parallel.builder.sh delete mode 100644 tests/parallel.nix delete mode 100644 tests/parallel.sh delete mode 100644 tests/pass-as-file.sh delete mode 100644 tests/path-from-hash-part.sh delete mode 100644 tests/path.nix delete mode 100644 tests/placeholders.sh delete mode 100644 tests/plugins.sh delete mode 100644 tests/plugins/local.mk delete mode 100644 tests/plugins/plugintest.cc delete mode 100644 tests/post-hook.sh delete mode 100644 tests/pure-eval.nix delete mode 100644 tests/pure-eval.sh delete mode 100755 tests/push-to-store-old.sh delete mode 100755 tests/push-to-store.sh delete mode 100644 tests/read-only-store.sh delete mode 100644 tests/readfile-context.nix delete mode 100644 tests/readfile-context.sh delete mode 100644 tests/recursive.nix delete mode 100644 tests/recursive.sh delete mode 100644 tests/referrers.sh delete mode 100644 tests/remote-store.sh delete mode 100644 tests/repair.sh delete mode 100644 tests/repl.sh delete mode 100644 tests/restricted.nix delete mode 100644 tests/restricted.sh delete mode 100644 tests/search.nix delete mode 100644 tests/search.sh delete mode 100644 tests/secure-drv-outputs.nix delete mode 100644 tests/secure-drv-outputs.sh delete mode 100644 tests/selfref-gc.sh delete mode 100644 tests/shell-hello.nix delete mode 100644 tests/shell.nix delete mode 100644 tests/shell.sh delete mode 100644 tests/shell.shebang.rb delete mode 100755 tests/shell.shebang.sh delete mode 100644 tests/signing.sh delete mode 100644 tests/simple-failing.nix delete mode 100644 tests/simple.builder.sh delete mode 100644 tests/simple.nix delete mode 100644 tests/simple.sh delete mode 100644 tests/ssh-relay.sh delete mode 100644 tests/store-ping.sh delete mode 100644 tests/structured-attrs-shell.nix delete mode 100644 tests/structured-attrs.nix delete mode 100644 tests/structured-attrs.sh delete mode 100644 tests/substitute-with-invalid-ca.sh delete mode 100644 tests/suggestions.sh delete mode 100644 tests/supplementary-groups.sh delete mode 100644 tests/tarball.sh delete mode 100644 tests/test-infra.sh delete mode 100644 tests/test-libstoreconsumer.sh delete mode 100644 tests/test-libstoreconsumer/README.md delete mode 100644 tests/test-libstoreconsumer/local.mk delete mode 100644 tests/test-libstoreconsumer/main.cc delete mode 100644 tests/timeout.nix delete mode 100644 tests/timeout.sh delete mode 100644 tests/toString-path.sh delete mode 100644 tests/undefined-variable.nix delete mode 100644 tests/user-envs-migration.sh delete mode 100644 tests/user-envs.builder.sh delete mode 100644 tests/user-envs.nix delete mode 100644 tests/user-envs.sh delete mode 100644 tests/why-depends.sh delete mode 100644 tests/zstd.sh diff --git a/.github/labeler.yml b/.github/labeler.yml index 12120bdb3..7544f07a6 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -20,4 +20,4 @@ # Unit tests - src/*/tests/**/* # Functional and integration tests - - tests/**/* + - tests/functional/**/* diff --git a/.gitignore b/.gitignore index bf4f33564..2d3314015 100644 --- a/.gitignore +++ b/.gitignore @@ -79,24 +79,24 @@ perl/Makefile.config /src/build-remote/build-remote -# /tests/ -/tests/test-tmp -/tests/common/vars-and-functions.sh -/tests/result* -/tests/restricted-innocent -/tests/shell -/tests/shell.drv -/tests/config.nix -/tests/ca/config.nix -/tests/dyn-drv/config.nix -/tests/repl-result-out -/tests/test-libstoreconsumer/test-libstoreconsumer - -# /tests/lang/ -/tests/lang/*.out -/tests/lang/*.out.xml -/tests/lang/*.err -/tests/lang/*.ast +# /tests/functional/ +/tests/functional/test-tmp +/tests/functional/common/vars-and-functions.sh +/tests/functional/result* +/tests/functional/restricted-innocent +/tests/functional/shell +/tests/functional/shell.drv +/tests/functional/config.nix +/tests/functional/ca/config.nix +/tests/functional/dyn-drv/config.nix +/tests/functional/repl-result-out +/tests/functional/test-libstoreconsumer/test-libstoreconsumer + +# /tests/functional/lang/ +/tests/functional/lang/*.out +/tests/functional/lang/*.out.xml +/tests/functional/lang/*.err +/tests/functional/lang/*.ast /perl/lib/Nix/Config.pm /perl/lib/Nix/Store.cc diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index facbf0eb0..8908b9887 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -52,7 +52,7 @@ Check out the [security policy](https://github.com/NixOS/nix/security/policy). - [ ] Fixes an [idea approved](https://github.com/NixOS/nix/labels/idea%20approved) issue - [ ] Tests, as appropriate: - - Functional tests – [`tests/**.sh`](./tests) + - Functional tests – [`tests/functional/**.sh`](./tests/functional) - Unit tests – [`src/*/tests`](./src/) - Integration tests – [`tests/nixos/*`](./tests/nixos) - [ ] User documentation in the [manual](..doc/manual/src) diff --git a/Makefile b/Makefile index 31b54b93d..c0b27e904 100644 --- a/Makefile +++ b/Makefile @@ -26,11 +26,11 @@ makefiles += \ src/libutil/tests/local.mk \ src/libstore/tests/local.mk \ src/libexpr/tests/local.mk \ - tests/local.mk \ - tests/ca/local.mk \ - tests/dyn-drv/local.mk \ - tests/test-libstoreconsumer/local.mk \ - tests/plugins/local.mk + tests/functional/local.mk \ + tests/functional/ca/local.mk \ + tests/functional/dyn-drv/local.mk \ + tests/functional/test-libstoreconsumer/local.mk \ + tests/functional/plugins/local.mk else makefiles += \ mk/disable-tests.mk diff --git a/doc/manual/src/contributing/testing.md b/doc/manual/src/contributing/testing.md index cd94d5cfb..ccd90088e 100644 --- a/doc/manual/src/contributing/testing.md +++ b/doc/manual/src/contributing/testing.md @@ -12,7 +12,7 @@ Finer-grained filtering is also possible using the [--gtest_filter](https://goog ## Functional tests -The functional tests reside under the `tests` directory and are listed in `tests/local.mk`. +The functional tests reside under the `tests/functional` directory and are listed in `tests/functional/local.mk`. Each test is a bash script. ### Running the whole test suite @@ -21,8 +21,8 @@ The whole test suite can be run with: ```shell-session $ make install && make installcheck -ran test tests/foo.sh... [PASS] -ran test tests/bar.sh... [PASS] +ran test tests/functional/foo.sh... [PASS] +ran test tests/functional/bar.sh... [PASS] ... ``` @@ -30,14 +30,14 @@ ran test tests/bar.sh... [PASS] Sometimes it is useful to group related tests so they can be easily run together without running the entire test suite. Each test group is in a subdirectory of `tests`. -For example, `tests/ca/local.mk` defines a `ca` test group for content-addressed derivation outputs. +For example, `tests/functional/ca/local.mk` defines a `ca` test group for content-addressed derivation outputs. That test group can be run like this: ```shell-session $ make ca.test-group -j50 -ran test tests/ca/nix-run.sh... [PASS] -ran test tests/ca/import-derivation.sh... [PASS] +ran test tests/functional/ca/nix-run.sh... [PASS] +ran test tests/functional/ca/import-derivation.sh... [PASS] ... ``` @@ -56,21 +56,21 @@ install-tests-groups += $(test-group-name) Individual tests can be run with `make`: ```shell-session -$ make tests/${testName}.sh.test -ran test tests/${testName}.sh... [PASS] +$ make tests/functional/${testName}.sh.test +ran test tests/functional/${testName}.sh... [PASS] ``` or without `make`: ```shell-session -$ ./mk/run-test.sh tests/${testName}.sh -ran test tests/${testName}.sh... [PASS] +$ ./mk/run-test.sh tests/functional/${testName}.sh +ran test tests/functional/${testName}.sh... [PASS] ``` To see the complete output, one can also run: ```shell-session -$ ./mk/debug-test.sh tests/${testName}.sh +$ ./mk/debug-test.sh tests/functional/${testName}.sh + foo output from foo + bar @@ -105,7 +105,7 @@ edit it like so: Then, running the test with `./mk/debug-test.sh` will drop you into GDB once the script reaches that point: ```shell-session -$ ./mk/debug-test.sh tests/${testName}.sh +$ ./mk/debug-test.sh tests/functional/${testName}.sh ... + gdb blash blub GNU gdb (GDB) 12.1 @@ -124,9 +124,11 @@ This technique is to include the exact output/behavior of a former version of Ni For example, this technique is used for the language tests, to check both the printed final value if evaluation was successful, and any errors and warnings encountered. It is frequently useful to regenerate the expected output. -To do that, rerun the failed test with `_NIX_TEST_ACCEPT=1`. -(At least, this is the convention we've used for `tests/lang.sh`. -If we add more characterization testing we should always strive to be consistent.) +To do that, rerun the failed test(s) with `_NIX_TEST_ACCEPT=1`. +For example: +```bash +_NIX_TEST_ACCEPT=1 make tests/functional/lang.sh.test +``` An interesting situation to document is the case when these tests are "overfitted". The language tests are, again, an example of this. diff --git a/flake.nix b/flake.nix index 1d629bb6a..beedb000f 100644 --- a/flake.nix +++ b/flake.nix @@ -24,7 +24,7 @@ linuxSystems = linux32BitSystems ++ linux64BitSystems; darwinSystems = [ "x86_64-darwin" "aarch64-darwin" ]; systems = linuxSystems ++ darwinSystems; - + crossSystems = [ "armv6l-linux" "armv7l-linux" ]; stdenvs = [ "gccStdenv" "clangStdenv" "clang11Stdenv" "stdenv" "libcxxStdenv" "ccacheStdenv" ]; @@ -58,35 +58,27 @@ nixSrc = fileset.toSource { root = ./.; - fileset = fileset.intersect baseFiles ( - fileset.difference - (fileset.unions [ - ./.version - ./boehmgc-coroutine-sp-fallback.diff - ./bootstrap.sh - ./configure.ac - ./doc - ./local.mk - ./m4 - ./Makefile - ./Makefile.config.in - ./misc - ./mk - ./precompiled-headers.h - ./src - ./tests - ./COPYING - ./scripts/local.mk - (fileset.fileFilter (f: lib.strings.hasPrefix "nix-profile" f.name) ./scripts) - # TODO: do we really need README.md? It doesn't seem used in the build. - ./README.md - ]) - (fileset.unions [ - # Removed file sets - ./tests/nixos - ./tests/installer - ]) - ); + fileset = fileset.intersect baseFiles (fileset.unions [ + ./.version + ./boehmgc-coroutine-sp-fallback.diff + ./bootstrap.sh + ./configure.ac + ./doc + ./local.mk + ./m4 + ./Makefile + ./Makefile.config.in + ./misc + ./mk + ./precompiled-headers.h + ./src + ./tests/functional + ./COPYING + ./scripts/local.mk + (fileset.fileFilter (f: lib.strings.hasPrefix "nix-profile" f.name) ./scripts) + # TODO: do we really need README.md? It doesn't seem used in the build. + ./README.md + ]); }; # Memoize nixpkgs for different platforms for efficiency. diff --git a/mk/common-test.sh b/mk/common-test.sh index 0a2e4c1c2..7ab25febf 100644 --- a/mk/common-test.sh +++ b/mk/common-test.sh @@ -1,11 +1,15 @@ +test_dir=tests/functional + +test=$(echo -n "$test" | sed -e "s|^$test_dir/||") + TESTS_ENVIRONMENT=("TEST_NAME=${test%.*}" 'NIX_REMOTE=') : ${BASH:=/usr/bin/env bash} init_test () { - cd tests && env "${TESTS_ENVIRONMENT[@]}" $BASH -e init.sh 2>/dev/null > /dev/null + cd "$test_dir" && env "${TESTS_ENVIRONMENT[@]}" $BASH -e init.sh 2>/dev/null > /dev/null } run_test_proper () { - cd $(dirname $test) && env "${TESTS_ENVIRONMENT[@]}" $BASH -e $(basename $test) + cd "$test_dir/$(dirname $test)" && env "${TESTS_ENVIRONMENT[@]}" $BASH -e $(basename $test) } diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 26c87391c..516cbef83 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -776,7 +776,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) } }; - /* Synchronisation point for testing, see tests/gc-concurrent.sh. */ + /* Synchronisation point for testing, see tests/functional/gc-concurrent.sh. */ if (auto p = getEnv("_NIX_TEST_GC_SYNC")) readFile(*p); diff --git a/src/libutil/url-parts.hh b/src/libutil/url-parts.hh index 98162b0f7..12026921f 100644 --- a/src/libutil/url-parts.hh +++ b/src/libutil/url-parts.hh @@ -30,7 +30,7 @@ extern std::regex refRegex; /// Instead of defining what a good Git Ref is, we define what a bad Git Ref is /// This is because of the definition of a ref in refs.c in https://github.com/git/git -/// See tests/fetchGitRefs.sh for the full definition +/// See tests/functional/fetchGitRefs.sh for the full definition const static std::string badGitRefRegexS = "//|^[./]|/\\.|\\.\\.|[[:cntrl:][:space:]:?^~\[]|\\\\|\\*|\\.lock$|\\.lock/|@\\{|[/.]$|^@$|^$"; extern std::regex badGitRefRegex; diff --git a/tests/add.sh b/tests/add.sh deleted file mode 100644 index 5c3eed793..000000000 --- a/tests/add.sh +++ /dev/null @@ -1,28 +0,0 @@ -source common.sh - -path1=$(nix-store --add ./dummy) -echo $path1 - -path2=$(nix-store --add-fixed sha256 --recursive ./dummy) -echo $path2 - -if test "$path1" != "$path2"; then - echo "nix-store --add and --add-fixed mismatch" - exit 1 -fi - -path3=$(nix-store --add-fixed sha256 ./dummy) -echo $path3 -test "$path1" != "$path3" || exit 1 - -path4=$(nix-store --add-fixed sha1 --recursive ./dummy) -echo $path4 -test "$path1" != "$path4" || exit 1 - -hash1=$(nix-store -q --hash $path1) -echo $hash1 - -hash2=$(nix-hash --type sha256 --base32 ./dummy) -echo $hash2 - -test "$hash1" = "sha256:$hash2" diff --git a/tests/bad.tar.xz b/tests/bad.tar.xz deleted file mode 100644 index 250a5ad1a..000000000 Binary files a/tests/bad.tar.xz and /dev/null differ diff --git a/tests/bash-profile.sh b/tests/bash-profile.sh deleted file mode 100644 index e2e0d1090..000000000 --- a/tests/bash-profile.sh +++ /dev/null @@ -1,9 +0,0 @@ -source common.sh - -sed -e "s|@localstatedir@|$TEST_ROOT/profile-var|g" -e "s|@coreutils@|$coreutils|g" < ../scripts/nix-profile.sh.in > $TEST_ROOT/nix-profile.sh - -user=$(whoami) -rm -rf $TEST_HOME $TEST_ROOT/profile-var -mkdir -p $TEST_HOME -USER=$user $SHELL -e -c ". $TEST_ROOT/nix-profile.sh; set" -USER=$user $SHELL -e -c ". $TEST_ROOT/nix-profile.sh" # test idempotency diff --git a/tests/big-derivation-attr.nix b/tests/big-derivation-attr.nix deleted file mode 100644 index 35c1187f6..000000000 --- a/tests/big-derivation-attr.nix +++ /dev/null @@ -1,13 +0,0 @@ -let - sixteenBytes = "0123456789abcdef"; - times16 = s: builtins.concatStringsSep "" [s s s s s s s s s s s s s s s s]; - exp = n: x: if n == 1 then x else times16 (exp (n - 1) x); - sixteenMegabyte = exp 6 sixteenBytes; -in -assert builtins.stringLength sixteenMegabyte == 16777216; -derivation { - name = "big-derivation-attr"; - builder = "/x"; - system = "y"; - bigAttr = sixteenMegabyte; -} diff --git a/tests/binary-cache-build-remote.sh b/tests/binary-cache-build-remote.sh deleted file mode 100644 index 81cd21a4a..000000000 --- a/tests/binary-cache-build-remote.sh +++ /dev/null @@ -1,16 +0,0 @@ -source common.sh - -clearStore -clearCacheCache - -# Fails without remote builders -(! nix-build --store "file://$cacheDir" dependencies.nix) - -# Succeeds with default store as build remote. -outPath=$(nix-build --store "file://$cacheDir" --builders 'auto - - 1 1' -j0 dependencies.nix) - -# Test that the path exactly exists in the destination store. -nix path-info --store "file://$cacheDir" $outPath - -# Succeeds without any build capability because no-op -nix-build --store "file://$cacheDir" -j0 dependencies.nix diff --git a/tests/binary-cache.sh b/tests/binary-cache.sh deleted file mode 100644 index 7c64a115c..000000000 --- a/tests/binary-cache.sh +++ /dev/null @@ -1,286 +0,0 @@ -source common.sh - -needLocalStore "'--no-require-sigs' can’t be used with the daemon" - -# We can produce drvs directly into the binary cache -clearStore -clearCacheCache -nix-instantiate --store "file://$cacheDir" dependencies.nix - -# Create the binary cache. -clearStore -clearCache -outPath=$(nix-build dependencies.nix --no-out-link) - -nix copy --to file://$cacheDir $outPath - -# Test copying build logs to the binary cache. -expect 1 nix log --store file://$cacheDir $outPath 2>&1 | grep 'is not available' -nix store copy-log --to file://$cacheDir $outPath -nix log --store file://$cacheDir $outPath | grep FOO -rm -rf $TEST_ROOT/var/log/nix -expect 1 nix log $outPath 2>&1 | grep 'is not available' -nix log --substituters file://$cacheDir $outPath | grep FOO - -# Test copying build logs from the binary cache. -nix store copy-log --from file://$cacheDir $(nix-store -qd $outPath)^'*' -nix log $outPath | grep FOO - -basicDownloadTests() { - # No uploading tests bcause upload with force HTTP doesn't work. - - # By default, a binary cache doesn't support "nix-env -qas", but does - # support installation. - clearStore - clearCacheCache - - nix-env --substituters "file://$cacheDir" -f dependencies.nix -qas \* | grep -- "---" - - nix-store --substituters "file://$cacheDir" --no-require-sigs -r $outPath - - [ -x $outPath/program ] - - - # But with the right configuration, "nix-env -qas" should also work. - clearStore - clearCacheCache - echo "WantMassQuery: 1" >> $cacheDir/nix-cache-info - - nix-env --substituters "file://$cacheDir" -f dependencies.nix -qas \* | grep -- "--S" - nix-env --substituters "file://$cacheDir" -f dependencies.nix -qas \* | grep -- "--S" - - x=$(nix-env -f dependencies.nix -qas \* --prebuilt-only) - [ -z "$x" ] - - nix-store --substituters "file://$cacheDir" --no-require-sigs -r $outPath - - nix-store --check-validity $outPath - nix-store -qR $outPath | grep input-2 - - echo "WantMassQuery: 0" >> $cacheDir/nix-cache-info -} - - -# Test LocalBinaryCacheStore. -basicDownloadTests - - -# Test HttpBinaryCacheStore. -export _NIX_FORCE_HTTP=1 -basicDownloadTests - - -# Test whether Nix notices if the NAR doesn't match the hash in the NAR info. -clearStore - -nar=$(ls $cacheDir/nar/*.nar.xz | head -n1) -mv $nar $nar.good -mkdir -p $TEST_ROOT/empty -nix-store --dump $TEST_ROOT/empty | xz > $nar - -expect 1 nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result 2>&1 | tee $TEST_ROOT/log -grepQuiet "hash mismatch" $TEST_ROOT/log - -mv $nar.good $nar - - -# Test whether this unsigned cache is rejected if the user requires signed caches. -clearStore -clearCacheCache - -if nix-store --substituters "file://$cacheDir" -r $outPath; then - echo "unsigned binary cache incorrectly accepted" - exit 1 -fi - - -# Test whether fallback works if a NAR has disappeared. This does not require --fallback. -clearStore - -mv $cacheDir/nar $cacheDir/nar2 - -nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result - -mv $cacheDir/nar2 $cacheDir/nar - - -# Test whether fallback works if a NAR is corrupted. This does require --fallback. -clearStore - -mv $cacheDir/nar $cacheDir/nar2 -mkdir $cacheDir/nar -for i in $(cd $cacheDir/nar2 && echo *); do touch $cacheDir/nar/$i; done - -(! nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result) - -nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result --fallback - -rm -rf $cacheDir/nar -mv $cacheDir/nar2 $cacheDir/nar - - -# Test whether building works if the binary cache contains an -# incomplete closure. -clearStore - -rm -v $(grep -l "StorePath:.*dependencies-input-2" $cacheDir/*.narinfo) - -nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result 2>&1 | tee $TEST_ROOT/log -grepQuiet "copying path.*input-0" $TEST_ROOT/log -grepQuiet "copying path.*input-2" $TEST_ROOT/log -grepQuiet "copying path.*top" $TEST_ROOT/log - - -# Idem, but without cached .narinfo. -clearStore -clearCacheCache - -nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result 2>&1 | tee $TEST_ROOT/log -grepQuiet "don't know how to build" $TEST_ROOT/log -grepQuiet "building.*input-1" $TEST_ROOT/log -grepQuiet "building.*input-2" $TEST_ROOT/log -grepQuiet "copying path.*input-0" $TEST_ROOT/log -grepQuiet "copying path.*top" $TEST_ROOT/log - - -# Create a signed binary cache. -clearCache -clearCacheCache - -nix key generate-secret --key-name test.nixos.org-1 > $TEST_ROOT/sk1 -publicKey=$(nix key convert-secret-to-public < $TEST_ROOT/sk1) - -nix key generate-secret --key-name test.nixos.org-1 > $TEST_ROOT/sk2 -badKey=$(nix key convert-secret-to-public < $TEST_ROOT/sk2) - -nix key generate-secret --key-name foo.nixos.org-1 > $TEST_ROOT/sk3 -otherKey=$(nix key convert-secret-to-public < $TEST_ROOT/sk3) - -_NIX_FORCE_HTTP= nix copy --to file://$cacheDir?secret-key=$TEST_ROOT/sk1 $outPath - - -# Downloading should fail if we don't provide a key. -clearStore -clearCacheCache - -(! nix-store -r $outPath --substituters "file://$cacheDir") - - -# And it should fail if we provide an incorrect key. -clearStore -clearCacheCache - -(! nix-store -r $outPath --substituters "file://$cacheDir" --trusted-public-keys "$badKey") - - -# It should succeed if we provide the correct key. -nix-store -r $outPath --substituters "file://$cacheDir" --trusted-public-keys "$otherKey $publicKey" - - -# It should fail if we corrupt the .narinfo. -clearStore - -cacheDir2=$TEST_ROOT/binary-cache-2 -rm -rf $cacheDir2 -cp -r $cacheDir $cacheDir2 - -for i in $cacheDir2/*.narinfo; do - grep -v References $i > $i.tmp - mv $i.tmp $i -done - -clearCacheCache - -(! nix-store -r $outPath --substituters "file://$cacheDir2" --trusted-public-keys "$publicKey") - -# If we provide a bad and a good binary cache, it should succeed. - -nix-store -r $outPath --substituters "file://$cacheDir2 file://$cacheDir" --trusted-public-keys "$publicKey" - - -unset _NIX_FORCE_HTTP - - -# Test 'nix verify --all' on a binary cache. -nix store verify -vvvvv --all --store file://$cacheDir --no-trust - - -# Test local NAR caching. -narCache=$TEST_ROOT/nar-cache -rm -rf $narCache -mkdir $narCache - -[[ $(nix store cat --store "file://$cacheDir?local-nar-cache=$narCache" $outPath/foobar) = FOOBAR ]] - -rm -rfv "$cacheDir/nar" - -[[ $(nix store cat --store "file://$cacheDir?local-nar-cache=$narCache" $outPath/foobar) = FOOBAR ]] - -(! nix store cat --store file://$cacheDir $outPath/foobar) - - -# Test NAR listing generation. -clearCache - -outPath=$(nix-build --no-out-link -E ' - with import ./config.nix; - mkDerivation { - name = "nar-listing"; - buildCommand = "mkdir $out; echo foo > $out/bar; ln -s xyzzy $out/link"; - } -') - -nix copy --to file://$cacheDir?write-nar-listing=1 $outPath - -diff -u \ - <(jq -S < $cacheDir/$(basename $outPath | cut -c1-32).ls) \ - <(echo '{"version":1,"root":{"type":"directory","entries":{"bar":{"type":"regular","size":4,"narOffset":232},"link":{"type":"symlink","target":"xyzzy"}}}}' | jq -S) - - -# Test debug info index generation. -clearCache - -outPath=$(nix-build --no-out-link -E ' - with import ./config.nix; - mkDerivation { - name = "debug-info"; - buildCommand = "mkdir -p $out/lib/debug/.build-id/02; echo foo > $out/lib/debug/.build-id/02/623eda209c26a59b1a8638ff7752f6b945c26b.debug"; - } -') - -nix copy --to "file://$cacheDir?index-debug-info=1&compression=none" $outPath - -diff -u \ - <(cat $cacheDir/debuginfo/02623eda209c26a59b1a8638ff7752f6b945c26b.debug | jq -S) \ - <(echo '{"archive":"../nar/100vxs724qr46phz8m24iswmg9p3785hsyagz0kchf6q6gf06sw6.nar","member":"lib/debug/.build-id/02/623eda209c26a59b1a8638ff7752f6b945c26b.debug"}' | jq -S) - -# Test against issue https://github.com/NixOS/nix/issues/3964 -# -expr=' - with import ./config.nix; - mkDerivation { - name = "multi-output"; - buildCommand = "mkdir -p $out; echo foo > $doc; echo $doc > $out/docref"; - outputs = ["out" "doc"]; - } -' -outPath=$(nix-build --no-out-link -E "$expr") -docPath=$(nix-store -q --references $outPath) - -# $ nix-store -q --tree $outPath -# ...-multi-output -# +---...-multi-output-doc - -nix copy --to "file://$cacheDir" $outPath - -hashpart() { - basename "$1" | cut -c1-32 -} - -# break the closure of out by removing doc -rm $cacheDir/$(hashpart $docPath).narinfo - -nix-store --delete $outPath $docPath -# -vvv is the level that logs during the loop -timeout 60 nix-build --no-out-link -E "$expr" --option substituters "file://$cacheDir" \ - --option trusted-binary-caches "file://$cacheDir" --no-require-sigs diff --git a/tests/brotli.sh b/tests/brotli.sh deleted file mode 100644 index dc9bbdb66..000000000 --- a/tests/brotli.sh +++ /dev/null @@ -1,21 +0,0 @@ -source common.sh - -clearStore -clearCache - -cacheURI="file://$cacheDir?compression=br" - -outPath=$(nix-build dependencies.nix --no-out-link) - -nix copy --to $cacheURI $outPath - -HASH=$(nix hash path $outPath) - -clearStore -clearCacheCache - -nix copy --from $cacheURI $outPath --no-check-sigs - -HASH2=$(nix hash path $outPath) - -[[ $HASH = $HASH2 ]] diff --git a/tests/build-delete.sh b/tests/build-delete.sh deleted file mode 100644 index 9c56b00e8..000000000 --- a/tests/build-delete.sh +++ /dev/null @@ -1,54 +0,0 @@ -source common.sh - -clearStore - -# https://github.com/NixOS/nix/issues/6572 -issue_6572_independent_outputs() { - nix build -f multiple-outputs.nix --json independent --no-link > $TEST_ROOT/independent.json - - # Make sure that 'nix build' can build a derivation that depends on both outputs of another derivation. - p=$(nix build -f multiple-outputs.nix use-independent --no-link --print-out-paths) - nix-store --delete "$p" # Clean up for next test - - # Make sure that 'nix build' tracks input-outputs correctly when a single output is already present. - nix-store --delete "$(jq -r <$TEST_ROOT/independent.json .[0].outputs.first)" - p=$(nix build -f multiple-outputs.nix use-independent --no-link --print-out-paths) - cmp $p < $TEST_ROOT/a.json - - # # Make sure that 'nix build' can build a derivation that depends on both outputs of another derivation. - p=$(nix build -f multiple-outputs.nix use-a --no-link --print-out-paths) - nix-store --delete "$p" # Clean up for next test - - # Make sure that 'nix build' tracks input-outputs correctly when a single output is already present. - nix-store --delete "$(jq -r <$TEST_ROOT/a.json .[0].outputs.second)" - p=$(nix build -f multiple-outputs.nix use-a --no-link --print-out-paths) - cmp $p <&1 | grep "will be built" -# Now new command: -nix build -f dependencies.nix --dry-run 2>&1 | grep "will be built" - -clearStore -clearCache - -# Try --dry-run using new command first -nix build -f dependencies.nix --dry-run 2>&1 | grep "will be built" -# Now old command: -nix-build --no-out-link dependencies.nix --dry-run 2>&1 | grep "will be built" - -################################################### -# Check --dry-run doesn't create links with --dry-run -# https://github.com/NixOS/nix/issues/1849 -clearStore -clearCache - -RESULT=$TEST_ROOT/result-link -rm -f $RESULT - -nix-build dependencies.nix -o $RESULT --dry-run - -[[ ! -h $RESULT ]] || fail "nix-build --dry-run created output link" - -nix build -f dependencies.nix -o $RESULT --dry-run - -[[ ! -h $RESULT ]] || fail "nix build --dry-run created output link" - -nix build -f dependencies.nix -o $RESULT - -[[ -h $RESULT ]] - -################################################### -# Check the JSON output -clearStore -clearCache - -RES=$(nix build -f dependencies.nix --dry-run --json) - -if [[ -z "${NIX_TESTS_CA_BY_DEFAULT-}" ]]; then - echo "$RES" | jq '.[0] | [ - (.drvPath | test("'$NIX_STORE_DIR'.*\\.drv")), - (.outputs.out | test("'$NIX_STORE_DIR'")) - ] | all' -else - echo "$RES" | jq '.[0] | [ - (.drvPath | test("'$NIX_STORE_DIR'.*\\.drv")), - .outputs.out == null - ] | all' -fi diff --git a/tests/build-hook-ca-fixed.nix b/tests/build-hook-ca-fixed.nix deleted file mode 100644 index 4cb9e85d1..000000000 --- a/tests/build-hook-ca-fixed.nix +++ /dev/null @@ -1,58 +0,0 @@ -{ busybox }: - -with import ./config.nix; - -let - - mkDerivation = args: - derivation ({ - inherit system; - builder = busybox; - args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" "if [ -e .attrs.sh ]; then source .attrs.sh; fi; eval \"$buildCommand\"")]; - outputHashMode = "recursive"; - outputHashAlgo = "sha256"; - } // removeAttrs args ["builder" "meta" "passthru"]) - // { meta = args.meta or {}; passthru = args.passthru or {}; }; - - input1 = mkDerivation { - shell = busybox; - name = "build-remote-input-1"; - buildCommand = "echo hi-input1; echo FOO > $out"; - requiredSystemFeatures = ["foo"]; - outputHash = "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="; - }; - - input2 = mkDerivation { - shell = busybox; - name = "build-remote-input-2"; - buildCommand = "echo hi; echo BAR > $out"; - requiredSystemFeatures = ["bar"]; - outputHash = "sha256-XArauVH91AVwP9hBBQNlkX9ccuPpSYx9o0zeIHb6e+Q="; - }; - - input3 = mkDerivation { - shell = busybox; - name = "build-remote-input-3"; - buildCommand = '' - echo hi-input3 - read x < ${input2} - echo $x BAZ > $out - ''; - requiredSystemFeatures = ["baz"]; - outputHash = "sha256-daKAcPp/+BYMQsVi/YYMlCKoNAxCNDsaivwSHgQqD2s="; - }; - -in - - mkDerivation { - shell = busybox; - name = "build-remote"; - passthru = { inherit input1 input2 input3; }; - buildCommand = - '' - read x < ${input1} - read y < ${input3} - echo "$x $y" > $out - ''; - outputHash = "sha256-5SxbkUw6xe2l9TE1uwCvTtTDysD1vhRor38OtDF0LqQ="; - } diff --git a/tests/build-hook-ca-floating.nix b/tests/build-hook-ca-floating.nix deleted file mode 100644 index dfdbb82da..000000000 --- a/tests/build-hook-ca-floating.nix +++ /dev/null @@ -1,6 +0,0 @@ -{ busybox }: - -import ./build-hook.nix { - inherit busybox; - contentAddressed = true; -} diff --git a/tests/build-hook.nix b/tests/build-hook.nix deleted file mode 100644 index 7effd7903..000000000 --- a/tests/build-hook.nix +++ /dev/null @@ -1,59 +0,0 @@ -{ busybox, contentAddressed ? false }: - -with import ./config.nix; - -let - - caArgs = if contentAddressed then { - outputHashMode = "recursive"; - outputHashAlgo = "sha256"; - __contentAddressed = true; - } else {}; - - mkDerivation = args: - derivation ({ - inherit system; - builder = busybox; - args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" "if [ -e .attrs.sh ]; then source .attrs.sh; fi; eval \"$buildCommand\"")]; - } // removeAttrs args ["builder" "meta" "passthru"] - // caArgs) - // { meta = args.meta or {}; passthru = args.passthru or {}; }; - - input1 = mkDerivation { - shell = busybox; - name = "build-remote-input-1"; - buildCommand = "echo hi-input1; echo FOO > $out"; - requiredSystemFeatures = ["foo"]; - }; - - input2 = mkDerivation { - shell = busybox; - name = "build-remote-input-2"; - buildCommand = "echo hi; echo BAR > $out"; - requiredSystemFeatures = ["bar"]; - }; - - input3 = mkDerivation { - shell = busybox; - name = "build-remote-input-3"; - buildCommand = '' - echo hi-input3 - read x < ${input2} - echo $x BAZ > $out - ''; - requiredSystemFeatures = ["baz"]; - }; - -in - - mkDerivation { - shell = busybox; - name = "build-remote"; - passthru = { inherit input1 input2 input3; }; - buildCommand = - '' - read x < ${input1} - read y < ${input3} - echo "$x $y" > $out - ''; - } diff --git a/tests/build-remote-content-addressed-fixed.sh b/tests/build-remote-content-addressed-fixed.sh deleted file mode 100644 index ae7441591..000000000 --- a/tests/build-remote-content-addressed-fixed.sh +++ /dev/null @@ -1,5 +0,0 @@ -source common.sh - -file=build-hook-ca-fixed.nix - -source build-remote.sh diff --git a/tests/build-remote-content-addressed-floating.sh b/tests/build-remote-content-addressed-floating.sh deleted file mode 100644 index e83b42b41..000000000 --- a/tests/build-remote-content-addressed-floating.sh +++ /dev/null @@ -1,9 +0,0 @@ -source common.sh - -file=build-hook-ca-floating.nix - -enableFeatures "ca-derivations" - -CONTENT_ADDRESSED=true - -source build-remote.sh diff --git a/tests/build-remote-input-addressed.sh b/tests/build-remote-input-addressed.sh deleted file mode 100644 index 49d15c389..000000000 --- a/tests/build-remote-input-addressed.sh +++ /dev/null @@ -1,33 +0,0 @@ -source common.sh - -file=build-hook.nix - -source build-remote.sh - -# Add a `post-build-hook` option to the nix conf. -# This hook will be executed both for the local machine and the remote builders -# (because they share the same config). -registerBuildHook () { - # Dummy post-build-hook just to ensure that it's executed correctly. - # (we can't reuse the one from `$PWD/push-to-store.sh` because of - # https://github.com/NixOS/nix/issues/4341) - cat < $TEST_ROOT/post-build-hook.sh -#!/bin/sh - -echo "Post hook ran successfully" -# Add an empty line to a counter file, just to check that this hook ran properly -echo "" >> $TEST_ROOT/post-hook-counter -EOF - chmod +x $TEST_ROOT/post-build-hook.sh - rm -f $TEST_ROOT/post-hook-counter - - echo "post-build-hook = $TEST_ROOT/post-build-hook.sh" >> $NIX_CONF_DIR/nix.conf -} - -registerBuildHook -source build-remote.sh - -# `build-hook.nix` has four derivations to build, and the hook runs twice for -# each derivation (once on the builder and once on the host), so the counter -# should contain eight lines now -[[ $(cat $TEST_ROOT/post-hook-counter | wc -l) -eq 8 ]] diff --git a/tests/build-remote-trustless-after.sh b/tests/build-remote-trustless-after.sh deleted file mode 100644 index 19f59e6ae..000000000 --- a/tests/build-remote-trustless-after.sh +++ /dev/null @@ -1,2 +0,0 @@ -outPath=$(readlink -f $TEST_ROOT/result) -grep 'FOO BAR BAZ' ${remoteDir}/${outPath} diff --git a/tests/build-remote-trustless-should-fail-0.sh b/tests/build-remote-trustless-should-fail-0.sh deleted file mode 100644 index fad1def59..000000000 --- a/tests/build-remote-trustless-should-fail-0.sh +++ /dev/null @@ -1,29 +0,0 @@ -source common.sh - -enableFeatures "daemon-trust-override" - -restartDaemon - -[[ $busybox =~ busybox ]] || skipTest "no busybox" - -unset NIX_STORE_DIR -unset NIX_STATE_DIR - -# We first build a dependency of the derivation we eventually want to -# build. -nix-build build-hook.nix -A passthru.input2 \ - -o "$TEST_ROOT/input2" \ - --arg busybox "$busybox" \ - --store "$TEST_ROOT/local" \ - --option system-features bar - -# Now when we go to build that downstream derivation, Nix will try to -# copy our already-build `input2` to the remote store. That store object -# is input-addressed, so this will fail. - -file=build-hook.nix -prog=$(readlink -e ./nix-daemon-untrusting.sh) -proto=ssh-ng - -expectStderr 1 source build-remote-trustless.sh \ - | grepQuiet "cannot add path '[^ ]*' because it lacks a signature by a trusted key" diff --git a/tests/build-remote-trustless-should-pass-0.sh b/tests/build-remote-trustless-should-pass-0.sh deleted file mode 100644 index 2a7ebd8c6..000000000 --- a/tests/build-remote-trustless-should-pass-0.sh +++ /dev/null @@ -1,9 +0,0 @@ -source common.sh - -# Remote trusts us -file=build-hook.nix -prog=nix-store -proto=ssh - -source build-remote-trustless.sh -source build-remote-trustless-after.sh diff --git a/tests/build-remote-trustless-should-pass-1.sh b/tests/build-remote-trustless-should-pass-1.sh deleted file mode 100644 index 516bdf092..000000000 --- a/tests/build-remote-trustless-should-pass-1.sh +++ /dev/null @@ -1,9 +0,0 @@ -source common.sh - -# Remote trusts us -file=build-hook.nix -prog=nix-daemon -proto=ssh-ng - -source build-remote-trustless.sh -source build-remote-trustless-after.sh diff --git a/tests/build-remote-trustless-should-pass-2.sh b/tests/build-remote-trustless-should-pass-2.sh deleted file mode 100644 index b769a88f0..000000000 --- a/tests/build-remote-trustless-should-pass-2.sh +++ /dev/null @@ -1,13 +0,0 @@ -source common.sh - -enableFeatures "daemon-trust-override" - -restartDaemon - -# Remote doesn't trust us -file=build-hook.nix -prog=$(readlink -e ./nix-daemon-untrusting.sh) -proto=ssh-ng - -source build-remote-trustless.sh -source build-remote-trustless-after.sh diff --git a/tests/build-remote-trustless-should-pass-3.sh b/tests/build-remote-trustless-should-pass-3.sh deleted file mode 100644 index 40f81da5a..000000000 --- a/tests/build-remote-trustless-should-pass-3.sh +++ /dev/null @@ -1,14 +0,0 @@ -source common.sh - -enableFeatures "daemon-trust-override" - -restartDaemon - -# Remote doesn't trusts us, but this is fine because we are only -# building (fixed) CA derivations. -file=build-hook-ca-fixed.nix -prog=$(readlink -e ./nix-daemon-untrusting.sh) -proto=ssh-ng - -source build-remote-trustless.sh -source build-remote-trustless-after.sh diff --git a/tests/build-remote-trustless.sh b/tests/build-remote-trustless.sh deleted file mode 100644 index 9df44e0c5..000000000 --- a/tests/build-remote-trustless.sh +++ /dev/null @@ -1,14 +0,0 @@ -requireSandboxSupport -[[ $busybox =~ busybox ]] || skipTest "no busybox" - -unset NIX_STORE_DIR -unset NIX_STATE_DIR - -remoteDir=$TEST_ROOT/remote - -# Note: ssh{-ng}://localhost bypasses ssh. See tests/build-remote.sh for -# more details. -nix-build $file -o $TEST_ROOT/result --max-jobs 0 \ - --arg busybox $busybox \ - --store $TEST_ROOT/local \ - --builders "$proto://localhost?remote-program=$prog&remote-store=${remoteDir}%3Fsystem-features=foo%20bar%20baz - - 1 1 foo,bar,baz" diff --git a/tests/build-remote.sh b/tests/build-remote.sh deleted file mode 100644 index d2a2132c1..000000000 --- a/tests/build-remote.sh +++ /dev/null @@ -1,84 +0,0 @@ -requireSandboxSupport -[[ $busybox =~ busybox ]] || skipTest "no busybox" - -# Avoid store dir being inside sandbox build-dir -unset NIX_STORE_DIR -unset NIX_STATE_DIR - -function join_by { local d=$1; shift; echo -n "$1"; shift; printf "%s" "${@/#/$d}"; } - -EXTRA_SYSTEM_FEATURES=() -if [[ -n "${CONTENT_ADDRESSED-}" ]]; then - EXTRA_SYSTEM_FEATURES=("ca-derivations") -fi - -builders=( - # system-features will automatically be added to the outer URL, but not inner - # remote-store URL. - "ssh://localhost?remote-store=$TEST_ROOT/machine1?system-features=$(join_by "%20" foo ${EXTRA_SYSTEM_FEATURES[@]}) - - 1 1 $(join_by "," foo ${EXTRA_SYSTEM_FEATURES[@]})" - "$TEST_ROOT/machine2 - - 1 1 $(join_by "," bar ${EXTRA_SYSTEM_FEATURES[@]})" - "ssh-ng://localhost?remote-store=$TEST_ROOT/machine3?system-features=$(join_by "%20" baz ${EXTRA_SYSTEM_FEATURES[@]}) - - 1 1 $(join_by "," baz ${EXTRA_SYSTEM_FEATURES[@]})" -) - -chmod -R +w $TEST_ROOT/machine* || true -rm -rf $TEST_ROOT/machine* || true - -# Note: ssh://localhost bypasses ssh, directly invoking nix-store as a -# child process. This allows us to test LegacySSHStore::buildDerivation(). -# ssh-ng://... likewise allows us to test RemoteStore::buildDerivation(). -nix build -L -v -f $file -o $TEST_ROOT/result --max-jobs 0 \ - --arg busybox $busybox \ - --store $TEST_ROOT/machine0 \ - --builders "$(join_by '; ' "${builders[@]}")" - -outPath=$(readlink -f $TEST_ROOT/result) - -grep 'FOO BAR BAZ' $TEST_ROOT/machine0/$outPath - -testPrintOutPath=$(nix build -L -v -f $file --no-link --print-out-paths --max-jobs 0 \ - --arg busybox $busybox \ - --store $TEST_ROOT/machine0 \ - --builders "$(join_by '; ' "${builders[@]}")" -) - -[[ $testPrintOutPath =~ store.*build-remote ]] - -# Ensure that input1 was built on store1 due to the required feature. -output=$(nix path-info --store $TEST_ROOT/machine1 --all) -echo "$output" | grepQuiet builder-build-remote-input-1.sh -echo "$output" | grepQuietInverse builder-build-remote-input-2.sh -echo "$output" | grepQuietInverse builder-build-remote-input-3.sh -unset output - -# Ensure that input2 was built on store2 due to the required feature. -output=$(nix path-info --store $TEST_ROOT/machine2 --all) -echo "$output" | grepQuietInverse builder-build-remote-input-1.sh -echo "$output" | grepQuiet builder-build-remote-input-2.sh -echo "$output" | grepQuietInverse builder-build-remote-input-3.sh -unset output - -# Ensure that input3 was built on store3 due to the required feature. -output=$(nix path-info --store $TEST_ROOT/machine3 --all) -echo "$output" | grepQuietInverse builder-build-remote-input-1.sh -echo "$output" | grepQuietInverse builder-build-remote-input-2.sh -echo "$output" | grepQuiet builder-build-remote-input-3.sh -unset output - - -for i in input1 input3; do -nix log --store $TEST_ROOT/machine0 --file "$file" --arg busybox $busybox passthru."$i" | grep hi-$i -done - -# Behavior of keep-failed -out="$(nix-build 2>&1 failing.nix \ - --no-out-link \ - --builders "$(join_by '; ' "${builders[@]}")" \ - --keep-failed \ - --store $TEST_ROOT/machine0 \ - -j0 \ - --arg busybox $busybox)" || true - -[[ "$out" =~ .*"note: keeping build directory".* ]] - -build_dir="$(grep "note: keeping build" <<< "$out" | sed -E "s/^(.*)note: keeping build directory '(.*)'(.*)$/\2/")" -[[ "foo" = $(<"$build_dir"/bar) ]] diff --git a/tests/build.sh b/tests/build.sh deleted file mode 100644 index 7fbdb0f07..000000000 --- a/tests/build.sh +++ /dev/null @@ -1,135 +0,0 @@ -source common.sh - -clearStore - -# Make sure that 'nix build' returns all outputs by default. -nix build -f multiple-outputs.nix --json a b --no-link | jq --exit-status ' - (.[0] | - (.drvPath | match(".*multiple-outputs-a.drv")) and - (.outputs | - (keys | length == 2) and - (.first | match(".*multiple-outputs-a-first")) and - (.second | match(".*multiple-outputs-a-second")))) - and (.[1] | - (.drvPath | match(".*multiple-outputs-b.drv")) and - (.outputs | - (keys | length == 1) and - (.out | match(".*multiple-outputs-b")))) -' - -# Test output selection using the '^' syntax. -nix build -f multiple-outputs.nix --json a^first --no-link | jq --exit-status ' - (.[0] | - (.drvPath | match(".*multiple-outputs-a.drv")) and - (.outputs | keys == ["first"])) -' - -nix build -f multiple-outputs.nix --json a^second,first --no-link | jq --exit-status ' - (.[0] | - (.drvPath | match(".*multiple-outputs-a.drv")) and - (.outputs | keys == ["first", "second"])) -' - -nix build -f multiple-outputs.nix --json 'a^*' --no-link | jq --exit-status ' - (.[0] | - (.drvPath | match(".*multiple-outputs-a.drv")) and - (.outputs | keys == ["first", "second"])) -' - -# Test that 'outputsToInstall' is respected by default. -nix build -f multiple-outputs.nix --json e --no-link | jq --exit-status ' - (.[0] | - (.drvPath | match(".*multiple-outputs-e.drv")) and - (.outputs | keys == ["a_a", "b"])) -' - -# But not when it's overriden. -nix build -f multiple-outputs.nix --json e^a_a --no-link -nix build -f multiple-outputs.nix --json e^a_a --no-link | jq --exit-status ' - (.[0] | - (.drvPath | match(".*multiple-outputs-e.drv")) and - (.outputs | keys == ["a_a"])) -' - -nix build -f multiple-outputs.nix --json 'e^*' --no-link | jq --exit-status ' - (.[0] | - (.drvPath | match(".*multiple-outputs-e.drv")) and - (.outputs | keys == ["a_a", "b", "c"])) -' - -# test buidling from non-drv attr path - -nix build -f multiple-outputs.nix --json 'e.a_a.outPath' --no-link | jq --exit-status ' - (.[0] | - (.drvPath | match(".*multiple-outputs-e.drv")) and - (.outputs | keys == ["a_a"])) -' - -# Illegal type of string context -expectStderr 1 nix build -f multiple-outputs.nix 'e.a_a.drvPath' \ - | grepQuiet "has a context which refers to a complete source and binary closure." - -# No string context -expectStderr 1 nix build --expr '""' --no-link \ - | grepQuiet "has 0 entries in its context. It should only have exactly one entry" - -# Too much string context -expectStderr 1 nix build --impure --expr 'with (import ./multiple-outputs.nix).e.a_a; "${drvPath}${outPath}"' --no-link \ - | grepQuiet "has 2 entries in its context. It should only have exactly one entry" - -nix build --impure --json --expr 'builtins.unsafeDiscardOutputDependency (import ./multiple-outputs.nix).e.a_a.drvPath' --no-link | jq --exit-status ' - (.[0] | match(".*multiple-outputs-e.drv")) -' - -# Test building from raw store path to drv not expression. - -drv=$(nix eval -f multiple-outputs.nix --raw a.drvPath) -if nix build "$drv^not-an-output" --no-link --json; then - fail "'not-an-output' should fail to build" -fi - -if nix build "$drv^" --no-link --json; then - fail "'empty outputs list' should fail to build" -fi - -if nix build "$drv^*nope" --no-link --json; then - fail "'* must be entire string' should fail to build" -fi - -nix build "$drv^first" --no-link --json | jq --exit-status ' - (.[0] | - (.drvPath | match(".*multiple-outputs-a.drv")) and - (.outputs | - (keys | length == 1) and - (.first | match(".*multiple-outputs-a-first")) and - (has("second") | not))) -' - -nix build "$drv^first,second" --no-link --json | jq --exit-status ' - (.[0] | - (.drvPath | match(".*multiple-outputs-a.drv")) and - (.outputs | - (keys | length == 2) and - (.first | match(".*multiple-outputs-a-first")) and - (.second | match(".*multiple-outputs-a-second")))) -' - -nix build "$drv^*" --no-link --json | jq --exit-status ' - (.[0] | - (.drvPath | match(".*multiple-outputs-a.drv")) and - (.outputs | - (keys | length == 2) and - (.first | match(".*multiple-outputs-a-first")) and - (.second | match(".*multiple-outputs-a-second")))) -' - -# Make sure that `--impure` works (regression test for https://github.com/NixOS/nix/issues/6488) -nix build --impure -f multiple-outputs.nix --json e --no-link | jq --exit-status ' - (.[0] | - (.drvPath | match(".*multiple-outputs-e.drv")) and - (.outputs | keys == ["a_a", "b"])) -' - -# Make sure that `--stdin` works and does not apply any defaults -printf "" | nix build --no-link --stdin --json | jq --exit-status '. == []' -printf "%s\n" "$drv^*" | nix build --no-link --stdin --json | jq --exit-status '.[0]|has("drvPath")' diff --git a/tests/ca-shell.nix b/tests/ca-shell.nix deleted file mode 100644 index 36e1d1526..000000000 --- a/tests/ca-shell.nix +++ /dev/null @@ -1 +0,0 @@ -{ inNixShell ? false, ... }@args: import ./shell.nix (args // { contentAddressed = true; }) diff --git a/tests/ca/build-cache.sh b/tests/ca/build-cache.sh deleted file mode 100644 index 6a4080fec..000000000 --- a/tests/ca/build-cache.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash - -source common.sh - -# The substituters didn't work prior to this time. -requireDaemonNewerThan "2.18.0pre20230808" - -drv=$(nix-instantiate ./content-addressed.nix -A rootCA --arg seed 1)^out -nix derivation show "$drv" --arg seed 1 - -buildAttr () { - local derivationPath=$1 - local seedValue=$2 - shift; shift - local args=("./content-addressed.nix" "-A" "$derivationPath" --arg seed "$seedValue" "--no-out-link") - args+=("$@") - nix-build "${args[@]}" -} - -copyAttr () { - local derivationPath=$1 - local seedValue=$2 - shift; shift - local args=("-f" "./content-addressed.nix" "$derivationPath" --arg seed "$seedValue") - args+=("$@") - # Note: to copy CA derivations, we need to copy the realisations, which - # currently requires naming the installables, not just the derivation output - # path. - nix copy --to file://$cacheDir "${args[@]}" -} - -testRemoteCacheFor () { - local derivationPath=$1 - clearCache - copyAttr "$derivationPath" 1 - clearStore - # Check nothing gets built. - buildAttr "$derivationPath" 1 --option substituters file://$cacheDir --no-require-sigs |& grepQuietInverse " will be built:" -} - -testRemoteCache () { - testRemoteCacheFor rootCA - testRemoteCacheFor dependentCA - testRemoteCacheFor dependentNonCA - testRemoteCacheFor dependentFixedOutput - testRemoteCacheFor dependentForBuildCA - testRemoteCacheFor dependentForBuildNonCA -} - -clearStore -testRemoteCache \ No newline at end of file diff --git a/tests/ca/build-dry.sh b/tests/ca/build-dry.sh deleted file mode 100644 index 9a72075ec..000000000 --- a/tests/ca/build-dry.sh +++ /dev/null @@ -1,6 +0,0 @@ -source common.sh - -export NIX_TESTS_CA_BY_DEFAULT=1 - -cd .. && source build-dry.sh - diff --git a/tests/ca/build-with-garbage-path.sh b/tests/ca/build-with-garbage-path.sh deleted file mode 100755 index 884cd2802..000000000 --- a/tests/ca/build-with-garbage-path.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash - -# Regression test for https://github.com/NixOS/nix/issues/4858 - -source common.sh - -requireDaemonNewerThan "2.4pre20210621" - -# Get the output path of `rootCA`, and put some garbage instead -outPath="$(nix-build ./content-addressed.nix -A rootCA --no-out-link)" -nix-store --delete $(nix-store -q --referrers-closure "$outPath") -touch "$outPath" - -# The build should correctly remove the garbage and put the expected path instead -nix-build ./content-addressed.nix -A rootCA --no-out-link - -# Rebuild it. This shouldn’t overwrite the existing path -oldInode=$(stat -c '%i' "$outPath") -nix-build ./content-addressed.nix -A rootCA --no-out-link --arg seed 2 -newInode=$(stat -c '%i' "$outPath") -[[ "$oldInode" == "$newInode" ]] diff --git a/tests/ca/build.sh b/tests/ca/build.sh deleted file mode 100644 index e1a8a7625..000000000 --- a/tests/ca/build.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env bash - -source common.sh - -drv=$(nix-instantiate ./content-addressed.nix -A rootCA --arg seed 1)^out -nix derivation show "$drv" --arg seed 1 - -buildAttr () { - local derivationPath=$1 - local seedValue=$2 - shift; shift - local args=("./content-addressed.nix" "-A" "$derivationPath" --arg seed "$seedValue" "--no-out-link") - args+=("$@") - nix-build "${args[@]}" -} - -testDeterministicCA () { - [[ $(buildAttr rootCA 1) = $(buildAttr rootCA 2) ]] -} - -testCutoffFor () { - local out1 out2 - out1=$(buildAttr $1 1) - # The seed only changes the root derivation, and not it's output, so the - # dependent derivations should only need to be built once. - buildAttr rootCA 2 - out2=$(buildAttr $1 2 -j0) - test "$out1" == "$out2" -} - -testCutoff () { - # Don't directly build dependentCA, that way we'll make sure we don't rely on - # dependent derivations always being already built. - #testDerivation dependentCA - testCutoffFor transitivelyDependentCA - testCutoffFor dependentNonCA - testCutoffFor dependentFixedOutput -} - -testGC () { - nix-instantiate ./content-addressed.nix -A rootCA --arg seed 5 - nix-collect-garbage --option keep-derivations true - clearStore - buildAttr rootCA 1 --out-link $TEST_ROOT/rootCA - nix-collect-garbage - buildAttr rootCA 1 -j0 -} - -testNixCommand () { - clearStore - nix build --file ./content-addressed.nix --no-link -} - -# Regression test for https://github.com/NixOS/nix/issues/4775 -testNormalization () { - clearStore - outPath=$(buildAttr rootCA 1) - test "$(stat -c %Y $outPath)" -eq 1 -} - -clearStore -testNormalization -testDeterministicCA -clearStore -testCutoff -testGC -testNixCommand diff --git a/tests/ca/common.sh b/tests/ca/common.sh deleted file mode 100644 index b104b5a78..000000000 --- a/tests/ca/common.sh +++ /dev/null @@ -1,5 +0,0 @@ -source ../common.sh - -enableFeatures "ca-derivations" - -restartDaemon diff --git a/tests/ca/concurrent-builds.sh b/tests/ca/concurrent-builds.sh deleted file mode 100755 index b442619e2..000000000 --- a/tests/ca/concurrent-builds.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash - -# Ensure that we can’t build twice the same derivation concurrently. -# Regression test for https://github.com/NixOS/nix/issues/5029 - -source common.sh - -buggyNeedLocalStore "For some reason, this deadlocks with the daemon" - -export NIX_TESTS_CA_BY_DEFAULT=1 - -clearStore - -for i in {0..5}; do - nix build --no-link --file ./racy.nix & -done - -wait diff --git a/tests/ca/config.nix.in b/tests/ca/config.nix.in deleted file mode 120000 index af24ddb30..000000000 --- a/tests/ca/config.nix.in +++ /dev/null @@ -1 +0,0 @@ -../config.nix.in \ No newline at end of file diff --git a/tests/ca/content-addressed.nix b/tests/ca/content-addressed.nix deleted file mode 100644 index 2559c562f..000000000 --- a/tests/ca/content-addressed.nix +++ /dev/null @@ -1,100 +0,0 @@ -with import ./config.nix; - -let mkCADerivation = args: mkDerivation ({ - __contentAddressed = true; - outputHashMode = "recursive"; - outputHashAlgo = "sha256"; -} // args); -in - -{ seed ? 0 }: -# A simple content-addressed derivation. -# The derivation can be arbitrarily modified by passing a different `seed`, -# but the output will always be the same -rec { - rootLegacy = mkDerivation { - name = "simple-input-addressed"; - buildCommand = '' - set -x - echo "Building a legacy derivation" - mkdir -p $out - echo "Hello World" > $out/hello - ''; - }; - rootCA = mkCADerivation { - name = "rootCA"; - outputs = [ "out" "dev" "foo" ]; - buildCommand = '' - echo "building a CA derivation" - echo "The seed is ${toString seed}" - mkdir -p $out - echo ${rootLegacy}/hello > $out/dep - ln -s $out $out/self - # test symlinks at root - ln -s $out $dev - ln -s $out $foo - ''; - }; - dependentCA = mkCADerivation { - name = "dependent"; - buildCommand = '' - echo "building a dependent derivation" - mkdir -p $out - cat ${rootCA}/self/dep - echo ${rootCA}/self/dep > $out/dep - ''; - }; - transitivelyDependentCA = mkCADerivation { - name = "transitively-dependent"; - buildCommand = '' - echo "building transitively-dependent" - cat ${dependentCA}/dep - echo ${dependentCA} > $out - ''; - }; - dependentNonCA = mkDerivation { - name = "dependent-non-ca"; - buildCommand = '' - echo "Didn't cut-off" - echo "building dependent-non-ca" - mkdir -p $out - echo ${rootCA}/non-ca-hello > $out/dep - ''; - }; - dependentForBuildCA = mkCADerivation { - name = "dependent-for-build-ca"; - buildCommand = '' - echo "Depends on rootCA for building only" - mkdir -p $out - echo ${rootCA} - touch $out - ''; - }; - dependentForBuildNonCA = mkDerivation { - name = "dependent-for-build-non-ca"; - buildCommand = '' - echo "Depends on rootCA for building only" - mkdir -p $out - echo ${rootCA} - touch $out - ''; - }; - dependentFixedOutput = mkDerivation { - name = "dependent-fixed-output"; - outputHashMode = "recursive"; - outputHash = "sha512-7aJcmSuEuYP5tGKcmGY8bRr/lrCjJlOxP2mIUjO/vMQeg6gx/65IbzRWES8EKiPDOs9z+wF30lEfcwxM/cT4pw=="; - buildCommand = '' - cat ${dependentCA}/dep - echo foo > $out - ''; - }; - runnable = mkCADerivation rec { - name = "runnable-thing"; - buildCommand = '' - mkdir -p $out/bin - echo ${rootCA} # Just to make it depend on it - echo "#! ${shell}" > $out/bin/${name} - chmod +x $out/bin/${name} - ''; - }; -} diff --git a/tests/ca/derivation-json.sh b/tests/ca/derivation-json.sh deleted file mode 100644 index c1480fd17..000000000 --- a/tests/ca/derivation-json.sh +++ /dev/null @@ -1,29 +0,0 @@ -source common.sh - -export NIX_TESTS_CA_BY_DEFAULT=1 - -drvPath=$(nix-instantiate ../simple.nix) - -nix derivation show $drvPath | jq .[] > $TEST_HOME/simple.json - -drvPath2=$(nix derivation add < $TEST_HOME/simple.json) - -[[ "$drvPath" = "$drvPath2" ]] - -# Content-addressed derivations can be renamed. -jq '.name = "foo"' < $TEST_HOME/simple.json > $TEST_HOME/foo.json -drvPath3=$(nix derivation add --dry-run < $TEST_HOME/foo.json) -# With --dry-run nothing is actually written -[[ ! -e "$drvPath3" ]] - -# But the JSON is rejected without the experimental feature -expectStderr 1 nix derivation add < $TEST_HOME/foo.json --experimental-features nix-command | grepQuiet "experimental Nix feature 'ca-derivations' is disabled" - -# Without --dry-run it is actually written -drvPath4=$(nix derivation add < $TEST_HOME/foo.json) -[[ "$drvPath4" = "$drvPath3" ]] -[[ -e "$drvPath3" ]] - -# The modified derivation read back as JSON matches -nix derivation show $drvPath3 | jq .[] > $TEST_HOME/foo-read.json -diff $TEST_HOME/foo.json $TEST_HOME/foo-read.json diff --git a/tests/ca/duplicate-realisation-in-closure.sh b/tests/ca/duplicate-realisation-in-closure.sh deleted file mode 100644 index da9cd8fb4..000000000 --- a/tests/ca/duplicate-realisation-in-closure.sh +++ /dev/null @@ -1,26 +0,0 @@ -source ./common.sh - -requireDaemonNewerThan "2.4pre20210625" - -export REMOTE_STORE_DIR="$TEST_ROOT/remote_store" -export REMOTE_STORE="file://$REMOTE_STORE_DIR" - -rm -rf $REMOTE_STORE_DIR -clearStore - -# Build dep1 and push that to the binary cache. -# This entails building (and pushing) current-time. -nix copy --to "$REMOTE_STORE" -f nondeterministic.nix dep1 -clearStore -sleep 2 # To make sure that `$(date)` will be different -# Build dep2. -# As we’ve cleared the cache, we’ll have to rebuild current-time. And because -# the current time isn’t the same as before, this will yield a new (different) -# realisation -nix build -f nondeterministic.nix dep2 --no-link - -# Build something that depends both on dep1 and dep2. -# If everything goes right, we should rebuild dep2 rather than fetch it from -# the cache (because that would mean duplicating `current-time` in the closure), -# and have `dep1 == dep2`. -nix build --substituters "$REMOTE_STORE" -f nondeterministic.nix toplevel --no-require-sigs --no-link diff --git a/tests/ca/flake.nix b/tests/ca/flake.nix deleted file mode 100644 index 332c92a67..000000000 --- a/tests/ca/flake.nix +++ /dev/null @@ -1,3 +0,0 @@ -{ - outputs = { self }: import ./content-addressed.nix {}; -} diff --git a/tests/ca/gc.sh b/tests/ca/gc.sh deleted file mode 100755 index e9b6c5ab5..000000000 --- a/tests/ca/gc.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -# Ensure that garbage collection works properly with ca derivations - -source common.sh - -export NIX_TESTS_CA_BY_DEFAULT=1 - -cd .. -source gc.sh diff --git a/tests/ca/import-derivation.sh b/tests/ca/import-derivation.sh deleted file mode 100644 index e98e0fbd0..000000000 --- a/tests/ca/import-derivation.sh +++ /dev/null @@ -1,6 +0,0 @@ -source common.sh - -export NIX_TESTS_CA_BY_DEFAULT=1 - -cd .. && source import-derivation.sh - diff --git a/tests/ca/local.mk b/tests/ca/local.mk deleted file mode 100644 index 0852e592e..000000000 --- a/tests/ca/local.mk +++ /dev/null @@ -1,28 +0,0 @@ -ca-tests := \ - $(d)/build-with-garbage-path.sh \ - $(d)/build.sh \ - $(d)/build-cache.sh \ - $(d)/concurrent-builds.sh \ - $(d)/derivation-json.sh \ - $(d)/duplicate-realisation-in-closure.sh \ - $(d)/gc.sh \ - $(d)/import-derivation.sh \ - $(d)/new-build-cmd.sh \ - $(d)/nix-copy.sh \ - $(d)/nix-run.sh \ - $(d)/nix-shell.sh \ - $(d)/post-hook.sh \ - $(d)/recursive.sh \ - $(d)/repl.sh \ - $(d)/selfref-gc.sh \ - $(d)/signatures.sh \ - $(d)/substitute.sh \ - $(d)/why-depends.sh - -install-tests-groups += ca - -clean-files += \ - $(d)/config.nix - -test-deps += \ - tests/ca/config.nix diff --git a/tests/ca/new-build-cmd.sh b/tests/ca/new-build-cmd.sh deleted file mode 100644 index 432d4d132..000000000 --- a/tests/ca/new-build-cmd.sh +++ /dev/null @@ -1,5 +0,0 @@ -source common.sh - -export NIX_TESTS_CA_BY_DEFAULT=1 -cd .. -source ./build.sh diff --git a/tests/ca/nix-copy.sh b/tests/ca/nix-copy.sh deleted file mode 100755 index 7a8307a4e..000000000 --- a/tests/ca/nix-copy.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash - -source common.sh - -export REMOTE_STORE_DIR="$TEST_ROOT/remote_store" -export REMOTE_STORE="file://$REMOTE_STORE_DIR" - -ensureCorrectlyCopied () { - attrPath="$1" - nix build --store "$REMOTE_STORE" --file ./content-addressed.nix "$attrPath" -} - -testOneCopy () { - clearStore - rm -rf "$REMOTE_STORE_DIR" - - attrPath="$1" - nix copy --to $REMOTE_STORE "$attrPath" --file ./content-addressed.nix - - ensureCorrectlyCopied "$attrPath" - - # Ensure that we can copy back what we put in the store - clearStore - nix copy --from $REMOTE_STORE \ - --file ./content-addressed.nix "$attrPath" \ - --no-check-sigs -} - -for attrPath in rootCA dependentCA transitivelyDependentCA dependentNonCA dependentFixedOutput; do - testOneCopy "$attrPath" -done diff --git a/tests/ca/nix-run.sh b/tests/ca/nix-run.sh deleted file mode 100755 index 5f46518e8..000000000 --- a/tests/ca/nix-run.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -source common.sh - -FLAKE_PATH=path:$PWD - -nix run --no-write-lock-file $FLAKE_PATH#runnable diff --git a/tests/ca/nix-shell.sh b/tests/ca/nix-shell.sh deleted file mode 100755 index 1c5a6639f..000000000 --- a/tests/ca/nix-shell.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -source common.sh - -CONTENT_ADDRESSED=true -cd .. -source ./nix-shell.sh - diff --git a/tests/ca/nondeterministic.nix b/tests/ca/nondeterministic.nix deleted file mode 100644 index d6d099a3e..000000000 --- a/tests/ca/nondeterministic.nix +++ /dev/null @@ -1,35 +0,0 @@ -with import ./config.nix; - -let mkCADerivation = args: mkDerivation ({ - __contentAddressed = true; - outputHashMode = "recursive"; - outputHashAlgo = "sha256"; -} // args); -in - -rec { - currentTime = mkCADerivation { - name = "current-time"; - buildCommand = '' - mkdir $out - echo $(date) > $out/current-time - ''; - }; - dep = seed: mkCADerivation { - name = "dep"; - inherit seed; - buildCommand = '' - echo ${currentTime} > $out - ''; - }; - dep1 = dep 1; - dep2 = dep 2; - toplevel = mkCADerivation { - name = "toplevel"; - buildCommand = '' - test ${dep1} == ${dep2} - touch $out - ''; - }; -} - diff --git a/tests/ca/post-hook.sh b/tests/ca/post-hook.sh deleted file mode 100755 index 705bde9d4..000000000 --- a/tests/ca/post-hook.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -source common.sh - -requireDaemonNewerThan "2.4pre20210626" - -export NIX_TESTS_CA_BY_DEFAULT=1 -cd .. -source ./post-hook.sh - - diff --git a/tests/ca/racy.nix b/tests/ca/racy.nix deleted file mode 100644 index 555a15484..000000000 --- a/tests/ca/racy.nix +++ /dev/null @@ -1,15 +0,0 @@ -# A derivation that would certainly fail if several builders tried to -# build it at once. - - -with import ./config.nix; - -mkDerivation { - name = "simple"; - buildCommand = '' - mkdir $out - echo bar >> $out/foo - sleep 3 - [[ "$(cat $out/foo)" == bar ]] - ''; -} diff --git a/tests/ca/recursive.sh b/tests/ca/recursive.sh deleted file mode 100755 index cd6736b24..000000000 --- a/tests/ca/recursive.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -source common.sh - -requireDaemonNewerThan "2.4pre20210623" - -export NIX_TESTS_CA_BY_DEFAULT=1 -cd .. -source ./recursive.sh diff --git a/tests/ca/repl.sh b/tests/ca/repl.sh deleted file mode 100644 index 3808c7cb2..000000000 --- a/tests/ca/repl.sh +++ /dev/null @@ -1,5 +0,0 @@ -source common.sh - -export NIX_TESTS_CA_BY_DEFAULT=1 - -cd .. && source repl.sh diff --git a/tests/ca/selfref-gc.sh b/tests/ca/selfref-gc.sh deleted file mode 100755 index 248778894..000000000 --- a/tests/ca/selfref-gc.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -source common.sh - -requireDaemonNewerThan "2.4pre20210626" - -enableFeatures "ca-derivations nix-command flakes" - -export NIX_TESTS_CA_BY_DEFAULT=1 -cd .. -source ./selfref-gc.sh diff --git a/tests/ca/signatures.sh b/tests/ca/signatures.sh deleted file mode 100644 index eb18a4130..000000000 --- a/tests/ca/signatures.sh +++ /dev/null @@ -1,36 +0,0 @@ -source common.sh - -clearStore -clearCache - -nix-store --generate-binary-cache-key cache1.example.org $TEST_ROOT/sk1 $TEST_ROOT/pk1 -pk1=$(cat $TEST_ROOT/pk1) - -export REMOTE_STORE_DIR="$TEST_ROOT/remote_store" -export REMOTE_STORE="file://$REMOTE_STORE_DIR" - -ensureCorrectlyCopied () { - attrPath="$1" - nix build --store "$REMOTE_STORE" --file ./content-addressed.nix "$attrPath" -} - -testOneCopy () { - clearStore - rm -rf "$REMOTE_STORE_DIR" - - attrPath="$1" - nix copy -vvvv --to $REMOTE_STORE "$attrPath" --file ./content-addressed.nix \ - --secret-key-files "$TEST_ROOT/sk1" --show-trace - - ensureCorrectlyCopied "$attrPath" - - # Ensure that we can copy back what we put in the store - clearStore - nix copy --from $REMOTE_STORE \ - --file ./content-addressed.nix "$attrPath" \ - --trusted-public-keys $pk1 -} - -for attrPath in rootCA dependentCA transitivelyDependentCA dependentNonCA dependentFixedOutput; do - testOneCopy "$attrPath" -done diff --git a/tests/ca/substitute.sh b/tests/ca/substitute.sh deleted file mode 100644 index ea981adc4..000000000 --- a/tests/ca/substitute.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env bash - -# Ensure that binary substitution works properly with ca derivations - -source common.sh - -needLocalStore "“--no-require-sigs” can’t be used with the daemon" - -rm -rf $TEST_ROOT/binary_cache - -export REMOTE_STORE_DIR=$TEST_ROOT/binary_cache -export REMOTE_STORE=file://$REMOTE_STORE_DIR - -buildDrvs () { - nix build --file ./content-addressed.nix -L --no-link "$@" -} - -# Populate the remote cache -clearStore -nix copy --to $REMOTE_STORE --file ./content-addressed.nix - -# Restart the build on an empty store, ensuring that we don't build -clearStore -buildDrvs --substitute --substituters $REMOTE_STORE --no-require-sigs -j0 transitivelyDependentCA -# Check that the thing we’ve just substituted has its realisation stored -nix realisation info --file ./content-addressed.nix transitivelyDependentCA -# Check that its dependencies have it too -nix realisation info --file ./content-addressed.nix dependentCA -# nix realisation info --file ./content-addressed.nix rootCA --outputs out - -if isDaemonNewer "2.13"; then - pushToStore="../push-to-store.sh" -else - pushToStore="../push-to-store-old.sh" -fi - -# Same thing, but -# 1. With non-ca derivations -# 2. Erasing the realisations on the remote store -# -# Even in that case, realising the derivations should still produce the right -# realisations on the local store -# -# Regression test for #4725 -clearStore -nix build --file ../simple.nix -L --no-link --post-build-hook "$pushToStore" -clearStore -rm -r "$REMOTE_STORE_DIR/realisations" -nix build --file ../simple.nix -L --no-link --substitute --substituters "$REMOTE_STORE" --no-require-sigs -j0 -# There's no easy way to check whether a realisation is present on the local -# store − short of manually querying the db, but the build environment doesn't -# have the sqlite binary − so we instead push things again, and check that the -# realisations have correctly been pushed to the remote store -nix copy --to "$REMOTE_STORE" --file ../simple.nix -if [[ -z "$(ls "$REMOTE_STORE_DIR/realisations")" ]]; then - echo "Realisations not rebuilt" - exit 1 -fi - -# Test the local realisation disk cache -buildDrvs --post-build-hook "$pushToStore" -clearStore -# Add the realisations of rootCA to the cachecache -clearCacheCache -export _NIX_FORCE_HTTP=1 -buildDrvs --substitute --substituters $REMOTE_STORE --no-require-sigs -j0 -# Try rebuilding, but remove the realisations from the remote cache to force -# using the cachecache -clearStore -rm $REMOTE_STORE_DIR/realisations/* -buildDrvs --substitute --substituters $REMOTE_STORE --no-require-sigs -j0 diff --git a/tests/ca/why-depends.sh b/tests/ca/why-depends.sh deleted file mode 100644 index 0c079f63b..000000000 --- a/tests/ca/why-depends.sh +++ /dev/null @@ -1,5 +0,0 @@ -source common.sh - -export NIX_TESTS_CA_BY_DEFAULT=1 - -cd .. && source why-depends.sh diff --git a/tests/case-hack.sh b/tests/case-hack.sh deleted file mode 100644 index 61bf9b94b..000000000 --- a/tests/case-hack.sh +++ /dev/null @@ -1,19 +0,0 @@ -source common.sh - -clearStore - -rm -rf $TEST_ROOT/case - -opts="--option use-case-hack true" - -# Check whether restoring and dumping a NAR that contains case -# collisions is round-tripping, even on a case-insensitive system. -nix-store $opts --restore $TEST_ROOT/case < case.nar -nix-store $opts --dump $TEST_ROOT/case > $TEST_ROOT/case.nar -cmp case.nar $TEST_ROOT/case.nar -[ "$(nix-hash $opts --type sha256 $TEST_ROOT/case)" = "$(nix-hash --flat --type sha256 case.nar)" ] - -# Check whether we detect true collisions (e.g. those remaining after -# removal of the suffix). -touch "$TEST_ROOT/case/xt_CONNMARK.h~nix~case~hack~3" -(! nix-store $opts --dump $TEST_ROOT/case > /dev/null) diff --git a/tests/case.nar b/tests/case.nar deleted file mode 100644 index 22ff26db5..000000000 Binary files a/tests/case.nar and /dev/null differ diff --git a/tests/check-refs.nix b/tests/check-refs.nix deleted file mode 100644 index 89690e456..000000000 --- a/tests/check-refs.nix +++ /dev/null @@ -1,77 +0,0 @@ -with import ./config.nix; - -rec { - - dep = import ./dependencies.nix {}; - - makeTest = nr: args: mkDerivation ({ - name = "check-refs-" + toString nr; - } // args); - - src = builtins.toFile "aux-ref" "bla bla"; - - test1 = makeTest 1 { - builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $dep $out/link"; - inherit dep; - }; - - test2 = makeTest 2 { - builder = builtins.toFile "builder.sh" "mkdir $out; ln -s ${src} $out/link"; - inherit dep; - }; - - test3 = makeTest 3 { - builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $dep $out/link"; - allowedReferences = []; - inherit dep; - }; - - test4 = makeTest 4 { - builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $dep $out/link"; - allowedReferences = [dep]; - inherit dep; - }; - - test5 = makeTest 5 { - builder = builtins.toFile "builder.sh" "mkdir $out"; - allowedReferences = []; - inherit dep; - }; - - test6 = makeTest 6 { - builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $out $out/link"; - allowedReferences = []; - inherit dep; - }; - - test7 = makeTest 7 { - builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $out $out/link"; - allowedReferences = ["out"]; - inherit dep; - }; - - test8 = makeTest 8 { - builder = builtins.toFile "builder.sh" "mkdir $out; ln -s ${test1} $out/link"; - inherit dep; - }; - - test9 = makeTest 9 { - builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $dep $out/link"; - inherit dep; - disallowedReferences = [dep]; - }; - - test10 = makeTest 10 { - builder = builtins.toFile "builder.sh" "mkdir $out; echo $test5; ln -s $dep $out/link"; - inherit dep test5; - disallowedReferences = [test5]; - }; - - test11 = makeTest 11 { - __structuredAttrs = true; - unsafeDiscardReferences.out = true; - outputChecks.out.allowedReferences = []; - buildCommand = ''echo ${dep} > "''${outputs[out]}"''; - }; - -} diff --git a/tests/check-refs.sh b/tests/check-refs.sh deleted file mode 100644 index 3b587d1e5..000000000 --- a/tests/check-refs.sh +++ /dev/null @@ -1,53 +0,0 @@ -source common.sh - -clearStore - -RESULT=$TEST_ROOT/result - -dep=$(nix-build -o $RESULT check-refs.nix -A dep) - -# test1 references dep, not itself. -test1=$(nix-build -o $RESULT check-refs.nix -A test1) -nix-store -q --references $test1 | grepQuietInverse $test1 -nix-store -q --references $test1 | grepQuiet $dep - -# test2 references src, not itself nor dep. -test2=$(nix-build -o $RESULT check-refs.nix -A test2) -nix-store -q --references $test2 | grepQuietInverse $test2 -nix-store -q --references $test2 | grepQuietInverse $dep -nix-store -q --references $test2 | grepQuiet aux-ref - -# test3 should fail (unallowed ref). -(! nix-build -o $RESULT check-refs.nix -A test3) - -# test4 should succeed. -nix-build -o $RESULT check-refs.nix -A test4 - -# test5 should succeed. -nix-build -o $RESULT check-refs.nix -A test5 - -# test6 should fail (unallowed self-ref). -(! nix-build -o $RESULT check-refs.nix -A test6) - -# test7 should succeed (allowed self-ref). -nix-build -o $RESULT check-refs.nix -A test7 - -# test8 should fail (toFile depending on derivation output). -(! nix-build -o $RESULT check-refs.nix -A test8) - -# test9 should fail (disallowed reference). -(! nix-build -o $RESULT check-refs.nix -A test9) - -# test10 should succeed (no disallowed references). -nix-build -o $RESULT check-refs.nix -A test10 - -if isDaemonNewer 2.12pre20230103; then - if ! isDaemonNewer 2.16.0; then - enableFeatures discard-references - restartDaemon - fi - - # test11 should succeed. - test11=$(nix-build -o $RESULT check-refs.nix -A test11) - [[ -z $(nix-store -q --references "$test11") ]] -fi diff --git a/tests/check-reqs.nix b/tests/check-reqs.nix deleted file mode 100644 index 41436cb48..000000000 --- a/tests/check-reqs.nix +++ /dev/null @@ -1,57 +0,0 @@ -with import ./config.nix; - -rec { - dep1 = mkDerivation { - name = "check-reqs-dep1"; - builder = builtins.toFile "builder.sh" "mkdir $out; touch $out/file1"; - }; - - dep2 = mkDerivation { - name = "check-reqs-dep2"; - builder = builtins.toFile "builder.sh" "mkdir $out; touch $out/file2"; - }; - - deps = mkDerivation { - name = "check-reqs-deps"; - dep1 = dep1; - dep2 = dep2; - builder = builtins.toFile "builder.sh" '' - mkdir $out - ln -s $dep1/file1 $out/file1 - ln -s $dep2/file2 $out/file2 - ''; - }; - - makeTest = nr: allowreqs: mkDerivation { - name = "check-reqs-" + toString nr; - inherit deps; - builder = builtins.toFile "builder.sh" '' - mkdir $out - ln -s $deps $out/depdir1 - ''; - allowedRequisites = allowreqs; - }; - - # When specifying all the requisites, the build succeeds. - test1 = makeTest 1 [ dep1 dep2 deps ]; - - # But missing anything it fails. - test2 = makeTest 2 [ dep2 deps ]; - test3 = makeTest 3 [ dep1 deps ]; - test4 = makeTest 4 [ deps ]; - test5 = makeTest 5 []; - - test6 = mkDerivation { - name = "check-reqs"; - inherit deps; - builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $deps $out/depdir1"; - disallowedRequisites = [dep1]; - }; - - test7 = mkDerivation { - name = "check-reqs"; - inherit deps; - builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $deps $out/depdir1"; - disallowedRequisites = [test1]; - }; -} diff --git a/tests/check-reqs.sh b/tests/check-reqs.sh deleted file mode 100644 index 856c94cec..000000000 --- a/tests/check-reqs.sh +++ /dev/null @@ -1,16 +0,0 @@ -source common.sh - -clearStore - -RESULT=$TEST_ROOT/result - -nix-build -o $RESULT check-reqs.nix -A test1 - -(! nix-build -o $RESULT check-reqs.nix -A test2) -(! nix-build -o $RESULT check-reqs.nix -A test3) -(! nix-build -o $RESULT check-reqs.nix -A test4) 2>&1 | grepQuiet 'check-reqs-dep1' -(! nix-build -o $RESULT check-reqs.nix -A test4) 2>&1 | grepQuiet 'check-reqs-dep2' -(! nix-build -o $RESULT check-reqs.nix -A test5) -(! nix-build -o $RESULT check-reqs.nix -A test6) - -nix-build -o $RESULT check-reqs.nix -A test7 diff --git a/tests/check.nix b/tests/check.nix deleted file mode 100644 index ddab8eea9..000000000 --- a/tests/check.nix +++ /dev/null @@ -1,55 +0,0 @@ -{checkBuildId ? 0}: - -with import ./config.nix; - -{ - nondeterministic = mkDerivation { - inherit checkBuildId; - name = "nondeterministic"; - buildCommand = - '' - mkdir $out - date +%s.%N > $out/date - echo "CHECK_TMPDIR=$TMPDIR" - echo "checkBuildId=$checkBuildId" - echo "$checkBuildId" > $TMPDIR/checkBuildId - ''; - }; - - deterministic = mkDerivation { - inherit checkBuildId; - name = "deterministic"; - buildCommand = - '' - mkdir $out - echo date > $out/date - echo "CHECK_TMPDIR=$TMPDIR" - echo "checkBuildId=$checkBuildId" - echo "$checkBuildId" > $TMPDIR/checkBuildId - ''; - }; - - failed = mkDerivation { - inherit checkBuildId; - name = "failed"; - buildCommand = - '' - mkdir $out - echo date > $out/date - echo "CHECK_TMPDIR=$TMPDIR" - echo "checkBuildId=$checkBuildId" - echo "$checkBuildId" > $TMPDIR/checkBuildId - false - ''; - }; - - hashmismatch = import { - url = "file://" + builtins.getEnv "TEST_ROOT" + "/dummy"; - sha256 = "0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73"; - }; - - fetchurl = import { - url = "file://" + toString ./lang/eval-okay-xml.exp.xml; - sha256 = "sha256-behBlX+DQK/Pjvkuc8Tx68Jwi4E5v86wDq+ZLaHyhQE="; - }; -} diff --git a/tests/check.sh b/tests/check.sh deleted file mode 100644 index e13abf747..000000000 --- a/tests/check.sh +++ /dev/null @@ -1,91 +0,0 @@ -source common.sh - -# XXX: This shouldn’t be, but #4813 cause this test to fail -buggyNeedLocalStore "see #4813" - -checkBuildTempDirRemoved () -{ - buildDir=$(sed -n 's/CHECK_TMPDIR=//p' $1 | head -1) - checkBuildIdFile=${buildDir}/checkBuildId - [[ ! -f $checkBuildIdFile ]] || ! grep $checkBuildId $checkBuildIdFile -} - -# written to build temp directories to verify created by this instance -checkBuildId=$(date +%s%N) - -clearStore - -nix-build dependencies.nix --no-out-link -nix-build dependencies.nix --no-out-link --check - -# Build failure exit codes (100, 104, etc.) are from -# doc/manual/src/command-ref/status-build-failure.md - -# check for dangling temporary build directories -# only retain if build fails and --keep-failed is specified, or... -# ...build is non-deterministic and --check and --keep-failed are both specified -nix-build check.nix -A failed --argstr checkBuildId $checkBuildId \ - --no-out-link 2> $TEST_ROOT/log || status=$? -[ "$status" = "100" ] -checkBuildTempDirRemoved $TEST_ROOT/log - -nix-build check.nix -A failed --argstr checkBuildId $checkBuildId \ - --no-out-link --keep-failed 2> $TEST_ROOT/log || status=$? -[ "$status" = "100" ] -if checkBuildTempDirRemoved $TEST_ROOT/log; then false; fi - -nix-build check.nix -A deterministic --argstr checkBuildId $checkBuildId \ - --no-out-link 2> $TEST_ROOT/log -checkBuildTempDirRemoved $TEST_ROOT/log - -nix-build check.nix -A deterministic --argstr checkBuildId $checkBuildId \ - --no-out-link --check --keep-failed 2> $TEST_ROOT/log -if grepQuiet 'may not be deterministic' $TEST_ROOT/log; then false; fi -checkBuildTempDirRemoved $TEST_ROOT/log - -nix-build check.nix -A nondeterministic --argstr checkBuildId $checkBuildId \ - --no-out-link 2> $TEST_ROOT/log -checkBuildTempDirRemoved $TEST_ROOT/log - -nix-build check.nix -A nondeterministic --argstr checkBuildId $checkBuildId \ - --no-out-link --check 2> $TEST_ROOT/log || status=$? -grep 'may not be deterministic' $TEST_ROOT/log -[ "$status" = "104" ] -checkBuildTempDirRemoved $TEST_ROOT/log - -nix-build check.nix -A nondeterministic --argstr checkBuildId $checkBuildId \ - --no-out-link --check --keep-failed 2> $TEST_ROOT/log || status=$? -grep 'may not be deterministic' $TEST_ROOT/log -[ "$status" = "104" ] -if checkBuildTempDirRemoved $TEST_ROOT/log; then false; fi - -clearStore - -path=$(nix-build check.nix -A fetchurl --no-out-link) - -chmod +w $path -echo foo > $path -chmod -w $path - -nix-build check.nix -A fetchurl --no-out-link --check -# Note: "check" doesn't repair anything, it just compares to the hash stored in the database. -[[ $(cat $path) = foo ]] - -nix-build check.nix -A fetchurl --no-out-link --repair -[[ $(cat $path) != foo ]] - -echo 'Hello World' > $TEST_ROOT/dummy -nix-build check.nix -A hashmismatch --no-out-link || status=$? -[ "$status" = "102" ] - -echo -n > $TEST_ROOT/dummy -nix-build check.nix -A hashmismatch --no-out-link -echo 'Hello World' > $TEST_ROOT/dummy - -nix-build check.nix -A hashmismatch --no-out-link --check || status=$? -[ "$status" = "102" ] - -# Multiple failures with --keep-going -nix-build check.nix -A nondeterministic --no-out-link -nix-build check.nix -A nondeterministic -A hashmismatch --no-out-link --check --keep-going || status=$? -[ "$status" = "110" ] diff --git a/tests/common.sh b/tests/common.sh deleted file mode 100644 index 7b0922c9f..000000000 --- a/tests/common.sh +++ /dev/null @@ -1,12 +0,0 @@ -set -eu -o pipefail - -if [[ -z "${COMMON_SH_SOURCED-}" ]]; then - -COMMON_SH_SOURCED=1 - -source "$(readlink -f "$(dirname "${BASH_SOURCE[0]-$0}")")/common/vars-and-functions.sh" -if [[ -n "${NIX_DAEMON_PACKAGE:-}" ]]; then - startDaemon -fi - -fi # COMMON_SH_SOURCED diff --git a/tests/common/vars-and-functions.sh.in b/tests/common/vars-and-functions.sh.in deleted file mode 100644 index 8f9ec4b1a..000000000 --- a/tests/common/vars-and-functions.sh.in +++ /dev/null @@ -1,276 +0,0 @@ -set -eu -o pipefail - -if [[ -z "${COMMON_VARS_AND_FUNCTIONS_SH_SOURCED-}" ]]; then - -COMMON_VARS_AND_FUNCTIONS_SH_SOURCED=1 - -export PS4='+(${BASH_SOURCE[0]-$0}:$LINENO) ' - -export TEST_ROOT=$(realpath ${TMPDIR:-/tmp}/nix-test)/${TEST_NAME:-default} -export NIX_STORE_DIR -if ! NIX_STORE_DIR=$(readlink -f $TEST_ROOT/store 2> /dev/null); then - # Maybe the build directory is symlinked. - export NIX_IGNORE_SYMLINK_STORE=1 - NIX_STORE_DIR=$TEST_ROOT/store -fi -export NIX_LOCALSTATE_DIR=$TEST_ROOT/var -export NIX_LOG_DIR=$TEST_ROOT/var/log/nix -export NIX_STATE_DIR=$TEST_ROOT/var/nix -export NIX_CONF_DIR=$TEST_ROOT/etc -export NIX_DAEMON_SOCKET_PATH=$TEST_ROOT/dSocket -unset NIX_USER_CONF_FILES -export _NIX_TEST_SHARED=$TEST_ROOT/shared -if [[ -n $NIX_STORE ]]; then - export _NIX_TEST_NO_SANDBOX=1 -fi -export _NIX_IN_TEST=$TEST_ROOT/shared -export _NIX_TEST_NO_LSOF=1 -export NIX_REMOTE=${NIX_REMOTE_-} -unset NIX_PATH -export TEST_HOME=$TEST_ROOT/test-home -export HOME=$TEST_HOME -unset XDG_STATE_HOME -unset XDG_DATA_HOME -unset XDG_CONFIG_HOME -unset XDG_CONFIG_DIRS -unset XDG_CACHE_HOME -mkdir -p $TEST_HOME - -export PATH=@bindir@:$PATH -if [[ -n "${NIX_CLIENT_PACKAGE:-}" ]]; then - export PATH="$NIX_CLIENT_PACKAGE/bin":$PATH -fi -DAEMON_PATH="$PATH" -if [[ -n "${NIX_DAEMON_PACKAGE:-}" ]]; then - DAEMON_PATH="${NIX_DAEMON_PACKAGE}/bin:$DAEMON_PATH" -fi -coreutils=@coreutils@ - -export dot=@dot@ -export SHELL="@bash@" -export PAGER=cat -export busybox="@sandbox_shell@" - -export version=@PACKAGE_VERSION@ -export system=@system@ - -export BUILD_SHARED_LIBS=@BUILD_SHARED_LIBS@ - -export IMPURE_VAR1=foo -export IMPURE_VAR2=bar - -cacheDir=$TEST_ROOT/binary-cache - -readLink() { - ls -l "$1" | sed 's/.*->\ //' -} - -clearProfiles() { - profiles="$HOME"/.local/state/nix/profiles - rm -rf "$profiles" -} - -clearStore() { - echo "clearing store..." - chmod -R +w "$NIX_STORE_DIR" - rm -rf "$NIX_STORE_DIR" - mkdir "$NIX_STORE_DIR" - rm -rf "$NIX_STATE_DIR" - mkdir "$NIX_STATE_DIR" - clearProfiles -} - -clearCache() { - rm -rf "$cacheDir" -} - -clearCacheCache() { - rm -f $TEST_HOME/.cache/nix/binary-cache* -} - -startDaemon() { - # Don’t start the daemon twice, as this would just make it loop indefinitely - if [[ "${_NIX_TEST_DAEMON_PID-}" != '' ]]; then - return - fi - # Start the daemon, wait for the socket to appear. - rm -f $NIX_DAEMON_SOCKET_PATH - PATH=$DAEMON_PATH nix-daemon & - _NIX_TEST_DAEMON_PID=$! - export _NIX_TEST_DAEMON_PID - for ((i = 0; i < 300; i++)); do - if [[ -S $NIX_DAEMON_SOCKET_PATH ]]; then - DAEMON_STARTED=1 - break; - fi - sleep 0.1 - done - if [[ -z ${DAEMON_STARTED+x} ]]; then - fail "Didn’t manage to start the daemon" - fi - trap "killDaemon" EXIT - # Save for if daemon is killed - NIX_REMOTE_OLD=$NIX_REMOTE - export NIX_REMOTE=daemon -} - -killDaemon() { - # Don’t fail trying to stop a non-existant daemon twice - if [[ "${_NIX_TEST_DAEMON_PID-}" == '' ]]; then - return - fi - kill $_NIX_TEST_DAEMON_PID - for i in {0..100}; do - kill -0 $_NIX_TEST_DAEMON_PID 2> /dev/null || break - sleep 0.1 - done - kill -9 $_NIX_TEST_DAEMON_PID 2> /dev/null || true - wait $_NIX_TEST_DAEMON_PID || true - rm -f $NIX_DAEMON_SOCKET_PATH - # Indicate daemon is stopped - unset _NIX_TEST_DAEMON_PID - # Restore old nix remote - NIX_REMOTE=$NIX_REMOTE_OLD - trap "" EXIT -} - -restartDaemon() { - [[ -z "${_NIX_TEST_DAEMON_PID:-}" ]] && return 0 - - killDaemon - startDaemon -} - -if [[ $(uname) == Linux ]] && [[ -L /proc/self/ns/user ]] && unshare --user true; then - _canUseSandbox=1 -fi - -isDaemonNewer () { - [[ -n "${NIX_DAEMON_PACKAGE:-}" ]] || return 0 - local requiredVersion="$1" - local daemonVersion=$($NIX_DAEMON_PACKAGE/bin/nix-daemon --version | cut -d' ' -f3) - [[ $(nix eval --expr "builtins.compareVersions ''$daemonVersion'' ''$requiredVersion''") -ge 0 ]] -} - -skipTest () { - echo "$1, skipping this test..." >&2 - exit 99 -} - -requireDaemonNewerThan () { - isDaemonNewer "$1" || skipTest "Daemon is too old" -} - -canUseSandbox() { - [[ ${_canUseSandbox-} ]] -} - -requireSandboxSupport () { - canUseSandbox || skipTest "Sandboxing not supported" -} - -requireGit() { - [[ $(type -p git) ]] || skipTest "Git not installed" -} - -fail() { - echo "$1" >&2 - exit 1 -} - -# Run a command failing if it didn't exit with the expected exit code. -# -# Has two advantages over the built-in `!`: -# -# 1. `!` conflates all non-0 codes. `expect` allows testing for an exact -# code. -# -# 2. `!` unexpectedly negates `set -e`, and cannot be used on individual -# pipeline stages with `set -o pipefail`. It only works on the entire -# pipeline, which is useless if we want, say, `nix ...` invocation to -# *fail*, but a grep on the error message it outputs to *succeed*. -expect() { - local expected res - expected="$1" - shift - "$@" && res=0 || res="$?" - if [[ $res -ne $expected ]]; then - echo "Expected exit code '$expected' but got '$res' from command ${*@Q}" >&2 - return 1 - fi - return 0 -} - -# Better than just doing `expect ... >&2` because the "Expected..." -# message below will *not* be redirected. -expectStderr() { - local expected res - expected="$1" - shift - "$@" 2>&1 && res=0 || res="$?" - if [[ $res -ne $expected ]]; then - echo "Expected exit code '$expected' but got '$res' from command ${*@Q}" >&2 - return 1 - fi - return 0 -} - -needLocalStore() { - if [[ "$NIX_REMOTE" == "daemon" ]]; then - skipTest "Can’t run through the daemon ($1)" - fi -} - -# Just to make it easy to find which tests should be fixed -buggyNeedLocalStore() { - needLocalStore "$1" -} - -enableFeatures() { - local features="$1" - sed -i 's/experimental-features .*/& '"$features"'/' "$NIX_CONF_DIR"/nix.conf -} - -set -x - -onError() { - set +x - echo "$0: test failed at:" >&2 - for ((i = 1; i < ${#BASH_SOURCE[@]}; i++)); do - if [[ -z ${BASH_SOURCE[i]} ]]; then break; fi - echo " ${FUNCNAME[i]} in ${BASH_SOURCE[i]}:${BASH_LINENO[i-1]}" >&2 - done -} - -# `grep -v` doesn't work well for exit codes. We want `!(exist line l. l -# matches)`. It gives us `exist line l. !(l matches)`. -# -# `!` normally doesn't work well with `set -e`, but when we wrap in a -# function it *does*. -grepInverse() { - ! grep "$@" -} - -# A shorthand, `> /dev/null` is a bit noisy. -# -# `grep -q` would seem to do this, no function necessary, but it is a -# bad fit with pipes and `set -o pipefail`: `-q` will exit after the -# first match, and then subsequent writes will result in broken pipes. -# -# Note that reproducing the above is a bit tricky as it depends on -# non-deterministic properties such as the timing between the match and -# the closing of the pipe, the buffering of the pipe, and the speed of -# the producer into the pipe. But rest assured we've seen it happen in -# CI reliably. -grepQuiet() { - grep "$@" > /dev/null -} - -# The previous two, combined -grepQuietInverse() { - ! grep "$@" > /dev/null -} - -trap onError ERR - -fi # COMMON_VARS_AND_FUNCTIONS_SH_SOURCED diff --git a/tests/completions.sh b/tests/completions.sh deleted file mode 100644 index 19dc61098..000000000 --- a/tests/completions.sh +++ /dev/null @@ -1,68 +0,0 @@ -source common.sh - -cd "$TEST_ROOT" - -mkdir -p dep -cat < dep/flake.nix -{ - outputs = i: { }; -} -EOF -mkdir -p foo -cat < foo/flake.nix -{ - inputs.a.url = "path:$(realpath dep)"; - - outputs = i: { - sampleOutput = 1; - }; -} -EOF -mkdir -p bar -cat < bar/flake.nix -{ - inputs.b.url = "path:$(realpath dep)"; - - outputs = i: { - sampleOutput = 1; - }; -} -EOF -mkdir -p err -cat < err/flake.nix -throw "error" -EOF - -# Test the completion of a subcommand -[[ "$(NIX_GET_COMPLETIONS=1 nix buil)" == $'normal\nbuild\t' ]] -[[ "$(NIX_GET_COMPLETIONS=2 nix flake metad)" == $'normal\nmetadata\t' ]] - -# Filename completion -[[ "$(NIX_GET_COMPLETIONS=2 nix build ./f)" == $'filenames\n./foo\t' ]] -[[ "$(NIX_GET_COMPLETIONS=2 nix build ./nonexistent)" == $'filenames' ]] - -# Input override completion -[[ "$(NIX_GET_COMPLETIONS=4 nix build ./foo --override-input '')" == $'normal\na\t' ]] -[[ "$(NIX_GET_COMPLETIONS=5 nix flake show ./foo --override-input '')" == $'normal\na\t' ]] -## With multiple input flakes -[[ "$(NIX_GET_COMPLETIONS=5 nix build ./foo ./bar --override-input '')" == $'normal\na\t\nb\t' ]] -## With tilde expansion -[[ "$(HOME=$PWD NIX_GET_COMPLETIONS=4 nix build '~/foo' --override-input '')" == $'normal\na\t' ]] -## Out of order -[[ "$(NIX_GET_COMPLETIONS=3 nix build --update-input '' ./foo)" == $'normal\na\t' ]] -[[ "$(NIX_GET_COMPLETIONS=4 nix build ./foo --update-input '' ./bar)" == $'normal\na\t\nb\t' ]] - -# Cli flag completion -NIX_GET_COMPLETIONS=2 nix build --log-form | grep -- "--log-format" - -# Config option completion -## With `--option` -NIX_GET_COMPLETIONS=3 nix build --option allow-import-from | grep -- "allow-import-from-derivation" -## As a cli flag – not working atm -# NIX_GET_COMPLETIONS=2 nix build --allow-import-from | grep -- "allow-import-from-derivation" - -# Attr path completions -[[ "$(NIX_GET_COMPLETIONS=2 nix eval ./foo\#sam)" == $'attrs\n./foo#sampleOutput\t' ]] -[[ "$(NIX_GET_COMPLETIONS=4 nix eval --file ./foo/flake.nix outp)" == $'attrs\noutputs\t' ]] -[[ "$(NIX_GET_COMPLETIONS=4 nix eval --file ./err/flake.nix outp 2>&1)" == $'attrs' ]] -[[ "$(NIX_GET_COMPLETIONS=2 nix eval ./err\# 2>&1)" == $'attrs' ]] diff --git a/tests/compression-levels.sh b/tests/compression-levels.sh deleted file mode 100644 index 85f12974a..000000000 --- a/tests/compression-levels.sh +++ /dev/null @@ -1,22 +0,0 @@ -source common.sh - -clearStore -clearCache - -outPath=$(nix-build dependencies.nix --no-out-link) - -cacheURI="file://$cacheDir?compression=xz&compression-level=0" - -nix copy --to $cacheURI $outPath - -FILESIZES=$(cat ${cacheDir}/*.narinfo | awk '/FileSize: /{sum+=$2}END{print sum}') - -clearCache - -cacheURI="file://$cacheDir?compression=xz&compression-level=5" - -nix copy --to $cacheURI $outPath - -FILESIZES2=$(cat ${cacheDir}/*.narinfo | awk '/FileSize: /{sum+=$2}END{print sum}') - -[[ $FILESIZES -gt $FILESIZES2 ]] diff --git a/tests/compute-levels.sh b/tests/compute-levels.sh deleted file mode 100644 index de3da2ebd..000000000 --- a/tests/compute-levels.sh +++ /dev/null @@ -1,7 +0,0 @@ -source common.sh - -if [[ $(uname -ms) = "Linux x86_64" ]]; then - # x86_64 CPUs must always support the baseline - # microarchitecture level. - nix -vv --version | grepQuiet "x86_64-v1-linux" -fi diff --git a/tests/config.nix.in b/tests/config.nix.in deleted file mode 100644 index 7facbdcbc..000000000 --- a/tests/config.nix.in +++ /dev/null @@ -1,27 +0,0 @@ -let - contentAddressedByDefault = builtins.getEnv "NIX_TESTS_CA_BY_DEFAULT" == "1"; - caArgs = if contentAddressedByDefault then { - __contentAddressed = true; - outputHashMode = "recursive"; - outputHashAlgo = "sha256"; - } else {}; -in - -rec { - shell = "@bash@"; - - path = "@coreutils@"; - - system = "@system@"; - - shared = builtins.getEnv "_NIX_TEST_SHARED"; - - mkDerivation = args: - derivation ({ - inherit system; - builder = shell; - args = ["-e" args.builder or (builtins.toFile "builder-${args.name}.sh" "if [ -e .attrs.sh ]; then source .attrs.sh; fi; eval \"$buildCommand\"")]; - PATH = path; - } // caArgs // removeAttrs args ["builder" "meta"]) - // { meta = args.meta or {}; }; -} diff --git a/tests/config.sh b/tests/config.sh deleted file mode 100644 index 723f575ed..000000000 --- a/tests/config.sh +++ /dev/null @@ -1,58 +0,0 @@ -source common.sh - -# Isolate the home for this test. -# Other tests (e.g. flake registry tests) could be writing to $HOME in parallel. -export HOME=$TEST_ROOT/userhome - -# Test that using XDG_CONFIG_HOME works -# Assert the config folder didn't exist initially. -[ ! -e "$HOME/.config" ] -# Without XDG_CONFIG_HOME, creates $HOME/.config -unset XDG_CONFIG_HOME -# Run against the nix registry to create the config dir -# (Tip: this relies on removing non-existent entries being a no-op!) -nix registry remove userhome-without-xdg -# Verifies it created it -[ -e "$HOME/.config" ] -# Remove the directory it created -rm -rf "$HOME/.config" -# Run the same test, but with XDG_CONFIG_HOME -export XDG_CONFIG_HOME=$TEST_ROOT/confighome -# Assert the XDG_CONFIG_HOME/nix path does not exist yet. -[ ! -e "$TEST_ROOT/confighome/nix" ] -nix registry remove userhome-with-xdg -# Verifies the confighome path has been created -[ -e "$TEST_ROOT/confighome/nix" ] -# Assert the .config folder hasn't been created. -[ ! -e "$HOME/.config" ] - -# Test that files are loaded from XDG by default -export XDG_CONFIG_HOME=$TEST_ROOT/confighome -export XDG_CONFIG_DIRS=$TEST_ROOT/dir1:$TEST_ROOT/dir2 -files=$(nix-build --verbose --version | grep "User config" | cut -d ':' -f2- | xargs) -[[ $files == "$TEST_ROOT/confighome/nix/nix.conf:$TEST_ROOT/dir1/nix/nix.conf:$TEST_ROOT/dir2/nix/nix.conf" ]] - -# Test that setting NIX_USER_CONF_FILES overrides all the default user config files -export NIX_USER_CONF_FILES=$TEST_ROOT/file1.conf:$TEST_ROOT/file2.conf -files=$(nix-build --verbose --version | grep "User config" | cut -d ':' -f2- | xargs) -[[ $files == "$TEST_ROOT/file1.conf:$TEST_ROOT/file2.conf" ]] - -# Test that it's possible to load the config from a custom location -here=$(readlink -f "$(dirname "${BASH_SOURCE[0]}")") -export NIX_USER_CONF_FILES=$here/config/nix-with-substituters.conf -var=$(nix show-config | grep '^substituters =' | cut -d '=' -f 2 | xargs) -[[ $var == https://example.com ]] - -# Test that it's possible to load config from the environment -prev=$(nix show-config | grep '^cores' | cut -d '=' -f 2 | xargs) -export NIX_CONFIG="cores = 4242"$'\n'"experimental-features = nix-command flakes" -exp_cores=$(nix show-config | grep '^cores' | cut -d '=' -f 2 | xargs) -exp_features=$(nix show-config | grep '^experimental-features' | cut -d '=' -f 2 | xargs) -[[ $prev != $exp_cores ]] -[[ $exp_cores == "4242" ]] -[[ $exp_features == "flakes nix-command" ]] - -# Test that it's possible to retrieve a single setting's value -val=$(nix show-config | grep '^warn-dirty' | cut -d '=' -f 2 | xargs) -val2=$(nix show-config warn-dirty) -[[ $val == $val2 ]] diff --git a/tests/config/nix-with-substituters.conf b/tests/config/nix-with-substituters.conf deleted file mode 100644 index 90f359a6f..000000000 --- a/tests/config/nix-with-substituters.conf +++ /dev/null @@ -1,2 +0,0 @@ -experimental-features = nix-command -substituters = https://example.com diff --git a/tests/db-migration.sh b/tests/db-migration.sh deleted file mode 100644 index 44cd16bc0..000000000 --- a/tests/db-migration.sh +++ /dev/null @@ -1,28 +0,0 @@ -# Test that we can successfully migrate from an older db schema - -source common.sh - -# Only run this if we have an older Nix available -# XXX: This assumes that the `daemon` package is older than the `client` one -if [[ -z "${NIX_DAEMON_PACKAGE-}" ]]; then - skipTest "not using the Nix daemon" -fi - -killDaemon - -# Fill the db using the older Nix -PATH_WITH_NEW_NIX="$PATH" -export PATH="${NIX_DAEMON_PACKAGE}/bin:$PATH" -clearStore -nix-build simple.nix --no-out-link -nix-store --generate-binary-cache-key cache1.example.org $TEST_ROOT/sk1 $TEST_ROOT/pk1 -dependenciesOutPath=$(nix-build dependencies.nix --no-out-link --secret-key-files "$TEST_ROOT/sk1") -fixedOutPath=$(IMPURE_VAR1=foo IMPURE_VAR2=bar nix-build fixed.nix -A good.0 --no-out-link) - -# Migrate to the new schema and ensure that everything's there -export PATH="$PATH_WITH_NEW_NIX" -info=$(nix path-info --json $dependenciesOutPath) -[[ $info =~ '"ultimate":true' ]] -[[ $info =~ 'cache1.example.org' ]] -nix verify -r "$fixedOutPath" -nix verify -r "$dependenciesOutPath" --sigs-needed 1 --trusted-public-keys $(cat $TEST_ROOT/pk1) diff --git a/tests/dependencies.builder0.sh b/tests/dependencies.builder0.sh deleted file mode 100644 index 9b11576e0..000000000 --- a/tests/dependencies.builder0.sh +++ /dev/null @@ -1,16 +0,0 @@ -[ "${input1: -2}" = /. ] -[ "${input2: -2}" = /. ] - -mkdir $out -echo $(cat $input1/foo)$(cat $input2/bar) > $out/foobar - -ln -s $input2 $out/reference-to-input-2 - -# Self-reference. -ln -s $out $out/self - -# Executable. -echo program > $out/program -chmod +x $out/program - -echo FOO diff --git a/tests/dependencies.nix b/tests/dependencies.nix deleted file mode 100644 index be1a7ae9a..000000000 --- a/tests/dependencies.nix +++ /dev/null @@ -1,48 +0,0 @@ -{ hashInvalidator ? "" }: -with import ./config.nix; - -let { - - input0 = mkDerivation { - name = "dependencies-input-0"; - buildCommand = "mkdir $out; echo foo > $out/bar"; - }; - - input1 = mkDerivation { - name = "dependencies-input-1"; - buildCommand = "mkdir $out; echo FOO > $out/foo"; - }; - - input2 = mkDerivation { - name = "dependencies-input-2"; - buildCommand = '' - mkdir $out - echo BAR > $out/bar - echo ${input0} > $out/input0 - ''; - }; - - fod_input = mkDerivation { - name = "fod-input"; - buildCommand = '' - echo ${hashInvalidator} - echo FOD > $out - ''; - outputHashMode = "flat"; - outputHashAlgo = "sha256"; - outputHash = "1dq9p0hnm1y75q2x40fws5887bq1r840hzdxak0a9djbwvx0b16d"; - }; - - body = mkDerivation { - name = "dependencies-top"; - builder = ./dependencies.builder0.sh + "/FOOBAR/../."; - input1 = input1 + "/."; - input2 = "${input2}/."; - input1_drv = input1; - input2_drv = input2; - input0_drv = input0; - fod_input_drv = fod_input; - meta.description = "Random test package"; - }; - -} diff --git a/tests/dependencies.sh b/tests/dependencies.sh deleted file mode 100644 index b93dacac0..000000000 --- a/tests/dependencies.sh +++ /dev/null @@ -1,72 +0,0 @@ -source common.sh - -clearStore - -drvPath=$(nix-instantiate dependencies.nix) - -echo "derivation is $drvPath" - -nix-store -q --tree "$drvPath" | grep '───.*builder-dependencies-input-1.sh' - -# Test Graphviz graph generation. -nix-store -q --graph "$drvPath" > $TEST_ROOT/graph -if test -n "$dot"; then - # Does it parse? - $dot < $TEST_ROOT/graph -fi - -# Test GraphML graph generation -nix-store -q --graphml "$drvPath" > $TEST_ROOT/graphml - -outPath=$(nix-store -rvv "$drvPath") || fail "build failed" - -# Test Graphviz graph generation. -nix-store -q --graph "$outPath" > $TEST_ROOT/graph -if test -n "$dot"; then - # Does it parse? - $dot < $TEST_ROOT/graph -fi - -nix-store -q --tree "$outPath" | grep '───.*dependencies-input-2' - -echo "output path is $outPath" - -text=$(cat "$outPath"/foobar) -if test "$text" != "FOOBAR"; then exit 1; fi - -deps=$(nix-store -quR "$drvPath") - -echo "output closure contains $deps" - -# The output path should be in the closure. -echo "$deps" | grepQuiet "$outPath" - -# Input-1 is not retained. -if echo "$deps" | grepQuiet "dependencies-input-1"; then exit 1; fi - -# Input-2 is retained. -input2OutPath=$(echo "$deps" | grep "dependencies-input-2") - -# The referrers closure of input-2 should include outPath. -nix-store -q --referrers-closure "$input2OutPath" | grep "$outPath" - -# Check that the derivers are set properly. -test $(nix-store -q --deriver "$outPath") = "$drvPath" -nix-store -q --deriver "$input2OutPath" | grepQuiet -- "-input-2.drv" - -# --valid-derivers returns the currently single valid .drv file -test "$(nix-store -q --valid-derivers "$outPath")" = "$drvPath" - -# instantiate a different drv with the same output -drvPath2=$(nix-instantiate dependencies.nix --argstr hashInvalidator yay) - -# now --valid-derivers returns both -test "$(nix-store -q --valid-derivers "$outPath" | sort)" = "$(sort <<< "$drvPath"$'\n'"$drvPath2")" - -# check that nix-store --valid-derivers only returns existing drv -nix-store --delete "$drvPath" -test "$(nix-store -q --valid-derivers "$outPath")" = "$drvPath2" - -# check that --valid-derivers returns nothing when there are no valid derivers -nix-store --delete "$drvPath2" -test -z "$(nix-store -q --valid-derivers "$outPath")" diff --git a/tests/derivation-json.sh b/tests/derivation-json.sh deleted file mode 100644 index b6be5d977..000000000 --- a/tests/derivation-json.sh +++ /dev/null @@ -1,12 +0,0 @@ -source common.sh - -drvPath=$(nix-instantiate simple.nix) - -nix derivation show $drvPath | jq .[] > $TEST_HOME/simple.json - -drvPath2=$(nix derivation add < $TEST_HOME/simple.json) - -[[ "$drvPath" = "$drvPath2" ]] - -# Input addressed derivations cannot be renamed. -jq '.name = "foo"' < $TEST_HOME/simple.json | expectStderr 1 nix derivation add | grepQuiet "has incorrect output" diff --git a/tests/dummy b/tests/dummy deleted file mode 100644 index 557db03de..000000000 --- a/tests/dummy +++ /dev/null @@ -1 +0,0 @@ -Hello World diff --git a/tests/dump-db.sh b/tests/dump-db.sh deleted file mode 100644 index 48647f403..000000000 --- a/tests/dump-db.sh +++ /dev/null @@ -1,22 +0,0 @@ -source common.sh - -needLocalStore "--dump-db requires a local store" - -clearStore - -path=$(nix-build dependencies.nix -o $TEST_ROOT/result) - -deps="$(nix-store -qR $TEST_ROOT/result)" - -nix-store --dump-db > $TEST_ROOT/dump - -rm -rf $NIX_STATE_DIR/db - -nix-store --load-db < $TEST_ROOT/dump - -deps2="$(nix-store -qR $TEST_ROOT/result)" - -[ "$deps" = "$deps2" ]; - -nix-store --dump-db > $TEST_ROOT/dump2 -cmp $TEST_ROOT/dump $TEST_ROOT/dump2 diff --git a/tests/dyn-drv/build-built-drv.sh b/tests/dyn-drv/build-built-drv.sh deleted file mode 100644 index 647be9457..000000000 --- a/tests/dyn-drv/build-built-drv.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash - -source common.sh - -# In the corresponding nix file, we have two derivations: the first, named `hello`, -# is a normal recursive derivation, while the second, named dependent, has the -# new outputHashMode "text". Note that in "dependent", we don't refer to the -# build output of `hello`, but only to the path of the drv file. For this reason, -# we only need to: -# -# - instantiate `hello` -# - build `producingDrv` -# - check that the path of the output coincides with that of the original derivation - -out1=$(nix build -f ./text-hashed-output.nix hello --no-link) - -clearStore - -drvDep=$(nix-instantiate ./text-hashed-output.nix -A producingDrv) - -expectStderr 1 nix build "${drvDep}^out^out" --no-link | grepQuiet "Building dynamic derivations in one shot is not yet implemented" diff --git a/tests/dyn-drv/common.sh b/tests/dyn-drv/common.sh deleted file mode 100644 index c786f6925..000000000 --- a/tests/dyn-drv/common.sh +++ /dev/null @@ -1,8 +0,0 @@ -source ../common.sh - -# Need backend to support text-hashing too -requireDaemonNewerThan "2.16.0pre20230419" - -enableFeatures "ca-derivations dynamic-derivations" - -restartDaemon diff --git a/tests/dyn-drv/config.nix.in b/tests/dyn-drv/config.nix.in deleted file mode 120000 index af24ddb30..000000000 --- a/tests/dyn-drv/config.nix.in +++ /dev/null @@ -1 +0,0 @@ -../config.nix.in \ No newline at end of file diff --git a/tests/dyn-drv/dep-built-drv.sh b/tests/dyn-drv/dep-built-drv.sh deleted file mode 100644 index 4f6e9b080..000000000 --- a/tests/dyn-drv/dep-built-drv.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -source common.sh - -out1=$(nix-build ./text-hashed-output.nix -A hello --no-out-link) - -clearStore - -expectStderr 1 nix-build ./text-hashed-output.nix -A wrapper --no-out-link | grepQuiet "Building dynamic derivations in one shot is not yet implemented" - -# diff -r $out1 $out2 diff --git a/tests/dyn-drv/eval-outputOf.sh b/tests/dyn-drv/eval-outputOf.sh deleted file mode 100644 index 9467feb8d..000000000 --- a/tests/dyn-drv/eval-outputOf.sh +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env bash - -source ./common.sh - -# Without the dynamic-derivations XP feature, we don't have the builtin. -nix --experimental-features 'nix-command' eval --impure --expr \ - 'assert ! (builtins ? outputOf); ""' - -# Test that a string is required. -# -# We currently require a string to be passed, rather than a derivation -# object that could be coerced to a string. We might liberalise this in -# the future so it does work, but there are some design questions to -# resolve first. Adding a test so we don't liberalise it by accident. -expectStderr 1 nix --experimental-features 'nix-command dynamic-derivations' eval --impure --expr \ - 'builtins.outputOf (import ../dependencies.nix {}) "out"' \ - | grepQuiet "value is a set while a string was expected" - -# Test that "DrvDeep" string contexts are not supported at this time -# -# Like the above, this is a restriction we could relax later. -expectStderr 1 nix --experimental-features 'nix-command dynamic-derivations' eval --impure --expr \ - 'builtins.outputOf (import ../dependencies.nix {}).drvPath "out"' \ - | grepQuiet "has a context which refers to a complete source and binary closure. This is not supported at this time" - -# Test using `builtins.outputOf` with static derivations -testStaticHello () { - nix eval --impure --expr \ - 'with (import ./text-hashed-output.nix); let - a = hello.outPath; - b = builtins.outputOf (builtins.unsafeDiscardOutputDependency hello.drvPath) "out"; - in builtins.trace a - (builtins.trace b - (assert a == b; null))' -} - -# Test with a regular old input-addresed derivation -# -# `builtins.outputOf` works without ca-derivations and doesn't create a -# placeholder but just returns the output path. -testStaticHello - -# Test with content addressed derivation. -NIX_TESTS_CA_BY_DEFAULT=1 testStaticHello - -# Test with derivation-producing derivation -# -# This is hardly different from the preceding cases, except that we're -# only taking 1 outputOf out of 2 possible outputOfs. Note that -# `.outPath` could be defined as `outputOf drvPath`, which is what we're -# testing here. The other `outputOf` that we're not testing here is the -# use of _dynamic_ derivations. -nix eval --impure --expr \ - 'with (import ./text-hashed-output.nix); let - a = producingDrv.outPath; - b = builtins.outputOf (builtins.builtins.unsafeDiscardOutputDependency producingDrv.drvPath) "out"; - in builtins.trace a - (builtins.trace b - (assert a == b; null))' - -# Test with unbuilt output of derivation-producing derivation. -# -# This function similar to `testStaticHello` used above, but instead of -# checking the property on a constant derivation, we check it on a -# derivation that's from another derivation's output (outPath). -testDynamicHello () { - nix eval --impure --expr \ - 'with (import ./text-hashed-output.nix); let - a = builtins.outputOf producingDrv.outPath "out"; - b = builtins.outputOf (builtins.outputOf (builtins.unsafeDiscardOutputDependency producingDrv.drvPath) "out") "out"; - in builtins.trace a - (builtins.trace b - (assert a == b; null))' -} - -# inner dynamic derivation is input-addressed -testDynamicHello - -# inner dynamic derivation is content-addressed -NIX_TESTS_CA_BY_DEFAULT=1 testDynamicHello diff --git a/tests/dyn-drv/local.mk b/tests/dyn-drv/local.mk deleted file mode 100644 index 6b435499b..000000000 --- a/tests/dyn-drv/local.mk +++ /dev/null @@ -1,15 +0,0 @@ -dyn-drv-tests := \ - $(d)/text-hashed-output.sh \ - $(d)/recursive-mod-json.sh \ - $(d)/build-built-drv.sh \ - $(d)/eval-outputOf.sh \ - $(d)/dep-built-drv.sh \ - $(d)/old-daemon-error-hack.sh - -install-tests-groups += dyn-drv - -clean-files += \ - $(d)/config.nix - -test-deps += \ - tests/dyn-drv/config.nix diff --git a/tests/dyn-drv/old-daemon-error-hack.nix b/tests/dyn-drv/old-daemon-error-hack.nix deleted file mode 100644 index c9d4a62d4..000000000 --- a/tests/dyn-drv/old-daemon-error-hack.nix +++ /dev/null @@ -1,20 +0,0 @@ -with import ./config.nix; - -# A simple content-addressed derivation. -# The derivation can be arbitrarily modified by passing a different `seed`, -# but the output will always be the same -rec { - stub = mkDerivation { - name = "stub"; - buildCommand = '' - echo stub > $out - ''; - }; - wrapper = mkDerivation { - name = "has-dynamic-drv-dep"; - buildCommand = '' - exit 1 # we're not building this derivation - ${builtins.outputOf stub.outPath "out"} - ''; - }; -} diff --git a/tests/dyn-drv/old-daemon-error-hack.sh b/tests/dyn-drv/old-daemon-error-hack.sh deleted file mode 100644 index 43b049973..000000000 --- a/tests/dyn-drv/old-daemon-error-hack.sh +++ /dev/null @@ -1,11 +0,0 @@ -# Purposely bypassing our usual common for this subgroup -source ../common.sh - -# Need backend to support text-hashing too -isDaemonNewer "2.18.0pre20230906" && skipTest "Daemon is too new" - -enableFeatures "ca-derivations dynamic-derivations" - -restartDaemon - -expectStderr 1 nix-instantiate --read-write-mode ./old-daemon-error-hack.nix | grepQuiet "the daemon is too old to understand dependencies on dynamic derivations" diff --git a/tests/dyn-drv/recursive-mod-json.nix b/tests/dyn-drv/recursive-mod-json.nix deleted file mode 100644 index c6a24ca4f..000000000 --- a/tests/dyn-drv/recursive-mod-json.nix +++ /dev/null @@ -1,33 +0,0 @@ -with import ./config.nix; - -let innerName = "foo"; in - -mkDerivation rec { - name = "${innerName}.drv"; - SHELL = shell; - - requiredSystemFeatures = [ "recursive-nix" ]; - - drv = builtins.unsafeDiscardOutputDependency (import ./text-hashed-output.nix).hello.drvPath; - - buildCommand = '' - export NIX_CONFIG='experimental-features = nix-command ca-derivations' - - PATH=${builtins.getEnv "EXTRA_PATH"}:$PATH - - # JSON of pre-existing drv - nix derivation show $drv | jq .[] > drv0.json - - # Fix name - jq < drv0.json '.name = "${innerName}"' > drv1.json - - # Extend `buildCommand` - jq < drv1.json '.env.buildCommand += "echo \"I am alive!\" >> $out/hello\n"' > drv0.json - - # Used as our output - cp $(nix derivation add < drv0.json) $out - ''; - __contentAddressed = true; - outputHashMode = "text"; - outputHashAlgo = "sha256"; -} diff --git a/tests/dyn-drv/recursive-mod-json.sh b/tests/dyn-drv/recursive-mod-json.sh deleted file mode 100644 index 0698b81bd..000000000 --- a/tests/dyn-drv/recursive-mod-json.sh +++ /dev/null @@ -1,27 +0,0 @@ -source common.sh - -# FIXME -if [[ $(uname) != Linux ]]; then skipTest "Not running Linux"; fi - -export NIX_TESTS_CA_BY_DEFAULT=1 - -enableFeatures 'recursive-nix' -restartDaemon - -clearStore - -rm -f $TEST_ROOT/result - -EXTRA_PATH=$(dirname $(type -p nix)):$(dirname $(type -p jq)) -export EXTRA_PATH - -# Will produce a drv -metaDrv=$(nix-instantiate ./recursive-mod-json.nix) - -# computed "dynamic" derivation -drv=$(nix-store -r $metaDrv) - -# build that dyn drv -res=$(nix-store -r $drv) - -grep 'I am alive!' $res/hello diff --git a/tests/dyn-drv/text-hashed-output.nix b/tests/dyn-drv/text-hashed-output.nix deleted file mode 100644 index 99203b518..000000000 --- a/tests/dyn-drv/text-hashed-output.nix +++ /dev/null @@ -1,33 +0,0 @@ -with import ./config.nix; - -# A simple content-addressed derivation. -# The derivation can be arbitrarily modified by passing a different `seed`, -# but the output will always be the same -rec { - hello = mkDerivation { - name = "hello"; - buildCommand = '' - set -x - echo "Building a CA derivation" - mkdir -p $out - echo "Hello World" > $out/hello - ''; - }; - producingDrv = mkDerivation { - name = "hello.drv"; - buildCommand = '' - echo "Copying the derivation" - cp ${builtins.unsafeDiscardOutputDependency hello.drvPath} $out - ''; - __contentAddressed = true; - outputHashMode = "text"; - outputHashAlgo = "sha256"; - }; - wrapper = mkDerivation { - name = "use-dynamic-drv-in-non-dynamic-drv"; - buildCommand = '' - echo "Copying the output of the dynamic derivation" - cp -r ${builtins.outputOf producingDrv.outPath "out"} $out - ''; - }; -} diff --git a/tests/dyn-drv/text-hashed-output.sh b/tests/dyn-drv/text-hashed-output.sh deleted file mode 100644 index f3e5aa93b..000000000 --- a/tests/dyn-drv/text-hashed-output.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash - -source common.sh - -# In the corresponding nix file, we have two derivations: the first, named root, -# is a normal recursive derivation, while the second, named dependent, has the -# new outputHashMode "text". Note that in "dependent", we don't refer to the -# build output of root, but only to the path of the drv file. For this reason, -# we only need to: -# -# - instantiate the root derivation -# - build the dependent derivation -# - check that the path of the output coincides with that of the original derivation - -drv=$(nix-instantiate ./text-hashed-output.nix -A hello) -nix show-derivation "$drv" - -drvProducingDrv=$(nix-instantiate ./text-hashed-output.nix -A producingDrv) -nix show-derivation "$drvProducingDrv" - -out1=$(nix-build ./text-hashed-output.nix -A producingDrv --no-out-link) - -nix path-info $drv --derivation --json | jq -nix path-info $out1 --derivation --json | jq - -test $out1 == $drv diff --git a/tests/eval-store.sh b/tests/eval-store.sh deleted file mode 100644 index 8fc859730..000000000 --- a/tests/eval-store.sh +++ /dev/null @@ -1,30 +0,0 @@ -source common.sh - -# Using `--eval-store` with the daemon will eventually copy everything -# to the build store, invalidating most of the tests here -needLocalStore "“--eval-store” doesn't achieve much with the daemon" - -eval_store=$TEST_ROOT/eval-store - -clearStore -rm -rf "$eval_store" - -nix build -f dependencies.nix --eval-store "$eval_store" -o "$TEST_ROOT/result" -[[ -e $TEST_ROOT/result/foobar ]] -(! ls $NIX_STORE_DIR/*.drv) -ls $eval_store/nix/store/*.drv - -clearStore -rm -rf "$eval_store" - -nix-instantiate dependencies.nix --eval-store "$eval_store" -(! ls $NIX_STORE_DIR/*.drv) -ls $eval_store/nix/store/*.drv - -clearStore -rm -rf "$eval_store" - -nix-build dependencies.nix --eval-store "$eval_store" -o "$TEST_ROOT/result" -[[ -e $TEST_ROOT/result/foobar ]] -(! ls $NIX_STORE_DIR/*.drv) -ls $eval_store/nix/store/*.drv diff --git a/tests/eval.nix b/tests/eval.nix deleted file mode 100644 index befbd17a9..000000000 --- a/tests/eval.nix +++ /dev/null @@ -1,5 +0,0 @@ -{ - int = 123; - str = "foo"; - attr.foo = "bar"; -} diff --git a/tests/eval.sh b/tests/eval.sh deleted file mode 100644 index b81bb1e2c..000000000 --- a/tests/eval.sh +++ /dev/null @@ -1,43 +0,0 @@ -source common.sh - -clearStore - -testStdinHeredoc=$(nix eval -f - < $TEST_ROOT/xyzzy/default.nix -[[ $(nix eval --impure --expr "import $TEST_ROOT/foo/bar") = 123 ]] diff --git a/tests/experimental-features.sh b/tests/experimental-features.sh deleted file mode 100644 index 607bf0a8e..000000000 --- a/tests/experimental-features.sh +++ /dev/null @@ -1,86 +0,0 @@ -source common.sh - -# Skipping these two for now, because we actually *do* want flags and -# config settings to always show up in the manual, just be marked -# experimental. Will reenable once the manual generation takes advantage -# of the JSON metadata on this. -# -# # Without flakes, flake options should not show up -# # With flakes, flake options should show up -# -# function grep_both_ways { -# nix --experimental-features 'nix-command' "$@" | grepQuietInverse flake -# nix --experimental-features 'nix-command flakes' "$@" | grepQuiet flake -# -# # Also, the order should not matter -# nix "$@" --experimental-features 'nix-command' | grepQuietInverse flake -# nix "$@" --experimental-features 'nix-command flakes' | grepQuiet flake -# } -# -# # Simple case, the configuration effects the running command -# grep_both_ways show-config -# -# # Medium case, the configuration effects --help -# grep_both_ways store gc --help - -# Test settings that are gated on experimental features; the setting is ignored -# with a warning if the experimental feature is not enabled. The order of the -# `setting = value` lines in the configuration should not matter. - -# 'flakes' experimental-feature is disabled before, ignore and warn -NIX_CONFIG=' - experimental-features = nix-command - accept-flake-config = true -' nix show-config accept-flake-config 1>$TEST_ROOT/stdout 2>$TEST_ROOT/stderr -grepQuiet "false" $TEST_ROOT/stdout -grepQuiet "Ignoring setting 'accept-flake-config' because experimental feature 'flakes' is not enabled" $TEST_ROOT/stderr - -# 'flakes' experimental-feature is disabled after, ignore and warn -NIX_CONFIG=' - accept-flake-config = true - experimental-features = nix-command -' nix show-config accept-flake-config 1>$TEST_ROOT/stdout 2>$TEST_ROOT/stderr -grepQuiet "false" $TEST_ROOT/stdout -grepQuiet "Ignoring setting 'accept-flake-config' because experimental feature 'flakes' is not enabled" $TEST_ROOT/stderr - -# 'flakes' experimental-feature is enabled before, process -NIX_CONFIG=' - experimental-features = nix-command flakes - accept-flake-config = true -' nix show-config accept-flake-config 1>$TEST_ROOT/stdout 2>$TEST_ROOT/stderr -grepQuiet "true" $TEST_ROOT/stdout -grepQuietInverse "Ignoring setting 'accept-flake-config'" $TEST_ROOT/stderr - -# 'flakes' experimental-feature is enabled after, process -NIX_CONFIG=' - accept-flake-config = true - experimental-features = nix-command flakes -' nix show-config accept-flake-config 1>$TEST_ROOT/stdout 2>$TEST_ROOT/stderr -grepQuiet "true" $TEST_ROOT/stdout -grepQuietInverse "Ignoring setting 'accept-flake-config'" $TEST_ROOT/stderr - -function exit_code_both_ways { - expect 1 nix --experimental-features 'nix-command' "$@" 1>/dev/null - nix --experimental-features 'nix-command flakes' "$@" 1>/dev/null - - # Also, the order should not matter - expect 1 nix "$@" --experimental-features 'nix-command' 1>/dev/null - nix "$@" --experimental-features 'nix-command flakes' 1>/dev/null -} - -exit_code_both_ways show-config --flake-registry 'https://no' - -# Double check these are stable -nix --experimental-features '' --help 1>/dev/null -nix --experimental-features '' doctor --help 1>/dev/null -nix --experimental-features '' repl --help 1>/dev/null -nix --experimental-features '' upgrade-nix --help 1>/dev/null - -# These 3 arguments are currently given to all commands, which is wrong (as not -# all care). To deal with fixing later, we simply make them require the -# nix-command experimental features --- it so happens that the commands we wish -# stabilizing to do not need them anyways. -for arg in '--print-build-logs' '--offline' '--refresh'; do - nix --experimental-features 'nix-command' "$arg" --help 1>/dev/null - expect 1 nix --experimental-features '' "$arg" --help 1>/dev/null -done diff --git a/tests/export-graph.nix b/tests/export-graph.nix deleted file mode 100644 index 64fe36bd1..000000000 --- a/tests/export-graph.nix +++ /dev/null @@ -1,29 +0,0 @@ -with import ./config.nix; - -rec { - - printRefs = - '' - echo $exportReferencesGraph - while read path; do - read drv - read nrRefs - echo "$path has $nrRefs references" - echo "$path" >> $out - for ((n = 0; n < $nrRefs; n++)); do read ref; echo "ref $ref"; test -e "$ref"; done - done < refs - ''; - - foo."bar.runtimeGraph" = mkDerivation { - name = "dependencies"; - builder = builtins.toFile "build-graph-builder" "${printRefs}"; - exportReferencesGraph = ["refs" (import ./dependencies.nix {})]; - }; - - foo."bar.buildGraph" = mkDerivation { - name = "dependencies"; - builder = builtins.toFile "build-graph-builder" "${printRefs}"; - exportReferencesGraph = ["refs" (import ./dependencies.nix {}).drvPath]; - }; - -} diff --git a/tests/export-graph.sh b/tests/export-graph.sh deleted file mode 100644 index 1f6232a40..000000000 --- a/tests/export-graph.sh +++ /dev/null @@ -1,30 +0,0 @@ -source common.sh - -clearStore -clearProfiles - -checkRef() { - nix-store -q --references $TEST_ROOT/result | grepQuiet "$1"'$' || fail "missing reference $1" -} - -# Test the export of the runtime dependency graph. - -outPath=$(nix-build ./export-graph.nix -A 'foo."bar.runtimeGraph"' -o $TEST_ROOT/result) - -test $(nix-store -q --references $TEST_ROOT/result | wc -l) = 3 || fail "bad nr of references" - -checkRef input-2 -for i in $(cat $outPath); do checkRef $i; done - -# Test the export of the build-time dependency graph. - -nix-store --gc # should force rebuild of input-1 - -outPath=$(nix-build ./export-graph.nix -A 'foo."bar.buildGraph"' -o $TEST_ROOT/result) - -checkRef input-1 -checkRef input-1.drv -checkRef input-2 -checkRef input-2.drv - -for i in $(cat $outPath); do checkRef $i; done diff --git a/tests/export.sh b/tests/export.sh deleted file mode 100644 index 2238539bc..000000000 --- a/tests/export.sh +++ /dev/null @@ -1,36 +0,0 @@ -source common.sh - -clearStore - -outPath=$(nix-build dependencies.nix --no-out-link) - -nix-store --export $outPath > $TEST_ROOT/exp - -nix-store --export $(nix-store -qR $outPath) > $TEST_ROOT/exp_all - -if nix-store --export $outPath >/dev/full ; then - echo "exporting to a bad file descriptor should fail" - exit 1 -fi - - -clearStore - -if nix-store --import < $TEST_ROOT/exp; then - echo "importing a non-closure should fail" - exit 1 -fi - - -clearStore - -nix-store --import < $TEST_ROOT/exp_all - -nix-store --export $(nix-store -qR $outPath) > $TEST_ROOT/exp_all2 - - -clearStore - -# Regression test: the derivers in exp_all2 are empty, which shouldn't -# cause a failure. -nix-store --import < $TEST_ROOT/exp_all2 diff --git a/tests/failing.nix b/tests/failing.nix deleted file mode 100644 index 2a0350d4d..000000000 --- a/tests/failing.nix +++ /dev/null @@ -1,22 +0,0 @@ -{ busybox }: -with import ./config.nix; -let - - mkDerivation = args: - derivation ({ - inherit system; - builder = busybox; - args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" "if [ -e .attrs.sh ]; then source .attrs.sh; fi; eval \"$buildCommand\"")]; - } // removeAttrs args ["builder" "meta"]) - // { meta = args.meta or {}; }; -in -{ - - failing = mkDerivation { - name = "failing"; - buildCommand = '' - echo foo > bar - exit 1 - ''; - }; -} diff --git a/tests/fetchClosure.sh b/tests/fetchClosure.sh deleted file mode 100644 index a02d1ce7a..000000000 --- a/tests/fetchClosure.sh +++ /dev/null @@ -1,150 +0,0 @@ -source common.sh - -enableFeatures "fetch-closure" - -clearStore -clearCacheCache - -# Old daemons don't properly zero out the self-references when -# calculating the CA hashes, so this breaks `nix store -# make-content-addressed` which expects the client and the daemon to -# compute the same hash -requireDaemonNewerThan "2.16.0pre20230524" - -# Initialize binary cache. -nonCaPath=$(nix build --json --file ./dependencies.nix --no-link | jq -r .[].outputs.out) -caPath=$(nix store make-content-addressed --json $nonCaPath | jq -r '.rewrites | map(.) | .[]') -nix copy --to file://$cacheDir $nonCaPath - -# Test basic fetchClosure rewriting from non-CA to CA. -clearStore - -[ ! -e $nonCaPath ] -[ ! -e $caPath ] - -[[ $(nix eval -v --raw --expr " - builtins.fetchClosure { - fromStore = \"file://$cacheDir\"; - fromPath = $nonCaPath; - toPath = $caPath; - } -") = $caPath ]] - -[ ! -e $nonCaPath ] -[ -e $caPath ] - -clearStore - -# The daemon will reject input addressed paths unless configured to trust the -# cache key or the user. This behavior should be covered by another test, so we -# skip this part when using the daemon. -if [[ "$NIX_REMOTE" != "daemon" ]]; then - - # If we want to return a non-CA path, we have to be explicit about it. - expectStderr 1 nix eval --raw --no-require-sigs --expr " - builtins.fetchClosure { - fromStore = \"file://$cacheDir\"; - fromPath = $nonCaPath; - } - " | grepQuiet -E "The .fromPath. value .* is input-addressed, but .inputAddressed. is set to .false." - - # TODO: Should the closure be rejected, despite single user mode? - # [ ! -e $nonCaPath ] - - [ ! -e $caPath ] - - # We can use non-CA paths when we ask explicitly. - [[ $(nix eval --raw --no-require-sigs --expr " - builtins.fetchClosure { - fromStore = \"file://$cacheDir\"; - fromPath = $nonCaPath; - inputAddressed = true; - } - ") = $nonCaPath ]] - - [ -e $nonCaPath ] - [ ! -e $caPath ] - - -fi - -[ ! -e $caPath ] - -# 'toPath' set to empty string should fail but print the expected path. -expectStderr 1 nix eval -v --json --expr " - builtins.fetchClosure { - fromStore = \"file://$cacheDir\"; - fromPath = $nonCaPath; - toPath = \"\"; - } -" | grep "error: rewriting.*$nonCaPath.*yielded.*$caPath" - -# If fromPath is CA, then toPath isn't needed. -nix copy --to file://$cacheDir $caPath - -clearStore - -[ ! -e $caPath ] - -[[ $(nix eval -v --raw --expr " - builtins.fetchClosure { - fromStore = \"file://$cacheDir\"; - fromPath = $caPath; - } -") = $caPath ]] - -[ -e $caPath ] - -# Check that URL query parameters aren't allowed. -clearStore -narCache=$TEST_ROOT/nar-cache -rm -rf $narCache -(! nix eval -v --raw --expr " - builtins.fetchClosure { - fromStore = \"file://$cacheDir?local-nar-cache=$narCache\"; - fromPath = $caPath; - } -") -(! [ -e $narCache ]) - -# If toPath is specified but wrong, we check it (only) when the path is missing. -clearStore - -badPath=$(echo $caPath | sed -e 's!/store/................................-!/store/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-!') - -[ ! -e $badPath ] - -expectStderr 1 nix eval -v --raw --expr " - builtins.fetchClosure { - fromStore = \"file://$cacheDir\"; - fromPath = $nonCaPath; - toPath = $badPath; - } -" | grep "error: rewriting.*$nonCaPath.*yielded.*$caPath.*while.*$badPath.*was expected" - -[ ! -e $badPath ] - -# We only check it when missing, as a performance optimization similar to what we do for fixed output derivations. So if it's already there, we don't check it. -# It would be nice for this to fail, but checking it would be too(?) slow. -[ -e $caPath ] - -[[ $(nix eval -v --raw --expr " - builtins.fetchClosure { - fromStore = \"file://$cacheDir\"; - fromPath = $badPath; - toPath = $caPath; - } -") = $caPath ]] - - -# However, if the output address is unexpected, we can report it - - -expectStderr 1 nix eval -v --raw --expr " - builtins.fetchClosure { - fromStore = \"file://$cacheDir\"; - fromPath = $caPath; - inputAddressed = true; - } -" | grepQuiet 'error.*The store object referred to by.*fromPath.* at .* is not input-addressed, but .*inputAddressed.* is set to .*true.*' - diff --git a/tests/fetchGit.sh b/tests/fetchGit.sh deleted file mode 100644 index 418b4f63f..000000000 --- a/tests/fetchGit.sh +++ /dev/null @@ -1,256 +0,0 @@ -source common.sh - -requireGit - -clearStore - -# Intentionally not in a canonical form -# See https://github.com/NixOS/nix/issues/6195 -repo=$TEST_ROOT/./git - -export _NIX_FORCE_HTTP=1 - -rm -rf $repo ${repo}-tmp $TEST_HOME/.cache/nix $TEST_ROOT/worktree $TEST_ROOT/shallow $TEST_ROOT/minimal - -git init $repo -git -C $repo config user.email "foobar@example.com" -git -C $repo config user.name "Foobar" - -echo utrecht > $repo/hello -touch $repo/.gitignore -git -C $repo add hello .gitignore -git -C $repo commit -m 'Bla1' -rev1=$(git -C $repo rev-parse HEAD) -git -C $repo tag -a tag1 -m tag1 - -echo world > $repo/hello -git -C $repo commit -m 'Bla2' -a -git -C $repo worktree add $TEST_ROOT/worktree -echo hello >> $TEST_ROOT/worktree/hello -rev2=$(git -C $repo rev-parse HEAD) -git -C $repo tag -a tag2 -m tag2 - -# Fetch a worktree -unset _NIX_FORCE_HTTP -path0=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$TEST_ROOT/worktree).outPath") -path0_=$(nix eval --impure --raw --expr "(builtins.fetchTree { type = \"git\"; url = file://$TEST_ROOT/worktree; }).outPath") -[[ $path0 = $path0_ ]] -export _NIX_FORCE_HTTP=1 -[[ $(tail -n 1 $path0/hello) = "hello" ]] - -# Fetch the default branch. -path=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).outPath") -[[ $(cat $path/hello) = world ]] - -# Fetch a rev from another branch -git -C $repo checkout -b devtest -echo "different file" >> $TEST_ROOT/git/differentbranch -git -C $repo add differentbranch -git -C $repo commit -m 'Test2' -git -C $repo checkout master -devrev=$(git -C $repo rev-parse devtest) -out=$(nix eval --impure --raw --expr "builtins.fetchGit { url = file://$repo; rev = \"$devrev\"; }" 2>&1) || status=$? -[[ $status == 1 ]] -[[ $out =~ 'Cannot find Git revision' ]] - -[[ $(nix eval --raw --expr "builtins.readFile (builtins.fetchGit { url = file://$repo; rev = \"$devrev\"; allRefs = true; } + \"/differentbranch\")") = 'different file' ]] - -# In pure eval mode, fetchGit without a revision should fail. -[[ $(nix eval --impure --raw --expr "builtins.readFile (fetchGit file://$repo + \"/hello\")") = world ]] -(! nix eval --raw --expr "builtins.readFile (fetchGit file://$repo + \"/hello\")") - -# Fetch using an explicit revision hash. -path2=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$repo; rev = \"$rev2\"; }).outPath") -[[ $path = $path2 ]] - -# In pure eval mode, fetchGit with a revision should succeed. -[[ $(nix eval --raw --expr "builtins.readFile (fetchGit { url = file://$repo; rev = \"$rev2\"; } + \"/hello\")") = world ]] - -# Fetch again. This should be cached. -mv $repo ${repo}-tmp -path2=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).outPath") -[[ $path = $path2 ]] - -[[ $(nix eval --impure --expr "(builtins.fetchGit file://$repo).revCount") = 2 ]] -[[ $(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).rev") = $rev2 ]] -[[ $(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).shortRev") = ${rev2:0:7} ]] - -# Fetching with a explicit hash should succeed. -path2=$(nix eval --refresh --raw --expr "(builtins.fetchGit { url = file://$repo; rev = \"$rev2\"; }).outPath") -[[ $path = $path2 ]] - -path2=$(nix eval --refresh --raw --expr "(builtins.fetchGit { url = file://$repo; rev = \"$rev1\"; }).outPath") -[[ $(cat $path2/hello) = utrecht ]] - -mv ${repo}-tmp $repo - -# Using a clean working tree should produce the same result. -path2=$(nix eval --impure --raw --expr "(builtins.fetchGit $repo).outPath") -[[ $path = $path2 ]] - -# Using an unclean tree should yield the tracked but uncommitted changes. -mkdir $repo/dir1 $repo/dir2 -echo foo > $repo/dir1/foo -echo bar > $repo/bar -echo bar > $repo/dir2/bar -git -C $repo add dir1/foo -git -C $repo rm hello - -unset _NIX_FORCE_HTTP -path2=$(nix eval --impure --raw --expr "(builtins.fetchGit $repo).outPath") -[ ! -e $path2/hello ] -[ ! -e $path2/bar ] -[ ! -e $path2/dir2/bar ] -[ ! -e $path2/.git ] -[[ $(cat $path2/dir1/foo) = foo ]] - -[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).rev") = 0000000000000000000000000000000000000000 ]] -[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).dirtyRev") = "${rev2}-dirty" ]] -[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).dirtyShortRev") = "${rev2:0:7}-dirty" ]] - -# ... unless we're using an explicit ref or rev. -path3=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; ref = \"master\"; }).outPath") -[[ $path = $path3 ]] - -path3=$(nix eval --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; }).outPath") -[[ $path = $path3 ]] - -# Committing should not affect the store path. -git -C $repo commit -m 'Bla3' -a - -path4=$(nix eval --impure --refresh --raw --expr "(builtins.fetchGit file://$repo).outPath") -[[ $path2 = $path4 ]] - -[[ $(nix eval --impure --expr "builtins.hasAttr \"rev\" (builtins.fetchGit $repo)") == "true" ]] -[[ $(nix eval --impure --expr "builtins.hasAttr \"dirtyRev\" (builtins.fetchGit $repo)") == "false" ]] -[[ $(nix eval --impure --expr "builtins.hasAttr \"dirtyShortRev\" (builtins.fetchGit $repo)") == "false" ]] - -status=0 -nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; narHash = \"sha256-B5yIPHhEm0eysJKEsO7nqxprh9vcblFxpJG11gXJus1=\"; }).outPath" || status=$? -[[ "$status" = "102" ]] - -path5=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; narHash = \"sha256-Hr8g6AqANb3xqX28eu1XnjK/3ab8Gv6TJSnkb1LezG9=\"; }).outPath") -[[ $path = $path5 ]] - -# tarball-ttl should be ignored if we specify a rev -echo delft > $repo/hello -git -C $repo add hello -git -C $repo commit -m 'Bla4' -rev3=$(git -C $repo rev-parse HEAD) -nix eval --tarball-ttl 3600 --expr "builtins.fetchGit { url = $repo; rev = \"$rev3\"; }" >/dev/null - -# Update 'path' to reflect latest master -path=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).outPath") - -# Check behavior when non-master branch is used -git -C $repo checkout $rev2 -b dev -echo dev > $repo/hello - -# File URI uses dirty tree unless specified otherwise -path2=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).outPath") -[ $(cat $path2/hello) = dev ] - -# Using local path with branch other than 'master' should work when clean or dirty -path3=$(nix eval --impure --raw --expr "(builtins.fetchGit $repo).outPath") -# (check dirty-tree handling was used) -[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).rev") = 0000000000000000000000000000000000000000 ]] -[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).shortRev") = 0000000 ]] -# Making a dirty tree clean again and fetching it should -# record correct revision information. See: #4140 -echo world > $repo/hello -[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).rev") = $rev2 ]] - -# Committing shouldn't change store path, or switch to using 'master' -echo dev > $repo/hello -git -C $repo commit -m 'Bla5' -a -path4=$(nix eval --impure --raw --expr "(builtins.fetchGit $repo).outPath") -[[ $(cat $path4/hello) = dev ]] -[[ $path3 = $path4 ]] - -# Using remote path with branch other than 'master' should fetch the HEAD revision. -# (--tarball-ttl 0 to prevent using the cached repo above) -export _NIX_FORCE_HTTP=1 -path4=$(nix eval --tarball-ttl 0 --impure --raw --expr "(builtins.fetchGit $repo).outPath") -[[ $(cat $path4/hello) = dev ]] -[[ $path3 = $path4 ]] -unset _NIX_FORCE_HTTP - -# Confirm same as 'dev' branch -path5=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; ref = \"dev\"; }).outPath") -[[ $path3 = $path5 ]] - - -# Nuke the cache -rm -rf $TEST_HOME/.cache/nix - -# Try again, but without 'git' on PATH. This should fail. -NIX=$(command -v nix) -(! PATH= $NIX eval --impure --raw --expr "(builtins.fetchGit { url = $repo; ref = \"dev\"; }).outPath" ) - -# Try again, with 'git' available. This should work. -path5=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; ref = \"dev\"; }).outPath") -[[ $path3 = $path5 ]] - -# Fetching from a repo with only a specific revision and no branches should -# not fall back to copying files and record correct revision information. See: #5302 -mkdir $TEST_ROOT/minimal -git -C $TEST_ROOT/minimal init -git -C $TEST_ROOT/minimal fetch $repo $rev2 -git -C $TEST_ROOT/minimal checkout $rev2 -[[ $(nix eval --impure --raw --expr "(builtins.fetchGit { url = $TEST_ROOT/minimal; }).rev") = $rev2 ]] - -# Fetching a shallow repo shouldn't work by default, because we can't -# return a revCount. -git clone --depth 1 file://$repo $TEST_ROOT/shallow -(! nix eval --impure --raw --expr "(builtins.fetchGit { url = $TEST_ROOT/shallow; ref = \"dev\"; }).outPath") - -# But you can request a shallow clone, which won't return a revCount. -path6=$(nix eval --impure --raw --expr "(builtins.fetchTree { type = \"git\"; url = \"file://$TEST_ROOT/shallow\"; ref = \"dev\"; shallow = true; }).outPath") -[[ $path3 = $path6 ]] -[[ $(nix eval --impure --expr "(builtins.fetchTree { type = \"git\"; url = \"file://$TEST_ROOT/shallow\"; ref = \"dev\"; shallow = true; }).revCount or 123") == 123 ]] - -# Explicit ref = "HEAD" should work, and produce the same outPath as without ref -path7=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"HEAD\"; }).outPath") -path8=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; }).outPath") -[[ $path7 = $path8 ]] - -# ref = "HEAD" should fetch the HEAD revision -rev4=$(git -C $repo rev-parse HEAD) -rev4_nix=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"HEAD\"; }).rev") -[[ $rev4 = $rev4_nix ]] - -# The name argument should be handled -path9=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"HEAD\"; name = \"foo\"; }).outPath") -[[ $path9 =~ -foo$ ]] - -# Specifying a ref without a rev shouldn't pick a cached rev for a different ref -export _NIX_FORCE_HTTP=1 -rev_tag1_nix=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"refs/tags/tag1\"; }).rev") -rev_tag1=$(git -C $repo rev-parse refs/tags/tag1) -[[ $rev_tag1_nix = $rev_tag1 ]] -rev_tag2_nix=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"refs/tags/tag2\"; }).rev") -rev_tag2=$(git -C $repo rev-parse refs/tags/tag2) -[[ $rev_tag2_nix = $rev_tag2 ]] -unset _NIX_FORCE_HTTP - -# should fail if there is no repo -rm -rf $repo/.git -(! nix eval --impure --raw --expr "(builtins.fetchGit \"file://$repo\").outPath") - -# should succeed for a repo without commits -git init $repo -path10=$(nix eval --impure --raw --expr "(builtins.fetchGit \"file://$repo\").outPath") - -# should succeed for a path with a space -# regression test for #7707 -repo="$TEST_ROOT/a b" -git init "$repo" -git -C "$repo" config user.email "foobar@example.com" -git -C "$repo" config user.name "Foobar" - -echo utrecht > "$repo/hello" -touch "$repo/.gitignore" -git -C "$repo" add hello .gitignore -git -C "$repo" commit -m 'Bla1' -cd "$repo" -path11=$(nix eval --impure --raw --expr "(builtins.fetchGit ./.).outPath") diff --git a/tests/fetchGitRefs.sh b/tests/fetchGitRefs.sh deleted file mode 100644 index d643fea04..000000000 --- a/tests/fetchGitRefs.sh +++ /dev/null @@ -1,108 +0,0 @@ -source common.sh - -requireGit - -clearStore - -repo="$TEST_ROOT/git" - -rm -rf "$repo" "${repo}-tmp" "$TEST_HOME/.cache/nix" - -git init "$repo" -git -C "$repo" config user.email "foobar@example.com" -git -C "$repo" config user.name "Foobar" - -echo utrecht > "$repo"/hello -git -C "$repo" add hello -git -C "$repo" commit -m 'Bla1' - -path=$(nix eval --raw --impure --expr "(builtins.fetchGit { url = $repo; ref = \"master\"; }).outPath") - -# Test various combinations of ref names -# (taken from the git project) - -# git help check-ref-format -# Git imposes the following rules on how references are named: -# -# 1. They can include slash / for hierarchical (directory) grouping, but no slash-separated component can begin with a dot . or end with the sequence .lock. -# 2. They must contain at least one /. This enforces the presence of a category like heads/, tags/ etc. but the actual names are not restricted. If the --allow-onelevel option is used, this rule is waived. -# 3. They cannot have two consecutive dots .. anywhere. -# 4. They cannot have ASCII control characters (i.e. bytes whose values are lower than \040, or \177 DEL), space, tilde ~, caret ^, or colon : anywhere. -# 5. They cannot have question-mark ?, asterisk *, or open bracket [ anywhere. See the --refspec-pattern option below for an exception to this rule. -# 6. They cannot begin or end with a slash / or contain multiple consecutive slashes (see the --normalize option below for an exception to this rule) -# 7. They cannot end with a dot .. -# 8. They cannot contain a sequence @{. -# 9. They cannot be the single character @. -# 10. They cannot contain a \. - -valid_ref() { - { set +x; printf >&2 '\n>>>>>>>>>> valid_ref %s\b <<<<<<<<<<\n' $(printf %s "$1" | sed -n -e l); set -x; } - git check-ref-format --branch "$1" >/dev/null - git -C "$repo" branch "$1" master >/dev/null - path1=$(nix eval --raw --impure --expr "(builtins.fetchGit { url = $repo; ref = ''$1''; }).outPath") - [[ $path1 = $path ]] - git -C "$repo" branch -D "$1" >/dev/null -} - -invalid_ref() { - { set +x; printf >&2 '\n>>>>>>>>>> invalid_ref %s\b <<<<<<<<<<\n' $(printf %s "$1" | sed -n -e l); set -x; } - # special case for a sole @: - # --branch @ will try to interpret @ as a branch reference and not fail. Thus we need --allow-onelevel - if [ "$1" = "@" ]; then - (! git check-ref-format --allow-onelevel "$1" >/dev/null 2>&1) - else - (! git check-ref-format --branch "$1" >/dev/null 2>&1) - fi - expect 1 nix --debug eval --raw --impure --expr "(builtins.fetchGit { url = $repo; ref = ''$1''; }).outPath" 2>&1 | grep 'invalid Git branch/tag name' >/dev/null -} - - -valid_ref 'foox' -valid_ref '1337' -valid_ref 'foo.baz' -valid_ref 'foo/bar/baz' -valid_ref 'foo./bar' -valid_ref 'heads/foo@bar' -valid_ref "$(printf 'heads/fu\303\237')" -valid_ref 'foo-bar-baz' -valid_ref '$1' -valid_ref 'foo.locke' - -invalid_ref 'refs///heads/foo' -invalid_ref 'heads/foo/' -invalid_ref '///heads/foo' -invalid_ref '.foo' -invalid_ref './foo' -invalid_ref './foo/bar' -invalid_ref 'foo/./bar' -invalid_ref 'foo/bar/.' -invalid_ref 'foo bar' -invalid_ref 'foo?bar' -invalid_ref 'foo^bar' -invalid_ref 'foo~bar' -invalid_ref 'foo:bar' -invalid_ref 'foo[bar' -invalid_ref 'foo/bar/.' -invalid_ref '.refs/foo' -invalid_ref 'refs/heads/foo.' -invalid_ref 'heads/foo..bar' -invalid_ref 'heads/foo?bar' -invalid_ref 'heads/foo.lock' -invalid_ref 'heads///foo.lock' -invalid_ref 'foo.lock/bar' -invalid_ref 'foo.lock///bar' -invalid_ref 'heads/v@{ation' -invalid_ref 'heads/foo\.ar' # should fail due to \ -invalid_ref 'heads/foo\bar' # should fail due to \ -invalid_ref "$(printf 'heads/foo\t')" # should fail because it has a TAB -invalid_ref "$(printf 'heads/foo\177')" -invalid_ref '@' - -invalid_ref 'foo/*' -invalid_ref '*/foo' -invalid_ref 'foo/*/bar' -invalid_ref '*' -invalid_ref 'foo/*/*' -invalid_ref '*/foo/*' -invalid_ref '/foo' -invalid_ref '' diff --git a/tests/fetchGitSubmodules.sh b/tests/fetchGitSubmodules.sh deleted file mode 100644 index df81232e5..000000000 --- a/tests/fetchGitSubmodules.sh +++ /dev/null @@ -1,128 +0,0 @@ -source common.sh - -set -u - -requireGit - -clearStore - -rootRepo=$TEST_ROOT/gitSubmodulesRoot -subRepo=$TEST_ROOT/gitSubmodulesSub - -rm -rf ${rootRepo} ${subRepo} $TEST_HOME/.cache/nix - -# Submodules can't be fetched locally by default, which can cause -# information leakage vulnerabilities, but for these tests our -# submodule is intentionally local and it's all trusted, so we -# disable this restriction. Setting it per repo is not sufficient, as -# the repo-local config does not apply to the commands run from -# outside the repos by Nix. -export XDG_CONFIG_HOME=$TEST_HOME/.config -git config --global protocol.file.allow always - -initGitRepo() { - git init $1 - git -C $1 config user.email "foobar@example.com" - git -C $1 config user.name "Foobar" -} - -addGitContent() { - echo "lorem ipsum" > $1/content - git -C $1 add content - git -C $1 commit -m "Initial commit" -} - -initGitRepo $subRepo -addGitContent $subRepo - -initGitRepo $rootRepo - -git -C $rootRepo submodule init -git -C $rootRepo submodule add $subRepo sub -git -C $rootRepo add sub -git -C $rootRepo commit -m "Add submodule" - -rev=$(git -C $rootRepo rev-parse HEAD) - -r1=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; }).outPath") -r2=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; submodules = false; }).outPath") -r3=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; submodules = true; }).outPath") - -[[ $r1 == $r2 ]] -[[ $r2 != $r3 ]] - -r4=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; ref = \"master\"; rev = \"$rev\"; }).outPath") -r5=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; ref = \"master\"; rev = \"$rev\"; submodules = false; }).outPath") -r6=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; ref = \"master\"; rev = \"$rev\"; submodules = true; }).outPath") -r7=$(nix eval --raw --expr "(builtins.fetchGit { url = $rootRepo; ref = \"master\"; rev = \"$rev\"; submodules = true; }).outPath") -r8=$(nix eval --raw --expr "(builtins.fetchGit { url = $rootRepo; rev = \"$rev\"; submodules = true; }).outPath") - -[[ $r1 == $r4 ]] -[[ $r4 == $r5 ]] -[[ $r3 == $r6 ]] -[[ $r6 == $r7 ]] -[[ $r7 == $r8 ]] - -have_submodules=$(nix eval --expr "(builtins.fetchGit { url = $rootRepo; rev = \"$rev\"; }).submodules") -[[ $have_submodules == false ]] - -have_submodules=$(nix eval --expr "(builtins.fetchGit { url = $rootRepo; rev = \"$rev\"; submodules = false; }).submodules") -[[ $have_submodules == false ]] - -have_submodules=$(nix eval --expr "(builtins.fetchGit { url = $rootRepo; rev = \"$rev\"; submodules = true; }).submodules") -[[ $have_submodules == true ]] - -pathWithoutSubmodules=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; }).outPath") -pathWithSubmodules=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; submodules = true; }).outPath") -pathWithSubmodulesAgain=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; submodules = true; }).outPath") -pathWithSubmodulesAgainWithRef=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; ref = \"master\"; rev = \"$rev\"; submodules = true; }).outPath") - -# The resulting store path cannot be the same. -[[ $pathWithoutSubmodules != $pathWithSubmodules ]] - -# Checking out the same repo with submodules returns in the same store path. -[[ $pathWithSubmodules == $pathWithSubmodulesAgain ]] - -# Checking out the same repo with submodules returns in the same store path. -[[ $pathWithSubmodulesAgain == $pathWithSubmodulesAgainWithRef ]] - -# The submodules flag is actually honored. -[[ ! -e $pathWithoutSubmodules/sub/content ]] -[[ -e $pathWithSubmodules/sub/content ]] - -[[ -e $pathWithSubmodulesAgainWithRef/sub/content ]] - -# No .git directory or submodule reference files must be left -test "$(find "$pathWithSubmodules" -name .git)" = "" - -# Git repos without submodules can be fetched with submodules = true. -subRev=$(git -C $subRepo rev-parse HEAD) -noSubmoduleRepoBaseline=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$subRepo; rev = \"$subRev\"; }).outPath") -noSubmoduleRepo=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$subRepo; rev = \"$subRev\"; submodules = true; }).outPath") - -[[ $noSubmoduleRepoBaseline == $noSubmoduleRepo ]] - -# Test relative submodule URLs. -rm $TEST_HOME/.cache/nix/fetcher-cache* -rm -rf $rootRepo/.git $rootRepo/.gitmodules $rootRepo/sub -initGitRepo $rootRepo -git -C $rootRepo submodule add ../gitSubmodulesSub sub -git -C $rootRepo commit -m "Add submodule" -rev2=$(git -C $rootRepo rev-parse HEAD) -pathWithRelative=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev2\"; submodules = true; }).outPath") -diff -r -x .gitmodules $pathWithSubmodules $pathWithRelative - -# Test clones that have an upstream with relative submodule URLs. -rm $TEST_HOME/.cache/nix/fetcher-cache* -cloneRepo=$TEST_ROOT/a/b/gitSubmodulesClone # NB /a/b to make the relative path not work relative to $cloneRepo -git clone $rootRepo $cloneRepo -pathIndirect=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$cloneRepo; rev = \"$rev2\"; submodules = true; }).outPath") -[[ $pathIndirect = $pathWithRelative ]] - -# Test that if the clone has the submodule already, we're not fetching -# it again. -git -C $cloneRepo submodule update --init -rm $TEST_HOME/.cache/nix/fetcher-cache* -rm -rf $subRepo -pathSubmoduleGone=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$cloneRepo; rev = \"$rev2\"; submodules = true; }).outPath") -[[ $pathSubmoduleGone = $pathWithRelative ]] diff --git a/tests/fetchMercurial.sh b/tests/fetchMercurial.sh deleted file mode 100644 index e6f8525c6..000000000 --- a/tests/fetchMercurial.sh +++ /dev/null @@ -1,106 +0,0 @@ -source common.sh - -[[ $(type -p hq) ]] || skipTest "Mercurial not installed" - -clearStore - -# Intentionally not in a canonical form -# See https://github.com/NixOS/nix/issues/6195 -repo=$TEST_ROOT/./hg - -rm -rf $repo ${repo}-tmp $TEST_HOME/.cache/nix - -hg init $repo -echo '[ui]' >> $repo/.hg/hgrc -echo 'username = Foobar ' >> $repo/.hg/hgrc - -# Set ui.tweakdefaults to ensure HGPLAIN is being set. -echo 'tweakdefaults = True' >> $repo/.hg/hgrc - -echo utrecht > $repo/hello -touch $repo/.hgignore -hg add --cwd $repo hello .hgignore -hg commit --cwd $repo -m 'Bla1' -rev1=$(hg log --cwd $repo -r tip --template '{node}') - -echo world > $repo/hello -hg commit --cwd $repo -m 'Bla2' -rev2=$(hg log --cwd $repo -r tip --template '{node}') - -# Fetch an unclean branch. -echo unclean > $repo/hello -path=$(nix eval --impure --raw --expr "(builtins.fetchMercurial file://$repo).outPath") -[[ $(cat $path/hello) = unclean ]] -hg revert --cwd $repo --all - -# Fetch the default branch. -path=$(nix eval --impure --raw --expr "(builtins.fetchMercurial file://$repo).outPath") -[[ $(cat $path/hello) = world ]] - -# In pure eval mode, fetchGit without a revision should fail. -[[ $(nix eval --impure --raw --expr "(builtins.readFile (fetchMercurial file://$repo + \"/hello\"))") = world ]] -(! nix eval --raw --expr "builtins.readFile (fetchMercurial file://$repo + \"/hello\")") - -# Fetch using an explicit revision hash. -path2=$(nix eval --impure --raw --expr "(builtins.fetchMercurial { url = file://$repo; rev = \"$rev2\"; }).outPath") -[[ $path = $path2 ]] - -# In pure eval mode, fetchGit with a revision should succeed. -[[ $(nix eval --raw --expr "builtins.readFile (fetchMercurial { url = file://$repo; rev = \"$rev2\"; } + \"/hello\")") = world ]] - -# Fetch again. This should be cached. -mv $repo ${repo}-tmp -path2=$(nix eval --impure --raw --expr "(builtins.fetchMercurial file://$repo).outPath") -[[ $path = $path2 ]] - -[[ $(nix eval --impure --raw --expr "(builtins.fetchMercurial file://$repo).branch") = default ]] -[[ $(nix eval --impure --expr "(builtins.fetchMercurial file://$repo).revCount") = 1 ]] -[[ $(nix eval --impure --raw --expr "(builtins.fetchMercurial file://$repo).rev") = $rev2 ]] - -# But with TTL 0, it should fail. -(! nix eval --impure --refresh --expr "builtins.fetchMercurial file://$repo") - -# Fetching with a explicit hash should succeed. -path2=$(nix eval --refresh --raw --expr "(builtins.fetchMercurial { url = file://$repo; rev = \"$rev2\"; }).outPath") -[[ $path = $path2 ]] - -path2=$(nix eval --refresh --raw --expr "(builtins.fetchMercurial { url = file://$repo; rev = \"$rev1\"; }).outPath") -[[ $(cat $path2/hello) = utrecht ]] - -mv ${repo}-tmp $repo - -# Using a clean working tree should produce the same result. -path2=$(nix eval --impure --raw --expr "(builtins.fetchMercurial $repo).outPath") -[[ $path = $path2 ]] - -# Using an unclean tree should yield the tracked but uncommitted changes. -mkdir $repo/dir1 $repo/dir2 -echo foo > $repo/dir1/foo -echo bar > $repo/bar -echo bar > $repo/dir2/bar -hg add --cwd $repo dir1/foo -hg rm --cwd $repo hello - -path2=$(nix eval --impure --raw --expr "(builtins.fetchMercurial $repo).outPath") -[ ! -e $path2/hello ] -[ ! -e $path2/bar ] -[ ! -e $path2/dir2/bar ] -[ ! -e $path2/.hg ] -[[ $(cat $path2/dir1/foo) = foo ]] - -[[ $(nix eval --impure --raw --expr "(builtins.fetchMercurial $repo).rev") = 0000000000000000000000000000000000000000 ]] - -# ... unless we're using an explicit ref. -path3=$(nix eval --impure --raw --expr "(builtins.fetchMercurial { url = $repo; rev = \"default\"; }).outPath") -[[ $path = $path3 ]] - -# Committing should not affect the store path. -hg commit --cwd $repo -m 'Bla3' - -path4=$(nix eval --impure --refresh --raw --expr "(builtins.fetchMercurial file://$repo).outPath") -[[ $path2 = $path4 ]] - -echo paris > $repo/hello -# Passing a `name` argument should be reflected in the output path -path5=$(nix eval -vvvvv --impure --refresh --raw --expr "(builtins.fetchMercurial { url = \"file://$repo\"; name = \"foo\"; } ).outPath") -[[ $path5 =~ -foo$ ]] diff --git a/tests/fetchPath.sh b/tests/fetchPath.sh deleted file mode 100644 index 29be38ce2..000000000 --- a/tests/fetchPath.sh +++ /dev/null @@ -1,6 +0,0 @@ -source common.sh - -touch $TEST_ROOT/foo -t 202211111111 -# We only check whether 2022-11-1* **:**:** is the last modified date since -# `lastModified` is transformed into UTC in `builtins.fetchTarball`. -[[ "$(nix eval --impure --raw --expr "(builtins.fetchTree \"path://$TEST_ROOT/foo\").lastModifiedDate")" =~ 2022111.* ]] diff --git a/tests/fetchTree-file.sh b/tests/fetchTree-file.sh deleted file mode 100644 index 6395c133d..000000000 --- a/tests/fetchTree-file.sh +++ /dev/null @@ -1,117 +0,0 @@ -source common.sh - -clearStore - -cd "$TEST_ROOT" - -test_fetch_file () { - echo foo > test_input - - input_hash="$(nix hash path test_input)" - - nix eval --impure --file - < inputs/test_input_file - echo '{ outputs = { self }: { }; }' > inputs/flake.nix - tar cfa test_input.tar.gz inputs - cp test_input.tar.gz test_input_no_ext - input_tarball_hash="$(nix hash path test_input.tar.gz)" - input_directory_hash="$(nix hash path inputs)" - - cat < flake.nix - { - inputs.no_ext_default_no_unpack = { - url = "file://$PWD/test_input_no_ext"; - flake = false; - }; - inputs.no_ext_explicit_unpack = { - url = "tarball+file://$PWD/test_input_no_ext"; - flake = false; - }; - inputs.tarball_default_unpack = { - url = "file://$PWD/test_input.tar.gz"; - flake = false; - }; - inputs.tarball_explicit_no_unpack = { - url = "file+file://$PWD/test_input.tar.gz"; - flake = false; - }; - inputs.flake_no_ext = { - url = "file://$PWD/test_input_no_ext"; - }; - outputs = { ... }: {}; - } -EOF - - nix flake update - nix eval --file - < flake.nix - { - inputs.tarball = { - url = "file://$PWD/test_input.tar.gz"; - flake = false; - }; - outputs = { self, tarball }: { - foo = builtins.readFile "\${tarball}/test_input_file"; - }; - } - nix flake update - - clearStore - "$NIX_DAEMON_PACKAGE/bin/nix" eval .#foo -EOF -} - -test_fetch_file -test_file_flake_input diff --git a/tests/fetchurl.sh b/tests/fetchurl.sh deleted file mode 100644 index 8cd40c09f..000000000 --- a/tests/fetchurl.sh +++ /dev/null @@ -1,80 +0,0 @@ -source common.sh - -clearStore - -# Test fetching a flat file. -hash=$(nix-hash --flat --type sha256 ./fetchurl.sh) - -outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file://$(pwd)/fetchurl.sh --argstr sha256 $hash --no-out-link) - -cmp $outPath fetchurl.sh - -# Do not re-fetch paths already present. -outPath2=$(nix-build -vvvvv --expr 'import ' --argstr url file:///does-not-exist/must-remain-unused/fetchurl.sh --argstr sha256 $hash --no-out-link) -test "$outPath" == "$outPath2" - -# Now using a base-64 hash. -clearStore - -hash=$(nix hash file --type sha512 --base64 ./fetchurl.sh) - -outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file://$(pwd)/fetchurl.sh --argstr sha512 $hash --no-out-link) - -cmp $outPath fetchurl.sh - -# Now using an SRI hash. -clearStore - -hash=$(nix hash file ./fetchurl.sh) - -[[ $hash =~ ^sha256- ]] - -outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file://$(pwd)/fetchurl.sh --argstr hash $hash --no-out-link) - -cmp $outPath fetchurl.sh - -# Test that we can substitute from a different store dir. -clearStore - -other_store=file://$TEST_ROOT/other_store?store=/fnord/store - -hash=$(nix hash file --type sha256 --base16 ./fetchurl.sh) - -storePath=$(nix --store $other_store store add-file ./fetchurl.sh) - -outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file:///no-such-dir/fetchurl.sh --argstr sha256 $hash --no-out-link --substituters $other_store) - -# Test hashed mirrors with an SRI hash. -nix-build -vvvvv --expr 'import ' --argstr url file:///no-such-dir/fetchurl.sh --argstr hash $(nix hash to-sri --type sha256 $hash) \ - --no-out-link --substituters $other_store - -# Test unpacking a NAR. -rm -rf $TEST_ROOT/archive -mkdir -p $TEST_ROOT/archive -cp ./fetchurl.sh $TEST_ROOT/archive -chmod +x $TEST_ROOT/archive/fetchurl.sh -ln -s foo $TEST_ROOT/archive/symlink -nar=$TEST_ROOT/archive.nar -nix-store --dump $TEST_ROOT/archive > $nar - -hash=$(nix-hash --flat --type sha256 $nar) - -outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file://$nar --argstr sha256 $hash \ - --arg unpack true --argstr name xyzzy --no-out-link) - -echo $outPath | grepQuiet 'xyzzy' - -test -x $outPath/fetchurl.sh -test -L $outPath/symlink - -nix-store --delete $outPath - -# Test unpacking a compressed NAR. -narxz=$TEST_ROOT/archive.nar.xz -rm -f $narxz -xz --keep $nar -outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file://$narxz --argstr sha256 $hash \ - --arg unpack true --argstr name xyzzy --no-out-link) - -test -x $outPath/fetchurl.sh -test -L $outPath/symlink diff --git a/tests/filter-source.nix b/tests/filter-source.nix deleted file mode 100644 index 907163639..000000000 --- a/tests/filter-source.nix +++ /dev/null @@ -1,12 +0,0 @@ -with import ./config.nix; - -mkDerivation { - name = "filter"; - builder = builtins.toFile "builder" "ln -s $input $out"; - input = - let filter = path: type: - type != "symlink" - && baseNameOf path != "foo" - && !((import ./lang/lib.nix).hasSuffix ".bak" (baseNameOf path)); - in builtins.filterSource filter ((builtins.getEnv "TEST_ROOT") + "/filterin"); -} diff --git a/tests/filter-source.sh b/tests/filter-source.sh deleted file mode 100644 index ba34d2eac..000000000 --- a/tests/filter-source.sh +++ /dev/null @@ -1,25 +0,0 @@ -source common.sh - -rm -rf $TEST_ROOT/filterin -mkdir $TEST_ROOT/filterin -mkdir $TEST_ROOT/filterin/foo -touch $TEST_ROOT/filterin/foo/bar -touch $TEST_ROOT/filterin/xyzzy -touch $TEST_ROOT/filterin/b -touch $TEST_ROOT/filterin/bak -touch $TEST_ROOT/filterin/bla.c.bak -ln -s xyzzy $TEST_ROOT/filterin/link - -checkFilter() { - test ! -e $1/foo/bar - test -e $1/xyzzy - test -e $1/bak - test ! -e $1/bla.c.bak - test ! -L $1/link -} - -nix-build ./filter-source.nix -o $TEST_ROOT/filterout1 -checkFilter $TEST_ROOT/filterout1 - -nix-build ./path.nix -o $TEST_ROOT/filterout2 -checkFilter $TEST_ROOT/filterout2 diff --git a/tests/fixed.builder1.sh b/tests/fixed.builder1.sh deleted file mode 100644 index c41bb2b9a..000000000 --- a/tests/fixed.builder1.sh +++ /dev/null @@ -1,3 +0,0 @@ -if test "$IMPURE_VAR1" != "foo"; then exit 1; fi -if test "$IMPURE_VAR2" != "bar"; then exit 1; fi -echo "Hello World!" > $out diff --git a/tests/fixed.builder2.sh b/tests/fixed.builder2.sh deleted file mode 100644 index 31ea1579a..000000000 --- a/tests/fixed.builder2.sh +++ /dev/null @@ -1,6 +0,0 @@ -echo dummy: $dummy -if test -n "$dummy"; then sleep 2; fi -mkdir $out -mkdir $out/bla -echo "Hello World!" > $out/foo -ln -s foo $out/bar diff --git a/tests/fixed.nix b/tests/fixed.nix deleted file mode 100644 index babe71504..000000000 --- a/tests/fixed.nix +++ /dev/null @@ -1,58 +0,0 @@ -with import ./config.nix; - -rec { - - f2 = dummy: builder: mode: algo: hash: mkDerivation { - name = "fixed"; - inherit builder; - outputHashMode = mode; - outputHashAlgo = algo; - outputHash = hash; - inherit dummy; - impureEnvVars = ["IMPURE_VAR1" "IMPURE_VAR2"]; - }; - - f = f2 ""; - - good = [ - (f ./fixed.builder1.sh "flat" "md5" "8ddd8be4b179a529afa5f2ffae4b9858") - (f ./fixed.builder1.sh "flat" "sha1" "a0b65939670bc2c010f4d5d6a0b3e4e4590fb92b") - (f ./fixed.builder2.sh "recursive" "md5" "3670af73070fa14077ad74e0f5ea4e42") - (f ./fixed.builder2.sh "recursive" "sha1" "vw46m23bizj4n8afrc0fj19wrp7mj3c0") - ]; - - # Expression to test that `nix-build --check` also throws an error if the hash of - # fixed-output derivation has changed even if the hash exists in the store (in this - # case the hash exists because of `fixed.builder2.sh`, but building a derivation - # with the same hash and a different result must throw an error). - check = [ - (f ./fixed.builder1.sh "recursive" "md5" "3670af73070fa14077ad74e0f5ea4e42") - ]; - - good2 = [ - # Yes, this looks fscked up: builder2 doesn't have that result. - # But Nix sees that an output with the desired hash already - # exists, and will refrain from building it. - (f ./fixed.builder2.sh "flat" "md5" "8ddd8be4b179a529afa5f2ffae4b9858") - ]; - - sameAsAdd = - f ./fixed.builder2.sh "recursive" "sha256" "1ixr6yd3297ciyp9im522dfxpqbkhcw0pylkb2aab915278fqaik"; - - bad = [ - (f ./fixed.builder1.sh "flat" "md5" "0ddd8be4b179a529afa5f2ffae4b9858") - ]; - - reallyBad = [ - # Hash too short, and not base-32 either. - (f ./fixed.builder1.sh "flat" "md5" "ddd8be4b179a529afa5f2ffae4b9858") - ]; - - # Test for building two derivations in parallel that produce the - # same output path because they're fixed-output derivations. - parallelSame = [ - (f2 "foo" ./fixed.builder2.sh "recursive" "md5" "3670af73070fa14077ad74e0f5ea4e42") - (f2 "bar" ./fixed.builder2.sh "recursive" "md5" "3670af73070fa14077ad74e0f5ea4e42") - ]; - -} diff --git a/tests/fixed.sh b/tests/fixed.sh deleted file mode 100644 index f1e1ce420..000000000 --- a/tests/fixed.sh +++ /dev/null @@ -1,58 +0,0 @@ -source common.sh - -clearStore - -path=$(nix-store -q $(nix-instantiate fixed.nix -A good.0)) - -echo 'testing bad...' -nix-build fixed.nix -A bad --no-out-link && fail "should fail" - -# Building with the bad hash should produce the "good" output path as -# a side-effect. -[[ -e $path ]] -nix path-info --json $path | grep fixed:md5:2qk15sxzzjlnpjk9brn7j8ppcd - -echo 'testing good...' -nix-build fixed.nix -A good --no-out-link - -if isDaemonNewer "2.4pre20210927"; then - echo 'testing --check...' - nix-build fixed.nix -A check --check && fail "should fail" -fi - -echo 'testing good2...' -nix-build fixed.nix -A good2 --no-out-link - -echo 'testing reallyBad...' -nix-instantiate fixed.nix -A reallyBad && fail "should fail" - -# While we're at it, check attribute selection a bit more. -echo 'testing attribute selection...' -test $(nix-instantiate fixed.nix -A good.1 | wc -l) = 1 - -# Test parallel builds of derivations that produce the same output. -# Only one should run at the same time. -echo 'testing parallelSame...' -clearStore -nix-build fixed.nix -A parallelSame --no-out-link -j2 - -# Fixed-output derivations with a recursive SHA-256 hash should -# produce the same path as "nix-store --add". -echo 'testing sameAsAdd...' -out=$(nix-build fixed.nix -A sameAsAdd --no-out-link) - -# This is what fixed.builder2 produces... -rm -rf $TEST_ROOT/fixed -mkdir $TEST_ROOT/fixed -mkdir $TEST_ROOT/fixed/bla -echo "Hello World!" > $TEST_ROOT/fixed/foo -ln -s foo $TEST_ROOT/fixed/bar - -out2=$(nix-store --add $TEST_ROOT/fixed) -[ "$out" = "$out2" ] - -out3=$(nix-store --add-fixed --recursive sha256 $TEST_ROOT/fixed) -[ "$out" = "$out3" ] - -out4=$(nix-store --print-fixed-path --recursive sha256 "1ixr6yd3297ciyp9im522dfxpqbkhcw0pylkb2aab915278fqaik" fixed) -[ "$out" = "$out4" ] diff --git a/tests/flakes/absolute-paths.sh b/tests/flakes/absolute-paths.sh deleted file mode 100644 index e7bfba12d..000000000 --- a/tests/flakes/absolute-paths.sh +++ /dev/null @@ -1,17 +0,0 @@ -source ./common.sh - -requireGit - -flake1Dir=$TEST_ROOT/flake1 -flake2Dir=$TEST_ROOT/flake2 - -createGitRepo $flake1Dir -cat > $flake1Dir/flake.nix < $flake1Dir/flake.nix < $flake1Dir/foo - -nix build --json --out-link $TEST_ROOT/result $flake1Dir#a1 -[[ -e $TEST_ROOT/result/simple.nix ]] - -nix build --json --out-link $TEST_ROOT/result $flake1Dir#a2 -[[ $(cat $TEST_ROOT/result) = bar ]] - -nix build --json --out-link $TEST_ROOT/result $flake1Dir#a3 - -nix build --json --out-link $TEST_ROOT/result $flake1Dir#a4 - -nix build --json --out-link $TEST_ROOT/result $flake1Dir#a6 -[[ -e $TEST_ROOT/result/simple.nix ]] - -nix build --impure --json --out-link $TEST_ROOT/result $flake1Dir#a8 -diff common.sh $TEST_ROOT/result - -expectStderr 1 nix build --impure --json --out-link $TEST_ROOT/result $flake1Dir#a9 \ - | grepQuiet "has 0 entries in its context. It should only have exactly one entry" - -nix build --json --out-link $TEST_ROOT/result $flake1Dir#a10 -[[ $(readlink -e $TEST_ROOT/result) = *simple.drv ]] - -expectStderr 1 nix build --json --out-link $TEST_ROOT/result $flake1Dir#a11 \ - | grepQuiet "has a context which refers to a complete source and binary closure" - -nix build --json --out-link $TEST_ROOT/result $flake1Dir#a12 -[[ -e $TEST_ROOT/result/hello ]] - -expectStderr 1 nix build --impure --json --out-link $TEST_ROOT/result $flake1Dir#a13 \ - | grepQuiet "has 2 entries in its context. It should only have exactly one entry" diff --git a/tests/flakes/bundle.sh b/tests/flakes/bundle.sh deleted file mode 100644 index 67bbb05ac..000000000 --- a/tests/flakes/bundle.sh +++ /dev/null @@ -1,32 +0,0 @@ -source common.sh - -cp ../simple.nix ../simple.builder.sh ../config.nix $TEST_HOME - -cd $TEST_HOME - -cat < flake.nix -{ - outputs = {self}: { - bundlers.$system = rec { - simple = drv: - if drv?type && drv.type == "derivation" - then drv - else self.packages.$system.default; - default = simple; - }; - packages.$system.default = import ./simple.nix; - apps.$system.default = { - type = "app"; - program = "\${import ./simple.nix}/hello"; - }; - }; -} -EOF - -nix build .# -nix bundle --bundler .# .# -nix bundle --bundler .#bundlers.$system.default .#packages.$system.default -nix bundle --bundler .#bundlers.$system.simple .#packages.$system.default - -nix bundle --bundler .#bundlers.$system.default .#apps.$system.default -nix bundle --bundler .#bundlers.$system.simple .#apps.$system.default diff --git a/tests/flakes/check.sh b/tests/flakes/check.sh deleted file mode 100644 index 0433e5335..000000000 --- a/tests/flakes/check.sh +++ /dev/null @@ -1,91 +0,0 @@ -source common.sh - -flakeDir=$TEST_ROOT/flake3 -mkdir -p $flakeDir - -cat > $flakeDir/flake.nix < $flakeDir/flake.nix < $flakeDir/flake.nix <&1 && fail "nix flake check --all-systems should have failed" || true) -echo "$checkRes" | grepQuiet "error: overlay is not a function, but a set instead" - -cat > $flakeDir/flake.nix < $flakeDir/flake.nix < $flakeDir/flake.nix < $flakeDir/flake.nix <&1 && fail "nix flake check --all-systems should have failed" || true) -echo "$checkRes" | grepQuiet "packages.system-1.default" -echo "$checkRes" | grepQuiet "packages.system-2.default" diff --git a/tests/flakes/circular.sh b/tests/flakes/circular.sh deleted file mode 100644 index 09cd02edf..000000000 --- a/tests/flakes/circular.sh +++ /dev/null @@ -1,49 +0,0 @@ -# Test circular flake dependencies. -source ./common.sh - -requireGit - -flakeA=$TEST_ROOT/flakeA -flakeB=$TEST_ROOT/flakeB - -createGitRepo $flakeA -createGitRepo $flakeB - -cat > $flakeA/flake.nix < $flakeB/flake.nix < $flakeDir/flake.nix < $flakeDir/flake.nix < $flakeDir/flake.nix < echoing-post-hook.sh -#!/bin/sh - -echo "ThePostHookRan as \$0" > $PWD/post-hook-ran -EOF -chmod +x echoing-post-hook.sh - -cat < flake.nix -{ - nixConfig.post-build-hook = ./echoing-post-hook.sh; - nixConfig.allow-dirty = false; # See #5621 - - outputs = a: { - packages.$system.default = import ./simple.nix; - }; -} -EOF - -# Without --accept-flake-config, the post hook should not run. -nix build < /dev/null -(! [[ -f post-hook-ran ]]) -clearStore - -nix build --accept-flake-config -test -f post-hook-ran || fail "The post hook should have ran" - -# Make sure that the path to the post hook doesn’t change if we change -# something in the flake. -# Otherwise the user would have to re-validate the setting each time. -mv post-hook-ran previous-post-hook-run -echo "# Dummy comment" >> flake.nix -clearStore -nix build --accept-flake-config -diff -q post-hook-ran previous-post-hook-run || \ - fail "Both post hook runs should report the same filename" diff --git a/tests/flakes/flake-in-submodule.sh b/tests/flakes/flake-in-submodule.sh deleted file mode 100644 index 21a4b52de..000000000 --- a/tests/flakes/flake-in-submodule.sh +++ /dev/null @@ -1,52 +0,0 @@ -source common.sh - -# Tests that: -# - flake.nix may reside inside of a git submodule -# - the flake can access content outside of the submodule -# -# rootRepo -# ├── root.nix -# └── submodule -# ├── flake.nix -# └── sub.nix - - -requireGit - -clearStore - -# Submodules can't be fetched locally by default. -# See fetchGitSubmodules.sh -export XDG_CONFIG_HOME=$TEST_HOME/.config -git config --global protocol.file.allow always - - -rootRepo=$TEST_ROOT/rootRepo -subRepo=$TEST_ROOT/submodule - - -createGitRepo $subRepo -cat > $subRepo/flake.nix < $subRepo/sub.nix -git -C $subRepo add flake.nix sub.nix -git -C $subRepo commit -m Initial - -createGitRepo $rootRepo - -git -C $rootRepo submodule init -git -C $rootRepo submodule add $subRepo submodule -echo '"expression in root repo"' > $rootRepo/root.nix -git -C $rootRepo add root.nix -git -C $rootRepo commit -m "Add root.nix" - -# Flake can live inside a submodule and can be accessed via ?dir=submodule -[[ $(nix eval --json git+file://$rootRepo\?submodules=1\&dir=submodule#sub ) = '"expression in submodule"' ]] -# The flake can access content outside of the submodule -[[ $(nix eval --json git+file://$rootRepo\?submodules=1\&dir=submodule#root ) = '"expression in root repo"' ]] diff --git a/tests/flakes/flakes.sh b/tests/flakes/flakes.sh deleted file mode 100644 index 128f759ea..000000000 --- a/tests/flakes/flakes.sh +++ /dev/null @@ -1,511 +0,0 @@ -source ./common.sh - -requireGit - -clearStore -rm -rf $TEST_HOME/.cache $TEST_HOME/.config - -flake1Dir=$TEST_ROOT/flake1 -flake2Dir=$TEST_ROOT/flake2 -flake3Dir=$TEST_ROOT/flake3 -flake5Dir=$TEST_ROOT/flake5 -flake7Dir=$TEST_ROOT/flake7 -nonFlakeDir=$TEST_ROOT/nonFlake -badFlakeDir=$TEST_ROOT/badFlake -flakeGitBare=$TEST_ROOT/flakeGitBare - -for repo in $flake1Dir $flake2Dir $flake3Dir $flake7Dir $nonFlakeDir; do - # Give one repo a non-main initial branch. - extraArgs= - if [[ $repo == $flake2Dir ]]; then - extraArgs="--initial-branch=main" - fi - - createGitRepo "$repo" "$extraArgs" -done - -createSimpleGitFlake $flake1Dir - -cat > $flake2Dir/flake.nix < $flake3Dir/flake.nix < $flake3Dir/default.nix < $nonFlakeDir/README.md < $flake1Dir/foo -git -C $flake1Dir add $flake1Dir/foo -[[ $(nix flake metadata flake1 --json --refresh | jq -r .dirtyRevision) == "$hash1-dirty" ]] - -echo -n '# foo' >> $flake1Dir/flake.nix -flake1OriginalCommit=$(git -C $flake1Dir rev-parse HEAD) -git -C $flake1Dir commit -a -m 'Foo' -flake1NewCommit=$(git -C $flake1Dir rev-parse HEAD) -hash2=$(nix flake metadata flake1 --json --refresh | jq -r .revision) -[[ $(nix flake metadata flake1 --json --refresh | jq -r .dirtyRevision) == "null" ]] -[[ $hash1 != $hash2 ]] - -# Test 'nix build' on a flake. -nix build -o $TEST_ROOT/result flake1#foo -[[ -e $TEST_ROOT/result/hello ]] - -# Test packages.default. -nix build -o $TEST_ROOT/result flake1 -[[ -e $TEST_ROOT/result/hello ]] - -nix build -o $TEST_ROOT/result $flake1Dir -nix build -o $TEST_ROOT/result git+file://$flake1Dir - -# Check that store symlinks inside a flake are not interpreted as flakes. -nix build -o $flake1Dir/result git+file://$flake1Dir -nix path-info $flake1Dir/result - -# 'getFlake' on an unlocked flakeref should fail in pure mode, but -# succeed in impure mode. -(! nix build -o $TEST_ROOT/result --expr "(builtins.getFlake \"$flake1Dir\").packages.$system.default") -nix build -o $TEST_ROOT/result --expr "(builtins.getFlake \"$flake1Dir\").packages.$system.default" --impure - -# 'getFlake' on a locked flakeref should succeed even in pure mode. -nix build -o $TEST_ROOT/result --expr "(builtins.getFlake \"git+file://$flake1Dir?rev=$hash2\").packages.$system.default" - -# Building a flake with an unlocked dependency should fail in pure mode. -(! nix build -o $TEST_ROOT/result flake2#bar --no-registries) -(! nix build -o $TEST_ROOT/result flake2#bar --no-use-registries) -(! nix eval --expr "builtins.getFlake \"$flake2Dir\"") - -# But should succeed in impure mode. -(! nix build -o $TEST_ROOT/result flake2#bar --impure) -nix build -o $TEST_ROOT/result flake2#bar --impure --no-write-lock-file -nix eval --expr "builtins.getFlake \"$flake2Dir\"" --impure - -# Building a local flake with an unlocked dependency should fail with --no-update-lock-file. -expect 1 nix build -o $TEST_ROOT/result $flake2Dir#bar --no-update-lock-file 2>&1 | grep 'requires lock file changes' - -# But it should succeed without that flag. -nix build -o $TEST_ROOT/result $flake2Dir#bar --no-write-lock-file -expect 1 nix build -o $TEST_ROOT/result $flake2Dir#bar --no-update-lock-file 2>&1 | grep 'requires lock file changes' -nix build -o $TEST_ROOT/result $flake2Dir#bar --commit-lock-file -[[ -e $flake2Dir/flake.lock ]] -[[ -z $(git -C $flake2Dir diff main || echo failed) ]] - -# Rerunning the build should not change the lockfile. -nix build -o $TEST_ROOT/result $flake2Dir#bar -[[ -z $(git -C $flake2Dir diff main || echo failed) ]] - -# Building with a lockfile should not require a fetch of the registry. -nix build -o $TEST_ROOT/result --flake-registry file:///no-registry.json $flake2Dir#bar --refresh -nix build -o $TEST_ROOT/result --no-registries $flake2Dir#bar --refresh -nix build -o $TEST_ROOT/result --no-use-registries $flake2Dir#bar --refresh - -# Updating the flake should not change the lockfile. -nix flake lock $flake2Dir -[[ -z $(git -C $flake2Dir diff main || echo failed) ]] - -# Now we should be able to build the flake in pure mode. -nix build -o $TEST_ROOT/result flake2#bar - -# Or without a registry. -nix build -o $TEST_ROOT/result --no-registries git+file://$flake2Dir#bar --refresh -nix build -o $TEST_ROOT/result --no-use-registries git+file://$flake2Dir#bar --refresh - -# Test whether indirect dependencies work. -nix build -o $TEST_ROOT/result $flake3Dir#xyzzy -git -C $flake3Dir add flake.lock - -# Add dependency to flake3. -rm $flake3Dir/flake.nix - -cat > $flake3Dir/flake.nix < $flake3Dir/flake.nix < \$out - [[ \$(cat \${inputs.nonFlake}/README.md) = \$(cat \${inputs.nonFlakeFile}) ]] - [[ \${inputs.nonFlakeFile} = \${inputs.nonFlakeFile2} ]] - ''; - }; - }; -} -EOF - -cp ../config.nix $flake3Dir - -git -C $flake3Dir add flake.nix config.nix -git -C $flake3Dir commit -m 'Add nonFlakeInputs' - -# Check whether `nix build` works with a lockfile which is missing a -# nonFlakeInputs. -nix build -o $TEST_ROOT/result $flake3Dir#sth --commit-lock-file - -nix build -o $TEST_ROOT/result flake3#fnord -[[ $(cat $TEST_ROOT/result) = FNORD ]] - -# Check whether flake input fetching is lazy: flake3#sth does not -# depend on flake2, so this shouldn't fail. -rm -rf $TEST_HOME/.cache -clearStore -mv $flake2Dir $flake2Dir.tmp -mv $nonFlakeDir $nonFlakeDir.tmp -nix build -o $TEST_ROOT/result flake3#sth -(! nix build -o $TEST_ROOT/result flake3#xyzzy) -(! nix build -o $TEST_ROOT/result flake3#fnord) -mv $flake2Dir.tmp $flake2Dir -mv $nonFlakeDir.tmp $nonFlakeDir -nix build -o $TEST_ROOT/result flake3#xyzzy flake3#fnord - -# Test doing multiple `lookupFlake`s -nix build -o $TEST_ROOT/result flake4#xyzzy - -# Test 'nix flake update' and --override-flake. -nix flake lock $flake3Dir -[[ -z $(git -C $flake3Dir diff master || echo failed) ]] - -nix flake update $flake3Dir --override-flake flake2 nixpkgs -[[ ! -z $(git -C $flake3Dir diff master || echo failed) ]] - -# Make branch "removeXyzzy" where flake3 doesn't have xyzzy anymore -git -C $flake3Dir checkout -b removeXyzzy -rm $flake3Dir/flake.nix - -cat > $flake3Dir/flake.nix < \$out - ''; - }; - }; -} -EOF -nix flake lock $flake3Dir -git -C $flake3Dir add flake.nix flake.lock -git -C $flake3Dir commit -m 'Remove packages.xyzzy' -git -C $flake3Dir checkout master - -# Test whether fuzzy-matching works for registry entries. -(! nix build -o $TEST_ROOT/result flake4/removeXyzzy#xyzzy) -nix build -o $TEST_ROOT/result flake4/removeXyzzy#sth - -# Testing the nix CLI -nix registry add flake1 flake3 -[[ $(nix registry list | wc -l) == 6 ]] -nix registry pin flake1 -[[ $(nix registry list | wc -l) == 6 ]] -nix registry pin flake1 flake3 -[[ $(nix registry list | wc -l) == 6 ]] -nix registry remove flake1 -[[ $(nix registry list | wc -l) == 5 ]] - -# Test 'nix registry list' with a disabled global registry. -nix registry add user-flake1 git+file://$flake1Dir -nix registry add user-flake2 git+file://$flake2Dir -[[ $(nix --flake-registry "" registry list | wc -l) == 2 ]] -nix --flake-registry "" registry list | grepQuietInverse '^global' # nothing in global registry -nix --flake-registry "" registry list | grepQuiet '^user' -nix registry remove user-flake1 -nix registry remove user-flake2 -[[ $(nix registry list | wc -l) == 5 ]] - -# Test 'nix flake clone'. -rm -rf $TEST_ROOT/flake1-v2 -nix flake clone flake1 --dest $TEST_ROOT/flake1-v2 -[ -e $TEST_ROOT/flake1-v2/flake.nix ] - -# Test 'follows' inputs. -cat > $flake3Dir/flake.nix < $flake3Dir/flake.nix < $flake3Dir/flake.nix < $flake3Dir/flake.nix < $flake3Dir/flake.nix < $badFlakeDir/flake.nix -nix store delete $(nix store add-path $badFlakeDir) - -[[ $(nix path-info $(nix store add-path $flake1Dir)) =~ flake1 ]] -[[ $(nix path-info path:$(nix store add-path $flake1Dir)) =~ simple ]] - -# Test fetching flakerefs in the legacy CLI. -[[ $(nix-instantiate --eval flake:flake3 -A x) = 123 ]] -[[ $(nix-instantiate --eval flake:git+file://$flake3Dir -A x) = 123 ]] -[[ $(nix-instantiate -I flake3=flake:flake3 --eval '' -A x) = 123 ]] -[[ $(NIX_PATH=flake3=flake:flake3 nix-instantiate --eval '' -A x) = 123 ]] - -# Test alternate lockfile paths. -nix flake lock $flake2Dir --output-lock-file $TEST_ROOT/flake2.lock -cmp $flake2Dir/flake.lock $TEST_ROOT/flake2.lock >/dev/null # lockfiles should be identical, since we're referencing flake2's original one - -nix flake lock $flake2Dir --output-lock-file $TEST_ROOT/flake2-overridden.lock --override-input flake1 git+file://$flake1Dir?rev=$flake1OriginalCommit -expectStderr 1 cmp $flake2Dir/flake.lock $TEST_ROOT/flake2-overridden.lock -nix flake metadata $flake2Dir --reference-lock-file $TEST_ROOT/flake2-overridden.lock | grepQuiet $flake1OriginalCommit - -# reference-lock-file can only be used if allow-dirty is set. -expectStderr 1 nix flake metadata $flake2Dir --no-allow-dirty --reference-lock-file $TEST_ROOT/flake2-overridden.lock diff --git a/tests/flakes/follow-paths.sh b/tests/flakes/follow-paths.sh deleted file mode 100644 index dc97027ac..000000000 --- a/tests/flakes/follow-paths.sh +++ /dev/null @@ -1,232 +0,0 @@ -source ./common.sh - -requireGit - -flakeFollowsA=$TEST_ROOT/follows/flakeA -flakeFollowsB=$TEST_ROOT/follows/flakeA/flakeB -flakeFollowsC=$TEST_ROOT/follows/flakeA/flakeB/flakeC -flakeFollowsD=$TEST_ROOT/follows/flakeA/flakeD -flakeFollowsE=$TEST_ROOT/follows/flakeA/flakeE - -# Test following path flakerefs. -createGitRepo $flakeFollowsA -mkdir -p $flakeFollowsB -mkdir -p $flakeFollowsC -mkdir -p $flakeFollowsD -mkdir -p $flakeFollowsE - -cat > $flakeFollowsA/flake.nix < $flakeFollowsB/flake.nix < $flakeFollowsC/flake.nix < $flakeFollowsD/flake.nix < $flakeFollowsE/flake.nix < $flakeFollowsA/flake.nix < $flakeFollowsA/flake.nix <&1 | grep 'points outside' - -# Non-existant follows should print a warning. -cat >$flakeFollowsA/flake.nix <&1 | grep "warning: input 'B' has an override for a non-existent input 'invalid'" -nix flake lock "$flakeFollowsA" 2>&1 | grep "warning: input 'B' has an override for a non-existent input 'invalid2'" - -# Now test follow path overloading -# This tests a lockfile checking regression https://github.com/NixOS/nix/pull/8819 -# -# We construct the following graph, where p->q means p has input q. -# A double edge means that the edge gets overridden using `follows`. -# -# A -# / \ -# / \ -# v v -# B ==> C --- follows declared in A -# \\ / -# \\/ --- follows declared in B -# v -# D -# -# The message was -# error: input 'B/D' follows a non-existent input 'B/C/D' -# -# Note that for `B` to resolve its follow for `D`, it needs `C/D`, for which it needs to resolve the follow on `C` first. -flakeFollowsOverloadA="$TEST_ROOT/follows/overload/flakeA" -flakeFollowsOverloadB="$TEST_ROOT/follows/overload/flakeA/flakeB" -flakeFollowsOverloadC="$TEST_ROOT/follows/overload/flakeA/flakeB/flakeC" -flakeFollowsOverloadD="$TEST_ROOT/follows/overload/flakeA/flakeB/flakeC/flakeD" - -# Test following path flakerefs. -createGitRepo "$flakeFollowsOverloadA" -mkdir -p "$flakeFollowsOverloadB" -mkdir -p "$flakeFollowsOverloadC" -mkdir -p "$flakeFollowsOverloadD" - -cat > "$flakeFollowsOverloadD/flake.nix" < "$flakeFollowsOverloadC/flake.nix" < "$flakeFollowsOverloadB/flake.nix" < "$flakeFollowsOverloadA/flake.nix" < $templatesDir/flake.nix < $templatesDir/trivial/flake.nix < $templatesDir/trivial/a -echo b > $templatesDir/trivial/b - -git -C $templatesDir add flake.nix trivial/ -git -C $templatesDir commit -m 'Initial' - -nix flake check templates -nix flake show templates -nix flake show templates --json | jq - -createGitRepo $flakeDir -(cd $flakeDir && nix flake init) -(cd $flakeDir && nix flake init) # check idempotence -git -C $flakeDir add flake.nix -nix flake check $flakeDir -nix flake show $flakeDir -nix flake show $flakeDir --json | jq -git -C $flakeDir commit -a -m 'Initial' - -# Test 'nix flake init' with benign conflicts -createGitRepo "$flakeDir" -echo a > $flakeDir/a -(cd $flakeDir && nix flake init) # check idempotence - -# Test 'nix flake init' with conflicts -createGitRepo "$flakeDir" -echo b > $flakeDir/a -pushd $flakeDir -(! nix flake init) |& grep "refusing to overwrite existing file '$flakeDir/a'" -popd -git -C $flakeDir commit -a -m 'Changed' - -# Test 'nix flake new'. -rm -rf $flakeDir -nix flake new -t templates#trivial $flakeDir -nix flake new -t templates#trivial $flakeDir # check idempotence -nix flake check $flakeDir diff --git a/tests/flakes/inputs.sh b/tests/flakes/inputs.sh deleted file mode 100644 index 80620488a..000000000 --- a/tests/flakes/inputs.sh +++ /dev/null @@ -1,80 +0,0 @@ -source ./common.sh - -requireGit - - -test_subdir_self_path() { - baseDir=$TEST_ROOT/$RANDOM - flakeDir=$baseDir/b-low - mkdir -p $flakeDir - writeSimpleFlake $baseDir - writeSimpleFlake $flakeDir - - echo all good > $flakeDir/message - cat > $flakeDir/flake.nix < $flakeDir/message - cat > $flakeDir/flake.nix < $clientDir/flake.nix < flake.nix -{ - outputs = {self}: { - packages.$system.pkgAsPkg = (import ./shell-hello.nix).hello; - packages.$system.appAsApp = self.packages.$system.appAsApp; - - apps.$system.pkgAsApp = self.packages.$system.pkgAsPkg; - apps.$system.appAsApp = { - type = "app"; - program = "\${(import ./shell-hello.nix).hello}/bin/hello"; - }; - }; -} -EOF -nix run --no-write-lock-file .#appAsApp -nix run --no-write-lock-file .#pkgAsPkg - -! nix run --no-write-lock-file .#pkgAsApp || fail "'nix run' shouldn’t accept an 'app' defined under 'packages'" -! nix run --no-write-lock-file .#appAsPkg || fail "elements of 'apps' should be of type 'app'" - -clearStore - diff --git a/tests/flakes/search-root.sh b/tests/flakes/search-root.sh deleted file mode 100644 index d8586dc8a..000000000 --- a/tests/flakes/search-root.sh +++ /dev/null @@ -1,50 +0,0 @@ -source common.sh - -clearStore - -writeSimpleFlake $TEST_HOME -cd $TEST_HOME -mkdir -p foo/subdir - -echo '{ outputs = _: {}; }' > foo/flake.nix -cat < flake.nix -{ - inputs.foo.url = "$PWD/foo"; - outputs = a: { - packages.$system = rec { - test = import ./simple.nix; - default = test; - }; - }; -} -EOF -mkdir subdir -pushd subdir - -success=("" . .# .#test ../subdir ../subdir#test "$PWD") -failure=("path:$PWD") - -for i in "${success[@]}"; do - nix build $i || fail "flake should be found by searching up directories" -done - -for i in "${failure[@]}"; do - ! nix build $i || fail "flake should not search up directories when using 'path:'" -done - -popd - -nix build --override-input foo . || fail "flake should search up directories when not an installable" - -sed "s,$PWD/foo,$PWD/foo/subdir,g" -i flake.nix -! nix build || fail "flake should not search upwards when part of inputs" - -if [[ -n $(type -p git) ]]; then - pushd subdir - git init - for i in "${success[@]}" "${failure[@]}"; do - ! nix build $i || fail "flake should not search past a git repository" - done - rm -rf .git - popd -fi diff --git a/tests/flakes/show.sh b/tests/flakes/show.sh deleted file mode 100644 index a3d300552..000000000 --- a/tests/flakes/show.sh +++ /dev/null @@ -1,87 +0,0 @@ -source ./common.sh - -flakeDir=$TEST_ROOT/flake -mkdir -p "$flakeDir" - -writeSimpleFlake "$flakeDir" -cd "$flakeDir" - - -# By default: Only show the packages content for the current system and no -# legacyPackages at all -nix flake show --json > show-output.json -nix eval --impure --expr ' -let show_output = builtins.fromJSON (builtins.readFile ./show-output.json); -in -assert show_output.packages.someOtherSystem.default == {}; -assert show_output.packages.${builtins.currentSystem}.default.name == "simple"; -assert show_output.legacyPackages.${builtins.currentSystem} == {}; -true -' - -# With `--all-systems`, show the packages for all systems -nix flake show --json --all-systems > show-output.json -nix eval --impure --expr ' -let show_output = builtins.fromJSON (builtins.readFile ./show-output.json); -in -assert show_output.packages.someOtherSystem.default.name == "simple"; -assert show_output.legacyPackages.${builtins.currentSystem} == {}; -true -' - -# With `--legacy`, show the legacy packages -nix flake show --json --legacy > show-output.json -nix eval --impure --expr ' -let show_output = builtins.fromJSON (builtins.readFile ./show-output.json); -in -assert show_output.legacyPackages.${builtins.currentSystem}.hello.name == "simple"; -true -' - -# Test that attributes are only reported when they have actual content -cat >flake.nix < show-output.json -nix eval --impure --expr ' -let show_output = builtins.fromJSON (builtins.readFile ./show-output.json); -in -assert show_output == { }; -true -' - -# Test that attributes with errors are handled correctly. -# nixpkgs.legacyPackages is a particularly prominent instance of this. -cat >flake.nix < show-output.json -nix eval --impure --expr ' -let show_output = builtins.fromJSON (builtins.readFile ./show-output.json); -in -assert show_output.legacyPackages.${builtins.currentSystem}.AAAAAASomeThingsFailToEvaluate == { }; -assert show_output.legacyPackages.${builtins.currentSystem}.simple.name == "simple"; -true -' diff --git a/tests/flakes/unlocked-override.sh b/tests/flakes/unlocked-override.sh deleted file mode 100644 index 8abc8b7d3..000000000 --- a/tests/flakes/unlocked-override.sh +++ /dev/null @@ -1,30 +0,0 @@ -source ./common.sh - -requireGit - -flake1Dir=$TEST_ROOT/flake1 -flake2Dir=$TEST_ROOT/flake2 - -createGitRepo $flake1Dir -cat > $flake1Dir/flake.nix < $flake1Dir/x.nix -git -C $flake1Dir add flake.nix x.nix -git -C $flake1Dir commit -m Initial - -createGitRepo $flake2Dir -cat > $flake2Dir/flake.nix < $flake1Dir/x.nix - -[[ $(nix eval --json $flake2Dir#x --override-input flake1 $TEST_ROOT/flake1) = 456 ]] diff --git a/tests/fmt.sh b/tests/fmt.sh deleted file mode 100644 index 3c1bd9989..000000000 --- a/tests/fmt.sh +++ /dev/null @@ -1,33 +0,0 @@ -source common.sh - -clearStore -rm -rf $TEST_HOME/.cache $TEST_HOME/.config $TEST_HOME/.local - -cp ./simple.nix ./simple.builder.sh ./fmt.simple.sh ./config.nix $TEST_HOME - -cd $TEST_HOME - -nix fmt --help | grep "Format" - -cat << EOF > flake.nix -{ - outputs = _: { - formatter.$system = - with import ./config.nix; - mkDerivation { - name = "formatter"; - buildCommand = '' - mkdir -p \$out/bin - echo "#! ${shell}" > \$out/bin/formatter - cat \${./fmt.simple.sh} >> \$out/bin/formatter - chmod +x \$out/bin/formatter - ''; - }; - }; -} -EOF -nix fmt ./file ./folder | grep 'Formatting: ./file ./folder' -nix flake check -nix flake show | grep -P "package 'formatter'" - -clearStore diff --git a/tests/fmt.simple.sh b/tests/fmt.simple.sh deleted file mode 100755 index 4c8c67ebb..000000000 --- a/tests/fmt.simple.sh +++ /dev/null @@ -1 +0,0 @@ -echo Formatting: "${@}" diff --git a/tests/function-trace.sh b/tests/function-trace.sh deleted file mode 100755 index bd804bf18..000000000 --- a/tests/function-trace.sh +++ /dev/null @@ -1,67 +0,0 @@ -source common.sh - -set +x - -expect_trace() { - expr="$1" - expect="$2" - actual=$( - nix-instantiate \ - --trace-function-calls \ - --expr "$expr" 2>&1 \ - | grep "function-trace" \ - | sed -e 's/ [0-9]*$//' \ - || true - ) - - echo -n "Tracing expression '$expr'" - msg=$(diff -swB \ - <(echo "$expect") \ - <(echo "$actual") - ) && result=0 || result=$? - if [ $result -eq 0 ]; then - echo " ok." - else - echo " failed. difference:" - echo "$msg" - return $result - fi -} - -# failure inside a tryEval -expect_trace 'builtins.tryEval (throw "example")' " -function-trace entered «string»:1:1 at -function-trace entered «string»:1:19 at -function-trace exited «string»:1:19 at -function-trace exited «string»:1:1 at -" - -# Missing argument to a formal function -expect_trace '({ x }: x) { }' " -function-trace entered «string»:1:1 at -function-trace exited «string»:1:1 at -" - -# Too many arguments to a formal function -expect_trace '({ x }: x) { x = "x"; y = "y"; }' " -function-trace entered «string»:1:1 at -function-trace exited «string»:1:1 at -" - -# Not enough arguments to a lambda -expect_trace '(x: y: x + y) 1' " -function-trace entered «string»:1:1 at -function-trace exited «string»:1:1 at -" - -# Too many arguments to a lambda -expect_trace '(x: x) 1 2' " -function-trace entered «string»:1:1 at -function-trace exited «string»:1:1 at -" - -# Not a function -expect_trace '1 2' " -function-trace entered «string»:1:1 at -function-trace exited «string»:1:1 at -" diff --git a/tests/functional/add.sh b/tests/functional/add.sh new file mode 100644 index 000000000..5c3eed793 --- /dev/null +++ b/tests/functional/add.sh @@ -0,0 +1,28 @@ +source common.sh + +path1=$(nix-store --add ./dummy) +echo $path1 + +path2=$(nix-store --add-fixed sha256 --recursive ./dummy) +echo $path2 + +if test "$path1" != "$path2"; then + echo "nix-store --add and --add-fixed mismatch" + exit 1 +fi + +path3=$(nix-store --add-fixed sha256 ./dummy) +echo $path3 +test "$path1" != "$path3" || exit 1 + +path4=$(nix-store --add-fixed sha1 --recursive ./dummy) +echo $path4 +test "$path1" != "$path4" || exit 1 + +hash1=$(nix-store -q --hash $path1) +echo $hash1 + +hash2=$(nix-hash --type sha256 --base32 ./dummy) +echo $hash2 + +test "$hash1" = "sha256:$hash2" diff --git a/tests/functional/bad.tar.xz b/tests/functional/bad.tar.xz new file mode 100644 index 000000000..250a5ad1a Binary files /dev/null and b/tests/functional/bad.tar.xz differ diff --git a/tests/functional/bash-profile.sh b/tests/functional/bash-profile.sh new file mode 100644 index 000000000..3faeaaba1 --- /dev/null +++ b/tests/functional/bash-profile.sh @@ -0,0 +1,9 @@ +source common.sh + +sed -e "s|@localstatedir@|$TEST_ROOT/profile-var|g" -e "s|@coreutils@|$coreutils|g" < ../../scripts/nix-profile.sh.in > $TEST_ROOT/nix-profile.sh + +user=$(whoami) +rm -rf $TEST_HOME $TEST_ROOT/profile-var +mkdir -p $TEST_HOME +USER=$user $SHELL -e -c ". $TEST_ROOT/nix-profile.sh; set" +USER=$user $SHELL -e -c ". $TEST_ROOT/nix-profile.sh" # test idempotency diff --git a/tests/functional/big-derivation-attr.nix b/tests/functional/big-derivation-attr.nix new file mode 100644 index 000000000..35c1187f6 --- /dev/null +++ b/tests/functional/big-derivation-attr.nix @@ -0,0 +1,13 @@ +let + sixteenBytes = "0123456789abcdef"; + times16 = s: builtins.concatStringsSep "" [s s s s s s s s s s s s s s s s]; + exp = n: x: if n == 1 then x else times16 (exp (n - 1) x); + sixteenMegabyte = exp 6 sixteenBytes; +in +assert builtins.stringLength sixteenMegabyte == 16777216; +derivation { + name = "big-derivation-attr"; + builder = "/x"; + system = "y"; + bigAttr = sixteenMegabyte; +} diff --git a/tests/functional/binary-cache-build-remote.sh b/tests/functional/binary-cache-build-remote.sh new file mode 100644 index 000000000..81cd21a4a --- /dev/null +++ b/tests/functional/binary-cache-build-remote.sh @@ -0,0 +1,16 @@ +source common.sh + +clearStore +clearCacheCache + +# Fails without remote builders +(! nix-build --store "file://$cacheDir" dependencies.nix) + +# Succeeds with default store as build remote. +outPath=$(nix-build --store "file://$cacheDir" --builders 'auto - - 1 1' -j0 dependencies.nix) + +# Test that the path exactly exists in the destination store. +nix path-info --store "file://$cacheDir" $outPath + +# Succeeds without any build capability because no-op +nix-build --store "file://$cacheDir" -j0 dependencies.nix diff --git a/tests/functional/binary-cache.sh b/tests/functional/binary-cache.sh new file mode 100644 index 000000000..7c64a115c --- /dev/null +++ b/tests/functional/binary-cache.sh @@ -0,0 +1,286 @@ +source common.sh + +needLocalStore "'--no-require-sigs' can’t be used with the daemon" + +# We can produce drvs directly into the binary cache +clearStore +clearCacheCache +nix-instantiate --store "file://$cacheDir" dependencies.nix + +# Create the binary cache. +clearStore +clearCache +outPath=$(nix-build dependencies.nix --no-out-link) + +nix copy --to file://$cacheDir $outPath + +# Test copying build logs to the binary cache. +expect 1 nix log --store file://$cacheDir $outPath 2>&1 | grep 'is not available' +nix store copy-log --to file://$cacheDir $outPath +nix log --store file://$cacheDir $outPath | grep FOO +rm -rf $TEST_ROOT/var/log/nix +expect 1 nix log $outPath 2>&1 | grep 'is not available' +nix log --substituters file://$cacheDir $outPath | grep FOO + +# Test copying build logs from the binary cache. +nix store copy-log --from file://$cacheDir $(nix-store -qd $outPath)^'*' +nix log $outPath | grep FOO + +basicDownloadTests() { + # No uploading tests bcause upload with force HTTP doesn't work. + + # By default, a binary cache doesn't support "nix-env -qas", but does + # support installation. + clearStore + clearCacheCache + + nix-env --substituters "file://$cacheDir" -f dependencies.nix -qas \* | grep -- "---" + + nix-store --substituters "file://$cacheDir" --no-require-sigs -r $outPath + + [ -x $outPath/program ] + + + # But with the right configuration, "nix-env -qas" should also work. + clearStore + clearCacheCache + echo "WantMassQuery: 1" >> $cacheDir/nix-cache-info + + nix-env --substituters "file://$cacheDir" -f dependencies.nix -qas \* | grep -- "--S" + nix-env --substituters "file://$cacheDir" -f dependencies.nix -qas \* | grep -- "--S" + + x=$(nix-env -f dependencies.nix -qas \* --prebuilt-only) + [ -z "$x" ] + + nix-store --substituters "file://$cacheDir" --no-require-sigs -r $outPath + + nix-store --check-validity $outPath + nix-store -qR $outPath | grep input-2 + + echo "WantMassQuery: 0" >> $cacheDir/nix-cache-info +} + + +# Test LocalBinaryCacheStore. +basicDownloadTests + + +# Test HttpBinaryCacheStore. +export _NIX_FORCE_HTTP=1 +basicDownloadTests + + +# Test whether Nix notices if the NAR doesn't match the hash in the NAR info. +clearStore + +nar=$(ls $cacheDir/nar/*.nar.xz | head -n1) +mv $nar $nar.good +mkdir -p $TEST_ROOT/empty +nix-store --dump $TEST_ROOT/empty | xz > $nar + +expect 1 nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result 2>&1 | tee $TEST_ROOT/log +grepQuiet "hash mismatch" $TEST_ROOT/log + +mv $nar.good $nar + + +# Test whether this unsigned cache is rejected if the user requires signed caches. +clearStore +clearCacheCache + +if nix-store --substituters "file://$cacheDir" -r $outPath; then + echo "unsigned binary cache incorrectly accepted" + exit 1 +fi + + +# Test whether fallback works if a NAR has disappeared. This does not require --fallback. +clearStore + +mv $cacheDir/nar $cacheDir/nar2 + +nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result + +mv $cacheDir/nar2 $cacheDir/nar + + +# Test whether fallback works if a NAR is corrupted. This does require --fallback. +clearStore + +mv $cacheDir/nar $cacheDir/nar2 +mkdir $cacheDir/nar +for i in $(cd $cacheDir/nar2 && echo *); do touch $cacheDir/nar/$i; done + +(! nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result) + +nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result --fallback + +rm -rf $cacheDir/nar +mv $cacheDir/nar2 $cacheDir/nar + + +# Test whether building works if the binary cache contains an +# incomplete closure. +clearStore + +rm -v $(grep -l "StorePath:.*dependencies-input-2" $cacheDir/*.narinfo) + +nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result 2>&1 | tee $TEST_ROOT/log +grepQuiet "copying path.*input-0" $TEST_ROOT/log +grepQuiet "copying path.*input-2" $TEST_ROOT/log +grepQuiet "copying path.*top" $TEST_ROOT/log + + +# Idem, but without cached .narinfo. +clearStore +clearCacheCache + +nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result 2>&1 | tee $TEST_ROOT/log +grepQuiet "don't know how to build" $TEST_ROOT/log +grepQuiet "building.*input-1" $TEST_ROOT/log +grepQuiet "building.*input-2" $TEST_ROOT/log +grepQuiet "copying path.*input-0" $TEST_ROOT/log +grepQuiet "copying path.*top" $TEST_ROOT/log + + +# Create a signed binary cache. +clearCache +clearCacheCache + +nix key generate-secret --key-name test.nixos.org-1 > $TEST_ROOT/sk1 +publicKey=$(nix key convert-secret-to-public < $TEST_ROOT/sk1) + +nix key generate-secret --key-name test.nixos.org-1 > $TEST_ROOT/sk2 +badKey=$(nix key convert-secret-to-public < $TEST_ROOT/sk2) + +nix key generate-secret --key-name foo.nixos.org-1 > $TEST_ROOT/sk3 +otherKey=$(nix key convert-secret-to-public < $TEST_ROOT/sk3) + +_NIX_FORCE_HTTP= nix copy --to file://$cacheDir?secret-key=$TEST_ROOT/sk1 $outPath + + +# Downloading should fail if we don't provide a key. +clearStore +clearCacheCache + +(! nix-store -r $outPath --substituters "file://$cacheDir") + + +# And it should fail if we provide an incorrect key. +clearStore +clearCacheCache + +(! nix-store -r $outPath --substituters "file://$cacheDir" --trusted-public-keys "$badKey") + + +# It should succeed if we provide the correct key. +nix-store -r $outPath --substituters "file://$cacheDir" --trusted-public-keys "$otherKey $publicKey" + + +# It should fail if we corrupt the .narinfo. +clearStore + +cacheDir2=$TEST_ROOT/binary-cache-2 +rm -rf $cacheDir2 +cp -r $cacheDir $cacheDir2 + +for i in $cacheDir2/*.narinfo; do + grep -v References $i > $i.tmp + mv $i.tmp $i +done + +clearCacheCache + +(! nix-store -r $outPath --substituters "file://$cacheDir2" --trusted-public-keys "$publicKey") + +# If we provide a bad and a good binary cache, it should succeed. + +nix-store -r $outPath --substituters "file://$cacheDir2 file://$cacheDir" --trusted-public-keys "$publicKey" + + +unset _NIX_FORCE_HTTP + + +# Test 'nix verify --all' on a binary cache. +nix store verify -vvvvv --all --store file://$cacheDir --no-trust + + +# Test local NAR caching. +narCache=$TEST_ROOT/nar-cache +rm -rf $narCache +mkdir $narCache + +[[ $(nix store cat --store "file://$cacheDir?local-nar-cache=$narCache" $outPath/foobar) = FOOBAR ]] + +rm -rfv "$cacheDir/nar" + +[[ $(nix store cat --store "file://$cacheDir?local-nar-cache=$narCache" $outPath/foobar) = FOOBAR ]] + +(! nix store cat --store file://$cacheDir $outPath/foobar) + + +# Test NAR listing generation. +clearCache + +outPath=$(nix-build --no-out-link -E ' + with import ./config.nix; + mkDerivation { + name = "nar-listing"; + buildCommand = "mkdir $out; echo foo > $out/bar; ln -s xyzzy $out/link"; + } +') + +nix copy --to file://$cacheDir?write-nar-listing=1 $outPath + +diff -u \ + <(jq -S < $cacheDir/$(basename $outPath | cut -c1-32).ls) \ + <(echo '{"version":1,"root":{"type":"directory","entries":{"bar":{"type":"regular","size":4,"narOffset":232},"link":{"type":"symlink","target":"xyzzy"}}}}' | jq -S) + + +# Test debug info index generation. +clearCache + +outPath=$(nix-build --no-out-link -E ' + with import ./config.nix; + mkDerivation { + name = "debug-info"; + buildCommand = "mkdir -p $out/lib/debug/.build-id/02; echo foo > $out/lib/debug/.build-id/02/623eda209c26a59b1a8638ff7752f6b945c26b.debug"; + } +') + +nix copy --to "file://$cacheDir?index-debug-info=1&compression=none" $outPath + +diff -u \ + <(cat $cacheDir/debuginfo/02623eda209c26a59b1a8638ff7752f6b945c26b.debug | jq -S) \ + <(echo '{"archive":"../nar/100vxs724qr46phz8m24iswmg9p3785hsyagz0kchf6q6gf06sw6.nar","member":"lib/debug/.build-id/02/623eda209c26a59b1a8638ff7752f6b945c26b.debug"}' | jq -S) + +# Test against issue https://github.com/NixOS/nix/issues/3964 +# +expr=' + with import ./config.nix; + mkDerivation { + name = "multi-output"; + buildCommand = "mkdir -p $out; echo foo > $doc; echo $doc > $out/docref"; + outputs = ["out" "doc"]; + } +' +outPath=$(nix-build --no-out-link -E "$expr") +docPath=$(nix-store -q --references $outPath) + +# $ nix-store -q --tree $outPath +# ...-multi-output +# +---...-multi-output-doc + +nix copy --to "file://$cacheDir" $outPath + +hashpart() { + basename "$1" | cut -c1-32 +} + +# break the closure of out by removing doc +rm $cacheDir/$(hashpart $docPath).narinfo + +nix-store --delete $outPath $docPath +# -vvv is the level that logs during the loop +timeout 60 nix-build --no-out-link -E "$expr" --option substituters "file://$cacheDir" \ + --option trusted-binary-caches "file://$cacheDir" --no-require-sigs diff --git a/tests/functional/brotli.sh b/tests/functional/brotli.sh new file mode 100644 index 000000000..dc9bbdb66 --- /dev/null +++ b/tests/functional/brotli.sh @@ -0,0 +1,21 @@ +source common.sh + +clearStore +clearCache + +cacheURI="file://$cacheDir?compression=br" + +outPath=$(nix-build dependencies.nix --no-out-link) + +nix copy --to $cacheURI $outPath + +HASH=$(nix hash path $outPath) + +clearStore +clearCacheCache + +nix copy --from $cacheURI $outPath --no-check-sigs + +HASH2=$(nix hash path $outPath) + +[[ $HASH = $HASH2 ]] diff --git a/tests/functional/build-delete.sh b/tests/functional/build-delete.sh new file mode 100644 index 000000000..9c56b00e8 --- /dev/null +++ b/tests/functional/build-delete.sh @@ -0,0 +1,54 @@ +source common.sh + +clearStore + +# https://github.com/NixOS/nix/issues/6572 +issue_6572_independent_outputs() { + nix build -f multiple-outputs.nix --json independent --no-link > $TEST_ROOT/independent.json + + # Make sure that 'nix build' can build a derivation that depends on both outputs of another derivation. + p=$(nix build -f multiple-outputs.nix use-independent --no-link --print-out-paths) + nix-store --delete "$p" # Clean up for next test + + # Make sure that 'nix build' tracks input-outputs correctly when a single output is already present. + nix-store --delete "$(jq -r <$TEST_ROOT/independent.json .[0].outputs.first)" + p=$(nix build -f multiple-outputs.nix use-independent --no-link --print-out-paths) + cmp $p < $TEST_ROOT/a.json + + # # Make sure that 'nix build' can build a derivation that depends on both outputs of another derivation. + p=$(nix build -f multiple-outputs.nix use-a --no-link --print-out-paths) + nix-store --delete "$p" # Clean up for next test + + # Make sure that 'nix build' tracks input-outputs correctly when a single output is already present. + nix-store --delete "$(jq -r <$TEST_ROOT/a.json .[0].outputs.second)" + p=$(nix build -f multiple-outputs.nix use-a --no-link --print-out-paths) + cmp $p <&1 | grep "will be built" +# Now new command: +nix build -f dependencies.nix --dry-run 2>&1 | grep "will be built" + +clearStore +clearCache + +# Try --dry-run using new command first +nix build -f dependencies.nix --dry-run 2>&1 | grep "will be built" +# Now old command: +nix-build --no-out-link dependencies.nix --dry-run 2>&1 | grep "will be built" + +################################################### +# Check --dry-run doesn't create links with --dry-run +# https://github.com/NixOS/nix/issues/1849 +clearStore +clearCache + +RESULT=$TEST_ROOT/result-link +rm -f $RESULT + +nix-build dependencies.nix -o $RESULT --dry-run + +[[ ! -h $RESULT ]] || fail "nix-build --dry-run created output link" + +nix build -f dependencies.nix -o $RESULT --dry-run + +[[ ! -h $RESULT ]] || fail "nix build --dry-run created output link" + +nix build -f dependencies.nix -o $RESULT + +[[ -h $RESULT ]] + +################################################### +# Check the JSON output +clearStore +clearCache + +RES=$(nix build -f dependencies.nix --dry-run --json) + +if [[ -z "${NIX_TESTS_CA_BY_DEFAULT-}" ]]; then + echo "$RES" | jq '.[0] | [ + (.drvPath | test("'$NIX_STORE_DIR'.*\\.drv")), + (.outputs.out | test("'$NIX_STORE_DIR'")) + ] | all' +else + echo "$RES" | jq '.[0] | [ + (.drvPath | test("'$NIX_STORE_DIR'.*\\.drv")), + .outputs.out == null + ] | all' +fi diff --git a/tests/functional/build-hook-ca-fixed.nix b/tests/functional/build-hook-ca-fixed.nix new file mode 100644 index 000000000..4cb9e85d1 --- /dev/null +++ b/tests/functional/build-hook-ca-fixed.nix @@ -0,0 +1,58 @@ +{ busybox }: + +with import ./config.nix; + +let + + mkDerivation = args: + derivation ({ + inherit system; + builder = busybox; + args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" "if [ -e .attrs.sh ]; then source .attrs.sh; fi; eval \"$buildCommand\"")]; + outputHashMode = "recursive"; + outputHashAlgo = "sha256"; + } // removeAttrs args ["builder" "meta" "passthru"]) + // { meta = args.meta or {}; passthru = args.passthru or {}; }; + + input1 = mkDerivation { + shell = busybox; + name = "build-remote-input-1"; + buildCommand = "echo hi-input1; echo FOO > $out"; + requiredSystemFeatures = ["foo"]; + outputHash = "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="; + }; + + input2 = mkDerivation { + shell = busybox; + name = "build-remote-input-2"; + buildCommand = "echo hi; echo BAR > $out"; + requiredSystemFeatures = ["bar"]; + outputHash = "sha256-XArauVH91AVwP9hBBQNlkX9ccuPpSYx9o0zeIHb6e+Q="; + }; + + input3 = mkDerivation { + shell = busybox; + name = "build-remote-input-3"; + buildCommand = '' + echo hi-input3 + read x < ${input2} + echo $x BAZ > $out + ''; + requiredSystemFeatures = ["baz"]; + outputHash = "sha256-daKAcPp/+BYMQsVi/YYMlCKoNAxCNDsaivwSHgQqD2s="; + }; + +in + + mkDerivation { + shell = busybox; + name = "build-remote"; + passthru = { inherit input1 input2 input3; }; + buildCommand = + '' + read x < ${input1} + read y < ${input3} + echo "$x $y" > $out + ''; + outputHash = "sha256-5SxbkUw6xe2l9TE1uwCvTtTDysD1vhRor38OtDF0LqQ="; + } diff --git a/tests/functional/build-hook-ca-floating.nix b/tests/functional/build-hook-ca-floating.nix new file mode 100644 index 000000000..dfdbb82da --- /dev/null +++ b/tests/functional/build-hook-ca-floating.nix @@ -0,0 +1,6 @@ +{ busybox }: + +import ./build-hook.nix { + inherit busybox; + contentAddressed = true; +} diff --git a/tests/functional/build-hook.nix b/tests/functional/build-hook.nix new file mode 100644 index 000000000..7effd7903 --- /dev/null +++ b/tests/functional/build-hook.nix @@ -0,0 +1,59 @@ +{ busybox, contentAddressed ? false }: + +with import ./config.nix; + +let + + caArgs = if contentAddressed then { + outputHashMode = "recursive"; + outputHashAlgo = "sha256"; + __contentAddressed = true; + } else {}; + + mkDerivation = args: + derivation ({ + inherit system; + builder = busybox; + args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" "if [ -e .attrs.sh ]; then source .attrs.sh; fi; eval \"$buildCommand\"")]; + } // removeAttrs args ["builder" "meta" "passthru"] + // caArgs) + // { meta = args.meta or {}; passthru = args.passthru or {}; }; + + input1 = mkDerivation { + shell = busybox; + name = "build-remote-input-1"; + buildCommand = "echo hi-input1; echo FOO > $out"; + requiredSystemFeatures = ["foo"]; + }; + + input2 = mkDerivation { + shell = busybox; + name = "build-remote-input-2"; + buildCommand = "echo hi; echo BAR > $out"; + requiredSystemFeatures = ["bar"]; + }; + + input3 = mkDerivation { + shell = busybox; + name = "build-remote-input-3"; + buildCommand = '' + echo hi-input3 + read x < ${input2} + echo $x BAZ > $out + ''; + requiredSystemFeatures = ["baz"]; + }; + +in + + mkDerivation { + shell = busybox; + name = "build-remote"; + passthru = { inherit input1 input2 input3; }; + buildCommand = + '' + read x < ${input1} + read y < ${input3} + echo "$x $y" > $out + ''; + } diff --git a/tests/functional/build-remote-content-addressed-fixed.sh b/tests/functional/build-remote-content-addressed-fixed.sh new file mode 100644 index 000000000..ae7441591 --- /dev/null +++ b/tests/functional/build-remote-content-addressed-fixed.sh @@ -0,0 +1,5 @@ +source common.sh + +file=build-hook-ca-fixed.nix + +source build-remote.sh diff --git a/tests/functional/build-remote-content-addressed-floating.sh b/tests/functional/build-remote-content-addressed-floating.sh new file mode 100644 index 000000000..e83b42b41 --- /dev/null +++ b/tests/functional/build-remote-content-addressed-floating.sh @@ -0,0 +1,9 @@ +source common.sh + +file=build-hook-ca-floating.nix + +enableFeatures "ca-derivations" + +CONTENT_ADDRESSED=true + +source build-remote.sh diff --git a/tests/functional/build-remote-input-addressed.sh b/tests/functional/build-remote-input-addressed.sh new file mode 100644 index 000000000..49d15c389 --- /dev/null +++ b/tests/functional/build-remote-input-addressed.sh @@ -0,0 +1,33 @@ +source common.sh + +file=build-hook.nix + +source build-remote.sh + +# Add a `post-build-hook` option to the nix conf. +# This hook will be executed both for the local machine and the remote builders +# (because they share the same config). +registerBuildHook () { + # Dummy post-build-hook just to ensure that it's executed correctly. + # (we can't reuse the one from `$PWD/push-to-store.sh` because of + # https://github.com/NixOS/nix/issues/4341) + cat < $TEST_ROOT/post-build-hook.sh +#!/bin/sh + +echo "Post hook ran successfully" +# Add an empty line to a counter file, just to check that this hook ran properly +echo "" >> $TEST_ROOT/post-hook-counter +EOF + chmod +x $TEST_ROOT/post-build-hook.sh + rm -f $TEST_ROOT/post-hook-counter + + echo "post-build-hook = $TEST_ROOT/post-build-hook.sh" >> $NIX_CONF_DIR/nix.conf +} + +registerBuildHook +source build-remote.sh + +# `build-hook.nix` has four derivations to build, and the hook runs twice for +# each derivation (once on the builder and once on the host), so the counter +# should contain eight lines now +[[ $(cat $TEST_ROOT/post-hook-counter | wc -l) -eq 8 ]] diff --git a/tests/functional/build-remote-trustless-after.sh b/tests/functional/build-remote-trustless-after.sh new file mode 100644 index 000000000..19f59e6ae --- /dev/null +++ b/tests/functional/build-remote-trustless-after.sh @@ -0,0 +1,2 @@ +outPath=$(readlink -f $TEST_ROOT/result) +grep 'FOO BAR BAZ' ${remoteDir}/${outPath} diff --git a/tests/functional/build-remote-trustless-should-fail-0.sh b/tests/functional/build-remote-trustless-should-fail-0.sh new file mode 100644 index 000000000..fad1def59 --- /dev/null +++ b/tests/functional/build-remote-trustless-should-fail-0.sh @@ -0,0 +1,29 @@ +source common.sh + +enableFeatures "daemon-trust-override" + +restartDaemon + +[[ $busybox =~ busybox ]] || skipTest "no busybox" + +unset NIX_STORE_DIR +unset NIX_STATE_DIR + +# We first build a dependency of the derivation we eventually want to +# build. +nix-build build-hook.nix -A passthru.input2 \ + -o "$TEST_ROOT/input2" \ + --arg busybox "$busybox" \ + --store "$TEST_ROOT/local" \ + --option system-features bar + +# Now when we go to build that downstream derivation, Nix will try to +# copy our already-build `input2` to the remote store. That store object +# is input-addressed, so this will fail. + +file=build-hook.nix +prog=$(readlink -e ./nix-daemon-untrusting.sh) +proto=ssh-ng + +expectStderr 1 source build-remote-trustless.sh \ + | grepQuiet "cannot add path '[^ ]*' because it lacks a signature by a trusted key" diff --git a/tests/functional/build-remote-trustless-should-pass-0.sh b/tests/functional/build-remote-trustless-should-pass-0.sh new file mode 100644 index 000000000..2a7ebd8c6 --- /dev/null +++ b/tests/functional/build-remote-trustless-should-pass-0.sh @@ -0,0 +1,9 @@ +source common.sh + +# Remote trusts us +file=build-hook.nix +prog=nix-store +proto=ssh + +source build-remote-trustless.sh +source build-remote-trustless-after.sh diff --git a/tests/functional/build-remote-trustless-should-pass-1.sh b/tests/functional/build-remote-trustless-should-pass-1.sh new file mode 100644 index 000000000..516bdf092 --- /dev/null +++ b/tests/functional/build-remote-trustless-should-pass-1.sh @@ -0,0 +1,9 @@ +source common.sh + +# Remote trusts us +file=build-hook.nix +prog=nix-daemon +proto=ssh-ng + +source build-remote-trustless.sh +source build-remote-trustless-after.sh diff --git a/tests/functional/build-remote-trustless-should-pass-2.sh b/tests/functional/build-remote-trustless-should-pass-2.sh new file mode 100644 index 000000000..b769a88f0 --- /dev/null +++ b/tests/functional/build-remote-trustless-should-pass-2.sh @@ -0,0 +1,13 @@ +source common.sh + +enableFeatures "daemon-trust-override" + +restartDaemon + +# Remote doesn't trust us +file=build-hook.nix +prog=$(readlink -e ./nix-daemon-untrusting.sh) +proto=ssh-ng + +source build-remote-trustless.sh +source build-remote-trustless-after.sh diff --git a/tests/functional/build-remote-trustless-should-pass-3.sh b/tests/functional/build-remote-trustless-should-pass-3.sh new file mode 100644 index 000000000..40f81da5a --- /dev/null +++ b/tests/functional/build-remote-trustless-should-pass-3.sh @@ -0,0 +1,14 @@ +source common.sh + +enableFeatures "daemon-trust-override" + +restartDaemon + +# Remote doesn't trusts us, but this is fine because we are only +# building (fixed) CA derivations. +file=build-hook-ca-fixed.nix +prog=$(readlink -e ./nix-daemon-untrusting.sh) +proto=ssh-ng + +source build-remote-trustless.sh +source build-remote-trustless-after.sh diff --git a/tests/functional/build-remote-trustless.sh b/tests/functional/build-remote-trustless.sh new file mode 100644 index 000000000..81e5253bf --- /dev/null +++ b/tests/functional/build-remote-trustless.sh @@ -0,0 +1,14 @@ +requireSandboxSupport +[[ $busybox =~ busybox ]] || skipTest "no busybox" + +unset NIX_STORE_DIR +unset NIX_STATE_DIR + +remoteDir=$TEST_ROOT/remote + +# Note: ssh{-ng}://localhost bypasses ssh. See tests/functional/build-remote.sh for +# more details. +nix-build $file -o $TEST_ROOT/result --max-jobs 0 \ + --arg busybox $busybox \ + --store $TEST_ROOT/local \ + --builders "$proto://localhost?remote-program=$prog&remote-store=${remoteDir}%3Fsystem-features=foo%20bar%20baz - - 1 1 foo,bar,baz" diff --git a/tests/functional/build-remote.sh b/tests/functional/build-remote.sh new file mode 100644 index 000000000..d2a2132c1 --- /dev/null +++ b/tests/functional/build-remote.sh @@ -0,0 +1,84 @@ +requireSandboxSupport +[[ $busybox =~ busybox ]] || skipTest "no busybox" + +# Avoid store dir being inside sandbox build-dir +unset NIX_STORE_DIR +unset NIX_STATE_DIR + +function join_by { local d=$1; shift; echo -n "$1"; shift; printf "%s" "${@/#/$d}"; } + +EXTRA_SYSTEM_FEATURES=() +if [[ -n "${CONTENT_ADDRESSED-}" ]]; then + EXTRA_SYSTEM_FEATURES=("ca-derivations") +fi + +builders=( + # system-features will automatically be added to the outer URL, but not inner + # remote-store URL. + "ssh://localhost?remote-store=$TEST_ROOT/machine1?system-features=$(join_by "%20" foo ${EXTRA_SYSTEM_FEATURES[@]}) - - 1 1 $(join_by "," foo ${EXTRA_SYSTEM_FEATURES[@]})" + "$TEST_ROOT/machine2 - - 1 1 $(join_by "," bar ${EXTRA_SYSTEM_FEATURES[@]})" + "ssh-ng://localhost?remote-store=$TEST_ROOT/machine3?system-features=$(join_by "%20" baz ${EXTRA_SYSTEM_FEATURES[@]}) - - 1 1 $(join_by "," baz ${EXTRA_SYSTEM_FEATURES[@]})" +) + +chmod -R +w $TEST_ROOT/machine* || true +rm -rf $TEST_ROOT/machine* || true + +# Note: ssh://localhost bypasses ssh, directly invoking nix-store as a +# child process. This allows us to test LegacySSHStore::buildDerivation(). +# ssh-ng://... likewise allows us to test RemoteStore::buildDerivation(). +nix build -L -v -f $file -o $TEST_ROOT/result --max-jobs 0 \ + --arg busybox $busybox \ + --store $TEST_ROOT/machine0 \ + --builders "$(join_by '; ' "${builders[@]}")" + +outPath=$(readlink -f $TEST_ROOT/result) + +grep 'FOO BAR BAZ' $TEST_ROOT/machine0/$outPath + +testPrintOutPath=$(nix build -L -v -f $file --no-link --print-out-paths --max-jobs 0 \ + --arg busybox $busybox \ + --store $TEST_ROOT/machine0 \ + --builders "$(join_by '; ' "${builders[@]}")" +) + +[[ $testPrintOutPath =~ store.*build-remote ]] + +# Ensure that input1 was built on store1 due to the required feature. +output=$(nix path-info --store $TEST_ROOT/machine1 --all) +echo "$output" | grepQuiet builder-build-remote-input-1.sh +echo "$output" | grepQuietInverse builder-build-remote-input-2.sh +echo "$output" | grepQuietInverse builder-build-remote-input-3.sh +unset output + +# Ensure that input2 was built on store2 due to the required feature. +output=$(nix path-info --store $TEST_ROOT/machine2 --all) +echo "$output" | grepQuietInverse builder-build-remote-input-1.sh +echo "$output" | grepQuiet builder-build-remote-input-2.sh +echo "$output" | grepQuietInverse builder-build-remote-input-3.sh +unset output + +# Ensure that input3 was built on store3 due to the required feature. +output=$(nix path-info --store $TEST_ROOT/machine3 --all) +echo "$output" | grepQuietInverse builder-build-remote-input-1.sh +echo "$output" | grepQuietInverse builder-build-remote-input-2.sh +echo "$output" | grepQuiet builder-build-remote-input-3.sh +unset output + + +for i in input1 input3; do +nix log --store $TEST_ROOT/machine0 --file "$file" --arg busybox $busybox passthru."$i" | grep hi-$i +done + +# Behavior of keep-failed +out="$(nix-build 2>&1 failing.nix \ + --no-out-link \ + --builders "$(join_by '; ' "${builders[@]}")" \ + --keep-failed \ + --store $TEST_ROOT/machine0 \ + -j0 \ + --arg busybox $busybox)" || true + +[[ "$out" =~ .*"note: keeping build directory".* ]] + +build_dir="$(grep "note: keeping build" <<< "$out" | sed -E "s/^(.*)note: keeping build directory '(.*)'(.*)$/\2/")" +[[ "foo" = $(<"$build_dir"/bar) ]] diff --git a/tests/functional/build.sh b/tests/functional/build.sh new file mode 100644 index 000000000..7fbdb0f07 --- /dev/null +++ b/tests/functional/build.sh @@ -0,0 +1,135 @@ +source common.sh + +clearStore + +# Make sure that 'nix build' returns all outputs by default. +nix build -f multiple-outputs.nix --json a b --no-link | jq --exit-status ' + (.[0] | + (.drvPath | match(".*multiple-outputs-a.drv")) and + (.outputs | + (keys | length == 2) and + (.first | match(".*multiple-outputs-a-first")) and + (.second | match(".*multiple-outputs-a-second")))) + and (.[1] | + (.drvPath | match(".*multiple-outputs-b.drv")) and + (.outputs | + (keys | length == 1) and + (.out | match(".*multiple-outputs-b")))) +' + +# Test output selection using the '^' syntax. +nix build -f multiple-outputs.nix --json a^first --no-link | jq --exit-status ' + (.[0] | + (.drvPath | match(".*multiple-outputs-a.drv")) and + (.outputs | keys == ["first"])) +' + +nix build -f multiple-outputs.nix --json a^second,first --no-link | jq --exit-status ' + (.[0] | + (.drvPath | match(".*multiple-outputs-a.drv")) and + (.outputs | keys == ["first", "second"])) +' + +nix build -f multiple-outputs.nix --json 'a^*' --no-link | jq --exit-status ' + (.[0] | + (.drvPath | match(".*multiple-outputs-a.drv")) and + (.outputs | keys == ["first", "second"])) +' + +# Test that 'outputsToInstall' is respected by default. +nix build -f multiple-outputs.nix --json e --no-link | jq --exit-status ' + (.[0] | + (.drvPath | match(".*multiple-outputs-e.drv")) and + (.outputs | keys == ["a_a", "b"])) +' + +# But not when it's overriden. +nix build -f multiple-outputs.nix --json e^a_a --no-link +nix build -f multiple-outputs.nix --json e^a_a --no-link | jq --exit-status ' + (.[0] | + (.drvPath | match(".*multiple-outputs-e.drv")) and + (.outputs | keys == ["a_a"])) +' + +nix build -f multiple-outputs.nix --json 'e^*' --no-link | jq --exit-status ' + (.[0] | + (.drvPath | match(".*multiple-outputs-e.drv")) and + (.outputs | keys == ["a_a", "b", "c"])) +' + +# test buidling from non-drv attr path + +nix build -f multiple-outputs.nix --json 'e.a_a.outPath' --no-link | jq --exit-status ' + (.[0] | + (.drvPath | match(".*multiple-outputs-e.drv")) and + (.outputs | keys == ["a_a"])) +' + +# Illegal type of string context +expectStderr 1 nix build -f multiple-outputs.nix 'e.a_a.drvPath' \ + | grepQuiet "has a context which refers to a complete source and binary closure." + +# No string context +expectStderr 1 nix build --expr '""' --no-link \ + | grepQuiet "has 0 entries in its context. It should only have exactly one entry" + +# Too much string context +expectStderr 1 nix build --impure --expr 'with (import ./multiple-outputs.nix).e.a_a; "${drvPath}${outPath}"' --no-link \ + | grepQuiet "has 2 entries in its context. It should only have exactly one entry" + +nix build --impure --json --expr 'builtins.unsafeDiscardOutputDependency (import ./multiple-outputs.nix).e.a_a.drvPath' --no-link | jq --exit-status ' + (.[0] | match(".*multiple-outputs-e.drv")) +' + +# Test building from raw store path to drv not expression. + +drv=$(nix eval -f multiple-outputs.nix --raw a.drvPath) +if nix build "$drv^not-an-output" --no-link --json; then + fail "'not-an-output' should fail to build" +fi + +if nix build "$drv^" --no-link --json; then + fail "'empty outputs list' should fail to build" +fi + +if nix build "$drv^*nope" --no-link --json; then + fail "'* must be entire string' should fail to build" +fi + +nix build "$drv^first" --no-link --json | jq --exit-status ' + (.[0] | + (.drvPath | match(".*multiple-outputs-a.drv")) and + (.outputs | + (keys | length == 1) and + (.first | match(".*multiple-outputs-a-first")) and + (has("second") | not))) +' + +nix build "$drv^first,second" --no-link --json | jq --exit-status ' + (.[0] | + (.drvPath | match(".*multiple-outputs-a.drv")) and + (.outputs | + (keys | length == 2) and + (.first | match(".*multiple-outputs-a-first")) and + (.second | match(".*multiple-outputs-a-second")))) +' + +nix build "$drv^*" --no-link --json | jq --exit-status ' + (.[0] | + (.drvPath | match(".*multiple-outputs-a.drv")) and + (.outputs | + (keys | length == 2) and + (.first | match(".*multiple-outputs-a-first")) and + (.second | match(".*multiple-outputs-a-second")))) +' + +# Make sure that `--impure` works (regression test for https://github.com/NixOS/nix/issues/6488) +nix build --impure -f multiple-outputs.nix --json e --no-link | jq --exit-status ' + (.[0] | + (.drvPath | match(".*multiple-outputs-e.drv")) and + (.outputs | keys == ["a_a", "b"])) +' + +# Make sure that `--stdin` works and does not apply any defaults +printf "" | nix build --no-link --stdin --json | jq --exit-status '. == []' +printf "%s\n" "$drv^*" | nix build --no-link --stdin --json | jq --exit-status '.[0]|has("drvPath")' diff --git a/tests/functional/ca-shell.nix b/tests/functional/ca-shell.nix new file mode 100644 index 000000000..36e1d1526 --- /dev/null +++ b/tests/functional/ca-shell.nix @@ -0,0 +1 @@ +{ inNixShell ? false, ... }@args: import ./shell.nix (args // { contentAddressed = true; }) diff --git a/tests/functional/ca/build-cache.sh b/tests/functional/ca/build-cache.sh new file mode 100644 index 000000000..6a4080fec --- /dev/null +++ b/tests/functional/ca/build-cache.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +source common.sh + +# The substituters didn't work prior to this time. +requireDaemonNewerThan "2.18.0pre20230808" + +drv=$(nix-instantiate ./content-addressed.nix -A rootCA --arg seed 1)^out +nix derivation show "$drv" --arg seed 1 + +buildAttr () { + local derivationPath=$1 + local seedValue=$2 + shift; shift + local args=("./content-addressed.nix" "-A" "$derivationPath" --arg seed "$seedValue" "--no-out-link") + args+=("$@") + nix-build "${args[@]}" +} + +copyAttr () { + local derivationPath=$1 + local seedValue=$2 + shift; shift + local args=("-f" "./content-addressed.nix" "$derivationPath" --arg seed "$seedValue") + args+=("$@") + # Note: to copy CA derivations, we need to copy the realisations, which + # currently requires naming the installables, not just the derivation output + # path. + nix copy --to file://$cacheDir "${args[@]}" +} + +testRemoteCacheFor () { + local derivationPath=$1 + clearCache + copyAttr "$derivationPath" 1 + clearStore + # Check nothing gets built. + buildAttr "$derivationPath" 1 --option substituters file://$cacheDir --no-require-sigs |& grepQuietInverse " will be built:" +} + +testRemoteCache () { + testRemoteCacheFor rootCA + testRemoteCacheFor dependentCA + testRemoteCacheFor dependentNonCA + testRemoteCacheFor dependentFixedOutput + testRemoteCacheFor dependentForBuildCA + testRemoteCacheFor dependentForBuildNonCA +} + +clearStore +testRemoteCache \ No newline at end of file diff --git a/tests/functional/ca/build-dry.sh b/tests/functional/ca/build-dry.sh new file mode 100644 index 000000000..9a72075ec --- /dev/null +++ b/tests/functional/ca/build-dry.sh @@ -0,0 +1,6 @@ +source common.sh + +export NIX_TESTS_CA_BY_DEFAULT=1 + +cd .. && source build-dry.sh + diff --git a/tests/functional/ca/build-with-garbage-path.sh b/tests/functional/ca/build-with-garbage-path.sh new file mode 100755 index 000000000..884cd2802 --- /dev/null +++ b/tests/functional/ca/build-with-garbage-path.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +# Regression test for https://github.com/NixOS/nix/issues/4858 + +source common.sh + +requireDaemonNewerThan "2.4pre20210621" + +# Get the output path of `rootCA`, and put some garbage instead +outPath="$(nix-build ./content-addressed.nix -A rootCA --no-out-link)" +nix-store --delete $(nix-store -q --referrers-closure "$outPath") +touch "$outPath" + +# The build should correctly remove the garbage and put the expected path instead +nix-build ./content-addressed.nix -A rootCA --no-out-link + +# Rebuild it. This shouldn’t overwrite the existing path +oldInode=$(stat -c '%i' "$outPath") +nix-build ./content-addressed.nix -A rootCA --no-out-link --arg seed 2 +newInode=$(stat -c '%i' "$outPath") +[[ "$oldInode" == "$newInode" ]] diff --git a/tests/functional/ca/build.sh b/tests/functional/ca/build.sh new file mode 100644 index 000000000..e1a8a7625 --- /dev/null +++ b/tests/functional/ca/build.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash + +source common.sh + +drv=$(nix-instantiate ./content-addressed.nix -A rootCA --arg seed 1)^out +nix derivation show "$drv" --arg seed 1 + +buildAttr () { + local derivationPath=$1 + local seedValue=$2 + shift; shift + local args=("./content-addressed.nix" "-A" "$derivationPath" --arg seed "$seedValue" "--no-out-link") + args+=("$@") + nix-build "${args[@]}" +} + +testDeterministicCA () { + [[ $(buildAttr rootCA 1) = $(buildAttr rootCA 2) ]] +} + +testCutoffFor () { + local out1 out2 + out1=$(buildAttr $1 1) + # The seed only changes the root derivation, and not it's output, so the + # dependent derivations should only need to be built once. + buildAttr rootCA 2 + out2=$(buildAttr $1 2 -j0) + test "$out1" == "$out2" +} + +testCutoff () { + # Don't directly build dependentCA, that way we'll make sure we don't rely on + # dependent derivations always being already built. + #testDerivation dependentCA + testCutoffFor transitivelyDependentCA + testCutoffFor dependentNonCA + testCutoffFor dependentFixedOutput +} + +testGC () { + nix-instantiate ./content-addressed.nix -A rootCA --arg seed 5 + nix-collect-garbage --option keep-derivations true + clearStore + buildAttr rootCA 1 --out-link $TEST_ROOT/rootCA + nix-collect-garbage + buildAttr rootCA 1 -j0 +} + +testNixCommand () { + clearStore + nix build --file ./content-addressed.nix --no-link +} + +# Regression test for https://github.com/NixOS/nix/issues/4775 +testNormalization () { + clearStore + outPath=$(buildAttr rootCA 1) + test "$(stat -c %Y $outPath)" -eq 1 +} + +clearStore +testNormalization +testDeterministicCA +clearStore +testCutoff +testGC +testNixCommand diff --git a/tests/functional/ca/common.sh b/tests/functional/ca/common.sh new file mode 100644 index 000000000..b104b5a78 --- /dev/null +++ b/tests/functional/ca/common.sh @@ -0,0 +1,5 @@ +source ../common.sh + +enableFeatures "ca-derivations" + +restartDaemon diff --git a/tests/functional/ca/concurrent-builds.sh b/tests/functional/ca/concurrent-builds.sh new file mode 100755 index 000000000..b442619e2 --- /dev/null +++ b/tests/functional/ca/concurrent-builds.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +# Ensure that we can’t build twice the same derivation concurrently. +# Regression test for https://github.com/NixOS/nix/issues/5029 + +source common.sh + +buggyNeedLocalStore "For some reason, this deadlocks with the daemon" + +export NIX_TESTS_CA_BY_DEFAULT=1 + +clearStore + +for i in {0..5}; do + nix build --no-link --file ./racy.nix & +done + +wait diff --git a/tests/functional/ca/config.nix.in b/tests/functional/ca/config.nix.in new file mode 120000 index 000000000..af24ddb30 --- /dev/null +++ b/tests/functional/ca/config.nix.in @@ -0,0 +1 @@ +../config.nix.in \ No newline at end of file diff --git a/tests/functional/ca/content-addressed.nix b/tests/functional/ca/content-addressed.nix new file mode 100644 index 000000000..2559c562f --- /dev/null +++ b/tests/functional/ca/content-addressed.nix @@ -0,0 +1,100 @@ +with import ./config.nix; + +let mkCADerivation = args: mkDerivation ({ + __contentAddressed = true; + outputHashMode = "recursive"; + outputHashAlgo = "sha256"; +} // args); +in + +{ seed ? 0 }: +# A simple content-addressed derivation. +# The derivation can be arbitrarily modified by passing a different `seed`, +# but the output will always be the same +rec { + rootLegacy = mkDerivation { + name = "simple-input-addressed"; + buildCommand = '' + set -x + echo "Building a legacy derivation" + mkdir -p $out + echo "Hello World" > $out/hello + ''; + }; + rootCA = mkCADerivation { + name = "rootCA"; + outputs = [ "out" "dev" "foo" ]; + buildCommand = '' + echo "building a CA derivation" + echo "The seed is ${toString seed}" + mkdir -p $out + echo ${rootLegacy}/hello > $out/dep + ln -s $out $out/self + # test symlinks at root + ln -s $out $dev + ln -s $out $foo + ''; + }; + dependentCA = mkCADerivation { + name = "dependent"; + buildCommand = '' + echo "building a dependent derivation" + mkdir -p $out + cat ${rootCA}/self/dep + echo ${rootCA}/self/dep > $out/dep + ''; + }; + transitivelyDependentCA = mkCADerivation { + name = "transitively-dependent"; + buildCommand = '' + echo "building transitively-dependent" + cat ${dependentCA}/dep + echo ${dependentCA} > $out + ''; + }; + dependentNonCA = mkDerivation { + name = "dependent-non-ca"; + buildCommand = '' + echo "Didn't cut-off" + echo "building dependent-non-ca" + mkdir -p $out + echo ${rootCA}/non-ca-hello > $out/dep + ''; + }; + dependentForBuildCA = mkCADerivation { + name = "dependent-for-build-ca"; + buildCommand = '' + echo "Depends on rootCA for building only" + mkdir -p $out + echo ${rootCA} + touch $out + ''; + }; + dependentForBuildNonCA = mkDerivation { + name = "dependent-for-build-non-ca"; + buildCommand = '' + echo "Depends on rootCA for building only" + mkdir -p $out + echo ${rootCA} + touch $out + ''; + }; + dependentFixedOutput = mkDerivation { + name = "dependent-fixed-output"; + outputHashMode = "recursive"; + outputHash = "sha512-7aJcmSuEuYP5tGKcmGY8bRr/lrCjJlOxP2mIUjO/vMQeg6gx/65IbzRWES8EKiPDOs9z+wF30lEfcwxM/cT4pw=="; + buildCommand = '' + cat ${dependentCA}/dep + echo foo > $out + ''; + }; + runnable = mkCADerivation rec { + name = "runnable-thing"; + buildCommand = '' + mkdir -p $out/bin + echo ${rootCA} # Just to make it depend on it + echo "#! ${shell}" > $out/bin/${name} + chmod +x $out/bin/${name} + ''; + }; +} diff --git a/tests/functional/ca/derivation-json.sh b/tests/functional/ca/derivation-json.sh new file mode 100644 index 000000000..c1480fd17 --- /dev/null +++ b/tests/functional/ca/derivation-json.sh @@ -0,0 +1,29 @@ +source common.sh + +export NIX_TESTS_CA_BY_DEFAULT=1 + +drvPath=$(nix-instantiate ../simple.nix) + +nix derivation show $drvPath | jq .[] > $TEST_HOME/simple.json + +drvPath2=$(nix derivation add < $TEST_HOME/simple.json) + +[[ "$drvPath" = "$drvPath2" ]] + +# Content-addressed derivations can be renamed. +jq '.name = "foo"' < $TEST_HOME/simple.json > $TEST_HOME/foo.json +drvPath3=$(nix derivation add --dry-run < $TEST_HOME/foo.json) +# With --dry-run nothing is actually written +[[ ! -e "$drvPath3" ]] + +# But the JSON is rejected without the experimental feature +expectStderr 1 nix derivation add < $TEST_HOME/foo.json --experimental-features nix-command | grepQuiet "experimental Nix feature 'ca-derivations' is disabled" + +# Without --dry-run it is actually written +drvPath4=$(nix derivation add < $TEST_HOME/foo.json) +[[ "$drvPath4" = "$drvPath3" ]] +[[ -e "$drvPath3" ]] + +# The modified derivation read back as JSON matches +nix derivation show $drvPath3 | jq .[] > $TEST_HOME/foo-read.json +diff $TEST_HOME/foo.json $TEST_HOME/foo-read.json diff --git a/tests/functional/ca/duplicate-realisation-in-closure.sh b/tests/functional/ca/duplicate-realisation-in-closure.sh new file mode 100644 index 000000000..da9cd8fb4 --- /dev/null +++ b/tests/functional/ca/duplicate-realisation-in-closure.sh @@ -0,0 +1,26 @@ +source ./common.sh + +requireDaemonNewerThan "2.4pre20210625" + +export REMOTE_STORE_DIR="$TEST_ROOT/remote_store" +export REMOTE_STORE="file://$REMOTE_STORE_DIR" + +rm -rf $REMOTE_STORE_DIR +clearStore + +# Build dep1 and push that to the binary cache. +# This entails building (and pushing) current-time. +nix copy --to "$REMOTE_STORE" -f nondeterministic.nix dep1 +clearStore +sleep 2 # To make sure that `$(date)` will be different +# Build dep2. +# As we’ve cleared the cache, we’ll have to rebuild current-time. And because +# the current time isn’t the same as before, this will yield a new (different) +# realisation +nix build -f nondeterministic.nix dep2 --no-link + +# Build something that depends both on dep1 and dep2. +# If everything goes right, we should rebuild dep2 rather than fetch it from +# the cache (because that would mean duplicating `current-time` in the closure), +# and have `dep1 == dep2`. +nix build --substituters "$REMOTE_STORE" -f nondeterministic.nix toplevel --no-require-sigs --no-link diff --git a/tests/functional/ca/flake.nix b/tests/functional/ca/flake.nix new file mode 100644 index 000000000..332c92a67 --- /dev/null +++ b/tests/functional/ca/flake.nix @@ -0,0 +1,3 @@ +{ + outputs = { self }: import ./content-addressed.nix {}; +} diff --git a/tests/functional/ca/gc.sh b/tests/functional/ca/gc.sh new file mode 100755 index 000000000..e9b6c5ab5 --- /dev/null +++ b/tests/functional/ca/gc.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +# Ensure that garbage collection works properly with ca derivations + +source common.sh + +export NIX_TESTS_CA_BY_DEFAULT=1 + +cd .. +source gc.sh diff --git a/tests/functional/ca/import-derivation.sh b/tests/functional/ca/import-derivation.sh new file mode 100644 index 000000000..e98e0fbd0 --- /dev/null +++ b/tests/functional/ca/import-derivation.sh @@ -0,0 +1,6 @@ +source common.sh + +export NIX_TESTS_CA_BY_DEFAULT=1 + +cd .. && source import-derivation.sh + diff --git a/tests/functional/ca/local.mk b/tests/functional/ca/local.mk new file mode 100644 index 000000000..fd87b8d1f --- /dev/null +++ b/tests/functional/ca/local.mk @@ -0,0 +1,28 @@ +ca-tests := \ + $(d)/build-with-garbage-path.sh \ + $(d)/build.sh \ + $(d)/build-cache.sh \ + $(d)/concurrent-builds.sh \ + $(d)/derivation-json.sh \ + $(d)/duplicate-realisation-in-closure.sh \ + $(d)/gc.sh \ + $(d)/import-derivation.sh \ + $(d)/new-build-cmd.sh \ + $(d)/nix-copy.sh \ + $(d)/nix-run.sh \ + $(d)/nix-shell.sh \ + $(d)/post-hook.sh \ + $(d)/recursive.sh \ + $(d)/repl.sh \ + $(d)/selfref-gc.sh \ + $(d)/signatures.sh \ + $(d)/substitute.sh \ + $(d)/why-depends.sh + +install-tests-groups += ca + +clean-files += \ + $(d)/config.nix + +test-deps += \ + tests/functional/ca/config.nix diff --git a/tests/functional/ca/new-build-cmd.sh b/tests/functional/ca/new-build-cmd.sh new file mode 100644 index 000000000..432d4d132 --- /dev/null +++ b/tests/functional/ca/new-build-cmd.sh @@ -0,0 +1,5 @@ +source common.sh + +export NIX_TESTS_CA_BY_DEFAULT=1 +cd .. +source ./build.sh diff --git a/tests/functional/ca/nix-copy.sh b/tests/functional/ca/nix-copy.sh new file mode 100755 index 000000000..7a8307a4e --- /dev/null +++ b/tests/functional/ca/nix-copy.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +source common.sh + +export REMOTE_STORE_DIR="$TEST_ROOT/remote_store" +export REMOTE_STORE="file://$REMOTE_STORE_DIR" + +ensureCorrectlyCopied () { + attrPath="$1" + nix build --store "$REMOTE_STORE" --file ./content-addressed.nix "$attrPath" +} + +testOneCopy () { + clearStore + rm -rf "$REMOTE_STORE_DIR" + + attrPath="$1" + nix copy --to $REMOTE_STORE "$attrPath" --file ./content-addressed.nix + + ensureCorrectlyCopied "$attrPath" + + # Ensure that we can copy back what we put in the store + clearStore + nix copy --from $REMOTE_STORE \ + --file ./content-addressed.nix "$attrPath" \ + --no-check-sigs +} + +for attrPath in rootCA dependentCA transitivelyDependentCA dependentNonCA dependentFixedOutput; do + testOneCopy "$attrPath" +done diff --git a/tests/functional/ca/nix-run.sh b/tests/functional/ca/nix-run.sh new file mode 100755 index 000000000..5f46518e8 --- /dev/null +++ b/tests/functional/ca/nix-run.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +source common.sh + +FLAKE_PATH=path:$PWD + +nix run --no-write-lock-file $FLAKE_PATH#runnable diff --git a/tests/functional/ca/nix-shell.sh b/tests/functional/ca/nix-shell.sh new file mode 100755 index 000000000..1c5a6639f --- /dev/null +++ b/tests/functional/ca/nix-shell.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +source common.sh + +CONTENT_ADDRESSED=true +cd .. +source ./nix-shell.sh + diff --git a/tests/functional/ca/nondeterministic.nix b/tests/functional/ca/nondeterministic.nix new file mode 100644 index 000000000..d6d099a3e --- /dev/null +++ b/tests/functional/ca/nondeterministic.nix @@ -0,0 +1,35 @@ +with import ./config.nix; + +let mkCADerivation = args: mkDerivation ({ + __contentAddressed = true; + outputHashMode = "recursive"; + outputHashAlgo = "sha256"; +} // args); +in + +rec { + currentTime = mkCADerivation { + name = "current-time"; + buildCommand = '' + mkdir $out + echo $(date) > $out/current-time + ''; + }; + dep = seed: mkCADerivation { + name = "dep"; + inherit seed; + buildCommand = '' + echo ${currentTime} > $out + ''; + }; + dep1 = dep 1; + dep2 = dep 2; + toplevel = mkCADerivation { + name = "toplevel"; + buildCommand = '' + test ${dep1} == ${dep2} + touch $out + ''; + }; +} + diff --git a/tests/functional/ca/post-hook.sh b/tests/functional/ca/post-hook.sh new file mode 100755 index 000000000..705bde9d4 --- /dev/null +++ b/tests/functional/ca/post-hook.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +source common.sh + +requireDaemonNewerThan "2.4pre20210626" + +export NIX_TESTS_CA_BY_DEFAULT=1 +cd .. +source ./post-hook.sh + + diff --git a/tests/functional/ca/racy.nix b/tests/functional/ca/racy.nix new file mode 100644 index 000000000..555a15484 --- /dev/null +++ b/tests/functional/ca/racy.nix @@ -0,0 +1,15 @@ +# A derivation that would certainly fail if several builders tried to +# build it at once. + + +with import ./config.nix; + +mkDerivation { + name = "simple"; + buildCommand = '' + mkdir $out + echo bar >> $out/foo + sleep 3 + [[ "$(cat $out/foo)" == bar ]] + ''; +} diff --git a/tests/functional/ca/recursive.sh b/tests/functional/ca/recursive.sh new file mode 100755 index 000000000..cd6736b24 --- /dev/null +++ b/tests/functional/ca/recursive.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +source common.sh + +requireDaemonNewerThan "2.4pre20210623" + +export NIX_TESTS_CA_BY_DEFAULT=1 +cd .. +source ./recursive.sh diff --git a/tests/functional/ca/repl.sh b/tests/functional/ca/repl.sh new file mode 100644 index 000000000..3808c7cb2 --- /dev/null +++ b/tests/functional/ca/repl.sh @@ -0,0 +1,5 @@ +source common.sh + +export NIX_TESTS_CA_BY_DEFAULT=1 + +cd .. && source repl.sh diff --git a/tests/functional/ca/selfref-gc.sh b/tests/functional/ca/selfref-gc.sh new file mode 100755 index 000000000..248778894 --- /dev/null +++ b/tests/functional/ca/selfref-gc.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +source common.sh + +requireDaemonNewerThan "2.4pre20210626" + +enableFeatures "ca-derivations nix-command flakes" + +export NIX_TESTS_CA_BY_DEFAULT=1 +cd .. +source ./selfref-gc.sh diff --git a/tests/functional/ca/signatures.sh b/tests/functional/ca/signatures.sh new file mode 100644 index 000000000..eb18a4130 --- /dev/null +++ b/tests/functional/ca/signatures.sh @@ -0,0 +1,36 @@ +source common.sh + +clearStore +clearCache + +nix-store --generate-binary-cache-key cache1.example.org $TEST_ROOT/sk1 $TEST_ROOT/pk1 +pk1=$(cat $TEST_ROOT/pk1) + +export REMOTE_STORE_DIR="$TEST_ROOT/remote_store" +export REMOTE_STORE="file://$REMOTE_STORE_DIR" + +ensureCorrectlyCopied () { + attrPath="$1" + nix build --store "$REMOTE_STORE" --file ./content-addressed.nix "$attrPath" +} + +testOneCopy () { + clearStore + rm -rf "$REMOTE_STORE_DIR" + + attrPath="$1" + nix copy -vvvv --to $REMOTE_STORE "$attrPath" --file ./content-addressed.nix \ + --secret-key-files "$TEST_ROOT/sk1" --show-trace + + ensureCorrectlyCopied "$attrPath" + + # Ensure that we can copy back what we put in the store + clearStore + nix copy --from $REMOTE_STORE \ + --file ./content-addressed.nix "$attrPath" \ + --trusted-public-keys $pk1 +} + +for attrPath in rootCA dependentCA transitivelyDependentCA dependentNonCA dependentFixedOutput; do + testOneCopy "$attrPath" +done diff --git a/tests/functional/ca/substitute.sh b/tests/functional/ca/substitute.sh new file mode 100644 index 000000000..ea981adc4 --- /dev/null +++ b/tests/functional/ca/substitute.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash + +# Ensure that binary substitution works properly with ca derivations + +source common.sh + +needLocalStore "“--no-require-sigs” can’t be used with the daemon" + +rm -rf $TEST_ROOT/binary_cache + +export REMOTE_STORE_DIR=$TEST_ROOT/binary_cache +export REMOTE_STORE=file://$REMOTE_STORE_DIR + +buildDrvs () { + nix build --file ./content-addressed.nix -L --no-link "$@" +} + +# Populate the remote cache +clearStore +nix copy --to $REMOTE_STORE --file ./content-addressed.nix + +# Restart the build on an empty store, ensuring that we don't build +clearStore +buildDrvs --substitute --substituters $REMOTE_STORE --no-require-sigs -j0 transitivelyDependentCA +# Check that the thing we’ve just substituted has its realisation stored +nix realisation info --file ./content-addressed.nix transitivelyDependentCA +# Check that its dependencies have it too +nix realisation info --file ./content-addressed.nix dependentCA +# nix realisation info --file ./content-addressed.nix rootCA --outputs out + +if isDaemonNewer "2.13"; then + pushToStore="../push-to-store.sh" +else + pushToStore="../push-to-store-old.sh" +fi + +# Same thing, but +# 1. With non-ca derivations +# 2. Erasing the realisations on the remote store +# +# Even in that case, realising the derivations should still produce the right +# realisations on the local store +# +# Regression test for #4725 +clearStore +nix build --file ../simple.nix -L --no-link --post-build-hook "$pushToStore" +clearStore +rm -r "$REMOTE_STORE_DIR/realisations" +nix build --file ../simple.nix -L --no-link --substitute --substituters "$REMOTE_STORE" --no-require-sigs -j0 +# There's no easy way to check whether a realisation is present on the local +# store − short of manually querying the db, but the build environment doesn't +# have the sqlite binary − so we instead push things again, and check that the +# realisations have correctly been pushed to the remote store +nix copy --to "$REMOTE_STORE" --file ../simple.nix +if [[ -z "$(ls "$REMOTE_STORE_DIR/realisations")" ]]; then + echo "Realisations not rebuilt" + exit 1 +fi + +# Test the local realisation disk cache +buildDrvs --post-build-hook "$pushToStore" +clearStore +# Add the realisations of rootCA to the cachecache +clearCacheCache +export _NIX_FORCE_HTTP=1 +buildDrvs --substitute --substituters $REMOTE_STORE --no-require-sigs -j0 +# Try rebuilding, but remove the realisations from the remote cache to force +# using the cachecache +clearStore +rm $REMOTE_STORE_DIR/realisations/* +buildDrvs --substitute --substituters $REMOTE_STORE --no-require-sigs -j0 diff --git a/tests/functional/ca/why-depends.sh b/tests/functional/ca/why-depends.sh new file mode 100644 index 000000000..0c079f63b --- /dev/null +++ b/tests/functional/ca/why-depends.sh @@ -0,0 +1,5 @@ +source common.sh + +export NIX_TESTS_CA_BY_DEFAULT=1 + +cd .. && source why-depends.sh diff --git a/tests/functional/case-hack.sh b/tests/functional/case-hack.sh new file mode 100644 index 000000000..61bf9b94b --- /dev/null +++ b/tests/functional/case-hack.sh @@ -0,0 +1,19 @@ +source common.sh + +clearStore + +rm -rf $TEST_ROOT/case + +opts="--option use-case-hack true" + +# Check whether restoring and dumping a NAR that contains case +# collisions is round-tripping, even on a case-insensitive system. +nix-store $opts --restore $TEST_ROOT/case < case.nar +nix-store $opts --dump $TEST_ROOT/case > $TEST_ROOT/case.nar +cmp case.nar $TEST_ROOT/case.nar +[ "$(nix-hash $opts --type sha256 $TEST_ROOT/case)" = "$(nix-hash --flat --type sha256 case.nar)" ] + +# Check whether we detect true collisions (e.g. those remaining after +# removal of the suffix). +touch "$TEST_ROOT/case/xt_CONNMARK.h~nix~case~hack~3" +(! nix-store $opts --dump $TEST_ROOT/case > /dev/null) diff --git a/tests/functional/case.nar b/tests/functional/case.nar new file mode 100644 index 000000000..22ff26db5 Binary files /dev/null and b/tests/functional/case.nar differ diff --git a/tests/functional/check-refs.nix b/tests/functional/check-refs.nix new file mode 100644 index 000000000..89690e456 --- /dev/null +++ b/tests/functional/check-refs.nix @@ -0,0 +1,77 @@ +with import ./config.nix; + +rec { + + dep = import ./dependencies.nix {}; + + makeTest = nr: args: mkDerivation ({ + name = "check-refs-" + toString nr; + } // args); + + src = builtins.toFile "aux-ref" "bla bla"; + + test1 = makeTest 1 { + builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $dep $out/link"; + inherit dep; + }; + + test2 = makeTest 2 { + builder = builtins.toFile "builder.sh" "mkdir $out; ln -s ${src} $out/link"; + inherit dep; + }; + + test3 = makeTest 3 { + builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $dep $out/link"; + allowedReferences = []; + inherit dep; + }; + + test4 = makeTest 4 { + builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $dep $out/link"; + allowedReferences = [dep]; + inherit dep; + }; + + test5 = makeTest 5 { + builder = builtins.toFile "builder.sh" "mkdir $out"; + allowedReferences = []; + inherit dep; + }; + + test6 = makeTest 6 { + builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $out $out/link"; + allowedReferences = []; + inherit dep; + }; + + test7 = makeTest 7 { + builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $out $out/link"; + allowedReferences = ["out"]; + inherit dep; + }; + + test8 = makeTest 8 { + builder = builtins.toFile "builder.sh" "mkdir $out; ln -s ${test1} $out/link"; + inherit dep; + }; + + test9 = makeTest 9 { + builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $dep $out/link"; + inherit dep; + disallowedReferences = [dep]; + }; + + test10 = makeTest 10 { + builder = builtins.toFile "builder.sh" "mkdir $out; echo $test5; ln -s $dep $out/link"; + inherit dep test5; + disallowedReferences = [test5]; + }; + + test11 = makeTest 11 { + __structuredAttrs = true; + unsafeDiscardReferences.out = true; + outputChecks.out.allowedReferences = []; + buildCommand = ''echo ${dep} > "''${outputs[out]}"''; + }; + +} diff --git a/tests/functional/check-refs.sh b/tests/functional/check-refs.sh new file mode 100644 index 000000000..3b587d1e5 --- /dev/null +++ b/tests/functional/check-refs.sh @@ -0,0 +1,53 @@ +source common.sh + +clearStore + +RESULT=$TEST_ROOT/result + +dep=$(nix-build -o $RESULT check-refs.nix -A dep) + +# test1 references dep, not itself. +test1=$(nix-build -o $RESULT check-refs.nix -A test1) +nix-store -q --references $test1 | grepQuietInverse $test1 +nix-store -q --references $test1 | grepQuiet $dep + +# test2 references src, not itself nor dep. +test2=$(nix-build -o $RESULT check-refs.nix -A test2) +nix-store -q --references $test2 | grepQuietInverse $test2 +nix-store -q --references $test2 | grepQuietInverse $dep +nix-store -q --references $test2 | grepQuiet aux-ref + +# test3 should fail (unallowed ref). +(! nix-build -o $RESULT check-refs.nix -A test3) + +# test4 should succeed. +nix-build -o $RESULT check-refs.nix -A test4 + +# test5 should succeed. +nix-build -o $RESULT check-refs.nix -A test5 + +# test6 should fail (unallowed self-ref). +(! nix-build -o $RESULT check-refs.nix -A test6) + +# test7 should succeed (allowed self-ref). +nix-build -o $RESULT check-refs.nix -A test7 + +# test8 should fail (toFile depending on derivation output). +(! nix-build -o $RESULT check-refs.nix -A test8) + +# test9 should fail (disallowed reference). +(! nix-build -o $RESULT check-refs.nix -A test9) + +# test10 should succeed (no disallowed references). +nix-build -o $RESULT check-refs.nix -A test10 + +if isDaemonNewer 2.12pre20230103; then + if ! isDaemonNewer 2.16.0; then + enableFeatures discard-references + restartDaemon + fi + + # test11 should succeed. + test11=$(nix-build -o $RESULT check-refs.nix -A test11) + [[ -z $(nix-store -q --references "$test11") ]] +fi diff --git a/tests/functional/check-reqs.nix b/tests/functional/check-reqs.nix new file mode 100644 index 000000000..41436cb48 --- /dev/null +++ b/tests/functional/check-reqs.nix @@ -0,0 +1,57 @@ +with import ./config.nix; + +rec { + dep1 = mkDerivation { + name = "check-reqs-dep1"; + builder = builtins.toFile "builder.sh" "mkdir $out; touch $out/file1"; + }; + + dep2 = mkDerivation { + name = "check-reqs-dep2"; + builder = builtins.toFile "builder.sh" "mkdir $out; touch $out/file2"; + }; + + deps = mkDerivation { + name = "check-reqs-deps"; + dep1 = dep1; + dep2 = dep2; + builder = builtins.toFile "builder.sh" '' + mkdir $out + ln -s $dep1/file1 $out/file1 + ln -s $dep2/file2 $out/file2 + ''; + }; + + makeTest = nr: allowreqs: mkDerivation { + name = "check-reqs-" + toString nr; + inherit deps; + builder = builtins.toFile "builder.sh" '' + mkdir $out + ln -s $deps $out/depdir1 + ''; + allowedRequisites = allowreqs; + }; + + # When specifying all the requisites, the build succeeds. + test1 = makeTest 1 [ dep1 dep2 deps ]; + + # But missing anything it fails. + test2 = makeTest 2 [ dep2 deps ]; + test3 = makeTest 3 [ dep1 deps ]; + test4 = makeTest 4 [ deps ]; + test5 = makeTest 5 []; + + test6 = mkDerivation { + name = "check-reqs"; + inherit deps; + builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $deps $out/depdir1"; + disallowedRequisites = [dep1]; + }; + + test7 = mkDerivation { + name = "check-reqs"; + inherit deps; + builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $deps $out/depdir1"; + disallowedRequisites = [test1]; + }; +} diff --git a/tests/functional/check-reqs.sh b/tests/functional/check-reqs.sh new file mode 100644 index 000000000..856c94cec --- /dev/null +++ b/tests/functional/check-reqs.sh @@ -0,0 +1,16 @@ +source common.sh + +clearStore + +RESULT=$TEST_ROOT/result + +nix-build -o $RESULT check-reqs.nix -A test1 + +(! nix-build -o $RESULT check-reqs.nix -A test2) +(! nix-build -o $RESULT check-reqs.nix -A test3) +(! nix-build -o $RESULT check-reqs.nix -A test4) 2>&1 | grepQuiet 'check-reqs-dep1' +(! nix-build -o $RESULT check-reqs.nix -A test4) 2>&1 | grepQuiet 'check-reqs-dep2' +(! nix-build -o $RESULT check-reqs.nix -A test5) +(! nix-build -o $RESULT check-reqs.nix -A test6) + +nix-build -o $RESULT check-reqs.nix -A test7 diff --git a/tests/functional/check.nix b/tests/functional/check.nix new file mode 100644 index 000000000..ddab8eea9 --- /dev/null +++ b/tests/functional/check.nix @@ -0,0 +1,55 @@ +{checkBuildId ? 0}: + +with import ./config.nix; + +{ + nondeterministic = mkDerivation { + inherit checkBuildId; + name = "nondeterministic"; + buildCommand = + '' + mkdir $out + date +%s.%N > $out/date + echo "CHECK_TMPDIR=$TMPDIR" + echo "checkBuildId=$checkBuildId" + echo "$checkBuildId" > $TMPDIR/checkBuildId + ''; + }; + + deterministic = mkDerivation { + inherit checkBuildId; + name = "deterministic"; + buildCommand = + '' + mkdir $out + echo date > $out/date + echo "CHECK_TMPDIR=$TMPDIR" + echo "checkBuildId=$checkBuildId" + echo "$checkBuildId" > $TMPDIR/checkBuildId + ''; + }; + + failed = mkDerivation { + inherit checkBuildId; + name = "failed"; + buildCommand = + '' + mkdir $out + echo date > $out/date + echo "CHECK_TMPDIR=$TMPDIR" + echo "checkBuildId=$checkBuildId" + echo "$checkBuildId" > $TMPDIR/checkBuildId + false + ''; + }; + + hashmismatch = import { + url = "file://" + builtins.getEnv "TEST_ROOT" + "/dummy"; + sha256 = "0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73"; + }; + + fetchurl = import { + url = "file://" + toString ./lang/eval-okay-xml.exp.xml; + sha256 = "sha256-behBlX+DQK/Pjvkuc8Tx68Jwi4E5v86wDq+ZLaHyhQE="; + }; +} diff --git a/tests/functional/check.sh b/tests/functional/check.sh new file mode 100644 index 000000000..e13abf747 --- /dev/null +++ b/tests/functional/check.sh @@ -0,0 +1,91 @@ +source common.sh + +# XXX: This shouldn’t be, but #4813 cause this test to fail +buggyNeedLocalStore "see #4813" + +checkBuildTempDirRemoved () +{ + buildDir=$(sed -n 's/CHECK_TMPDIR=//p' $1 | head -1) + checkBuildIdFile=${buildDir}/checkBuildId + [[ ! -f $checkBuildIdFile ]] || ! grep $checkBuildId $checkBuildIdFile +} + +# written to build temp directories to verify created by this instance +checkBuildId=$(date +%s%N) + +clearStore + +nix-build dependencies.nix --no-out-link +nix-build dependencies.nix --no-out-link --check + +# Build failure exit codes (100, 104, etc.) are from +# doc/manual/src/command-ref/status-build-failure.md + +# check for dangling temporary build directories +# only retain if build fails and --keep-failed is specified, or... +# ...build is non-deterministic and --check and --keep-failed are both specified +nix-build check.nix -A failed --argstr checkBuildId $checkBuildId \ + --no-out-link 2> $TEST_ROOT/log || status=$? +[ "$status" = "100" ] +checkBuildTempDirRemoved $TEST_ROOT/log + +nix-build check.nix -A failed --argstr checkBuildId $checkBuildId \ + --no-out-link --keep-failed 2> $TEST_ROOT/log || status=$? +[ "$status" = "100" ] +if checkBuildTempDirRemoved $TEST_ROOT/log; then false; fi + +nix-build check.nix -A deterministic --argstr checkBuildId $checkBuildId \ + --no-out-link 2> $TEST_ROOT/log +checkBuildTempDirRemoved $TEST_ROOT/log + +nix-build check.nix -A deterministic --argstr checkBuildId $checkBuildId \ + --no-out-link --check --keep-failed 2> $TEST_ROOT/log +if grepQuiet 'may not be deterministic' $TEST_ROOT/log; then false; fi +checkBuildTempDirRemoved $TEST_ROOT/log + +nix-build check.nix -A nondeterministic --argstr checkBuildId $checkBuildId \ + --no-out-link 2> $TEST_ROOT/log +checkBuildTempDirRemoved $TEST_ROOT/log + +nix-build check.nix -A nondeterministic --argstr checkBuildId $checkBuildId \ + --no-out-link --check 2> $TEST_ROOT/log || status=$? +grep 'may not be deterministic' $TEST_ROOT/log +[ "$status" = "104" ] +checkBuildTempDirRemoved $TEST_ROOT/log + +nix-build check.nix -A nondeterministic --argstr checkBuildId $checkBuildId \ + --no-out-link --check --keep-failed 2> $TEST_ROOT/log || status=$? +grep 'may not be deterministic' $TEST_ROOT/log +[ "$status" = "104" ] +if checkBuildTempDirRemoved $TEST_ROOT/log; then false; fi + +clearStore + +path=$(nix-build check.nix -A fetchurl --no-out-link) + +chmod +w $path +echo foo > $path +chmod -w $path + +nix-build check.nix -A fetchurl --no-out-link --check +# Note: "check" doesn't repair anything, it just compares to the hash stored in the database. +[[ $(cat $path) = foo ]] + +nix-build check.nix -A fetchurl --no-out-link --repair +[[ $(cat $path) != foo ]] + +echo 'Hello World' > $TEST_ROOT/dummy +nix-build check.nix -A hashmismatch --no-out-link || status=$? +[ "$status" = "102" ] + +echo -n > $TEST_ROOT/dummy +nix-build check.nix -A hashmismatch --no-out-link +echo 'Hello World' > $TEST_ROOT/dummy + +nix-build check.nix -A hashmismatch --no-out-link --check || status=$? +[ "$status" = "102" ] + +# Multiple failures with --keep-going +nix-build check.nix -A nondeterministic --no-out-link +nix-build check.nix -A nondeterministic -A hashmismatch --no-out-link --check --keep-going || status=$? +[ "$status" = "110" ] diff --git a/tests/functional/common.sh b/tests/functional/common.sh new file mode 100644 index 000000000..7b0922c9f --- /dev/null +++ b/tests/functional/common.sh @@ -0,0 +1,12 @@ +set -eu -o pipefail + +if [[ -z "${COMMON_SH_SOURCED-}" ]]; then + +COMMON_SH_SOURCED=1 + +source "$(readlink -f "$(dirname "${BASH_SOURCE[0]-$0}")")/common/vars-and-functions.sh" +if [[ -n "${NIX_DAEMON_PACKAGE:-}" ]]; then + startDaemon +fi + +fi # COMMON_SH_SOURCED diff --git a/tests/functional/common/vars-and-functions.sh.in b/tests/functional/common/vars-and-functions.sh.in new file mode 100644 index 000000000..967d6be54 --- /dev/null +++ b/tests/functional/common/vars-and-functions.sh.in @@ -0,0 +1,276 @@ +set -eu -o pipefail + +if [[ -z "${COMMON_VARS_AND_FUNCTIONS_SH_SOURCED-}" ]]; then + +COMMON_VARS_AND_FUNCTIONS_SH_SOURCED=1 + +export PS4='+(${BASH_SOURCE[0]-$0}:$LINENO) ' + +export TEST_ROOT=$(realpath ${TMPDIR:-/tmp}/nix-test)/${TEST_NAME:-default/tests\/functional//} +export NIX_STORE_DIR +if ! NIX_STORE_DIR=$(readlink -f $TEST_ROOT/store 2> /dev/null); then + # Maybe the build directory is symlinked. + export NIX_IGNORE_SYMLINK_STORE=1 + NIX_STORE_DIR=$TEST_ROOT/store +fi +export NIX_LOCALSTATE_DIR=$TEST_ROOT/var +export NIX_LOG_DIR=$TEST_ROOT/var/log/nix +export NIX_STATE_DIR=$TEST_ROOT/var/nix +export NIX_CONF_DIR=$TEST_ROOT/etc +export NIX_DAEMON_SOCKET_PATH=$TEST_ROOT/dSocket +unset NIX_USER_CONF_FILES +export _NIX_TEST_SHARED=$TEST_ROOT/shared +if [[ -n $NIX_STORE ]]; then + export _NIX_TEST_NO_SANDBOX=1 +fi +export _NIX_IN_TEST=$TEST_ROOT/shared +export _NIX_TEST_NO_LSOF=1 +export NIX_REMOTE=${NIX_REMOTE_-} +unset NIX_PATH +export TEST_HOME=$TEST_ROOT/test-home +export HOME=$TEST_HOME +unset XDG_STATE_HOME +unset XDG_DATA_HOME +unset XDG_CONFIG_HOME +unset XDG_CONFIG_DIRS +unset XDG_CACHE_HOME +mkdir -p $TEST_HOME + +export PATH=@bindir@:$PATH +if [[ -n "${NIX_CLIENT_PACKAGE:-}" ]]; then + export PATH="$NIX_CLIENT_PACKAGE/bin":$PATH +fi +DAEMON_PATH="$PATH" +if [[ -n "${NIX_DAEMON_PACKAGE:-}" ]]; then + DAEMON_PATH="${NIX_DAEMON_PACKAGE}/bin:$DAEMON_PATH" +fi +coreutils=@coreutils@ + +export dot=@dot@ +export SHELL="@bash@" +export PAGER=cat +export busybox="@sandbox_shell@" + +export version=@PACKAGE_VERSION@ +export system=@system@ + +export BUILD_SHARED_LIBS=@BUILD_SHARED_LIBS@ + +export IMPURE_VAR1=foo +export IMPURE_VAR2=bar + +cacheDir=$TEST_ROOT/binary-cache + +readLink() { + ls -l "$1" | sed 's/.*->\ //' +} + +clearProfiles() { + profiles="$HOME"/.local/state/nix/profiles + rm -rf "$profiles" +} + +clearStore() { + echo "clearing store..." + chmod -R +w "$NIX_STORE_DIR" + rm -rf "$NIX_STORE_DIR" + mkdir "$NIX_STORE_DIR" + rm -rf "$NIX_STATE_DIR" + mkdir "$NIX_STATE_DIR" + clearProfiles +} + +clearCache() { + rm -rf "$cacheDir" +} + +clearCacheCache() { + rm -f $TEST_HOME/.cache/nix/binary-cache* +} + +startDaemon() { + # Don’t start the daemon twice, as this would just make it loop indefinitely + if [[ "${_NIX_TEST_DAEMON_PID-}" != '' ]]; then + return + fi + # Start the daemon, wait for the socket to appear. + rm -f $NIX_DAEMON_SOCKET_PATH + PATH=$DAEMON_PATH nix-daemon & + _NIX_TEST_DAEMON_PID=$! + export _NIX_TEST_DAEMON_PID + for ((i = 0; i < 300; i++)); do + if [[ -S $NIX_DAEMON_SOCKET_PATH ]]; then + DAEMON_STARTED=1 + break; + fi + sleep 0.1 + done + if [[ -z ${DAEMON_STARTED+x} ]]; then + fail "Didn’t manage to start the daemon" + fi + trap "killDaemon" EXIT + # Save for if daemon is killed + NIX_REMOTE_OLD=$NIX_REMOTE + export NIX_REMOTE=daemon +} + +killDaemon() { + # Don’t fail trying to stop a non-existant daemon twice + if [[ "${_NIX_TEST_DAEMON_PID-}" == '' ]]; then + return + fi + kill $_NIX_TEST_DAEMON_PID + for i in {0..100}; do + kill -0 $_NIX_TEST_DAEMON_PID 2> /dev/null || break + sleep 0.1 + done + kill -9 $_NIX_TEST_DAEMON_PID 2> /dev/null || true + wait $_NIX_TEST_DAEMON_PID || true + rm -f $NIX_DAEMON_SOCKET_PATH + # Indicate daemon is stopped + unset _NIX_TEST_DAEMON_PID + # Restore old nix remote + NIX_REMOTE=$NIX_REMOTE_OLD + trap "" EXIT +} + +restartDaemon() { + [[ -z "${_NIX_TEST_DAEMON_PID:-}" ]] && return 0 + + killDaemon + startDaemon +} + +if [[ $(uname) == Linux ]] && [[ -L /proc/self/ns/user ]] && unshare --user true; then + _canUseSandbox=1 +fi + +isDaemonNewer () { + [[ -n "${NIX_DAEMON_PACKAGE:-}" ]] || return 0 + local requiredVersion="$1" + local daemonVersion=$($NIX_DAEMON_PACKAGE/bin/nix-daemon --version | cut -d' ' -f3) + [[ $(nix eval --expr "builtins.compareVersions ''$daemonVersion'' ''$requiredVersion''") -ge 0 ]] +} + +skipTest () { + echo "$1, skipping this test..." >&2 + exit 99 +} + +requireDaemonNewerThan () { + isDaemonNewer "$1" || skipTest "Daemon is too old" +} + +canUseSandbox() { + [[ ${_canUseSandbox-} ]] +} + +requireSandboxSupport () { + canUseSandbox || skipTest "Sandboxing not supported" +} + +requireGit() { + [[ $(type -p git) ]] || skipTest "Git not installed" +} + +fail() { + echo "$1" >&2 + exit 1 +} + +# Run a command failing if it didn't exit with the expected exit code. +# +# Has two advantages over the built-in `!`: +# +# 1. `!` conflates all non-0 codes. `expect` allows testing for an exact +# code. +# +# 2. `!` unexpectedly negates `set -e`, and cannot be used on individual +# pipeline stages with `set -o pipefail`. It only works on the entire +# pipeline, which is useless if we want, say, `nix ...` invocation to +# *fail*, but a grep on the error message it outputs to *succeed*. +expect() { + local expected res + expected="$1" + shift + "$@" && res=0 || res="$?" + if [[ $res -ne $expected ]]; then + echo "Expected exit code '$expected' but got '$res' from command ${*@Q}" >&2 + return 1 + fi + return 0 +} + +# Better than just doing `expect ... >&2` because the "Expected..." +# message below will *not* be redirected. +expectStderr() { + local expected res + expected="$1" + shift + "$@" 2>&1 && res=0 || res="$?" + if [[ $res -ne $expected ]]; then + echo "Expected exit code '$expected' but got '$res' from command ${*@Q}" >&2 + return 1 + fi + return 0 +} + +needLocalStore() { + if [[ "$NIX_REMOTE" == "daemon" ]]; then + skipTest "Can’t run through the daemon ($1)" + fi +} + +# Just to make it easy to find which tests should be fixed +buggyNeedLocalStore() { + needLocalStore "$1" +} + +enableFeatures() { + local features="$1" + sed -i 's/experimental-features .*/& '"$features"'/' "$NIX_CONF_DIR"/nix.conf +} + +set -x + +onError() { + set +x + echo "$0: test failed at:" >&2 + for ((i = 1; i < ${#BASH_SOURCE[@]}; i++)); do + if [[ -z ${BASH_SOURCE[i]} ]]; then break; fi + echo " ${FUNCNAME[i]} in ${BASH_SOURCE[i]}:${BASH_LINENO[i-1]}" >&2 + done +} + +# `grep -v` doesn't work well for exit codes. We want `!(exist line l. l +# matches)`. It gives us `exist line l. !(l matches)`. +# +# `!` normally doesn't work well with `set -e`, but when we wrap in a +# function it *does*. +grepInverse() { + ! grep "$@" +} + +# A shorthand, `> /dev/null` is a bit noisy. +# +# `grep -q` would seem to do this, no function necessary, but it is a +# bad fit with pipes and `set -o pipefail`: `-q` will exit after the +# first match, and then subsequent writes will result in broken pipes. +# +# Note that reproducing the above is a bit tricky as it depends on +# non-deterministic properties such as the timing between the match and +# the closing of the pipe, the buffering of the pipe, and the speed of +# the producer into the pipe. But rest assured we've seen it happen in +# CI reliably. +grepQuiet() { + grep "$@" > /dev/null +} + +# The previous two, combined +grepQuietInverse() { + ! grep "$@" > /dev/null +} + +trap onError ERR + +fi # COMMON_VARS_AND_FUNCTIONS_SH_SOURCED diff --git a/tests/functional/completions.sh b/tests/functional/completions.sh new file mode 100644 index 000000000..19dc61098 --- /dev/null +++ b/tests/functional/completions.sh @@ -0,0 +1,68 @@ +source common.sh + +cd "$TEST_ROOT" + +mkdir -p dep +cat < dep/flake.nix +{ + outputs = i: { }; +} +EOF +mkdir -p foo +cat < foo/flake.nix +{ + inputs.a.url = "path:$(realpath dep)"; + + outputs = i: { + sampleOutput = 1; + }; +} +EOF +mkdir -p bar +cat < bar/flake.nix +{ + inputs.b.url = "path:$(realpath dep)"; + + outputs = i: { + sampleOutput = 1; + }; +} +EOF +mkdir -p err +cat < err/flake.nix +throw "error" +EOF + +# Test the completion of a subcommand +[[ "$(NIX_GET_COMPLETIONS=1 nix buil)" == $'normal\nbuild\t' ]] +[[ "$(NIX_GET_COMPLETIONS=2 nix flake metad)" == $'normal\nmetadata\t' ]] + +# Filename completion +[[ "$(NIX_GET_COMPLETIONS=2 nix build ./f)" == $'filenames\n./foo\t' ]] +[[ "$(NIX_GET_COMPLETIONS=2 nix build ./nonexistent)" == $'filenames' ]] + +# Input override completion +[[ "$(NIX_GET_COMPLETIONS=4 nix build ./foo --override-input '')" == $'normal\na\t' ]] +[[ "$(NIX_GET_COMPLETIONS=5 nix flake show ./foo --override-input '')" == $'normal\na\t' ]] +## With multiple input flakes +[[ "$(NIX_GET_COMPLETIONS=5 nix build ./foo ./bar --override-input '')" == $'normal\na\t\nb\t' ]] +## With tilde expansion +[[ "$(HOME=$PWD NIX_GET_COMPLETIONS=4 nix build '~/foo' --override-input '')" == $'normal\na\t' ]] +## Out of order +[[ "$(NIX_GET_COMPLETIONS=3 nix build --update-input '' ./foo)" == $'normal\na\t' ]] +[[ "$(NIX_GET_COMPLETIONS=4 nix build ./foo --update-input '' ./bar)" == $'normal\na\t\nb\t' ]] + +# Cli flag completion +NIX_GET_COMPLETIONS=2 nix build --log-form | grep -- "--log-format" + +# Config option completion +## With `--option` +NIX_GET_COMPLETIONS=3 nix build --option allow-import-from | grep -- "allow-import-from-derivation" +## As a cli flag – not working atm +# NIX_GET_COMPLETIONS=2 nix build --allow-import-from | grep -- "allow-import-from-derivation" + +# Attr path completions +[[ "$(NIX_GET_COMPLETIONS=2 nix eval ./foo\#sam)" == $'attrs\n./foo#sampleOutput\t' ]] +[[ "$(NIX_GET_COMPLETIONS=4 nix eval --file ./foo/flake.nix outp)" == $'attrs\noutputs\t' ]] +[[ "$(NIX_GET_COMPLETIONS=4 nix eval --file ./err/flake.nix outp 2>&1)" == $'attrs' ]] +[[ "$(NIX_GET_COMPLETIONS=2 nix eval ./err\# 2>&1)" == $'attrs' ]] diff --git a/tests/functional/compression-levels.sh b/tests/functional/compression-levels.sh new file mode 100644 index 000000000..85f12974a --- /dev/null +++ b/tests/functional/compression-levels.sh @@ -0,0 +1,22 @@ +source common.sh + +clearStore +clearCache + +outPath=$(nix-build dependencies.nix --no-out-link) + +cacheURI="file://$cacheDir?compression=xz&compression-level=0" + +nix copy --to $cacheURI $outPath + +FILESIZES=$(cat ${cacheDir}/*.narinfo | awk '/FileSize: /{sum+=$2}END{print sum}') + +clearCache + +cacheURI="file://$cacheDir?compression=xz&compression-level=5" + +nix copy --to $cacheURI $outPath + +FILESIZES2=$(cat ${cacheDir}/*.narinfo | awk '/FileSize: /{sum+=$2}END{print sum}') + +[[ $FILESIZES -gt $FILESIZES2 ]] diff --git a/tests/functional/compute-levels.sh b/tests/functional/compute-levels.sh new file mode 100644 index 000000000..de3da2ebd --- /dev/null +++ b/tests/functional/compute-levels.sh @@ -0,0 +1,7 @@ +source common.sh + +if [[ $(uname -ms) = "Linux x86_64" ]]; then + # x86_64 CPUs must always support the baseline + # microarchitecture level. + nix -vv --version | grepQuiet "x86_64-v1-linux" +fi diff --git a/tests/functional/config.nix.in b/tests/functional/config.nix.in new file mode 100644 index 000000000..7facbdcbc --- /dev/null +++ b/tests/functional/config.nix.in @@ -0,0 +1,27 @@ +let + contentAddressedByDefault = builtins.getEnv "NIX_TESTS_CA_BY_DEFAULT" == "1"; + caArgs = if contentAddressedByDefault then { + __contentAddressed = true; + outputHashMode = "recursive"; + outputHashAlgo = "sha256"; + } else {}; +in + +rec { + shell = "@bash@"; + + path = "@coreutils@"; + + system = "@system@"; + + shared = builtins.getEnv "_NIX_TEST_SHARED"; + + mkDerivation = args: + derivation ({ + inherit system; + builder = shell; + args = ["-e" args.builder or (builtins.toFile "builder-${args.name}.sh" "if [ -e .attrs.sh ]; then source .attrs.sh; fi; eval \"$buildCommand\"")]; + PATH = path; + } // caArgs // removeAttrs args ["builder" "meta"]) + // { meta = args.meta or {}; }; +} diff --git a/tests/functional/config.sh b/tests/functional/config.sh new file mode 100644 index 000000000..723f575ed --- /dev/null +++ b/tests/functional/config.sh @@ -0,0 +1,58 @@ +source common.sh + +# Isolate the home for this test. +# Other tests (e.g. flake registry tests) could be writing to $HOME in parallel. +export HOME=$TEST_ROOT/userhome + +# Test that using XDG_CONFIG_HOME works +# Assert the config folder didn't exist initially. +[ ! -e "$HOME/.config" ] +# Without XDG_CONFIG_HOME, creates $HOME/.config +unset XDG_CONFIG_HOME +# Run against the nix registry to create the config dir +# (Tip: this relies on removing non-existent entries being a no-op!) +nix registry remove userhome-without-xdg +# Verifies it created it +[ -e "$HOME/.config" ] +# Remove the directory it created +rm -rf "$HOME/.config" +# Run the same test, but with XDG_CONFIG_HOME +export XDG_CONFIG_HOME=$TEST_ROOT/confighome +# Assert the XDG_CONFIG_HOME/nix path does not exist yet. +[ ! -e "$TEST_ROOT/confighome/nix" ] +nix registry remove userhome-with-xdg +# Verifies the confighome path has been created +[ -e "$TEST_ROOT/confighome/nix" ] +# Assert the .config folder hasn't been created. +[ ! -e "$HOME/.config" ] + +# Test that files are loaded from XDG by default +export XDG_CONFIG_HOME=$TEST_ROOT/confighome +export XDG_CONFIG_DIRS=$TEST_ROOT/dir1:$TEST_ROOT/dir2 +files=$(nix-build --verbose --version | grep "User config" | cut -d ':' -f2- | xargs) +[[ $files == "$TEST_ROOT/confighome/nix/nix.conf:$TEST_ROOT/dir1/nix/nix.conf:$TEST_ROOT/dir2/nix/nix.conf" ]] + +# Test that setting NIX_USER_CONF_FILES overrides all the default user config files +export NIX_USER_CONF_FILES=$TEST_ROOT/file1.conf:$TEST_ROOT/file2.conf +files=$(nix-build --verbose --version | grep "User config" | cut -d ':' -f2- | xargs) +[[ $files == "$TEST_ROOT/file1.conf:$TEST_ROOT/file2.conf" ]] + +# Test that it's possible to load the config from a custom location +here=$(readlink -f "$(dirname "${BASH_SOURCE[0]}")") +export NIX_USER_CONF_FILES=$here/config/nix-with-substituters.conf +var=$(nix show-config | grep '^substituters =' | cut -d '=' -f 2 | xargs) +[[ $var == https://example.com ]] + +# Test that it's possible to load config from the environment +prev=$(nix show-config | grep '^cores' | cut -d '=' -f 2 | xargs) +export NIX_CONFIG="cores = 4242"$'\n'"experimental-features = nix-command flakes" +exp_cores=$(nix show-config | grep '^cores' | cut -d '=' -f 2 | xargs) +exp_features=$(nix show-config | grep '^experimental-features' | cut -d '=' -f 2 | xargs) +[[ $prev != $exp_cores ]] +[[ $exp_cores == "4242" ]] +[[ $exp_features == "flakes nix-command" ]] + +# Test that it's possible to retrieve a single setting's value +val=$(nix show-config | grep '^warn-dirty' | cut -d '=' -f 2 | xargs) +val2=$(nix show-config warn-dirty) +[[ $val == $val2 ]] diff --git a/tests/functional/config/nix-with-substituters.conf b/tests/functional/config/nix-with-substituters.conf new file mode 100644 index 000000000..90f359a6f --- /dev/null +++ b/tests/functional/config/nix-with-substituters.conf @@ -0,0 +1,2 @@ +experimental-features = nix-command +substituters = https://example.com diff --git a/tests/functional/db-migration.sh b/tests/functional/db-migration.sh new file mode 100644 index 000000000..44cd16bc0 --- /dev/null +++ b/tests/functional/db-migration.sh @@ -0,0 +1,28 @@ +# Test that we can successfully migrate from an older db schema + +source common.sh + +# Only run this if we have an older Nix available +# XXX: This assumes that the `daemon` package is older than the `client` one +if [[ -z "${NIX_DAEMON_PACKAGE-}" ]]; then + skipTest "not using the Nix daemon" +fi + +killDaemon + +# Fill the db using the older Nix +PATH_WITH_NEW_NIX="$PATH" +export PATH="${NIX_DAEMON_PACKAGE}/bin:$PATH" +clearStore +nix-build simple.nix --no-out-link +nix-store --generate-binary-cache-key cache1.example.org $TEST_ROOT/sk1 $TEST_ROOT/pk1 +dependenciesOutPath=$(nix-build dependencies.nix --no-out-link --secret-key-files "$TEST_ROOT/sk1") +fixedOutPath=$(IMPURE_VAR1=foo IMPURE_VAR2=bar nix-build fixed.nix -A good.0 --no-out-link) + +# Migrate to the new schema and ensure that everything's there +export PATH="$PATH_WITH_NEW_NIX" +info=$(nix path-info --json $dependenciesOutPath) +[[ $info =~ '"ultimate":true' ]] +[[ $info =~ 'cache1.example.org' ]] +nix verify -r "$fixedOutPath" +nix verify -r "$dependenciesOutPath" --sigs-needed 1 --trusted-public-keys $(cat $TEST_ROOT/pk1) diff --git a/tests/functional/dependencies.builder0.sh b/tests/functional/dependencies.builder0.sh new file mode 100644 index 000000000..9b11576e0 --- /dev/null +++ b/tests/functional/dependencies.builder0.sh @@ -0,0 +1,16 @@ +[ "${input1: -2}" = /. ] +[ "${input2: -2}" = /. ] + +mkdir $out +echo $(cat $input1/foo)$(cat $input2/bar) > $out/foobar + +ln -s $input2 $out/reference-to-input-2 + +# Self-reference. +ln -s $out $out/self + +# Executable. +echo program > $out/program +chmod +x $out/program + +echo FOO diff --git a/tests/functional/dependencies.nix b/tests/functional/dependencies.nix new file mode 100644 index 000000000..be1a7ae9a --- /dev/null +++ b/tests/functional/dependencies.nix @@ -0,0 +1,48 @@ +{ hashInvalidator ? "" }: +with import ./config.nix; + +let { + + input0 = mkDerivation { + name = "dependencies-input-0"; + buildCommand = "mkdir $out; echo foo > $out/bar"; + }; + + input1 = mkDerivation { + name = "dependencies-input-1"; + buildCommand = "mkdir $out; echo FOO > $out/foo"; + }; + + input2 = mkDerivation { + name = "dependencies-input-2"; + buildCommand = '' + mkdir $out + echo BAR > $out/bar + echo ${input0} > $out/input0 + ''; + }; + + fod_input = mkDerivation { + name = "fod-input"; + buildCommand = '' + echo ${hashInvalidator} + echo FOD > $out + ''; + outputHashMode = "flat"; + outputHashAlgo = "sha256"; + outputHash = "1dq9p0hnm1y75q2x40fws5887bq1r840hzdxak0a9djbwvx0b16d"; + }; + + body = mkDerivation { + name = "dependencies-top"; + builder = ./dependencies.builder0.sh + "/FOOBAR/../."; + input1 = input1 + "/."; + input2 = "${input2}/."; + input1_drv = input1; + input2_drv = input2; + input0_drv = input0; + fod_input_drv = fod_input; + meta.description = "Random test package"; + }; + +} diff --git a/tests/functional/dependencies.sh b/tests/functional/dependencies.sh new file mode 100644 index 000000000..b93dacac0 --- /dev/null +++ b/tests/functional/dependencies.sh @@ -0,0 +1,72 @@ +source common.sh + +clearStore + +drvPath=$(nix-instantiate dependencies.nix) + +echo "derivation is $drvPath" + +nix-store -q --tree "$drvPath" | grep '───.*builder-dependencies-input-1.sh' + +# Test Graphviz graph generation. +nix-store -q --graph "$drvPath" > $TEST_ROOT/graph +if test -n "$dot"; then + # Does it parse? + $dot < $TEST_ROOT/graph +fi + +# Test GraphML graph generation +nix-store -q --graphml "$drvPath" > $TEST_ROOT/graphml + +outPath=$(nix-store -rvv "$drvPath") || fail "build failed" + +# Test Graphviz graph generation. +nix-store -q --graph "$outPath" > $TEST_ROOT/graph +if test -n "$dot"; then + # Does it parse? + $dot < $TEST_ROOT/graph +fi + +nix-store -q --tree "$outPath" | grep '───.*dependencies-input-2' + +echo "output path is $outPath" + +text=$(cat "$outPath"/foobar) +if test "$text" != "FOOBAR"; then exit 1; fi + +deps=$(nix-store -quR "$drvPath") + +echo "output closure contains $deps" + +# The output path should be in the closure. +echo "$deps" | grepQuiet "$outPath" + +# Input-1 is not retained. +if echo "$deps" | grepQuiet "dependencies-input-1"; then exit 1; fi + +# Input-2 is retained. +input2OutPath=$(echo "$deps" | grep "dependencies-input-2") + +# The referrers closure of input-2 should include outPath. +nix-store -q --referrers-closure "$input2OutPath" | grep "$outPath" + +# Check that the derivers are set properly. +test $(nix-store -q --deriver "$outPath") = "$drvPath" +nix-store -q --deriver "$input2OutPath" | grepQuiet -- "-input-2.drv" + +# --valid-derivers returns the currently single valid .drv file +test "$(nix-store -q --valid-derivers "$outPath")" = "$drvPath" + +# instantiate a different drv with the same output +drvPath2=$(nix-instantiate dependencies.nix --argstr hashInvalidator yay) + +# now --valid-derivers returns both +test "$(nix-store -q --valid-derivers "$outPath" | sort)" = "$(sort <<< "$drvPath"$'\n'"$drvPath2")" + +# check that nix-store --valid-derivers only returns existing drv +nix-store --delete "$drvPath" +test "$(nix-store -q --valid-derivers "$outPath")" = "$drvPath2" + +# check that --valid-derivers returns nothing when there are no valid derivers +nix-store --delete "$drvPath2" +test -z "$(nix-store -q --valid-derivers "$outPath")" diff --git a/tests/functional/derivation-json.sh b/tests/functional/derivation-json.sh new file mode 100644 index 000000000..b6be5d977 --- /dev/null +++ b/tests/functional/derivation-json.sh @@ -0,0 +1,12 @@ +source common.sh + +drvPath=$(nix-instantiate simple.nix) + +nix derivation show $drvPath | jq .[] > $TEST_HOME/simple.json + +drvPath2=$(nix derivation add < $TEST_HOME/simple.json) + +[[ "$drvPath" = "$drvPath2" ]] + +# Input addressed derivations cannot be renamed. +jq '.name = "foo"' < $TEST_HOME/simple.json | expectStderr 1 nix derivation add | grepQuiet "has incorrect output" diff --git a/tests/functional/dummy b/tests/functional/dummy new file mode 100644 index 000000000..557db03de --- /dev/null +++ b/tests/functional/dummy @@ -0,0 +1 @@ +Hello World diff --git a/tests/functional/dump-db.sh b/tests/functional/dump-db.sh new file mode 100644 index 000000000..48647f403 --- /dev/null +++ b/tests/functional/dump-db.sh @@ -0,0 +1,22 @@ +source common.sh + +needLocalStore "--dump-db requires a local store" + +clearStore + +path=$(nix-build dependencies.nix -o $TEST_ROOT/result) + +deps="$(nix-store -qR $TEST_ROOT/result)" + +nix-store --dump-db > $TEST_ROOT/dump + +rm -rf $NIX_STATE_DIR/db + +nix-store --load-db < $TEST_ROOT/dump + +deps2="$(nix-store -qR $TEST_ROOT/result)" + +[ "$deps" = "$deps2" ]; + +nix-store --dump-db > $TEST_ROOT/dump2 +cmp $TEST_ROOT/dump $TEST_ROOT/dump2 diff --git a/tests/functional/dyn-drv/build-built-drv.sh b/tests/functional/dyn-drv/build-built-drv.sh new file mode 100644 index 000000000..647be9457 --- /dev/null +++ b/tests/functional/dyn-drv/build-built-drv.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +source common.sh + +# In the corresponding nix file, we have two derivations: the first, named `hello`, +# is a normal recursive derivation, while the second, named dependent, has the +# new outputHashMode "text". Note that in "dependent", we don't refer to the +# build output of `hello`, but only to the path of the drv file. For this reason, +# we only need to: +# +# - instantiate `hello` +# - build `producingDrv` +# - check that the path of the output coincides with that of the original derivation + +out1=$(nix build -f ./text-hashed-output.nix hello --no-link) + +clearStore + +drvDep=$(nix-instantiate ./text-hashed-output.nix -A producingDrv) + +expectStderr 1 nix build "${drvDep}^out^out" --no-link | grepQuiet "Building dynamic derivations in one shot is not yet implemented" diff --git a/tests/functional/dyn-drv/common.sh b/tests/functional/dyn-drv/common.sh new file mode 100644 index 000000000..c786f6925 --- /dev/null +++ b/tests/functional/dyn-drv/common.sh @@ -0,0 +1,8 @@ +source ../common.sh + +# Need backend to support text-hashing too +requireDaemonNewerThan "2.16.0pre20230419" + +enableFeatures "ca-derivations dynamic-derivations" + +restartDaemon diff --git a/tests/functional/dyn-drv/config.nix.in b/tests/functional/dyn-drv/config.nix.in new file mode 120000 index 000000000..af24ddb30 --- /dev/null +++ b/tests/functional/dyn-drv/config.nix.in @@ -0,0 +1 @@ +../config.nix.in \ No newline at end of file diff --git a/tests/functional/dyn-drv/dep-built-drv.sh b/tests/functional/dyn-drv/dep-built-drv.sh new file mode 100644 index 000000000..4f6e9b080 --- /dev/null +++ b/tests/functional/dyn-drv/dep-built-drv.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +source common.sh + +out1=$(nix-build ./text-hashed-output.nix -A hello --no-out-link) + +clearStore + +expectStderr 1 nix-build ./text-hashed-output.nix -A wrapper --no-out-link | grepQuiet "Building dynamic derivations in one shot is not yet implemented" + +# diff -r $out1 $out2 diff --git a/tests/functional/dyn-drv/eval-outputOf.sh b/tests/functional/dyn-drv/eval-outputOf.sh new file mode 100644 index 000000000..9467feb8d --- /dev/null +++ b/tests/functional/dyn-drv/eval-outputOf.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash + +source ./common.sh + +# Without the dynamic-derivations XP feature, we don't have the builtin. +nix --experimental-features 'nix-command' eval --impure --expr \ + 'assert ! (builtins ? outputOf); ""' + +# Test that a string is required. +# +# We currently require a string to be passed, rather than a derivation +# object that could be coerced to a string. We might liberalise this in +# the future so it does work, but there are some design questions to +# resolve first. Adding a test so we don't liberalise it by accident. +expectStderr 1 nix --experimental-features 'nix-command dynamic-derivations' eval --impure --expr \ + 'builtins.outputOf (import ../dependencies.nix {}) "out"' \ + | grepQuiet "value is a set while a string was expected" + +# Test that "DrvDeep" string contexts are not supported at this time +# +# Like the above, this is a restriction we could relax later. +expectStderr 1 nix --experimental-features 'nix-command dynamic-derivations' eval --impure --expr \ + 'builtins.outputOf (import ../dependencies.nix {}).drvPath "out"' \ + | grepQuiet "has a context which refers to a complete source and binary closure. This is not supported at this time" + +# Test using `builtins.outputOf` with static derivations +testStaticHello () { + nix eval --impure --expr \ + 'with (import ./text-hashed-output.nix); let + a = hello.outPath; + b = builtins.outputOf (builtins.unsafeDiscardOutputDependency hello.drvPath) "out"; + in builtins.trace a + (builtins.trace b + (assert a == b; null))' +} + +# Test with a regular old input-addresed derivation +# +# `builtins.outputOf` works without ca-derivations and doesn't create a +# placeholder but just returns the output path. +testStaticHello + +# Test with content addressed derivation. +NIX_TESTS_CA_BY_DEFAULT=1 testStaticHello + +# Test with derivation-producing derivation +# +# This is hardly different from the preceding cases, except that we're +# only taking 1 outputOf out of 2 possible outputOfs. Note that +# `.outPath` could be defined as `outputOf drvPath`, which is what we're +# testing here. The other `outputOf` that we're not testing here is the +# use of _dynamic_ derivations. +nix eval --impure --expr \ + 'with (import ./text-hashed-output.nix); let + a = producingDrv.outPath; + b = builtins.outputOf (builtins.builtins.unsafeDiscardOutputDependency producingDrv.drvPath) "out"; + in builtins.trace a + (builtins.trace b + (assert a == b; null))' + +# Test with unbuilt output of derivation-producing derivation. +# +# This function similar to `testStaticHello` used above, but instead of +# checking the property on a constant derivation, we check it on a +# derivation that's from another derivation's output (outPath). +testDynamicHello () { + nix eval --impure --expr \ + 'with (import ./text-hashed-output.nix); let + a = builtins.outputOf producingDrv.outPath "out"; + b = builtins.outputOf (builtins.outputOf (builtins.unsafeDiscardOutputDependency producingDrv.drvPath) "out") "out"; + in builtins.trace a + (builtins.trace b + (assert a == b; null))' +} + +# inner dynamic derivation is input-addressed +testDynamicHello + +# inner dynamic derivation is content-addressed +NIX_TESTS_CA_BY_DEFAULT=1 testDynamicHello diff --git a/tests/functional/dyn-drv/local.mk b/tests/functional/dyn-drv/local.mk new file mode 100644 index 000000000..c87534944 --- /dev/null +++ b/tests/functional/dyn-drv/local.mk @@ -0,0 +1,15 @@ +dyn-drv-tests := \ + $(d)/text-hashed-output.sh \ + $(d)/recursive-mod-json.sh \ + $(d)/build-built-drv.sh \ + $(d)/eval-outputOf.sh \ + $(d)/dep-built-drv.sh \ + $(d)/old-daemon-error-hack.sh + +install-tests-groups += dyn-drv + +clean-files += \ + $(d)/config.nix + +test-deps += \ + tests/functional/dyn-drv/config.nix diff --git a/tests/functional/dyn-drv/old-daemon-error-hack.nix b/tests/functional/dyn-drv/old-daemon-error-hack.nix new file mode 100644 index 000000000..c9d4a62d4 --- /dev/null +++ b/tests/functional/dyn-drv/old-daemon-error-hack.nix @@ -0,0 +1,20 @@ +with import ./config.nix; + +# A simple content-addressed derivation. +# The derivation can be arbitrarily modified by passing a different `seed`, +# but the output will always be the same +rec { + stub = mkDerivation { + name = "stub"; + buildCommand = '' + echo stub > $out + ''; + }; + wrapper = mkDerivation { + name = "has-dynamic-drv-dep"; + buildCommand = '' + exit 1 # we're not building this derivation + ${builtins.outputOf stub.outPath "out"} + ''; + }; +} diff --git a/tests/functional/dyn-drv/old-daemon-error-hack.sh b/tests/functional/dyn-drv/old-daemon-error-hack.sh new file mode 100644 index 000000000..43b049973 --- /dev/null +++ b/tests/functional/dyn-drv/old-daemon-error-hack.sh @@ -0,0 +1,11 @@ +# Purposely bypassing our usual common for this subgroup +source ../common.sh + +# Need backend to support text-hashing too +isDaemonNewer "2.18.0pre20230906" && skipTest "Daemon is too new" + +enableFeatures "ca-derivations dynamic-derivations" + +restartDaemon + +expectStderr 1 nix-instantiate --read-write-mode ./old-daemon-error-hack.nix | grepQuiet "the daemon is too old to understand dependencies on dynamic derivations" diff --git a/tests/functional/dyn-drv/recursive-mod-json.nix b/tests/functional/dyn-drv/recursive-mod-json.nix new file mode 100644 index 000000000..c6a24ca4f --- /dev/null +++ b/tests/functional/dyn-drv/recursive-mod-json.nix @@ -0,0 +1,33 @@ +with import ./config.nix; + +let innerName = "foo"; in + +mkDerivation rec { + name = "${innerName}.drv"; + SHELL = shell; + + requiredSystemFeatures = [ "recursive-nix" ]; + + drv = builtins.unsafeDiscardOutputDependency (import ./text-hashed-output.nix).hello.drvPath; + + buildCommand = '' + export NIX_CONFIG='experimental-features = nix-command ca-derivations' + + PATH=${builtins.getEnv "EXTRA_PATH"}:$PATH + + # JSON of pre-existing drv + nix derivation show $drv | jq .[] > drv0.json + + # Fix name + jq < drv0.json '.name = "${innerName}"' > drv1.json + + # Extend `buildCommand` + jq < drv1.json '.env.buildCommand += "echo \"I am alive!\" >> $out/hello\n"' > drv0.json + + # Used as our output + cp $(nix derivation add < drv0.json) $out + ''; + __contentAddressed = true; + outputHashMode = "text"; + outputHashAlgo = "sha256"; +} diff --git a/tests/functional/dyn-drv/recursive-mod-json.sh b/tests/functional/dyn-drv/recursive-mod-json.sh new file mode 100644 index 000000000..0698b81bd --- /dev/null +++ b/tests/functional/dyn-drv/recursive-mod-json.sh @@ -0,0 +1,27 @@ +source common.sh + +# FIXME +if [[ $(uname) != Linux ]]; then skipTest "Not running Linux"; fi + +export NIX_TESTS_CA_BY_DEFAULT=1 + +enableFeatures 'recursive-nix' +restartDaemon + +clearStore + +rm -f $TEST_ROOT/result + +EXTRA_PATH=$(dirname $(type -p nix)):$(dirname $(type -p jq)) +export EXTRA_PATH + +# Will produce a drv +metaDrv=$(nix-instantiate ./recursive-mod-json.nix) + +# computed "dynamic" derivation +drv=$(nix-store -r $metaDrv) + +# build that dyn drv +res=$(nix-store -r $drv) + +grep 'I am alive!' $res/hello diff --git a/tests/functional/dyn-drv/text-hashed-output.nix b/tests/functional/dyn-drv/text-hashed-output.nix new file mode 100644 index 000000000..99203b518 --- /dev/null +++ b/tests/functional/dyn-drv/text-hashed-output.nix @@ -0,0 +1,33 @@ +with import ./config.nix; + +# A simple content-addressed derivation. +# The derivation can be arbitrarily modified by passing a different `seed`, +# but the output will always be the same +rec { + hello = mkDerivation { + name = "hello"; + buildCommand = '' + set -x + echo "Building a CA derivation" + mkdir -p $out + echo "Hello World" > $out/hello + ''; + }; + producingDrv = mkDerivation { + name = "hello.drv"; + buildCommand = '' + echo "Copying the derivation" + cp ${builtins.unsafeDiscardOutputDependency hello.drvPath} $out + ''; + __contentAddressed = true; + outputHashMode = "text"; + outputHashAlgo = "sha256"; + }; + wrapper = mkDerivation { + name = "use-dynamic-drv-in-non-dynamic-drv"; + buildCommand = '' + echo "Copying the output of the dynamic derivation" + cp -r ${builtins.outputOf producingDrv.outPath "out"} $out + ''; + }; +} diff --git a/tests/functional/dyn-drv/text-hashed-output.sh b/tests/functional/dyn-drv/text-hashed-output.sh new file mode 100644 index 000000000..f3e5aa93b --- /dev/null +++ b/tests/functional/dyn-drv/text-hashed-output.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +source common.sh + +# In the corresponding nix file, we have two derivations: the first, named root, +# is a normal recursive derivation, while the second, named dependent, has the +# new outputHashMode "text". Note that in "dependent", we don't refer to the +# build output of root, but only to the path of the drv file. For this reason, +# we only need to: +# +# - instantiate the root derivation +# - build the dependent derivation +# - check that the path of the output coincides with that of the original derivation + +drv=$(nix-instantiate ./text-hashed-output.nix -A hello) +nix show-derivation "$drv" + +drvProducingDrv=$(nix-instantiate ./text-hashed-output.nix -A producingDrv) +nix show-derivation "$drvProducingDrv" + +out1=$(nix-build ./text-hashed-output.nix -A producingDrv --no-out-link) + +nix path-info $drv --derivation --json | jq +nix path-info $out1 --derivation --json | jq + +test $out1 == $drv diff --git a/tests/functional/eval-store.sh b/tests/functional/eval-store.sh new file mode 100644 index 000000000..8fc859730 --- /dev/null +++ b/tests/functional/eval-store.sh @@ -0,0 +1,30 @@ +source common.sh + +# Using `--eval-store` with the daemon will eventually copy everything +# to the build store, invalidating most of the tests here +needLocalStore "“--eval-store” doesn't achieve much with the daemon" + +eval_store=$TEST_ROOT/eval-store + +clearStore +rm -rf "$eval_store" + +nix build -f dependencies.nix --eval-store "$eval_store" -o "$TEST_ROOT/result" +[[ -e $TEST_ROOT/result/foobar ]] +(! ls $NIX_STORE_DIR/*.drv) +ls $eval_store/nix/store/*.drv + +clearStore +rm -rf "$eval_store" + +nix-instantiate dependencies.nix --eval-store "$eval_store" +(! ls $NIX_STORE_DIR/*.drv) +ls $eval_store/nix/store/*.drv + +clearStore +rm -rf "$eval_store" + +nix-build dependencies.nix --eval-store "$eval_store" -o "$TEST_ROOT/result" +[[ -e $TEST_ROOT/result/foobar ]] +(! ls $NIX_STORE_DIR/*.drv) +ls $eval_store/nix/store/*.drv diff --git a/tests/functional/eval.nix b/tests/functional/eval.nix new file mode 100644 index 000000000..befbd17a9 --- /dev/null +++ b/tests/functional/eval.nix @@ -0,0 +1,5 @@ +{ + int = 123; + str = "foo"; + attr.foo = "bar"; +} diff --git a/tests/functional/eval.sh b/tests/functional/eval.sh new file mode 100644 index 000000000..b81bb1e2c --- /dev/null +++ b/tests/functional/eval.sh @@ -0,0 +1,43 @@ +source common.sh + +clearStore + +testStdinHeredoc=$(nix eval -f - < $TEST_ROOT/xyzzy/default.nix +[[ $(nix eval --impure --expr "import $TEST_ROOT/foo/bar") = 123 ]] diff --git a/tests/functional/experimental-features.sh b/tests/functional/experimental-features.sh new file mode 100644 index 000000000..607bf0a8e --- /dev/null +++ b/tests/functional/experimental-features.sh @@ -0,0 +1,86 @@ +source common.sh + +# Skipping these two for now, because we actually *do* want flags and +# config settings to always show up in the manual, just be marked +# experimental. Will reenable once the manual generation takes advantage +# of the JSON metadata on this. +# +# # Without flakes, flake options should not show up +# # With flakes, flake options should show up +# +# function grep_both_ways { +# nix --experimental-features 'nix-command' "$@" | grepQuietInverse flake +# nix --experimental-features 'nix-command flakes' "$@" | grepQuiet flake +# +# # Also, the order should not matter +# nix "$@" --experimental-features 'nix-command' | grepQuietInverse flake +# nix "$@" --experimental-features 'nix-command flakes' | grepQuiet flake +# } +# +# # Simple case, the configuration effects the running command +# grep_both_ways show-config +# +# # Medium case, the configuration effects --help +# grep_both_ways store gc --help + +# Test settings that are gated on experimental features; the setting is ignored +# with a warning if the experimental feature is not enabled. The order of the +# `setting = value` lines in the configuration should not matter. + +# 'flakes' experimental-feature is disabled before, ignore and warn +NIX_CONFIG=' + experimental-features = nix-command + accept-flake-config = true +' nix show-config accept-flake-config 1>$TEST_ROOT/stdout 2>$TEST_ROOT/stderr +grepQuiet "false" $TEST_ROOT/stdout +grepQuiet "Ignoring setting 'accept-flake-config' because experimental feature 'flakes' is not enabled" $TEST_ROOT/stderr + +# 'flakes' experimental-feature is disabled after, ignore and warn +NIX_CONFIG=' + accept-flake-config = true + experimental-features = nix-command +' nix show-config accept-flake-config 1>$TEST_ROOT/stdout 2>$TEST_ROOT/stderr +grepQuiet "false" $TEST_ROOT/stdout +grepQuiet "Ignoring setting 'accept-flake-config' because experimental feature 'flakes' is not enabled" $TEST_ROOT/stderr + +# 'flakes' experimental-feature is enabled before, process +NIX_CONFIG=' + experimental-features = nix-command flakes + accept-flake-config = true +' nix show-config accept-flake-config 1>$TEST_ROOT/stdout 2>$TEST_ROOT/stderr +grepQuiet "true" $TEST_ROOT/stdout +grepQuietInverse "Ignoring setting 'accept-flake-config'" $TEST_ROOT/stderr + +# 'flakes' experimental-feature is enabled after, process +NIX_CONFIG=' + accept-flake-config = true + experimental-features = nix-command flakes +' nix show-config accept-flake-config 1>$TEST_ROOT/stdout 2>$TEST_ROOT/stderr +grepQuiet "true" $TEST_ROOT/stdout +grepQuietInverse "Ignoring setting 'accept-flake-config'" $TEST_ROOT/stderr + +function exit_code_both_ways { + expect 1 nix --experimental-features 'nix-command' "$@" 1>/dev/null + nix --experimental-features 'nix-command flakes' "$@" 1>/dev/null + + # Also, the order should not matter + expect 1 nix "$@" --experimental-features 'nix-command' 1>/dev/null + nix "$@" --experimental-features 'nix-command flakes' 1>/dev/null +} + +exit_code_both_ways show-config --flake-registry 'https://no' + +# Double check these are stable +nix --experimental-features '' --help 1>/dev/null +nix --experimental-features '' doctor --help 1>/dev/null +nix --experimental-features '' repl --help 1>/dev/null +nix --experimental-features '' upgrade-nix --help 1>/dev/null + +# These 3 arguments are currently given to all commands, which is wrong (as not +# all care). To deal with fixing later, we simply make them require the +# nix-command experimental features --- it so happens that the commands we wish +# stabilizing to do not need them anyways. +for arg in '--print-build-logs' '--offline' '--refresh'; do + nix --experimental-features 'nix-command' "$arg" --help 1>/dev/null + expect 1 nix --experimental-features '' "$arg" --help 1>/dev/null +done diff --git a/tests/functional/export-graph.nix b/tests/functional/export-graph.nix new file mode 100644 index 000000000..64fe36bd1 --- /dev/null +++ b/tests/functional/export-graph.nix @@ -0,0 +1,29 @@ +with import ./config.nix; + +rec { + + printRefs = + '' + echo $exportReferencesGraph + while read path; do + read drv + read nrRefs + echo "$path has $nrRefs references" + echo "$path" >> $out + for ((n = 0; n < $nrRefs; n++)); do read ref; echo "ref $ref"; test -e "$ref"; done + done < refs + ''; + + foo."bar.runtimeGraph" = mkDerivation { + name = "dependencies"; + builder = builtins.toFile "build-graph-builder" "${printRefs}"; + exportReferencesGraph = ["refs" (import ./dependencies.nix {})]; + }; + + foo."bar.buildGraph" = mkDerivation { + name = "dependencies"; + builder = builtins.toFile "build-graph-builder" "${printRefs}"; + exportReferencesGraph = ["refs" (import ./dependencies.nix {}).drvPath]; + }; + +} diff --git a/tests/functional/export-graph.sh b/tests/functional/export-graph.sh new file mode 100644 index 000000000..1f6232a40 --- /dev/null +++ b/tests/functional/export-graph.sh @@ -0,0 +1,30 @@ +source common.sh + +clearStore +clearProfiles + +checkRef() { + nix-store -q --references $TEST_ROOT/result | grepQuiet "$1"'$' || fail "missing reference $1" +} + +# Test the export of the runtime dependency graph. + +outPath=$(nix-build ./export-graph.nix -A 'foo."bar.runtimeGraph"' -o $TEST_ROOT/result) + +test $(nix-store -q --references $TEST_ROOT/result | wc -l) = 3 || fail "bad nr of references" + +checkRef input-2 +for i in $(cat $outPath); do checkRef $i; done + +# Test the export of the build-time dependency graph. + +nix-store --gc # should force rebuild of input-1 + +outPath=$(nix-build ./export-graph.nix -A 'foo."bar.buildGraph"' -o $TEST_ROOT/result) + +checkRef input-1 +checkRef input-1.drv +checkRef input-2 +checkRef input-2.drv + +for i in $(cat $outPath); do checkRef $i; done diff --git a/tests/functional/export.sh b/tests/functional/export.sh new file mode 100644 index 000000000..2238539bc --- /dev/null +++ b/tests/functional/export.sh @@ -0,0 +1,36 @@ +source common.sh + +clearStore + +outPath=$(nix-build dependencies.nix --no-out-link) + +nix-store --export $outPath > $TEST_ROOT/exp + +nix-store --export $(nix-store -qR $outPath) > $TEST_ROOT/exp_all + +if nix-store --export $outPath >/dev/full ; then + echo "exporting to a bad file descriptor should fail" + exit 1 +fi + + +clearStore + +if nix-store --import < $TEST_ROOT/exp; then + echo "importing a non-closure should fail" + exit 1 +fi + + +clearStore + +nix-store --import < $TEST_ROOT/exp_all + +nix-store --export $(nix-store -qR $outPath) > $TEST_ROOT/exp_all2 + + +clearStore + +# Regression test: the derivers in exp_all2 are empty, which shouldn't +# cause a failure. +nix-store --import < $TEST_ROOT/exp_all2 diff --git a/tests/functional/failing.nix b/tests/functional/failing.nix new file mode 100644 index 000000000..2a0350d4d --- /dev/null +++ b/tests/functional/failing.nix @@ -0,0 +1,22 @@ +{ busybox }: +with import ./config.nix; +let + + mkDerivation = args: + derivation ({ + inherit system; + builder = busybox; + args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" "if [ -e .attrs.sh ]; then source .attrs.sh; fi; eval \"$buildCommand\"")]; + } // removeAttrs args ["builder" "meta"]) + // { meta = args.meta or {}; }; +in +{ + + failing = mkDerivation { + name = "failing"; + buildCommand = '' + echo foo > bar + exit 1 + ''; + }; +} diff --git a/tests/functional/fetchClosure.sh b/tests/functional/fetchClosure.sh new file mode 100644 index 000000000..a02d1ce7a --- /dev/null +++ b/tests/functional/fetchClosure.sh @@ -0,0 +1,150 @@ +source common.sh + +enableFeatures "fetch-closure" + +clearStore +clearCacheCache + +# Old daemons don't properly zero out the self-references when +# calculating the CA hashes, so this breaks `nix store +# make-content-addressed` which expects the client and the daemon to +# compute the same hash +requireDaemonNewerThan "2.16.0pre20230524" + +# Initialize binary cache. +nonCaPath=$(nix build --json --file ./dependencies.nix --no-link | jq -r .[].outputs.out) +caPath=$(nix store make-content-addressed --json $nonCaPath | jq -r '.rewrites | map(.) | .[]') +nix copy --to file://$cacheDir $nonCaPath + +# Test basic fetchClosure rewriting from non-CA to CA. +clearStore + +[ ! -e $nonCaPath ] +[ ! -e $caPath ] + +[[ $(nix eval -v --raw --expr " + builtins.fetchClosure { + fromStore = \"file://$cacheDir\"; + fromPath = $nonCaPath; + toPath = $caPath; + } +") = $caPath ]] + +[ ! -e $nonCaPath ] +[ -e $caPath ] + +clearStore + +# The daemon will reject input addressed paths unless configured to trust the +# cache key or the user. This behavior should be covered by another test, so we +# skip this part when using the daemon. +if [[ "$NIX_REMOTE" != "daemon" ]]; then + + # If we want to return a non-CA path, we have to be explicit about it. + expectStderr 1 nix eval --raw --no-require-sigs --expr " + builtins.fetchClosure { + fromStore = \"file://$cacheDir\"; + fromPath = $nonCaPath; + } + " | grepQuiet -E "The .fromPath. value .* is input-addressed, but .inputAddressed. is set to .false." + + # TODO: Should the closure be rejected, despite single user mode? + # [ ! -e $nonCaPath ] + + [ ! -e $caPath ] + + # We can use non-CA paths when we ask explicitly. + [[ $(nix eval --raw --no-require-sigs --expr " + builtins.fetchClosure { + fromStore = \"file://$cacheDir\"; + fromPath = $nonCaPath; + inputAddressed = true; + } + ") = $nonCaPath ]] + + [ -e $nonCaPath ] + [ ! -e $caPath ] + + +fi + +[ ! -e $caPath ] + +# 'toPath' set to empty string should fail but print the expected path. +expectStderr 1 nix eval -v --json --expr " + builtins.fetchClosure { + fromStore = \"file://$cacheDir\"; + fromPath = $nonCaPath; + toPath = \"\"; + } +" | grep "error: rewriting.*$nonCaPath.*yielded.*$caPath" + +# If fromPath is CA, then toPath isn't needed. +nix copy --to file://$cacheDir $caPath + +clearStore + +[ ! -e $caPath ] + +[[ $(nix eval -v --raw --expr " + builtins.fetchClosure { + fromStore = \"file://$cacheDir\"; + fromPath = $caPath; + } +") = $caPath ]] + +[ -e $caPath ] + +# Check that URL query parameters aren't allowed. +clearStore +narCache=$TEST_ROOT/nar-cache +rm -rf $narCache +(! nix eval -v --raw --expr " + builtins.fetchClosure { + fromStore = \"file://$cacheDir?local-nar-cache=$narCache\"; + fromPath = $caPath; + } +") +(! [ -e $narCache ]) + +# If toPath is specified but wrong, we check it (only) when the path is missing. +clearStore + +badPath=$(echo $caPath | sed -e 's!/store/................................-!/store/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-!') + +[ ! -e $badPath ] + +expectStderr 1 nix eval -v --raw --expr " + builtins.fetchClosure { + fromStore = \"file://$cacheDir\"; + fromPath = $nonCaPath; + toPath = $badPath; + } +" | grep "error: rewriting.*$nonCaPath.*yielded.*$caPath.*while.*$badPath.*was expected" + +[ ! -e $badPath ] + +# We only check it when missing, as a performance optimization similar to what we do for fixed output derivations. So if it's already there, we don't check it. +# It would be nice for this to fail, but checking it would be too(?) slow. +[ -e $caPath ] + +[[ $(nix eval -v --raw --expr " + builtins.fetchClosure { + fromStore = \"file://$cacheDir\"; + fromPath = $badPath; + toPath = $caPath; + } +") = $caPath ]] + + +# However, if the output address is unexpected, we can report it + + +expectStderr 1 nix eval -v --raw --expr " + builtins.fetchClosure { + fromStore = \"file://$cacheDir\"; + fromPath = $caPath; + inputAddressed = true; + } +" | grepQuiet 'error.*The store object referred to by.*fromPath.* at .* is not input-addressed, but .*inputAddressed.* is set to .*true.*' + diff --git a/tests/functional/fetchGit.sh b/tests/functional/fetchGit.sh new file mode 100644 index 000000000..418b4f63f --- /dev/null +++ b/tests/functional/fetchGit.sh @@ -0,0 +1,256 @@ +source common.sh + +requireGit + +clearStore + +# Intentionally not in a canonical form +# See https://github.com/NixOS/nix/issues/6195 +repo=$TEST_ROOT/./git + +export _NIX_FORCE_HTTP=1 + +rm -rf $repo ${repo}-tmp $TEST_HOME/.cache/nix $TEST_ROOT/worktree $TEST_ROOT/shallow $TEST_ROOT/minimal + +git init $repo +git -C $repo config user.email "foobar@example.com" +git -C $repo config user.name "Foobar" + +echo utrecht > $repo/hello +touch $repo/.gitignore +git -C $repo add hello .gitignore +git -C $repo commit -m 'Bla1' +rev1=$(git -C $repo rev-parse HEAD) +git -C $repo tag -a tag1 -m tag1 + +echo world > $repo/hello +git -C $repo commit -m 'Bla2' -a +git -C $repo worktree add $TEST_ROOT/worktree +echo hello >> $TEST_ROOT/worktree/hello +rev2=$(git -C $repo rev-parse HEAD) +git -C $repo tag -a tag2 -m tag2 + +# Fetch a worktree +unset _NIX_FORCE_HTTP +path0=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$TEST_ROOT/worktree).outPath") +path0_=$(nix eval --impure --raw --expr "(builtins.fetchTree { type = \"git\"; url = file://$TEST_ROOT/worktree; }).outPath") +[[ $path0 = $path0_ ]] +export _NIX_FORCE_HTTP=1 +[[ $(tail -n 1 $path0/hello) = "hello" ]] + +# Fetch the default branch. +path=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).outPath") +[[ $(cat $path/hello) = world ]] + +# Fetch a rev from another branch +git -C $repo checkout -b devtest +echo "different file" >> $TEST_ROOT/git/differentbranch +git -C $repo add differentbranch +git -C $repo commit -m 'Test2' +git -C $repo checkout master +devrev=$(git -C $repo rev-parse devtest) +out=$(nix eval --impure --raw --expr "builtins.fetchGit { url = file://$repo; rev = \"$devrev\"; }" 2>&1) || status=$? +[[ $status == 1 ]] +[[ $out =~ 'Cannot find Git revision' ]] + +[[ $(nix eval --raw --expr "builtins.readFile (builtins.fetchGit { url = file://$repo; rev = \"$devrev\"; allRefs = true; } + \"/differentbranch\")") = 'different file' ]] + +# In pure eval mode, fetchGit without a revision should fail. +[[ $(nix eval --impure --raw --expr "builtins.readFile (fetchGit file://$repo + \"/hello\")") = world ]] +(! nix eval --raw --expr "builtins.readFile (fetchGit file://$repo + \"/hello\")") + +# Fetch using an explicit revision hash. +path2=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$repo; rev = \"$rev2\"; }).outPath") +[[ $path = $path2 ]] + +# In pure eval mode, fetchGit with a revision should succeed. +[[ $(nix eval --raw --expr "builtins.readFile (fetchGit { url = file://$repo; rev = \"$rev2\"; } + \"/hello\")") = world ]] + +# Fetch again. This should be cached. +mv $repo ${repo}-tmp +path2=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).outPath") +[[ $path = $path2 ]] + +[[ $(nix eval --impure --expr "(builtins.fetchGit file://$repo).revCount") = 2 ]] +[[ $(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).rev") = $rev2 ]] +[[ $(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).shortRev") = ${rev2:0:7} ]] + +# Fetching with a explicit hash should succeed. +path2=$(nix eval --refresh --raw --expr "(builtins.fetchGit { url = file://$repo; rev = \"$rev2\"; }).outPath") +[[ $path = $path2 ]] + +path2=$(nix eval --refresh --raw --expr "(builtins.fetchGit { url = file://$repo; rev = \"$rev1\"; }).outPath") +[[ $(cat $path2/hello) = utrecht ]] + +mv ${repo}-tmp $repo + +# Using a clean working tree should produce the same result. +path2=$(nix eval --impure --raw --expr "(builtins.fetchGit $repo).outPath") +[[ $path = $path2 ]] + +# Using an unclean tree should yield the tracked but uncommitted changes. +mkdir $repo/dir1 $repo/dir2 +echo foo > $repo/dir1/foo +echo bar > $repo/bar +echo bar > $repo/dir2/bar +git -C $repo add dir1/foo +git -C $repo rm hello + +unset _NIX_FORCE_HTTP +path2=$(nix eval --impure --raw --expr "(builtins.fetchGit $repo).outPath") +[ ! -e $path2/hello ] +[ ! -e $path2/bar ] +[ ! -e $path2/dir2/bar ] +[ ! -e $path2/.git ] +[[ $(cat $path2/dir1/foo) = foo ]] + +[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).rev") = 0000000000000000000000000000000000000000 ]] +[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).dirtyRev") = "${rev2}-dirty" ]] +[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).dirtyShortRev") = "${rev2:0:7}-dirty" ]] + +# ... unless we're using an explicit ref or rev. +path3=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; ref = \"master\"; }).outPath") +[[ $path = $path3 ]] + +path3=$(nix eval --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; }).outPath") +[[ $path = $path3 ]] + +# Committing should not affect the store path. +git -C $repo commit -m 'Bla3' -a + +path4=$(nix eval --impure --refresh --raw --expr "(builtins.fetchGit file://$repo).outPath") +[[ $path2 = $path4 ]] + +[[ $(nix eval --impure --expr "builtins.hasAttr \"rev\" (builtins.fetchGit $repo)") == "true" ]] +[[ $(nix eval --impure --expr "builtins.hasAttr \"dirtyRev\" (builtins.fetchGit $repo)") == "false" ]] +[[ $(nix eval --impure --expr "builtins.hasAttr \"dirtyShortRev\" (builtins.fetchGit $repo)") == "false" ]] + +status=0 +nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; narHash = \"sha256-B5yIPHhEm0eysJKEsO7nqxprh9vcblFxpJG11gXJus1=\"; }).outPath" || status=$? +[[ "$status" = "102" ]] + +path5=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; narHash = \"sha256-Hr8g6AqANb3xqX28eu1XnjK/3ab8Gv6TJSnkb1LezG9=\"; }).outPath") +[[ $path = $path5 ]] + +# tarball-ttl should be ignored if we specify a rev +echo delft > $repo/hello +git -C $repo add hello +git -C $repo commit -m 'Bla4' +rev3=$(git -C $repo rev-parse HEAD) +nix eval --tarball-ttl 3600 --expr "builtins.fetchGit { url = $repo; rev = \"$rev3\"; }" >/dev/null + +# Update 'path' to reflect latest master +path=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).outPath") + +# Check behavior when non-master branch is used +git -C $repo checkout $rev2 -b dev +echo dev > $repo/hello + +# File URI uses dirty tree unless specified otherwise +path2=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).outPath") +[ $(cat $path2/hello) = dev ] + +# Using local path with branch other than 'master' should work when clean or dirty +path3=$(nix eval --impure --raw --expr "(builtins.fetchGit $repo).outPath") +# (check dirty-tree handling was used) +[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).rev") = 0000000000000000000000000000000000000000 ]] +[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).shortRev") = 0000000 ]] +# Making a dirty tree clean again and fetching it should +# record correct revision information. See: #4140 +echo world > $repo/hello +[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).rev") = $rev2 ]] + +# Committing shouldn't change store path, or switch to using 'master' +echo dev > $repo/hello +git -C $repo commit -m 'Bla5' -a +path4=$(nix eval --impure --raw --expr "(builtins.fetchGit $repo).outPath") +[[ $(cat $path4/hello) = dev ]] +[[ $path3 = $path4 ]] + +# Using remote path with branch other than 'master' should fetch the HEAD revision. +# (--tarball-ttl 0 to prevent using the cached repo above) +export _NIX_FORCE_HTTP=1 +path4=$(nix eval --tarball-ttl 0 --impure --raw --expr "(builtins.fetchGit $repo).outPath") +[[ $(cat $path4/hello) = dev ]] +[[ $path3 = $path4 ]] +unset _NIX_FORCE_HTTP + +# Confirm same as 'dev' branch +path5=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; ref = \"dev\"; }).outPath") +[[ $path3 = $path5 ]] + + +# Nuke the cache +rm -rf $TEST_HOME/.cache/nix + +# Try again, but without 'git' on PATH. This should fail. +NIX=$(command -v nix) +(! PATH= $NIX eval --impure --raw --expr "(builtins.fetchGit { url = $repo; ref = \"dev\"; }).outPath" ) + +# Try again, with 'git' available. This should work. +path5=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; ref = \"dev\"; }).outPath") +[[ $path3 = $path5 ]] + +# Fetching from a repo with only a specific revision and no branches should +# not fall back to copying files and record correct revision information. See: #5302 +mkdir $TEST_ROOT/minimal +git -C $TEST_ROOT/minimal init +git -C $TEST_ROOT/minimal fetch $repo $rev2 +git -C $TEST_ROOT/minimal checkout $rev2 +[[ $(nix eval --impure --raw --expr "(builtins.fetchGit { url = $TEST_ROOT/minimal; }).rev") = $rev2 ]] + +# Fetching a shallow repo shouldn't work by default, because we can't +# return a revCount. +git clone --depth 1 file://$repo $TEST_ROOT/shallow +(! nix eval --impure --raw --expr "(builtins.fetchGit { url = $TEST_ROOT/shallow; ref = \"dev\"; }).outPath") + +# But you can request a shallow clone, which won't return a revCount. +path6=$(nix eval --impure --raw --expr "(builtins.fetchTree { type = \"git\"; url = \"file://$TEST_ROOT/shallow\"; ref = \"dev\"; shallow = true; }).outPath") +[[ $path3 = $path6 ]] +[[ $(nix eval --impure --expr "(builtins.fetchTree { type = \"git\"; url = \"file://$TEST_ROOT/shallow\"; ref = \"dev\"; shallow = true; }).revCount or 123") == 123 ]] + +# Explicit ref = "HEAD" should work, and produce the same outPath as without ref +path7=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"HEAD\"; }).outPath") +path8=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; }).outPath") +[[ $path7 = $path8 ]] + +# ref = "HEAD" should fetch the HEAD revision +rev4=$(git -C $repo rev-parse HEAD) +rev4_nix=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"HEAD\"; }).rev") +[[ $rev4 = $rev4_nix ]] + +# The name argument should be handled +path9=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"HEAD\"; name = \"foo\"; }).outPath") +[[ $path9 =~ -foo$ ]] + +# Specifying a ref without a rev shouldn't pick a cached rev for a different ref +export _NIX_FORCE_HTTP=1 +rev_tag1_nix=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"refs/tags/tag1\"; }).rev") +rev_tag1=$(git -C $repo rev-parse refs/tags/tag1) +[[ $rev_tag1_nix = $rev_tag1 ]] +rev_tag2_nix=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"refs/tags/tag2\"; }).rev") +rev_tag2=$(git -C $repo rev-parse refs/tags/tag2) +[[ $rev_tag2_nix = $rev_tag2 ]] +unset _NIX_FORCE_HTTP + +# should fail if there is no repo +rm -rf $repo/.git +(! nix eval --impure --raw --expr "(builtins.fetchGit \"file://$repo\").outPath") + +# should succeed for a repo without commits +git init $repo +path10=$(nix eval --impure --raw --expr "(builtins.fetchGit \"file://$repo\").outPath") + +# should succeed for a path with a space +# regression test for #7707 +repo="$TEST_ROOT/a b" +git init "$repo" +git -C "$repo" config user.email "foobar@example.com" +git -C "$repo" config user.name "Foobar" + +echo utrecht > "$repo/hello" +touch "$repo/.gitignore" +git -C "$repo" add hello .gitignore +git -C "$repo" commit -m 'Bla1' +cd "$repo" +path11=$(nix eval --impure --raw --expr "(builtins.fetchGit ./.).outPath") diff --git a/tests/functional/fetchGitRefs.sh b/tests/functional/fetchGitRefs.sh new file mode 100644 index 000000000..d643fea04 --- /dev/null +++ b/tests/functional/fetchGitRefs.sh @@ -0,0 +1,108 @@ +source common.sh + +requireGit + +clearStore + +repo="$TEST_ROOT/git" + +rm -rf "$repo" "${repo}-tmp" "$TEST_HOME/.cache/nix" + +git init "$repo" +git -C "$repo" config user.email "foobar@example.com" +git -C "$repo" config user.name "Foobar" + +echo utrecht > "$repo"/hello +git -C "$repo" add hello +git -C "$repo" commit -m 'Bla1' + +path=$(nix eval --raw --impure --expr "(builtins.fetchGit { url = $repo; ref = \"master\"; }).outPath") + +# Test various combinations of ref names +# (taken from the git project) + +# git help check-ref-format +# Git imposes the following rules on how references are named: +# +# 1. They can include slash / for hierarchical (directory) grouping, but no slash-separated component can begin with a dot . or end with the sequence .lock. +# 2. They must contain at least one /. This enforces the presence of a category like heads/, tags/ etc. but the actual names are not restricted. If the --allow-onelevel option is used, this rule is waived. +# 3. They cannot have two consecutive dots .. anywhere. +# 4. They cannot have ASCII control characters (i.e. bytes whose values are lower than \040, or \177 DEL), space, tilde ~, caret ^, or colon : anywhere. +# 5. They cannot have question-mark ?, asterisk *, or open bracket [ anywhere. See the --refspec-pattern option below for an exception to this rule. +# 6. They cannot begin or end with a slash / or contain multiple consecutive slashes (see the --normalize option below for an exception to this rule) +# 7. They cannot end with a dot .. +# 8. They cannot contain a sequence @{. +# 9. They cannot be the single character @. +# 10. They cannot contain a \. + +valid_ref() { + { set +x; printf >&2 '\n>>>>>>>>>> valid_ref %s\b <<<<<<<<<<\n' $(printf %s "$1" | sed -n -e l); set -x; } + git check-ref-format --branch "$1" >/dev/null + git -C "$repo" branch "$1" master >/dev/null + path1=$(nix eval --raw --impure --expr "(builtins.fetchGit { url = $repo; ref = ''$1''; }).outPath") + [[ $path1 = $path ]] + git -C "$repo" branch -D "$1" >/dev/null +} + +invalid_ref() { + { set +x; printf >&2 '\n>>>>>>>>>> invalid_ref %s\b <<<<<<<<<<\n' $(printf %s "$1" | sed -n -e l); set -x; } + # special case for a sole @: + # --branch @ will try to interpret @ as a branch reference and not fail. Thus we need --allow-onelevel + if [ "$1" = "@" ]; then + (! git check-ref-format --allow-onelevel "$1" >/dev/null 2>&1) + else + (! git check-ref-format --branch "$1" >/dev/null 2>&1) + fi + expect 1 nix --debug eval --raw --impure --expr "(builtins.fetchGit { url = $repo; ref = ''$1''; }).outPath" 2>&1 | grep 'invalid Git branch/tag name' >/dev/null +} + + +valid_ref 'foox' +valid_ref '1337' +valid_ref 'foo.baz' +valid_ref 'foo/bar/baz' +valid_ref 'foo./bar' +valid_ref 'heads/foo@bar' +valid_ref "$(printf 'heads/fu\303\237')" +valid_ref 'foo-bar-baz' +valid_ref '$1' +valid_ref 'foo.locke' + +invalid_ref 'refs///heads/foo' +invalid_ref 'heads/foo/' +invalid_ref '///heads/foo' +invalid_ref '.foo' +invalid_ref './foo' +invalid_ref './foo/bar' +invalid_ref 'foo/./bar' +invalid_ref 'foo/bar/.' +invalid_ref 'foo bar' +invalid_ref 'foo?bar' +invalid_ref 'foo^bar' +invalid_ref 'foo~bar' +invalid_ref 'foo:bar' +invalid_ref 'foo[bar' +invalid_ref 'foo/bar/.' +invalid_ref '.refs/foo' +invalid_ref 'refs/heads/foo.' +invalid_ref 'heads/foo..bar' +invalid_ref 'heads/foo?bar' +invalid_ref 'heads/foo.lock' +invalid_ref 'heads///foo.lock' +invalid_ref 'foo.lock/bar' +invalid_ref 'foo.lock///bar' +invalid_ref 'heads/v@{ation' +invalid_ref 'heads/foo\.ar' # should fail due to \ +invalid_ref 'heads/foo\bar' # should fail due to \ +invalid_ref "$(printf 'heads/foo\t')" # should fail because it has a TAB +invalid_ref "$(printf 'heads/foo\177')" +invalid_ref '@' + +invalid_ref 'foo/*' +invalid_ref '*/foo' +invalid_ref 'foo/*/bar' +invalid_ref '*' +invalid_ref 'foo/*/*' +invalid_ref '*/foo/*' +invalid_ref '/foo' +invalid_ref '' diff --git a/tests/functional/fetchGitSubmodules.sh b/tests/functional/fetchGitSubmodules.sh new file mode 100644 index 000000000..df81232e5 --- /dev/null +++ b/tests/functional/fetchGitSubmodules.sh @@ -0,0 +1,128 @@ +source common.sh + +set -u + +requireGit + +clearStore + +rootRepo=$TEST_ROOT/gitSubmodulesRoot +subRepo=$TEST_ROOT/gitSubmodulesSub + +rm -rf ${rootRepo} ${subRepo} $TEST_HOME/.cache/nix + +# Submodules can't be fetched locally by default, which can cause +# information leakage vulnerabilities, but for these tests our +# submodule is intentionally local and it's all trusted, so we +# disable this restriction. Setting it per repo is not sufficient, as +# the repo-local config does not apply to the commands run from +# outside the repos by Nix. +export XDG_CONFIG_HOME=$TEST_HOME/.config +git config --global protocol.file.allow always + +initGitRepo() { + git init $1 + git -C $1 config user.email "foobar@example.com" + git -C $1 config user.name "Foobar" +} + +addGitContent() { + echo "lorem ipsum" > $1/content + git -C $1 add content + git -C $1 commit -m "Initial commit" +} + +initGitRepo $subRepo +addGitContent $subRepo + +initGitRepo $rootRepo + +git -C $rootRepo submodule init +git -C $rootRepo submodule add $subRepo sub +git -C $rootRepo add sub +git -C $rootRepo commit -m "Add submodule" + +rev=$(git -C $rootRepo rev-parse HEAD) + +r1=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; }).outPath") +r2=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; submodules = false; }).outPath") +r3=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; submodules = true; }).outPath") + +[[ $r1 == $r2 ]] +[[ $r2 != $r3 ]] + +r4=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; ref = \"master\"; rev = \"$rev\"; }).outPath") +r5=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; ref = \"master\"; rev = \"$rev\"; submodules = false; }).outPath") +r6=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; ref = \"master\"; rev = \"$rev\"; submodules = true; }).outPath") +r7=$(nix eval --raw --expr "(builtins.fetchGit { url = $rootRepo; ref = \"master\"; rev = \"$rev\"; submodules = true; }).outPath") +r8=$(nix eval --raw --expr "(builtins.fetchGit { url = $rootRepo; rev = \"$rev\"; submodules = true; }).outPath") + +[[ $r1 == $r4 ]] +[[ $r4 == $r5 ]] +[[ $r3 == $r6 ]] +[[ $r6 == $r7 ]] +[[ $r7 == $r8 ]] + +have_submodules=$(nix eval --expr "(builtins.fetchGit { url = $rootRepo; rev = \"$rev\"; }).submodules") +[[ $have_submodules == false ]] + +have_submodules=$(nix eval --expr "(builtins.fetchGit { url = $rootRepo; rev = \"$rev\"; submodules = false; }).submodules") +[[ $have_submodules == false ]] + +have_submodules=$(nix eval --expr "(builtins.fetchGit { url = $rootRepo; rev = \"$rev\"; submodules = true; }).submodules") +[[ $have_submodules == true ]] + +pathWithoutSubmodules=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; }).outPath") +pathWithSubmodules=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; submodules = true; }).outPath") +pathWithSubmodulesAgain=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; submodules = true; }).outPath") +pathWithSubmodulesAgainWithRef=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; ref = \"master\"; rev = \"$rev\"; submodules = true; }).outPath") + +# The resulting store path cannot be the same. +[[ $pathWithoutSubmodules != $pathWithSubmodules ]] + +# Checking out the same repo with submodules returns in the same store path. +[[ $pathWithSubmodules == $pathWithSubmodulesAgain ]] + +# Checking out the same repo with submodules returns in the same store path. +[[ $pathWithSubmodulesAgain == $pathWithSubmodulesAgainWithRef ]] + +# The submodules flag is actually honored. +[[ ! -e $pathWithoutSubmodules/sub/content ]] +[[ -e $pathWithSubmodules/sub/content ]] + +[[ -e $pathWithSubmodulesAgainWithRef/sub/content ]] + +# No .git directory or submodule reference files must be left +test "$(find "$pathWithSubmodules" -name .git)" = "" + +# Git repos without submodules can be fetched with submodules = true. +subRev=$(git -C $subRepo rev-parse HEAD) +noSubmoduleRepoBaseline=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$subRepo; rev = \"$subRev\"; }).outPath") +noSubmoduleRepo=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$subRepo; rev = \"$subRev\"; submodules = true; }).outPath") + +[[ $noSubmoduleRepoBaseline == $noSubmoduleRepo ]] + +# Test relative submodule URLs. +rm $TEST_HOME/.cache/nix/fetcher-cache* +rm -rf $rootRepo/.git $rootRepo/.gitmodules $rootRepo/sub +initGitRepo $rootRepo +git -C $rootRepo submodule add ../gitSubmodulesSub sub +git -C $rootRepo commit -m "Add submodule" +rev2=$(git -C $rootRepo rev-parse HEAD) +pathWithRelative=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev2\"; submodules = true; }).outPath") +diff -r -x .gitmodules $pathWithSubmodules $pathWithRelative + +# Test clones that have an upstream with relative submodule URLs. +rm $TEST_HOME/.cache/nix/fetcher-cache* +cloneRepo=$TEST_ROOT/a/b/gitSubmodulesClone # NB /a/b to make the relative path not work relative to $cloneRepo +git clone $rootRepo $cloneRepo +pathIndirect=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$cloneRepo; rev = \"$rev2\"; submodules = true; }).outPath") +[[ $pathIndirect = $pathWithRelative ]] + +# Test that if the clone has the submodule already, we're not fetching +# it again. +git -C $cloneRepo submodule update --init +rm $TEST_HOME/.cache/nix/fetcher-cache* +rm -rf $subRepo +pathSubmoduleGone=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$cloneRepo; rev = \"$rev2\"; submodules = true; }).outPath") +[[ $pathSubmoduleGone = $pathWithRelative ]] diff --git a/tests/functional/fetchMercurial.sh b/tests/functional/fetchMercurial.sh new file mode 100644 index 000000000..e6f8525c6 --- /dev/null +++ b/tests/functional/fetchMercurial.sh @@ -0,0 +1,106 @@ +source common.sh + +[[ $(type -p hq) ]] || skipTest "Mercurial not installed" + +clearStore + +# Intentionally not in a canonical form +# See https://github.com/NixOS/nix/issues/6195 +repo=$TEST_ROOT/./hg + +rm -rf $repo ${repo}-tmp $TEST_HOME/.cache/nix + +hg init $repo +echo '[ui]' >> $repo/.hg/hgrc +echo 'username = Foobar ' >> $repo/.hg/hgrc + +# Set ui.tweakdefaults to ensure HGPLAIN is being set. +echo 'tweakdefaults = True' >> $repo/.hg/hgrc + +echo utrecht > $repo/hello +touch $repo/.hgignore +hg add --cwd $repo hello .hgignore +hg commit --cwd $repo -m 'Bla1' +rev1=$(hg log --cwd $repo -r tip --template '{node}') + +echo world > $repo/hello +hg commit --cwd $repo -m 'Bla2' +rev2=$(hg log --cwd $repo -r tip --template '{node}') + +# Fetch an unclean branch. +echo unclean > $repo/hello +path=$(nix eval --impure --raw --expr "(builtins.fetchMercurial file://$repo).outPath") +[[ $(cat $path/hello) = unclean ]] +hg revert --cwd $repo --all + +# Fetch the default branch. +path=$(nix eval --impure --raw --expr "(builtins.fetchMercurial file://$repo).outPath") +[[ $(cat $path/hello) = world ]] + +# In pure eval mode, fetchGit without a revision should fail. +[[ $(nix eval --impure --raw --expr "(builtins.readFile (fetchMercurial file://$repo + \"/hello\"))") = world ]] +(! nix eval --raw --expr "builtins.readFile (fetchMercurial file://$repo + \"/hello\")") + +# Fetch using an explicit revision hash. +path2=$(nix eval --impure --raw --expr "(builtins.fetchMercurial { url = file://$repo; rev = \"$rev2\"; }).outPath") +[[ $path = $path2 ]] + +# In pure eval mode, fetchGit with a revision should succeed. +[[ $(nix eval --raw --expr "builtins.readFile (fetchMercurial { url = file://$repo; rev = \"$rev2\"; } + \"/hello\")") = world ]] + +# Fetch again. This should be cached. +mv $repo ${repo}-tmp +path2=$(nix eval --impure --raw --expr "(builtins.fetchMercurial file://$repo).outPath") +[[ $path = $path2 ]] + +[[ $(nix eval --impure --raw --expr "(builtins.fetchMercurial file://$repo).branch") = default ]] +[[ $(nix eval --impure --expr "(builtins.fetchMercurial file://$repo).revCount") = 1 ]] +[[ $(nix eval --impure --raw --expr "(builtins.fetchMercurial file://$repo).rev") = $rev2 ]] + +# But with TTL 0, it should fail. +(! nix eval --impure --refresh --expr "builtins.fetchMercurial file://$repo") + +# Fetching with a explicit hash should succeed. +path2=$(nix eval --refresh --raw --expr "(builtins.fetchMercurial { url = file://$repo; rev = \"$rev2\"; }).outPath") +[[ $path = $path2 ]] + +path2=$(nix eval --refresh --raw --expr "(builtins.fetchMercurial { url = file://$repo; rev = \"$rev1\"; }).outPath") +[[ $(cat $path2/hello) = utrecht ]] + +mv ${repo}-tmp $repo + +# Using a clean working tree should produce the same result. +path2=$(nix eval --impure --raw --expr "(builtins.fetchMercurial $repo).outPath") +[[ $path = $path2 ]] + +# Using an unclean tree should yield the tracked but uncommitted changes. +mkdir $repo/dir1 $repo/dir2 +echo foo > $repo/dir1/foo +echo bar > $repo/bar +echo bar > $repo/dir2/bar +hg add --cwd $repo dir1/foo +hg rm --cwd $repo hello + +path2=$(nix eval --impure --raw --expr "(builtins.fetchMercurial $repo).outPath") +[ ! -e $path2/hello ] +[ ! -e $path2/bar ] +[ ! -e $path2/dir2/bar ] +[ ! -e $path2/.hg ] +[[ $(cat $path2/dir1/foo) = foo ]] + +[[ $(nix eval --impure --raw --expr "(builtins.fetchMercurial $repo).rev") = 0000000000000000000000000000000000000000 ]] + +# ... unless we're using an explicit ref. +path3=$(nix eval --impure --raw --expr "(builtins.fetchMercurial { url = $repo; rev = \"default\"; }).outPath") +[[ $path = $path3 ]] + +# Committing should not affect the store path. +hg commit --cwd $repo -m 'Bla3' + +path4=$(nix eval --impure --refresh --raw --expr "(builtins.fetchMercurial file://$repo).outPath") +[[ $path2 = $path4 ]] + +echo paris > $repo/hello +# Passing a `name` argument should be reflected in the output path +path5=$(nix eval -vvvvv --impure --refresh --raw --expr "(builtins.fetchMercurial { url = \"file://$repo\"; name = \"foo\"; } ).outPath") +[[ $path5 =~ -foo$ ]] diff --git a/tests/functional/fetchPath.sh b/tests/functional/fetchPath.sh new file mode 100644 index 000000000..29be38ce2 --- /dev/null +++ b/tests/functional/fetchPath.sh @@ -0,0 +1,6 @@ +source common.sh + +touch $TEST_ROOT/foo -t 202211111111 +# We only check whether 2022-11-1* **:**:** is the last modified date since +# `lastModified` is transformed into UTC in `builtins.fetchTarball`. +[[ "$(nix eval --impure --raw --expr "(builtins.fetchTree \"path://$TEST_ROOT/foo\").lastModifiedDate")" =~ 2022111.* ]] diff --git a/tests/functional/fetchTree-file.sh b/tests/functional/fetchTree-file.sh new file mode 100644 index 000000000..6395c133d --- /dev/null +++ b/tests/functional/fetchTree-file.sh @@ -0,0 +1,117 @@ +source common.sh + +clearStore + +cd "$TEST_ROOT" + +test_fetch_file () { + echo foo > test_input + + input_hash="$(nix hash path test_input)" + + nix eval --impure --file - < inputs/test_input_file + echo '{ outputs = { self }: { }; }' > inputs/flake.nix + tar cfa test_input.tar.gz inputs + cp test_input.tar.gz test_input_no_ext + input_tarball_hash="$(nix hash path test_input.tar.gz)" + input_directory_hash="$(nix hash path inputs)" + + cat < flake.nix + { + inputs.no_ext_default_no_unpack = { + url = "file://$PWD/test_input_no_ext"; + flake = false; + }; + inputs.no_ext_explicit_unpack = { + url = "tarball+file://$PWD/test_input_no_ext"; + flake = false; + }; + inputs.tarball_default_unpack = { + url = "file://$PWD/test_input.tar.gz"; + flake = false; + }; + inputs.tarball_explicit_no_unpack = { + url = "file+file://$PWD/test_input.tar.gz"; + flake = false; + }; + inputs.flake_no_ext = { + url = "file://$PWD/test_input_no_ext"; + }; + outputs = { ... }: {}; + } +EOF + + nix flake update + nix eval --file - < flake.nix + { + inputs.tarball = { + url = "file://$PWD/test_input.tar.gz"; + flake = false; + }; + outputs = { self, tarball }: { + foo = builtins.readFile "\${tarball}/test_input_file"; + }; + } + nix flake update + + clearStore + "$NIX_DAEMON_PACKAGE/bin/nix" eval .#foo +EOF +} + +test_fetch_file +test_file_flake_input diff --git a/tests/functional/fetchurl.sh b/tests/functional/fetchurl.sh new file mode 100644 index 000000000..8cd40c09f --- /dev/null +++ b/tests/functional/fetchurl.sh @@ -0,0 +1,80 @@ +source common.sh + +clearStore + +# Test fetching a flat file. +hash=$(nix-hash --flat --type sha256 ./fetchurl.sh) + +outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file://$(pwd)/fetchurl.sh --argstr sha256 $hash --no-out-link) + +cmp $outPath fetchurl.sh + +# Do not re-fetch paths already present. +outPath2=$(nix-build -vvvvv --expr 'import ' --argstr url file:///does-not-exist/must-remain-unused/fetchurl.sh --argstr sha256 $hash --no-out-link) +test "$outPath" == "$outPath2" + +# Now using a base-64 hash. +clearStore + +hash=$(nix hash file --type sha512 --base64 ./fetchurl.sh) + +outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file://$(pwd)/fetchurl.sh --argstr sha512 $hash --no-out-link) + +cmp $outPath fetchurl.sh + +# Now using an SRI hash. +clearStore + +hash=$(nix hash file ./fetchurl.sh) + +[[ $hash =~ ^sha256- ]] + +outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file://$(pwd)/fetchurl.sh --argstr hash $hash --no-out-link) + +cmp $outPath fetchurl.sh + +# Test that we can substitute from a different store dir. +clearStore + +other_store=file://$TEST_ROOT/other_store?store=/fnord/store + +hash=$(nix hash file --type sha256 --base16 ./fetchurl.sh) + +storePath=$(nix --store $other_store store add-file ./fetchurl.sh) + +outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file:///no-such-dir/fetchurl.sh --argstr sha256 $hash --no-out-link --substituters $other_store) + +# Test hashed mirrors with an SRI hash. +nix-build -vvvvv --expr 'import ' --argstr url file:///no-such-dir/fetchurl.sh --argstr hash $(nix hash to-sri --type sha256 $hash) \ + --no-out-link --substituters $other_store + +# Test unpacking a NAR. +rm -rf $TEST_ROOT/archive +mkdir -p $TEST_ROOT/archive +cp ./fetchurl.sh $TEST_ROOT/archive +chmod +x $TEST_ROOT/archive/fetchurl.sh +ln -s foo $TEST_ROOT/archive/symlink +nar=$TEST_ROOT/archive.nar +nix-store --dump $TEST_ROOT/archive > $nar + +hash=$(nix-hash --flat --type sha256 $nar) + +outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file://$nar --argstr sha256 $hash \ + --arg unpack true --argstr name xyzzy --no-out-link) + +echo $outPath | grepQuiet 'xyzzy' + +test -x $outPath/fetchurl.sh +test -L $outPath/symlink + +nix-store --delete $outPath + +# Test unpacking a compressed NAR. +narxz=$TEST_ROOT/archive.nar.xz +rm -f $narxz +xz --keep $nar +outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file://$narxz --argstr sha256 $hash \ + --arg unpack true --argstr name xyzzy --no-out-link) + +test -x $outPath/fetchurl.sh +test -L $outPath/symlink diff --git a/tests/functional/filter-source.nix b/tests/functional/filter-source.nix new file mode 100644 index 000000000..907163639 --- /dev/null +++ b/tests/functional/filter-source.nix @@ -0,0 +1,12 @@ +with import ./config.nix; + +mkDerivation { + name = "filter"; + builder = builtins.toFile "builder" "ln -s $input $out"; + input = + let filter = path: type: + type != "symlink" + && baseNameOf path != "foo" + && !((import ./lang/lib.nix).hasSuffix ".bak" (baseNameOf path)); + in builtins.filterSource filter ((builtins.getEnv "TEST_ROOT") + "/filterin"); +} diff --git a/tests/functional/filter-source.sh b/tests/functional/filter-source.sh new file mode 100644 index 000000000..ba34d2eac --- /dev/null +++ b/tests/functional/filter-source.sh @@ -0,0 +1,25 @@ +source common.sh + +rm -rf $TEST_ROOT/filterin +mkdir $TEST_ROOT/filterin +mkdir $TEST_ROOT/filterin/foo +touch $TEST_ROOT/filterin/foo/bar +touch $TEST_ROOT/filterin/xyzzy +touch $TEST_ROOT/filterin/b +touch $TEST_ROOT/filterin/bak +touch $TEST_ROOT/filterin/bla.c.bak +ln -s xyzzy $TEST_ROOT/filterin/link + +checkFilter() { + test ! -e $1/foo/bar + test -e $1/xyzzy + test -e $1/bak + test ! -e $1/bla.c.bak + test ! -L $1/link +} + +nix-build ./filter-source.nix -o $TEST_ROOT/filterout1 +checkFilter $TEST_ROOT/filterout1 + +nix-build ./path.nix -o $TEST_ROOT/filterout2 +checkFilter $TEST_ROOT/filterout2 diff --git a/tests/functional/fixed.builder1.sh b/tests/functional/fixed.builder1.sh new file mode 100644 index 000000000..c41bb2b9a --- /dev/null +++ b/tests/functional/fixed.builder1.sh @@ -0,0 +1,3 @@ +if test "$IMPURE_VAR1" != "foo"; then exit 1; fi +if test "$IMPURE_VAR2" != "bar"; then exit 1; fi +echo "Hello World!" > $out diff --git a/tests/functional/fixed.builder2.sh b/tests/functional/fixed.builder2.sh new file mode 100644 index 000000000..31ea1579a --- /dev/null +++ b/tests/functional/fixed.builder2.sh @@ -0,0 +1,6 @@ +echo dummy: $dummy +if test -n "$dummy"; then sleep 2; fi +mkdir $out +mkdir $out/bla +echo "Hello World!" > $out/foo +ln -s foo $out/bar diff --git a/tests/functional/fixed.nix b/tests/functional/fixed.nix new file mode 100644 index 000000000..babe71504 --- /dev/null +++ b/tests/functional/fixed.nix @@ -0,0 +1,58 @@ +with import ./config.nix; + +rec { + + f2 = dummy: builder: mode: algo: hash: mkDerivation { + name = "fixed"; + inherit builder; + outputHashMode = mode; + outputHashAlgo = algo; + outputHash = hash; + inherit dummy; + impureEnvVars = ["IMPURE_VAR1" "IMPURE_VAR2"]; + }; + + f = f2 ""; + + good = [ + (f ./fixed.builder1.sh "flat" "md5" "8ddd8be4b179a529afa5f2ffae4b9858") + (f ./fixed.builder1.sh "flat" "sha1" "a0b65939670bc2c010f4d5d6a0b3e4e4590fb92b") + (f ./fixed.builder2.sh "recursive" "md5" "3670af73070fa14077ad74e0f5ea4e42") + (f ./fixed.builder2.sh "recursive" "sha1" "vw46m23bizj4n8afrc0fj19wrp7mj3c0") + ]; + + # Expression to test that `nix-build --check` also throws an error if the hash of + # fixed-output derivation has changed even if the hash exists in the store (in this + # case the hash exists because of `fixed.builder2.sh`, but building a derivation + # with the same hash and a different result must throw an error). + check = [ + (f ./fixed.builder1.sh "recursive" "md5" "3670af73070fa14077ad74e0f5ea4e42") + ]; + + good2 = [ + # Yes, this looks fscked up: builder2 doesn't have that result. + # But Nix sees that an output with the desired hash already + # exists, and will refrain from building it. + (f ./fixed.builder2.sh "flat" "md5" "8ddd8be4b179a529afa5f2ffae4b9858") + ]; + + sameAsAdd = + f ./fixed.builder2.sh "recursive" "sha256" "1ixr6yd3297ciyp9im522dfxpqbkhcw0pylkb2aab915278fqaik"; + + bad = [ + (f ./fixed.builder1.sh "flat" "md5" "0ddd8be4b179a529afa5f2ffae4b9858") + ]; + + reallyBad = [ + # Hash too short, and not base-32 either. + (f ./fixed.builder1.sh "flat" "md5" "ddd8be4b179a529afa5f2ffae4b9858") + ]; + + # Test for building two derivations in parallel that produce the + # same output path because they're fixed-output derivations. + parallelSame = [ + (f2 "foo" ./fixed.builder2.sh "recursive" "md5" "3670af73070fa14077ad74e0f5ea4e42") + (f2 "bar" ./fixed.builder2.sh "recursive" "md5" "3670af73070fa14077ad74e0f5ea4e42") + ]; + +} diff --git a/tests/functional/fixed.sh b/tests/functional/fixed.sh new file mode 100644 index 000000000..f1e1ce420 --- /dev/null +++ b/tests/functional/fixed.sh @@ -0,0 +1,58 @@ +source common.sh + +clearStore + +path=$(nix-store -q $(nix-instantiate fixed.nix -A good.0)) + +echo 'testing bad...' +nix-build fixed.nix -A bad --no-out-link && fail "should fail" + +# Building with the bad hash should produce the "good" output path as +# a side-effect. +[[ -e $path ]] +nix path-info --json $path | grep fixed:md5:2qk15sxzzjlnpjk9brn7j8ppcd + +echo 'testing good...' +nix-build fixed.nix -A good --no-out-link + +if isDaemonNewer "2.4pre20210927"; then + echo 'testing --check...' + nix-build fixed.nix -A check --check && fail "should fail" +fi + +echo 'testing good2...' +nix-build fixed.nix -A good2 --no-out-link + +echo 'testing reallyBad...' +nix-instantiate fixed.nix -A reallyBad && fail "should fail" + +# While we're at it, check attribute selection a bit more. +echo 'testing attribute selection...' +test $(nix-instantiate fixed.nix -A good.1 | wc -l) = 1 + +# Test parallel builds of derivations that produce the same output. +# Only one should run at the same time. +echo 'testing parallelSame...' +clearStore +nix-build fixed.nix -A parallelSame --no-out-link -j2 + +# Fixed-output derivations with a recursive SHA-256 hash should +# produce the same path as "nix-store --add". +echo 'testing sameAsAdd...' +out=$(nix-build fixed.nix -A sameAsAdd --no-out-link) + +# This is what fixed.builder2 produces... +rm -rf $TEST_ROOT/fixed +mkdir $TEST_ROOT/fixed +mkdir $TEST_ROOT/fixed/bla +echo "Hello World!" > $TEST_ROOT/fixed/foo +ln -s foo $TEST_ROOT/fixed/bar + +out2=$(nix-store --add $TEST_ROOT/fixed) +[ "$out" = "$out2" ] + +out3=$(nix-store --add-fixed --recursive sha256 $TEST_ROOT/fixed) +[ "$out" = "$out3" ] + +out4=$(nix-store --print-fixed-path --recursive sha256 "1ixr6yd3297ciyp9im522dfxpqbkhcw0pylkb2aab915278fqaik" fixed) +[ "$out" = "$out4" ] diff --git a/tests/functional/flakes/absolute-paths.sh b/tests/functional/flakes/absolute-paths.sh new file mode 100644 index 000000000..e7bfba12d --- /dev/null +++ b/tests/functional/flakes/absolute-paths.sh @@ -0,0 +1,17 @@ +source ./common.sh + +requireGit + +flake1Dir=$TEST_ROOT/flake1 +flake2Dir=$TEST_ROOT/flake2 + +createGitRepo $flake1Dir +cat > $flake1Dir/flake.nix < $flake1Dir/flake.nix < $flake1Dir/foo + +nix build --json --out-link $TEST_ROOT/result $flake1Dir#a1 +[[ -e $TEST_ROOT/result/simple.nix ]] + +nix build --json --out-link $TEST_ROOT/result $flake1Dir#a2 +[[ $(cat $TEST_ROOT/result) = bar ]] + +nix build --json --out-link $TEST_ROOT/result $flake1Dir#a3 + +nix build --json --out-link $TEST_ROOT/result $flake1Dir#a4 + +nix build --json --out-link $TEST_ROOT/result $flake1Dir#a6 +[[ -e $TEST_ROOT/result/simple.nix ]] + +nix build --impure --json --out-link $TEST_ROOT/result $flake1Dir#a8 +diff common.sh $TEST_ROOT/result + +expectStderr 1 nix build --impure --json --out-link $TEST_ROOT/result $flake1Dir#a9 \ + | grepQuiet "has 0 entries in its context. It should only have exactly one entry" + +nix build --json --out-link $TEST_ROOT/result $flake1Dir#a10 +[[ $(readlink -e $TEST_ROOT/result) = *simple.drv ]] + +expectStderr 1 nix build --json --out-link $TEST_ROOT/result $flake1Dir#a11 \ + | grepQuiet "has a context which refers to a complete source and binary closure" + +nix build --json --out-link $TEST_ROOT/result $flake1Dir#a12 +[[ -e $TEST_ROOT/result/hello ]] + +expectStderr 1 nix build --impure --json --out-link $TEST_ROOT/result $flake1Dir#a13 \ + | grepQuiet "has 2 entries in its context. It should only have exactly one entry" diff --git a/tests/functional/flakes/bundle.sh b/tests/functional/flakes/bundle.sh new file mode 100644 index 000000000..67bbb05ac --- /dev/null +++ b/tests/functional/flakes/bundle.sh @@ -0,0 +1,32 @@ +source common.sh + +cp ../simple.nix ../simple.builder.sh ../config.nix $TEST_HOME + +cd $TEST_HOME + +cat < flake.nix +{ + outputs = {self}: { + bundlers.$system = rec { + simple = drv: + if drv?type && drv.type == "derivation" + then drv + else self.packages.$system.default; + default = simple; + }; + packages.$system.default = import ./simple.nix; + apps.$system.default = { + type = "app"; + program = "\${import ./simple.nix}/hello"; + }; + }; +} +EOF + +nix build .# +nix bundle --bundler .# .# +nix bundle --bundler .#bundlers.$system.default .#packages.$system.default +nix bundle --bundler .#bundlers.$system.simple .#packages.$system.default + +nix bundle --bundler .#bundlers.$system.default .#apps.$system.default +nix bundle --bundler .#bundlers.$system.simple .#apps.$system.default diff --git a/tests/functional/flakes/check.sh b/tests/functional/flakes/check.sh new file mode 100644 index 000000000..0433e5335 --- /dev/null +++ b/tests/functional/flakes/check.sh @@ -0,0 +1,91 @@ +source common.sh + +flakeDir=$TEST_ROOT/flake3 +mkdir -p $flakeDir + +cat > $flakeDir/flake.nix < $flakeDir/flake.nix < $flakeDir/flake.nix <&1 && fail "nix flake check --all-systems should have failed" || true) +echo "$checkRes" | grepQuiet "error: overlay is not a function, but a set instead" + +cat > $flakeDir/flake.nix < $flakeDir/flake.nix < $flakeDir/flake.nix < $flakeDir/flake.nix <&1 && fail "nix flake check --all-systems should have failed" || true) +echo "$checkRes" | grepQuiet "packages.system-1.default" +echo "$checkRes" | grepQuiet "packages.system-2.default" diff --git a/tests/functional/flakes/circular.sh b/tests/functional/flakes/circular.sh new file mode 100644 index 000000000..09cd02edf --- /dev/null +++ b/tests/functional/flakes/circular.sh @@ -0,0 +1,49 @@ +# Test circular flake dependencies. +source ./common.sh + +requireGit + +flakeA=$TEST_ROOT/flakeA +flakeB=$TEST_ROOT/flakeB + +createGitRepo $flakeA +createGitRepo $flakeB + +cat > $flakeA/flake.nix < $flakeB/flake.nix < $flakeDir/flake.nix < $flakeDir/flake.nix < $flakeDir/flake.nix < echoing-post-hook.sh +#!/bin/sh + +echo "ThePostHookRan as \$0" > $PWD/post-hook-ran +EOF +chmod +x echoing-post-hook.sh + +cat < flake.nix +{ + nixConfig.post-build-hook = ./echoing-post-hook.sh; + nixConfig.allow-dirty = false; # See #5621 + + outputs = a: { + packages.$system.default = import ./simple.nix; + }; +} +EOF + +# Without --accept-flake-config, the post hook should not run. +nix build < /dev/null +(! [[ -f post-hook-ran ]]) +clearStore + +nix build --accept-flake-config +test -f post-hook-ran || fail "The post hook should have ran" + +# Make sure that the path to the post hook doesn’t change if we change +# something in the flake. +# Otherwise the user would have to re-validate the setting each time. +mv post-hook-ran previous-post-hook-run +echo "# Dummy comment" >> flake.nix +clearStore +nix build --accept-flake-config +diff -q post-hook-ran previous-post-hook-run || \ + fail "Both post hook runs should report the same filename" diff --git a/tests/functional/flakes/flake-in-submodule.sh b/tests/functional/flakes/flake-in-submodule.sh new file mode 100644 index 000000000..21a4b52de --- /dev/null +++ b/tests/functional/flakes/flake-in-submodule.sh @@ -0,0 +1,52 @@ +source common.sh + +# Tests that: +# - flake.nix may reside inside of a git submodule +# - the flake can access content outside of the submodule +# +# rootRepo +# ├── root.nix +# └── submodule +# ├── flake.nix +# └── sub.nix + + +requireGit + +clearStore + +# Submodules can't be fetched locally by default. +# See fetchGitSubmodules.sh +export XDG_CONFIG_HOME=$TEST_HOME/.config +git config --global protocol.file.allow always + + +rootRepo=$TEST_ROOT/rootRepo +subRepo=$TEST_ROOT/submodule + + +createGitRepo $subRepo +cat > $subRepo/flake.nix < $subRepo/sub.nix +git -C $subRepo add flake.nix sub.nix +git -C $subRepo commit -m Initial + +createGitRepo $rootRepo + +git -C $rootRepo submodule init +git -C $rootRepo submodule add $subRepo submodule +echo '"expression in root repo"' > $rootRepo/root.nix +git -C $rootRepo add root.nix +git -C $rootRepo commit -m "Add root.nix" + +# Flake can live inside a submodule and can be accessed via ?dir=submodule +[[ $(nix eval --json git+file://$rootRepo\?submodules=1\&dir=submodule#sub ) = '"expression in submodule"' ]] +# The flake can access content outside of the submodule +[[ $(nix eval --json git+file://$rootRepo\?submodules=1\&dir=submodule#root ) = '"expression in root repo"' ]] diff --git a/tests/functional/flakes/flakes.sh b/tests/functional/flakes/flakes.sh new file mode 100644 index 000000000..128f759ea --- /dev/null +++ b/tests/functional/flakes/flakes.sh @@ -0,0 +1,511 @@ +source ./common.sh + +requireGit + +clearStore +rm -rf $TEST_HOME/.cache $TEST_HOME/.config + +flake1Dir=$TEST_ROOT/flake1 +flake2Dir=$TEST_ROOT/flake2 +flake3Dir=$TEST_ROOT/flake3 +flake5Dir=$TEST_ROOT/flake5 +flake7Dir=$TEST_ROOT/flake7 +nonFlakeDir=$TEST_ROOT/nonFlake +badFlakeDir=$TEST_ROOT/badFlake +flakeGitBare=$TEST_ROOT/flakeGitBare + +for repo in $flake1Dir $flake2Dir $flake3Dir $flake7Dir $nonFlakeDir; do + # Give one repo a non-main initial branch. + extraArgs= + if [[ $repo == $flake2Dir ]]; then + extraArgs="--initial-branch=main" + fi + + createGitRepo "$repo" "$extraArgs" +done + +createSimpleGitFlake $flake1Dir + +cat > $flake2Dir/flake.nix < $flake3Dir/flake.nix < $flake3Dir/default.nix < $nonFlakeDir/README.md < $flake1Dir/foo +git -C $flake1Dir add $flake1Dir/foo +[[ $(nix flake metadata flake1 --json --refresh | jq -r .dirtyRevision) == "$hash1-dirty" ]] + +echo -n '# foo' >> $flake1Dir/flake.nix +flake1OriginalCommit=$(git -C $flake1Dir rev-parse HEAD) +git -C $flake1Dir commit -a -m 'Foo' +flake1NewCommit=$(git -C $flake1Dir rev-parse HEAD) +hash2=$(nix flake metadata flake1 --json --refresh | jq -r .revision) +[[ $(nix flake metadata flake1 --json --refresh | jq -r .dirtyRevision) == "null" ]] +[[ $hash1 != $hash2 ]] + +# Test 'nix build' on a flake. +nix build -o $TEST_ROOT/result flake1#foo +[[ -e $TEST_ROOT/result/hello ]] + +# Test packages.default. +nix build -o $TEST_ROOT/result flake1 +[[ -e $TEST_ROOT/result/hello ]] + +nix build -o $TEST_ROOT/result $flake1Dir +nix build -o $TEST_ROOT/result git+file://$flake1Dir + +# Check that store symlinks inside a flake are not interpreted as flakes. +nix build -o $flake1Dir/result git+file://$flake1Dir +nix path-info $flake1Dir/result + +# 'getFlake' on an unlocked flakeref should fail in pure mode, but +# succeed in impure mode. +(! nix build -o $TEST_ROOT/result --expr "(builtins.getFlake \"$flake1Dir\").packages.$system.default") +nix build -o $TEST_ROOT/result --expr "(builtins.getFlake \"$flake1Dir\").packages.$system.default" --impure + +# 'getFlake' on a locked flakeref should succeed even in pure mode. +nix build -o $TEST_ROOT/result --expr "(builtins.getFlake \"git+file://$flake1Dir?rev=$hash2\").packages.$system.default" + +# Building a flake with an unlocked dependency should fail in pure mode. +(! nix build -o $TEST_ROOT/result flake2#bar --no-registries) +(! nix build -o $TEST_ROOT/result flake2#bar --no-use-registries) +(! nix eval --expr "builtins.getFlake \"$flake2Dir\"") + +# But should succeed in impure mode. +(! nix build -o $TEST_ROOT/result flake2#bar --impure) +nix build -o $TEST_ROOT/result flake2#bar --impure --no-write-lock-file +nix eval --expr "builtins.getFlake \"$flake2Dir\"" --impure + +# Building a local flake with an unlocked dependency should fail with --no-update-lock-file. +expect 1 nix build -o $TEST_ROOT/result $flake2Dir#bar --no-update-lock-file 2>&1 | grep 'requires lock file changes' + +# But it should succeed without that flag. +nix build -o $TEST_ROOT/result $flake2Dir#bar --no-write-lock-file +expect 1 nix build -o $TEST_ROOT/result $flake2Dir#bar --no-update-lock-file 2>&1 | grep 'requires lock file changes' +nix build -o $TEST_ROOT/result $flake2Dir#bar --commit-lock-file +[[ -e $flake2Dir/flake.lock ]] +[[ -z $(git -C $flake2Dir diff main || echo failed) ]] + +# Rerunning the build should not change the lockfile. +nix build -o $TEST_ROOT/result $flake2Dir#bar +[[ -z $(git -C $flake2Dir diff main || echo failed) ]] + +# Building with a lockfile should not require a fetch of the registry. +nix build -o $TEST_ROOT/result --flake-registry file:///no-registry.json $flake2Dir#bar --refresh +nix build -o $TEST_ROOT/result --no-registries $flake2Dir#bar --refresh +nix build -o $TEST_ROOT/result --no-use-registries $flake2Dir#bar --refresh + +# Updating the flake should not change the lockfile. +nix flake lock $flake2Dir +[[ -z $(git -C $flake2Dir diff main || echo failed) ]] + +# Now we should be able to build the flake in pure mode. +nix build -o $TEST_ROOT/result flake2#bar + +# Or without a registry. +nix build -o $TEST_ROOT/result --no-registries git+file://$flake2Dir#bar --refresh +nix build -o $TEST_ROOT/result --no-use-registries git+file://$flake2Dir#bar --refresh + +# Test whether indirect dependencies work. +nix build -o $TEST_ROOT/result $flake3Dir#xyzzy +git -C $flake3Dir add flake.lock + +# Add dependency to flake3. +rm $flake3Dir/flake.nix + +cat > $flake3Dir/flake.nix < $flake3Dir/flake.nix < \$out + [[ \$(cat \${inputs.nonFlake}/README.md) = \$(cat \${inputs.nonFlakeFile}) ]] + [[ \${inputs.nonFlakeFile} = \${inputs.nonFlakeFile2} ]] + ''; + }; + }; +} +EOF + +cp ../config.nix $flake3Dir + +git -C $flake3Dir add flake.nix config.nix +git -C $flake3Dir commit -m 'Add nonFlakeInputs' + +# Check whether `nix build` works with a lockfile which is missing a +# nonFlakeInputs. +nix build -o $TEST_ROOT/result $flake3Dir#sth --commit-lock-file + +nix build -o $TEST_ROOT/result flake3#fnord +[[ $(cat $TEST_ROOT/result) = FNORD ]] + +# Check whether flake input fetching is lazy: flake3#sth does not +# depend on flake2, so this shouldn't fail. +rm -rf $TEST_HOME/.cache +clearStore +mv $flake2Dir $flake2Dir.tmp +mv $nonFlakeDir $nonFlakeDir.tmp +nix build -o $TEST_ROOT/result flake3#sth +(! nix build -o $TEST_ROOT/result flake3#xyzzy) +(! nix build -o $TEST_ROOT/result flake3#fnord) +mv $flake2Dir.tmp $flake2Dir +mv $nonFlakeDir.tmp $nonFlakeDir +nix build -o $TEST_ROOT/result flake3#xyzzy flake3#fnord + +# Test doing multiple `lookupFlake`s +nix build -o $TEST_ROOT/result flake4#xyzzy + +# Test 'nix flake update' and --override-flake. +nix flake lock $flake3Dir +[[ -z $(git -C $flake3Dir diff master || echo failed) ]] + +nix flake update $flake3Dir --override-flake flake2 nixpkgs +[[ ! -z $(git -C $flake3Dir diff master || echo failed) ]] + +# Make branch "removeXyzzy" where flake3 doesn't have xyzzy anymore +git -C $flake3Dir checkout -b removeXyzzy +rm $flake3Dir/flake.nix + +cat > $flake3Dir/flake.nix < \$out + ''; + }; + }; +} +EOF +nix flake lock $flake3Dir +git -C $flake3Dir add flake.nix flake.lock +git -C $flake3Dir commit -m 'Remove packages.xyzzy' +git -C $flake3Dir checkout master + +# Test whether fuzzy-matching works for registry entries. +(! nix build -o $TEST_ROOT/result flake4/removeXyzzy#xyzzy) +nix build -o $TEST_ROOT/result flake4/removeXyzzy#sth + +# Testing the nix CLI +nix registry add flake1 flake3 +[[ $(nix registry list | wc -l) == 6 ]] +nix registry pin flake1 +[[ $(nix registry list | wc -l) == 6 ]] +nix registry pin flake1 flake3 +[[ $(nix registry list | wc -l) == 6 ]] +nix registry remove flake1 +[[ $(nix registry list | wc -l) == 5 ]] + +# Test 'nix registry list' with a disabled global registry. +nix registry add user-flake1 git+file://$flake1Dir +nix registry add user-flake2 git+file://$flake2Dir +[[ $(nix --flake-registry "" registry list | wc -l) == 2 ]] +nix --flake-registry "" registry list | grepQuietInverse '^global' # nothing in global registry +nix --flake-registry "" registry list | grepQuiet '^user' +nix registry remove user-flake1 +nix registry remove user-flake2 +[[ $(nix registry list | wc -l) == 5 ]] + +# Test 'nix flake clone'. +rm -rf $TEST_ROOT/flake1-v2 +nix flake clone flake1 --dest $TEST_ROOT/flake1-v2 +[ -e $TEST_ROOT/flake1-v2/flake.nix ] + +# Test 'follows' inputs. +cat > $flake3Dir/flake.nix < $flake3Dir/flake.nix < $flake3Dir/flake.nix < $flake3Dir/flake.nix < $flake3Dir/flake.nix < $badFlakeDir/flake.nix +nix store delete $(nix store add-path $badFlakeDir) + +[[ $(nix path-info $(nix store add-path $flake1Dir)) =~ flake1 ]] +[[ $(nix path-info path:$(nix store add-path $flake1Dir)) =~ simple ]] + +# Test fetching flakerefs in the legacy CLI. +[[ $(nix-instantiate --eval flake:flake3 -A x) = 123 ]] +[[ $(nix-instantiate --eval flake:git+file://$flake3Dir -A x) = 123 ]] +[[ $(nix-instantiate -I flake3=flake:flake3 --eval '' -A x) = 123 ]] +[[ $(NIX_PATH=flake3=flake:flake3 nix-instantiate --eval '' -A x) = 123 ]] + +# Test alternate lockfile paths. +nix flake lock $flake2Dir --output-lock-file $TEST_ROOT/flake2.lock +cmp $flake2Dir/flake.lock $TEST_ROOT/flake2.lock >/dev/null # lockfiles should be identical, since we're referencing flake2's original one + +nix flake lock $flake2Dir --output-lock-file $TEST_ROOT/flake2-overridden.lock --override-input flake1 git+file://$flake1Dir?rev=$flake1OriginalCommit +expectStderr 1 cmp $flake2Dir/flake.lock $TEST_ROOT/flake2-overridden.lock +nix flake metadata $flake2Dir --reference-lock-file $TEST_ROOT/flake2-overridden.lock | grepQuiet $flake1OriginalCommit + +# reference-lock-file can only be used if allow-dirty is set. +expectStderr 1 nix flake metadata $flake2Dir --no-allow-dirty --reference-lock-file $TEST_ROOT/flake2-overridden.lock diff --git a/tests/functional/flakes/follow-paths.sh b/tests/functional/flakes/follow-paths.sh new file mode 100644 index 000000000..dc97027ac --- /dev/null +++ b/tests/functional/flakes/follow-paths.sh @@ -0,0 +1,232 @@ +source ./common.sh + +requireGit + +flakeFollowsA=$TEST_ROOT/follows/flakeA +flakeFollowsB=$TEST_ROOT/follows/flakeA/flakeB +flakeFollowsC=$TEST_ROOT/follows/flakeA/flakeB/flakeC +flakeFollowsD=$TEST_ROOT/follows/flakeA/flakeD +flakeFollowsE=$TEST_ROOT/follows/flakeA/flakeE + +# Test following path flakerefs. +createGitRepo $flakeFollowsA +mkdir -p $flakeFollowsB +mkdir -p $flakeFollowsC +mkdir -p $flakeFollowsD +mkdir -p $flakeFollowsE + +cat > $flakeFollowsA/flake.nix < $flakeFollowsB/flake.nix < $flakeFollowsC/flake.nix < $flakeFollowsD/flake.nix < $flakeFollowsE/flake.nix < $flakeFollowsA/flake.nix < $flakeFollowsA/flake.nix <&1 | grep 'points outside' + +# Non-existant follows should print a warning. +cat >$flakeFollowsA/flake.nix <&1 | grep "warning: input 'B' has an override for a non-existent input 'invalid'" +nix flake lock "$flakeFollowsA" 2>&1 | grep "warning: input 'B' has an override for a non-existent input 'invalid2'" + +# Now test follow path overloading +# This tests a lockfile checking regression https://github.com/NixOS/nix/pull/8819 +# +# We construct the following graph, where p->q means p has input q. +# A double edge means that the edge gets overridden using `follows`. +# +# A +# / \ +# / \ +# v v +# B ==> C --- follows declared in A +# \\ / +# \\/ --- follows declared in B +# v +# D +# +# The message was +# error: input 'B/D' follows a non-existent input 'B/C/D' +# +# Note that for `B` to resolve its follow for `D`, it needs `C/D`, for which it needs to resolve the follow on `C` first. +flakeFollowsOverloadA="$TEST_ROOT/follows/overload/flakeA" +flakeFollowsOverloadB="$TEST_ROOT/follows/overload/flakeA/flakeB" +flakeFollowsOverloadC="$TEST_ROOT/follows/overload/flakeA/flakeB/flakeC" +flakeFollowsOverloadD="$TEST_ROOT/follows/overload/flakeA/flakeB/flakeC/flakeD" + +# Test following path flakerefs. +createGitRepo "$flakeFollowsOverloadA" +mkdir -p "$flakeFollowsOverloadB" +mkdir -p "$flakeFollowsOverloadC" +mkdir -p "$flakeFollowsOverloadD" + +cat > "$flakeFollowsOverloadD/flake.nix" < "$flakeFollowsOverloadC/flake.nix" < "$flakeFollowsOverloadB/flake.nix" < "$flakeFollowsOverloadA/flake.nix" < $templatesDir/flake.nix < $templatesDir/trivial/flake.nix < $templatesDir/trivial/a +echo b > $templatesDir/trivial/b + +git -C $templatesDir add flake.nix trivial/ +git -C $templatesDir commit -m 'Initial' + +nix flake check templates +nix flake show templates +nix flake show templates --json | jq + +createGitRepo $flakeDir +(cd $flakeDir && nix flake init) +(cd $flakeDir && nix flake init) # check idempotence +git -C $flakeDir add flake.nix +nix flake check $flakeDir +nix flake show $flakeDir +nix flake show $flakeDir --json | jq +git -C $flakeDir commit -a -m 'Initial' + +# Test 'nix flake init' with benign conflicts +createGitRepo "$flakeDir" +echo a > $flakeDir/a +(cd $flakeDir && nix flake init) # check idempotence + +# Test 'nix flake init' with conflicts +createGitRepo "$flakeDir" +echo b > $flakeDir/a +pushd $flakeDir +(! nix flake init) |& grep "refusing to overwrite existing file '$flakeDir/a'" +popd +git -C $flakeDir commit -a -m 'Changed' + +# Test 'nix flake new'. +rm -rf $flakeDir +nix flake new -t templates#trivial $flakeDir +nix flake new -t templates#trivial $flakeDir # check idempotence +nix flake check $flakeDir diff --git a/tests/functional/flakes/inputs.sh b/tests/functional/flakes/inputs.sh new file mode 100644 index 000000000..80620488a --- /dev/null +++ b/tests/functional/flakes/inputs.sh @@ -0,0 +1,80 @@ +source ./common.sh + +requireGit + + +test_subdir_self_path() { + baseDir=$TEST_ROOT/$RANDOM + flakeDir=$baseDir/b-low + mkdir -p $flakeDir + writeSimpleFlake $baseDir + writeSimpleFlake $flakeDir + + echo all good > $flakeDir/message + cat > $flakeDir/flake.nix < $flakeDir/message + cat > $flakeDir/flake.nix < $clientDir/flake.nix < flake.nix +{ + outputs = {self}: { + packages.$system.pkgAsPkg = (import ./shell-hello.nix).hello; + packages.$system.appAsApp = self.packages.$system.appAsApp; + + apps.$system.pkgAsApp = self.packages.$system.pkgAsPkg; + apps.$system.appAsApp = { + type = "app"; + program = "\${(import ./shell-hello.nix).hello}/bin/hello"; + }; + }; +} +EOF +nix run --no-write-lock-file .#appAsApp +nix run --no-write-lock-file .#pkgAsPkg + +! nix run --no-write-lock-file .#pkgAsApp || fail "'nix run' shouldn’t accept an 'app' defined under 'packages'" +! nix run --no-write-lock-file .#appAsPkg || fail "elements of 'apps' should be of type 'app'" + +clearStore + diff --git a/tests/functional/flakes/search-root.sh b/tests/functional/flakes/search-root.sh new file mode 100644 index 000000000..d8586dc8a --- /dev/null +++ b/tests/functional/flakes/search-root.sh @@ -0,0 +1,50 @@ +source common.sh + +clearStore + +writeSimpleFlake $TEST_HOME +cd $TEST_HOME +mkdir -p foo/subdir + +echo '{ outputs = _: {}; }' > foo/flake.nix +cat < flake.nix +{ + inputs.foo.url = "$PWD/foo"; + outputs = a: { + packages.$system = rec { + test = import ./simple.nix; + default = test; + }; + }; +} +EOF +mkdir subdir +pushd subdir + +success=("" . .# .#test ../subdir ../subdir#test "$PWD") +failure=("path:$PWD") + +for i in "${success[@]}"; do + nix build $i || fail "flake should be found by searching up directories" +done + +for i in "${failure[@]}"; do + ! nix build $i || fail "flake should not search up directories when using 'path:'" +done + +popd + +nix build --override-input foo . || fail "flake should search up directories when not an installable" + +sed "s,$PWD/foo,$PWD/foo/subdir,g" -i flake.nix +! nix build || fail "flake should not search upwards when part of inputs" + +if [[ -n $(type -p git) ]]; then + pushd subdir + git init + for i in "${success[@]}" "${failure[@]}"; do + ! nix build $i || fail "flake should not search past a git repository" + done + rm -rf .git + popd +fi diff --git a/tests/functional/flakes/show.sh b/tests/functional/flakes/show.sh new file mode 100644 index 000000000..a3d300552 --- /dev/null +++ b/tests/functional/flakes/show.sh @@ -0,0 +1,87 @@ +source ./common.sh + +flakeDir=$TEST_ROOT/flake +mkdir -p "$flakeDir" + +writeSimpleFlake "$flakeDir" +cd "$flakeDir" + + +# By default: Only show the packages content for the current system and no +# legacyPackages at all +nix flake show --json > show-output.json +nix eval --impure --expr ' +let show_output = builtins.fromJSON (builtins.readFile ./show-output.json); +in +assert show_output.packages.someOtherSystem.default == {}; +assert show_output.packages.${builtins.currentSystem}.default.name == "simple"; +assert show_output.legacyPackages.${builtins.currentSystem} == {}; +true +' + +# With `--all-systems`, show the packages for all systems +nix flake show --json --all-systems > show-output.json +nix eval --impure --expr ' +let show_output = builtins.fromJSON (builtins.readFile ./show-output.json); +in +assert show_output.packages.someOtherSystem.default.name == "simple"; +assert show_output.legacyPackages.${builtins.currentSystem} == {}; +true +' + +# With `--legacy`, show the legacy packages +nix flake show --json --legacy > show-output.json +nix eval --impure --expr ' +let show_output = builtins.fromJSON (builtins.readFile ./show-output.json); +in +assert show_output.legacyPackages.${builtins.currentSystem}.hello.name == "simple"; +true +' + +# Test that attributes are only reported when they have actual content +cat >flake.nix < show-output.json +nix eval --impure --expr ' +let show_output = builtins.fromJSON (builtins.readFile ./show-output.json); +in +assert show_output == { }; +true +' + +# Test that attributes with errors are handled correctly. +# nixpkgs.legacyPackages is a particularly prominent instance of this. +cat >flake.nix < show-output.json +nix eval --impure --expr ' +let show_output = builtins.fromJSON (builtins.readFile ./show-output.json); +in +assert show_output.legacyPackages.${builtins.currentSystem}.AAAAAASomeThingsFailToEvaluate == { }; +assert show_output.legacyPackages.${builtins.currentSystem}.simple.name == "simple"; +true +' diff --git a/tests/functional/flakes/unlocked-override.sh b/tests/functional/flakes/unlocked-override.sh new file mode 100644 index 000000000..8abc8b7d3 --- /dev/null +++ b/tests/functional/flakes/unlocked-override.sh @@ -0,0 +1,30 @@ +source ./common.sh + +requireGit + +flake1Dir=$TEST_ROOT/flake1 +flake2Dir=$TEST_ROOT/flake2 + +createGitRepo $flake1Dir +cat > $flake1Dir/flake.nix < $flake1Dir/x.nix +git -C $flake1Dir add flake.nix x.nix +git -C $flake1Dir commit -m Initial + +createGitRepo $flake2Dir +cat > $flake2Dir/flake.nix < $flake1Dir/x.nix + +[[ $(nix eval --json $flake2Dir#x --override-input flake1 $TEST_ROOT/flake1) = 456 ]] diff --git a/tests/functional/fmt.sh b/tests/functional/fmt.sh new file mode 100644 index 000000000..3c1bd9989 --- /dev/null +++ b/tests/functional/fmt.sh @@ -0,0 +1,33 @@ +source common.sh + +clearStore +rm -rf $TEST_HOME/.cache $TEST_HOME/.config $TEST_HOME/.local + +cp ./simple.nix ./simple.builder.sh ./fmt.simple.sh ./config.nix $TEST_HOME + +cd $TEST_HOME + +nix fmt --help | grep "Format" + +cat << EOF > flake.nix +{ + outputs = _: { + formatter.$system = + with import ./config.nix; + mkDerivation { + name = "formatter"; + buildCommand = '' + mkdir -p \$out/bin + echo "#! ${shell}" > \$out/bin/formatter + cat \${./fmt.simple.sh} >> \$out/bin/formatter + chmod +x \$out/bin/formatter + ''; + }; + }; +} +EOF +nix fmt ./file ./folder | grep 'Formatting: ./file ./folder' +nix flake check +nix flake show | grep -P "package 'formatter'" + +clearStore diff --git a/tests/functional/fmt.simple.sh b/tests/functional/fmt.simple.sh new file mode 100755 index 000000000..4c8c67ebb --- /dev/null +++ b/tests/functional/fmt.simple.sh @@ -0,0 +1 @@ +echo Formatting: "${@}" diff --git a/tests/functional/function-trace.sh b/tests/functional/function-trace.sh new file mode 100755 index 000000000..bd804bf18 --- /dev/null +++ b/tests/functional/function-trace.sh @@ -0,0 +1,67 @@ +source common.sh + +set +x + +expect_trace() { + expr="$1" + expect="$2" + actual=$( + nix-instantiate \ + --trace-function-calls \ + --expr "$expr" 2>&1 \ + | grep "function-trace" \ + | sed -e 's/ [0-9]*$//' \ + || true + ) + + echo -n "Tracing expression '$expr'" + msg=$(diff -swB \ + <(echo "$expect") \ + <(echo "$actual") + ) && result=0 || result=$? + if [ $result -eq 0 ]; then + echo " ok." + else + echo " failed. difference:" + echo "$msg" + return $result + fi +} + +# failure inside a tryEval +expect_trace 'builtins.tryEval (throw "example")' " +function-trace entered «string»:1:1 at +function-trace entered «string»:1:19 at +function-trace exited «string»:1:19 at +function-trace exited «string»:1:1 at +" + +# Missing argument to a formal function +expect_trace '({ x }: x) { }' " +function-trace entered «string»:1:1 at +function-trace exited «string»:1:1 at +" + +# Too many arguments to a formal function +expect_trace '({ x }: x) { x = "x"; y = "y"; }' " +function-trace entered «string»:1:1 at +function-trace exited «string»:1:1 at +" + +# Not enough arguments to a lambda +expect_trace '(x: y: x + y) 1' " +function-trace entered «string»:1:1 at +function-trace exited «string»:1:1 at +" + +# Too many arguments to a lambda +expect_trace '(x: x) 1 2' " +function-trace entered «string»:1:1 at +function-trace exited «string»:1:1 at +" + +# Not a function +expect_trace '1 2' " +function-trace entered «string»:1:1 at +function-trace exited «string»:1:1 at +" diff --git a/tests/functional/gc-auto.sh b/tests/functional/gc-auto.sh new file mode 100644 index 000000000..521d9e539 --- /dev/null +++ b/tests/functional/gc-auto.sh @@ -0,0 +1,81 @@ +source common.sh + +needLocalStore "“min-free” and “max-free” are daemon options" + +clearStore + +garbage1=$(nix store add-path --name garbage1 ./nar-access.sh) +garbage2=$(nix store add-path --name garbage2 ./nar-access.sh) +garbage3=$(nix store add-path --name garbage3 ./nar-access.sh) + +ls -l $garbage3 +POSIXLY_CORRECT=1 du $garbage3 + +fake_free=$TEST_ROOT/fake-free +export _NIX_TEST_FREE_SPACE_FILE=$fake_free +echo 1100 > $fake_free + +fifoLock=$TEST_ROOT/fifoLock +mkfifo "$fifoLock" + +expr=$(cat < \$out/bar + + # Pretend that we run out of space + echo 100 > ${fake_free}.tmp1 + mv ${fake_free}.tmp1 $fake_free + + # Wait for the GC to run + for i in {1..20}; do + echo ''\${i}... + if [[ \$(ls \$NIX_STORE/*-garbage? | wc -l) = 1 ]]; then + exit 0 + fi + sleep 1 + done + exit 1 + ''; +} +EOF +) + +expr2=$(cat < \$out/bar + + # Wait for the first build to finish + cat "$fifoLock" + ''; +} +EOF +) + +nix build --impure -v -o $TEST_ROOT/result-A -L --expr "$expr" \ + --min-free 1000 --max-free 2000 --min-free-check-interval 1 & +pid1=$! + +nix build --impure -v -o $TEST_ROOT/result-B -L --expr "$expr2" \ + --min-free 1000 --max-free 2000 --min-free-check-interval 1 & +pid2=$! + +# Once the first build is done, unblock the second one. +# If the first build fails, we need to postpone the failure to still allow +# the second one to finish +wait "$pid1" || FIRSTBUILDSTATUS=$? +echo "unlock" > $fifoLock +( exit ${FIRSTBUILDSTATUS:-0} ) +wait "$pid2" + +[[ foo = $(cat $TEST_ROOT/result-A/bar) ]] +[[ foo = $(cat $TEST_ROOT/result-B/bar) ]] diff --git a/tests/functional/gc-concurrent.builder.sh b/tests/functional/gc-concurrent.builder.sh new file mode 100644 index 000000000..bb6dcd4cf --- /dev/null +++ b/tests/functional/gc-concurrent.builder.sh @@ -0,0 +1,16 @@ +echo "Build started" > "$lockFifo" + +mkdir $out +echo $(cat $input1/foo)$(cat $input2/bar) > $out/foobar + +# Wait for someone to write on the fifo +cat "$lockFifo" + +# $out should not have been GC'ed while we were sleeping, but just in +# case... +mkdir -p $out + +# Check that the GC hasn't deleted the lock on our output. +test -e "$out.lock" + +ln -s $input2 $out/input-2 diff --git a/tests/functional/gc-concurrent.nix b/tests/functional/gc-concurrent.nix new file mode 100644 index 000000000..0aba1f983 --- /dev/null +++ b/tests/functional/gc-concurrent.nix @@ -0,0 +1,30 @@ +with import ./config.nix; + +{ lockFifo ? null }: + +rec { + + input1 = mkDerivation { + name = "dependencies-input-1"; + buildCommand = "mkdir $out; echo FOO > $out/foo"; + }; + + input2 = mkDerivation { + name = "dependencies-input-2"; + buildCommand = "mkdir $out; echo BAR > $out/bar"; + }; + + test1 = mkDerivation { + name = "gc-concurrent"; + builder = ./gc-concurrent.builder.sh; + inherit input1 input2; + inherit lockFifo; + }; + + test2 = mkDerivation { + name = "gc-concurrent2"; + builder = ./gc-concurrent2.builder.sh; + inherit input1 input2; + }; + +} diff --git a/tests/functional/gc-concurrent.sh b/tests/functional/gc-concurrent.sh new file mode 100644 index 000000000..2c6622c62 --- /dev/null +++ b/tests/functional/gc-concurrent.sh @@ -0,0 +1,59 @@ +source common.sh + +clearStore + +lockFifo1=$TEST_ROOT/test1.fifo +mkfifo "$lockFifo1" + +drvPath1=$(nix-instantiate gc-concurrent.nix -A test1 --argstr lockFifo "$lockFifo1") +outPath1=$(nix-store -q $drvPath1) + +drvPath2=$(nix-instantiate gc-concurrent.nix -A test2) +outPath2=$(nix-store -q $drvPath2) + +drvPath3=$(nix-instantiate simple.nix) +outPath3=$(nix-store -r $drvPath3) + +(! test -e $outPath3.lock) +touch $outPath3.lock + +rm -f "$NIX_STATE_DIR"/gcroots/foo* +ln -s $drvPath2 "$NIX_STATE_DIR"/gcroots/foo +ln -s $outPath3 "$NIX_STATE_DIR"/gcroots/foo2 + +# Start build #1 in the background. It starts immediately. +nix-store -rvv "$drvPath1" & +pid1=$! + +# Wait for the build of $drvPath1 to start +cat $lockFifo1 + +# Run the garbage collector while the build is running. +nix-collect-garbage + +# Unlock the build of $drvPath1 +echo "" > $lockFifo1 +echo waiting for pid $pid1 to finish... +wait $pid1 + +# Check that the root of build #1 and its dependencies haven't been +# deleted. The should not be deleted by the GC because they were +# being built during the GC. +cat $outPath1/foobar +cat $outPath1/input-2/bar + +# Check that the build build $drvPath2 succeeds. +# It should succeed because the derivation is a GC root. +nix-store -rvv "$drvPath2" +cat $outPath2/foobar + +rm -f "$NIX_STATE_DIR"/gcroots/foo* + +# The collector should have deleted lock files for paths that have +# been built previously. +(! test -e $outPath3.lock) + +# If we run the collector now, it should delete outPath1/2. +nix-collect-garbage +(! test -e $outPath1) +(! test -e $outPath2) diff --git a/tests/functional/gc-concurrent2.builder.sh b/tests/functional/gc-concurrent2.builder.sh new file mode 100644 index 000000000..4f6c58b96 --- /dev/null +++ b/tests/functional/gc-concurrent2.builder.sh @@ -0,0 +1,5 @@ +mkdir $out +echo $(cat $input1/foo)$(cat $input2/bar)xyzzy > $out/foobar + +# Check that the GC hasn't deleted the lock on our output. +test -e "$out.lock" diff --git a/tests/functional/gc-non-blocking.sh b/tests/functional/gc-non-blocking.sh new file mode 100644 index 000000000..0d781485d --- /dev/null +++ b/tests/functional/gc-non-blocking.sh @@ -0,0 +1,33 @@ +# Test whether the collector is non-blocking, i.e. a build can run in +# parallel with it. +source common.sh + +needLocalStore "the GC test needs a synchronisation point" + +clearStore + +fifo=$TEST_ROOT/test.fifo +mkfifo "$fifo" + +dummy=$(nix store add-path ./simple.nix) + +running=$TEST_ROOT/running +touch $running + +(_NIX_TEST_GC_SYNC=$fifo nix-store --gc -vvvvv; rm $running) & +pid=$! + +sleep 2 + +outPath=$(nix-build --max-silent-time 60 -o "$TEST_ROOT/result" -E " + with import ./config.nix; + mkDerivation { + name = \"non-blocking\"; + buildCommand = \"set -x; test -e $running; mkdir \$out; echo > $fifo\"; + }") + +wait $pid + +(! test -e $running) +(! test -e $dummy) +test -e $outPath diff --git a/tests/functional/gc-runtime.nix b/tests/functional/gc-runtime.nix new file mode 100644 index 000000000..ee5980bdf --- /dev/null +++ b/tests/functional/gc-runtime.nix @@ -0,0 +1,17 @@ +with import ./config.nix; + +mkDerivation { + name = "gc-runtime"; + builder = + # Test inline source file definitions. + builtins.toFile "builder.sh" '' + mkdir $out + + cat > $out/program < $TEST_ROOT/vector + hash="$(nix-hash --flat ${FORMAT_FLAG-} --type "$1" "$TEST_ROOT/vector")" + if ! (( "${NO_TEST_CLASSIC-}" )) && test "$hash" != "$3"; then + echo "try nix-hash: hash $1, expected $3, got $hash" + exit 1 + fi + hash="$(nix hash file ${FORMAT_FLAG-} --type "$1" "$TEST_ROOT/vector")" + if ! (( "${NO_TEST_NIX_COMMAND-}" )) && test "$hash" != "$3"; then + echo "try nix hash: hash $1, expected $3, got $hash" + exit 1 + fi +} + +FORMAT_FLAG=--base16 +try md5 "" "d41d8cd98f00b204e9800998ecf8427e" +try md5 "a" "0cc175b9c0f1b6a831c399e269772661" +try md5 "abc" "900150983cd24fb0d6963f7d28e17f72" +try md5 "message digest" "f96b697d7cb7938d525a2f31aaf161d0" +try md5 "abcdefghijklmnopqrstuvwxyz" "c3fcd3d76192e4007dfb496cca67e13b" +try md5 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" "d174ab98d277d9f5a5611c2c9f419d9f" +try md5 "12345678901234567890123456789012345678901234567890123456789012345678901234567890" "57edf4a22be3c955ac49da2e2107b67a" + +try sha1 "" "da39a3ee5e6b4b0d3255bfef95601890afd80709" +try sha1 "abc" "a9993e364706816aba3e25717850c26c9cd0d89d" +try sha1 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" "84983e441c3bd26ebaae4aa1f95129e5e54670f1" + +try sha256 "" "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" +try sha256 "abc" "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" +try sha256 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" + +try sha512 "" "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" +try sha512 "abc" "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" +try sha512 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445" +unset FORMAT_FLAG + +FORMAT_FLAG=--base32 +try sha256 "abc" "1b8m03r63zqhnjf7l5wnldhh7c134ap5vpj0850ymkq1iyzicy5s" +unset FORMAT_FLAG + +FORMAT_FLAG=--sri +try sha512 "" "sha512-z4PhNX7vuL3xVChQ1m2AB9Yg5AULVxXcg/SpIdNs6c5H0NE8XYXysP+DGNKHfuwvY7kxvUdBeoGlODJ6+SfaPg==" +try sha512 "abc" "sha512-3a81oZNherrMQXNJriBBMRLm+k6JqX6iCp7u5ktV05ohkpkqJ0/BqDa6PCOj/uu9RU1EI2Q86A4qmslPpUyknw==" +try sha512 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" "sha512-IEqPxt2oLwoM7XvrjgikFlfBbvRosiioJ5vjMacDwzWW/RXBOxsH+aodO+pXeJygMa2Fx6cd1wNU7GMSOMo0RQ==" +try sha256 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" "sha256-JI1qYdIGOLjlwCaTDD5gOaM85Flk/yFn9uzt1BnbBsE=" +unset FORMAT_FLAG + +# nix-hash [--flat] defaults to the Base16 format +NO_TEST_NIX_COMMAND=1 try sha512 "abc" "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" + +# nix hash [file|path] defaults to the SRI format +NO_TEST_CLASSIC=1 try sha512 "abc" "sha512-3a81oZNherrMQXNJriBBMRLm+k6JqX6iCp7u5ktV05ohkpkqJ0/BqDa6PCOj/uu9RU1EI2Q86A4qmslPpUyknw==" + +try2 () { + hash=$(nix-hash --type "$1" $TEST_ROOT/hash-path) + if test "$hash" != "$2"; then + echo "hash $1, expected $2, got $hash" + exit 1 + fi +} + +rm -rf $TEST_ROOT/hash-path +mkdir $TEST_ROOT/hash-path +echo "Hello World" > $TEST_ROOT/hash-path/hello + +try2 md5 "ea9b55537dd4c7e104515b2ccfaf4100" + +# Execute bit matters. +chmod +x $TEST_ROOT/hash-path/hello +try2 md5 "20f3ffe011d4cfa7d72bfabef7882836" + +# Mtime and other bits don't. +touch -r . $TEST_ROOT/hash-path/hello +chmod 744 $TEST_ROOT/hash-path/hello +try2 md5 "20f3ffe011d4cfa7d72bfabef7882836" + +# File type (e.g., symlink) does. +rm $TEST_ROOT/hash-path/hello +ln -s x $TEST_ROOT/hash-path/hello +try2 md5 "f78b733a68f5edbdf9413899339eaa4a" + +# Conversion. +try3() { + h64=$(nix-hash --type "$1" --to-base64 "$2") + [ "$h64" = "$4" ] + h64=$(nix hash to-base64 --type "$1" "$2") + [ "$h64" = "$4" ] + sri=$(nix-hash --type "$1" --to-sri "$2") + [ "$sri" = "$1-$4" ] + sri=$(nix hash to-sri --type "$1" "$2") + [ "$sri" = "$1-$4" ] + h32=$(nix-hash --type "$1" --to-base32 "$2") + [ "$h32" = "$3" ] + h32=$(nix hash to-base32 --type "$1" "$2") + [ "$h32" = "$3" ] + h16=$(nix-hash --type "$1" --to-base16 "$h32") + [ "$h16" = "$2" ] + h16=$(nix hash to-base16 --type "$1" "$h64") + [ "$h16" = "$2" ] + h16=$(nix hash to-base16 "$sri") + [ "$h16" = "$2" ] +} +try3 sha1 "800d59cfcd3c05e900cb4e214be48f6b886a08df" "vw46m23bizj4n8afrc0fj19wrp7mj3c0" "gA1Zz808BekAy04hS+SPa4hqCN8=" +try3 sha256 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" "1b8m03r63zqhnjf7l5wnldhh7c134ap5vpj0850ymkq1iyzicy5s" "ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=" +try3 sha512 "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445" "12k9jiq29iyqm03swfsgiw5mlqs173qazm3n7daz43infy12pyrcdf30fkk3qwv4yl2ick8yipc2mqnlh48xsvvxl60lbx8vp38yji0" "IEqPxt2oLwoM7XvrjgikFlfBbvRosiioJ5vjMacDwzWW/RXBOxsH+aodO+pXeJygMa2Fx6cd1wNU7GMSOMo0RQ==" diff --git a/tests/functional/hermetic.nix b/tests/functional/hermetic.nix new file mode 100644 index 000000000..4c9d7a51f --- /dev/null +++ b/tests/functional/hermetic.nix @@ -0,0 +1,56 @@ +{ busybox, seed }: + +with import ./config.nix; + +let + contentAddressedByDefault = builtins.getEnv "NIX_TESTS_CA_BY_DEFAULT" == "1"; + caArgs = if contentAddressedByDefault then { + __contentAddressed = true; + outputHashMode = "recursive"; + outputHashAlgo = "sha256"; + } else {}; + + mkDerivation = args: + derivation ({ + inherit system; + builder = busybox; + args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" "if [ -e .attrs.sh ]; then source .attrs.sh; fi; eval \"$buildCommand\"")]; + } // removeAttrs args ["builder" "meta" "passthru"] + // caArgs) + // { meta = args.meta or {}; passthru = args.passthru or {}; }; + + input1 = mkDerivation { + shell = busybox; + name = "hermetic-input-1"; + buildCommand = "echo hi-input1 seed=${toString seed}; echo FOO > $out"; + }; + + input2 = mkDerivation { + shell = busybox; + name = "hermetic-input-2"; + buildCommand = "echo hi; echo BAR > $out"; + }; + + input3 = mkDerivation { + shell = busybox; + name = "hermetic-input-3"; + buildCommand = '' + echo hi-input3 + read x < ${input2} + echo $x BAZ > $out + ''; + }; + +in + + mkDerivation { + shell = busybox; + name = "hermetic"; + passthru = { inherit input1 input2 input3; }; + buildCommand = + '' + read x < ${input1} + read y < ${input3} + echo "$x $y" > $out + ''; + } diff --git a/tests/functional/import-derivation.nix b/tests/functional/import-derivation.nix new file mode 100644 index 000000000..44fa9a45d --- /dev/null +++ b/tests/functional/import-derivation.nix @@ -0,0 +1,26 @@ +with import ./config.nix; + +let + + bar = mkDerivation { + name = "bar"; + builder = builtins.toFile "builder.sh" + '' + echo 'builtins.add 123 456' > $out + ''; + }; + + value = + # Test that pathExists can check the existence of /nix/store paths + assert builtins.pathExists bar; + import bar; + +in + +mkDerivation { + name = "foo"; + builder = builtins.toFile "builder.sh" + '' + echo -n FOO${toString value} > $out + ''; +} diff --git a/tests/functional/import-derivation.sh b/tests/functional/import-derivation.sh new file mode 100644 index 000000000..98d61ef49 --- /dev/null +++ b/tests/functional/import-derivation.sh @@ -0,0 +1,12 @@ +source common.sh + +clearStore + +if nix-instantiate --readonly-mode ./import-derivation.nix; then + echo "read-only evaluation of an imported derivation unexpectedly failed" + exit 1 +fi + +outPath=$(nix-build ./import-derivation.nix --no-out-link) + +[ "$(cat $outPath)" = FOO579 ] diff --git a/tests/functional/impure-derivations.nix b/tests/functional/impure-derivations.nix new file mode 100644 index 000000000..98547e6c1 --- /dev/null +++ b/tests/functional/impure-derivations.nix @@ -0,0 +1,63 @@ +with import ./config.nix; + +rec { + + impure = mkDerivation { + name = "impure"; + outputs = [ "out" "stuff" ]; + buildCommand = + '' + echo impure + x=$(< $TEST_ROOT/counter) + mkdir $out $stuff + echo $x > $out/n + ln -s $out/n $stuff/bla + printf $((x + 1)) > $TEST_ROOT/counter + ''; + __impure = true; + impureEnvVars = [ "TEST_ROOT" ]; + }; + + impureOnImpure = mkDerivation { + name = "impure-on-impure"; + buildCommand = + '' + echo impure-on-impure + x=$(< ${impure}/n) + mkdir $out + printf X$x > $out/n + ln -s ${impure.stuff} $out/symlink + ln -s $out $out/self + ''; + __impure = true; + }; + + # This is not allowed. + inputAddressed = mkDerivation { + name = "input-addressed"; + buildCommand = + '' + cat ${impure} > $out + ''; + }; + + contentAddressed = mkDerivation { + name = "content-addressed"; + buildCommand = + '' + echo content-addressed + x=$(< ${impureOnImpure}/n) + printf ''${x:0:1} > $out + ''; + outputHashMode = "recursive"; + outputHash = "sha256-eBYxcgkuWuiqs4cKNgKwkb3vY/HR0vVsJnqe8itJGcQ="; + }; + + inputAddressedAfterCA = mkDerivation { + name = "input-addressed-after-ca"; + buildCommand = + '' + cat ${contentAddressed} > $out + ''; + }; +} diff --git a/tests/functional/impure-derivations.sh b/tests/functional/impure-derivations.sh new file mode 100644 index 000000000..39d053a04 --- /dev/null +++ b/tests/functional/impure-derivations.sh @@ -0,0 +1,65 @@ +source common.sh + +requireDaemonNewerThan "2.8pre20220311" + +enableFeatures "ca-derivations impure-derivations" +restartDaemon + +clearStore + +# Basic test of impure derivations: building one a second time should not use the previous result. +printf 0 > $TEST_ROOT/counter + +# `nix derivation add` with impure derivations work +drvPath=$(nix-instantiate ./impure-derivations.nix -A impure) +nix derivation show $drvPath | jq .[] > $TEST_HOME/impure-drv.json +drvPath2=$(nix derivation add < $TEST_HOME/impure-drv.json) +[[ "$drvPath" = "$drvPath2" ]] + +# But only with the experimental feature! +expectStderr 1 nix derivation add < $TEST_HOME/impure-drv.json --experimental-features nix-command | grepQuiet "experimental Nix feature 'impure-derivations' is disabled" + +nix build --dry-run --json --file ./impure-derivations.nix impure.all +json=$(nix build -L --no-link --json --file ./impure-derivations.nix impure.all) +path1=$(echo $json | jq -r .[].outputs.out) +path1_stuff=$(echo $json | jq -r .[].outputs.stuff) +[[ $(< $path1/n) = 0 ]] +[[ $(< $path1_stuff/bla) = 0 ]] + +[[ $(nix path-info --json $path1 | jq .[].ca) =~ fixed:r:sha256: ]] + +path2=$(nix build -L --no-link --json --file ./impure-derivations.nix impure | jq -r .[].outputs.out) +[[ $(< $path2/n) = 1 ]] + +# Test impure derivations that depend on impure derivations. +path3=$(nix build -L --no-link --json --file ./impure-derivations.nix impureOnImpure | jq -r .[].outputs.out) +[[ $(< $path3/n) = X2 ]] + +path4=$(nix build -L --no-link --json --file ./impure-derivations.nix impureOnImpure | jq -r .[].outputs.out) +[[ $(< $path4/n) = X3 ]] + +# Test that (self-)references work. +[[ $(< $path4/symlink/bla) = 3 ]] +[[ $(< $path4/self/n) = X3 ]] + +# Input-addressed derivations cannot depend on impure derivations directly. +(! nix build -L --no-link --json --file ./impure-derivations.nix inputAddressed 2>&1) | grep 'depends on impure derivation' + +drvPath=$(nix eval --json --file ./impure-derivations.nix impure.drvPath | jq -r .) +[[ $(nix derivation show $drvPath | jq ".[\"$drvPath\"].outputs.out.impure") = true ]] +[[ $(nix derivation show $drvPath | jq ".[\"$drvPath\"].outputs.stuff.impure") = true ]] + +# Fixed-output derivations *can* depend on impure derivations. +path5=$(nix build -L --no-link --json --file ./impure-derivations.nix contentAddressed | jq -r .[].outputs.out) +[[ $(< $path5) = X ]] +[[ $(< $TEST_ROOT/counter) = 5 ]] + +# And they should not be rebuilt. +path5=$(nix build -L --no-link --json --file ./impure-derivations.nix contentAddressed | jq -r .[].outputs.out) +[[ $(< $path5) = X ]] +[[ $(< $TEST_ROOT/counter) = 5 ]] + +# Input-addressed derivations can depend on fixed-output derivations that depend on impure derivations. +path6=$(nix build -L --no-link --json --file ./impure-derivations.nix inputAddressedAfterCA | jq -r .[].outputs.out) +[[ $(< $path6) = X ]] +[[ $(< $TEST_ROOT/counter) = 5 ]] diff --git a/tests/functional/init.sh b/tests/functional/init.sh new file mode 100755 index 000000000..c420e8c9f --- /dev/null +++ b/tests/functional/init.sh @@ -0,0 +1,41 @@ +# Don't start the daemon +source common/vars-and-functions.sh + +test -n "$TEST_ROOT" +if test -d "$TEST_ROOT"; then + chmod -R u+w "$TEST_ROOT" + # We would delete any daemon socket, so let's stop the daemon first. + killDaemon + rm -rf "$TEST_ROOT" +fi +mkdir "$TEST_ROOT" + +mkdir "$NIX_STORE_DIR" +mkdir "$NIX_LOCALSTATE_DIR" +mkdir -p "$NIX_LOG_DIR"/drvs +mkdir "$NIX_STATE_DIR" +mkdir "$NIX_CONF_DIR" + +cat > "$NIX_CONF_DIR"/nix.conf < "$NIX_CONF_DIR"/nix.conf.extra < "$file.next" + mv "$file.next" "$file" + fi + done + + for i in $(seq 1 $(sysctl -n hw.ncpu)); do + sudo /usr/bin/dscl . -delete "/Users/nixbld$i" || true + done + sudo /usr/bin/dscl . -delete "/Groups/nixbld" || true + + sudo rm -rf /etc/nix \ + /nix \ + /var/root/.nix-profile /var/root/.nix-defexpr /var/root/.nix-channels \ + "$HOME/.nix-profile" "$HOME/.nix-defexpr" "$HOME/.nix-channels" +} + +verify() { + set +e + output=$(echo "nix-shell -p bash --run 'echo toow | rev'" | bash -l) + set -e + + test "$output" = "woot" +} + +scratch=$(mktemp -d -t tmp.XXXXXXXXXX) +function finish { + rm -rf "$scratch" +} +trap finish EXIT + +# First setup Nix +cleanup +curl -L -o install https://nixos.org/nix/install +yes | bash ./install +verify + + +( + set +e + ( + echo "cd $(pwd)" + echo nix-build ./release.nix -A binaryTarball.x86_64-darwin + ) | bash -l + set -e + cp ./result/nix-*.tar.bz2 $scratch/nix.tar.bz2 +) + +( + cd $scratch + tar -xf ./nix.tar.bz2 + + cd nix-* + + set -eux + + cleanup + + yes | ./install + verify + cleanup + + echo -n "" | ./install + verify + cleanup + + sudo mkdir -p /nix/store + sudo touch /nix/store/.silly-hint + echo -n "" | ALLOW_PREEXISTING_INSTALLATION=true ./install + verify + test -e /nix/store/.silly-hint + + cleanup +) diff --git a/tests/functional/lang-test-infra.sh b/tests/functional/lang-test-infra.sh new file mode 100644 index 000000000..30da8977b --- /dev/null +++ b/tests/functional/lang-test-infra.sh @@ -0,0 +1,86 @@ +# Test the function for lang.sh +source common.sh + +source lang/framework.sh + +# We are testing this, so don't want outside world to affect us. +unset _NIX_TEST_ACCEPT + +# We'll only modify this in subshells so we don't need to reset it. +badDiff=0 + +# matches non-empty +echo Hi! > "$TEST_ROOT/got" +cp "$TEST_ROOT/got" "$TEST_ROOT/expected" +( + diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/expected" + (( "$badDiff" == 0 )) +) + +# matches empty, non-existant file is the same as empty file +echo -n > "$TEST_ROOT/got" +( + diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/does-not-exist" + (( "$badDiff" == 0 )) +) + +# doesn't matches non-empty, non-existant file is the same as empty file +echo Hi! > "$TEST_ROOT/got" +( + diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/does-not-exist" + (( "$badDiff" == 1 )) +) + +# doesn't match, `badDiff` set, file unchanged +echo Hi! > "$TEST_ROOT/got" +echo Bye! > "$TEST_ROOT/expected" +( + diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/expected" + (( "$badDiff" == 1 )) +) +[[ "$(echo Bye! )" == $(< "$TEST_ROOT/expected") ]] + +# _NIX_TEST_ACCEPT=1 matches non-empty +echo Hi! > "$TEST_ROOT/got" +cp "$TEST_ROOT/got" "$TEST_ROOT/expected" +( + _NIX_TEST_ACCEPT=1 diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/expected" + (( "$badDiff" == 0 )) +) + +# _NIX_TEST_ACCEPT doesn't match, `badDiff=1` set, file changed (was previously non-empty) +echo Hi! > "$TEST_ROOT/got" +echo Bye! > "$TEST_ROOT/expected" +( + _NIX_TEST_ACCEPT=1 diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/expected" + (( "$badDiff" == 1 )) +) +[[ "$(echo Hi! )" == $(< "$TEST_ROOT/expected") ]] +# second time succeeds +( + diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/expected" + (( "$badDiff" == 0 )) +) + +# _NIX_TEST_ACCEPT matches empty, non-existant file not created +echo -n > "$TEST_ROOT/got" +( + _NIX_TEST_ACCEPT=1 diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/does-not-exists" + (( "$badDiff" == 0 )) +) +[[ ! -f "$TEST_ROOT/does-not-exist" ]] + +# _NIX_TEST_ACCEPT doesn't match, output empty, file deleted +echo -n > "$TEST_ROOT/got" +echo Bye! > "$TEST_ROOT/expected" +badDiff=0 +( + _NIX_TEST_ACCEPT=1 diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/expected" + (( "$badDiff" == 1 )) +) +[[ ! -f "$TEST_ROOT/expected" ]] +# second time succeeds +( + diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/expected" + (( "$badDiff" == 0 )) +) diff --git a/tests/functional/lang.sh b/tests/functional/lang.sh new file mode 100755 index 000000000..f4760eced --- /dev/null +++ b/tests/functional/lang.sh @@ -0,0 +1,146 @@ +source common.sh + +set -o pipefail + +source lang/framework.sh + +# specialize function a bit +function diffAndAccept() { + local -r testName="$1" + local -r got="lang/$testName.$2" + local -r expected="lang/$testName.$3" + diffAndAcceptInner "$testName" "$got" "$expected" +} + +export TEST_VAR=foo # for eval-okay-getenv.nix +export NIX_REMOTE=dummy:// +export NIX_STORE_DIR=/nix/store + +nix-instantiate --eval -E 'builtins.trace "Hello" 123' 2>&1 | grepQuiet Hello +nix-instantiate --eval -E 'builtins.trace "Hello" 123' 2>/dev/null | grepQuiet 123 +nix-instantiate --eval -E 'builtins.addErrorContext "Hello" 123' 2>&1 +nix-instantiate --trace-verbose --eval -E 'builtins.traceVerbose "Hello" 123' 2>&1 | grepQuiet Hello +nix-instantiate --eval -E 'builtins.traceVerbose "Hello" 123' 2>&1 | grepQuietInverse Hello +nix-instantiate --show-trace --eval -E 'builtins.addErrorContext "Hello" 123' 2>&1 | grepQuietInverse Hello +expectStderr 1 nix-instantiate --show-trace --eval -E 'builtins.addErrorContext "Hello" (throw "Foo")' | grepQuiet Hello + +nix-instantiate --eval -E 'let x = builtins.trace { x = x; } true; in x' \ + 2>&1 | grepQuiet -E 'trace: { x = «potential infinite recursion»; }' + +nix-instantiate --eval -E 'let x = { repeating = x; tracing = builtins.trace x true; }; in x.tracing'\ + 2>&1 | grepQuiet -F 'trace: { repeating = «repeated»; tracing = «potential infinite recursion»; }' + +set +x + +badDiff=0 +badExitCode=0 + +for i in lang/parse-fail-*.nix; do + echo "parsing $i (should fail)"; + i=$(basename "$i" .nix) + if expectStderr 1 nix-instantiate --parse - < "lang/$i.nix" > "lang/$i.err" + then + diffAndAccept "$i" err err.exp + else + echo "FAIL: $i shouldn't parse" + badExitCode=1 + fi +done + +for i in lang/parse-okay-*.nix; do + echo "parsing $i (should succeed)"; + i=$(basename "$i" .nix) + if + expect 0 nix-instantiate --parse - < "lang/$i.nix" \ + 1> "lang/$i.out" \ + 2> "lang/$i.err" + then + sed "s!$(pwd)!/pwd!g" "lang/$i.out" "lang/$i.err" + diffAndAccept "$i" out exp + diffAndAccept "$i" err err.exp + else + echo "FAIL: $i should parse" + badExitCode=1 + fi +done + +for i in lang/eval-fail-*.nix; do + echo "evaluating $i (should fail)"; + i=$(basename "$i" .nix) + if + expectStderr 1 nix-instantiate --show-trace "lang/$i.nix" \ + | sed "s!$(pwd)!/pwd!g" > "lang/$i.err" + then + diffAndAccept "$i" err err.exp + else + echo "FAIL: $i shouldn't evaluate" + badExitCode=1 + fi +done + +for i in lang/eval-okay-*.nix; do + echo "evaluating $i (should succeed)"; + i=$(basename "$i" .nix) + + if test -e "lang/$i.exp.xml"; then + if expect 0 nix-instantiate --eval --xml --no-location --strict \ + "lang/$i.nix" > "lang/$i.out.xml" + then + diffAndAccept "$i" out.xml exp.xml + else + echo "FAIL: $i should evaluate" + badExitCode=1 + fi + elif test ! -e "lang/$i.exp-disabled"; then + declare -a flags=() + if test -e "lang/$i.flags"; then + read -r -a flags < "lang/$i.flags" + fi + + if + expect 0 env \ + NIX_PATH=lang/dir3:lang/dir4 \ + HOME=/fake-home \ + nix-instantiate "${flags[@]}" --eval --strict "lang/$i.nix" \ + 1> "lang/$i.out" \ + 2> "lang/$i.err" + then + sed -i "s!$(pwd)!/pwd!g" "lang/$i.out" "lang/$i.err" + diffAndAccept "$i" out exp + diffAndAccept "$i" err err.exp + else + echo "FAIL: $i should evaluate" + badExitCode=1 + fi + fi +done + +if test -n "${_NIX_TEST_ACCEPT-}"; then + if (( "$badDiff" )); then + echo 'Output did mot match, but accepted output as the persisted expected output.' + echo 'That means the next time the tests are run, they should pass.' + else + echo 'NOTE: Environment variable _NIX_TEST_ACCEPT is defined,' + echo 'indicating the unexpected output should be accepted as the expected output going forward,' + echo 'but no tests had unexpected output so there was no expected output to update.' + fi + if (( "$badExitCode" )); then + exit "$badExitCode" + else + skipTest "regenerating golden masters" + fi +else + if (( "$badDiff" )); then + echo '' + echo 'You can rerun this test with:' + echo '' + echo ' _NIX_TEST_ACCEPT=1 make tests/functional/lang.sh.test' + echo '' + echo 'to regenerate the files containing the expected output,' + echo 'and then view the git diff to decide whether a change is' + echo 'good/intentional or bad/unintentional.' + echo 'If the diff contains arbitrary or impure information,' + echo 'please improve the normalization that the test applies to the output.' + fi + exit $(( "$badExitCode" + "$badDiff" )) +fi diff --git a/tests/functional/lang/binary-data b/tests/functional/lang/binary-data new file mode 100644 index 000000000..06d740502 Binary files /dev/null and b/tests/functional/lang/binary-data differ diff --git a/tests/functional/lang/data b/tests/functional/lang/data new file mode 100644 index 000000000..257cc5642 --- /dev/null +++ b/tests/functional/lang/data @@ -0,0 +1 @@ +foo diff --git a/tests/functional/lang/dir1/a.nix b/tests/functional/lang/dir1/a.nix new file mode 100644 index 000000000..231f150c5 --- /dev/null +++ b/tests/functional/lang/dir1/a.nix @@ -0,0 +1 @@ +"a" diff --git a/tests/functional/lang/dir2/a.nix b/tests/functional/lang/dir2/a.nix new file mode 100644 index 000000000..170df520a --- /dev/null +++ b/tests/functional/lang/dir2/a.nix @@ -0,0 +1 @@ +"X" diff --git a/tests/functional/lang/dir2/b.nix b/tests/functional/lang/dir2/b.nix new file mode 100644 index 000000000..19010cc35 --- /dev/null +++ b/tests/functional/lang/dir2/b.nix @@ -0,0 +1 @@ +"b" diff --git a/tests/functional/lang/dir3/a.nix b/tests/functional/lang/dir3/a.nix new file mode 100644 index 000000000..170df520a --- /dev/null +++ b/tests/functional/lang/dir3/a.nix @@ -0,0 +1 @@ +"X" diff --git a/tests/functional/lang/dir3/b.nix b/tests/functional/lang/dir3/b.nix new file mode 100644 index 000000000..170df520a --- /dev/null +++ b/tests/functional/lang/dir3/b.nix @@ -0,0 +1 @@ +"X" diff --git a/tests/functional/lang/dir3/c.nix b/tests/functional/lang/dir3/c.nix new file mode 100644 index 000000000..cdf158597 --- /dev/null +++ b/tests/functional/lang/dir3/c.nix @@ -0,0 +1 @@ +"c" diff --git a/tests/functional/lang/dir4/a.nix b/tests/functional/lang/dir4/a.nix new file mode 100644 index 000000000..170df520a --- /dev/null +++ b/tests/functional/lang/dir4/a.nix @@ -0,0 +1 @@ +"X" diff --git a/tests/functional/lang/dir4/c.nix b/tests/functional/lang/dir4/c.nix new file mode 100644 index 000000000..170df520a --- /dev/null +++ b/tests/functional/lang/dir4/c.nix @@ -0,0 +1 @@ +"X" diff --git a/tests/functional/lang/empty.exp b/tests/functional/lang/empty.exp new file mode 100644 index 000000000..e69de29bb diff --git a/tests/functional/lang/eval-fail-abort.err.exp b/tests/functional/lang/eval-fail-abort.err.exp new file mode 100644 index 000000000..345232d3f --- /dev/null +++ b/tests/functional/lang/eval-fail-abort.err.exp @@ -0,0 +1,10 @@ +error: + … while calling the 'abort' builtin + + at /pwd/lang/eval-fail-abort.nix:1:14: + + 1| if true then abort "this should fail" else 1 + | ^ + 2| + + error: evaluation aborted with the following error message: 'this should fail' diff --git a/tests/functional/lang/eval-fail-abort.nix b/tests/functional/lang/eval-fail-abort.nix new file mode 100644 index 000000000..75c51bceb --- /dev/null +++ b/tests/functional/lang/eval-fail-abort.nix @@ -0,0 +1 @@ +if true then abort "this should fail" else 1 diff --git a/tests/functional/lang/eval-fail-antiquoted-path.err.exp b/tests/functional/lang/eval-fail-antiquoted-path.err.exp new file mode 100644 index 000000000..425deba42 --- /dev/null +++ b/tests/functional/lang/eval-fail-antiquoted-path.err.exp @@ -0,0 +1 @@ +error: getting attributes of path ‘PWD/lang/fnord’: No such file or directory diff --git a/tests/functional/lang/eval-fail-assert.err.exp b/tests/functional/lang/eval-fail-assert.err.exp new file mode 100644 index 000000000..aeecd8167 --- /dev/null +++ b/tests/functional/lang/eval-fail-assert.err.exp @@ -0,0 +1,36 @@ +error: + … while evaluating the attribute 'body' + + at /pwd/lang/eval-fail-assert.nix:4:3: + + 3| + 4| body = x "x"; + | ^ + 5| } + + … from call site + + at /pwd/lang/eval-fail-assert.nix:4:10: + + 3| + 4| body = x "x"; + | ^ + 5| } + + … while calling 'x' + + at /pwd/lang/eval-fail-assert.nix:2:7: + + 1| let { + 2| x = arg: assert arg == "y"; 123; + | ^ + 3| + + error: assertion '(arg == "y")' failed + + at /pwd/lang/eval-fail-assert.nix:2:12: + + 1| let { + 2| x = arg: assert arg == "y"; 123; + | ^ + 3| diff --git a/tests/functional/lang/eval-fail-assert.nix b/tests/functional/lang/eval-fail-assert.nix new file mode 100644 index 000000000..3b7a1e8bf --- /dev/null +++ b/tests/functional/lang/eval-fail-assert.nix @@ -0,0 +1,5 @@ +let { + x = arg: assert arg == "y"; 123; + + body = x "x"; +} \ No newline at end of file diff --git a/tests/functional/lang/eval-fail-bad-antiquote-1.err.exp b/tests/functional/lang/eval-fail-bad-antiquote-1.err.exp new file mode 100644 index 000000000..cf94f53bc --- /dev/null +++ b/tests/functional/lang/eval-fail-bad-antiquote-1.err.exp @@ -0,0 +1,10 @@ +error: + … while evaluating a path segment + + at /pwd/lang/eval-fail-bad-antiquote-1.nix:1:2: + + 1| "${x: x}" + | ^ + 2| + + error: cannot coerce a function to a string diff --git a/tests/functional/lang/eval-fail-bad-antiquote-2.err.exp b/tests/functional/lang/eval-fail-bad-antiquote-2.err.exp new file mode 100644 index 000000000..c8fe39d12 --- /dev/null +++ b/tests/functional/lang/eval-fail-bad-antiquote-2.err.exp @@ -0,0 +1 @@ +error: operation 'addToStoreFromDump' is not supported by store 'dummy' diff --git a/tests/functional/lang/eval-fail-bad-antiquote-3.err.exp b/tests/functional/lang/eval-fail-bad-antiquote-3.err.exp new file mode 100644 index 000000000..fbefbc826 --- /dev/null +++ b/tests/functional/lang/eval-fail-bad-antiquote-3.err.exp @@ -0,0 +1,10 @@ +error: + … while evaluating a path segment + + at /pwd/lang/eval-fail-bad-antiquote-3.nix:1:3: + + 1| ''${x: x}'' + | ^ + 2| + + error: cannot coerce a function to a string diff --git a/tests/functional/lang/eval-fail-bad-string-interpolation-1.err.exp b/tests/functional/lang/eval-fail-bad-string-interpolation-1.err.exp new file mode 100644 index 000000000..eb73e9a52 --- /dev/null +++ b/tests/functional/lang/eval-fail-bad-string-interpolation-1.err.exp @@ -0,0 +1,10 @@ +error: + … while evaluating a path segment + + at /pwd/lang/eval-fail-bad-string-interpolation-1.nix:1:2: + + 1| "${x: x}" + | ^ + 2| + + error: cannot coerce a function to a string diff --git a/tests/functional/lang/eval-fail-bad-string-interpolation-1.nix b/tests/functional/lang/eval-fail-bad-string-interpolation-1.nix new file mode 100644 index 000000000..ffe9c983c --- /dev/null +++ b/tests/functional/lang/eval-fail-bad-string-interpolation-1.nix @@ -0,0 +1 @@ +"${x: x}" diff --git a/tests/functional/lang/eval-fail-bad-string-interpolation-2.err.exp b/tests/functional/lang/eval-fail-bad-string-interpolation-2.err.exp new file mode 100644 index 000000000..c8fe39d12 --- /dev/null +++ b/tests/functional/lang/eval-fail-bad-string-interpolation-2.err.exp @@ -0,0 +1 @@ +error: operation 'addToStoreFromDump' is not supported by store 'dummy' diff --git a/tests/functional/lang/eval-fail-bad-string-interpolation-2.nix b/tests/functional/lang/eval-fail-bad-string-interpolation-2.nix new file mode 100644 index 000000000..3745235ce --- /dev/null +++ b/tests/functional/lang/eval-fail-bad-string-interpolation-2.nix @@ -0,0 +1 @@ +"${./fnord}" diff --git a/tests/functional/lang/eval-fail-bad-string-interpolation-3.err.exp b/tests/functional/lang/eval-fail-bad-string-interpolation-3.err.exp new file mode 100644 index 000000000..ac14f329b --- /dev/null +++ b/tests/functional/lang/eval-fail-bad-string-interpolation-3.err.exp @@ -0,0 +1,10 @@ +error: + … while evaluating a path segment + + at /pwd/lang/eval-fail-bad-string-interpolation-3.nix:1:3: + + 1| ''${x: x}'' + | ^ + 2| + + error: cannot coerce a function to a string diff --git a/tests/functional/lang/eval-fail-bad-string-interpolation-3.nix b/tests/functional/lang/eval-fail-bad-string-interpolation-3.nix new file mode 100644 index 000000000..65b9d4f50 --- /dev/null +++ b/tests/functional/lang/eval-fail-bad-string-interpolation-3.nix @@ -0,0 +1 @@ +''${x: x}'' diff --git a/tests/functional/lang/eval-fail-blackhole.err.exp b/tests/functional/lang/eval-fail-blackhole.err.exp new file mode 100644 index 000000000..f0618d8ac --- /dev/null +++ b/tests/functional/lang/eval-fail-blackhole.err.exp @@ -0,0 +1,18 @@ +error: + … while evaluating the attribute 'body' + + at /pwd/lang/eval-fail-blackhole.nix:2:3: + + 1| let { + 2| body = x; + | ^ + 3| x = y; + + error: infinite recursion encountered + + at /pwd/lang/eval-fail-blackhole.nix:3:7: + + 2| body = x; + 3| x = y; + | ^ + 4| y = x; diff --git a/tests/functional/lang/eval-fail-blackhole.nix b/tests/functional/lang/eval-fail-blackhole.nix new file mode 100644 index 000000000..81133b511 --- /dev/null +++ b/tests/functional/lang/eval-fail-blackhole.nix @@ -0,0 +1,5 @@ +let { + body = x; + x = y; + y = x; +} diff --git a/tests/functional/lang/eval-fail-deepseq.err.exp b/tests/functional/lang/eval-fail-deepseq.err.exp new file mode 100644 index 000000000..5e204ba73 --- /dev/null +++ b/tests/functional/lang/eval-fail-deepseq.err.exp @@ -0,0 +1,26 @@ +error: + … while calling the 'deepSeq' builtin + + at /pwd/lang/eval-fail-deepseq.nix:1:1: + + 1| builtins.deepSeq { x = abort "foo"; } 456 + | ^ + 2| + + … while evaluating the attribute 'x' + + at /pwd/lang/eval-fail-deepseq.nix:1:20: + + 1| builtins.deepSeq { x = abort "foo"; } 456 + | ^ + 2| + + … while calling the 'abort' builtin + + at /pwd/lang/eval-fail-deepseq.nix:1:24: + + 1| builtins.deepSeq { x = abort "foo"; } 456 + | ^ + 2| + + error: evaluation aborted with the following error message: 'foo' diff --git a/tests/functional/lang/eval-fail-deepseq.nix b/tests/functional/lang/eval-fail-deepseq.nix new file mode 100644 index 000000000..9baa49b06 --- /dev/null +++ b/tests/functional/lang/eval-fail-deepseq.nix @@ -0,0 +1 @@ +builtins.deepSeq { x = abort "foo"; } 456 diff --git a/tests/functional/lang/eval-fail-dup-dynamic-attrs.err.exp b/tests/functional/lang/eval-fail-dup-dynamic-attrs.err.exp new file mode 100644 index 000000000..e01f8e6d0 --- /dev/null +++ b/tests/functional/lang/eval-fail-dup-dynamic-attrs.err.exp @@ -0,0 +1,8 @@ +error: dynamic attribute 'b' already defined at /pwd/lang/eval-fail-dup-dynamic-attrs.nix:2:11 + + at /pwd/lang/eval-fail-dup-dynamic-attrs.nix:3:11: + + 2| set = { "${"" + "b"}" = 1; }; + 3| set = { "${"b" + ""}" = 2; }; + | ^ + 4| } diff --git a/tests/functional/lang/eval-fail-dup-dynamic-attrs.nix b/tests/functional/lang/eval-fail-dup-dynamic-attrs.nix new file mode 100644 index 000000000..7ea17f6c8 --- /dev/null +++ b/tests/functional/lang/eval-fail-dup-dynamic-attrs.nix @@ -0,0 +1,4 @@ +{ + set = { "${"" + "b"}" = 1; }; + set = { "${"b" + ""}" = 2; }; +} diff --git a/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.err.exp b/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.err.exp new file mode 100644 index 000000000..0069285fb --- /dev/null +++ b/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.err.exp @@ -0,0 +1,38 @@ +error: + … while calling the 'foldl'' builtin + + at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:2:1: + + 1| # Tests that the result of applying op is forced even if the value is never used + 2| builtins.foldl' + | ^ + 3| (_: f: f null) + + … while calling anonymous lambda + + at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:3:7: + + 2| builtins.foldl' + 3| (_: f: f null) + | ^ + 4| null + + … from call site + + at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:3:10: + + 2| builtins.foldl' + 3| (_: f: f null) + | ^ + 4| null + + … while calling anonymous lambda + + at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:5:6: + + 4| null + 5| [ (_: throw "Not the final value, but is still forced!") (_: 23) ] + | ^ + 6| + + error: Not the final value, but is still forced! diff --git a/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.nix b/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.nix new file mode 100644 index 000000000..1620cc76e --- /dev/null +++ b/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.nix @@ -0,0 +1,5 @@ +# Tests that the result of applying op is forced even if the value is never used +builtins.foldl' + (_: f: f null) + null + [ (_: throw "Not the final value, but is still forced!") (_: 23) ] diff --git a/tests/functional/lang/eval-fail-fromTOML-timestamps.err.exp b/tests/functional/lang/eval-fail-fromTOML-timestamps.err.exp new file mode 100644 index 000000000..f6bd19f5a --- /dev/null +++ b/tests/functional/lang/eval-fail-fromTOML-timestamps.err.exp @@ -0,0 +1,12 @@ +error: + … while calling the 'fromTOML' builtin + + at /pwd/lang/eval-fail-fromTOML-timestamps.nix:1:1: + + 1| builtins.fromTOML '' + | ^ + 2| key = "value" + + error: while parsing a TOML string: Dates and times are not supported + + at «none»:0: (source not available) diff --git a/tests/functional/lang/eval-fail-fromTOML-timestamps.nix b/tests/functional/lang/eval-fail-fromTOML-timestamps.nix new file mode 100644 index 000000000..74cff9470 --- /dev/null +++ b/tests/functional/lang/eval-fail-fromTOML-timestamps.nix @@ -0,0 +1,130 @@ +builtins.fromTOML '' + key = "value" + bare_key = "value" + bare-key = "value" + 1234 = "value" + + "127.0.0.1" = "value" + "character encoding" = "value" + "ʎǝʞ" = "value" + 'key2' = "value" + 'quoted "value"' = "value" + + name = "Orange" + + physical.color = "orange" + physical.shape = "round" + site."google.com" = true + + # This is legal according to the spec, but cpptoml doesn't handle it. + #a.b.c = 1 + #a.d = 2 + + str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF." + + int1 = +99 + int2 = 42 + int3 = 0 + int4 = -17 + int5 = 1_000 + int6 = 5_349_221 + int7 = 1_2_3_4_5 + + hex1 = 0xDEADBEEF + hex2 = 0xdeadbeef + hex3 = 0xdead_beef + + oct1 = 0o01234567 + oct2 = 0o755 + + bin1 = 0b11010110 + + flt1 = +1.0 + flt2 = 3.1415 + flt3 = -0.01 + flt4 = 5e+22 + flt5 = 1e6 + flt6 = -2E-2 + flt7 = 6.626e-34 + flt8 = 9_224_617.445_991_228_313 + + bool1 = true + bool2 = false + + odt1 = 1979-05-27T07:32:00Z + odt2 = 1979-05-27T00:32:00-07:00 + odt3 = 1979-05-27T00:32:00.999999-07:00 + odt4 = 1979-05-27 07:32:00Z + ldt1 = 1979-05-27T07:32:00 + ldt2 = 1979-05-27T00:32:00.999999 + ld1 = 1979-05-27 + lt1 = 07:32:00 + lt2 = 00:32:00.999999 + + arr1 = [ 1, 2, 3 ] + arr2 = [ "red", "yellow", "green" ] + arr3 = [ [ 1, 2 ], [3, 4, 5] ] + arr4 = [ "all", 'strings', """are the same""", ''''type''''] + arr5 = [ [ 1, 2 ], ["a", "b", "c"] ] + + arr7 = [ + 1, 2, 3 + ] + + arr8 = [ + 1, + 2, # this is ok + ] + + [table-1] + key1 = "some string" + key2 = 123 + + + [table-2] + key1 = "another string" + key2 = 456 + + [dog."tater.man"] + type.name = "pug" + + [a.b.c] + [ d.e.f ] + [ g . h . i ] + [ j . "ʞ" . 'l' ] + [x.y.z.w] + + name = { first = "Tom", last = "Preston-Werner" } + point = { x = 1, y = 2 } + animal = { type.name = "pug" } + + [[products]] + name = "Hammer" + sku = 738594937 + + [[products]] + + [[products]] + name = "Nail" + sku = 284758393 + color = "gray" + + [[fruit]] + name = "apple" + + [fruit.physical] + color = "red" + shape = "round" + + [[fruit.variety]] + name = "red delicious" + + [[fruit.variety]] + name = "granny smith" + + [[fruit]] + name = "banana" + + [[fruit.variety]] + name = "plantain" +'' diff --git a/tests/functional/lang/eval-fail-hashfile-missing.err.exp b/tests/functional/lang/eval-fail-hashfile-missing.err.exp new file mode 100644 index 000000000..8e77dec1e --- /dev/null +++ b/tests/functional/lang/eval-fail-hashfile-missing.err.exp @@ -0,0 +1,19 @@ +error: + … while calling the 'toString' builtin + + at /pwd/lang/eval-fail-hashfile-missing.nix:4:3: + + 3| in + 4| toString (builtins.concatLists (map (hash: map (builtins.hashFile hash) paths) ["md5" "sha1" "sha256" "sha512"])) + | ^ + 5| + + … while evaluating the first argument passed to builtins.toString + + at «none»:0: (source not available) + + … while calling the 'hashFile' builtin + + at «none»:0: (source not available) + + error: opening file '/pwd/lang/this-file-is-definitely-not-there-7392097': No such file or directory diff --git a/tests/functional/lang/eval-fail-hashfile-missing.nix b/tests/functional/lang/eval-fail-hashfile-missing.nix new file mode 100644 index 000000000..ce098b823 --- /dev/null +++ b/tests/functional/lang/eval-fail-hashfile-missing.nix @@ -0,0 +1,5 @@ +let + paths = [ ./this-file-is-definitely-not-there-7392097 "/and/neither/is/this/37293620" ]; +in + toString (builtins.concatLists (map (hash: map (builtins.hashFile hash) paths) ["md5" "sha1" "sha256" "sha512"])) + diff --git a/tests/functional/lang/eval-fail-list.err.exp b/tests/functional/lang/eval-fail-list.err.exp new file mode 100644 index 000000000..24d682118 --- /dev/null +++ b/tests/functional/lang/eval-fail-list.err.exp @@ -0,0 +1,10 @@ +error: + … while evaluating one of the elements to concatenate + + at /pwd/lang/eval-fail-list.nix:1:2: + + 1| 8++1 + | ^ + 2| + + error: value is an integer while a list was expected diff --git a/tests/functional/lang/eval-fail-list.nix b/tests/functional/lang/eval-fail-list.nix new file mode 100644 index 000000000..fa749f2f7 --- /dev/null +++ b/tests/functional/lang/eval-fail-list.nix @@ -0,0 +1 @@ +8++1 diff --git a/tests/functional/lang/eval-fail-missing-arg.err.exp b/tests/functional/lang/eval-fail-missing-arg.err.exp new file mode 100644 index 000000000..61fabf0d5 --- /dev/null +++ b/tests/functional/lang/eval-fail-missing-arg.err.exp @@ -0,0 +1,16 @@ +error: + … from call site + + at /pwd/lang/eval-fail-missing-arg.nix:1:1: + + 1| ({x, y, z}: x + y + z) {x = "foo"; z = "bar";} + | ^ + 2| + + error: function 'anonymous lambda' called without required argument 'y' + + at /pwd/lang/eval-fail-missing-arg.nix:1:2: + + 1| ({x, y, z}: x + y + z) {x = "foo"; z = "bar";} + | ^ + 2| diff --git a/tests/functional/lang/eval-fail-missing-arg.nix b/tests/functional/lang/eval-fail-missing-arg.nix new file mode 100644 index 000000000..c4be9797c --- /dev/null +++ b/tests/functional/lang/eval-fail-missing-arg.nix @@ -0,0 +1 @@ +({x, y, z}: x + y + z) {x = "foo"; z = "bar";} diff --git a/tests/functional/lang/eval-fail-nonexist-path.err.exp b/tests/functional/lang/eval-fail-nonexist-path.err.exp new file mode 100644 index 000000000..c8fe39d12 --- /dev/null +++ b/tests/functional/lang/eval-fail-nonexist-path.err.exp @@ -0,0 +1 @@ +error: operation 'addToStoreFromDump' is not supported by store 'dummy' diff --git a/tests/functional/lang/eval-fail-nonexist-path.nix b/tests/functional/lang/eval-fail-nonexist-path.nix new file mode 100644 index 000000000..f2f08107b --- /dev/null +++ b/tests/functional/lang/eval-fail-nonexist-path.nix @@ -0,0 +1,4 @@ +# This must fail to evaluate, since ./fnord doesn't exist. If it did +# exist, it would produce "/nix/store/-fnord/xyzzy" (with an +# appropriate context). +"${./fnord}/xyzzy" diff --git a/tests/functional/lang/eval-fail-path-slash.err.exp b/tests/functional/lang/eval-fail-path-slash.err.exp new file mode 100644 index 000000000..f0011c97f --- /dev/null +++ b/tests/functional/lang/eval-fail-path-slash.err.exp @@ -0,0 +1,8 @@ +error: path has a trailing slash + + at /pwd/lang/eval-fail-path-slash.nix:6:12: + + 5| # and https://nixos.org/nix-dev/2016-June/020829.html + 6| /nix/store/ + | ^ + 7| diff --git a/tests/functional/lang/eval-fail-path-slash.nix b/tests/functional/lang/eval-fail-path-slash.nix new file mode 100644 index 000000000..8c2e104c7 --- /dev/null +++ b/tests/functional/lang/eval-fail-path-slash.nix @@ -0,0 +1,6 @@ +# Trailing slashes in paths are not allowed. +# This restriction could be lifted sometime, +# for example if we make '/' a path concatenation operator. +# See https://github.com/NixOS/nix/issues/1138 +# and https://nixos.org/nix-dev/2016-June/020829.html +/nix/store/ diff --git a/tests/functional/lang/eval-fail-recursion.err.exp b/tests/functional/lang/eval-fail-recursion.err.exp new file mode 100644 index 000000000..af64133cb --- /dev/null +++ b/tests/functional/lang/eval-fail-recursion.err.exp @@ -0,0 +1,16 @@ +error: + … in the right operand of the update (//) operator + + at /pwd/lang/eval-fail-recursion.nix:1:12: + + 1| let a = {} // a; in a.foo + | ^ + 2| + + error: infinite recursion encountered + + at /pwd/lang/eval-fail-recursion.nix:1:15: + + 1| let a = {} // a; in a.foo + | ^ + 2| diff --git a/tests/functional/lang/eval-fail-recursion.nix b/tests/functional/lang/eval-fail-recursion.nix new file mode 100644 index 000000000..075b5ed06 --- /dev/null +++ b/tests/functional/lang/eval-fail-recursion.nix @@ -0,0 +1 @@ +let a = {} // a; in a.foo diff --git a/tests/functional/lang/eval-fail-remove.err.exp b/tests/functional/lang/eval-fail-remove.err.exp new file mode 100644 index 000000000..e82cdac98 --- /dev/null +++ b/tests/functional/lang/eval-fail-remove.err.exp @@ -0,0 +1,19 @@ +error: + … while evaluating the attribute 'body' + + at /pwd/lang/eval-fail-remove.nix:4:3: + + 3| + 4| body = (removeAttrs attrs ["x"]).x; + | ^ + 5| } + + error: attribute 'x' missing + + at /pwd/lang/eval-fail-remove.nix:4:10: + + 3| + 4| body = (removeAttrs attrs ["x"]).x; + | ^ + 5| } + Did you mean y? diff --git a/tests/functional/lang/eval-fail-remove.nix b/tests/functional/lang/eval-fail-remove.nix new file mode 100644 index 000000000..539e0eb0a --- /dev/null +++ b/tests/functional/lang/eval-fail-remove.nix @@ -0,0 +1,5 @@ +let { + attrs = {x = 123; y = 456;}; + + body = (removeAttrs attrs ["x"]).x; +} \ No newline at end of file diff --git a/tests/functional/lang/eval-fail-scope-5.err.exp b/tests/functional/lang/eval-fail-scope-5.err.exp new file mode 100644 index 000000000..22b6166f8 --- /dev/null +++ b/tests/functional/lang/eval-fail-scope-5.err.exp @@ -0,0 +1,36 @@ +error: + … while evaluating the attribute 'body' + + at /pwd/lang/eval-fail-scope-5.nix:8:3: + + 7| + 8| body = f {}; + | ^ + 9| + + … from call site + + at /pwd/lang/eval-fail-scope-5.nix:8:10: + + 7| + 8| body = f {}; + | ^ + 9| + + … while calling 'f' + + at /pwd/lang/eval-fail-scope-5.nix:6:7: + + 5| + 6| f = {x ? y, y ? x}: x + y; + | ^ + 7| + + error: infinite recursion encountered + + at /pwd/lang/eval-fail-scope-5.nix:6:12: + + 5| + 6| f = {x ? y, y ? x}: x + y; + | ^ + 7| diff --git a/tests/functional/lang/eval-fail-scope-5.nix b/tests/functional/lang/eval-fail-scope-5.nix new file mode 100644 index 000000000..f89a65a99 --- /dev/null +++ b/tests/functional/lang/eval-fail-scope-5.nix @@ -0,0 +1,10 @@ +let { + + x = "a"; + y = "b"; + + f = {x ? y, y ? x}: x + y; + + body = f {}; + +} diff --git a/tests/functional/lang/eval-fail-seq.err.exp b/tests/functional/lang/eval-fail-seq.err.exp new file mode 100644 index 000000000..33a7e9491 --- /dev/null +++ b/tests/functional/lang/eval-fail-seq.err.exp @@ -0,0 +1,18 @@ +error: + … while calling the 'seq' builtin + + at /pwd/lang/eval-fail-seq.nix:1:1: + + 1| builtins.seq (abort "foo") 2 + | ^ + 2| + + … while calling the 'abort' builtin + + at /pwd/lang/eval-fail-seq.nix:1:15: + + 1| builtins.seq (abort "foo") 2 + | ^ + 2| + + error: evaluation aborted with the following error message: 'foo' diff --git a/tests/functional/lang/eval-fail-seq.nix b/tests/functional/lang/eval-fail-seq.nix new file mode 100644 index 000000000..cddbbfd32 --- /dev/null +++ b/tests/functional/lang/eval-fail-seq.nix @@ -0,0 +1 @@ +builtins.seq (abort "foo") 2 diff --git a/tests/functional/lang/eval-fail-set-override.err.exp b/tests/functional/lang/eval-fail-set-override.err.exp new file mode 100644 index 000000000..beb29d678 --- /dev/null +++ b/tests/functional/lang/eval-fail-set-override.err.exp @@ -0,0 +1,6 @@ +error: + … while evaluating the `__overrides` attribute + + at «none»:0: (source not available) + + error: value is an integer while a set was expected diff --git a/tests/functional/lang/eval-fail-set-override.nix b/tests/functional/lang/eval-fail-set-override.nix new file mode 100644 index 000000000..03551c186 --- /dev/null +++ b/tests/functional/lang/eval-fail-set-override.nix @@ -0,0 +1 @@ +rec { __overrides = 1; } diff --git a/tests/functional/lang/eval-fail-set.err.exp b/tests/functional/lang/eval-fail-set.err.exp new file mode 100644 index 000000000..0d0140508 --- /dev/null +++ b/tests/functional/lang/eval-fail-set.err.exp @@ -0,0 +1,7 @@ +error: undefined variable 'x' + + at /pwd/lang/eval-fail-set.nix:1:3: + + 1| 8.x + | ^ + 2| diff --git a/tests/functional/lang/eval-fail-set.nix b/tests/functional/lang/eval-fail-set.nix new file mode 100644 index 000000000..c6b7980b6 --- /dev/null +++ b/tests/functional/lang/eval-fail-set.nix @@ -0,0 +1 @@ +8.x diff --git a/tests/functional/lang/eval-fail-substring.err.exp b/tests/functional/lang/eval-fail-substring.err.exp new file mode 100644 index 000000000..dc26a00bd --- /dev/null +++ b/tests/functional/lang/eval-fail-substring.err.exp @@ -0,0 +1,12 @@ +error: + … while calling the 'substring' builtin + + at /pwd/lang/eval-fail-substring.nix:1:1: + + 1| builtins.substring (builtins.sub 0 1) 1 "x" + | ^ + 2| + + error: negative start position in 'substring' + + at «none»:0: (source not available) diff --git a/tests/functional/lang/eval-fail-substring.nix b/tests/functional/lang/eval-fail-substring.nix new file mode 100644 index 000000000..f37c2bc0a --- /dev/null +++ b/tests/functional/lang/eval-fail-substring.nix @@ -0,0 +1 @@ +builtins.substring (builtins.sub 0 1) 1 "x" diff --git a/tests/functional/lang/eval-fail-to-path.err.exp b/tests/functional/lang/eval-fail-to-path.err.exp new file mode 100644 index 000000000..43ed2bdfc --- /dev/null +++ b/tests/functional/lang/eval-fail-to-path.err.exp @@ -0,0 +1,14 @@ +error: + … while calling the 'toPath' builtin + + at /pwd/lang/eval-fail-to-path.nix:1:1: + + 1| builtins.toPath "foo/bar" + | ^ + 2| + + … while evaluating the first argument passed to builtins.toPath + + at «none»:0: (source not available) + + error: string 'foo/bar' doesn't represent an absolute path diff --git a/tests/functional/lang/eval-fail-to-path.nix b/tests/functional/lang/eval-fail-to-path.nix new file mode 100644 index 000000000..5e322bc31 --- /dev/null +++ b/tests/functional/lang/eval-fail-to-path.nix @@ -0,0 +1 @@ +builtins.toPath "foo/bar" diff --git a/tests/functional/lang/eval-fail-toJSON.err.exp b/tests/functional/lang/eval-fail-toJSON.err.exp new file mode 100644 index 000000000..4e618c203 --- /dev/null +++ b/tests/functional/lang/eval-fail-toJSON.err.exp @@ -0,0 +1,57 @@ +error: + … while calling the 'toJSON' builtin + + at /pwd/lang/eval-fail-toJSON.nix:1:1: + + 1| builtins.toJSON { + | ^ + 2| a.b = [ + + … while evaluating attribute 'a' + + at /pwd/lang/eval-fail-toJSON.nix:2:3: + + 1| builtins.toJSON { + 2| a.b = [ + | ^ + 3| true + + … while evaluating attribute 'b' + + at /pwd/lang/eval-fail-toJSON.nix:2:3: + + 1| builtins.toJSON { + 2| a.b = [ + | ^ + 3| true + + … while evaluating list element at index 3 + + … while evaluating attribute 'c' + + at /pwd/lang/eval-fail-toJSON.nix:7:7: + + 6| { + 7| c.d = throw "hah no"; + | ^ + 8| } + + … while evaluating attribute 'd' + + at /pwd/lang/eval-fail-toJSON.nix:7:7: + + 6| { + 7| c.d = throw "hah no"; + | ^ + 8| } + + … while calling the 'throw' builtin + + at /pwd/lang/eval-fail-toJSON.nix:7:13: + + 6| { + 7| c.d = throw "hah no"; + | ^ + 8| } + + error: hah no diff --git a/tests/functional/lang/eval-fail-toJSON.nix b/tests/functional/lang/eval-fail-toJSON.nix new file mode 100644 index 000000000..8112e1c1f --- /dev/null +++ b/tests/functional/lang/eval-fail-toJSON.nix @@ -0,0 +1,10 @@ +builtins.toJSON { + a.b = [ + true + false + "it's a bird" + { + c.d = throw "hah no"; + } + ]; +} diff --git a/tests/functional/lang/eval-fail-undeclared-arg.err.exp b/tests/functional/lang/eval-fail-undeclared-arg.err.exp new file mode 100644 index 000000000..30db743c7 --- /dev/null +++ b/tests/functional/lang/eval-fail-undeclared-arg.err.exp @@ -0,0 +1,17 @@ +error: + … from call site + + at /pwd/lang/eval-fail-undeclared-arg.nix:1:1: + + 1| ({x, z}: x + z) {x = "foo"; y = "bla"; z = "bar";} + | ^ + 2| + + error: function 'anonymous lambda' called with unexpected argument 'y' + + at /pwd/lang/eval-fail-undeclared-arg.nix:1:2: + + 1| ({x, z}: x + z) {x = "foo"; y = "bla"; z = "bar";} + | ^ + 2| + Did you mean one of x or z? diff --git a/tests/functional/lang/eval-fail-undeclared-arg.nix b/tests/functional/lang/eval-fail-undeclared-arg.nix new file mode 100644 index 000000000..cafdf1636 --- /dev/null +++ b/tests/functional/lang/eval-fail-undeclared-arg.nix @@ -0,0 +1 @@ +({x, z}: x + z) {x = "foo"; y = "bla"; z = "bar";} diff --git a/tests/functional/lang/eval-okay-any-all.exp b/tests/functional/lang/eval-okay-any-all.exp new file mode 100644 index 000000000..eb273f45b --- /dev/null +++ b/tests/functional/lang/eval-okay-any-all.exp @@ -0,0 +1 @@ +[ false false true true true true false true ] diff --git a/tests/functional/lang/eval-okay-any-all.nix b/tests/functional/lang/eval-okay-any-all.nix new file mode 100644 index 000000000..a3f26ea2a --- /dev/null +++ b/tests/functional/lang/eval-okay-any-all.nix @@ -0,0 +1,11 @@ +with builtins; + +[ (any (x: x == 1) []) + (any (x: x == 1) [2 3 4]) + (any (x: x == 1) [1 2 3 4]) + (any (x: x == 1) [4 3 2 1]) + (all (x: x == 1) []) + (all (x: x == 1) [1]) + (all (x: x == 1) [1 2 3]) + (all (x: x == 1) [1 1 1]) +] diff --git a/tests/functional/lang/eval-okay-arithmetic.exp b/tests/functional/lang/eval-okay-arithmetic.exp new file mode 100644 index 000000000..5c54d10b7 --- /dev/null +++ b/tests/functional/lang/eval-okay-arithmetic.exp @@ -0,0 +1 @@ +2216 diff --git a/tests/functional/lang/eval-okay-arithmetic.nix b/tests/functional/lang/eval-okay-arithmetic.nix new file mode 100644 index 000000000..7e9e6a0b6 --- /dev/null +++ b/tests/functional/lang/eval-okay-arithmetic.nix @@ -0,0 +1,59 @@ +with import ./lib.nix; + +let { + + /* Supposedly tail recursive version: + + range_ = accum: first: last: + if first == last then ([first] ++ accum) + else range_ ([first] ++ accum) (builtins.add first 1) last; + + range = range_ []; + */ + + x = 12; + + err = abort "urgh"; + + body = sum + [ (sum (range 1 50)) + (123 + 456) + (0 + -10 + -(-11) + -x) + (10 - 7 - -2) + (10 - (6 - -1)) + (10 - 1 + 2) + (3 * 4 * 5) + (56088 / 123 / 2) + (3 + 4 * const 5 0 - 6 / id 2) + + (builtins.bitAnd 12 10) # 0b1100 & 0b1010 = 8 + (builtins.bitOr 12 10) # 0b1100 | 0b1010 = 14 + (builtins.bitXor 12 10) # 0b1100 ^ 0b1010 = 6 + + (if 3 < 7 then 1 else err) + (if 7 < 3 then err else 1) + (if 3 < 3 then err else 1) + + (if 3 <= 7 then 1 else err) + (if 7 <= 3 then err else 1) + (if 3 <= 3 then 1 else err) + + (if 3 > 7 then err else 1) + (if 7 > 3 then 1 else err) + (if 3 > 3 then err else 1) + + (if 3 >= 7 then err else 1) + (if 7 >= 3 then 1 else err) + (if 3 >= 3 then 1 else err) + + (if 2 > 1 == 1 < 2 then 1 else err) + (if 1 + 2 * 3 >= 7 then 1 else err) + (if 1 + 2 * 3 < 7 then err else 1) + + # Not integer, but so what. + (if "aa" < "ab" then 1 else err) + (if "aa" < "aa" then err else 1) + (if "foo" < "foobar" then 1 else err) + ]; + +} diff --git a/tests/functional/lang/eval-okay-attrnames.exp b/tests/functional/lang/eval-okay-attrnames.exp new file mode 100644 index 000000000..b4aa387e0 --- /dev/null +++ b/tests/functional/lang/eval-okay-attrnames.exp @@ -0,0 +1 @@ +"newxfoonewxy" diff --git a/tests/functional/lang/eval-okay-attrnames.nix b/tests/functional/lang/eval-okay-attrnames.nix new file mode 100644 index 000000000..e5b26e9f2 --- /dev/null +++ b/tests/functional/lang/eval-okay-attrnames.nix @@ -0,0 +1,11 @@ +with import ./lib.nix; + +let + + attrs = {y = "y"; x = "x"; foo = "foo";} // rec {x = "newx"; bar = x;}; + + names = builtins.attrNames attrs; + + values = map (name: builtins.getAttr name attrs) names; + +in assert values == builtins.attrValues attrs; concat values diff --git a/tests/functional/lang/eval-okay-attrs.exp b/tests/functional/lang/eval-okay-attrs.exp new file mode 100644 index 000000000..45b0f829e --- /dev/null +++ b/tests/functional/lang/eval-okay-attrs.exp @@ -0,0 +1 @@ +987 diff --git a/tests/functional/lang/eval-okay-attrs.nix b/tests/functional/lang/eval-okay-attrs.nix new file mode 100644 index 000000000..810b31a5d --- /dev/null +++ b/tests/functional/lang/eval-okay-attrs.nix @@ -0,0 +1,5 @@ +let { + as = { x = 123; y = 456; } // { z = 789; } // { z = 987; }; + + body = if as ? a then as.a else assert as ? z; as.z; +} diff --git a/tests/functional/lang/eval-okay-attrs2.exp b/tests/functional/lang/eval-okay-attrs2.exp new file mode 100644 index 000000000..45b0f829e --- /dev/null +++ b/tests/functional/lang/eval-okay-attrs2.exp @@ -0,0 +1 @@ +987 diff --git a/tests/functional/lang/eval-okay-attrs2.nix b/tests/functional/lang/eval-okay-attrs2.nix new file mode 100644 index 000000000..9e06b83ac --- /dev/null +++ b/tests/functional/lang/eval-okay-attrs2.nix @@ -0,0 +1,10 @@ +let { + as = { x = 123; y = 456; } // { z = 789; } // { z = 987; }; + + A = "a"; + Z = "z"; + + body = if builtins.hasAttr A as + then builtins.getAttr A as + else assert builtins.hasAttr Z as; builtins.getAttr Z as; +} diff --git a/tests/functional/lang/eval-okay-attrs3.exp b/tests/functional/lang/eval-okay-attrs3.exp new file mode 100644 index 000000000..19de4fdf7 --- /dev/null +++ b/tests/functional/lang/eval-okay-attrs3.exp @@ -0,0 +1 @@ +"foo 22 80 itchyxac" diff --git a/tests/functional/lang/eval-okay-attrs3.nix b/tests/functional/lang/eval-okay-attrs3.nix new file mode 100644 index 000000000..f29de11fe --- /dev/null +++ b/tests/functional/lang/eval-okay-attrs3.nix @@ -0,0 +1,22 @@ +let + + config = + { + services.sshd.enable = true; + services.sshd.port = 22; + services.httpd.port = 80; + hostName = "itchy"; + a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z = "x"; + foo = { + a = "a"; + b.c = "c"; + }; + }; + +in + if config.services.sshd.enable + then "foo ${toString config.services.sshd.port} ${toString config.services.httpd.port} ${config.hostName}" + + "${config.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z}" + + "${config.foo.a}" + + "${config.foo.b.c}" + else "bar" diff --git a/tests/functional/lang/eval-okay-attrs4.exp b/tests/functional/lang/eval-okay-attrs4.exp new file mode 100644 index 000000000..185173144 --- /dev/null +++ b/tests/functional/lang/eval-okay-attrs4.exp @@ -0,0 +1 @@ +[ true false true false false true false false ] diff --git a/tests/functional/lang/eval-okay-attrs4.nix b/tests/functional/lang/eval-okay-attrs4.nix new file mode 100644 index 000000000..43ec81210 --- /dev/null +++ b/tests/functional/lang/eval-okay-attrs4.nix @@ -0,0 +1,7 @@ +let + + as = { x.y.z = 123; a.b.c = 456; }; + + bs = null; + +in [ (as ? x) (as ? y) (as ? x.y.z) (as ? x.y.z.a) (as ? x.y.a) (as ? a.b.c) (bs ? x) (bs ? x.y.z) ] diff --git a/tests/functional/lang/eval-okay-attrs5.exp b/tests/functional/lang/eval-okay-attrs5.exp new file mode 100644 index 000000000..ce0430d78 --- /dev/null +++ b/tests/functional/lang/eval-okay-attrs5.exp @@ -0,0 +1 @@ +[ 123 "foo" 456 456 "foo" "xyzzy" "xyzzy" true ] diff --git a/tests/functional/lang/eval-okay-attrs5.nix b/tests/functional/lang/eval-okay-attrs5.nix new file mode 100644 index 000000000..a4584cd3b --- /dev/null +++ b/tests/functional/lang/eval-okay-attrs5.nix @@ -0,0 +1,21 @@ +with import ./lib.nix; + +let + + as = { x.y.z = 123; a.b.c = 456; }; + + bs = { f-o-o.bar = "foo"; }; + + or = x: y: x || y; + +in + [ as.x.y.z + as.foo or "foo" + as.x.y.bla or as.a.b.c + as.a.b.c or as.x.y.z + as.x.y.bla or bs.f-o-o.bar or "xyzzy" + as.x.y.bla or bs.bar.foo or "xyzzy" + (123).bla or null.foo or "xyzzy" + # Backwards compatibility test. + (fold or [] [true false false]) + ] diff --git a/tests/functional/lang/eval-okay-attrs6.exp b/tests/functional/lang/eval-okay-attrs6.exp new file mode 100644 index 000000000..b46938032 --- /dev/null +++ b/tests/functional/lang/eval-okay-attrs6.exp @@ -0,0 +1 @@ +{ __overrides = { bar = "qux"; }; bar = "qux"; foo = "bar"; } diff --git a/tests/functional/lang/eval-okay-attrs6.nix b/tests/functional/lang/eval-okay-attrs6.nix new file mode 100644 index 000000000..2e5c85483 --- /dev/null +++ b/tests/functional/lang/eval-okay-attrs6.nix @@ -0,0 +1,4 @@ +rec { + "${"foo"}" = "bar"; + __overrides = { bar = "qux"; }; +} diff --git a/tests/functional/lang/eval-okay-autoargs.exp b/tests/functional/lang/eval-okay-autoargs.exp new file mode 100644 index 000000000..7a8391786 --- /dev/null +++ b/tests/functional/lang/eval-okay-autoargs.exp @@ -0,0 +1 @@ +"xyzzy!xyzzy!foobar" diff --git a/tests/functional/lang/eval-okay-autoargs.flags b/tests/functional/lang/eval-okay-autoargs.flags new file mode 100644 index 000000000..ae3762254 --- /dev/null +++ b/tests/functional/lang/eval-okay-autoargs.flags @@ -0,0 +1 @@ +--arg lib import(lang/lib.nix) --argstr xyzzy xyzzy! -A result diff --git a/tests/functional/lang/eval-okay-autoargs.nix b/tests/functional/lang/eval-okay-autoargs.nix new file mode 100644 index 000000000..815f51b1d --- /dev/null +++ b/tests/functional/lang/eval-okay-autoargs.nix @@ -0,0 +1,15 @@ +let + + foobar = "foobar"; + +in + +{ xyzzy2 ? xyzzy # mutually recursive args +, xyzzy ? "blaat" # will be overridden by --argstr +, fb ? foobar +, lib # will be set by --arg +}: + +{ + result = lib.concat [xyzzy xyzzy2 fb]; +} diff --git a/tests/functional/lang/eval-okay-backslash-newline-1.exp b/tests/functional/lang/eval-okay-backslash-newline-1.exp new file mode 100644 index 000000000..3e754364c --- /dev/null +++ b/tests/functional/lang/eval-okay-backslash-newline-1.exp @@ -0,0 +1 @@ +"a\nb" diff --git a/tests/functional/lang/eval-okay-backslash-newline-1.nix b/tests/functional/lang/eval-okay-backslash-newline-1.nix new file mode 100644 index 000000000..7fef3dddd --- /dev/null +++ b/tests/functional/lang/eval-okay-backslash-newline-1.nix @@ -0,0 +1,2 @@ +"a\ +b" diff --git a/tests/functional/lang/eval-okay-backslash-newline-2.exp b/tests/functional/lang/eval-okay-backslash-newline-2.exp new file mode 100644 index 000000000..3e754364c --- /dev/null +++ b/tests/functional/lang/eval-okay-backslash-newline-2.exp @@ -0,0 +1 @@ +"a\nb" diff --git a/tests/functional/lang/eval-okay-backslash-newline-2.nix b/tests/functional/lang/eval-okay-backslash-newline-2.nix new file mode 100644 index 000000000..35ddf495c --- /dev/null +++ b/tests/functional/lang/eval-okay-backslash-newline-2.nix @@ -0,0 +1,2 @@ +''a''\ +b'' diff --git a/tests/functional/lang/eval-okay-builtins-add.exp b/tests/functional/lang/eval-okay-builtins-add.exp new file mode 100644 index 000000000..0350b518a --- /dev/null +++ b/tests/functional/lang/eval-okay-builtins-add.exp @@ -0,0 +1 @@ +[ 5 4 "int" "tt" "float" 4 ] diff --git a/tests/functional/lang/eval-okay-builtins-add.nix b/tests/functional/lang/eval-okay-builtins-add.nix new file mode 100644 index 000000000..c84181622 --- /dev/null +++ b/tests/functional/lang/eval-okay-builtins-add.nix @@ -0,0 +1,8 @@ +[ +(builtins.add 2 3) +(builtins.add 2 2) +(builtins.typeOf (builtins.add 2 2)) +("t" + "t") +(builtins.typeOf (builtins.add 2.0 2)) +(builtins.add 2.0 2) +] diff --git a/tests/functional/lang/eval-okay-builtins.exp b/tests/functional/lang/eval-okay-builtins.exp new file mode 100644 index 000000000..0661686d6 --- /dev/null +++ b/tests/functional/lang/eval-okay-builtins.exp @@ -0,0 +1 @@ +/foo diff --git a/tests/functional/lang/eval-okay-builtins.nix b/tests/functional/lang/eval-okay-builtins.nix new file mode 100644 index 000000000..e9d65e88a --- /dev/null +++ b/tests/functional/lang/eval-okay-builtins.nix @@ -0,0 +1,12 @@ +assert builtins ? currentSystem; +assert !builtins ? __currentSystem; + +let { + + x = if builtins ? dirOf then builtins.dirOf /foo/bar else ""; + + y = if builtins ? fnord then builtins.fnord "foo" else ""; + + body = x + y; + +} diff --git a/tests/functional/lang/eval-okay-callable-attrs.exp b/tests/functional/lang/eval-okay-callable-attrs.exp new file mode 100644 index 000000000..27ba77dda --- /dev/null +++ b/tests/functional/lang/eval-okay-callable-attrs.exp @@ -0,0 +1 @@ +true diff --git a/tests/functional/lang/eval-okay-callable-attrs.nix b/tests/functional/lang/eval-okay-callable-attrs.nix new file mode 100644 index 000000000..310a030df --- /dev/null +++ b/tests/functional/lang/eval-okay-callable-attrs.nix @@ -0,0 +1 @@ +({ __functor = self: x: self.foo && x; foo = false; } // { foo = true; }) true diff --git a/tests/functional/lang/eval-okay-catattrs.exp b/tests/functional/lang/eval-okay-catattrs.exp new file mode 100644 index 000000000..b4a1e66d6 --- /dev/null +++ b/tests/functional/lang/eval-okay-catattrs.exp @@ -0,0 +1 @@ +[ 1 2 ] diff --git a/tests/functional/lang/eval-okay-catattrs.nix b/tests/functional/lang/eval-okay-catattrs.nix new file mode 100644 index 000000000..2c3dc10da --- /dev/null +++ b/tests/functional/lang/eval-okay-catattrs.nix @@ -0,0 +1 @@ +builtins.catAttrs "a" [ { a = 1; } { b = 0; } { a = 2; } ] diff --git a/tests/functional/lang/eval-okay-closure.exp b/tests/functional/lang/eval-okay-closure.exp new file mode 100644 index 000000000..e7dbf9781 --- /dev/null +++ b/tests/functional/lang/eval-okay-closure.exp @@ -0,0 +1 @@ +[ { foo = true; key = -13; } { foo = true; key = -12; } { foo = true; key = -11; } { foo = true; key = -9; } { foo = true; key = -8; } { foo = true; key = -7; } { foo = true; key = -5; } { foo = true; key = -4; } { foo = true; key = -3; } { key = -1; } { foo = true; key = 0; } { foo = true; key = 1; } { foo = true; key = 2; } { foo = true; key = 4; } { foo = true; key = 5; } { foo = true; key = 6; } { key = 8; } { foo = true; key = 9; } { foo = true; key = 10; } { foo = true; key = 13; } { foo = true; key = 14; } { foo = true; key = 15; } { key = 17; } { foo = true; key = 18; } { foo = true; key = 19; } { foo = true; key = 22; } { foo = true; key = 23; } { key = 26; } { foo = true; key = 27; } { foo = true; key = 28; } { foo = true; key = 31; } { foo = true; key = 32; } { key = 35; } { foo = true; key = 36; } { foo = true; key = 40; } { foo = true; key = 41; } { key = 44; } { foo = true; key = 45; } { foo = true; key = 49; } { key = 53; } { foo = true; key = 54; } { foo = true; key = 58; } { key = 62; } { foo = true; key = 67; } { key = 71; } { key = 80; } ] diff --git a/tests/functional/lang/eval-okay-closure.exp.xml b/tests/functional/lang/eval-okay-closure.exp.xml new file mode 100644 index 000000000..dffc03a99 --- /dev/null +++ b/tests/functional/lang/eval-okay-closure.exp.xml @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/functional/lang/eval-okay-closure.nix b/tests/functional/lang/eval-okay-closure.nix new file mode 100644 index 000000000..cccd4dc35 --- /dev/null +++ b/tests/functional/lang/eval-okay-closure.nix @@ -0,0 +1,13 @@ +let + + closure = builtins.genericClosure { + startSet = [{key = 80;}]; + operator = {key, foo ? false}: + if builtins.lessThan key 0 + then [] + else [{key = builtins.sub key 9;} {key = builtins.sub key 13; foo = true;}]; + }; + + sort = (import ./lib.nix).sortBy (a: b: builtins.lessThan a.key b.key); + +in sort closure diff --git a/tests/functional/lang/eval-okay-comments.exp b/tests/functional/lang/eval-okay-comments.exp new file mode 100644 index 000000000..7182dc2f9 --- /dev/null +++ b/tests/functional/lang/eval-okay-comments.exp @@ -0,0 +1 @@ +"abcdefghijklmnopqrstuvwxyz" diff --git a/tests/functional/lang/eval-okay-comments.nix b/tests/functional/lang/eval-okay-comments.nix new file mode 100644 index 000000000..cb2cce218 --- /dev/null +++ b/tests/functional/lang/eval-okay-comments.nix @@ -0,0 +1,59 @@ +# A simple comment +"a"+ # And another +## A double comment +"b"+ ## And another +# Nested # comments # +"c"+ # and # some # other # +# An empty line, following here: + +"d"+ # and a comment not starting the line ! + +"e"+ +/* multiline comments */ +"f" + +/* multiline + comments, + on + multiple + lines +*/ +"g" + +# Small, tricky comments +/**/ "h"+ /*/*/ "i"+ /***/ "j"+ /* /*/ "k"+ /*/* /*/ "l"+ +# Comments with an even number of ending '*' used to fail: +"m"+ +/* */ /* **/ /* ***/ /* ****/ "n"+ +/* */ /** */ /*** */ /**** */ "o"+ +/** **/ /*** ***/ /**** ****/ "p"+ +/* * ** *** **** ***** */ "q"+ +# Random comments +/* ***** ////// * / * / /* */ "r"+ +# Mixed comments +/* # */ +"s"+ +# /* # +"t"+ +# /* # */ +"u"+ +# /*********/ +"v"+ +## */* +"w"+ +/* + * Multiline, decorated comments + * # This ain't a nest'd comm'nt + */ +"x"+ +''${/** with **/"y" + # real + /* comments + inside ! # */ + + # (and empty lines) + +}''+ /* And a multiline comment, + on the same line, + after some spaces +*/ # followed by a one-line comment +"z" +/* EOF */ diff --git a/tests/functional/lang/eval-okay-concat.exp b/tests/functional/lang/eval-okay-concat.exp new file mode 100644 index 000000000..bb4bbd577 --- /dev/null +++ b/tests/functional/lang/eval-okay-concat.exp @@ -0,0 +1 @@ +[ 1 2 3 4 5 6 7 8 9 ] diff --git a/tests/functional/lang/eval-okay-concat.nix b/tests/functional/lang/eval-okay-concat.nix new file mode 100644 index 000000000..d158a9bf0 --- /dev/null +++ b/tests/functional/lang/eval-okay-concat.nix @@ -0,0 +1 @@ +[1 2 3] ++ [4 5 6] ++ [7 8 9] diff --git a/tests/functional/lang/eval-okay-concatmap.exp b/tests/functional/lang/eval-okay-concatmap.exp new file mode 100644 index 000000000..3b8be7739 --- /dev/null +++ b/tests/functional/lang/eval-okay-concatmap.exp @@ -0,0 +1 @@ +[ [ 1 3 5 7 9 ] [ "a" "z" "b" "z" ] ] diff --git a/tests/functional/lang/eval-okay-concatmap.nix b/tests/functional/lang/eval-okay-concatmap.nix new file mode 100644 index 000000000..97da5d37a --- /dev/null +++ b/tests/functional/lang/eval-okay-concatmap.nix @@ -0,0 +1,5 @@ +with import ./lib.nix; + +[ (builtins.concatMap (x: if x / 2 * 2 == x then [] else [ x ]) (range 0 10)) + (builtins.concatMap (x: [x] ++ ["z"]) ["a" "b"]) +] diff --git a/tests/functional/lang/eval-okay-concatstringssep.exp b/tests/functional/lang/eval-okay-concatstringssep.exp new file mode 100644 index 000000000..93987647f --- /dev/null +++ b/tests/functional/lang/eval-okay-concatstringssep.exp @@ -0,0 +1 @@ +[ "" "foobarxyzzy" "foo, bar, xyzzy" "foo" "" ] diff --git a/tests/functional/lang/eval-okay-concatstringssep.nix b/tests/functional/lang/eval-okay-concatstringssep.nix new file mode 100644 index 000000000..adc4c41bd --- /dev/null +++ b/tests/functional/lang/eval-okay-concatstringssep.nix @@ -0,0 +1,8 @@ +with builtins; + +[ (concatStringsSep "" []) + (concatStringsSep "" ["foo" "bar" "xyzzy"]) + (concatStringsSep ", " ["foo" "bar" "xyzzy"]) + (concatStringsSep ", " ["foo"]) + (concatStringsSep ", " []) +] diff --git a/tests/functional/lang/eval-okay-context-introspection.exp b/tests/functional/lang/eval-okay-context-introspection.exp new file mode 100644 index 000000000..03b400cc8 --- /dev/null +++ b/tests/functional/lang/eval-okay-context-introspection.exp @@ -0,0 +1 @@ +[ true true true true true true ] diff --git a/tests/functional/lang/eval-okay-context-introspection.nix b/tests/functional/lang/eval-okay-context-introspection.nix new file mode 100644 index 000000000..50a78d946 --- /dev/null +++ b/tests/functional/lang/eval-okay-context-introspection.nix @@ -0,0 +1,41 @@ +let + drv = derivation { + name = "fail"; + builder = "/bin/false"; + system = "x86_64-linux"; + outputs = [ "out" "foo" ]; + }; + + path = "${./eval-okay-context-introspection.nix}"; + + desired-context = { + "${builtins.unsafeDiscardStringContext path}" = { + path = true; + }; + "${builtins.unsafeDiscardStringContext drv.drvPath}" = { + outputs = [ "foo" "out" ]; + allOutputs = true; + }; + }; + + combo-path = "${path}${drv.outPath}${drv.foo.outPath}${drv.drvPath}"; + legit-context = builtins.getContext combo-path; + + reconstructed-path = builtins.appendContext + (builtins.unsafeDiscardStringContext combo-path) + desired-context; + + # Eta rule for strings with context. + etaRule = str: + str == builtins.appendContext + (builtins.unsafeDiscardStringContext str) + (builtins.getContext str); + +in [ + (legit-context == desired-context) + (reconstructed-path == combo-path) + (etaRule "foo") + (etaRule drv.drvPath) + (etaRule drv.foo.outPath) + (etaRule (builtins.unsafeDiscardOutputDependency drv.drvPath)) +] diff --git a/tests/functional/lang/eval-okay-context.exp b/tests/functional/lang/eval-okay-context.exp new file mode 100644 index 000000000..2f535bdbc --- /dev/null +++ b/tests/functional/lang/eval-okay-context.exp @@ -0,0 +1 @@ +"foo eval-okay-context.nix bar" diff --git a/tests/functional/lang/eval-okay-context.nix b/tests/functional/lang/eval-okay-context.nix new file mode 100644 index 000000000..7b9531cfe --- /dev/null +++ b/tests/functional/lang/eval-okay-context.nix @@ -0,0 +1,6 @@ +let s = "foo ${builtins.substring 33 100 (baseNameOf "${./eval-okay-context.nix}")} bar"; +in + if s != "foo eval-okay-context.nix bar" + then abort "context not discarded" + else builtins.unsafeDiscardStringContext s + diff --git a/tests/functional/lang/eval-okay-curpos.exp b/tests/functional/lang/eval-okay-curpos.exp new file mode 100644 index 000000000..65fd65b4d --- /dev/null +++ b/tests/functional/lang/eval-okay-curpos.exp @@ -0,0 +1 @@ +[ 3 7 4 9 ] diff --git a/tests/functional/lang/eval-okay-curpos.nix b/tests/functional/lang/eval-okay-curpos.nix new file mode 100644 index 000000000..b79553df0 --- /dev/null +++ b/tests/functional/lang/eval-okay-curpos.nix @@ -0,0 +1,5 @@ +# Bla +let + x = __curPos; + y = __curPos; +in [ x.line x.column y.line y.column ] diff --git a/tests/functional/lang/eval-okay-deepseq.exp b/tests/functional/lang/eval-okay-deepseq.exp new file mode 100644 index 000000000..8d38505c1 --- /dev/null +++ b/tests/functional/lang/eval-okay-deepseq.exp @@ -0,0 +1 @@ +456 diff --git a/tests/functional/lang/eval-okay-deepseq.nix b/tests/functional/lang/eval-okay-deepseq.nix new file mode 100644 index 000000000..53aa4b1dc --- /dev/null +++ b/tests/functional/lang/eval-okay-deepseq.nix @@ -0,0 +1 @@ +builtins.deepSeq (let as = { x = 123; y = as; }; in as) 456 diff --git a/tests/functional/lang/eval-okay-delayed-with-inherit.exp b/tests/functional/lang/eval-okay-delayed-with-inherit.exp new file mode 100644 index 000000000..eaacb55c1 --- /dev/null +++ b/tests/functional/lang/eval-okay-delayed-with-inherit.exp @@ -0,0 +1 @@ +"b-overridden" diff --git a/tests/functional/lang/eval-okay-delayed-with-inherit.nix b/tests/functional/lang/eval-okay-delayed-with-inherit.nix new file mode 100644 index 000000000..84b388c27 --- /dev/null +++ b/tests/functional/lang/eval-okay-delayed-with-inherit.nix @@ -0,0 +1,24 @@ +let + pkgs_ = with pkgs; { + a = derivation { + name = "a"; + system = builtins.currentSystem; + builder = "/bin/sh"; + args = [ "-c" "touch $out" ]; + inherit b; + }; + + inherit b; + }; + + packageOverrides = p: { + b = derivation { + name = "b-overridden"; + system = builtins.currentSystem; + builder = "/bin/sh"; + args = [ "-c" "touch $out" ]; + }; + }; + + pkgs = pkgs_ // (packageOverrides pkgs_); +in pkgs.a.b.name diff --git a/tests/functional/lang/eval-okay-delayed-with.exp b/tests/functional/lang/eval-okay-delayed-with.exp new file mode 100644 index 000000000..8e7c61ab8 --- /dev/null +++ b/tests/functional/lang/eval-okay-delayed-with.exp @@ -0,0 +1 @@ +"b-overridden b-overridden a" diff --git a/tests/functional/lang/eval-okay-delayed-with.nix b/tests/functional/lang/eval-okay-delayed-with.nix new file mode 100644 index 000000000..3fb023e1c --- /dev/null +++ b/tests/functional/lang/eval-okay-delayed-with.nix @@ -0,0 +1,29 @@ +let + + pkgs_ = with pkgs; { + a = derivation { + name = "a"; + system = builtins.currentSystem; + builder = "/bin/sh"; + args = [ "-c" "touch $out" ]; + inherit b; + }; + + b = derivation { + name = "b"; + system = builtins.currentSystem; + builder = "/bin/sh"; + args = [ "-c" "touch $out" ]; + inherit a; + }; + + c = b; + }; + + packageOverrides = pkgs: with pkgs; { + b = derivation (b.drvAttrs // { name = "${b.name}-overridden"; }); + }; + + pkgs = pkgs_ // (packageOverrides pkgs_); + +in "${pkgs.a.b.name} ${pkgs.c.name} ${pkgs.b.a.name}" diff --git a/tests/functional/lang/eval-okay-dynamic-attrs-2.exp b/tests/functional/lang/eval-okay-dynamic-attrs-2.exp new file mode 100644 index 000000000..27ba77dda --- /dev/null +++ b/tests/functional/lang/eval-okay-dynamic-attrs-2.exp @@ -0,0 +1 @@ +true diff --git a/tests/functional/lang/eval-okay-dynamic-attrs-2.nix b/tests/functional/lang/eval-okay-dynamic-attrs-2.nix new file mode 100644 index 000000000..6d57bf854 --- /dev/null +++ b/tests/functional/lang/eval-okay-dynamic-attrs-2.nix @@ -0,0 +1 @@ +{ a."${"b"}" = true; a."${"c"}" = false; }.a.b diff --git a/tests/functional/lang/eval-okay-dynamic-attrs-bare.exp b/tests/functional/lang/eval-okay-dynamic-attrs-bare.exp new file mode 100644 index 000000000..df8750afc --- /dev/null +++ b/tests/functional/lang/eval-okay-dynamic-attrs-bare.exp @@ -0,0 +1 @@ +{ binds = true; hasAttrs = true; multiAttrs = true; recBinds = true; selectAttrs = true; selectOrAttrs = true; } diff --git a/tests/functional/lang/eval-okay-dynamic-attrs-bare.nix b/tests/functional/lang/eval-okay-dynamic-attrs-bare.nix new file mode 100644 index 000000000..0dbe15e63 --- /dev/null +++ b/tests/functional/lang/eval-okay-dynamic-attrs-bare.nix @@ -0,0 +1,17 @@ +let + aString = "a"; + + bString = "b"; +in { + hasAttrs = { a.b = null; } ? ${aString}.b; + + selectAttrs = { a.b = true; }.a.${bString}; + + selectOrAttrs = { }.${aString} or true; + + binds = { ${aString}."${bString}c" = true; }.a.bc; + + recBinds = rec { ${bString} = a; a = true; }.b; + + multiAttrs = { ${aString} = true; ${bString} = false; }.a; +} diff --git a/tests/functional/lang/eval-okay-dynamic-attrs.exp b/tests/functional/lang/eval-okay-dynamic-attrs.exp new file mode 100644 index 000000000..df8750afc --- /dev/null +++ b/tests/functional/lang/eval-okay-dynamic-attrs.exp @@ -0,0 +1 @@ +{ binds = true; hasAttrs = true; multiAttrs = true; recBinds = true; selectAttrs = true; selectOrAttrs = true; } diff --git a/tests/functional/lang/eval-okay-dynamic-attrs.nix b/tests/functional/lang/eval-okay-dynamic-attrs.nix new file mode 100644 index 000000000..ee02ac7e6 --- /dev/null +++ b/tests/functional/lang/eval-okay-dynamic-attrs.nix @@ -0,0 +1,17 @@ +let + aString = "a"; + + bString = "b"; +in { + hasAttrs = { a.b = null; } ? "${aString}".b; + + selectAttrs = { a.b = true; }.a."${bString}"; + + selectOrAttrs = { }."${aString}" or true; + + binds = { "${aString}"."${bString}c" = true; }.a.bc; + + recBinds = rec { "${bString}" = a; a = true; }.b; + + multiAttrs = { "${aString}" = true; "${bString}" = false; }.a; +} diff --git a/tests/functional/lang/eval-okay-elem.exp b/tests/functional/lang/eval-okay-elem.exp new file mode 100644 index 000000000..3cf6c0e96 --- /dev/null +++ b/tests/functional/lang/eval-okay-elem.exp @@ -0,0 +1 @@ +[ true false 30 ] diff --git a/tests/functional/lang/eval-okay-elem.nix b/tests/functional/lang/eval-okay-elem.nix new file mode 100644 index 000000000..71ea7a4ed --- /dev/null +++ b/tests/functional/lang/eval-okay-elem.nix @@ -0,0 +1,6 @@ +with import ./lib.nix; + +let xs = range 10 40; in + +[ (builtins.elem 23 xs) (builtins.elem 42 xs) (builtins.elemAt xs 20) ] + diff --git a/tests/functional/lang/eval-okay-empty-args.exp b/tests/functional/lang/eval-okay-empty-args.exp new file mode 100644 index 000000000..cb5537d5d --- /dev/null +++ b/tests/functional/lang/eval-okay-empty-args.exp @@ -0,0 +1 @@ +"ab" diff --git a/tests/functional/lang/eval-okay-empty-args.nix b/tests/functional/lang/eval-okay-empty-args.nix new file mode 100644 index 000000000..78c133afd --- /dev/null +++ b/tests/functional/lang/eval-okay-empty-args.nix @@ -0,0 +1 @@ +({}: {x,y,}: "${x}${y}") {} {x = "a"; y = "b";} diff --git a/tests/functional/lang/eval-okay-eq-derivations.exp b/tests/functional/lang/eval-okay-eq-derivations.exp new file mode 100644 index 000000000..ec04aab6a --- /dev/null +++ b/tests/functional/lang/eval-okay-eq-derivations.exp @@ -0,0 +1 @@ +[ true true true false ] diff --git a/tests/functional/lang/eval-okay-eq-derivations.nix b/tests/functional/lang/eval-okay-eq-derivations.nix new file mode 100644 index 000000000..d526cb4a2 --- /dev/null +++ b/tests/functional/lang/eval-okay-eq-derivations.nix @@ -0,0 +1,10 @@ +let + + drvA1 = derivation { name = "a"; builder = "/foo"; system = "i686-linux"; }; + drvA2 = derivation { name = "a"; builder = "/foo"; system = "i686-linux"; }; + drvA3 = derivation { name = "a"; builder = "/foo"; system = "i686-linux"; } // { dummy = 1; }; + + drvC1 = derivation { name = "c"; builder = "/foo"; system = "i686-linux"; }; + drvC2 = derivation { name = "c"; builder = "/bar"; system = "i686-linux"; }; + +in [ (drvA1 == drvA1) (drvA1 == drvA2) (drvA1 == drvA3) (drvC1 == drvC2) ] diff --git a/tests/functional/lang/eval-okay-eq.exp b/tests/functional/lang/eval-okay-eq.exp new file mode 100644 index 000000000..27ba77dda --- /dev/null +++ b/tests/functional/lang/eval-okay-eq.exp @@ -0,0 +1 @@ +true diff --git a/tests/functional/lang/eval-okay-eq.nix b/tests/functional/lang/eval-okay-eq.nix new file mode 100644 index 000000000..73d200b38 --- /dev/null +++ b/tests/functional/lang/eval-okay-eq.nix @@ -0,0 +1,3 @@ +["foobar" (rec {x = 1; y = x;})] +== +[("foo" + "bar") ({x = 1; y = 1;})] diff --git a/tests/functional/lang/eval-okay-filter.exp b/tests/functional/lang/eval-okay-filter.exp new file mode 100644 index 000000000..355d51c27 --- /dev/null +++ b/tests/functional/lang/eval-okay-filter.exp @@ -0,0 +1 @@ +[ 0 2 4 6 8 10 100 102 104 106 108 110 ] diff --git a/tests/functional/lang/eval-okay-filter.nix b/tests/functional/lang/eval-okay-filter.nix new file mode 100644 index 000000000..85109b0d0 --- /dev/null +++ b/tests/functional/lang/eval-okay-filter.nix @@ -0,0 +1,5 @@ +with import ./lib.nix; + +builtins.filter + (x: x / 2 * 2 == x) + (builtins.concatLists [ (range 0 10) (range 100 110) ]) diff --git a/tests/functional/lang/eval-okay-flake-ref-to-string.exp b/tests/functional/lang/eval-okay-flake-ref-to-string.exp new file mode 100644 index 000000000..110f8442d --- /dev/null +++ b/tests/functional/lang/eval-okay-flake-ref-to-string.exp @@ -0,0 +1 @@ +"github:NixOS/nixpkgs/23.05?dir=lib" diff --git a/tests/functional/lang/eval-okay-flake-ref-to-string.nix b/tests/functional/lang/eval-okay-flake-ref-to-string.nix new file mode 100644 index 000000000..dbb4e5b2a --- /dev/null +++ b/tests/functional/lang/eval-okay-flake-ref-to-string.nix @@ -0,0 +1,7 @@ +builtins.flakeRefToString { + type = "github"; + owner = "NixOS"; + repo = "nixpkgs"; + ref = "23.05"; + dir = "lib"; +} diff --git a/tests/functional/lang/eval-okay-flatten.exp b/tests/functional/lang/eval-okay-flatten.exp new file mode 100644 index 000000000..b979b2b8b --- /dev/null +++ b/tests/functional/lang/eval-okay-flatten.exp @@ -0,0 +1 @@ +"1234567" diff --git a/tests/functional/lang/eval-okay-flatten.nix b/tests/functional/lang/eval-okay-flatten.nix new file mode 100644 index 000000000..fe911e968 --- /dev/null +++ b/tests/functional/lang/eval-okay-flatten.nix @@ -0,0 +1,8 @@ +with import ./lib.nix; + +let { + + l = ["1" "2" ["3" ["4"] ["5" "6"]] "7"]; + + body = concat (flatten l); +} diff --git a/tests/functional/lang/eval-okay-float.exp b/tests/functional/lang/eval-okay-float.exp new file mode 100644 index 000000000..3c50a8adc --- /dev/null +++ b/tests/functional/lang/eval-okay-float.exp @@ -0,0 +1 @@ +[ 3.4 3.5 2.5 1.5 ] diff --git a/tests/functional/lang/eval-okay-float.nix b/tests/functional/lang/eval-okay-float.nix new file mode 100644 index 000000000..b2702c7b1 --- /dev/null +++ b/tests/functional/lang/eval-okay-float.nix @@ -0,0 +1,6 @@ +[ + (1.1 + 2.3) + (builtins.add (0.5 + 0.5) (2.0 + 0.5)) + ((0.5 + 0.5) * (2.0 + 0.5)) + ((1.5 + 1.5) / (0.5 * 4.0)) +] diff --git a/tests/functional/lang/eval-okay-floor-ceil.exp b/tests/functional/lang/eval-okay-floor-ceil.exp new file mode 100644 index 000000000..81f80420b --- /dev/null +++ b/tests/functional/lang/eval-okay-floor-ceil.exp @@ -0,0 +1 @@ +"23;24;23;23" diff --git a/tests/functional/lang/eval-okay-floor-ceil.nix b/tests/functional/lang/eval-okay-floor-ceil.nix new file mode 100644 index 000000000..d76a0d86e --- /dev/null +++ b/tests/functional/lang/eval-okay-floor-ceil.nix @@ -0,0 +1,9 @@ +with import ./lib.nix; + +let + n1 = builtins.floor 23.5; + n2 = builtins.ceil 23.5; + n3 = builtins.floor 23; + n4 = builtins.ceil 23; +in + builtins.concatStringsSep ";" (map toString [ n1 n2 n3 n4 ]) diff --git a/tests/functional/lang/eval-okay-foldlStrict-lazy-elements.exp b/tests/functional/lang/eval-okay-foldlStrict-lazy-elements.exp new file mode 100644 index 000000000..d81cc0710 --- /dev/null +++ b/tests/functional/lang/eval-okay-foldlStrict-lazy-elements.exp @@ -0,0 +1 @@ +42 diff --git a/tests/functional/lang/eval-okay-foldlStrict-lazy-elements.nix b/tests/functional/lang/eval-okay-foldlStrict-lazy-elements.nix new file mode 100644 index 000000000..c666e07f3 --- /dev/null +++ b/tests/functional/lang/eval-okay-foldlStrict-lazy-elements.nix @@ -0,0 +1,9 @@ +# Tests that the rhs argument of op is not forced unconditionally +let + lst = builtins.foldl' + (acc: x: acc ++ [ x ]) + [ ] + [ 42 (throw "this shouldn't be evaluated") ]; +in + +builtins.head lst diff --git a/tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.exp b/tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.exp new file mode 100644 index 000000000..d81cc0710 --- /dev/null +++ b/tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.exp @@ -0,0 +1 @@ +42 diff --git a/tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.nix b/tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.nix new file mode 100644 index 000000000..abcd5366a --- /dev/null +++ b/tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.nix @@ -0,0 +1,6 @@ +# Checks that the nul value for the accumulator is not forced unconditionally. +# Some languages provide a foldl' that is strict in this argument, but Nix does not. +builtins.foldl' + (_: x: x) + (throw "This is never forced") + [ "but the results of applying op are" 42 ] diff --git a/tests/functional/lang/eval-okay-foldlStrict.exp b/tests/functional/lang/eval-okay-foldlStrict.exp new file mode 100644 index 000000000..837e12b40 --- /dev/null +++ b/tests/functional/lang/eval-okay-foldlStrict.exp @@ -0,0 +1 @@ +500500 diff --git a/tests/functional/lang/eval-okay-foldlStrict.nix b/tests/functional/lang/eval-okay-foldlStrict.nix new file mode 100644 index 000000000..3b87188d2 --- /dev/null +++ b/tests/functional/lang/eval-okay-foldlStrict.nix @@ -0,0 +1,3 @@ +with import ./lib.nix; + +builtins.foldl' (x: y: x + y) 0 (range 1 1000) diff --git a/tests/functional/lang/eval-okay-fromTOML-timestamps.exp b/tests/functional/lang/eval-okay-fromTOML-timestamps.exp new file mode 100644 index 000000000..08b3c69a6 --- /dev/null +++ b/tests/functional/lang/eval-okay-fromTOML-timestamps.exp @@ -0,0 +1 @@ +{ "1234" = "value"; "127.0.0.1" = "value"; a = { b = { c = { }; }; }; arr1 = [ 1 2 3 ]; arr2 = [ "red" "yellow" "green" ]; arr3 = [ [ 1 2 ] [ 3 4 5 ] ]; arr4 = [ "all" "strings" "are the same" "type" ]; arr5 = [ [ 1 2 ] [ "a" "b" "c" ] ]; arr7 = [ 1 2 3 ]; arr8 = [ 1 2 ]; bare-key = "value"; bare_key = "value"; bin1 = 214; bool1 = true; bool2 = false; "character encoding" = "value"; d = { e = { f = { }; }; }; dog = { "tater.man" = { type = { name = "pug"; }; }; }; flt1 = 1; flt2 = 3.1415; flt3 = -0.01; flt4 = 5e+22; flt5 = 1e+06; flt6 = -0.02; flt7 = 6.626e-34; flt8 = 9.22462e+06; fruit = [ { name = "apple"; physical = { color = "red"; shape = "round"; }; variety = [ { name = "red delicious"; } { name = "granny smith"; } ]; } { name = "banana"; variety = [ { name = "plantain"; } ]; } ]; g = { h = { i = { }; }; }; hex1 = 3735928559; hex2 = 3735928559; hex3 = 3735928559; int1 = 99; int2 = 42; int3 = 0; int4 = -17; int5 = 1000; int6 = 5349221; int7 = 12345; j = { "ʞ" = { l = { }; }; }; key = "value"; key2 = "value"; ld1 = { _type = "timestamp"; value = "1979-05-27"; }; ldt1 = { _type = "timestamp"; value = "1979-05-27T07:32:00"; }; ldt2 = { _type = "timestamp"; value = "1979-05-27T00:32:00.999999"; }; lt1 = { _type = "timestamp"; value = "07:32:00"; }; lt2 = { _type = "timestamp"; value = "00:32:00.999999"; }; name = "Orange"; oct1 = 342391; oct2 = 493; odt1 = { _type = "timestamp"; value = "1979-05-27T07:32:00Z"; }; odt2 = { _type = "timestamp"; value = "1979-05-27T00:32:00-07:00"; }; odt3 = { _type = "timestamp"; value = "1979-05-27T00:32:00.999999-07:00"; }; odt4 = { _type = "timestamp"; value = "1979-05-27T07:32:00Z"; }; physical = { color = "orange"; shape = "round"; }; products = [ { name = "Hammer"; sku = 738594937; } { } { color = "gray"; name = "Nail"; sku = 284758393; } ]; "quoted \"value\"" = "value"; site = { "google.com" = true; }; str = "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF."; table-1 = { key1 = "some string"; key2 = 123; }; table-2 = { key1 = "another string"; key2 = 456; }; x = { y = { z = { w = { animal = { type = { name = "pug"; }; }; name = { first = "Tom"; last = "Preston-Werner"; }; point = { x = 1; y = 2; }; }; }; }; }; "ʎǝʞ" = "value"; } diff --git a/tests/functional/lang/eval-okay-fromTOML-timestamps.flags b/tests/functional/lang/eval-okay-fromTOML-timestamps.flags new file mode 100644 index 000000000..9ed39dc6b --- /dev/null +++ b/tests/functional/lang/eval-okay-fromTOML-timestamps.flags @@ -0,0 +1 @@ +--extra-experimental-features parse-toml-timestamps diff --git a/tests/functional/lang/eval-okay-fromTOML-timestamps.nix b/tests/functional/lang/eval-okay-fromTOML-timestamps.nix new file mode 100644 index 000000000..74cff9470 --- /dev/null +++ b/tests/functional/lang/eval-okay-fromTOML-timestamps.nix @@ -0,0 +1,130 @@ +builtins.fromTOML '' + key = "value" + bare_key = "value" + bare-key = "value" + 1234 = "value" + + "127.0.0.1" = "value" + "character encoding" = "value" + "ʎǝʞ" = "value" + 'key2' = "value" + 'quoted "value"' = "value" + + name = "Orange" + + physical.color = "orange" + physical.shape = "round" + site."google.com" = true + + # This is legal according to the spec, but cpptoml doesn't handle it. + #a.b.c = 1 + #a.d = 2 + + str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF." + + int1 = +99 + int2 = 42 + int3 = 0 + int4 = -17 + int5 = 1_000 + int6 = 5_349_221 + int7 = 1_2_3_4_5 + + hex1 = 0xDEADBEEF + hex2 = 0xdeadbeef + hex3 = 0xdead_beef + + oct1 = 0o01234567 + oct2 = 0o755 + + bin1 = 0b11010110 + + flt1 = +1.0 + flt2 = 3.1415 + flt3 = -0.01 + flt4 = 5e+22 + flt5 = 1e6 + flt6 = -2E-2 + flt7 = 6.626e-34 + flt8 = 9_224_617.445_991_228_313 + + bool1 = true + bool2 = false + + odt1 = 1979-05-27T07:32:00Z + odt2 = 1979-05-27T00:32:00-07:00 + odt3 = 1979-05-27T00:32:00.999999-07:00 + odt4 = 1979-05-27 07:32:00Z + ldt1 = 1979-05-27T07:32:00 + ldt2 = 1979-05-27T00:32:00.999999 + ld1 = 1979-05-27 + lt1 = 07:32:00 + lt2 = 00:32:00.999999 + + arr1 = [ 1, 2, 3 ] + arr2 = [ "red", "yellow", "green" ] + arr3 = [ [ 1, 2 ], [3, 4, 5] ] + arr4 = [ "all", 'strings', """are the same""", ''''type''''] + arr5 = [ [ 1, 2 ], ["a", "b", "c"] ] + + arr7 = [ + 1, 2, 3 + ] + + arr8 = [ + 1, + 2, # this is ok + ] + + [table-1] + key1 = "some string" + key2 = 123 + + + [table-2] + key1 = "another string" + key2 = 456 + + [dog."tater.man"] + type.name = "pug" + + [a.b.c] + [ d.e.f ] + [ g . h . i ] + [ j . "ʞ" . 'l' ] + [x.y.z.w] + + name = { first = "Tom", last = "Preston-Werner" } + point = { x = 1, y = 2 } + animal = { type.name = "pug" } + + [[products]] + name = "Hammer" + sku = 738594937 + + [[products]] + + [[products]] + name = "Nail" + sku = 284758393 + color = "gray" + + [[fruit]] + name = "apple" + + [fruit.physical] + color = "red" + shape = "round" + + [[fruit.variety]] + name = "red delicious" + + [[fruit.variety]] + name = "granny smith" + + [[fruit]] + name = "banana" + + [[fruit.variety]] + name = "plantain" +'' diff --git a/tests/functional/lang/eval-okay-fromTOML.exp b/tests/functional/lang/eval-okay-fromTOML.exp new file mode 100644 index 000000000..d0dd3af2c --- /dev/null +++ b/tests/functional/lang/eval-okay-fromTOML.exp @@ -0,0 +1 @@ +[ { clients = { data = [ [ "gamma" "delta" ] [ 1 2 ] ]; hosts = [ "alpha" "omega" ]; }; database = { connection_max = 5000; enabled = true; ports = [ 8001 8001 8002 ]; server = "192.168.1.1"; }; owner = { name = "Tom Preston-Werner"; }; servers = { alpha = { dc = "eqdc10"; ip = "10.0.0.1"; }; beta = { dc = "eqdc10"; ip = "10.0.0.2"; }; }; title = "TOML Example"; } { "1234" = "value"; "127.0.0.1" = "value"; a = { b = { c = { }; }; }; arr1 = [ 1 2 3 ]; arr2 = [ "red" "yellow" "green" ]; arr3 = [ [ 1 2 ] [ 3 4 5 ] ]; arr4 = [ "all" "strings" "are the same" "type" ]; arr5 = [ [ 1 2 ] [ "a" "b" "c" ] ]; arr7 = [ 1 2 3 ]; arr8 = [ 1 2 ]; bare-key = "value"; bare_key = "value"; bin1 = 214; bool1 = true; bool2 = false; "character encoding" = "value"; d = { e = { f = { }; }; }; dog = { "tater.man" = { type = { name = "pug"; }; }; }; flt1 = 1; flt2 = 3.1415; flt3 = -0.01; flt4 = 5e+22; flt5 = 1e+06; flt6 = -0.02; flt7 = 6.626e-34; flt8 = 9.22462e+06; fruit = [ { name = "apple"; physical = { color = "red"; shape = "round"; }; variety = [ { name = "red delicious"; } { name = "granny smith"; } ]; } { name = "banana"; variety = [ { name = "plantain"; } ]; } ]; g = { h = { i = { }; }; }; hex1 = 3735928559; hex2 = 3735928559; hex3 = 3735928559; int1 = 99; int2 = 42; int3 = 0; int4 = -17; int5 = 1000; int6 = 5349221; int7 = 12345; j = { "ʞ" = { l = { }; }; }; key = "value"; key2 = "value"; name = "Orange"; oct1 = 342391; oct2 = 493; physical = { color = "orange"; shape = "round"; }; products = [ { name = "Hammer"; sku = 738594937; } { } { color = "gray"; name = "Nail"; sku = 284758393; } ]; "quoted \"value\"" = "value"; site = { "google.com" = true; }; str = "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF."; table-1 = { key1 = "some string"; key2 = 123; }; table-2 = { key1 = "another string"; key2 = 456; }; x = { y = { z = { w = { animal = { type = { name = "pug"; }; }; name = { first = "Tom"; last = "Preston-Werner"; }; point = { x = 1; y = 2; }; }; }; }; }; "ʎǝʞ" = "value"; } { metadata = { "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"; "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"; "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"; "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"; }; package = [ { dependencies = [ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" ]; name = "aho-corasick"; source = "registry+https://github.com/rust-lang/crates.io-index"; version = "0.6.4"; } { name = "ansi_term"; source = "registry+https://github.com/rust-lang/crates.io-index"; version = "0.9.0"; } { dependencies = [ "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" ]; name = "atty"; source = "registry+https://github.com/rust-lang/crates.io-index"; version = "0.2.10"; } ]; } { a = [ [ { b = true; } ] ]; c = [ [ { d = true; } ] ]; e = [ [ 123 ] ]; } ] diff --git a/tests/functional/lang/eval-okay-fromTOML.nix b/tests/functional/lang/eval-okay-fromTOML.nix new file mode 100644 index 000000000..963932689 --- /dev/null +++ b/tests/functional/lang/eval-okay-fromTOML.nix @@ -0,0 +1,208 @@ +[ + + (builtins.fromTOML '' + # This is a TOML document. + + title = "TOML Example" + + [owner] + name = "Tom Preston-Werner" + #dob = 1979-05-27T07:32:00-08:00 # First class dates + + [database] + server = "192.168.1.1" + ports = [ 8001, 8001, 8002 ] + connection_max = 5000 + enabled = true + + [servers] + + # Indentation (tabs and/or spaces) is allowed but not required + [servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10" + + [clients] + data = [ ["gamma", "delta"], [1, 2] ] + + # Line breaks are OK when inside arrays + hosts = [ + "alpha", + "omega" + ] + '') + + (builtins.fromTOML '' + key = "value" + bare_key = "value" + bare-key = "value" + 1234 = "value" + + "127.0.0.1" = "value" + "character encoding" = "value" + "ʎǝʞ" = "value" + 'key2' = "value" + 'quoted "value"' = "value" + + name = "Orange" + + physical.color = "orange" + physical.shape = "round" + site."google.com" = true + + # This is legal according to the spec, but cpptoml doesn't handle it. + #a.b.c = 1 + #a.d = 2 + + str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF." + + int1 = +99 + int2 = 42 + int3 = 0 + int4 = -17 + int5 = 1_000 + int6 = 5_349_221 + int7 = 1_2_3_4_5 + + hex1 = 0xDEADBEEF + hex2 = 0xdeadbeef + hex3 = 0xdead_beef + + oct1 = 0o01234567 + oct2 = 0o755 + + bin1 = 0b11010110 + + flt1 = +1.0 + flt2 = 3.1415 + flt3 = -0.01 + flt4 = 5e+22 + flt5 = 1e6 + flt6 = -2E-2 + flt7 = 6.626e-34 + flt8 = 9_224_617.445_991_228_313 + + bool1 = true + bool2 = false + + # FIXME: not supported because Nix doesn't have a date/time type. + #odt1 = 1979-05-27T07:32:00Z + #odt2 = 1979-05-27T00:32:00-07:00 + #odt3 = 1979-05-27T00:32:00.999999-07:00 + #odt4 = 1979-05-27 07:32:00Z + #ldt1 = 1979-05-27T07:32:00 + #ldt2 = 1979-05-27T00:32:00.999999 + #ld1 = 1979-05-27 + #lt1 = 07:32:00 + #lt2 = 00:32:00.999999 + + arr1 = [ 1, 2, 3 ] + arr2 = [ "red", "yellow", "green" ] + arr3 = [ [ 1, 2 ], [3, 4, 5] ] + arr4 = [ "all", 'strings', """are the same""", ''''type''''] + arr5 = [ [ 1, 2 ], ["a", "b", "c"] ] + + arr7 = [ + 1, 2, 3 + ] + + arr8 = [ + 1, + 2, # this is ok + ] + + [table-1] + key1 = "some string" + key2 = 123 + + + [table-2] + key1 = "another string" + key2 = 456 + + [dog."tater.man"] + type.name = "pug" + + [a.b.c] + [ d.e.f ] + [ g . h . i ] + [ j . "ʞ" . 'l' ] + [x.y.z.w] + + name = { first = "Tom", last = "Preston-Werner" } + point = { x = 1, y = 2 } + animal = { type.name = "pug" } + + [[products]] + name = "Hammer" + sku = 738594937 + + [[products]] + + [[products]] + name = "Nail" + sku = 284758393 + color = "gray" + + [[fruit]] + name = "apple" + + [fruit.physical] + color = "red" + shape = "round" + + [[fruit.variety]] + name = "red delicious" + + [[fruit.variety]] + name = "granny smith" + + [[fruit]] + name = "banana" + + [[fruit.variety]] + name = "plantain" + '') + + (builtins.fromTOML '' + [[package]] + name = "aho-corasick" + version = "0.6.4" + source = "registry+https://github.com/rust-lang/crates.io-index" + dependencies = [ + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + ] + + [[package]] + name = "ansi_term" + version = "0.9.0" + source = "registry+https://github.com/rust-lang/crates.io-index" + + [[package]] + name = "atty" + version = "0.2.10" + source = "registry+https://github.com/rust-lang/crates.io-index" + dependencies = [ + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + ] + + [metadata] + "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" + "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" + "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" + "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" + '') + + (builtins.fromTOML '' + a = [[{ b = true }]] + c = [ [ { d = true } ] ] + e = [[123]] + '') + +] diff --git a/tests/functional/lang/eval-okay-fromjson-escapes.exp b/tests/functional/lang/eval-okay-fromjson-escapes.exp new file mode 100644 index 000000000..add5505a8 --- /dev/null +++ b/tests/functional/lang/eval-okay-fromjson-escapes.exp @@ -0,0 +1 @@ +"quote \" reverse solidus \\ solidus / backspace  formfeed newline \n carriage return \r horizontal tab \t 1 char unicode encoded backspace  1 char unicode encoded e with accent é 2 char unicode encoded s with caron š 3 char unicode encoded rightwards arrow →" diff --git a/tests/functional/lang/eval-okay-fromjson-escapes.nix b/tests/functional/lang/eval-okay-fromjson-escapes.nix new file mode 100644 index 000000000..f00713507 --- /dev/null +++ b/tests/functional/lang/eval-okay-fromjson-escapes.nix @@ -0,0 +1,3 @@ +# This string contains all supported escapes in a JSON string, per json.org +# \b and \f are not supported by Nix +builtins.fromJSON ''"quote \" reverse solidus \\ solidus \/ backspace \b formfeed \f newline \n carriage return \r horizontal tab \t 1 char unicode encoded backspace \u0008 1 char unicode encoded e with accent \u00e9 2 char unicode encoded s with caron \u0161 3 char unicode encoded rightwards arrow \u2192"'' diff --git a/tests/functional/lang/eval-okay-fromjson.exp b/tests/functional/lang/eval-okay-fromjson.exp new file mode 100644 index 000000000..27ba77dda --- /dev/null +++ b/tests/functional/lang/eval-okay-fromjson.exp @@ -0,0 +1 @@ +true diff --git a/tests/functional/lang/eval-okay-fromjson.nix b/tests/functional/lang/eval-okay-fromjson.nix new file mode 100644 index 000000000..4c526b9ae --- /dev/null +++ b/tests/functional/lang/eval-okay-fromjson.nix @@ -0,0 +1,41 @@ +builtins.fromJSON + '' + { + "Video": { + "Title": "The Penguin Chronicles", + "Width": 1920, + "Height": 1080, + "EmbeddedData": [3.14159, 23493,null, true ,false, -10], + "Thumb": { + "Url": "http://www.example.com/video/5678931", + "Width": 200, + "Height": 250 + }, + "Animated" : false, + "IDs": [116, 943, 234, 38793, true ,false,null, -100], + "Escapes": "\"\\\/\t\n\r\t", + "Subtitle" : false, + "Latitude": 37.7668, + "Longitude": -122.3959 + } + } + '' +== + { Video = + { Title = "The Penguin Chronicles"; + Width = 1920; + Height = 1080; + EmbeddedData = [ 3.14159 23493 null true false (0-10) ]; + Thumb = + { Url = "http://www.example.com/video/5678931"; + Width = 200; + Height = 250; + }; + Animated = false; + IDs = [ 116 943 234 38793 true false null (0-100) ]; + Escapes = "\"\\\/\t\n\r\t"; # supported in JSON but not Nix: \b\f + Subtitle = false; + Latitude = 37.7668; + Longitude = -122.3959; + }; + } diff --git a/tests/functional/lang/eval-okay-functionargs.exp b/tests/functional/lang/eval-okay-functionargs.exp new file mode 100644 index 000000000..c1c9f8ffa --- /dev/null +++ b/tests/functional/lang/eval-okay-functionargs.exp @@ -0,0 +1 @@ +[ "stdenv" "fetchurl" "aterm-stdenv" "aterm-stdenv2" "libX11" "libXv" "mplayer-stdenv2.libXv-libX11" "mplayer-stdenv2.libXv-libX11_2" "nix-stdenv-aterm-stdenv" "nix-stdenv2-aterm2-stdenv2" ] diff --git a/tests/functional/lang/eval-okay-functionargs.exp.xml b/tests/functional/lang/eval-okay-functionargs.exp.xml new file mode 100644 index 000000000..651f54c36 --- /dev/null +++ b/tests/functional/lang/eval-okay-functionargs.exp.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/tests/functional/lang/eval-okay-functionargs.nix b/tests/functional/lang/eval-okay-functionargs.nix new file mode 100644 index 000000000..68dca62ee --- /dev/null +++ b/tests/functional/lang/eval-okay-functionargs.nix @@ -0,0 +1,80 @@ +let + + stdenvFun = { }: { name = "stdenv"; }; + stdenv2Fun = { }: { name = "stdenv2"; }; + fetchurlFun = { stdenv }: assert stdenv.name == "stdenv"; { name = "fetchurl"; }; + atermFun = { stdenv, fetchurl }: { name = "aterm-${stdenv.name}"; }; + aterm2Fun = { stdenv, fetchurl }: { name = "aterm2-${stdenv.name}"; }; + nixFun = { stdenv, fetchurl, aterm }: { name = "nix-${stdenv.name}-${aterm.name}"; }; + + mplayerFun = + { stdenv, fetchurl, enableX11 ? false, xorg ? null, enableFoo ? true, foo ? null }: + assert stdenv.name == "stdenv2"; + assert enableX11 -> xorg.libXv.name == "libXv"; + assert enableFoo -> foo != null; + { name = "mplayer-${stdenv.name}.${xorg.libXv.name}-${xorg.libX11.name}"; }; + + makeOverridable = f: origArgs: f origArgs // + { override = newArgs: + makeOverridable f (origArgs // (if builtins.isFunction newArgs then newArgs origArgs else newArgs)); + }; + + callPackage_ = pkgs: f: args: + makeOverridable f ((builtins.intersectAttrs (builtins.functionArgs f) pkgs) // args); + + allPackages = + { overrides ? (pkgs: pkgsPrev: { }) }: + let + callPackage = callPackage_ pkgs; + pkgs = pkgsStd // (overrides pkgs pkgsStd); + pkgsStd = { + inherit pkgs; + stdenv = callPackage stdenvFun { }; + stdenv2 = callPackage stdenv2Fun { }; + fetchurl = callPackage fetchurlFun { }; + aterm = callPackage atermFun { }; + xorg = callPackage xorgFun { }; + mplayer = callPackage mplayerFun { stdenv = pkgs.stdenv2; enableFoo = false; }; + nix = callPackage nixFun { }; + }; + in pkgs; + + libX11Fun = { stdenv, fetchurl }: { name = "libX11"; }; + libX11_2Fun = { stdenv, fetchurl }: { name = "libX11_2"; }; + libXvFun = { stdenv, fetchurl, libX11 }: { name = "libXv"; }; + + xorgFun = + { pkgs }: + let callPackage = callPackage_ (pkgs // pkgs.xorg); in + { + libX11 = callPackage libX11Fun { }; + libXv = callPackage libXvFun { }; + }; + +in + +let + + pkgs = allPackages { }; + + pkgs2 = allPackages { + overrides = pkgs: pkgsPrev: { + stdenv = pkgs.stdenv2; + nix = pkgsPrev.nix.override { aterm = aterm2Fun { inherit (pkgs) stdenv fetchurl; }; }; + xorg = pkgsPrev.xorg // { libX11 = libX11_2Fun { inherit (pkgs) stdenv fetchurl; }; }; + }; + }; + +in + + [ pkgs.stdenv.name + pkgs.fetchurl.name + pkgs.aterm.name + pkgs2.aterm.name + pkgs.xorg.libX11.name + pkgs.xorg.libXv.name + pkgs.mplayer.name + pkgs2.mplayer.name + pkgs.nix.name + pkgs2.nix.name + ] diff --git a/tests/functional/lang/eval-okay-getattrpos-functionargs.exp b/tests/functional/lang/eval-okay-getattrpos-functionargs.exp new file mode 100644 index 000000000..7f9ac40e8 --- /dev/null +++ b/tests/functional/lang/eval-okay-getattrpos-functionargs.exp @@ -0,0 +1 @@ +{ column = 11; file = "eval-okay-getattrpos-functionargs.nix"; line = 2; } diff --git a/tests/functional/lang/eval-okay-getattrpos-functionargs.nix b/tests/functional/lang/eval-okay-getattrpos-functionargs.nix new file mode 100644 index 000000000..11d6bb0e3 --- /dev/null +++ b/tests/functional/lang/eval-okay-getattrpos-functionargs.nix @@ -0,0 +1,4 @@ +let + fun = { foo }: {}; + pos = builtins.unsafeGetAttrPos "foo" (builtins.functionArgs fun); +in { inherit (pos) column line; file = baseNameOf pos.file; } diff --git a/tests/functional/lang/eval-okay-getattrpos-undefined.exp b/tests/functional/lang/eval-okay-getattrpos-undefined.exp new file mode 100644 index 000000000..19765bd50 --- /dev/null +++ b/tests/functional/lang/eval-okay-getattrpos-undefined.exp @@ -0,0 +1 @@ +null diff --git a/tests/functional/lang/eval-okay-getattrpos-undefined.nix b/tests/functional/lang/eval-okay-getattrpos-undefined.nix new file mode 100644 index 000000000..14dd38f77 --- /dev/null +++ b/tests/functional/lang/eval-okay-getattrpos-undefined.nix @@ -0,0 +1 @@ +builtins.unsafeGetAttrPos "abort" builtins diff --git a/tests/functional/lang/eval-okay-getattrpos.exp b/tests/functional/lang/eval-okay-getattrpos.exp new file mode 100644 index 000000000..469249bbc --- /dev/null +++ b/tests/functional/lang/eval-okay-getattrpos.exp @@ -0,0 +1 @@ +{ column = 5; file = "eval-okay-getattrpos.nix"; line = 3; } diff --git a/tests/functional/lang/eval-okay-getattrpos.nix b/tests/functional/lang/eval-okay-getattrpos.nix new file mode 100644 index 000000000..ca6b07961 --- /dev/null +++ b/tests/functional/lang/eval-okay-getattrpos.nix @@ -0,0 +1,6 @@ +let + as = { + foo = "bar"; + }; + pos = builtins.unsafeGetAttrPos "foo" as; +in { inherit (pos) column line; file = baseNameOf pos.file; } diff --git a/tests/functional/lang/eval-okay-getenv.exp b/tests/functional/lang/eval-okay-getenv.exp new file mode 100644 index 000000000..14e24d419 --- /dev/null +++ b/tests/functional/lang/eval-okay-getenv.exp @@ -0,0 +1 @@ +"foobar" diff --git a/tests/functional/lang/eval-okay-getenv.nix b/tests/functional/lang/eval-okay-getenv.nix new file mode 100644 index 000000000..4cfec5f55 --- /dev/null +++ b/tests/functional/lang/eval-okay-getenv.nix @@ -0,0 +1 @@ +builtins.getEnv "TEST_VAR" + (if builtins.getEnv "NO_SUCH_VAR" == "" then "bar" else "bla") diff --git a/tests/functional/lang/eval-okay-groupBy.exp b/tests/functional/lang/eval-okay-groupBy.exp new file mode 100644 index 000000000..bfca5652a --- /dev/null +++ b/tests/functional/lang/eval-okay-groupBy.exp @@ -0,0 +1 @@ +{ "1" = [ 9 ]; "2" = [ 8 ]; "3" = [ 13 29 ]; "4" = [ 3 4 10 11 17 18 ]; "5" = [ 0 23 26 28 ]; "6" = [ 1 12 21 27 30 ]; "7" = [ 7 22 ]; "8" = [ 14 ]; "9" = [ 19 ]; b = [ 16 25 ]; c = [ 24 ]; d = [ 2 ]; e = [ 5 6 15 31 ]; f = [ 20 ]; } diff --git a/tests/functional/lang/eval-okay-groupBy.nix b/tests/functional/lang/eval-okay-groupBy.nix new file mode 100644 index 000000000..862d89dbd --- /dev/null +++ b/tests/functional/lang/eval-okay-groupBy.nix @@ -0,0 +1,5 @@ +with import ./lib.nix; + +builtins.groupBy (n: + builtins.substring 0 1 (builtins.hashString "sha256" (toString n)) +) (range 0 31) diff --git a/tests/functional/lang/eval-okay-hash.exp b/tests/functional/lang/eval-okay-hash.exp new file mode 100644 index 000000000..e69de29bb diff --git a/tests/functional/lang/eval-okay-hashfile.exp b/tests/functional/lang/eval-okay-hashfile.exp new file mode 100644 index 000000000..ff1e8293e --- /dev/null +++ b/tests/functional/lang/eval-okay-hashfile.exp @@ -0,0 +1 @@ +[ "d3b07384d113edec49eaa6238ad5ff00" "0f343b0931126a20f133d67c2b018a3b" "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15" "60cacbf3d72e1e7834203da608037b1bf83b40e8" "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c" "5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef" "0cf9180a764aba863a67b6d72f0918bc131c6772642cb2dce5a34f0a702f9470ddc2bf125c12198b1995c233c34b4afd346c54a2334c350a948a51b6e8b4e6b6" "8efb4f73c5655351c444eb109230c556d39e2c7624e9c11abc9e3fb4b9b9254218cc5085b454a9698d085cfa92198491f07a723be4574adc70617b73eb0b6461" ] diff --git a/tests/functional/lang/eval-okay-hashfile.nix b/tests/functional/lang/eval-okay-hashfile.nix new file mode 100644 index 000000000..aff5a1856 --- /dev/null +++ b/tests/functional/lang/eval-okay-hashfile.nix @@ -0,0 +1,4 @@ +let + paths = [ ./data ./binary-data ]; +in + builtins.concatLists (map (hash: map (builtins.hashFile hash) paths) ["md5" "sha1" "sha256" "sha512"]) diff --git a/tests/functional/lang/eval-okay-hashstring.exp b/tests/functional/lang/eval-okay-hashstring.exp new file mode 100644 index 000000000..d720a082d --- /dev/null +++ b/tests/functional/lang/eval-okay-hashstring.exp @@ -0,0 +1 @@ +[ "d41d8cd98f00b204e9800998ecf8427e" "6c69ee7f211c640419d5366cc076ae46" "bb3438fbabd460ea6dbd27d153e2233b" "da39a3ee5e6b4b0d3255bfef95601890afd80709" "cd54e8568c1b37cf1e5badb0779bcbf382212189" "6d12e10b1d331dad210e47fd25d4f260802b7e77" "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" "900a4469df00ccbfd0c145c6d1e4b7953dd0afafadd7534e3a4019e8d38fc663" "ad0387b3bd8652f730ca46d25f9c170af0fd589f42e7f23f5a9e6412d97d7e56" "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" "9d0886f8c6b389398a16257bc79780fab9831c7fc11c8ab07fa732cb7b348feade382f92617c9c5305fefba0af02ab5fd39a587d330997ff5bd0db19f7666653" "21644b72aa259e5a588cd3afbafb1d4310f4889680f6c83b9d531596a5a284f34dbebff409d23bcc86aee6bad10c891606f075c6f4755cb536da27db5693f3a7" ] diff --git a/tests/functional/lang/eval-okay-hashstring.nix b/tests/functional/lang/eval-okay-hashstring.nix new file mode 100644 index 000000000..b0f62b245 --- /dev/null +++ b/tests/functional/lang/eval-okay-hashstring.nix @@ -0,0 +1,4 @@ +let + strings = [ "" "text 1" "text 2" ]; +in + builtins.concatLists (map (hash: map (builtins.hashString hash) strings) ["md5" "sha1" "sha256" "sha512"]) diff --git a/tests/functional/lang/eval-okay-if.exp b/tests/functional/lang/eval-okay-if.exp new file mode 100644 index 000000000..00750edc0 --- /dev/null +++ b/tests/functional/lang/eval-okay-if.exp @@ -0,0 +1 @@ +3 diff --git a/tests/functional/lang/eval-okay-if.nix b/tests/functional/lang/eval-okay-if.nix new file mode 100644 index 000000000..23e4c74d5 --- /dev/null +++ b/tests/functional/lang/eval-okay-if.nix @@ -0,0 +1 @@ +if "foo" != "f" + "oo" then 1 else if false then 2 else 3 diff --git a/tests/functional/lang/eval-okay-import.exp b/tests/functional/lang/eval-okay-import.exp new file mode 100644 index 000000000..c508125b5 --- /dev/null +++ b/tests/functional/lang/eval-okay-import.exp @@ -0,0 +1 @@ +[ 1 2 3 4 5 6 7 8 9 10 ] diff --git a/tests/functional/lang/eval-okay-import.nix b/tests/functional/lang/eval-okay-import.nix new file mode 100644 index 000000000..0b18d9413 --- /dev/null +++ b/tests/functional/lang/eval-okay-import.nix @@ -0,0 +1,11 @@ +let + + overrides = { + import = fn: scopedImport overrides fn; + + scopedImport = attrs: fn: scopedImport (overrides // attrs) fn; + + builtins = builtins // overrides; + } // import ./lib.nix; + +in scopedImport overrides ./imported.nix diff --git a/tests/functional/lang/eval-okay-ind-string.exp b/tests/functional/lang/eval-okay-ind-string.exp new file mode 100644 index 000000000..7862331fa --- /dev/null +++ b/tests/functional/lang/eval-okay-ind-string.exp @@ -0,0 +1 @@ +"This is an indented multi-line string\nliteral. An amount of whitespace at\nthe start of each line matching the minimum\nindentation of all lines in the string\nliteral together will be removed. Thus,\nin this case four spaces will be\nstripped from each line, even though\n THIS LINE is indented six spaces.\n\nAlso, empty lines don't count in the\ndetermination of the indentation level (the\nprevious empty line has indentation 0, but\nit doesn't matter).\nIf the string starts with whitespace\n followed by a newline, it's stripped, but\n that's not the case here. Two spaces are\n stripped because of the \" \" at the start. \nThis line is indented\na bit further.\nAnti-quotations, like so, are\nalso allowed.\n The \\ is not special here.\n' can be followed by any character except another ', e.g. 'x'.\nLikewise for $, e.g. $$ or $varName.\nBut ' followed by ' is special, as is $ followed by {.\nIf you want them, use anti-quotations: '', \${.\n Tabs are not interpreted as whitespace (since we can't guess\n what tab settings are intended), so don't use them.\n\tThis line starts with a space and a tab, so only one\n space will be stripped from each line.\nAlso note that if the last line (just before the closing ' ')\nconsists only of whitespace, it's ignored. But here there is\nsome non-whitespace stuff, so the line isn't removed. \nThis shows a hacky way to preserve an empty line after the start.\nBut there's no reason to do so: you could just repeat the empty\nline.\n Similarly you can force an indentation level,\n in this case to 2 spaces. This works because the anti-quote\n is significant (not whitespace).\nstart on network-interfaces\n\nstart script\n\n rm -f /var/run/opengl-driver\n ln -sf 123 /var/run/opengl-driver\n\n rm -f /var/log/slim.log\n \nend script\n\nenv SLIM_CFGFILE=abc\nenv SLIM_THEMESDIR=def\nenv FONTCONFIG_FILE=/etc/fonts/fonts.conf \t\t\t\t# !!! cleanup\nenv XKB_BINDIR=foo/bin \t\t\t\t# Needed for the Xkb extension.\nenv LD_LIBRARY_PATH=libX11/lib:libXext/lib:/usr/lib/ # related to xorg-sys-opengl - needed to load libglx for (AI)GLX support (for compiz)\n\nenv XORG_DRI_DRIVER_PATH=nvidiaDrivers/X11R6/lib/modules/drivers/ \n\nexec slim/bin/slim\nEscaping of ' followed by ': ''\nEscaping of $ followed by {: \${\nAnd finally to interpret \\n etc. as in a string: \n, \r, \t.\nfoo\n'bla'\nbar\ncut -d $'\\t' -f 1\nending dollar $$\n" diff --git a/tests/functional/lang/eval-okay-ind-string.nix b/tests/functional/lang/eval-okay-ind-string.nix new file mode 100644 index 000000000..95d59b508 --- /dev/null +++ b/tests/functional/lang/eval-okay-ind-string.nix @@ -0,0 +1,128 @@ +let + + s1 = '' + This is an indented multi-line string + literal. An amount of whitespace at + the start of each line matching the minimum + indentation of all lines in the string + literal together will be removed. Thus, + in this case four spaces will be + stripped from each line, even though + THIS LINE is indented six spaces. + + Also, empty lines don't count in the + determination of the indentation level (the + previous empty line has indentation 0, but + it doesn't matter). + ''; + + s2 = '' If the string starts with whitespace + followed by a newline, it's stripped, but + that's not the case here. Two spaces are + stripped because of the " " at the start. + ''; + + s3 = '' + This line is indented + a bit further. + ''; # indentation of last line doesn't count if it's empty + + s4 = '' + Anti-quotations, like ${if true then "so" else "not so"}, are + also allowed. + ''; + + s5 = '' + The \ is not special here. + ' can be followed by any character except another ', e.g. 'x'. + Likewise for $, e.g. $$ or $varName. + But ' followed by ' is special, as is $ followed by {. + If you want them, use anti-quotations: ${"''"}, ${"\${"}. + ''; + + s6 = '' + Tabs are not interpreted as whitespace (since we can't guess + what tab settings are intended), so don't use them. + This line starts with a space and a tab, so only one + space will be stripped from each line. + ''; + + s7 = '' + Also note that if the last line (just before the closing ' ') + consists only of whitespace, it's ignored. But here there is + some non-whitespace stuff, so the line isn't removed. ''; + + s8 = '' ${""} + This shows a hacky way to preserve an empty line after the start. + But there's no reason to do so: you could just repeat the empty + line. + ''; + + s9 = '' + ${""} Similarly you can force an indentation level, + in this case to 2 spaces. This works because the anti-quote + is significant (not whitespace). + ''; + + s10 = '' + ''; + + s11 = ''''; + + s12 = '' ''; + + s13 = '' + start on network-interfaces + + start script + + rm -f /var/run/opengl-driver + ${if true + then "ln -sf 123 /var/run/opengl-driver" + else if true + then "ln -sf 456 /var/run/opengl-driver" + else "" + } + + rm -f /var/log/slim.log + + end script + + env SLIM_CFGFILE=${"abc"} + env SLIM_THEMESDIR=${"def"} + env FONTCONFIG_FILE=/etc/fonts/fonts.conf # !!! cleanup + env XKB_BINDIR=${"foo"}/bin # Needed for the Xkb extension. + env LD_LIBRARY_PATH=${"libX11"}/lib:${"libXext"}/lib:/usr/lib/ # related to xorg-sys-opengl - needed to load libglx for (AI)GLX support (for compiz) + + ${if true + then "env XORG_DRI_DRIVER_PATH=${"nvidiaDrivers"}/X11R6/lib/modules/drivers/" + else if true + then "env XORG_DRI_DRIVER_PATH=${"mesa"}/lib/modules/dri" + else "" + } + + exec ${"slim"}/bin/slim + ''; + + s14 = '' + Escaping of ' followed by ': ''' + Escaping of $ followed by {: ''${ + And finally to interpret \n etc. as in a string: ''\n, ''\r, ''\t. + ''; + + # Regression test: string interpolation in '${x}' should work, but didn't. + s15 = let x = "bla"; in '' + foo + '${x}' + bar + ''; + + # Regression test: accept $'. + s16 = '' + cut -d $'\t' -f 1 + ''; + + # Accept dollars at end of strings + s17 = ''ending dollar $'' + ''$'' + "\n"; + +in s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10 + s11 + s12 + s13 + s14 + s15 + s16 + s17 diff --git a/tests/functional/lang/eval-okay-intersectAttrs.exp b/tests/functional/lang/eval-okay-intersectAttrs.exp new file mode 100644 index 000000000..50445bc0e --- /dev/null +++ b/tests/functional/lang/eval-okay-intersectAttrs.exp @@ -0,0 +1 @@ +[ { } { a = 1; } { a = 1; } { a = "a"; } { m = 1; } { m = "m"; } { n = 1; } { n = "n"; } { n = 1; p = 2; } { n = "n"; p = "p"; } { n = 1; p = 2; } { n = "n"; p = "p"; } { a = "a"; b = "b"; c = "c"; d = "d"; e = "e"; f = "f"; g = "g"; h = "h"; i = "i"; j = "j"; k = "k"; l = "l"; m = "m"; n = "n"; o = "o"; p = "p"; q = "q"; r = "r"; s = "s"; t = "t"; u = "u"; v = "v"; w = "w"; x = "x"; y = "y"; z = "z"; } true ] diff --git a/tests/functional/lang/eval-okay-intersectAttrs.nix b/tests/functional/lang/eval-okay-intersectAttrs.nix new file mode 100644 index 000000000..39d49938c --- /dev/null +++ b/tests/functional/lang/eval-okay-intersectAttrs.nix @@ -0,0 +1,50 @@ +let + alphabet = + { a = "a"; + b = "b"; + c = "c"; + d = "d"; + e = "e"; + f = "f"; + g = "g"; + h = "h"; + i = "i"; + j = "j"; + k = "k"; + l = "l"; + m = "m"; + n = "n"; + o = "o"; + p = "p"; + q = "q"; + r = "r"; + s = "s"; + t = "t"; + u = "u"; + v = "v"; + w = "w"; + x = "x"; + y = "y"; + z = "z"; + }; + foo = { + inherit (alphabet) f o b a r z q u x; + aa = throw "aa"; + }; + alphabetFail = builtins.mapAttrs throw alphabet; +in +[ (builtins.intersectAttrs { a = abort "l1"; } { b = abort "r1"; }) + (builtins.intersectAttrs { a = abort "l2"; } { a = 1; }) + (builtins.intersectAttrs alphabetFail { a = 1; }) + (builtins.intersectAttrs { a = abort "laa"; } alphabet) + (builtins.intersectAttrs alphabetFail { m = 1; }) + (builtins.intersectAttrs { m = abort "lam"; } alphabet) + (builtins.intersectAttrs alphabetFail { n = 1; }) + (builtins.intersectAttrs { n = abort "lan"; } alphabet) + (builtins.intersectAttrs alphabetFail { n = 1; p = 2; }) + (builtins.intersectAttrs { n = abort "lan2"; p = abort "lap"; } alphabet) + (builtins.intersectAttrs alphabetFail { n = 1; p = 2; }) + (builtins.intersectAttrs { n = abort "lan2"; p = abort "lap"; } alphabet) + (builtins.intersectAttrs alphabetFail alphabet) + (builtins.intersectAttrs alphabet foo == builtins.intersectAttrs foo alphabet) +] diff --git a/tests/functional/lang/eval-okay-let.exp b/tests/functional/lang/eval-okay-let.exp new file mode 100644 index 000000000..14e24d419 --- /dev/null +++ b/tests/functional/lang/eval-okay-let.exp @@ -0,0 +1 @@ +"foobar" diff --git a/tests/functional/lang/eval-okay-let.nix b/tests/functional/lang/eval-okay-let.nix new file mode 100644 index 000000000..fe118c528 --- /dev/null +++ b/tests/functional/lang/eval-okay-let.nix @@ -0,0 +1,5 @@ +let { + x = "foo"; + y = "bar"; + body = x + y; +} diff --git a/tests/functional/lang/eval-okay-list.exp b/tests/functional/lang/eval-okay-list.exp new file mode 100644 index 000000000..f784f26d8 --- /dev/null +++ b/tests/functional/lang/eval-okay-list.exp @@ -0,0 +1 @@ +"foobarblatest" diff --git a/tests/functional/lang/eval-okay-list.nix b/tests/functional/lang/eval-okay-list.nix new file mode 100644 index 000000000..d433bcf90 --- /dev/null +++ b/tests/functional/lang/eval-okay-list.nix @@ -0,0 +1,7 @@ +with import ./lib.nix; + +let { + + body = concat ["foo" "bar" "bla" "test"]; + +} \ No newline at end of file diff --git a/tests/functional/lang/eval-okay-listtoattrs.exp b/tests/functional/lang/eval-okay-listtoattrs.exp new file mode 100644 index 000000000..74abef7bc --- /dev/null +++ b/tests/functional/lang/eval-okay-listtoattrs.exp @@ -0,0 +1 @@ +"AAbar" diff --git a/tests/functional/lang/eval-okay-listtoattrs.nix b/tests/functional/lang/eval-okay-listtoattrs.nix new file mode 100644 index 000000000..4186e029b --- /dev/null +++ b/tests/functional/lang/eval-okay-listtoattrs.nix @@ -0,0 +1,11 @@ +# this test shows how to use listToAttrs and that evaluation is still lazy (throw isn't called) +with import ./lib.nix; + +let + asi = name: value : { inherit name value; }; + list = [ ( asi "a" "A" ) ( asi "b" "B" ) ]; + a = builtins.listToAttrs list; + b = builtins.listToAttrs ( list ++ list ); + r = builtins.listToAttrs [ (asi "result" [ a b ]) ( asi "throw" (throw "this should not be thrown")) ]; + x = builtins.listToAttrs [ (asi "foo" "bar") (asi "foo" "bla") ]; +in concat (map (x: x.a) r.result) + x.foo diff --git a/tests/functional/lang/eval-okay-logic.exp b/tests/functional/lang/eval-okay-logic.exp new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/tests/functional/lang/eval-okay-logic.exp @@ -0,0 +1 @@ +1 diff --git a/tests/functional/lang/eval-okay-logic.nix b/tests/functional/lang/eval-okay-logic.nix new file mode 100644 index 000000000..fbb127944 --- /dev/null +++ b/tests/functional/lang/eval-okay-logic.nix @@ -0,0 +1 @@ +assert !false && (true || false) -> true; 1 diff --git a/tests/functional/lang/eval-okay-map.exp b/tests/functional/lang/eval-okay-map.exp new file mode 100644 index 000000000..dbb64f717 --- /dev/null +++ b/tests/functional/lang/eval-okay-map.exp @@ -0,0 +1 @@ +"foobarblabarxyzzybar" diff --git a/tests/functional/lang/eval-okay-map.nix b/tests/functional/lang/eval-okay-map.nix new file mode 100644 index 000000000..a76c1d811 --- /dev/null +++ b/tests/functional/lang/eval-okay-map.nix @@ -0,0 +1,3 @@ +with import ./lib.nix; + +concat (map (x: x + "bar") [ "foo" "bla" "xyzzy" ]) \ No newline at end of file diff --git a/tests/functional/lang/eval-okay-mapattrs.exp b/tests/functional/lang/eval-okay-mapattrs.exp new file mode 100644 index 000000000..3f113f17b --- /dev/null +++ b/tests/functional/lang/eval-okay-mapattrs.exp @@ -0,0 +1 @@ +{ x = "x-foo"; y = "y-bar"; } diff --git a/tests/functional/lang/eval-okay-mapattrs.nix b/tests/functional/lang/eval-okay-mapattrs.nix new file mode 100644 index 000000000..f075b6275 --- /dev/null +++ b/tests/functional/lang/eval-okay-mapattrs.nix @@ -0,0 +1,3 @@ +with import ./lib.nix; + +builtins.mapAttrs (name: value: name + "-" + value) { x = "foo"; y = "bar"; } diff --git a/tests/functional/lang/eval-okay-merge-dynamic-attrs.exp b/tests/functional/lang/eval-okay-merge-dynamic-attrs.exp new file mode 100644 index 000000000..157d677ce --- /dev/null +++ b/tests/functional/lang/eval-okay-merge-dynamic-attrs.exp @@ -0,0 +1 @@ +{ set1 = { a = 1; b = 2; }; set2 = { a = 1; b = 2; }; set3 = { a = 1; b = 2; }; set4 = { a = 1; b = 2; }; } diff --git a/tests/functional/lang/eval-okay-merge-dynamic-attrs.nix b/tests/functional/lang/eval-okay-merge-dynamic-attrs.nix new file mode 100644 index 000000000..f459a554f --- /dev/null +++ b/tests/functional/lang/eval-okay-merge-dynamic-attrs.nix @@ -0,0 +1,13 @@ +{ + set1 = { a = 1; }; + set1 = { "${"b" + ""}" = 2; }; + + set2 = { "${"b" + ""}" = 2; }; + set2 = { a = 1; }; + + set3.a = 1; + set3."${"b" + ""}" = 2; + + set4."${"b" + ""}" = 2; + set4.a = 1; +} diff --git a/tests/functional/lang/eval-okay-nested-with.exp b/tests/functional/lang/eval-okay-nested-with.exp new file mode 100644 index 000000000..0cfbf0888 --- /dev/null +++ b/tests/functional/lang/eval-okay-nested-with.exp @@ -0,0 +1 @@ +2 diff --git a/tests/functional/lang/eval-okay-nested-with.nix b/tests/functional/lang/eval-okay-nested-with.nix new file mode 100644 index 000000000..ba9d79aa7 --- /dev/null +++ b/tests/functional/lang/eval-okay-nested-with.nix @@ -0,0 +1,3 @@ +with { x = 1; }; +with { x = 2; }; +x diff --git a/tests/functional/lang/eval-okay-new-let.exp b/tests/functional/lang/eval-okay-new-let.exp new file mode 100644 index 000000000..f98b38807 --- /dev/null +++ b/tests/functional/lang/eval-okay-new-let.exp @@ -0,0 +1 @@ +"xyzzyfoobar" diff --git a/tests/functional/lang/eval-okay-new-let.nix b/tests/functional/lang/eval-okay-new-let.nix new file mode 100644 index 000000000..738123141 --- /dev/null +++ b/tests/functional/lang/eval-okay-new-let.nix @@ -0,0 +1,14 @@ +let + + f = z: + + let + x = "foo"; + y = "bar"; + body = 1; # compat test + in + z + x + y; + + arg = "xyzzy"; + +in f arg diff --git a/tests/functional/lang/eval-okay-null-dynamic-attrs.exp b/tests/functional/lang/eval-okay-null-dynamic-attrs.exp new file mode 100644 index 000000000..27ba77dda --- /dev/null +++ b/tests/functional/lang/eval-okay-null-dynamic-attrs.exp @@ -0,0 +1 @@ +true diff --git a/tests/functional/lang/eval-okay-null-dynamic-attrs.nix b/tests/functional/lang/eval-okay-null-dynamic-attrs.nix new file mode 100644 index 000000000..b060c0bc9 --- /dev/null +++ b/tests/functional/lang/eval-okay-null-dynamic-attrs.nix @@ -0,0 +1 @@ +{ ${null} = true; } == {} diff --git a/tests/functional/lang/eval-okay-overrides.exp b/tests/functional/lang/eval-okay-overrides.exp new file mode 100644 index 000000000..0cfbf0888 --- /dev/null +++ b/tests/functional/lang/eval-okay-overrides.exp @@ -0,0 +1 @@ +2 diff --git a/tests/functional/lang/eval-okay-overrides.nix b/tests/functional/lang/eval-okay-overrides.nix new file mode 100644 index 000000000..719bdc9c0 --- /dev/null +++ b/tests/functional/lang/eval-okay-overrides.nix @@ -0,0 +1,9 @@ +let + + overrides = { a = 2; b = 3; }; + +in (rec { + __overrides = overrides; + x = a; + a = 1; +}).x diff --git a/tests/functional/lang/eval-okay-parse-flake-ref.exp b/tests/functional/lang/eval-okay-parse-flake-ref.exp new file mode 100644 index 000000000..fc17ba085 --- /dev/null +++ b/tests/functional/lang/eval-okay-parse-flake-ref.exp @@ -0,0 +1 @@ +{ dir = "lib"; owner = "NixOS"; ref = "23.05"; repo = "nixpkgs"; type = "github"; } diff --git a/tests/functional/lang/eval-okay-parse-flake-ref.nix b/tests/functional/lang/eval-okay-parse-flake-ref.nix new file mode 100644 index 000000000..db4ed2742 --- /dev/null +++ b/tests/functional/lang/eval-okay-parse-flake-ref.nix @@ -0,0 +1 @@ + builtins.parseFlakeRef "github:NixOS/nixpkgs/23.05?dir=lib" diff --git a/tests/functional/lang/eval-okay-partition.exp b/tests/functional/lang/eval-okay-partition.exp new file mode 100644 index 000000000..cd8b8b020 --- /dev/null +++ b/tests/functional/lang/eval-okay-partition.exp @@ -0,0 +1 @@ +{ right = [ 0 2 4 6 8 10 100 102 104 106 108 110 ]; wrong = [ 1 3 5 7 9 101 103 105 107 109 ]; } diff --git a/tests/functional/lang/eval-okay-partition.nix b/tests/functional/lang/eval-okay-partition.nix new file mode 100644 index 000000000..846d2ce49 --- /dev/null +++ b/tests/functional/lang/eval-okay-partition.nix @@ -0,0 +1,5 @@ +with import ./lib.nix; + +builtins.partition + (x: x / 2 * 2 == x) + (builtins.concatLists [ (range 0 10) (range 100 110) ]) diff --git a/tests/functional/lang/eval-okay-path-string-interpolation.exp b/tests/functional/lang/eval-okay-path-string-interpolation.exp new file mode 100644 index 000000000..5b8ea0243 --- /dev/null +++ b/tests/functional/lang/eval-okay-path-string-interpolation.exp @@ -0,0 +1 @@ +{ absolute = /foo; expr = /pwd/lang/foo/bar; home = /fake-home/foo; notfirst = /pwd/lang/bar/foo; simple = /pwd/lang/foo; slashes = /foo/bar; surrounded = /pwd/lang/a-foo-b; } diff --git a/tests/functional/lang/eval-okay-path-string-interpolation.nix b/tests/functional/lang/eval-okay-path-string-interpolation.nix new file mode 100644 index 000000000..497d7c1c7 --- /dev/null +++ b/tests/functional/lang/eval-okay-path-string-interpolation.nix @@ -0,0 +1,12 @@ +let + foo = "foo"; +in +{ + simple = ./${foo}; + surrounded = ./a-${foo}-b; + absolute = /${foo}; + expr = ./${foo + "/bar"}; + home = ~/${foo}; + notfirst = ./bar/${foo}; + slashes = /${foo}/${"bar"}; +} diff --git a/tests/functional/lang/eval-okay-path.exp b/tests/functional/lang/eval-okay-path.exp new file mode 100644 index 000000000..3ce7f8283 --- /dev/null +++ b/tests/functional/lang/eval-okay-path.exp @@ -0,0 +1 @@ +"/nix/store/ya937r4ydw0l6kayq8jkyqaips9c75jm-output" diff --git a/tests/functional/lang/eval-okay-path.nix b/tests/functional/lang/eval-okay-path.nix new file mode 100644 index 000000000..e67168cf3 --- /dev/null +++ b/tests/functional/lang/eval-okay-path.nix @@ -0,0 +1,7 @@ +builtins.path + { path = ./.; + filter = path: _: baseNameOf path == "data"; + recursive = true; + sha256 = "1yhm3gwvg5a41yylymgblsclk95fs6jy72w0wv925mmidlhcq4sw"; + name = "output"; + } diff --git a/tests/functional/lang/eval-okay-pathexists.exp b/tests/functional/lang/eval-okay-pathexists.exp new file mode 100644 index 000000000..27ba77dda --- /dev/null +++ b/tests/functional/lang/eval-okay-pathexists.exp @@ -0,0 +1 @@ +true diff --git a/tests/functional/lang/eval-okay-pathexists.nix b/tests/functional/lang/eval-okay-pathexists.nix new file mode 100644 index 000000000..c5e7a62de --- /dev/null +++ b/tests/functional/lang/eval-okay-pathexists.nix @@ -0,0 +1,29 @@ +builtins.pathExists (./lib.nix) +&& builtins.pathExists (builtins.toPath ./lib.nix) +&& builtins.pathExists (builtins.toString ./lib.nix) +&& !builtins.pathExists (builtins.toString ./lib.nix + "/") +&& !builtins.pathExists (builtins.toString ./lib.nix + "/.") +# FIXME +# && !builtins.pathExists (builtins.toString ./lib.nix + "/..") +# && !builtins.pathExists (builtins.toString ./lib.nix + "/a/..") +# && !builtins.pathExists (builtins.toString ./lib.nix + "/../lib.nix") +&& !builtins.pathExists (builtins.toString ./lib.nix + "/./") +&& !builtins.pathExists (builtins.toString ./lib.nix + "/./.") +&& builtins.pathExists (builtins.toString ./.. + "/lang/lib.nix") +&& !builtins.pathExists (builtins.toString ./.. + "lang/lib.nix") +&& builtins.pathExists (builtins.toString ./. + "/../lang/lib.nix") +&& builtins.pathExists (builtins.toString ./. + "/../lang/./lib.nix") +&& builtins.pathExists (builtins.toString ./.) +&& builtins.pathExists (builtins.toString ./. + "/") +&& builtins.pathExists (builtins.toString ./. + "/../lang") +&& builtins.pathExists (builtins.toString ./. + "/../lang/") +&& builtins.pathExists (builtins.toString ./. + "/../lang/.") +&& builtins.pathExists (builtins.toString ./. + "/../lang/./") +&& builtins.pathExists (builtins.toString ./. + "/../lang//./") +&& builtins.pathExists (builtins.toString ./. + "/../lang/..") +&& builtins.pathExists (builtins.toString ./. + "/../lang/../") +&& builtins.pathExists (builtins.toString ./. + "/../lang/..//") +&& builtins.pathExists (builtins.toPath (builtins.toString ./lib.nix)) +&& !builtins.pathExists (builtins.toPath (builtins.toString ./bla.nix)) +&& builtins.pathExists ./lib.nix +&& !builtins.pathExists ./bla.nix diff --git a/tests/functional/lang/eval-okay-patterns.exp b/tests/functional/lang/eval-okay-patterns.exp new file mode 100644 index 000000000..a4304010f --- /dev/null +++ b/tests/functional/lang/eval-okay-patterns.exp @@ -0,0 +1 @@ +"abcxyzDDDDEFijk" diff --git a/tests/functional/lang/eval-okay-patterns.nix b/tests/functional/lang/eval-okay-patterns.nix new file mode 100644 index 000000000..96fd25a01 --- /dev/null +++ b/tests/functional/lang/eval-okay-patterns.nix @@ -0,0 +1,16 @@ +let + + f = args@{x, y, z}: x + args.y + z; + + g = {x, y, z}@args: f args; + + h = {x ? "d", y ? x, z ? args.x}@args: x + y + z; + + j = {x, y, z, ...}: x + y + z; + +in + f {x = "a"; y = "b"; z = "c";} + + g {x = "x"; y = "y"; z = "z";} + + h {x = "D";} + + h {x = "D"; y = "E"; z = "F";} + + j {x = "i"; y = "j"; z = "k"; bla = "bla"; foo = "bar";} diff --git a/tests/functional/lang/eval-okay-print.err.exp b/tests/functional/lang/eval-okay-print.err.exp new file mode 100644 index 000000000..3fc99be3e --- /dev/null +++ b/tests/functional/lang/eval-okay-print.err.exp @@ -0,0 +1 @@ +trace: [ ] diff --git a/tests/functional/lang/eval-okay-print.exp b/tests/functional/lang/eval-okay-print.exp new file mode 100644 index 000000000..0d960fb70 --- /dev/null +++ b/tests/functional/lang/eval-okay-print.exp @@ -0,0 +1 @@ +[ null [ [ «repeated» ] ] ] diff --git a/tests/functional/lang/eval-okay-print.nix b/tests/functional/lang/eval-okay-print.nix new file mode 100644 index 000000000..d36ba4da3 --- /dev/null +++ b/tests/functional/lang/eval-okay-print.nix @@ -0,0 +1 @@ +with builtins; trace [(1+1)] [ null toString (deepSeq "x") (a: a) (let x=[x]; in x) ] diff --git a/tests/functional/lang/eval-okay-readDir.exp b/tests/functional/lang/eval-okay-readDir.exp new file mode 100644 index 000000000..6413f6d4f --- /dev/null +++ b/tests/functional/lang/eval-okay-readDir.exp @@ -0,0 +1 @@ +{ bar = "regular"; foo = "directory"; ldir = "symlink"; linked = "symlink"; } diff --git a/tests/functional/lang/eval-okay-readDir.nix b/tests/functional/lang/eval-okay-readDir.nix new file mode 100644 index 000000000..a7ec9292a --- /dev/null +++ b/tests/functional/lang/eval-okay-readDir.nix @@ -0,0 +1 @@ +builtins.readDir ./readDir diff --git a/tests/functional/lang/eval-okay-readFileType.exp b/tests/functional/lang/eval-okay-readFileType.exp new file mode 100644 index 000000000..6413f6d4f --- /dev/null +++ b/tests/functional/lang/eval-okay-readFileType.exp @@ -0,0 +1 @@ +{ bar = "regular"; foo = "directory"; ldir = "symlink"; linked = "symlink"; } diff --git a/tests/functional/lang/eval-okay-readFileType.nix b/tests/functional/lang/eval-okay-readFileType.nix new file mode 100644 index 000000000..174fb6c3a --- /dev/null +++ b/tests/functional/lang/eval-okay-readFileType.nix @@ -0,0 +1,6 @@ +{ + bar = builtins.readFileType ./readDir/bar; + foo = builtins.readFileType ./readDir/foo; + linked = builtins.readFileType ./readDir/linked; + ldir = builtins.readFileType ./readDir/ldir; +} diff --git a/tests/functional/lang/eval-okay-readfile.exp b/tests/functional/lang/eval-okay-readfile.exp new file mode 100644 index 000000000..a2c87d0c4 --- /dev/null +++ b/tests/functional/lang/eval-okay-readfile.exp @@ -0,0 +1 @@ +"builtins.readFile ./eval-okay-readfile.nix\n" diff --git a/tests/functional/lang/eval-okay-readfile.nix b/tests/functional/lang/eval-okay-readfile.nix new file mode 100644 index 000000000..82f7cb174 --- /dev/null +++ b/tests/functional/lang/eval-okay-readfile.nix @@ -0,0 +1 @@ +builtins.readFile ./eval-okay-readfile.nix diff --git a/tests/functional/lang/eval-okay-redefine-builtin.exp b/tests/functional/lang/eval-okay-redefine-builtin.exp new file mode 100644 index 000000000..c508d5366 --- /dev/null +++ b/tests/functional/lang/eval-okay-redefine-builtin.exp @@ -0,0 +1 @@ +false diff --git a/tests/functional/lang/eval-okay-redefine-builtin.nix b/tests/functional/lang/eval-okay-redefine-builtin.nix new file mode 100644 index 000000000..df9fc3f37 --- /dev/null +++ b/tests/functional/lang/eval-okay-redefine-builtin.nix @@ -0,0 +1,3 @@ +let + throw = abort "Error!"; +in (builtins.tryEval ).success diff --git a/tests/functional/lang/eval-okay-regex-match.exp b/tests/functional/lang/eval-okay-regex-match.exp new file mode 100644 index 000000000..27ba77dda --- /dev/null +++ b/tests/functional/lang/eval-okay-regex-match.exp @@ -0,0 +1 @@ +true diff --git a/tests/functional/lang/eval-okay-regex-match.nix b/tests/functional/lang/eval-okay-regex-match.nix new file mode 100644 index 000000000..273e25907 --- /dev/null +++ b/tests/functional/lang/eval-okay-regex-match.nix @@ -0,0 +1,29 @@ +with builtins; + +let + + matches = pat: s: match pat s != null; + + splitFN = match "((.*)/)?([^/]*)\\.(nix|cc)"; + +in + +assert matches "foobar" "foobar"; +assert matches "fo*" "f"; +assert !matches "fo+" "f"; +assert matches "fo*" "fo"; +assert matches "fo*" "foo"; +assert matches "fo+" "foo"; +assert matches "fo{1,2}" "foo"; +assert !matches "fo{1,2}" "fooo"; +assert !matches "fo*" "foobar"; +assert matches "[[:space:]]+([^[:space:]]+)[[:space:]]+" " foo "; +assert !matches "[[:space:]]+([[:upper:]]+)[[:space:]]+" " foo "; + +assert match "(.*)\\.nix" "foobar.nix" == [ "foobar" ]; +assert match "[[:space:]]+([[:upper:]]+)[[:space:]]+" " FOO " == [ "FOO" ]; + +assert splitFN "/path/to/foobar.nix" == [ "/path/to/" "/path/to" "foobar" "nix" ]; +assert splitFN "foobar.cc" == [ null null "foobar" "cc" ]; + +true diff --git a/tests/functional/lang/eval-okay-regex-split.exp b/tests/functional/lang/eval-okay-regex-split.exp new file mode 100644 index 000000000..27ba77dda --- /dev/null +++ b/tests/functional/lang/eval-okay-regex-split.exp @@ -0,0 +1 @@ +true diff --git a/tests/functional/lang/eval-okay-regex-split.nix b/tests/functional/lang/eval-okay-regex-split.nix new file mode 100644 index 000000000..0073e0577 --- /dev/null +++ b/tests/functional/lang/eval-okay-regex-split.nix @@ -0,0 +1,48 @@ +with builtins; + +# Non capturing regex returns empty lists +assert split "foobar" "foobar" == ["" [] ""]; +assert split "fo*" "f" == ["" [] ""]; +assert split "fo+" "f" == ["f"]; +assert split "fo*" "fo" == ["" [] ""]; +assert split "fo*" "foo" == ["" [] ""]; +assert split "fo+" "foo" == ["" [] ""]; +assert split "fo{1,2}" "foo" == ["" [] ""]; +assert split "fo{1,2}" "fooo" == ["" [] "o"]; +assert split "fo*" "foobar" == ["" [] "bar"]; + +# Capturing regex returns a list of sub-matches +assert split "(fo*)" "f" == ["" ["f"] ""]; +assert split "(fo+)" "f" == ["f"]; +assert split "(fo*)" "fo" == ["" ["fo"] ""]; +assert split "(f)(o*)" "f" == ["" ["f" ""] ""]; +assert split "(f)(o*)" "foo" == ["" ["f" "oo"] ""]; +assert split "(fo+)" "foo" == ["" ["foo"] ""]; +assert split "(fo{1,2})" "foo" == ["" ["foo"] ""]; +assert split "(fo{1,2})" "fooo" == ["" ["foo"] "o"]; +assert split "(fo*)" "foobar" == ["" ["foo"] "bar"]; + +# Matches are greedy. +assert split "(o+)" "oooofoooo" == ["" ["oooo"] "f" ["oooo"] ""]; + +# Matches multiple times. +assert split "(b)" "foobarbaz" == ["foo" ["b"] "ar" ["b"] "az"]; + +# Split large strings containing newlines. null are inserted when a +# pattern within the current did not match anything. +assert split "[[:space:]]+|([',.!?])" '' + Nix Rocks! + That's why I use it. +'' == [ + "Nix" [ null ] "Rocks" ["!"] "" [ null ] + "That" ["'"] "s" [ null ] "why" [ null ] "I" [ null ] "use" [ null ] "it" ["."] "" [ null ] + "" +]; + +# Documentation examples +assert split "(a)b" "abc" == [ "" [ "a" ] "c" ]; +assert split "([ac])" "abc" == [ "" [ "a" ] "b" [ "c" ] "" ]; +assert split "(a)|(c)" "abc" == [ "" [ "a" null ] "b" [ null "c" ] "" ]; +assert split "([[:upper:]]+)" " FOO " == [ " " [ "FOO" ] " " ]; + +true diff --git a/tests/functional/lang/eval-okay-regression-20220122.exp b/tests/functional/lang/eval-okay-regression-20220122.exp new file mode 100644 index 000000000..00750edc0 --- /dev/null +++ b/tests/functional/lang/eval-okay-regression-20220122.exp @@ -0,0 +1 @@ +3 diff --git a/tests/functional/lang/eval-okay-regression-20220122.nix b/tests/functional/lang/eval-okay-regression-20220122.nix new file mode 100644 index 000000000..694e9a13b --- /dev/null +++ b/tests/functional/lang/eval-okay-regression-20220122.nix @@ -0,0 +1 @@ +((_: _) 1) + ((__: __) 2) diff --git a/tests/functional/lang/eval-okay-regression-20220125.exp b/tests/functional/lang/eval-okay-regression-20220125.exp new file mode 100644 index 000000000..00750edc0 --- /dev/null +++ b/tests/functional/lang/eval-okay-regression-20220125.exp @@ -0,0 +1 @@ +3 diff --git a/tests/functional/lang/eval-okay-regression-20220125.nix b/tests/functional/lang/eval-okay-regression-20220125.nix new file mode 100644 index 000000000..485502373 --- /dev/null +++ b/tests/functional/lang/eval-okay-regression-20220125.nix @@ -0,0 +1,2 @@ +((__curPosFoo: __curPosFoo) 1) + ((__curPosBar: __curPosBar) 2) + diff --git a/tests/functional/lang/eval-okay-remove.exp b/tests/functional/lang/eval-okay-remove.exp new file mode 100644 index 000000000..8d38505c1 --- /dev/null +++ b/tests/functional/lang/eval-okay-remove.exp @@ -0,0 +1 @@ +456 diff --git a/tests/functional/lang/eval-okay-remove.nix b/tests/functional/lang/eval-okay-remove.nix new file mode 100644 index 000000000..4ad5ba897 --- /dev/null +++ b/tests/functional/lang/eval-okay-remove.nix @@ -0,0 +1,5 @@ +let { + attrs = {x = 123; y = 456;}; + + body = (removeAttrs attrs ["x"]).y; +} \ No newline at end of file diff --git a/tests/functional/lang/eval-okay-replacestrings.exp b/tests/functional/lang/eval-okay-replacestrings.exp new file mode 100644 index 000000000..eac67c5fe --- /dev/null +++ b/tests/functional/lang/eval-okay-replacestrings.exp @@ -0,0 +1 @@ +[ "faabar" "fbar" "fubar" "faboor" "fubar" "XaXbXcX" "X" "a_b" "fubar" ] diff --git a/tests/functional/lang/eval-okay-replacestrings.nix b/tests/functional/lang/eval-okay-replacestrings.nix new file mode 100644 index 000000000..a803e6519 --- /dev/null +++ b/tests/functional/lang/eval-okay-replacestrings.nix @@ -0,0 +1,12 @@ +with builtins; + +[ (replaceStrings ["o"] ["a"] "foobar") + (replaceStrings ["o"] [""] "foobar") + (replaceStrings ["oo"] ["u"] "foobar") + (replaceStrings ["oo" "a"] ["a" "oo"] "foobar") + (replaceStrings ["oo" "oo"] ["u" "i"] "foobar") + (replaceStrings [""] ["X"] "abc") + (replaceStrings [""] ["X"] "") + (replaceStrings ["-"] ["_"] "a-b") + (replaceStrings ["oo" "XX"] ["u" (throw "unreachable")] "foobar") +] diff --git a/tests/functional/lang/eval-okay-scope-1.exp b/tests/functional/lang/eval-okay-scope-1.exp new file mode 100644 index 000000000..00750edc0 --- /dev/null +++ b/tests/functional/lang/eval-okay-scope-1.exp @@ -0,0 +1 @@ +3 diff --git a/tests/functional/lang/eval-okay-scope-1.nix b/tests/functional/lang/eval-okay-scope-1.nix new file mode 100644 index 000000000..fa38a7174 --- /dev/null +++ b/tests/functional/lang/eval-okay-scope-1.nix @@ -0,0 +1,6 @@ +(({x}: x: + + { x = 1; + y = x; + } +) {x = 2;} 3).y diff --git a/tests/functional/lang/eval-okay-scope-2.exp b/tests/functional/lang/eval-okay-scope-2.exp new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/tests/functional/lang/eval-okay-scope-2.exp @@ -0,0 +1 @@ +1 diff --git a/tests/functional/lang/eval-okay-scope-2.nix b/tests/functional/lang/eval-okay-scope-2.nix new file mode 100644 index 000000000..eb8b02bc4 --- /dev/null +++ b/tests/functional/lang/eval-okay-scope-2.nix @@ -0,0 +1,6 @@ +((x: {x}: + rec { + x = 1; + y = x; + } +) 2 {x = 3;}).y diff --git a/tests/functional/lang/eval-okay-scope-3.exp b/tests/functional/lang/eval-okay-scope-3.exp new file mode 100644 index 000000000..b8626c4cf --- /dev/null +++ b/tests/functional/lang/eval-okay-scope-3.exp @@ -0,0 +1 @@ +4 diff --git a/tests/functional/lang/eval-okay-scope-3.nix b/tests/functional/lang/eval-okay-scope-3.nix new file mode 100644 index 000000000..10d6bc04d --- /dev/null +++ b/tests/functional/lang/eval-okay-scope-3.nix @@ -0,0 +1,6 @@ +((x: as: {x}: + rec { + inherit (as) x; + y = x; + } +) 2 {x = 4;} {x = 3;}).y diff --git a/tests/functional/lang/eval-okay-scope-4.exp b/tests/functional/lang/eval-okay-scope-4.exp new file mode 100644 index 000000000..00ff03a46 --- /dev/null +++ b/tests/functional/lang/eval-okay-scope-4.exp @@ -0,0 +1 @@ +"ccdd" diff --git a/tests/functional/lang/eval-okay-scope-4.nix b/tests/functional/lang/eval-okay-scope-4.nix new file mode 100644 index 000000000..dc8243bc8 --- /dev/null +++ b/tests/functional/lang/eval-okay-scope-4.nix @@ -0,0 +1,10 @@ +let { + + x = "a"; + y = "b"; + + f = {x ? y, y ? x}: x + y; + + body = f {x = "c";} + f {y = "d";}; + +} diff --git a/tests/functional/lang/eval-okay-scope-6.exp b/tests/functional/lang/eval-okay-scope-6.exp new file mode 100644 index 000000000..00ff03a46 --- /dev/null +++ b/tests/functional/lang/eval-okay-scope-6.exp @@ -0,0 +1 @@ +"ccdd" diff --git a/tests/functional/lang/eval-okay-scope-6.nix b/tests/functional/lang/eval-okay-scope-6.nix new file mode 100644 index 000000000..0995d4e7e --- /dev/null +++ b/tests/functional/lang/eval-okay-scope-6.nix @@ -0,0 +1,7 @@ +let { + + f = {x ? y, y ? x}: x + y; + + body = f {x = "c";} + f {y = "d";}; + +} diff --git a/tests/functional/lang/eval-okay-scope-7.exp b/tests/functional/lang/eval-okay-scope-7.exp new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/tests/functional/lang/eval-okay-scope-7.exp @@ -0,0 +1 @@ +1 diff --git a/tests/functional/lang/eval-okay-scope-7.nix b/tests/functional/lang/eval-okay-scope-7.nix new file mode 100644 index 000000000..4da02968f --- /dev/null +++ b/tests/functional/lang/eval-okay-scope-7.nix @@ -0,0 +1,6 @@ +rec { + inherit (x) y; + x = { + y = 1; + }; +}.y diff --git a/tests/functional/lang/eval-okay-search-path.exp b/tests/functional/lang/eval-okay-search-path.exp new file mode 100644 index 000000000..4519bc406 --- /dev/null +++ b/tests/functional/lang/eval-okay-search-path.exp @@ -0,0 +1 @@ +"abccX" diff --git a/tests/functional/lang/eval-okay-search-path.flags b/tests/functional/lang/eval-okay-search-path.flags new file mode 100644 index 000000000..dfad1c611 --- /dev/null +++ b/tests/functional/lang/eval-okay-search-path.flags @@ -0,0 +1 @@ +-I lang/dir1 -I lang/dir2 -I dir5=lang/dir3 diff --git a/tests/functional/lang/eval-okay-search-path.nix b/tests/functional/lang/eval-okay-search-path.nix new file mode 100644 index 000000000..6fe33decc --- /dev/null +++ b/tests/functional/lang/eval-okay-search-path.nix @@ -0,0 +1,10 @@ +with import ./lib.nix; +with builtins; + +assert isFunction (import ); + +assert length __nixPath == 5; +assert length (filter (x: baseNameOf x.path == "dir4") __nixPath) == 1; + +import + import + import + import + + (let __nixPath = [ { path = ./dir2; } { path = ./dir1; } ]; in import ) diff --git a/tests/functional/lang/eval-okay-seq.exp b/tests/functional/lang/eval-okay-seq.exp new file mode 100644 index 000000000..0cfbf0888 --- /dev/null +++ b/tests/functional/lang/eval-okay-seq.exp @@ -0,0 +1 @@ +2 diff --git a/tests/functional/lang/eval-okay-seq.nix b/tests/functional/lang/eval-okay-seq.nix new file mode 100644 index 000000000..0a9a21c03 --- /dev/null +++ b/tests/functional/lang/eval-okay-seq.nix @@ -0,0 +1 @@ +builtins.seq 1 2 diff --git a/tests/functional/lang/eval-okay-sort.exp b/tests/functional/lang/eval-okay-sort.exp new file mode 100644 index 000000000..899119e20 --- /dev/null +++ b/tests/functional/lang/eval-okay-sort.exp @@ -0,0 +1 @@ +[ [ 42 77 147 249 483 526 ] [ 526 483 249 147 77 42 ] [ "bar" "fnord" "foo" "xyzzy" ] [ { key = 1; value = "foo"; } { key = 1; value = "fnord"; } { key = 2; value = "bar"; } ] [ [ ] [ ] [ 1 ] [ 1 4 ] [ 1 5 ] [ 1 6 ] [ 2 ] [ 2 3 ] [ 3 ] [ 3 ] ] ] diff --git a/tests/functional/lang/eval-okay-sort.nix b/tests/functional/lang/eval-okay-sort.nix new file mode 100644 index 000000000..50aa78e40 --- /dev/null +++ b/tests/functional/lang/eval-okay-sort.nix @@ -0,0 +1,20 @@ +with builtins; + +[ (sort lessThan [ 483 249 526 147 42 77 ]) + (sort (x: y: y < x) [ 483 249 526 147 42 77 ]) + (sort lessThan [ "foo" "bar" "xyzzy" "fnord" ]) + (sort (x: y: x.key < y.key) + [ { key = 1; value = "foo"; } { key = 2; value = "bar"; } { key = 1; value = "fnord"; } ]) + (sort lessThan [ + [ 1 6 ] + [ ] + [ 2 3 ] + [ 3 ] + [ 1 5 ] + [ 2 ] + [ 1 ] + [ ] + [ 1 4 ] + [ 3 ] + ]) +] diff --git a/tests/functional/lang/eval-okay-splitversion.exp b/tests/functional/lang/eval-okay-splitversion.exp new file mode 100644 index 000000000..153ceb818 --- /dev/null +++ b/tests/functional/lang/eval-okay-splitversion.exp @@ -0,0 +1 @@ +[ "1" "2" "3" ] diff --git a/tests/functional/lang/eval-okay-splitversion.nix b/tests/functional/lang/eval-okay-splitversion.nix new file mode 100644 index 000000000..9e5c99d2e --- /dev/null +++ b/tests/functional/lang/eval-okay-splitversion.nix @@ -0,0 +1 @@ +builtins.splitVersion "1.2.3" diff --git a/tests/functional/lang/eval-okay-string.exp b/tests/functional/lang/eval-okay-string.exp new file mode 100644 index 000000000..63f650f73 --- /dev/null +++ b/tests/functional/lang/eval-okay-string.exp @@ -0,0 +1 @@ +"foobar/a/b/c/d/foo/xyzzy/foo.txt/../foo/x/yescape: \"quote\" \n \\end\nof\nlinefoobarblaatfoo$bar$\"$\"$" diff --git a/tests/functional/lang/eval-okay-string.nix b/tests/functional/lang/eval-okay-string.nix new file mode 100644 index 000000000..47cc989ad --- /dev/null +++ b/tests/functional/lang/eval-okay-string.nix @@ -0,0 +1,12 @@ +"foo" + "bar" + + toString (/a/b + /c/d) + + toString (/foo/bar + "/../xyzzy/." + "/foo.txt") + + ("/../foo" + toString /x/y) + + "escape: \"quote\" \n \\" + + "end +of +line" + + "foo${if true then "b${"a" + "r"}" else "xyzzy"}blaat" + + "foo$bar" + + "$\"$\"" + + "$" diff --git a/tests/functional/lang/eval-okay-strings-as-attrs-names.exp b/tests/functional/lang/eval-okay-strings-as-attrs-names.exp new file mode 100644 index 000000000..27ba77dda --- /dev/null +++ b/tests/functional/lang/eval-okay-strings-as-attrs-names.exp @@ -0,0 +1 @@ +true diff --git a/tests/functional/lang/eval-okay-strings-as-attrs-names.nix b/tests/functional/lang/eval-okay-strings-as-attrs-names.nix new file mode 100644 index 000000000..5e40928db --- /dev/null +++ b/tests/functional/lang/eval-okay-strings-as-attrs-names.nix @@ -0,0 +1,20 @@ +let + + attr = { + "key 1" = "test"; + "key 2" = "caseok"; + }; + + t1 = builtins.getAttr "key 1" attr; + t2 = attr."key 2"; + t3 = attr ? "key 1"; + t4 = builtins.attrNames { inherit (attr) "key 1"; }; + + # This is permitted, but there is currently no way to reference this + # variable. + "foo bar" = 1; + +in t1 == "test" + && t2 == "caseok" + && t3 == true + && t4 == ["key 1"] diff --git a/tests/functional/lang/eval-okay-substring.exp b/tests/functional/lang/eval-okay-substring.exp new file mode 100644 index 000000000..6aace04b0 --- /dev/null +++ b/tests/functional/lang/eval-okay-substring.exp @@ -0,0 +1 @@ +"ooxfoobarybarzobaabbc" diff --git a/tests/functional/lang/eval-okay-substring.nix b/tests/functional/lang/eval-okay-substring.nix new file mode 100644 index 000000000..424af00d9 --- /dev/null +++ b/tests/functional/lang/eval-okay-substring.nix @@ -0,0 +1,21 @@ +with builtins; + +let + + s = "foobar"; + +in + +substring 1 2 s ++ "x" ++ substring 0 (stringLength s) s ++ "y" ++ substring 3 100 s ++ "z" ++ substring 2 (sub (stringLength s) 3) s ++ "a" ++ substring 3 0 s ++ "b" ++ substring 3 1 s ++ "c" ++ substring 5 10 "perl" diff --git a/tests/functional/lang/eval-okay-tail-call-1.exp-disabled b/tests/functional/lang/eval-okay-tail-call-1.exp-disabled new file mode 100644 index 000000000..f7393e847 --- /dev/null +++ b/tests/functional/lang/eval-okay-tail-call-1.exp-disabled @@ -0,0 +1 @@ +100000 diff --git a/tests/functional/lang/eval-okay-tail-call-1.nix b/tests/functional/lang/eval-okay-tail-call-1.nix new file mode 100644 index 000000000..a3962ce3f --- /dev/null +++ b/tests/functional/lang/eval-okay-tail-call-1.nix @@ -0,0 +1,3 @@ +let + f = n: if n == 100000 then n else f (n + 1); +in f 0 diff --git a/tests/functional/lang/eval-okay-tojson.exp b/tests/functional/lang/eval-okay-tojson.exp new file mode 100644 index 000000000..e92aae323 --- /dev/null +++ b/tests/functional/lang/eval-okay-tojson.exp @@ -0,0 +1 @@ +"{\"a\":123,\"b\":-456,\"c\":\"foo\",\"d\":\"foo\\n\\\"bar\\\"\",\"e\":true,\"f\":false,\"g\":[1,2,3],\"h\":[\"a\",[\"b\",{\"foo\\nbar\":{}}]],\"i\":3,\"j\":1.44,\"k\":\"foo\"}" diff --git a/tests/functional/lang/eval-okay-tojson.nix b/tests/functional/lang/eval-okay-tojson.nix new file mode 100644 index 000000000..ce67943be --- /dev/null +++ b/tests/functional/lang/eval-okay-tojson.nix @@ -0,0 +1,13 @@ +builtins.toJSON + { a = 123; + b = -456; + c = "foo"; + d = "foo\n\"bar\""; + e = true; + f = false; + g = [ 1 2 3 ]; + h = [ "a" [ "b" { "foo\nbar" = {}; } ] ]; + i = 1 + 2; + j = 1.44; + k = { __toString = self: self.a; a = "foo"; }; + } diff --git a/tests/functional/lang/eval-okay-toxml.exp b/tests/functional/lang/eval-okay-toxml.exp new file mode 100644 index 000000000..828220890 --- /dev/null +++ b/tests/functional/lang/eval-okay-toxml.exp @@ -0,0 +1 @@ +"\n\n \n \n \n \n \n\n" diff --git a/tests/functional/lang/eval-okay-toxml.nix b/tests/functional/lang/eval-okay-toxml.nix new file mode 100644 index 000000000..068c97a6c --- /dev/null +++ b/tests/functional/lang/eval-okay-toxml.nix @@ -0,0 +1,3 @@ +# Make sure the expected XML output is produced; in particular, make sure it +# doesn't contain source location information. +builtins.toXML { a = "s"; } diff --git a/tests/functional/lang/eval-okay-toxml2.exp b/tests/functional/lang/eval-okay-toxml2.exp new file mode 100644 index 000000000..634a841eb --- /dev/null +++ b/tests/functional/lang/eval-okay-toxml2.exp @@ -0,0 +1 @@ +"\n\n \n \n \n \n \n \n \n \n \n \n \n \n\n" diff --git a/tests/functional/lang/eval-okay-toxml2.nix b/tests/functional/lang/eval-okay-toxml2.nix new file mode 100644 index 000000000..ff1791b30 --- /dev/null +++ b/tests/functional/lang/eval-okay-toxml2.nix @@ -0,0 +1 @@ +builtins.toXML [("a" + "b") 10 (rec {x = "x"; y = x;})] diff --git a/tests/functional/lang/eval-okay-tryeval.exp b/tests/functional/lang/eval-okay-tryeval.exp new file mode 100644 index 000000000..2b2e6fa71 --- /dev/null +++ b/tests/functional/lang/eval-okay-tryeval.exp @@ -0,0 +1 @@ +{ x = { success = true; value = "x"; }; y = { success = false; value = false; }; z = { success = false; value = false; }; } diff --git a/tests/functional/lang/eval-okay-tryeval.nix b/tests/functional/lang/eval-okay-tryeval.nix new file mode 100644 index 000000000..629bc440a --- /dev/null +++ b/tests/functional/lang/eval-okay-tryeval.nix @@ -0,0 +1,5 @@ +{ + x = builtins.tryEval "x"; + y = builtins.tryEval (assert false; "y"); + z = builtins.tryEval (throw "bla"); +} diff --git a/tests/functional/lang/eval-okay-types.exp b/tests/functional/lang/eval-okay-types.exp new file mode 100644 index 000000000..92a153299 --- /dev/null +++ b/tests/functional/lang/eval-okay-types.exp @@ -0,0 +1 @@ +[ true false true false true false true false true true true true true true true true true true true false true true true false "int" "bool" "string" "null" "set" "list" "lambda" "lambda" "lambda" "lambda" ] diff --git a/tests/functional/lang/eval-okay-types.nix b/tests/functional/lang/eval-okay-types.nix new file mode 100644 index 000000000..9b58be5d1 --- /dev/null +++ b/tests/functional/lang/eval-okay-types.nix @@ -0,0 +1,37 @@ +with builtins; + +[ (isNull null) + (isNull (x: x)) + (isFunction (x: x)) + (isFunction "fnord") + (isString ("foo" + "bar")) + (isString [ "x" ]) + (isInt (1 + 2)) + (isInt { x = 123; }) + (isInt (1 / 2)) + (isInt (1 + 1)) + (isInt (1 / 2)) + (isInt (1 * 2)) + (isInt (1 - 2)) + (isFloat (1.2)) + (isFloat (1 + 1.0)) + (isFloat (1 / 2.0)) + (isFloat (1 * 2.0)) + (isFloat (1 - 2.0)) + (isBool (true && false)) + (isBool null) + (isPath /nix/store) + (isPath ./.) + (isAttrs { x = 123; }) + (isAttrs null) + (typeOf (3 * 4)) + (typeOf true) + (typeOf "xyzzy") + (typeOf null) + (typeOf { x = 456; }) + (typeOf [ 1 2 3 ]) + (typeOf (x: x)) + (typeOf ((x: y: x) 1)) + (typeOf map) + (typeOf (map (x: x))) +] diff --git a/tests/functional/lang/eval-okay-versions.exp b/tests/functional/lang/eval-okay-versions.exp new file mode 100644 index 000000000..27ba77dda --- /dev/null +++ b/tests/functional/lang/eval-okay-versions.exp @@ -0,0 +1 @@ +true diff --git a/tests/functional/lang/eval-okay-versions.nix b/tests/functional/lang/eval-okay-versions.nix new file mode 100644 index 000000000..e9111f5f4 --- /dev/null +++ b/tests/functional/lang/eval-okay-versions.nix @@ -0,0 +1,43 @@ +let + + name1 = "hello-1.0.2"; + name2 = "hello"; + name3 = "915resolution-0.5.2"; + name4 = "xf86-video-i810-1.7.4"; + name5 = "name-that-ends-with-dash--1.0"; + + eq = 0; + lt = builtins.sub 0 1; + gt = 1; + + versionTest = v1: v2: expected: + let d1 = builtins.compareVersions v1 v2; + d2 = builtins.compareVersions v2 v1; + in d1 == builtins.sub 0 d2 && d1 == expected; + + tests = [ + ((builtins.parseDrvName name1).name == "hello") + ((builtins.parseDrvName name1).version == "1.0.2") + ((builtins.parseDrvName name2).name == "hello") + ((builtins.parseDrvName name2).version == "") + ((builtins.parseDrvName name3).name == "915resolution") + ((builtins.parseDrvName name3).version == "0.5.2") + ((builtins.parseDrvName name4).name == "xf86-video-i810") + ((builtins.parseDrvName name4).version == "1.7.4") + ((builtins.parseDrvName name5).name == "name-that-ends-with-dash") + ((builtins.parseDrvName name5).version == "-1.0") + (versionTest "1.0" "2.3" lt) + (versionTest "2.1" "2.3" lt) + (versionTest "2.3" "2.3" eq) + (versionTest "2.5" "2.3" gt) + (versionTest "3.1" "2.3" gt) + (versionTest "2.3.1" "2.3" gt) + (versionTest "2.3.1" "2.3a" gt) + (versionTest "2.3pre1" "2.3" lt) + (versionTest "2.3pre3" "2.3pre12" lt) + (versionTest "2.3a" "2.3c" lt) + (versionTest "2.3pre1" "2.3c" lt) + (versionTest "2.3pre1" "2.3q" lt) + ]; + +in (import ./lib.nix).and tests diff --git a/tests/functional/lang/eval-okay-with.exp b/tests/functional/lang/eval-okay-with.exp new file mode 100644 index 000000000..378c8dc80 --- /dev/null +++ b/tests/functional/lang/eval-okay-with.exp @@ -0,0 +1 @@ +"xyzzybarxyzzybar" diff --git a/tests/functional/lang/eval-okay-with.nix b/tests/functional/lang/eval-okay-with.nix new file mode 100644 index 000000000..033e8d3ab --- /dev/null +++ b/tests/functional/lang/eval-okay-with.nix @@ -0,0 +1,19 @@ +let { + + a = "xyzzy"; + + as = { + a = "foo"; + b = "bar"; + }; + + bs = { + a = "bar"; + }; + + x = with as; a + b; + + y = with as; with bs; a + b; + + body = x + y; +} diff --git a/tests/functional/lang/eval-okay-xml.exp.xml b/tests/functional/lang/eval-okay-xml.exp.xml new file mode 100644 index 000000000..20099326c --- /dev/null +++ b/tests/functional/lang/eval-okay-xml.exp.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/functional/lang/eval-okay-xml.nix b/tests/functional/lang/eval-okay-xml.nix new file mode 100644 index 000000000..9ee9f8a0b --- /dev/null +++ b/tests/functional/lang/eval-okay-xml.nix @@ -0,0 +1,21 @@ +rec { + + x = 123; + + y = 567.890; + + a = "foo"; + + b = "bar"; + + c = "foo" + "bar"; + + f = {z, x, y}: if y then x else z; + + id = x: x; + + at = args@{x, y, z}: x; + + ellipsis = {x, y, z, ...}: x; + +} diff --git a/tests/functional/lang/eval-okay-zipAttrsWith.exp b/tests/functional/lang/eval-okay-zipAttrsWith.exp new file mode 100644 index 000000000..9c0b15d22 --- /dev/null +++ b/tests/functional/lang/eval-okay-zipAttrsWith.exp @@ -0,0 +1 @@ +{ "0" = { n = "0"; v = [ 5 23 29 ]; }; "1" = { n = "1"; v = [ 7 30 ]; }; "2" = { n = "2"; v = [ 18 ]; }; "4" = { n = "4"; v = [ 10 ]; }; "5" = { n = "5"; v = [ 15 25 26 31 ]; }; "6" = { n = "6"; v = [ 3 14 ]; }; "7" = { n = "7"; v = [ 12 ]; }; "8" = { n = "8"; v = [ 2 6 8 9 ]; }; "9" = { n = "9"; v = [ 0 16 ]; }; a = { n = "a"; v = [ 17 21 22 27 ]; }; c = { n = "c"; v = [ 11 24 ]; }; d = { n = "d"; v = [ 4 13 28 ]; }; e = { n = "e"; v = [ 20 ]; }; f = { n = "f"; v = [ 1 19 ]; }; } diff --git a/tests/functional/lang/eval-okay-zipAttrsWith.nix b/tests/functional/lang/eval-okay-zipAttrsWith.nix new file mode 100644 index 000000000..877d4e5fa --- /dev/null +++ b/tests/functional/lang/eval-okay-zipAttrsWith.nix @@ -0,0 +1,9 @@ +with import ./lib.nix; + +let + str = builtins.hashString "sha256" "test"; +in +builtins.zipAttrsWith + (n: v: { inherit n v; }) + (map (n: { ${builtins.substring n 1 str} = n; }) + (range 0 31)) diff --git a/tests/functional/lang/framework.sh b/tests/functional/lang/framework.sh new file mode 100644 index 000000000..516bff8ad --- /dev/null +++ b/tests/functional/lang/framework.sh @@ -0,0 +1,33 @@ +# Golden test support +# +# Test that the output of the given test matches what is expected. If +# `_NIX_TEST_ACCEPT` is non-empty also update the expected output so +# that next time the test succeeds. +function diffAndAcceptInner() { + local -r testName=$1 + local -r got="$2" + local -r expected="$3" + + # Absence of expected file indicates empty output expected. + if test -e "$expected"; then + local -r expectedOrEmpty="$expected" + else + local -r expectedOrEmpty=lang/empty.exp + fi + + # Diff so we get a nice message + if ! diff --unified "$got" "$expectedOrEmpty"; then + echo "FAIL: evaluation result of $testName not as expected" + badDiff=1 + fi + + # Update expected if `_NIX_TEST_ACCEPT` is non-empty. + if test -n "${_NIX_TEST_ACCEPT-}"; then + cp "$got" "$expected" + # Delete empty expected files to avoid bloating the repo with + # empty files. + if ! test -s "$expected"; then + rm "$expected" + fi + fi +} diff --git a/tests/functional/lang/imported.nix b/tests/functional/lang/imported.nix new file mode 100644 index 000000000..fb39ee4ef --- /dev/null +++ b/tests/functional/lang/imported.nix @@ -0,0 +1,3 @@ +# The function ‘range’ comes from lib.nix and was added to the lexical +# scope by scopedImport. +range 1 5 ++ import ./imported2.nix diff --git a/tests/functional/lang/imported2.nix b/tests/functional/lang/imported2.nix new file mode 100644 index 000000000..6d0a2992b --- /dev/null +++ b/tests/functional/lang/imported2.nix @@ -0,0 +1 @@ +range 6 10 diff --git a/tests/functional/lang/lib.nix b/tests/functional/lang/lib.nix new file mode 100644 index 000000000..028a53831 --- /dev/null +++ b/tests/functional/lang/lib.nix @@ -0,0 +1,61 @@ +with builtins; + +rec { + + fold = op: nul: list: + if list == [] + then nul + else op (head list) (fold op nul (tail list)); + + concat = + fold (x: y: x + y) ""; + + and = fold (x: y: x && y) true; + + flatten = x: + if isList x + then fold (x: y: (flatten x) ++ y) [] x + else [x]; + + sum = foldl' (x: y: add x y) 0; + + hasSuffix = ext: fileName: + let lenFileName = stringLength fileName; + lenExt = stringLength ext; + in !(lessThan lenFileName lenExt) && + substring (sub lenFileName lenExt) lenFileName fileName == ext; + + # Split a list at the given position. + splitAt = pos: list: + if pos == 0 then {first = []; second = list;} else + if list == [] then {first = []; second = [];} else + let res = splitAt (sub pos 1) (tail list); + in {first = [(head list)] ++ res.first; second = res.second;}; + + # Stable merge sort. + sortBy = comp: list: + if lessThan 1 (length list) + then + let + split = splitAt (div (length list) 2) list; + first = sortBy comp split.first; + second = sortBy comp split.second; + in mergeLists comp first second + else list; + + mergeLists = comp: list1: list2: + if list1 == [] then list2 else + if list2 == [] then list1 else + if comp (head list2) (head list1) then [(head list2)] ++ mergeLists comp list1 (tail list2) else + [(head list1)] ++ mergeLists comp (tail list1) list2; + + id = x: x; + + const = x: y: x; + + range = first: last: + if first > last + then [] + else genList (n: first + n) (last - first + 1); + +} diff --git a/tests/functional/lang/parse-fail-dup-attrs-1.err.exp b/tests/functional/lang/parse-fail-dup-attrs-1.err.exp new file mode 100644 index 000000000..4fe6b7a1f --- /dev/null +++ b/tests/functional/lang/parse-fail-dup-attrs-1.err.exp @@ -0,0 +1,7 @@ +error: attribute 'x' already defined at «stdin»:1:3 + + at «stdin»:3:3: + + 2| y = 456; + 3| x = 789; + | ^ diff --git a/tests/functional/lang/parse-fail-dup-attrs-1.nix b/tests/functional/lang/parse-fail-dup-attrs-1.nix new file mode 100644 index 000000000..2c02317d2 --- /dev/null +++ b/tests/functional/lang/parse-fail-dup-attrs-1.nix @@ -0,0 +1,4 @@ +{ x = 123; + y = 456; + x = 789; +} diff --git a/tests/functional/lang/parse-fail-dup-attrs-2.err.exp b/tests/functional/lang/parse-fail-dup-attrs-2.err.exp new file mode 100644 index 000000000..3aba2891f --- /dev/null +++ b/tests/functional/lang/parse-fail-dup-attrs-2.err.exp @@ -0,0 +1,7 @@ +error: attribute 'x' already defined at «stdin»:9:5 + + at «stdin»:10:17: + + 9| x = 789; + 10| inherit (as) x; + | ^ diff --git a/tests/functional/lang/parse-fail-dup-attrs-2.nix b/tests/functional/lang/parse-fail-dup-attrs-2.nix new file mode 100644 index 000000000..864d9865e --- /dev/null +++ b/tests/functional/lang/parse-fail-dup-attrs-2.nix @@ -0,0 +1,13 @@ +let { + + as = { + x = 123; + y = 456; + }; + + bs = { + x = 789; + inherit (as) x; + }; + +} diff --git a/tests/functional/lang/parse-fail-dup-attrs-3.err.exp b/tests/functional/lang/parse-fail-dup-attrs-3.err.exp new file mode 100644 index 000000000..3aba2891f --- /dev/null +++ b/tests/functional/lang/parse-fail-dup-attrs-3.err.exp @@ -0,0 +1,7 @@ +error: attribute 'x' already defined at «stdin»:9:5 + + at «stdin»:10:17: + + 9| x = 789; + 10| inherit (as) x; + | ^ diff --git a/tests/functional/lang/parse-fail-dup-attrs-3.nix b/tests/functional/lang/parse-fail-dup-attrs-3.nix new file mode 100644 index 000000000..114d19779 --- /dev/null +++ b/tests/functional/lang/parse-fail-dup-attrs-3.nix @@ -0,0 +1,13 @@ +let { + + as = { + x = 123; + y = 456; + }; + + bs = rec { + x = 789; + inherit (as) x; + }; + +} diff --git a/tests/functional/lang/parse-fail-dup-attrs-4.err.exp b/tests/functional/lang/parse-fail-dup-attrs-4.err.exp new file mode 100644 index 000000000..ff68446a1 --- /dev/null +++ b/tests/functional/lang/parse-fail-dup-attrs-4.err.exp @@ -0,0 +1,7 @@ +error: attribute 'services.ssh.port' already defined at «stdin»:2:3 + + at «stdin»:3:3: + + 2| services.ssh.port = 22; + 3| services.ssh.port = 23; + | ^ diff --git a/tests/functional/lang/parse-fail-dup-attrs-4.nix b/tests/functional/lang/parse-fail-dup-attrs-4.nix new file mode 100644 index 000000000..77417432b --- /dev/null +++ b/tests/functional/lang/parse-fail-dup-attrs-4.nix @@ -0,0 +1,4 @@ +{ + services.ssh.port = 22; + services.ssh.port = 23; +} diff --git a/tests/functional/lang/parse-fail-dup-attrs-6.err.exp b/tests/functional/lang/parse-fail-dup-attrs-6.err.exp new file mode 100644 index 000000000..74823fc25 --- /dev/null +++ b/tests/functional/lang/parse-fail-dup-attrs-6.err.exp @@ -0,0 +1 @@ +error: attribute ‘services.ssh’ at (string):3:3 already defined at (string):2:3 diff --git a/tests/functional/lang/parse-fail-dup-attrs-7.err.exp b/tests/functional/lang/parse-fail-dup-attrs-7.err.exp new file mode 100644 index 000000000..512a499ca --- /dev/null +++ b/tests/functional/lang/parse-fail-dup-attrs-7.err.exp @@ -0,0 +1,7 @@ +error: attribute 'x' already defined at «stdin»:6:12 + + at «stdin»:7:12: + + 6| inherit x; + 7| inherit x; + | ^ diff --git a/tests/functional/lang/parse-fail-dup-attrs-7.nix b/tests/functional/lang/parse-fail-dup-attrs-7.nix new file mode 100644 index 000000000..bbc3eb08c --- /dev/null +++ b/tests/functional/lang/parse-fail-dup-attrs-7.nix @@ -0,0 +1,9 @@ +rec { + + x = 1; + + as = { + inherit x; + inherit x; + }; +} \ No newline at end of file diff --git a/tests/functional/lang/parse-fail-dup-formals.err.exp b/tests/functional/lang/parse-fail-dup-formals.err.exp new file mode 100644 index 000000000..1d566fb33 --- /dev/null +++ b/tests/functional/lang/parse-fail-dup-formals.err.exp @@ -0,0 +1,6 @@ +error: duplicate formal function argument 'x' + + at «stdin»:1:8: + + 1| {x, y, x}: x + | ^ diff --git a/tests/functional/lang/parse-fail-dup-formals.nix b/tests/functional/lang/parse-fail-dup-formals.nix new file mode 100644 index 000000000..a0edd91a9 --- /dev/null +++ b/tests/functional/lang/parse-fail-dup-formals.nix @@ -0,0 +1 @@ +{x, y, x}: x \ No newline at end of file diff --git a/tests/functional/lang/parse-fail-eof-in-string.err.exp b/tests/functional/lang/parse-fail-eof-in-string.err.exp new file mode 100644 index 000000000..f9fa72312 --- /dev/null +++ b/tests/functional/lang/parse-fail-eof-in-string.err.exp @@ -0,0 +1,7 @@ +error: syntax error, unexpected end of file, expecting '"' + + at «stdin»:3:5: + + 2| # Note that this file must not end with a newline. + 3| a 1"$ + | ^ diff --git a/tests/functional/lang/parse-fail-eof-in-string.nix b/tests/functional/lang/parse-fail-eof-in-string.nix new file mode 100644 index 000000000..19775d2ec --- /dev/null +++ b/tests/functional/lang/parse-fail-eof-in-string.nix @@ -0,0 +1,3 @@ +# https://github.com/NixOS/nix/issues/6562 +# Note that this file must not end with a newline. +a 1"$ \ No newline at end of file diff --git a/tests/functional/lang/parse-fail-mixed-nested-attrs1.err.exp b/tests/functional/lang/parse-fail-mixed-nested-attrs1.err.exp new file mode 100644 index 000000000..32f776795 --- /dev/null +++ b/tests/functional/lang/parse-fail-mixed-nested-attrs1.err.exp @@ -0,0 +1,8 @@ +error: attribute 'z' already defined at «stdin»:3:16 + + at «stdin»:2:3: + + 1| { + 2| x.z = 3; + | ^ + 3| x = { y = 3; z = 3; }; diff --git a/tests/functional/lang/parse-fail-mixed-nested-attrs1.nix b/tests/functional/lang/parse-fail-mixed-nested-attrs1.nix new file mode 100644 index 000000000..11e40e66f --- /dev/null +++ b/tests/functional/lang/parse-fail-mixed-nested-attrs1.nix @@ -0,0 +1,4 @@ +{ + x.z = 3; + x = { y = 3; z = 3; }; +} diff --git a/tests/functional/lang/parse-fail-mixed-nested-attrs2.err.exp b/tests/functional/lang/parse-fail-mixed-nested-attrs2.err.exp new file mode 100644 index 000000000..0437cd50c --- /dev/null +++ b/tests/functional/lang/parse-fail-mixed-nested-attrs2.err.exp @@ -0,0 +1,8 @@ +error: attribute 'y' already defined at «stdin»:3:9 + + at «stdin»:2:3: + + 1| { + 2| x.y.y = 3; + | ^ + 3| x = { y.y= 3; z = 3; }; diff --git a/tests/functional/lang/parse-fail-mixed-nested-attrs2.nix b/tests/functional/lang/parse-fail-mixed-nested-attrs2.nix new file mode 100644 index 000000000..17da82e5f --- /dev/null +++ b/tests/functional/lang/parse-fail-mixed-nested-attrs2.nix @@ -0,0 +1,4 @@ +{ + x.y.y = 3; + x = { y.y= 3; z = 3; }; +} diff --git a/tests/functional/lang/parse-fail-patterns-1.err.exp b/tests/functional/lang/parse-fail-patterns-1.err.exp new file mode 100644 index 000000000..634a04aaa --- /dev/null +++ b/tests/functional/lang/parse-fail-patterns-1.err.exp @@ -0,0 +1,7 @@ +error: duplicate formal function argument 'args' + + at «stdin»:1:1: + + 1| args@{args, x, y, z}: x + | ^ + 2| diff --git a/tests/functional/lang/parse-fail-patterns-1.nix b/tests/functional/lang/parse-fail-patterns-1.nix new file mode 100644 index 000000000..7b4061641 --- /dev/null +++ b/tests/functional/lang/parse-fail-patterns-1.nix @@ -0,0 +1 @@ +args@{args, x, y, z}: x diff --git a/tests/functional/lang/parse-fail-regression-20060610.err.exp b/tests/functional/lang/parse-fail-regression-20060610.err.exp new file mode 100644 index 000000000..167d01e85 --- /dev/null +++ b/tests/functional/lang/parse-fail-regression-20060610.err.exp @@ -0,0 +1,8 @@ +error: undefined variable 'gcc' + + at «stdin»:8:12: + + 7| + 8| body = ({ + | ^ + 9| inherit gcc; diff --git a/tests/functional/lang/parse-fail-regression-20060610.nix b/tests/functional/lang/parse-fail-regression-20060610.nix new file mode 100644 index 000000000..b1934f7e1 --- /dev/null +++ b/tests/functional/lang/parse-fail-regression-20060610.nix @@ -0,0 +1,11 @@ +let { + x = + {gcc}: + { + inherit gcc; + }; + + body = ({ + inherit gcc; + }).gcc; +} diff --git a/tests/functional/lang/parse-fail-undef-var-2.err.exp b/tests/functional/lang/parse-fail-undef-var-2.err.exp new file mode 100644 index 000000000..77c96bbd2 --- /dev/null +++ b/tests/functional/lang/parse-fail-undef-var-2.err.exp @@ -0,0 +1,7 @@ +error: syntax error, unexpected ':', expecting '}' + + at «stdin»:3:13: + + 2| + 3| f = {x, y : + | ^ diff --git a/tests/functional/lang/parse-fail-undef-var-2.nix b/tests/functional/lang/parse-fail-undef-var-2.nix new file mode 100644 index 000000000..c10a52b1e --- /dev/null +++ b/tests/functional/lang/parse-fail-undef-var-2.nix @@ -0,0 +1,7 @@ +let { + + f = {x, y : ["baz" "bar" z "bat"]}: x + y; + + body = f {x = "foo"; y = "bar";}; + +} diff --git a/tests/functional/lang/parse-fail-undef-var.err.exp b/tests/functional/lang/parse-fail-undef-var.err.exp new file mode 100644 index 000000000..48e88747f --- /dev/null +++ b/tests/functional/lang/parse-fail-undef-var.err.exp @@ -0,0 +1,7 @@ +error: undefined variable 'y' + + at «stdin»:1:4: + + 1| x: y + | ^ + 2| diff --git a/tests/functional/lang/parse-fail-undef-var.nix b/tests/functional/lang/parse-fail-undef-var.nix new file mode 100644 index 000000000..7b6300811 --- /dev/null +++ b/tests/functional/lang/parse-fail-undef-var.nix @@ -0,0 +1 @@ +x: y diff --git a/tests/functional/lang/parse-fail-utf8.err.exp b/tests/functional/lang/parse-fail-utf8.err.exp new file mode 100644 index 000000000..6087479a3 --- /dev/null +++ b/tests/functional/lang/parse-fail-utf8.err.exp @@ -0,0 +1,6 @@ +error: syntax error, unexpected invalid token, expecting end of file + + at «stdin»:1:5: + + 1| 123 + | ^ diff --git a/tests/functional/lang/parse-fail-utf8.nix b/tests/functional/lang/parse-fail-utf8.nix new file mode 100644 index 000000000..34948d48a --- /dev/null +++ b/tests/functional/lang/parse-fail-utf8.nix @@ -0,0 +1 @@ +123 é 4 diff --git a/tests/functional/lang/parse-okay-1.exp b/tests/functional/lang/parse-okay-1.exp new file mode 100644 index 000000000..d5ab5f18a --- /dev/null +++ b/tests/functional/lang/parse-okay-1.exp @@ -0,0 +1 @@ +({ x, y, z }: ((x + y) + z)) diff --git a/tests/functional/lang/parse-okay-1.nix b/tests/functional/lang/parse-okay-1.nix new file mode 100644 index 000000000..23a58ed10 --- /dev/null +++ b/tests/functional/lang/parse-okay-1.nix @@ -0,0 +1 @@ +{x, y, z}: x + y + z diff --git a/tests/functional/lang/parse-okay-crlf.exp b/tests/functional/lang/parse-okay-crlf.exp new file mode 100644 index 000000000..4213609fc --- /dev/null +++ b/tests/functional/lang/parse-okay-crlf.exp @@ -0,0 +1 @@ +rec { foo = "multi\nline\n string\n test\r"; x = y; y = 123; z = 456; } diff --git a/tests/functional/lang/parse-okay-crlf.nix b/tests/functional/lang/parse-okay-crlf.nix new file mode 100644 index 000000000..21518d4c6 --- /dev/null +++ b/tests/functional/lang/parse-okay-crlf.nix @@ -0,0 +1,17 @@ +rec { + + /* Dit is + een test. */ + + x = + # Dit is een test. y; + + y = 123; + + # CR or CR/LF (but not explicit \r's) in strings should be + # translated to LF. + foo = "multi line + string + test\r"; + + z = 456; } diff --git a/tests/functional/lang/parse-okay-dup-attrs-5.exp b/tests/functional/lang/parse-okay-dup-attrs-5.exp new file mode 100644 index 000000000..88b0b036f --- /dev/null +++ b/tests/functional/lang/parse-okay-dup-attrs-5.exp @@ -0,0 +1 @@ +{ services = { ssh = { enable = true; port = 23; }; }; } diff --git a/tests/functional/lang/parse-okay-dup-attrs-5.nix b/tests/functional/lang/parse-okay-dup-attrs-5.nix new file mode 100644 index 000000000..f4b9efd0c --- /dev/null +++ b/tests/functional/lang/parse-okay-dup-attrs-5.nix @@ -0,0 +1,4 @@ +{ + services.ssh = { enable = true; }; + services.ssh.port = 23; +} diff --git a/tests/functional/lang/parse-okay-dup-attrs-6.exp b/tests/functional/lang/parse-okay-dup-attrs-6.exp new file mode 100644 index 000000000..88b0b036f --- /dev/null +++ b/tests/functional/lang/parse-okay-dup-attrs-6.exp @@ -0,0 +1 @@ +{ services = { ssh = { enable = true; port = 23; }; }; } diff --git a/tests/functional/lang/parse-okay-dup-attrs-6.nix b/tests/functional/lang/parse-okay-dup-attrs-6.nix new file mode 100644 index 000000000..ae6d7a769 --- /dev/null +++ b/tests/functional/lang/parse-okay-dup-attrs-6.nix @@ -0,0 +1,4 @@ +{ + services.ssh.port = 23; + services.ssh = { enable = true; }; +} diff --git a/tests/functional/lang/parse-okay-mixed-nested-attrs-1.exp b/tests/functional/lang/parse-okay-mixed-nested-attrs-1.exp new file mode 100644 index 000000000..89c66f760 --- /dev/null +++ b/tests/functional/lang/parse-okay-mixed-nested-attrs-1.exp @@ -0,0 +1 @@ +{ x = { q = 3; y = 3; z = 3; }; } diff --git a/tests/functional/lang/parse-okay-mixed-nested-attrs-1.nix b/tests/functional/lang/parse-okay-mixed-nested-attrs-1.nix new file mode 100644 index 000000000..fd1001c8c --- /dev/null +++ b/tests/functional/lang/parse-okay-mixed-nested-attrs-1.nix @@ -0,0 +1,4 @@ +{ + x = { y = 3; z = 3; }; + x.q = 3; +} diff --git a/tests/functional/lang/parse-okay-mixed-nested-attrs-2.exp b/tests/functional/lang/parse-okay-mixed-nested-attrs-2.exp new file mode 100644 index 000000000..89c66f760 --- /dev/null +++ b/tests/functional/lang/parse-okay-mixed-nested-attrs-2.exp @@ -0,0 +1 @@ +{ x = { q = 3; y = 3; z = 3; }; } diff --git a/tests/functional/lang/parse-okay-mixed-nested-attrs-2.nix b/tests/functional/lang/parse-okay-mixed-nested-attrs-2.nix new file mode 100644 index 000000000..ad066b680 --- /dev/null +++ b/tests/functional/lang/parse-okay-mixed-nested-attrs-2.nix @@ -0,0 +1,4 @@ +{ + x.q = 3; + x = { y = 3; z = 3; }; +} diff --git a/tests/functional/lang/parse-okay-mixed-nested-attrs-3.exp b/tests/functional/lang/parse-okay-mixed-nested-attrs-3.exp new file mode 100644 index 000000000..b89a59734 --- /dev/null +++ b/tests/functional/lang/parse-okay-mixed-nested-attrs-3.exp @@ -0,0 +1 @@ +{ services = { httpd = { enable = true; }; ssh = { enable = true; port = 123; }; }; } diff --git a/tests/functional/lang/parse-okay-mixed-nested-attrs-3.nix b/tests/functional/lang/parse-okay-mixed-nested-attrs-3.nix new file mode 100644 index 000000000..45a33e480 --- /dev/null +++ b/tests/functional/lang/parse-okay-mixed-nested-attrs-3.nix @@ -0,0 +1,7 @@ +{ + services.ssh.enable = true; + services.ssh = { port = 123; }; + services = { + httpd.enable = true; + }; +} diff --git a/tests/functional/lang/parse-okay-regression-20041027.exp b/tests/functional/lang/parse-okay-regression-20041027.exp new file mode 100644 index 000000000..9df7219e4 --- /dev/null +++ b/tests/functional/lang/parse-okay-regression-20041027.exp @@ -0,0 +1 @@ +({ fetchurl, stdenv }: ((stdenv).mkDerivation { name = "libXi-6.0.1"; src = (fetchurl { md5 = "7e935a42428d63a387b3c048be0f2756"; url = "http://freedesktop.org/~xlibs/release/libXi-6.0.1.tar.bz2"; }); })) diff --git a/tests/functional/lang/parse-okay-regression-20041027.nix b/tests/functional/lang/parse-okay-regression-20041027.nix new file mode 100644 index 000000000..ae2e256ee --- /dev/null +++ b/tests/functional/lang/parse-okay-regression-20041027.nix @@ -0,0 +1,11 @@ +{stdenv, fetchurl /* pkgconfig, libX11 */ }: + +stdenv.mkDerivation { + name = "libXi-6.0.1"; + src = fetchurl { + url = http://freedesktop.org/~xlibs/release/libXi-6.0.1.tar.bz2; + md5 = "7e935a42428d63a387b3c048be0f2756"; + }; +/* buildInputs = [pkgconfig]; + propagatedBuildInputs = [libX11]; */ +} diff --git a/tests/functional/lang/parse-okay-regression-751.exp b/tests/functional/lang/parse-okay-regression-751.exp new file mode 100644 index 000000000..e2ed886fe --- /dev/null +++ b/tests/functional/lang/parse-okay-regression-751.exp @@ -0,0 +1 @@ +(let const = (a: "const"); in ((const { x = "q"; }))) diff --git a/tests/functional/lang/parse-okay-regression-751.nix b/tests/functional/lang/parse-okay-regression-751.nix new file mode 100644 index 000000000..05c78b301 --- /dev/null +++ b/tests/functional/lang/parse-okay-regression-751.nix @@ -0,0 +1,2 @@ +let const = a: "const"; in +''${ const { x = "q"; }}'' diff --git a/tests/functional/lang/parse-okay-subversion.exp b/tests/functional/lang/parse-okay-subversion.exp new file mode 100644 index 000000000..4168ee8bf --- /dev/null +++ b/tests/functional/lang/parse-okay-subversion.exp @@ -0,0 +1 @@ +({ fetchurl, localServer ? false, httpServer ? false, sslSupport ? false, pythonBindings ? false, javaSwigBindings ? false, javahlBindings ? false, stdenv, openssl ? null, httpd ? null, db4 ? null, expat, swig ? null, j2sdk ? null }: assert (expat != null); assert (localServer -> (db4 != null)); assert (httpServer -> ((httpd != null) && ((httpd).expat == expat))); assert (sslSupport -> ((openssl != null) && (httpServer -> ((httpd).openssl == openssl)))); assert (pythonBindings -> ((swig != null) && (swig).pythonSupport)); assert (javaSwigBindings -> ((swig != null) && (swig).javaSupport)); assert (javahlBindings -> (j2sdk != null)); ((stdenv).mkDerivation { builder = /foo/bar; db4 = (if localServer then db4 else null); inherit expat ; inherit httpServer ; httpd = (if httpServer then httpd else null); j2sdk = (if javaSwigBindings then (swig).j2sdk else (if javahlBindings then j2sdk else null)); inherit javaSwigBindings ; inherit javahlBindings ; inherit localServer ; name = "subversion-1.1.1"; openssl = (if sslSupport then openssl else null); patches = (if javahlBindings then [ (/javahl.patch) ] else [ ]); python = (if pythonBindings then (swig).python else null); inherit pythonBindings ; src = (fetchurl { md5 = "a180c3fe91680389c210c99def54d9e0"; url = "http://subversion.tigris.org/tarballs/subversion-1.1.1.tar.bz2"; }); inherit sslSupport ; swig = (if (pythonBindings || javaSwigBindings) then swig else null); })) diff --git a/tests/functional/lang/parse-okay-subversion.nix b/tests/functional/lang/parse-okay-subversion.nix new file mode 100644 index 000000000..356272815 --- /dev/null +++ b/tests/functional/lang/parse-okay-subversion.nix @@ -0,0 +1,43 @@ +{ localServer ? false +, httpServer ? false +, sslSupport ? false +, pythonBindings ? false +, javaSwigBindings ? false +, javahlBindings ? false +, stdenv, fetchurl +, openssl ? null, httpd ? null, db4 ? null, expat, swig ? null, j2sdk ? null +}: + +assert expat != null; +assert localServer -> db4 != null; +assert httpServer -> httpd != null && httpd.expat == expat; +assert sslSupport -> openssl != null && (httpServer -> httpd.openssl == openssl); +assert pythonBindings -> swig != null && swig.pythonSupport; +assert javaSwigBindings -> swig != null && swig.javaSupport; +assert javahlBindings -> j2sdk != null; + +stdenv.mkDerivation { + name = "subversion-1.1.1"; + + builder = /foo/bar; + src = fetchurl { + url = http://subversion.tigris.org/tarballs/subversion-1.1.1.tar.bz2; + md5 = "a180c3fe91680389c210c99def54d9e0"; + }; + + # This is a hopefully temporary fix for the problem that + # libsvnjavahl.so isn't linked against libstdc++, which causes + # loading the library into the JVM to fail. + patches = if javahlBindings then [/javahl.patch] else []; + + openssl = if sslSupport then openssl else null; + httpd = if httpServer then httpd else null; + db4 = if localServer then db4 else null; + swig = if pythonBindings || javaSwigBindings then swig else null; + python = if pythonBindings then swig.python else null; + j2sdk = if javaSwigBindings then swig.j2sdk else + if javahlBindings then j2sdk else null; + + inherit expat localServer httpServer sslSupport + pythonBindings javaSwigBindings javahlBindings; +} diff --git a/tests/functional/lang/parse-okay-url.exp b/tests/functional/lang/parse-okay-url.exp new file mode 100644 index 000000000..e5f0829b0 --- /dev/null +++ b/tests/functional/lang/parse-okay-url.exp @@ -0,0 +1 @@ +[ ("x:x") ("https://svn.cs.uu.nl:12443/repos/trace/trunk") ("http://www2.mplayerhq.hu/MPlayer/releases/fonts/font-arial-iso-8859-1.tar.bz2") ("http://losser.st-lab.cs.uu.nl/~armijn/.nix/gcc-3.3.4-static-nix.tar.gz") ("http://fpdownload.macromedia.com/get/shockwave/flash/english/linux/7.0r25/install_flash_player_7_linux.tar.gz") ("https://ftp5.gwdg.de/pub/linux/archlinux/extra/os/x86_64/unzip-6.0-14-x86_64.pkg.tar.zst") ("ftp://ftp.gtk.org/pub/gtk/v1.2/gtk+-1.2.10.tar.gz") ] diff --git a/tests/functional/lang/parse-okay-url.nix b/tests/functional/lang/parse-okay-url.nix new file mode 100644 index 000000000..08de27d0a --- /dev/null +++ b/tests/functional/lang/parse-okay-url.nix @@ -0,0 +1,8 @@ +[ x:x + https://svn.cs.uu.nl:12443/repos/trace/trunk + http://www2.mplayerhq.hu/MPlayer/releases/fonts/font-arial-iso-8859-1.tar.bz2 + http://losser.st-lab.cs.uu.nl/~armijn/.nix/gcc-3.3.4-static-nix.tar.gz + http://fpdownload.macromedia.com/get/shockwave/flash/english/linux/7.0r25/install_flash_player_7_linux.tar.gz + https://ftp5.gwdg.de/pub/linux/archlinux/extra/os/x86_64/unzip-6.0-14-x86_64.pkg.tar.zst + ftp://ftp.gtk.org/pub/gtk/v1.2/gtk+-1.2.10.tar.gz +] diff --git a/tests/functional/lang/readDir/bar b/tests/functional/lang/readDir/bar new file mode 100644 index 000000000..e69de29bb diff --git a/tests/functional/lang/readDir/foo/git-hates-directories b/tests/functional/lang/readDir/foo/git-hates-directories new file mode 100644 index 000000000..e69de29bb diff --git a/tests/functional/lang/readDir/ldir b/tests/functional/lang/readDir/ldir new file mode 120000 index 000000000..191028156 --- /dev/null +++ b/tests/functional/lang/readDir/ldir @@ -0,0 +1 @@ +foo \ No newline at end of file diff --git a/tests/functional/lang/readDir/linked b/tests/functional/lang/readDir/linked new file mode 120000 index 000000000..c503f86a0 --- /dev/null +++ b/tests/functional/lang/readDir/linked @@ -0,0 +1 @@ +foo/git-hates-directories \ No newline at end of file diff --git a/tests/functional/legacy-ssh-store.sh b/tests/functional/legacy-ssh-store.sh new file mode 100644 index 000000000..71b716b84 --- /dev/null +++ b/tests/functional/legacy-ssh-store.sh @@ -0,0 +1,4 @@ +source common.sh + +# Check that store ping trusted doesn't yet work with ssh:// +nix --store ssh://localhost?remote-store=$TEST_ROOT/other-store store ping --json | jq -e 'has("trusted") | not' diff --git a/tests/functional/linux-sandbox-cert-test.nix b/tests/functional/linux-sandbox-cert-test.nix new file mode 100644 index 000000000..2fc083ea9 --- /dev/null +++ b/tests/functional/linux-sandbox-cert-test.nix @@ -0,0 +1,30 @@ +{ mode }: + +with import ./config.nix; + +mkDerivation ( + { + name = "ssl-export"; + buildCommand = '' + # Add some indirection, otherwise grepping into the debug output finds the string. + report () { echo CERT_$1_IN_SANDBOX; } + + if [ -f /etc/ssl/certs/ca-certificates.crt ]; then + content=$( $TEST_ROOT/log +grepQuietInverse 'error: renaming' $TEST_ROOT/log +grepQuiet 'may not be deterministic' $TEST_ROOT/log + +# Test that sandboxed builds cannot write to /etc easily +# `100` means build failure without extra info, see doc/manual/src/command-ref/status-build-failure.md +expectStderr 100 nix-sandbox-build -E 'with import ./config.nix; mkDerivation { name = "etc-write"; buildCommand = "echo > /etc/test"; }' | + grepQuiet "/etc/test: Permission denied" + + +## Test mounting of SSL certificates into the sandbox +testCert () { + expectation=$1 # "missing" | "present" + mode=$2 # "normal" | "fixed-output" + certFile=$3 # a string that can be the path to a cert file + # `100` means build failure without extra info, see doc/manual/src/command-ref/status-build-failure.md + [ "$mode" == fixed-output ] && ret=1 || ret=100 + expectStderr $ret nix-sandbox-build linux-sandbox-cert-test.nix --argstr mode "$mode" --option ssl-cert-file "$certFile" | + grepQuiet "CERT_${expectation}_IN_SANDBOX" +} + +nocert=$TEST_ROOT/no-cert-file.pem +cert=$TEST_ROOT/some-cert-file.pem +echo -n "CERT_CONTENT" > $cert + +# No cert in sandbox when not a fixed-output derivation +testCert missing normal "$cert" + +# No cert in sandbox when ssl-cert-file is empty +testCert missing fixed-output "" + +# No cert in sandbox when ssl-cert-file is a nonexistent file +testCert missing fixed-output "$nocert" + +# Cert in sandbox when ssl-cert-file is set to an existing file +testCert present fixed-output "$cert" diff --git a/tests/functional/local-store.sh b/tests/functional/local-store.sh new file mode 100644 index 000000000..89502f864 --- /dev/null +++ b/tests/functional/local-store.sh @@ -0,0 +1,22 @@ +source common.sh + +cd $TEST_ROOT + +echo example > example.txt +mkdir -p ./x + +NIX_STORE_DIR=$TEST_ROOT/x + +CORRECT_PATH=$(nix-store --store ./x --add example.txt) + +PATH1=$(nix path-info --store ./x $CORRECT_PATH) +[ $CORRECT_PATH == $PATH1 ] + +PATH2=$(nix path-info --store "$PWD/x" $CORRECT_PATH) +[ $CORRECT_PATH == $PATH2 ] + +PATH3=$(nix path-info --store "local?root=$PWD/x" $CORRECT_PATH) +[ $CORRECT_PATH == $PATH3 ] + +# Ensure store ping trusted works with local store +nix --store ./x store ping --json | jq -e '.trusted' diff --git a/tests/functional/local.mk b/tests/functional/local.mk new file mode 100644 index 000000000..d60f1e08e --- /dev/null +++ b/tests/functional/local.mk @@ -0,0 +1,146 @@ +nix_tests = \ + test-infra.sh \ + init.sh \ + flakes/flakes.sh \ + flakes/run.sh \ + flakes/mercurial.sh \ + flakes/circular.sh \ + flakes/init.sh \ + flakes/inputs.sh \ + flakes/follow-paths.sh \ + flakes/bundle.sh \ + flakes/check.sh \ + flakes/unlocked-override.sh \ + flakes/absolute-paths.sh \ + flakes/build-paths.sh \ + flakes/flake-in-submodule.sh \ + gc.sh \ + nix-collect-garbage-d.sh \ + remote-store.sh \ + legacy-ssh-store.sh \ + lang.sh \ + lang-test-infra.sh \ + experimental-features.sh \ + fetchMercurial.sh \ + gc-auto.sh \ + user-envs.sh \ + user-envs-migration.sh \ + binary-cache.sh \ + multiple-outputs.sh \ + nix-build.sh \ + gc-concurrent.sh \ + repair.sh \ + fixed.sh \ + export-graph.sh \ + timeout.sh \ + fetchGitRefs.sh \ + gc-runtime.sh \ + tarball.sh \ + fetchGit.sh \ + fetchurl.sh \ + fetchPath.sh \ + fetchTree-file.sh \ + simple.sh \ + referrers.sh \ + optimise-store.sh \ + substitute-with-invalid-ca.sh \ + signing.sh \ + hash.sh \ + gc-non-blocking.sh \ + check.sh \ + nix-shell.sh \ + check-refs.sh \ + build-remote-input-addressed.sh \ + secure-drv-outputs.sh \ + restricted.sh \ + fetchGitSubmodules.sh \ + flakes/search-root.sh \ + readfile-context.sh \ + nix-channel.sh \ + recursive.sh \ + dependencies.sh \ + check-reqs.sh \ + build-remote-content-addressed-fixed.sh \ + build-remote-content-addressed-floating.sh \ + build-remote-trustless-should-pass-0.sh \ + build-remote-trustless-should-pass-1.sh \ + build-remote-trustless-should-pass-2.sh \ + build-remote-trustless-should-pass-3.sh \ + build-remote-trustless-should-fail-0.sh \ + nar-access.sh \ + pure-eval.sh \ + eval.sh \ + repl.sh \ + binary-cache-build-remote.sh \ + search.sh \ + logging.sh \ + export.sh \ + config.sh \ + add.sh \ + local-store.sh \ + filter-source.sh \ + misc.sh \ + dump-db.sh \ + linux-sandbox.sh \ + supplementary-groups.sh \ + build-dry.sh \ + structured-attrs.sh \ + shell.sh \ + brotli.sh \ + zstd.sh \ + compression-levels.sh \ + nix-copy-ssh.sh \ + nix-copy-ssh-ng.sh \ + post-hook.sh \ + function-trace.sh \ + flakes/config.sh \ + fmt.sh \ + eval-store.sh \ + why-depends.sh \ + derivation-json.sh \ + import-derivation.sh \ + nix_path.sh \ + case-hack.sh \ + placeholders.sh \ + ssh-relay.sh \ + build.sh \ + build-delete.sh \ + output-normalization.sh \ + selfref-gc.sh \ + db-migration.sh \ + bash-profile.sh \ + pass-as-file.sh \ + nix-profile.sh \ + suggestions.sh \ + store-ping.sh \ + fetchClosure.sh \ + completions.sh \ + flakes/show.sh \ + impure-derivations.sh \ + path-from-hash-part.sh \ + test-libstoreconsumer.sh \ + toString-path.sh \ + read-only-store.sh \ + nested-sandboxing.sh + +ifeq ($(HAVE_LIBCPUID), 1) + nix_tests += compute-levels.sh +endif + +ifeq ($(BUILD_SHARED_LIBS), 1) + nix_tests += plugins.sh +endif + +$(d)/test-libstoreconsumer.sh.test $(d)/test-libstoreconsumer.sh.test-debug: \ + $(d)/test-libstoreconsumer/test-libstoreconsumer +$(d)/plugins.sh.test $(d)/plugins.sh.test-debug: \ + $(d)/plugins/libplugintest.$(SO_EXT) + +install-tests += $(foreach x, $(nix_tests), $(d)/$(x)) + +test-clean-files := \ + $(d)/common/vars-and-functions.sh \ + $(d)/config.nix + +clean-files += $(test-clean-files) +test-deps += $(test-clean-files) diff --git a/tests/functional/logging.sh b/tests/functional/logging.sh new file mode 100644 index 000000000..1481b9b36 --- /dev/null +++ b/tests/functional/logging.sh @@ -0,0 +1,26 @@ +source common.sh + +clearStore + +path=$(nix-build dependencies.nix --no-out-link) + +# Test nix-store -l. +[ "$(nix-store -l $path)" = FOO ] + +# Test compressed logs. +clearStore +rm -rf $NIX_LOG_DIR +(! nix-store -l $path) +nix-build dependencies.nix --no-out-link --compress-build-log +[ "$(nix-store -l $path)" = FOO ] + +# test whether empty logs work fine with `nix log`. +builder="$(mktemp)" +echo -e "#!/bin/sh\nmkdir \$out" > "$builder" +outp="$(nix-build -E \ + 'with import ./config.nix; mkDerivation { name = "fnord"; builder = '"$builder"'; }' \ + --out-link "$(mktemp -d)/result")" + +test -d "$outp" + +nix log "$outp" diff --git a/tests/functional/misc.sh b/tests/functional/misc.sh new file mode 100644 index 000000000..af96d20bd --- /dev/null +++ b/tests/functional/misc.sh @@ -0,0 +1,32 @@ +source common.sh + +# Tests miscellaneous commands. + +# Do all commands have help? +#nix-env --help | grepQuiet install +#nix-store --help | grepQuiet realise +#nix-instantiate --help | grepQuiet eval +#nix-hash --help | grepQuiet base32 + +# Can we ask for the version number? +nix-env --version | grep "$version" + +# Usage errors. +expect 1 nix-env --foo 2>&1 | grep "no operation" +expect 1 nix-env -q --foo 2>&1 | grep "unknown flag" + +# Eval Errors. +eval_arg_res=$(nix-instantiate --eval -E 'let a = {} // a; in a.foo' 2>&1 || true) +echo $eval_arg_res | grep "at «string»:1:15:" +echo $eval_arg_res | grep "infinite recursion encountered" + +eval_stdin_res=$(echo 'let a = {} // a; in a.foo' | nix-instantiate --eval -E - 2>&1 || true) +echo $eval_stdin_res | grep "at «stdin»:1:15:" +echo $eval_stdin_res | grep "infinite recursion encountered" + +# Attribute path errors +expectStderr 1 nix-instantiate --eval -E '{}' -A '"x' | grepQuiet "missing closing quote in selection path" +expectStderr 1 nix-instantiate --eval -E '[]' -A 'x' | grepQuiet "should be a set" +expectStderr 1 nix-instantiate --eval -E '{}' -A '1' | grepQuiet "should be a list" +expectStderr 1 nix-instantiate --eval -E '{}' -A '.' | grepQuiet "empty attribute name" +expectStderr 1 nix-instantiate --eval -E '[]' -A '1' | grepQuiet "out of range" diff --git a/tests/functional/multiple-outputs.nix b/tests/functional/multiple-outputs.nix new file mode 100644 index 000000000..413d392e4 --- /dev/null +++ b/tests/functional/multiple-outputs.nix @@ -0,0 +1,130 @@ +with import ./config.nix; + +rec { + + # Want to ensure that "out" doesn't get a suffix on it's path. + nameCheck = mkDerivation { + name = "multiple-outputs-a"; + outputs = [ "out" "dev" ]; + builder = builtins.toFile "builder.sh" + '' + mkdir $first $second + test -z $all + echo "first" > $first/file + echo "second" > $second/file + ln -s $first $second/link + ''; + helloString = "Hello, world!"; + }; + + a = mkDerivation { + name = "multiple-outputs-a"; + outputs = [ "first" "second" ]; + builder = builtins.toFile "builder.sh" + '' + mkdir $first $second + test -z $all + echo "first" > $first/file + echo "second" > $second/file + ln -s $first $second/link + ''; + helloString = "Hello, world!"; + }; + + use-a = mkDerivation { + name = "use-a"; + inherit (a) first second; + builder = builtins.toFile "builder.sh" + '' + cat $first/file $second/file >$out + ''; + }; + + b = mkDerivation { + defaultOutput = assert a.second.helloString == "Hello, world!"; a; + firstOutput = assert a.outputName == "first"; a.first.first; + secondOutput = assert a.second.outputName == "second"; a.second.first.first.second.second.first.second; + allOutputs = a.all; + name = "multiple-outputs-b"; + builder = builtins.toFile "builder.sh" + '' + mkdir $out + test "$firstOutput $secondOutput" = "$allOutputs" + test "$defaultOutput" = "$firstOutput" + test "$(cat $firstOutput/file)" = "first" + test "$(cat $secondOutput/file)" = "second" + echo "success" > $out/file + ''; + }; + + c = mkDerivation { + name = "multiple-outputs-c"; + drv = b.drvPath; + builder = builtins.toFile "builder.sh" + '' + mkdir $out + ln -s $drv $out/drv + ''; + }; + + d = mkDerivation { + name = "multiple-outputs-d"; + drv = builtins.unsafeDiscardOutputDependency b.drvPath; + builder = builtins.toFile "builder.sh" + '' + mkdir $out + echo $drv > $out/drv + ''; + }; + + cyclic = (mkDerivation { + name = "cyclic-outputs"; + outputs = [ "a" "b" "c" ]; + builder = builtins.toFile "builder.sh" + '' + mkdir $a $b $c + echo $a > $b/foo + echo $b > $c/bar + echo $c > $a/baz + ''; + }).a; + + e = mkDerivation { + name = "multiple-outputs-e"; + outputs = [ "a_a" "b" "c" ]; + meta.outputsToInstall = [ "a_a" "b" ]; + buildCommand = "mkdir $a_a $b $c"; + }; + + independent = mkDerivation { + name = "multiple-outputs-independent"; + outputs = [ "first" "second" ]; + builder = builtins.toFile "builder.sh" + '' + mkdir $first $second + test -z $all + echo "first" > $first/file + echo "second" > $second/file + ''; + }; + + use-independent = mkDerivation { + name = "use-independent"; + inherit (a) first second; + builder = builtins.toFile "builder.sh" + '' + cat $first/file $second/file >$out + ''; + }; + + invalid-output-name-1 = mkDerivation { + name = "invalid-output-name-1"; + outputs = [ "out/"]; + }; + + invalid-output-name-2 = mkDerivation { + name = "invalid-output-name-2"; + outputs = [ "x" "foo$"]; + }; + +} diff --git a/tests/functional/multiple-outputs.sh b/tests/functional/multiple-outputs.sh new file mode 100644 index 000000000..330600d08 --- /dev/null +++ b/tests/functional/multiple-outputs.sh @@ -0,0 +1,88 @@ +source common.sh + +clearStore + +rm -f $TEST_ROOT/result* + +# Test whether the output names match our expectations +outPath=$(nix-instantiate multiple-outputs.nix --eval -A nameCheck.out.outPath) +[ "$(echo "$outPath" | sed -E 's_^".*/[^-/]*-([^/]*)"$_\1_')" = "multiple-outputs-a" ] +outPath=$(nix-instantiate multiple-outputs.nix --eval -A nameCheck.dev.outPath) +[ "$(echo "$outPath" | sed -E 's_^".*/[^-/]*-([^/]*)"$_\1_')" = "multiple-outputs-a-dev" ] + +# Test whether read-only evaluation works when referring to the +# ‘drvPath’ attribute. +echo "evaluating c..." +#drvPath=$(nix-instantiate multiple-outputs.nix -A c --readonly-mode) + +# And check whether the resulting derivation explicitly depends on all +# outputs. +drvPath=$(nix-instantiate multiple-outputs.nix -A c) +#[ "$drvPath" = "$drvPath2" ] +grepQuiet 'multiple-outputs-a.drv",\["first","second"\]' $drvPath +grepQuiet 'multiple-outputs-b.drv",\["out"\]' $drvPath + +# While we're at it, test the ‘unsafeDiscardOutputDependency’ primop. +outPath=$(nix-build multiple-outputs.nix -A d --no-out-link) +drvPath=$(cat $outPath/drv) +outPath=$(nix-store -q $drvPath) +(! [ -e "$outPath" ]) + +# Do a build of something that depends on a derivation with multiple +# outputs. +echo "building b..." +outPath=$(nix-build multiple-outputs.nix -A b --no-out-link) +echo "output path is $outPath" +[ "$(cat "$outPath"/file)" = "success" ] + +# Test nix-build on a derivation with multiple outputs. +outPath1=$(nix-build multiple-outputs.nix -A a -o $TEST_ROOT/result) +[ -e $TEST_ROOT/result-first ] +(! [ -e $TEST_ROOT/result-second ]) +nix-build multiple-outputs.nix -A a.all -o $TEST_ROOT/result +[ "$(cat $TEST_ROOT/result-first/file)" = "first" ] +[ "$(cat $TEST_ROOT/result-second/file)" = "second" ] +[ "$(cat $TEST_ROOT/result-second/link/file)" = "first" ] +hash1=$(nix-store -q --hash $TEST_ROOT/result-second) + +outPath2=$(nix-build $(nix-instantiate multiple-outputs.nix -A a) --no-out-link) +[[ $outPath1 = $outPath2 ]] + +outPath2=$(nix-build $(nix-instantiate multiple-outputs.nix -A a.first) --no-out-link) +[[ $outPath1 = $outPath2 ]] + +outPath2=$(nix-build $(nix-instantiate multiple-outputs.nix -A a.second) --no-out-link) +[[ $(cat $outPath2/file) = second ]] + +[[ $(nix-build $(nix-instantiate multiple-outputs.nix -A a.all) --no-out-link | wc -l) -eq 2 ]] + +# Delete one of the outputs and rebuild it. This will cause a hash +# rewrite. +env -u NIX_REMOTE nix store delete $TEST_ROOT/result-second --ignore-liveness +nix-build multiple-outputs.nix -A a.all -o $TEST_ROOT/result +[ "$(cat $TEST_ROOT/result-second/file)" = "second" ] +[ "$(cat $TEST_ROOT/result-second/link/file)" = "first" ] +hash2=$(nix-store -q --hash $TEST_ROOT/result-second) +[ "$hash1" = "$hash2" ] + +# Make sure that nix-build works on derivations with multiple outputs. +echo "building a.first..." +nix-build multiple-outputs.nix -A a.first --no-out-link + +# Cyclic outputs should be rejected. +echo "building cyclic..." +if nix-build multiple-outputs.nix -A cyclic --no-out-link; then + echo "Cyclic outputs incorrectly accepted!" + exit 1 +fi + +# Do a GC. This should leave an empty store. +echo "collecting garbage..." +rm $TEST_ROOT/result* +nix-store --gc --keep-derivations --keep-outputs +nix-store --gc --print-roots +rm -rf $NIX_STORE_DIR/.links +rmdir $NIX_STORE_DIR + +expect 1 nix build -f multiple-outputs.nix invalid-output-name-1 2>&1 | grep 'contains illegal character' +expect 1 nix build -f multiple-outputs.nix invalid-output-name-2 2>&1 | grep 'contains illegal character' diff --git a/tests/functional/nar-access.nix b/tests/functional/nar-access.nix new file mode 100644 index 000000000..0e2a7f721 --- /dev/null +++ b/tests/functional/nar-access.nix @@ -0,0 +1,23 @@ +with import ./config.nix; + +rec { + a = mkDerivation { + name = "nar-index-a"; + builder = builtins.toFile "builder.sh" + '' + mkdir $out + mkdir $out/foo + touch $out/foo-x + touch $out/foo/bar + touch $out/foo/baz + touch $out/qux + mkdir $out/zyx + + cat >$out/foo/data < $narFile + +# Check that find and nar ls match. +( cd $storePath; find . | sort ) > files.find +nix nar ls -R -d $narFile "" | sort > files.ls-nar +diff -u files.find files.ls-nar + +# Check that file contents of data match. +nix nar cat $narFile /foo/data > data.cat-nar +diff -u data.cat-nar $storePath/foo/data + +# Check that file contents of baz match. +nix nar cat $narFile /foo/baz > baz.cat-nar +diff -u baz.cat-nar $storePath/foo/baz + +nix store cat $storePath/foo/baz > baz.cat-nar +diff -u baz.cat-nar $storePath/foo/baz + +# Test --json. +diff -u \ + <(nix nar ls --json $narFile / | jq -S) \ + <(echo '{"type":"directory","entries":{"foo":{},"foo-x":{},"qux":{},"zyx":{}}}' | jq -S) +diff -u \ + <(nix nar ls --json -R $narFile /foo | jq -S) \ + <(echo '{"type":"directory","entries":{"bar":{"type":"regular","size":0,"narOffset":368},"baz":{"type":"regular","size":0,"narOffset":552},"data":{"type":"regular","size":58,"narOffset":736}}}' | jq -S) +diff -u \ + <(nix nar ls --json -R $narFile /foo/bar | jq -S) \ + <(echo '{"type":"regular","size":0,"narOffset":368}' | jq -S) +diff -u \ + <(nix store ls --json $storePath | jq -S) \ + <(echo '{"type":"directory","entries":{"foo":{},"foo-x":{},"qux":{},"zyx":{}}}' | jq -S) +diff -u \ + <(nix store ls --json -R $storePath/foo | jq -S) \ + <(echo '{"type":"directory","entries":{"bar":{"type":"regular","size":0},"baz":{"type":"regular","size":0},"data":{"type":"regular","size":58}}}' | jq -S) +diff -u \ + <(nix store ls --json -R $storePath/foo/bar| jq -S) \ + <(echo '{"type":"regular","size":0}' | jq -S) + +# Test missing files. +expect 1 nix store ls --json -R $storePath/xyzzy 2>&1 | grep 'does not exist in NAR' +expect 1 nix store ls $storePath/xyzzy 2>&1 | grep 'does not exist' + +# Test failure to dump. +if nix-store --dump $storePath >/dev/full ; then + echo "dumping to /dev/full should fail" + exit -1 +fi diff --git a/tests/functional/nested-sandboxing.sh b/tests/functional/nested-sandboxing.sh new file mode 100644 index 000000000..61fe043c6 --- /dev/null +++ b/tests/functional/nested-sandboxing.sh @@ -0,0 +1,11 @@ +source common.sh +# This test is run by `tests/functional/nested-sandboxing/runner.nix` in an extra layer of sandboxing. +[[ -d /nix/store ]] || skipTest "running this test without Nix's deps being drawn from /nix/store is not yet supported" + +requireSandboxSupport + +source ./nested-sandboxing/command.sh + +expectStderr 100 runNixBuild badStoreUrl 2 | grepQuiet '`sandbox-build-dir` must not contain' + +runNixBuild goodStoreUrl 5 diff --git a/tests/functional/nested-sandboxing/command.sh b/tests/functional/nested-sandboxing/command.sh new file mode 100644 index 000000000..69366486c --- /dev/null +++ b/tests/functional/nested-sandboxing/command.sh @@ -0,0 +1,29 @@ +export NIX_BIN_DIR=$(dirname $(type -p nix)) +# TODO Get Nix and its closure more flexibly +export EXTRA_SANDBOX="/nix/store $(dirname $NIX_BIN_DIR)" + +badStoreUrl () { + local altitude=$1 + echo $TEST_ROOT/store-$altitude +} + +goodStoreUrl () { + local altitude=$1 + echo $("badStoreUrl" "$altitude")?store=/foo-$altitude +} + +# The non-standard sandbox-build-dir helps ensure that we get the same behavior +# whether this test is being run in a derivation as part of the nix build or +# being manually run by a developer outside a derivation +runNixBuild () { + local storeFun=$1 + local altitude=$2 + nix-build \ + --no-substitute --no-out-link \ + --store "$("$storeFun" "$altitude")" \ + --extra-sandbox-paths "$EXTRA_SANDBOX" \ + ./nested-sandboxing/runner.nix \ + --arg altitude "$((altitude - 1))" \ + --argstr storeFun "$storeFun" \ + --sandbox-build-dir /build-non-standard +} diff --git a/tests/functional/nested-sandboxing/runner.nix b/tests/functional/nested-sandboxing/runner.nix new file mode 100644 index 000000000..9a5822c88 --- /dev/null +++ b/tests/functional/nested-sandboxing/runner.nix @@ -0,0 +1,24 @@ +{ altitude, storeFun }: + +with import ../config.nix; + +mkDerivation { + name = "nested-sandboxing"; + busybox = builtins.getEnv "busybox"; + EXTRA_SANDBOX = builtins.getEnv "EXTRA_SANDBOX"; + buildCommand = if altitude == 0 then '' + echo Deep enough! > $out + '' else '' + cp -r ${../common} ./common + cp ${../common.sh} ./common.sh + cp ${../config.nix} ./config.nix + cp -r ${./.} ./nested-sandboxing + + export PATH=${builtins.getEnv "NIX_BIN_DIR"}:$PATH + + source common.sh + source ./nested-sandboxing/command.sh + + runNixBuild ${storeFun} ${toString altitude} >> $out + ''; +} diff --git a/tests/functional/nix-build-examples.nix b/tests/functional/nix-build-examples.nix new file mode 100644 index 000000000..e54dbbf62 --- /dev/null +++ b/tests/functional/nix-build-examples.nix @@ -0,0 +1,33 @@ +with import ./config.nix; + +rec { + + input0 = mkDerivation { + name = "dependencies-input-0"; + buildCommand = "mkdir $out; echo foo > $out/bar"; + }; + + input1 = mkDerivation { + name = "dependencies-input-1"; + buildCommand = "mkdir $out; echo FOO > $out/foo"; + }; + + input2 = mkDerivation { + name = "dependencies-input-2"; + buildCommand = '' + mkdir $out + echo BAR > $out/bar + echo ${input0} > $out/input0 + ''; + }; + + body = mkDerivation { + name = "dependencies-top"; + builder = ./dependencies.builder0.sh + "/FOOBAR/../."; + input1 = input1 + "/."; + input2 = "${input2}/."; + input1_drv = input1; + meta.description = "Random test package"; + }; + +} diff --git a/tests/functional/nix-build.sh b/tests/functional/nix-build.sh new file mode 100644 index 000000000..44a5a14cd --- /dev/null +++ b/tests/functional/nix-build.sh @@ -0,0 +1,43 @@ +source common.sh + +clearStore + +outPath=$(nix-build dependencies.nix -o $TEST_ROOT/result) +test "$(cat $TEST_ROOT/result/foobar)" = FOOBAR + +# The result should be retained by a GC. +echo A +target=$(readLink $TEST_ROOT/result) +echo B +echo target is $target +nix-store --gc +test -e $target/foobar + +# But now it should be gone. +rm $TEST_ROOT/result +nix-store --gc +if test -e $target/foobar; then false; fi + +outPath2=$(nix-build $(nix-instantiate dependencies.nix) --no-out-link) +[[ $outPath = $outPath2 ]] + +outPath2=$(nix-build $(nix-instantiate dependencies.nix)!out --no-out-link) +[[ $outPath = $outPath2 ]] + +outPath2=$(nix-store -r $(nix-instantiate --add-root $TEST_ROOT/indirect dependencies.nix)!out) +[[ $outPath = $outPath2 ]] + +# The order of the paths on stdout must correspond to the -A options +# https://github.com/NixOS/nix/issues/4197 + +input0="$(nix-build nix-build-examples.nix -A input0 --no-out-link)" +input1="$(nix-build nix-build-examples.nix -A input1 --no-out-link)" +input2="$(nix-build nix-build-examples.nix -A input2 --no-out-link)" +body="$(nix-build nix-build-examples.nix -A body --no-out-link)" + +outPathsA="$(echo $(nix-build nix-build-examples.nix -A input0 -A input1 -A input2 -A body --no-out-link))" +[[ "$outPathsA" = "$input0 $input1 $input2 $body" ]] + +# test a different ordering to make sure it fails, not just in 23 out of 24 permutations +outPathsB="$(echo $(nix-build nix-build-examples.nix -A body -A input1 -A input2 -A input0 --no-out-link))" +[[ "$outPathsB" = "$body $input1 $input2 $input0" ]] diff --git a/tests/functional/nix-channel.sh b/tests/functional/nix-channel.sh new file mode 100644 index 000000000..b5d935004 --- /dev/null +++ b/tests/functional/nix-channel.sh @@ -0,0 +1,66 @@ +source common.sh + +clearProfiles + +rm -f $TEST_HOME/.nix-channels $TEST_HOME/.nix-profile + +# Test add/list/remove. +nix-channel --add http://foo/bar xyzzy +nix-channel --list | grepQuiet http://foo/bar +nix-channel --remove xyzzy +[[ $(nix-channel --list-generations | wc -l) == 1 ]] + +[ -e $TEST_HOME/.nix-channels ] +[ "$(cat $TEST_HOME/.nix-channels)" = '' ] + +# Test the XDG Base Directories support + +export NIX_CONFIG="use-xdg-base-directories = true" + +nix-channel --add http://foo/bar xyzzy +nix-channel --list | grepQuiet http://foo/bar +nix-channel --remove xyzzy + +unset NIX_CONFIG + +[ -e $TEST_HOME/.local/state/nix/channels ] +[ "$(cat $TEST_HOME/.local/state/nix/channels)" = '' ] + +# Create a channel. +rm -rf $TEST_ROOT/foo +mkdir -p $TEST_ROOT/foo +nix copy --to file://$TEST_ROOT/foo?compression="bzip2" $(nix-store -r $(nix-instantiate dependencies.nix)) +rm -rf $TEST_ROOT/nixexprs +mkdir -p $TEST_ROOT/nixexprs +cp config.nix dependencies.nix dependencies.builder*.sh $TEST_ROOT/nixexprs/ +ln -s dependencies.nix $TEST_ROOT/nixexprs/default.nix +(cd $TEST_ROOT && tar cvf - nixexprs) | bzip2 > $TEST_ROOT/foo/nixexprs.tar.bz2 + +# Test the update action. +nix-channel --add file://$TEST_ROOT/foo +nix-channel --update +[[ $(nix-channel --list-generations | wc -l) == 2 ]] + +# Do a query. +nix-env -qa \* --meta --xml --out-path > $TEST_ROOT/meta.xml +grepQuiet 'meta.*description.*Random test package' $TEST_ROOT/meta.xml +grepQuiet 'item.*attrPath="foo".*name="dependencies-top"' $TEST_ROOT/meta.xml + +# Do an install. +nix-env -i dependencies-top +[ -e $TEST_HOME/.nix-profile/foobar ] + +# Test updating from a tarball +nix-channel --add file://$TEST_ROOT/foo/nixexprs.tar.bz2 bar +nix-channel --update + +# Do a query. +nix-env -qa \* --meta --xml --out-path > $TEST_ROOT/meta.xml +grepQuiet 'meta.*description.*Random test package' $TEST_ROOT/meta.xml +grepQuiet 'item.*attrPath="bar".*name="dependencies-top"' $TEST_ROOT/meta.xml +grepQuiet 'item.*attrPath="foo".*name="dependencies-top"' $TEST_ROOT/meta.xml + +# Do an install. +nix-env -i dependencies-top +[ -e $TEST_HOME/.nix-profile/foobar ] + diff --git a/tests/functional/nix-collect-garbage-d.sh b/tests/functional/nix-collect-garbage-d.sh new file mode 100644 index 000000000..bf30f8938 --- /dev/null +++ b/tests/functional/nix-collect-garbage-d.sh @@ -0,0 +1,40 @@ +source common.sh + +clearStore + +## Test `nix-collect-garbage -d` + +# TODO make `nix-env` doesn't work with CA derivations, and make +# `ca/nix-collect-garbage-d.sh` wrapper. + +testCollectGarbageD () { + clearProfiles + # Run two `nix-env` commands, should create two generations of + # the profile + nix-env -f ./user-envs.nix -i foo-1.0 "$@" + nix-env -f ./user-envs.nix -i foo-2.0pre1 "$@" + [[ $(nix-env --list-generations "$@" | wc -l) -eq 2 ]] + + # Clear the profile history. There should be only one generation + # left + nix-collect-garbage -d + [[ $(nix-env --list-generations "$@" | wc -l) -eq 1 ]] +} + +testCollectGarbageD + +# Run the same test, but forcing the profiles an arbitrary location. +rm ~/.nix-profile +ln -s $TEST_ROOT/blah ~/.nix-profile +testCollectGarbageD + +# Run the same test, but forcing the profiles at their legacy location under +# /nix/var/nix. +# +# Note that we *don't* use the default profile; `nix-collect-garbage` will +# need to check the legacy conditional unconditionally not just follow +# `~/.nix-profile` to pass this test. +# +# Regression test for #8294 +rm ~/.nix-profile +testCollectGarbageD --profile "$NIX_STATE_DIR/profiles/per-user/me" diff --git a/tests/functional/nix-copy-ssh-ng.sh b/tests/functional/nix-copy-ssh-ng.sh new file mode 100644 index 000000000..45e53c9c0 --- /dev/null +++ b/tests/functional/nix-copy-ssh-ng.sh @@ -0,0 +1,18 @@ +source common.sh + +clearStore +clearCache + +remoteRoot=$TEST_ROOT/store2 +chmod -R u+w "$remoteRoot" || true +rm -rf "$remoteRoot" + +outPath=$(nix-build --no-out-link dependencies.nix) + +nix store ping --store "ssh-ng://localhost?store=$NIX_STORE_DIR&remote-store=$remoteRoot%3fstore=$NIX_STORE_DIR%26real=$remoteRoot$NIX_STORE_DIR" + +# Regression test for https://github.com/NixOS/nix/issues/6253 +nix copy --to "ssh-ng://localhost?store=$NIX_STORE_DIR&remote-store=$remoteRoot%3fstore=$NIX_STORE_DIR%26real=$remoteRoot$NIX_STORE_DIR" $outPath --no-check-sigs & +nix copy --to "ssh-ng://localhost?store=$NIX_STORE_DIR&remote-store=$remoteRoot%3fstore=$NIX_STORE_DIR%26real=$remoteRoot$NIX_STORE_DIR" $outPath --no-check-sigs + +[ -f $remoteRoot$outPath/foobar ] diff --git a/tests/functional/nix-copy-ssh.sh b/tests/functional/nix-copy-ssh.sh new file mode 100644 index 000000000..eb801548d --- /dev/null +++ b/tests/functional/nix-copy-ssh.sh @@ -0,0 +1,20 @@ +source common.sh + +clearStore +clearCache + +remoteRoot=$TEST_ROOT/store2 +chmod -R u+w "$remoteRoot" || true +rm -rf "$remoteRoot" + +outPath=$(nix-build --no-out-link dependencies.nix) + +nix copy --to "ssh://localhost?store=$NIX_STORE_DIR&remote-store=$remoteRoot%3fstore=$NIX_STORE_DIR%26real=$remoteRoot$NIX_STORE_DIR" $outPath + +[ -f $remoteRoot$outPath/foobar ] + +clearStore + +nix copy --no-check-sigs --from "ssh://localhost?store=$NIX_STORE_DIR&remote-store=$remoteRoot%3fstore=$NIX_STORE_DIR%26real=$remoteRoot$NIX_STORE_DIR" $outPath + +[ -f $outPath/foobar ] diff --git a/tests/functional/nix-daemon-untrusting.sh b/tests/functional/nix-daemon-untrusting.sh new file mode 100755 index 000000000..bcdb70989 --- /dev/null +++ b/tests/functional/nix-daemon-untrusting.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +exec nix-daemon --force-untrusted "$@" diff --git a/tests/functional/nix-profile.sh b/tests/functional/nix-profile.sh new file mode 100644 index 000000000..7c478a0cd --- /dev/null +++ b/tests/functional/nix-profile.sh @@ -0,0 +1,187 @@ +source common.sh + +clearStore +clearProfiles + +enableFeatures "ca-derivations" +restartDaemon + +# Make a flake. +flake1Dir=$TEST_ROOT/flake1 +mkdir -p $flake1Dir + +cat > $flake1Dir/flake.nix < \$out/bin/hello < $flake1Dir/who +printf 1.0 > $flake1Dir/version +printf false > $flake1Dir/ca.nix + +cp ./config.nix $flake1Dir/ + +# Test upgrading from nix-env. +nix-env -f ./user-envs.nix -i foo-1.0 +nix profile list | grep -A2 'Index:.*0' | grep 'Store paths:.*foo-1.0' +nix profile install $flake1Dir -L +nix profile list | grep -A4 'Index:.*1' | grep 'Locked flake URL:.*narHash' +[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello World" ]] +[ -e $TEST_HOME/.nix-profile/share/man ] +(! [ -e $TEST_HOME/.nix-profile/include ]) +nix profile history +nix profile history | grep "packages.$system.default: ∅ -> 1.0" +nix profile diff-closures | grep 'env-manifest.nix: ε → ∅' + +# Test XDG Base Directories support + +export NIX_CONFIG="use-xdg-base-directories = true" +nix profile remove 1 +nix profile install $flake1Dir +[[ $($TEST_HOME/.local/state/nix/profile/bin/hello) = "Hello World" ]] +unset NIX_CONFIG + +# Test upgrading a package. +printf NixOS > $flake1Dir/who +printf 2.0 > $flake1Dir/version +nix profile upgrade 1 +[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello NixOS" ]] +nix profile history | grep "packages.$system.default: 1.0, 1.0-man -> 2.0, 2.0-man" + +# Test 'history', 'diff-closures'. +nix profile diff-closures + +# Test rollback. +nix profile rollback +[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello World" ]] + +# Test uninstall. +[ -e $TEST_HOME/.nix-profile/bin/foo ] +nix profile remove 0 +(! [ -e $TEST_HOME/.nix-profile/bin/foo ]) +nix profile history | grep 'foo: 1.0 -> ∅' +nix profile diff-closures | grep 'Version 3 -> 4' + +# Test installing a non-flake package. +nix profile install --file ./simple.nix '' +[[ $(cat $TEST_HOME/.nix-profile/hello) = "Hello World!" ]] +nix profile remove 1 +nix profile install $(nix-build --no-out-link ./simple.nix) +[[ $(cat $TEST_HOME/.nix-profile/hello) = "Hello World!" ]] + +# Test wipe-history. +nix profile wipe-history +[[ $(nix profile history | grep Version | wc -l) -eq 1 ]] + +# Test upgrade to CA package. +printf true > $flake1Dir/ca.nix +printf 3.0 > $flake1Dir/version +nix profile upgrade 0 +nix profile history | grep "packages.$system.default: 1.0, 1.0-man -> 3.0, 3.0-man" + +# Test new install of CA package. +nix profile remove 0 +printf 4.0 > $flake1Dir/version +printf Utrecht > $flake1Dir/who +nix profile install $flake1Dir +[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello Utrecht" ]] +[[ $(nix path-info --json $(realpath $TEST_HOME/.nix-profile/bin/hello) | jq -r .[].ca) =~ fixed:r:sha256: ]] + +# Override the outputs. +nix profile remove 0 1 +nix profile install "$flake1Dir^*" +[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello Utrecht" ]] +[ -e $TEST_HOME/.nix-profile/share/man ] +[ -e $TEST_HOME/.nix-profile/include ] + +printf Nix > $flake1Dir/who +nix profile upgrade 0 +[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello Nix" ]] +[ -e $TEST_HOME/.nix-profile/share/man ] +[ -e $TEST_HOME/.nix-profile/include ] + +nix profile remove 0 +nix profile install "$flake1Dir^man" +(! [ -e $TEST_HOME/.nix-profile/bin/hello ]) +[ -e $TEST_HOME/.nix-profile/share/man ] +(! [ -e $TEST_HOME/.nix-profile/include ]) + +# test priority +nix profile remove 0 + +# Make another flake. +flake2Dir=$TEST_ROOT/flake2 +printf World > $flake1Dir/who +cp -r $flake1Dir $flake2Dir +printf World2 > $flake2Dir/who + +nix profile install $flake1Dir +[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello World" ]] +expect 1 nix profile install $flake2Dir +diff -u <( + nix --offline profile install $flake2Dir 2>&1 1> /dev/null \ + | grep -vE "^warning: " \ + | grep -vE "^error \(ignored\): " \ + || true +) <(cat << EOF +error: An existing package already provides the following file: + + $(nix build --no-link --print-out-paths ${flake1Dir}"#default.out")/bin/hello + + This is the conflicting file from the new package: + + $(nix build --no-link --print-out-paths ${flake2Dir}"#default.out")/bin/hello + + To remove the existing package: + + nix profile remove path:${flake1Dir}#packages.${system}.default + + The new package can also be installed next to the existing one by assigning a different priority. + The conflicting packages have a priority of 5. + To prioritise the new package: + + nix profile install path:${flake2Dir}#packages.${system}.default --priority 4 + + To prioritise the existing package: + + nix profile install path:${flake2Dir}#packages.${system}.default --priority 6 +EOF +) +[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello World" ]] +nix profile install $flake2Dir --priority 100 +[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello World" ]] +nix profile install $flake2Dir --priority 0 +[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello World2" ]] +# nix profile install $flake1Dir --priority 100 +# [[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello World" ]] + +# Ensure that conflicts are handled properly even when the installables aren't +# flake references. +# Regression test for https://github.com/NixOS/nix/issues/8284 +clearProfiles +nix profile install $(nix build $flake1Dir --no-link --print-out-paths) +expect 1 nix profile install --impure --expr "(builtins.getFlake ''$flake2Dir'').packages.$system.default" diff --git a/tests/functional/nix-shell.sh b/tests/functional/nix-shell.sh new file mode 100644 index 000000000..edaa1249b --- /dev/null +++ b/tests/functional/nix-shell.sh @@ -0,0 +1,147 @@ +source common.sh + +clearStore + +if [[ -n ${CONTENT_ADDRESSED:-} ]]; then + shellDotNix="$PWD/ca-shell.nix" +else + shellDotNix="$PWD/shell.nix" +fi + +export NIX_PATH=nixpkgs="$shellDotNix" + +# Test nix-shell -A +export IMPURE_VAR=foo +export SELECTED_IMPURE_VAR=baz + +output=$(nix-shell --pure "$shellDotNix" -A shellDrv --run \ + 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $TEST_inNixShell"') + +[ "$output" = " - foo - bar - true" ] + +# Test --keep +output=$(nix-shell --pure --keep SELECTED_IMPURE_VAR "$shellDotNix" -A shellDrv --run \ + 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $SELECTED_IMPURE_VAR"') + +[ "$output" = " - foo - bar - baz" ] + +# Test nix-shell on a .drv +[[ $(nix-shell --pure $(nix-instantiate "$shellDotNix" -A shellDrv) --run \ + 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $TEST_inNixShell"') = " - foo - bar - false" ]] + +[[ $(nix-shell --pure $(nix-instantiate "$shellDotNix" -A shellDrv) --run \ + 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $TEST_inNixShell"') = " - foo - bar - false" ]] + +# Test nix-shell on a .drv symlink + +# Legacy: absolute path and .drv extension required +nix-instantiate "$shellDotNix" -A shellDrv --add-root $TEST_ROOT/shell.drv +[[ $(nix-shell --pure $TEST_ROOT/shell.drv --run \ + 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX"') = " - foo - bar" ]] + +# New behaviour: just needs to resolve to a derivation in the store +nix-instantiate "$shellDotNix" -A shellDrv --add-root $TEST_ROOT/shell +[[ $(nix-shell --pure $TEST_ROOT/shell --run \ + 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX"') = " - foo - bar" ]] + +# Test nix-shell -p +output=$(NIX_PATH=nixpkgs="$shellDotNix" nix-shell --pure -p foo bar --run 'echo "$(foo) $(bar)"') +[ "$output" = "foo bar" ] + +# Test nix-shell -p --arg x y +output=$(NIX_PATH=nixpkgs="$shellDotNix" nix-shell --pure -p foo --argstr fooContents baz --run 'echo "$(foo)"') +[ "$output" = "baz" ] + +# Test nix-shell shebang mode +sed -e "s|@ENV_PROG@|$(type -P env)|" shell.shebang.sh > $TEST_ROOT/shell.shebang.sh +chmod a+rx $TEST_ROOT/shell.shebang.sh + +output=$($TEST_ROOT/shell.shebang.sh abc def) +[ "$output" = "foo bar abc def" ] + +# Test nix-shell shebang mode again with metacharacters in the filename. +# First word of filename is chosen to not match any file in the test root. +sed -e "s|@ENV_PROG@|$(type -P env)|" shell.shebang.sh > $TEST_ROOT/spaced\ \\\'\"shell.shebang.sh +chmod a+rx $TEST_ROOT/spaced\ \\\'\"shell.shebang.sh + +output=$($TEST_ROOT/spaced\ \\\'\"shell.shebang.sh abc def) +[ "$output" = "foo bar abc def" ] + +# Test nix-shell shebang mode for ruby +# This uses a fake interpreter that returns the arguments passed +# This, in turn, verifies the `rc` script is valid and the `load()` script (given using `-e`) is as expected. +sed -e "s|@SHELL_PROG@|$(type -P nix-shell)|" shell.shebang.rb > $TEST_ROOT/shell.shebang.rb +chmod a+rx $TEST_ROOT/shell.shebang.rb + +output=$($TEST_ROOT/shell.shebang.rb abc ruby) +[ "$output" = '-e load(ARGV.shift) -- '"$TEST_ROOT"'/shell.shebang.rb abc ruby' ] + +# Test nix-shell shebang mode for ruby again with metacharacters in the filename. +# Note: fake interpreter only space-separates args without adding escapes to its output. +sed -e "s|@SHELL_PROG@|$(type -P nix-shell)|" shell.shebang.rb > $TEST_ROOT/spaced\ \\\'\"shell.shebang.rb +chmod a+rx $TEST_ROOT/spaced\ \\\'\"shell.shebang.rb + +output=$($TEST_ROOT/spaced\ \\\'\"shell.shebang.rb abc ruby) +[ "$output" = '-e load(ARGV.shift) -- '"$TEST_ROOT"'/spaced \'\''"shell.shebang.rb abc ruby' ] + +# Test 'nix develop'. +nix develop -f "$shellDotNix" shellDrv -c bash -c '[[ -n $stdenv ]]' + +# Ensure `nix develop -c` preserves stdin +echo foo | nix develop -f "$shellDotNix" shellDrv -c cat | grepQuiet foo + +# Ensure `nix develop -c` actually executes the command if stdout isn't a terminal +nix develop -f "$shellDotNix" shellDrv -c echo foo |& grepQuiet foo + +# Test 'nix print-dev-env'. + +nix print-dev-env -f "$shellDotNix" shellDrv > $TEST_ROOT/dev-env.sh +nix print-dev-env -f "$shellDotNix" shellDrv --json > $TEST_ROOT/dev-env.json + +# Test with raw drv + +shellDrv=$(nix-instantiate "$shellDotNix" -A shellDrv.out) + +nix develop $shellDrv -c bash -c '[[ -n $stdenv ]]' + +nix print-dev-env $shellDrv > $TEST_ROOT/dev-env2.sh +nix print-dev-env $shellDrv --json > $TEST_ROOT/dev-env2.json + +diff $TEST_ROOT/dev-env{,2}.sh +diff $TEST_ROOT/dev-env{,2}.json + +# Ensure `nix print-dev-env --json` contains variable assignments. +[[ $(jq -r .variables.arr1.value[2] $TEST_ROOT/dev-env.json) = '3 4' ]] + +# Run tests involving `source <(nix print-dev-inv)` in subshells to avoid modifying the current +# environment. + +set +u # FIXME: Make print-dev-env `set -u` compliant (issue #7951) + +# Ensure `source <(nix print-dev-env)` modifies the environment. +( + path=$PATH + source $TEST_ROOT/dev-env.sh + [[ -n $stdenv ]] + [[ ${arr1[2]} = "3 4" ]] + [[ ${arr2[1]} = $'\n' ]] + [[ ${arr2[2]} = $'x\ny' ]] + [[ $(fun) = blabla ]] + [[ $PATH = $(jq -r .variables.PATH.value $TEST_ROOT/dev-env.json):$path ]] +) + +# Ensure `source <(nix print-dev-env)` handles the case when PATH is empty. +( + path=$PATH + PATH= + source $TEST_ROOT/dev-env.sh + [[ $PATH = $(PATH=$path jq -r .variables.PATH.value $TEST_ROOT/dev-env.json) ]] +) + +# Test nix-shell with ellipsis and no `inNixShell` argument (for backwards compat with old nixpkgs) +cat >$TEST_ROOT/shell-ellipsis.nix <' --restrict-eval +nix-instantiate --eval -E '' --restrict-eval + +# Should ideally also test this, but there’s no pure way to do it, so just trust me that it works +# nix-instantiate --eval -E '' -I nixpkgs=channel:nixos-unstable --restrict-eval + +[[ $(nix-instantiate --find-file by-absolute-path/simple.nix) = $PWD/simple.nix ]] +[[ $(nix-instantiate --find-file by-relative-path/simple.nix) = $PWD/simple.nix ]] diff --git a/tests/functional/optimise-store.sh b/tests/functional/optimise-store.sh new file mode 100644 index 000000000..8c2d05cd5 --- /dev/null +++ b/tests/functional/optimise-store.sh @@ -0,0 +1,44 @@ +source common.sh + +clearStore + +outPath1=$(echo 'with import ./config.nix; mkDerivation { name = "foo1"; builder = builtins.toFile "builder" "mkdir $out; echo hello > $out/foo"; }' | nix-build - --no-out-link --auto-optimise-store) +outPath2=$(echo 'with import ./config.nix; mkDerivation { name = "foo2"; builder = builtins.toFile "builder" "mkdir $out; echo hello > $out/foo"; }' | nix-build - --no-out-link --auto-optimise-store) + +inode1="$(stat --format=%i $outPath1/foo)" +inode2="$(stat --format=%i $outPath2/foo)" +if [ "$inode1" != "$inode2" ]; then + echo "inodes do not match" + exit 1 +fi + +nlink="$(stat --format=%h $outPath1/foo)" +if [ "$nlink" != 3 ]; then + echo "link count incorrect" + exit 1 +fi + +outPath3=$(echo 'with import ./config.nix; mkDerivation { name = "foo3"; builder = builtins.toFile "builder" "mkdir $out; echo hello > $out/foo"; }' | nix-build - --no-out-link) + +inode3="$(stat --format=%i $outPath3/foo)" +if [ "$inode1" = "$inode3" ]; then + echo "inodes match unexpectedly" + exit 1 +fi + +# XXX: This should work through the daemon too +NIX_REMOTE="" nix-store --optimise + +inode1="$(stat --format=%i $outPath1/foo)" +inode3="$(stat --format=%i $outPath3/foo)" +if [ "$inode1" != "$inode3" ]; then + echo "inodes do not match" + exit 1 +fi + +nix-store --gc + +if [ -n "$(ls $NIX_STORE_DIR/.links)" ]; then + echo ".links directory not empty after GC" + exit 1 +fi diff --git a/tests/functional/output-normalization.sh b/tests/functional/output-normalization.sh new file mode 100644 index 000000000..0f6df5e31 --- /dev/null +++ b/tests/functional/output-normalization.sh @@ -0,0 +1,9 @@ +source common.sh + +testNormalization () { + clearStore + outPath=$(nix-build ./simple.nix --no-out-link) + test "$(stat -c %Y $outPath)" -eq 1 +} + +testNormalization diff --git a/tests/functional/parallel.builder.sh b/tests/functional/parallel.builder.sh new file mode 100644 index 000000000..d092bc5a6 --- /dev/null +++ b/tests/functional/parallel.builder.sh @@ -0,0 +1,29 @@ +echo "DOING $text" + + +# increase counter +while ! ln -s x $shared.lock 2> /dev/null; do + sleep 1 +done +test -f $shared.cur || echo 0 > $shared.cur +test -f $shared.max || echo 0 > $shared.max +new=$(($(cat $shared.cur) + 1)) +if test $new -gt $(cat $shared.max); then + echo $new > $shared.max +fi +echo $new > $shared.cur +rm $shared.lock + + +echo -n $(cat $inputs)$text > $out + +sleep $sleepTime + + +# decrease counter +while ! ln -s x $shared.lock 2> /dev/null; do + sleep 1 +done +test -f $shared.cur || echo 0 > $shared.cur +echo $(($(cat $shared.cur) - 1)) > $shared.cur +rm $shared.lock diff --git a/tests/functional/parallel.nix b/tests/functional/parallel.nix new file mode 100644 index 000000000..23f142059 --- /dev/null +++ b/tests/functional/parallel.nix @@ -0,0 +1,19 @@ +{sleepTime ? 3}: + +with import ./config.nix; + +let + + mkDrv = text: inputs: mkDerivation { + name = "parallel"; + builder = ./parallel.builder.sh; + inherit text inputs shared sleepTime; + }; + + a = mkDrv "a" []; + b = mkDrv "b" [a]; + c = mkDrv "c" [a]; + d = mkDrv "d" [a]; + e = mkDrv "e" [b c d]; + +in e diff --git a/tests/functional/parallel.sh b/tests/functional/parallel.sh new file mode 100644 index 000000000..3b7bbe5a2 --- /dev/null +++ b/tests/functional/parallel.sh @@ -0,0 +1,56 @@ +source common.sh + + +# First, test that -jN performs builds in parallel. +echo "testing nix-build -j..." + +clearStore + +rm -f $_NIX_TEST_SHARED.cur $_NIX_TEST_SHARED.max + +outPath=$(nix-build -j10000 parallel.nix --no-out-link) + +echo "output path is $outPath" + +text=$(cat "$outPath") +if test "$text" != "abacade"; then exit 1; fi + +if test "$(cat $_NIX_TEST_SHARED.cur)" != 0; then fail "wrong current process count"; fi +if test "$(cat $_NIX_TEST_SHARED.max)" != 3; then fail "not enough parallelism"; fi + + +# Second, test that parallel invocations of nix-build perform builds +# in parallel, and don't block waiting on locks held by the others. +echo "testing multiple nix-build -j1..." + +clearStore + +rm -f $_NIX_TEST_SHARED.cur $_NIX_TEST_SHARED.max + +drvPath=$(nix-instantiate parallel.nix --argstr sleepTime 15) + +cmd="nix-store -j1 -r $drvPath" + +$cmd & +pid1=$! +echo "pid 1 is $pid1" + +$cmd & +pid2=$! +echo "pid 2 is $pid2" + +$cmd & +pid3=$! +echo "pid 3 is $pid3" + +$cmd & +pid4=$! +echo "pid 4 is $pid4" + +wait $pid1 || fail "instance 1 failed: $?" +wait $pid2 || fail "instance 2 failed: $?" +wait $pid3 || fail "instance 3 failed: $?" +wait $pid4 || fail "instance 4 failed: $?" + +if test "$(cat $_NIX_TEST_SHARED.cur)" != 0; then fail "wrong current process count"; fi +if test "$(cat $_NIX_TEST_SHARED.max)" != 3; then fail "not enough parallelism"; fi diff --git a/tests/functional/pass-as-file.sh b/tests/functional/pass-as-file.sh new file mode 100644 index 000000000..2c0bc5031 --- /dev/null +++ b/tests/functional/pass-as-file.sh @@ -0,0 +1,18 @@ +source common.sh + +clearStore + +outPath=$(nix-build --no-out-link -E " +with import ./config.nix; + +mkDerivation { + name = \"pass-as-file\"; + passAsFile = [ \"foo\" ]; + foo = [ \"xyzzy\" ]; + builder = builtins.toFile \"builder.sh\" '' + [ \"\$(basename \$fooPath)\" = .attr-1bp7cri8hplaz6hbz0v4f0nl44rl84q1sg25kgwqzipzd1mv89ic ] + [ \"\$(cat \$fooPath)\" = xyzzy ] + touch \$out + ''; +} +") diff --git a/tests/functional/path-from-hash-part.sh b/tests/functional/path-from-hash-part.sh new file mode 100644 index 000000000..bdd104434 --- /dev/null +++ b/tests/functional/path-from-hash-part.sh @@ -0,0 +1,10 @@ +source common.sh + +path=$(nix build --no-link --print-out-paths -f simple.nix) + +hash_part=$(basename $path) +hash_part=${hash_part:0:32} + +path2=$(nix store path-from-hash-part $hash_part) + +[[ $path = $path2 ]] diff --git a/tests/functional/path.nix b/tests/functional/path.nix new file mode 100644 index 000000000..883c3c41b --- /dev/null +++ b/tests/functional/path.nix @@ -0,0 +1,14 @@ +with import ./config.nix; + +mkDerivation { + name = "filter"; + builder = builtins.toFile "builder" "ln -s $input $out"; + input = + builtins.path { + path = ((builtins.getEnv "TEST_ROOT") + "/filterin"); + filter = path: type: + type != "symlink" + && baseNameOf path != "foo" + && !((import ./lang/lib.nix).hasSuffix ".bak" (baseNameOf path)); + }; +} diff --git a/tests/functional/placeholders.sh b/tests/functional/placeholders.sh new file mode 100644 index 000000000..cd1bb7bc2 --- /dev/null +++ b/tests/functional/placeholders.sh @@ -0,0 +1,20 @@ +source common.sh + +clearStore + +nix-build --no-out-link -E ' + with import ./config.nix; + + mkDerivation { + name = "placeholders"; + outputs = [ "out" "bin" "dev" ]; + buildCommand = " + echo foo1 > $out + echo foo2 > $bin + echo foo3 > $dev + [[ $(cat ${placeholder "out"}) = foo1 ]] + [[ $(cat ${placeholder "bin"}) = foo2 ]] + [[ $(cat ${placeholder "dev"}) = foo3 ]] + "; + } +' diff --git a/tests/functional/plugins.sh b/tests/functional/plugins.sh new file mode 100644 index 000000000..baf71a362 --- /dev/null +++ b/tests/functional/plugins.sh @@ -0,0 +1,9 @@ +source common.sh + +if [[ $BUILD_SHARED_LIBS != 1 ]]; then + skipTest "Plugins are not supported" +fi + +res=$(nix --option setting-set true --option plugin-files $PWD/plugins/libplugintest* eval --expr builtins.anotherNull) + +[ "$res"x = "nullx" ] diff --git a/tests/functional/plugins/local.mk b/tests/functional/plugins/local.mk new file mode 100644 index 000000000..40350aa96 --- /dev/null +++ b/tests/functional/plugins/local.mk @@ -0,0 +1,11 @@ +libraries += libplugintest + +libplugintest_DIR := $(d) + +libplugintest_SOURCES := $(d)/plugintest.cc + +libplugintest_ALLOW_UNDEFINED := 1 + +libplugintest_EXCLUDE_FROM_LIBRARY_LIST := 1 + +libplugintest_CXXFLAGS := -I src/libutil -I src/libstore -I src/libexpr -I src/libfetchers diff --git a/tests/functional/plugins/plugintest.cc b/tests/functional/plugins/plugintest.cc new file mode 100644 index 000000000..e02fd68d5 --- /dev/null +++ b/tests/functional/plugins/plugintest.cc @@ -0,0 +1,28 @@ +#include "config.hh" +#include "primops.hh" + +using namespace nix; + +struct MySettings : Config +{ + Setting settingSet{this, false, "setting-set", + "Whether the plugin-defined setting was set"}; +}; + +MySettings mySettings; + +static GlobalConfig::Register rs(&mySettings); + +static void prim_anotherNull (EvalState & state, const PosIdx pos, Value ** args, Value & v) +{ + if (mySettings.settingSet) + v.mkNull(); + else + v.mkBool(false); +} + +static RegisterPrimOp rp({ + .name = "anotherNull", + .arity = 0, + .fun = prim_anotherNull, +}); diff --git a/tests/functional/post-hook.sh b/tests/functional/post-hook.sh new file mode 100644 index 000000000..752f8220c --- /dev/null +++ b/tests/functional/post-hook.sh @@ -0,0 +1,31 @@ +source common.sh + +clearStore + +rm -f $TEST_ROOT/result + +export REMOTE_STORE=file:$TEST_ROOT/remote_store +echo 'require-sigs = false' >> $NIX_CONF_DIR/nix.conf + +restartDaemon + +if isDaemonNewer "2.13"; then + pushToStore="$PWD/push-to-store.sh" +else + pushToStore="$PWD/push-to-store-old.sh" +fi + +# Build the dependencies and push them to the remote store. +nix-build -o $TEST_ROOT/result dependencies.nix --post-build-hook "$pushToStore" +# See if all outputs are passed to the post-build hook by only specifying one +# We're not able to test CA tests this way +export BUILD_HOOK_ONLY_OUT_PATHS=$([ ! $NIX_TESTS_CA_BY_DEFAULT ]) +nix-build -o $TEST_ROOT/result-mult multiple-outputs.nix -A a.first --post-build-hook "$pushToStore" + +clearStore + +# Ensure that the remote store contains both the runtime and build-time +# closure of what we've just built. +nix copy --from "$REMOTE_STORE" --no-require-sigs -f dependencies.nix +nix copy --from "$REMOTE_STORE" --no-require-sigs -f dependencies.nix input1_drv +nix copy --from "$REMOTE_STORE" --no-require-sigs -f multiple-outputs.nix a^second diff --git a/tests/functional/pure-eval.nix b/tests/functional/pure-eval.nix new file mode 100644 index 000000000..ed25b3d45 --- /dev/null +++ b/tests/functional/pure-eval.nix @@ -0,0 +1,3 @@ +{ + x = 123; +} diff --git a/tests/functional/pure-eval.sh b/tests/functional/pure-eval.sh new file mode 100644 index 000000000..5334bf28e --- /dev/null +++ b/tests/functional/pure-eval.sh @@ -0,0 +1,34 @@ +source common.sh + +clearStore + +nix eval --expr 'assert 1 + 2 == 3; true' + +[[ $(nix eval --impure --expr 'builtins.readFile ./pure-eval.sh') =~ clearStore ]] + +missingImpureErrorMsg=$(! nix eval --expr 'builtins.readFile ./pure-eval.sh' 2>&1) + +echo "$missingImpureErrorMsg" | grepQuiet -- --impure || \ + fail "The error message should mention the “--impure” flag to unblock users" + +[[ $(nix eval --expr 'builtins.pathExists ./pure-eval.sh') == false ]] || \ + fail "Calling 'pathExists' on a non-authorised path should return false" + +(! nix eval --expr builtins.currentTime) +(! nix eval --expr builtins.currentSystem) + +(! nix-instantiate --pure-eval ./simple.nix) + +[[ $(nix eval --impure --expr "(import (builtins.fetchurl { url = file://$(pwd)/pure-eval.nix; })).x") == 123 ]] +(! nix eval --expr "(import (builtins.fetchurl { url = file://$(pwd)/pure-eval.nix; })).x") +nix eval --expr "(import (builtins.fetchurl { url = file://$(pwd)/pure-eval.nix; sha256 = \"$(nix hash file pure-eval.nix --type sha256)\"; })).x" + +rm -rf $TEST_ROOT/eval-out +nix eval --store dummy:// --write-to $TEST_ROOT/eval-out --expr '{ x = "foo" + "bar"; y = { z = "bla"; }; }' +[[ $(cat $TEST_ROOT/eval-out/x) = foobar ]] +[[ $(cat $TEST_ROOT/eval-out/y/z) = bla ]] + +rm -rf $TEST_ROOT/eval-out +(! nix eval --store dummy:// --write-to $TEST_ROOT/eval-out --expr '{ "." = "bla"; }') + +(! nix eval --expr '~/foo') diff --git a/tests/functional/push-to-store-old.sh b/tests/functional/push-to-store-old.sh new file mode 100755 index 000000000..4187958b2 --- /dev/null +++ b/tests/functional/push-to-store-old.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +set -x +set -e + +[ -n "$OUT_PATHS" ] +[ -n "$DRV_PATH" ] + +echo Pushing "$OUT_PATHS" to "$REMOTE_STORE" +if [ -n "$BUILD_HOOK_ONLY_OUT_PATHS" ]; then + printf "%s" "$OUT_PATHS" | xargs nix copy --to "$REMOTE_STORE" --no-require-sigs +else + printf "%s" "$DRV_PATH" | xargs nix copy --to "$REMOTE_STORE" --no-require-sigs +fi diff --git a/tests/functional/push-to-store.sh b/tests/functional/push-to-store.sh new file mode 100755 index 000000000..9e4e475e0 --- /dev/null +++ b/tests/functional/push-to-store.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +set -x +set -e + +[ -n "$OUT_PATHS" ] +[ -n "$DRV_PATH" ] + +echo Pushing "$OUT_PATHS" to "$REMOTE_STORE" +if [ -n "$BUILD_HOOK_ONLY_OUT_PATHS" ]; then + printf "%s" "$OUT_PATHS" | xargs nix copy --to "$REMOTE_STORE" --no-require-sigs +else + printf "%s" "$DRV_PATH"^'*' | xargs nix copy --to "$REMOTE_STORE" --no-require-sigs +fi diff --git a/tests/functional/read-only-store.sh b/tests/functional/read-only-store.sh new file mode 100644 index 000000000..d63920c19 --- /dev/null +++ b/tests/functional/read-only-store.sh @@ -0,0 +1,42 @@ +source common.sh + +enableFeatures "read-only-local-store" + +needLocalStore "cannot open store read-only when daemon has already opened it writeable" + +clearStore + +happy () { + # We can do a read-only query just fine with a read-only store + nix --store local?read-only=true path-info $dummyPath + + # We can "write" an already-present store-path a read-only store, because no IO is actually required + nix-store --store local?read-only=true --add dummy +} +## Testing read-only mode without forcing the underlying store to actually be read-only + +# Make sure the command fails when the store doesn't already have a database +expectStderr 1 nix-store --store local?read-only=true --add dummy | grepQuiet "database does not exist, and cannot be created in read-only mode" + +# Make sure the store actually has a current-database, with at least one store object +dummyPath=$(nix-store --add dummy) + +# Try again and make sure we fail when adding a item not already in the store +expectStderr 1 nix-store --store local?read-only=true --add eval.nix | grepQuiet "attempt to write a readonly database" + +# Test a few operations that should work with the read-only store in its current state +happy + +## Testing read-only mode with an underlying store that is actually read-only + +# Ensure store is actually read-only +chmod -R -w $TEST_ROOT/store +chmod -R -w $TEST_ROOT/var + +# Make sure we fail on add operations on the read-only store +# This is only for adding files that are not *already* in the store +expectStderr 1 nix-store --add eval.nix | grepQuiet "error: opening lock file '$(readlink -e $TEST_ROOT)/var/nix/db/big-lock'" +expectStderr 1 nix-store --store local?read-only=true --add eval.nix | grepQuiet "Permission denied" + +# Test the same operations from before should again succeed +happy diff --git a/tests/functional/readfile-context.nix b/tests/functional/readfile-context.nix new file mode 100644 index 000000000..54cd1afd9 --- /dev/null +++ b/tests/functional/readfile-context.nix @@ -0,0 +1,28 @@ +with import ./config.nix; + +let + + input = import ./simple.nix; + + dependent = mkDerivation { + name = "dependent"; + buildCommand = '' + mkdir -p $out + echo -n "$input1" > "$out/file1" + echo -n "$input2" > "$out/file2" + ''; + input1 = "${input}/hello"; + input2 = "hello"; + }; + + readDependent = mkDerivation { + # Will evaluate correctly because file2 doesn't have any references, + # even though the `dependent` derivation does. + name = builtins.readFile (dependent + "/file2"); + buildCommand = '' + echo "$input" > "$out" + ''; + input = builtins.readFile (dependent + "/file1"); + }; + +in readDependent diff --git a/tests/functional/readfile-context.sh b/tests/functional/readfile-context.sh new file mode 100644 index 000000000..31e70ddb1 --- /dev/null +++ b/tests/functional/readfile-context.sh @@ -0,0 +1,16 @@ +source common.sh + +clearStore + +outPath=$(nix-build --no-out-link readfile-context.nix) + +# Set a GC root. +ln -s $outPath "$NIX_STATE_DIR"/gcroots/foo + +# Check that file exists. +[ "$(cat $(cat $outPath))" = "Hello World!" ] + +nix-collect-garbage + +# Check that file still exists. +[ "$(cat $(cat $outPath))" = "Hello World!" ] diff --git a/tests/functional/recursive.nix b/tests/functional/recursive.nix new file mode 100644 index 000000000..fa8cc04db --- /dev/null +++ b/tests/functional/recursive.nix @@ -0,0 +1,56 @@ +with import ./config.nix; + +mkDerivation rec { + name = "recursive"; + dummy = builtins.toFile "dummy" "bla bla"; + SHELL = shell; + + # Note: this is a string without context. + unreachable = builtins.getEnv "unreachable"; + + NIX_TESTS_CA_BY_DEFAULT = builtins.getEnv "NIX_TESTS_CA_BY_DEFAULT"; + + requiredSystemFeatures = [ "recursive-nix" ]; + + buildCommand = '' + mkdir $out + opts="--experimental-features nix-command ${if (NIX_TESTS_CA_BY_DEFAULT == "1") then "--extra-experimental-features ca-derivations" else ""}" + + PATH=${builtins.getEnv "NIX_BIN_DIR"}:$PATH + + # Check that we can query/build paths in our input closure. + nix $opts path-info $dummy + nix $opts build $dummy + + # Make sure we cannot query/build paths not in out input closure. + [[ -e $unreachable ]] + (! nix $opts path-info $unreachable) + (! nix $opts build $unreachable) + + # Add something to the store. + echo foobar > foobar + foobar=$(nix $opts store add-path ./foobar) + + nix $opts path-info $foobar + nix $opts build $foobar + + # Add it to our closure. + ln -s $foobar $out/foobar + + [[ $(nix $opts path-info --all | wc -l) -eq 4 ]] + + # Build a derivation. + nix $opts build -L --impure --expr ' + with import ${./config.nix}; + mkDerivation { + name = "inner1"; + buildCommand = "echo $fnord blaat > $out"; + fnord = builtins.toFile "fnord" "fnord"; + } + ' + + [[ $(nix $opts path-info --json ./result) =~ fnord ]] + + ln -s $(nix $opts path-info ./result) $out/inner1 + ''; +} diff --git a/tests/functional/recursive.sh b/tests/functional/recursive.sh new file mode 100644 index 000000000..0bf00f8fa --- /dev/null +++ b/tests/functional/recursive.sh @@ -0,0 +1,19 @@ +source common.sh + +enableFeatures 'recursive-nix' +restartDaemon + +clearStore + +rm -f $TEST_ROOT/result + +export unreachable=$(nix store add-path ./recursive.sh) + +NIX_BIN_DIR=$(dirname $(type -p nix)) nix --extra-experimental-features 'nix-command recursive-nix' build -o $TEST_ROOT/result -L --impure --file ./recursive.nix + +[[ $(cat $TEST_ROOT/result/inner1) =~ blaat ]] + +# Make sure the recursively created paths are in the closure. +nix path-info -r $TEST_ROOT/result | grep foobar +nix path-info -r $TEST_ROOT/result | grep fnord +nix path-info -r $TEST_ROOT/result | grep inner1 diff --git a/tests/functional/referrers.sh b/tests/functional/referrers.sh new file mode 100644 index 000000000..81323c280 --- /dev/null +++ b/tests/functional/referrers.sh @@ -0,0 +1,38 @@ +source common.sh + +needLocalStore "uses some low-level store manipulations that aren’t available through the daemon" + +clearStore + +max=500 + +reference=$NIX_STORE_DIR/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-bla +touch $reference +(echo $reference && echo && echo 0) | nix-store --register-validity + +echo "making registration..." + +set +x +for ((n = 0; n < $max; n++)); do + storePath=$NIX_STORE_DIR/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-$n + echo -n > $storePath + ref2=$NIX_STORE_DIR/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-$((n+1)) + if test $((n+1)) = $max; then + ref2=$reference + fi + echo $storePath; echo; echo 2; echo $reference; echo $ref2 +done > $TEST_ROOT/reg_info +set -x + +echo "registering..." + +nix-store --register-validity < $TEST_ROOT/reg_info + +echo "collecting garbage..." +ln -sfn $reference "$NIX_STATE_DIR"/gcroots/ref +nix-store --gc + +if [ -n "$(type -p sqlite3)" -a "$(sqlite3 $NIX_STATE_DIR/db/db.sqlite 'select count(*) from Refs')" -ne 0 ]; then + echo "referrers not cleaned up" + exit 1 +fi diff --git a/tests/functional/remote-store.sh b/tests/functional/remote-store.sh new file mode 100644 index 000000000..50e6f24b9 --- /dev/null +++ b/tests/functional/remote-store.sh @@ -0,0 +1,43 @@ +source common.sh + +clearStore + +# Ensure "fake ssh" remote store works just as legacy fake ssh would. +nix --store ssh-ng://localhost?remote-store=$TEST_ROOT/other-store doctor + +# Ensure that store ping trusted works with ssh-ng:// +nix --store ssh-ng://localhost?remote-store=$TEST_ROOT/other-store store ping --json | jq -e '.trusted' + +startDaemon + +if isDaemonNewer "2.15pre0"; then + # Ensure that ping works trusted with new daemon + nix store ping --json | jq -e '.trusted' +else + # And the the field is absent with the old daemon + nix store ping --json | jq -e 'has("trusted") | not' +fi + +# Test import-from-derivation through the daemon. +[[ $(nix eval --impure --raw --expr ' + with import ./config.nix; + import ( + mkDerivation { + name = "foo"; + bla = import ./dependencies.nix {}; + buildCommand = " + echo \\\"hi\\\" > $out + "; + } + ) +') = hi ]] + +storeCleared=1 NIX_REMOTE_=$NIX_REMOTE $SHELL ./user-envs.sh + +nix-store --gc --max-freed 1K + +nix-store --dump-db > $TEST_ROOT/d1 +NIX_REMOTE= nix-store --dump-db > $TEST_ROOT/d2 +cmp $TEST_ROOT/d1 $TEST_ROOT/d2 + +killDaemon diff --git a/tests/functional/repair.sh b/tests/functional/repair.sh new file mode 100644 index 000000000..c8f07b1c6 --- /dev/null +++ b/tests/functional/repair.sh @@ -0,0 +1,123 @@ +source common.sh + +needLocalStore "--repair needs a local store" + +clearStore + +path=$(nix-build dependencies.nix -o $TEST_ROOT/result) +path2=$(nix-store -qR $path | grep input-2) + +nix-store --verify --check-contents -v + +hash=$(nix-hash $path2) + +# Corrupt a path and check whether nix-build --repair can fix it. +chmod u+w $path2 +touch $path2/bad + +(! nix-store --verify --check-contents -v) + +# The path can be repaired by rebuilding the derivation. +nix-store --verify --check-contents --repair + +(! [ -e $path2/bad ]) +(! [ -w $path2 ]) + +nix-store --verify-path $path2 + +# Re-corrupt and delete the deriver. Now --verify --repair should +# not work. +chmod u+w $path2 +touch $path2/bad + +nix-store --delete $(nix-store -q --referrers-closure $(nix-store -qd $path2)) + +(! nix-store --verify --check-contents --repair) + +nix-build dependencies.nix -o $TEST_ROOT/result --repair + +if [ "$(nix-hash $path2)" != "$hash" -o -e $path2/bad ]; then + echo "path not repaired properly" >&2 + exit 1 +fi + +# Corrupt a path that has a substitute and check whether nix-store +# --verify can fix it. +clearCache + +nix copy --to file://$cacheDir $path + +chmod u+w $path2 +rm -rf $path2 + +nix-store --verify --check-contents --repair --substituters "file://$cacheDir" --no-require-sigs + +if [ "$(nix-hash $path2)" != "$hash" -o -e $path2/bad ]; then + echo "path not repaired properly" >&2 + exit 1 +fi + +# Check --verify-path and --repair-path. +nix-store --verify-path $path2 + +chmod u+w $path2 +rm -rf $path2 + +if nix-store --verify-path $path2; then + echo "nix-store --verify-path succeeded unexpectedly" >&2 + exit 1 +fi + +nix-store --repair-path $path2 --substituters "file://$cacheDir" --no-require-sigs + +if [ "$(nix-hash $path2)" != "$hash" -o -e $path2/bad ]; then + echo "path not repaired properly" >&2 + exit 1 +fi + +# Check that --repair-path also checks content of optimised symlinks (1/2) +nix-store --verify-path $path2 + +if (! nix-store --optimize); then + echo "nix-store --optimize failed to optimize the store" >&2 + exit 1 +fi +chmod u+w $path2/bar +echo 'rabrab' > $path2/bar # different length + +if nix-store --verify-path $path2; then + echo "nix-store --verify-path did not detect .links file corruption" >&2 + exit 1 +fi + +nix-store --repair-path $path2 --option auto-optimise-store true + +if [ "$(nix-hash $path2)" != "$hash" -o "BAR" != "$(< $path2/bar)" ]; then + echo "path not repaired properly" >&2 + exit 1 +fi + +# Check that --repair-path also checks content of optimised symlinks (2/2) +nix-store --verify-path $path2 + +if (! nix-store --optimize); then + echo "nix-store --optimize failed to optimize the store" >&2 + exit 1 +fi +chmod u+w $path2 +chmod u+w $path2/bar +sed -e 's/./X/g' < $path2/bar > $path2/tmp # same length, different content. +cp $path2/tmp $path2/bar +rm $path2/tmp + +if nix-store --verify-path $path2; then + echo "nix-store --verify-path did not detect .links file corruption" >&2 + exit 1 +fi + +nix-store --repair-path $path2 --substituters "file://$cacheDir" --no-require-sigs --option auto-optimise-store true + +if [ "$(nix-hash $path2)" != "$hash" -o "BAR" != "$(< $path2/bar)" ]; then + echo "path not repaired properly" >&2 + exit 1 +fi diff --git a/tests/functional/repl.sh b/tests/functional/repl.sh new file mode 100644 index 000000000..bb8b60e50 --- /dev/null +++ b/tests/functional/repl.sh @@ -0,0 +1,179 @@ +source common.sh + +testDir="$PWD" +cd "$TEST_ROOT" + +replCmds=" +simple = 1 +simple = import $testDir/simple.nix +:bl simple +:log simple +" + +replFailingCmds=" +failing = import $testDir/simple-failing.nix +:b failing +:log failing +" + +replUndefinedVariable=" +import $testDir/undefined-variable.nix +" + +testRepl () { + local nixArgs=("$@") + rm -rf repl-result-out || true # cleanup from other runs backed by a foreign nix store + local replOutput="$(nix repl "${nixArgs[@]}" <<< "$replCmds")" + echo "$replOutput" + local outPath=$(echo "$replOutput" |& + grep -o -E "$NIX_STORE_DIR/\w*-simple") + nix path-info "${nixArgs[@]}" "$outPath" + [ "$(realpath ./repl-result-out)" == "$outPath" ] || fail "nix repl :bl doesn't make a symlink" + # run it again without checking the output to ensure the previously created symlink gets overwritten + nix repl "${nixArgs[@]}" <<< "$replCmds" || fail "nix repl does not work twice with the same inputs" + + # simple.nix prints a PATH during build + echo "$replOutput" | grepQuiet -s 'PATH=' || fail "nix repl :log doesn't output logs" + local replOutput="$(nix repl "${nixArgs[@]}" <<< "$replFailingCmds" 2>&1)" + echo "$replOutput" + echo "$replOutput" | grepQuiet -s 'This should fail' \ + || fail "nix repl :log doesn't output logs for a failed derivation" + local replOutput="$(nix repl --show-trace "${nixArgs[@]}" <<< "$replUndefinedVariable" 2>&1)" + echo "$replOutput" + echo "$replOutput" | grepQuiet -s "while evaluating the file" \ + || fail "nix repl --show-trace doesn't show the trace" + + nix repl "${nixArgs[@]}" --option pure-eval true 2>&1 <<< "builtins.currentSystem" \ + | grep "attribute 'currentSystem' missing" + nix repl "${nixArgs[@]}" 2>&1 <<< "builtins.currentSystem" \ + | grep "$(nix-instantiate --eval -E 'builtins.currentSystem')" +} + +# Simple test, try building a drv +testRepl +# Same thing (kind-of), but with a remote store. +testRepl --store "$TEST_ROOT/store?real=$NIX_STORE_DIR" + +# Remove ANSI escape sequences. They can prevent grep from finding a match. +stripColors () { + sed -E 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' +} + +testReplResponseGeneral () { + local grepMode="$1"; shift + local commands="$1"; shift + local expectedResponse="$1"; shift + local response="$(nix repl "$@" <<< "$commands" | stripColors)" + echo "$response" | grepQuiet "$grepMode" -s "$expectedResponse" \ + || fail "repl command set: + +$commands + +does not respond with: + +$expectedResponse + +but with: + +$response +" +} + +testReplResponse () { + testReplResponseGeneral --basic-regexp "$@" +} + +testReplResponseNoRegex () { + testReplResponseGeneral --fixed-strings "$@" +} + +# :a uses the newest version of a symbol +testReplResponse ' +:a { a = "1"; } +:a { a = "2"; } +"result: ${a}" +' "result: 2" + +# check dollar escaping https://github.com/NixOS/nix/issues/4909 +# note the escaped \, +# \\ +# because the second argument is a regex +testReplResponseNoRegex ' +"$" + "{hi}" +' '"\${hi}"' + +testReplResponse ' +drvPath +' '".*-simple.drv"' \ +$testDir/simple.nix + +testReplResponse ' +drvPath +' '".*-simple.drv"' \ +--file $testDir/simple.nix --experimental-features 'ca-derivations' + +testReplResponse ' +drvPath +' '".*-simple.drv"' \ +--file $testDir/simple.nix --extra-experimental-features 'repl-flake ca-derivations' + +mkdir -p flake && cat < flake/flake.nix +{ + outputs = { self }: { + foo = 1; + bar.baz = 2; + + changingThing = "beforeChange"; + }; +} +EOF +testReplResponse ' +foo + baz +' "3" \ + ./flake ./flake\#bar --experimental-features 'flakes repl-flake' + +# Test the `:reload` mechansim with flakes: +# - Eval `./flake#changingThing` +# - Modify the flake +# - Re-eval it +# - Check that the result has changed +replResult=$( ( +echo "changingThing" +sleep 1 # Leave the repl the time to eval 'foo' +sed -i 's/beforeChange/afterChange/' flake/flake.nix +echo ":reload" +echo "changingThing" +) | nix repl ./flake --experimental-features 'flakes repl-flake') +echo "$replResult" | grepQuiet -s beforeChange +echo "$replResult" | grepQuiet -s afterChange + +# Test recursive printing and formatting +# Normal output should print attributes in lexicographical order non-recursively +testReplResponseNoRegex ' +{ a = { b = 2; }; l = [ 1 2 3 ]; s = "string"; n = 1234; x = rec { y = { z = { inherit y; }; }; }; } +' '{ a = { ... }; l = [ ... ]; n = 1234; s = "string"; x = { ... }; }' + +# Same for lists, but order is preserved +testReplResponseNoRegex ' +[ 42 1 "thingy" ({ a = 1; }) ([ 1 2 3 ]) ] +' '[ 42 1 "thingy" { ... } [ ... ] ]' + +# Same for let expressions +testReplResponseNoRegex ' +let x = { y = { a = 1; }; inherit x; }; in x +' '{ x = { ... }; y = { ... }; }' + +# The :p command should recursively print sets, but prevent infinite recursion +testReplResponseNoRegex ' +:p { a = { b = 2; }; s = "string"; n = 1234; x = rec { y = { z = { inherit y; }; }; }; } +' '{ a = { b = 2; }; n = 1234; s = "string"; x = { y = { z = { y = «repeated»; }; }; }; }' + +# Same for lists +testReplResponseNoRegex ' +:p [ 42 1 "thingy" (rec { a = 1; b = { inherit a; inherit b; }; }) ([ 1 2 3 ]) ] +' '[ 42 1 "thingy" { a = 1; b = { a = 1; b = «repeated»; }; } [ 1 2 3 ] ]' + +# Same for let expressions +testReplResponseNoRegex ' +:p let x = { y = { a = 1; }; inherit x; }; in x +' '{ x = { x = «repeated»; y = { a = 1; }; }; y = «repeated»; }' diff --git a/tests/functional/restricted.nix b/tests/functional/restricted.nix new file mode 100644 index 000000000..e0ef58402 --- /dev/null +++ b/tests/functional/restricted.nix @@ -0,0 +1 @@ +1 + 2 diff --git a/tests/functional/restricted.sh b/tests/functional/restricted.sh new file mode 100644 index 000000000..197ae7a10 --- /dev/null +++ b/tests/functional/restricted.sh @@ -0,0 +1,53 @@ +source common.sh + +clearStore + +nix-instantiate --restrict-eval --eval -E '1 + 2' +(! nix-instantiate --eval --restrict-eval ./restricted.nix) +(! nix-instantiate --eval --restrict-eval <(echo '1 + 2')) +nix-instantiate --restrict-eval ./simple.nix -I src=. +nix-instantiate --restrict-eval ./simple.nix -I src1=simple.nix -I src2=config.nix -I src3=./simple.builder.sh + +(! nix-instantiate --restrict-eval --eval -E 'builtins.readFile ./simple.nix') +nix-instantiate --restrict-eval --eval -E 'builtins.readFile ./simple.nix' -I src=../.. + +(! nix-instantiate --restrict-eval --eval -E 'builtins.readDir ../../src/nix-channel') +nix-instantiate --restrict-eval --eval -E 'builtins.readDir ../../src/nix-channel' -I src=../../src + +(! nix-instantiate --restrict-eval --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in ') +nix-instantiate --restrict-eval --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in ' -I src=. + +p=$(nix eval --raw --expr "builtins.fetchurl file://$(pwd)/restricted.sh" --impure --restrict-eval --allowed-uris "file://$(pwd)") +cmp $p restricted.sh + +(! nix eval --raw --expr "builtins.fetchurl file://$(pwd)/restricted.sh" --impure --restrict-eval) + +(! nix eval --raw --expr "builtins.fetchurl file://$(pwd)/restricted.sh" --impure --restrict-eval --allowed-uris "file://$(pwd)/restricted.sh/") + +nix eval --raw --expr "builtins.fetchurl file://$(pwd)/restricted.sh" --impure --restrict-eval --allowed-uris "file://$(pwd)/restricted.sh" + +(! nix eval --raw --expr "builtins.fetchurl https://github.com/NixOS/patchelf/archive/master.tar.gz" --impure --restrict-eval) +(! nix eval --raw --expr "builtins.fetchTarball https://github.com/NixOS/patchelf/archive/master.tar.gz" --impure --restrict-eval) +(! nix eval --raw --expr "fetchGit git://github.com/NixOS/patchelf.git" --impure --restrict-eval) + +ln -sfn $(pwd)/restricted.nix $TEST_ROOT/restricted.nix +[[ $(nix-instantiate --eval $TEST_ROOT/restricted.nix) == 3 ]] +(! nix-instantiate --eval --restrict-eval $TEST_ROOT/restricted.nix) +(! nix-instantiate --eval --restrict-eval $TEST_ROOT/restricted.nix -I $TEST_ROOT) +(! nix-instantiate --eval --restrict-eval $TEST_ROOT/restricted.nix -I .) +nix-instantiate --eval --restrict-eval $TEST_ROOT/restricted.nix -I $TEST_ROOT -I . + +[[ $(nix eval --raw --impure --restrict-eval -I . --expr 'builtins.readFile "${import ./simple.nix}/hello"') == 'Hello World!' ]] + +# Check whether we can leak symlink information through directory traversal. +traverseDir="$(pwd)/restricted-traverse-me" +ln -sfn "$(pwd)/restricted-secret" "$(pwd)/restricted-innocent" +mkdir -p "$traverseDir" +goUp="..$(echo "$traverseDir" | sed -e 's,[^/]\+,..,g')" +output="$(nix eval --raw --restrict-eval -I "$traverseDir" \ + --expr "builtins.readFile \"$traverseDir/$goUp$(pwd)/restricted-innocent\"" \ + 2>&1 || :)" +echo "$output" | grep "is forbidden" +echo "$output" | grepInverse -F restricted-secret + +expectStderr 1 nix-instantiate --restrict-eval true ./dependencies.nix | grepQuiet "forbidden in restricted mode" diff --git a/tests/functional/search.nix b/tests/functional/search.nix new file mode 100644 index 000000000..fea6e7a7a --- /dev/null +++ b/tests/functional/search.nix @@ -0,0 +1,25 @@ +with import ./config.nix; + +{ + hello = mkDerivation rec { + name = "hello-${version}"; + version = "0.1"; + buildCommand = "touch $out"; + meta.description = "Empty file"; + }; + foo = mkDerivation rec { + name = "foo-5"; + buildCommand = '' + mkdir -p $out + echo ${name} > $out/${name} + ''; + }; + bar = mkDerivation rec { + name = "bar-3"; + buildCommand = '' + echo "Does not build successfully" + exit 1 + ''; + meta.description = "broken bar"; + }; +} diff --git a/tests/functional/search.sh b/tests/functional/search.sh new file mode 100644 index 000000000..8742f8736 --- /dev/null +++ b/tests/functional/search.sh @@ -0,0 +1,46 @@ +source common.sh + +clearStore +clearCache + +(( $(nix search -f search.nix '' hello | wc -l) > 0 )) + +# Check descriptions are searched +(( $(nix search -f search.nix '' broken | wc -l) > 0 )) + +# Check search that matches nothing +(( $(nix search -f search.nix '' nosuchpackageexists | wc -l) == 0 )) + +# Search for multiple arguments +(( $(nix search -f search.nix '' hello empty | wc -l) == 2 )) + +# Multiple arguments will not exist +(( $(nix search -f search.nix '' hello broken | wc -l) == 0 )) + +## Search expressions + +# Check that empty search string matches all +nix search -f search.nix '' |grepQuiet foo +nix search -f search.nix '' |grepQuiet bar +nix search -f search.nix '' |grepQuiet hello + +## Tests for multiple regex/match highlighting + +e=$'\x1b' # grep doesn't support \e, \033 or even \x1b +# Multiple overlapping regexes +(( $(nix search -f search.nix '' 'oo' 'foo' 'oo' | grep -c "$e\[32;1mfoo$e\\[0;1m") == 1 )) +(( $(nix search -f search.nix '' 'broken b' 'en bar' | grep -c "$e\[32;1mbroken bar$e\\[0m") == 1 )) + +# Multiple matches +# Searching for 'o' should yield the 'o' in 'broken bar', the 'oo' in foo and 'o' in hello +(( $(nix search -f search.nix '' 'o' | grep -Eoc "$e\[32;1mo{1,2}$e\[(0|0;1)m") == 3 )) +# Searching for 'b' should yield the 'b' in bar and the two 'b's in 'broken bar' +# NOTE: This does not work with `grep -c` because it counts the two 'b's in 'broken bar' as one matched line +(( $(nix search -f search.nix '' 'b' | grep -Eo "$e\[32;1mb$e\[(0|0;1)m" | wc -l) == 3 )) + +## Tests for --exclude +(( $(nix search -f search.nix -e hello | grep -c hello) == 0 )) + +(( $(nix search -f search.nix foo --exclude 'foo|bar' | grep -Ec 'foo|bar') == 0 )) +(( $(nix search -f search.nix foo -e foo --exclude bar | grep -Ec 'foo|bar') == 0 )) +[[ $(nix search -f search.nix -e bar --json | jq -c 'keys') == '["foo","hello"]' ]] diff --git a/tests/functional/secure-drv-outputs.nix b/tests/functional/secure-drv-outputs.nix new file mode 100644 index 000000000..b4ac8ff53 --- /dev/null +++ b/tests/functional/secure-drv-outputs.nix @@ -0,0 +1,23 @@ +with import ./config.nix; + +{ + + good = mkDerivation { + name = "good"; + builder = builtins.toFile "builder" + '' + mkdir $out + echo > $out/good + ''; + }; + + bad = mkDerivation { + name = "good"; + builder = builtins.toFile "builder" + '' + mkdir $out + echo > $out/bad + ''; + }; + +} diff --git a/tests/functional/secure-drv-outputs.sh b/tests/functional/secure-drv-outputs.sh new file mode 100644 index 000000000..50a9c4428 --- /dev/null +++ b/tests/functional/secure-drv-outputs.sh @@ -0,0 +1,36 @@ +# Test that users cannot register specially-crafted derivations that +# produce output paths belonging to other derivations. This could be +# used to inject malware into the store. + +source common.sh + +clearStore + +startDaemon + +# Determine the output path of the "good" derivation. +goodOut=$(nix-store -q $(nix-instantiate ./secure-drv-outputs.nix -A good)) + +# Instantiate the "bad" derivation. +badDrv=$(nix-instantiate ./secure-drv-outputs.nix -A bad) +badOut=$(nix-store -q $badDrv) + +# Rewrite the bad derivation to produce the output path of the good +# derivation. +rm -f $TEST_ROOT/bad.drv +sed -e "s|$badOut|$goodOut|g" < $badDrv > $TEST_ROOT/bad.drv + +# Add the manipulated derivation to the store and build it. This +# should fail. +if badDrv2=$(nix-store --add $TEST_ROOT/bad.drv); then + nix-store -r "$badDrv2" +fi + +# Now build the good derivation. +goodOut2=$(nix-build ./secure-drv-outputs.nix -A good --no-out-link) +test "$goodOut" = "$goodOut2" + +if ! test -e "$goodOut"/good; then + echo "Bad derivation stole the output path of the good derivation!" + exit 1 +fi diff --git a/tests/functional/selfref-gc.sh b/tests/functional/selfref-gc.sh new file mode 100644 index 000000000..3f1f50eea --- /dev/null +++ b/tests/functional/selfref-gc.sh @@ -0,0 +1,30 @@ +source common.sh + +requireDaemonNewerThan "2.6.0pre20211215" + +clearStore + +nix-build --no-out-link -E ' + with import ./config.nix; + + let d1 = mkDerivation { + name = "selfref-gc"; + outputs = [ "out" ]; + buildCommand = " + echo SELF_REF: $out > $out + "; + }; in + + # the only change from d1 is d1 as an (unused) build input + # to get identical store path in CA. + mkDerivation { + name = "selfref-gc"; + outputs = [ "out" ]; + buildCommand = " + echo UNUSED: ${d1} + echo SELF_REF: $out > $out + "; + } +' + +nix-collect-garbage diff --git a/tests/functional/shell-hello.nix b/tests/functional/shell-hello.nix new file mode 100644 index 000000000..3fdd3501d --- /dev/null +++ b/tests/functional/shell-hello.nix @@ -0,0 +1,26 @@ +with import ./config.nix; + +{ + hello = mkDerivation { + name = "hello"; + outputs = [ "out" "dev" ]; + meta.outputsToInstall = [ "out" ]; + buildCommand = + '' + mkdir -p $out/bin $dev/bin + + cat > $out/bin/hello < $dev/bin/hello2 < $out/bin/foo + chmod a+rx $out/bin/foo + ln -s ${shell} $out/bin/bash + ''; + + bar = runCommand "bar" {} '' + mkdir -p $out/bin + echo 'echo bar' > $out/bin/bar + chmod a+rx $out/bin/bar + ''; + + bash = shell; + bashInteractive = runCommand "bash" {} '' + mkdir -p $out/bin + ln -s ${shell} $out/bin/bash + ''; + + # ruby "interpreter" that outputs "$@" + ruby = runCommand "ruby" {} '' + mkdir -p $out/bin + echo 'printf %s "$*"' > $out/bin/ruby + chmod a+rx $out/bin/ruby + ''; + + inherit pkgs; +}; in pkgs diff --git a/tests/functional/shell.sh b/tests/functional/shell.sh new file mode 100644 index 000000000..d2f7cf14e --- /dev/null +++ b/tests/functional/shell.sh @@ -0,0 +1,32 @@ +source common.sh + +clearStore +clearCache + +nix shell -f shell-hello.nix hello -c hello | grep 'Hello World' +nix shell -f shell-hello.nix hello -c hello NixOS | grep 'Hello NixOS' + +# Test output selection. +nix shell -f shell-hello.nix hello^dev -c hello2 | grep 'Hello2' +nix shell -f shell-hello.nix 'hello^*' -c hello2 | grep 'Hello2' + +requireSandboxSupport + +chmod -R u+w $TEST_ROOT/store0 || true +rm -rf $TEST_ROOT/store0 + +clearStore + +path=$(nix eval --raw -f shell-hello.nix hello) + +# Note: we need the sandbox paths to ensure that the shell is +# visible in the sandbox. +nix shell --sandbox-build-dir /build-tmp \ + --sandbox-paths '/nix? /bin? /lib? /lib64? /usr?' \ + --store $TEST_ROOT/store0 -f shell-hello.nix hello -c hello | grep 'Hello World' + +path2=$(nix shell --sandbox-paths '/nix? /bin? /lib? /lib64? /usr?' --store $TEST_ROOT/store0 -f shell-hello.nix hello -c $SHELL -c 'type -p hello') + +[[ $path/bin/hello = $path2 ]] + +[[ -e $TEST_ROOT/store0/nix/store/$(basename $path)/bin/hello ]] diff --git a/tests/functional/shell.shebang.rb b/tests/functional/shell.shebang.rb new file mode 100644 index 000000000..ea67eb09c --- /dev/null +++ b/tests/functional/shell.shebang.rb @@ -0,0 +1,7 @@ +#! @SHELL_PROG@ +#! ruby +#! nix-shell -I nixpkgs=shell.nix --no-substitute +#! nix-shell --pure -p ruby -i ruby + +# Contents doesn't matter. +abort("This shouldn't be executed.") diff --git a/tests/functional/shell.shebang.sh b/tests/functional/shell.shebang.sh new file mode 100755 index 000000000..f7132043d --- /dev/null +++ b/tests/functional/shell.shebang.sh @@ -0,0 +1,4 @@ +#! @ENV_PROG@ nix-shell +#! nix-shell -I nixpkgs=shell.nix --no-substitute +#! nix-shell --pure -i bash -p foo bar +echo "$(foo) $(bar) $@" diff --git a/tests/functional/signing.sh b/tests/functional/signing.sh new file mode 100644 index 000000000..942b51630 --- /dev/null +++ b/tests/functional/signing.sh @@ -0,0 +1,109 @@ +source common.sh + +clearStore +clearCache + +nix-store --generate-binary-cache-key cache1.example.org $TEST_ROOT/sk1 $TEST_ROOT/pk1 +pk1=$(cat $TEST_ROOT/pk1) +nix-store --generate-binary-cache-key cache2.example.org $TEST_ROOT/sk2 $TEST_ROOT/pk2 +pk2=$(cat $TEST_ROOT/pk2) + +# Build a path. +outPath=$(nix-build dependencies.nix --no-out-link --secret-key-files "$TEST_ROOT/sk1 $TEST_ROOT/sk2") + +# Verify that the path got signed. +info=$(nix path-info --json $outPath) +[[ $info =~ '"ultimate":true' ]] +[[ $info =~ 'cache1.example.org' ]] +[[ $info =~ 'cache2.example.org' ]] + +# Test "nix store verify". +nix store verify -r $outPath + +expect 2 nix store verify -r $outPath --sigs-needed 1 + +nix store verify -r $outPath --sigs-needed 1 --trusted-public-keys $pk1 + +expect 2 nix store verify -r $outPath --sigs-needed 2 --trusted-public-keys $pk1 + +nix store verify -r $outPath --sigs-needed 2 --trusted-public-keys "$pk1 $pk2" + +nix store verify --all --sigs-needed 2 --trusted-public-keys "$pk1 $pk2" + +# Build something unsigned. +outPath2=$(nix-build simple.nix --no-out-link) + +nix store verify -r $outPath + +# Verify that the path did not get signed but does have the ultimate bit. +info=$(nix path-info --json $outPath2) +[[ $info =~ '"ultimate":true' ]] +(! [[ $info =~ 'signatures' ]]) + +# Test "nix store verify". +nix store verify -r $outPath2 + +expect 2 nix store verify -r $outPath2 --sigs-needed 1 + +expect 2 nix store verify -r $outPath2 --sigs-needed 1 --trusted-public-keys $pk1 + +# Test "nix store sign". +nix store sign --key-file $TEST_ROOT/sk1 $outPath2 + +nix store verify -r $outPath2 --sigs-needed 1 --trusted-public-keys $pk1 + +# Build something content-addressed. +outPathCA=$(IMPURE_VAR1=foo IMPURE_VAR2=bar nix-build ./fixed.nix -A good.0 --no-out-link) + +[[ $(nix path-info --json $outPathCA) =~ '"ca":"fixed:md5:' ]] + +# Content-addressed paths don't need signatures, so they verify +# regardless of --sigs-needed. +nix store verify $outPathCA +nix store verify $outPathCA --sigs-needed 1000 + +# Check that signing a content-addressed path doesn't overflow validSigs +nix store sign --key-file $TEST_ROOT/sk1 $outPathCA +nix store verify -r $outPathCA --sigs-needed 1000 --trusted-public-keys $pk1 + +# Copy to a binary cache. +nix copy --to file://$cacheDir $outPath2 + +# Verify that signatures got copied. +info=$(nix path-info --store file://$cacheDir --json $outPath2) +(! [[ $info =~ '"ultimate":true' ]]) +[[ $info =~ 'cache1.example.org' ]] +(! [[ $info =~ 'cache2.example.org' ]]) + +# Verify that adding a signature to a path in a binary cache works. +nix store sign --store file://$cacheDir --key-file $TEST_ROOT/sk2 $outPath2 +info=$(nix path-info --store file://$cacheDir --json $outPath2) +[[ $info =~ 'cache1.example.org' ]] +[[ $info =~ 'cache2.example.org' ]] + +# Copying to a diverted store should fail due to a lack of signatures by trusted keys. +chmod -R u+w $TEST_ROOT/store0 || true +rm -rf $TEST_ROOT/store0 + +# Fails or very flaky only on GHA + macOS: +# expectStderr 1 nix copy --to $TEST_ROOT/store0 $outPath | grepQuiet -E 'cannot add path .* because it lacks a signature by a trusted key' +# but this works: +(! nix copy --to $TEST_ROOT/store0 $outPath) + +# But succeed if we supply the public keys. +nix copy --to $TEST_ROOT/store0 $outPath --trusted-public-keys $pk1 + +expect 2 nix store verify --store $TEST_ROOT/store0 -r $outPath + +nix store verify --store $TEST_ROOT/store0 -r $outPath --trusted-public-keys $pk1 +nix store verify --store $TEST_ROOT/store0 -r $outPath --sigs-needed 2 --trusted-public-keys "$pk1 $pk2" + +# It should also succeed if we disable signature checking. +(! nix copy --to $TEST_ROOT/store0 $outPath2) +nix copy --to $TEST_ROOT/store0?require-sigs=false $outPath2 + +# But signatures should still get copied. +nix store verify --store $TEST_ROOT/store0 -r $outPath2 --trusted-public-keys $pk1 + +# Content-addressed stuff can be copied without signatures. +nix copy --to $TEST_ROOT/store0 $outPathCA diff --git a/tests/functional/simple-failing.nix b/tests/functional/simple-failing.nix new file mode 100644 index 000000000..d176c9c51 --- /dev/null +++ b/tests/functional/simple-failing.nix @@ -0,0 +1,12 @@ +with import ./config.nix; + +mkDerivation { + name = "simple-failing"; + builder = builtins.toFile "builder.sh" + '' + echo "This should fail" + exit 1 + ''; + PATH = ""; + goodPath = path; +} diff --git a/tests/functional/simple.builder.sh b/tests/functional/simple.builder.sh new file mode 100644 index 000000000..569e8ca88 --- /dev/null +++ b/tests/functional/simple.builder.sh @@ -0,0 +1,11 @@ +echo "PATH=$PATH" + +# Verify that the PATH is empty. +if mkdir foo 2> /dev/null; then exit 1; fi + +# Set a PATH (!!! impure). +export PATH=$goodPath + +mkdir $out + +echo "Hello World!" > $out/hello \ No newline at end of file diff --git a/tests/functional/simple.nix b/tests/functional/simple.nix new file mode 100644 index 000000000..4223c0f23 --- /dev/null +++ b/tests/functional/simple.nix @@ -0,0 +1,8 @@ +with import ./config.nix; + +mkDerivation { + name = "simple"; + builder = ./simple.builder.sh; + PATH = ""; + goodPath = path; +} diff --git a/tests/functional/simple.sh b/tests/functional/simple.sh new file mode 100644 index 000000000..50d44f93f --- /dev/null +++ b/tests/functional/simple.sh @@ -0,0 +1,33 @@ +source common.sh + +drvPath=$(nix-instantiate simple.nix) + +test "$(nix-store -q --binding system "$drvPath")" = "$system" + +echo "derivation is $drvPath" + +outPath=$(nix-store -rvv "$drvPath") + +echo "output path is $outPath" + +(! [ -w $outPath ]) + +text=$(cat "$outPath"/hello) +if test "$text" != "Hello World!"; then exit 1; fi + +# Directed delete: $outPath is not reachable from a root, so it should +# be deleteable. +nix-store --delete $outPath +(! [ -e $outPath/hello ]) + +outPath="$(NIX_REMOTE=local?store=/foo\&real=$TEST_ROOT/real-store nix-instantiate --readonly-mode hash-check.nix)" +if test "$outPath" != "/foo/lfy1s6ca46rm5r6w4gg9hc0axiakjcnm-dependencies.drv"; then + echo "hashDerivationModulo appears broken, got $outPath" + exit 1 +fi + +outPath="$(NIX_REMOTE=local?store=/foo\&real=$TEST_ROOT/real-store nix-instantiate --readonly-mode big-derivation-attr.nix)" +if test "$outPath" != "/foo/xxiwa5zlaajv6xdjynf9yym9g319d6mn-big-derivation-attr.drv"; then + echo "big-derivation-attr.nix hash appears broken, got $outPath. Memory corruption in large drv attr?" + exit 1 +fi diff --git a/tests/functional/ssh-relay.sh b/tests/functional/ssh-relay.sh new file mode 100644 index 000000000..053b2f00d --- /dev/null +++ b/tests/functional/ssh-relay.sh @@ -0,0 +1,16 @@ +source common.sh + +echo foo > $TEST_ROOT/hello.sh + +ssh_localhost=ssh://localhost +remote_store=?remote-store=$ssh_localhost + +store=$ssh_localhost + +store+=$remote_store +store+=$remote_store +store+=$remote_store + +out=$(nix store add-path --store "$store" $TEST_ROOT/hello.sh) + +[ foo = $(< $out) ] diff --git a/tests/functional/store-ping.sh b/tests/functional/store-ping.sh new file mode 100644 index 000000000..9846c7d3d --- /dev/null +++ b/tests/functional/store-ping.sh @@ -0,0 +1,17 @@ +source common.sh + +STORE_INFO=$(nix store ping 2>&1) +STORE_INFO_JSON=$(nix store ping --json) + +echo "$STORE_INFO" | grep "Store URL: ${NIX_REMOTE}" + +if [[ -v NIX_DAEMON_PACKAGE ]] && isDaemonNewer "2.7.0pre20220126"; then + DAEMON_VERSION=$($NIX_DAEMON_PACKAGE/bin/nix-daemon --version | cut -d' ' -f3) + echo "$STORE_INFO" | grep "Version: $DAEMON_VERSION" + [[ "$(echo "$STORE_INFO_JSON" | jq -r ".version")" == "$DAEMON_VERSION" ]] +fi + +expect 127 NIX_REMOTE=unix:$PWD/store nix store ping || \ + fail "nix store ping on a non-existent store should fail" + +[[ "$(echo "$STORE_INFO_JSON" | jq -r ".url")" == "${NIX_REMOTE:-local}" ]] diff --git a/tests/functional/structured-attrs-shell.nix b/tests/functional/structured-attrs-shell.nix new file mode 100644 index 000000000..57c1e6bd2 --- /dev/null +++ b/tests/functional/structured-attrs-shell.nix @@ -0,0 +1,21 @@ +with import ./config.nix; +let + dep = mkDerivation { + name = "dep"; + buildCommand = '' + mkdir $out; echo bla > $out/bla + ''; + }; + inherit (import ./shell.nix { inNixShell = true; }) stdenv; +in +mkDerivation { + name = "structured2"; + __structuredAttrs = true; + inherit stdenv; + outputs = [ "out" "dev" ]; + my.list = [ "a" "b" "c" ]; + exportReferencesGraph.refs = [ dep ]; + buildCommand = '' + touch ''${outputs[out]}; touch ''${outputs[dev]} + ''; +} diff --git a/tests/functional/structured-attrs.nix b/tests/functional/structured-attrs.nix new file mode 100644 index 000000000..e93139a44 --- /dev/null +++ b/tests/functional/structured-attrs.nix @@ -0,0 +1,70 @@ +with import ./config.nix; + +let + + dep = mkDerivation { + name = "dep"; + buildCommand = '' + mkdir $out; echo bla > $out/bla + ''; + }; + +in + +mkDerivation { + name = "structured"; + + __structuredAttrs = true; + + outputs = [ "out" "dev" ]; + + buildCommand = '' + set -x + + [[ $int = 123456789 ]] + [[ -z $float ]] + [[ -n $boolTrue ]] + [[ -z $boolFalse ]] + [[ -n ''${hardening[format]} ]] + [[ -z ''${hardening[fortify]} ]] + [[ ''${#buildInputs[@]} = 7 ]] + [[ ''${buildInputs[2]} = c ]] + [[ -v nothing ]] + [[ -z $nothing ]] + + mkdir ''${outputs[out]} ''${outputs[dev]} + echo bar > $dest + echo foo > $dest2 + + json=$(cat $NIX_ATTRS_JSON_FILE) + [[ $json =~ '"narHash":"sha256:1r7yc43zqnzl5b0als5vnyp649gk17i37s7mj00xr8kc47rjcybk"' ]] + [[ $json =~ '"narSize":288' ]] + [[ $json =~ '"closureSize":288' ]] + [[ $json =~ '"references":[]' ]] + ''; + + buildInputs = [ "a" "b" "c" 123 "'" "\"" null ]; + + hardening.format = true; + hardening.fortify = false; + + outer.inner = [ 1 2 3 ]; + + int = 123456789; + + float = 123.456; + + boolTrue = true; + boolFalse = false; + + nothing = null; + + dest = "${placeholder "out"}/foo"; + dest2 = "${placeholder "dev"}/foo"; + + "foo bar" = "BAD"; + "1foobar" = "BAD"; + "foo$" = "BAD"; + + exportReferencesGraph.refs = [ dep ]; +} diff --git a/tests/functional/structured-attrs.sh b/tests/functional/structured-attrs.sh new file mode 100644 index 000000000..378dbc735 --- /dev/null +++ b/tests/functional/structured-attrs.sh @@ -0,0 +1,23 @@ +source common.sh + +# 27ce722638 required some incompatible changes to the nix file, so skip this +# tests for the older versions +requireDaemonNewerThan "2.4pre20210712" + +clearStore + +rm -f $TEST_ROOT/result + +nix-build structured-attrs.nix -A all -o $TEST_ROOT/result + +[[ $(cat $TEST_ROOT/result/foo) = bar ]] +[[ $(cat $TEST_ROOT/result-dev/foo) = foo ]] + +export NIX_BUILD_SHELL=$SHELL +env NIX_PATH=nixpkgs=shell.nix nix-shell structured-attrs-shell.nix \ + --run 'test -e .attrs.json; test "3" = "$(jq ".my.list|length" < $NIX_ATTRS_JSON_FILE)"' + +# `nix develop` is a slightly special way of dealing with environment vars, it parses +# these from a shell-file exported from a derivation. This is to test especially `outputs` +# (which is an associative array in thsi case) being fine. +nix develop -f structured-attrs-shell.nix -c bash -c 'test -n "$out"' diff --git a/tests/functional/substitute-with-invalid-ca.sh b/tests/functional/substitute-with-invalid-ca.sh new file mode 100644 index 000000000..4d0b01e0f --- /dev/null +++ b/tests/functional/substitute-with-invalid-ca.sh @@ -0,0 +1,38 @@ +source common.sh + +BINARY_CACHE=file://$cacheDir + +getHash() { + basename "$1" | cut -d '-' -f 1 +} +getRemoteNarInfo () { + echo "$cacheDir/$(getHash "$1").narinfo" +} + +cat < $TEST_HOME/good.txt +I’m a good path +EOF + +cat < $TEST_HOME/bad.txt +I’m a bad path +EOF + +good=$(nix-store --add $TEST_HOME/good.txt) +bad=$(nix-store --add $TEST_HOME/bad.txt) +nix copy --to "$BINARY_CACHE" "$good" +nix copy --to "$BINARY_CACHE" "$bad" +nix-collect-garbage >/dev/null 2>&1 + +# Falsifying the narinfo file for '$good' +goodPathNarInfo=$(getRemoteNarInfo "$good") +badPathNarInfo=$(getRemoteNarInfo "$bad") +for fieldName in URL FileHash FileSize NarHash NarSize; do + sed -i "/^$fieldName/d" "$goodPathNarInfo" + grep -E "^$fieldName" "$badPathNarInfo" >> "$goodPathNarInfo" +done + +# Copying back '$good' from the binary cache. This should fail as it is +# corrupted +if nix copy --from "$BINARY_CACHE" "$good"; then + fail "Importing a path with a wrong CA field should fail" +fi diff --git a/tests/functional/suggestions.sh b/tests/functional/suggestions.sh new file mode 100644 index 000000000..f18fefef9 --- /dev/null +++ b/tests/functional/suggestions.sh @@ -0,0 +1,44 @@ +source common.sh + +clearStore + +cd "$TEST_HOME" + +cat < flake.nix +{ + outputs = a: { + packages.$system = { + foo = 1; + fo1 = 1; + fo2 = 1; + fooo = 1; + foooo = 1; + fooooo = 1; + fooooo1 = 1; + fooooo2 = 1; + fooooo3 = 1; + fooooo4 = 1; + fooooo5 = 1; + fooooo6 = 1; + }; + }; +} +EOF + +# Probable typo in the requested attribute path. Suggest some close possibilities +NIX_BUILD_STDERR_WITH_SUGGESTIONS=$(! nix build .\#fob 2>&1 1>/dev/null) +[[ "$NIX_BUILD_STDERR_WITH_SUGGESTIONS" =~ "Did you mean one of fo1, fo2, foo or fooo?" ]] || \ + fail "The nix build stderr should suggest the three closest possiblities" + +# None of the possible attributes is close to `bar`, so shouldn’t suggest anything +NIX_BUILD_STDERR_WITH_NO_CLOSE_SUGGESTION=$(! nix build .\#bar 2>&1 1>/dev/null) +[[ ! "$NIX_BUILD_STDERR_WITH_NO_CLOSE_SUGGESTION" =~ "Did you mean" ]] || \ + fail "The nix build stderr shouldn’t suggest anything if there’s nothing relevant to suggest" + +NIX_EVAL_STDERR_WITH_SUGGESTIONS=$(! nix build --impure --expr '(builtins.getFlake (builtins.toPath ./.)).packages.'$system'.fob' 2>&1 1>/dev/null) +[[ "$NIX_EVAL_STDERR_WITH_SUGGESTIONS" =~ "Did you mean one of fo1, fo2, foo or fooo?" ]] || \ + fail "The evaluator should suggest the three closest possiblities" + +NIX_EVAL_STDERR_WITH_SUGGESTIONS=$(! nix build --impure --expr '({ foo }: foo) { foo = 1; fob = 2; }' 2>&1 1>/dev/null) +[[ "$NIX_EVAL_STDERR_WITH_SUGGESTIONS" =~ "Did you mean foo?" ]] || \ + fail "The evaluator should suggest the three closest possiblities" diff --git a/tests/functional/supplementary-groups.sh b/tests/functional/supplementary-groups.sh new file mode 100644 index 000000000..d18fb2414 --- /dev/null +++ b/tests/functional/supplementary-groups.sh @@ -0,0 +1,37 @@ +source common.sh + +requireSandboxSupport +[[ $busybox =~ busybox ]] || skipTest "no busybox" +if ! command -p -v unshare; then skipTest "Need unshare"; fi +needLocalStore "The test uses --store always so we would just be bypassing the daemon" + +unshare --mount --map-root-user bash < $tarball + + nix-env -f file://$tarball -qa --out-path | grepQuiet dependencies + + nix-build -o $TEST_ROOT/result file://$tarball + + nix-build -o $TEST_ROOT/result '' -I foo=file://$tarball + + nix-build -o $TEST_ROOT/result -E "import (fetchTarball file://$tarball)" + # Do not re-fetch paths already present + nix-build -o $TEST_ROOT/result -E "import (fetchTarball { url = file:///does-not-exist/must-remain-unused/$tarball; sha256 = \"$hash\"; })" + + nix-build -o $TEST_ROOT/result -E "import (fetchTree file://$tarball)" + nix-build -o $TEST_ROOT/result -E "import (fetchTree { type = \"tarball\"; url = file://$tarball; })" + nix-build -o $TEST_ROOT/result -E "import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; })" + # Do not re-fetch paths already present + nix-build -o $TEST_ROOT/result -E "import (fetchTree { type = \"tarball\"; url = file:///does-not-exist/must-remain-unused/$tarball; narHash = \"$hash\"; })" + expectStderr 102 nix-build -o $TEST_ROOT/result -E "import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"sha256-xdKv2pq/IiwLSnBBJXW8hNowI4MrdZfW+SYqDQs7Tzc=\"; })" | grep 'NAR hash mismatch in input' + + [[ $(nix eval --impure --expr "(fetchTree file://$tarball).lastModified") = 1000000000 ]] + + nix-instantiate --strict --eval -E "!((import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; })) ? submodules)" >&2 + nix-instantiate --strict --eval -E "!((import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; })) ? submodules)" 2>&1 | grep 'true' + + nix-instantiate --eval -E '1 + 2' -I fnord=file://no-such-tarball.tar$ext + nix-instantiate --eval -E 'with ; 1 + 2' -I fnord=file://no-such-tarball$ext + (! nix-instantiate --eval -E ' 1' -I fnord=file://no-such-tarball$ext) + + nix-instantiate --eval -E '' -I fnord=file://no-such-tarball$ext -I fnord=. + + # Ensure that the `name` attribute isn’t accepted as that would mess + # with the content-addressing + (! nix-instantiate --eval -E "fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; name = \"foo\"; }") + +} + +test_tarball '' cat +test_tarball .xz xz +test_tarball .gz gzip + +rm -rf $TEST_ROOT/tmp +mkdir -p $TEST_ROOT/tmp +(! TMPDIR=$TEST_ROOT/tmp XDG_RUNTIME_DIR=$TEST_ROOT/tmp nix-env -f file://$(pwd)/bad.tar.xz -qa --out-path) +(! [ -e $TEST_ROOT/tmp/bad ]) diff --git a/tests/functional/test-infra.sh b/tests/functional/test-infra.sh new file mode 100644 index 000000000..54ae120e7 --- /dev/null +++ b/tests/functional/test-infra.sh @@ -0,0 +1,85 @@ +# Test the functions for testing themselves! +# Also test some assumptions on how bash works that they rely on. +source common.sh + +# `true` should exit with 0 +expect 0 true + +# `false` should exit with 1 +expect 1 false + +# `expect` will fail when we get it wrong +expect 1 expect 0 false + +noisyTrue () { + echo YAY! >&2 + true +} + +noisyFalse () { + echo NAY! >&2 + false +} + +# These should redirect standard error to standard output +expectStderr 0 noisyTrue | grepQuiet YAY +expectStderr 1 noisyFalse | grepQuiet NAY + +# `set -o pipefile` is enabled + +pipefailure () { + # shellcheck disable=SC2216 + true | false | true +} +expect 1 pipefailure +unset pipefailure + +pipefailure () { + # shellcheck disable=SC2216 + false | true | true +} +expect 1 pipefailure +unset pipefailure + +commandSubstitutionPipeFailure () { + # shellcheck disable=SC2216 + res=$(set -eu -o pipefail; false | true | echo 0) +} +expect 1 commandSubstitutionPipeFailure + +# `set -u` is enabled + +# note (...), making function use subshell, as unbound variable errors +# in the outer shell are *rightly* not recoverable. +useUnbound () ( + set -eu + # shellcheck disable=SC2154 + echo "$thisVariableIsNotBound" +) +expect 1 useUnbound + +# ! alone unfortunately negates `set -e`, but it works in functions: +# shellcheck disable=SC2251 +! true +funBang () { + ! true +} +expect 1 funBang +unset funBang + +# `grep -v -q` is not what we want for exit codes, but `grepInverse` is +# Avoid `grep -v -q`. The following line proves the point, and if it fails, +# we'll know that `grep` had a breaking change or `-v -q` may not be portable. +{ echo foo; echo bar; } | grep -v -q foo +{ echo foo; echo bar; } | expect 1 grepInverse foo + +# `grepQuiet` is quiet +res=$(set -eu -o pipefail; echo foo | grepQuiet foo | wc -c) +(( res == 0 )) +unset res + +# `greqQietInverse` is both +{ echo foo; echo bar; } | expect 1 grepQuietInverse foo +res=$(set -eu -o pipefail; echo foo | expect 1 grepQuietInverse foo | wc -c) +(( res == 0 )) +unset res diff --git a/tests/functional/test-libstoreconsumer.sh b/tests/functional/test-libstoreconsumer.sh new file mode 100644 index 000000000..8a77cf5a1 --- /dev/null +++ b/tests/functional/test-libstoreconsumer.sh @@ -0,0 +1,6 @@ +source common.sh + +drv="$(nix-instantiate simple.nix)" +cat "$drv" +out="$(./test-libstoreconsumer/test-libstoreconsumer "$drv")" +cat "$out/hello" | grep -F "Hello World!" diff --git a/tests/functional/test-libstoreconsumer/README.md b/tests/functional/test-libstoreconsumer/README.md new file mode 100644 index 000000000..ded69850f --- /dev/null +++ b/tests/functional/test-libstoreconsumer/README.md @@ -0,0 +1,6 @@ + +A very simple C++ consumer of the libstore library. + + - Keep it simple. Library consumers expect something simple. + - No build hook, or any other reinvocations. + - No more global state than necessary. diff --git a/tests/functional/test-libstoreconsumer/local.mk b/tests/functional/test-libstoreconsumer/local.mk new file mode 100644 index 000000000..edc140723 --- /dev/null +++ b/tests/functional/test-libstoreconsumer/local.mk @@ -0,0 +1,15 @@ +programs += test-libstoreconsumer + +test-libstoreconsumer_DIR := $(d) + +# do not install +test-libstoreconsumer_INSTALL_DIR := + +test-libstoreconsumer_SOURCES := \ + $(wildcard $(d)/*.cc) \ + +test-libstoreconsumer_CXXFLAGS += -I src/libutil -I src/libstore + +test-libstoreconsumer_LIBS = libstore libutil + +test-libstoreconsumer_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) $(LOWDOWN_LIBS) diff --git a/tests/functional/test-libstoreconsumer/main.cc b/tests/functional/test-libstoreconsumer/main.cc new file mode 100644 index 000000000..c61489af6 --- /dev/null +++ b/tests/functional/test-libstoreconsumer/main.cc @@ -0,0 +1,45 @@ +#include "globals.hh" +#include "store-api.hh" +#include "build-result.hh" +#include + +using namespace nix; + +int main (int argc, char **argv) +{ + try { + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " store/path/to/something.drv\n"; + return 1; + } + + std::string drvPath = argv[1]; + + initLibStore(); + + auto store = nix::openStore(); + + // build the derivation + + std::vector paths { + DerivedPath::Built { + .drvPath = makeConstantStorePathRef(store->parseStorePath(drvPath)), + .outputs = OutputsSpec::Names{"out"} + } + }; + + const auto results = store->buildPathsWithResults(paths, bmNormal, store); + + for (const auto & result : results) { + for (const auto & [outputName, realisation] : result.builtOutputs) { + std::cout << store->printStorePath(realisation.outPath) << "\n"; + } + } + + return 0; + + } catch (const std::exception & e) { + std::cerr << "Error: " << e.what() << "\n"; + return 1; + } +} diff --git a/tests/functional/timeout.nix b/tests/functional/timeout.nix new file mode 100644 index 000000000..d0e949e31 --- /dev/null +++ b/tests/functional/timeout.nix @@ -0,0 +1,31 @@ +with import ./config.nix; + +{ + + infiniteLoop = mkDerivation { + name = "timeout"; + buildCommand = '' + touch $out + echo "'timeout' builder entering an infinite loop" + while true ; do echo -n .; done + ''; + }; + + silent = mkDerivation { + name = "silent"; + buildCommand = '' + touch $out + sleep 60 + ''; + }; + + closeLog = mkDerivation { + name = "silent"; + buildCommand = '' + touch $out + exec > /dev/null 2>&1 + sleep 1000000000 + ''; + }; + +} diff --git a/tests/functional/timeout.sh b/tests/functional/timeout.sh new file mode 100644 index 000000000..b179b79a2 --- /dev/null +++ b/tests/functional/timeout.sh @@ -0,0 +1,39 @@ +# Test the `--timeout' option. + +source common.sh + +# XXX: This shouldn’t be, but #4813 cause this test to fail +needLocalStore "see #4813" + +messages=$(nix-build -Q timeout.nix -A infiniteLoop --timeout 2 2>&1) && status=0 || status=$? + +if [ $status -ne 101 ]; then + echo "error: 'nix-store' exited with '$status'; should have exited 101" + exit 1 +fi + +if echo "$messages" | grepQuietInvert "timed out"; then + echo "error: build may have failed for reasons other than timeout; output:" + echo "$messages" >&2 + exit 1 +fi + +if nix-build -Q timeout.nix -A infiniteLoop --max-build-log-size 100; then + echo "build should have failed" + exit 1 +fi + +if nix-build timeout.nix -A silent --max-silent-time 2; then + echo "build should have failed" + exit 1 +fi + +if nix-build timeout.nix -A closeLog; then + echo "build should have failed" + exit 1 +fi + +if nix build -f timeout.nix silent --max-silent-time 2; then + echo "build should have failed" + exit 1 +fi diff --git a/tests/functional/toString-path.sh b/tests/functional/toString-path.sh new file mode 100644 index 000000000..07eb87465 --- /dev/null +++ b/tests/functional/toString-path.sh @@ -0,0 +1,8 @@ +source common.sh + +mkdir -p $TEST_ROOT/foo +echo bla > $TEST_ROOT/foo/bar + +[[ $(nix eval --raw --impure --expr "builtins.readFile (builtins.toString (builtins.fetchTree { type = \"path\"; path = \"$TEST_ROOT/foo\"; } + \"/bar\"))") = bla ]] + +[[ $(nix eval --json --impure --expr "builtins.readDir (builtins.toString (builtins.fetchTree { type = \"path\"; path = \"$TEST_ROOT/foo\"; }))") = '{"bar":"regular"}' ]] diff --git a/tests/functional/undefined-variable.nix b/tests/functional/undefined-variable.nix new file mode 100644 index 000000000..579985497 --- /dev/null +++ b/tests/functional/undefined-variable.nix @@ -0,0 +1 @@ +let f = builtins.toFile "test-file.nix" "asd"; in import f diff --git a/tests/functional/user-envs-migration.sh b/tests/functional/user-envs-migration.sh new file mode 100644 index 000000000..187372b16 --- /dev/null +++ b/tests/functional/user-envs-migration.sh @@ -0,0 +1,35 @@ +# Test that the migration of user environments +# (https://github.com/NixOS/nix/pull/5226) does preserve everything + +source common.sh + +if isDaemonNewer "2.4pre20211005"; then + skipTest "Daemon is too new" +fi + + +killDaemon +unset NIX_REMOTE + +clearStore +clearProfiles +rm -rf ~/.nix-profile + +# Fill the environment using the older Nix +PATH_WITH_NEW_NIX="$PATH" +export PATH="$NIX_DAEMON_PACKAGE/bin:$PATH" + +nix-env -f user-envs.nix -i foo-1.0 +nix-env -f user-envs.nix -i bar-0.1 + +# Migrate to the new profile dir, and ensure that everything’s there +export PATH="$PATH_WITH_NEW_NIX" +nix-env -q # Trigger the migration +( [[ -L ~/.nix-profile ]] && \ + [[ $(readlink ~/.nix-profile) == ~/.local/share/nix/profiles/profile ]] ) || \ + fail "The nix profile should point to the new location" + +(nix-env -q | grep foo && nix-env -q | grep bar && \ + [[ -e ~/.nix-profile/bin/foo ]] && \ + [[ $(nix-env --list-generations | wc -l) == 2 ]]) || + fail "The nix profile should have the same content as before the migration" diff --git a/tests/functional/user-envs.builder.sh b/tests/functional/user-envs.builder.sh new file mode 100644 index 000000000..5fafa797f --- /dev/null +++ b/tests/functional/user-envs.builder.sh @@ -0,0 +1,5 @@ +mkdir $out +mkdir $out/bin +echo "#! $shell" > $out/bin/$progName +echo "echo $name" >> $out/bin/$progName +chmod +x $out/bin/$progName diff --git a/tests/functional/user-envs.nix b/tests/functional/user-envs.nix new file mode 100644 index 000000000..46f8b51dd --- /dev/null +++ b/tests/functional/user-envs.nix @@ -0,0 +1,34 @@ +# Some dummy arguments... +{ foo ? "foo" +}: + +with import ./config.nix; + +assert foo == "foo"; + +let + + platforms = let x = "foobar"; in [ x x ]; + + makeDrv = name: progName: (mkDerivation { + name = assert progName != "fail"; name; + inherit progName system; + builder = ./user-envs.builder.sh; + } // { + meta = { + description = "A silly test package with some \${escaped anti-quotation} in it"; + inherit platforms; + }; + }); + +in + + [ + (makeDrv "foo-1.0" "foo") + (makeDrv "foo-2.0pre1" "foo") + (makeDrv "bar-0.1" "bar") + (makeDrv "foo-2.0" "foo") + (makeDrv "bar-0.1.1" "bar") + (makeDrv "foo-0.1" "foo" // { meta.priority = 10; }) + (makeDrv "fail-0.1" "fail") + ] diff --git a/tests/functional/user-envs.sh b/tests/functional/user-envs.sh new file mode 100644 index 000000000..d1260ba04 --- /dev/null +++ b/tests/functional/user-envs.sh @@ -0,0 +1,190 @@ +source common.sh + +if [ -z "${storeCleared-}" ]; then + clearStore +fi + +clearProfiles + +# Query installed: should be empty. +test "$(nix-env -p $profiles/test -q '*' | wc -l)" -eq 0 + +nix-env --switch-profile $profiles/test + +# Query available: should contain several. +test "$(nix-env -f ./user-envs.nix -qa '*' | wc -l)" -eq 6 +outPath10=$(nix-env -f ./user-envs.nix -qa --out-path --no-name '*' | grep foo-1.0) +drvPath10=$(nix-env -f ./user-envs.nix -qa --drv-path --no-name '*' | grep foo-1.0) +[ -n "$outPath10" -a -n "$drvPath10" ] + +# Query with json +nix-env -f ./user-envs.nix -qa --json | jq -e '.[] | select(.name == "bar-0.1") | [ + .outputName == "out", + .outputs.out == null +] | all' +nix-env -f ./user-envs.nix -qa --json --out-path | jq -e '.[] | select(.name == "bar-0.1") | [ + .outputName == "out", + (.outputs.out | test("'$NIX_STORE_DIR'.*-0\\.1")) +] | all' + +# Query descriptions. +nix-env -f ./user-envs.nix -qa '*' --description | grepQuiet silly +rm -rf $HOME/.nix-defexpr +ln -s $(pwd)/user-envs.nix $HOME/.nix-defexpr +nix-env -qa '*' --description | grepQuiet silly + +# Query the system. +nix-env -qa '*' --system | grepQuiet $system + +# Install "foo-1.0". +nix-env -i foo-1.0 + +# Query installed: should contain foo-1.0 now (which should be +# executable). +test "$(nix-env -q '*' | wc -l)" -eq 1 +nix-env -q '*' | grepQuiet foo-1.0 +test "$($profiles/test/bin/foo)" = "foo-1.0" + +# Test nix-env -qc to compare installed against available packages, and vice versa. +nix-env -qc '*' | grepQuiet '< 2.0' +nix-env -qac '*' | grepQuiet '> 1.0' + +# Test the -b flag to filter out source-only packages. +[ "$(nix-env -qab | wc -l)" -eq 1 ] + +# Test the -s flag to get package status. +nix-env -qas | grepQuiet 'IP- foo-1.0' +nix-env -qas | grepQuiet -- '--- bar-0.1' + +# Disable foo. +nix-env --set-flag active false foo +(! [ -e "$profiles/test/bin/foo" ]) + +# Enable foo. +nix-env --set-flag active true foo +[ -e "$profiles/test/bin/foo" ] + +# Store the path of foo-1.0. +outPath10_=$(nix-env -q --out-path --no-name '*' | grep foo-1.0) +echo "foo-1.0 = $outPath10" +[ "$outPath10" = "$outPath10_" ] + +# Install "foo-2.0pre1": should remove foo-1.0. +nix-env -i foo-2.0pre1 + +# Query installed: should contain foo-2.0pre1 now. +test "$(nix-env -q '*' | wc -l)" -eq 1 +nix-env -q '*' | grepQuiet foo-2.0pre1 +test "$($profiles/test/bin/foo)" = "foo-2.0pre1" + +# Upgrade "foo": should install foo-2.0. +NIX_PATH=nixpkgs=./user-envs.nix:${NIX_PATH-} nix-env -f '' -u foo + +# Query installed: should contain foo-2.0 now. +test "$(nix-env -q '*' | wc -l)" -eq 1 +nix-env -q '*' | grepQuiet foo-2.0 +test "$($profiles/test/bin/foo)" = "foo-2.0" + +# Store the path of foo-2.0. +outPath20=$(nix-env -q --out-path --no-name '*' | grep foo-2.0) +test -n "$outPath20" + +# Install bar-0.1, uninstall foo. +nix-env -i bar-0.1 +nix-env -e foo + +# Query installed: should only contain bar-0.1 now. +if nix-env -q '*' | grepQuiet foo; then false; fi +nix-env -q '*' | grepQuiet bar + +# Rollback: should bring "foo" back. +oldGen="$(nix-store -q --resolve $profiles/test)" +nix-env --rollback +[ "$(nix-store -q --resolve $profiles/test)" != "$oldGen" ] +nix-env -q '*' | grepQuiet foo-2.0 +nix-env -q '*' | grepQuiet bar + +# Rollback again: should remove "bar". +nix-env --rollback +nix-env -q '*' | grepQuiet foo-2.0 +if nix-env -q '*' | grepQuiet bar; then false; fi + +# Count generations. +nix-env --list-generations +test "$(nix-env --list-generations | wc -l)" -eq 7 + +# Doing the same operation twice results in the same generation, which triggers +# "lazy" behaviour and does not create a new symlink. + +nix-env -i foo +nix-env -i foo + +# Count generations. +nix-env --list-generations +test "$(nix-env --list-generations | wc -l)" -eq 8 + +# Switch to a specified generation. +nix-env --switch-generation 7 +[ "$(nix-store -q --resolve $profiles/test)" = "$oldGen" ] + +# Install foo-1.0, now using its store path. +nix-env -i "$outPath10" +nix-env -q '*' | grepQuiet foo-1.0 +nix-store -qR $profiles/test | grep "$outPath10" +nix-store -q --referrers-closure $profiles/test | grep "$(nix-store -q --resolve $profiles/test)" +[ "$(nix-store -q --deriver "$outPath10")" = $drvPath10 ] + +# Uninstall foo-1.0, using a symlink to its store path. +ln -sfn $outPath10/bin/foo $TEST_ROOT/symlink +nix-env -e $TEST_ROOT/symlink +if nix-env -q '*' | grepQuiet foo; then false; fi +nix-store -qR $profiles/test | grepInverse "$outPath10" + +# Install foo-1.0, now using a symlink to its store path. +nix-env -i $TEST_ROOT/symlink +nix-env -q '*' | grepQuiet foo + +# Delete all old generations. +nix-env --delete-generations old + +# Run the garbage collector. This should get rid of foo-2.0 but not +# foo-1.0. +nix-collect-garbage +test -e "$outPath10" +(! [ -e "$outPath20" ]) + +# Uninstall everything +nix-env -e '*' +test "$(nix-env -q '*' | wc -l)" -eq 0 + +# Installing "foo" should only install the newest foo. +nix-env -i foo +test "$(nix-env -q '*' | grep foo- | wc -l)" -eq 1 +nix-env -q '*' | grepQuiet foo-2.0 + +# On the other hand, this should install both (and should fail due to +# a collision). +nix-env -e '*' +(! nix-env -i foo-1.0 foo-2.0) + +# Installing "*" should install one foo and one bar. +nix-env -e '*' +nix-env -i '*' +test "$(nix-env -q '*' | wc -l)" -eq 2 +nix-env -q '*' | grepQuiet foo-2.0 +nix-env -q '*' | grepQuiet bar-0.1.1 + +# Test priorities: foo-0.1 has a lower priority than foo-1.0, so it +# should be possible to install both without a collision. Also test +# ‘--set-flag priority’ to manually override the declared priorities. +nix-env -e '*' +nix-env -i foo-0.1 foo-1.0 +[ "$($profiles/test/bin/foo)" = "foo-1.0" ] +nix-env --set-flag priority 1 foo-0.1 +[ "$($profiles/test/bin/foo)" = "foo-0.1" ] + +# Test nix-env --set. +nix-env --set $outPath10 +[ "$(nix-store -q --resolve $profiles/test)" = $outPath10 ] +nix-env --set $drvPath10 +[ "$(nix-store -q --resolve $profiles/test)" = $outPath10 ] diff --git a/tests/functional/why-depends.sh b/tests/functional/why-depends.sh new file mode 100644 index 000000000..9680bf80e --- /dev/null +++ b/tests/functional/why-depends.sh @@ -0,0 +1,29 @@ +source common.sh + +clearStore + +cp ./dependencies.nix ./dependencies.builder0.sh ./config.nix $TEST_HOME + +cd $TEST_HOME + +nix why-depends --derivation --file ./dependencies.nix input2_drv input1_drv +nix why-depends --file ./dependencies.nix input2_drv input1_drv + +nix-build ./dependencies.nix -A input0_drv -o dep +nix-build ./dependencies.nix -o toplevel + +FAST_WHY_DEPENDS_OUTPUT=$(nix why-depends ./toplevel ./dep) +PRECISE_WHY_DEPENDS_OUTPUT=$(nix why-depends ./toplevel ./dep --precise) + +# Both outputs should show that `input-2` is in the dependency chain +echo "$FAST_WHY_DEPENDS_OUTPUT" | grepQuiet input-2 +echo "$PRECISE_WHY_DEPENDS_OUTPUT" | grepQuiet input-2 + +# But only the “precise” one should refer to `reference-to-input-2` +echo "$FAST_WHY_DEPENDS_OUTPUT" | grepQuietInverse reference-to-input-2 +echo "$PRECISE_WHY_DEPENDS_OUTPUT" | grepQuiet reference-to-input-2 + +<<<"$PRECISE_WHY_DEPENDS_OUTPUT" sed -n '2p' | grepQuiet "└───reference-to-input-2 -> " +<<<"$PRECISE_WHY_DEPENDS_OUTPUT" sed -n '3p' | grep " →" | grepQuiet "dependencies-input-2" +<<<"$PRECISE_WHY_DEPENDS_OUTPUT" sed -n '4p' | grepQuiet " └───input0: …" # in input-2, file input0 +<<<"$PRECISE_WHY_DEPENDS_OUTPUT" sed -n '5p' | grep " →" | grepQuiet "dependencies-input-0" # is dependencies-input-0 referenced diff --git a/tests/functional/zstd.sh b/tests/functional/zstd.sh new file mode 100644 index 000000000..ba7c20501 --- /dev/null +++ b/tests/functional/zstd.sh @@ -0,0 +1,28 @@ +source common.sh + +clearStore +clearCache + +cacheURI="file://$cacheDir?compression=zstd" + +outPath=$(nix-build dependencies.nix --no-out-link) + +nix copy --to $cacheURI $outPath + +HASH=$(nix hash path $outPath) + +clearStore +clearCacheCache + +nix copy --from $cacheURI $outPath --no-check-sigs + +if ls $cacheDir/nar/*.zst &> /dev/null; then + echo "files do exist" +else + echo "nars do not exist" + exit 1 +fi + +HASH2=$(nix hash path $outPath) + +[[ $HASH = $HASH2 ]] diff --git a/tests/gc-auto.sh b/tests/gc-auto.sh deleted file mode 100644 index 521d9e539..000000000 --- a/tests/gc-auto.sh +++ /dev/null @@ -1,81 +0,0 @@ -source common.sh - -needLocalStore "“min-free” and “max-free” are daemon options" - -clearStore - -garbage1=$(nix store add-path --name garbage1 ./nar-access.sh) -garbage2=$(nix store add-path --name garbage2 ./nar-access.sh) -garbage3=$(nix store add-path --name garbage3 ./nar-access.sh) - -ls -l $garbage3 -POSIXLY_CORRECT=1 du $garbage3 - -fake_free=$TEST_ROOT/fake-free -export _NIX_TEST_FREE_SPACE_FILE=$fake_free -echo 1100 > $fake_free - -fifoLock=$TEST_ROOT/fifoLock -mkfifo "$fifoLock" - -expr=$(cat < \$out/bar - - # Pretend that we run out of space - echo 100 > ${fake_free}.tmp1 - mv ${fake_free}.tmp1 $fake_free - - # Wait for the GC to run - for i in {1..20}; do - echo ''\${i}... - if [[ \$(ls \$NIX_STORE/*-garbage? | wc -l) = 1 ]]; then - exit 0 - fi - sleep 1 - done - exit 1 - ''; -} -EOF -) - -expr2=$(cat < \$out/bar - - # Wait for the first build to finish - cat "$fifoLock" - ''; -} -EOF -) - -nix build --impure -v -o $TEST_ROOT/result-A -L --expr "$expr" \ - --min-free 1000 --max-free 2000 --min-free-check-interval 1 & -pid1=$! - -nix build --impure -v -o $TEST_ROOT/result-B -L --expr "$expr2" \ - --min-free 1000 --max-free 2000 --min-free-check-interval 1 & -pid2=$! - -# Once the first build is done, unblock the second one. -# If the first build fails, we need to postpone the failure to still allow -# the second one to finish -wait "$pid1" || FIRSTBUILDSTATUS=$? -echo "unlock" > $fifoLock -( exit ${FIRSTBUILDSTATUS:-0} ) -wait "$pid2" - -[[ foo = $(cat $TEST_ROOT/result-A/bar) ]] -[[ foo = $(cat $TEST_ROOT/result-B/bar) ]] diff --git a/tests/gc-concurrent.builder.sh b/tests/gc-concurrent.builder.sh deleted file mode 100644 index bb6dcd4cf..000000000 --- a/tests/gc-concurrent.builder.sh +++ /dev/null @@ -1,16 +0,0 @@ -echo "Build started" > "$lockFifo" - -mkdir $out -echo $(cat $input1/foo)$(cat $input2/bar) > $out/foobar - -# Wait for someone to write on the fifo -cat "$lockFifo" - -# $out should not have been GC'ed while we were sleeping, but just in -# case... -mkdir -p $out - -# Check that the GC hasn't deleted the lock on our output. -test -e "$out.lock" - -ln -s $input2 $out/input-2 diff --git a/tests/gc-concurrent.nix b/tests/gc-concurrent.nix deleted file mode 100644 index 0aba1f983..000000000 --- a/tests/gc-concurrent.nix +++ /dev/null @@ -1,30 +0,0 @@ -with import ./config.nix; - -{ lockFifo ? null }: - -rec { - - input1 = mkDerivation { - name = "dependencies-input-1"; - buildCommand = "mkdir $out; echo FOO > $out/foo"; - }; - - input2 = mkDerivation { - name = "dependencies-input-2"; - buildCommand = "mkdir $out; echo BAR > $out/bar"; - }; - - test1 = mkDerivation { - name = "gc-concurrent"; - builder = ./gc-concurrent.builder.sh; - inherit input1 input2; - inherit lockFifo; - }; - - test2 = mkDerivation { - name = "gc-concurrent2"; - builder = ./gc-concurrent2.builder.sh; - inherit input1 input2; - }; - -} diff --git a/tests/gc-concurrent.sh b/tests/gc-concurrent.sh deleted file mode 100644 index 2c6622c62..000000000 --- a/tests/gc-concurrent.sh +++ /dev/null @@ -1,59 +0,0 @@ -source common.sh - -clearStore - -lockFifo1=$TEST_ROOT/test1.fifo -mkfifo "$lockFifo1" - -drvPath1=$(nix-instantiate gc-concurrent.nix -A test1 --argstr lockFifo "$lockFifo1") -outPath1=$(nix-store -q $drvPath1) - -drvPath2=$(nix-instantiate gc-concurrent.nix -A test2) -outPath2=$(nix-store -q $drvPath2) - -drvPath3=$(nix-instantiate simple.nix) -outPath3=$(nix-store -r $drvPath3) - -(! test -e $outPath3.lock) -touch $outPath3.lock - -rm -f "$NIX_STATE_DIR"/gcroots/foo* -ln -s $drvPath2 "$NIX_STATE_DIR"/gcroots/foo -ln -s $outPath3 "$NIX_STATE_DIR"/gcroots/foo2 - -# Start build #1 in the background. It starts immediately. -nix-store -rvv "$drvPath1" & -pid1=$! - -# Wait for the build of $drvPath1 to start -cat $lockFifo1 - -# Run the garbage collector while the build is running. -nix-collect-garbage - -# Unlock the build of $drvPath1 -echo "" > $lockFifo1 -echo waiting for pid $pid1 to finish... -wait $pid1 - -# Check that the root of build #1 and its dependencies haven't been -# deleted. The should not be deleted by the GC because they were -# being built during the GC. -cat $outPath1/foobar -cat $outPath1/input-2/bar - -# Check that the build build $drvPath2 succeeds. -# It should succeed because the derivation is a GC root. -nix-store -rvv "$drvPath2" -cat $outPath2/foobar - -rm -f "$NIX_STATE_DIR"/gcroots/foo* - -# The collector should have deleted lock files for paths that have -# been built previously. -(! test -e $outPath3.lock) - -# If we run the collector now, it should delete outPath1/2. -nix-collect-garbage -(! test -e $outPath1) -(! test -e $outPath2) diff --git a/tests/gc-concurrent2.builder.sh b/tests/gc-concurrent2.builder.sh deleted file mode 100644 index 4f6c58b96..000000000 --- a/tests/gc-concurrent2.builder.sh +++ /dev/null @@ -1,5 +0,0 @@ -mkdir $out -echo $(cat $input1/foo)$(cat $input2/bar)xyzzy > $out/foobar - -# Check that the GC hasn't deleted the lock on our output. -test -e "$out.lock" diff --git a/tests/gc-non-blocking.sh b/tests/gc-non-blocking.sh deleted file mode 100644 index 0d781485d..000000000 --- a/tests/gc-non-blocking.sh +++ /dev/null @@ -1,33 +0,0 @@ -# Test whether the collector is non-blocking, i.e. a build can run in -# parallel with it. -source common.sh - -needLocalStore "the GC test needs a synchronisation point" - -clearStore - -fifo=$TEST_ROOT/test.fifo -mkfifo "$fifo" - -dummy=$(nix store add-path ./simple.nix) - -running=$TEST_ROOT/running -touch $running - -(_NIX_TEST_GC_SYNC=$fifo nix-store --gc -vvvvv; rm $running) & -pid=$! - -sleep 2 - -outPath=$(nix-build --max-silent-time 60 -o "$TEST_ROOT/result" -E " - with import ./config.nix; - mkDerivation { - name = \"non-blocking\"; - buildCommand = \"set -x; test -e $running; mkdir \$out; echo > $fifo\"; - }") - -wait $pid - -(! test -e $running) -(! test -e $dummy) -test -e $outPath diff --git a/tests/gc-runtime.nix b/tests/gc-runtime.nix deleted file mode 100644 index ee5980bdf..000000000 --- a/tests/gc-runtime.nix +++ /dev/null @@ -1,17 +0,0 @@ -with import ./config.nix; - -mkDerivation { - name = "gc-runtime"; - builder = - # Test inline source file definitions. - builtins.toFile "builder.sh" '' - mkdir $out - - cat > $out/program < $TEST_ROOT/vector - hash="$(nix-hash --flat ${FORMAT_FLAG-} --type "$1" "$TEST_ROOT/vector")" - if ! (( "${NO_TEST_CLASSIC-}" )) && test "$hash" != "$3"; then - echo "try nix-hash: hash $1, expected $3, got $hash" - exit 1 - fi - hash="$(nix hash file ${FORMAT_FLAG-} --type "$1" "$TEST_ROOT/vector")" - if ! (( "${NO_TEST_NIX_COMMAND-}" )) && test "$hash" != "$3"; then - echo "try nix hash: hash $1, expected $3, got $hash" - exit 1 - fi -} - -FORMAT_FLAG=--base16 -try md5 "" "d41d8cd98f00b204e9800998ecf8427e" -try md5 "a" "0cc175b9c0f1b6a831c399e269772661" -try md5 "abc" "900150983cd24fb0d6963f7d28e17f72" -try md5 "message digest" "f96b697d7cb7938d525a2f31aaf161d0" -try md5 "abcdefghijklmnopqrstuvwxyz" "c3fcd3d76192e4007dfb496cca67e13b" -try md5 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" "d174ab98d277d9f5a5611c2c9f419d9f" -try md5 "12345678901234567890123456789012345678901234567890123456789012345678901234567890" "57edf4a22be3c955ac49da2e2107b67a" - -try sha1 "" "da39a3ee5e6b4b0d3255bfef95601890afd80709" -try sha1 "abc" "a9993e364706816aba3e25717850c26c9cd0d89d" -try sha1 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" "84983e441c3bd26ebaae4aa1f95129e5e54670f1" - -try sha256 "" "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" -try sha256 "abc" "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" -try sha256 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" - -try sha512 "" "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" -try sha512 "abc" "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" -try sha512 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445" -unset FORMAT_FLAG - -FORMAT_FLAG=--base32 -try sha256 "abc" "1b8m03r63zqhnjf7l5wnldhh7c134ap5vpj0850ymkq1iyzicy5s" -unset FORMAT_FLAG - -FORMAT_FLAG=--sri -try sha512 "" "sha512-z4PhNX7vuL3xVChQ1m2AB9Yg5AULVxXcg/SpIdNs6c5H0NE8XYXysP+DGNKHfuwvY7kxvUdBeoGlODJ6+SfaPg==" -try sha512 "abc" "sha512-3a81oZNherrMQXNJriBBMRLm+k6JqX6iCp7u5ktV05ohkpkqJ0/BqDa6PCOj/uu9RU1EI2Q86A4qmslPpUyknw==" -try sha512 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" "sha512-IEqPxt2oLwoM7XvrjgikFlfBbvRosiioJ5vjMacDwzWW/RXBOxsH+aodO+pXeJygMa2Fx6cd1wNU7GMSOMo0RQ==" -try sha256 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" "sha256-JI1qYdIGOLjlwCaTDD5gOaM85Flk/yFn9uzt1BnbBsE=" -unset FORMAT_FLAG - -# nix-hash [--flat] defaults to the Base16 format -NO_TEST_NIX_COMMAND=1 try sha512 "abc" "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" - -# nix hash [file|path] defaults to the SRI format -NO_TEST_CLASSIC=1 try sha512 "abc" "sha512-3a81oZNherrMQXNJriBBMRLm+k6JqX6iCp7u5ktV05ohkpkqJ0/BqDa6PCOj/uu9RU1EI2Q86A4qmslPpUyknw==" - -try2 () { - hash=$(nix-hash --type "$1" $TEST_ROOT/hash-path) - if test "$hash" != "$2"; then - echo "hash $1, expected $2, got $hash" - exit 1 - fi -} - -rm -rf $TEST_ROOT/hash-path -mkdir $TEST_ROOT/hash-path -echo "Hello World" > $TEST_ROOT/hash-path/hello - -try2 md5 "ea9b55537dd4c7e104515b2ccfaf4100" - -# Execute bit matters. -chmod +x $TEST_ROOT/hash-path/hello -try2 md5 "20f3ffe011d4cfa7d72bfabef7882836" - -# Mtime and other bits don't. -touch -r . $TEST_ROOT/hash-path/hello -chmod 744 $TEST_ROOT/hash-path/hello -try2 md5 "20f3ffe011d4cfa7d72bfabef7882836" - -# File type (e.g., symlink) does. -rm $TEST_ROOT/hash-path/hello -ln -s x $TEST_ROOT/hash-path/hello -try2 md5 "f78b733a68f5edbdf9413899339eaa4a" - -# Conversion. -try3() { - h64=$(nix-hash --type "$1" --to-base64 "$2") - [ "$h64" = "$4" ] - h64=$(nix hash to-base64 --type "$1" "$2") - [ "$h64" = "$4" ] - sri=$(nix-hash --type "$1" --to-sri "$2") - [ "$sri" = "$1-$4" ] - sri=$(nix hash to-sri --type "$1" "$2") - [ "$sri" = "$1-$4" ] - h32=$(nix-hash --type "$1" --to-base32 "$2") - [ "$h32" = "$3" ] - h32=$(nix hash to-base32 --type "$1" "$2") - [ "$h32" = "$3" ] - h16=$(nix-hash --type "$1" --to-base16 "$h32") - [ "$h16" = "$2" ] - h16=$(nix hash to-base16 --type "$1" "$h64") - [ "$h16" = "$2" ] - h16=$(nix hash to-base16 "$sri") - [ "$h16" = "$2" ] -} -try3 sha1 "800d59cfcd3c05e900cb4e214be48f6b886a08df" "vw46m23bizj4n8afrc0fj19wrp7mj3c0" "gA1Zz808BekAy04hS+SPa4hqCN8=" -try3 sha256 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" "1b8m03r63zqhnjf7l5wnldhh7c134ap5vpj0850ymkq1iyzicy5s" "ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=" -try3 sha512 "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445" "12k9jiq29iyqm03swfsgiw5mlqs173qazm3n7daz43infy12pyrcdf30fkk3qwv4yl2ick8yipc2mqnlh48xsvvxl60lbx8vp38yji0" "IEqPxt2oLwoM7XvrjgikFlfBbvRosiioJ5vjMacDwzWW/RXBOxsH+aodO+pXeJygMa2Fx6cd1wNU7GMSOMo0RQ==" diff --git a/tests/hermetic.nix b/tests/hermetic.nix deleted file mode 100644 index 4c9d7a51f..000000000 --- a/tests/hermetic.nix +++ /dev/null @@ -1,56 +0,0 @@ -{ busybox, seed }: - -with import ./config.nix; - -let - contentAddressedByDefault = builtins.getEnv "NIX_TESTS_CA_BY_DEFAULT" == "1"; - caArgs = if contentAddressedByDefault then { - __contentAddressed = true; - outputHashMode = "recursive"; - outputHashAlgo = "sha256"; - } else {}; - - mkDerivation = args: - derivation ({ - inherit system; - builder = busybox; - args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" "if [ -e .attrs.sh ]; then source .attrs.sh; fi; eval \"$buildCommand\"")]; - } // removeAttrs args ["builder" "meta" "passthru"] - // caArgs) - // { meta = args.meta or {}; passthru = args.passthru or {}; }; - - input1 = mkDerivation { - shell = busybox; - name = "hermetic-input-1"; - buildCommand = "echo hi-input1 seed=${toString seed}; echo FOO > $out"; - }; - - input2 = mkDerivation { - shell = busybox; - name = "hermetic-input-2"; - buildCommand = "echo hi; echo BAR > $out"; - }; - - input3 = mkDerivation { - shell = busybox; - name = "hermetic-input-3"; - buildCommand = '' - echo hi-input3 - read x < ${input2} - echo $x BAZ > $out - ''; - }; - -in - - mkDerivation { - shell = busybox; - name = "hermetic"; - passthru = { inherit input1 input2 input3; }; - buildCommand = - '' - read x < ${input1} - read y < ${input3} - echo "$x $y" > $out - ''; - } diff --git a/tests/import-derivation.nix b/tests/import-derivation.nix deleted file mode 100644 index 44fa9a45d..000000000 --- a/tests/import-derivation.nix +++ /dev/null @@ -1,26 +0,0 @@ -with import ./config.nix; - -let - - bar = mkDerivation { - name = "bar"; - builder = builtins.toFile "builder.sh" - '' - echo 'builtins.add 123 456' > $out - ''; - }; - - value = - # Test that pathExists can check the existence of /nix/store paths - assert builtins.pathExists bar; - import bar; - -in - -mkDerivation { - name = "foo"; - builder = builtins.toFile "builder.sh" - '' - echo -n FOO${toString value} > $out - ''; -} diff --git a/tests/import-derivation.sh b/tests/import-derivation.sh deleted file mode 100644 index 98d61ef49..000000000 --- a/tests/import-derivation.sh +++ /dev/null @@ -1,12 +0,0 @@ -source common.sh - -clearStore - -if nix-instantiate --readonly-mode ./import-derivation.nix; then - echo "read-only evaluation of an imported derivation unexpectedly failed" - exit 1 -fi - -outPath=$(nix-build ./import-derivation.nix --no-out-link) - -[ "$(cat $outPath)" = FOO579 ] diff --git a/tests/impure-derivations.nix b/tests/impure-derivations.nix deleted file mode 100644 index 98547e6c1..000000000 --- a/tests/impure-derivations.nix +++ /dev/null @@ -1,63 +0,0 @@ -with import ./config.nix; - -rec { - - impure = mkDerivation { - name = "impure"; - outputs = [ "out" "stuff" ]; - buildCommand = - '' - echo impure - x=$(< $TEST_ROOT/counter) - mkdir $out $stuff - echo $x > $out/n - ln -s $out/n $stuff/bla - printf $((x + 1)) > $TEST_ROOT/counter - ''; - __impure = true; - impureEnvVars = [ "TEST_ROOT" ]; - }; - - impureOnImpure = mkDerivation { - name = "impure-on-impure"; - buildCommand = - '' - echo impure-on-impure - x=$(< ${impure}/n) - mkdir $out - printf X$x > $out/n - ln -s ${impure.stuff} $out/symlink - ln -s $out $out/self - ''; - __impure = true; - }; - - # This is not allowed. - inputAddressed = mkDerivation { - name = "input-addressed"; - buildCommand = - '' - cat ${impure} > $out - ''; - }; - - contentAddressed = mkDerivation { - name = "content-addressed"; - buildCommand = - '' - echo content-addressed - x=$(< ${impureOnImpure}/n) - printf ''${x:0:1} > $out - ''; - outputHashMode = "recursive"; - outputHash = "sha256-eBYxcgkuWuiqs4cKNgKwkb3vY/HR0vVsJnqe8itJGcQ="; - }; - - inputAddressedAfterCA = mkDerivation { - name = "input-addressed-after-ca"; - buildCommand = - '' - cat ${contentAddressed} > $out - ''; - }; -} diff --git a/tests/impure-derivations.sh b/tests/impure-derivations.sh deleted file mode 100644 index 39d053a04..000000000 --- a/tests/impure-derivations.sh +++ /dev/null @@ -1,65 +0,0 @@ -source common.sh - -requireDaemonNewerThan "2.8pre20220311" - -enableFeatures "ca-derivations impure-derivations" -restartDaemon - -clearStore - -# Basic test of impure derivations: building one a second time should not use the previous result. -printf 0 > $TEST_ROOT/counter - -# `nix derivation add` with impure derivations work -drvPath=$(nix-instantiate ./impure-derivations.nix -A impure) -nix derivation show $drvPath | jq .[] > $TEST_HOME/impure-drv.json -drvPath2=$(nix derivation add < $TEST_HOME/impure-drv.json) -[[ "$drvPath" = "$drvPath2" ]] - -# But only with the experimental feature! -expectStderr 1 nix derivation add < $TEST_HOME/impure-drv.json --experimental-features nix-command | grepQuiet "experimental Nix feature 'impure-derivations' is disabled" - -nix build --dry-run --json --file ./impure-derivations.nix impure.all -json=$(nix build -L --no-link --json --file ./impure-derivations.nix impure.all) -path1=$(echo $json | jq -r .[].outputs.out) -path1_stuff=$(echo $json | jq -r .[].outputs.stuff) -[[ $(< $path1/n) = 0 ]] -[[ $(< $path1_stuff/bla) = 0 ]] - -[[ $(nix path-info --json $path1 | jq .[].ca) =~ fixed:r:sha256: ]] - -path2=$(nix build -L --no-link --json --file ./impure-derivations.nix impure | jq -r .[].outputs.out) -[[ $(< $path2/n) = 1 ]] - -# Test impure derivations that depend on impure derivations. -path3=$(nix build -L --no-link --json --file ./impure-derivations.nix impureOnImpure | jq -r .[].outputs.out) -[[ $(< $path3/n) = X2 ]] - -path4=$(nix build -L --no-link --json --file ./impure-derivations.nix impureOnImpure | jq -r .[].outputs.out) -[[ $(< $path4/n) = X3 ]] - -# Test that (self-)references work. -[[ $(< $path4/symlink/bla) = 3 ]] -[[ $(< $path4/self/n) = X3 ]] - -# Input-addressed derivations cannot depend on impure derivations directly. -(! nix build -L --no-link --json --file ./impure-derivations.nix inputAddressed 2>&1) | grep 'depends on impure derivation' - -drvPath=$(nix eval --json --file ./impure-derivations.nix impure.drvPath | jq -r .) -[[ $(nix derivation show $drvPath | jq ".[\"$drvPath\"].outputs.out.impure") = true ]] -[[ $(nix derivation show $drvPath | jq ".[\"$drvPath\"].outputs.stuff.impure") = true ]] - -# Fixed-output derivations *can* depend on impure derivations. -path5=$(nix build -L --no-link --json --file ./impure-derivations.nix contentAddressed | jq -r .[].outputs.out) -[[ $(< $path5) = X ]] -[[ $(< $TEST_ROOT/counter) = 5 ]] - -# And they should not be rebuilt. -path5=$(nix build -L --no-link --json --file ./impure-derivations.nix contentAddressed | jq -r .[].outputs.out) -[[ $(< $path5) = X ]] -[[ $(< $TEST_ROOT/counter) = 5 ]] - -# Input-addressed derivations can depend on fixed-output derivations that depend on impure derivations. -path6=$(nix build -L --no-link --json --file ./impure-derivations.nix inputAddressedAfterCA | jq -r .[].outputs.out) -[[ $(< $path6) = X ]] -[[ $(< $TEST_ROOT/counter) = 5 ]] diff --git a/tests/init.sh b/tests/init.sh deleted file mode 100755 index c420e8c9f..000000000 --- a/tests/init.sh +++ /dev/null @@ -1,41 +0,0 @@ -# Don't start the daemon -source common/vars-and-functions.sh - -test -n "$TEST_ROOT" -if test -d "$TEST_ROOT"; then - chmod -R u+w "$TEST_ROOT" - # We would delete any daemon socket, so let's stop the daemon first. - killDaemon - rm -rf "$TEST_ROOT" -fi -mkdir "$TEST_ROOT" - -mkdir "$NIX_STORE_DIR" -mkdir "$NIX_LOCALSTATE_DIR" -mkdir -p "$NIX_LOG_DIR"/drvs -mkdir "$NIX_STATE_DIR" -mkdir "$NIX_CONF_DIR" - -cat > "$NIX_CONF_DIR"/nix.conf < "$NIX_CONF_DIR"/nix.conf.extra < "$file.next" - mv "$file.next" "$file" - fi - done - - for i in $(seq 1 $(sysctl -n hw.ncpu)); do - sudo /usr/bin/dscl . -delete "/Users/nixbld$i" || true - done - sudo /usr/bin/dscl . -delete "/Groups/nixbld" || true - - sudo rm -rf /etc/nix \ - /nix \ - /var/root/.nix-profile /var/root/.nix-defexpr /var/root/.nix-channels \ - "$HOME/.nix-profile" "$HOME/.nix-defexpr" "$HOME/.nix-channels" -} - -verify() { - set +e - output=$(echo "nix-shell -p bash --run 'echo toow | rev'" | bash -l) - set -e - - test "$output" = "woot" -} - -scratch=$(mktemp -d -t tmp.XXXXXXXXXX) -function finish { - rm -rf "$scratch" -} -trap finish EXIT - -# First setup Nix -cleanup -curl -L -o install https://nixos.org/nix/install -yes | bash ./install -verify - - -( - set +e - ( - echo "cd $(pwd)" - echo nix-build ./release.nix -A binaryTarball.x86_64-darwin - ) | bash -l - set -e - cp ./result/nix-*.tar.bz2 $scratch/nix.tar.bz2 -) - -( - cd $scratch - tar -xf ./nix.tar.bz2 - - cd nix-* - - set -eux - - cleanup - - yes | ./install - verify - cleanup - - echo -n "" | ./install - verify - cleanup - - sudo mkdir -p /nix/store - sudo touch /nix/store/.silly-hint - echo -n "" | ALLOW_PREEXISTING_INSTALLATION=true ./install - verify - test -e /nix/store/.silly-hint - - cleanup -) diff --git a/tests/lang-test-infra.sh b/tests/lang-test-infra.sh deleted file mode 100644 index 30da8977b..000000000 --- a/tests/lang-test-infra.sh +++ /dev/null @@ -1,86 +0,0 @@ -# Test the function for lang.sh -source common.sh - -source lang/framework.sh - -# We are testing this, so don't want outside world to affect us. -unset _NIX_TEST_ACCEPT - -# We'll only modify this in subshells so we don't need to reset it. -badDiff=0 - -# matches non-empty -echo Hi! > "$TEST_ROOT/got" -cp "$TEST_ROOT/got" "$TEST_ROOT/expected" -( - diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/expected" - (( "$badDiff" == 0 )) -) - -# matches empty, non-existant file is the same as empty file -echo -n > "$TEST_ROOT/got" -( - diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/does-not-exist" - (( "$badDiff" == 0 )) -) - -# doesn't matches non-empty, non-existant file is the same as empty file -echo Hi! > "$TEST_ROOT/got" -( - diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/does-not-exist" - (( "$badDiff" == 1 )) -) - -# doesn't match, `badDiff` set, file unchanged -echo Hi! > "$TEST_ROOT/got" -echo Bye! > "$TEST_ROOT/expected" -( - diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/expected" - (( "$badDiff" == 1 )) -) -[[ "$(echo Bye! )" == $(< "$TEST_ROOT/expected") ]] - -# _NIX_TEST_ACCEPT=1 matches non-empty -echo Hi! > "$TEST_ROOT/got" -cp "$TEST_ROOT/got" "$TEST_ROOT/expected" -( - _NIX_TEST_ACCEPT=1 diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/expected" - (( "$badDiff" == 0 )) -) - -# _NIX_TEST_ACCEPT doesn't match, `badDiff=1` set, file changed (was previously non-empty) -echo Hi! > "$TEST_ROOT/got" -echo Bye! > "$TEST_ROOT/expected" -( - _NIX_TEST_ACCEPT=1 diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/expected" - (( "$badDiff" == 1 )) -) -[[ "$(echo Hi! )" == $(< "$TEST_ROOT/expected") ]] -# second time succeeds -( - diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/expected" - (( "$badDiff" == 0 )) -) - -# _NIX_TEST_ACCEPT matches empty, non-existant file not created -echo -n > "$TEST_ROOT/got" -( - _NIX_TEST_ACCEPT=1 diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/does-not-exists" - (( "$badDiff" == 0 )) -) -[[ ! -f "$TEST_ROOT/does-not-exist" ]] - -# _NIX_TEST_ACCEPT doesn't match, output empty, file deleted -echo -n > "$TEST_ROOT/got" -echo Bye! > "$TEST_ROOT/expected" -badDiff=0 -( - _NIX_TEST_ACCEPT=1 diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/expected" - (( "$badDiff" == 1 )) -) -[[ ! -f "$TEST_ROOT/expected" ]] -# second time succeeds -( - diffAndAcceptInner test "$TEST_ROOT/got" "$TEST_ROOT/expected" - (( "$badDiff" == 0 )) -) diff --git a/tests/lang.sh b/tests/lang.sh deleted file mode 100755 index 75dbbc38e..000000000 --- a/tests/lang.sh +++ /dev/null @@ -1,146 +0,0 @@ -source common.sh - -set -o pipefail - -source lang/framework.sh - -# specialize function a bit -function diffAndAccept() { - local -r testName="$1" - local -r got="lang/$testName.$2" - local -r expected="lang/$testName.$3" - diffAndAcceptInner "$testName" "$got" "$expected" -} - -export TEST_VAR=foo # for eval-okay-getenv.nix -export NIX_REMOTE=dummy:// -export NIX_STORE_DIR=/nix/store - -nix-instantiate --eval -E 'builtins.trace "Hello" 123' 2>&1 | grepQuiet Hello -nix-instantiate --eval -E 'builtins.trace "Hello" 123' 2>/dev/null | grepQuiet 123 -nix-instantiate --eval -E 'builtins.addErrorContext "Hello" 123' 2>&1 -nix-instantiate --trace-verbose --eval -E 'builtins.traceVerbose "Hello" 123' 2>&1 | grepQuiet Hello -nix-instantiate --eval -E 'builtins.traceVerbose "Hello" 123' 2>&1 | grepQuietInverse Hello -nix-instantiate --show-trace --eval -E 'builtins.addErrorContext "Hello" 123' 2>&1 | grepQuietInverse Hello -expectStderr 1 nix-instantiate --show-trace --eval -E 'builtins.addErrorContext "Hello" (throw "Foo")' | grepQuiet Hello - -nix-instantiate --eval -E 'let x = builtins.trace { x = x; } true; in x' \ - 2>&1 | grepQuiet -E 'trace: { x = «potential infinite recursion»; }' - -nix-instantiate --eval -E 'let x = { repeating = x; tracing = builtins.trace x true; }; in x.tracing'\ - 2>&1 | grepQuiet -F 'trace: { repeating = «repeated»; tracing = «potential infinite recursion»; }' - -set +x - -badDiff=0 -badExitCode=0 - -for i in lang/parse-fail-*.nix; do - echo "parsing $i (should fail)"; - i=$(basename "$i" .nix) - if expectStderr 1 nix-instantiate --parse - < "lang/$i.nix" > "lang/$i.err" - then - diffAndAccept "$i" err err.exp - else - echo "FAIL: $i shouldn't parse" - badExitCode=1 - fi -done - -for i in lang/parse-okay-*.nix; do - echo "parsing $i (should succeed)"; - i=$(basename "$i" .nix) - if - expect 0 nix-instantiate --parse - < "lang/$i.nix" \ - 1> "lang/$i.out" \ - 2> "lang/$i.err" - then - sed "s!$(pwd)!/pwd!g" "lang/$i.out" "lang/$i.err" - diffAndAccept "$i" out exp - diffAndAccept "$i" err err.exp - else - echo "FAIL: $i should parse" - badExitCode=1 - fi -done - -for i in lang/eval-fail-*.nix; do - echo "evaluating $i (should fail)"; - i=$(basename "$i" .nix) - if - expectStderr 1 nix-instantiate --show-trace "lang/$i.nix" \ - | sed "s!$(pwd)!/pwd!g" > "lang/$i.err" - then - diffAndAccept "$i" err err.exp - else - echo "FAIL: $i shouldn't evaluate" - badExitCode=1 - fi -done - -for i in lang/eval-okay-*.nix; do - echo "evaluating $i (should succeed)"; - i=$(basename "$i" .nix) - - if test -e "lang/$i.exp.xml"; then - if expect 0 nix-instantiate --eval --xml --no-location --strict \ - "lang/$i.nix" > "lang/$i.out.xml" - then - diffAndAccept "$i" out.xml exp.xml - else - echo "FAIL: $i should evaluate" - badExitCode=1 - fi - elif test ! -e "lang/$i.exp-disabled"; then - declare -a flags=() - if test -e "lang/$i.flags"; then - read -r -a flags < "lang/$i.flags" - fi - - if - expect 0 env \ - NIX_PATH=lang/dir3:lang/dir4 \ - HOME=/fake-home \ - nix-instantiate "${flags[@]}" --eval --strict "lang/$i.nix" \ - 1> "lang/$i.out" \ - 2> "lang/$i.err" - then - sed -i "s!$(pwd)!/pwd!g" "lang/$i.out" "lang/$i.err" - diffAndAccept "$i" out exp - diffAndAccept "$i" err err.exp - else - echo "FAIL: $i should evaluate" - badExitCode=1 - fi - fi -done - -if test -n "${_NIX_TEST_ACCEPT-}"; then - if (( "$badDiff" )); then - echo 'Output did mot match, but accepted output as the persisted expected output.' - echo 'That means the next time the tests are run, they should pass.' - else - echo 'NOTE: Environment variable _NIX_TEST_ACCEPT is defined,' - echo 'indicating the unexpected output should be accepted as the expected output going forward,' - echo 'but no tests had unexpected output so there was no expected output to update.' - fi - if (( "$badExitCode" )); then - exit "$badExitCode" - else - skipTest "regenerating golden masters" - fi -else - if (( "$badDiff" )); then - echo '' - echo 'You can rerun this test with:' - echo '' - echo ' _NIX_TEST_ACCEPT=1 make tests/lang.sh.test' - echo '' - echo 'to regenerate the files containing the expected output,' - echo 'and then view the git diff to decide whether a change is' - echo 'good/intentional or bad/unintentional.' - echo 'If the diff contains arbitrary or impure information,' - echo 'please improve the normalization that the test applies to the output.' - fi - exit $(( "$badExitCode" + "$badDiff" )) -fi diff --git a/tests/lang/binary-data b/tests/lang/binary-data deleted file mode 100644 index 06d740502..000000000 Binary files a/tests/lang/binary-data and /dev/null differ diff --git a/tests/lang/data b/tests/lang/data deleted file mode 100644 index 257cc5642..000000000 --- a/tests/lang/data +++ /dev/null @@ -1 +0,0 @@ -foo diff --git a/tests/lang/dir1/a.nix b/tests/lang/dir1/a.nix deleted file mode 100644 index 231f150c5..000000000 --- a/tests/lang/dir1/a.nix +++ /dev/null @@ -1 +0,0 @@ -"a" diff --git a/tests/lang/dir2/a.nix b/tests/lang/dir2/a.nix deleted file mode 100644 index 170df520a..000000000 --- a/tests/lang/dir2/a.nix +++ /dev/null @@ -1 +0,0 @@ -"X" diff --git a/tests/lang/dir2/b.nix b/tests/lang/dir2/b.nix deleted file mode 100644 index 19010cc35..000000000 --- a/tests/lang/dir2/b.nix +++ /dev/null @@ -1 +0,0 @@ -"b" diff --git a/tests/lang/dir3/a.nix b/tests/lang/dir3/a.nix deleted file mode 100644 index 170df520a..000000000 --- a/tests/lang/dir3/a.nix +++ /dev/null @@ -1 +0,0 @@ -"X" diff --git a/tests/lang/dir3/b.nix b/tests/lang/dir3/b.nix deleted file mode 100644 index 170df520a..000000000 --- a/tests/lang/dir3/b.nix +++ /dev/null @@ -1 +0,0 @@ -"X" diff --git a/tests/lang/dir3/c.nix b/tests/lang/dir3/c.nix deleted file mode 100644 index cdf158597..000000000 --- a/tests/lang/dir3/c.nix +++ /dev/null @@ -1 +0,0 @@ -"c" diff --git a/tests/lang/dir4/a.nix b/tests/lang/dir4/a.nix deleted file mode 100644 index 170df520a..000000000 --- a/tests/lang/dir4/a.nix +++ /dev/null @@ -1 +0,0 @@ -"X" diff --git a/tests/lang/dir4/c.nix b/tests/lang/dir4/c.nix deleted file mode 100644 index 170df520a..000000000 --- a/tests/lang/dir4/c.nix +++ /dev/null @@ -1 +0,0 @@ -"X" diff --git a/tests/lang/empty.exp b/tests/lang/empty.exp deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/lang/eval-fail-abort.err.exp b/tests/lang/eval-fail-abort.err.exp deleted file mode 100644 index 345232d3f..000000000 --- a/tests/lang/eval-fail-abort.err.exp +++ /dev/null @@ -1,10 +0,0 @@ -error: - … while calling the 'abort' builtin - - at /pwd/lang/eval-fail-abort.nix:1:14: - - 1| if true then abort "this should fail" else 1 - | ^ - 2| - - error: evaluation aborted with the following error message: 'this should fail' diff --git a/tests/lang/eval-fail-abort.nix b/tests/lang/eval-fail-abort.nix deleted file mode 100644 index 75c51bceb..000000000 --- a/tests/lang/eval-fail-abort.nix +++ /dev/null @@ -1 +0,0 @@ -if true then abort "this should fail" else 1 diff --git a/tests/lang/eval-fail-antiquoted-path.err.exp b/tests/lang/eval-fail-antiquoted-path.err.exp deleted file mode 100644 index 425deba42..000000000 --- a/tests/lang/eval-fail-antiquoted-path.err.exp +++ /dev/null @@ -1 +0,0 @@ -error: getting attributes of path ‘PWD/lang/fnord’: No such file or directory diff --git a/tests/lang/eval-fail-assert.err.exp b/tests/lang/eval-fail-assert.err.exp deleted file mode 100644 index aeecd8167..000000000 --- a/tests/lang/eval-fail-assert.err.exp +++ /dev/null @@ -1,36 +0,0 @@ -error: - … while evaluating the attribute 'body' - - at /pwd/lang/eval-fail-assert.nix:4:3: - - 3| - 4| body = x "x"; - | ^ - 5| } - - … from call site - - at /pwd/lang/eval-fail-assert.nix:4:10: - - 3| - 4| body = x "x"; - | ^ - 5| } - - … while calling 'x' - - at /pwd/lang/eval-fail-assert.nix:2:7: - - 1| let { - 2| x = arg: assert arg == "y"; 123; - | ^ - 3| - - error: assertion '(arg == "y")' failed - - at /pwd/lang/eval-fail-assert.nix:2:12: - - 1| let { - 2| x = arg: assert arg == "y"; 123; - | ^ - 3| diff --git a/tests/lang/eval-fail-assert.nix b/tests/lang/eval-fail-assert.nix deleted file mode 100644 index 3b7a1e8bf..000000000 --- a/tests/lang/eval-fail-assert.nix +++ /dev/null @@ -1,5 +0,0 @@ -let { - x = arg: assert arg == "y"; 123; - - body = x "x"; -} \ No newline at end of file diff --git a/tests/lang/eval-fail-bad-antiquote-1.err.exp b/tests/lang/eval-fail-bad-antiquote-1.err.exp deleted file mode 100644 index cf94f53bc..000000000 --- a/tests/lang/eval-fail-bad-antiquote-1.err.exp +++ /dev/null @@ -1,10 +0,0 @@ -error: - … while evaluating a path segment - - at /pwd/lang/eval-fail-bad-antiquote-1.nix:1:2: - - 1| "${x: x}" - | ^ - 2| - - error: cannot coerce a function to a string diff --git a/tests/lang/eval-fail-bad-antiquote-2.err.exp b/tests/lang/eval-fail-bad-antiquote-2.err.exp deleted file mode 100644 index c8fe39d12..000000000 --- a/tests/lang/eval-fail-bad-antiquote-2.err.exp +++ /dev/null @@ -1 +0,0 @@ -error: operation 'addToStoreFromDump' is not supported by store 'dummy' diff --git a/tests/lang/eval-fail-bad-antiquote-3.err.exp b/tests/lang/eval-fail-bad-antiquote-3.err.exp deleted file mode 100644 index fbefbc826..000000000 --- a/tests/lang/eval-fail-bad-antiquote-3.err.exp +++ /dev/null @@ -1,10 +0,0 @@ -error: - … while evaluating a path segment - - at /pwd/lang/eval-fail-bad-antiquote-3.nix:1:3: - - 1| ''${x: x}'' - | ^ - 2| - - error: cannot coerce a function to a string diff --git a/tests/lang/eval-fail-bad-string-interpolation-1.err.exp b/tests/lang/eval-fail-bad-string-interpolation-1.err.exp deleted file mode 100644 index eb73e9a52..000000000 --- a/tests/lang/eval-fail-bad-string-interpolation-1.err.exp +++ /dev/null @@ -1,10 +0,0 @@ -error: - … while evaluating a path segment - - at /pwd/lang/eval-fail-bad-string-interpolation-1.nix:1:2: - - 1| "${x: x}" - | ^ - 2| - - error: cannot coerce a function to a string diff --git a/tests/lang/eval-fail-bad-string-interpolation-1.nix b/tests/lang/eval-fail-bad-string-interpolation-1.nix deleted file mode 100644 index ffe9c983c..000000000 --- a/tests/lang/eval-fail-bad-string-interpolation-1.nix +++ /dev/null @@ -1 +0,0 @@ -"${x: x}" diff --git a/tests/lang/eval-fail-bad-string-interpolation-2.err.exp b/tests/lang/eval-fail-bad-string-interpolation-2.err.exp deleted file mode 100644 index c8fe39d12..000000000 --- a/tests/lang/eval-fail-bad-string-interpolation-2.err.exp +++ /dev/null @@ -1 +0,0 @@ -error: operation 'addToStoreFromDump' is not supported by store 'dummy' diff --git a/tests/lang/eval-fail-bad-string-interpolation-2.nix b/tests/lang/eval-fail-bad-string-interpolation-2.nix deleted file mode 100644 index 3745235ce..000000000 --- a/tests/lang/eval-fail-bad-string-interpolation-2.nix +++ /dev/null @@ -1 +0,0 @@ -"${./fnord}" diff --git a/tests/lang/eval-fail-bad-string-interpolation-3.err.exp b/tests/lang/eval-fail-bad-string-interpolation-3.err.exp deleted file mode 100644 index ac14f329b..000000000 --- a/tests/lang/eval-fail-bad-string-interpolation-3.err.exp +++ /dev/null @@ -1,10 +0,0 @@ -error: - … while evaluating a path segment - - at /pwd/lang/eval-fail-bad-string-interpolation-3.nix:1:3: - - 1| ''${x: x}'' - | ^ - 2| - - error: cannot coerce a function to a string diff --git a/tests/lang/eval-fail-bad-string-interpolation-3.nix b/tests/lang/eval-fail-bad-string-interpolation-3.nix deleted file mode 100644 index 65b9d4f50..000000000 --- a/tests/lang/eval-fail-bad-string-interpolation-3.nix +++ /dev/null @@ -1 +0,0 @@ -''${x: x}'' diff --git a/tests/lang/eval-fail-blackhole.err.exp b/tests/lang/eval-fail-blackhole.err.exp deleted file mode 100644 index f0618d8ac..000000000 --- a/tests/lang/eval-fail-blackhole.err.exp +++ /dev/null @@ -1,18 +0,0 @@ -error: - … while evaluating the attribute 'body' - - at /pwd/lang/eval-fail-blackhole.nix:2:3: - - 1| let { - 2| body = x; - | ^ - 3| x = y; - - error: infinite recursion encountered - - at /pwd/lang/eval-fail-blackhole.nix:3:7: - - 2| body = x; - 3| x = y; - | ^ - 4| y = x; diff --git a/tests/lang/eval-fail-blackhole.nix b/tests/lang/eval-fail-blackhole.nix deleted file mode 100644 index 81133b511..000000000 --- a/tests/lang/eval-fail-blackhole.nix +++ /dev/null @@ -1,5 +0,0 @@ -let { - body = x; - x = y; - y = x; -} diff --git a/tests/lang/eval-fail-deepseq.err.exp b/tests/lang/eval-fail-deepseq.err.exp deleted file mode 100644 index 5e204ba73..000000000 --- a/tests/lang/eval-fail-deepseq.err.exp +++ /dev/null @@ -1,26 +0,0 @@ -error: - … while calling the 'deepSeq' builtin - - at /pwd/lang/eval-fail-deepseq.nix:1:1: - - 1| builtins.deepSeq { x = abort "foo"; } 456 - | ^ - 2| - - … while evaluating the attribute 'x' - - at /pwd/lang/eval-fail-deepseq.nix:1:20: - - 1| builtins.deepSeq { x = abort "foo"; } 456 - | ^ - 2| - - … while calling the 'abort' builtin - - at /pwd/lang/eval-fail-deepseq.nix:1:24: - - 1| builtins.deepSeq { x = abort "foo"; } 456 - | ^ - 2| - - error: evaluation aborted with the following error message: 'foo' diff --git a/tests/lang/eval-fail-deepseq.nix b/tests/lang/eval-fail-deepseq.nix deleted file mode 100644 index 9baa49b06..000000000 --- a/tests/lang/eval-fail-deepseq.nix +++ /dev/null @@ -1 +0,0 @@ -builtins.deepSeq { x = abort "foo"; } 456 diff --git a/tests/lang/eval-fail-dup-dynamic-attrs.err.exp b/tests/lang/eval-fail-dup-dynamic-attrs.err.exp deleted file mode 100644 index e01f8e6d0..000000000 --- a/tests/lang/eval-fail-dup-dynamic-attrs.err.exp +++ /dev/null @@ -1,8 +0,0 @@ -error: dynamic attribute 'b' already defined at /pwd/lang/eval-fail-dup-dynamic-attrs.nix:2:11 - - at /pwd/lang/eval-fail-dup-dynamic-attrs.nix:3:11: - - 2| set = { "${"" + "b"}" = 1; }; - 3| set = { "${"b" + ""}" = 2; }; - | ^ - 4| } diff --git a/tests/lang/eval-fail-dup-dynamic-attrs.nix b/tests/lang/eval-fail-dup-dynamic-attrs.nix deleted file mode 100644 index 7ea17f6c8..000000000 --- a/tests/lang/eval-fail-dup-dynamic-attrs.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ - set = { "${"" + "b"}" = 1; }; - set = { "${"b" + ""}" = 2; }; -} diff --git a/tests/lang/eval-fail-foldlStrict-strict-op-application.err.exp b/tests/lang/eval-fail-foldlStrict-strict-op-application.err.exp deleted file mode 100644 index 0069285fb..000000000 --- a/tests/lang/eval-fail-foldlStrict-strict-op-application.err.exp +++ /dev/null @@ -1,38 +0,0 @@ -error: - … while calling the 'foldl'' builtin - - at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:2:1: - - 1| # Tests that the result of applying op is forced even if the value is never used - 2| builtins.foldl' - | ^ - 3| (_: f: f null) - - … while calling anonymous lambda - - at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:3:7: - - 2| builtins.foldl' - 3| (_: f: f null) - | ^ - 4| null - - … from call site - - at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:3:10: - - 2| builtins.foldl' - 3| (_: f: f null) - | ^ - 4| null - - … while calling anonymous lambda - - at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:5:6: - - 4| null - 5| [ (_: throw "Not the final value, but is still forced!") (_: 23) ] - | ^ - 6| - - error: Not the final value, but is still forced! diff --git a/tests/lang/eval-fail-foldlStrict-strict-op-application.nix b/tests/lang/eval-fail-foldlStrict-strict-op-application.nix deleted file mode 100644 index 1620cc76e..000000000 --- a/tests/lang/eval-fail-foldlStrict-strict-op-application.nix +++ /dev/null @@ -1,5 +0,0 @@ -# Tests that the result of applying op is forced even if the value is never used -builtins.foldl' - (_: f: f null) - null - [ (_: throw "Not the final value, but is still forced!") (_: 23) ] diff --git a/tests/lang/eval-fail-fromTOML-timestamps.err.exp b/tests/lang/eval-fail-fromTOML-timestamps.err.exp deleted file mode 100644 index f6bd19f5a..000000000 --- a/tests/lang/eval-fail-fromTOML-timestamps.err.exp +++ /dev/null @@ -1,12 +0,0 @@ -error: - … while calling the 'fromTOML' builtin - - at /pwd/lang/eval-fail-fromTOML-timestamps.nix:1:1: - - 1| builtins.fromTOML '' - | ^ - 2| key = "value" - - error: while parsing a TOML string: Dates and times are not supported - - at «none»:0: (source not available) diff --git a/tests/lang/eval-fail-fromTOML-timestamps.nix b/tests/lang/eval-fail-fromTOML-timestamps.nix deleted file mode 100644 index 74cff9470..000000000 --- a/tests/lang/eval-fail-fromTOML-timestamps.nix +++ /dev/null @@ -1,130 +0,0 @@ -builtins.fromTOML '' - key = "value" - bare_key = "value" - bare-key = "value" - 1234 = "value" - - "127.0.0.1" = "value" - "character encoding" = "value" - "ʎǝʞ" = "value" - 'key2' = "value" - 'quoted "value"' = "value" - - name = "Orange" - - physical.color = "orange" - physical.shape = "round" - site."google.com" = true - - # This is legal according to the spec, but cpptoml doesn't handle it. - #a.b.c = 1 - #a.d = 2 - - str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF." - - int1 = +99 - int2 = 42 - int3 = 0 - int4 = -17 - int5 = 1_000 - int6 = 5_349_221 - int7 = 1_2_3_4_5 - - hex1 = 0xDEADBEEF - hex2 = 0xdeadbeef - hex3 = 0xdead_beef - - oct1 = 0o01234567 - oct2 = 0o755 - - bin1 = 0b11010110 - - flt1 = +1.0 - flt2 = 3.1415 - flt3 = -0.01 - flt4 = 5e+22 - flt5 = 1e6 - flt6 = -2E-2 - flt7 = 6.626e-34 - flt8 = 9_224_617.445_991_228_313 - - bool1 = true - bool2 = false - - odt1 = 1979-05-27T07:32:00Z - odt2 = 1979-05-27T00:32:00-07:00 - odt3 = 1979-05-27T00:32:00.999999-07:00 - odt4 = 1979-05-27 07:32:00Z - ldt1 = 1979-05-27T07:32:00 - ldt2 = 1979-05-27T00:32:00.999999 - ld1 = 1979-05-27 - lt1 = 07:32:00 - lt2 = 00:32:00.999999 - - arr1 = [ 1, 2, 3 ] - arr2 = [ "red", "yellow", "green" ] - arr3 = [ [ 1, 2 ], [3, 4, 5] ] - arr4 = [ "all", 'strings', """are the same""", ''''type''''] - arr5 = [ [ 1, 2 ], ["a", "b", "c"] ] - - arr7 = [ - 1, 2, 3 - ] - - arr8 = [ - 1, - 2, # this is ok - ] - - [table-1] - key1 = "some string" - key2 = 123 - - - [table-2] - key1 = "another string" - key2 = 456 - - [dog."tater.man"] - type.name = "pug" - - [a.b.c] - [ d.e.f ] - [ g . h . i ] - [ j . "ʞ" . 'l' ] - [x.y.z.w] - - name = { first = "Tom", last = "Preston-Werner" } - point = { x = 1, y = 2 } - animal = { type.name = "pug" } - - [[products]] - name = "Hammer" - sku = 738594937 - - [[products]] - - [[products]] - name = "Nail" - sku = 284758393 - color = "gray" - - [[fruit]] - name = "apple" - - [fruit.physical] - color = "red" - shape = "round" - - [[fruit.variety]] - name = "red delicious" - - [[fruit.variety]] - name = "granny smith" - - [[fruit]] - name = "banana" - - [[fruit.variety]] - name = "plantain" -'' diff --git a/tests/lang/eval-fail-hashfile-missing.err.exp b/tests/lang/eval-fail-hashfile-missing.err.exp deleted file mode 100644 index 8e77dec1e..000000000 --- a/tests/lang/eval-fail-hashfile-missing.err.exp +++ /dev/null @@ -1,19 +0,0 @@ -error: - … while calling the 'toString' builtin - - at /pwd/lang/eval-fail-hashfile-missing.nix:4:3: - - 3| in - 4| toString (builtins.concatLists (map (hash: map (builtins.hashFile hash) paths) ["md5" "sha1" "sha256" "sha512"])) - | ^ - 5| - - … while evaluating the first argument passed to builtins.toString - - at «none»:0: (source not available) - - … while calling the 'hashFile' builtin - - at «none»:0: (source not available) - - error: opening file '/pwd/lang/this-file-is-definitely-not-there-7392097': No such file or directory diff --git a/tests/lang/eval-fail-hashfile-missing.nix b/tests/lang/eval-fail-hashfile-missing.nix deleted file mode 100644 index ce098b823..000000000 --- a/tests/lang/eval-fail-hashfile-missing.nix +++ /dev/null @@ -1,5 +0,0 @@ -let - paths = [ ./this-file-is-definitely-not-there-7392097 "/and/neither/is/this/37293620" ]; -in - toString (builtins.concatLists (map (hash: map (builtins.hashFile hash) paths) ["md5" "sha1" "sha256" "sha512"])) - diff --git a/tests/lang/eval-fail-list.err.exp b/tests/lang/eval-fail-list.err.exp deleted file mode 100644 index 24d682118..000000000 --- a/tests/lang/eval-fail-list.err.exp +++ /dev/null @@ -1,10 +0,0 @@ -error: - … while evaluating one of the elements to concatenate - - at /pwd/lang/eval-fail-list.nix:1:2: - - 1| 8++1 - | ^ - 2| - - error: value is an integer while a list was expected diff --git a/tests/lang/eval-fail-list.nix b/tests/lang/eval-fail-list.nix deleted file mode 100644 index fa749f2f7..000000000 --- a/tests/lang/eval-fail-list.nix +++ /dev/null @@ -1 +0,0 @@ -8++1 diff --git a/tests/lang/eval-fail-missing-arg.err.exp b/tests/lang/eval-fail-missing-arg.err.exp deleted file mode 100644 index 61fabf0d5..000000000 --- a/tests/lang/eval-fail-missing-arg.err.exp +++ /dev/null @@ -1,16 +0,0 @@ -error: - … from call site - - at /pwd/lang/eval-fail-missing-arg.nix:1:1: - - 1| ({x, y, z}: x + y + z) {x = "foo"; z = "bar";} - | ^ - 2| - - error: function 'anonymous lambda' called without required argument 'y' - - at /pwd/lang/eval-fail-missing-arg.nix:1:2: - - 1| ({x, y, z}: x + y + z) {x = "foo"; z = "bar";} - | ^ - 2| diff --git a/tests/lang/eval-fail-missing-arg.nix b/tests/lang/eval-fail-missing-arg.nix deleted file mode 100644 index c4be9797c..000000000 --- a/tests/lang/eval-fail-missing-arg.nix +++ /dev/null @@ -1 +0,0 @@ -({x, y, z}: x + y + z) {x = "foo"; z = "bar";} diff --git a/tests/lang/eval-fail-nonexist-path.err.exp b/tests/lang/eval-fail-nonexist-path.err.exp deleted file mode 100644 index c8fe39d12..000000000 --- a/tests/lang/eval-fail-nonexist-path.err.exp +++ /dev/null @@ -1 +0,0 @@ -error: operation 'addToStoreFromDump' is not supported by store 'dummy' diff --git a/tests/lang/eval-fail-nonexist-path.nix b/tests/lang/eval-fail-nonexist-path.nix deleted file mode 100644 index f2f08107b..000000000 --- a/tests/lang/eval-fail-nonexist-path.nix +++ /dev/null @@ -1,4 +0,0 @@ -# This must fail to evaluate, since ./fnord doesn't exist. If it did -# exist, it would produce "/nix/store/-fnord/xyzzy" (with an -# appropriate context). -"${./fnord}/xyzzy" diff --git a/tests/lang/eval-fail-path-slash.err.exp b/tests/lang/eval-fail-path-slash.err.exp deleted file mode 100644 index f0011c97f..000000000 --- a/tests/lang/eval-fail-path-slash.err.exp +++ /dev/null @@ -1,8 +0,0 @@ -error: path has a trailing slash - - at /pwd/lang/eval-fail-path-slash.nix:6:12: - - 5| # and https://nixos.org/nix-dev/2016-June/020829.html - 6| /nix/store/ - | ^ - 7| diff --git a/tests/lang/eval-fail-path-slash.nix b/tests/lang/eval-fail-path-slash.nix deleted file mode 100644 index 8c2e104c7..000000000 --- a/tests/lang/eval-fail-path-slash.nix +++ /dev/null @@ -1,6 +0,0 @@ -# Trailing slashes in paths are not allowed. -# This restriction could be lifted sometime, -# for example if we make '/' a path concatenation operator. -# See https://github.com/NixOS/nix/issues/1138 -# and https://nixos.org/nix-dev/2016-June/020829.html -/nix/store/ diff --git a/tests/lang/eval-fail-recursion.err.exp b/tests/lang/eval-fail-recursion.err.exp deleted file mode 100644 index af64133cb..000000000 --- a/tests/lang/eval-fail-recursion.err.exp +++ /dev/null @@ -1,16 +0,0 @@ -error: - … in the right operand of the update (//) operator - - at /pwd/lang/eval-fail-recursion.nix:1:12: - - 1| let a = {} // a; in a.foo - | ^ - 2| - - error: infinite recursion encountered - - at /pwd/lang/eval-fail-recursion.nix:1:15: - - 1| let a = {} // a; in a.foo - | ^ - 2| diff --git a/tests/lang/eval-fail-recursion.nix b/tests/lang/eval-fail-recursion.nix deleted file mode 100644 index 075b5ed06..000000000 --- a/tests/lang/eval-fail-recursion.nix +++ /dev/null @@ -1 +0,0 @@ -let a = {} // a; in a.foo diff --git a/tests/lang/eval-fail-remove.err.exp b/tests/lang/eval-fail-remove.err.exp deleted file mode 100644 index e82cdac98..000000000 --- a/tests/lang/eval-fail-remove.err.exp +++ /dev/null @@ -1,19 +0,0 @@ -error: - … while evaluating the attribute 'body' - - at /pwd/lang/eval-fail-remove.nix:4:3: - - 3| - 4| body = (removeAttrs attrs ["x"]).x; - | ^ - 5| } - - error: attribute 'x' missing - - at /pwd/lang/eval-fail-remove.nix:4:10: - - 3| - 4| body = (removeAttrs attrs ["x"]).x; - | ^ - 5| } - Did you mean y? diff --git a/tests/lang/eval-fail-remove.nix b/tests/lang/eval-fail-remove.nix deleted file mode 100644 index 539e0eb0a..000000000 --- a/tests/lang/eval-fail-remove.nix +++ /dev/null @@ -1,5 +0,0 @@ -let { - attrs = {x = 123; y = 456;}; - - body = (removeAttrs attrs ["x"]).x; -} \ No newline at end of file diff --git a/tests/lang/eval-fail-scope-5.err.exp b/tests/lang/eval-fail-scope-5.err.exp deleted file mode 100644 index 22b6166f8..000000000 --- a/tests/lang/eval-fail-scope-5.err.exp +++ /dev/null @@ -1,36 +0,0 @@ -error: - … while evaluating the attribute 'body' - - at /pwd/lang/eval-fail-scope-5.nix:8:3: - - 7| - 8| body = f {}; - | ^ - 9| - - … from call site - - at /pwd/lang/eval-fail-scope-5.nix:8:10: - - 7| - 8| body = f {}; - | ^ - 9| - - … while calling 'f' - - at /pwd/lang/eval-fail-scope-5.nix:6:7: - - 5| - 6| f = {x ? y, y ? x}: x + y; - | ^ - 7| - - error: infinite recursion encountered - - at /pwd/lang/eval-fail-scope-5.nix:6:12: - - 5| - 6| f = {x ? y, y ? x}: x + y; - | ^ - 7| diff --git a/tests/lang/eval-fail-scope-5.nix b/tests/lang/eval-fail-scope-5.nix deleted file mode 100644 index f89a65a99..000000000 --- a/tests/lang/eval-fail-scope-5.nix +++ /dev/null @@ -1,10 +0,0 @@ -let { - - x = "a"; - y = "b"; - - f = {x ? y, y ? x}: x + y; - - body = f {}; - -} diff --git a/tests/lang/eval-fail-seq.err.exp b/tests/lang/eval-fail-seq.err.exp deleted file mode 100644 index 33a7e9491..000000000 --- a/tests/lang/eval-fail-seq.err.exp +++ /dev/null @@ -1,18 +0,0 @@ -error: - … while calling the 'seq' builtin - - at /pwd/lang/eval-fail-seq.nix:1:1: - - 1| builtins.seq (abort "foo") 2 - | ^ - 2| - - … while calling the 'abort' builtin - - at /pwd/lang/eval-fail-seq.nix:1:15: - - 1| builtins.seq (abort "foo") 2 - | ^ - 2| - - error: evaluation aborted with the following error message: 'foo' diff --git a/tests/lang/eval-fail-seq.nix b/tests/lang/eval-fail-seq.nix deleted file mode 100644 index cddbbfd32..000000000 --- a/tests/lang/eval-fail-seq.nix +++ /dev/null @@ -1 +0,0 @@ -builtins.seq (abort "foo") 2 diff --git a/tests/lang/eval-fail-set-override.err.exp b/tests/lang/eval-fail-set-override.err.exp deleted file mode 100644 index beb29d678..000000000 --- a/tests/lang/eval-fail-set-override.err.exp +++ /dev/null @@ -1,6 +0,0 @@ -error: - … while evaluating the `__overrides` attribute - - at «none»:0: (source not available) - - error: value is an integer while a set was expected diff --git a/tests/lang/eval-fail-set-override.nix b/tests/lang/eval-fail-set-override.nix deleted file mode 100644 index 03551c186..000000000 --- a/tests/lang/eval-fail-set-override.nix +++ /dev/null @@ -1 +0,0 @@ -rec { __overrides = 1; } diff --git a/tests/lang/eval-fail-set.err.exp b/tests/lang/eval-fail-set.err.exp deleted file mode 100644 index 0d0140508..000000000 --- a/tests/lang/eval-fail-set.err.exp +++ /dev/null @@ -1,7 +0,0 @@ -error: undefined variable 'x' - - at /pwd/lang/eval-fail-set.nix:1:3: - - 1| 8.x - | ^ - 2| diff --git a/tests/lang/eval-fail-set.nix b/tests/lang/eval-fail-set.nix deleted file mode 100644 index c6b7980b6..000000000 --- a/tests/lang/eval-fail-set.nix +++ /dev/null @@ -1 +0,0 @@ -8.x diff --git a/tests/lang/eval-fail-substring.err.exp b/tests/lang/eval-fail-substring.err.exp deleted file mode 100644 index dc26a00bd..000000000 --- a/tests/lang/eval-fail-substring.err.exp +++ /dev/null @@ -1,12 +0,0 @@ -error: - … while calling the 'substring' builtin - - at /pwd/lang/eval-fail-substring.nix:1:1: - - 1| builtins.substring (builtins.sub 0 1) 1 "x" - | ^ - 2| - - error: negative start position in 'substring' - - at «none»:0: (source not available) diff --git a/tests/lang/eval-fail-substring.nix b/tests/lang/eval-fail-substring.nix deleted file mode 100644 index f37c2bc0a..000000000 --- a/tests/lang/eval-fail-substring.nix +++ /dev/null @@ -1 +0,0 @@ -builtins.substring (builtins.sub 0 1) 1 "x" diff --git a/tests/lang/eval-fail-to-path.err.exp b/tests/lang/eval-fail-to-path.err.exp deleted file mode 100644 index 43ed2bdfc..000000000 --- a/tests/lang/eval-fail-to-path.err.exp +++ /dev/null @@ -1,14 +0,0 @@ -error: - … while calling the 'toPath' builtin - - at /pwd/lang/eval-fail-to-path.nix:1:1: - - 1| builtins.toPath "foo/bar" - | ^ - 2| - - … while evaluating the first argument passed to builtins.toPath - - at «none»:0: (source not available) - - error: string 'foo/bar' doesn't represent an absolute path diff --git a/tests/lang/eval-fail-to-path.nix b/tests/lang/eval-fail-to-path.nix deleted file mode 100644 index 5e322bc31..000000000 --- a/tests/lang/eval-fail-to-path.nix +++ /dev/null @@ -1 +0,0 @@ -builtins.toPath "foo/bar" diff --git a/tests/lang/eval-fail-toJSON.err.exp b/tests/lang/eval-fail-toJSON.err.exp deleted file mode 100644 index 4e618c203..000000000 --- a/tests/lang/eval-fail-toJSON.err.exp +++ /dev/null @@ -1,57 +0,0 @@ -error: - … while calling the 'toJSON' builtin - - at /pwd/lang/eval-fail-toJSON.nix:1:1: - - 1| builtins.toJSON { - | ^ - 2| a.b = [ - - … while evaluating attribute 'a' - - at /pwd/lang/eval-fail-toJSON.nix:2:3: - - 1| builtins.toJSON { - 2| a.b = [ - | ^ - 3| true - - … while evaluating attribute 'b' - - at /pwd/lang/eval-fail-toJSON.nix:2:3: - - 1| builtins.toJSON { - 2| a.b = [ - | ^ - 3| true - - … while evaluating list element at index 3 - - … while evaluating attribute 'c' - - at /pwd/lang/eval-fail-toJSON.nix:7:7: - - 6| { - 7| c.d = throw "hah no"; - | ^ - 8| } - - … while evaluating attribute 'd' - - at /pwd/lang/eval-fail-toJSON.nix:7:7: - - 6| { - 7| c.d = throw "hah no"; - | ^ - 8| } - - … while calling the 'throw' builtin - - at /pwd/lang/eval-fail-toJSON.nix:7:13: - - 6| { - 7| c.d = throw "hah no"; - | ^ - 8| } - - error: hah no diff --git a/tests/lang/eval-fail-toJSON.nix b/tests/lang/eval-fail-toJSON.nix deleted file mode 100644 index 8112e1c1f..000000000 --- a/tests/lang/eval-fail-toJSON.nix +++ /dev/null @@ -1,10 +0,0 @@ -builtins.toJSON { - a.b = [ - true - false - "it's a bird" - { - c.d = throw "hah no"; - } - ]; -} diff --git a/tests/lang/eval-fail-undeclared-arg.err.exp b/tests/lang/eval-fail-undeclared-arg.err.exp deleted file mode 100644 index 30db743c7..000000000 --- a/tests/lang/eval-fail-undeclared-arg.err.exp +++ /dev/null @@ -1,17 +0,0 @@ -error: - … from call site - - at /pwd/lang/eval-fail-undeclared-arg.nix:1:1: - - 1| ({x, z}: x + z) {x = "foo"; y = "bla"; z = "bar";} - | ^ - 2| - - error: function 'anonymous lambda' called with unexpected argument 'y' - - at /pwd/lang/eval-fail-undeclared-arg.nix:1:2: - - 1| ({x, z}: x + z) {x = "foo"; y = "bla"; z = "bar";} - | ^ - 2| - Did you mean one of x or z? diff --git a/tests/lang/eval-fail-undeclared-arg.nix b/tests/lang/eval-fail-undeclared-arg.nix deleted file mode 100644 index cafdf1636..000000000 --- a/tests/lang/eval-fail-undeclared-arg.nix +++ /dev/null @@ -1 +0,0 @@ -({x, z}: x + z) {x = "foo"; y = "bla"; z = "bar";} diff --git a/tests/lang/eval-okay-any-all.exp b/tests/lang/eval-okay-any-all.exp deleted file mode 100644 index eb273f45b..000000000 --- a/tests/lang/eval-okay-any-all.exp +++ /dev/null @@ -1 +0,0 @@ -[ false false true true true true false true ] diff --git a/tests/lang/eval-okay-any-all.nix b/tests/lang/eval-okay-any-all.nix deleted file mode 100644 index a3f26ea2a..000000000 --- a/tests/lang/eval-okay-any-all.nix +++ /dev/null @@ -1,11 +0,0 @@ -with builtins; - -[ (any (x: x == 1) []) - (any (x: x == 1) [2 3 4]) - (any (x: x == 1) [1 2 3 4]) - (any (x: x == 1) [4 3 2 1]) - (all (x: x == 1) []) - (all (x: x == 1) [1]) - (all (x: x == 1) [1 2 3]) - (all (x: x == 1) [1 1 1]) -] diff --git a/tests/lang/eval-okay-arithmetic.exp b/tests/lang/eval-okay-arithmetic.exp deleted file mode 100644 index 5c54d10b7..000000000 --- a/tests/lang/eval-okay-arithmetic.exp +++ /dev/null @@ -1 +0,0 @@ -2216 diff --git a/tests/lang/eval-okay-arithmetic.nix b/tests/lang/eval-okay-arithmetic.nix deleted file mode 100644 index 7e9e6a0b6..000000000 --- a/tests/lang/eval-okay-arithmetic.nix +++ /dev/null @@ -1,59 +0,0 @@ -with import ./lib.nix; - -let { - - /* Supposedly tail recursive version: - - range_ = accum: first: last: - if first == last then ([first] ++ accum) - else range_ ([first] ++ accum) (builtins.add first 1) last; - - range = range_ []; - */ - - x = 12; - - err = abort "urgh"; - - body = sum - [ (sum (range 1 50)) - (123 + 456) - (0 + -10 + -(-11) + -x) - (10 - 7 - -2) - (10 - (6 - -1)) - (10 - 1 + 2) - (3 * 4 * 5) - (56088 / 123 / 2) - (3 + 4 * const 5 0 - 6 / id 2) - - (builtins.bitAnd 12 10) # 0b1100 & 0b1010 = 8 - (builtins.bitOr 12 10) # 0b1100 | 0b1010 = 14 - (builtins.bitXor 12 10) # 0b1100 ^ 0b1010 = 6 - - (if 3 < 7 then 1 else err) - (if 7 < 3 then err else 1) - (if 3 < 3 then err else 1) - - (if 3 <= 7 then 1 else err) - (if 7 <= 3 then err else 1) - (if 3 <= 3 then 1 else err) - - (if 3 > 7 then err else 1) - (if 7 > 3 then 1 else err) - (if 3 > 3 then err else 1) - - (if 3 >= 7 then err else 1) - (if 7 >= 3 then 1 else err) - (if 3 >= 3 then 1 else err) - - (if 2 > 1 == 1 < 2 then 1 else err) - (if 1 + 2 * 3 >= 7 then 1 else err) - (if 1 + 2 * 3 < 7 then err else 1) - - # Not integer, but so what. - (if "aa" < "ab" then 1 else err) - (if "aa" < "aa" then err else 1) - (if "foo" < "foobar" then 1 else err) - ]; - -} diff --git a/tests/lang/eval-okay-attrnames.exp b/tests/lang/eval-okay-attrnames.exp deleted file mode 100644 index b4aa387e0..000000000 --- a/tests/lang/eval-okay-attrnames.exp +++ /dev/null @@ -1 +0,0 @@ -"newxfoonewxy" diff --git a/tests/lang/eval-okay-attrnames.nix b/tests/lang/eval-okay-attrnames.nix deleted file mode 100644 index e5b26e9f2..000000000 --- a/tests/lang/eval-okay-attrnames.nix +++ /dev/null @@ -1,11 +0,0 @@ -with import ./lib.nix; - -let - - attrs = {y = "y"; x = "x"; foo = "foo";} // rec {x = "newx"; bar = x;}; - - names = builtins.attrNames attrs; - - values = map (name: builtins.getAttr name attrs) names; - -in assert values == builtins.attrValues attrs; concat values diff --git a/tests/lang/eval-okay-attrs.exp b/tests/lang/eval-okay-attrs.exp deleted file mode 100644 index 45b0f829e..000000000 --- a/tests/lang/eval-okay-attrs.exp +++ /dev/null @@ -1 +0,0 @@ -987 diff --git a/tests/lang/eval-okay-attrs.nix b/tests/lang/eval-okay-attrs.nix deleted file mode 100644 index 810b31a5d..000000000 --- a/tests/lang/eval-okay-attrs.nix +++ /dev/null @@ -1,5 +0,0 @@ -let { - as = { x = 123; y = 456; } // { z = 789; } // { z = 987; }; - - body = if as ? a then as.a else assert as ? z; as.z; -} diff --git a/tests/lang/eval-okay-attrs2.exp b/tests/lang/eval-okay-attrs2.exp deleted file mode 100644 index 45b0f829e..000000000 --- a/tests/lang/eval-okay-attrs2.exp +++ /dev/null @@ -1 +0,0 @@ -987 diff --git a/tests/lang/eval-okay-attrs2.nix b/tests/lang/eval-okay-attrs2.nix deleted file mode 100644 index 9e06b83ac..000000000 --- a/tests/lang/eval-okay-attrs2.nix +++ /dev/null @@ -1,10 +0,0 @@ -let { - as = { x = 123; y = 456; } // { z = 789; } // { z = 987; }; - - A = "a"; - Z = "z"; - - body = if builtins.hasAttr A as - then builtins.getAttr A as - else assert builtins.hasAttr Z as; builtins.getAttr Z as; -} diff --git a/tests/lang/eval-okay-attrs3.exp b/tests/lang/eval-okay-attrs3.exp deleted file mode 100644 index 19de4fdf7..000000000 --- a/tests/lang/eval-okay-attrs3.exp +++ /dev/null @@ -1 +0,0 @@ -"foo 22 80 itchyxac" diff --git a/tests/lang/eval-okay-attrs3.nix b/tests/lang/eval-okay-attrs3.nix deleted file mode 100644 index f29de11fe..000000000 --- a/tests/lang/eval-okay-attrs3.nix +++ /dev/null @@ -1,22 +0,0 @@ -let - - config = - { - services.sshd.enable = true; - services.sshd.port = 22; - services.httpd.port = 80; - hostName = "itchy"; - a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z = "x"; - foo = { - a = "a"; - b.c = "c"; - }; - }; - -in - if config.services.sshd.enable - then "foo ${toString config.services.sshd.port} ${toString config.services.httpd.port} ${config.hostName}" - + "${config.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z}" - + "${config.foo.a}" - + "${config.foo.b.c}" - else "bar" diff --git a/tests/lang/eval-okay-attrs4.exp b/tests/lang/eval-okay-attrs4.exp deleted file mode 100644 index 185173144..000000000 --- a/tests/lang/eval-okay-attrs4.exp +++ /dev/null @@ -1 +0,0 @@ -[ true false true false false true false false ] diff --git a/tests/lang/eval-okay-attrs4.nix b/tests/lang/eval-okay-attrs4.nix deleted file mode 100644 index 43ec81210..000000000 --- a/tests/lang/eval-okay-attrs4.nix +++ /dev/null @@ -1,7 +0,0 @@ -let - - as = { x.y.z = 123; a.b.c = 456; }; - - bs = null; - -in [ (as ? x) (as ? y) (as ? x.y.z) (as ? x.y.z.a) (as ? x.y.a) (as ? a.b.c) (bs ? x) (bs ? x.y.z) ] diff --git a/tests/lang/eval-okay-attrs5.exp b/tests/lang/eval-okay-attrs5.exp deleted file mode 100644 index ce0430d78..000000000 --- a/tests/lang/eval-okay-attrs5.exp +++ /dev/null @@ -1 +0,0 @@ -[ 123 "foo" 456 456 "foo" "xyzzy" "xyzzy" true ] diff --git a/tests/lang/eval-okay-attrs5.nix b/tests/lang/eval-okay-attrs5.nix deleted file mode 100644 index a4584cd3b..000000000 --- a/tests/lang/eval-okay-attrs5.nix +++ /dev/null @@ -1,21 +0,0 @@ -with import ./lib.nix; - -let - - as = { x.y.z = 123; a.b.c = 456; }; - - bs = { f-o-o.bar = "foo"; }; - - or = x: y: x || y; - -in - [ as.x.y.z - as.foo or "foo" - as.x.y.bla or as.a.b.c - as.a.b.c or as.x.y.z - as.x.y.bla or bs.f-o-o.bar or "xyzzy" - as.x.y.bla or bs.bar.foo or "xyzzy" - (123).bla or null.foo or "xyzzy" - # Backwards compatibility test. - (fold or [] [true false false]) - ] diff --git a/tests/lang/eval-okay-attrs6.exp b/tests/lang/eval-okay-attrs6.exp deleted file mode 100644 index b46938032..000000000 --- a/tests/lang/eval-okay-attrs6.exp +++ /dev/null @@ -1 +0,0 @@ -{ __overrides = { bar = "qux"; }; bar = "qux"; foo = "bar"; } diff --git a/tests/lang/eval-okay-attrs6.nix b/tests/lang/eval-okay-attrs6.nix deleted file mode 100644 index 2e5c85483..000000000 --- a/tests/lang/eval-okay-attrs6.nix +++ /dev/null @@ -1,4 +0,0 @@ -rec { - "${"foo"}" = "bar"; - __overrides = { bar = "qux"; }; -} diff --git a/tests/lang/eval-okay-autoargs.exp b/tests/lang/eval-okay-autoargs.exp deleted file mode 100644 index 7a8391786..000000000 --- a/tests/lang/eval-okay-autoargs.exp +++ /dev/null @@ -1 +0,0 @@ -"xyzzy!xyzzy!foobar" diff --git a/tests/lang/eval-okay-autoargs.flags b/tests/lang/eval-okay-autoargs.flags deleted file mode 100644 index ae3762254..000000000 --- a/tests/lang/eval-okay-autoargs.flags +++ /dev/null @@ -1 +0,0 @@ ---arg lib import(lang/lib.nix) --argstr xyzzy xyzzy! -A result diff --git a/tests/lang/eval-okay-autoargs.nix b/tests/lang/eval-okay-autoargs.nix deleted file mode 100644 index 815f51b1d..000000000 --- a/tests/lang/eval-okay-autoargs.nix +++ /dev/null @@ -1,15 +0,0 @@ -let - - foobar = "foobar"; - -in - -{ xyzzy2 ? xyzzy # mutually recursive args -, xyzzy ? "blaat" # will be overridden by --argstr -, fb ? foobar -, lib # will be set by --arg -}: - -{ - result = lib.concat [xyzzy xyzzy2 fb]; -} diff --git a/tests/lang/eval-okay-backslash-newline-1.exp b/tests/lang/eval-okay-backslash-newline-1.exp deleted file mode 100644 index 3e754364c..000000000 --- a/tests/lang/eval-okay-backslash-newline-1.exp +++ /dev/null @@ -1 +0,0 @@ -"a\nb" diff --git a/tests/lang/eval-okay-backslash-newline-1.nix b/tests/lang/eval-okay-backslash-newline-1.nix deleted file mode 100644 index 7fef3dddd..000000000 --- a/tests/lang/eval-okay-backslash-newline-1.nix +++ /dev/null @@ -1,2 +0,0 @@ -"a\ -b" diff --git a/tests/lang/eval-okay-backslash-newline-2.exp b/tests/lang/eval-okay-backslash-newline-2.exp deleted file mode 100644 index 3e754364c..000000000 --- a/tests/lang/eval-okay-backslash-newline-2.exp +++ /dev/null @@ -1 +0,0 @@ -"a\nb" diff --git a/tests/lang/eval-okay-backslash-newline-2.nix b/tests/lang/eval-okay-backslash-newline-2.nix deleted file mode 100644 index 35ddf495c..000000000 --- a/tests/lang/eval-okay-backslash-newline-2.nix +++ /dev/null @@ -1,2 +0,0 @@ -''a''\ -b'' diff --git a/tests/lang/eval-okay-builtins-add.exp b/tests/lang/eval-okay-builtins-add.exp deleted file mode 100644 index 0350b518a..000000000 --- a/tests/lang/eval-okay-builtins-add.exp +++ /dev/null @@ -1 +0,0 @@ -[ 5 4 "int" "tt" "float" 4 ] diff --git a/tests/lang/eval-okay-builtins-add.nix b/tests/lang/eval-okay-builtins-add.nix deleted file mode 100644 index c84181622..000000000 --- a/tests/lang/eval-okay-builtins-add.nix +++ /dev/null @@ -1,8 +0,0 @@ -[ -(builtins.add 2 3) -(builtins.add 2 2) -(builtins.typeOf (builtins.add 2 2)) -("t" + "t") -(builtins.typeOf (builtins.add 2.0 2)) -(builtins.add 2.0 2) -] diff --git a/tests/lang/eval-okay-builtins.exp b/tests/lang/eval-okay-builtins.exp deleted file mode 100644 index 0661686d6..000000000 --- a/tests/lang/eval-okay-builtins.exp +++ /dev/null @@ -1 +0,0 @@ -/foo diff --git a/tests/lang/eval-okay-builtins.nix b/tests/lang/eval-okay-builtins.nix deleted file mode 100644 index e9d65e88a..000000000 --- a/tests/lang/eval-okay-builtins.nix +++ /dev/null @@ -1,12 +0,0 @@ -assert builtins ? currentSystem; -assert !builtins ? __currentSystem; - -let { - - x = if builtins ? dirOf then builtins.dirOf /foo/bar else ""; - - y = if builtins ? fnord then builtins.fnord "foo" else ""; - - body = x + y; - -} diff --git a/tests/lang/eval-okay-callable-attrs.exp b/tests/lang/eval-okay-callable-attrs.exp deleted file mode 100644 index 27ba77dda..000000000 --- a/tests/lang/eval-okay-callable-attrs.exp +++ /dev/null @@ -1 +0,0 @@ -true diff --git a/tests/lang/eval-okay-callable-attrs.nix b/tests/lang/eval-okay-callable-attrs.nix deleted file mode 100644 index 310a030df..000000000 --- a/tests/lang/eval-okay-callable-attrs.nix +++ /dev/null @@ -1 +0,0 @@ -({ __functor = self: x: self.foo && x; foo = false; } // { foo = true; }) true diff --git a/tests/lang/eval-okay-catattrs.exp b/tests/lang/eval-okay-catattrs.exp deleted file mode 100644 index b4a1e66d6..000000000 --- a/tests/lang/eval-okay-catattrs.exp +++ /dev/null @@ -1 +0,0 @@ -[ 1 2 ] diff --git a/tests/lang/eval-okay-catattrs.nix b/tests/lang/eval-okay-catattrs.nix deleted file mode 100644 index 2c3dc10da..000000000 --- a/tests/lang/eval-okay-catattrs.nix +++ /dev/null @@ -1 +0,0 @@ -builtins.catAttrs "a" [ { a = 1; } { b = 0; } { a = 2; } ] diff --git a/tests/lang/eval-okay-closure.exp b/tests/lang/eval-okay-closure.exp deleted file mode 100644 index e7dbf9781..000000000 --- a/tests/lang/eval-okay-closure.exp +++ /dev/null @@ -1 +0,0 @@ -[ { foo = true; key = -13; } { foo = true; key = -12; } { foo = true; key = -11; } { foo = true; key = -9; } { foo = true; key = -8; } { foo = true; key = -7; } { foo = true; key = -5; } { foo = true; key = -4; } { foo = true; key = -3; } { key = -1; } { foo = true; key = 0; } { foo = true; key = 1; } { foo = true; key = 2; } { foo = true; key = 4; } { foo = true; key = 5; } { foo = true; key = 6; } { key = 8; } { foo = true; key = 9; } { foo = true; key = 10; } { foo = true; key = 13; } { foo = true; key = 14; } { foo = true; key = 15; } { key = 17; } { foo = true; key = 18; } { foo = true; key = 19; } { foo = true; key = 22; } { foo = true; key = 23; } { key = 26; } { foo = true; key = 27; } { foo = true; key = 28; } { foo = true; key = 31; } { foo = true; key = 32; } { key = 35; } { foo = true; key = 36; } { foo = true; key = 40; } { foo = true; key = 41; } { key = 44; } { foo = true; key = 45; } { foo = true; key = 49; } { key = 53; } { foo = true; key = 54; } { foo = true; key = 58; } { key = 62; } { foo = true; key = 67; } { key = 71; } { key = 80; } ] diff --git a/tests/lang/eval-okay-closure.exp.xml b/tests/lang/eval-okay-closure.exp.xml deleted file mode 100644 index dffc03a99..000000000 --- a/tests/lang/eval-okay-closure.exp.xml +++ /dev/null @@ -1,343 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/lang/eval-okay-closure.nix b/tests/lang/eval-okay-closure.nix deleted file mode 100644 index cccd4dc35..000000000 --- a/tests/lang/eval-okay-closure.nix +++ /dev/null @@ -1,13 +0,0 @@ -let - - closure = builtins.genericClosure { - startSet = [{key = 80;}]; - operator = {key, foo ? false}: - if builtins.lessThan key 0 - then [] - else [{key = builtins.sub key 9;} {key = builtins.sub key 13; foo = true;}]; - }; - - sort = (import ./lib.nix).sortBy (a: b: builtins.lessThan a.key b.key); - -in sort closure diff --git a/tests/lang/eval-okay-comments.exp b/tests/lang/eval-okay-comments.exp deleted file mode 100644 index 7182dc2f9..000000000 --- a/tests/lang/eval-okay-comments.exp +++ /dev/null @@ -1 +0,0 @@ -"abcdefghijklmnopqrstuvwxyz" diff --git a/tests/lang/eval-okay-comments.nix b/tests/lang/eval-okay-comments.nix deleted file mode 100644 index cb2cce218..000000000 --- a/tests/lang/eval-okay-comments.nix +++ /dev/null @@ -1,59 +0,0 @@ -# A simple comment -"a"+ # And another -## A double comment -"b"+ ## And another -# Nested # comments # -"c"+ # and # some # other # -# An empty line, following here: - -"d"+ # and a comment not starting the line ! - -"e"+ -/* multiline comments */ -"f" + -/* multiline - comments, - on - multiple - lines -*/ -"g" + -# Small, tricky comments -/**/ "h"+ /*/*/ "i"+ /***/ "j"+ /* /*/ "k"+ /*/* /*/ "l"+ -# Comments with an even number of ending '*' used to fail: -"m"+ -/* */ /* **/ /* ***/ /* ****/ "n"+ -/* */ /** */ /*** */ /**** */ "o"+ -/** **/ /*** ***/ /**** ****/ "p"+ -/* * ** *** **** ***** */ "q"+ -# Random comments -/* ***** ////// * / * / /* */ "r"+ -# Mixed comments -/* # */ -"s"+ -# /* # -"t"+ -# /* # */ -"u"+ -# /*********/ -"v"+ -## */* -"w"+ -/* - * Multiline, decorated comments - * # This ain't a nest'd comm'nt - */ -"x"+ -''${/** with **/"y" - # real - /* comments - inside ! # */ - - # (and empty lines) - -}''+ /* And a multiline comment, - on the same line, - after some spaces -*/ # followed by a one-line comment -"z" -/* EOF */ diff --git a/tests/lang/eval-okay-concat.exp b/tests/lang/eval-okay-concat.exp deleted file mode 100644 index bb4bbd577..000000000 --- a/tests/lang/eval-okay-concat.exp +++ /dev/null @@ -1 +0,0 @@ -[ 1 2 3 4 5 6 7 8 9 ] diff --git a/tests/lang/eval-okay-concat.nix b/tests/lang/eval-okay-concat.nix deleted file mode 100644 index d158a9bf0..000000000 --- a/tests/lang/eval-okay-concat.nix +++ /dev/null @@ -1 +0,0 @@ -[1 2 3] ++ [4 5 6] ++ [7 8 9] diff --git a/tests/lang/eval-okay-concatmap.exp b/tests/lang/eval-okay-concatmap.exp deleted file mode 100644 index 3b8be7739..000000000 --- a/tests/lang/eval-okay-concatmap.exp +++ /dev/null @@ -1 +0,0 @@ -[ [ 1 3 5 7 9 ] [ "a" "z" "b" "z" ] ] diff --git a/tests/lang/eval-okay-concatmap.nix b/tests/lang/eval-okay-concatmap.nix deleted file mode 100644 index 97da5d37a..000000000 --- a/tests/lang/eval-okay-concatmap.nix +++ /dev/null @@ -1,5 +0,0 @@ -with import ./lib.nix; - -[ (builtins.concatMap (x: if x / 2 * 2 == x then [] else [ x ]) (range 0 10)) - (builtins.concatMap (x: [x] ++ ["z"]) ["a" "b"]) -] diff --git a/tests/lang/eval-okay-concatstringssep.exp b/tests/lang/eval-okay-concatstringssep.exp deleted file mode 100644 index 93987647f..000000000 --- a/tests/lang/eval-okay-concatstringssep.exp +++ /dev/null @@ -1 +0,0 @@ -[ "" "foobarxyzzy" "foo, bar, xyzzy" "foo" "" ] diff --git a/tests/lang/eval-okay-concatstringssep.nix b/tests/lang/eval-okay-concatstringssep.nix deleted file mode 100644 index adc4c41bd..000000000 --- a/tests/lang/eval-okay-concatstringssep.nix +++ /dev/null @@ -1,8 +0,0 @@ -with builtins; - -[ (concatStringsSep "" []) - (concatStringsSep "" ["foo" "bar" "xyzzy"]) - (concatStringsSep ", " ["foo" "bar" "xyzzy"]) - (concatStringsSep ", " ["foo"]) - (concatStringsSep ", " []) -] diff --git a/tests/lang/eval-okay-context-introspection.exp b/tests/lang/eval-okay-context-introspection.exp deleted file mode 100644 index 03b400cc8..000000000 --- a/tests/lang/eval-okay-context-introspection.exp +++ /dev/null @@ -1 +0,0 @@ -[ true true true true true true ] diff --git a/tests/lang/eval-okay-context-introspection.nix b/tests/lang/eval-okay-context-introspection.nix deleted file mode 100644 index 50a78d946..000000000 --- a/tests/lang/eval-okay-context-introspection.nix +++ /dev/null @@ -1,41 +0,0 @@ -let - drv = derivation { - name = "fail"; - builder = "/bin/false"; - system = "x86_64-linux"; - outputs = [ "out" "foo" ]; - }; - - path = "${./eval-okay-context-introspection.nix}"; - - desired-context = { - "${builtins.unsafeDiscardStringContext path}" = { - path = true; - }; - "${builtins.unsafeDiscardStringContext drv.drvPath}" = { - outputs = [ "foo" "out" ]; - allOutputs = true; - }; - }; - - combo-path = "${path}${drv.outPath}${drv.foo.outPath}${drv.drvPath}"; - legit-context = builtins.getContext combo-path; - - reconstructed-path = builtins.appendContext - (builtins.unsafeDiscardStringContext combo-path) - desired-context; - - # Eta rule for strings with context. - etaRule = str: - str == builtins.appendContext - (builtins.unsafeDiscardStringContext str) - (builtins.getContext str); - -in [ - (legit-context == desired-context) - (reconstructed-path == combo-path) - (etaRule "foo") - (etaRule drv.drvPath) - (etaRule drv.foo.outPath) - (etaRule (builtins.unsafeDiscardOutputDependency drv.drvPath)) -] diff --git a/tests/lang/eval-okay-context.exp b/tests/lang/eval-okay-context.exp deleted file mode 100644 index 2f535bdbc..000000000 --- a/tests/lang/eval-okay-context.exp +++ /dev/null @@ -1 +0,0 @@ -"foo eval-okay-context.nix bar" diff --git a/tests/lang/eval-okay-context.nix b/tests/lang/eval-okay-context.nix deleted file mode 100644 index 7b9531cfe..000000000 --- a/tests/lang/eval-okay-context.nix +++ /dev/null @@ -1,6 +0,0 @@ -let s = "foo ${builtins.substring 33 100 (baseNameOf "${./eval-okay-context.nix}")} bar"; -in - if s != "foo eval-okay-context.nix bar" - then abort "context not discarded" - else builtins.unsafeDiscardStringContext s - diff --git a/tests/lang/eval-okay-curpos.exp b/tests/lang/eval-okay-curpos.exp deleted file mode 100644 index 65fd65b4d..000000000 --- a/tests/lang/eval-okay-curpos.exp +++ /dev/null @@ -1 +0,0 @@ -[ 3 7 4 9 ] diff --git a/tests/lang/eval-okay-curpos.nix b/tests/lang/eval-okay-curpos.nix deleted file mode 100644 index b79553df0..000000000 --- a/tests/lang/eval-okay-curpos.nix +++ /dev/null @@ -1,5 +0,0 @@ -# Bla -let - x = __curPos; - y = __curPos; -in [ x.line x.column y.line y.column ] diff --git a/tests/lang/eval-okay-deepseq.exp b/tests/lang/eval-okay-deepseq.exp deleted file mode 100644 index 8d38505c1..000000000 --- a/tests/lang/eval-okay-deepseq.exp +++ /dev/null @@ -1 +0,0 @@ -456 diff --git a/tests/lang/eval-okay-deepseq.nix b/tests/lang/eval-okay-deepseq.nix deleted file mode 100644 index 53aa4b1dc..000000000 --- a/tests/lang/eval-okay-deepseq.nix +++ /dev/null @@ -1 +0,0 @@ -builtins.deepSeq (let as = { x = 123; y = as; }; in as) 456 diff --git a/tests/lang/eval-okay-delayed-with-inherit.exp b/tests/lang/eval-okay-delayed-with-inherit.exp deleted file mode 100644 index eaacb55c1..000000000 --- a/tests/lang/eval-okay-delayed-with-inherit.exp +++ /dev/null @@ -1 +0,0 @@ -"b-overridden" diff --git a/tests/lang/eval-okay-delayed-with-inherit.nix b/tests/lang/eval-okay-delayed-with-inherit.nix deleted file mode 100644 index 84b388c27..000000000 --- a/tests/lang/eval-okay-delayed-with-inherit.nix +++ /dev/null @@ -1,24 +0,0 @@ -let - pkgs_ = with pkgs; { - a = derivation { - name = "a"; - system = builtins.currentSystem; - builder = "/bin/sh"; - args = [ "-c" "touch $out" ]; - inherit b; - }; - - inherit b; - }; - - packageOverrides = p: { - b = derivation { - name = "b-overridden"; - system = builtins.currentSystem; - builder = "/bin/sh"; - args = [ "-c" "touch $out" ]; - }; - }; - - pkgs = pkgs_ // (packageOverrides pkgs_); -in pkgs.a.b.name diff --git a/tests/lang/eval-okay-delayed-with.exp b/tests/lang/eval-okay-delayed-with.exp deleted file mode 100644 index 8e7c61ab8..000000000 --- a/tests/lang/eval-okay-delayed-with.exp +++ /dev/null @@ -1 +0,0 @@ -"b-overridden b-overridden a" diff --git a/tests/lang/eval-okay-delayed-with.nix b/tests/lang/eval-okay-delayed-with.nix deleted file mode 100644 index 3fb023e1c..000000000 --- a/tests/lang/eval-okay-delayed-with.nix +++ /dev/null @@ -1,29 +0,0 @@ -let - - pkgs_ = with pkgs; { - a = derivation { - name = "a"; - system = builtins.currentSystem; - builder = "/bin/sh"; - args = [ "-c" "touch $out" ]; - inherit b; - }; - - b = derivation { - name = "b"; - system = builtins.currentSystem; - builder = "/bin/sh"; - args = [ "-c" "touch $out" ]; - inherit a; - }; - - c = b; - }; - - packageOverrides = pkgs: with pkgs; { - b = derivation (b.drvAttrs // { name = "${b.name}-overridden"; }); - }; - - pkgs = pkgs_ // (packageOverrides pkgs_); - -in "${pkgs.a.b.name} ${pkgs.c.name} ${pkgs.b.a.name}" diff --git a/tests/lang/eval-okay-dynamic-attrs-2.exp b/tests/lang/eval-okay-dynamic-attrs-2.exp deleted file mode 100644 index 27ba77dda..000000000 --- a/tests/lang/eval-okay-dynamic-attrs-2.exp +++ /dev/null @@ -1 +0,0 @@ -true diff --git a/tests/lang/eval-okay-dynamic-attrs-2.nix b/tests/lang/eval-okay-dynamic-attrs-2.nix deleted file mode 100644 index 6d57bf854..000000000 --- a/tests/lang/eval-okay-dynamic-attrs-2.nix +++ /dev/null @@ -1 +0,0 @@ -{ a."${"b"}" = true; a."${"c"}" = false; }.a.b diff --git a/tests/lang/eval-okay-dynamic-attrs-bare.exp b/tests/lang/eval-okay-dynamic-attrs-bare.exp deleted file mode 100644 index df8750afc..000000000 --- a/tests/lang/eval-okay-dynamic-attrs-bare.exp +++ /dev/null @@ -1 +0,0 @@ -{ binds = true; hasAttrs = true; multiAttrs = true; recBinds = true; selectAttrs = true; selectOrAttrs = true; } diff --git a/tests/lang/eval-okay-dynamic-attrs-bare.nix b/tests/lang/eval-okay-dynamic-attrs-bare.nix deleted file mode 100644 index 0dbe15e63..000000000 --- a/tests/lang/eval-okay-dynamic-attrs-bare.nix +++ /dev/null @@ -1,17 +0,0 @@ -let - aString = "a"; - - bString = "b"; -in { - hasAttrs = { a.b = null; } ? ${aString}.b; - - selectAttrs = { a.b = true; }.a.${bString}; - - selectOrAttrs = { }.${aString} or true; - - binds = { ${aString}."${bString}c" = true; }.a.bc; - - recBinds = rec { ${bString} = a; a = true; }.b; - - multiAttrs = { ${aString} = true; ${bString} = false; }.a; -} diff --git a/tests/lang/eval-okay-dynamic-attrs.exp b/tests/lang/eval-okay-dynamic-attrs.exp deleted file mode 100644 index df8750afc..000000000 --- a/tests/lang/eval-okay-dynamic-attrs.exp +++ /dev/null @@ -1 +0,0 @@ -{ binds = true; hasAttrs = true; multiAttrs = true; recBinds = true; selectAttrs = true; selectOrAttrs = true; } diff --git a/tests/lang/eval-okay-dynamic-attrs.nix b/tests/lang/eval-okay-dynamic-attrs.nix deleted file mode 100644 index ee02ac7e6..000000000 --- a/tests/lang/eval-okay-dynamic-attrs.nix +++ /dev/null @@ -1,17 +0,0 @@ -let - aString = "a"; - - bString = "b"; -in { - hasAttrs = { a.b = null; } ? "${aString}".b; - - selectAttrs = { a.b = true; }.a."${bString}"; - - selectOrAttrs = { }."${aString}" or true; - - binds = { "${aString}"."${bString}c" = true; }.a.bc; - - recBinds = rec { "${bString}" = a; a = true; }.b; - - multiAttrs = { "${aString}" = true; "${bString}" = false; }.a; -} diff --git a/tests/lang/eval-okay-elem.exp b/tests/lang/eval-okay-elem.exp deleted file mode 100644 index 3cf6c0e96..000000000 --- a/tests/lang/eval-okay-elem.exp +++ /dev/null @@ -1 +0,0 @@ -[ true false 30 ] diff --git a/tests/lang/eval-okay-elem.nix b/tests/lang/eval-okay-elem.nix deleted file mode 100644 index 71ea7a4ed..000000000 --- a/tests/lang/eval-okay-elem.nix +++ /dev/null @@ -1,6 +0,0 @@ -with import ./lib.nix; - -let xs = range 10 40; in - -[ (builtins.elem 23 xs) (builtins.elem 42 xs) (builtins.elemAt xs 20) ] - diff --git a/tests/lang/eval-okay-empty-args.exp b/tests/lang/eval-okay-empty-args.exp deleted file mode 100644 index cb5537d5d..000000000 --- a/tests/lang/eval-okay-empty-args.exp +++ /dev/null @@ -1 +0,0 @@ -"ab" diff --git a/tests/lang/eval-okay-empty-args.nix b/tests/lang/eval-okay-empty-args.nix deleted file mode 100644 index 78c133afd..000000000 --- a/tests/lang/eval-okay-empty-args.nix +++ /dev/null @@ -1 +0,0 @@ -({}: {x,y,}: "${x}${y}") {} {x = "a"; y = "b";} diff --git a/tests/lang/eval-okay-eq-derivations.exp b/tests/lang/eval-okay-eq-derivations.exp deleted file mode 100644 index ec04aab6a..000000000 --- a/tests/lang/eval-okay-eq-derivations.exp +++ /dev/null @@ -1 +0,0 @@ -[ true true true false ] diff --git a/tests/lang/eval-okay-eq-derivations.nix b/tests/lang/eval-okay-eq-derivations.nix deleted file mode 100644 index d526cb4a2..000000000 --- a/tests/lang/eval-okay-eq-derivations.nix +++ /dev/null @@ -1,10 +0,0 @@ -let - - drvA1 = derivation { name = "a"; builder = "/foo"; system = "i686-linux"; }; - drvA2 = derivation { name = "a"; builder = "/foo"; system = "i686-linux"; }; - drvA3 = derivation { name = "a"; builder = "/foo"; system = "i686-linux"; } // { dummy = 1; }; - - drvC1 = derivation { name = "c"; builder = "/foo"; system = "i686-linux"; }; - drvC2 = derivation { name = "c"; builder = "/bar"; system = "i686-linux"; }; - -in [ (drvA1 == drvA1) (drvA1 == drvA2) (drvA1 == drvA3) (drvC1 == drvC2) ] diff --git a/tests/lang/eval-okay-eq.exp b/tests/lang/eval-okay-eq.exp deleted file mode 100644 index 27ba77dda..000000000 --- a/tests/lang/eval-okay-eq.exp +++ /dev/null @@ -1 +0,0 @@ -true diff --git a/tests/lang/eval-okay-eq.nix b/tests/lang/eval-okay-eq.nix deleted file mode 100644 index 73d200b38..000000000 --- a/tests/lang/eval-okay-eq.nix +++ /dev/null @@ -1,3 +0,0 @@ -["foobar" (rec {x = 1; y = x;})] -== -[("foo" + "bar") ({x = 1; y = 1;})] diff --git a/tests/lang/eval-okay-filter.exp b/tests/lang/eval-okay-filter.exp deleted file mode 100644 index 355d51c27..000000000 --- a/tests/lang/eval-okay-filter.exp +++ /dev/null @@ -1 +0,0 @@ -[ 0 2 4 6 8 10 100 102 104 106 108 110 ] diff --git a/tests/lang/eval-okay-filter.nix b/tests/lang/eval-okay-filter.nix deleted file mode 100644 index 85109b0d0..000000000 --- a/tests/lang/eval-okay-filter.nix +++ /dev/null @@ -1,5 +0,0 @@ -with import ./lib.nix; - -builtins.filter - (x: x / 2 * 2 == x) - (builtins.concatLists [ (range 0 10) (range 100 110) ]) diff --git a/tests/lang/eval-okay-flake-ref-to-string.exp b/tests/lang/eval-okay-flake-ref-to-string.exp deleted file mode 100644 index 110f8442d..000000000 --- a/tests/lang/eval-okay-flake-ref-to-string.exp +++ /dev/null @@ -1 +0,0 @@ -"github:NixOS/nixpkgs/23.05?dir=lib" diff --git a/tests/lang/eval-okay-flake-ref-to-string.nix b/tests/lang/eval-okay-flake-ref-to-string.nix deleted file mode 100644 index dbb4e5b2a..000000000 --- a/tests/lang/eval-okay-flake-ref-to-string.nix +++ /dev/null @@ -1,7 +0,0 @@ -builtins.flakeRefToString { - type = "github"; - owner = "NixOS"; - repo = "nixpkgs"; - ref = "23.05"; - dir = "lib"; -} diff --git a/tests/lang/eval-okay-flatten.exp b/tests/lang/eval-okay-flatten.exp deleted file mode 100644 index b979b2b8b..000000000 --- a/tests/lang/eval-okay-flatten.exp +++ /dev/null @@ -1 +0,0 @@ -"1234567" diff --git a/tests/lang/eval-okay-flatten.nix b/tests/lang/eval-okay-flatten.nix deleted file mode 100644 index fe911e968..000000000 --- a/tests/lang/eval-okay-flatten.nix +++ /dev/null @@ -1,8 +0,0 @@ -with import ./lib.nix; - -let { - - l = ["1" "2" ["3" ["4"] ["5" "6"]] "7"]; - - body = concat (flatten l); -} diff --git a/tests/lang/eval-okay-float.exp b/tests/lang/eval-okay-float.exp deleted file mode 100644 index 3c50a8adc..000000000 --- a/tests/lang/eval-okay-float.exp +++ /dev/null @@ -1 +0,0 @@ -[ 3.4 3.5 2.5 1.5 ] diff --git a/tests/lang/eval-okay-float.nix b/tests/lang/eval-okay-float.nix deleted file mode 100644 index b2702c7b1..000000000 --- a/tests/lang/eval-okay-float.nix +++ /dev/null @@ -1,6 +0,0 @@ -[ - (1.1 + 2.3) - (builtins.add (0.5 + 0.5) (2.0 + 0.5)) - ((0.5 + 0.5) * (2.0 + 0.5)) - ((1.5 + 1.5) / (0.5 * 4.0)) -] diff --git a/tests/lang/eval-okay-floor-ceil.exp b/tests/lang/eval-okay-floor-ceil.exp deleted file mode 100644 index 81f80420b..000000000 --- a/tests/lang/eval-okay-floor-ceil.exp +++ /dev/null @@ -1 +0,0 @@ -"23;24;23;23" diff --git a/tests/lang/eval-okay-floor-ceil.nix b/tests/lang/eval-okay-floor-ceil.nix deleted file mode 100644 index d76a0d86e..000000000 --- a/tests/lang/eval-okay-floor-ceil.nix +++ /dev/null @@ -1,9 +0,0 @@ -with import ./lib.nix; - -let - n1 = builtins.floor 23.5; - n2 = builtins.ceil 23.5; - n3 = builtins.floor 23; - n4 = builtins.ceil 23; -in - builtins.concatStringsSep ";" (map toString [ n1 n2 n3 n4 ]) diff --git a/tests/lang/eval-okay-foldlStrict-lazy-elements.exp b/tests/lang/eval-okay-foldlStrict-lazy-elements.exp deleted file mode 100644 index d81cc0710..000000000 --- a/tests/lang/eval-okay-foldlStrict-lazy-elements.exp +++ /dev/null @@ -1 +0,0 @@ -42 diff --git a/tests/lang/eval-okay-foldlStrict-lazy-elements.nix b/tests/lang/eval-okay-foldlStrict-lazy-elements.nix deleted file mode 100644 index c666e07f3..000000000 --- a/tests/lang/eval-okay-foldlStrict-lazy-elements.nix +++ /dev/null @@ -1,9 +0,0 @@ -# Tests that the rhs argument of op is not forced unconditionally -let - lst = builtins.foldl' - (acc: x: acc ++ [ x ]) - [ ] - [ 42 (throw "this shouldn't be evaluated") ]; -in - -builtins.head lst diff --git a/tests/lang/eval-okay-foldlStrict-lazy-initial-accumulator.exp b/tests/lang/eval-okay-foldlStrict-lazy-initial-accumulator.exp deleted file mode 100644 index d81cc0710..000000000 --- a/tests/lang/eval-okay-foldlStrict-lazy-initial-accumulator.exp +++ /dev/null @@ -1 +0,0 @@ -42 diff --git a/tests/lang/eval-okay-foldlStrict-lazy-initial-accumulator.nix b/tests/lang/eval-okay-foldlStrict-lazy-initial-accumulator.nix deleted file mode 100644 index abcd5366a..000000000 --- a/tests/lang/eval-okay-foldlStrict-lazy-initial-accumulator.nix +++ /dev/null @@ -1,6 +0,0 @@ -# Checks that the nul value for the accumulator is not forced unconditionally. -# Some languages provide a foldl' that is strict in this argument, but Nix does not. -builtins.foldl' - (_: x: x) - (throw "This is never forced") - [ "but the results of applying op are" 42 ] diff --git a/tests/lang/eval-okay-foldlStrict.exp b/tests/lang/eval-okay-foldlStrict.exp deleted file mode 100644 index 837e12b40..000000000 --- a/tests/lang/eval-okay-foldlStrict.exp +++ /dev/null @@ -1 +0,0 @@ -500500 diff --git a/tests/lang/eval-okay-foldlStrict.nix b/tests/lang/eval-okay-foldlStrict.nix deleted file mode 100644 index 3b87188d2..000000000 --- a/tests/lang/eval-okay-foldlStrict.nix +++ /dev/null @@ -1,3 +0,0 @@ -with import ./lib.nix; - -builtins.foldl' (x: y: x + y) 0 (range 1 1000) diff --git a/tests/lang/eval-okay-fromTOML-timestamps.exp b/tests/lang/eval-okay-fromTOML-timestamps.exp deleted file mode 100644 index 08b3c69a6..000000000 --- a/tests/lang/eval-okay-fromTOML-timestamps.exp +++ /dev/null @@ -1 +0,0 @@ -{ "1234" = "value"; "127.0.0.1" = "value"; a = { b = { c = { }; }; }; arr1 = [ 1 2 3 ]; arr2 = [ "red" "yellow" "green" ]; arr3 = [ [ 1 2 ] [ 3 4 5 ] ]; arr4 = [ "all" "strings" "are the same" "type" ]; arr5 = [ [ 1 2 ] [ "a" "b" "c" ] ]; arr7 = [ 1 2 3 ]; arr8 = [ 1 2 ]; bare-key = "value"; bare_key = "value"; bin1 = 214; bool1 = true; bool2 = false; "character encoding" = "value"; d = { e = { f = { }; }; }; dog = { "tater.man" = { type = { name = "pug"; }; }; }; flt1 = 1; flt2 = 3.1415; flt3 = -0.01; flt4 = 5e+22; flt5 = 1e+06; flt6 = -0.02; flt7 = 6.626e-34; flt8 = 9.22462e+06; fruit = [ { name = "apple"; physical = { color = "red"; shape = "round"; }; variety = [ { name = "red delicious"; } { name = "granny smith"; } ]; } { name = "banana"; variety = [ { name = "plantain"; } ]; } ]; g = { h = { i = { }; }; }; hex1 = 3735928559; hex2 = 3735928559; hex3 = 3735928559; int1 = 99; int2 = 42; int3 = 0; int4 = -17; int5 = 1000; int6 = 5349221; int7 = 12345; j = { "ʞ" = { l = { }; }; }; key = "value"; key2 = "value"; ld1 = { _type = "timestamp"; value = "1979-05-27"; }; ldt1 = { _type = "timestamp"; value = "1979-05-27T07:32:00"; }; ldt2 = { _type = "timestamp"; value = "1979-05-27T00:32:00.999999"; }; lt1 = { _type = "timestamp"; value = "07:32:00"; }; lt2 = { _type = "timestamp"; value = "00:32:00.999999"; }; name = "Orange"; oct1 = 342391; oct2 = 493; odt1 = { _type = "timestamp"; value = "1979-05-27T07:32:00Z"; }; odt2 = { _type = "timestamp"; value = "1979-05-27T00:32:00-07:00"; }; odt3 = { _type = "timestamp"; value = "1979-05-27T00:32:00.999999-07:00"; }; odt4 = { _type = "timestamp"; value = "1979-05-27T07:32:00Z"; }; physical = { color = "orange"; shape = "round"; }; products = [ { name = "Hammer"; sku = 738594937; } { } { color = "gray"; name = "Nail"; sku = 284758393; } ]; "quoted \"value\"" = "value"; site = { "google.com" = true; }; str = "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF."; table-1 = { key1 = "some string"; key2 = 123; }; table-2 = { key1 = "another string"; key2 = 456; }; x = { y = { z = { w = { animal = { type = { name = "pug"; }; }; name = { first = "Tom"; last = "Preston-Werner"; }; point = { x = 1; y = 2; }; }; }; }; }; "ʎǝʞ" = "value"; } diff --git a/tests/lang/eval-okay-fromTOML-timestamps.flags b/tests/lang/eval-okay-fromTOML-timestamps.flags deleted file mode 100644 index 9ed39dc6b..000000000 --- a/tests/lang/eval-okay-fromTOML-timestamps.flags +++ /dev/null @@ -1 +0,0 @@ ---extra-experimental-features parse-toml-timestamps diff --git a/tests/lang/eval-okay-fromTOML-timestamps.nix b/tests/lang/eval-okay-fromTOML-timestamps.nix deleted file mode 100644 index 74cff9470..000000000 --- a/tests/lang/eval-okay-fromTOML-timestamps.nix +++ /dev/null @@ -1,130 +0,0 @@ -builtins.fromTOML '' - key = "value" - bare_key = "value" - bare-key = "value" - 1234 = "value" - - "127.0.0.1" = "value" - "character encoding" = "value" - "ʎǝʞ" = "value" - 'key2' = "value" - 'quoted "value"' = "value" - - name = "Orange" - - physical.color = "orange" - physical.shape = "round" - site."google.com" = true - - # This is legal according to the spec, but cpptoml doesn't handle it. - #a.b.c = 1 - #a.d = 2 - - str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF." - - int1 = +99 - int2 = 42 - int3 = 0 - int4 = -17 - int5 = 1_000 - int6 = 5_349_221 - int7 = 1_2_3_4_5 - - hex1 = 0xDEADBEEF - hex2 = 0xdeadbeef - hex3 = 0xdead_beef - - oct1 = 0o01234567 - oct2 = 0o755 - - bin1 = 0b11010110 - - flt1 = +1.0 - flt2 = 3.1415 - flt3 = -0.01 - flt4 = 5e+22 - flt5 = 1e6 - flt6 = -2E-2 - flt7 = 6.626e-34 - flt8 = 9_224_617.445_991_228_313 - - bool1 = true - bool2 = false - - odt1 = 1979-05-27T07:32:00Z - odt2 = 1979-05-27T00:32:00-07:00 - odt3 = 1979-05-27T00:32:00.999999-07:00 - odt4 = 1979-05-27 07:32:00Z - ldt1 = 1979-05-27T07:32:00 - ldt2 = 1979-05-27T00:32:00.999999 - ld1 = 1979-05-27 - lt1 = 07:32:00 - lt2 = 00:32:00.999999 - - arr1 = [ 1, 2, 3 ] - arr2 = [ "red", "yellow", "green" ] - arr3 = [ [ 1, 2 ], [3, 4, 5] ] - arr4 = [ "all", 'strings', """are the same""", ''''type''''] - arr5 = [ [ 1, 2 ], ["a", "b", "c"] ] - - arr7 = [ - 1, 2, 3 - ] - - arr8 = [ - 1, - 2, # this is ok - ] - - [table-1] - key1 = "some string" - key2 = 123 - - - [table-2] - key1 = "another string" - key2 = 456 - - [dog."tater.man"] - type.name = "pug" - - [a.b.c] - [ d.e.f ] - [ g . h . i ] - [ j . "ʞ" . 'l' ] - [x.y.z.w] - - name = { first = "Tom", last = "Preston-Werner" } - point = { x = 1, y = 2 } - animal = { type.name = "pug" } - - [[products]] - name = "Hammer" - sku = 738594937 - - [[products]] - - [[products]] - name = "Nail" - sku = 284758393 - color = "gray" - - [[fruit]] - name = "apple" - - [fruit.physical] - color = "red" - shape = "round" - - [[fruit.variety]] - name = "red delicious" - - [[fruit.variety]] - name = "granny smith" - - [[fruit]] - name = "banana" - - [[fruit.variety]] - name = "plantain" -'' diff --git a/tests/lang/eval-okay-fromTOML.exp b/tests/lang/eval-okay-fromTOML.exp deleted file mode 100644 index d0dd3af2c..000000000 --- a/tests/lang/eval-okay-fromTOML.exp +++ /dev/null @@ -1 +0,0 @@ -[ { clients = { data = [ [ "gamma" "delta" ] [ 1 2 ] ]; hosts = [ "alpha" "omega" ]; }; database = { connection_max = 5000; enabled = true; ports = [ 8001 8001 8002 ]; server = "192.168.1.1"; }; owner = { name = "Tom Preston-Werner"; }; servers = { alpha = { dc = "eqdc10"; ip = "10.0.0.1"; }; beta = { dc = "eqdc10"; ip = "10.0.0.2"; }; }; title = "TOML Example"; } { "1234" = "value"; "127.0.0.1" = "value"; a = { b = { c = { }; }; }; arr1 = [ 1 2 3 ]; arr2 = [ "red" "yellow" "green" ]; arr3 = [ [ 1 2 ] [ 3 4 5 ] ]; arr4 = [ "all" "strings" "are the same" "type" ]; arr5 = [ [ 1 2 ] [ "a" "b" "c" ] ]; arr7 = [ 1 2 3 ]; arr8 = [ 1 2 ]; bare-key = "value"; bare_key = "value"; bin1 = 214; bool1 = true; bool2 = false; "character encoding" = "value"; d = { e = { f = { }; }; }; dog = { "tater.man" = { type = { name = "pug"; }; }; }; flt1 = 1; flt2 = 3.1415; flt3 = -0.01; flt4 = 5e+22; flt5 = 1e+06; flt6 = -0.02; flt7 = 6.626e-34; flt8 = 9.22462e+06; fruit = [ { name = "apple"; physical = { color = "red"; shape = "round"; }; variety = [ { name = "red delicious"; } { name = "granny smith"; } ]; } { name = "banana"; variety = [ { name = "plantain"; } ]; } ]; g = { h = { i = { }; }; }; hex1 = 3735928559; hex2 = 3735928559; hex3 = 3735928559; int1 = 99; int2 = 42; int3 = 0; int4 = -17; int5 = 1000; int6 = 5349221; int7 = 12345; j = { "ʞ" = { l = { }; }; }; key = "value"; key2 = "value"; name = "Orange"; oct1 = 342391; oct2 = 493; physical = { color = "orange"; shape = "round"; }; products = [ { name = "Hammer"; sku = 738594937; } { } { color = "gray"; name = "Nail"; sku = 284758393; } ]; "quoted \"value\"" = "value"; site = { "google.com" = true; }; str = "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF."; table-1 = { key1 = "some string"; key2 = 123; }; table-2 = { key1 = "another string"; key2 = 456; }; x = { y = { z = { w = { animal = { type = { name = "pug"; }; }; name = { first = "Tom"; last = "Preston-Werner"; }; point = { x = 1; y = 2; }; }; }; }; }; "ʎǝʞ" = "value"; } { metadata = { "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"; "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"; "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"; "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"; }; package = [ { dependencies = [ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" ]; name = "aho-corasick"; source = "registry+https://github.com/rust-lang/crates.io-index"; version = "0.6.4"; } { name = "ansi_term"; source = "registry+https://github.com/rust-lang/crates.io-index"; version = "0.9.0"; } { dependencies = [ "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" ]; name = "atty"; source = "registry+https://github.com/rust-lang/crates.io-index"; version = "0.2.10"; } ]; } { a = [ [ { b = true; } ] ]; c = [ [ { d = true; } ] ]; e = [ [ 123 ] ]; } ] diff --git a/tests/lang/eval-okay-fromTOML.nix b/tests/lang/eval-okay-fromTOML.nix deleted file mode 100644 index 963932689..000000000 --- a/tests/lang/eval-okay-fromTOML.nix +++ /dev/null @@ -1,208 +0,0 @@ -[ - - (builtins.fromTOML '' - # This is a TOML document. - - title = "TOML Example" - - [owner] - name = "Tom Preston-Werner" - #dob = 1979-05-27T07:32:00-08:00 # First class dates - - [database] - server = "192.168.1.1" - ports = [ 8001, 8001, 8002 ] - connection_max = 5000 - enabled = true - - [servers] - - # Indentation (tabs and/or spaces) is allowed but not required - [servers.alpha] - ip = "10.0.0.1" - dc = "eqdc10" - - [servers.beta] - ip = "10.0.0.2" - dc = "eqdc10" - - [clients] - data = [ ["gamma", "delta"], [1, 2] ] - - # Line breaks are OK when inside arrays - hosts = [ - "alpha", - "omega" - ] - '') - - (builtins.fromTOML '' - key = "value" - bare_key = "value" - bare-key = "value" - 1234 = "value" - - "127.0.0.1" = "value" - "character encoding" = "value" - "ʎǝʞ" = "value" - 'key2' = "value" - 'quoted "value"' = "value" - - name = "Orange" - - physical.color = "orange" - physical.shape = "round" - site."google.com" = true - - # This is legal according to the spec, but cpptoml doesn't handle it. - #a.b.c = 1 - #a.d = 2 - - str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF." - - int1 = +99 - int2 = 42 - int3 = 0 - int4 = -17 - int5 = 1_000 - int6 = 5_349_221 - int7 = 1_2_3_4_5 - - hex1 = 0xDEADBEEF - hex2 = 0xdeadbeef - hex3 = 0xdead_beef - - oct1 = 0o01234567 - oct2 = 0o755 - - bin1 = 0b11010110 - - flt1 = +1.0 - flt2 = 3.1415 - flt3 = -0.01 - flt4 = 5e+22 - flt5 = 1e6 - flt6 = -2E-2 - flt7 = 6.626e-34 - flt8 = 9_224_617.445_991_228_313 - - bool1 = true - bool2 = false - - # FIXME: not supported because Nix doesn't have a date/time type. - #odt1 = 1979-05-27T07:32:00Z - #odt2 = 1979-05-27T00:32:00-07:00 - #odt3 = 1979-05-27T00:32:00.999999-07:00 - #odt4 = 1979-05-27 07:32:00Z - #ldt1 = 1979-05-27T07:32:00 - #ldt2 = 1979-05-27T00:32:00.999999 - #ld1 = 1979-05-27 - #lt1 = 07:32:00 - #lt2 = 00:32:00.999999 - - arr1 = [ 1, 2, 3 ] - arr2 = [ "red", "yellow", "green" ] - arr3 = [ [ 1, 2 ], [3, 4, 5] ] - arr4 = [ "all", 'strings', """are the same""", ''''type''''] - arr5 = [ [ 1, 2 ], ["a", "b", "c"] ] - - arr7 = [ - 1, 2, 3 - ] - - arr8 = [ - 1, - 2, # this is ok - ] - - [table-1] - key1 = "some string" - key2 = 123 - - - [table-2] - key1 = "another string" - key2 = 456 - - [dog."tater.man"] - type.name = "pug" - - [a.b.c] - [ d.e.f ] - [ g . h . i ] - [ j . "ʞ" . 'l' ] - [x.y.z.w] - - name = { first = "Tom", last = "Preston-Werner" } - point = { x = 1, y = 2 } - animal = { type.name = "pug" } - - [[products]] - name = "Hammer" - sku = 738594937 - - [[products]] - - [[products]] - name = "Nail" - sku = 284758393 - color = "gray" - - [[fruit]] - name = "apple" - - [fruit.physical] - color = "red" - shape = "round" - - [[fruit.variety]] - name = "red delicious" - - [[fruit.variety]] - name = "granny smith" - - [[fruit]] - name = "banana" - - [[fruit.variety]] - name = "plantain" - '') - - (builtins.fromTOML '' - [[package]] - name = "aho-corasick" - version = "0.6.4" - source = "registry+https://github.com/rust-lang/crates.io-index" - dependencies = [ - "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - ] - - [[package]] - name = "ansi_term" - version = "0.9.0" - source = "registry+https://github.com/rust-lang/crates.io-index" - - [[package]] - name = "atty" - version = "0.2.10" - source = "registry+https://github.com/rust-lang/crates.io-index" - dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - ] - - [metadata] - "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" - "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" - "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" - "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" - '') - - (builtins.fromTOML '' - a = [[{ b = true }]] - c = [ [ { d = true } ] ] - e = [[123]] - '') - -] diff --git a/tests/lang/eval-okay-fromjson-escapes.exp b/tests/lang/eval-okay-fromjson-escapes.exp deleted file mode 100644 index add5505a8..000000000 --- a/tests/lang/eval-okay-fromjson-escapes.exp +++ /dev/null @@ -1 +0,0 @@ -"quote \" reverse solidus \\ solidus / backspace  formfeed newline \n carriage return \r horizontal tab \t 1 char unicode encoded backspace  1 char unicode encoded e with accent é 2 char unicode encoded s with caron š 3 char unicode encoded rightwards arrow →" diff --git a/tests/lang/eval-okay-fromjson-escapes.nix b/tests/lang/eval-okay-fromjson-escapes.nix deleted file mode 100644 index f00713507..000000000 --- a/tests/lang/eval-okay-fromjson-escapes.nix +++ /dev/null @@ -1,3 +0,0 @@ -# This string contains all supported escapes in a JSON string, per json.org -# \b and \f are not supported by Nix -builtins.fromJSON ''"quote \" reverse solidus \\ solidus \/ backspace \b formfeed \f newline \n carriage return \r horizontal tab \t 1 char unicode encoded backspace \u0008 1 char unicode encoded e with accent \u00e9 2 char unicode encoded s with caron \u0161 3 char unicode encoded rightwards arrow \u2192"'' diff --git a/tests/lang/eval-okay-fromjson.exp b/tests/lang/eval-okay-fromjson.exp deleted file mode 100644 index 27ba77dda..000000000 --- a/tests/lang/eval-okay-fromjson.exp +++ /dev/null @@ -1 +0,0 @@ -true diff --git a/tests/lang/eval-okay-fromjson.nix b/tests/lang/eval-okay-fromjson.nix deleted file mode 100644 index 4c526b9ae..000000000 --- a/tests/lang/eval-okay-fromjson.nix +++ /dev/null @@ -1,41 +0,0 @@ -builtins.fromJSON - '' - { - "Video": { - "Title": "The Penguin Chronicles", - "Width": 1920, - "Height": 1080, - "EmbeddedData": [3.14159, 23493,null, true ,false, -10], - "Thumb": { - "Url": "http://www.example.com/video/5678931", - "Width": 200, - "Height": 250 - }, - "Animated" : false, - "IDs": [116, 943, 234, 38793, true ,false,null, -100], - "Escapes": "\"\\\/\t\n\r\t", - "Subtitle" : false, - "Latitude": 37.7668, - "Longitude": -122.3959 - } - } - '' -== - { Video = - { Title = "The Penguin Chronicles"; - Width = 1920; - Height = 1080; - EmbeddedData = [ 3.14159 23493 null true false (0-10) ]; - Thumb = - { Url = "http://www.example.com/video/5678931"; - Width = 200; - Height = 250; - }; - Animated = false; - IDs = [ 116 943 234 38793 true false null (0-100) ]; - Escapes = "\"\\\/\t\n\r\t"; # supported in JSON but not Nix: \b\f - Subtitle = false; - Latitude = 37.7668; - Longitude = -122.3959; - }; - } diff --git a/tests/lang/eval-okay-functionargs.exp b/tests/lang/eval-okay-functionargs.exp deleted file mode 100644 index c1c9f8ffa..000000000 --- a/tests/lang/eval-okay-functionargs.exp +++ /dev/null @@ -1 +0,0 @@ -[ "stdenv" "fetchurl" "aterm-stdenv" "aterm-stdenv2" "libX11" "libXv" "mplayer-stdenv2.libXv-libX11" "mplayer-stdenv2.libXv-libX11_2" "nix-stdenv-aterm-stdenv" "nix-stdenv2-aterm2-stdenv2" ] diff --git a/tests/lang/eval-okay-functionargs.exp.xml b/tests/lang/eval-okay-functionargs.exp.xml deleted file mode 100644 index 651f54c36..000000000 --- a/tests/lang/eval-okay-functionargs.exp.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/tests/lang/eval-okay-functionargs.nix b/tests/lang/eval-okay-functionargs.nix deleted file mode 100644 index 68dca62ee..000000000 --- a/tests/lang/eval-okay-functionargs.nix +++ /dev/null @@ -1,80 +0,0 @@ -let - - stdenvFun = { }: { name = "stdenv"; }; - stdenv2Fun = { }: { name = "stdenv2"; }; - fetchurlFun = { stdenv }: assert stdenv.name == "stdenv"; { name = "fetchurl"; }; - atermFun = { stdenv, fetchurl }: { name = "aterm-${stdenv.name}"; }; - aterm2Fun = { stdenv, fetchurl }: { name = "aterm2-${stdenv.name}"; }; - nixFun = { stdenv, fetchurl, aterm }: { name = "nix-${stdenv.name}-${aterm.name}"; }; - - mplayerFun = - { stdenv, fetchurl, enableX11 ? false, xorg ? null, enableFoo ? true, foo ? null }: - assert stdenv.name == "stdenv2"; - assert enableX11 -> xorg.libXv.name == "libXv"; - assert enableFoo -> foo != null; - { name = "mplayer-${stdenv.name}.${xorg.libXv.name}-${xorg.libX11.name}"; }; - - makeOverridable = f: origArgs: f origArgs // - { override = newArgs: - makeOverridable f (origArgs // (if builtins.isFunction newArgs then newArgs origArgs else newArgs)); - }; - - callPackage_ = pkgs: f: args: - makeOverridable f ((builtins.intersectAttrs (builtins.functionArgs f) pkgs) // args); - - allPackages = - { overrides ? (pkgs: pkgsPrev: { }) }: - let - callPackage = callPackage_ pkgs; - pkgs = pkgsStd // (overrides pkgs pkgsStd); - pkgsStd = { - inherit pkgs; - stdenv = callPackage stdenvFun { }; - stdenv2 = callPackage stdenv2Fun { }; - fetchurl = callPackage fetchurlFun { }; - aterm = callPackage atermFun { }; - xorg = callPackage xorgFun { }; - mplayer = callPackage mplayerFun { stdenv = pkgs.stdenv2; enableFoo = false; }; - nix = callPackage nixFun { }; - }; - in pkgs; - - libX11Fun = { stdenv, fetchurl }: { name = "libX11"; }; - libX11_2Fun = { stdenv, fetchurl }: { name = "libX11_2"; }; - libXvFun = { stdenv, fetchurl, libX11 }: { name = "libXv"; }; - - xorgFun = - { pkgs }: - let callPackage = callPackage_ (pkgs // pkgs.xorg); in - { - libX11 = callPackage libX11Fun { }; - libXv = callPackage libXvFun { }; - }; - -in - -let - - pkgs = allPackages { }; - - pkgs2 = allPackages { - overrides = pkgs: pkgsPrev: { - stdenv = pkgs.stdenv2; - nix = pkgsPrev.nix.override { aterm = aterm2Fun { inherit (pkgs) stdenv fetchurl; }; }; - xorg = pkgsPrev.xorg // { libX11 = libX11_2Fun { inherit (pkgs) stdenv fetchurl; }; }; - }; - }; - -in - - [ pkgs.stdenv.name - pkgs.fetchurl.name - pkgs.aterm.name - pkgs2.aterm.name - pkgs.xorg.libX11.name - pkgs.xorg.libXv.name - pkgs.mplayer.name - pkgs2.mplayer.name - pkgs.nix.name - pkgs2.nix.name - ] diff --git a/tests/lang/eval-okay-getattrpos-functionargs.exp b/tests/lang/eval-okay-getattrpos-functionargs.exp deleted file mode 100644 index 7f9ac40e8..000000000 --- a/tests/lang/eval-okay-getattrpos-functionargs.exp +++ /dev/null @@ -1 +0,0 @@ -{ column = 11; file = "eval-okay-getattrpos-functionargs.nix"; line = 2; } diff --git a/tests/lang/eval-okay-getattrpos-functionargs.nix b/tests/lang/eval-okay-getattrpos-functionargs.nix deleted file mode 100644 index 11d6bb0e3..000000000 --- a/tests/lang/eval-okay-getattrpos-functionargs.nix +++ /dev/null @@ -1,4 +0,0 @@ -let - fun = { foo }: {}; - pos = builtins.unsafeGetAttrPos "foo" (builtins.functionArgs fun); -in { inherit (pos) column line; file = baseNameOf pos.file; } diff --git a/tests/lang/eval-okay-getattrpos-undefined.exp b/tests/lang/eval-okay-getattrpos-undefined.exp deleted file mode 100644 index 19765bd50..000000000 --- a/tests/lang/eval-okay-getattrpos-undefined.exp +++ /dev/null @@ -1 +0,0 @@ -null diff --git a/tests/lang/eval-okay-getattrpos-undefined.nix b/tests/lang/eval-okay-getattrpos-undefined.nix deleted file mode 100644 index 14dd38f77..000000000 --- a/tests/lang/eval-okay-getattrpos-undefined.nix +++ /dev/null @@ -1 +0,0 @@ -builtins.unsafeGetAttrPos "abort" builtins diff --git a/tests/lang/eval-okay-getattrpos.exp b/tests/lang/eval-okay-getattrpos.exp deleted file mode 100644 index 469249bbc..000000000 --- a/tests/lang/eval-okay-getattrpos.exp +++ /dev/null @@ -1 +0,0 @@ -{ column = 5; file = "eval-okay-getattrpos.nix"; line = 3; } diff --git a/tests/lang/eval-okay-getattrpos.nix b/tests/lang/eval-okay-getattrpos.nix deleted file mode 100644 index ca6b07961..000000000 --- a/tests/lang/eval-okay-getattrpos.nix +++ /dev/null @@ -1,6 +0,0 @@ -let - as = { - foo = "bar"; - }; - pos = builtins.unsafeGetAttrPos "foo" as; -in { inherit (pos) column line; file = baseNameOf pos.file; } diff --git a/tests/lang/eval-okay-getenv.exp b/tests/lang/eval-okay-getenv.exp deleted file mode 100644 index 14e24d419..000000000 --- a/tests/lang/eval-okay-getenv.exp +++ /dev/null @@ -1 +0,0 @@ -"foobar" diff --git a/tests/lang/eval-okay-getenv.nix b/tests/lang/eval-okay-getenv.nix deleted file mode 100644 index 4cfec5f55..000000000 --- a/tests/lang/eval-okay-getenv.nix +++ /dev/null @@ -1 +0,0 @@ -builtins.getEnv "TEST_VAR" + (if builtins.getEnv "NO_SUCH_VAR" == "" then "bar" else "bla") diff --git a/tests/lang/eval-okay-groupBy.exp b/tests/lang/eval-okay-groupBy.exp deleted file mode 100644 index bfca5652a..000000000 --- a/tests/lang/eval-okay-groupBy.exp +++ /dev/null @@ -1 +0,0 @@ -{ "1" = [ 9 ]; "2" = [ 8 ]; "3" = [ 13 29 ]; "4" = [ 3 4 10 11 17 18 ]; "5" = [ 0 23 26 28 ]; "6" = [ 1 12 21 27 30 ]; "7" = [ 7 22 ]; "8" = [ 14 ]; "9" = [ 19 ]; b = [ 16 25 ]; c = [ 24 ]; d = [ 2 ]; e = [ 5 6 15 31 ]; f = [ 20 ]; } diff --git a/tests/lang/eval-okay-groupBy.nix b/tests/lang/eval-okay-groupBy.nix deleted file mode 100644 index 862d89dbd..000000000 --- a/tests/lang/eval-okay-groupBy.nix +++ /dev/null @@ -1,5 +0,0 @@ -with import ./lib.nix; - -builtins.groupBy (n: - builtins.substring 0 1 (builtins.hashString "sha256" (toString n)) -) (range 0 31) diff --git a/tests/lang/eval-okay-hash.exp b/tests/lang/eval-okay-hash.exp deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/lang/eval-okay-hashfile.exp b/tests/lang/eval-okay-hashfile.exp deleted file mode 100644 index ff1e8293e..000000000 --- a/tests/lang/eval-okay-hashfile.exp +++ /dev/null @@ -1 +0,0 @@ -[ "d3b07384d113edec49eaa6238ad5ff00" "0f343b0931126a20f133d67c2b018a3b" "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15" "60cacbf3d72e1e7834203da608037b1bf83b40e8" "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c" "5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef" "0cf9180a764aba863a67b6d72f0918bc131c6772642cb2dce5a34f0a702f9470ddc2bf125c12198b1995c233c34b4afd346c54a2334c350a948a51b6e8b4e6b6" "8efb4f73c5655351c444eb109230c556d39e2c7624e9c11abc9e3fb4b9b9254218cc5085b454a9698d085cfa92198491f07a723be4574adc70617b73eb0b6461" ] diff --git a/tests/lang/eval-okay-hashfile.nix b/tests/lang/eval-okay-hashfile.nix deleted file mode 100644 index aff5a1856..000000000 --- a/tests/lang/eval-okay-hashfile.nix +++ /dev/null @@ -1,4 +0,0 @@ -let - paths = [ ./data ./binary-data ]; -in - builtins.concatLists (map (hash: map (builtins.hashFile hash) paths) ["md5" "sha1" "sha256" "sha512"]) diff --git a/tests/lang/eval-okay-hashstring.exp b/tests/lang/eval-okay-hashstring.exp deleted file mode 100644 index d720a082d..000000000 --- a/tests/lang/eval-okay-hashstring.exp +++ /dev/null @@ -1 +0,0 @@ -[ "d41d8cd98f00b204e9800998ecf8427e" "6c69ee7f211c640419d5366cc076ae46" "bb3438fbabd460ea6dbd27d153e2233b" "da39a3ee5e6b4b0d3255bfef95601890afd80709" "cd54e8568c1b37cf1e5badb0779bcbf382212189" "6d12e10b1d331dad210e47fd25d4f260802b7e77" "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" "900a4469df00ccbfd0c145c6d1e4b7953dd0afafadd7534e3a4019e8d38fc663" "ad0387b3bd8652f730ca46d25f9c170af0fd589f42e7f23f5a9e6412d97d7e56" "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" "9d0886f8c6b389398a16257bc79780fab9831c7fc11c8ab07fa732cb7b348feade382f92617c9c5305fefba0af02ab5fd39a587d330997ff5bd0db19f7666653" "21644b72aa259e5a588cd3afbafb1d4310f4889680f6c83b9d531596a5a284f34dbebff409d23bcc86aee6bad10c891606f075c6f4755cb536da27db5693f3a7" ] diff --git a/tests/lang/eval-okay-hashstring.nix b/tests/lang/eval-okay-hashstring.nix deleted file mode 100644 index b0f62b245..000000000 --- a/tests/lang/eval-okay-hashstring.nix +++ /dev/null @@ -1,4 +0,0 @@ -let - strings = [ "" "text 1" "text 2" ]; -in - builtins.concatLists (map (hash: map (builtins.hashString hash) strings) ["md5" "sha1" "sha256" "sha512"]) diff --git a/tests/lang/eval-okay-if.exp b/tests/lang/eval-okay-if.exp deleted file mode 100644 index 00750edc0..000000000 --- a/tests/lang/eval-okay-if.exp +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/tests/lang/eval-okay-if.nix b/tests/lang/eval-okay-if.nix deleted file mode 100644 index 23e4c74d5..000000000 --- a/tests/lang/eval-okay-if.nix +++ /dev/null @@ -1 +0,0 @@ -if "foo" != "f" + "oo" then 1 else if false then 2 else 3 diff --git a/tests/lang/eval-okay-import.exp b/tests/lang/eval-okay-import.exp deleted file mode 100644 index c508125b5..000000000 --- a/tests/lang/eval-okay-import.exp +++ /dev/null @@ -1 +0,0 @@ -[ 1 2 3 4 5 6 7 8 9 10 ] diff --git a/tests/lang/eval-okay-import.nix b/tests/lang/eval-okay-import.nix deleted file mode 100644 index 0b18d9413..000000000 --- a/tests/lang/eval-okay-import.nix +++ /dev/null @@ -1,11 +0,0 @@ -let - - overrides = { - import = fn: scopedImport overrides fn; - - scopedImport = attrs: fn: scopedImport (overrides // attrs) fn; - - builtins = builtins // overrides; - } // import ./lib.nix; - -in scopedImport overrides ./imported.nix diff --git a/tests/lang/eval-okay-ind-string.exp b/tests/lang/eval-okay-ind-string.exp deleted file mode 100644 index 7862331fa..000000000 --- a/tests/lang/eval-okay-ind-string.exp +++ /dev/null @@ -1 +0,0 @@ -"This is an indented multi-line string\nliteral. An amount of whitespace at\nthe start of each line matching the minimum\nindentation of all lines in the string\nliteral together will be removed. Thus,\nin this case four spaces will be\nstripped from each line, even though\n THIS LINE is indented six spaces.\n\nAlso, empty lines don't count in the\ndetermination of the indentation level (the\nprevious empty line has indentation 0, but\nit doesn't matter).\nIf the string starts with whitespace\n followed by a newline, it's stripped, but\n that's not the case here. Two spaces are\n stripped because of the \" \" at the start. \nThis line is indented\na bit further.\nAnti-quotations, like so, are\nalso allowed.\n The \\ is not special here.\n' can be followed by any character except another ', e.g. 'x'.\nLikewise for $, e.g. $$ or $varName.\nBut ' followed by ' is special, as is $ followed by {.\nIf you want them, use anti-quotations: '', \${.\n Tabs are not interpreted as whitespace (since we can't guess\n what tab settings are intended), so don't use them.\n\tThis line starts with a space and a tab, so only one\n space will be stripped from each line.\nAlso note that if the last line (just before the closing ' ')\nconsists only of whitespace, it's ignored. But here there is\nsome non-whitespace stuff, so the line isn't removed. \nThis shows a hacky way to preserve an empty line after the start.\nBut there's no reason to do so: you could just repeat the empty\nline.\n Similarly you can force an indentation level,\n in this case to 2 spaces. This works because the anti-quote\n is significant (not whitespace).\nstart on network-interfaces\n\nstart script\n\n rm -f /var/run/opengl-driver\n ln -sf 123 /var/run/opengl-driver\n\n rm -f /var/log/slim.log\n \nend script\n\nenv SLIM_CFGFILE=abc\nenv SLIM_THEMESDIR=def\nenv FONTCONFIG_FILE=/etc/fonts/fonts.conf \t\t\t\t# !!! cleanup\nenv XKB_BINDIR=foo/bin \t\t\t\t# Needed for the Xkb extension.\nenv LD_LIBRARY_PATH=libX11/lib:libXext/lib:/usr/lib/ # related to xorg-sys-opengl - needed to load libglx for (AI)GLX support (for compiz)\n\nenv XORG_DRI_DRIVER_PATH=nvidiaDrivers/X11R6/lib/modules/drivers/ \n\nexec slim/bin/slim\nEscaping of ' followed by ': ''\nEscaping of $ followed by {: \${\nAnd finally to interpret \\n etc. as in a string: \n, \r, \t.\nfoo\n'bla'\nbar\ncut -d $'\\t' -f 1\nending dollar $$\n" diff --git a/tests/lang/eval-okay-ind-string.nix b/tests/lang/eval-okay-ind-string.nix deleted file mode 100644 index 95d59b508..000000000 --- a/tests/lang/eval-okay-ind-string.nix +++ /dev/null @@ -1,128 +0,0 @@ -let - - s1 = '' - This is an indented multi-line string - literal. An amount of whitespace at - the start of each line matching the minimum - indentation of all lines in the string - literal together will be removed. Thus, - in this case four spaces will be - stripped from each line, even though - THIS LINE is indented six spaces. - - Also, empty lines don't count in the - determination of the indentation level (the - previous empty line has indentation 0, but - it doesn't matter). - ''; - - s2 = '' If the string starts with whitespace - followed by a newline, it's stripped, but - that's not the case here. Two spaces are - stripped because of the " " at the start. - ''; - - s3 = '' - This line is indented - a bit further. - ''; # indentation of last line doesn't count if it's empty - - s4 = '' - Anti-quotations, like ${if true then "so" else "not so"}, are - also allowed. - ''; - - s5 = '' - The \ is not special here. - ' can be followed by any character except another ', e.g. 'x'. - Likewise for $, e.g. $$ or $varName. - But ' followed by ' is special, as is $ followed by {. - If you want them, use anti-quotations: ${"''"}, ${"\${"}. - ''; - - s6 = '' - Tabs are not interpreted as whitespace (since we can't guess - what tab settings are intended), so don't use them. - This line starts with a space and a tab, so only one - space will be stripped from each line. - ''; - - s7 = '' - Also note that if the last line (just before the closing ' ') - consists only of whitespace, it's ignored. But here there is - some non-whitespace stuff, so the line isn't removed. ''; - - s8 = '' ${""} - This shows a hacky way to preserve an empty line after the start. - But there's no reason to do so: you could just repeat the empty - line. - ''; - - s9 = '' - ${""} Similarly you can force an indentation level, - in this case to 2 spaces. This works because the anti-quote - is significant (not whitespace). - ''; - - s10 = '' - ''; - - s11 = ''''; - - s12 = '' ''; - - s13 = '' - start on network-interfaces - - start script - - rm -f /var/run/opengl-driver - ${if true - then "ln -sf 123 /var/run/opengl-driver" - else if true - then "ln -sf 456 /var/run/opengl-driver" - else "" - } - - rm -f /var/log/slim.log - - end script - - env SLIM_CFGFILE=${"abc"} - env SLIM_THEMESDIR=${"def"} - env FONTCONFIG_FILE=/etc/fonts/fonts.conf # !!! cleanup - env XKB_BINDIR=${"foo"}/bin # Needed for the Xkb extension. - env LD_LIBRARY_PATH=${"libX11"}/lib:${"libXext"}/lib:/usr/lib/ # related to xorg-sys-opengl - needed to load libglx for (AI)GLX support (for compiz) - - ${if true - then "env XORG_DRI_DRIVER_PATH=${"nvidiaDrivers"}/X11R6/lib/modules/drivers/" - else if true - then "env XORG_DRI_DRIVER_PATH=${"mesa"}/lib/modules/dri" - else "" - } - - exec ${"slim"}/bin/slim - ''; - - s14 = '' - Escaping of ' followed by ': ''' - Escaping of $ followed by {: ''${ - And finally to interpret \n etc. as in a string: ''\n, ''\r, ''\t. - ''; - - # Regression test: string interpolation in '${x}' should work, but didn't. - s15 = let x = "bla"; in '' - foo - '${x}' - bar - ''; - - # Regression test: accept $'. - s16 = '' - cut -d $'\t' -f 1 - ''; - - # Accept dollars at end of strings - s17 = ''ending dollar $'' + ''$'' + "\n"; - -in s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10 + s11 + s12 + s13 + s14 + s15 + s16 + s17 diff --git a/tests/lang/eval-okay-intersectAttrs.exp b/tests/lang/eval-okay-intersectAttrs.exp deleted file mode 100644 index 50445bc0e..000000000 --- a/tests/lang/eval-okay-intersectAttrs.exp +++ /dev/null @@ -1 +0,0 @@ -[ { } { a = 1; } { a = 1; } { a = "a"; } { m = 1; } { m = "m"; } { n = 1; } { n = "n"; } { n = 1; p = 2; } { n = "n"; p = "p"; } { n = 1; p = 2; } { n = "n"; p = "p"; } { a = "a"; b = "b"; c = "c"; d = "d"; e = "e"; f = "f"; g = "g"; h = "h"; i = "i"; j = "j"; k = "k"; l = "l"; m = "m"; n = "n"; o = "o"; p = "p"; q = "q"; r = "r"; s = "s"; t = "t"; u = "u"; v = "v"; w = "w"; x = "x"; y = "y"; z = "z"; } true ] diff --git a/tests/lang/eval-okay-intersectAttrs.nix b/tests/lang/eval-okay-intersectAttrs.nix deleted file mode 100644 index 39d49938c..000000000 --- a/tests/lang/eval-okay-intersectAttrs.nix +++ /dev/null @@ -1,50 +0,0 @@ -let - alphabet = - { a = "a"; - b = "b"; - c = "c"; - d = "d"; - e = "e"; - f = "f"; - g = "g"; - h = "h"; - i = "i"; - j = "j"; - k = "k"; - l = "l"; - m = "m"; - n = "n"; - o = "o"; - p = "p"; - q = "q"; - r = "r"; - s = "s"; - t = "t"; - u = "u"; - v = "v"; - w = "w"; - x = "x"; - y = "y"; - z = "z"; - }; - foo = { - inherit (alphabet) f o b a r z q u x; - aa = throw "aa"; - }; - alphabetFail = builtins.mapAttrs throw alphabet; -in -[ (builtins.intersectAttrs { a = abort "l1"; } { b = abort "r1"; }) - (builtins.intersectAttrs { a = abort "l2"; } { a = 1; }) - (builtins.intersectAttrs alphabetFail { a = 1; }) - (builtins.intersectAttrs { a = abort "laa"; } alphabet) - (builtins.intersectAttrs alphabetFail { m = 1; }) - (builtins.intersectAttrs { m = abort "lam"; } alphabet) - (builtins.intersectAttrs alphabetFail { n = 1; }) - (builtins.intersectAttrs { n = abort "lan"; } alphabet) - (builtins.intersectAttrs alphabetFail { n = 1; p = 2; }) - (builtins.intersectAttrs { n = abort "lan2"; p = abort "lap"; } alphabet) - (builtins.intersectAttrs alphabetFail { n = 1; p = 2; }) - (builtins.intersectAttrs { n = abort "lan2"; p = abort "lap"; } alphabet) - (builtins.intersectAttrs alphabetFail alphabet) - (builtins.intersectAttrs alphabet foo == builtins.intersectAttrs foo alphabet) -] diff --git a/tests/lang/eval-okay-let.exp b/tests/lang/eval-okay-let.exp deleted file mode 100644 index 14e24d419..000000000 --- a/tests/lang/eval-okay-let.exp +++ /dev/null @@ -1 +0,0 @@ -"foobar" diff --git a/tests/lang/eval-okay-let.nix b/tests/lang/eval-okay-let.nix deleted file mode 100644 index fe118c528..000000000 --- a/tests/lang/eval-okay-let.nix +++ /dev/null @@ -1,5 +0,0 @@ -let { - x = "foo"; - y = "bar"; - body = x + y; -} diff --git a/tests/lang/eval-okay-list.exp b/tests/lang/eval-okay-list.exp deleted file mode 100644 index f784f26d8..000000000 --- a/tests/lang/eval-okay-list.exp +++ /dev/null @@ -1 +0,0 @@ -"foobarblatest" diff --git a/tests/lang/eval-okay-list.nix b/tests/lang/eval-okay-list.nix deleted file mode 100644 index d433bcf90..000000000 --- a/tests/lang/eval-okay-list.nix +++ /dev/null @@ -1,7 +0,0 @@ -with import ./lib.nix; - -let { - - body = concat ["foo" "bar" "bla" "test"]; - -} \ No newline at end of file diff --git a/tests/lang/eval-okay-listtoattrs.exp b/tests/lang/eval-okay-listtoattrs.exp deleted file mode 100644 index 74abef7bc..000000000 --- a/tests/lang/eval-okay-listtoattrs.exp +++ /dev/null @@ -1 +0,0 @@ -"AAbar" diff --git a/tests/lang/eval-okay-listtoattrs.nix b/tests/lang/eval-okay-listtoattrs.nix deleted file mode 100644 index 4186e029b..000000000 --- a/tests/lang/eval-okay-listtoattrs.nix +++ /dev/null @@ -1,11 +0,0 @@ -# this test shows how to use listToAttrs and that evaluation is still lazy (throw isn't called) -with import ./lib.nix; - -let - asi = name: value : { inherit name value; }; - list = [ ( asi "a" "A" ) ( asi "b" "B" ) ]; - a = builtins.listToAttrs list; - b = builtins.listToAttrs ( list ++ list ); - r = builtins.listToAttrs [ (asi "result" [ a b ]) ( asi "throw" (throw "this should not be thrown")) ]; - x = builtins.listToAttrs [ (asi "foo" "bar") (asi "foo" "bla") ]; -in concat (map (x: x.a) r.result) + x.foo diff --git a/tests/lang/eval-okay-logic.exp b/tests/lang/eval-okay-logic.exp deleted file mode 100644 index d00491fd7..000000000 --- a/tests/lang/eval-okay-logic.exp +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/tests/lang/eval-okay-logic.nix b/tests/lang/eval-okay-logic.nix deleted file mode 100644 index fbb127944..000000000 --- a/tests/lang/eval-okay-logic.nix +++ /dev/null @@ -1 +0,0 @@ -assert !false && (true || false) -> true; 1 diff --git a/tests/lang/eval-okay-map.exp b/tests/lang/eval-okay-map.exp deleted file mode 100644 index dbb64f717..000000000 --- a/tests/lang/eval-okay-map.exp +++ /dev/null @@ -1 +0,0 @@ -"foobarblabarxyzzybar" diff --git a/tests/lang/eval-okay-map.nix b/tests/lang/eval-okay-map.nix deleted file mode 100644 index a76c1d811..000000000 --- a/tests/lang/eval-okay-map.nix +++ /dev/null @@ -1,3 +0,0 @@ -with import ./lib.nix; - -concat (map (x: x + "bar") [ "foo" "bla" "xyzzy" ]) \ No newline at end of file diff --git a/tests/lang/eval-okay-mapattrs.exp b/tests/lang/eval-okay-mapattrs.exp deleted file mode 100644 index 3f113f17b..000000000 --- a/tests/lang/eval-okay-mapattrs.exp +++ /dev/null @@ -1 +0,0 @@ -{ x = "x-foo"; y = "y-bar"; } diff --git a/tests/lang/eval-okay-mapattrs.nix b/tests/lang/eval-okay-mapattrs.nix deleted file mode 100644 index f075b6275..000000000 --- a/tests/lang/eval-okay-mapattrs.nix +++ /dev/null @@ -1,3 +0,0 @@ -with import ./lib.nix; - -builtins.mapAttrs (name: value: name + "-" + value) { x = "foo"; y = "bar"; } diff --git a/tests/lang/eval-okay-merge-dynamic-attrs.exp b/tests/lang/eval-okay-merge-dynamic-attrs.exp deleted file mode 100644 index 157d677ce..000000000 --- a/tests/lang/eval-okay-merge-dynamic-attrs.exp +++ /dev/null @@ -1 +0,0 @@ -{ set1 = { a = 1; b = 2; }; set2 = { a = 1; b = 2; }; set3 = { a = 1; b = 2; }; set4 = { a = 1; b = 2; }; } diff --git a/tests/lang/eval-okay-merge-dynamic-attrs.nix b/tests/lang/eval-okay-merge-dynamic-attrs.nix deleted file mode 100644 index f459a554f..000000000 --- a/tests/lang/eval-okay-merge-dynamic-attrs.nix +++ /dev/null @@ -1,13 +0,0 @@ -{ - set1 = { a = 1; }; - set1 = { "${"b" + ""}" = 2; }; - - set2 = { "${"b" + ""}" = 2; }; - set2 = { a = 1; }; - - set3.a = 1; - set3."${"b" + ""}" = 2; - - set4."${"b" + ""}" = 2; - set4.a = 1; -} diff --git a/tests/lang/eval-okay-nested-with.exp b/tests/lang/eval-okay-nested-with.exp deleted file mode 100644 index 0cfbf0888..000000000 --- a/tests/lang/eval-okay-nested-with.exp +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/tests/lang/eval-okay-nested-with.nix b/tests/lang/eval-okay-nested-with.nix deleted file mode 100644 index ba9d79aa7..000000000 --- a/tests/lang/eval-okay-nested-with.nix +++ /dev/null @@ -1,3 +0,0 @@ -with { x = 1; }; -with { x = 2; }; -x diff --git a/tests/lang/eval-okay-new-let.exp b/tests/lang/eval-okay-new-let.exp deleted file mode 100644 index f98b38807..000000000 --- a/tests/lang/eval-okay-new-let.exp +++ /dev/null @@ -1 +0,0 @@ -"xyzzyfoobar" diff --git a/tests/lang/eval-okay-new-let.nix b/tests/lang/eval-okay-new-let.nix deleted file mode 100644 index 738123141..000000000 --- a/tests/lang/eval-okay-new-let.nix +++ /dev/null @@ -1,14 +0,0 @@ -let - - f = z: - - let - x = "foo"; - y = "bar"; - body = 1; # compat test - in - z + x + y; - - arg = "xyzzy"; - -in f arg diff --git a/tests/lang/eval-okay-null-dynamic-attrs.exp b/tests/lang/eval-okay-null-dynamic-attrs.exp deleted file mode 100644 index 27ba77dda..000000000 --- a/tests/lang/eval-okay-null-dynamic-attrs.exp +++ /dev/null @@ -1 +0,0 @@ -true diff --git a/tests/lang/eval-okay-null-dynamic-attrs.nix b/tests/lang/eval-okay-null-dynamic-attrs.nix deleted file mode 100644 index b060c0bc9..000000000 --- a/tests/lang/eval-okay-null-dynamic-attrs.nix +++ /dev/null @@ -1 +0,0 @@ -{ ${null} = true; } == {} diff --git a/tests/lang/eval-okay-overrides.exp b/tests/lang/eval-okay-overrides.exp deleted file mode 100644 index 0cfbf0888..000000000 --- a/tests/lang/eval-okay-overrides.exp +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/tests/lang/eval-okay-overrides.nix b/tests/lang/eval-okay-overrides.nix deleted file mode 100644 index 719bdc9c0..000000000 --- a/tests/lang/eval-okay-overrides.nix +++ /dev/null @@ -1,9 +0,0 @@ -let - - overrides = { a = 2; b = 3; }; - -in (rec { - __overrides = overrides; - x = a; - a = 1; -}).x diff --git a/tests/lang/eval-okay-parse-flake-ref.exp b/tests/lang/eval-okay-parse-flake-ref.exp deleted file mode 100644 index fc17ba085..000000000 --- a/tests/lang/eval-okay-parse-flake-ref.exp +++ /dev/null @@ -1 +0,0 @@ -{ dir = "lib"; owner = "NixOS"; ref = "23.05"; repo = "nixpkgs"; type = "github"; } diff --git a/tests/lang/eval-okay-parse-flake-ref.nix b/tests/lang/eval-okay-parse-flake-ref.nix deleted file mode 100644 index db4ed2742..000000000 --- a/tests/lang/eval-okay-parse-flake-ref.nix +++ /dev/null @@ -1 +0,0 @@ - builtins.parseFlakeRef "github:NixOS/nixpkgs/23.05?dir=lib" diff --git a/tests/lang/eval-okay-partition.exp b/tests/lang/eval-okay-partition.exp deleted file mode 100644 index cd8b8b020..000000000 --- a/tests/lang/eval-okay-partition.exp +++ /dev/null @@ -1 +0,0 @@ -{ right = [ 0 2 4 6 8 10 100 102 104 106 108 110 ]; wrong = [ 1 3 5 7 9 101 103 105 107 109 ]; } diff --git a/tests/lang/eval-okay-partition.nix b/tests/lang/eval-okay-partition.nix deleted file mode 100644 index 846d2ce49..000000000 --- a/tests/lang/eval-okay-partition.nix +++ /dev/null @@ -1,5 +0,0 @@ -with import ./lib.nix; - -builtins.partition - (x: x / 2 * 2 == x) - (builtins.concatLists [ (range 0 10) (range 100 110) ]) diff --git a/tests/lang/eval-okay-path-string-interpolation.exp b/tests/lang/eval-okay-path-string-interpolation.exp deleted file mode 100644 index 5b8ea0243..000000000 --- a/tests/lang/eval-okay-path-string-interpolation.exp +++ /dev/null @@ -1 +0,0 @@ -{ absolute = /foo; expr = /pwd/lang/foo/bar; home = /fake-home/foo; notfirst = /pwd/lang/bar/foo; simple = /pwd/lang/foo; slashes = /foo/bar; surrounded = /pwd/lang/a-foo-b; } diff --git a/tests/lang/eval-okay-path-string-interpolation.nix b/tests/lang/eval-okay-path-string-interpolation.nix deleted file mode 100644 index 497d7c1c7..000000000 --- a/tests/lang/eval-okay-path-string-interpolation.nix +++ /dev/null @@ -1,12 +0,0 @@ -let - foo = "foo"; -in -{ - simple = ./${foo}; - surrounded = ./a-${foo}-b; - absolute = /${foo}; - expr = ./${foo + "/bar"}; - home = ~/${foo}; - notfirst = ./bar/${foo}; - slashes = /${foo}/${"bar"}; -} diff --git a/tests/lang/eval-okay-path.exp b/tests/lang/eval-okay-path.exp deleted file mode 100644 index 3ce7f8283..000000000 --- a/tests/lang/eval-okay-path.exp +++ /dev/null @@ -1 +0,0 @@ -"/nix/store/ya937r4ydw0l6kayq8jkyqaips9c75jm-output" diff --git a/tests/lang/eval-okay-path.nix b/tests/lang/eval-okay-path.nix deleted file mode 100644 index e67168cf3..000000000 --- a/tests/lang/eval-okay-path.nix +++ /dev/null @@ -1,7 +0,0 @@ -builtins.path - { path = ./.; - filter = path: _: baseNameOf path == "data"; - recursive = true; - sha256 = "1yhm3gwvg5a41yylymgblsclk95fs6jy72w0wv925mmidlhcq4sw"; - name = "output"; - } diff --git a/tests/lang/eval-okay-pathexists.exp b/tests/lang/eval-okay-pathexists.exp deleted file mode 100644 index 27ba77dda..000000000 --- a/tests/lang/eval-okay-pathexists.exp +++ /dev/null @@ -1 +0,0 @@ -true diff --git a/tests/lang/eval-okay-pathexists.nix b/tests/lang/eval-okay-pathexists.nix deleted file mode 100644 index c5e7a62de..000000000 --- a/tests/lang/eval-okay-pathexists.nix +++ /dev/null @@ -1,29 +0,0 @@ -builtins.pathExists (./lib.nix) -&& builtins.pathExists (builtins.toPath ./lib.nix) -&& builtins.pathExists (builtins.toString ./lib.nix) -&& !builtins.pathExists (builtins.toString ./lib.nix + "/") -&& !builtins.pathExists (builtins.toString ./lib.nix + "/.") -# FIXME -# && !builtins.pathExists (builtins.toString ./lib.nix + "/..") -# && !builtins.pathExists (builtins.toString ./lib.nix + "/a/..") -# && !builtins.pathExists (builtins.toString ./lib.nix + "/../lib.nix") -&& !builtins.pathExists (builtins.toString ./lib.nix + "/./") -&& !builtins.pathExists (builtins.toString ./lib.nix + "/./.") -&& builtins.pathExists (builtins.toString ./.. + "/lang/lib.nix") -&& !builtins.pathExists (builtins.toString ./.. + "lang/lib.nix") -&& builtins.pathExists (builtins.toString ./. + "/../lang/lib.nix") -&& builtins.pathExists (builtins.toString ./. + "/../lang/./lib.nix") -&& builtins.pathExists (builtins.toString ./.) -&& builtins.pathExists (builtins.toString ./. + "/") -&& builtins.pathExists (builtins.toString ./. + "/../lang") -&& builtins.pathExists (builtins.toString ./. + "/../lang/") -&& builtins.pathExists (builtins.toString ./. + "/../lang/.") -&& builtins.pathExists (builtins.toString ./. + "/../lang/./") -&& builtins.pathExists (builtins.toString ./. + "/../lang//./") -&& builtins.pathExists (builtins.toString ./. + "/../lang/..") -&& builtins.pathExists (builtins.toString ./. + "/../lang/../") -&& builtins.pathExists (builtins.toString ./. + "/../lang/..//") -&& builtins.pathExists (builtins.toPath (builtins.toString ./lib.nix)) -&& !builtins.pathExists (builtins.toPath (builtins.toString ./bla.nix)) -&& builtins.pathExists ./lib.nix -&& !builtins.pathExists ./bla.nix diff --git a/tests/lang/eval-okay-patterns.exp b/tests/lang/eval-okay-patterns.exp deleted file mode 100644 index a4304010f..000000000 --- a/tests/lang/eval-okay-patterns.exp +++ /dev/null @@ -1 +0,0 @@ -"abcxyzDDDDEFijk" diff --git a/tests/lang/eval-okay-patterns.nix b/tests/lang/eval-okay-patterns.nix deleted file mode 100644 index 96fd25a01..000000000 --- a/tests/lang/eval-okay-patterns.nix +++ /dev/null @@ -1,16 +0,0 @@ -let - - f = args@{x, y, z}: x + args.y + z; - - g = {x, y, z}@args: f args; - - h = {x ? "d", y ? x, z ? args.x}@args: x + y + z; - - j = {x, y, z, ...}: x + y + z; - -in - f {x = "a"; y = "b"; z = "c";} + - g {x = "x"; y = "y"; z = "z";} + - h {x = "D";} + - h {x = "D"; y = "E"; z = "F";} + - j {x = "i"; y = "j"; z = "k"; bla = "bla"; foo = "bar";} diff --git a/tests/lang/eval-okay-print.err.exp b/tests/lang/eval-okay-print.err.exp deleted file mode 100644 index 3fc99be3e..000000000 --- a/tests/lang/eval-okay-print.err.exp +++ /dev/null @@ -1 +0,0 @@ -trace: [ ] diff --git a/tests/lang/eval-okay-print.exp b/tests/lang/eval-okay-print.exp deleted file mode 100644 index 0d960fb70..000000000 --- a/tests/lang/eval-okay-print.exp +++ /dev/null @@ -1 +0,0 @@ -[ null [ [ «repeated» ] ] ] diff --git a/tests/lang/eval-okay-print.nix b/tests/lang/eval-okay-print.nix deleted file mode 100644 index d36ba4da3..000000000 --- a/tests/lang/eval-okay-print.nix +++ /dev/null @@ -1 +0,0 @@ -with builtins; trace [(1+1)] [ null toString (deepSeq "x") (a: a) (let x=[x]; in x) ] diff --git a/tests/lang/eval-okay-readDir.exp b/tests/lang/eval-okay-readDir.exp deleted file mode 100644 index 6413f6d4f..000000000 --- a/tests/lang/eval-okay-readDir.exp +++ /dev/null @@ -1 +0,0 @@ -{ bar = "regular"; foo = "directory"; ldir = "symlink"; linked = "symlink"; } diff --git a/tests/lang/eval-okay-readDir.nix b/tests/lang/eval-okay-readDir.nix deleted file mode 100644 index a7ec9292a..000000000 --- a/tests/lang/eval-okay-readDir.nix +++ /dev/null @@ -1 +0,0 @@ -builtins.readDir ./readDir diff --git a/tests/lang/eval-okay-readFileType.exp b/tests/lang/eval-okay-readFileType.exp deleted file mode 100644 index 6413f6d4f..000000000 --- a/tests/lang/eval-okay-readFileType.exp +++ /dev/null @@ -1 +0,0 @@ -{ bar = "regular"; foo = "directory"; ldir = "symlink"; linked = "symlink"; } diff --git a/tests/lang/eval-okay-readFileType.nix b/tests/lang/eval-okay-readFileType.nix deleted file mode 100644 index 174fb6c3a..000000000 --- a/tests/lang/eval-okay-readFileType.nix +++ /dev/null @@ -1,6 +0,0 @@ -{ - bar = builtins.readFileType ./readDir/bar; - foo = builtins.readFileType ./readDir/foo; - linked = builtins.readFileType ./readDir/linked; - ldir = builtins.readFileType ./readDir/ldir; -} diff --git a/tests/lang/eval-okay-readfile.exp b/tests/lang/eval-okay-readfile.exp deleted file mode 100644 index a2c87d0c4..000000000 --- a/tests/lang/eval-okay-readfile.exp +++ /dev/null @@ -1 +0,0 @@ -"builtins.readFile ./eval-okay-readfile.nix\n" diff --git a/tests/lang/eval-okay-readfile.nix b/tests/lang/eval-okay-readfile.nix deleted file mode 100644 index 82f7cb174..000000000 --- a/tests/lang/eval-okay-readfile.nix +++ /dev/null @@ -1 +0,0 @@ -builtins.readFile ./eval-okay-readfile.nix diff --git a/tests/lang/eval-okay-redefine-builtin.exp b/tests/lang/eval-okay-redefine-builtin.exp deleted file mode 100644 index c508d5366..000000000 --- a/tests/lang/eval-okay-redefine-builtin.exp +++ /dev/null @@ -1 +0,0 @@ -false diff --git a/tests/lang/eval-okay-redefine-builtin.nix b/tests/lang/eval-okay-redefine-builtin.nix deleted file mode 100644 index df9fc3f37..000000000 --- a/tests/lang/eval-okay-redefine-builtin.nix +++ /dev/null @@ -1,3 +0,0 @@ -let - throw = abort "Error!"; -in (builtins.tryEval ).success diff --git a/tests/lang/eval-okay-regex-match.exp b/tests/lang/eval-okay-regex-match.exp deleted file mode 100644 index 27ba77dda..000000000 --- a/tests/lang/eval-okay-regex-match.exp +++ /dev/null @@ -1 +0,0 @@ -true diff --git a/tests/lang/eval-okay-regex-match.nix b/tests/lang/eval-okay-regex-match.nix deleted file mode 100644 index 273e25907..000000000 --- a/tests/lang/eval-okay-regex-match.nix +++ /dev/null @@ -1,29 +0,0 @@ -with builtins; - -let - - matches = pat: s: match pat s != null; - - splitFN = match "((.*)/)?([^/]*)\\.(nix|cc)"; - -in - -assert matches "foobar" "foobar"; -assert matches "fo*" "f"; -assert !matches "fo+" "f"; -assert matches "fo*" "fo"; -assert matches "fo*" "foo"; -assert matches "fo+" "foo"; -assert matches "fo{1,2}" "foo"; -assert !matches "fo{1,2}" "fooo"; -assert !matches "fo*" "foobar"; -assert matches "[[:space:]]+([^[:space:]]+)[[:space:]]+" " foo "; -assert !matches "[[:space:]]+([[:upper:]]+)[[:space:]]+" " foo "; - -assert match "(.*)\\.nix" "foobar.nix" == [ "foobar" ]; -assert match "[[:space:]]+([[:upper:]]+)[[:space:]]+" " FOO " == [ "FOO" ]; - -assert splitFN "/path/to/foobar.nix" == [ "/path/to/" "/path/to" "foobar" "nix" ]; -assert splitFN "foobar.cc" == [ null null "foobar" "cc" ]; - -true diff --git a/tests/lang/eval-okay-regex-split.exp b/tests/lang/eval-okay-regex-split.exp deleted file mode 100644 index 27ba77dda..000000000 --- a/tests/lang/eval-okay-regex-split.exp +++ /dev/null @@ -1 +0,0 @@ -true diff --git a/tests/lang/eval-okay-regex-split.nix b/tests/lang/eval-okay-regex-split.nix deleted file mode 100644 index 0073e0577..000000000 --- a/tests/lang/eval-okay-regex-split.nix +++ /dev/null @@ -1,48 +0,0 @@ -with builtins; - -# Non capturing regex returns empty lists -assert split "foobar" "foobar" == ["" [] ""]; -assert split "fo*" "f" == ["" [] ""]; -assert split "fo+" "f" == ["f"]; -assert split "fo*" "fo" == ["" [] ""]; -assert split "fo*" "foo" == ["" [] ""]; -assert split "fo+" "foo" == ["" [] ""]; -assert split "fo{1,2}" "foo" == ["" [] ""]; -assert split "fo{1,2}" "fooo" == ["" [] "o"]; -assert split "fo*" "foobar" == ["" [] "bar"]; - -# Capturing regex returns a list of sub-matches -assert split "(fo*)" "f" == ["" ["f"] ""]; -assert split "(fo+)" "f" == ["f"]; -assert split "(fo*)" "fo" == ["" ["fo"] ""]; -assert split "(f)(o*)" "f" == ["" ["f" ""] ""]; -assert split "(f)(o*)" "foo" == ["" ["f" "oo"] ""]; -assert split "(fo+)" "foo" == ["" ["foo"] ""]; -assert split "(fo{1,2})" "foo" == ["" ["foo"] ""]; -assert split "(fo{1,2})" "fooo" == ["" ["foo"] "o"]; -assert split "(fo*)" "foobar" == ["" ["foo"] "bar"]; - -# Matches are greedy. -assert split "(o+)" "oooofoooo" == ["" ["oooo"] "f" ["oooo"] ""]; - -# Matches multiple times. -assert split "(b)" "foobarbaz" == ["foo" ["b"] "ar" ["b"] "az"]; - -# Split large strings containing newlines. null are inserted when a -# pattern within the current did not match anything. -assert split "[[:space:]]+|([',.!?])" '' - Nix Rocks! - That's why I use it. -'' == [ - "Nix" [ null ] "Rocks" ["!"] "" [ null ] - "That" ["'"] "s" [ null ] "why" [ null ] "I" [ null ] "use" [ null ] "it" ["."] "" [ null ] - "" -]; - -# Documentation examples -assert split "(a)b" "abc" == [ "" [ "a" ] "c" ]; -assert split "([ac])" "abc" == [ "" [ "a" ] "b" [ "c" ] "" ]; -assert split "(a)|(c)" "abc" == [ "" [ "a" null ] "b" [ null "c" ] "" ]; -assert split "([[:upper:]]+)" " FOO " == [ " " [ "FOO" ] " " ]; - -true diff --git a/tests/lang/eval-okay-regression-20220122.exp b/tests/lang/eval-okay-regression-20220122.exp deleted file mode 100644 index 00750edc0..000000000 --- a/tests/lang/eval-okay-regression-20220122.exp +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/tests/lang/eval-okay-regression-20220122.nix b/tests/lang/eval-okay-regression-20220122.nix deleted file mode 100644 index 694e9a13b..000000000 --- a/tests/lang/eval-okay-regression-20220122.nix +++ /dev/null @@ -1 +0,0 @@ -((_: _) 1) + ((__: __) 2) diff --git a/tests/lang/eval-okay-regression-20220125.exp b/tests/lang/eval-okay-regression-20220125.exp deleted file mode 100644 index 00750edc0..000000000 --- a/tests/lang/eval-okay-regression-20220125.exp +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/tests/lang/eval-okay-regression-20220125.nix b/tests/lang/eval-okay-regression-20220125.nix deleted file mode 100644 index 485502373..000000000 --- a/tests/lang/eval-okay-regression-20220125.nix +++ /dev/null @@ -1,2 +0,0 @@ -((__curPosFoo: __curPosFoo) 1) + ((__curPosBar: __curPosBar) 2) - diff --git a/tests/lang/eval-okay-remove.exp b/tests/lang/eval-okay-remove.exp deleted file mode 100644 index 8d38505c1..000000000 --- a/tests/lang/eval-okay-remove.exp +++ /dev/null @@ -1 +0,0 @@ -456 diff --git a/tests/lang/eval-okay-remove.nix b/tests/lang/eval-okay-remove.nix deleted file mode 100644 index 4ad5ba897..000000000 --- a/tests/lang/eval-okay-remove.nix +++ /dev/null @@ -1,5 +0,0 @@ -let { - attrs = {x = 123; y = 456;}; - - body = (removeAttrs attrs ["x"]).y; -} \ No newline at end of file diff --git a/tests/lang/eval-okay-replacestrings.exp b/tests/lang/eval-okay-replacestrings.exp deleted file mode 100644 index eac67c5fe..000000000 --- a/tests/lang/eval-okay-replacestrings.exp +++ /dev/null @@ -1 +0,0 @@ -[ "faabar" "fbar" "fubar" "faboor" "fubar" "XaXbXcX" "X" "a_b" "fubar" ] diff --git a/tests/lang/eval-okay-replacestrings.nix b/tests/lang/eval-okay-replacestrings.nix deleted file mode 100644 index a803e6519..000000000 --- a/tests/lang/eval-okay-replacestrings.nix +++ /dev/null @@ -1,12 +0,0 @@ -with builtins; - -[ (replaceStrings ["o"] ["a"] "foobar") - (replaceStrings ["o"] [""] "foobar") - (replaceStrings ["oo"] ["u"] "foobar") - (replaceStrings ["oo" "a"] ["a" "oo"] "foobar") - (replaceStrings ["oo" "oo"] ["u" "i"] "foobar") - (replaceStrings [""] ["X"] "abc") - (replaceStrings [""] ["X"] "") - (replaceStrings ["-"] ["_"] "a-b") - (replaceStrings ["oo" "XX"] ["u" (throw "unreachable")] "foobar") -] diff --git a/tests/lang/eval-okay-scope-1.exp b/tests/lang/eval-okay-scope-1.exp deleted file mode 100644 index 00750edc0..000000000 --- a/tests/lang/eval-okay-scope-1.exp +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/tests/lang/eval-okay-scope-1.nix b/tests/lang/eval-okay-scope-1.nix deleted file mode 100644 index fa38a7174..000000000 --- a/tests/lang/eval-okay-scope-1.nix +++ /dev/null @@ -1,6 +0,0 @@ -(({x}: x: - - { x = 1; - y = x; - } -) {x = 2;} 3).y diff --git a/tests/lang/eval-okay-scope-2.exp b/tests/lang/eval-okay-scope-2.exp deleted file mode 100644 index d00491fd7..000000000 --- a/tests/lang/eval-okay-scope-2.exp +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/tests/lang/eval-okay-scope-2.nix b/tests/lang/eval-okay-scope-2.nix deleted file mode 100644 index eb8b02bc4..000000000 --- a/tests/lang/eval-okay-scope-2.nix +++ /dev/null @@ -1,6 +0,0 @@ -((x: {x}: - rec { - x = 1; - y = x; - } -) 2 {x = 3;}).y diff --git a/tests/lang/eval-okay-scope-3.exp b/tests/lang/eval-okay-scope-3.exp deleted file mode 100644 index b8626c4cf..000000000 --- a/tests/lang/eval-okay-scope-3.exp +++ /dev/null @@ -1 +0,0 @@ -4 diff --git a/tests/lang/eval-okay-scope-3.nix b/tests/lang/eval-okay-scope-3.nix deleted file mode 100644 index 10d6bc04d..000000000 --- a/tests/lang/eval-okay-scope-3.nix +++ /dev/null @@ -1,6 +0,0 @@ -((x: as: {x}: - rec { - inherit (as) x; - y = x; - } -) 2 {x = 4;} {x = 3;}).y diff --git a/tests/lang/eval-okay-scope-4.exp b/tests/lang/eval-okay-scope-4.exp deleted file mode 100644 index 00ff03a46..000000000 --- a/tests/lang/eval-okay-scope-4.exp +++ /dev/null @@ -1 +0,0 @@ -"ccdd" diff --git a/tests/lang/eval-okay-scope-4.nix b/tests/lang/eval-okay-scope-4.nix deleted file mode 100644 index dc8243bc8..000000000 --- a/tests/lang/eval-okay-scope-4.nix +++ /dev/null @@ -1,10 +0,0 @@ -let { - - x = "a"; - y = "b"; - - f = {x ? y, y ? x}: x + y; - - body = f {x = "c";} + f {y = "d";}; - -} diff --git a/tests/lang/eval-okay-scope-6.exp b/tests/lang/eval-okay-scope-6.exp deleted file mode 100644 index 00ff03a46..000000000 --- a/tests/lang/eval-okay-scope-6.exp +++ /dev/null @@ -1 +0,0 @@ -"ccdd" diff --git a/tests/lang/eval-okay-scope-6.nix b/tests/lang/eval-okay-scope-6.nix deleted file mode 100644 index 0995d4e7e..000000000 --- a/tests/lang/eval-okay-scope-6.nix +++ /dev/null @@ -1,7 +0,0 @@ -let { - - f = {x ? y, y ? x}: x + y; - - body = f {x = "c";} + f {y = "d";}; - -} diff --git a/tests/lang/eval-okay-scope-7.exp b/tests/lang/eval-okay-scope-7.exp deleted file mode 100644 index d00491fd7..000000000 --- a/tests/lang/eval-okay-scope-7.exp +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/tests/lang/eval-okay-scope-7.nix b/tests/lang/eval-okay-scope-7.nix deleted file mode 100644 index 4da02968f..000000000 --- a/tests/lang/eval-okay-scope-7.nix +++ /dev/null @@ -1,6 +0,0 @@ -rec { - inherit (x) y; - x = { - y = 1; - }; -}.y diff --git a/tests/lang/eval-okay-search-path.exp b/tests/lang/eval-okay-search-path.exp deleted file mode 100644 index 4519bc406..000000000 --- a/tests/lang/eval-okay-search-path.exp +++ /dev/null @@ -1 +0,0 @@ -"abccX" diff --git a/tests/lang/eval-okay-search-path.flags b/tests/lang/eval-okay-search-path.flags deleted file mode 100644 index dfad1c611..000000000 --- a/tests/lang/eval-okay-search-path.flags +++ /dev/null @@ -1 +0,0 @@ --I lang/dir1 -I lang/dir2 -I dir5=lang/dir3 diff --git a/tests/lang/eval-okay-search-path.nix b/tests/lang/eval-okay-search-path.nix deleted file mode 100644 index 6fe33decc..000000000 --- a/tests/lang/eval-okay-search-path.nix +++ /dev/null @@ -1,10 +0,0 @@ -with import ./lib.nix; -with builtins; - -assert isFunction (import ); - -assert length __nixPath == 5; -assert length (filter (x: baseNameOf x.path == "dir4") __nixPath) == 1; - -import + import + import + import - + (let __nixPath = [ { path = ./dir2; } { path = ./dir1; } ]; in import ) diff --git a/tests/lang/eval-okay-seq.exp b/tests/lang/eval-okay-seq.exp deleted file mode 100644 index 0cfbf0888..000000000 --- a/tests/lang/eval-okay-seq.exp +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/tests/lang/eval-okay-seq.nix b/tests/lang/eval-okay-seq.nix deleted file mode 100644 index 0a9a21c03..000000000 --- a/tests/lang/eval-okay-seq.nix +++ /dev/null @@ -1 +0,0 @@ -builtins.seq 1 2 diff --git a/tests/lang/eval-okay-sort.exp b/tests/lang/eval-okay-sort.exp deleted file mode 100644 index 899119e20..000000000 --- a/tests/lang/eval-okay-sort.exp +++ /dev/null @@ -1 +0,0 @@ -[ [ 42 77 147 249 483 526 ] [ 526 483 249 147 77 42 ] [ "bar" "fnord" "foo" "xyzzy" ] [ { key = 1; value = "foo"; } { key = 1; value = "fnord"; } { key = 2; value = "bar"; } ] [ [ ] [ ] [ 1 ] [ 1 4 ] [ 1 5 ] [ 1 6 ] [ 2 ] [ 2 3 ] [ 3 ] [ 3 ] ] ] diff --git a/tests/lang/eval-okay-sort.nix b/tests/lang/eval-okay-sort.nix deleted file mode 100644 index 50aa78e40..000000000 --- a/tests/lang/eval-okay-sort.nix +++ /dev/null @@ -1,20 +0,0 @@ -with builtins; - -[ (sort lessThan [ 483 249 526 147 42 77 ]) - (sort (x: y: y < x) [ 483 249 526 147 42 77 ]) - (sort lessThan [ "foo" "bar" "xyzzy" "fnord" ]) - (sort (x: y: x.key < y.key) - [ { key = 1; value = "foo"; } { key = 2; value = "bar"; } { key = 1; value = "fnord"; } ]) - (sort lessThan [ - [ 1 6 ] - [ ] - [ 2 3 ] - [ 3 ] - [ 1 5 ] - [ 2 ] - [ 1 ] - [ ] - [ 1 4 ] - [ 3 ] - ]) -] diff --git a/tests/lang/eval-okay-splitversion.exp b/tests/lang/eval-okay-splitversion.exp deleted file mode 100644 index 153ceb818..000000000 --- a/tests/lang/eval-okay-splitversion.exp +++ /dev/null @@ -1 +0,0 @@ -[ "1" "2" "3" ] diff --git a/tests/lang/eval-okay-splitversion.nix b/tests/lang/eval-okay-splitversion.nix deleted file mode 100644 index 9e5c99d2e..000000000 --- a/tests/lang/eval-okay-splitversion.nix +++ /dev/null @@ -1 +0,0 @@ -builtins.splitVersion "1.2.3" diff --git a/tests/lang/eval-okay-string.exp b/tests/lang/eval-okay-string.exp deleted file mode 100644 index 63f650f73..000000000 --- a/tests/lang/eval-okay-string.exp +++ /dev/null @@ -1 +0,0 @@ -"foobar/a/b/c/d/foo/xyzzy/foo.txt/../foo/x/yescape: \"quote\" \n \\end\nof\nlinefoobarblaatfoo$bar$\"$\"$" diff --git a/tests/lang/eval-okay-string.nix b/tests/lang/eval-okay-string.nix deleted file mode 100644 index 47cc989ad..000000000 --- a/tests/lang/eval-okay-string.nix +++ /dev/null @@ -1,12 +0,0 @@ -"foo" + "bar" - + toString (/a/b + /c/d) - + toString (/foo/bar + "/../xyzzy/." + "/foo.txt") - + ("/../foo" + toString /x/y) - + "escape: \"quote\" \n \\" - + "end -of -line" - + "foo${if true then "b${"a" + "r"}" else "xyzzy"}blaat" - + "foo$bar" - + "$\"$\"" - + "$" diff --git a/tests/lang/eval-okay-strings-as-attrs-names.exp b/tests/lang/eval-okay-strings-as-attrs-names.exp deleted file mode 100644 index 27ba77dda..000000000 --- a/tests/lang/eval-okay-strings-as-attrs-names.exp +++ /dev/null @@ -1 +0,0 @@ -true diff --git a/tests/lang/eval-okay-strings-as-attrs-names.nix b/tests/lang/eval-okay-strings-as-attrs-names.nix deleted file mode 100644 index 5e40928db..000000000 --- a/tests/lang/eval-okay-strings-as-attrs-names.nix +++ /dev/null @@ -1,20 +0,0 @@ -let - - attr = { - "key 1" = "test"; - "key 2" = "caseok"; - }; - - t1 = builtins.getAttr "key 1" attr; - t2 = attr."key 2"; - t3 = attr ? "key 1"; - t4 = builtins.attrNames { inherit (attr) "key 1"; }; - - # This is permitted, but there is currently no way to reference this - # variable. - "foo bar" = 1; - -in t1 == "test" - && t2 == "caseok" - && t3 == true - && t4 == ["key 1"] diff --git a/tests/lang/eval-okay-substring.exp b/tests/lang/eval-okay-substring.exp deleted file mode 100644 index 6aace04b0..000000000 --- a/tests/lang/eval-okay-substring.exp +++ /dev/null @@ -1 +0,0 @@ -"ooxfoobarybarzobaabbc" diff --git a/tests/lang/eval-okay-substring.nix b/tests/lang/eval-okay-substring.nix deleted file mode 100644 index 424af00d9..000000000 --- a/tests/lang/eval-okay-substring.nix +++ /dev/null @@ -1,21 +0,0 @@ -with builtins; - -let - - s = "foobar"; - -in - -substring 1 2 s -+ "x" -+ substring 0 (stringLength s) s -+ "y" -+ substring 3 100 s -+ "z" -+ substring 2 (sub (stringLength s) 3) s -+ "a" -+ substring 3 0 s -+ "b" -+ substring 3 1 s -+ "c" -+ substring 5 10 "perl" diff --git a/tests/lang/eval-okay-tail-call-1.exp-disabled b/tests/lang/eval-okay-tail-call-1.exp-disabled deleted file mode 100644 index f7393e847..000000000 --- a/tests/lang/eval-okay-tail-call-1.exp-disabled +++ /dev/null @@ -1 +0,0 @@ -100000 diff --git a/tests/lang/eval-okay-tail-call-1.nix b/tests/lang/eval-okay-tail-call-1.nix deleted file mode 100644 index a3962ce3f..000000000 --- a/tests/lang/eval-okay-tail-call-1.nix +++ /dev/null @@ -1,3 +0,0 @@ -let - f = n: if n == 100000 then n else f (n + 1); -in f 0 diff --git a/tests/lang/eval-okay-tojson.exp b/tests/lang/eval-okay-tojson.exp deleted file mode 100644 index e92aae323..000000000 --- a/tests/lang/eval-okay-tojson.exp +++ /dev/null @@ -1 +0,0 @@ -"{\"a\":123,\"b\":-456,\"c\":\"foo\",\"d\":\"foo\\n\\\"bar\\\"\",\"e\":true,\"f\":false,\"g\":[1,2,3],\"h\":[\"a\",[\"b\",{\"foo\\nbar\":{}}]],\"i\":3,\"j\":1.44,\"k\":\"foo\"}" diff --git a/tests/lang/eval-okay-tojson.nix b/tests/lang/eval-okay-tojson.nix deleted file mode 100644 index ce67943be..000000000 --- a/tests/lang/eval-okay-tojson.nix +++ /dev/null @@ -1,13 +0,0 @@ -builtins.toJSON - { a = 123; - b = -456; - c = "foo"; - d = "foo\n\"bar\""; - e = true; - f = false; - g = [ 1 2 3 ]; - h = [ "a" [ "b" { "foo\nbar" = {}; } ] ]; - i = 1 + 2; - j = 1.44; - k = { __toString = self: self.a; a = "foo"; }; - } diff --git a/tests/lang/eval-okay-toxml.exp b/tests/lang/eval-okay-toxml.exp deleted file mode 100644 index 828220890..000000000 --- a/tests/lang/eval-okay-toxml.exp +++ /dev/null @@ -1 +0,0 @@ -"\n\n \n \n \n \n \n\n" diff --git a/tests/lang/eval-okay-toxml.nix b/tests/lang/eval-okay-toxml.nix deleted file mode 100644 index 068c97a6c..000000000 --- a/tests/lang/eval-okay-toxml.nix +++ /dev/null @@ -1,3 +0,0 @@ -# Make sure the expected XML output is produced; in particular, make sure it -# doesn't contain source location information. -builtins.toXML { a = "s"; } diff --git a/tests/lang/eval-okay-toxml2.exp b/tests/lang/eval-okay-toxml2.exp deleted file mode 100644 index 634a841eb..000000000 --- a/tests/lang/eval-okay-toxml2.exp +++ /dev/null @@ -1 +0,0 @@ -"\n\n \n \n \n \n \n \n \n \n \n \n \n \n\n" diff --git a/tests/lang/eval-okay-toxml2.nix b/tests/lang/eval-okay-toxml2.nix deleted file mode 100644 index ff1791b30..000000000 --- a/tests/lang/eval-okay-toxml2.nix +++ /dev/null @@ -1 +0,0 @@ -builtins.toXML [("a" + "b") 10 (rec {x = "x"; y = x;})] diff --git a/tests/lang/eval-okay-tryeval.exp b/tests/lang/eval-okay-tryeval.exp deleted file mode 100644 index 2b2e6fa71..000000000 --- a/tests/lang/eval-okay-tryeval.exp +++ /dev/null @@ -1 +0,0 @@ -{ x = { success = true; value = "x"; }; y = { success = false; value = false; }; z = { success = false; value = false; }; } diff --git a/tests/lang/eval-okay-tryeval.nix b/tests/lang/eval-okay-tryeval.nix deleted file mode 100644 index 629bc440a..000000000 --- a/tests/lang/eval-okay-tryeval.nix +++ /dev/null @@ -1,5 +0,0 @@ -{ - x = builtins.tryEval "x"; - y = builtins.tryEval (assert false; "y"); - z = builtins.tryEval (throw "bla"); -} diff --git a/tests/lang/eval-okay-types.exp b/tests/lang/eval-okay-types.exp deleted file mode 100644 index 92a153299..000000000 --- a/tests/lang/eval-okay-types.exp +++ /dev/null @@ -1 +0,0 @@ -[ true false true false true false true false true true true true true true true true true true true false true true true false "int" "bool" "string" "null" "set" "list" "lambda" "lambda" "lambda" "lambda" ] diff --git a/tests/lang/eval-okay-types.nix b/tests/lang/eval-okay-types.nix deleted file mode 100644 index 9b58be5d1..000000000 --- a/tests/lang/eval-okay-types.nix +++ /dev/null @@ -1,37 +0,0 @@ -with builtins; - -[ (isNull null) - (isNull (x: x)) - (isFunction (x: x)) - (isFunction "fnord") - (isString ("foo" + "bar")) - (isString [ "x" ]) - (isInt (1 + 2)) - (isInt { x = 123; }) - (isInt (1 / 2)) - (isInt (1 + 1)) - (isInt (1 / 2)) - (isInt (1 * 2)) - (isInt (1 - 2)) - (isFloat (1.2)) - (isFloat (1 + 1.0)) - (isFloat (1 / 2.0)) - (isFloat (1 * 2.0)) - (isFloat (1 - 2.0)) - (isBool (true && false)) - (isBool null) - (isPath /nix/store) - (isPath ./.) - (isAttrs { x = 123; }) - (isAttrs null) - (typeOf (3 * 4)) - (typeOf true) - (typeOf "xyzzy") - (typeOf null) - (typeOf { x = 456; }) - (typeOf [ 1 2 3 ]) - (typeOf (x: x)) - (typeOf ((x: y: x) 1)) - (typeOf map) - (typeOf (map (x: x))) -] diff --git a/tests/lang/eval-okay-versions.exp b/tests/lang/eval-okay-versions.exp deleted file mode 100644 index 27ba77dda..000000000 --- a/tests/lang/eval-okay-versions.exp +++ /dev/null @@ -1 +0,0 @@ -true diff --git a/tests/lang/eval-okay-versions.nix b/tests/lang/eval-okay-versions.nix deleted file mode 100644 index e9111f5f4..000000000 --- a/tests/lang/eval-okay-versions.nix +++ /dev/null @@ -1,43 +0,0 @@ -let - - name1 = "hello-1.0.2"; - name2 = "hello"; - name3 = "915resolution-0.5.2"; - name4 = "xf86-video-i810-1.7.4"; - name5 = "name-that-ends-with-dash--1.0"; - - eq = 0; - lt = builtins.sub 0 1; - gt = 1; - - versionTest = v1: v2: expected: - let d1 = builtins.compareVersions v1 v2; - d2 = builtins.compareVersions v2 v1; - in d1 == builtins.sub 0 d2 && d1 == expected; - - tests = [ - ((builtins.parseDrvName name1).name == "hello") - ((builtins.parseDrvName name1).version == "1.0.2") - ((builtins.parseDrvName name2).name == "hello") - ((builtins.parseDrvName name2).version == "") - ((builtins.parseDrvName name3).name == "915resolution") - ((builtins.parseDrvName name3).version == "0.5.2") - ((builtins.parseDrvName name4).name == "xf86-video-i810") - ((builtins.parseDrvName name4).version == "1.7.4") - ((builtins.parseDrvName name5).name == "name-that-ends-with-dash") - ((builtins.parseDrvName name5).version == "-1.0") - (versionTest "1.0" "2.3" lt) - (versionTest "2.1" "2.3" lt) - (versionTest "2.3" "2.3" eq) - (versionTest "2.5" "2.3" gt) - (versionTest "3.1" "2.3" gt) - (versionTest "2.3.1" "2.3" gt) - (versionTest "2.3.1" "2.3a" gt) - (versionTest "2.3pre1" "2.3" lt) - (versionTest "2.3pre3" "2.3pre12" lt) - (versionTest "2.3a" "2.3c" lt) - (versionTest "2.3pre1" "2.3c" lt) - (versionTest "2.3pre1" "2.3q" lt) - ]; - -in (import ./lib.nix).and tests diff --git a/tests/lang/eval-okay-with.exp b/tests/lang/eval-okay-with.exp deleted file mode 100644 index 378c8dc80..000000000 --- a/tests/lang/eval-okay-with.exp +++ /dev/null @@ -1 +0,0 @@ -"xyzzybarxyzzybar" diff --git a/tests/lang/eval-okay-with.nix b/tests/lang/eval-okay-with.nix deleted file mode 100644 index 033e8d3ab..000000000 --- a/tests/lang/eval-okay-with.nix +++ /dev/null @@ -1,19 +0,0 @@ -let { - - a = "xyzzy"; - - as = { - a = "foo"; - b = "bar"; - }; - - bs = { - a = "bar"; - }; - - x = with as; a + b; - - y = with as; with bs; a + b; - - body = x + y; -} diff --git a/tests/lang/eval-okay-xml.exp.xml b/tests/lang/eval-okay-xml.exp.xml deleted file mode 100644 index 20099326c..000000000 --- a/tests/lang/eval-okay-xml.exp.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/lang/eval-okay-xml.nix b/tests/lang/eval-okay-xml.nix deleted file mode 100644 index 9ee9f8a0b..000000000 --- a/tests/lang/eval-okay-xml.nix +++ /dev/null @@ -1,21 +0,0 @@ -rec { - - x = 123; - - y = 567.890; - - a = "foo"; - - b = "bar"; - - c = "foo" + "bar"; - - f = {z, x, y}: if y then x else z; - - id = x: x; - - at = args@{x, y, z}: x; - - ellipsis = {x, y, z, ...}: x; - -} diff --git a/tests/lang/eval-okay-zipAttrsWith.exp b/tests/lang/eval-okay-zipAttrsWith.exp deleted file mode 100644 index 9c0b15d22..000000000 --- a/tests/lang/eval-okay-zipAttrsWith.exp +++ /dev/null @@ -1 +0,0 @@ -{ "0" = { n = "0"; v = [ 5 23 29 ]; }; "1" = { n = "1"; v = [ 7 30 ]; }; "2" = { n = "2"; v = [ 18 ]; }; "4" = { n = "4"; v = [ 10 ]; }; "5" = { n = "5"; v = [ 15 25 26 31 ]; }; "6" = { n = "6"; v = [ 3 14 ]; }; "7" = { n = "7"; v = [ 12 ]; }; "8" = { n = "8"; v = [ 2 6 8 9 ]; }; "9" = { n = "9"; v = [ 0 16 ]; }; a = { n = "a"; v = [ 17 21 22 27 ]; }; c = { n = "c"; v = [ 11 24 ]; }; d = { n = "d"; v = [ 4 13 28 ]; }; e = { n = "e"; v = [ 20 ]; }; f = { n = "f"; v = [ 1 19 ]; }; } diff --git a/tests/lang/eval-okay-zipAttrsWith.nix b/tests/lang/eval-okay-zipAttrsWith.nix deleted file mode 100644 index 877d4e5fa..000000000 --- a/tests/lang/eval-okay-zipAttrsWith.nix +++ /dev/null @@ -1,9 +0,0 @@ -with import ./lib.nix; - -let - str = builtins.hashString "sha256" "test"; -in -builtins.zipAttrsWith - (n: v: { inherit n v; }) - (map (n: { ${builtins.substring n 1 str} = n; }) - (range 0 31)) diff --git a/tests/lang/framework.sh b/tests/lang/framework.sh deleted file mode 100644 index 516bff8ad..000000000 --- a/tests/lang/framework.sh +++ /dev/null @@ -1,33 +0,0 @@ -# Golden test support -# -# Test that the output of the given test matches what is expected. If -# `_NIX_TEST_ACCEPT` is non-empty also update the expected output so -# that next time the test succeeds. -function diffAndAcceptInner() { - local -r testName=$1 - local -r got="$2" - local -r expected="$3" - - # Absence of expected file indicates empty output expected. - if test -e "$expected"; then - local -r expectedOrEmpty="$expected" - else - local -r expectedOrEmpty=lang/empty.exp - fi - - # Diff so we get a nice message - if ! diff --unified "$got" "$expectedOrEmpty"; then - echo "FAIL: evaluation result of $testName not as expected" - badDiff=1 - fi - - # Update expected if `_NIX_TEST_ACCEPT` is non-empty. - if test -n "${_NIX_TEST_ACCEPT-}"; then - cp "$got" "$expected" - # Delete empty expected files to avoid bloating the repo with - # empty files. - if ! test -s "$expected"; then - rm "$expected" - fi - fi -} diff --git a/tests/lang/imported.nix b/tests/lang/imported.nix deleted file mode 100644 index fb39ee4ef..000000000 --- a/tests/lang/imported.nix +++ /dev/null @@ -1,3 +0,0 @@ -# The function ‘range’ comes from lib.nix and was added to the lexical -# scope by scopedImport. -range 1 5 ++ import ./imported2.nix diff --git a/tests/lang/imported2.nix b/tests/lang/imported2.nix deleted file mode 100644 index 6d0a2992b..000000000 --- a/tests/lang/imported2.nix +++ /dev/null @@ -1 +0,0 @@ -range 6 10 diff --git a/tests/lang/lib.nix b/tests/lang/lib.nix deleted file mode 100644 index 028a53831..000000000 --- a/tests/lang/lib.nix +++ /dev/null @@ -1,61 +0,0 @@ -with builtins; - -rec { - - fold = op: nul: list: - if list == [] - then nul - else op (head list) (fold op nul (tail list)); - - concat = - fold (x: y: x + y) ""; - - and = fold (x: y: x && y) true; - - flatten = x: - if isList x - then fold (x: y: (flatten x) ++ y) [] x - else [x]; - - sum = foldl' (x: y: add x y) 0; - - hasSuffix = ext: fileName: - let lenFileName = stringLength fileName; - lenExt = stringLength ext; - in !(lessThan lenFileName lenExt) && - substring (sub lenFileName lenExt) lenFileName fileName == ext; - - # Split a list at the given position. - splitAt = pos: list: - if pos == 0 then {first = []; second = list;} else - if list == [] then {first = []; second = [];} else - let res = splitAt (sub pos 1) (tail list); - in {first = [(head list)] ++ res.first; second = res.second;}; - - # Stable merge sort. - sortBy = comp: list: - if lessThan 1 (length list) - then - let - split = splitAt (div (length list) 2) list; - first = sortBy comp split.first; - second = sortBy comp split.second; - in mergeLists comp first second - else list; - - mergeLists = comp: list1: list2: - if list1 == [] then list2 else - if list2 == [] then list1 else - if comp (head list2) (head list1) then [(head list2)] ++ mergeLists comp list1 (tail list2) else - [(head list1)] ++ mergeLists comp (tail list1) list2; - - id = x: x; - - const = x: y: x; - - range = first: last: - if first > last - then [] - else genList (n: first + n) (last - first + 1); - -} diff --git a/tests/lang/parse-fail-dup-attrs-1.err.exp b/tests/lang/parse-fail-dup-attrs-1.err.exp deleted file mode 100644 index 4fe6b7a1f..000000000 --- a/tests/lang/parse-fail-dup-attrs-1.err.exp +++ /dev/null @@ -1,7 +0,0 @@ -error: attribute 'x' already defined at «stdin»:1:3 - - at «stdin»:3:3: - - 2| y = 456; - 3| x = 789; - | ^ diff --git a/tests/lang/parse-fail-dup-attrs-1.nix b/tests/lang/parse-fail-dup-attrs-1.nix deleted file mode 100644 index 2c02317d2..000000000 --- a/tests/lang/parse-fail-dup-attrs-1.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ x = 123; - y = 456; - x = 789; -} diff --git a/tests/lang/parse-fail-dup-attrs-2.err.exp b/tests/lang/parse-fail-dup-attrs-2.err.exp deleted file mode 100644 index 3aba2891f..000000000 --- a/tests/lang/parse-fail-dup-attrs-2.err.exp +++ /dev/null @@ -1,7 +0,0 @@ -error: attribute 'x' already defined at «stdin»:9:5 - - at «stdin»:10:17: - - 9| x = 789; - 10| inherit (as) x; - | ^ diff --git a/tests/lang/parse-fail-dup-attrs-2.nix b/tests/lang/parse-fail-dup-attrs-2.nix deleted file mode 100644 index 864d9865e..000000000 --- a/tests/lang/parse-fail-dup-attrs-2.nix +++ /dev/null @@ -1,13 +0,0 @@ -let { - - as = { - x = 123; - y = 456; - }; - - bs = { - x = 789; - inherit (as) x; - }; - -} diff --git a/tests/lang/parse-fail-dup-attrs-3.err.exp b/tests/lang/parse-fail-dup-attrs-3.err.exp deleted file mode 100644 index 3aba2891f..000000000 --- a/tests/lang/parse-fail-dup-attrs-3.err.exp +++ /dev/null @@ -1,7 +0,0 @@ -error: attribute 'x' already defined at «stdin»:9:5 - - at «stdin»:10:17: - - 9| x = 789; - 10| inherit (as) x; - | ^ diff --git a/tests/lang/parse-fail-dup-attrs-3.nix b/tests/lang/parse-fail-dup-attrs-3.nix deleted file mode 100644 index 114d19779..000000000 --- a/tests/lang/parse-fail-dup-attrs-3.nix +++ /dev/null @@ -1,13 +0,0 @@ -let { - - as = { - x = 123; - y = 456; - }; - - bs = rec { - x = 789; - inherit (as) x; - }; - -} diff --git a/tests/lang/parse-fail-dup-attrs-4.err.exp b/tests/lang/parse-fail-dup-attrs-4.err.exp deleted file mode 100644 index ff68446a1..000000000 --- a/tests/lang/parse-fail-dup-attrs-4.err.exp +++ /dev/null @@ -1,7 +0,0 @@ -error: attribute 'services.ssh.port' already defined at «stdin»:2:3 - - at «stdin»:3:3: - - 2| services.ssh.port = 22; - 3| services.ssh.port = 23; - | ^ diff --git a/tests/lang/parse-fail-dup-attrs-4.nix b/tests/lang/parse-fail-dup-attrs-4.nix deleted file mode 100644 index 77417432b..000000000 --- a/tests/lang/parse-fail-dup-attrs-4.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ - services.ssh.port = 22; - services.ssh.port = 23; -} diff --git a/tests/lang/parse-fail-dup-attrs-6.err.exp b/tests/lang/parse-fail-dup-attrs-6.err.exp deleted file mode 100644 index 74823fc25..000000000 --- a/tests/lang/parse-fail-dup-attrs-6.err.exp +++ /dev/null @@ -1 +0,0 @@ -error: attribute ‘services.ssh’ at (string):3:3 already defined at (string):2:3 diff --git a/tests/lang/parse-fail-dup-attrs-7.err.exp b/tests/lang/parse-fail-dup-attrs-7.err.exp deleted file mode 100644 index 512a499ca..000000000 --- a/tests/lang/parse-fail-dup-attrs-7.err.exp +++ /dev/null @@ -1,7 +0,0 @@ -error: attribute 'x' already defined at «stdin»:6:12 - - at «stdin»:7:12: - - 6| inherit x; - 7| inherit x; - | ^ diff --git a/tests/lang/parse-fail-dup-attrs-7.nix b/tests/lang/parse-fail-dup-attrs-7.nix deleted file mode 100644 index bbc3eb08c..000000000 --- a/tests/lang/parse-fail-dup-attrs-7.nix +++ /dev/null @@ -1,9 +0,0 @@ -rec { - - x = 1; - - as = { - inherit x; - inherit x; - }; -} \ No newline at end of file diff --git a/tests/lang/parse-fail-dup-formals.err.exp b/tests/lang/parse-fail-dup-formals.err.exp deleted file mode 100644 index 1d566fb33..000000000 --- a/tests/lang/parse-fail-dup-formals.err.exp +++ /dev/null @@ -1,6 +0,0 @@ -error: duplicate formal function argument 'x' - - at «stdin»:1:8: - - 1| {x, y, x}: x - | ^ diff --git a/tests/lang/parse-fail-dup-formals.nix b/tests/lang/parse-fail-dup-formals.nix deleted file mode 100644 index a0edd91a9..000000000 --- a/tests/lang/parse-fail-dup-formals.nix +++ /dev/null @@ -1 +0,0 @@ -{x, y, x}: x \ No newline at end of file diff --git a/tests/lang/parse-fail-eof-in-string.err.exp b/tests/lang/parse-fail-eof-in-string.err.exp deleted file mode 100644 index f9fa72312..000000000 --- a/tests/lang/parse-fail-eof-in-string.err.exp +++ /dev/null @@ -1,7 +0,0 @@ -error: syntax error, unexpected end of file, expecting '"' - - at «stdin»:3:5: - - 2| # Note that this file must not end with a newline. - 3| a 1"$ - | ^ diff --git a/tests/lang/parse-fail-eof-in-string.nix b/tests/lang/parse-fail-eof-in-string.nix deleted file mode 100644 index 19775d2ec..000000000 --- a/tests/lang/parse-fail-eof-in-string.nix +++ /dev/null @@ -1,3 +0,0 @@ -# https://github.com/NixOS/nix/issues/6562 -# Note that this file must not end with a newline. -a 1"$ \ No newline at end of file diff --git a/tests/lang/parse-fail-mixed-nested-attrs1.err.exp b/tests/lang/parse-fail-mixed-nested-attrs1.err.exp deleted file mode 100644 index 32f776795..000000000 --- a/tests/lang/parse-fail-mixed-nested-attrs1.err.exp +++ /dev/null @@ -1,8 +0,0 @@ -error: attribute 'z' already defined at «stdin»:3:16 - - at «stdin»:2:3: - - 1| { - 2| x.z = 3; - | ^ - 3| x = { y = 3; z = 3; }; diff --git a/tests/lang/parse-fail-mixed-nested-attrs1.nix b/tests/lang/parse-fail-mixed-nested-attrs1.nix deleted file mode 100644 index 11e40e66f..000000000 --- a/tests/lang/parse-fail-mixed-nested-attrs1.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ - x.z = 3; - x = { y = 3; z = 3; }; -} diff --git a/tests/lang/parse-fail-mixed-nested-attrs2.err.exp b/tests/lang/parse-fail-mixed-nested-attrs2.err.exp deleted file mode 100644 index 0437cd50c..000000000 --- a/tests/lang/parse-fail-mixed-nested-attrs2.err.exp +++ /dev/null @@ -1,8 +0,0 @@ -error: attribute 'y' already defined at «stdin»:3:9 - - at «stdin»:2:3: - - 1| { - 2| x.y.y = 3; - | ^ - 3| x = { y.y= 3; z = 3; }; diff --git a/tests/lang/parse-fail-mixed-nested-attrs2.nix b/tests/lang/parse-fail-mixed-nested-attrs2.nix deleted file mode 100644 index 17da82e5f..000000000 --- a/tests/lang/parse-fail-mixed-nested-attrs2.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ - x.y.y = 3; - x = { y.y= 3; z = 3; }; -} diff --git a/tests/lang/parse-fail-patterns-1.err.exp b/tests/lang/parse-fail-patterns-1.err.exp deleted file mode 100644 index 634a04aaa..000000000 --- a/tests/lang/parse-fail-patterns-1.err.exp +++ /dev/null @@ -1,7 +0,0 @@ -error: duplicate formal function argument 'args' - - at «stdin»:1:1: - - 1| args@{args, x, y, z}: x - | ^ - 2| diff --git a/tests/lang/parse-fail-patterns-1.nix b/tests/lang/parse-fail-patterns-1.nix deleted file mode 100644 index 7b4061641..000000000 --- a/tests/lang/parse-fail-patterns-1.nix +++ /dev/null @@ -1 +0,0 @@ -args@{args, x, y, z}: x diff --git a/tests/lang/parse-fail-regression-20060610.err.exp b/tests/lang/parse-fail-regression-20060610.err.exp deleted file mode 100644 index 167d01e85..000000000 --- a/tests/lang/parse-fail-regression-20060610.err.exp +++ /dev/null @@ -1,8 +0,0 @@ -error: undefined variable 'gcc' - - at «stdin»:8:12: - - 7| - 8| body = ({ - | ^ - 9| inherit gcc; diff --git a/tests/lang/parse-fail-regression-20060610.nix b/tests/lang/parse-fail-regression-20060610.nix deleted file mode 100644 index b1934f7e1..000000000 --- a/tests/lang/parse-fail-regression-20060610.nix +++ /dev/null @@ -1,11 +0,0 @@ -let { - x = - {gcc}: - { - inherit gcc; - }; - - body = ({ - inherit gcc; - }).gcc; -} diff --git a/tests/lang/parse-fail-undef-var-2.err.exp b/tests/lang/parse-fail-undef-var-2.err.exp deleted file mode 100644 index 77c96bbd2..000000000 --- a/tests/lang/parse-fail-undef-var-2.err.exp +++ /dev/null @@ -1,7 +0,0 @@ -error: syntax error, unexpected ':', expecting '}' - - at «stdin»:3:13: - - 2| - 3| f = {x, y : - | ^ diff --git a/tests/lang/parse-fail-undef-var-2.nix b/tests/lang/parse-fail-undef-var-2.nix deleted file mode 100644 index c10a52b1e..000000000 --- a/tests/lang/parse-fail-undef-var-2.nix +++ /dev/null @@ -1,7 +0,0 @@ -let { - - f = {x, y : ["baz" "bar" z "bat"]}: x + y; - - body = f {x = "foo"; y = "bar";}; - -} diff --git a/tests/lang/parse-fail-undef-var.err.exp b/tests/lang/parse-fail-undef-var.err.exp deleted file mode 100644 index 48e88747f..000000000 --- a/tests/lang/parse-fail-undef-var.err.exp +++ /dev/null @@ -1,7 +0,0 @@ -error: undefined variable 'y' - - at «stdin»:1:4: - - 1| x: y - | ^ - 2| diff --git a/tests/lang/parse-fail-undef-var.nix b/tests/lang/parse-fail-undef-var.nix deleted file mode 100644 index 7b6300811..000000000 --- a/tests/lang/parse-fail-undef-var.nix +++ /dev/null @@ -1 +0,0 @@ -x: y diff --git a/tests/lang/parse-fail-utf8.err.exp b/tests/lang/parse-fail-utf8.err.exp deleted file mode 100644 index 6087479a3..000000000 --- a/tests/lang/parse-fail-utf8.err.exp +++ /dev/null @@ -1,6 +0,0 @@ -error: syntax error, unexpected invalid token, expecting end of file - - at «stdin»:1:5: - - 1| 123 - | ^ diff --git a/tests/lang/parse-fail-utf8.nix b/tests/lang/parse-fail-utf8.nix deleted file mode 100644 index 34948d48a..000000000 --- a/tests/lang/parse-fail-utf8.nix +++ /dev/null @@ -1 +0,0 @@ -123 é 4 diff --git a/tests/lang/parse-okay-1.exp b/tests/lang/parse-okay-1.exp deleted file mode 100644 index d5ab5f18a..000000000 --- a/tests/lang/parse-okay-1.exp +++ /dev/null @@ -1 +0,0 @@ -({ x, y, z }: ((x + y) + z)) diff --git a/tests/lang/parse-okay-1.nix b/tests/lang/parse-okay-1.nix deleted file mode 100644 index 23a58ed10..000000000 --- a/tests/lang/parse-okay-1.nix +++ /dev/null @@ -1 +0,0 @@ -{x, y, z}: x + y + z diff --git a/tests/lang/parse-okay-crlf.exp b/tests/lang/parse-okay-crlf.exp deleted file mode 100644 index 4213609fc..000000000 --- a/tests/lang/parse-okay-crlf.exp +++ /dev/null @@ -1 +0,0 @@ -rec { foo = "multi\nline\n string\n test\r"; x = y; y = 123; z = 456; } diff --git a/tests/lang/parse-okay-crlf.nix b/tests/lang/parse-okay-crlf.nix deleted file mode 100644 index 21518d4c6..000000000 --- a/tests/lang/parse-okay-crlf.nix +++ /dev/null @@ -1,17 +0,0 @@ -rec { - - /* Dit is - een test. */ - - x = - # Dit is een test. y; - - y = 123; - - # CR or CR/LF (but not explicit \r's) in strings should be - # translated to LF. - foo = "multi line - string - test\r"; - - z = 456; } diff --git a/tests/lang/parse-okay-dup-attrs-5.exp b/tests/lang/parse-okay-dup-attrs-5.exp deleted file mode 100644 index 88b0b036f..000000000 --- a/tests/lang/parse-okay-dup-attrs-5.exp +++ /dev/null @@ -1 +0,0 @@ -{ services = { ssh = { enable = true; port = 23; }; }; } diff --git a/tests/lang/parse-okay-dup-attrs-5.nix b/tests/lang/parse-okay-dup-attrs-5.nix deleted file mode 100644 index f4b9efd0c..000000000 --- a/tests/lang/parse-okay-dup-attrs-5.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ - services.ssh = { enable = true; }; - services.ssh.port = 23; -} diff --git a/tests/lang/parse-okay-dup-attrs-6.exp b/tests/lang/parse-okay-dup-attrs-6.exp deleted file mode 100644 index 88b0b036f..000000000 --- a/tests/lang/parse-okay-dup-attrs-6.exp +++ /dev/null @@ -1 +0,0 @@ -{ services = { ssh = { enable = true; port = 23; }; }; } diff --git a/tests/lang/parse-okay-dup-attrs-6.nix b/tests/lang/parse-okay-dup-attrs-6.nix deleted file mode 100644 index ae6d7a769..000000000 --- a/tests/lang/parse-okay-dup-attrs-6.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ - services.ssh.port = 23; - services.ssh = { enable = true; }; -} diff --git a/tests/lang/parse-okay-mixed-nested-attrs-1.exp b/tests/lang/parse-okay-mixed-nested-attrs-1.exp deleted file mode 100644 index 89c66f760..000000000 --- a/tests/lang/parse-okay-mixed-nested-attrs-1.exp +++ /dev/null @@ -1 +0,0 @@ -{ x = { q = 3; y = 3; z = 3; }; } diff --git a/tests/lang/parse-okay-mixed-nested-attrs-1.nix b/tests/lang/parse-okay-mixed-nested-attrs-1.nix deleted file mode 100644 index fd1001c8c..000000000 --- a/tests/lang/parse-okay-mixed-nested-attrs-1.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ - x = { y = 3; z = 3; }; - x.q = 3; -} diff --git a/tests/lang/parse-okay-mixed-nested-attrs-2.exp b/tests/lang/parse-okay-mixed-nested-attrs-2.exp deleted file mode 100644 index 89c66f760..000000000 --- a/tests/lang/parse-okay-mixed-nested-attrs-2.exp +++ /dev/null @@ -1 +0,0 @@ -{ x = { q = 3; y = 3; z = 3; }; } diff --git a/tests/lang/parse-okay-mixed-nested-attrs-2.nix b/tests/lang/parse-okay-mixed-nested-attrs-2.nix deleted file mode 100644 index ad066b680..000000000 --- a/tests/lang/parse-okay-mixed-nested-attrs-2.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ - x.q = 3; - x = { y = 3; z = 3; }; -} diff --git a/tests/lang/parse-okay-mixed-nested-attrs-3.exp b/tests/lang/parse-okay-mixed-nested-attrs-3.exp deleted file mode 100644 index b89a59734..000000000 --- a/tests/lang/parse-okay-mixed-nested-attrs-3.exp +++ /dev/null @@ -1 +0,0 @@ -{ services = { httpd = { enable = true; }; ssh = { enable = true; port = 123; }; }; } diff --git a/tests/lang/parse-okay-mixed-nested-attrs-3.nix b/tests/lang/parse-okay-mixed-nested-attrs-3.nix deleted file mode 100644 index 45a33e480..000000000 --- a/tests/lang/parse-okay-mixed-nested-attrs-3.nix +++ /dev/null @@ -1,7 +0,0 @@ -{ - services.ssh.enable = true; - services.ssh = { port = 123; }; - services = { - httpd.enable = true; - }; -} diff --git a/tests/lang/parse-okay-regression-20041027.exp b/tests/lang/parse-okay-regression-20041027.exp deleted file mode 100644 index 9df7219e4..000000000 --- a/tests/lang/parse-okay-regression-20041027.exp +++ /dev/null @@ -1 +0,0 @@ -({ fetchurl, stdenv }: ((stdenv).mkDerivation { name = "libXi-6.0.1"; src = (fetchurl { md5 = "7e935a42428d63a387b3c048be0f2756"; url = "http://freedesktop.org/~xlibs/release/libXi-6.0.1.tar.bz2"; }); })) diff --git a/tests/lang/parse-okay-regression-20041027.nix b/tests/lang/parse-okay-regression-20041027.nix deleted file mode 100644 index ae2e256ee..000000000 --- a/tests/lang/parse-okay-regression-20041027.nix +++ /dev/null @@ -1,11 +0,0 @@ -{stdenv, fetchurl /* pkgconfig, libX11 */ }: - -stdenv.mkDerivation { - name = "libXi-6.0.1"; - src = fetchurl { - url = http://freedesktop.org/~xlibs/release/libXi-6.0.1.tar.bz2; - md5 = "7e935a42428d63a387b3c048be0f2756"; - }; -/* buildInputs = [pkgconfig]; - propagatedBuildInputs = [libX11]; */ -} diff --git a/tests/lang/parse-okay-regression-751.exp b/tests/lang/parse-okay-regression-751.exp deleted file mode 100644 index e2ed886fe..000000000 --- a/tests/lang/parse-okay-regression-751.exp +++ /dev/null @@ -1 +0,0 @@ -(let const = (a: "const"); in ((const { x = "q"; }))) diff --git a/tests/lang/parse-okay-regression-751.nix b/tests/lang/parse-okay-regression-751.nix deleted file mode 100644 index 05c78b301..000000000 --- a/tests/lang/parse-okay-regression-751.nix +++ /dev/null @@ -1,2 +0,0 @@ -let const = a: "const"; in -''${ const { x = "q"; }}'' diff --git a/tests/lang/parse-okay-subversion.exp b/tests/lang/parse-okay-subversion.exp deleted file mode 100644 index 4168ee8bf..000000000 --- a/tests/lang/parse-okay-subversion.exp +++ /dev/null @@ -1 +0,0 @@ -({ fetchurl, localServer ? false, httpServer ? false, sslSupport ? false, pythonBindings ? false, javaSwigBindings ? false, javahlBindings ? false, stdenv, openssl ? null, httpd ? null, db4 ? null, expat, swig ? null, j2sdk ? null }: assert (expat != null); assert (localServer -> (db4 != null)); assert (httpServer -> ((httpd != null) && ((httpd).expat == expat))); assert (sslSupport -> ((openssl != null) && (httpServer -> ((httpd).openssl == openssl)))); assert (pythonBindings -> ((swig != null) && (swig).pythonSupport)); assert (javaSwigBindings -> ((swig != null) && (swig).javaSupport)); assert (javahlBindings -> (j2sdk != null)); ((stdenv).mkDerivation { builder = /foo/bar; db4 = (if localServer then db4 else null); inherit expat ; inherit httpServer ; httpd = (if httpServer then httpd else null); j2sdk = (if javaSwigBindings then (swig).j2sdk else (if javahlBindings then j2sdk else null)); inherit javaSwigBindings ; inherit javahlBindings ; inherit localServer ; name = "subversion-1.1.1"; openssl = (if sslSupport then openssl else null); patches = (if javahlBindings then [ (/javahl.patch) ] else [ ]); python = (if pythonBindings then (swig).python else null); inherit pythonBindings ; src = (fetchurl { md5 = "a180c3fe91680389c210c99def54d9e0"; url = "http://subversion.tigris.org/tarballs/subversion-1.1.1.tar.bz2"; }); inherit sslSupport ; swig = (if (pythonBindings || javaSwigBindings) then swig else null); })) diff --git a/tests/lang/parse-okay-subversion.nix b/tests/lang/parse-okay-subversion.nix deleted file mode 100644 index 356272815..000000000 --- a/tests/lang/parse-okay-subversion.nix +++ /dev/null @@ -1,43 +0,0 @@ -{ localServer ? false -, httpServer ? false -, sslSupport ? false -, pythonBindings ? false -, javaSwigBindings ? false -, javahlBindings ? false -, stdenv, fetchurl -, openssl ? null, httpd ? null, db4 ? null, expat, swig ? null, j2sdk ? null -}: - -assert expat != null; -assert localServer -> db4 != null; -assert httpServer -> httpd != null && httpd.expat == expat; -assert sslSupport -> openssl != null && (httpServer -> httpd.openssl == openssl); -assert pythonBindings -> swig != null && swig.pythonSupport; -assert javaSwigBindings -> swig != null && swig.javaSupport; -assert javahlBindings -> j2sdk != null; - -stdenv.mkDerivation { - name = "subversion-1.1.1"; - - builder = /foo/bar; - src = fetchurl { - url = http://subversion.tigris.org/tarballs/subversion-1.1.1.tar.bz2; - md5 = "a180c3fe91680389c210c99def54d9e0"; - }; - - # This is a hopefully temporary fix for the problem that - # libsvnjavahl.so isn't linked against libstdc++, which causes - # loading the library into the JVM to fail. - patches = if javahlBindings then [/javahl.patch] else []; - - openssl = if sslSupport then openssl else null; - httpd = if httpServer then httpd else null; - db4 = if localServer then db4 else null; - swig = if pythonBindings || javaSwigBindings then swig else null; - python = if pythonBindings then swig.python else null; - j2sdk = if javaSwigBindings then swig.j2sdk else - if javahlBindings then j2sdk else null; - - inherit expat localServer httpServer sslSupport - pythonBindings javaSwigBindings javahlBindings; -} diff --git a/tests/lang/parse-okay-url.exp b/tests/lang/parse-okay-url.exp deleted file mode 100644 index e5f0829b0..000000000 --- a/tests/lang/parse-okay-url.exp +++ /dev/null @@ -1 +0,0 @@ -[ ("x:x") ("https://svn.cs.uu.nl:12443/repos/trace/trunk") ("http://www2.mplayerhq.hu/MPlayer/releases/fonts/font-arial-iso-8859-1.tar.bz2") ("http://losser.st-lab.cs.uu.nl/~armijn/.nix/gcc-3.3.4-static-nix.tar.gz") ("http://fpdownload.macromedia.com/get/shockwave/flash/english/linux/7.0r25/install_flash_player_7_linux.tar.gz") ("https://ftp5.gwdg.de/pub/linux/archlinux/extra/os/x86_64/unzip-6.0-14-x86_64.pkg.tar.zst") ("ftp://ftp.gtk.org/pub/gtk/v1.2/gtk+-1.2.10.tar.gz") ] diff --git a/tests/lang/parse-okay-url.nix b/tests/lang/parse-okay-url.nix deleted file mode 100644 index 08de27d0a..000000000 --- a/tests/lang/parse-okay-url.nix +++ /dev/null @@ -1,8 +0,0 @@ -[ x:x - https://svn.cs.uu.nl:12443/repos/trace/trunk - http://www2.mplayerhq.hu/MPlayer/releases/fonts/font-arial-iso-8859-1.tar.bz2 - http://losser.st-lab.cs.uu.nl/~armijn/.nix/gcc-3.3.4-static-nix.tar.gz - http://fpdownload.macromedia.com/get/shockwave/flash/english/linux/7.0r25/install_flash_player_7_linux.tar.gz - https://ftp5.gwdg.de/pub/linux/archlinux/extra/os/x86_64/unzip-6.0-14-x86_64.pkg.tar.zst - ftp://ftp.gtk.org/pub/gtk/v1.2/gtk+-1.2.10.tar.gz -] diff --git a/tests/lang/readDir/bar b/tests/lang/readDir/bar deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/lang/readDir/foo/git-hates-directories b/tests/lang/readDir/foo/git-hates-directories deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/lang/readDir/ldir b/tests/lang/readDir/ldir deleted file mode 120000 index 191028156..000000000 --- a/tests/lang/readDir/ldir +++ /dev/null @@ -1 +0,0 @@ -foo \ No newline at end of file diff --git a/tests/lang/readDir/linked b/tests/lang/readDir/linked deleted file mode 120000 index c503f86a0..000000000 --- a/tests/lang/readDir/linked +++ /dev/null @@ -1 +0,0 @@ -foo/git-hates-directories \ No newline at end of file diff --git a/tests/legacy-ssh-store.sh b/tests/legacy-ssh-store.sh deleted file mode 100644 index 71b716b84..000000000 --- a/tests/legacy-ssh-store.sh +++ /dev/null @@ -1,4 +0,0 @@ -source common.sh - -# Check that store ping trusted doesn't yet work with ssh:// -nix --store ssh://localhost?remote-store=$TEST_ROOT/other-store store ping --json | jq -e 'has("trusted") | not' diff --git a/tests/linux-sandbox-cert-test.nix b/tests/linux-sandbox-cert-test.nix deleted file mode 100644 index 2fc083ea9..000000000 --- a/tests/linux-sandbox-cert-test.nix +++ /dev/null @@ -1,30 +0,0 @@ -{ mode }: - -with import ./config.nix; - -mkDerivation ( - { - name = "ssl-export"; - buildCommand = '' - # Add some indirection, otherwise grepping into the debug output finds the string. - report () { echo CERT_$1_IN_SANDBOX; } - - if [ -f /etc/ssl/certs/ca-certificates.crt ]; then - content=$( $TEST_ROOT/log -grepQuietInverse 'error: renaming' $TEST_ROOT/log -grepQuiet 'may not be deterministic' $TEST_ROOT/log - -# Test that sandboxed builds cannot write to /etc easily -# `100` means build failure without extra info, see doc/manual/src/command-ref/status-build-failure.md -expectStderr 100 nix-sandbox-build -E 'with import ./config.nix; mkDerivation { name = "etc-write"; buildCommand = "echo > /etc/test"; }' | - grepQuiet "/etc/test: Permission denied" - - -## Test mounting of SSL certificates into the sandbox -testCert () { - expectation=$1 # "missing" | "present" - mode=$2 # "normal" | "fixed-output" - certFile=$3 # a string that can be the path to a cert file - # `100` means build failure without extra info, see doc/manual/src/command-ref/status-build-failure.md - [ "$mode" == fixed-output ] && ret=1 || ret=100 - expectStderr $ret nix-sandbox-build linux-sandbox-cert-test.nix --argstr mode "$mode" --option ssl-cert-file "$certFile" | - grepQuiet "CERT_${expectation}_IN_SANDBOX" -} - -nocert=$TEST_ROOT/no-cert-file.pem -cert=$TEST_ROOT/some-cert-file.pem -echo -n "CERT_CONTENT" > $cert - -# No cert in sandbox when not a fixed-output derivation -testCert missing normal "$cert" - -# No cert in sandbox when ssl-cert-file is empty -testCert missing fixed-output "" - -# No cert in sandbox when ssl-cert-file is a nonexistent file -testCert missing fixed-output "$nocert" - -# Cert in sandbox when ssl-cert-file is set to an existing file -testCert present fixed-output "$cert" diff --git a/tests/local-store.sh b/tests/local-store.sh deleted file mode 100644 index 89502f864..000000000 --- a/tests/local-store.sh +++ /dev/null @@ -1,22 +0,0 @@ -source common.sh - -cd $TEST_ROOT - -echo example > example.txt -mkdir -p ./x - -NIX_STORE_DIR=$TEST_ROOT/x - -CORRECT_PATH=$(nix-store --store ./x --add example.txt) - -PATH1=$(nix path-info --store ./x $CORRECT_PATH) -[ $CORRECT_PATH == $PATH1 ] - -PATH2=$(nix path-info --store "$PWD/x" $CORRECT_PATH) -[ $CORRECT_PATH == $PATH2 ] - -PATH3=$(nix path-info --store "local?root=$PWD/x" $CORRECT_PATH) -[ $CORRECT_PATH == $PATH3 ] - -# Ensure store ping trusted works with local store -nix --store ./x store ping --json | jq -e '.trusted' diff --git a/tests/local.mk b/tests/local.mk deleted file mode 100644 index 4edf31303..000000000 --- a/tests/local.mk +++ /dev/null @@ -1,144 +0,0 @@ -nix_tests = \ - test-infra.sh \ - init.sh \ - flakes/flakes.sh \ - flakes/run.sh \ - flakes/mercurial.sh \ - flakes/circular.sh \ - flakes/init.sh \ - flakes/inputs.sh \ - flakes/follow-paths.sh \ - flakes/bundle.sh \ - flakes/check.sh \ - flakes/unlocked-override.sh \ - flakes/absolute-paths.sh \ - flakes/build-paths.sh \ - flakes/flake-in-submodule.sh \ - gc.sh \ - nix-collect-garbage-d.sh \ - remote-store.sh \ - legacy-ssh-store.sh \ - lang.sh \ - lang-test-infra.sh \ - experimental-features.sh \ - fetchMercurial.sh \ - gc-auto.sh \ - user-envs.sh \ - user-envs-migration.sh \ - binary-cache.sh \ - multiple-outputs.sh \ - nix-build.sh \ - gc-concurrent.sh \ - repair.sh \ - fixed.sh \ - export-graph.sh \ - timeout.sh \ - fetchGitRefs.sh \ - gc-runtime.sh \ - tarball.sh \ - fetchGit.sh \ - fetchurl.sh \ - fetchPath.sh \ - fetchTree-file.sh \ - simple.sh \ - referrers.sh \ - optimise-store.sh \ - substitute-with-invalid-ca.sh \ - signing.sh \ - hash.sh \ - gc-non-blocking.sh \ - check.sh \ - nix-shell.sh \ - check-refs.sh \ - build-remote-input-addressed.sh \ - secure-drv-outputs.sh \ - restricted.sh \ - fetchGitSubmodules.sh \ - flakes/search-root.sh \ - readfile-context.sh \ - nix-channel.sh \ - recursive.sh \ - dependencies.sh \ - check-reqs.sh \ - build-remote-content-addressed-fixed.sh \ - build-remote-content-addressed-floating.sh \ - build-remote-trustless-should-pass-0.sh \ - build-remote-trustless-should-pass-1.sh \ - build-remote-trustless-should-pass-2.sh \ - build-remote-trustless-should-pass-3.sh \ - build-remote-trustless-should-fail-0.sh \ - nar-access.sh \ - pure-eval.sh \ - eval.sh \ - repl.sh \ - binary-cache-build-remote.sh \ - search.sh \ - logging.sh \ - export.sh \ - config.sh \ - add.sh \ - local-store.sh \ - filter-source.sh \ - misc.sh \ - dump-db.sh \ - linux-sandbox.sh \ - supplementary-groups.sh \ - build-dry.sh \ - structured-attrs.sh \ - shell.sh \ - brotli.sh \ - zstd.sh \ - compression-levels.sh \ - nix-copy-ssh.sh \ - nix-copy-ssh-ng.sh \ - post-hook.sh \ - function-trace.sh \ - flakes/config.sh \ - fmt.sh \ - eval-store.sh \ - why-depends.sh \ - derivation-json.sh \ - import-derivation.sh \ - nix_path.sh \ - case-hack.sh \ - placeholders.sh \ - ssh-relay.sh \ - plugins.sh \ - build.sh \ - build-delete.sh \ - output-normalization.sh \ - selfref-gc.sh \ - db-migration.sh \ - bash-profile.sh \ - pass-as-file.sh \ - nix-profile.sh \ - suggestions.sh \ - store-ping.sh \ - fetchClosure.sh \ - completions.sh \ - flakes/show.sh \ - impure-derivations.sh \ - path-from-hash-part.sh \ - test-libstoreconsumer.sh \ - toString-path.sh \ - read-only-store.sh \ - nested-sandboxing.sh - -ifeq ($(HAVE_LIBCPUID), 1) - nix_tests += compute-levels.sh -endif - -install-tests += $(foreach x, $(nix_tests), $(d)/$(x)) - -clean-files += \ - $(d)/common/vars-and-functions.sh \ - $(d)/config.nix - -test-deps += \ - tests/common/vars-and-functions.sh \ - tests/config.nix \ - tests/test-libstoreconsumer/test-libstoreconsumer - -ifeq ($(BUILD_SHARED_LIBS), 1) - test-deps += tests/plugins/libplugintest.$(SO_EXT) -endif diff --git a/tests/logging.sh b/tests/logging.sh deleted file mode 100644 index 1481b9b36..000000000 --- a/tests/logging.sh +++ /dev/null @@ -1,26 +0,0 @@ -source common.sh - -clearStore - -path=$(nix-build dependencies.nix --no-out-link) - -# Test nix-store -l. -[ "$(nix-store -l $path)" = FOO ] - -# Test compressed logs. -clearStore -rm -rf $NIX_LOG_DIR -(! nix-store -l $path) -nix-build dependencies.nix --no-out-link --compress-build-log -[ "$(nix-store -l $path)" = FOO ] - -# test whether empty logs work fine with `nix log`. -builder="$(mktemp)" -echo -e "#!/bin/sh\nmkdir \$out" > "$builder" -outp="$(nix-build -E \ - 'with import ./config.nix; mkDerivation { name = "fnord"; builder = '"$builder"'; }' \ - --out-link "$(mktemp -d)/result")" - -test -d "$outp" - -nix log "$outp" diff --git a/tests/misc.sh b/tests/misc.sh deleted file mode 100644 index af96d20bd..000000000 --- a/tests/misc.sh +++ /dev/null @@ -1,32 +0,0 @@ -source common.sh - -# Tests miscellaneous commands. - -# Do all commands have help? -#nix-env --help | grepQuiet install -#nix-store --help | grepQuiet realise -#nix-instantiate --help | grepQuiet eval -#nix-hash --help | grepQuiet base32 - -# Can we ask for the version number? -nix-env --version | grep "$version" - -# Usage errors. -expect 1 nix-env --foo 2>&1 | grep "no operation" -expect 1 nix-env -q --foo 2>&1 | grep "unknown flag" - -# Eval Errors. -eval_arg_res=$(nix-instantiate --eval -E 'let a = {} // a; in a.foo' 2>&1 || true) -echo $eval_arg_res | grep "at «string»:1:15:" -echo $eval_arg_res | grep "infinite recursion encountered" - -eval_stdin_res=$(echo 'let a = {} // a; in a.foo' | nix-instantiate --eval -E - 2>&1 || true) -echo $eval_stdin_res | grep "at «stdin»:1:15:" -echo $eval_stdin_res | grep "infinite recursion encountered" - -# Attribute path errors -expectStderr 1 nix-instantiate --eval -E '{}' -A '"x' | grepQuiet "missing closing quote in selection path" -expectStderr 1 nix-instantiate --eval -E '[]' -A 'x' | grepQuiet "should be a set" -expectStderr 1 nix-instantiate --eval -E '{}' -A '1' | grepQuiet "should be a list" -expectStderr 1 nix-instantiate --eval -E '{}' -A '.' | grepQuiet "empty attribute name" -expectStderr 1 nix-instantiate --eval -E '[]' -A '1' | grepQuiet "out of range" diff --git a/tests/multiple-outputs.nix b/tests/multiple-outputs.nix deleted file mode 100644 index 413d392e4..000000000 --- a/tests/multiple-outputs.nix +++ /dev/null @@ -1,130 +0,0 @@ -with import ./config.nix; - -rec { - - # Want to ensure that "out" doesn't get a suffix on it's path. - nameCheck = mkDerivation { - name = "multiple-outputs-a"; - outputs = [ "out" "dev" ]; - builder = builtins.toFile "builder.sh" - '' - mkdir $first $second - test -z $all - echo "first" > $first/file - echo "second" > $second/file - ln -s $first $second/link - ''; - helloString = "Hello, world!"; - }; - - a = mkDerivation { - name = "multiple-outputs-a"; - outputs = [ "first" "second" ]; - builder = builtins.toFile "builder.sh" - '' - mkdir $first $second - test -z $all - echo "first" > $first/file - echo "second" > $second/file - ln -s $first $second/link - ''; - helloString = "Hello, world!"; - }; - - use-a = mkDerivation { - name = "use-a"; - inherit (a) first second; - builder = builtins.toFile "builder.sh" - '' - cat $first/file $second/file >$out - ''; - }; - - b = mkDerivation { - defaultOutput = assert a.second.helloString == "Hello, world!"; a; - firstOutput = assert a.outputName == "first"; a.first.first; - secondOutput = assert a.second.outputName == "second"; a.second.first.first.second.second.first.second; - allOutputs = a.all; - name = "multiple-outputs-b"; - builder = builtins.toFile "builder.sh" - '' - mkdir $out - test "$firstOutput $secondOutput" = "$allOutputs" - test "$defaultOutput" = "$firstOutput" - test "$(cat $firstOutput/file)" = "first" - test "$(cat $secondOutput/file)" = "second" - echo "success" > $out/file - ''; - }; - - c = mkDerivation { - name = "multiple-outputs-c"; - drv = b.drvPath; - builder = builtins.toFile "builder.sh" - '' - mkdir $out - ln -s $drv $out/drv - ''; - }; - - d = mkDerivation { - name = "multiple-outputs-d"; - drv = builtins.unsafeDiscardOutputDependency b.drvPath; - builder = builtins.toFile "builder.sh" - '' - mkdir $out - echo $drv > $out/drv - ''; - }; - - cyclic = (mkDerivation { - name = "cyclic-outputs"; - outputs = [ "a" "b" "c" ]; - builder = builtins.toFile "builder.sh" - '' - mkdir $a $b $c - echo $a > $b/foo - echo $b > $c/bar - echo $c > $a/baz - ''; - }).a; - - e = mkDerivation { - name = "multiple-outputs-e"; - outputs = [ "a_a" "b" "c" ]; - meta.outputsToInstall = [ "a_a" "b" ]; - buildCommand = "mkdir $a_a $b $c"; - }; - - independent = mkDerivation { - name = "multiple-outputs-independent"; - outputs = [ "first" "second" ]; - builder = builtins.toFile "builder.sh" - '' - mkdir $first $second - test -z $all - echo "first" > $first/file - echo "second" > $second/file - ''; - }; - - use-independent = mkDerivation { - name = "use-independent"; - inherit (a) first second; - builder = builtins.toFile "builder.sh" - '' - cat $first/file $second/file >$out - ''; - }; - - invalid-output-name-1 = mkDerivation { - name = "invalid-output-name-1"; - outputs = [ "out/"]; - }; - - invalid-output-name-2 = mkDerivation { - name = "invalid-output-name-2"; - outputs = [ "x" "foo$"]; - }; - -} diff --git a/tests/multiple-outputs.sh b/tests/multiple-outputs.sh deleted file mode 100644 index 330600d08..000000000 --- a/tests/multiple-outputs.sh +++ /dev/null @@ -1,88 +0,0 @@ -source common.sh - -clearStore - -rm -f $TEST_ROOT/result* - -# Test whether the output names match our expectations -outPath=$(nix-instantiate multiple-outputs.nix --eval -A nameCheck.out.outPath) -[ "$(echo "$outPath" | sed -E 's_^".*/[^-/]*-([^/]*)"$_\1_')" = "multiple-outputs-a" ] -outPath=$(nix-instantiate multiple-outputs.nix --eval -A nameCheck.dev.outPath) -[ "$(echo "$outPath" | sed -E 's_^".*/[^-/]*-([^/]*)"$_\1_')" = "multiple-outputs-a-dev" ] - -# Test whether read-only evaluation works when referring to the -# ‘drvPath’ attribute. -echo "evaluating c..." -#drvPath=$(nix-instantiate multiple-outputs.nix -A c --readonly-mode) - -# And check whether the resulting derivation explicitly depends on all -# outputs. -drvPath=$(nix-instantiate multiple-outputs.nix -A c) -#[ "$drvPath" = "$drvPath2" ] -grepQuiet 'multiple-outputs-a.drv",\["first","second"\]' $drvPath -grepQuiet 'multiple-outputs-b.drv",\["out"\]' $drvPath - -# While we're at it, test the ‘unsafeDiscardOutputDependency’ primop. -outPath=$(nix-build multiple-outputs.nix -A d --no-out-link) -drvPath=$(cat $outPath/drv) -outPath=$(nix-store -q $drvPath) -(! [ -e "$outPath" ]) - -# Do a build of something that depends on a derivation with multiple -# outputs. -echo "building b..." -outPath=$(nix-build multiple-outputs.nix -A b --no-out-link) -echo "output path is $outPath" -[ "$(cat "$outPath"/file)" = "success" ] - -# Test nix-build on a derivation with multiple outputs. -outPath1=$(nix-build multiple-outputs.nix -A a -o $TEST_ROOT/result) -[ -e $TEST_ROOT/result-first ] -(! [ -e $TEST_ROOT/result-second ]) -nix-build multiple-outputs.nix -A a.all -o $TEST_ROOT/result -[ "$(cat $TEST_ROOT/result-first/file)" = "first" ] -[ "$(cat $TEST_ROOT/result-second/file)" = "second" ] -[ "$(cat $TEST_ROOT/result-second/link/file)" = "first" ] -hash1=$(nix-store -q --hash $TEST_ROOT/result-second) - -outPath2=$(nix-build $(nix-instantiate multiple-outputs.nix -A a) --no-out-link) -[[ $outPath1 = $outPath2 ]] - -outPath2=$(nix-build $(nix-instantiate multiple-outputs.nix -A a.first) --no-out-link) -[[ $outPath1 = $outPath2 ]] - -outPath2=$(nix-build $(nix-instantiate multiple-outputs.nix -A a.second) --no-out-link) -[[ $(cat $outPath2/file) = second ]] - -[[ $(nix-build $(nix-instantiate multiple-outputs.nix -A a.all) --no-out-link | wc -l) -eq 2 ]] - -# Delete one of the outputs and rebuild it. This will cause a hash -# rewrite. -env -u NIX_REMOTE nix store delete $TEST_ROOT/result-second --ignore-liveness -nix-build multiple-outputs.nix -A a.all -o $TEST_ROOT/result -[ "$(cat $TEST_ROOT/result-second/file)" = "second" ] -[ "$(cat $TEST_ROOT/result-second/link/file)" = "first" ] -hash2=$(nix-store -q --hash $TEST_ROOT/result-second) -[ "$hash1" = "$hash2" ] - -# Make sure that nix-build works on derivations with multiple outputs. -echo "building a.first..." -nix-build multiple-outputs.nix -A a.first --no-out-link - -# Cyclic outputs should be rejected. -echo "building cyclic..." -if nix-build multiple-outputs.nix -A cyclic --no-out-link; then - echo "Cyclic outputs incorrectly accepted!" - exit 1 -fi - -# Do a GC. This should leave an empty store. -echo "collecting garbage..." -rm $TEST_ROOT/result* -nix-store --gc --keep-derivations --keep-outputs -nix-store --gc --print-roots -rm -rf $NIX_STORE_DIR/.links -rmdir $NIX_STORE_DIR - -expect 1 nix build -f multiple-outputs.nix invalid-output-name-1 2>&1 | grep 'contains illegal character' -expect 1 nix build -f multiple-outputs.nix invalid-output-name-2 2>&1 | grep 'contains illegal character' diff --git a/tests/nar-access.nix b/tests/nar-access.nix deleted file mode 100644 index 0e2a7f721..000000000 --- a/tests/nar-access.nix +++ /dev/null @@ -1,23 +0,0 @@ -with import ./config.nix; - -rec { - a = mkDerivation { - name = "nar-index-a"; - builder = builtins.toFile "builder.sh" - '' - mkdir $out - mkdir $out/foo - touch $out/foo-x - touch $out/foo/bar - touch $out/foo/baz - touch $out/qux - mkdir $out/zyx - - cat >$out/foo/data < $narFile - -# Check that find and nar ls match. -( cd $storePath; find . | sort ) > files.find -nix nar ls -R -d $narFile "" | sort > files.ls-nar -diff -u files.find files.ls-nar - -# Check that file contents of data match. -nix nar cat $narFile /foo/data > data.cat-nar -diff -u data.cat-nar $storePath/foo/data - -# Check that file contents of baz match. -nix nar cat $narFile /foo/baz > baz.cat-nar -diff -u baz.cat-nar $storePath/foo/baz - -nix store cat $storePath/foo/baz > baz.cat-nar -diff -u baz.cat-nar $storePath/foo/baz - -# Test --json. -diff -u \ - <(nix nar ls --json $narFile / | jq -S) \ - <(echo '{"type":"directory","entries":{"foo":{},"foo-x":{},"qux":{},"zyx":{}}}' | jq -S) -diff -u \ - <(nix nar ls --json -R $narFile /foo | jq -S) \ - <(echo '{"type":"directory","entries":{"bar":{"type":"regular","size":0,"narOffset":368},"baz":{"type":"regular","size":0,"narOffset":552},"data":{"type":"regular","size":58,"narOffset":736}}}' | jq -S) -diff -u \ - <(nix nar ls --json -R $narFile /foo/bar | jq -S) \ - <(echo '{"type":"regular","size":0,"narOffset":368}' | jq -S) -diff -u \ - <(nix store ls --json $storePath | jq -S) \ - <(echo '{"type":"directory","entries":{"foo":{},"foo-x":{},"qux":{},"zyx":{}}}' | jq -S) -diff -u \ - <(nix store ls --json -R $storePath/foo | jq -S) \ - <(echo '{"type":"directory","entries":{"bar":{"type":"regular","size":0},"baz":{"type":"regular","size":0},"data":{"type":"regular","size":58}}}' | jq -S) -diff -u \ - <(nix store ls --json -R $storePath/foo/bar| jq -S) \ - <(echo '{"type":"regular","size":0}' | jq -S) - -# Test missing files. -expect 1 nix store ls --json -R $storePath/xyzzy 2>&1 | grep 'does not exist in NAR' -expect 1 nix store ls $storePath/xyzzy 2>&1 | grep 'does not exist' - -# Test failure to dump. -if nix-store --dump $storePath >/dev/full ; then - echo "dumping to /dev/full should fail" - exit -1 -fi diff --git a/tests/nested-sandboxing.sh b/tests/nested-sandboxing.sh deleted file mode 100644 index d9fa788aa..000000000 --- a/tests/nested-sandboxing.sh +++ /dev/null @@ -1,11 +0,0 @@ -source common.sh -# This test is run by `tests/nested-sandboxing/runner.nix` in an extra layer of sandboxing. -[[ -d /nix/store ]] || skipTest "running this test without Nix's deps being drawn from /nix/store is not yet supported" - -requireSandboxSupport - -source ./nested-sandboxing/command.sh - -expectStderr 100 runNixBuild badStoreUrl 2 | grepQuiet '`sandbox-build-dir` must not contain' - -runNixBuild goodStoreUrl 5 diff --git a/tests/nested-sandboxing/command.sh b/tests/nested-sandboxing/command.sh deleted file mode 100644 index 69366486c..000000000 --- a/tests/nested-sandboxing/command.sh +++ /dev/null @@ -1,29 +0,0 @@ -export NIX_BIN_DIR=$(dirname $(type -p nix)) -# TODO Get Nix and its closure more flexibly -export EXTRA_SANDBOX="/nix/store $(dirname $NIX_BIN_DIR)" - -badStoreUrl () { - local altitude=$1 - echo $TEST_ROOT/store-$altitude -} - -goodStoreUrl () { - local altitude=$1 - echo $("badStoreUrl" "$altitude")?store=/foo-$altitude -} - -# The non-standard sandbox-build-dir helps ensure that we get the same behavior -# whether this test is being run in a derivation as part of the nix build or -# being manually run by a developer outside a derivation -runNixBuild () { - local storeFun=$1 - local altitude=$2 - nix-build \ - --no-substitute --no-out-link \ - --store "$("$storeFun" "$altitude")" \ - --extra-sandbox-paths "$EXTRA_SANDBOX" \ - ./nested-sandboxing/runner.nix \ - --arg altitude "$((altitude - 1))" \ - --argstr storeFun "$storeFun" \ - --sandbox-build-dir /build-non-standard -} diff --git a/tests/nested-sandboxing/runner.nix b/tests/nested-sandboxing/runner.nix deleted file mode 100644 index 9a5822c88..000000000 --- a/tests/nested-sandboxing/runner.nix +++ /dev/null @@ -1,24 +0,0 @@ -{ altitude, storeFun }: - -with import ../config.nix; - -mkDerivation { - name = "nested-sandboxing"; - busybox = builtins.getEnv "busybox"; - EXTRA_SANDBOX = builtins.getEnv "EXTRA_SANDBOX"; - buildCommand = if altitude == 0 then '' - echo Deep enough! > $out - '' else '' - cp -r ${../common} ./common - cp ${../common.sh} ./common.sh - cp ${../config.nix} ./config.nix - cp -r ${./.} ./nested-sandboxing - - export PATH=${builtins.getEnv "NIX_BIN_DIR"}:$PATH - - source common.sh - source ./nested-sandboxing/command.sh - - runNixBuild ${storeFun} ${toString altitude} >> $out - ''; -} diff --git a/tests/nix-build-examples.nix b/tests/nix-build-examples.nix deleted file mode 100644 index e54dbbf62..000000000 --- a/tests/nix-build-examples.nix +++ /dev/null @@ -1,33 +0,0 @@ -with import ./config.nix; - -rec { - - input0 = mkDerivation { - name = "dependencies-input-0"; - buildCommand = "mkdir $out; echo foo > $out/bar"; - }; - - input1 = mkDerivation { - name = "dependencies-input-1"; - buildCommand = "mkdir $out; echo FOO > $out/foo"; - }; - - input2 = mkDerivation { - name = "dependencies-input-2"; - buildCommand = '' - mkdir $out - echo BAR > $out/bar - echo ${input0} > $out/input0 - ''; - }; - - body = mkDerivation { - name = "dependencies-top"; - builder = ./dependencies.builder0.sh + "/FOOBAR/../."; - input1 = input1 + "/."; - input2 = "${input2}/."; - input1_drv = input1; - meta.description = "Random test package"; - }; - -} diff --git a/tests/nix-build.sh b/tests/nix-build.sh deleted file mode 100644 index 44a5a14cd..000000000 --- a/tests/nix-build.sh +++ /dev/null @@ -1,43 +0,0 @@ -source common.sh - -clearStore - -outPath=$(nix-build dependencies.nix -o $TEST_ROOT/result) -test "$(cat $TEST_ROOT/result/foobar)" = FOOBAR - -# The result should be retained by a GC. -echo A -target=$(readLink $TEST_ROOT/result) -echo B -echo target is $target -nix-store --gc -test -e $target/foobar - -# But now it should be gone. -rm $TEST_ROOT/result -nix-store --gc -if test -e $target/foobar; then false; fi - -outPath2=$(nix-build $(nix-instantiate dependencies.nix) --no-out-link) -[[ $outPath = $outPath2 ]] - -outPath2=$(nix-build $(nix-instantiate dependencies.nix)!out --no-out-link) -[[ $outPath = $outPath2 ]] - -outPath2=$(nix-store -r $(nix-instantiate --add-root $TEST_ROOT/indirect dependencies.nix)!out) -[[ $outPath = $outPath2 ]] - -# The order of the paths on stdout must correspond to the -A options -# https://github.com/NixOS/nix/issues/4197 - -input0="$(nix-build nix-build-examples.nix -A input0 --no-out-link)" -input1="$(nix-build nix-build-examples.nix -A input1 --no-out-link)" -input2="$(nix-build nix-build-examples.nix -A input2 --no-out-link)" -body="$(nix-build nix-build-examples.nix -A body --no-out-link)" - -outPathsA="$(echo $(nix-build nix-build-examples.nix -A input0 -A input1 -A input2 -A body --no-out-link))" -[[ "$outPathsA" = "$input0 $input1 $input2 $body" ]] - -# test a different ordering to make sure it fails, not just in 23 out of 24 permutations -outPathsB="$(echo $(nix-build nix-build-examples.nix -A body -A input1 -A input2 -A input0 --no-out-link))" -[[ "$outPathsB" = "$body $input1 $input2 $input0" ]] diff --git a/tests/nix-channel.sh b/tests/nix-channel.sh deleted file mode 100644 index b5d935004..000000000 --- a/tests/nix-channel.sh +++ /dev/null @@ -1,66 +0,0 @@ -source common.sh - -clearProfiles - -rm -f $TEST_HOME/.nix-channels $TEST_HOME/.nix-profile - -# Test add/list/remove. -nix-channel --add http://foo/bar xyzzy -nix-channel --list | grepQuiet http://foo/bar -nix-channel --remove xyzzy -[[ $(nix-channel --list-generations | wc -l) == 1 ]] - -[ -e $TEST_HOME/.nix-channels ] -[ "$(cat $TEST_HOME/.nix-channels)" = '' ] - -# Test the XDG Base Directories support - -export NIX_CONFIG="use-xdg-base-directories = true" - -nix-channel --add http://foo/bar xyzzy -nix-channel --list | grepQuiet http://foo/bar -nix-channel --remove xyzzy - -unset NIX_CONFIG - -[ -e $TEST_HOME/.local/state/nix/channels ] -[ "$(cat $TEST_HOME/.local/state/nix/channels)" = '' ] - -# Create a channel. -rm -rf $TEST_ROOT/foo -mkdir -p $TEST_ROOT/foo -nix copy --to file://$TEST_ROOT/foo?compression="bzip2" $(nix-store -r $(nix-instantiate dependencies.nix)) -rm -rf $TEST_ROOT/nixexprs -mkdir -p $TEST_ROOT/nixexprs -cp config.nix dependencies.nix dependencies.builder*.sh $TEST_ROOT/nixexprs/ -ln -s dependencies.nix $TEST_ROOT/nixexprs/default.nix -(cd $TEST_ROOT && tar cvf - nixexprs) | bzip2 > $TEST_ROOT/foo/nixexprs.tar.bz2 - -# Test the update action. -nix-channel --add file://$TEST_ROOT/foo -nix-channel --update -[[ $(nix-channel --list-generations | wc -l) == 2 ]] - -# Do a query. -nix-env -qa \* --meta --xml --out-path > $TEST_ROOT/meta.xml -grepQuiet 'meta.*description.*Random test package' $TEST_ROOT/meta.xml -grepQuiet 'item.*attrPath="foo".*name="dependencies-top"' $TEST_ROOT/meta.xml - -# Do an install. -nix-env -i dependencies-top -[ -e $TEST_HOME/.nix-profile/foobar ] - -# Test updating from a tarball -nix-channel --add file://$TEST_ROOT/foo/nixexprs.tar.bz2 bar -nix-channel --update - -# Do a query. -nix-env -qa \* --meta --xml --out-path > $TEST_ROOT/meta.xml -grepQuiet 'meta.*description.*Random test package' $TEST_ROOT/meta.xml -grepQuiet 'item.*attrPath="bar".*name="dependencies-top"' $TEST_ROOT/meta.xml -grepQuiet 'item.*attrPath="foo".*name="dependencies-top"' $TEST_ROOT/meta.xml - -# Do an install. -nix-env -i dependencies-top -[ -e $TEST_HOME/.nix-profile/foobar ] - diff --git a/tests/nix-collect-garbage-d.sh b/tests/nix-collect-garbage-d.sh deleted file mode 100644 index bf30f8938..000000000 --- a/tests/nix-collect-garbage-d.sh +++ /dev/null @@ -1,40 +0,0 @@ -source common.sh - -clearStore - -## Test `nix-collect-garbage -d` - -# TODO make `nix-env` doesn't work with CA derivations, and make -# `ca/nix-collect-garbage-d.sh` wrapper. - -testCollectGarbageD () { - clearProfiles - # Run two `nix-env` commands, should create two generations of - # the profile - nix-env -f ./user-envs.nix -i foo-1.0 "$@" - nix-env -f ./user-envs.nix -i foo-2.0pre1 "$@" - [[ $(nix-env --list-generations "$@" | wc -l) -eq 2 ]] - - # Clear the profile history. There should be only one generation - # left - nix-collect-garbage -d - [[ $(nix-env --list-generations "$@" | wc -l) -eq 1 ]] -} - -testCollectGarbageD - -# Run the same test, but forcing the profiles an arbitrary location. -rm ~/.nix-profile -ln -s $TEST_ROOT/blah ~/.nix-profile -testCollectGarbageD - -# Run the same test, but forcing the profiles at their legacy location under -# /nix/var/nix. -# -# Note that we *don't* use the default profile; `nix-collect-garbage` will -# need to check the legacy conditional unconditionally not just follow -# `~/.nix-profile` to pass this test. -# -# Regression test for #8294 -rm ~/.nix-profile -testCollectGarbageD --profile "$NIX_STATE_DIR/profiles/per-user/me" diff --git a/tests/nix-copy-ssh-ng.sh b/tests/nix-copy-ssh-ng.sh deleted file mode 100644 index 45e53c9c0..000000000 --- a/tests/nix-copy-ssh-ng.sh +++ /dev/null @@ -1,18 +0,0 @@ -source common.sh - -clearStore -clearCache - -remoteRoot=$TEST_ROOT/store2 -chmod -R u+w "$remoteRoot" || true -rm -rf "$remoteRoot" - -outPath=$(nix-build --no-out-link dependencies.nix) - -nix store ping --store "ssh-ng://localhost?store=$NIX_STORE_DIR&remote-store=$remoteRoot%3fstore=$NIX_STORE_DIR%26real=$remoteRoot$NIX_STORE_DIR" - -# Regression test for https://github.com/NixOS/nix/issues/6253 -nix copy --to "ssh-ng://localhost?store=$NIX_STORE_DIR&remote-store=$remoteRoot%3fstore=$NIX_STORE_DIR%26real=$remoteRoot$NIX_STORE_DIR" $outPath --no-check-sigs & -nix copy --to "ssh-ng://localhost?store=$NIX_STORE_DIR&remote-store=$remoteRoot%3fstore=$NIX_STORE_DIR%26real=$remoteRoot$NIX_STORE_DIR" $outPath --no-check-sigs - -[ -f $remoteRoot$outPath/foobar ] diff --git a/tests/nix-copy-ssh.sh b/tests/nix-copy-ssh.sh deleted file mode 100644 index eb801548d..000000000 --- a/tests/nix-copy-ssh.sh +++ /dev/null @@ -1,20 +0,0 @@ -source common.sh - -clearStore -clearCache - -remoteRoot=$TEST_ROOT/store2 -chmod -R u+w "$remoteRoot" || true -rm -rf "$remoteRoot" - -outPath=$(nix-build --no-out-link dependencies.nix) - -nix copy --to "ssh://localhost?store=$NIX_STORE_DIR&remote-store=$remoteRoot%3fstore=$NIX_STORE_DIR%26real=$remoteRoot$NIX_STORE_DIR" $outPath - -[ -f $remoteRoot$outPath/foobar ] - -clearStore - -nix copy --no-check-sigs --from "ssh://localhost?store=$NIX_STORE_DIR&remote-store=$remoteRoot%3fstore=$NIX_STORE_DIR%26real=$remoteRoot$NIX_STORE_DIR" $outPath - -[ -f $outPath/foobar ] diff --git a/tests/nix-daemon-untrusting.sh b/tests/nix-daemon-untrusting.sh deleted file mode 100755 index bcdb70989..000000000 --- a/tests/nix-daemon-untrusting.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -exec nix-daemon --force-untrusted "$@" diff --git a/tests/nix-profile.sh b/tests/nix-profile.sh deleted file mode 100644 index 7c478a0cd..000000000 --- a/tests/nix-profile.sh +++ /dev/null @@ -1,187 +0,0 @@ -source common.sh - -clearStore -clearProfiles - -enableFeatures "ca-derivations" -restartDaemon - -# Make a flake. -flake1Dir=$TEST_ROOT/flake1 -mkdir -p $flake1Dir - -cat > $flake1Dir/flake.nix < \$out/bin/hello < $flake1Dir/who -printf 1.0 > $flake1Dir/version -printf false > $flake1Dir/ca.nix - -cp ./config.nix $flake1Dir/ - -# Test upgrading from nix-env. -nix-env -f ./user-envs.nix -i foo-1.0 -nix profile list | grep -A2 'Index:.*0' | grep 'Store paths:.*foo-1.0' -nix profile install $flake1Dir -L -nix profile list | grep -A4 'Index:.*1' | grep 'Locked flake URL:.*narHash' -[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello World" ]] -[ -e $TEST_HOME/.nix-profile/share/man ] -(! [ -e $TEST_HOME/.nix-profile/include ]) -nix profile history -nix profile history | grep "packages.$system.default: ∅ -> 1.0" -nix profile diff-closures | grep 'env-manifest.nix: ε → ∅' - -# Test XDG Base Directories support - -export NIX_CONFIG="use-xdg-base-directories = true" -nix profile remove 1 -nix profile install $flake1Dir -[[ $($TEST_HOME/.local/state/nix/profile/bin/hello) = "Hello World" ]] -unset NIX_CONFIG - -# Test upgrading a package. -printf NixOS > $flake1Dir/who -printf 2.0 > $flake1Dir/version -nix profile upgrade 1 -[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello NixOS" ]] -nix profile history | grep "packages.$system.default: 1.0, 1.0-man -> 2.0, 2.0-man" - -# Test 'history', 'diff-closures'. -nix profile diff-closures - -# Test rollback. -nix profile rollback -[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello World" ]] - -# Test uninstall. -[ -e $TEST_HOME/.nix-profile/bin/foo ] -nix profile remove 0 -(! [ -e $TEST_HOME/.nix-profile/bin/foo ]) -nix profile history | grep 'foo: 1.0 -> ∅' -nix profile diff-closures | grep 'Version 3 -> 4' - -# Test installing a non-flake package. -nix profile install --file ./simple.nix '' -[[ $(cat $TEST_HOME/.nix-profile/hello) = "Hello World!" ]] -nix profile remove 1 -nix profile install $(nix-build --no-out-link ./simple.nix) -[[ $(cat $TEST_HOME/.nix-profile/hello) = "Hello World!" ]] - -# Test wipe-history. -nix profile wipe-history -[[ $(nix profile history | grep Version | wc -l) -eq 1 ]] - -# Test upgrade to CA package. -printf true > $flake1Dir/ca.nix -printf 3.0 > $flake1Dir/version -nix profile upgrade 0 -nix profile history | grep "packages.$system.default: 1.0, 1.0-man -> 3.0, 3.0-man" - -# Test new install of CA package. -nix profile remove 0 -printf 4.0 > $flake1Dir/version -printf Utrecht > $flake1Dir/who -nix profile install $flake1Dir -[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello Utrecht" ]] -[[ $(nix path-info --json $(realpath $TEST_HOME/.nix-profile/bin/hello) | jq -r .[].ca) =~ fixed:r:sha256: ]] - -# Override the outputs. -nix profile remove 0 1 -nix profile install "$flake1Dir^*" -[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello Utrecht" ]] -[ -e $TEST_HOME/.nix-profile/share/man ] -[ -e $TEST_HOME/.nix-profile/include ] - -printf Nix > $flake1Dir/who -nix profile upgrade 0 -[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello Nix" ]] -[ -e $TEST_HOME/.nix-profile/share/man ] -[ -e $TEST_HOME/.nix-profile/include ] - -nix profile remove 0 -nix profile install "$flake1Dir^man" -(! [ -e $TEST_HOME/.nix-profile/bin/hello ]) -[ -e $TEST_HOME/.nix-profile/share/man ] -(! [ -e $TEST_HOME/.nix-profile/include ]) - -# test priority -nix profile remove 0 - -# Make another flake. -flake2Dir=$TEST_ROOT/flake2 -printf World > $flake1Dir/who -cp -r $flake1Dir $flake2Dir -printf World2 > $flake2Dir/who - -nix profile install $flake1Dir -[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello World" ]] -expect 1 nix profile install $flake2Dir -diff -u <( - nix --offline profile install $flake2Dir 2>&1 1> /dev/null \ - | grep -vE "^warning: " \ - | grep -vE "^error \(ignored\): " \ - || true -) <(cat << EOF -error: An existing package already provides the following file: - - $(nix build --no-link --print-out-paths ${flake1Dir}"#default.out")/bin/hello - - This is the conflicting file from the new package: - - $(nix build --no-link --print-out-paths ${flake2Dir}"#default.out")/bin/hello - - To remove the existing package: - - nix profile remove path:${flake1Dir}#packages.${system}.default - - The new package can also be installed next to the existing one by assigning a different priority. - The conflicting packages have a priority of 5. - To prioritise the new package: - - nix profile install path:${flake2Dir}#packages.${system}.default --priority 4 - - To prioritise the existing package: - - nix profile install path:${flake2Dir}#packages.${system}.default --priority 6 -EOF -) -[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello World" ]] -nix profile install $flake2Dir --priority 100 -[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello World" ]] -nix profile install $flake2Dir --priority 0 -[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello World2" ]] -# nix profile install $flake1Dir --priority 100 -# [[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello World" ]] - -# Ensure that conflicts are handled properly even when the installables aren't -# flake references. -# Regression test for https://github.com/NixOS/nix/issues/8284 -clearProfiles -nix profile install $(nix build $flake1Dir --no-link --print-out-paths) -expect 1 nix profile install --impure --expr "(builtins.getFlake ''$flake2Dir'').packages.$system.default" diff --git a/tests/nix-shell.sh b/tests/nix-shell.sh deleted file mode 100644 index edaa1249b..000000000 --- a/tests/nix-shell.sh +++ /dev/null @@ -1,147 +0,0 @@ -source common.sh - -clearStore - -if [[ -n ${CONTENT_ADDRESSED:-} ]]; then - shellDotNix="$PWD/ca-shell.nix" -else - shellDotNix="$PWD/shell.nix" -fi - -export NIX_PATH=nixpkgs="$shellDotNix" - -# Test nix-shell -A -export IMPURE_VAR=foo -export SELECTED_IMPURE_VAR=baz - -output=$(nix-shell --pure "$shellDotNix" -A shellDrv --run \ - 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $TEST_inNixShell"') - -[ "$output" = " - foo - bar - true" ] - -# Test --keep -output=$(nix-shell --pure --keep SELECTED_IMPURE_VAR "$shellDotNix" -A shellDrv --run \ - 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $SELECTED_IMPURE_VAR"') - -[ "$output" = " - foo - bar - baz" ] - -# Test nix-shell on a .drv -[[ $(nix-shell --pure $(nix-instantiate "$shellDotNix" -A shellDrv) --run \ - 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $TEST_inNixShell"') = " - foo - bar - false" ]] - -[[ $(nix-shell --pure $(nix-instantiate "$shellDotNix" -A shellDrv) --run \ - 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $TEST_inNixShell"') = " - foo - bar - false" ]] - -# Test nix-shell on a .drv symlink - -# Legacy: absolute path and .drv extension required -nix-instantiate "$shellDotNix" -A shellDrv --add-root $TEST_ROOT/shell.drv -[[ $(nix-shell --pure $TEST_ROOT/shell.drv --run \ - 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX"') = " - foo - bar" ]] - -# New behaviour: just needs to resolve to a derivation in the store -nix-instantiate "$shellDotNix" -A shellDrv --add-root $TEST_ROOT/shell -[[ $(nix-shell --pure $TEST_ROOT/shell --run \ - 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX"') = " - foo - bar" ]] - -# Test nix-shell -p -output=$(NIX_PATH=nixpkgs="$shellDotNix" nix-shell --pure -p foo bar --run 'echo "$(foo) $(bar)"') -[ "$output" = "foo bar" ] - -# Test nix-shell -p --arg x y -output=$(NIX_PATH=nixpkgs="$shellDotNix" nix-shell --pure -p foo --argstr fooContents baz --run 'echo "$(foo)"') -[ "$output" = "baz" ] - -# Test nix-shell shebang mode -sed -e "s|@ENV_PROG@|$(type -P env)|" shell.shebang.sh > $TEST_ROOT/shell.shebang.sh -chmod a+rx $TEST_ROOT/shell.shebang.sh - -output=$($TEST_ROOT/shell.shebang.sh abc def) -[ "$output" = "foo bar abc def" ] - -# Test nix-shell shebang mode again with metacharacters in the filename. -# First word of filename is chosen to not match any file in the test root. -sed -e "s|@ENV_PROG@|$(type -P env)|" shell.shebang.sh > $TEST_ROOT/spaced\ \\\'\"shell.shebang.sh -chmod a+rx $TEST_ROOT/spaced\ \\\'\"shell.shebang.sh - -output=$($TEST_ROOT/spaced\ \\\'\"shell.shebang.sh abc def) -[ "$output" = "foo bar abc def" ] - -# Test nix-shell shebang mode for ruby -# This uses a fake interpreter that returns the arguments passed -# This, in turn, verifies the `rc` script is valid and the `load()` script (given using `-e`) is as expected. -sed -e "s|@SHELL_PROG@|$(type -P nix-shell)|" shell.shebang.rb > $TEST_ROOT/shell.shebang.rb -chmod a+rx $TEST_ROOT/shell.shebang.rb - -output=$($TEST_ROOT/shell.shebang.rb abc ruby) -[ "$output" = '-e load(ARGV.shift) -- '"$TEST_ROOT"'/shell.shebang.rb abc ruby' ] - -# Test nix-shell shebang mode for ruby again with metacharacters in the filename. -# Note: fake interpreter only space-separates args without adding escapes to its output. -sed -e "s|@SHELL_PROG@|$(type -P nix-shell)|" shell.shebang.rb > $TEST_ROOT/spaced\ \\\'\"shell.shebang.rb -chmod a+rx $TEST_ROOT/spaced\ \\\'\"shell.shebang.rb - -output=$($TEST_ROOT/spaced\ \\\'\"shell.shebang.rb abc ruby) -[ "$output" = '-e load(ARGV.shift) -- '"$TEST_ROOT"'/spaced \'\''"shell.shebang.rb abc ruby' ] - -# Test 'nix develop'. -nix develop -f "$shellDotNix" shellDrv -c bash -c '[[ -n $stdenv ]]' - -# Ensure `nix develop -c` preserves stdin -echo foo | nix develop -f "$shellDotNix" shellDrv -c cat | grepQuiet foo - -# Ensure `nix develop -c` actually executes the command if stdout isn't a terminal -nix develop -f "$shellDotNix" shellDrv -c echo foo |& grepQuiet foo - -# Test 'nix print-dev-env'. - -nix print-dev-env -f "$shellDotNix" shellDrv > $TEST_ROOT/dev-env.sh -nix print-dev-env -f "$shellDotNix" shellDrv --json > $TEST_ROOT/dev-env.json - -# Test with raw drv - -shellDrv=$(nix-instantiate "$shellDotNix" -A shellDrv.out) - -nix develop $shellDrv -c bash -c '[[ -n $stdenv ]]' - -nix print-dev-env $shellDrv > $TEST_ROOT/dev-env2.sh -nix print-dev-env $shellDrv --json > $TEST_ROOT/dev-env2.json - -diff $TEST_ROOT/dev-env{,2}.sh -diff $TEST_ROOT/dev-env{,2}.json - -# Ensure `nix print-dev-env --json` contains variable assignments. -[[ $(jq -r .variables.arr1.value[2] $TEST_ROOT/dev-env.json) = '3 4' ]] - -# Run tests involving `source <(nix print-dev-inv)` in subshells to avoid modifying the current -# environment. - -set +u # FIXME: Make print-dev-env `set -u` compliant (issue #7951) - -# Ensure `source <(nix print-dev-env)` modifies the environment. -( - path=$PATH - source $TEST_ROOT/dev-env.sh - [[ -n $stdenv ]] - [[ ${arr1[2]} = "3 4" ]] - [[ ${arr2[1]} = $'\n' ]] - [[ ${arr2[2]} = $'x\ny' ]] - [[ $(fun) = blabla ]] - [[ $PATH = $(jq -r .variables.PATH.value $TEST_ROOT/dev-env.json):$path ]] -) - -# Ensure `source <(nix print-dev-env)` handles the case when PATH is empty. -( - path=$PATH - PATH= - source $TEST_ROOT/dev-env.sh - [[ $PATH = $(PATH=$path jq -r .variables.PATH.value $TEST_ROOT/dev-env.json) ]] -) - -# Test nix-shell with ellipsis and no `inNixShell` argument (for backwards compat with old nixpkgs) -cat >$TEST_ROOT/shell-ellipsis.nix <' --restrict-eval -nix-instantiate --eval -E '' --restrict-eval - -# Should ideally also test this, but there’s no pure way to do it, so just trust me that it works -# nix-instantiate --eval -E '' -I nixpkgs=channel:nixos-unstable --restrict-eval - -[[ $(nix-instantiate --find-file by-absolute-path/simple.nix) = $PWD/simple.nix ]] -[[ $(nix-instantiate --find-file by-relative-path/simple.nix) = $PWD/simple.nix ]] diff --git a/tests/optimise-store.sh b/tests/optimise-store.sh deleted file mode 100644 index 8c2d05cd5..000000000 --- a/tests/optimise-store.sh +++ /dev/null @@ -1,44 +0,0 @@ -source common.sh - -clearStore - -outPath1=$(echo 'with import ./config.nix; mkDerivation { name = "foo1"; builder = builtins.toFile "builder" "mkdir $out; echo hello > $out/foo"; }' | nix-build - --no-out-link --auto-optimise-store) -outPath2=$(echo 'with import ./config.nix; mkDerivation { name = "foo2"; builder = builtins.toFile "builder" "mkdir $out; echo hello > $out/foo"; }' | nix-build - --no-out-link --auto-optimise-store) - -inode1="$(stat --format=%i $outPath1/foo)" -inode2="$(stat --format=%i $outPath2/foo)" -if [ "$inode1" != "$inode2" ]; then - echo "inodes do not match" - exit 1 -fi - -nlink="$(stat --format=%h $outPath1/foo)" -if [ "$nlink" != 3 ]; then - echo "link count incorrect" - exit 1 -fi - -outPath3=$(echo 'with import ./config.nix; mkDerivation { name = "foo3"; builder = builtins.toFile "builder" "mkdir $out; echo hello > $out/foo"; }' | nix-build - --no-out-link) - -inode3="$(stat --format=%i $outPath3/foo)" -if [ "$inode1" = "$inode3" ]; then - echo "inodes match unexpectedly" - exit 1 -fi - -# XXX: This should work through the daemon too -NIX_REMOTE="" nix-store --optimise - -inode1="$(stat --format=%i $outPath1/foo)" -inode3="$(stat --format=%i $outPath3/foo)" -if [ "$inode1" != "$inode3" ]; then - echo "inodes do not match" - exit 1 -fi - -nix-store --gc - -if [ -n "$(ls $NIX_STORE_DIR/.links)" ]; then - echo ".links directory not empty after GC" - exit 1 -fi diff --git a/tests/output-normalization.sh b/tests/output-normalization.sh deleted file mode 100644 index 0f6df5e31..000000000 --- a/tests/output-normalization.sh +++ /dev/null @@ -1,9 +0,0 @@ -source common.sh - -testNormalization () { - clearStore - outPath=$(nix-build ./simple.nix --no-out-link) - test "$(stat -c %Y $outPath)" -eq 1 -} - -testNormalization diff --git a/tests/parallel.builder.sh b/tests/parallel.builder.sh deleted file mode 100644 index d092bc5a6..000000000 --- a/tests/parallel.builder.sh +++ /dev/null @@ -1,29 +0,0 @@ -echo "DOING $text" - - -# increase counter -while ! ln -s x $shared.lock 2> /dev/null; do - sleep 1 -done -test -f $shared.cur || echo 0 > $shared.cur -test -f $shared.max || echo 0 > $shared.max -new=$(($(cat $shared.cur) + 1)) -if test $new -gt $(cat $shared.max); then - echo $new > $shared.max -fi -echo $new > $shared.cur -rm $shared.lock - - -echo -n $(cat $inputs)$text > $out - -sleep $sleepTime - - -# decrease counter -while ! ln -s x $shared.lock 2> /dev/null; do - sleep 1 -done -test -f $shared.cur || echo 0 > $shared.cur -echo $(($(cat $shared.cur) - 1)) > $shared.cur -rm $shared.lock diff --git a/tests/parallel.nix b/tests/parallel.nix deleted file mode 100644 index 23f142059..000000000 --- a/tests/parallel.nix +++ /dev/null @@ -1,19 +0,0 @@ -{sleepTime ? 3}: - -with import ./config.nix; - -let - - mkDrv = text: inputs: mkDerivation { - name = "parallel"; - builder = ./parallel.builder.sh; - inherit text inputs shared sleepTime; - }; - - a = mkDrv "a" []; - b = mkDrv "b" [a]; - c = mkDrv "c" [a]; - d = mkDrv "d" [a]; - e = mkDrv "e" [b c d]; - -in e diff --git a/tests/parallel.sh b/tests/parallel.sh deleted file mode 100644 index 3b7bbe5a2..000000000 --- a/tests/parallel.sh +++ /dev/null @@ -1,56 +0,0 @@ -source common.sh - - -# First, test that -jN performs builds in parallel. -echo "testing nix-build -j..." - -clearStore - -rm -f $_NIX_TEST_SHARED.cur $_NIX_TEST_SHARED.max - -outPath=$(nix-build -j10000 parallel.nix --no-out-link) - -echo "output path is $outPath" - -text=$(cat "$outPath") -if test "$text" != "abacade"; then exit 1; fi - -if test "$(cat $_NIX_TEST_SHARED.cur)" != 0; then fail "wrong current process count"; fi -if test "$(cat $_NIX_TEST_SHARED.max)" != 3; then fail "not enough parallelism"; fi - - -# Second, test that parallel invocations of nix-build perform builds -# in parallel, and don't block waiting on locks held by the others. -echo "testing multiple nix-build -j1..." - -clearStore - -rm -f $_NIX_TEST_SHARED.cur $_NIX_TEST_SHARED.max - -drvPath=$(nix-instantiate parallel.nix --argstr sleepTime 15) - -cmd="nix-store -j1 -r $drvPath" - -$cmd & -pid1=$! -echo "pid 1 is $pid1" - -$cmd & -pid2=$! -echo "pid 2 is $pid2" - -$cmd & -pid3=$! -echo "pid 3 is $pid3" - -$cmd & -pid4=$! -echo "pid 4 is $pid4" - -wait $pid1 || fail "instance 1 failed: $?" -wait $pid2 || fail "instance 2 failed: $?" -wait $pid3 || fail "instance 3 failed: $?" -wait $pid4 || fail "instance 4 failed: $?" - -if test "$(cat $_NIX_TEST_SHARED.cur)" != 0; then fail "wrong current process count"; fi -if test "$(cat $_NIX_TEST_SHARED.max)" != 3; then fail "not enough parallelism"; fi diff --git a/tests/pass-as-file.sh b/tests/pass-as-file.sh deleted file mode 100644 index 2c0bc5031..000000000 --- a/tests/pass-as-file.sh +++ /dev/null @@ -1,18 +0,0 @@ -source common.sh - -clearStore - -outPath=$(nix-build --no-out-link -E " -with import ./config.nix; - -mkDerivation { - name = \"pass-as-file\"; - passAsFile = [ \"foo\" ]; - foo = [ \"xyzzy\" ]; - builder = builtins.toFile \"builder.sh\" '' - [ \"\$(basename \$fooPath)\" = .attr-1bp7cri8hplaz6hbz0v4f0nl44rl84q1sg25kgwqzipzd1mv89ic ] - [ \"\$(cat \$fooPath)\" = xyzzy ] - touch \$out - ''; -} -") diff --git a/tests/path-from-hash-part.sh b/tests/path-from-hash-part.sh deleted file mode 100644 index bdd104434..000000000 --- a/tests/path-from-hash-part.sh +++ /dev/null @@ -1,10 +0,0 @@ -source common.sh - -path=$(nix build --no-link --print-out-paths -f simple.nix) - -hash_part=$(basename $path) -hash_part=${hash_part:0:32} - -path2=$(nix store path-from-hash-part $hash_part) - -[[ $path = $path2 ]] diff --git a/tests/path.nix b/tests/path.nix deleted file mode 100644 index 883c3c41b..000000000 --- a/tests/path.nix +++ /dev/null @@ -1,14 +0,0 @@ -with import ./config.nix; - -mkDerivation { - name = "filter"; - builder = builtins.toFile "builder" "ln -s $input $out"; - input = - builtins.path { - path = ((builtins.getEnv "TEST_ROOT") + "/filterin"); - filter = path: type: - type != "symlink" - && baseNameOf path != "foo" - && !((import ./lang/lib.nix).hasSuffix ".bak" (baseNameOf path)); - }; -} diff --git a/tests/placeholders.sh b/tests/placeholders.sh deleted file mode 100644 index cd1bb7bc2..000000000 --- a/tests/placeholders.sh +++ /dev/null @@ -1,20 +0,0 @@ -source common.sh - -clearStore - -nix-build --no-out-link -E ' - with import ./config.nix; - - mkDerivation { - name = "placeholders"; - outputs = [ "out" "bin" "dev" ]; - buildCommand = " - echo foo1 > $out - echo foo2 > $bin - echo foo3 > $dev - [[ $(cat ${placeholder "out"}) = foo1 ]] - [[ $(cat ${placeholder "bin"}) = foo2 ]] - [[ $(cat ${placeholder "dev"}) = foo3 ]] - "; - } -' diff --git a/tests/plugins.sh b/tests/plugins.sh deleted file mode 100644 index baf71a362..000000000 --- a/tests/plugins.sh +++ /dev/null @@ -1,9 +0,0 @@ -source common.sh - -if [[ $BUILD_SHARED_LIBS != 1 ]]; then - skipTest "Plugins are not supported" -fi - -res=$(nix --option setting-set true --option plugin-files $PWD/plugins/libplugintest* eval --expr builtins.anotherNull) - -[ "$res"x = "nullx" ] diff --git a/tests/plugins/local.mk b/tests/plugins/local.mk deleted file mode 100644 index 40350aa96..000000000 --- a/tests/plugins/local.mk +++ /dev/null @@ -1,11 +0,0 @@ -libraries += libplugintest - -libplugintest_DIR := $(d) - -libplugintest_SOURCES := $(d)/plugintest.cc - -libplugintest_ALLOW_UNDEFINED := 1 - -libplugintest_EXCLUDE_FROM_LIBRARY_LIST := 1 - -libplugintest_CXXFLAGS := -I src/libutil -I src/libstore -I src/libexpr -I src/libfetchers diff --git a/tests/plugins/plugintest.cc b/tests/plugins/plugintest.cc deleted file mode 100644 index e02fd68d5..000000000 --- a/tests/plugins/plugintest.cc +++ /dev/null @@ -1,28 +0,0 @@ -#include "config.hh" -#include "primops.hh" - -using namespace nix; - -struct MySettings : Config -{ - Setting settingSet{this, false, "setting-set", - "Whether the plugin-defined setting was set"}; -}; - -MySettings mySettings; - -static GlobalConfig::Register rs(&mySettings); - -static void prim_anotherNull (EvalState & state, const PosIdx pos, Value ** args, Value & v) -{ - if (mySettings.settingSet) - v.mkNull(); - else - v.mkBool(false); -} - -static RegisterPrimOp rp({ - .name = "anotherNull", - .arity = 0, - .fun = prim_anotherNull, -}); diff --git a/tests/post-hook.sh b/tests/post-hook.sh deleted file mode 100644 index 752f8220c..000000000 --- a/tests/post-hook.sh +++ /dev/null @@ -1,31 +0,0 @@ -source common.sh - -clearStore - -rm -f $TEST_ROOT/result - -export REMOTE_STORE=file:$TEST_ROOT/remote_store -echo 'require-sigs = false' >> $NIX_CONF_DIR/nix.conf - -restartDaemon - -if isDaemonNewer "2.13"; then - pushToStore="$PWD/push-to-store.sh" -else - pushToStore="$PWD/push-to-store-old.sh" -fi - -# Build the dependencies and push them to the remote store. -nix-build -o $TEST_ROOT/result dependencies.nix --post-build-hook "$pushToStore" -# See if all outputs are passed to the post-build hook by only specifying one -# We're not able to test CA tests this way -export BUILD_HOOK_ONLY_OUT_PATHS=$([ ! $NIX_TESTS_CA_BY_DEFAULT ]) -nix-build -o $TEST_ROOT/result-mult multiple-outputs.nix -A a.first --post-build-hook "$pushToStore" - -clearStore - -# Ensure that the remote store contains both the runtime and build-time -# closure of what we've just built. -nix copy --from "$REMOTE_STORE" --no-require-sigs -f dependencies.nix -nix copy --from "$REMOTE_STORE" --no-require-sigs -f dependencies.nix input1_drv -nix copy --from "$REMOTE_STORE" --no-require-sigs -f multiple-outputs.nix a^second diff --git a/tests/pure-eval.nix b/tests/pure-eval.nix deleted file mode 100644 index ed25b3d45..000000000 --- a/tests/pure-eval.nix +++ /dev/null @@ -1,3 +0,0 @@ -{ - x = 123; -} diff --git a/tests/pure-eval.sh b/tests/pure-eval.sh deleted file mode 100644 index 5334bf28e..000000000 --- a/tests/pure-eval.sh +++ /dev/null @@ -1,34 +0,0 @@ -source common.sh - -clearStore - -nix eval --expr 'assert 1 + 2 == 3; true' - -[[ $(nix eval --impure --expr 'builtins.readFile ./pure-eval.sh') =~ clearStore ]] - -missingImpureErrorMsg=$(! nix eval --expr 'builtins.readFile ./pure-eval.sh' 2>&1) - -echo "$missingImpureErrorMsg" | grepQuiet -- --impure || \ - fail "The error message should mention the “--impure” flag to unblock users" - -[[ $(nix eval --expr 'builtins.pathExists ./pure-eval.sh') == false ]] || \ - fail "Calling 'pathExists' on a non-authorised path should return false" - -(! nix eval --expr builtins.currentTime) -(! nix eval --expr builtins.currentSystem) - -(! nix-instantiate --pure-eval ./simple.nix) - -[[ $(nix eval --impure --expr "(import (builtins.fetchurl { url = file://$(pwd)/pure-eval.nix; })).x") == 123 ]] -(! nix eval --expr "(import (builtins.fetchurl { url = file://$(pwd)/pure-eval.nix; })).x") -nix eval --expr "(import (builtins.fetchurl { url = file://$(pwd)/pure-eval.nix; sha256 = \"$(nix hash file pure-eval.nix --type sha256)\"; })).x" - -rm -rf $TEST_ROOT/eval-out -nix eval --store dummy:// --write-to $TEST_ROOT/eval-out --expr '{ x = "foo" + "bar"; y = { z = "bla"; }; }' -[[ $(cat $TEST_ROOT/eval-out/x) = foobar ]] -[[ $(cat $TEST_ROOT/eval-out/y/z) = bla ]] - -rm -rf $TEST_ROOT/eval-out -(! nix eval --store dummy:// --write-to $TEST_ROOT/eval-out --expr '{ "." = "bla"; }') - -(! nix eval --expr '~/foo') diff --git a/tests/push-to-store-old.sh b/tests/push-to-store-old.sh deleted file mode 100755 index 4187958b2..000000000 --- a/tests/push-to-store-old.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -set -x -set -e - -[ -n "$OUT_PATHS" ] -[ -n "$DRV_PATH" ] - -echo Pushing "$OUT_PATHS" to "$REMOTE_STORE" -if [ -n "$BUILD_HOOK_ONLY_OUT_PATHS" ]; then - printf "%s" "$OUT_PATHS" | xargs nix copy --to "$REMOTE_STORE" --no-require-sigs -else - printf "%s" "$DRV_PATH" | xargs nix copy --to "$REMOTE_STORE" --no-require-sigs -fi diff --git a/tests/push-to-store.sh b/tests/push-to-store.sh deleted file mode 100755 index 9e4e475e0..000000000 --- a/tests/push-to-store.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -set -x -set -e - -[ -n "$OUT_PATHS" ] -[ -n "$DRV_PATH" ] - -echo Pushing "$OUT_PATHS" to "$REMOTE_STORE" -if [ -n "$BUILD_HOOK_ONLY_OUT_PATHS" ]; then - printf "%s" "$OUT_PATHS" | xargs nix copy --to "$REMOTE_STORE" --no-require-sigs -else - printf "%s" "$DRV_PATH"^'*' | xargs nix copy --to "$REMOTE_STORE" --no-require-sigs -fi diff --git a/tests/read-only-store.sh b/tests/read-only-store.sh deleted file mode 100644 index d63920c19..000000000 --- a/tests/read-only-store.sh +++ /dev/null @@ -1,42 +0,0 @@ -source common.sh - -enableFeatures "read-only-local-store" - -needLocalStore "cannot open store read-only when daemon has already opened it writeable" - -clearStore - -happy () { - # We can do a read-only query just fine with a read-only store - nix --store local?read-only=true path-info $dummyPath - - # We can "write" an already-present store-path a read-only store, because no IO is actually required - nix-store --store local?read-only=true --add dummy -} -## Testing read-only mode without forcing the underlying store to actually be read-only - -# Make sure the command fails when the store doesn't already have a database -expectStderr 1 nix-store --store local?read-only=true --add dummy | grepQuiet "database does not exist, and cannot be created in read-only mode" - -# Make sure the store actually has a current-database, with at least one store object -dummyPath=$(nix-store --add dummy) - -# Try again and make sure we fail when adding a item not already in the store -expectStderr 1 nix-store --store local?read-only=true --add eval.nix | grepQuiet "attempt to write a readonly database" - -# Test a few operations that should work with the read-only store in its current state -happy - -## Testing read-only mode with an underlying store that is actually read-only - -# Ensure store is actually read-only -chmod -R -w $TEST_ROOT/store -chmod -R -w $TEST_ROOT/var - -# Make sure we fail on add operations on the read-only store -# This is only for adding files that are not *already* in the store -expectStderr 1 nix-store --add eval.nix | grepQuiet "error: opening lock file '$(readlink -e $TEST_ROOT)/var/nix/db/big-lock'" -expectStderr 1 nix-store --store local?read-only=true --add eval.nix | grepQuiet "Permission denied" - -# Test the same operations from before should again succeed -happy diff --git a/tests/readfile-context.nix b/tests/readfile-context.nix deleted file mode 100644 index 54cd1afd9..000000000 --- a/tests/readfile-context.nix +++ /dev/null @@ -1,28 +0,0 @@ -with import ./config.nix; - -let - - input = import ./simple.nix; - - dependent = mkDerivation { - name = "dependent"; - buildCommand = '' - mkdir -p $out - echo -n "$input1" > "$out/file1" - echo -n "$input2" > "$out/file2" - ''; - input1 = "${input}/hello"; - input2 = "hello"; - }; - - readDependent = mkDerivation { - # Will evaluate correctly because file2 doesn't have any references, - # even though the `dependent` derivation does. - name = builtins.readFile (dependent + "/file2"); - buildCommand = '' - echo "$input" > "$out" - ''; - input = builtins.readFile (dependent + "/file1"); - }; - -in readDependent diff --git a/tests/readfile-context.sh b/tests/readfile-context.sh deleted file mode 100644 index 31e70ddb1..000000000 --- a/tests/readfile-context.sh +++ /dev/null @@ -1,16 +0,0 @@ -source common.sh - -clearStore - -outPath=$(nix-build --no-out-link readfile-context.nix) - -# Set a GC root. -ln -s $outPath "$NIX_STATE_DIR"/gcroots/foo - -# Check that file exists. -[ "$(cat $(cat $outPath))" = "Hello World!" ] - -nix-collect-garbage - -# Check that file still exists. -[ "$(cat $(cat $outPath))" = "Hello World!" ] diff --git a/tests/recursive.nix b/tests/recursive.nix deleted file mode 100644 index fa8cc04db..000000000 --- a/tests/recursive.nix +++ /dev/null @@ -1,56 +0,0 @@ -with import ./config.nix; - -mkDerivation rec { - name = "recursive"; - dummy = builtins.toFile "dummy" "bla bla"; - SHELL = shell; - - # Note: this is a string without context. - unreachable = builtins.getEnv "unreachable"; - - NIX_TESTS_CA_BY_DEFAULT = builtins.getEnv "NIX_TESTS_CA_BY_DEFAULT"; - - requiredSystemFeatures = [ "recursive-nix" ]; - - buildCommand = '' - mkdir $out - opts="--experimental-features nix-command ${if (NIX_TESTS_CA_BY_DEFAULT == "1") then "--extra-experimental-features ca-derivations" else ""}" - - PATH=${builtins.getEnv "NIX_BIN_DIR"}:$PATH - - # Check that we can query/build paths in our input closure. - nix $opts path-info $dummy - nix $opts build $dummy - - # Make sure we cannot query/build paths not in out input closure. - [[ -e $unreachable ]] - (! nix $opts path-info $unreachable) - (! nix $opts build $unreachable) - - # Add something to the store. - echo foobar > foobar - foobar=$(nix $opts store add-path ./foobar) - - nix $opts path-info $foobar - nix $opts build $foobar - - # Add it to our closure. - ln -s $foobar $out/foobar - - [[ $(nix $opts path-info --all | wc -l) -eq 4 ]] - - # Build a derivation. - nix $opts build -L --impure --expr ' - with import ${./config.nix}; - mkDerivation { - name = "inner1"; - buildCommand = "echo $fnord blaat > $out"; - fnord = builtins.toFile "fnord" "fnord"; - } - ' - - [[ $(nix $opts path-info --json ./result) =~ fnord ]] - - ln -s $(nix $opts path-info ./result) $out/inner1 - ''; -} diff --git a/tests/recursive.sh b/tests/recursive.sh deleted file mode 100644 index 0bf00f8fa..000000000 --- a/tests/recursive.sh +++ /dev/null @@ -1,19 +0,0 @@ -source common.sh - -enableFeatures 'recursive-nix' -restartDaemon - -clearStore - -rm -f $TEST_ROOT/result - -export unreachable=$(nix store add-path ./recursive.sh) - -NIX_BIN_DIR=$(dirname $(type -p nix)) nix --extra-experimental-features 'nix-command recursive-nix' build -o $TEST_ROOT/result -L --impure --file ./recursive.nix - -[[ $(cat $TEST_ROOT/result/inner1) =~ blaat ]] - -# Make sure the recursively created paths are in the closure. -nix path-info -r $TEST_ROOT/result | grep foobar -nix path-info -r $TEST_ROOT/result | grep fnord -nix path-info -r $TEST_ROOT/result | grep inner1 diff --git a/tests/referrers.sh b/tests/referrers.sh deleted file mode 100644 index 81323c280..000000000 --- a/tests/referrers.sh +++ /dev/null @@ -1,38 +0,0 @@ -source common.sh - -needLocalStore "uses some low-level store manipulations that aren’t available through the daemon" - -clearStore - -max=500 - -reference=$NIX_STORE_DIR/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-bla -touch $reference -(echo $reference && echo && echo 0) | nix-store --register-validity - -echo "making registration..." - -set +x -for ((n = 0; n < $max; n++)); do - storePath=$NIX_STORE_DIR/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-$n - echo -n > $storePath - ref2=$NIX_STORE_DIR/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-$((n+1)) - if test $((n+1)) = $max; then - ref2=$reference - fi - echo $storePath; echo; echo 2; echo $reference; echo $ref2 -done > $TEST_ROOT/reg_info -set -x - -echo "registering..." - -nix-store --register-validity < $TEST_ROOT/reg_info - -echo "collecting garbage..." -ln -sfn $reference "$NIX_STATE_DIR"/gcroots/ref -nix-store --gc - -if [ -n "$(type -p sqlite3)" -a "$(sqlite3 $NIX_STATE_DIR/db/db.sqlite 'select count(*) from Refs')" -ne 0 ]; then - echo "referrers not cleaned up" - exit 1 -fi diff --git a/tests/remote-store.sh b/tests/remote-store.sh deleted file mode 100644 index 50e6f24b9..000000000 --- a/tests/remote-store.sh +++ /dev/null @@ -1,43 +0,0 @@ -source common.sh - -clearStore - -# Ensure "fake ssh" remote store works just as legacy fake ssh would. -nix --store ssh-ng://localhost?remote-store=$TEST_ROOT/other-store doctor - -# Ensure that store ping trusted works with ssh-ng:// -nix --store ssh-ng://localhost?remote-store=$TEST_ROOT/other-store store ping --json | jq -e '.trusted' - -startDaemon - -if isDaemonNewer "2.15pre0"; then - # Ensure that ping works trusted with new daemon - nix store ping --json | jq -e '.trusted' -else - # And the the field is absent with the old daemon - nix store ping --json | jq -e 'has("trusted") | not' -fi - -# Test import-from-derivation through the daemon. -[[ $(nix eval --impure --raw --expr ' - with import ./config.nix; - import ( - mkDerivation { - name = "foo"; - bla = import ./dependencies.nix {}; - buildCommand = " - echo \\\"hi\\\" > $out - "; - } - ) -') = hi ]] - -storeCleared=1 NIX_REMOTE_=$NIX_REMOTE $SHELL ./user-envs.sh - -nix-store --gc --max-freed 1K - -nix-store --dump-db > $TEST_ROOT/d1 -NIX_REMOTE= nix-store --dump-db > $TEST_ROOT/d2 -cmp $TEST_ROOT/d1 $TEST_ROOT/d2 - -killDaemon diff --git a/tests/repair.sh b/tests/repair.sh deleted file mode 100644 index c8f07b1c6..000000000 --- a/tests/repair.sh +++ /dev/null @@ -1,123 +0,0 @@ -source common.sh - -needLocalStore "--repair needs a local store" - -clearStore - -path=$(nix-build dependencies.nix -o $TEST_ROOT/result) -path2=$(nix-store -qR $path | grep input-2) - -nix-store --verify --check-contents -v - -hash=$(nix-hash $path2) - -# Corrupt a path and check whether nix-build --repair can fix it. -chmod u+w $path2 -touch $path2/bad - -(! nix-store --verify --check-contents -v) - -# The path can be repaired by rebuilding the derivation. -nix-store --verify --check-contents --repair - -(! [ -e $path2/bad ]) -(! [ -w $path2 ]) - -nix-store --verify-path $path2 - -# Re-corrupt and delete the deriver. Now --verify --repair should -# not work. -chmod u+w $path2 -touch $path2/bad - -nix-store --delete $(nix-store -q --referrers-closure $(nix-store -qd $path2)) - -(! nix-store --verify --check-contents --repair) - -nix-build dependencies.nix -o $TEST_ROOT/result --repair - -if [ "$(nix-hash $path2)" != "$hash" -o -e $path2/bad ]; then - echo "path not repaired properly" >&2 - exit 1 -fi - -# Corrupt a path that has a substitute and check whether nix-store -# --verify can fix it. -clearCache - -nix copy --to file://$cacheDir $path - -chmod u+w $path2 -rm -rf $path2 - -nix-store --verify --check-contents --repair --substituters "file://$cacheDir" --no-require-sigs - -if [ "$(nix-hash $path2)" != "$hash" -o -e $path2/bad ]; then - echo "path not repaired properly" >&2 - exit 1 -fi - -# Check --verify-path and --repair-path. -nix-store --verify-path $path2 - -chmod u+w $path2 -rm -rf $path2 - -if nix-store --verify-path $path2; then - echo "nix-store --verify-path succeeded unexpectedly" >&2 - exit 1 -fi - -nix-store --repair-path $path2 --substituters "file://$cacheDir" --no-require-sigs - -if [ "$(nix-hash $path2)" != "$hash" -o -e $path2/bad ]; then - echo "path not repaired properly" >&2 - exit 1 -fi - -# Check that --repair-path also checks content of optimised symlinks (1/2) -nix-store --verify-path $path2 - -if (! nix-store --optimize); then - echo "nix-store --optimize failed to optimize the store" >&2 - exit 1 -fi -chmod u+w $path2/bar -echo 'rabrab' > $path2/bar # different length - -if nix-store --verify-path $path2; then - echo "nix-store --verify-path did not detect .links file corruption" >&2 - exit 1 -fi - -nix-store --repair-path $path2 --option auto-optimise-store true - -if [ "$(nix-hash $path2)" != "$hash" -o "BAR" != "$(< $path2/bar)" ]; then - echo "path not repaired properly" >&2 - exit 1 -fi - -# Check that --repair-path also checks content of optimised symlinks (2/2) -nix-store --verify-path $path2 - -if (! nix-store --optimize); then - echo "nix-store --optimize failed to optimize the store" >&2 - exit 1 -fi -chmod u+w $path2 -chmod u+w $path2/bar -sed -e 's/./X/g' < $path2/bar > $path2/tmp # same length, different content. -cp $path2/tmp $path2/bar -rm $path2/tmp - -if nix-store --verify-path $path2; then - echo "nix-store --verify-path did not detect .links file corruption" >&2 - exit 1 -fi - -nix-store --repair-path $path2 --substituters "file://$cacheDir" --no-require-sigs --option auto-optimise-store true - -if [ "$(nix-hash $path2)" != "$hash" -o "BAR" != "$(< $path2/bar)" ]; then - echo "path not repaired properly" >&2 - exit 1 -fi diff --git a/tests/repl.sh b/tests/repl.sh deleted file mode 100644 index bb8b60e50..000000000 --- a/tests/repl.sh +++ /dev/null @@ -1,179 +0,0 @@ -source common.sh - -testDir="$PWD" -cd "$TEST_ROOT" - -replCmds=" -simple = 1 -simple = import $testDir/simple.nix -:bl simple -:log simple -" - -replFailingCmds=" -failing = import $testDir/simple-failing.nix -:b failing -:log failing -" - -replUndefinedVariable=" -import $testDir/undefined-variable.nix -" - -testRepl () { - local nixArgs=("$@") - rm -rf repl-result-out || true # cleanup from other runs backed by a foreign nix store - local replOutput="$(nix repl "${nixArgs[@]}" <<< "$replCmds")" - echo "$replOutput" - local outPath=$(echo "$replOutput" |& - grep -o -E "$NIX_STORE_DIR/\w*-simple") - nix path-info "${nixArgs[@]}" "$outPath" - [ "$(realpath ./repl-result-out)" == "$outPath" ] || fail "nix repl :bl doesn't make a symlink" - # run it again without checking the output to ensure the previously created symlink gets overwritten - nix repl "${nixArgs[@]}" <<< "$replCmds" || fail "nix repl does not work twice with the same inputs" - - # simple.nix prints a PATH during build - echo "$replOutput" | grepQuiet -s 'PATH=' || fail "nix repl :log doesn't output logs" - local replOutput="$(nix repl "${nixArgs[@]}" <<< "$replFailingCmds" 2>&1)" - echo "$replOutput" - echo "$replOutput" | grepQuiet -s 'This should fail' \ - || fail "nix repl :log doesn't output logs for a failed derivation" - local replOutput="$(nix repl --show-trace "${nixArgs[@]}" <<< "$replUndefinedVariable" 2>&1)" - echo "$replOutput" - echo "$replOutput" | grepQuiet -s "while evaluating the file" \ - || fail "nix repl --show-trace doesn't show the trace" - - nix repl "${nixArgs[@]}" --option pure-eval true 2>&1 <<< "builtins.currentSystem" \ - | grep "attribute 'currentSystem' missing" - nix repl "${nixArgs[@]}" 2>&1 <<< "builtins.currentSystem" \ - | grep "$(nix-instantiate --eval -E 'builtins.currentSystem')" -} - -# Simple test, try building a drv -testRepl -# Same thing (kind-of), but with a remote store. -testRepl --store "$TEST_ROOT/store?real=$NIX_STORE_DIR" - -# Remove ANSI escape sequences. They can prevent grep from finding a match. -stripColors () { - sed -E 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' -} - -testReplResponseGeneral () { - local grepMode="$1"; shift - local commands="$1"; shift - local expectedResponse="$1"; shift - local response="$(nix repl "$@" <<< "$commands" | stripColors)" - echo "$response" | grepQuiet "$grepMode" -s "$expectedResponse" \ - || fail "repl command set: - -$commands - -does not respond with: - -$expectedResponse - -but with: - -$response -" -} - -testReplResponse () { - testReplResponseGeneral --basic-regexp "$@" -} - -testReplResponseNoRegex () { - testReplResponseGeneral --fixed-strings "$@" -} - -# :a uses the newest version of a symbol -testReplResponse ' -:a { a = "1"; } -:a { a = "2"; } -"result: ${a}" -' "result: 2" - -# check dollar escaping https://github.com/NixOS/nix/issues/4909 -# note the escaped \, -# \\ -# because the second argument is a regex -testReplResponseNoRegex ' -"$" + "{hi}" -' '"\${hi}"' - -testReplResponse ' -drvPath -' '".*-simple.drv"' \ -$testDir/simple.nix - -testReplResponse ' -drvPath -' '".*-simple.drv"' \ ---file $testDir/simple.nix --experimental-features 'ca-derivations' - -testReplResponse ' -drvPath -' '".*-simple.drv"' \ ---file $testDir/simple.nix --extra-experimental-features 'repl-flake ca-derivations' - -mkdir -p flake && cat < flake/flake.nix -{ - outputs = { self }: { - foo = 1; - bar.baz = 2; - - changingThing = "beforeChange"; - }; -} -EOF -testReplResponse ' -foo + baz -' "3" \ - ./flake ./flake\#bar --experimental-features 'flakes repl-flake' - -# Test the `:reload` mechansim with flakes: -# - Eval `./flake#changingThing` -# - Modify the flake -# - Re-eval it -# - Check that the result has changed -replResult=$( ( -echo "changingThing" -sleep 1 # Leave the repl the time to eval 'foo' -sed -i 's/beforeChange/afterChange/' flake/flake.nix -echo ":reload" -echo "changingThing" -) | nix repl ./flake --experimental-features 'flakes repl-flake') -echo "$replResult" | grepQuiet -s beforeChange -echo "$replResult" | grepQuiet -s afterChange - -# Test recursive printing and formatting -# Normal output should print attributes in lexicographical order non-recursively -testReplResponseNoRegex ' -{ a = { b = 2; }; l = [ 1 2 3 ]; s = "string"; n = 1234; x = rec { y = { z = { inherit y; }; }; }; } -' '{ a = { ... }; l = [ ... ]; n = 1234; s = "string"; x = { ... }; }' - -# Same for lists, but order is preserved -testReplResponseNoRegex ' -[ 42 1 "thingy" ({ a = 1; }) ([ 1 2 3 ]) ] -' '[ 42 1 "thingy" { ... } [ ... ] ]' - -# Same for let expressions -testReplResponseNoRegex ' -let x = { y = { a = 1; }; inherit x; }; in x -' '{ x = { ... }; y = { ... }; }' - -# The :p command should recursively print sets, but prevent infinite recursion -testReplResponseNoRegex ' -:p { a = { b = 2; }; s = "string"; n = 1234; x = rec { y = { z = { inherit y; }; }; }; } -' '{ a = { b = 2; }; n = 1234; s = "string"; x = { y = { z = { y = «repeated»; }; }; }; }' - -# Same for lists -testReplResponseNoRegex ' -:p [ 42 1 "thingy" (rec { a = 1; b = { inherit a; inherit b; }; }) ([ 1 2 3 ]) ] -' '[ 42 1 "thingy" { a = 1; b = { a = 1; b = «repeated»; }; } [ 1 2 3 ] ]' - -# Same for let expressions -testReplResponseNoRegex ' -:p let x = { y = { a = 1; }; inherit x; }; in x -' '{ x = { x = «repeated»; y = { a = 1; }; }; y = «repeated»; }' diff --git a/tests/restricted.nix b/tests/restricted.nix deleted file mode 100644 index e0ef58402..000000000 --- a/tests/restricted.nix +++ /dev/null @@ -1 +0,0 @@ -1 + 2 diff --git a/tests/restricted.sh b/tests/restricted.sh deleted file mode 100644 index 17f310a4b..000000000 --- a/tests/restricted.sh +++ /dev/null @@ -1,53 +0,0 @@ -source common.sh - -clearStore - -nix-instantiate --restrict-eval --eval -E '1 + 2' -(! nix-instantiate --eval --restrict-eval ./restricted.nix) -(! nix-instantiate --eval --restrict-eval <(echo '1 + 2')) -nix-instantiate --restrict-eval ./simple.nix -I src=. -nix-instantiate --restrict-eval ./simple.nix -I src1=simple.nix -I src2=config.nix -I src3=./simple.builder.sh - -(! nix-instantiate --restrict-eval --eval -E 'builtins.readFile ./simple.nix') -nix-instantiate --restrict-eval --eval -E 'builtins.readFile ./simple.nix' -I src=.. - -(! nix-instantiate --restrict-eval --eval -E 'builtins.readDir ../src/nix-channel') -nix-instantiate --restrict-eval --eval -E 'builtins.readDir ../src/nix-channel' -I src=../src - -(! nix-instantiate --restrict-eval --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in ') -nix-instantiate --restrict-eval --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in ' -I src=. - -p=$(nix eval --raw --expr "builtins.fetchurl file://$(pwd)/restricted.sh" --impure --restrict-eval --allowed-uris "file://$(pwd)") -cmp $p restricted.sh - -(! nix eval --raw --expr "builtins.fetchurl file://$(pwd)/restricted.sh" --impure --restrict-eval) - -(! nix eval --raw --expr "builtins.fetchurl file://$(pwd)/restricted.sh" --impure --restrict-eval --allowed-uris "file://$(pwd)/restricted.sh/") - -nix eval --raw --expr "builtins.fetchurl file://$(pwd)/restricted.sh" --impure --restrict-eval --allowed-uris "file://$(pwd)/restricted.sh" - -(! nix eval --raw --expr "builtins.fetchurl https://github.com/NixOS/patchelf/archive/master.tar.gz" --impure --restrict-eval) -(! nix eval --raw --expr "builtins.fetchTarball https://github.com/NixOS/patchelf/archive/master.tar.gz" --impure --restrict-eval) -(! nix eval --raw --expr "fetchGit git://github.com/NixOS/patchelf.git" --impure --restrict-eval) - -ln -sfn $(pwd)/restricted.nix $TEST_ROOT/restricted.nix -[[ $(nix-instantiate --eval $TEST_ROOT/restricted.nix) == 3 ]] -(! nix-instantiate --eval --restrict-eval $TEST_ROOT/restricted.nix) -(! nix-instantiate --eval --restrict-eval $TEST_ROOT/restricted.nix -I $TEST_ROOT) -(! nix-instantiate --eval --restrict-eval $TEST_ROOT/restricted.nix -I .) -nix-instantiate --eval --restrict-eval $TEST_ROOT/restricted.nix -I $TEST_ROOT -I . - -[[ $(nix eval --raw --impure --restrict-eval -I . --expr 'builtins.readFile "${import ./simple.nix}/hello"') == 'Hello World!' ]] - -# Check whether we can leak symlink information through directory traversal. -traverseDir="$(pwd)/restricted-traverse-me" -ln -sfn "$(pwd)/restricted-secret" "$(pwd)/restricted-innocent" -mkdir -p "$traverseDir" -goUp="..$(echo "$traverseDir" | sed -e 's,[^/]\+,..,g')" -output="$(nix eval --raw --restrict-eval -I "$traverseDir" \ - --expr "builtins.readFile \"$traverseDir/$goUp$(pwd)/restricted-innocent\"" \ - 2>&1 || :)" -echo "$output" | grep "is forbidden" -echo "$output" | grepInverse -F restricted-secret - -expectStderr 1 nix-instantiate --restrict-eval true ./dependencies.nix | grepQuiet "forbidden in restricted mode" diff --git a/tests/search.nix b/tests/search.nix deleted file mode 100644 index fea6e7a7a..000000000 --- a/tests/search.nix +++ /dev/null @@ -1,25 +0,0 @@ -with import ./config.nix; - -{ - hello = mkDerivation rec { - name = "hello-${version}"; - version = "0.1"; - buildCommand = "touch $out"; - meta.description = "Empty file"; - }; - foo = mkDerivation rec { - name = "foo-5"; - buildCommand = '' - mkdir -p $out - echo ${name} > $out/${name} - ''; - }; - bar = mkDerivation rec { - name = "bar-3"; - buildCommand = '' - echo "Does not build successfully" - exit 1 - ''; - meta.description = "broken bar"; - }; -} diff --git a/tests/search.sh b/tests/search.sh deleted file mode 100644 index 8742f8736..000000000 --- a/tests/search.sh +++ /dev/null @@ -1,46 +0,0 @@ -source common.sh - -clearStore -clearCache - -(( $(nix search -f search.nix '' hello | wc -l) > 0 )) - -# Check descriptions are searched -(( $(nix search -f search.nix '' broken | wc -l) > 0 )) - -# Check search that matches nothing -(( $(nix search -f search.nix '' nosuchpackageexists | wc -l) == 0 )) - -# Search for multiple arguments -(( $(nix search -f search.nix '' hello empty | wc -l) == 2 )) - -# Multiple arguments will not exist -(( $(nix search -f search.nix '' hello broken | wc -l) == 0 )) - -## Search expressions - -# Check that empty search string matches all -nix search -f search.nix '' |grepQuiet foo -nix search -f search.nix '' |grepQuiet bar -nix search -f search.nix '' |grepQuiet hello - -## Tests for multiple regex/match highlighting - -e=$'\x1b' # grep doesn't support \e, \033 or even \x1b -# Multiple overlapping regexes -(( $(nix search -f search.nix '' 'oo' 'foo' 'oo' | grep -c "$e\[32;1mfoo$e\\[0;1m") == 1 )) -(( $(nix search -f search.nix '' 'broken b' 'en bar' | grep -c "$e\[32;1mbroken bar$e\\[0m") == 1 )) - -# Multiple matches -# Searching for 'o' should yield the 'o' in 'broken bar', the 'oo' in foo and 'o' in hello -(( $(nix search -f search.nix '' 'o' | grep -Eoc "$e\[32;1mo{1,2}$e\[(0|0;1)m") == 3 )) -# Searching for 'b' should yield the 'b' in bar and the two 'b's in 'broken bar' -# NOTE: This does not work with `grep -c` because it counts the two 'b's in 'broken bar' as one matched line -(( $(nix search -f search.nix '' 'b' | grep -Eo "$e\[32;1mb$e\[(0|0;1)m" | wc -l) == 3 )) - -## Tests for --exclude -(( $(nix search -f search.nix -e hello | grep -c hello) == 0 )) - -(( $(nix search -f search.nix foo --exclude 'foo|bar' | grep -Ec 'foo|bar') == 0 )) -(( $(nix search -f search.nix foo -e foo --exclude bar | grep -Ec 'foo|bar') == 0 )) -[[ $(nix search -f search.nix -e bar --json | jq -c 'keys') == '["foo","hello"]' ]] diff --git a/tests/secure-drv-outputs.nix b/tests/secure-drv-outputs.nix deleted file mode 100644 index b4ac8ff53..000000000 --- a/tests/secure-drv-outputs.nix +++ /dev/null @@ -1,23 +0,0 @@ -with import ./config.nix; - -{ - - good = mkDerivation { - name = "good"; - builder = builtins.toFile "builder" - '' - mkdir $out - echo > $out/good - ''; - }; - - bad = mkDerivation { - name = "good"; - builder = builtins.toFile "builder" - '' - mkdir $out - echo > $out/bad - ''; - }; - -} diff --git a/tests/secure-drv-outputs.sh b/tests/secure-drv-outputs.sh deleted file mode 100644 index 50a9c4428..000000000 --- a/tests/secure-drv-outputs.sh +++ /dev/null @@ -1,36 +0,0 @@ -# Test that users cannot register specially-crafted derivations that -# produce output paths belonging to other derivations. This could be -# used to inject malware into the store. - -source common.sh - -clearStore - -startDaemon - -# Determine the output path of the "good" derivation. -goodOut=$(nix-store -q $(nix-instantiate ./secure-drv-outputs.nix -A good)) - -# Instantiate the "bad" derivation. -badDrv=$(nix-instantiate ./secure-drv-outputs.nix -A bad) -badOut=$(nix-store -q $badDrv) - -# Rewrite the bad derivation to produce the output path of the good -# derivation. -rm -f $TEST_ROOT/bad.drv -sed -e "s|$badOut|$goodOut|g" < $badDrv > $TEST_ROOT/bad.drv - -# Add the manipulated derivation to the store and build it. This -# should fail. -if badDrv2=$(nix-store --add $TEST_ROOT/bad.drv); then - nix-store -r "$badDrv2" -fi - -# Now build the good derivation. -goodOut2=$(nix-build ./secure-drv-outputs.nix -A good --no-out-link) -test "$goodOut" = "$goodOut2" - -if ! test -e "$goodOut"/good; then - echo "Bad derivation stole the output path of the good derivation!" - exit 1 -fi diff --git a/tests/selfref-gc.sh b/tests/selfref-gc.sh deleted file mode 100644 index 3f1f50eea..000000000 --- a/tests/selfref-gc.sh +++ /dev/null @@ -1,30 +0,0 @@ -source common.sh - -requireDaemonNewerThan "2.6.0pre20211215" - -clearStore - -nix-build --no-out-link -E ' - with import ./config.nix; - - let d1 = mkDerivation { - name = "selfref-gc"; - outputs = [ "out" ]; - buildCommand = " - echo SELF_REF: $out > $out - "; - }; in - - # the only change from d1 is d1 as an (unused) build input - # to get identical store path in CA. - mkDerivation { - name = "selfref-gc"; - outputs = [ "out" ]; - buildCommand = " - echo UNUSED: ${d1} - echo SELF_REF: $out > $out - "; - } -' - -nix-collect-garbage diff --git a/tests/shell-hello.nix b/tests/shell-hello.nix deleted file mode 100644 index 3fdd3501d..000000000 --- a/tests/shell-hello.nix +++ /dev/null @@ -1,26 +0,0 @@ -with import ./config.nix; - -{ - hello = mkDerivation { - name = "hello"; - outputs = [ "out" "dev" ]; - meta.outputsToInstall = [ "out" ]; - buildCommand = - '' - mkdir -p $out/bin $dev/bin - - cat > $out/bin/hello < $dev/bin/hello2 < $out/bin/foo - chmod a+rx $out/bin/foo - ln -s ${shell} $out/bin/bash - ''; - - bar = runCommand "bar" {} '' - mkdir -p $out/bin - echo 'echo bar' > $out/bin/bar - chmod a+rx $out/bin/bar - ''; - - bash = shell; - bashInteractive = runCommand "bash" {} '' - mkdir -p $out/bin - ln -s ${shell} $out/bin/bash - ''; - - # ruby "interpreter" that outputs "$@" - ruby = runCommand "ruby" {} '' - mkdir -p $out/bin - echo 'printf %s "$*"' > $out/bin/ruby - chmod a+rx $out/bin/ruby - ''; - - inherit pkgs; -}; in pkgs diff --git a/tests/shell.sh b/tests/shell.sh deleted file mode 100644 index d2f7cf14e..000000000 --- a/tests/shell.sh +++ /dev/null @@ -1,32 +0,0 @@ -source common.sh - -clearStore -clearCache - -nix shell -f shell-hello.nix hello -c hello | grep 'Hello World' -nix shell -f shell-hello.nix hello -c hello NixOS | grep 'Hello NixOS' - -# Test output selection. -nix shell -f shell-hello.nix hello^dev -c hello2 | grep 'Hello2' -nix shell -f shell-hello.nix 'hello^*' -c hello2 | grep 'Hello2' - -requireSandboxSupport - -chmod -R u+w $TEST_ROOT/store0 || true -rm -rf $TEST_ROOT/store0 - -clearStore - -path=$(nix eval --raw -f shell-hello.nix hello) - -# Note: we need the sandbox paths to ensure that the shell is -# visible in the sandbox. -nix shell --sandbox-build-dir /build-tmp \ - --sandbox-paths '/nix? /bin? /lib? /lib64? /usr?' \ - --store $TEST_ROOT/store0 -f shell-hello.nix hello -c hello | grep 'Hello World' - -path2=$(nix shell --sandbox-paths '/nix? /bin? /lib? /lib64? /usr?' --store $TEST_ROOT/store0 -f shell-hello.nix hello -c $SHELL -c 'type -p hello') - -[[ $path/bin/hello = $path2 ]] - -[[ -e $TEST_ROOT/store0/nix/store/$(basename $path)/bin/hello ]] diff --git a/tests/shell.shebang.rb b/tests/shell.shebang.rb deleted file mode 100644 index ea67eb09c..000000000 --- a/tests/shell.shebang.rb +++ /dev/null @@ -1,7 +0,0 @@ -#! @SHELL_PROG@ -#! ruby -#! nix-shell -I nixpkgs=shell.nix --no-substitute -#! nix-shell --pure -p ruby -i ruby - -# Contents doesn't matter. -abort("This shouldn't be executed.") diff --git a/tests/shell.shebang.sh b/tests/shell.shebang.sh deleted file mode 100755 index f7132043d..000000000 --- a/tests/shell.shebang.sh +++ /dev/null @@ -1,4 +0,0 @@ -#! @ENV_PROG@ nix-shell -#! nix-shell -I nixpkgs=shell.nix --no-substitute -#! nix-shell --pure -i bash -p foo bar -echo "$(foo) $(bar) $@" diff --git a/tests/signing.sh b/tests/signing.sh deleted file mode 100644 index 942b51630..000000000 --- a/tests/signing.sh +++ /dev/null @@ -1,109 +0,0 @@ -source common.sh - -clearStore -clearCache - -nix-store --generate-binary-cache-key cache1.example.org $TEST_ROOT/sk1 $TEST_ROOT/pk1 -pk1=$(cat $TEST_ROOT/pk1) -nix-store --generate-binary-cache-key cache2.example.org $TEST_ROOT/sk2 $TEST_ROOT/pk2 -pk2=$(cat $TEST_ROOT/pk2) - -# Build a path. -outPath=$(nix-build dependencies.nix --no-out-link --secret-key-files "$TEST_ROOT/sk1 $TEST_ROOT/sk2") - -# Verify that the path got signed. -info=$(nix path-info --json $outPath) -[[ $info =~ '"ultimate":true' ]] -[[ $info =~ 'cache1.example.org' ]] -[[ $info =~ 'cache2.example.org' ]] - -# Test "nix store verify". -nix store verify -r $outPath - -expect 2 nix store verify -r $outPath --sigs-needed 1 - -nix store verify -r $outPath --sigs-needed 1 --trusted-public-keys $pk1 - -expect 2 nix store verify -r $outPath --sigs-needed 2 --trusted-public-keys $pk1 - -nix store verify -r $outPath --sigs-needed 2 --trusted-public-keys "$pk1 $pk2" - -nix store verify --all --sigs-needed 2 --trusted-public-keys "$pk1 $pk2" - -# Build something unsigned. -outPath2=$(nix-build simple.nix --no-out-link) - -nix store verify -r $outPath - -# Verify that the path did not get signed but does have the ultimate bit. -info=$(nix path-info --json $outPath2) -[[ $info =~ '"ultimate":true' ]] -(! [[ $info =~ 'signatures' ]]) - -# Test "nix store verify". -nix store verify -r $outPath2 - -expect 2 nix store verify -r $outPath2 --sigs-needed 1 - -expect 2 nix store verify -r $outPath2 --sigs-needed 1 --trusted-public-keys $pk1 - -# Test "nix store sign". -nix store sign --key-file $TEST_ROOT/sk1 $outPath2 - -nix store verify -r $outPath2 --sigs-needed 1 --trusted-public-keys $pk1 - -# Build something content-addressed. -outPathCA=$(IMPURE_VAR1=foo IMPURE_VAR2=bar nix-build ./fixed.nix -A good.0 --no-out-link) - -[[ $(nix path-info --json $outPathCA) =~ '"ca":"fixed:md5:' ]] - -# Content-addressed paths don't need signatures, so they verify -# regardless of --sigs-needed. -nix store verify $outPathCA -nix store verify $outPathCA --sigs-needed 1000 - -# Check that signing a content-addressed path doesn't overflow validSigs -nix store sign --key-file $TEST_ROOT/sk1 $outPathCA -nix store verify -r $outPathCA --sigs-needed 1000 --trusted-public-keys $pk1 - -# Copy to a binary cache. -nix copy --to file://$cacheDir $outPath2 - -# Verify that signatures got copied. -info=$(nix path-info --store file://$cacheDir --json $outPath2) -(! [[ $info =~ '"ultimate":true' ]]) -[[ $info =~ 'cache1.example.org' ]] -(! [[ $info =~ 'cache2.example.org' ]]) - -# Verify that adding a signature to a path in a binary cache works. -nix store sign --store file://$cacheDir --key-file $TEST_ROOT/sk2 $outPath2 -info=$(nix path-info --store file://$cacheDir --json $outPath2) -[[ $info =~ 'cache1.example.org' ]] -[[ $info =~ 'cache2.example.org' ]] - -# Copying to a diverted store should fail due to a lack of signatures by trusted keys. -chmod -R u+w $TEST_ROOT/store0 || true -rm -rf $TEST_ROOT/store0 - -# Fails or very flaky only on GHA + macOS: -# expectStderr 1 nix copy --to $TEST_ROOT/store0 $outPath | grepQuiet -E 'cannot add path .* because it lacks a signature by a trusted key' -# but this works: -(! nix copy --to $TEST_ROOT/store0 $outPath) - -# But succeed if we supply the public keys. -nix copy --to $TEST_ROOT/store0 $outPath --trusted-public-keys $pk1 - -expect 2 nix store verify --store $TEST_ROOT/store0 -r $outPath - -nix store verify --store $TEST_ROOT/store0 -r $outPath --trusted-public-keys $pk1 -nix store verify --store $TEST_ROOT/store0 -r $outPath --sigs-needed 2 --trusted-public-keys "$pk1 $pk2" - -# It should also succeed if we disable signature checking. -(! nix copy --to $TEST_ROOT/store0 $outPath2) -nix copy --to $TEST_ROOT/store0?require-sigs=false $outPath2 - -# But signatures should still get copied. -nix store verify --store $TEST_ROOT/store0 -r $outPath2 --trusted-public-keys $pk1 - -# Content-addressed stuff can be copied without signatures. -nix copy --to $TEST_ROOT/store0 $outPathCA diff --git a/tests/simple-failing.nix b/tests/simple-failing.nix deleted file mode 100644 index d176c9c51..000000000 --- a/tests/simple-failing.nix +++ /dev/null @@ -1,12 +0,0 @@ -with import ./config.nix; - -mkDerivation { - name = "simple-failing"; - builder = builtins.toFile "builder.sh" - '' - echo "This should fail" - exit 1 - ''; - PATH = ""; - goodPath = path; -} diff --git a/tests/simple.builder.sh b/tests/simple.builder.sh deleted file mode 100644 index 569e8ca88..000000000 --- a/tests/simple.builder.sh +++ /dev/null @@ -1,11 +0,0 @@ -echo "PATH=$PATH" - -# Verify that the PATH is empty. -if mkdir foo 2> /dev/null; then exit 1; fi - -# Set a PATH (!!! impure). -export PATH=$goodPath - -mkdir $out - -echo "Hello World!" > $out/hello \ No newline at end of file diff --git a/tests/simple.nix b/tests/simple.nix deleted file mode 100644 index 4223c0f23..000000000 --- a/tests/simple.nix +++ /dev/null @@ -1,8 +0,0 @@ -with import ./config.nix; - -mkDerivation { - name = "simple"; - builder = ./simple.builder.sh; - PATH = ""; - goodPath = path; -} diff --git a/tests/simple.sh b/tests/simple.sh deleted file mode 100644 index 50d44f93f..000000000 --- a/tests/simple.sh +++ /dev/null @@ -1,33 +0,0 @@ -source common.sh - -drvPath=$(nix-instantiate simple.nix) - -test "$(nix-store -q --binding system "$drvPath")" = "$system" - -echo "derivation is $drvPath" - -outPath=$(nix-store -rvv "$drvPath") - -echo "output path is $outPath" - -(! [ -w $outPath ]) - -text=$(cat "$outPath"/hello) -if test "$text" != "Hello World!"; then exit 1; fi - -# Directed delete: $outPath is not reachable from a root, so it should -# be deleteable. -nix-store --delete $outPath -(! [ -e $outPath/hello ]) - -outPath="$(NIX_REMOTE=local?store=/foo\&real=$TEST_ROOT/real-store nix-instantiate --readonly-mode hash-check.nix)" -if test "$outPath" != "/foo/lfy1s6ca46rm5r6w4gg9hc0axiakjcnm-dependencies.drv"; then - echo "hashDerivationModulo appears broken, got $outPath" - exit 1 -fi - -outPath="$(NIX_REMOTE=local?store=/foo\&real=$TEST_ROOT/real-store nix-instantiate --readonly-mode big-derivation-attr.nix)" -if test "$outPath" != "/foo/xxiwa5zlaajv6xdjynf9yym9g319d6mn-big-derivation-attr.drv"; then - echo "big-derivation-attr.nix hash appears broken, got $outPath. Memory corruption in large drv attr?" - exit 1 -fi diff --git a/tests/ssh-relay.sh b/tests/ssh-relay.sh deleted file mode 100644 index 053b2f00d..000000000 --- a/tests/ssh-relay.sh +++ /dev/null @@ -1,16 +0,0 @@ -source common.sh - -echo foo > $TEST_ROOT/hello.sh - -ssh_localhost=ssh://localhost -remote_store=?remote-store=$ssh_localhost - -store=$ssh_localhost - -store+=$remote_store -store+=$remote_store -store+=$remote_store - -out=$(nix store add-path --store "$store" $TEST_ROOT/hello.sh) - -[ foo = $(< $out) ] diff --git a/tests/store-ping.sh b/tests/store-ping.sh deleted file mode 100644 index 9846c7d3d..000000000 --- a/tests/store-ping.sh +++ /dev/null @@ -1,17 +0,0 @@ -source common.sh - -STORE_INFO=$(nix store ping 2>&1) -STORE_INFO_JSON=$(nix store ping --json) - -echo "$STORE_INFO" | grep "Store URL: ${NIX_REMOTE}" - -if [[ -v NIX_DAEMON_PACKAGE ]] && isDaemonNewer "2.7.0pre20220126"; then - DAEMON_VERSION=$($NIX_DAEMON_PACKAGE/bin/nix-daemon --version | cut -d' ' -f3) - echo "$STORE_INFO" | grep "Version: $DAEMON_VERSION" - [[ "$(echo "$STORE_INFO_JSON" | jq -r ".version")" == "$DAEMON_VERSION" ]] -fi - -expect 127 NIX_REMOTE=unix:$PWD/store nix store ping || \ - fail "nix store ping on a non-existent store should fail" - -[[ "$(echo "$STORE_INFO_JSON" | jq -r ".url")" == "${NIX_REMOTE:-local}" ]] diff --git a/tests/structured-attrs-shell.nix b/tests/structured-attrs-shell.nix deleted file mode 100644 index 57c1e6bd2..000000000 --- a/tests/structured-attrs-shell.nix +++ /dev/null @@ -1,21 +0,0 @@ -with import ./config.nix; -let - dep = mkDerivation { - name = "dep"; - buildCommand = '' - mkdir $out; echo bla > $out/bla - ''; - }; - inherit (import ./shell.nix { inNixShell = true; }) stdenv; -in -mkDerivation { - name = "structured2"; - __structuredAttrs = true; - inherit stdenv; - outputs = [ "out" "dev" ]; - my.list = [ "a" "b" "c" ]; - exportReferencesGraph.refs = [ dep ]; - buildCommand = '' - touch ''${outputs[out]}; touch ''${outputs[dev]} - ''; -} diff --git a/tests/structured-attrs.nix b/tests/structured-attrs.nix deleted file mode 100644 index e93139a44..000000000 --- a/tests/structured-attrs.nix +++ /dev/null @@ -1,70 +0,0 @@ -with import ./config.nix; - -let - - dep = mkDerivation { - name = "dep"; - buildCommand = '' - mkdir $out; echo bla > $out/bla - ''; - }; - -in - -mkDerivation { - name = "structured"; - - __structuredAttrs = true; - - outputs = [ "out" "dev" ]; - - buildCommand = '' - set -x - - [[ $int = 123456789 ]] - [[ -z $float ]] - [[ -n $boolTrue ]] - [[ -z $boolFalse ]] - [[ -n ''${hardening[format]} ]] - [[ -z ''${hardening[fortify]} ]] - [[ ''${#buildInputs[@]} = 7 ]] - [[ ''${buildInputs[2]} = c ]] - [[ -v nothing ]] - [[ -z $nothing ]] - - mkdir ''${outputs[out]} ''${outputs[dev]} - echo bar > $dest - echo foo > $dest2 - - json=$(cat $NIX_ATTRS_JSON_FILE) - [[ $json =~ '"narHash":"sha256:1r7yc43zqnzl5b0als5vnyp649gk17i37s7mj00xr8kc47rjcybk"' ]] - [[ $json =~ '"narSize":288' ]] - [[ $json =~ '"closureSize":288' ]] - [[ $json =~ '"references":[]' ]] - ''; - - buildInputs = [ "a" "b" "c" 123 "'" "\"" null ]; - - hardening.format = true; - hardening.fortify = false; - - outer.inner = [ 1 2 3 ]; - - int = 123456789; - - float = 123.456; - - boolTrue = true; - boolFalse = false; - - nothing = null; - - dest = "${placeholder "out"}/foo"; - dest2 = "${placeholder "dev"}/foo"; - - "foo bar" = "BAD"; - "1foobar" = "BAD"; - "foo$" = "BAD"; - - exportReferencesGraph.refs = [ dep ]; -} diff --git a/tests/structured-attrs.sh b/tests/structured-attrs.sh deleted file mode 100644 index 378dbc735..000000000 --- a/tests/structured-attrs.sh +++ /dev/null @@ -1,23 +0,0 @@ -source common.sh - -# 27ce722638 required some incompatible changes to the nix file, so skip this -# tests for the older versions -requireDaemonNewerThan "2.4pre20210712" - -clearStore - -rm -f $TEST_ROOT/result - -nix-build structured-attrs.nix -A all -o $TEST_ROOT/result - -[[ $(cat $TEST_ROOT/result/foo) = bar ]] -[[ $(cat $TEST_ROOT/result-dev/foo) = foo ]] - -export NIX_BUILD_SHELL=$SHELL -env NIX_PATH=nixpkgs=shell.nix nix-shell structured-attrs-shell.nix \ - --run 'test -e .attrs.json; test "3" = "$(jq ".my.list|length" < $NIX_ATTRS_JSON_FILE)"' - -# `nix develop` is a slightly special way of dealing with environment vars, it parses -# these from a shell-file exported from a derivation. This is to test especially `outputs` -# (which is an associative array in thsi case) being fine. -nix develop -f structured-attrs-shell.nix -c bash -c 'test -n "$out"' diff --git a/tests/substitute-with-invalid-ca.sh b/tests/substitute-with-invalid-ca.sh deleted file mode 100644 index 4d0b01e0f..000000000 --- a/tests/substitute-with-invalid-ca.sh +++ /dev/null @@ -1,38 +0,0 @@ -source common.sh - -BINARY_CACHE=file://$cacheDir - -getHash() { - basename "$1" | cut -d '-' -f 1 -} -getRemoteNarInfo () { - echo "$cacheDir/$(getHash "$1").narinfo" -} - -cat < $TEST_HOME/good.txt -I’m a good path -EOF - -cat < $TEST_HOME/bad.txt -I’m a bad path -EOF - -good=$(nix-store --add $TEST_HOME/good.txt) -bad=$(nix-store --add $TEST_HOME/bad.txt) -nix copy --to "$BINARY_CACHE" "$good" -nix copy --to "$BINARY_CACHE" "$bad" -nix-collect-garbage >/dev/null 2>&1 - -# Falsifying the narinfo file for '$good' -goodPathNarInfo=$(getRemoteNarInfo "$good") -badPathNarInfo=$(getRemoteNarInfo "$bad") -for fieldName in URL FileHash FileSize NarHash NarSize; do - sed -i "/^$fieldName/d" "$goodPathNarInfo" - grep -E "^$fieldName" "$badPathNarInfo" >> "$goodPathNarInfo" -done - -# Copying back '$good' from the binary cache. This should fail as it is -# corrupted -if nix copy --from "$BINARY_CACHE" "$good"; then - fail "Importing a path with a wrong CA field should fail" -fi diff --git a/tests/suggestions.sh b/tests/suggestions.sh deleted file mode 100644 index f18fefef9..000000000 --- a/tests/suggestions.sh +++ /dev/null @@ -1,44 +0,0 @@ -source common.sh - -clearStore - -cd "$TEST_HOME" - -cat < flake.nix -{ - outputs = a: { - packages.$system = { - foo = 1; - fo1 = 1; - fo2 = 1; - fooo = 1; - foooo = 1; - fooooo = 1; - fooooo1 = 1; - fooooo2 = 1; - fooooo3 = 1; - fooooo4 = 1; - fooooo5 = 1; - fooooo6 = 1; - }; - }; -} -EOF - -# Probable typo in the requested attribute path. Suggest some close possibilities -NIX_BUILD_STDERR_WITH_SUGGESTIONS=$(! nix build .\#fob 2>&1 1>/dev/null) -[[ "$NIX_BUILD_STDERR_WITH_SUGGESTIONS" =~ "Did you mean one of fo1, fo2, foo or fooo?" ]] || \ - fail "The nix build stderr should suggest the three closest possiblities" - -# None of the possible attributes is close to `bar`, so shouldn’t suggest anything -NIX_BUILD_STDERR_WITH_NO_CLOSE_SUGGESTION=$(! nix build .\#bar 2>&1 1>/dev/null) -[[ ! "$NIX_BUILD_STDERR_WITH_NO_CLOSE_SUGGESTION" =~ "Did you mean" ]] || \ - fail "The nix build stderr shouldn’t suggest anything if there’s nothing relevant to suggest" - -NIX_EVAL_STDERR_WITH_SUGGESTIONS=$(! nix build --impure --expr '(builtins.getFlake (builtins.toPath ./.)).packages.'$system'.fob' 2>&1 1>/dev/null) -[[ "$NIX_EVAL_STDERR_WITH_SUGGESTIONS" =~ "Did you mean one of fo1, fo2, foo or fooo?" ]] || \ - fail "The evaluator should suggest the three closest possiblities" - -NIX_EVAL_STDERR_WITH_SUGGESTIONS=$(! nix build --impure --expr '({ foo }: foo) { foo = 1; fob = 2; }' 2>&1 1>/dev/null) -[[ "$NIX_EVAL_STDERR_WITH_SUGGESTIONS" =~ "Did you mean foo?" ]] || \ - fail "The evaluator should suggest the three closest possiblities" diff --git a/tests/supplementary-groups.sh b/tests/supplementary-groups.sh deleted file mode 100644 index d18fb2414..000000000 --- a/tests/supplementary-groups.sh +++ /dev/null @@ -1,37 +0,0 @@ -source common.sh - -requireSandboxSupport -[[ $busybox =~ busybox ]] || skipTest "no busybox" -if ! command -p -v unshare; then skipTest "Need unshare"; fi -needLocalStore "The test uses --store always so we would just be bypassing the daemon" - -unshare --mount --map-root-user bash < $tarball - - nix-env -f file://$tarball -qa --out-path | grepQuiet dependencies - - nix-build -o $TEST_ROOT/result file://$tarball - - nix-build -o $TEST_ROOT/result '' -I foo=file://$tarball - - nix-build -o $TEST_ROOT/result -E "import (fetchTarball file://$tarball)" - # Do not re-fetch paths already present - nix-build -o $TEST_ROOT/result -E "import (fetchTarball { url = file:///does-not-exist/must-remain-unused/$tarball; sha256 = \"$hash\"; })" - - nix-build -o $TEST_ROOT/result -E "import (fetchTree file://$tarball)" - nix-build -o $TEST_ROOT/result -E "import (fetchTree { type = \"tarball\"; url = file://$tarball; })" - nix-build -o $TEST_ROOT/result -E "import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; })" - # Do not re-fetch paths already present - nix-build -o $TEST_ROOT/result -E "import (fetchTree { type = \"tarball\"; url = file:///does-not-exist/must-remain-unused/$tarball; narHash = \"$hash\"; })" - expectStderr 102 nix-build -o $TEST_ROOT/result -E "import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"sha256-xdKv2pq/IiwLSnBBJXW8hNowI4MrdZfW+SYqDQs7Tzc=\"; })" | grep 'NAR hash mismatch in input' - - [[ $(nix eval --impure --expr "(fetchTree file://$tarball).lastModified") = 1000000000 ]] - - nix-instantiate --strict --eval -E "!((import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; })) ? submodules)" >&2 - nix-instantiate --strict --eval -E "!((import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; })) ? submodules)" 2>&1 | grep 'true' - - nix-instantiate --eval -E '1 + 2' -I fnord=file://no-such-tarball.tar$ext - nix-instantiate --eval -E 'with ; 1 + 2' -I fnord=file://no-such-tarball$ext - (! nix-instantiate --eval -E ' 1' -I fnord=file://no-such-tarball$ext) - - nix-instantiate --eval -E '' -I fnord=file://no-such-tarball$ext -I fnord=. - - # Ensure that the `name` attribute isn’t accepted as that would mess - # with the content-addressing - (! nix-instantiate --eval -E "fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; name = \"foo\"; }") - -} - -test_tarball '' cat -test_tarball .xz xz -test_tarball .gz gzip - -rm -rf $TEST_ROOT/tmp -mkdir -p $TEST_ROOT/tmp -(! TMPDIR=$TEST_ROOT/tmp XDG_RUNTIME_DIR=$TEST_ROOT/tmp nix-env -f file://$(pwd)/bad.tar.xz -qa --out-path) -(! [ -e $TEST_ROOT/tmp/bad ]) diff --git a/tests/test-infra.sh b/tests/test-infra.sh deleted file mode 100644 index 54ae120e7..000000000 --- a/tests/test-infra.sh +++ /dev/null @@ -1,85 +0,0 @@ -# Test the functions for testing themselves! -# Also test some assumptions on how bash works that they rely on. -source common.sh - -# `true` should exit with 0 -expect 0 true - -# `false` should exit with 1 -expect 1 false - -# `expect` will fail when we get it wrong -expect 1 expect 0 false - -noisyTrue () { - echo YAY! >&2 - true -} - -noisyFalse () { - echo NAY! >&2 - false -} - -# These should redirect standard error to standard output -expectStderr 0 noisyTrue | grepQuiet YAY -expectStderr 1 noisyFalse | grepQuiet NAY - -# `set -o pipefile` is enabled - -pipefailure () { - # shellcheck disable=SC2216 - true | false | true -} -expect 1 pipefailure -unset pipefailure - -pipefailure () { - # shellcheck disable=SC2216 - false | true | true -} -expect 1 pipefailure -unset pipefailure - -commandSubstitutionPipeFailure () { - # shellcheck disable=SC2216 - res=$(set -eu -o pipefail; false | true | echo 0) -} -expect 1 commandSubstitutionPipeFailure - -# `set -u` is enabled - -# note (...), making function use subshell, as unbound variable errors -# in the outer shell are *rightly* not recoverable. -useUnbound () ( - set -eu - # shellcheck disable=SC2154 - echo "$thisVariableIsNotBound" -) -expect 1 useUnbound - -# ! alone unfortunately negates `set -e`, but it works in functions: -# shellcheck disable=SC2251 -! true -funBang () { - ! true -} -expect 1 funBang -unset funBang - -# `grep -v -q` is not what we want for exit codes, but `grepInverse` is -# Avoid `grep -v -q`. The following line proves the point, and if it fails, -# we'll know that `grep` had a breaking change or `-v -q` may not be portable. -{ echo foo; echo bar; } | grep -v -q foo -{ echo foo; echo bar; } | expect 1 grepInverse foo - -# `grepQuiet` is quiet -res=$(set -eu -o pipefail; echo foo | grepQuiet foo | wc -c) -(( res == 0 )) -unset res - -# `greqQietInverse` is both -{ echo foo; echo bar; } | expect 1 grepQuietInverse foo -res=$(set -eu -o pipefail; echo foo | expect 1 grepQuietInverse foo | wc -c) -(( res == 0 )) -unset res diff --git a/tests/test-libstoreconsumer.sh b/tests/test-libstoreconsumer.sh deleted file mode 100644 index 8a77cf5a1..000000000 --- a/tests/test-libstoreconsumer.sh +++ /dev/null @@ -1,6 +0,0 @@ -source common.sh - -drv="$(nix-instantiate simple.nix)" -cat "$drv" -out="$(./test-libstoreconsumer/test-libstoreconsumer "$drv")" -cat "$out/hello" | grep -F "Hello World!" diff --git a/tests/test-libstoreconsumer/README.md b/tests/test-libstoreconsumer/README.md deleted file mode 100644 index ded69850f..000000000 --- a/tests/test-libstoreconsumer/README.md +++ /dev/null @@ -1,6 +0,0 @@ - -A very simple C++ consumer of the libstore library. - - - Keep it simple. Library consumers expect something simple. - - No build hook, or any other reinvocations. - - No more global state than necessary. diff --git a/tests/test-libstoreconsumer/local.mk b/tests/test-libstoreconsumer/local.mk deleted file mode 100644 index edc140723..000000000 --- a/tests/test-libstoreconsumer/local.mk +++ /dev/null @@ -1,15 +0,0 @@ -programs += test-libstoreconsumer - -test-libstoreconsumer_DIR := $(d) - -# do not install -test-libstoreconsumer_INSTALL_DIR := - -test-libstoreconsumer_SOURCES := \ - $(wildcard $(d)/*.cc) \ - -test-libstoreconsumer_CXXFLAGS += -I src/libutil -I src/libstore - -test-libstoreconsumer_LIBS = libstore libutil - -test-libstoreconsumer_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) $(LOWDOWN_LIBS) diff --git a/tests/test-libstoreconsumer/main.cc b/tests/test-libstoreconsumer/main.cc deleted file mode 100644 index c61489af6..000000000 --- a/tests/test-libstoreconsumer/main.cc +++ /dev/null @@ -1,45 +0,0 @@ -#include "globals.hh" -#include "store-api.hh" -#include "build-result.hh" -#include - -using namespace nix; - -int main (int argc, char **argv) -{ - try { - if (argc != 2) { - std::cerr << "Usage: " << argv[0] << " store/path/to/something.drv\n"; - return 1; - } - - std::string drvPath = argv[1]; - - initLibStore(); - - auto store = nix::openStore(); - - // build the derivation - - std::vector paths { - DerivedPath::Built { - .drvPath = makeConstantStorePathRef(store->parseStorePath(drvPath)), - .outputs = OutputsSpec::Names{"out"} - } - }; - - const auto results = store->buildPathsWithResults(paths, bmNormal, store); - - for (const auto & result : results) { - for (const auto & [outputName, realisation] : result.builtOutputs) { - std::cout << store->printStorePath(realisation.outPath) << "\n"; - } - } - - return 0; - - } catch (const std::exception & e) { - std::cerr << "Error: " << e.what() << "\n"; - return 1; - } -} diff --git a/tests/timeout.nix b/tests/timeout.nix deleted file mode 100644 index d0e949e31..000000000 --- a/tests/timeout.nix +++ /dev/null @@ -1,31 +0,0 @@ -with import ./config.nix; - -{ - - infiniteLoop = mkDerivation { - name = "timeout"; - buildCommand = '' - touch $out - echo "'timeout' builder entering an infinite loop" - while true ; do echo -n .; done - ''; - }; - - silent = mkDerivation { - name = "silent"; - buildCommand = '' - touch $out - sleep 60 - ''; - }; - - closeLog = mkDerivation { - name = "silent"; - buildCommand = '' - touch $out - exec > /dev/null 2>&1 - sleep 1000000000 - ''; - }; - -} diff --git a/tests/timeout.sh b/tests/timeout.sh deleted file mode 100644 index b179b79a2..000000000 --- a/tests/timeout.sh +++ /dev/null @@ -1,39 +0,0 @@ -# Test the `--timeout' option. - -source common.sh - -# XXX: This shouldn’t be, but #4813 cause this test to fail -needLocalStore "see #4813" - -messages=$(nix-build -Q timeout.nix -A infiniteLoop --timeout 2 2>&1) && status=0 || status=$? - -if [ $status -ne 101 ]; then - echo "error: 'nix-store' exited with '$status'; should have exited 101" - exit 1 -fi - -if echo "$messages" | grepQuietInvert "timed out"; then - echo "error: build may have failed for reasons other than timeout; output:" - echo "$messages" >&2 - exit 1 -fi - -if nix-build -Q timeout.nix -A infiniteLoop --max-build-log-size 100; then - echo "build should have failed" - exit 1 -fi - -if nix-build timeout.nix -A silent --max-silent-time 2; then - echo "build should have failed" - exit 1 -fi - -if nix-build timeout.nix -A closeLog; then - echo "build should have failed" - exit 1 -fi - -if nix build -f timeout.nix silent --max-silent-time 2; then - echo "build should have failed" - exit 1 -fi diff --git a/tests/toString-path.sh b/tests/toString-path.sh deleted file mode 100644 index 07eb87465..000000000 --- a/tests/toString-path.sh +++ /dev/null @@ -1,8 +0,0 @@ -source common.sh - -mkdir -p $TEST_ROOT/foo -echo bla > $TEST_ROOT/foo/bar - -[[ $(nix eval --raw --impure --expr "builtins.readFile (builtins.toString (builtins.fetchTree { type = \"path\"; path = \"$TEST_ROOT/foo\"; } + \"/bar\"))") = bla ]] - -[[ $(nix eval --json --impure --expr "builtins.readDir (builtins.toString (builtins.fetchTree { type = \"path\"; path = \"$TEST_ROOT/foo\"; }))") = '{"bar":"regular"}' ]] diff --git a/tests/undefined-variable.nix b/tests/undefined-variable.nix deleted file mode 100644 index 579985497..000000000 --- a/tests/undefined-variable.nix +++ /dev/null @@ -1 +0,0 @@ -let f = builtins.toFile "test-file.nix" "asd"; in import f diff --git a/tests/user-envs-migration.sh b/tests/user-envs-migration.sh deleted file mode 100644 index 187372b16..000000000 --- a/tests/user-envs-migration.sh +++ /dev/null @@ -1,35 +0,0 @@ -# Test that the migration of user environments -# (https://github.com/NixOS/nix/pull/5226) does preserve everything - -source common.sh - -if isDaemonNewer "2.4pre20211005"; then - skipTest "Daemon is too new" -fi - - -killDaemon -unset NIX_REMOTE - -clearStore -clearProfiles -rm -rf ~/.nix-profile - -# Fill the environment using the older Nix -PATH_WITH_NEW_NIX="$PATH" -export PATH="$NIX_DAEMON_PACKAGE/bin:$PATH" - -nix-env -f user-envs.nix -i foo-1.0 -nix-env -f user-envs.nix -i bar-0.1 - -# Migrate to the new profile dir, and ensure that everything’s there -export PATH="$PATH_WITH_NEW_NIX" -nix-env -q # Trigger the migration -( [[ -L ~/.nix-profile ]] && \ - [[ $(readlink ~/.nix-profile) == ~/.local/share/nix/profiles/profile ]] ) || \ - fail "The nix profile should point to the new location" - -(nix-env -q | grep foo && nix-env -q | grep bar && \ - [[ -e ~/.nix-profile/bin/foo ]] && \ - [[ $(nix-env --list-generations | wc -l) == 2 ]]) || - fail "The nix profile should have the same content as before the migration" diff --git a/tests/user-envs.builder.sh b/tests/user-envs.builder.sh deleted file mode 100644 index 5fafa797f..000000000 --- a/tests/user-envs.builder.sh +++ /dev/null @@ -1,5 +0,0 @@ -mkdir $out -mkdir $out/bin -echo "#! $shell" > $out/bin/$progName -echo "echo $name" >> $out/bin/$progName -chmod +x $out/bin/$progName diff --git a/tests/user-envs.nix b/tests/user-envs.nix deleted file mode 100644 index 46f8b51dd..000000000 --- a/tests/user-envs.nix +++ /dev/null @@ -1,34 +0,0 @@ -# Some dummy arguments... -{ foo ? "foo" -}: - -with import ./config.nix; - -assert foo == "foo"; - -let - - platforms = let x = "foobar"; in [ x x ]; - - makeDrv = name: progName: (mkDerivation { - name = assert progName != "fail"; name; - inherit progName system; - builder = ./user-envs.builder.sh; - } // { - meta = { - description = "A silly test package with some \${escaped anti-quotation} in it"; - inherit platforms; - }; - }); - -in - - [ - (makeDrv "foo-1.0" "foo") - (makeDrv "foo-2.0pre1" "foo") - (makeDrv "bar-0.1" "bar") - (makeDrv "foo-2.0" "foo") - (makeDrv "bar-0.1.1" "bar") - (makeDrv "foo-0.1" "foo" // { meta.priority = 10; }) - (makeDrv "fail-0.1" "fail") - ] diff --git a/tests/user-envs.sh b/tests/user-envs.sh deleted file mode 100644 index d1260ba04..000000000 --- a/tests/user-envs.sh +++ /dev/null @@ -1,190 +0,0 @@ -source common.sh - -if [ -z "${storeCleared-}" ]; then - clearStore -fi - -clearProfiles - -# Query installed: should be empty. -test "$(nix-env -p $profiles/test -q '*' | wc -l)" -eq 0 - -nix-env --switch-profile $profiles/test - -# Query available: should contain several. -test "$(nix-env -f ./user-envs.nix -qa '*' | wc -l)" -eq 6 -outPath10=$(nix-env -f ./user-envs.nix -qa --out-path --no-name '*' | grep foo-1.0) -drvPath10=$(nix-env -f ./user-envs.nix -qa --drv-path --no-name '*' | grep foo-1.0) -[ -n "$outPath10" -a -n "$drvPath10" ] - -# Query with json -nix-env -f ./user-envs.nix -qa --json | jq -e '.[] | select(.name == "bar-0.1") | [ - .outputName == "out", - .outputs.out == null -] | all' -nix-env -f ./user-envs.nix -qa --json --out-path | jq -e '.[] | select(.name == "bar-0.1") | [ - .outputName == "out", - (.outputs.out | test("'$NIX_STORE_DIR'.*-0\\.1")) -] | all' - -# Query descriptions. -nix-env -f ./user-envs.nix -qa '*' --description | grepQuiet silly -rm -rf $HOME/.nix-defexpr -ln -s $(pwd)/user-envs.nix $HOME/.nix-defexpr -nix-env -qa '*' --description | grepQuiet silly - -# Query the system. -nix-env -qa '*' --system | grepQuiet $system - -# Install "foo-1.0". -nix-env -i foo-1.0 - -# Query installed: should contain foo-1.0 now (which should be -# executable). -test "$(nix-env -q '*' | wc -l)" -eq 1 -nix-env -q '*' | grepQuiet foo-1.0 -test "$($profiles/test/bin/foo)" = "foo-1.0" - -# Test nix-env -qc to compare installed against available packages, and vice versa. -nix-env -qc '*' | grepQuiet '< 2.0' -nix-env -qac '*' | grepQuiet '> 1.0' - -# Test the -b flag to filter out source-only packages. -[ "$(nix-env -qab | wc -l)" -eq 1 ] - -# Test the -s flag to get package status. -nix-env -qas | grepQuiet 'IP- foo-1.0' -nix-env -qas | grepQuiet -- '--- bar-0.1' - -# Disable foo. -nix-env --set-flag active false foo -(! [ -e "$profiles/test/bin/foo" ]) - -# Enable foo. -nix-env --set-flag active true foo -[ -e "$profiles/test/bin/foo" ] - -# Store the path of foo-1.0. -outPath10_=$(nix-env -q --out-path --no-name '*' | grep foo-1.0) -echo "foo-1.0 = $outPath10" -[ "$outPath10" = "$outPath10_" ] - -# Install "foo-2.0pre1": should remove foo-1.0. -nix-env -i foo-2.0pre1 - -# Query installed: should contain foo-2.0pre1 now. -test "$(nix-env -q '*' | wc -l)" -eq 1 -nix-env -q '*' | grepQuiet foo-2.0pre1 -test "$($profiles/test/bin/foo)" = "foo-2.0pre1" - -# Upgrade "foo": should install foo-2.0. -NIX_PATH=nixpkgs=./user-envs.nix:${NIX_PATH-} nix-env -f '' -u foo - -# Query installed: should contain foo-2.0 now. -test "$(nix-env -q '*' | wc -l)" -eq 1 -nix-env -q '*' | grepQuiet foo-2.0 -test "$($profiles/test/bin/foo)" = "foo-2.0" - -# Store the path of foo-2.0. -outPath20=$(nix-env -q --out-path --no-name '*' | grep foo-2.0) -test -n "$outPath20" - -# Install bar-0.1, uninstall foo. -nix-env -i bar-0.1 -nix-env -e foo - -# Query installed: should only contain bar-0.1 now. -if nix-env -q '*' | grepQuiet foo; then false; fi -nix-env -q '*' | grepQuiet bar - -# Rollback: should bring "foo" back. -oldGen="$(nix-store -q --resolve $profiles/test)" -nix-env --rollback -[ "$(nix-store -q --resolve $profiles/test)" != "$oldGen" ] -nix-env -q '*' | grepQuiet foo-2.0 -nix-env -q '*' | grepQuiet bar - -# Rollback again: should remove "bar". -nix-env --rollback -nix-env -q '*' | grepQuiet foo-2.0 -if nix-env -q '*' | grepQuiet bar; then false; fi - -# Count generations. -nix-env --list-generations -test "$(nix-env --list-generations | wc -l)" -eq 7 - -# Doing the same operation twice results in the same generation, which triggers -# "lazy" behaviour and does not create a new symlink. - -nix-env -i foo -nix-env -i foo - -# Count generations. -nix-env --list-generations -test "$(nix-env --list-generations | wc -l)" -eq 8 - -# Switch to a specified generation. -nix-env --switch-generation 7 -[ "$(nix-store -q --resolve $profiles/test)" = "$oldGen" ] - -# Install foo-1.0, now using its store path. -nix-env -i "$outPath10" -nix-env -q '*' | grepQuiet foo-1.0 -nix-store -qR $profiles/test | grep "$outPath10" -nix-store -q --referrers-closure $profiles/test | grep "$(nix-store -q --resolve $profiles/test)" -[ "$(nix-store -q --deriver "$outPath10")" = $drvPath10 ] - -# Uninstall foo-1.0, using a symlink to its store path. -ln -sfn $outPath10/bin/foo $TEST_ROOT/symlink -nix-env -e $TEST_ROOT/symlink -if nix-env -q '*' | grepQuiet foo; then false; fi -nix-store -qR $profiles/test | grepInverse "$outPath10" - -# Install foo-1.0, now using a symlink to its store path. -nix-env -i $TEST_ROOT/symlink -nix-env -q '*' | grepQuiet foo - -# Delete all old generations. -nix-env --delete-generations old - -# Run the garbage collector. This should get rid of foo-2.0 but not -# foo-1.0. -nix-collect-garbage -test -e "$outPath10" -(! [ -e "$outPath20" ]) - -# Uninstall everything -nix-env -e '*' -test "$(nix-env -q '*' | wc -l)" -eq 0 - -# Installing "foo" should only install the newest foo. -nix-env -i foo -test "$(nix-env -q '*' | grep foo- | wc -l)" -eq 1 -nix-env -q '*' | grepQuiet foo-2.0 - -# On the other hand, this should install both (and should fail due to -# a collision). -nix-env -e '*' -(! nix-env -i foo-1.0 foo-2.0) - -# Installing "*" should install one foo and one bar. -nix-env -e '*' -nix-env -i '*' -test "$(nix-env -q '*' | wc -l)" -eq 2 -nix-env -q '*' | grepQuiet foo-2.0 -nix-env -q '*' | grepQuiet bar-0.1.1 - -# Test priorities: foo-0.1 has a lower priority than foo-1.0, so it -# should be possible to install both without a collision. Also test -# ‘--set-flag priority’ to manually override the declared priorities. -nix-env -e '*' -nix-env -i foo-0.1 foo-1.0 -[ "$($profiles/test/bin/foo)" = "foo-1.0" ] -nix-env --set-flag priority 1 foo-0.1 -[ "$($profiles/test/bin/foo)" = "foo-0.1" ] - -# Test nix-env --set. -nix-env --set $outPath10 -[ "$(nix-store -q --resolve $profiles/test)" = $outPath10 ] -nix-env --set $drvPath10 -[ "$(nix-store -q --resolve $profiles/test)" = $outPath10 ] diff --git a/tests/why-depends.sh b/tests/why-depends.sh deleted file mode 100644 index 9680bf80e..000000000 --- a/tests/why-depends.sh +++ /dev/null @@ -1,29 +0,0 @@ -source common.sh - -clearStore - -cp ./dependencies.nix ./dependencies.builder0.sh ./config.nix $TEST_HOME - -cd $TEST_HOME - -nix why-depends --derivation --file ./dependencies.nix input2_drv input1_drv -nix why-depends --file ./dependencies.nix input2_drv input1_drv - -nix-build ./dependencies.nix -A input0_drv -o dep -nix-build ./dependencies.nix -o toplevel - -FAST_WHY_DEPENDS_OUTPUT=$(nix why-depends ./toplevel ./dep) -PRECISE_WHY_DEPENDS_OUTPUT=$(nix why-depends ./toplevel ./dep --precise) - -# Both outputs should show that `input-2` is in the dependency chain -echo "$FAST_WHY_DEPENDS_OUTPUT" | grepQuiet input-2 -echo "$PRECISE_WHY_DEPENDS_OUTPUT" | grepQuiet input-2 - -# But only the “precise” one should refer to `reference-to-input-2` -echo "$FAST_WHY_DEPENDS_OUTPUT" | grepQuietInverse reference-to-input-2 -echo "$PRECISE_WHY_DEPENDS_OUTPUT" | grepQuiet reference-to-input-2 - -<<<"$PRECISE_WHY_DEPENDS_OUTPUT" sed -n '2p' | grepQuiet "└───reference-to-input-2 -> " -<<<"$PRECISE_WHY_DEPENDS_OUTPUT" sed -n '3p' | grep " →" | grepQuiet "dependencies-input-2" -<<<"$PRECISE_WHY_DEPENDS_OUTPUT" sed -n '4p' | grepQuiet " └───input0: …" # in input-2, file input0 -<<<"$PRECISE_WHY_DEPENDS_OUTPUT" sed -n '5p' | grep " →" | grepQuiet "dependencies-input-0" # is dependencies-input-0 referenced diff --git a/tests/zstd.sh b/tests/zstd.sh deleted file mode 100644 index ba7c20501..000000000 --- a/tests/zstd.sh +++ /dev/null @@ -1,28 +0,0 @@ -source common.sh - -clearStore -clearCache - -cacheURI="file://$cacheDir?compression=zstd" - -outPath=$(nix-build dependencies.nix --no-out-link) - -nix copy --to $cacheURI $outPath - -HASH=$(nix hash path $outPath) - -clearStore -clearCacheCache - -nix copy --from $cacheURI $outPath --no-check-sigs - -if ls $cacheDir/nar/*.zst &> /dev/null; then - echo "files do exist" -else - echo "nars do not exist" - exit 1 -fi - -HASH2=$(nix hash path $outPath) - -[[ $HASH = $HASH2 ]] -- cgit v1.2.3 From f7f37035c81fa825a4dfc2df1ad2589013ac6380 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Fri, 25 Aug 2023 10:20:28 -0400 Subject: Move tests to separate directories, and document Today, with the tests inside a `tests` intermingled with the corresponding library's source code, we have a few problems: - We have to be careful that wildcards don't end up with tests being built as part of Nix proper, or test headers being installed as part of Nix proper. - Tests in libraries but not executables is not right: - It means each executable runs the previous unit tests again, because it needs the libraries. - It doesn't work right on Windows, which doesn't want you to load a DLL just for the side global variable . It could be made to work with the dlopen equivalent, but that's gross! This reorg solves these problems. There is a remaining problem which is that sibbling headers (like `hash.hh` the test header vs `hash.hh` the main `libnixutil` header) end up shadowing each other. This PR doesn't solve that. That is left as future work for a future PR. Co-authored-by: Valentin Gagarin (cherry picked from commit 91b6833686a6a6d9eac7f3f66393ec89ef1d3b57) (cherry picked from commit a61e42adb528b3d40ce43e07c79368d779a8b624) --- .gitignore | 6 +- Makefile | 9 +- doc/internal-api/doxygen.cfg.in | 12 +- doc/manual/src/contributing/testing.md | 14 +- flake.nix | 1 + src/libexpr/tests/derived-path.cc | 68 -- src/libexpr/tests/error_traces.cc | 1298 --------------------- src/libexpr/tests/flakeref.cc | 22 - src/libexpr/tests/json.cc | 68 -- src/libexpr/tests/libexpr.hh | 140 --- src/libexpr/tests/local.mk | 19 - src/libexpr/tests/primops.cc | 832 ------------- src/libexpr/tests/search-path.cc | 90 -- src/libexpr/tests/trivial.cc | 196 ---- src/libexpr/tests/value/context.cc | 162 --- src/libexpr/tests/value/context.hh | 31 - src/libexpr/tests/value/print.cc | 236 ---- src/libstore/tests/derivation.cc | 369 ------ src/libstore/tests/derived-path.cc | 153 --- src/libstore/tests/derived-path.hh | 39 - src/libstore/tests/downstream-placeholder.cc | 41 - src/libstore/tests/libstore.hh | 26 - src/libstore/tests/local.mk | 29 - src/libstore/tests/machines.cc | 169 --- src/libstore/tests/nar-info-disk-cache.cc | 123 -- src/libstore/tests/outputs-spec.cc | 239 ---- src/libstore/tests/outputs-spec.hh | 18 - src/libstore/tests/path.cc | 162 --- src/libstore/tests/path.hh | 29 - src/libstore/tests/references.cc | 45 - src/libstore/tests/test-data/machines.bad_format | 1 - src/libstore/tests/test-data/machines.valid | 3 - src/libutil/tests/canon-path.cc | 162 --- src/libutil/tests/chunked-vector.cc | 54 - src/libutil/tests/closure.cc | 70 -- src/libutil/tests/compression.cc | 96 -- src/libutil/tests/config.cc | 295 ----- src/libutil/tests/git.cc | 33 - src/libutil/tests/hash.cc | 95 -- src/libutil/tests/hash.hh | 16 - src/libutil/tests/hilite.cc | 66 -- src/libutil/tests/local.mk | 29 - src/libutil/tests/logging.cc | 370 ------ src/libutil/tests/lru-cache.cc | 130 --- src/libutil/tests/pool.cc | 127 -- src/libutil/tests/references.cc | 46 - src/libutil/tests/suggestions.cc | 43 - src/libutil/tests/tests.cc | 659 ----------- src/libutil/tests/url.cc | 338 ------ src/libutil/tests/xml-writer.cc | 105 -- tests/unit/libexpr-support/local.mk | 19 + tests/unit/libexpr-support/tests/libexpr.hh | 140 +++ tests/unit/libexpr-support/tests/value/context.cc | 30 + tests/unit/libexpr-support/tests/value/context.hh | 31 + tests/unit/libexpr/derived-path.cc | 68 ++ tests/unit/libexpr/error_traces.cc | 1298 +++++++++++++++++++++ tests/unit/libexpr/flakeref.cc | 22 + tests/unit/libexpr/json.cc | 68 ++ tests/unit/libexpr/local.mk | 32 + tests/unit/libexpr/primops.cc | 832 +++++++++++++ tests/unit/libexpr/search-path.cc | 90 ++ tests/unit/libexpr/trivial.cc | 196 ++++ tests/unit/libexpr/value/context.cc | 132 +++ tests/unit/libexpr/value/print.cc | 236 ++++ tests/unit/libstore-support/local.mk | 17 + tests/unit/libstore-support/tests/derived-path.cc | 57 + tests/unit/libstore-support/tests/derived-path.hh | 39 + tests/unit/libstore-support/tests/libstore.hh | 26 + tests/unit/libstore-support/tests/outputs-spec.cc | 24 + tests/unit/libstore-support/tests/outputs-spec.hh | 18 + tests/unit/libstore-support/tests/path.cc | 82 ++ tests/unit/libstore-support/tests/path.hh | 32 + tests/unit/libstore/derivation.cc | 369 ++++++ tests/unit/libstore/derived-path.cc | 100 ++ tests/unit/libstore/downstream-placeholder.cc | 41 + tests/unit/libstore/local.mk | 27 + tests/unit/libstore/machines.cc | 169 +++ tests/unit/libstore/nar-info-disk-cache.cc | 123 ++ tests/unit/libstore/outputs-spec.cc | 214 ++++ tests/unit/libstore/path.cc | 89 ++ tests/unit/libstore/references.cc | 45 + tests/unit/libstore/test-data/machines.bad_format | 1 + tests/unit/libstore/test-data/machines.valid | 3 + tests/unit/libutil-support/local.mk | 15 + tests/unit/libutil-support/tests/hash.cc | 20 + tests/unit/libutil-support/tests/hash.hh | 16 + tests/unit/libutil/canon-path.cc | 162 +++ tests/unit/libutil/chunked-vector.cc | 54 + tests/unit/libutil/closure.cc | 70 ++ tests/unit/libutil/compression.cc | 96 ++ tests/unit/libutil/config.cc | 295 +++++ tests/unit/libutil/git.cc | 33 + tests/unit/libutil/hash.cc | 77 ++ tests/unit/libutil/hilite.cc | 66 ++ tests/unit/libutil/local.mk | 23 + tests/unit/libutil/logging.cc | 370 ++++++ tests/unit/libutil/lru-cache.cc | 130 +++ tests/unit/libutil/pool.cc | 127 ++ tests/unit/libutil/references.cc | 46 + tests/unit/libutil/suggestions.cc | 43 + tests/unit/libutil/tests.cc | 659 +++++++++++ tests/unit/libutil/url.cc | 338 ++++++ tests/unit/libutil/xml-writer.cc | 105 ++ 103 files changed, 7446 insertions(+), 7353 deletions(-) delete mode 100644 src/libexpr/tests/derived-path.cc delete mode 100644 src/libexpr/tests/error_traces.cc delete mode 100644 src/libexpr/tests/flakeref.cc delete mode 100644 src/libexpr/tests/json.cc delete mode 100644 src/libexpr/tests/libexpr.hh delete mode 100644 src/libexpr/tests/local.mk delete mode 100644 src/libexpr/tests/primops.cc delete mode 100644 src/libexpr/tests/search-path.cc delete mode 100644 src/libexpr/tests/trivial.cc delete mode 100644 src/libexpr/tests/value/context.cc delete mode 100644 src/libexpr/tests/value/context.hh delete mode 100644 src/libexpr/tests/value/print.cc delete mode 100644 src/libstore/tests/derivation.cc delete mode 100644 src/libstore/tests/derived-path.cc delete mode 100644 src/libstore/tests/derived-path.hh delete mode 100644 src/libstore/tests/downstream-placeholder.cc delete mode 100644 src/libstore/tests/libstore.hh delete mode 100644 src/libstore/tests/local.mk delete mode 100644 src/libstore/tests/machines.cc delete mode 100644 src/libstore/tests/nar-info-disk-cache.cc delete mode 100644 src/libstore/tests/outputs-spec.cc delete mode 100644 src/libstore/tests/outputs-spec.hh delete mode 100644 src/libstore/tests/path.cc delete mode 100644 src/libstore/tests/path.hh delete mode 100644 src/libstore/tests/references.cc delete mode 100644 src/libstore/tests/test-data/machines.bad_format delete mode 100644 src/libstore/tests/test-data/machines.valid delete mode 100644 src/libutil/tests/canon-path.cc delete mode 100644 src/libutil/tests/chunked-vector.cc delete mode 100644 src/libutil/tests/closure.cc delete mode 100644 src/libutil/tests/compression.cc delete mode 100644 src/libutil/tests/config.cc delete mode 100644 src/libutil/tests/git.cc delete mode 100644 src/libutil/tests/hash.cc delete mode 100644 src/libutil/tests/hash.hh delete mode 100644 src/libutil/tests/hilite.cc delete mode 100644 src/libutil/tests/local.mk delete mode 100644 src/libutil/tests/logging.cc delete mode 100644 src/libutil/tests/lru-cache.cc delete mode 100644 src/libutil/tests/pool.cc delete mode 100644 src/libutil/tests/references.cc delete mode 100644 src/libutil/tests/suggestions.cc delete mode 100644 src/libutil/tests/tests.cc delete mode 100644 src/libutil/tests/url.cc delete mode 100644 src/libutil/tests/xml-writer.cc create mode 100644 tests/unit/libexpr-support/local.mk create mode 100644 tests/unit/libexpr-support/tests/libexpr.hh create mode 100644 tests/unit/libexpr-support/tests/value/context.cc create mode 100644 tests/unit/libexpr-support/tests/value/context.hh create mode 100644 tests/unit/libexpr/derived-path.cc create mode 100644 tests/unit/libexpr/error_traces.cc create mode 100644 tests/unit/libexpr/flakeref.cc create mode 100644 tests/unit/libexpr/json.cc create mode 100644 tests/unit/libexpr/local.mk create mode 100644 tests/unit/libexpr/primops.cc create mode 100644 tests/unit/libexpr/search-path.cc create mode 100644 tests/unit/libexpr/trivial.cc create mode 100644 tests/unit/libexpr/value/context.cc create mode 100644 tests/unit/libexpr/value/print.cc create mode 100644 tests/unit/libstore-support/local.mk create mode 100644 tests/unit/libstore-support/tests/derived-path.cc create mode 100644 tests/unit/libstore-support/tests/derived-path.hh create mode 100644 tests/unit/libstore-support/tests/libstore.hh create mode 100644 tests/unit/libstore-support/tests/outputs-spec.cc create mode 100644 tests/unit/libstore-support/tests/outputs-spec.hh create mode 100644 tests/unit/libstore-support/tests/path.cc create mode 100644 tests/unit/libstore-support/tests/path.hh create mode 100644 tests/unit/libstore/derivation.cc create mode 100644 tests/unit/libstore/derived-path.cc create mode 100644 tests/unit/libstore/downstream-placeholder.cc create mode 100644 tests/unit/libstore/local.mk create mode 100644 tests/unit/libstore/machines.cc create mode 100644 tests/unit/libstore/nar-info-disk-cache.cc create mode 100644 tests/unit/libstore/outputs-spec.cc create mode 100644 tests/unit/libstore/path.cc create mode 100644 tests/unit/libstore/references.cc create mode 100644 tests/unit/libstore/test-data/machines.bad_format create mode 100644 tests/unit/libstore/test-data/machines.valid create mode 100644 tests/unit/libutil-support/local.mk create mode 100644 tests/unit/libutil-support/tests/hash.cc create mode 100644 tests/unit/libutil-support/tests/hash.hh create mode 100644 tests/unit/libutil/canon-path.cc create mode 100644 tests/unit/libutil/chunked-vector.cc create mode 100644 tests/unit/libutil/closure.cc create mode 100644 tests/unit/libutil/compression.cc create mode 100644 tests/unit/libutil/config.cc create mode 100644 tests/unit/libutil/git.cc create mode 100644 tests/unit/libutil/hash.cc create mode 100644 tests/unit/libutil/hilite.cc create mode 100644 tests/unit/libutil/local.mk create mode 100644 tests/unit/libutil/logging.cc create mode 100644 tests/unit/libutil/lru-cache.cc create mode 100644 tests/unit/libutil/pool.cc create mode 100644 tests/unit/libutil/references.cc create mode 100644 tests/unit/libutil/suggestions.cc create mode 100644 tests/unit/libutil/tests.cc create mode 100644 tests/unit/libutil/url.cc create mode 100644 tests/unit/libutil/xml-writer.cc diff --git a/.gitignore b/.gitignore index 2d3314015..1e1361f5a 100644 --- a/.gitignore +++ b/.gitignore @@ -41,14 +41,14 @@ perl/Makefile.config /src/libexpr/parser-tab.hh /src/libexpr/parser-tab.output /src/libexpr/nix.tbl -/src/libexpr/tests/libnixexpr-tests +/tests/unit/libexpr/libnixexpr-tests # /src/libstore/ *.gen.* -/src/libstore/tests/libnixstore-tests +/tests/unit/libstore/libnixstore-tests # /src/libutil/ -/src/libutil/tests/libnixutil-tests +/tests/unit/libutil/libnixutil-tests /src/nix/nix diff --git a/Makefile b/Makefile index c0b27e904..41c0ab68a 100644 --- a/Makefile +++ b/Makefile @@ -23,9 +23,12 @@ makefiles = \ ifeq ($(tests), yes) makefiles += \ - src/libutil/tests/local.mk \ - src/libstore/tests/local.mk \ - src/libexpr/tests/local.mk \ + tests/unit/libutil/local.mk \ + tests/unit/libutil-support/local.mk \ + tests/unit/libstore/local.mk \ + tests/unit/libstore-support/local.mk \ + tests/unit/libexpr/local.mk \ + tests/unit/libexpr-support/local.mk \ tests/functional/local.mk \ tests/functional/ca/local.mk \ tests/functional/dyn-drv/local.mk \ diff --git a/doc/internal-api/doxygen.cfg.in b/doc/internal-api/doxygen.cfg.in index 8f526536d..a339662e3 100644 --- a/doc/internal-api/doxygen.cfg.in +++ b/doc/internal-api/doxygen.cfg.in @@ -39,17 +39,21 @@ INPUT = \ src/libcmd \ src/libexpr \ src/libexpr/flake \ - src/libexpr/tests \ - src/libexpr/tests/value \ + tests/unit/libexpr \ + tests/unit/libexpr/value \ + tests/unit/libexpr/test \ + tests/unit/libexpr/test/value \ src/libexpr/value \ src/libfetchers \ src/libmain \ src/libstore \ src/libstore/build \ src/libstore/builtins \ - src/libstore/tests \ + tests/unit/libstore \ + tests/unit/libstore/test \ src/libutil \ - src/libutil/tests \ + tests/unit/libutil \ + tests/unit/libutil/test \ src/nix \ src/nix-env \ src/nix-store diff --git a/doc/manual/src/contributing/testing.md b/doc/manual/src/contributing/testing.md index ccd90088e..1b15d12b1 100644 --- a/doc/manual/src/contributing/testing.md +++ b/doc/manual/src/contributing/testing.md @@ -3,13 +3,25 @@ ## Unit-tests The unit-tests for each Nix library (`libexpr`, `libstore`, etc..) are defined -under `src/{library_name}/tests` using the +under `tests/unit/{library_name}/tests` using the [googletest](https://google.github.io/googletest/) and [rapidcheck](https://github.com/emil-e/rapidcheck) frameworks. You can run the whole testsuite with `make check`, or the tests for a specific component with `make libfoo-tests_RUN`. Finer-grained filtering is also possible using the [--gtest_filter](https://google.github.io/googletest/advanced.html#running-a-subset-of-the-tests) command-line option, or the `GTEST_FILTER` environment variable. +### Unit test support libraries + +There are headers and code which are not just used to test the library in question, but also downstream libraries. +For example, we do [property testing] with the [rapidcheck] library. +This requires writing `Arbitrary` "instances", which are used to describe how to generate values of a given type for the sake of running property tests. +Because types contain other types, `Arbitrary` "instances" for some type are not just useful for testing that type, but also any other type that contains it. +Downstream types frequently contain upstream types, so it is very important that we share arbitrary instances so that downstream libraries' property tests can also use them. + +It is important that these testing libraries don't contain any actual tests themselves. +On some platforms they would be run as part of every test executable that uses them, which is redundant. +On other platforms they wouldn't be run at all. + ## Functional tests The functional tests reside under the `tests/functional` directory and are listed in `tests/functional/local.mk`. diff --git a/flake.nix b/flake.nix index beedb000f..230bb6031 100644 --- a/flake.nix +++ b/flake.nix @@ -73,6 +73,7 @@ ./precompiled-headers.h ./src ./tests/functional + ./tests/unit ./COPYING ./scripts/local.mk (fileset.fileFilter (f: lib.strings.hasPrefix "nix-profile" f.name) ./scripts) diff --git a/src/libexpr/tests/derived-path.cc b/src/libexpr/tests/derived-path.cc deleted file mode 100644 index d5fc6f201..000000000 --- a/src/libexpr/tests/derived-path.cc +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include -#include - -#include "tests/derived-path.hh" -#include "tests/libexpr.hh" - -namespace nix { - -// Testing of trivial expressions -class DerivedPathExpressionTest : public LibExprTest {}; - -// FIXME: `RC_GTEST_FIXTURE_PROP` isn't calling `SetUpTestSuite` because it is -// no a real fixture. -// -// See https://github.com/emil-e/rapidcheck/blob/master/doc/gtest.md#rc_gtest_fixture_propfixture-name-args -TEST_F(DerivedPathExpressionTest, force_init) -{ -} - -#ifndef COVERAGE - -RC_GTEST_FIXTURE_PROP( - DerivedPathExpressionTest, - prop_opaque_path_round_trip, - (const SingleDerivedPath::Opaque & o)) -{ - auto * v = state.allocValue(); - state.mkStorePathString(o.path, *v); - auto d = state.coerceToSingleDerivedPath(noPos, *v, ""); - RC_ASSERT(SingleDerivedPath { o } == d); -} - -// TODO use DerivedPath::Built for parameter once it supports a single output -// path only. - -RC_GTEST_FIXTURE_PROP( - DerivedPathExpressionTest, - prop_derived_path_built_placeholder_round_trip, - (const SingleDerivedPath::Built & b)) -{ - /** - * We set these in tests rather than the regular globals so we don't have - * to worry about race conditions if the tests run concurrently. - */ - ExperimentalFeatureSettings mockXpSettings; - mockXpSettings.set("experimental-features", "ca-derivations"); - - auto * v = state.allocValue(); - state.mkOutputString(*v, b, std::nullopt, mockXpSettings); - auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, ""); - RC_ASSERT(SingleDerivedPath { b } == d); -} - -RC_GTEST_FIXTURE_PROP( - DerivedPathExpressionTest, - prop_derived_path_built_out_path_round_trip, - (const SingleDerivedPath::Built & b, const StorePath & outPath)) -{ - auto * v = state.allocValue(); - state.mkOutputString(*v, b, outPath); - auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, ""); - RC_ASSERT(SingleDerivedPath { b } == d); -} - -#endif - -} /* namespace nix */ diff --git a/src/libexpr/tests/error_traces.cc b/src/libexpr/tests/error_traces.cc deleted file mode 100644 index 285651256..000000000 --- a/src/libexpr/tests/error_traces.cc +++ /dev/null @@ -1,1298 +0,0 @@ -#include -#include - -#include "tests/libexpr.hh" - -namespace nix { - - using namespace testing; - - // Testing eval of PrimOp's - class ErrorTraceTest : public LibExprTest { }; - - TEST_F(ErrorTraceTest, TraceBuilder) { - ASSERT_THROW( - state.error("Not much").debugThrow(), - EvalError - ); - - ASSERT_THROW( - state.error("Not much").withTrace(noPos, "No more").debugThrow(), - EvalError - ); - - ASSERT_THROW( - try { - try { - state.error("Not much").withTrace(noPos, "No more").debugThrow(); - } catch (Error & e) { - e.addTrace(state.positions[noPos], "Something", ""); - throw; - } - } catch (BaseError & e) { - ASSERT_EQ(PrintToString(e.info().msg), - PrintToString(hintfmt("Not much"))); - auto trace = e.info().traces.rbegin(); - ASSERT_EQ(e.info().traces.size(), 2); - ASSERT_EQ(PrintToString(trace->hint), - PrintToString(hintfmt("No more"))); - trace++; - ASSERT_EQ(PrintToString(trace->hint), - PrintToString(hintfmt("Something"))); - throw; - } - , EvalError - ); - } - - TEST_F(ErrorTraceTest, NestedThrows) { - try { - state.error("Not much").withTrace(noPos, "No more").debugThrow(); - } catch (BaseError & e) { - try { - state.error("Not much more").debugThrow(); - } catch (Error & e2) { - e.addTrace(state.positions[noPos], "Something", ""); - //e2.addTrace(state.positions[noPos], "Something", ""); - ASSERT_TRUE(e.info().traces.size() == 2); - ASSERT_TRUE(e2.info().traces.size() == 0); - ASSERT_FALSE(&e.info() == &e2.info()); - } - } - } - -#define ASSERT_TRACE1(args, type, message) \ - ASSERT_THROW( \ - std::string expr(args); \ - std::string name = expr.substr(0, expr.find(" ")); \ - try { \ - Value v = eval("builtins." args); \ - state.forceValueDeep(v); \ - } catch (BaseError & e) { \ - ASSERT_EQ(PrintToString(e.info().msg), \ - PrintToString(message)); \ - ASSERT_EQ(e.info().traces.size(), 1) << "while testing " args << std::endl << e.what(); \ - auto trace = e.info().traces.rbegin(); \ - ASSERT_EQ(PrintToString(trace->hint), \ - PrintToString(hintfmt("while calling the '%s' builtin", name))); \ - throw; \ - } \ - , type \ - ) - -#define ASSERT_TRACE2(args, type, message, context) \ - ASSERT_THROW( \ - std::string expr(args); \ - std::string name = expr.substr(0, expr.find(" ")); \ - try { \ - Value v = eval("builtins." args); \ - state.forceValueDeep(v); \ - } catch (BaseError & e) { \ - ASSERT_EQ(PrintToString(e.info().msg), \ - PrintToString(message)); \ - ASSERT_EQ(e.info().traces.size(), 2) << "while testing " args << std::endl << e.what(); \ - auto trace = e.info().traces.rbegin(); \ - ASSERT_EQ(PrintToString(trace->hint), \ - PrintToString(context)); \ - ++trace; \ - ASSERT_EQ(PrintToString(trace->hint), \ - PrintToString(hintfmt("while calling the '%s' builtin", name))); \ - throw; \ - } \ - , type \ - ) - - TEST_F(ErrorTraceTest, genericClosure) { - ASSERT_TRACE2("genericClosure 1", - TypeError, - hintfmt("value is %s while a set was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure {}", - TypeError, - hintfmt("attribute '%s' missing", "startSet"), - hintfmt("in the attrset passed as argument to builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure { startSet = 1; }", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating the 'startSet' attribute passed as argument to builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = true; }", - TypeError, - hintfmt("value is %s while a function was expected", "a Boolean"), - hintfmt("while evaluating the 'operator' attribute passed as argument to builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = item: true; }", - TypeError, - hintfmt("value is %s while a list was expected", "a Boolean"), - hintfmt("while evaluating the return value of the `operator` passed to builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = item: [ true ]; }", - TypeError, - hintfmt("value is %s while a set was expected", "a Boolean"), - hintfmt("while evaluating one of the elements generated by (or initially passed to) builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = item: [ {} ]; }", - TypeError, - hintfmt("attribute '%s' missing", "key"), - hintfmt("in one of the attrsets generated by (or initially passed to) builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = item: [{ key = ''a''; }]; }", - EvalError, - hintfmt("cannot compare %s with %s", "a string", "an integer"), - hintfmt("while comparing the `key` attributes of two genericClosure elements")); - - ASSERT_TRACE2("genericClosure { startSet = [ true ]; operator = item: [{ key = ''a''; }]; }", - TypeError, - hintfmt("value is %s while a set was expected", "a Boolean"), - hintfmt("while evaluating one of the elements generated by (or initially passed to) builtins.genericClosure")); - - } - - - TEST_F(ErrorTraceTest, replaceStrings) { - ASSERT_TRACE2("replaceStrings 0 0 {}", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.replaceStrings")); - - ASSERT_TRACE2("replaceStrings [] 0 {}", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating the second argument passed to builtins.replaceStrings")); - - ASSERT_TRACE1("replaceStrings [ 0 ] [] {}", - EvalError, - hintfmt("'from' and 'to' arguments passed to builtins.replaceStrings have different lengths")); - - ASSERT_TRACE2("replaceStrings [ 1 ] [ \"new\" ] {}", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating one of the strings to replace passed to builtins.replaceStrings")); - - ASSERT_TRACE2("replaceStrings [ \"oo\" ] [ true ] \"foo\"", - TypeError, - hintfmt("value is %s while a string was expected", "a Boolean"), - hintfmt("while evaluating one of the replacement strings passed to builtins.replaceStrings")); - - ASSERT_TRACE2("replaceStrings [ \"old\" ] [ \"new\" ] {}", - TypeError, - hintfmt("value is %s while a string was expected", "a set"), - hintfmt("while evaluating the third argument passed to builtins.replaceStrings")); - - } - - - TEST_F(ErrorTraceTest, scopedImport) { - } - - - TEST_F(ErrorTraceTest, import) { - } - - - TEST_F(ErrorTraceTest, typeOf) { - } - - - TEST_F(ErrorTraceTest, isNull) { - } - - - TEST_F(ErrorTraceTest, isFunction) { - } - - - TEST_F(ErrorTraceTest, isInt) { - } - - - TEST_F(ErrorTraceTest, isFloat) { - } - - - TEST_F(ErrorTraceTest, isString) { - } - - - TEST_F(ErrorTraceTest, isBool) { - } - - - TEST_F(ErrorTraceTest, isPath) { - } - - - TEST_F(ErrorTraceTest, break) { - } - - - TEST_F(ErrorTraceTest, abort) { - } - - - TEST_F(ErrorTraceTest, throw) { - } - - - TEST_F(ErrorTraceTest, addErrorContext) { - } - - - TEST_F(ErrorTraceTest, ceil) { - ASSERT_TRACE2("ceil \"foo\"", - TypeError, - hintfmt("value is %s while a float was expected", "a string"), - hintfmt("while evaluating the first argument passed to builtins.ceil")); - - } - - - TEST_F(ErrorTraceTest, floor) { - ASSERT_TRACE2("floor \"foo\"", - TypeError, - hintfmt("value is %s while a float was expected", "a string"), - hintfmt("while evaluating the first argument passed to builtins.floor")); - - } - - - TEST_F(ErrorTraceTest, tryEval) { - } - - - TEST_F(ErrorTraceTest, getEnv) { - ASSERT_TRACE2("getEnv [ ]", - TypeError, - hintfmt("value is %s while a string was expected", "a list"), - hintfmt("while evaluating the first argument passed to builtins.getEnv")); - - } - - - TEST_F(ErrorTraceTest, seq) { - } - - - TEST_F(ErrorTraceTest, deepSeq) { - } - - - TEST_F(ErrorTraceTest, trace) { - } - - - TEST_F(ErrorTraceTest, placeholder) { - ASSERT_TRACE2("placeholder []", - TypeError, - hintfmt("value is %s while a string was expected", "a list"), - hintfmt("while evaluating the first argument passed to builtins.placeholder")); - - } - - - TEST_F(ErrorTraceTest, toPath) { - ASSERT_TRACE2("toPath []", - TypeError, - hintfmt("cannot coerce %s to a string", "a list"), - hintfmt("while evaluating the first argument passed to builtins.toPath")); - - ASSERT_TRACE2("toPath \"foo\"", - EvalError, - hintfmt("string '%s' doesn't represent an absolute path", "foo"), - hintfmt("while evaluating the first argument passed to builtins.toPath")); - - } - - - TEST_F(ErrorTraceTest, storePath) { - ASSERT_TRACE2("storePath true", - TypeError, - hintfmt("cannot coerce %s to a string", "a Boolean"), - hintfmt("while evaluating the first argument passed to builtins.storePath")); - - } - - - TEST_F(ErrorTraceTest, pathExists) { - ASSERT_TRACE2("pathExists []", - TypeError, - hintfmt("cannot coerce %s to a string", "a list"), - hintfmt("while realising the context of a path")); - - ASSERT_TRACE2("pathExists \"zorglub\"", - EvalError, - hintfmt("string '%s' doesn't represent an absolute path", "zorglub"), - hintfmt("while realising the context of a path")); - - } - - - TEST_F(ErrorTraceTest, baseNameOf) { - ASSERT_TRACE2("baseNameOf []", - TypeError, - hintfmt("cannot coerce %s to a string", "a list"), - hintfmt("while evaluating the first argument passed to builtins.baseNameOf")); - - } - - - TEST_F(ErrorTraceTest, dirOf) { - } - - - TEST_F(ErrorTraceTest, readFile) { - } - - - TEST_F(ErrorTraceTest, findFile) { - } - - - TEST_F(ErrorTraceTest, hashFile) { - } - - - TEST_F(ErrorTraceTest, readDir) { - } - - - TEST_F(ErrorTraceTest, toXML) { - } - - - TEST_F(ErrorTraceTest, toJSON) { - } - - - TEST_F(ErrorTraceTest, fromJSON) { - } - - - TEST_F(ErrorTraceTest, toFile) { - } - - - TEST_F(ErrorTraceTest, filterSource) { - ASSERT_TRACE2("filterSource [] []", - TypeError, - hintfmt("cannot coerce %s to a string", "a list"), - hintfmt("while evaluating the second argument (the path to filter) passed to builtins.filterSource")); - - ASSERT_TRACE2("filterSource [] \"foo\"", - EvalError, - hintfmt("string '%s' doesn't represent an absolute path", "foo"), - hintfmt("while evaluating the second argument (the path to filter) passed to builtins.filterSource")); - - ASSERT_TRACE2("filterSource [] ./.", - TypeError, - hintfmt("value is %s while a function was expected", "a list"), - hintfmt("while evaluating the first argument passed to builtins.filterSource")); - - // Usupported by store "dummy" - - // ASSERT_TRACE2("filterSource (_: 1) ./.", - // TypeError, - // hintfmt("attempt to call something which is not a function but %s", "an integer"), - // hintfmt("while adding path '/home/layus/projects/nix'")); - - // ASSERT_TRACE2("filterSource (_: _: 1) ./.", - // TypeError, - // hintfmt("value is %s while a Boolean was expected", "an integer"), - // hintfmt("while evaluating the return value of the path filter function")); - - } - - - TEST_F(ErrorTraceTest, path) { - } - - - TEST_F(ErrorTraceTest, attrNames) { - ASSERT_TRACE2("attrNames []", - TypeError, - hintfmt("value is %s while a set was expected", "a list"), - hintfmt("while evaluating the argument passed to builtins.attrNames")); - - } - - - TEST_F(ErrorTraceTest, attrValues) { - ASSERT_TRACE2("attrValues []", - TypeError, - hintfmt("value is %s while a set was expected", "a list"), - hintfmt("while evaluating the argument passed to builtins.attrValues")); - - } - - - TEST_F(ErrorTraceTest, getAttr) { - ASSERT_TRACE2("getAttr [] []", - TypeError, - hintfmt("value is %s while a string was expected", "a list"), - hintfmt("while evaluating the first argument passed to builtins.getAttr")); - - ASSERT_TRACE2("getAttr \"foo\" []", - TypeError, - hintfmt("value is %s while a set was expected", "a list"), - hintfmt("while evaluating the second argument passed to builtins.getAttr")); - - ASSERT_TRACE2("getAttr \"foo\" {}", - TypeError, - hintfmt("attribute '%s' missing", "foo"), - hintfmt("in the attribute set under consideration")); - - } - - - TEST_F(ErrorTraceTest, unsafeGetAttrPos) { - } - - - TEST_F(ErrorTraceTest, hasAttr) { - ASSERT_TRACE2("hasAttr [] []", - TypeError, - hintfmt("value is %s while a string was expected", "a list"), - hintfmt("while evaluating the first argument passed to builtins.hasAttr")); - - ASSERT_TRACE2("hasAttr \"foo\" []", - TypeError, - hintfmt("value is %s while a set was expected", "a list"), - hintfmt("while evaluating the second argument passed to builtins.hasAttr")); - - } - - - TEST_F(ErrorTraceTest, isAttrs) { - } - - - TEST_F(ErrorTraceTest, removeAttrs) { - ASSERT_TRACE2("removeAttrs \"\" \"\"", - TypeError, - hintfmt("value is %s while a set was expected", "a string"), - hintfmt("while evaluating the first argument passed to builtins.removeAttrs")); - - ASSERT_TRACE2("removeAttrs \"\" [ 1 ]", - TypeError, - hintfmt("value is %s while a set was expected", "a string"), - hintfmt("while evaluating the first argument passed to builtins.removeAttrs")); - - ASSERT_TRACE2("removeAttrs \"\" [ \"1\" ]", - TypeError, - hintfmt("value is %s while a set was expected", "a string"), - hintfmt("while evaluating the first argument passed to builtins.removeAttrs")); - - } - - - TEST_F(ErrorTraceTest, listToAttrs) { - ASSERT_TRACE2("listToAttrs 1", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating the argument passed to builtins.listToAttrs")); - - ASSERT_TRACE2("listToAttrs [ 1 ]", - TypeError, - hintfmt("value is %s while a set was expected", "an integer"), - hintfmt("while evaluating an element of the list passed to builtins.listToAttrs")); - - ASSERT_TRACE2("listToAttrs [ {} ]", - TypeError, - hintfmt("attribute '%s' missing", "name"), - hintfmt("in a {name=...; value=...;} pair")); - - ASSERT_TRACE2("listToAttrs [ { name = 1; } ]", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the `name` attribute of an element of the list passed to builtins.listToAttrs")); - - ASSERT_TRACE2("listToAttrs [ { name = \"foo\"; } ]", - TypeError, - hintfmt("attribute '%s' missing", "value"), - hintfmt("in a {name=...; value=...;} pair")); - - } - - - TEST_F(ErrorTraceTest, intersectAttrs) { - ASSERT_TRACE2("intersectAttrs [] []", - TypeError, - hintfmt("value is %s while a set was expected", "a list"), - hintfmt("while evaluating the first argument passed to builtins.intersectAttrs")); - - ASSERT_TRACE2("intersectAttrs {} []", - TypeError, - hintfmt("value is %s while a set was expected", "a list"), - hintfmt("while evaluating the second argument passed to builtins.intersectAttrs")); - - } - - - TEST_F(ErrorTraceTest, catAttrs) { - ASSERT_TRACE2("catAttrs [] {}", - TypeError, - hintfmt("value is %s while a string was expected", "a list"), - hintfmt("while evaluating the first argument passed to builtins.catAttrs")); - - ASSERT_TRACE2("catAttrs \"foo\" {}", - TypeError, - hintfmt("value is %s while a list was expected", "a set"), - hintfmt("while evaluating the second argument passed to builtins.catAttrs")); - - ASSERT_TRACE2("catAttrs \"foo\" [ 1 ]", - TypeError, - hintfmt("value is %s while a set was expected", "an integer"), - hintfmt("while evaluating an element in the list passed as second argument to builtins.catAttrs")); - - ASSERT_TRACE2("catAttrs \"foo\" [ { foo = 1; } 1 { bar = 5;} ]", - TypeError, - hintfmt("value is %s while a set was expected", "an integer"), - hintfmt("while evaluating an element in the list passed as second argument to builtins.catAttrs")); - - } - - - TEST_F(ErrorTraceTest, functionArgs) { - ASSERT_TRACE1("functionArgs {}", - TypeError, - hintfmt("'functionArgs' requires a function")); - - } - - - TEST_F(ErrorTraceTest, mapAttrs) { - ASSERT_TRACE2("mapAttrs [] []", - TypeError, - hintfmt("value is %s while a set was expected", "a list"), - hintfmt("while evaluating the second argument passed to builtins.mapAttrs")); - - // XXX: defered - // ASSERT_TRACE2("mapAttrs \"\" { foo.bar = 1; }", - // TypeError, - // hintfmt("attempt to call something which is not a function but %s", "a string"), - // hintfmt("while evaluating the attribute 'foo'")); - - // ASSERT_TRACE2("mapAttrs (x: x + \"1\") { foo.bar = 1; }", - // TypeError, - // hintfmt("attempt to call something which is not a function but %s", "a string"), - // hintfmt("while evaluating the attribute 'foo'")); - - // ASSERT_TRACE2("mapAttrs (x: y: x + 1) { foo.bar = 1; }", - // TypeError, - // hintfmt("cannot coerce %s to a string", "an integer"), - // hintfmt("while evaluating a path segment")); - - } - - - TEST_F(ErrorTraceTest, zipAttrsWith) { - ASSERT_TRACE2("zipAttrsWith [] [ 1 ]", - TypeError, - hintfmt("value is %s while a function was expected", "a list"), - hintfmt("while evaluating the first argument passed to builtins.zipAttrsWith")); - - ASSERT_TRACE2("zipAttrsWith (_: 1) [ 1 ]", - TypeError, - hintfmt("value is %s while a set was expected", "an integer"), - hintfmt("while evaluating a value of the list passed as second argument to builtins.zipAttrsWith")); - - // XXX: How to properly tell that the fucntion takes two arguments ? - // The same question also applies to sort, and maybe others. - // Due to lazyness, we only create a thunk, and it fails later on. - // ASSERT_TRACE2("zipAttrsWith (_: 1) [ { foo = 1; } ]", - // TypeError, - // hintfmt("attempt to call something which is not a function but %s", "an integer"), - // hintfmt("while evaluating the attribute 'foo'")); - - // XXX: Also deferred deeply - // ASSERT_TRACE2("zipAttrsWith (a: b: a + b) [ { foo = 1; } { foo = 2; } ]", - // TypeError, - // hintfmt("cannot coerce %s to a string", "a list"), - // hintfmt("while evaluating a path segment")); - - } - - - TEST_F(ErrorTraceTest, isList) { - } - - - TEST_F(ErrorTraceTest, elemAt) { - ASSERT_TRACE2("elemAt \"foo\" (-1)", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the first argument passed to builtins.elemAt")); - - ASSERT_TRACE1("elemAt [] (-1)", - Error, - hintfmt("list index %d is out of bounds", -1)); - - ASSERT_TRACE1("elemAt [\"foo\"] 3", - Error, - hintfmt("list index %d is out of bounds", 3)); - - } - - - TEST_F(ErrorTraceTest, head) { - ASSERT_TRACE2("head 1", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.elemAt")); - - ASSERT_TRACE1("head []", - Error, - hintfmt("list index %d is out of bounds", 0)); - - } - - - TEST_F(ErrorTraceTest, tail) { - ASSERT_TRACE2("tail 1", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.tail")); - - ASSERT_TRACE1("tail []", - Error, - hintfmt("'tail' called on an empty list")); - - } - - - TEST_F(ErrorTraceTest, map) { - ASSERT_TRACE2("map 1 \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.map")); - - ASSERT_TRACE2("map 1 [ 1 ]", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.map")); - - } - - - TEST_F(ErrorTraceTest, filter) { - ASSERT_TRACE2("filter 1 \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.filter")); - - ASSERT_TRACE2("filter 1 [ \"foo\" ]", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.filter")); - - ASSERT_TRACE2("filter (_: 5) [ \"foo\" ]", - TypeError, - hintfmt("value is %s while a Boolean was expected", "an integer"), - hintfmt("while evaluating the return value of the filtering function passed to builtins.filter")); - - } - - - TEST_F(ErrorTraceTest, elem) { - ASSERT_TRACE2("elem 1 \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.elem")); - - } - - - TEST_F(ErrorTraceTest, concatLists) { - ASSERT_TRACE2("concatLists 1", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.concatLists")); - - ASSERT_TRACE2("concatLists [ 1 ]", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating a value of the list passed to builtins.concatLists")); - - ASSERT_TRACE2("concatLists [ [1] \"foo\" ]", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating a value of the list passed to builtins.concatLists")); - - } - - - TEST_F(ErrorTraceTest, length) { - ASSERT_TRACE2("length 1", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.length")); - - ASSERT_TRACE2("length \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the first argument passed to builtins.length")); - - } - - - TEST_F(ErrorTraceTest, foldlPrime) { - ASSERT_TRACE2("foldl' 1 \"foo\" true", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.foldlStrict")); - - ASSERT_TRACE2("foldl' (_: 1) \"foo\" true", - TypeError, - hintfmt("value is %s while a list was expected", "a Boolean"), - hintfmt("while evaluating the third argument passed to builtins.foldlStrict")); - - ASSERT_TRACE1("foldl' (_: 1) \"foo\" [ true ]", - TypeError, - hintfmt("attempt to call something which is not a function but %s", "an integer")); - - ASSERT_TRACE2("foldl' (a: b: a && b) \"foo\" [ true ]", - TypeError, - hintfmt("value is %s while a Boolean was expected", "a string"), - hintfmt("in the left operand of the AND (&&) operator")); - - } - - - TEST_F(ErrorTraceTest, any) { - ASSERT_TRACE2("any 1 \"foo\"", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.any")); - - ASSERT_TRACE2("any (_: 1) \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.any")); - - ASSERT_TRACE2("any (_: 1) [ \"foo\" ]", - TypeError, - hintfmt("value is %s while a Boolean was expected", "an integer"), - hintfmt("while evaluating the return value of the function passed to builtins.any")); - - } - - - TEST_F(ErrorTraceTest, all) { - ASSERT_TRACE2("all 1 \"foo\"", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.all")); - - ASSERT_TRACE2("all (_: 1) \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.all")); - - ASSERT_TRACE2("all (_: 1) [ \"foo\" ]", - TypeError, - hintfmt("value is %s while a Boolean was expected", "an integer"), - hintfmt("while evaluating the return value of the function passed to builtins.all")); - - } - - - TEST_F(ErrorTraceTest, genList) { - ASSERT_TRACE2("genList 1 \"foo\"", - TypeError, - hintfmt("value is %s while an integer was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.genList")); - - ASSERT_TRACE2("genList 1 2", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.genList", "an integer")); - - // XXX: defered - // ASSERT_TRACE2("genList (x: x + \"foo\") 2 #TODO", - // TypeError, - // hintfmt("cannot add %s to an integer", "a string"), - // hintfmt("while evaluating anonymous lambda")); - - ASSERT_TRACE1("genList false (-3)", - EvalError, - hintfmt("cannot create list of size %d", -3)); - - } - - - TEST_F(ErrorTraceTest, sort) { - ASSERT_TRACE2("sort 1 \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.sort")); - - ASSERT_TRACE2("sort 1 [ \"foo\" ]", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.sort")); - - ASSERT_TRACE1("sort (_: 1) [ \"foo\" \"bar\" ]", - TypeError, - hintfmt("attempt to call something which is not a function but %s", "an integer")); - - ASSERT_TRACE2("sort (_: _: 1) [ \"foo\" \"bar\" ]", - TypeError, - hintfmt("value is %s while a Boolean was expected", "an integer"), - hintfmt("while evaluating the return value of the sorting function passed to builtins.sort")); - - // XXX: Trace too deep, need better asserts - // ASSERT_TRACE1("sort (a: b: a <= b) [ \"foo\" {} ] # TODO", - // TypeError, - // hintfmt("cannot compare %s with %s", "a string", "a set")); - - // ASSERT_TRACE1("sort (a: b: a <= b) [ {} {} ] # TODO", - // TypeError, - // hintfmt("cannot compare %s with %s; values of that type are incomparable", "a set", "a set")); - - } - - - TEST_F(ErrorTraceTest, partition) { - ASSERT_TRACE2("partition 1 \"foo\"", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.partition")); - - ASSERT_TRACE2("partition (_: 1) \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.partition")); - - ASSERT_TRACE2("partition (_: 1) [ \"foo\" ]", - TypeError, - hintfmt("value is %s while a Boolean was expected", "an integer"), - hintfmt("while evaluating the return value of the partition function passed to builtins.partition")); - - } - - - TEST_F(ErrorTraceTest, groupBy) { - ASSERT_TRACE2("groupBy 1 \"foo\"", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.groupBy")); - - ASSERT_TRACE2("groupBy (_: 1) \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.groupBy")); - - ASSERT_TRACE2("groupBy (x: x) [ \"foo\" \"bar\" 1 ]", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the return value of the grouping function passed to builtins.groupBy")); - - } - - - TEST_F(ErrorTraceTest, concatMap) { - ASSERT_TRACE2("concatMap 1 \"foo\"", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.concatMap")); - - ASSERT_TRACE2("concatMap (x: 1) \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.concatMap")); - - ASSERT_TRACE2("concatMap (x: 1) [ \"foo\" ] # TODO", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating the return value of the function passed to buitlins.concatMap")); - - ASSERT_TRACE2("concatMap (x: \"foo\") [ 1 2 ] # TODO", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the return value of the function passed to buitlins.concatMap")); - - } - - - TEST_F(ErrorTraceTest, add) { - ASSERT_TRACE2("add \"foo\" 1", - TypeError, - hintfmt("value is %s while an integer was expected", "a string"), - hintfmt("while evaluating the first argument of the addition")); - - ASSERT_TRACE2("add 1 \"foo\"", - TypeError, - hintfmt("value is %s while an integer was expected", "a string"), - hintfmt("while evaluating the second argument of the addition")); - - } - - - TEST_F(ErrorTraceTest, sub) { - ASSERT_TRACE2("sub \"foo\" 1", - TypeError, - hintfmt("value is %s while an integer was expected", "a string"), - hintfmt("while evaluating the first argument of the subtraction")); - - ASSERT_TRACE2("sub 1 \"foo\"", - TypeError, - hintfmt("value is %s while an integer was expected", "a string"), - hintfmt("while evaluating the second argument of the subtraction")); - - } - - - TEST_F(ErrorTraceTest, mul) { - ASSERT_TRACE2("mul \"foo\" 1", - TypeError, - hintfmt("value is %s while an integer was expected", "a string"), - hintfmt("while evaluating the first argument of the multiplication")); - - ASSERT_TRACE2("mul 1 \"foo\"", - TypeError, - hintfmt("value is %s while an integer was expected", "a string"), - hintfmt("while evaluating the second argument of the multiplication")); - - } - - - TEST_F(ErrorTraceTest, div) { - ASSERT_TRACE2("div \"foo\" 1 # TODO: an integer was expected -> a number", - TypeError, - hintfmt("value is %s while an integer was expected", "a string"), - hintfmt("while evaluating the first operand of the division")); - - ASSERT_TRACE2("div 1 \"foo\"", - TypeError, - hintfmt("value is %s while a float was expected", "a string"), - hintfmt("while evaluating the second operand of the division")); - - ASSERT_TRACE1("div \"foo\" 0", - EvalError, - hintfmt("division by zero")); - - } - - - TEST_F(ErrorTraceTest, bitAnd) { - ASSERT_TRACE2("bitAnd 1.1 2", - TypeError, - hintfmt("value is %s while an integer was expected", "a float"), - hintfmt("while evaluating the first argument passed to builtins.bitAnd")); - - ASSERT_TRACE2("bitAnd 1 2.2", - TypeError, - hintfmt("value is %s while an integer was expected", "a float"), - hintfmt("while evaluating the second argument passed to builtins.bitAnd")); - - } - - - TEST_F(ErrorTraceTest, bitOr) { - ASSERT_TRACE2("bitOr 1.1 2", - TypeError, - hintfmt("value is %s while an integer was expected", "a float"), - hintfmt("while evaluating the first argument passed to builtins.bitOr")); - - ASSERT_TRACE2("bitOr 1 2.2", - TypeError, - hintfmt("value is %s while an integer was expected", "a float"), - hintfmt("while evaluating the second argument passed to builtins.bitOr")); - - } - - - TEST_F(ErrorTraceTest, bitXor) { - ASSERT_TRACE2("bitXor 1.1 2", - TypeError, - hintfmt("value is %s while an integer was expected", "a float"), - hintfmt("while evaluating the first argument passed to builtins.bitXor")); - - ASSERT_TRACE2("bitXor 1 2.2", - TypeError, - hintfmt("value is %s while an integer was expected", "a float"), - hintfmt("while evaluating the second argument passed to builtins.bitXor")); - - } - - - TEST_F(ErrorTraceTest, lessThan) { - ASSERT_TRACE1("lessThan 1 \"foo\"", - EvalError, - hintfmt("cannot compare %s with %s", "an integer", "a string")); - - ASSERT_TRACE1("lessThan {} {}", - EvalError, - hintfmt("cannot compare %s with %s; values of that type are incomparable", "a set", "a set")); - - ASSERT_TRACE2("lessThan [ 1 2 ] [ \"foo\" ]", - EvalError, - hintfmt("cannot compare %s with %s", "an integer", "a string"), - hintfmt("while comparing two list elements")); - - } - - - TEST_F(ErrorTraceTest, toString) { - ASSERT_TRACE2("toString { a = 1; }", - TypeError, - hintfmt("cannot coerce %s to a string", "a set"), - hintfmt("while evaluating the first argument passed to builtins.toString")); - - } - - - TEST_F(ErrorTraceTest, substring) { - ASSERT_TRACE2("substring {} \"foo\" true", - TypeError, - hintfmt("value is %s while an integer was expected", "a set"), - hintfmt("while evaluating the first argument (the start offset) passed to builtins.substring")); - - ASSERT_TRACE2("substring 3 \"foo\" true", - TypeError, - hintfmt("value is %s while an integer was expected", "a string"), - hintfmt("while evaluating the second argument (the substring length) passed to builtins.substring")); - - ASSERT_TRACE2("substring 0 3 {}", - TypeError, - hintfmt("cannot coerce %s to a string", "a set"), - hintfmt("while evaluating the third argument (the string) passed to builtins.substring")); - - ASSERT_TRACE1("substring (-3) 3 \"sometext\"", - EvalError, - hintfmt("negative start position in 'substring'")); - - } - - - TEST_F(ErrorTraceTest, stringLength) { - ASSERT_TRACE2("stringLength {} # TODO: context is missing ???", - TypeError, - hintfmt("cannot coerce %s to a string", "a set"), - hintfmt("while evaluating the argument passed to builtins.stringLength")); - - } - - - TEST_F(ErrorTraceTest, hashString) { - ASSERT_TRACE2("hashString 1 {}", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.hashString")); - - ASSERT_TRACE1("hashString \"foo\" \"content\"", - UsageError, - hintfmt("unknown hash algorithm '%s'", "foo")); - - ASSERT_TRACE2("hashString \"sha256\" {}", - TypeError, - hintfmt("value is %s while a string was expected", "a set"), - hintfmt("while evaluating the second argument passed to builtins.hashString")); - - } - - - TEST_F(ErrorTraceTest, match) { - ASSERT_TRACE2("match 1 {}", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.match")); - - ASSERT_TRACE2("match \"foo\" {}", - TypeError, - hintfmt("value is %s while a string was expected", "a set"), - hintfmt("while evaluating the second argument passed to builtins.match")); - - ASSERT_TRACE1("match \"(.*\" \"\"", - EvalError, - hintfmt("invalid regular expression '%s'", "(.*")); - - } - - - TEST_F(ErrorTraceTest, split) { - ASSERT_TRACE2("split 1 {}", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.split")); - - ASSERT_TRACE2("split \"foo\" {}", - TypeError, - hintfmt("value is %s while a string was expected", "a set"), - hintfmt("while evaluating the second argument passed to builtins.split")); - - ASSERT_TRACE1("split \"f(o*o\" \"1foo2\"", - EvalError, - hintfmt("invalid regular expression '%s'", "f(o*o")); - - } - - - TEST_F(ErrorTraceTest, concatStringsSep) { - ASSERT_TRACE2("concatStringsSep 1 {}", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the first argument (the separator string) passed to builtins.concatStringsSep")); - - ASSERT_TRACE2("concatStringsSep \"foo\" {}", - TypeError, - hintfmt("value is %s while a list was expected", "a set"), - hintfmt("while evaluating the second argument (the list of strings to concat) passed to builtins.concatStringsSep")); - - ASSERT_TRACE2("concatStringsSep \"foo\" [ 1 2 {} ] # TODO: coerce to string is buggy", - TypeError, - hintfmt("cannot coerce %s to a string", "an integer"), - hintfmt("while evaluating one element of the list of strings to concat passed to builtins.concatStringsSep")); - - } - - - TEST_F(ErrorTraceTest, parseDrvName) { - ASSERT_TRACE2("parseDrvName 1", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.parseDrvName")); - - } - - - TEST_F(ErrorTraceTest, compareVersions) { - ASSERT_TRACE2("compareVersions 1 {}", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.compareVersions")); - - ASSERT_TRACE2("compareVersions \"abd\" {}", - TypeError, - hintfmt("value is %s while a string was expected", "a set"), - hintfmt("while evaluating the second argument passed to builtins.compareVersions")); - - } - - - TEST_F(ErrorTraceTest, splitVersion) { - ASSERT_TRACE2("splitVersion 1", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.splitVersion")); - - } - - - TEST_F(ErrorTraceTest, traceVerbose) { - } - - - /* // Needs different ASSERTs - TEST_F(ErrorTraceTest, derivationStrict) { - ASSERT_TRACE2("derivationStrict \"\"", - TypeError, - hintfmt("value is %s while a set was expected", "a string"), - hintfmt("while evaluating the argument passed to builtins.derivationStrict")); - - ASSERT_TRACE2("derivationStrict {}", - TypeError, - hintfmt("attribute '%s' missing", "name"), - hintfmt("in the attrset passed as argument to builtins.derivationStrict")); - - ASSERT_TRACE2("derivationStrict { name = 1; }", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the `name` attribute passed to builtins.derivationStrict")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; }", - TypeError, - hintfmt("required attribute 'builder' missing"), - hintfmt("while evaluating derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; __structuredAttrs = 15; }", - TypeError, - hintfmt("value is %s while a Boolean was expected", "an integer"), - hintfmt("while evaluating the `__structuredAttrs` attribute passed to builtins.derivationStrict")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; __ignoreNulls = 15; }", - TypeError, - hintfmt("value is %s while a Boolean was expected", "an integer"), - hintfmt("while evaluating the `__ignoreNulls` attribute passed to builtins.derivationStrict")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; outputHashMode = 15; }", - TypeError, - hintfmt("invalid value '15' for 'outputHashMode' attribute"), - hintfmt("while evaluating the attribute 'outputHashMode' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; outputHashMode = \"custom\"; }", - TypeError, - hintfmt("invalid value 'custom' for 'outputHashMode' attribute"), - hintfmt("while evaluating the attribute 'outputHashMode' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = {}; }", - TypeError, - hintfmt("cannot coerce %s to a string", "a set"), - hintfmt("while evaluating the attribute 'system' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = {}; }", - TypeError, - hintfmt("cannot coerce %s to a string", "a set"), - hintfmt("while evaluating the attribute 'outputs' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"drv\"; }", - TypeError, - hintfmt("invalid derivation output name 'drv'"), - hintfmt("while evaluating the attribute 'outputs' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = []; }", - TypeError, - hintfmt("derivation cannot have an empty set of outputs"), - hintfmt("while evaluating the attribute 'outputs' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = [ \"drv\" ]; }", - TypeError, - hintfmt("invalid derivation output name 'drv'"), - hintfmt("while evaluating the attribute 'outputs' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = [ \"out\" \"out\" ]; }", - TypeError, - hintfmt("duplicate derivation output 'out'"), - hintfmt("while evaluating the attribute 'outputs' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; __contentAddressed = \"true\"; }", - TypeError, - hintfmt("value is %s while a Boolean was expected", "a string"), - hintfmt("while evaluating the attribute '__contentAddressed' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; __impure = \"true\"; }", - TypeError, - hintfmt("value is %s while a Boolean was expected", "a string"), - hintfmt("while evaluating the attribute '__impure' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; __impure = \"true\"; }", - TypeError, - hintfmt("value is %s while a Boolean was expected", "a string"), - hintfmt("while evaluating the attribute '__impure' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; args = \"foo\"; }", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the attribute 'args' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; args = [ {} ]; }", - TypeError, - hintfmt("cannot coerce %s to a string", "a set"), - hintfmt("while evaluating an element of the argument list")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; args = [ \"a\" {} ]; }", - TypeError, - hintfmt("cannot coerce %s to a string", "a set"), - hintfmt("while evaluating an element of the argument list")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; FOO = {}; }", - TypeError, - hintfmt("cannot coerce %s to a string", "a set"), - hintfmt("while evaluating the attribute 'FOO' of derivation 'foo'")); - - } - */ - -} /* namespace nix */ diff --git a/src/libexpr/tests/flakeref.cc b/src/libexpr/tests/flakeref.cc deleted file mode 100644 index 2b7809b93..000000000 --- a/src/libexpr/tests/flakeref.cc +++ /dev/null @@ -1,22 +0,0 @@ -#include - -#include "flake/flakeref.hh" - -namespace nix { - -/* ----------- tests for flake/flakeref.hh --------------------------------------------------*/ - - /* ---------------------------------------------------------------------------- - * to_string - * --------------------------------------------------------------------------*/ - - TEST(to_string, doesntReencodeUrl) { - auto s = "http://localhost:8181/test/+3d.tar.gz"; - auto flakeref = parseFlakeRef(s); - auto parsed = flakeref.to_string(); - auto expected = "http://localhost:8181/test/%2B3d.tar.gz"; - - ASSERT_EQ(parsed, expected); - } - -} diff --git a/src/libexpr/tests/json.cc b/src/libexpr/tests/json.cc deleted file mode 100644 index 7586bdd9b..000000000 --- a/src/libexpr/tests/json.cc +++ /dev/null @@ -1,68 +0,0 @@ -#include "tests/libexpr.hh" -#include "value-to-json.hh" - -namespace nix { -// Testing the conversion to JSON - - class JSONValueTest : public LibExprTest { - protected: - std::string getJSONValue(Value& value) { - std::stringstream ss; - NixStringContext ps; - printValueAsJSON(state, true, value, noPos, ss, ps); - return ss.str(); - } - }; - - TEST_F(JSONValueTest, null) { - Value v; - v.mkNull(); - ASSERT_EQ(getJSONValue(v), "null"); - } - - TEST_F(JSONValueTest, BoolFalse) { - Value v; - v.mkBool(false); - ASSERT_EQ(getJSONValue(v),"false"); - } - - TEST_F(JSONValueTest, BoolTrue) { - Value v; - v.mkBool(true); - ASSERT_EQ(getJSONValue(v), "true"); - } - - TEST_F(JSONValueTest, IntPositive) { - Value v; - v.mkInt(100); - ASSERT_EQ(getJSONValue(v), "100"); - } - - TEST_F(JSONValueTest, IntNegative) { - Value v; - v.mkInt(-100); - ASSERT_EQ(getJSONValue(v), "-100"); - } - - TEST_F(JSONValueTest, String) { - Value v; - v.mkString("test"); - ASSERT_EQ(getJSONValue(v), "\"test\""); - } - - TEST_F(JSONValueTest, StringQuotes) { - Value v; - - v.mkString("test\""); - ASSERT_EQ(getJSONValue(v), "\"test\\\"\""); - } - - // The dummy store doesn't support writing files. Fails with this exception message: - // C++ exception with description "error: operation 'addToStoreFromDump' is - // not supported by store 'dummy'" thrown in the test body. - TEST_F(JSONValueTest, DISABLED_Path) { - Value v; - v.mkPath("test"); - ASSERT_EQ(getJSONValue(v), "\"/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x\""); - } -} /* namespace nix */ diff --git a/src/libexpr/tests/libexpr.hh b/src/libexpr/tests/libexpr.hh deleted file mode 100644 index b8e65aafe..000000000 --- a/src/libexpr/tests/libexpr.hh +++ /dev/null @@ -1,140 +0,0 @@ -#pragma once -///@file - -#include -#include - -#include "value.hh" -#include "nixexpr.hh" -#include "eval.hh" -#include "eval-inline.hh" -#include "store-api.hh" - -#include "tests/libstore.hh" - -namespace nix { - class LibExprTest : public LibStoreTest { - public: - static void SetUpTestSuite() { - LibStoreTest::SetUpTestSuite(); - initGC(); - } - - protected: - LibExprTest() - : LibStoreTest() - , state({}, store) - { - } - Value eval(std::string input, bool forceValue = true) { - Value v; - Expr * e = state.parseExprFromString(input, state.rootPath(CanonPath::root)); - assert(e); - state.eval(e, v); - if (forceValue) - state.forceValue(v, noPos); - return v; - } - - Symbol createSymbol(const char * value) { - return state.symbols.create(value); - } - - EvalState state; - }; - - MATCHER(IsListType, "") { - return arg != nList; - } - - MATCHER(IsList, "") { - return arg.type() == nList; - } - - MATCHER(IsString, "") { - return arg.type() == nString; - } - - MATCHER(IsNull, "") { - return arg.type() == nNull; - } - - MATCHER(IsThunk, "") { - return arg.type() == nThunk; - } - - MATCHER(IsAttrs, "") { - return arg.type() == nAttrs; - } - - MATCHER_P(IsStringEq, s, fmt("The string is equal to \"%1%\"", s)) { - if (arg.type() != nString) { - return false; - } - return std::string_view(arg.string.s) == s; - } - - MATCHER_P(IsIntEq, v, fmt("The string is equal to \"%1%\"", v)) { - if (arg.type() != nInt) { - return false; - } - return arg.integer == v; - } - - MATCHER_P(IsFloatEq, v, fmt("The float is equal to \"%1%\"", v)) { - if (arg.type() != nFloat) { - return false; - } - return arg.fpoint == v; - } - - MATCHER(IsTrue, "") { - if (arg.type() != nBool) { - return false; - } - return arg.boolean == true; - } - - MATCHER(IsFalse, "") { - if (arg.type() != nBool) { - return false; - } - return arg.boolean == false; - } - - MATCHER_P(IsPathEq, p, fmt("Is a path equal to \"%1%\"", p)) { - if (arg.type() != nPath) { - *result_listener << "Expected a path got " << arg.type(); - return false; - } else if (std::string_view(arg.string.s) != p) { - *result_listener << "Expected a path that equals \"" << p << "\" but got: " << arg.string.s; - return false; - } - return true; - } - - - MATCHER_P(IsListOfSize, n, fmt("Is a list of size [%1%]", n)) { - if (arg.type() != nList) { - *result_listener << "Expected list got " << arg.type(); - return false; - } else if (arg.listSize() != (size_t)n) { - *result_listener << "Expected as list of size " << n << " got " << arg.listSize(); - return false; - } - return true; - } - - MATCHER_P(IsAttrsOfSize, n, fmt("Is a set of size [%1%]", n)) { - if (arg.type() != nAttrs) { - *result_listener << "Expected set got " << arg.type(); - return false; - } else if (arg.attrs->size() != (size_t)n) { - *result_listener << "Expected a set with " << n << " attributes but got " << arg.attrs->size(); - return false; - } - return true; - } - - -} /* namespace nix */ diff --git a/src/libexpr/tests/local.mk b/src/libexpr/tests/local.mk deleted file mode 100644 index c56848a14..000000000 --- a/src/libexpr/tests/local.mk +++ /dev/null @@ -1,19 +0,0 @@ -check: libexpr-tests_RUN - -programs += libexpr-tests - -libexpr-tests_NAME := libnixexpr-tests - -libexpr-tests_DIR := $(d) - -libexpr-tests_INSTALL_DIR := - -libexpr-tests_SOURCES := \ - $(wildcard $(d)/*.cc) \ - $(wildcard $(d)/value/*.cc) - -libexpr-tests_CXXFLAGS += -I src/libexpr -I src/libutil -I src/libstore -I src/libexpr/tests -I src/libfetchers - -libexpr-tests_LIBS = libstore-tests libutils-tests libexpr libutil libstore libfetchers - -libexpr-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock diff --git a/src/libexpr/tests/primops.cc b/src/libexpr/tests/primops.cc deleted file mode 100644 index ce3b5d11f..000000000 --- a/src/libexpr/tests/primops.cc +++ /dev/null @@ -1,832 +0,0 @@ -#include -#include - -#include "tests/libexpr.hh" - -namespace nix { - class CaptureLogger : public Logger - { - std::ostringstream oss; - - public: - CaptureLogger() {} - - std::string get() const { - return oss.str(); - } - - void log(Verbosity lvl, std::string_view s) override { - oss << s << std::endl; - } - - void logEI(const ErrorInfo & ei) override { - showErrorInfo(oss, ei, loggerSettings.showTrace.get()); - } - }; - - class CaptureLogging { - Logger * oldLogger; - std::unique_ptr tempLogger; - public: - CaptureLogging() : tempLogger(std::make_unique()) { - oldLogger = logger; - logger = tempLogger.get(); - } - - ~CaptureLogging() { - logger = oldLogger; - } - - std::string get() const { - return tempLogger->get(); - } - }; - - - // Testing eval of PrimOp's - class PrimOpTest : public LibExprTest {}; - - - TEST_F(PrimOpTest, throw) { - ASSERT_THROW(eval("throw \"foo\""), ThrownError); - } - - TEST_F(PrimOpTest, abort) { - ASSERT_THROW(eval("abort \"abort\""), Abort); - } - - TEST_F(PrimOpTest, ceil) { - auto v = eval("builtins.ceil 1.9"); - ASSERT_THAT(v, IsIntEq(2)); - } - - TEST_F(PrimOpTest, floor) { - auto v = eval("builtins.floor 1.9"); - ASSERT_THAT(v, IsIntEq(1)); - } - - TEST_F(PrimOpTest, tryEvalFailure) { - auto v = eval("builtins.tryEval (throw \"\")"); - ASSERT_THAT(v, IsAttrsOfSize(2)); - auto s = createSymbol("success"); - auto p = v.attrs->get(s); - ASSERT_NE(p, nullptr); - ASSERT_THAT(*p->value, IsFalse()); - } - - TEST_F(PrimOpTest, tryEvalSuccess) { - auto v = eval("builtins.tryEval 123"); - ASSERT_THAT(v, IsAttrs()); - auto s = createSymbol("success"); - auto p = v.attrs->get(s); - ASSERT_NE(p, nullptr); - ASSERT_THAT(*p->value, IsTrue()); - s = createSymbol("value"); - p = v.attrs->get(s); - ASSERT_NE(p, nullptr); - ASSERT_THAT(*p->value, IsIntEq(123)); - } - - TEST_F(PrimOpTest, getEnv) { - setenv("_NIX_UNIT_TEST_ENV_VALUE", "test value", 1); - auto v = eval("builtins.getEnv \"_NIX_UNIT_TEST_ENV_VALUE\""); - ASSERT_THAT(v, IsStringEq("test value")); - } - - TEST_F(PrimOpTest, seq) { - ASSERT_THROW(eval("let x = throw \"test\"; in builtins.seq x { }"), ThrownError); - } - - TEST_F(PrimOpTest, seqNotDeep) { - auto v = eval("let x = { z = throw \"test\"; }; in builtins.seq x { }"); - ASSERT_THAT(v, IsAttrs()); - } - - TEST_F(PrimOpTest, deepSeq) { - ASSERT_THROW(eval("let x = { z = throw \"test\"; }; in builtins.deepSeq x { }"), ThrownError); - } - - TEST_F(PrimOpTest, trace) { - CaptureLogging l; - auto v = eval("builtins.trace \"test string 123\" 123"); - ASSERT_THAT(v, IsIntEq(123)); - auto text = l.get(); - ASSERT_NE(text.find("test string 123"), std::string::npos); - } - - TEST_F(PrimOpTest, placeholder) { - auto v = eval("builtins.placeholder \"out\""); - ASSERT_THAT(v, IsStringEq("/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9")); - } - - TEST_F(PrimOpTest, baseNameOf) { - auto v = eval("builtins.baseNameOf /some/path"); - ASSERT_THAT(v, IsStringEq("path")); - } - - TEST_F(PrimOpTest, dirOf) { - auto v = eval("builtins.dirOf /some/path"); - ASSERT_THAT(v, IsPathEq("/some")); - } - - TEST_F(PrimOpTest, attrValues) { - auto v = eval("builtins.attrValues { x = \"foo\"; a = 1; }"); - ASSERT_THAT(v, IsListOfSize(2)); - ASSERT_THAT(*v.listElems()[0], IsIntEq(1)); - ASSERT_THAT(*v.listElems()[1], IsStringEq("foo")); - } - - TEST_F(PrimOpTest, getAttr) { - auto v = eval("builtins.getAttr \"x\" { x = \"foo\"; }"); - ASSERT_THAT(v, IsStringEq("foo")); - } - - TEST_F(PrimOpTest, getAttrNotFound) { - // FIXME: TypeError is really bad here, also the error wording is worse - // than on Nix <=2.3 - ASSERT_THROW(eval("builtins.getAttr \"y\" { }"), TypeError); - } - - TEST_F(PrimOpTest, unsafeGetAttrPos) { - // The `y` attribute is at position - const char* expr = "builtins.unsafeGetAttrPos \"y\" { y = \"x\"; }"; - auto v = eval(expr); - ASSERT_THAT(v, IsNull()); - } - - TEST_F(PrimOpTest, hasAttr) { - auto v = eval("builtins.hasAttr \"x\" { x = 1; }"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(PrimOpTest, hasAttrNotFound) { - auto v = eval("builtins.hasAttr \"x\" { }"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(PrimOpTest, isAttrs) { - auto v = eval("builtins.isAttrs {}"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(PrimOpTest, isAttrsFalse) { - auto v = eval("builtins.isAttrs null"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(PrimOpTest, removeAttrs) { - auto v = eval("builtins.removeAttrs { x = 1; } [\"x\"]"); - ASSERT_THAT(v, IsAttrsOfSize(0)); - } - - TEST_F(PrimOpTest, removeAttrsRetains) { - auto v = eval("builtins.removeAttrs { x = 1; y = 2; } [\"x\"]"); - ASSERT_THAT(v, IsAttrsOfSize(1)); - ASSERT_NE(v.attrs->find(createSymbol("y")), nullptr); - } - - TEST_F(PrimOpTest, listToAttrsEmptyList) { - auto v = eval("builtins.listToAttrs []"); - ASSERT_THAT(v, IsAttrsOfSize(0)); - ASSERT_EQ(v.type(), nAttrs); - ASSERT_EQ(v.attrs->size(), 0); - } - - TEST_F(PrimOpTest, listToAttrsNotFieldName) { - ASSERT_THROW(eval("builtins.listToAttrs [{}]"), Error); - } - - TEST_F(PrimOpTest, listToAttrs) { - auto v = eval("builtins.listToAttrs [ { name = \"key\"; value = 123; } ]"); - ASSERT_THAT(v, IsAttrsOfSize(1)); - auto key = v.attrs->find(createSymbol("key")); - ASSERT_NE(key, nullptr); - ASSERT_THAT(*key->value, IsIntEq(123)); - } - - TEST_F(PrimOpTest, intersectAttrs) { - auto v = eval("builtins.intersectAttrs { a = 1; b = 2; } { b = 3; c = 4; }"); - ASSERT_THAT(v, IsAttrsOfSize(1)); - auto b = v.attrs->find(createSymbol("b")); - ASSERT_NE(b, nullptr); - ASSERT_THAT(*b->value, IsIntEq(3)); - } - - TEST_F(PrimOpTest, catAttrs) { - auto v = eval("builtins.catAttrs \"a\" [{a = 1;} {b = 0;} {a = 2;}]"); - ASSERT_THAT(v, IsListOfSize(2)); - ASSERT_THAT(*v.listElems()[0], IsIntEq(1)); - ASSERT_THAT(*v.listElems()[1], IsIntEq(2)); - } - - TEST_F(PrimOpTest, functionArgs) { - auto v = eval("builtins.functionArgs ({ x, y ? 123}: 1)"); - ASSERT_THAT(v, IsAttrsOfSize(2)); - - auto x = v.attrs->find(createSymbol("x")); - ASSERT_NE(x, nullptr); - ASSERT_THAT(*x->value, IsFalse()); - - auto y = v.attrs->find(createSymbol("y")); - ASSERT_NE(y, nullptr); - ASSERT_THAT(*y->value, IsTrue()); - } - - TEST_F(PrimOpTest, mapAttrs) { - auto v = eval("builtins.mapAttrs (name: value: value * 10) { a = 1; b = 2; }"); - ASSERT_THAT(v, IsAttrsOfSize(2)); - - auto a = v.attrs->find(createSymbol("a")); - ASSERT_NE(a, nullptr); - ASSERT_THAT(*a->value, IsThunk()); - state.forceValue(*a->value, noPos); - ASSERT_THAT(*a->value, IsIntEq(10)); - - auto b = v.attrs->find(createSymbol("b")); - ASSERT_NE(b, nullptr); - ASSERT_THAT(*b->value, IsThunk()); - state.forceValue(*b->value, noPos); - ASSERT_THAT(*b->value, IsIntEq(20)); - } - - TEST_F(PrimOpTest, isList) { - auto v = eval("builtins.isList []"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(PrimOpTest, isListFalse) { - auto v = eval("builtins.isList null"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(PrimOpTest, elemtAt) { - auto v = eval("builtins.elemAt [0 1 2 3] 3"); - ASSERT_THAT(v, IsIntEq(3)); - } - - TEST_F(PrimOpTest, elemtAtOutOfBounds) { - ASSERT_THROW(eval("builtins.elemAt [0 1 2 3] 5"), Error); - } - - TEST_F(PrimOpTest, head) { - auto v = eval("builtins.head [ 3 2 1 0 ]"); - ASSERT_THAT(v, IsIntEq(3)); - } - - TEST_F(PrimOpTest, headEmpty) { - ASSERT_THROW(eval("builtins.head [ ]"), Error); - } - - TEST_F(PrimOpTest, headWrongType) { - ASSERT_THROW(eval("builtins.head { }"), Error); - } - - TEST_F(PrimOpTest, tail) { - auto v = eval("builtins.tail [ 3 2 1 0 ]"); - ASSERT_THAT(v, IsListOfSize(3)); - for (const auto [n, elem] : enumerate(v.listItems())) - ASSERT_THAT(*elem, IsIntEq(2 - static_cast(n))); - } - - TEST_F(PrimOpTest, tailEmpty) { - ASSERT_THROW(eval("builtins.tail []"), Error); - } - - TEST_F(PrimOpTest, map) { - auto v = eval("map (x: \"foo\" + x) [ \"bar\" \"bla\" \"abc\" ]"); - ASSERT_THAT(v, IsListOfSize(3)); - auto elem = v.listElems()[0]; - ASSERT_THAT(*elem, IsThunk()); - state.forceValue(*elem, noPos); - ASSERT_THAT(*elem, IsStringEq("foobar")); - - elem = v.listElems()[1]; - ASSERT_THAT(*elem, IsThunk()); - state.forceValue(*elem, noPos); - ASSERT_THAT(*elem, IsStringEq("foobla")); - - elem = v.listElems()[2]; - ASSERT_THAT(*elem, IsThunk()); - state.forceValue(*elem, noPos); - ASSERT_THAT(*elem, IsStringEq("fooabc")); - } - - TEST_F(PrimOpTest, filter) { - auto v = eval("builtins.filter (x: x == 2) [ 3 2 3 2 3 2 ]"); - ASSERT_THAT(v, IsListOfSize(3)); - for (const auto elem : v.listItems()) - ASSERT_THAT(*elem, IsIntEq(2)); - } - - TEST_F(PrimOpTest, elemTrue) { - auto v = eval("builtins.elem 3 [ 1 2 3 4 5 ]"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(PrimOpTest, elemFalse) { - auto v = eval("builtins.elem 6 [ 1 2 3 4 5 ]"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(PrimOpTest, concatLists) { - auto v = eval("builtins.concatLists [[1 2] [3 4]]"); - ASSERT_THAT(v, IsListOfSize(4)); - for (const auto [i, elem] : enumerate(v.listItems())) - ASSERT_THAT(*elem, IsIntEq(static_cast(i)+1)); - } - - TEST_F(PrimOpTest, length) { - auto v = eval("builtins.length [ 1 2 3 ]"); - ASSERT_THAT(v, IsIntEq(3)); - } - - TEST_F(PrimOpTest, foldStrict) { - auto v = eval("builtins.foldl' (a: b: a + b) 0 [1 2 3]"); - ASSERT_THAT(v, IsIntEq(6)); - } - - TEST_F(PrimOpTest, anyTrue) { - auto v = eval("builtins.any (x: x == 2) [ 1 2 3 ]"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(PrimOpTest, anyFalse) { - auto v = eval("builtins.any (x: x == 5) [ 1 2 3 ]"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(PrimOpTest, allTrue) { - auto v = eval("builtins.all (x: x > 0) [ 1 2 3 ]"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(PrimOpTest, allFalse) { - auto v = eval("builtins.all (x: x <= 0) [ 1 2 3 ]"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(PrimOpTest, genList) { - auto v = eval("builtins.genList (x: x + 1) 3"); - ASSERT_EQ(v.type(), nList); - ASSERT_EQ(v.listSize(), 3); - for (const auto [i, elem] : enumerate(v.listItems())) { - ASSERT_THAT(*elem, IsThunk()); - state.forceValue(*elem, noPos); - ASSERT_THAT(*elem, IsIntEq(static_cast(i)+1)); - } - } - - TEST_F(PrimOpTest, sortLessThan) { - auto v = eval("builtins.sort builtins.lessThan [ 483 249 526 147 42 77 ]"); - ASSERT_EQ(v.type(), nList); - ASSERT_EQ(v.listSize(), 6); - - const std::vector numbers = { 42, 77, 147, 249, 483, 526 }; - for (const auto [n, elem] : enumerate(v.listItems())) - ASSERT_THAT(*elem, IsIntEq(numbers[n])); - } - - TEST_F(PrimOpTest, partition) { - auto v = eval("builtins.partition (x: x > 10) [1 23 9 3 42]"); - ASSERT_THAT(v, IsAttrsOfSize(2)); - - auto right = v.attrs->get(createSymbol("right")); - ASSERT_NE(right, nullptr); - ASSERT_THAT(*right->value, IsListOfSize(2)); - ASSERT_THAT(*right->value->listElems()[0], IsIntEq(23)); - ASSERT_THAT(*right->value->listElems()[1], IsIntEq(42)); - - auto wrong = v.attrs->get(createSymbol("wrong")); - ASSERT_NE(wrong, nullptr); - ASSERT_EQ(wrong->value->type(), nList); - ASSERT_EQ(wrong->value->listSize(), 3); - ASSERT_THAT(*wrong->value, IsListOfSize(3)); - ASSERT_THAT(*wrong->value->listElems()[0], IsIntEq(1)); - ASSERT_THAT(*wrong->value->listElems()[1], IsIntEq(9)); - ASSERT_THAT(*wrong->value->listElems()[2], IsIntEq(3)); - } - - TEST_F(PrimOpTest, concatMap) { - auto v = eval("builtins.concatMap (x: x ++ [0]) [ [1 2] [3 4] ]"); - ASSERT_EQ(v.type(), nList); - ASSERT_EQ(v.listSize(), 6); - - const std::vector numbers = { 1, 2, 0, 3, 4, 0 }; - for (const auto [n, elem] : enumerate(v.listItems())) - ASSERT_THAT(*elem, IsIntEq(numbers[n])); - } - - TEST_F(PrimOpTest, addInt) { - auto v = eval("builtins.add 3 5"); - ASSERT_THAT(v, IsIntEq(8)); - } - - TEST_F(PrimOpTest, addFloat) { - auto v = eval("builtins.add 3.0 5.0"); - ASSERT_THAT(v, IsFloatEq(8.0)); - } - - TEST_F(PrimOpTest, addFloatToInt) { - auto v = eval("builtins.add 3.0 5"); - ASSERT_THAT(v, IsFloatEq(8.0)); - - v = eval("builtins.add 3 5.0"); - ASSERT_THAT(v, IsFloatEq(8.0)); - } - - TEST_F(PrimOpTest, subInt) { - auto v = eval("builtins.sub 5 2"); - ASSERT_THAT(v, IsIntEq(3)); - } - - TEST_F(PrimOpTest, subFloat) { - auto v = eval("builtins.sub 5.0 2.0"); - ASSERT_THAT(v, IsFloatEq(3.0)); - } - - TEST_F(PrimOpTest, subFloatFromInt) { - auto v = eval("builtins.sub 5.0 2"); - ASSERT_THAT(v, IsFloatEq(3.0)); - - v = eval("builtins.sub 4 2.0"); - ASSERT_THAT(v, IsFloatEq(2.0)); - } - - TEST_F(PrimOpTest, mulInt) { - auto v = eval("builtins.mul 3 5"); - ASSERT_THAT(v, IsIntEq(15)); - } - - TEST_F(PrimOpTest, mulFloat) { - auto v = eval("builtins.mul 3.0 5.0"); - ASSERT_THAT(v, IsFloatEq(15.0)); - } - - TEST_F(PrimOpTest, mulFloatMixed) { - auto v = eval("builtins.mul 3 5.0"); - ASSERT_THAT(v, IsFloatEq(15.0)); - - v = eval("builtins.mul 2.0 5"); - ASSERT_THAT(v, IsFloatEq(10.0)); - } - - TEST_F(PrimOpTest, divInt) { - auto v = eval("builtins.div 5 (-1)"); - ASSERT_THAT(v, IsIntEq(-5)); - } - - TEST_F(PrimOpTest, divIntZero) { - ASSERT_THROW(eval("builtins.div 5 0"), EvalError); - } - - TEST_F(PrimOpTest, divFloat) { - auto v = eval("builtins.div 5.0 (-1)"); - ASSERT_THAT(v, IsFloatEq(-5.0)); - } - - TEST_F(PrimOpTest, divFloatZero) { - ASSERT_THROW(eval("builtins.div 5.0 0.0"), EvalError); - } - - TEST_F(PrimOpTest, bitOr) { - auto v = eval("builtins.bitOr 1 2"); - ASSERT_THAT(v, IsIntEq(3)); - } - - TEST_F(PrimOpTest, bitXor) { - auto v = eval("builtins.bitXor 3 2"); - ASSERT_THAT(v, IsIntEq(1)); - } - - TEST_F(PrimOpTest, lessThanFalse) { - auto v = eval("builtins.lessThan 3 1"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(PrimOpTest, lessThanTrue) { - auto v = eval("builtins.lessThan 1 3"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(PrimOpTest, toStringAttrsThrows) { - ASSERT_THROW(eval("builtins.toString {}"), EvalError); - } - - TEST_F(PrimOpTest, toStringLambdaThrows) { - ASSERT_THROW(eval("builtins.toString (x: x)"), EvalError); - } - - class ToStringPrimOpTest : - public PrimOpTest, - public testing::WithParamInterface> - {}; - - TEST_P(ToStringPrimOpTest, toString) { - const auto [input, output] = GetParam(); - auto v = eval(input); - ASSERT_THAT(v, IsStringEq(output)); - } - -#define CASE(input, output) (std::make_tuple(std::string_view("builtins.toString " input), std::string_view(output))) - INSTANTIATE_TEST_SUITE_P( - toString, - ToStringPrimOpTest, - testing::Values( - CASE(R"("foo")", "foo"), - CASE(R"(1)", "1"), - CASE(R"([1 2 3])", "1 2 3"), - CASE(R"(.123)", "0.123000"), - CASE(R"(true)", "1"), - CASE(R"(false)", ""), - CASE(R"(null)", ""), - CASE(R"({ v = "bar"; __toString = self: self.v; })", "bar"), - CASE(R"({ v = "bar"; __toString = self: self.v; outPath = "foo"; })", "bar"), - CASE(R"({ outPath = "foo"; })", "foo"), - CASE(R"(./test)", "/test") - ) - ); -#undef CASE - - TEST_F(PrimOpTest, substring){ - auto v = eval("builtins.substring 0 3 \"nixos\""); - ASSERT_THAT(v, IsStringEq("nix")); - } - - TEST_F(PrimOpTest, substringSmallerString){ - auto v = eval("builtins.substring 0 3 \"n\""); - ASSERT_THAT(v, IsStringEq("n")); - } - - TEST_F(PrimOpTest, substringEmptyString){ - auto v = eval("builtins.substring 1 3 \"\""); - ASSERT_THAT(v, IsStringEq("")); - } - - TEST_F(PrimOpTest, stringLength) { - auto v = eval("builtins.stringLength \"123\""); - ASSERT_THAT(v, IsIntEq(3)); - } - TEST_F(PrimOpTest, hashStringMd5) { - auto v = eval("builtins.hashString \"md5\" \"asdf\""); - ASSERT_THAT(v, IsStringEq("912ec803b2ce49e4a541068d495ab570")); - } - - TEST_F(PrimOpTest, hashStringSha1) { - auto v = eval("builtins.hashString \"sha1\" \"asdf\""); - ASSERT_THAT(v, IsStringEq("3da541559918a808c2402bba5012f6c60b27661c")); - } - - TEST_F(PrimOpTest, hashStringSha256) { - auto v = eval("builtins.hashString \"sha256\" \"asdf\""); - ASSERT_THAT(v, IsStringEq("f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b")); - } - - TEST_F(PrimOpTest, hashStringSha512) { - auto v = eval("builtins.hashString \"sha512\" \"asdf\""); - ASSERT_THAT(v, IsStringEq("401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b3727429080fb337591abd3e44453b954555b7a0812e1081c39b740293f765eae731f5a65ed1")); - } - - TEST_F(PrimOpTest, hashStringInvalidHashType) { - ASSERT_THROW(eval("builtins.hashString \"foobar\" \"asdf\""), Error); - } - - TEST_F(PrimOpTest, nixPath) { - auto v = eval("builtins.nixPath"); - ASSERT_EQ(v.type(), nList); - // We can't test much more as currently the EvalSettings are a global - // that we can't easily swap / replace - } - - TEST_F(PrimOpTest, langVersion) { - auto v = eval("builtins.langVersion"); - ASSERT_EQ(v.type(), nInt); - } - - TEST_F(PrimOpTest, storeDir) { - auto v = eval("builtins.storeDir"); - ASSERT_THAT(v, IsStringEq(settings.nixStore)); - } - - TEST_F(PrimOpTest, nixVersion) { - auto v = eval("builtins.nixVersion"); - ASSERT_THAT(v, IsStringEq(nixVersion)); - } - - TEST_F(PrimOpTest, currentSystem) { - auto v = eval("builtins.currentSystem"); - ASSERT_THAT(v, IsStringEq(settings.thisSystem.get())); - } - - TEST_F(PrimOpTest, derivation) { - auto v = eval("derivation"); - ASSERT_EQ(v.type(), nFunction); - ASSERT_TRUE(v.isLambda()); - ASSERT_NE(v.lambda.fun, nullptr); - ASSERT_TRUE(v.lambda.fun->hasFormals()); - } - - TEST_F(PrimOpTest, currentTime) { - auto v = eval("builtins.currentTime"); - ASSERT_EQ(v.type(), nInt); - ASSERT_TRUE(v.integer > 0); - } - - TEST_F(PrimOpTest, splitVersion) { - auto v = eval("builtins.splitVersion \"1.2.3git\""); - ASSERT_THAT(v, IsListOfSize(4)); - - const std::vector strings = { "1", "2", "3", "git" }; - for (const auto [n, p] : enumerate(v.listItems())) - ASSERT_THAT(*p, IsStringEq(strings[n])); - } - - class CompareVersionsPrimOpTest : - public PrimOpTest, - public testing::WithParamInterface> - {}; - - TEST_P(CompareVersionsPrimOpTest, compareVersions) { - auto [expression, expectation] = GetParam(); - auto v = eval(expression); - ASSERT_THAT(v, IsIntEq(expectation)); - } - -#define CASE(a, b, expected) (std::make_tuple("builtins.compareVersions \"" #a "\" \"" #b "\"", expected)) - INSTANTIATE_TEST_SUITE_P( - compareVersions, - CompareVersionsPrimOpTest, - testing::Values( - // The first two are weird cases. Intuition tells they should - // be the same but they aren't. - CASE(1.0, 1.0.0, -1), - CASE(1.0.0, 1.0, 1), - // the following are from the nix-env manual: - CASE(1.0, 2.3, -1), - CASE(2.1, 2.3, -1), - CASE(2.3, 2.3, 0), - CASE(2.5, 2.3, 1), - CASE(3.1, 2.3, 1), - CASE(2.3.1, 2.3, 1), - CASE(2.3.1, 2.3a, 1), - CASE(2.3pre1, 2.3, -1), - CASE(2.3pre3, 2.3pre12, -1), - CASE(2.3a, 2.3c, -1), - CASE(2.3pre1, 2.3c, -1), - CASE(2.3pre1, 2.3q, -1) - ) - ); -#undef CASE - - - class ParseDrvNamePrimOpTest : - public PrimOpTest, - public testing::WithParamInterface> - {}; - - TEST_P(ParseDrvNamePrimOpTest, parseDrvName) { - auto [input, expectedName, expectedVersion] = GetParam(); - const auto expr = fmt("builtins.parseDrvName \"%1%\"", input); - auto v = eval(expr); - ASSERT_THAT(v, IsAttrsOfSize(2)); - - auto name = v.attrs->find(createSymbol("name")); - ASSERT_TRUE(name); - ASSERT_THAT(*name->value, IsStringEq(expectedName)); - - auto version = v.attrs->find(createSymbol("version")); - ASSERT_TRUE(version); - ASSERT_THAT(*version->value, IsStringEq(expectedVersion)); - } - - INSTANTIATE_TEST_SUITE_P( - parseDrvName, - ParseDrvNamePrimOpTest, - testing::Values( - std::make_tuple("nix-0.12pre12876", "nix", "0.12pre12876"), - std::make_tuple("a-b-c-1234pre5+git", "a-b-c", "1234pre5+git") - ) - ); - - TEST_F(PrimOpTest, replaceStrings) { - // FIXME: add a test that verifies the string context is as expected - auto v = eval("builtins.replaceStrings [\"oo\" \"a\"] [\"a\" \"i\"] \"foobar\""); - ASSERT_EQ(v.type(), nString); - ASSERT_EQ(v.string.s, std::string_view("fabir")); - } - - TEST_F(PrimOpTest, concatStringsSep) { - // FIXME: add a test that verifies the string context is as expected - auto v = eval("builtins.concatStringsSep \"%\" [\"foo\" \"bar\" \"baz\"]"); - ASSERT_EQ(v.type(), nString); - ASSERT_EQ(std::string_view(v.string.s), "foo%bar%baz"); - } - - TEST_F(PrimOpTest, split1) { - // v = [ "" [ "a" ] "c" ] - auto v = eval("builtins.split \"(a)b\" \"abc\""); - ASSERT_THAT(v, IsListOfSize(3)); - - ASSERT_THAT(*v.listElems()[0], IsStringEq("")); - - ASSERT_THAT(*v.listElems()[1], IsListOfSize(1)); - ASSERT_THAT(*v.listElems()[1]->listElems()[0], IsStringEq("a")); - - ASSERT_THAT(*v.listElems()[2], IsStringEq("c")); - } - - TEST_F(PrimOpTest, split2) { - // v is expected to be a list [ "" [ "a" ] "b" [ "c"] "" ] - auto v = eval("builtins.split \"([ac])\" \"abc\""); - ASSERT_THAT(v, IsListOfSize(5)); - - ASSERT_THAT(*v.listElems()[0], IsStringEq("")); - - ASSERT_THAT(*v.listElems()[1], IsListOfSize(1)); - ASSERT_THAT(*v.listElems()[1]->listElems()[0], IsStringEq("a")); - - ASSERT_THAT(*v.listElems()[2], IsStringEq("b")); - - ASSERT_THAT(*v.listElems()[3], IsListOfSize(1)); - ASSERT_THAT(*v.listElems()[3]->listElems()[0], IsStringEq("c")); - - ASSERT_THAT(*v.listElems()[4], IsStringEq("")); - } - - TEST_F(PrimOpTest, split3) { - auto v = eval("builtins.split \"(a)|(c)\" \"abc\""); - ASSERT_THAT(v, IsListOfSize(5)); - - // First list element - ASSERT_THAT(*v.listElems()[0], IsStringEq("")); - - // 2nd list element is a list [ "" null ] - ASSERT_THAT(*v.listElems()[1], IsListOfSize(2)); - ASSERT_THAT(*v.listElems()[1]->listElems()[0], IsStringEq("a")); - ASSERT_THAT(*v.listElems()[1]->listElems()[1], IsNull()); - - // 3rd element - ASSERT_THAT(*v.listElems()[2], IsStringEq("b")); - - // 4th element is a list: [ null "c" ] - ASSERT_THAT(*v.listElems()[3], IsListOfSize(2)); - ASSERT_THAT(*v.listElems()[3]->listElems()[0], IsNull()); - ASSERT_THAT(*v.listElems()[3]->listElems()[1], IsStringEq("c")); - - // 5th element is the empty string - ASSERT_THAT(*v.listElems()[4], IsStringEq("")); - } - - TEST_F(PrimOpTest, split4) { - auto v = eval("builtins.split \"([[:upper:]]+)\" \" FOO \""); - ASSERT_THAT(v, IsListOfSize(3)); - auto first = v.listElems()[0]; - auto second = v.listElems()[1]; - auto third = v.listElems()[2]; - - ASSERT_THAT(*first, IsStringEq(" ")); - - ASSERT_THAT(*second, IsListOfSize(1)); - ASSERT_THAT(*second->listElems()[0], IsStringEq("FOO")); - - ASSERT_THAT(*third, IsStringEq(" ")); - } - - TEST_F(PrimOpTest, match1) { - auto v = eval("builtins.match \"ab\" \"abc\""); - ASSERT_THAT(v, IsNull()); - } - - TEST_F(PrimOpTest, match2) { - auto v = eval("builtins.match \"abc\" \"abc\""); - ASSERT_THAT(v, IsListOfSize(0)); - } - - TEST_F(PrimOpTest, match3) { - auto v = eval("builtins.match \"a(b)(c)\" \"abc\""); - ASSERT_THAT(v, IsListOfSize(2)); - ASSERT_THAT(*v.listElems()[0], IsStringEq("b")); - ASSERT_THAT(*v.listElems()[1], IsStringEq("c")); - } - - TEST_F(PrimOpTest, match4) { - auto v = eval("builtins.match \"[[:space:]]+([[:upper:]]+)[[:space:]]+\" \" FOO \""); - ASSERT_THAT(v, IsListOfSize(1)); - ASSERT_THAT(*v.listElems()[0], IsStringEq("FOO")); - } - - TEST_F(PrimOpTest, attrNames) { - auto v = eval("builtins.attrNames { x = 1; y = 2; z = 3; a = 2; }"); - ASSERT_THAT(v, IsListOfSize(4)); - - // ensure that the list is sorted - const std::vector expected { "a", "x", "y", "z" }; - for (const auto [n, elem] : enumerate(v.listItems())) - ASSERT_THAT(*elem, IsStringEq(expected[n])); - } - - TEST_F(PrimOpTest, genericClosure_not_strict) { - // Operator should not be used when startSet is empty - auto v = eval("builtins.genericClosure { startSet = []; }"); - ASSERT_THAT(v, IsListOfSize(0)); - } -} /* namespace nix */ diff --git a/src/libexpr/tests/search-path.cc b/src/libexpr/tests/search-path.cc deleted file mode 100644 index dbe7ab95f..000000000 --- a/src/libexpr/tests/search-path.cc +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include - -#include "search-path.hh" - -namespace nix { - -TEST(SearchPathElem, parse_justPath) { - ASSERT_EQ( - SearchPath::Elem::parse("foo"), - (SearchPath::Elem { - .prefix = SearchPath::Prefix { .s = "" }, - .path = SearchPath::Path { .s = "foo" }, - })); -} - -TEST(SearchPathElem, parse_emptyPrefix) { - ASSERT_EQ( - SearchPath::Elem::parse("=foo"), - (SearchPath::Elem { - .prefix = SearchPath::Prefix { .s = "" }, - .path = SearchPath::Path { .s = "foo" }, - })); -} - -TEST(SearchPathElem, parse_oneEq) { - ASSERT_EQ( - SearchPath::Elem::parse("foo=bar"), - (SearchPath::Elem { - .prefix = SearchPath::Prefix { .s = "foo" }, - .path = SearchPath::Path { .s = "bar" }, - })); -} - -TEST(SearchPathElem, parse_twoEqs) { - ASSERT_EQ( - SearchPath::Elem::parse("foo=bar=baz"), - (SearchPath::Elem { - .prefix = SearchPath::Prefix { .s = "foo" }, - .path = SearchPath::Path { .s = "bar=baz" }, - })); -} - - -TEST(SearchPathElem, suffixIfPotentialMatch_justPath) { - SearchPath::Prefix prefix { .s = "" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("any/thing"), std::optional { "any/thing" }); -} - -TEST(SearchPathElem, suffixIfPotentialMatch_misleadingPrefix1) { - SearchPath::Prefix prefix { .s = "foo" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("fooX"), std::nullopt); -} - -TEST(SearchPathElem, suffixIfPotentialMatch_misleadingPrefix2) { - SearchPath::Prefix prefix { .s = "foo" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("fooX/bar"), std::nullopt); -} - -TEST(SearchPathElem, suffixIfPotentialMatch_partialPrefix) { - SearchPath::Prefix prefix { .s = "fooX" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("foo"), std::nullopt); -} - -TEST(SearchPathElem, suffixIfPotentialMatch_exactPrefix) { - SearchPath::Prefix prefix { .s = "foo" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("foo"), std::optional { "" }); -} - -TEST(SearchPathElem, suffixIfPotentialMatch_multiKey) { - SearchPath::Prefix prefix { .s = "foo/bar" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/bar/baz"), std::optional { "baz" }); -} - -TEST(SearchPathElem, suffixIfPotentialMatch_trailingSlash) { - SearchPath::Prefix prefix { .s = "foo" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/"), std::optional { "" }); -} - -TEST(SearchPathElem, suffixIfPotentialMatch_trailingDoubleSlash) { - SearchPath::Prefix prefix { .s = "foo" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("foo//"), std::optional { "/" }); -} - -TEST(SearchPathElem, suffixIfPotentialMatch_trailingPath) { - SearchPath::Prefix prefix { .s = "foo" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/bar/baz"), std::optional { "bar/baz" }); -} - -} diff --git a/src/libexpr/tests/trivial.cc b/src/libexpr/tests/trivial.cc deleted file mode 100644 index 171727ac7..000000000 --- a/src/libexpr/tests/trivial.cc +++ /dev/null @@ -1,196 +0,0 @@ -#include "tests/libexpr.hh" - -namespace nix { - // Testing of trivial expressions - class TrivialExpressionTest : public LibExprTest {}; - - TEST_F(TrivialExpressionTest, true) { - auto v = eval("true"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(TrivialExpressionTest, false) { - auto v = eval("false"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(TrivialExpressionTest, null) { - auto v = eval("null"); - ASSERT_THAT(v, IsNull()); - } - - TEST_F(TrivialExpressionTest, 1) { - auto v = eval("1"); - ASSERT_THAT(v, IsIntEq(1)); - } - - TEST_F(TrivialExpressionTest, 1plus1) { - auto v = eval("1+1"); - ASSERT_THAT(v, IsIntEq(2)); - } - - TEST_F(TrivialExpressionTest, minus1) { - auto v = eval("-1"); - ASSERT_THAT(v, IsIntEq(-1)); - } - - TEST_F(TrivialExpressionTest, 1minus1) { - auto v = eval("1-1"); - ASSERT_THAT(v, IsIntEq(0)); - } - - TEST_F(TrivialExpressionTest, lambdaAdd) { - auto v = eval("let add = a: b: a + b; in add 1 2"); - ASSERT_THAT(v, IsIntEq(3)); - } - - TEST_F(TrivialExpressionTest, list) { - auto v = eval("[]"); - ASSERT_THAT(v, IsListOfSize(0)); - } - - TEST_F(TrivialExpressionTest, attrs) { - auto v = eval("{}"); - ASSERT_THAT(v, IsAttrsOfSize(0)); - } - - TEST_F(TrivialExpressionTest, float) { - auto v = eval("1.234"); - ASSERT_THAT(v, IsFloatEq(1.234)); - } - - TEST_F(TrivialExpressionTest, updateAttrs) { - auto v = eval("{ a = 1; } // { b = 2; a = 3; }"); - ASSERT_THAT(v, IsAttrsOfSize(2)); - auto a = v.attrs->find(createSymbol("a")); - ASSERT_NE(a, nullptr); - ASSERT_THAT(*a->value, IsIntEq(3)); - - auto b = v.attrs->find(createSymbol("b")); - ASSERT_NE(b, nullptr); - ASSERT_THAT(*b->value, IsIntEq(2)); - } - - TEST_F(TrivialExpressionTest, hasAttrOpFalse) { - auto v = eval("{} ? a"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(TrivialExpressionTest, hasAttrOpTrue) { - auto v = eval("{ a = 123; } ? a"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(TrivialExpressionTest, withFound) { - auto v = eval("with { a = 23; }; a"); - ASSERT_THAT(v, IsIntEq(23)); - } - - TEST_F(TrivialExpressionTest, withNotFound) { - ASSERT_THROW(eval("with {}; a"), Error); - } - - TEST_F(TrivialExpressionTest, withOverride) { - auto v = eval("with { a = 23; }; with { a = 42; }; a"); - ASSERT_THAT(v, IsIntEq(42)); - } - - TEST_F(TrivialExpressionTest, letOverWith) { - auto v = eval("let a = 23; in with { a = 1; }; a"); - ASSERT_THAT(v, IsIntEq(23)); - } - - TEST_F(TrivialExpressionTest, multipleLet) { - auto v = eval("let a = 23; in let a = 42; in a"); - ASSERT_THAT(v, IsIntEq(42)); - } - - TEST_F(TrivialExpressionTest, defaultFunctionArgs) { - auto v = eval("({ a ? 123 }: a) {}"); - ASSERT_THAT(v, IsIntEq(123)); - } - - TEST_F(TrivialExpressionTest, defaultFunctionArgsOverride) { - auto v = eval("({ a ? 123 }: a) { a = 5; }"); - ASSERT_THAT(v, IsIntEq(5)); - } - - TEST_F(TrivialExpressionTest, defaultFunctionArgsCaptureBack) { - auto v = eval("({ a ? 123 }@args: args) {}"); - ASSERT_THAT(v, IsAttrsOfSize(0)); - } - - TEST_F(TrivialExpressionTest, defaultFunctionArgsCaptureFront) { - auto v = eval("(args@{ a ? 123 }: args) {}"); - ASSERT_THAT(v, IsAttrsOfSize(0)); - } - - TEST_F(TrivialExpressionTest, assertThrows) { - ASSERT_THROW(eval("let x = arg: assert arg == 1; 123; in x 2"), Error); - } - - TEST_F(TrivialExpressionTest, assertPassed) { - auto v = eval("let x = arg: assert arg == 1; 123; in x 1"); - ASSERT_THAT(v, IsIntEq(123)); - } - - class AttrSetMergeTrvialExpressionTest : - public TrivialExpressionTest, - public testing::WithParamInterface - {}; - - TEST_P(AttrSetMergeTrvialExpressionTest, attrsetMergeLazy) { - // Usually Nix rejects duplicate keys in an attrset but it does allow - // so if it is an attribute set that contains disjoint sets of keys. - // The below is equivalent to `{a.b = 1; a.c = 2; }`. - // The attribute set `a` will be a Thunk at first as the attribuets - // have to be merged (or otherwise computed) and that is done in a lazy - // manner. - - auto expr = GetParam(); - auto v = eval(expr); - ASSERT_THAT(v, IsAttrsOfSize(1)); - - auto a = v.attrs->find(createSymbol("a")); - ASSERT_NE(a, nullptr); - - ASSERT_THAT(*a->value, IsThunk()); - state.forceValue(*a->value, noPos); - - ASSERT_THAT(*a->value, IsAttrsOfSize(2)); - - auto b = a->value->attrs->find(createSymbol("b")); - ASSERT_NE(b, nullptr); - ASSERT_THAT(*b->value, IsIntEq(1)); - - auto c = a->value->attrs->find(createSymbol("c")); - ASSERT_NE(c, nullptr); - ASSERT_THAT(*c->value, IsIntEq(2)); - } - - INSTANTIATE_TEST_SUITE_P( - attrsetMergeLazy, - AttrSetMergeTrvialExpressionTest, - testing::Values( - "{ a.b = 1; a.c = 2; }", - "{ a = { b = 1; }; a = { c = 2; }; }" - ) - ); - - TEST_F(TrivialExpressionTest, functor) { - auto v = eval("{ __functor = self: arg: self.v + arg; v = 10; } 5"); - ASSERT_THAT(v, IsIntEq(15)); - } - - TEST_F(TrivialExpressionTest, bindOr) { - auto v = eval("{ or = 1; }"); - ASSERT_THAT(v, IsAttrsOfSize(1)); - auto b = v.attrs->find(createSymbol("or")); - ASSERT_NE(b, nullptr); - ASSERT_THAT(*b->value, IsIntEq(1)); - } - - TEST_F(TrivialExpressionTest, orCantBeUsed) { - ASSERT_THROW(eval("let or = 1; in or"), Error); - } -} /* namespace nix */ diff --git a/src/libexpr/tests/value/context.cc b/src/libexpr/tests/value/context.cc deleted file mode 100644 index 92d4889ab..000000000 --- a/src/libexpr/tests/value/context.cc +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include -#include - -#include "tests/path.hh" -#include "tests/libexpr.hh" -#include "tests/value/context.hh" - -namespace nix { - -// Test a few cases of invalid string context elements. - -TEST(NixStringContextElemTest, empty_invalid) { - EXPECT_THROW( - NixStringContextElem::parse(""), - BadNixStringContextElem); -} - -TEST(NixStringContextElemTest, single_bang_invalid) { - EXPECT_THROW( - NixStringContextElem::parse("!"), - BadNixStringContextElem); -} - -TEST(NixStringContextElemTest, double_bang_invalid) { - EXPECT_THROW( - NixStringContextElem::parse("!!/"), - BadStorePath); -} - -TEST(NixStringContextElemTest, eq_slash_invalid) { - EXPECT_THROW( - NixStringContextElem::parse("=/"), - BadStorePath); -} - -TEST(NixStringContextElemTest, slash_invalid) { - EXPECT_THROW( - NixStringContextElem::parse("/"), - BadStorePath); -} - -/** - * Round trip (string <-> data structure) test for - * `NixStringContextElem::Opaque`. - */ -TEST(NixStringContextElemTest, opaque) { - std::string_view opaque = "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x"; - auto elem = NixStringContextElem::parse(opaque); - auto * p = std::get_if(&elem.raw); - ASSERT_TRUE(p); - ASSERT_EQ(p->path, StorePath { opaque }); - ASSERT_EQ(elem.to_string(), opaque); -} - -/** - * Round trip (string <-> data structure) test for - * `NixStringContextElem::DrvDeep`. - */ -TEST(NixStringContextElemTest, drvDeep) { - std::string_view drvDeep = "=g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv"; - auto elem = NixStringContextElem::parse(drvDeep); - auto * p = std::get_if(&elem.raw); - ASSERT_TRUE(p); - ASSERT_EQ(p->drvPath, StorePath { drvDeep.substr(1) }); - ASSERT_EQ(elem.to_string(), drvDeep); -} - -/** - * Round trip (string <-> data structure) test for a simpler - * `NixStringContextElem::Built`. - */ -TEST(NixStringContextElemTest, built_opaque) { - std::string_view built = "!foo!g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv"; - auto elem = NixStringContextElem::parse(built); - auto * p = std::get_if(&elem.raw); - ASSERT_TRUE(p); - ASSERT_EQ(p->output, "foo"); - ASSERT_EQ(*p->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque { - .path = StorePath { built.substr(5) }, - })); - ASSERT_EQ(elem.to_string(), built); -} - -/** - * Round trip (string <-> data structure) test for a more complex, - * inductive `NixStringContextElem::Built`. - */ -TEST(NixStringContextElemTest, built_built) { - /** - * We set these in tests rather than the regular globals so we don't have - * to worry about race conditions if the tests run concurrently. - */ - ExperimentalFeatureSettings mockXpSettings; - mockXpSettings.set("experimental-features", "dynamic-derivations ca-derivations"); - - std::string_view built = "!foo!bar!g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv"; - auto elem = NixStringContextElem::parse(built, mockXpSettings); - auto * p = std::get_if(&elem.raw); - ASSERT_TRUE(p); - ASSERT_EQ(p->output, "foo"); - auto * drvPath = std::get_if(&*p->drvPath); - ASSERT_TRUE(drvPath); - ASSERT_EQ(drvPath->output, "bar"); - ASSERT_EQ(*drvPath->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque { - .path = StorePath { built.substr(9) }, - })); - ASSERT_EQ(elem.to_string(), built); -} - -/** - * Without the right experimental features enabled, we cannot parse a - * complex inductive string context element. - */ -TEST(NixStringContextElemTest, built_built_xp) { - ASSERT_THROW( - NixStringContextElem::parse("!foo!bar!g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv"), MissingExperimentalFeature); -} - -} - -namespace rc { -using namespace nix; - -Gen Arbitrary::arbitrary() -{ - return gen::just(NixStringContextElem::DrvDeep { - .drvPath = *gen::arbitrary(), - }); -} - -Gen Arbitrary::arbitrary() -{ - switch (*gen::inRange(0, std::variant_size_v)) { - case 0: - return gen::just(*gen::arbitrary()); - case 1: - return gen::just(*gen::arbitrary()); - case 2: - return gen::just(*gen::arbitrary()); - default: - assert(false); - } -} - -} - -namespace nix { - -#ifndef COVERAGE - -RC_GTEST_PROP( - NixStringContextElemTest, - prop_round_rip, - (const NixStringContextElem & o)) -{ - RC_ASSERT(o == NixStringContextElem::parse(o.to_string())); -} - -#endif - -} diff --git a/src/libexpr/tests/value/context.hh b/src/libexpr/tests/value/context.hh deleted file mode 100644 index c0bc97ba3..000000000 --- a/src/libexpr/tests/value/context.hh +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -///@file - -#include - -#include - -namespace rc { -using namespace nix; - -template<> -struct Arbitrary { - static Gen arbitrary(); -}; - -template<> -struct Arbitrary { - static Gen arbitrary(); -}; - -template<> -struct Arbitrary { - static Gen arbitrary(); -}; - -template<> -struct Arbitrary { - static Gen arbitrary(); -}; - -} diff --git a/src/libexpr/tests/value/print.cc b/src/libexpr/tests/value/print.cc deleted file mode 100644 index 5e96e12ec..000000000 --- a/src/libexpr/tests/value/print.cc +++ /dev/null @@ -1,236 +0,0 @@ -#include "tests/libexpr.hh" - -#include "value.hh" - -namespace nix { - -using namespace testing; - -struct ValuePrintingTests : LibExprTest -{ - template - void test(Value v, std::string_view expected, A... args) - { - std::stringstream out; - v.print(state.symbols, out, args...); - ASSERT_EQ(out.str(), expected); - } -}; - -TEST_F(ValuePrintingTests, tInt) -{ - Value vInt; - vInt.mkInt(10); - test(vInt, "10"); -} - -TEST_F(ValuePrintingTests, tBool) -{ - Value vBool; - vBool.mkBool(true); - test(vBool, "true"); -} - -TEST_F(ValuePrintingTests, tString) -{ - Value vString; - vString.mkString("some-string"); - test(vString, "\"some-string\""); -} - -TEST_F(ValuePrintingTests, tPath) -{ - Value vPath; - vPath.mkString("/foo"); - test(vPath, "\"/foo\""); -} - -TEST_F(ValuePrintingTests, tNull) -{ - Value vNull; - vNull.mkNull(); - test(vNull, "null"); -} - -TEST_F(ValuePrintingTests, tAttrs) -{ - Value vOne; - vOne.mkInt(1); - - Value vTwo; - vTwo.mkInt(2); - - BindingsBuilder builder(state, state.allocBindings(10)); - builder.insert(state.symbols.create("one"), &vOne); - builder.insert(state.symbols.create("two"), &vTwo); - - Value vAttrs; - vAttrs.mkAttrs(builder.finish()); - - test(vAttrs, "{ one = 1; two = 2; }"); -} - -TEST_F(ValuePrintingTests, tList) -{ - Value vOne; - vOne.mkInt(1); - - Value vTwo; - vTwo.mkInt(2); - - Value vList; - state.mkList(vList, 5); - vList.bigList.elems[0] = &vOne; - vList.bigList.elems[1] = &vTwo; - vList.bigList.size = 3; - - test(vList, "[ 1 2 (nullptr) ]"); -} - -TEST_F(ValuePrintingTests, vThunk) -{ - Value vThunk; - vThunk.mkThunk(nullptr, nullptr); - - test(vThunk, ""); -} - -TEST_F(ValuePrintingTests, vApp) -{ - Value vApp; - vApp.mkApp(nullptr, nullptr); - - test(vApp, ""); -} - -TEST_F(ValuePrintingTests, vLambda) -{ - Value vLambda; - vLambda.mkLambda(nullptr, nullptr); - - test(vLambda, ""); -} - -TEST_F(ValuePrintingTests, vPrimOp) -{ - Value vPrimOp; - vPrimOp.mkPrimOp(nullptr); - - test(vPrimOp, ""); -} - -TEST_F(ValuePrintingTests, vPrimOpApp) -{ - Value vPrimOpApp; - vPrimOpApp.mkPrimOpApp(nullptr, nullptr); - - test(vPrimOpApp, ""); -} - -TEST_F(ValuePrintingTests, vExternal) -{ - struct MyExternal : ExternalValueBase - { - public: - std::string showType() const override - { - return ""; - } - std::string typeOf() const override - { - return ""; - } - virtual std::ostream & print(std::ostream & str) const override - { - str << "testing-external!"; - return str; - } - } myExternal; - Value vExternal; - vExternal.mkExternal(&myExternal); - - test(vExternal, "testing-external!"); -} - -TEST_F(ValuePrintingTests, vFloat) -{ - Value vFloat; - vFloat.mkFloat(2.0); - - test(vFloat, "2"); -} - -TEST_F(ValuePrintingTests, vBlackhole) -{ - Value vBlackhole; - vBlackhole.mkBlackhole(); - test(vBlackhole, "«potential infinite recursion»"); -} - -TEST_F(ValuePrintingTests, depthAttrs) -{ - Value vOne; - vOne.mkInt(1); - - Value vTwo; - vTwo.mkInt(2); - - BindingsBuilder builder(state, state.allocBindings(10)); - builder.insert(state.symbols.create("one"), &vOne); - builder.insert(state.symbols.create("two"), &vTwo); - - Value vAttrs; - vAttrs.mkAttrs(builder.finish()); - - BindingsBuilder builder2(state, state.allocBindings(10)); - builder2.insert(state.symbols.create("one"), &vOne); - builder2.insert(state.symbols.create("two"), &vTwo); - builder2.insert(state.symbols.create("nested"), &vAttrs); - - Value vNested; - vNested.mkAttrs(builder2.finish()); - - test(vNested, "{ nested = «too deep»; one = «too deep»; two = «too deep»; }", false, 1); - test(vNested, "{ nested = { one = «too deep»; two = «too deep»; }; one = 1; two = 2; }", false, 2); - test(vNested, "{ nested = { one = 1; two = 2; }; one = 1; two = 2; }", false, 3); - test(vNested, "{ nested = { one = 1; two = 2; }; one = 1; two = 2; }", false, 4); -} - -TEST_F(ValuePrintingTests, depthList) -{ - Value vOne; - vOne.mkInt(1); - - Value vTwo; - vTwo.mkInt(2); - - BindingsBuilder builder(state, state.allocBindings(10)); - builder.insert(state.symbols.create("one"), &vOne); - builder.insert(state.symbols.create("two"), &vTwo); - - Value vAttrs; - vAttrs.mkAttrs(builder.finish()); - - BindingsBuilder builder2(state, state.allocBindings(10)); - builder2.insert(state.symbols.create("one"), &vOne); - builder2.insert(state.symbols.create("two"), &vTwo); - builder2.insert(state.symbols.create("nested"), &vAttrs); - - Value vNested; - vNested.mkAttrs(builder2.finish()); - - Value vList; - state.mkList(vList, 5); - vList.bigList.elems[0] = &vOne; - vList.bigList.elems[1] = &vTwo; - vList.bigList.elems[2] = &vNested; - vList.bigList.size = 3; - - test(vList, "[ «too deep» «too deep» «too deep» ]", false, 1); - test(vList, "[ 1 2 { nested = «too deep»; one = «too deep»; two = «too deep»; } ]", false, 2); - test(vList, "[ 1 2 { nested = { one = «too deep»; two = «too deep»; }; one = 1; two = 2; } ]", false, 3); - test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", false, 4); - test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", false, 5); -} - -} // namespace nix diff --git a/src/libstore/tests/derivation.cc b/src/libstore/tests/derivation.cc deleted file mode 100644 index c360c9707..000000000 --- a/src/libstore/tests/derivation.cc +++ /dev/null @@ -1,369 +0,0 @@ -#include -#include - -#include "experimental-features.hh" -#include "derivations.hh" - -#include "tests/libstore.hh" - -namespace nix { - -class DerivationTest : public LibStoreTest -{ -public: - /** - * We set these in tests rather than the regular globals so we don't have - * to worry about race conditions if the tests run concurrently. - */ - ExperimentalFeatureSettings mockXpSettings; -}; - -class CaDerivationTest : public DerivationTest -{ - void SetUp() override - { - mockXpSettings.set("experimental-features", "ca-derivations"); - } -}; - -class DynDerivationTest : public DerivationTest -{ - void SetUp() override - { - mockXpSettings.set("experimental-features", "dynamic-derivations ca-derivations"); - } -}; - -class ImpureDerivationTest : public DerivationTest -{ - void SetUp() override - { - mockXpSettings.set("experimental-features", "impure-derivations"); - } -}; - -TEST_F(DerivationTest, BadATerm_version) { - ASSERT_THROW( - parseDerivation( - *store, - R"(DrvWithVersion("invalid-version",[],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",["cat","dog"])],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")]))", - "whatever", - mockXpSettings), - FormatError); -} - -TEST_F(DynDerivationTest, BadATerm_oldVersionDynDeps) { - ASSERT_THROW( - parseDerivation( - *store, - R"(Derive([],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",(["cat","dog"],[("cat",["kitten"]),("goose",["gosling"])]))],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")]))", - "dyn-dep-derivation", - mockXpSettings), - FormatError); -} - -#define TEST_JSON(FIXTURE, NAME, STR, VAL, DRV_NAME, OUTPUT_NAME) \ - TEST_F(FIXTURE, DerivationOutput_ ## NAME ## _to_json) { \ - using nlohmann::literals::operator "" _json; \ - ASSERT_EQ( \ - STR ## _json, \ - (DerivationOutput { VAL }).toJSON( \ - *store, \ - DRV_NAME, \ - OUTPUT_NAME)); \ - } \ - \ - TEST_F(FIXTURE, DerivationOutput_ ## NAME ## _from_json) { \ - using nlohmann::literals::operator "" _json; \ - ASSERT_EQ( \ - DerivationOutput { VAL }, \ - DerivationOutput::fromJSON( \ - *store, \ - DRV_NAME, \ - OUTPUT_NAME, \ - STR ## _json, \ - mockXpSettings)); \ - } - -TEST_JSON(DerivationTest, inputAddressed, - R"({ - "path": "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name" - })", - (DerivationOutput::InputAddressed { - .path = store->parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"), - }), - "drv-name", "output-name") - -TEST_JSON(DerivationTest, caFixedFlat, - R"({ - "hashAlgo": "sha256", - "hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f", - "path": "/nix/store/rhcg9h16sqvlbpsa6dqm57sbr2al6nzg-drv-name-output-name" - })", - (DerivationOutput::CAFixed { - .ca = { - .method = FileIngestionMethod::Flat, - .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="), - }, - }), - "drv-name", "output-name") - -TEST_JSON(DerivationTest, caFixedNAR, - R"({ - "hashAlgo": "r:sha256", - "hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f", - "path": "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name" - })", - (DerivationOutput::CAFixed { - .ca = { - .method = FileIngestionMethod::Recursive, - .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="), - }, - }), - "drv-name", "output-name") - -TEST_JSON(DynDerivationTest, caFixedText, - R"({ - "hashAlgo": "text:sha256", - "hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f", - "path": "/nix/store/6s1zwabh956jvhv4w9xcdb5jiyanyxg1-drv-name-output-name" - })", - (DerivationOutput::CAFixed { - .ca = { - .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="), - }, - }), - "drv-name", "output-name") - -TEST_JSON(CaDerivationTest, caFloating, - R"({ - "hashAlgo": "r:sha256" - })", - (DerivationOutput::CAFloating { - .method = FileIngestionMethod::Recursive, - .hashType = htSHA256, - }), - "drv-name", "output-name") - -TEST_JSON(DerivationTest, deferred, - R"({ })", - DerivationOutput::Deferred { }, - "drv-name", "output-name") - -TEST_JSON(ImpureDerivationTest, impure, - R"({ - "hashAlgo": "r:sha256", - "impure": true - })", - (DerivationOutput::Impure { - .method = FileIngestionMethod::Recursive, - .hashType = htSHA256, - }), - "drv-name", "output-name") - -#undef TEST_JSON - -#define TEST_JSON(FIXTURE, NAME, STR, VAL) \ - TEST_F(FIXTURE, Derivation_ ## NAME ## _to_json) { \ - using nlohmann::literals::operator "" _json; \ - ASSERT_EQ( \ - STR ## _json, \ - (VAL).toJSON(*store)); \ - } \ - \ - TEST_F(FIXTURE, Derivation_ ## NAME ## _from_json) { \ - using nlohmann::literals::operator "" _json; \ - ASSERT_EQ( \ - (VAL), \ - Derivation::fromJSON( \ - *store, \ - STR ## _json, \ - mockXpSettings)); \ - } - -#define TEST_ATERM(FIXTURE, NAME, STR, VAL, DRV_NAME) \ - TEST_F(FIXTURE, Derivation_ ## NAME ## _to_aterm) { \ - ASSERT_EQ( \ - STR, \ - (VAL).unparse(*store, false)); \ - } \ - \ - TEST_F(FIXTURE, Derivation_ ## NAME ## _from_aterm) { \ - auto parsed = parseDerivation( \ - *store, \ - STR, \ - DRV_NAME, \ - mockXpSettings); \ - ASSERT_EQ( \ - (VAL).toJSON(*store), \ - parsed.toJSON(*store)); \ - ASSERT_EQ( \ - (VAL), \ - parsed); \ - } - -Derivation makeSimpleDrv(const Store & store) { - Derivation drv; - drv.name = "simple-derivation"; - drv.inputSrcs = { - store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"), - }; - drv.inputDrvs = { - .map = { - { - store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"), - { - .value = { - "cat", - "dog", - }, - }, - }, - }, - }; - drv.platform = "wasm-sel4"; - drv.builder = "foo"; - drv.args = { - "bar", - "baz", - }; - drv.env = { - { - "BIG_BAD", - "WOLF", - }, - }; - return drv; -} - -TEST_JSON(DerivationTest, simple, - R"({ - "name": "simple-derivation", - "inputSrcs": [ - "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1" - ], - "inputDrvs": { - "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": { - "dynamicOutputs": {}, - "outputs": [ - "cat", - "dog" - ] - } - }, - "system": "wasm-sel4", - "builder": "foo", - "args": [ - "bar", - "baz" - ], - "env": { - "BIG_BAD": "WOLF" - }, - "outputs": {} - })", - makeSimpleDrv(*store)) - -TEST_ATERM(DerivationTest, simple, - R"(Derive([],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",["cat","dog"])],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")]))", - makeSimpleDrv(*store), - "simple-derivation") - -Derivation makeDynDepDerivation(const Store & store) { - Derivation drv; - drv.name = "dyn-dep-derivation"; - drv.inputSrcs = { - store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"), - }; - drv.inputDrvs = { - .map = { - { - store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"), - DerivedPathMap::ChildNode { - .value = { - "cat", - "dog", - }, - .childMap = { - { - "cat", - DerivedPathMap::ChildNode { - .value = { - "kitten", - }, - }, - }, - { - "goose", - DerivedPathMap::ChildNode { - .value = { - "gosling", - }, - }, - }, - }, - }, - }, - }, - }; - drv.platform = "wasm-sel4"; - drv.builder = "foo"; - drv.args = { - "bar", - "baz", - }; - drv.env = { - { - "BIG_BAD", - "WOLF", - }, - }; - return drv; -} - -TEST_JSON(DynDerivationTest, dynDerivationDeps, - R"({ - "name": "dyn-dep-derivation", - "inputSrcs": [ - "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1" - ], - "inputDrvs": { - "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": { - "dynamicOutputs": { - "cat": { - "dynamicOutputs": {}, - "outputs": ["kitten"] - }, - "goose": { - "dynamicOutputs": {}, - "outputs": ["gosling"] - } - }, - "outputs": [ - "cat", - "dog" - ] - } - }, - "system": "wasm-sel4", - "builder": "foo", - "args": [ - "bar", - "baz" - ], - "env": { - "BIG_BAD": "WOLF" - }, - "outputs": {} - })", - makeDynDepDerivation(*store)) - -TEST_ATERM(DynDerivationTest, dynDerivationDeps, - R"(DrvWithVersion("xp-dyn-drv",[],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",(["cat","dog"],[("cat",["kitten"]),("goose",["gosling"])]))],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")]))", - makeDynDepDerivation(*store), - "dyn-dep-derivation") - -#undef TEST_JSON -#undef TEST_ATERM - -} diff --git a/src/libstore/tests/derived-path.cc b/src/libstore/tests/derived-path.cc deleted file mode 100644 index 3fa3c0801..000000000 --- a/src/libstore/tests/derived-path.cc +++ /dev/null @@ -1,153 +0,0 @@ -#include - -#include -#include -#include - -#include "tests/derived-path.hh" -#include "tests/libstore.hh" - -namespace rc { -using namespace nix; - -Gen Arbitrary::arbitrary() -{ - return gen::just(DerivedPath::Opaque { - .path = *gen::arbitrary(), - }); -} - -Gen Arbitrary::arbitrary() -{ - return gen::just(SingleDerivedPath::Built { - .drvPath = make_ref(*gen::arbitrary()), - .output = (*gen::arbitrary()).name, - }); -} - -Gen Arbitrary::arbitrary() -{ - return gen::just(DerivedPath::Built { - .drvPath = make_ref(*gen::arbitrary()), - .outputs = *gen::arbitrary(), - }); -} - -Gen Arbitrary::arbitrary() -{ - switch (*gen::inRange(0, std::variant_size_v)) { - case 0: - return gen::just(*gen::arbitrary()); - case 1: - return gen::just(*gen::arbitrary()); - default: - assert(false); - } -} - -Gen Arbitrary::arbitrary() -{ - switch (*gen::inRange(0, std::variant_size_v)) { - case 0: - return gen::just(*gen::arbitrary()); - case 1: - return gen::just(*gen::arbitrary()); - default: - assert(false); - } -} - -} - -namespace nix { - -class DerivedPathTest : public LibStoreTest -{ -}; - -/** - * Round trip (string <-> data structure) test for - * `DerivedPath::Opaque`. - */ -TEST_F(DerivedPathTest, opaque) { - std::string_view opaque = "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x"; - auto elem = DerivedPath::parse(*store, opaque); - auto * p = std::get_if(&elem); - ASSERT_TRUE(p); - ASSERT_EQ(p->path, store->parseStorePath(opaque)); - ASSERT_EQ(elem.to_string(*store), opaque); -} - -/** - * Round trip (string <-> data structure) test for a simpler - * `DerivedPath::Built`. - */ -TEST_F(DerivedPathTest, built_opaque) { - std::string_view built = "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv^bar,foo"; - auto elem = DerivedPath::parse(*store, built); - auto * p = std::get_if(&elem); - ASSERT_TRUE(p); - ASSERT_EQ(p->outputs, ((OutputsSpec) OutputsSpec::Names { "foo", "bar" })); - ASSERT_EQ(*p->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque { - .path = store->parseStorePath(built.substr(0, 49)), - })); - ASSERT_EQ(elem.to_string(*store), built); -} - -/** - * Round trip (string <-> data structure) test for a more complex, - * inductive `DerivedPath::Built`. - */ -TEST_F(DerivedPathTest, built_built) { - /** - * We set these in tests rather than the regular globals so we don't have - * to worry about race conditions if the tests run concurrently. - */ - ExperimentalFeatureSettings mockXpSettings; - mockXpSettings.set("experimental-features", "dynamic-derivations ca-derivations"); - - std::string_view built = "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv^foo^bar,baz"; - auto elem = DerivedPath::parse(*store, built, mockXpSettings); - auto * p = std::get_if(&elem); - ASSERT_TRUE(p); - ASSERT_EQ(p->outputs, ((OutputsSpec) OutputsSpec::Names { "bar", "baz" })); - auto * drvPath = std::get_if(&*p->drvPath); - ASSERT_TRUE(drvPath); - ASSERT_EQ(drvPath->output, "foo"); - ASSERT_EQ(*drvPath->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque { - .path = store->parseStorePath(built.substr(0, 49)), - })); - ASSERT_EQ(elem.to_string(*store), built); -} - -/** - * Without the right experimental features enabled, we cannot parse a - * complex inductive derived path. - */ -TEST_F(DerivedPathTest, built_built_xp) { - ASSERT_THROW( - DerivedPath::parse(*store, "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv^foo^bar,baz"), - MissingExperimentalFeature); -} - -#ifndef COVERAGE - -RC_GTEST_FIXTURE_PROP( - DerivedPathTest, - prop_legacy_round_rip, - (const DerivedPath & o)) -{ - RC_ASSERT(o == DerivedPath::parseLegacy(*store, o.to_string_legacy(*store))); -} - -RC_GTEST_FIXTURE_PROP( - DerivedPathTest, - prop_round_rip, - (const DerivedPath & o)) -{ - RC_ASSERT(o == DerivedPath::parse(*store, o.to_string(*store))); -} - -#endif - -} diff --git a/src/libstore/tests/derived-path.hh b/src/libstore/tests/derived-path.hh deleted file mode 100644 index 98d61f228..000000000 --- a/src/libstore/tests/derived-path.hh +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once -///@file - -#include - -#include - -#include "tests/path.hh" -#include "tests/outputs-spec.hh" - -namespace rc { -using namespace nix; - -template<> -struct Arbitrary { - static Gen arbitrary(); -}; - -template<> -struct Arbitrary { - static Gen arbitrary(); -}; - -template<> -struct Arbitrary { - static Gen arbitrary(); -}; - -template<> -struct Arbitrary { - static Gen arbitrary(); -}; - -template<> -struct Arbitrary { - static Gen arbitrary(); -}; - -} diff --git a/src/libstore/tests/downstream-placeholder.cc b/src/libstore/tests/downstream-placeholder.cc deleted file mode 100644 index fd29530ac..000000000 --- a/src/libstore/tests/downstream-placeholder.cc +++ /dev/null @@ -1,41 +0,0 @@ -#include - -#include "downstream-placeholder.hh" - -namespace nix { - -TEST(DownstreamPlaceholder, unknownCaOutput) { - /** - * We set these in tests rather than the regular globals so we don't have - * to worry about race conditions if the tests run concurrently. - */ - ExperimentalFeatureSettings mockXpSettings; - mockXpSettings.set("experimental-features", "ca-derivations"); - - ASSERT_EQ( - DownstreamPlaceholder::unknownCaOutput( - StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv" }, - "out", - mockXpSettings).render(), - "/0c6rn30q4frawknapgwq386zq358m8r6msvywcvc89n6m5p2dgbz"); -} - -TEST(DownstreamPlaceholder, unknownDerivation) { - /** - * Same reason as above - */ - ExperimentalFeatureSettings mockXpSettings; - mockXpSettings.set("experimental-features", "dynamic-derivations ca-derivations"); - - ASSERT_EQ( - DownstreamPlaceholder::unknownDerivation( - DownstreamPlaceholder::unknownCaOutput( - StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv.drv" }, - "out", - mockXpSettings), - "out", - mockXpSettings).render(), - "/0gn6agqxjyyalf0dpihgyf49xq5hqxgw100f0wydnj6yqrhqsb3w"); -} - -} diff --git a/src/libstore/tests/libstore.hh b/src/libstore/tests/libstore.hh deleted file mode 100644 index ef93457b5..000000000 --- a/src/libstore/tests/libstore.hh +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -///@file - -#include -#include - -#include "store-api.hh" - -namespace nix { - -class LibStoreTest : public ::testing::Test { - public: - static void SetUpTestSuite() { - initLibStore(); - } - - protected: - LibStoreTest() - : store(openStore("dummy://")) - { } - - ref store; -}; - - -} /* namespace nix */ diff --git a/src/libstore/tests/local.mk b/src/libstore/tests/local.mk deleted file mode 100644 index 03becc7d1..000000000 --- a/src/libstore/tests/local.mk +++ /dev/null @@ -1,29 +0,0 @@ -check: libstore-tests-exe_RUN - -programs += libstore-tests-exe - -libstore-tests-exe_NAME = libnixstore-tests - -libstore-tests-exe_DIR := $(d) - -libstore-tests-exe_INSTALL_DIR := - -libstore-tests-exe_LIBS = libstore-tests - -libstore-tests-exe_LDFLAGS := $(GTEST_LIBS) - -libraries += libstore-tests - -libstore-tests_NAME = libnixstore-tests - -libstore-tests_DIR := $(d) - -libstore-tests_INSTALL_DIR := - -libstore-tests_SOURCES := $(wildcard $(d)/*.cc) - -libstore-tests_CXXFLAGS += -I src/libstore -I src/libutil - -libstore-tests_LIBS = libutil-tests libstore libutil - -libstore-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) diff --git a/src/libstore/tests/machines.cc b/src/libstore/tests/machines.cc deleted file mode 100644 index f51052b14..000000000 --- a/src/libstore/tests/machines.cc +++ /dev/null @@ -1,169 +0,0 @@ -#include "machines.hh" -#include "globals.hh" - -#include - -using testing::Contains; -using testing::ElementsAre; -using testing::EndsWith; -using testing::Eq; -using testing::Field; -using testing::SizeIs; - -using nix::absPath; -using nix::FormatError; -using nix::getMachines; -using nix::Machine; -using nix::Machines; -using nix::pathExists; -using nix::Settings; -using nix::settings; - -class Environment : public ::testing::Environment { - public: - void SetUp() override { settings.thisSystem = "TEST_ARCH-TEST_OS"; } -}; - -testing::Environment* const foo_env = - testing::AddGlobalTestEnvironment(new Environment); - -TEST(machines, getMachinesWithEmptyBuilders) { - settings.builders = ""; - Machines actual = getMachines(); - ASSERT_THAT(actual, SizeIs(0)); -} - -TEST(machines, getMachinesUriOnly) { - settings.builders = "nix@scratchy.labs.cs.uu.nl"; - Machines actual = getMachines(); - ASSERT_THAT(actual, SizeIs(1)); - EXPECT_THAT(actual[0], Field(&Machine::storeUri, Eq("ssh://nix@scratchy.labs.cs.uu.nl"))); - EXPECT_THAT(actual[0], Field(&Machine::systemTypes, ElementsAre("TEST_ARCH-TEST_OS"))); - EXPECT_THAT(actual[0], Field(&Machine::sshKey, SizeIs(0))); - EXPECT_THAT(actual[0], Field(&Machine::maxJobs, Eq(1))); - EXPECT_THAT(actual[0], Field(&Machine::speedFactor, Eq(1))); - EXPECT_THAT(actual[0], Field(&Machine::supportedFeatures, SizeIs(0))); - EXPECT_THAT(actual[0], Field(&Machine::mandatoryFeatures, SizeIs(0))); - EXPECT_THAT(actual[0], Field(&Machine::sshPublicHostKey, SizeIs(0))); -} - -TEST(machines, getMachinesDefaults) { - settings.builders = "nix@scratchy.labs.cs.uu.nl - - - - - - -"; - Machines actual = getMachines(); - ASSERT_THAT(actual, SizeIs(1)); - EXPECT_THAT(actual[0], Field(&Machine::storeUri, Eq("ssh://nix@scratchy.labs.cs.uu.nl"))); - EXPECT_THAT(actual[0], Field(&Machine::systemTypes, ElementsAre("TEST_ARCH-TEST_OS"))); - EXPECT_THAT(actual[0], Field(&Machine::sshKey, SizeIs(0))); - EXPECT_THAT(actual[0], Field(&Machine::maxJobs, Eq(1))); - EXPECT_THAT(actual[0], Field(&Machine::speedFactor, Eq(1))); - EXPECT_THAT(actual[0], Field(&Machine::supportedFeatures, SizeIs(0))); - EXPECT_THAT(actual[0], Field(&Machine::mandatoryFeatures, SizeIs(0))); - EXPECT_THAT(actual[0], Field(&Machine::sshPublicHostKey, SizeIs(0))); -} - -TEST(machines, getMachinesWithNewLineSeparator) { - settings.builders = "nix@scratchy.labs.cs.uu.nl\nnix@itchy.labs.cs.uu.nl"; - Machines actual = getMachines(); - ASSERT_THAT(actual, SizeIs(2)); - EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@scratchy.labs.cs.uu.nl")))); - EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@itchy.labs.cs.uu.nl")))); -} - -TEST(machines, getMachinesWithSemicolonSeparator) { - settings.builders = "nix@scratchy.labs.cs.uu.nl ; nix@itchy.labs.cs.uu.nl"; - Machines actual = getMachines(); - EXPECT_THAT(actual, SizeIs(2)); - EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@scratchy.labs.cs.uu.nl")))); - EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@itchy.labs.cs.uu.nl")))); -} - -TEST(machines, getMachinesWithCorrectCompleteSingleBuilder) { - settings.builders = "nix@scratchy.labs.cs.uu.nl i686-linux " - "/home/nix/.ssh/id_scratchy_auto 8 3 kvm " - "benchmark SSH+HOST+PUBLIC+KEY+BASE64+ENCODED=="; - Machines actual = getMachines(); - ASSERT_THAT(actual, SizeIs(1)); - EXPECT_THAT(actual[0], Field(&Machine::storeUri, EndsWith("nix@scratchy.labs.cs.uu.nl"))); - EXPECT_THAT(actual[0], Field(&Machine::systemTypes, ElementsAre("i686-linux"))); - EXPECT_THAT(actual[0], Field(&Machine::sshKey, Eq("/home/nix/.ssh/id_scratchy_auto"))); - EXPECT_THAT(actual[0], Field(&Machine::maxJobs, Eq(8))); - EXPECT_THAT(actual[0], Field(&Machine::speedFactor, Eq(3))); - EXPECT_THAT(actual[0], Field(&Machine::supportedFeatures, ElementsAre("kvm"))); - EXPECT_THAT(actual[0], Field(&Machine::mandatoryFeatures, ElementsAre("benchmark"))); - EXPECT_THAT(actual[0], Field(&Machine::sshPublicHostKey, Eq("SSH+HOST+PUBLIC+KEY+BASE64+ENCODED=="))); -} - -TEST(machines, - getMachinesWithCorrectCompleteSingleBuilderWithTabColumnDelimiter) { - settings.builders = - "nix@scratchy.labs.cs.uu.nl\ti686-linux\t/home/nix/.ssh/" - "id_scratchy_auto\t8\t3\tkvm\tbenchmark\tSSH+HOST+PUBLIC+" - "KEY+BASE64+ENCODED=="; - Machines actual = getMachines(); - ASSERT_THAT(actual, SizeIs(1)); - EXPECT_THAT(actual[0], Field(&Machine::storeUri, EndsWith("nix@scratchy.labs.cs.uu.nl"))); - EXPECT_THAT(actual[0], Field(&Machine::systemTypes, ElementsAre("i686-linux"))); - EXPECT_THAT(actual[0], Field(&Machine::sshKey, Eq("/home/nix/.ssh/id_scratchy_auto"))); - EXPECT_THAT(actual[0], Field(&Machine::maxJobs, Eq(8))); - EXPECT_THAT(actual[0], Field(&Machine::speedFactor, Eq(3))); - EXPECT_THAT(actual[0], Field(&Machine::supportedFeatures, ElementsAre("kvm"))); - EXPECT_THAT(actual[0], Field(&Machine::mandatoryFeatures, ElementsAre("benchmark"))); - EXPECT_THAT(actual[0], Field(&Machine::sshPublicHostKey, Eq("SSH+HOST+PUBLIC+KEY+BASE64+ENCODED=="))); -} - -TEST(machines, getMachinesWithMultiOptions) { - settings.builders = "nix@scratchy.labs.cs.uu.nl Arch1,Arch2 - - - " - "SupportedFeature1,SupportedFeature2 " - "MandatoryFeature1,MandatoryFeature2"; - Machines actual = getMachines(); - ASSERT_THAT(actual, SizeIs(1)); - EXPECT_THAT(actual[0], Field(&Machine::storeUri, EndsWith("nix@scratchy.labs.cs.uu.nl"))); - EXPECT_THAT(actual[0], Field(&Machine::systemTypes, ElementsAre("Arch1", "Arch2"))); - EXPECT_THAT(actual[0], Field(&Machine::supportedFeatures, ElementsAre("SupportedFeature1", "SupportedFeature2"))); - EXPECT_THAT(actual[0], Field(&Machine::mandatoryFeatures, ElementsAre("MandatoryFeature1", "MandatoryFeature2"))); -} - -TEST(machines, getMachinesWithIncorrectFormat) { - settings.builders = "nix@scratchy.labs.cs.uu.nl - - eight"; - EXPECT_THROW(getMachines(), FormatError); - settings.builders = "nix@scratchy.labs.cs.uu.nl - - -1"; - EXPECT_THROW(getMachines(), FormatError); - settings.builders = "nix@scratchy.labs.cs.uu.nl - - 8 three"; - EXPECT_THROW(getMachines(), FormatError); - settings.builders = "nix@scratchy.labs.cs.uu.nl - - 8 -3"; - EXPECT_THROW(getMachines(), FormatError); - settings.builders = "nix@scratchy.labs.cs.uu.nl - - 8 3 - - BAD_BASE64"; - EXPECT_THROW(getMachines(), FormatError); -} - -TEST(machines, getMachinesWithCorrectFileReference) { - auto path = absPath("src/libstore/tests/test-data/machines.valid"); - ASSERT_TRUE(pathExists(path)); - - settings.builders = std::string("@") + path; - Machines actual = getMachines(); - ASSERT_THAT(actual, SizeIs(3)); - EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@scratchy.labs.cs.uu.nl")))); - EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@itchy.labs.cs.uu.nl")))); - EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@poochie.labs.cs.uu.nl")))); -} - -TEST(machines, getMachinesWithCorrectFileReferenceToEmptyFile) { - auto path = "/dev/null"; - ASSERT_TRUE(pathExists(path)); - - settings.builders = std::string("@") + path; - Machines actual = getMachines(); - ASSERT_THAT(actual, SizeIs(0)); -} - -TEST(machines, getMachinesWithIncorrectFileReference) { - settings.builders = std::string("@") + absPath("/not/a/file"); - Machines actual = getMachines(); - ASSERT_THAT(actual, SizeIs(0)); -} - -TEST(machines, getMachinesWithCorrectFileReferenceToIncorrectFile) { - settings.builders = std::string("@") + absPath("src/libstore/tests/test-data/machines.bad_format"); - EXPECT_THROW(getMachines(), FormatError); -} diff --git a/src/libstore/tests/nar-info-disk-cache.cc b/src/libstore/tests/nar-info-disk-cache.cc deleted file mode 100644 index b4bdb8329..000000000 --- a/src/libstore/tests/nar-info-disk-cache.cc +++ /dev/null @@ -1,123 +0,0 @@ -#include "nar-info-disk-cache.hh" - -#include -#include -#include "sqlite.hh" -#include - - -namespace nix { - -TEST(NarInfoDiskCacheImpl, create_and_read) { - // This is a large single test to avoid some setup overhead. - - int prio = 12345; - bool wantMassQuery = true; - - Path tmpDir = createTempDir(); - AutoDelete delTmpDir(tmpDir); - Path dbPath(tmpDir + "/test-narinfo-disk-cache.sqlite"); - - int savedId; - int barId; - SQLite db; - SQLiteStmt getIds; - - { - auto cache = getTestNarInfoDiskCache(dbPath); - - // Set up "background noise" and check that different caches receive different ids - { - auto bc1 = cache->createCache("https://bar", "/nix/storedir", wantMassQuery, prio); - auto bc2 = cache->createCache("https://xyz", "/nix/storedir", false, 12); - ASSERT_NE(bc1, bc2); - barId = bc1; - } - - // Check that the fields are saved and returned correctly. This does not test - // the select statement yet, because of in-memory caching. - savedId = cache->createCache("http://foo", "/nix/storedir", wantMassQuery, prio);; - { - auto r = cache->upToDateCacheExists("http://foo"); - ASSERT_TRUE(r); - ASSERT_EQ(r->priority, prio); - ASSERT_EQ(r->wantMassQuery, wantMassQuery); - ASSERT_EQ(savedId, r->id); - } - - // We're going to pay special attention to the id field because we had a bug - // that changed it. - db = SQLite(dbPath); - getIds.create(db, "select id from BinaryCaches where url = 'http://foo'"); - - { - auto q(getIds.use()); - ASSERT_TRUE(q.next()); - ASSERT_EQ(savedId, q.getInt(0)); - ASSERT_FALSE(q.next()); - } - - // Pretend that the caches are older, but keep one up to date, as "background noise" - db.exec("update BinaryCaches set timestamp = timestamp - 1 - 7 * 24 * 3600 where url <> 'https://xyz';"); - - // This shows that the in-memory cache works - { - auto r = cache->upToDateCacheExists("http://foo"); - ASSERT_TRUE(r); - ASSERT_EQ(r->priority, prio); - ASSERT_EQ(r->wantMassQuery, wantMassQuery); - } - } - - { - // We can't clear the in-memory cache, so we use a new cache object. This is - // more realistic anyway. - auto cache2 = getTestNarInfoDiskCache(dbPath); - - { - auto r = cache2->upToDateCacheExists("http://foo"); - ASSERT_FALSE(r); - } - - // "Update", same data, check that the id number is reused - cache2->createCache("http://foo", "/nix/storedir", wantMassQuery, prio); - - { - auto r = cache2->upToDateCacheExists("http://foo"); - ASSERT_TRUE(r); - ASSERT_EQ(r->priority, prio); - ASSERT_EQ(r->wantMassQuery, wantMassQuery); - ASSERT_EQ(r->id, savedId); - } - - { - auto q(getIds.use()); - ASSERT_TRUE(q.next()); - auto currentId = q.getInt(0); - ASSERT_FALSE(q.next()); - ASSERT_EQ(currentId, savedId); - } - - // Check that the fields can be modified, and the id remains the same - { - auto r0 = cache2->upToDateCacheExists("https://bar"); - ASSERT_FALSE(r0); - - cache2->createCache("https://bar", "/nix/storedir", !wantMassQuery, prio + 10); - auto r = cache2->upToDateCacheExists("https://bar"); - ASSERT_EQ(r->wantMassQuery, !wantMassQuery); - ASSERT_EQ(r->priority, prio + 10); - ASSERT_EQ(r->id, barId); - } - - // // Force update (no use case yet; we only retrieve cache metadata when stale based on timestamp) - // { - // cache2->createCache("https://bar", "/nix/storedir", wantMassQuery, prio + 20); - // auto r = cache2->upToDateCacheExists("https://bar"); - // ASSERT_EQ(r->wantMassQuery, wantMassQuery); - // ASSERT_EQ(r->priority, prio + 20); - // } - } -} - -} diff --git a/src/libstore/tests/outputs-spec.cc b/src/libstore/tests/outputs-spec.cc deleted file mode 100644 index 952945185..000000000 --- a/src/libstore/tests/outputs-spec.cc +++ /dev/null @@ -1,239 +0,0 @@ -#include "outputs-spec.hh" - -#include -#include -#include - -namespace nix { - -#ifndef NDEBUG -TEST(OutputsSpec, no_empty_names) { - ASSERT_DEATH(OutputsSpec::Names { std::set { } }, ""); -} -#endif - -#define TEST_DONT_PARSE(NAME, STR) \ - TEST(OutputsSpec, bad_ ## NAME) { \ - std::optional OutputsSpecOpt = \ - OutputsSpec::parseOpt(STR); \ - ASSERT_FALSE(OutputsSpecOpt); \ - } - -TEST_DONT_PARSE(empty, "") -TEST_DONT_PARSE(garbage, "&*()") -TEST_DONT_PARSE(double_star, "**") -TEST_DONT_PARSE(star_first, "*,foo") -TEST_DONT_PARSE(star_second, "foo,*") - -#undef TEST_DONT_PARSE - -TEST(OutputsSpec, all) { - std::string_view str = "*"; - OutputsSpec expected = OutputsSpec::All { }; - ASSERT_EQ(OutputsSpec::parse(str), expected); - ASSERT_EQ(expected.to_string(), str); -} - -TEST(OutputsSpec, names_out) { - std::string_view str = "out"; - OutputsSpec expected = OutputsSpec::Names { "out" }; - ASSERT_EQ(OutputsSpec::parse(str), expected); - ASSERT_EQ(expected.to_string(), str); -} - -TEST(OutputsSpec, names_underscore) { - std::string_view str = "a_b"; - OutputsSpec expected = OutputsSpec::Names { "a_b" }; - ASSERT_EQ(OutputsSpec::parse(str), expected); - ASSERT_EQ(expected.to_string(), str); -} - -TEST(OutputsSpec, names_numberic) { - std::string_view str = "01"; - OutputsSpec expected = OutputsSpec::Names { "01" }; - ASSERT_EQ(OutputsSpec::parse(str), expected); - ASSERT_EQ(expected.to_string(), str); -} - -TEST(OutputsSpec, names_out_bin) { - OutputsSpec expected = OutputsSpec::Names { "out", "bin" }; - ASSERT_EQ(OutputsSpec::parse("out,bin"), expected); - // N.B. This normalization is OK. - ASSERT_EQ(expected.to_string(), "bin,out"); -} - -#define TEST_SUBSET(X, THIS, THAT) \ - X((OutputsSpec { THIS }).isSubsetOf(THAT)); - -TEST(OutputsSpec, subsets_all_all) { - TEST_SUBSET(ASSERT_TRUE, OutputsSpec::All { }, OutputsSpec::All { }); -} - -TEST(OutputsSpec, subsets_names_all) { - TEST_SUBSET(ASSERT_TRUE, OutputsSpec::Names { "a" }, OutputsSpec::All { }); -} - -TEST(OutputsSpec, subsets_names_names_eq) { - TEST_SUBSET(ASSERT_TRUE, OutputsSpec::Names { "a" }, OutputsSpec::Names { "a" }); -} - -TEST(OutputsSpec, subsets_names_names_noneq) { - TEST_SUBSET(ASSERT_TRUE, OutputsSpec::Names { "a" }, (OutputsSpec::Names { "a", "b" })); -} - -TEST(OutputsSpec, not_subsets_all_names) { - TEST_SUBSET(ASSERT_FALSE, OutputsSpec::All { }, OutputsSpec::Names { "a" }); -} - -TEST(OutputsSpec, not_subsets_names_names) { - TEST_SUBSET(ASSERT_FALSE, (OutputsSpec::Names { "a", "b" }), (OutputsSpec::Names { "a" })); -} - -#undef TEST_SUBSET - -#define TEST_UNION(RES, THIS, THAT) \ - ASSERT_EQ(OutputsSpec { RES }, (OutputsSpec { THIS }).union_(THAT)); - -TEST(OutputsSpec, union_all_all) { - TEST_UNION(OutputsSpec::All { }, OutputsSpec::All { }, OutputsSpec::All { }); -} - -TEST(OutputsSpec, union_all_names) { - TEST_UNION(OutputsSpec::All { }, OutputsSpec::All { }, OutputsSpec::Names { "a" }); -} - -TEST(OutputsSpec, union_names_all) { - TEST_UNION(OutputsSpec::All { }, OutputsSpec::Names { "a" }, OutputsSpec::All { }); -} - -TEST(OutputsSpec, union_names_names) { - TEST_UNION((OutputsSpec::Names { "a", "b" }), OutputsSpec::Names { "a" }, OutputsSpec::Names { "b" }); -} - -#undef TEST_UNION - -#define TEST_DONT_PARSE(NAME, STR) \ - TEST(ExtendedOutputsSpec, bad_ ## NAME) { \ - std::optional extendedOutputsSpecOpt = \ - ExtendedOutputsSpec::parseOpt(STR); \ - ASSERT_FALSE(extendedOutputsSpecOpt); \ - } - -TEST_DONT_PARSE(carot_empty, "^") -TEST_DONT_PARSE(prefix_carot_empty, "foo^") -TEST_DONT_PARSE(garbage, "^&*()") -TEST_DONT_PARSE(double_star, "^**") -TEST_DONT_PARSE(star_first, "^*,foo") -TEST_DONT_PARSE(star_second, "^foo,*") - -#undef TEST_DONT_PARSE - -TEST(ExtendedOutputsSpec, defeault) { - std::string_view str = "foo"; - auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(str); - ASSERT_EQ(prefix, "foo"); - ExtendedOutputsSpec expected = ExtendedOutputsSpec::Default { }; - ASSERT_EQ(extendedOutputsSpec, expected); - ASSERT_EQ(std::string { prefix } + expected.to_string(), str); -} - -TEST(ExtendedOutputsSpec, all) { - std::string_view str = "foo^*"; - auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(str); - ASSERT_EQ(prefix, "foo"); - ExtendedOutputsSpec expected = OutputsSpec::All { }; - ASSERT_EQ(extendedOutputsSpec, expected); - ASSERT_EQ(std::string { prefix } + expected.to_string(), str); -} - -TEST(ExtendedOutputsSpec, out) { - std::string_view str = "foo^out"; - auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(str); - ASSERT_EQ(prefix, "foo"); - ExtendedOutputsSpec expected = OutputsSpec::Names { "out" }; - ASSERT_EQ(extendedOutputsSpec, expected); - ASSERT_EQ(std::string { prefix } + expected.to_string(), str); -} - -TEST(ExtendedOutputsSpec, out_bin) { - auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse("foo^out,bin"); - ASSERT_EQ(prefix, "foo"); - ExtendedOutputsSpec expected = OutputsSpec::Names { "out", "bin" }; - ASSERT_EQ(extendedOutputsSpec, expected); - ASSERT_EQ(std::string { prefix } + expected.to_string(), "foo^bin,out"); -} - -TEST(ExtendedOutputsSpec, many_carrot) { - auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse("foo^bar^out,bin"); - ASSERT_EQ(prefix, "foo^bar"); - ExtendedOutputsSpec expected = OutputsSpec::Names { "out", "bin" }; - ASSERT_EQ(extendedOutputsSpec, expected); - ASSERT_EQ(std::string { prefix } + expected.to_string(), "foo^bar^bin,out"); -} - - -#define TEST_JSON(TYPE, NAME, STR, VAL) \ - \ - TEST(TYPE, NAME ## _to_json) { \ - using nlohmann::literals::operator "" _json; \ - ASSERT_EQ( \ - STR ## _json, \ - ((nlohmann::json) TYPE { VAL })); \ - } \ - \ - TEST(TYPE, NAME ## _from_json) { \ - using nlohmann::literals::operator "" _json; \ - ASSERT_EQ( \ - TYPE { VAL }, \ - (STR ## _json).get()); \ - } - -TEST_JSON(OutputsSpec, all, R"(["*"])", OutputsSpec::All { }) -TEST_JSON(OutputsSpec, name, R"(["a"])", OutputsSpec::Names { "a" }) -TEST_JSON(OutputsSpec, names, R"(["a","b"])", (OutputsSpec::Names { "a", "b" })) - -TEST_JSON(ExtendedOutputsSpec, def, R"(null)", ExtendedOutputsSpec::Default { }) -TEST_JSON(ExtendedOutputsSpec, all, R"(["*"])", ExtendedOutputsSpec::Explicit { OutputsSpec::All { } }) -TEST_JSON(ExtendedOutputsSpec, name, R"(["a"])", ExtendedOutputsSpec::Explicit { OutputsSpec::Names { "a" } }) -TEST_JSON(ExtendedOutputsSpec, names, R"(["a","b"])", (ExtendedOutputsSpec::Explicit { OutputsSpec::Names { "a", "b" } })) - -#undef TEST_JSON - -} - -namespace rc { -using namespace nix; - -Gen Arbitrary::arbitrary() -{ - switch (*gen::inRange(0, std::variant_size_v)) { - case 0: - return gen::just((OutputsSpec) OutputsSpec::All { }); - case 1: - return gen::just((OutputsSpec) OutputsSpec::Names { - *gen::nonEmpty(gen::container(gen::map( - gen::arbitrary(), - [](StorePathName n) { return n.name; }))), - }); - default: - assert(false); - } -} - -} - -namespace nix { - -#ifndef COVERAGE - -RC_GTEST_PROP( - OutputsSpec, - prop_round_rip, - (const OutputsSpec & o)) -{ - RC_ASSERT(o == OutputsSpec::parse(o.to_string())); -} - -#endif - -} diff --git a/src/libstore/tests/outputs-spec.hh b/src/libstore/tests/outputs-spec.hh deleted file mode 100644 index ded331b33..000000000 --- a/src/libstore/tests/outputs-spec.hh +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -///@file - -#include - -#include - -#include - -namespace rc { -using namespace nix; - -template<> -struct Arbitrary { - static Gen arbitrary(); -}; - -} diff --git a/src/libstore/tests/path.cc b/src/libstore/tests/path.cc deleted file mode 100644 index 5a84d646c..000000000 --- a/src/libstore/tests/path.cc +++ /dev/null @@ -1,162 +0,0 @@ -#include - -#include -#include -#include - -#include "path-regex.hh" -#include "store-api.hh" - -#include "tests/hash.hh" -#include "tests/libstore.hh" -#include "tests/path.hh" - -namespace nix { - -#define STORE_DIR "/nix/store/" -#define HASH_PART "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q" - -class StorePathTest : public LibStoreTest -{ -}; - -static std::regex nameRegex { std::string { nameRegexStr } }; - -#define TEST_DONT_PARSE(NAME, STR) \ - TEST_F(StorePathTest, bad_ ## NAME) { \ - std::string_view str = \ - STORE_DIR HASH_PART "-" STR; \ - ASSERT_THROW( \ - store->parseStorePath(str), \ - BadStorePath); \ - std::string name { STR }; \ - EXPECT_FALSE(std::regex_match(name, nameRegex)); \ - } - -TEST_DONT_PARSE(empty, "") -TEST_DONT_PARSE(garbage, "&*()") -TEST_DONT_PARSE(double_star, "**") -TEST_DONT_PARSE(star_first, "*,foo") -TEST_DONT_PARSE(star_second, "foo,*") -TEST_DONT_PARSE(bang, "foo!o") -TEST_DONT_PARSE(dotfile, ".gitignore") - -#undef TEST_DONT_PARSE - -#define TEST_DO_PARSE(NAME, STR) \ - TEST_F(StorePathTest, good_ ## NAME) { \ - std::string_view str = \ - STORE_DIR HASH_PART "-" STR; \ - auto p = store->parseStorePath(str); \ - std::string name { p.name() }; \ - EXPECT_TRUE(std::regex_match(name, nameRegex)); \ - } - -// 0-9 a-z A-Z + - . _ ? = - -TEST_DO_PARSE(numbers, "02345") -TEST_DO_PARSE(lower_case, "foo") -TEST_DO_PARSE(upper_case, "FOO") -TEST_DO_PARSE(plus, "foo+bar") -TEST_DO_PARSE(dash, "foo-dev") -TEST_DO_PARSE(underscore, "foo_bar") -TEST_DO_PARSE(period, "foo.txt") -TEST_DO_PARSE(question_mark, "foo?why") -TEST_DO_PARSE(equals_sign, "foo=foo") - -#undef TEST_DO_PARSE - -// For rapidcheck -void showValue(const StorePath & p, std::ostream & os) { - os << p.to_string(); -} - -} - -namespace rc { -using namespace nix; - -Gen Arbitrary::arbitrary() -{ - auto len = *gen::inRange( - 1, - StorePath::MaxPathLen - std::string_view { HASH_PART }.size()); - - std::string pre; - pre.reserve(len); - - for (size_t c = 0; c < len; ++c) { - switch (auto i = *gen::inRange(0, 10 + 2 * 26 + 6)) { - case 0 ... 9: - pre += '0' + i; - case 10 ... 35: - pre += 'A' + (i - 10); - break; - case 36 ... 61: - pre += 'a' + (i - 36); - break; - case 62: - pre += '+'; - break; - case 63: - pre += '-'; - break; - case 64: - // names aren't permitted to start with a period, - // so just fall through to the next case here - if (c != 0) { - pre += '.'; - break; - } - case 65: - pre += '_'; - break; - case 66: - pre += '?'; - break; - case 67: - pre += '='; - break; - default: - assert(false); - } - } - - return gen::just(StorePathName { - .name = std::move(pre), - }); -} - -Gen Arbitrary::arbitrary() -{ - return gen::just(StorePath { - *gen::arbitrary(), - (*gen::arbitrary()).name, - }); -} - -} // namespace rc - -namespace nix { - -#ifndef COVERAGE - -RC_GTEST_FIXTURE_PROP( - StorePathTest, - prop_regex_accept, - (const StorePath & p)) -{ - RC_ASSERT(std::regex_match(std::string { p.name() }, nameRegex)); -} - -RC_GTEST_FIXTURE_PROP( - StorePathTest, - prop_round_rip, - (const StorePath & p)) -{ - RC_ASSERT(p == store->parseStorePath(store->printStorePath(p))); -} - -#endif - -} diff --git a/src/libstore/tests/path.hh b/src/libstore/tests/path.hh deleted file mode 100644 index 21cb62310..000000000 --- a/src/libstore/tests/path.hh +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once -///@file - -#include - -#include - -namespace nix { - -struct StorePathName { - std::string name; -}; - -} - -namespace rc { -using namespace nix; - -template<> -struct Arbitrary { - static Gen arbitrary(); -}; - -template<> -struct Arbitrary { - static Gen arbitrary(); -}; - -} diff --git a/src/libstore/tests/references.cc b/src/libstore/tests/references.cc deleted file mode 100644 index d91d1cedd..000000000 --- a/src/libstore/tests/references.cc +++ /dev/null @@ -1,45 +0,0 @@ -#include "references.hh" - -#include - -namespace nix { - -TEST(references, scan) -{ - std::string hash1 = "dc04vv14dak1c1r48qa0m23vr9jy8sm0"; - std::string hash2 = "zc842j0rz61mjsp3h3wp5ly71ak6qgdn"; - - { - RefScanSink scanner(StringSet{hash1}); - auto s = "foobar"; - scanner(s); - ASSERT_EQ(scanner.getResult(), StringSet{}); - } - - { - RefScanSink scanner(StringSet{hash1}); - auto s = "foobar" + hash1 + "xyzzy"; - scanner(s); - ASSERT_EQ(scanner.getResult(), StringSet{hash1}); - } - - { - RefScanSink scanner(StringSet{hash1, hash2}); - auto s = "foobar" + hash1 + "xyzzy" + hash2; - scanner(((std::string_view) s).substr(0, 10)); - scanner(((std::string_view) s).substr(10, 5)); - scanner(((std::string_view) s).substr(15, 5)); - scanner(((std::string_view) s).substr(20)); - ASSERT_EQ(scanner.getResult(), StringSet({hash1, hash2})); - } - - { - RefScanSink scanner(StringSet{hash1, hash2}); - auto s = "foobar" + hash1 + "xyzzy" + hash2; - for (auto & i : s) - scanner(std::string(1, i)); - ASSERT_EQ(scanner.getResult(), StringSet({hash1, hash2})); - } -} - -} diff --git a/src/libstore/tests/test-data/machines.bad_format b/src/libstore/tests/test-data/machines.bad_format deleted file mode 100644 index 7255a1216..000000000 --- a/src/libstore/tests/test-data/machines.bad_format +++ /dev/null @@ -1 +0,0 @@ -nix@scratchy.labs.cs.uu.nl - - eight diff --git a/src/libstore/tests/test-data/machines.valid b/src/libstore/tests/test-data/machines.valid deleted file mode 100644 index 1a6c8017c..000000000 --- a/src/libstore/tests/test-data/machines.valid +++ /dev/null @@ -1,3 +0,0 @@ -nix@scratchy.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 8 1 kvm -nix@itchy.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 8 2 -nix@poochie.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 1 2 kvm benchmark c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFDQVFDWWV5R1laNTNzd1VjMUZNSHBWL1BCcXlKaFR5S1JoRkpWWVRpRHlQN2h5c1JGa0w4VDlLOGdhL2Y2L3c3QjN2SjNHSFRIUFkybENiUEdZbGNLd2h6M2ZRbFNNOEViNi95b3ZLajdvM1FsMEx5Y0dzdGJvRmcwWkZKNldncUxsR0ltS0NobUlxOGZ3TW5ZTWUxbnRQeTBUZFZjSU1tOTV3YzF3SjBMd2c3cEVMRmtHazdkeTVvYnM4a3lGZ0pORDVRSmFwQWJjeWp4Z1QzdzdMcktNZ2xzeWhhd01JNVpkMGZsQTVudW5OZ3pid3plYVhLaUsyTW0vdGJXYTU1YTd4QmNYdHpIZGlPSWdSajJlRWxaMGh5bk10YjBmcklsdmxIcEtLaVFaZ3pQdCtIVXQ2bXpRMkRVME52MGYyYnNSU0krOGpJU2pQcmdlcVVHRldMUzVIUTg2N2xSMlpiaWtyclhZNTdqbVFEZk5DRHY1VFBHZU9UekFEd2pjMDc2aFZ3VFJCd3VTZFhtaWNxTS95b3lrWitkV1dnZ25MenE5QU1tdlNZcDhmZkZDcS9CSDBZNUFXWTFHay9vS3hMVTNaOWt3ZDd2UWNFQWFCQ2dxdnVZRGdTaHE1RlhndDM3OVZESWtEL05ZSTg2QXVvajVDRmVNTzlRM2pJSlRadlh6c1VldjVoSnA2djcxSVh5ODVtbTY5R20zcXdicVE1SjVQZDU1Um56SitpaW5BNjZxTEFSc0Y4amNsSnd5ekFXclBoYU9DRVY2bjVMeVhVazhzMW9EVVR4V1pWN25rVkFTbHJ0MllGcjN5dzdjRTRXQVhsemhHcDhocmdLMVVkMUlyeDVnZWRaSnBWcy9uNWVybmJFMUxmb2x5UHUvRUFIWlh6VGd4dHVDUFNobXc9PQo= diff --git a/src/libutil/tests/canon-path.cc b/src/libutil/tests/canon-path.cc deleted file mode 100644 index fc94ccc3d..000000000 --- a/src/libutil/tests/canon-path.cc +++ /dev/null @@ -1,162 +0,0 @@ -#include "canon-path.hh" - -#include - -namespace nix { - - TEST(CanonPath, basic) { - { - CanonPath p("/"); - ASSERT_EQ(p.abs(), "/"); - ASSERT_EQ(p.rel(), ""); - ASSERT_EQ(p.baseName(), std::nullopt); - ASSERT_EQ(p.dirOf(), std::nullopt); - ASSERT_FALSE(p.parent()); - } - - { - CanonPath p("/foo//"); - ASSERT_EQ(p.abs(), "/foo"); - ASSERT_EQ(p.rel(), "foo"); - ASSERT_EQ(*p.baseName(), "foo"); - ASSERT_EQ(*p.dirOf(), ""); // FIXME: do we want this? - ASSERT_EQ(p.parent()->abs(), "/"); - } - - { - CanonPath p("foo/bar"); - ASSERT_EQ(p.abs(), "/foo/bar"); - ASSERT_EQ(p.rel(), "foo/bar"); - ASSERT_EQ(*p.baseName(), "bar"); - ASSERT_EQ(*p.dirOf(), "/foo"); - ASSERT_EQ(p.parent()->abs(), "/foo"); - } - - { - CanonPath p("foo//bar/"); - ASSERT_EQ(p.abs(), "/foo/bar"); - ASSERT_EQ(p.rel(), "foo/bar"); - ASSERT_EQ(*p.baseName(), "bar"); - ASSERT_EQ(*p.dirOf(), "/foo"); - } - } - - TEST(CanonPath, pop) { - CanonPath p("foo/bar/x"); - ASSERT_EQ(p.abs(), "/foo/bar/x"); - p.pop(); - ASSERT_EQ(p.abs(), "/foo/bar"); - p.pop(); - ASSERT_EQ(p.abs(), "/foo"); - p.pop(); - ASSERT_EQ(p.abs(), "/"); - } - - TEST(CanonPath, removePrefix) { - CanonPath p1("foo/bar"); - CanonPath p2("foo/bar/a/b/c"); - ASSERT_EQ(p2.removePrefix(p1).abs(), "/a/b/c"); - ASSERT_EQ(p1.removePrefix(p1).abs(), "/"); - ASSERT_EQ(p1.removePrefix(CanonPath("/")).abs(), "/foo/bar"); - } - - TEST(CanonPath, iter) { - { - CanonPath p("a//foo/bar//"); - std::vector ss; - for (auto & c : p) ss.push_back(c); - ASSERT_EQ(ss, std::vector({"a", "foo", "bar"})); - } - - { - CanonPath p("/"); - std::vector ss; - for (auto & c : p) ss.push_back(c); - ASSERT_EQ(ss, std::vector()); - } - } - - TEST(CanonPath, concat) { - { - CanonPath p1("a//foo/bar//"); - CanonPath p2("xyzzy/bla"); - ASSERT_EQ((p1 + p2).abs(), "/a/foo/bar/xyzzy/bla"); - } - - { - CanonPath p1("/"); - CanonPath p2("/a/b"); - ASSERT_EQ((p1 + p2).abs(), "/a/b"); - } - - { - CanonPath p1("/a/b"); - CanonPath p2("/"); - ASSERT_EQ((p1 + p2).abs(), "/a/b"); - } - - { - CanonPath p("/foo/bar"); - ASSERT_EQ((p + "x").abs(), "/foo/bar/x"); - } - - { - CanonPath p("/"); - ASSERT_EQ((p + "foo" + "bar").abs(), "/foo/bar"); - } - } - - TEST(CanonPath, within) { - ASSERT_TRUE(CanonPath("foo").isWithin(CanonPath("foo"))); - ASSERT_FALSE(CanonPath("foo").isWithin(CanonPath("bar"))); - ASSERT_FALSE(CanonPath("foo").isWithin(CanonPath("fo"))); - ASSERT_TRUE(CanonPath("foo/bar").isWithin(CanonPath("foo"))); - ASSERT_FALSE(CanonPath("foo").isWithin(CanonPath("foo/bar"))); - ASSERT_TRUE(CanonPath("/foo/bar/default.nix").isWithin(CanonPath("/"))); - ASSERT_TRUE(CanonPath("/").isWithin(CanonPath("/"))); - } - - TEST(CanonPath, sort) { - ASSERT_FALSE(CanonPath("foo") < CanonPath("foo")); - ASSERT_TRUE (CanonPath("foo") < CanonPath("foo/bar")); - ASSERT_TRUE (CanonPath("foo/bar") < CanonPath("foo!")); - ASSERT_FALSE(CanonPath("foo!") < CanonPath("foo")); - ASSERT_TRUE (CanonPath("foo") < CanonPath("foo!")); - } - - TEST(CanonPath, allowed) { - std::set allowed { - CanonPath("foo/bar"), - CanonPath("foo!"), - CanonPath("xyzzy"), - CanonPath("a/b/c"), - }; - - ASSERT_TRUE (CanonPath("foo/bar").isAllowed(allowed)); - ASSERT_TRUE (CanonPath("foo/bar/bla").isAllowed(allowed)); - ASSERT_TRUE (CanonPath("foo").isAllowed(allowed)); - ASSERT_FALSE(CanonPath("bar").isAllowed(allowed)); - ASSERT_FALSE(CanonPath("bar/a").isAllowed(allowed)); - ASSERT_TRUE (CanonPath("a").isAllowed(allowed)); - ASSERT_TRUE (CanonPath("a/b").isAllowed(allowed)); - ASSERT_TRUE (CanonPath("a/b/c").isAllowed(allowed)); - ASSERT_TRUE (CanonPath("a/b/c/d").isAllowed(allowed)); - ASSERT_TRUE (CanonPath("a/b/c/d/e").isAllowed(allowed)); - ASSERT_FALSE(CanonPath("a/b/a").isAllowed(allowed)); - ASSERT_FALSE(CanonPath("a/b/d").isAllowed(allowed)); - ASSERT_FALSE(CanonPath("aaa").isAllowed(allowed)); - ASSERT_FALSE(CanonPath("zzz").isAllowed(allowed)); - ASSERT_TRUE (CanonPath("/").isAllowed(allowed)); - } - - TEST(CanonPath, makeRelative) { - CanonPath d("/foo/bar"); - ASSERT_EQ(d.makeRelative(CanonPath("/foo/bar")), "."); - ASSERT_EQ(d.makeRelative(CanonPath("/foo")), ".."); - ASSERT_EQ(d.makeRelative(CanonPath("/")), "../.."); - ASSERT_EQ(d.makeRelative(CanonPath("/foo/bar/xyzzy")), "xyzzy"); - ASSERT_EQ(d.makeRelative(CanonPath("/foo/bar/xyzzy/bla")), "xyzzy/bla"); - ASSERT_EQ(d.makeRelative(CanonPath("/foo/xyzzy/bla")), "../xyzzy/bla"); - ASSERT_EQ(d.makeRelative(CanonPath("/xyzzy/bla")), "../../xyzzy/bla"); - } -} diff --git a/src/libutil/tests/chunked-vector.cc b/src/libutil/tests/chunked-vector.cc deleted file mode 100644 index 868d11f6f..000000000 --- a/src/libutil/tests/chunked-vector.cc +++ /dev/null @@ -1,54 +0,0 @@ -#include "chunked-vector.hh" - -#include - -namespace nix { - TEST(ChunkedVector, InitEmpty) { - auto v = ChunkedVector(100); - ASSERT_EQ(v.size(), 0); - } - - TEST(ChunkedVector, GrowsCorrectly) { - auto v = ChunkedVector(100); - for (auto i = 1; i < 20; i++) { - v.add(i); - ASSERT_EQ(v.size(), i); - } - } - - TEST(ChunkedVector, AddAndGet) { - auto v = ChunkedVector(100); - for (auto i = 1; i < 20; i++) { - auto [i2, idx] = v.add(i); - auto & i3 = v[idx]; - ASSERT_EQ(i, i2); - ASSERT_EQ(&i2, &i3); - } - } - - TEST(ChunkedVector, ForEach) { - auto v = ChunkedVector(100); - for (auto i = 1; i < 20; i++) { - v.add(i); - } - int count = 0; - v.forEach([&count](int elt) { - count++; - }); - ASSERT_EQ(count, v.size()); - } - - TEST(ChunkedVector, OverflowOK) { - // Similar to the AddAndGet, but intentionnally use a small - // initial ChunkedVector to force it to overflow - auto v = ChunkedVector(2); - for (auto i = 1; i < 20; i++) { - auto [i2, idx] = v.add(i); - auto & i3 = v[idx]; - ASSERT_EQ(i, i2); - ASSERT_EQ(&i2, &i3); - } - } - -} - diff --git a/src/libutil/tests/closure.cc b/src/libutil/tests/closure.cc deleted file mode 100644 index 7597e7807..000000000 --- a/src/libutil/tests/closure.cc +++ /dev/null @@ -1,70 +0,0 @@ -#include "closure.hh" -#include - -namespace nix { - -using namespace std; - -map> testGraph = { - { "A", { "B", "C", "G" } }, - { "B", { "A" } }, // Loops back to A - { "C", { "F" } }, // Indirect reference - { "D", { "A" } }, // Not reachable, but has backreferences - { "E", {} }, // Just not reachable - { "F", {} }, - { "G", { "G" } }, // Self reference -}; - -TEST(closure, correctClosure) { - set aClosure; - set expectedClosure = {"A", "B", "C", "F", "G"}; - computeClosure( - {"A"}, - aClosure, - [&](const string currentNode, function> &)> processEdges) { - promise> promisedNodes; - promisedNodes.set_value(testGraph[currentNode]); - processEdges(promisedNodes); - } - ); - - ASSERT_EQ(aClosure, expectedClosure); -} - -TEST(closure, properlyHandlesDirectExceptions) { - struct TestExn {}; - set aClosure; - EXPECT_THROW( - computeClosure( - {"A"}, - aClosure, - [&](const string currentNode, function> &)> processEdges) { - throw TestExn(); - } - ), - TestExn - ); -} - -TEST(closure, properlyHandlesExceptionsInPromise) { - struct TestExn {}; - set aClosure; - EXPECT_THROW( - computeClosure( - {"A"}, - aClosure, - [&](const string currentNode, function> &)> processEdges) { - promise> promise; - try { - throw TestExn(); - } catch (...) { - promise.set_exception(std::current_exception()); - } - processEdges(promise); - } - ), - TestExn - ); -} - -} diff --git a/src/libutil/tests/compression.cc b/src/libutil/tests/compression.cc deleted file mode 100644 index bbbf3500f..000000000 --- a/src/libutil/tests/compression.cc +++ /dev/null @@ -1,96 +0,0 @@ -#include "compression.hh" -#include - -namespace nix { - - /* ---------------------------------------------------------------------------- - * compress / decompress - * --------------------------------------------------------------------------*/ - - TEST(compress, compressWithUnknownMethod) { - ASSERT_THROW(compress("invalid-method", "something-to-compress"), UnknownCompressionMethod); - } - - TEST(compress, noneMethodDoesNothingToTheInput) { - auto o = compress("none", "this-is-a-test"); - - ASSERT_EQ(o, "this-is-a-test"); - } - - TEST(decompress, decompressNoneCompressed) { - auto method = "none"; - auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; - auto o = decompress(method, str); - - ASSERT_EQ(o, str); - } - - TEST(decompress, decompressEmptyCompressed) { - // Empty-method decompression used e.g. by S3 store - // (Content-Encoding == ""). - auto method = ""; - auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; - auto o = decompress(method, str); - - ASSERT_EQ(o, str); - } - - TEST(decompress, decompressXzCompressed) { - auto method = "xz"; - auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; - auto o = decompress(method, compress(method, str)); - - ASSERT_EQ(o, str); - } - - TEST(decompress, decompressBzip2Compressed) { - auto method = "bzip2"; - auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; - auto o = decompress(method, compress(method, str)); - - ASSERT_EQ(o, str); - } - - TEST(decompress, decompressBrCompressed) { - auto method = "br"; - auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; - auto o = decompress(method, compress(method, str)); - - ASSERT_EQ(o, str); - } - - TEST(decompress, decompressInvalidInputThrowsCompressionError) { - auto method = "bzip2"; - auto str = "this is a string that does not qualify as valid bzip2 data"; - - ASSERT_THROW(decompress(method, str), CompressionError); - } - - /* ---------------------------------------------------------------------------- - * compression sinks - * --------------------------------------------------------------------------*/ - - TEST(makeCompressionSink, noneSinkDoesNothingToInput) { - StringSink strSink; - auto inputString = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; - auto sink = makeCompressionSink("none", strSink); - (*sink)(inputString); - sink->finish(); - - ASSERT_STREQ(strSink.s.c_str(), inputString); - } - - TEST(makeCompressionSink, compressAndDecompress) { - StringSink strSink; - auto inputString = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; - auto decompressionSink = makeDecompressionSink("bzip2", strSink); - auto sink = makeCompressionSink("bzip2", *decompressionSink); - - (*sink)(inputString); - sink->finish(); - decompressionSink->finish(); - - ASSERT_STREQ(strSink.s.c_str(), inputString); - } - -} diff --git a/src/libutil/tests/config.cc b/src/libutil/tests/config.cc deleted file mode 100644 index 886e70da5..000000000 --- a/src/libutil/tests/config.cc +++ /dev/null @@ -1,295 +0,0 @@ -#include "config.hh" -#include "args.hh" - -#include -#include -#include - -namespace nix { - - /* ---------------------------------------------------------------------------- - * Config - * --------------------------------------------------------------------------*/ - - TEST(Config, setUndefinedSetting) { - Config config; - ASSERT_EQ(config.set("undefined-key", "value"), false); - } - - TEST(Config, setDefinedSetting) { - Config config; - std::string value; - Setting foo{&config, value, "name-of-the-setting", "description"}; - ASSERT_EQ(config.set("name-of-the-setting", "value"), true); - } - - TEST(Config, getDefinedSetting) { - Config config; - std::string value; - std::map settings; - Setting foo{&config, value, "name-of-the-setting", "description"}; - - config.getSettings(settings, /* overriddenOnly = */ false); - const auto iter = settings.find("name-of-the-setting"); - ASSERT_NE(iter, settings.end()); - ASSERT_EQ(iter->second.value, ""); - ASSERT_EQ(iter->second.description, "description\n"); - } - - TEST(Config, getDefinedOverriddenSettingNotSet) { - Config config; - std::string value; - std::map settings; - Setting foo{&config, value, "name-of-the-setting", "description"}; - - config.getSettings(settings, /* overriddenOnly = */ true); - const auto e = settings.find("name-of-the-setting"); - ASSERT_EQ(e, settings.end()); - } - - TEST(Config, getDefinedSettingSet1) { - Config config; - std::string value; - std::map settings; - Setting setting{&config, value, "name-of-the-setting", "description"}; - - setting.assign("value"); - - config.getSettings(settings, /* overriddenOnly = */ false); - const auto iter = settings.find("name-of-the-setting"); - ASSERT_NE(iter, settings.end()); - ASSERT_EQ(iter->second.value, "value"); - ASSERT_EQ(iter->second.description, "description\n"); - } - - TEST(Config, getDefinedSettingSet2) { - Config config; - std::map settings; - Setting setting{&config, "", "name-of-the-setting", "description"}; - - ASSERT_TRUE(config.set("name-of-the-setting", "value")); - - config.getSettings(settings, /* overriddenOnly = */ false); - const auto e = settings.find("name-of-the-setting"); - ASSERT_NE(e, settings.end()); - ASSERT_EQ(e->second.value, "value"); - ASSERT_EQ(e->second.description, "description\n"); - } - - TEST(Config, addSetting) { - class TestSetting : public AbstractSetting { - public: - TestSetting() : AbstractSetting("test", "test", {}) {} - void set(const std::string & value, bool append) override {} - std::string to_string() const override { return {}; } - bool isAppendable() override { return false; } - }; - - Config config; - TestSetting setting; - - ASSERT_FALSE(config.set("test", "value")); - config.addSetting(&setting); - ASSERT_TRUE(config.set("test", "value")); - ASSERT_FALSE(config.set("extra-test", "value")); - } - - TEST(Config, withInitialValue) { - const StringMap initials = { - { "key", "value" }, - }; - Config config(initials); - - { - std::map settings; - config.getSettings(settings, /* overriddenOnly = */ false); - ASSERT_EQ(settings.find("key"), settings.end()); - } - - Setting setting{&config, "default-value", "key", "description"}; - - { - std::map settings; - config.getSettings(settings, /* overriddenOnly = */ false); - ASSERT_EQ(settings["key"].value, "value"); - } - } - - TEST(Config, resetOverridden) { - Config config; - config.resetOverridden(); - } - - TEST(Config, resetOverriddenWithSetting) { - Config config; - Setting setting{&config, "", "name-of-the-setting", "description"}; - - { - std::map settings; - - setting.set("foo"); - ASSERT_EQ(setting.get(), "foo"); - config.getSettings(settings, /* overriddenOnly = */ true); - ASSERT_TRUE(settings.empty()); - } - - { - std::map settings; - - setting.override("bar"); - ASSERT_TRUE(setting.overridden); - ASSERT_EQ(setting.get(), "bar"); - config.getSettings(settings, /* overriddenOnly = */ true); - ASSERT_FALSE(settings.empty()); - } - - { - std::map settings; - - config.resetOverridden(); - ASSERT_FALSE(setting.overridden); - config.getSettings(settings, /* overriddenOnly = */ true); - ASSERT_TRUE(settings.empty()); - } - } - - TEST(Config, toJSONOnEmptyConfig) { - ASSERT_EQ(Config().toJSON().dump(), "{}"); - } - - TEST(Config, toJSONOnNonEmptyConfig) { - using nlohmann::literals::operator "" _json; - Config config; - Setting setting{ - &config, - "", - "name-of-the-setting", - "description", - }; - setting.assign("value"); - - ASSERT_EQ(config.toJSON(), - R"#({ - "name-of-the-setting": { - "aliases": [], - "defaultValue": "", - "description": "description\n", - "documentDefault": true, - "value": "value", - "experimentalFeature": null - } - })#"_json); - } - - TEST(Config, toJSONOnNonEmptyConfigWithExperimentalSetting) { - using nlohmann::literals::operator "" _json; - Config config; - Setting setting{ - &config, - "", - "name-of-the-setting", - "description", - {}, - true, - Xp::Flakes, - }; - setting.assign("value"); - - ASSERT_EQ(config.toJSON(), - R"#({ - "name-of-the-setting": { - "aliases": [], - "defaultValue": "", - "description": "description\n", - "documentDefault": true, - "value": "value", - "experimentalFeature": "flakes" - } - })#"_json); - } - - TEST(Config, setSettingAlias) { - Config config; - Setting setting{&config, "", "some-int", "best number", { "another-int" }}; - ASSERT_TRUE(config.set("some-int", "1")); - ASSERT_EQ(setting.get(), "1"); - ASSERT_TRUE(config.set("another-int", "2")); - ASSERT_EQ(setting.get(), "2"); - ASSERT_TRUE(config.set("some-int", "3")); - ASSERT_EQ(setting.get(), "3"); - } - - /* FIXME: The reapplyUnknownSettings method doesn't seem to do anything - * useful (these days). Whenever we add a new setting to Config the - * unknown settings are always considered. In which case is this function - * actually useful? Is there some way to register a Setting without calling - * addSetting? */ - TEST(Config, DISABLED_reapplyUnknownSettings) { - Config config; - ASSERT_FALSE(config.set("name-of-the-setting", "unknownvalue")); - Setting setting{&config, "default", "name-of-the-setting", "description"}; - ASSERT_EQ(setting.get(), "default"); - config.reapplyUnknownSettings(); - ASSERT_EQ(setting.get(), "unknownvalue"); - } - - TEST(Config, applyConfigEmpty) { - Config config; - std::map settings; - config.applyConfig(""); - config.getSettings(settings); - ASSERT_TRUE(settings.empty()); - } - - TEST(Config, applyConfigEmptyWithComment) { - Config config; - std::map settings; - config.applyConfig("# just a comment"); - config.getSettings(settings); - ASSERT_TRUE(settings.empty()); - } - - TEST(Config, applyConfigAssignment) { - Config config; - std::map settings; - Setting setting{&config, "", "name-of-the-setting", "description"}; - config.applyConfig( - "name-of-the-setting = value-from-file #useful comment\n" - "# name-of-the-setting = foo\n" - ); - config.getSettings(settings); - ASSERT_FALSE(settings.empty()); - ASSERT_EQ(settings["name-of-the-setting"].value, "value-from-file"); - } - - TEST(Config, applyConfigWithReassignedSetting) { - Config config; - std::map settings; - Setting setting{&config, "", "name-of-the-setting", "description"}; - config.applyConfig( - "name-of-the-setting = first-value\n" - "name-of-the-setting = second-value\n" - ); - config.getSettings(settings); - ASSERT_FALSE(settings.empty()); - ASSERT_EQ(settings["name-of-the-setting"].value, "second-value"); - } - - TEST(Config, applyConfigFailsOnMissingIncludes) { - Config config; - std::map settings; - Setting setting{&config, "", "name-of-the-setting", "description"}; - - ASSERT_THROW(config.applyConfig( - "name-of-the-setting = value-from-file\n" - "# name-of-the-setting = foo\n" - "include /nix/store/does/not/exist.nix" - ), Error); - } - - TEST(Config, applyConfigInvalidThrows) { - Config config; - ASSERT_THROW(config.applyConfig("value == key"), UsageError); - ASSERT_THROW(config.applyConfig("value "), UsageError); - } -} diff --git a/src/libutil/tests/git.cc b/src/libutil/tests/git.cc deleted file mode 100644 index 5b5715fc2..000000000 --- a/src/libutil/tests/git.cc +++ /dev/null @@ -1,33 +0,0 @@ -#include "git.hh" -#include - -namespace nix { - - TEST(GitLsRemote, parseSymrefLineWithReference) { - auto line = "ref: refs/head/main HEAD"; - auto res = git::parseLsRemoteLine(line); - ASSERT_TRUE(res.has_value()); - ASSERT_EQ(res->kind, git::LsRemoteRefLine::Kind::Symbolic); - ASSERT_EQ(res->target, "refs/head/main"); - ASSERT_EQ(res->reference, "HEAD"); - } - - TEST(GitLsRemote, parseSymrefLineWithNoReference) { - auto line = "ref: refs/head/main"; - auto res = git::parseLsRemoteLine(line); - ASSERT_TRUE(res.has_value()); - ASSERT_EQ(res->kind, git::LsRemoteRefLine::Kind::Symbolic); - ASSERT_EQ(res->target, "refs/head/main"); - ASSERT_EQ(res->reference, std::nullopt); - } - - TEST(GitLsRemote, parseObjectRefLine) { - auto line = "abc123 refs/head/main"; - auto res = git::parseLsRemoteLine(line); - ASSERT_TRUE(res.has_value()); - ASSERT_EQ(res->kind, git::LsRemoteRefLine::Kind::Object); - ASSERT_EQ(res->target, "abc123"); - ASSERT_EQ(res->reference, "refs/head/main"); - } -} - diff --git a/src/libutil/tests/hash.cc b/src/libutil/tests/hash.cc deleted file mode 100644 index e4e928b3b..000000000 --- a/src/libutil/tests/hash.cc +++ /dev/null @@ -1,95 +0,0 @@ -#include - -#include -#include -#include - -#include - -#include "tests/hash.hh" - -namespace nix { - - /* ---------------------------------------------------------------------------- - * hashString - * --------------------------------------------------------------------------*/ - - TEST(hashString, testKnownMD5Hashes1) { - // values taken from: https://tools.ietf.org/html/rfc1321 - auto s1 = ""; - auto hash = hashString(HashType::htMD5, s1); - ASSERT_EQ(hash.to_string(Base::Base16, true), "md5:d41d8cd98f00b204e9800998ecf8427e"); - } - - TEST(hashString, testKnownMD5Hashes2) { - // values taken from: https://tools.ietf.org/html/rfc1321 - auto s2 = "abc"; - auto hash = hashString(HashType::htMD5, s2); - ASSERT_EQ(hash.to_string(Base::Base16, true), "md5:900150983cd24fb0d6963f7d28e17f72"); - } - - TEST(hashString, testKnownSHA1Hashes1) { - // values taken from: https://tools.ietf.org/html/rfc3174 - auto s = "abc"; - auto hash = hashString(HashType::htSHA1, s); - ASSERT_EQ(hash.to_string(Base::Base16, true),"sha1:a9993e364706816aba3e25717850c26c9cd0d89d"); - } - - TEST(hashString, testKnownSHA1Hashes2) { - // values taken from: https://tools.ietf.org/html/rfc3174 - auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; - auto hash = hashString(HashType::htSHA1, s); - ASSERT_EQ(hash.to_string(Base::Base16, true),"sha1:84983e441c3bd26ebaae4aa1f95129e5e54670f1"); - } - - TEST(hashString, testKnownSHA256Hashes1) { - // values taken from: https://tools.ietf.org/html/rfc4634 - auto s = "abc"; - - auto hash = hashString(HashType::htSHA256, s); - ASSERT_EQ(hash.to_string(Base::Base16, true), - "sha256:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); - } - - TEST(hashString, testKnownSHA256Hashes2) { - // values taken from: https://tools.ietf.org/html/rfc4634 - auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; - auto hash = hashString(HashType::htSHA256, s); - ASSERT_EQ(hash.to_string(Base::Base16, true), - "sha256:248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"); - } - - TEST(hashString, testKnownSHA512Hashes1) { - // values taken from: https://tools.ietf.org/html/rfc4634 - auto s = "abc"; - auto hash = hashString(HashType::htSHA512, s); - ASSERT_EQ(hash.to_string(Base::Base16, true), - "sha512:ddaf35a193617abacc417349ae20413112e6fa4e89a9" - "7ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd" - "454d4423643ce80e2a9ac94fa54ca49f"); - } - - TEST(hashString, testKnownSHA512Hashes2) { - // values taken from: https://tools.ietf.org/html/rfc4634 - auto s = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; - - auto hash = hashString(HashType::htSHA512, s); - ASSERT_EQ(hash.to_string(Base::Base16, true), - "sha512:8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa1" - "7299aeadb6889018501d289e4900f7e4331b99dec4b5433a" - "c7d329eeb6dd26545e96e55b874be909"); - } -} - -namespace rc { -using namespace nix; - -Gen Arbitrary::arbitrary() -{ - Hash hash(htSHA1); - for (size_t i = 0; i < hash.hashSize; ++i) - hash.hash[i] = *gen::arbitrary(); - return gen::just(hash); -} - -} diff --git a/src/libutil/tests/hash.hh b/src/libutil/tests/hash.hh deleted file mode 100644 index 1f9fa59ae..000000000 --- a/src/libutil/tests/hash.hh +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once -///@file - -#include - -#include - -namespace rc { -using namespace nix; - -template<> -struct Arbitrary { - static Gen arbitrary(); -}; - -} diff --git a/src/libutil/tests/hilite.cc b/src/libutil/tests/hilite.cc deleted file mode 100644 index 1ff5980d5..000000000 --- a/src/libutil/tests/hilite.cc +++ /dev/null @@ -1,66 +0,0 @@ -#include "hilite.hh" - -#include - -namespace nix { -/* ----------- tests for fmt.hh -------------------------------------------------*/ - - TEST(hiliteMatches, noHighlight) { - ASSERT_STREQ(hiliteMatches("Hello, world!", std::vector(), "(", ")").c_str(), "Hello, world!"); - } - - TEST(hiliteMatches, simpleHighlight) { - std::string str = "Hello, world!"; - std::regex re = std::regex("world"); - auto matches = std::vector(std::sregex_iterator(str.begin(), str.end(), re), std::sregex_iterator()); - ASSERT_STREQ( - hiliteMatches(str, matches, "(", ")").c_str(), - "Hello, (world)!" - ); - } - - TEST(hiliteMatches, multipleMatches) { - std::string str = "Hello, world, world, world, world, world, world, Hello!"; - std::regex re = std::regex("world"); - auto matches = std::vector(std::sregex_iterator(str.begin(), str.end(), re), std::sregex_iterator()); - ASSERT_STREQ( - hiliteMatches(str, matches, "(", ")").c_str(), - "Hello, (world), (world), (world), (world), (world), (world), Hello!" - ); - } - - TEST(hiliteMatches, overlappingMatches) { - std::string str = "world, Hello, world, Hello, world, Hello, world, Hello, world!"; - std::regex re = std::regex("Hello, world"); - std::regex re2 = std::regex("world, Hello"); - auto v = std::vector(std::sregex_iterator(str.begin(), str.end(), re), std::sregex_iterator()); - for(auto it = std::sregex_iterator(str.begin(), str.end(), re2); it != std::sregex_iterator(); ++it) { - v.push_back(*it); - } - ASSERT_STREQ( - hiliteMatches(str, v, "(", ")").c_str(), - "(world, Hello, world, Hello, world, Hello, world, Hello, world)!" - ); - } - - TEST(hiliteMatches, complexOverlappingMatches) { - std::string str = "legacyPackages.x86_64-linux.git-crypt"; - std::vector regexes = { - std::regex("t-cry"), - std::regex("ux\\.git-cry"), - std::regex("git-c"), - std::regex("pt"), - }; - std::vector matches; - for(auto regex : regexes) - { - for(auto it = std::sregex_iterator(str.begin(), str.end(), regex); it != std::sregex_iterator(); ++it) { - matches.push_back(*it); - } - } - ASSERT_STREQ( - hiliteMatches(str, matches, "(", ")").c_str(), - "legacyPackages.x86_64-lin(ux.git-crypt)" - ); - } -} diff --git a/src/libutil/tests/local.mk b/src/libutil/tests/local.mk deleted file mode 100644 index 167915439..000000000 --- a/src/libutil/tests/local.mk +++ /dev/null @@ -1,29 +0,0 @@ -check: libutil-tests_RUN - -programs += libutil-tests - -libutil-tests-exe_NAME = libnixutil-tests - -libutil-tests-exe_DIR := $(d) - -libutil-tests-exe_INSTALL_DIR := - -libutil-tests-exe_LIBS = libutil-tests - -libutil-tests-exe_LDFLAGS := $(GTEST_LIBS) - -libraries += libutil-tests - -libutil-tests_NAME = libnixutil-tests - -libutil-tests_DIR := $(d) - -libutil-tests_INSTALL_DIR := - -libutil-tests_SOURCES := $(wildcard $(d)/*.cc) - -libutil-tests_CXXFLAGS += -I src/libutil - -libutil-tests_LIBS = libutil - -libutil-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) diff --git a/src/libutil/tests/logging.cc b/src/libutil/tests/logging.cc deleted file mode 100644 index 2ffdc2e9b..000000000 --- a/src/libutil/tests/logging.cc +++ /dev/null @@ -1,370 +0,0 @@ -#if 0 - -#include "logging.hh" -#include "nixexpr.hh" -#include "util.hh" -#include - -#include - -namespace nix { - - /* ---------------------------------------------------------------------------- - * logEI - * --------------------------------------------------------------------------*/ - - const char *test_file = - "previous line of code\n" - "this is the problem line of code\n" - "next line of code\n"; - const char *one_liner = - "this is the other problem line of code"; - - TEST(logEI, catpuresBasicProperties) { - - MakeError(TestError, Error); - ErrorInfo::programName = std::optional("error-unit-test"); - - try { - throw TestError("an error for testing purposes"); - } catch (Error &e) { - testing::internal::CaptureStderr(); - logger->logEI(e.info()); - auto str = testing::internal::GetCapturedStderr(); - - ASSERT_STREQ(str.c_str(),"\x1B[31;1merror:\x1B[0m\x1B[34;1m --- TestError --- error-unit-test\x1B[0m\nan error for testing purposes\n"); - } - } - - TEST(logEI, jsonOutput) { - SymbolTable testTable; - auto problem_file = testTable.create("random.nix"); - testing::internal::CaptureStderr(); - - makeJSONLogger(*logger)->logEI({ - .name = "error name", - .msg = hintfmt("this hint has %1% templated %2%!!", - "yellow", - "values"), - .errPos = Pos(foFile, problem_file, 02, 13) - }); - - auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "@nix {\"action\":\"msg\",\"column\":13,\"file\":\"random.nix\",\"level\":0,\"line\":2,\"msg\":\"\\u001b[31;1merror:\\u001b[0m\\u001b[34;1m --- error name --- error-unit-test\\u001b[0m\\n\\u001b[34;1mat: \\u001b[33;1m(2:13)\\u001b[34;1m in file: \\u001b[0mrandom.nix\\n\\nerror without any code lines.\\n\\nthis hint has \\u001b[33;1myellow\\u001b[0m templated \\u001b[33;1mvalues\\u001b[0m!!\",\"raw_msg\":\"this hint has \\u001b[33;1myellow\\u001b[0m templated \\u001b[33;1mvalues\\u001b[0m!!\"}\n"); - } - - TEST(logEI, appendingHintsToPreviousError) { - - MakeError(TestError, Error); - ErrorInfo::programName = std::optional("error-unit-test"); - - try { - auto e = Error("initial error"); - throw TestError(e.info()); - } catch (Error &e) { - ErrorInfo ei = e.info(); - ei.msg = hintfmt("%s; subsequent error message.", normaltxt(e.info().msg.str())); - - testing::internal::CaptureStderr(); - logger->logEI(ei); - auto str = testing::internal::GetCapturedStderr(); - - ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- TestError --- error-unit-test\x1B[0m\ninitial error; subsequent error message.\n"); - } - - } - - TEST(logEI, picksUpSysErrorExitCode) { - - MakeError(TestError, Error); - ErrorInfo::programName = std::optional("error-unit-test"); - - try { - auto x = readFile(-1); - } - catch (SysError &e) { - testing::internal::CaptureStderr(); - logError(e.info()); - auto str = testing::internal::GetCapturedStderr(); - - ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- SysError --- error-unit-test\x1B[0m\nstatting file: \x1B[33;1mBad file descriptor\x1B[0m\n"); - } - } - - TEST(logEI, loggingErrorOnInfoLevel) { - testing::internal::CaptureStderr(); - - logger->logEI({ .level = lvlInfo, - .name = "Info name", - }); - - auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[32;1minfo:\x1B[0m\x1B[34;1m --- Info name --- error-unit-test\x1B[0m\nInfo description\n"); - } - - TEST(logEI, loggingErrorOnTalkativeLevel) { - verbosity = lvlTalkative; - - testing::internal::CaptureStderr(); - - logger->logEI({ .level = lvlTalkative, - .name = "Talkative name", - }); - - auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[32;1mtalk:\x1B[0m\x1B[34;1m --- Talkative name --- error-unit-test\x1B[0m\nTalkative description\n"); - } - - TEST(logEI, loggingErrorOnChattyLevel) { - verbosity = lvlChatty; - - testing::internal::CaptureStderr(); - - logger->logEI({ .level = lvlChatty, - .name = "Chatty name", - }); - - auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[32;1mchat:\x1B[0m\x1B[34;1m --- Chatty name --- error-unit-test\x1B[0m\nTalkative description\n"); - } - - TEST(logEI, loggingErrorOnDebugLevel) { - verbosity = lvlDebug; - - testing::internal::CaptureStderr(); - - logger->logEI({ .level = lvlDebug, - .name = "Debug name", - }); - - auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[33;1mdebug:\x1B[0m\x1B[34;1m --- Debug name --- error-unit-test\x1B[0m\nDebug description\n"); - } - - TEST(logEI, loggingErrorOnVomitLevel) { - verbosity = lvlVomit; - - testing::internal::CaptureStderr(); - - logger->logEI({ .level = lvlVomit, - .name = "Vomit name", - }); - - auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[32;1mvomit:\x1B[0m\x1B[34;1m --- Vomit name --- error-unit-test\x1B[0m\nVomit description\n"); - } - - /* ---------------------------------------------------------------------------- - * logError - * --------------------------------------------------------------------------*/ - - TEST(logError, logErrorWithoutHintOrCode) { - testing::internal::CaptureStderr(); - - logError({ - .name = "name", - }); - - auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- name --- error-unit-test\x1B[0m\nerror description\n"); - } - - TEST(logError, logErrorWithPreviousAndNextLinesOfCode) { - SymbolTable testTable; - auto problem_file = testTable.create(test_file); - - testing::internal::CaptureStderr(); - - logError({ - .name = "error name", - .msg = hintfmt("this hint has %1% templated %2%!!", - "yellow", - "values"), - .errPos = Pos(foString, problem_file, 02, 13), - }); - - auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name --- error-unit-test\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(2:13)\x1B[34;1m from string\x1B[0m\n\nerror with code lines\n\n 1| previous line of code\n 2| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n 3| next line of code\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n"); - } - - TEST(logError, logErrorWithInvalidFile) { - SymbolTable testTable; - auto problem_file = testTable.create("invalid filename"); - testing::internal::CaptureStderr(); - - logError({ - .name = "error name", - .msg = hintfmt("this hint has %1% templated %2%!!", - "yellow", - "values"), - .errPos = Pos(foFile, problem_file, 02, 13) - }); - - auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name --- error-unit-test\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(2:13)\x1B[34;1m in file: \x1B[0minvalid filename\n\nerror without any code lines.\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n"); - } - - TEST(logError, logErrorWithOnlyHintAndName) { - testing::internal::CaptureStderr(); - - logError({ - .name = "error name", - .msg = hintfmt("hint %1%", "only"), - }); - - auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name --- error-unit-test\x1B[0m\nhint \x1B[33;1monly\x1B[0m\n"); - - } - - /* ---------------------------------------------------------------------------- - * logWarning - * --------------------------------------------------------------------------*/ - - TEST(logWarning, logWarningWithNameDescriptionAndHint) { - testing::internal::CaptureStderr(); - - logWarning({ - .name = "name", - .msg = hintfmt("there was a %1%", "warning"), - }); - - auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[33;1mwarning:\x1B[0m\x1B[34;1m --- name --- error-unit-test\x1B[0m\nwarning description\n\nthere was a \x1B[33;1mwarning\x1B[0m\n"); - } - - TEST(logWarning, logWarningWithFileLineNumAndCode) { - - SymbolTable testTable; - auto problem_file = testTable.create(test_file); - - testing::internal::CaptureStderr(); - - logWarning({ - .name = "warning name", - .msg = hintfmt("this hint has %1% templated %2%!!", - "yellow", - "values"), - .errPos = Pos(foStdin, problem_file, 2, 13), - }); - - - auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[33;1mwarning:\x1B[0m\x1B[34;1m --- warning name --- error-unit-test\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(2:13)\x1B[34;1m from stdin\x1B[0m\n\nwarning description\n\n 1| previous line of code\n 2| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n 3| next line of code\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n"); - } - - /* ---------------------------------------------------------------------------- - * traces - * --------------------------------------------------------------------------*/ - - TEST(addTrace, showTracesWithShowTrace) { - SymbolTable testTable; - auto problem_file = testTable.create(test_file); - auto oneliner_file = testTable.create(one_liner); - auto invalidfilename = testTable.create("invalid filename"); - - auto e = AssertionError(ErrorInfo { - .name = "wat", - .msg = hintfmt("it has been %1% days since our last error", "zero"), - .errPos = Pos(foString, problem_file, 2, 13), - }); - - e.addTrace(Pos(foStdin, oneliner_file, 1, 19), "while trying to compute %1%", 42); - e.addTrace(std::nullopt, "while doing something without a %1%", "pos"); - e.addTrace(Pos(foFile, invalidfilename, 100, 1), "missing %s", "nix file"); - - testing::internal::CaptureStderr(); - - loggerSettings.showTrace.assign(true); - - logError(e.info()); - - auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- AssertionError --- error-unit-test\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(2:13)\x1B[34;1m from string\x1B[0m\n\nshow-traces\n\n 1| previous line of code\n 2| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n 3| next line of code\n\nit has been \x1B[33;1mzero\x1B[0m days since our last error\n\x1B[34;1m---- show-trace ----\x1B[0m\n\x1B[34;1mtrace: \x1B[0mwhile trying to compute \x1B[33;1m42\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(1:19)\x1B[34;1m from stdin\x1B[0m\n\n 1| this is the other problem line of code\n | \x1B[31;1m^\x1B[0m\n\n\x1B[34;1mtrace: \x1B[0mwhile doing something without a \x1B[33;1mpos\x1B[0m\n\x1B[34;1mtrace: \x1B[0mmissing \x1B[33;1mnix file\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(100:1)\x1B[34;1m in file: \x1B[0minvalid filename\n"); - } - - TEST(addTrace, hideTracesWithoutShowTrace) { - SymbolTable testTable; - auto problem_file = testTable.create(test_file); - auto oneliner_file = testTable.create(one_liner); - auto invalidfilename = testTable.create("invalid filename"); - - auto e = AssertionError(ErrorInfo { - .name = "wat", - .msg = hintfmt("it has been %1% days since our last error", "zero"), - .errPos = Pos(foString, problem_file, 2, 13), - }); - - e.addTrace(Pos(foStdin, oneliner_file, 1, 19), "while trying to compute %1%", 42); - e.addTrace(std::nullopt, "while doing something without a %1%", "pos"); - e.addTrace(Pos(foFile, invalidfilename, 100, 1), "missing %s", "nix file"); - - testing::internal::CaptureStderr(); - - loggerSettings.showTrace.assign(false); - - logError(e.info()); - - auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- AssertionError --- error-unit-test\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(2:13)\x1B[34;1m from string\x1B[0m\n\nhide traces\n\n 1| previous line of code\n 2| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n 3| next line of code\n\nit has been \x1B[33;1mzero\x1B[0m days since our last error\n"); - } - - - /* ---------------------------------------------------------------------------- - * hintfmt - * --------------------------------------------------------------------------*/ - - TEST(hintfmt, percentStringWithoutArgs) { - - const char *teststr = "this is 100%s correct!"; - - ASSERT_STREQ( - hintfmt(teststr).str().c_str(), - teststr); - - } - - TEST(hintfmt, fmtToHintfmt) { - - ASSERT_STREQ( - hintfmt(fmt("the color of this this text is %1%", "not yellow")).str().c_str(), - "the color of this this text is not yellow"); - - } - - TEST(hintfmt, tooFewArguments) { - - ASSERT_STREQ( - hintfmt("only one arg %1% %2%", "fulfilled").str().c_str(), - "only one arg " ANSI_WARNING "fulfilled" ANSI_NORMAL " "); - - } - - TEST(hintfmt, tooManyArguments) { - - ASSERT_STREQ( - hintfmt("what about this %1% %2%", "%3%", "one", "two").str().c_str(), - "what about this " ANSI_WARNING "%3%" ANSI_NORMAL " " ANSI_YELLOW "one" ANSI_NORMAL); - - } - - /* ---------------------------------------------------------------------------- - * ErrPos - * --------------------------------------------------------------------------*/ - - TEST(errpos, invalidPos) { - - // contains an invalid symbol, which we should not dereference! - Pos invalid; - - // constructing without access violation. - ErrPos ep(invalid); - - // assignment without access violation. - ep = invalid; - - } - -} - -#endif diff --git a/src/libutil/tests/lru-cache.cc b/src/libutil/tests/lru-cache.cc deleted file mode 100644 index 091d3d5ed..000000000 --- a/src/libutil/tests/lru-cache.cc +++ /dev/null @@ -1,130 +0,0 @@ -#include "lru-cache.hh" -#include - -namespace nix { - - /* ---------------------------------------------------------------------------- - * size - * --------------------------------------------------------------------------*/ - - TEST(LRUCache, sizeOfEmptyCacheIsZero) { - LRUCache c(10); - ASSERT_EQ(c.size(), 0); - } - - TEST(LRUCache, sizeOfSingleElementCacheIsOne) { - LRUCache c(10); - c.upsert("foo", "bar"); - ASSERT_EQ(c.size(), 1); - } - - /* ---------------------------------------------------------------------------- - * upsert / get - * --------------------------------------------------------------------------*/ - - TEST(LRUCache, getFromEmptyCache) { - LRUCache c(10); - auto val = c.get("x"); - ASSERT_EQ(val.has_value(), false); - } - - TEST(LRUCache, getExistingValue) { - LRUCache c(10); - c.upsert("foo", "bar"); - auto val = c.get("foo"); - ASSERT_EQ(val, "bar"); - } - - TEST(LRUCache, getNonExistingValueFromNonEmptyCache) { - LRUCache c(10); - c.upsert("foo", "bar"); - auto val = c.get("another"); - ASSERT_EQ(val.has_value(), false); - } - - TEST(LRUCache, upsertOnZeroCapacityCache) { - LRUCache c(0); - c.upsert("foo", "bar"); - auto val = c.get("foo"); - ASSERT_EQ(val.has_value(), false); - } - - TEST(LRUCache, updateExistingValue) { - LRUCache c(1); - c.upsert("foo", "bar"); - - auto val = c.get("foo"); - ASSERT_EQ(val.value_or("error"), "bar"); - ASSERT_EQ(c.size(), 1); - - c.upsert("foo", "changed"); - val = c.get("foo"); - ASSERT_EQ(val.value_or("error"), "changed"); - ASSERT_EQ(c.size(), 1); - } - - TEST(LRUCache, overwriteOldestWhenCapacityIsReached) { - LRUCache c(3); - c.upsert("one", "eins"); - c.upsert("two", "zwei"); - c.upsert("three", "drei"); - - ASSERT_EQ(c.size(), 3); - ASSERT_EQ(c.get("one").value_or("error"), "eins"); - - // exceed capacity - c.upsert("another", "whatever"); - - ASSERT_EQ(c.size(), 3); - // Retrieving "one" makes it the most recent element thus - // two will be the oldest one and thus replaced. - ASSERT_EQ(c.get("two").has_value(), false); - ASSERT_EQ(c.get("another").value(), "whatever"); - } - - /* ---------------------------------------------------------------------------- - * clear - * --------------------------------------------------------------------------*/ - - TEST(LRUCache, clearEmptyCache) { - LRUCache c(10); - c.clear(); - ASSERT_EQ(c.size(), 0); - } - - TEST(LRUCache, clearNonEmptyCache) { - LRUCache c(10); - c.upsert("one", "eins"); - c.upsert("two", "zwei"); - c.upsert("three", "drei"); - ASSERT_EQ(c.size(), 3); - c.clear(); - ASSERT_EQ(c.size(), 0); - } - - /* ---------------------------------------------------------------------------- - * erase - * --------------------------------------------------------------------------*/ - - TEST(LRUCache, eraseFromEmptyCache) { - LRUCache c(10); - ASSERT_EQ(c.erase("foo"), false); - ASSERT_EQ(c.size(), 0); - } - - TEST(LRUCache, eraseMissingFromNonEmptyCache) { - LRUCache c(10); - c.upsert("one", "eins"); - ASSERT_EQ(c.erase("foo"), false); - ASSERT_EQ(c.size(), 1); - ASSERT_EQ(c.get("one").value_or("error"), "eins"); - } - - TEST(LRUCache, eraseFromNonEmptyCache) { - LRUCache c(10); - c.upsert("one", "eins"); - ASSERT_EQ(c.erase("one"), true); - ASSERT_EQ(c.size(), 0); - ASSERT_EQ(c.get("one").value_or("empty"), "empty"); - } -} diff --git a/src/libutil/tests/pool.cc b/src/libutil/tests/pool.cc deleted file mode 100644 index 127e42dda..000000000 --- a/src/libutil/tests/pool.cc +++ /dev/null @@ -1,127 +0,0 @@ -#include "pool.hh" -#include - -namespace nix { - - struct TestResource - { - - TestResource() { - static int counter = 0; - num = counter++; - } - - int dummyValue = 1; - bool good = true; - int num; - }; - - /* ---------------------------------------------------------------------------- - * Pool - * --------------------------------------------------------------------------*/ - - TEST(Pool, freshPoolHasZeroCountAndSpecifiedCapacity) { - auto isGood = [](const ref & r) { return r->good; }; - auto createResource = []() { return make_ref(); }; - - Pool pool = Pool((size_t)1, createResource, isGood); - - ASSERT_EQ(pool.count(), 0); - ASSERT_EQ(pool.capacity(), 1); - } - - TEST(Pool, freshPoolCanGetAResource) { - auto isGood = [](const ref & r) { return r->good; }; - auto createResource = []() { return make_ref(); }; - - Pool pool = Pool((size_t)1, createResource, isGood); - ASSERT_EQ(pool.count(), 0); - - TestResource r = *(pool.get()); - - ASSERT_EQ(pool.count(), 1); - ASSERT_EQ(pool.capacity(), 1); - ASSERT_EQ(r.dummyValue, 1); - ASSERT_EQ(r.good, true); - } - - TEST(Pool, capacityCanBeIncremented) { - auto isGood = [](const ref & r) { return r->good; }; - auto createResource = []() { return make_ref(); }; - - Pool pool = Pool((size_t)1, createResource, isGood); - ASSERT_EQ(pool.capacity(), 1); - pool.incCapacity(); - ASSERT_EQ(pool.capacity(), 2); - } - - TEST(Pool, capacityCanBeDecremented) { - auto isGood = [](const ref & r) { return r->good; }; - auto createResource = []() { return make_ref(); }; - - Pool pool = Pool((size_t)1, createResource, isGood); - ASSERT_EQ(pool.capacity(), 1); - pool.decCapacity(); - ASSERT_EQ(pool.capacity(), 0); - } - - TEST(Pool, flushBadDropsOutOfScopeResources) { - auto isGood = [](const ref & r) { return false; }; - auto createResource = []() { return make_ref(); }; - - Pool pool = Pool((size_t)1, createResource, isGood); - - { - auto _r = pool.get(); - ASSERT_EQ(pool.count(), 1); - } - - pool.flushBad(); - ASSERT_EQ(pool.count(), 0); - } - - // Test that the resources we allocate are being reused when they are still good. - TEST(Pool, reuseResource) { - auto isGood = [](const ref & r) { return true; }; - auto createResource = []() { return make_ref(); }; - - Pool pool = Pool((size_t)1, createResource, isGood); - - // Compare the instance counter between the two handles. We expect them to be equal - // as the pool should hand out the same (still) good one again. - int counter = -1; - { - Pool::Handle h = pool.get(); - counter = h->num; - } // the first handle goes out of scope - - { // the second handle should contain the same resource (with the same counter value) - Pool::Handle h = pool.get(); - ASSERT_EQ(h->num, counter); - } - } - - // Test that the resources we allocate are being thrown away when they are no longer good. - TEST(Pool, badResourceIsNotReused) { - auto isGood = [](const ref & r) { return false; }; - auto createResource = []() { return make_ref(); }; - - Pool pool = Pool((size_t)1, createResource, isGood); - - // Compare the instance counter between the two handles. We expect them - // to *not* be equal as the pool should hand out a new instance after - // the first one was returned. - int counter = -1; - { - Pool::Handle h = pool.get(); - counter = h->num; - } // the first handle goes out of scope - - { - // the second handle should contain a different resource (with a - //different counter value) - Pool::Handle h = pool.get(); - ASSERT_NE(h->num, counter); - } - } -} diff --git a/src/libutil/tests/references.cc b/src/libutil/tests/references.cc deleted file mode 100644 index a517d9aa1..000000000 --- a/src/libutil/tests/references.cc +++ /dev/null @@ -1,46 +0,0 @@ -#include "references.hh" -#include - -namespace nix { - -using std::string; - -struct RewriteParams { - string originalString, finalString; - StringMap rewrites; - - friend std::ostream& operator<<(std::ostream& os, const RewriteParams& bar) { - StringSet strRewrites; - for (auto & [from, to] : bar.rewrites) - strRewrites.insert(from + "->" + to); - return os << - "OriginalString: " << bar.originalString << std::endl << - "Rewrites: " << concatStringsSep(",", strRewrites) << std::endl << - "Expected result: " << bar.finalString; - } -}; - -class RewriteTest : public ::testing::TestWithParam { -}; - -TEST_P(RewriteTest, IdentityRewriteIsIdentity) { - RewriteParams param = GetParam(); - StringSink rewritten; - auto rewriter = RewritingSink(param.rewrites, rewritten); - rewriter(param.originalString); - rewriter.flush(); - ASSERT_EQ(rewritten.s, param.finalString); -} - -INSTANTIATE_TEST_CASE_P( - references, - RewriteTest, - ::testing::Values( - RewriteParams{ "foooo", "baroo", {{"foo", "bar"}, {"bar", "baz"}}}, - RewriteParams{ "foooo", "bazoo", {{"fou", "bar"}, {"foo", "baz"}}}, - RewriteParams{ "foooo", "foooo", {}} - ) -); - -} - diff --git a/src/libutil/tests/suggestions.cc b/src/libutil/tests/suggestions.cc deleted file mode 100644 index 279994abc..000000000 --- a/src/libutil/tests/suggestions.cc +++ /dev/null @@ -1,43 +0,0 @@ -#include "suggestions.hh" -#include - -namespace nix { - - struct LevenshteinDistanceParam { - std::string s1, s2; - int distance; - }; - - class LevenshteinDistanceTest : - public testing::TestWithParam { - }; - - TEST_P(LevenshteinDistanceTest, CorrectlyComputed) { - auto params = GetParam(); - - ASSERT_EQ(levenshteinDistance(params.s1, params.s2), params.distance); - ASSERT_EQ(levenshteinDistance(params.s2, params.s1), params.distance); - } - - INSTANTIATE_TEST_SUITE_P(LevenshteinDistance, LevenshteinDistanceTest, - testing::Values( - LevenshteinDistanceParam{"foo", "foo", 0}, - LevenshteinDistanceParam{"foo", "", 3}, - LevenshteinDistanceParam{"", "", 0}, - LevenshteinDistanceParam{"foo", "fo", 1}, - LevenshteinDistanceParam{"foo", "oo", 1}, - LevenshteinDistanceParam{"foo", "fao", 1}, - LevenshteinDistanceParam{"foo", "abc", 3} - ) - ); - - TEST(Suggestions, Trim) { - auto suggestions = Suggestions::bestMatches({"foooo", "bar", "fo", "gao"}, "foo"); - auto onlyOne = suggestions.trim(1); - ASSERT_EQ(onlyOne.suggestions.size(), 1); - ASSERT_TRUE(onlyOne.suggestions.begin()->suggestion == "fo"); - - auto closest = suggestions.trim(999, 2); - ASSERT_EQ(closest.suggestions.size(), 3); - } -} diff --git a/src/libutil/tests/tests.cc b/src/libutil/tests/tests.cc deleted file mode 100644 index f3c1e8248..000000000 --- a/src/libutil/tests/tests.cc +++ /dev/null @@ -1,659 +0,0 @@ -#include "util.hh" -#include "types.hh" - -#include -#include - -#include - -namespace nix { - -/* ----------- tests for util.hh ------------------------------------------------*/ - - /* ---------------------------------------------------------------------------- - * absPath - * --------------------------------------------------------------------------*/ - - TEST(absPath, doesntChangeRoot) { - auto p = absPath("/"); - - ASSERT_EQ(p, "/"); - } - - - - - TEST(absPath, turnsEmptyPathIntoCWD) { - char cwd[PATH_MAX+1]; - auto p = absPath(""); - - ASSERT_EQ(p, getcwd((char*)&cwd, PATH_MAX)); - } - - TEST(absPath, usesOptionalBasePathWhenGiven) { - char _cwd[PATH_MAX+1]; - char* cwd = getcwd((char*)&_cwd, PATH_MAX); - - auto p = absPath("", cwd); - - ASSERT_EQ(p, cwd); - } - - TEST(absPath, isIdempotent) { - char _cwd[PATH_MAX+1]; - char* cwd = getcwd((char*)&_cwd, PATH_MAX); - auto p1 = absPath(cwd); - auto p2 = absPath(p1); - - ASSERT_EQ(p1, p2); - } - - - TEST(absPath, pathIsCanonicalised) { - auto path = "/some/path/with/trailing/dot/."; - auto p1 = absPath(path); - auto p2 = absPath(p1); - - ASSERT_EQ(p1, "/some/path/with/trailing/dot"); - ASSERT_EQ(p1, p2); - } - - /* ---------------------------------------------------------------------------- - * canonPath - * --------------------------------------------------------------------------*/ - - TEST(canonPath, removesTrailingSlashes) { - auto path = "/this/is/a/path//"; - auto p = canonPath(path); - - ASSERT_EQ(p, "/this/is/a/path"); - } - - TEST(canonPath, removesDots) { - auto path = "/this/./is/a/path/./"; - auto p = canonPath(path); - - ASSERT_EQ(p, "/this/is/a/path"); - } - - TEST(canonPath, removesDots2) { - auto path = "/this/a/../is/a////path/foo/.."; - auto p = canonPath(path); - - ASSERT_EQ(p, "/this/is/a/path"); - } - - TEST(canonPath, requiresAbsolutePath) { - ASSERT_ANY_THROW(canonPath(".")); - ASSERT_ANY_THROW(canonPath("..")); - ASSERT_ANY_THROW(canonPath("../")); - ASSERT_DEATH({ canonPath(""); }, "path != \"\""); - } - - /* ---------------------------------------------------------------------------- - * dirOf - * --------------------------------------------------------------------------*/ - - TEST(dirOf, returnsEmptyStringForRoot) { - auto p = dirOf("/"); - - ASSERT_EQ(p, "/"); - } - - TEST(dirOf, returnsFirstPathComponent) { - auto p1 = dirOf("/dir/"); - ASSERT_EQ(p1, "/dir"); - auto p2 = dirOf("/dir"); - ASSERT_EQ(p2, "/"); - auto p3 = dirOf("/dir/.."); - ASSERT_EQ(p3, "/dir"); - auto p4 = dirOf("/dir/../"); - ASSERT_EQ(p4, "/dir/.."); - } - - /* ---------------------------------------------------------------------------- - * baseNameOf - * --------------------------------------------------------------------------*/ - - TEST(baseNameOf, emptyPath) { - auto p1 = baseNameOf(""); - ASSERT_EQ(p1, ""); - } - - TEST(baseNameOf, pathOnRoot) { - auto p1 = baseNameOf("/dir"); - ASSERT_EQ(p1, "dir"); - } - - TEST(baseNameOf, relativePath) { - auto p1 = baseNameOf("dir/foo"); - ASSERT_EQ(p1, "foo"); - } - - TEST(baseNameOf, pathWithTrailingSlashRoot) { - auto p1 = baseNameOf("/"); - ASSERT_EQ(p1, ""); - } - - TEST(baseNameOf, trailingSlash) { - auto p1 = baseNameOf("/dir/"); - ASSERT_EQ(p1, "dir"); - } - - /* ---------------------------------------------------------------------------- - * isInDir - * --------------------------------------------------------------------------*/ - - TEST(isInDir, trivialCase) { - auto p1 = isInDir("/foo/bar", "/foo"); - ASSERT_EQ(p1, true); - } - - TEST(isInDir, notInDir) { - auto p1 = isInDir("/zes/foo/bar", "/foo"); - ASSERT_EQ(p1, false); - } - - // XXX: hm, bug or feature? :) Looking at the implementation - // this might be problematic. - TEST(isInDir, emptyDir) { - auto p1 = isInDir("/zes/foo/bar", ""); - ASSERT_EQ(p1, true); - } - - /* ---------------------------------------------------------------------------- - * isDirOrInDir - * --------------------------------------------------------------------------*/ - - TEST(isDirOrInDir, trueForSameDirectory) { - ASSERT_EQ(isDirOrInDir("/nix", "/nix"), true); - ASSERT_EQ(isDirOrInDir("/", "/"), true); - } - - TEST(isDirOrInDir, trueForEmptyPaths) { - ASSERT_EQ(isDirOrInDir("", ""), true); - } - - TEST(isDirOrInDir, falseForDisjunctPaths) { - ASSERT_EQ(isDirOrInDir("/foo", "/bar"), false); - } - - TEST(isDirOrInDir, relativePaths) { - ASSERT_EQ(isDirOrInDir("/foo/..", "/foo"), true); - } - - // XXX: while it is possible to use "." or ".." in the - // first argument this doesn't seem to work in the second. - TEST(isDirOrInDir, DISABLED_shouldWork) { - ASSERT_EQ(isDirOrInDir("/foo/..", "/foo/."), true); - - } - - /* ---------------------------------------------------------------------------- - * pathExists - * --------------------------------------------------------------------------*/ - - TEST(pathExists, rootExists) { - ASSERT_TRUE(pathExists("/")); - } - - TEST(pathExists, cwdExists) { - ASSERT_TRUE(pathExists(".")); - } - - TEST(pathExists, bogusPathDoesNotExist) { - ASSERT_FALSE(pathExists("/schnitzel/darmstadt/pommes")); - } - - /* ---------------------------------------------------------------------------- - * concatStringsSep - * --------------------------------------------------------------------------*/ - - TEST(concatStringsSep, buildCommaSeparatedString) { - Strings strings; - strings.push_back("this"); - strings.push_back("is"); - strings.push_back("great"); - - ASSERT_EQ(concatStringsSep(",", strings), "this,is,great"); - } - - TEST(concatStringsSep, buildStringWithEmptySeparator) { - Strings strings; - strings.push_back("this"); - strings.push_back("is"); - strings.push_back("great"); - - ASSERT_EQ(concatStringsSep("", strings), "thisisgreat"); - } - - TEST(concatStringsSep, buildSingleString) { - Strings strings; - strings.push_back("this"); - - ASSERT_EQ(concatStringsSep(",", strings), "this"); - } - - /* ---------------------------------------------------------------------------- - * hasPrefix - * --------------------------------------------------------------------------*/ - - TEST(hasPrefix, emptyStringHasNoPrefix) { - ASSERT_FALSE(hasPrefix("", "foo")); - } - - TEST(hasPrefix, emptyStringIsAlwaysPrefix) { - ASSERT_TRUE(hasPrefix("foo", "")); - ASSERT_TRUE(hasPrefix("jshjkfhsadf", "")); - } - - TEST(hasPrefix, trivialCase) { - ASSERT_TRUE(hasPrefix("foobar", "foo")); - } - - /* ---------------------------------------------------------------------------- - * hasSuffix - * --------------------------------------------------------------------------*/ - - TEST(hasSuffix, emptyStringHasNoSuffix) { - ASSERT_FALSE(hasSuffix("", "foo")); - } - - TEST(hasSuffix, trivialCase) { - ASSERT_TRUE(hasSuffix("foo", "foo")); - ASSERT_TRUE(hasSuffix("foobar", "bar")); - } - - /* ---------------------------------------------------------------------------- - * base64Encode - * --------------------------------------------------------------------------*/ - - TEST(base64Encode, emptyString) { - ASSERT_EQ(base64Encode(""), ""); - } - - TEST(base64Encode, encodesAString) { - ASSERT_EQ(base64Encode("quod erat demonstrandum"), "cXVvZCBlcmF0IGRlbW9uc3RyYW5kdW0="); - } - - TEST(base64Encode, encodeAndDecode) { - auto s = "quod erat demonstrandum"; - auto encoded = base64Encode(s); - auto decoded = base64Decode(encoded); - - ASSERT_EQ(decoded, s); - } - - TEST(base64Encode, encodeAndDecodeNonPrintable) { - char s[256]; - std::iota(std::rbegin(s), std::rend(s), 0); - - auto encoded = base64Encode(s); - auto decoded = base64Decode(encoded); - - EXPECT_EQ(decoded.length(), 255); - ASSERT_EQ(decoded, s); - } - - /* ---------------------------------------------------------------------------- - * base64Decode - * --------------------------------------------------------------------------*/ - - TEST(base64Decode, emptyString) { - ASSERT_EQ(base64Decode(""), ""); - } - - TEST(base64Decode, decodeAString) { - ASSERT_EQ(base64Decode("cXVvZCBlcmF0IGRlbW9uc3RyYW5kdW0="), "quod erat demonstrandum"); - } - - TEST(base64Decode, decodeThrowsOnInvalidChar) { - ASSERT_THROW(base64Decode("cXVvZCBlcm_0IGRlbW9uc3RyYW5kdW0="), Error); - } - - /* ---------------------------------------------------------------------------- - * getLine - * --------------------------------------------------------------------------*/ - - TEST(getLine, all) { - { - auto [line, rest] = getLine("foo\nbar\nxyzzy"); - ASSERT_EQ(line, "foo"); - ASSERT_EQ(rest, "bar\nxyzzy"); - } - - { - auto [line, rest] = getLine("foo\r\nbar\r\nxyzzy"); - ASSERT_EQ(line, "foo"); - ASSERT_EQ(rest, "bar\r\nxyzzy"); - } - - { - auto [line, rest] = getLine("foo\n"); - ASSERT_EQ(line, "foo"); - ASSERT_EQ(rest, ""); - } - - { - auto [line, rest] = getLine("foo"); - ASSERT_EQ(line, "foo"); - ASSERT_EQ(rest, ""); - } - - { - auto [line, rest] = getLine(""); - ASSERT_EQ(line, ""); - ASSERT_EQ(rest, ""); - } - } - - /* ---------------------------------------------------------------------------- - * toLower - * --------------------------------------------------------------------------*/ - - TEST(toLower, emptyString) { - ASSERT_EQ(toLower(""), ""); - } - - TEST(toLower, nonLetters) { - auto s = "!@(*$#)(@#=\\234_"; - ASSERT_EQ(toLower(s), s); - } - - // std::tolower() doesn't handle unicode characters. In the context of - // store paths this isn't relevant but doesn't hurt to record this behavior - // here. - TEST(toLower, umlauts) { - auto s = "ÄÖÜ"; - ASSERT_EQ(toLower(s), "ÄÖÜ"); - } - - /* ---------------------------------------------------------------------------- - * string2Float - * --------------------------------------------------------------------------*/ - - TEST(string2Float, emptyString) { - ASSERT_EQ(string2Float(""), std::nullopt); - } - - TEST(string2Float, trivialConversions) { - ASSERT_EQ(string2Float("1.0"), 1.0); - - ASSERT_EQ(string2Float("0.0"), 0.0); - - ASSERT_EQ(string2Float("-100.25"), -100.25); - } - - /* ---------------------------------------------------------------------------- - * string2Int - * --------------------------------------------------------------------------*/ - - TEST(string2Int, emptyString) { - ASSERT_EQ(string2Int(""), std::nullopt); - } - - TEST(string2Int, trivialConversions) { - ASSERT_EQ(string2Int("1"), 1); - - ASSERT_EQ(string2Int("0"), 0); - - ASSERT_EQ(string2Int("-100"), -100); - } - - /* ---------------------------------------------------------------------------- - * statusOk - * --------------------------------------------------------------------------*/ - - TEST(statusOk, zeroIsOk) { - ASSERT_EQ(statusOk(0), true); - ASSERT_EQ(statusOk(1), false); - } - - - /* ---------------------------------------------------------------------------- - * rewriteStrings - * --------------------------------------------------------------------------*/ - - TEST(rewriteStrings, emptyString) { - StringMap rewrites; - rewrites["this"] = "that"; - - ASSERT_EQ(rewriteStrings("", rewrites), ""); - } - - TEST(rewriteStrings, emptyRewrites) { - StringMap rewrites; - - ASSERT_EQ(rewriteStrings("this and that", rewrites), "this and that"); - } - - TEST(rewriteStrings, successfulRewrite) { - StringMap rewrites; - rewrites["this"] = "that"; - - ASSERT_EQ(rewriteStrings("this and that", rewrites), "that and that"); - } - - TEST(rewriteStrings, doesntOccur) { - StringMap rewrites; - rewrites["foo"] = "bar"; - - ASSERT_EQ(rewriteStrings("this and that", rewrites), "this and that"); - } - - /* ---------------------------------------------------------------------------- - * replaceStrings - * --------------------------------------------------------------------------*/ - - TEST(replaceStrings, emptyString) { - ASSERT_EQ(replaceStrings("", "this", "that"), ""); - ASSERT_EQ(replaceStrings("this and that", "", ""), "this and that"); - } - - TEST(replaceStrings, successfulReplace) { - ASSERT_EQ(replaceStrings("this and that", "this", "that"), "that and that"); - } - - TEST(replaceStrings, doesntOccur) { - ASSERT_EQ(replaceStrings("this and that", "foo", "bar"), "this and that"); - } - - /* ---------------------------------------------------------------------------- - * trim - * --------------------------------------------------------------------------*/ - - TEST(trim, emptyString) { - ASSERT_EQ(trim(""), ""); - } - - TEST(trim, removesWhitespace) { - ASSERT_EQ(trim("foo"), "foo"); - ASSERT_EQ(trim(" foo "), "foo"); - ASSERT_EQ(trim(" foo bar baz"), "foo bar baz"); - ASSERT_EQ(trim(" \t foo bar baz\n"), "foo bar baz"); - } - - /* ---------------------------------------------------------------------------- - * chomp - * --------------------------------------------------------------------------*/ - - TEST(chomp, emptyString) { - ASSERT_EQ(chomp(""), ""); - } - - TEST(chomp, removesWhitespace) { - ASSERT_EQ(chomp("foo"), "foo"); - ASSERT_EQ(chomp("foo "), "foo"); - ASSERT_EQ(chomp(" foo "), " foo"); - ASSERT_EQ(chomp(" foo bar baz "), " foo bar baz"); - ASSERT_EQ(chomp("\t foo bar baz\n"), "\t foo bar baz"); - } - - /* ---------------------------------------------------------------------------- - * quoteStrings - * --------------------------------------------------------------------------*/ - - TEST(quoteStrings, empty) { - Strings s = { }; - Strings expected = { }; - - ASSERT_EQ(quoteStrings(s), expected); - } - - TEST(quoteStrings, emptyStrings) { - Strings s = { "", "", "" }; - Strings expected = { "''", "''", "''" }; - ASSERT_EQ(quoteStrings(s), expected); - - } - - TEST(quoteStrings, trivialQuote) { - Strings s = { "foo", "bar", "baz" }; - Strings expected = { "'foo'", "'bar'", "'baz'" }; - - ASSERT_EQ(quoteStrings(s), expected); - } - - TEST(quoteStrings, quotedStrings) { - Strings s = { "'foo'", "'bar'", "'baz'" }; - Strings expected = { "''foo''", "''bar''", "''baz''" }; - - ASSERT_EQ(quoteStrings(s), expected); - } - - /* ---------------------------------------------------------------------------- - * tokenizeString - * --------------------------------------------------------------------------*/ - - TEST(tokenizeString, empty) { - Strings expected = { }; - - ASSERT_EQ(tokenizeString(""), expected); - } - - TEST(tokenizeString, tokenizeSpacesWithDefaults) { - auto s = "foo bar baz"; - Strings expected = { "foo", "bar", "baz" }; - - ASSERT_EQ(tokenizeString(s), expected); - } - - TEST(tokenizeString, tokenizeTabsWithDefaults) { - auto s = "foo\tbar\tbaz"; - Strings expected = { "foo", "bar", "baz" }; - - ASSERT_EQ(tokenizeString(s), expected); - } - - TEST(tokenizeString, tokenizeTabsSpacesWithDefaults) { - auto s = "foo\t bar\t baz"; - Strings expected = { "foo", "bar", "baz" }; - - ASSERT_EQ(tokenizeString(s), expected); - } - - TEST(tokenizeString, tokenizeTabsSpacesNewlineWithDefaults) { - auto s = "foo\t\n bar\t\n baz"; - Strings expected = { "foo", "bar", "baz" }; - - ASSERT_EQ(tokenizeString(s), expected); - } - - TEST(tokenizeString, tokenizeTabsSpacesNewlineRetWithDefaults) { - auto s = "foo\t\n\r bar\t\n\r baz"; - Strings expected = { "foo", "bar", "baz" }; - - ASSERT_EQ(tokenizeString(s), expected); - - auto s2 = "foo \t\n\r bar \t\n\r baz"; - Strings expected2 = { "foo", "bar", "baz" }; - - ASSERT_EQ(tokenizeString(s2), expected2); - } - - TEST(tokenizeString, tokenizeWithCustomSep) { - auto s = "foo\n,bar\n,baz\n"; - Strings expected = { "foo\n", "bar\n", "baz\n" }; - - ASSERT_EQ(tokenizeString(s, ","), expected); - } - - /* ---------------------------------------------------------------------------- - * get - * --------------------------------------------------------------------------*/ - - TEST(get, emptyContainer) { - StringMap s = { }; - auto expected = nullptr; - - ASSERT_EQ(get(s, "one"), expected); - } - - TEST(get, getFromContainer) { - StringMap s; - s["one"] = "yi"; - s["two"] = "er"; - auto expected = "yi"; - - ASSERT_EQ(*get(s, "one"), expected); - } - - TEST(getOr, emptyContainer) { - StringMap s = { }; - auto expected = "yi"; - - ASSERT_EQ(getOr(s, "one", "yi"), expected); - } - - TEST(getOr, getFromContainer) { - StringMap s; - s["one"] = "yi"; - s["two"] = "er"; - auto expected = "yi"; - - ASSERT_EQ(getOr(s, "one", "nope"), expected); - } - - /* ---------------------------------------------------------------------------- - * filterANSIEscapes - * --------------------------------------------------------------------------*/ - - TEST(filterANSIEscapes, emptyString) { - auto s = ""; - auto expected = ""; - - ASSERT_EQ(filterANSIEscapes(s), expected); - } - - TEST(filterANSIEscapes, doesntChangePrintableChars) { - auto s = "09 2q304ruyhr slk2-19024 kjsadh sar f"; - - ASSERT_EQ(filterANSIEscapes(s), s); - } - - TEST(filterANSIEscapes, filtersColorCodes) { - auto s = "\u001b[30m A \u001b[31m B \u001b[32m C \u001b[33m D \u001b[0m"; - - ASSERT_EQ(filterANSIEscapes(s, true, 2), " A" ); - ASSERT_EQ(filterANSIEscapes(s, true, 3), " A " ); - ASSERT_EQ(filterANSIEscapes(s, true, 4), " A " ); - ASSERT_EQ(filterANSIEscapes(s, true, 5), " A B" ); - ASSERT_EQ(filterANSIEscapes(s, true, 8), " A B C" ); - } - - TEST(filterANSIEscapes, expandsTabs) { - auto s = "foo\tbar\tbaz"; - - ASSERT_EQ(filterANSIEscapes(s, true), "foo bar baz" ); - } - - TEST(filterANSIEscapes, utf8) { - ASSERT_EQ(filterANSIEscapes("foobar", true, 5), "fooba"); - ASSERT_EQ(filterANSIEscapes("fóóbär", true, 6), "fóóbär"); - ASSERT_EQ(filterANSIEscapes("fóóbär", true, 5), "fóóbä"); - ASSERT_EQ(filterANSIEscapes("fóóbär", true, 3), "fóó"); - ASSERT_EQ(filterANSIEscapes("f€€bär", true, 4), "f€€b"); - ASSERT_EQ(filterANSIEscapes("f𐍈𐍈bär", true, 4), "f𐍈𐍈b"); - } - -} diff --git a/src/libutil/tests/url.cc b/src/libutil/tests/url.cc deleted file mode 100644 index a908631e6..000000000 --- a/src/libutil/tests/url.cc +++ /dev/null @@ -1,338 +0,0 @@ -#include "url.hh" -#include - -namespace nix { - -/* ----------- tests for url.hh --------------------------------------------------*/ - - std::string print_map(std::map m) { - std::map::iterator it; - std::string s = "{ "; - for (it = m.begin(); it != m.end(); ++it) { - s += "{ "; - s += it->first; - s += " = "; - s += it->second; - s += " } "; - } - s += "}"; - return s; - } - - - std::ostream& operator<<(std::ostream& os, const ParsedURL& p) { - return os << "\n" - << "url: " << p.url << "\n" - << "base: " << p.base << "\n" - << "scheme: " << p.scheme << "\n" - << "authority: " << p.authority.value() << "\n" - << "path: " << p.path << "\n" - << "query: " << print_map(p.query) << "\n" - << "fragment: " << p.fragment << "\n"; - } - - TEST(parseURL, parsesSimpleHttpUrl) { - auto s = "http://www.example.org/file.tar.gz"; - auto parsed = parseURL(s); - - ParsedURL expected { - .url = "http://www.example.org/file.tar.gz", - .base = "http://www.example.org/file.tar.gz", - .scheme = "http", - .authority = "www.example.org", - .path = "/file.tar.gz", - .query = (StringMap) { }, - .fragment = "", - }; - - ASSERT_EQ(parsed, expected); - } - - TEST(parseURL, parsesSimpleHttpsUrl) { - auto s = "https://www.example.org/file.tar.gz"; - auto parsed = parseURL(s); - - ParsedURL expected { - .url = "https://www.example.org/file.tar.gz", - .base = "https://www.example.org/file.tar.gz", - .scheme = "https", - .authority = "www.example.org", - .path = "/file.tar.gz", - .query = (StringMap) { }, - .fragment = "", - }; - - ASSERT_EQ(parsed, expected); - } - - TEST(parseURL, parsesSimpleHttpUrlWithQueryAndFragment) { - auto s = "https://www.example.org/file.tar.gz?download=fast&when=now#hello"; - auto parsed = parseURL(s); - - ParsedURL expected { - .url = "https://www.example.org/file.tar.gz", - .base = "https://www.example.org/file.tar.gz", - .scheme = "https", - .authority = "www.example.org", - .path = "/file.tar.gz", - .query = (StringMap) { { "download", "fast" }, { "when", "now" } }, - .fragment = "hello", - }; - - ASSERT_EQ(parsed, expected); - } - - TEST(parseURL, parsesSimpleHttpUrlWithComplexFragment) { - auto s = "http://www.example.org/file.tar.gz?field=value#?foo=bar%23"; - auto parsed = parseURL(s); - - ParsedURL expected { - .url = "http://www.example.org/file.tar.gz", - .base = "http://www.example.org/file.tar.gz", - .scheme = "http", - .authority = "www.example.org", - .path = "/file.tar.gz", - .query = (StringMap) { { "field", "value" } }, - .fragment = "?foo=bar#", - }; - - ASSERT_EQ(parsed, expected); - } - - TEST(parseURL, parsesFilePlusHttpsUrl) { - auto s = "file+https://www.example.org/video.mp4"; - auto parsed = parseURL(s); - - ParsedURL expected { - .url = "file+https://www.example.org/video.mp4", - .base = "https://www.example.org/video.mp4", - .scheme = "file+https", - .authority = "www.example.org", - .path = "/video.mp4", - .query = (StringMap) { }, - .fragment = "", - }; - - ASSERT_EQ(parsed, expected); - } - - TEST(parseURL, rejectsAuthorityInUrlsWithFileTransportation) { - auto s = "file://www.example.org/video.mp4"; - ASSERT_THROW(parseURL(s), Error); - } - - TEST(parseURL, parseIPv4Address) { - auto s = "http://127.0.0.1:8080/file.tar.gz?download=fast&when=now#hello"; - auto parsed = parseURL(s); - - ParsedURL expected { - .url = "http://127.0.0.1:8080/file.tar.gz", - .base = "https://127.0.0.1:8080/file.tar.gz", - .scheme = "http", - .authority = "127.0.0.1:8080", - .path = "/file.tar.gz", - .query = (StringMap) { { "download", "fast" }, { "when", "now" } }, - .fragment = "hello", - }; - - ASSERT_EQ(parsed, expected); - } - - TEST(parseURL, parseScopedRFC4007IPv6Address) { - auto s = "http://[fe80::818c:da4d:8975:415c\%enp0s25]:8080"; - auto parsed = parseURL(s); - - ParsedURL expected { - .url = "http://[fe80::818c:da4d:8975:415c\%enp0s25]:8080", - .base = "http://[fe80::818c:da4d:8975:415c\%enp0s25]:8080", - .scheme = "http", - .authority = "[fe80::818c:da4d:8975:415c\%enp0s25]:8080", - .path = "", - .query = (StringMap) { }, - .fragment = "", - }; - - ASSERT_EQ(parsed, expected); - - } - - TEST(parseURL, parseIPv6Address) { - auto s = "http://[2a02:8071:8192:c100:311d:192d:81ac:11ea]:8080"; - auto parsed = parseURL(s); - - ParsedURL expected { - .url = "http://[2a02:8071:8192:c100:311d:192d:81ac:11ea]:8080", - .base = "http://[2a02:8071:8192:c100:311d:192d:81ac:11ea]:8080", - .scheme = "http", - .authority = "[2a02:8071:8192:c100:311d:192d:81ac:11ea]:8080", - .path = "", - .query = (StringMap) { }, - .fragment = "", - }; - - ASSERT_EQ(parsed, expected); - - } - - TEST(parseURL, parseEmptyQueryParams) { - auto s = "http://127.0.0.1:8080/file.tar.gz?&&&&&"; - auto parsed = parseURL(s); - ASSERT_EQ(parsed.query, (StringMap) { }); - } - - TEST(parseURL, parseUserPassword) { - auto s = "http://user:pass@www.example.org:8080/file.tar.gz"; - auto parsed = parseURL(s); - - ParsedURL expected { - .url = "http://user:pass@www.example.org/file.tar.gz", - .base = "http://user:pass@www.example.org/file.tar.gz", - .scheme = "http", - .authority = "user:pass@www.example.org:8080", - .path = "/file.tar.gz", - .query = (StringMap) { }, - .fragment = "", - }; - - - ASSERT_EQ(parsed, expected); - } - - TEST(parseURL, parseFileURLWithQueryAndFragment) { - auto s = "file:///none/of//your/business"; - auto parsed = parseURL(s); - - ParsedURL expected { - .url = "", - .base = "", - .scheme = "file", - .authority = "", - .path = "/none/of//your/business", - .query = (StringMap) { }, - .fragment = "", - }; - - ASSERT_EQ(parsed, expected); - - } - - TEST(parseURL, parsedUrlsIsEqualToItself) { - auto s = "http://www.example.org/file.tar.gz"; - auto url = parseURL(s); - - ASSERT_TRUE(url == url); - } - - TEST(parseURL, parseFTPUrl) { - auto s = "ftp://ftp.nixos.org/downloads/nixos.iso"; - auto parsed = parseURL(s); - - ParsedURL expected { - .url = "ftp://ftp.nixos.org/downloads/nixos.iso", - .base = "ftp://ftp.nixos.org/downloads/nixos.iso", - .scheme = "ftp", - .authority = "ftp.nixos.org", - .path = "/downloads/nixos.iso", - .query = (StringMap) { }, - .fragment = "", - }; - - ASSERT_EQ(parsed, expected); - } - - TEST(parseURL, parsesAnythingInUriFormat) { - auto s = "whatever://github.com/NixOS/nixpkgs.git"; - auto parsed = parseURL(s); - } - - TEST(parseURL, parsesAnythingInUriFormatWithoutDoubleSlash) { - auto s = "whatever:github.com/NixOS/nixpkgs.git"; - auto parsed = parseURL(s); - } - - TEST(parseURL, emptyStringIsInvalidURL) { - ASSERT_THROW(parseURL(""), Error); - } - - /* ---------------------------------------------------------------------------- - * decodeQuery - * --------------------------------------------------------------------------*/ - - TEST(decodeQuery, emptyStringYieldsEmptyMap) { - auto d = decodeQuery(""); - ASSERT_EQ(d, (StringMap) { }); - } - - TEST(decodeQuery, simpleDecode) { - auto d = decodeQuery("yi=one&er=two"); - ASSERT_EQ(d, ((StringMap) { { "yi", "one" }, { "er", "two" } })); - } - - TEST(decodeQuery, decodeUrlEncodedArgs) { - auto d = decodeQuery("arg=%3D%3D%40%3D%3D"); - ASSERT_EQ(d, ((StringMap) { { "arg", "==@==" } })); - } - - TEST(decodeQuery, decodeArgWithEmptyValue) { - auto d = decodeQuery("arg="); - ASSERT_EQ(d, ((StringMap) { { "arg", ""} })); - } - - /* ---------------------------------------------------------------------------- - * percentDecode - * --------------------------------------------------------------------------*/ - - TEST(percentDecode, decodesUrlEncodedString) { - std::string s = "==@=="; - std::string d = percentDecode("%3D%3D%40%3D%3D"); - ASSERT_EQ(d, s); - } - - TEST(percentDecode, multipleDecodesAreIdempotent) { - std::string once = percentDecode("%3D%3D%40%3D%3D"); - std::string twice = percentDecode(once); - - ASSERT_EQ(once, twice); - } - - TEST(percentDecode, trailingPercent) { - std::string s = "==@==%"; - std::string d = percentDecode("%3D%3D%40%3D%3D%25"); - - ASSERT_EQ(d, s); - } - - - /* ---------------------------------------------------------------------------- - * percentEncode - * --------------------------------------------------------------------------*/ - - TEST(percentEncode, encodesUrlEncodedString) { - std::string s = percentEncode("==@=="); - std::string d = "%3D%3D%40%3D%3D"; - ASSERT_EQ(d, s); - } - - TEST(percentEncode, keepArgument) { - std::string a = percentEncode("abd / def"); - std::string b = percentEncode("abd / def", "/"); - ASSERT_EQ(a, "abd%20%2F%20def"); - ASSERT_EQ(b, "abd%20/%20def"); - } - - TEST(percentEncode, inverseOfDecode) { - std::string original = "%3D%3D%40%3D%3D"; - std::string once = percentEncode(original); - std::string back = percentDecode(once); - - ASSERT_EQ(back, original); - } - - TEST(percentEncode, trailingPercent) { - std::string s = percentEncode("==@==%"); - std::string d = "%3D%3D%40%3D%3D%25"; - - ASSERT_EQ(d, s); - } - -} diff --git a/src/libutil/tests/xml-writer.cc b/src/libutil/tests/xml-writer.cc deleted file mode 100644 index adcde25c9..000000000 --- a/src/libutil/tests/xml-writer.cc +++ /dev/null @@ -1,105 +0,0 @@ -#include "xml-writer.hh" -#include -#include - -namespace nix { - - /* ---------------------------------------------------------------------------- - * XMLWriter - * --------------------------------------------------------------------------*/ - - TEST(XMLWriter, emptyObject) { - std::stringstream out; - { - XMLWriter t(false, out); - } - - ASSERT_EQ(out.str(), "\n"); - } - - TEST(XMLWriter, objectWithEmptyElement) { - std::stringstream out; - { - XMLWriter t(false, out); - t.openElement("foobar"); - } - - ASSERT_EQ(out.str(), "\n"); - } - - TEST(XMLWriter, objectWithElementWithAttrs) { - std::stringstream out; - { - XMLWriter t(false, out); - XMLAttrs attrs = { - { "foo", "bar" } - }; - t.openElement("foobar", attrs); - } - - ASSERT_EQ(out.str(), "\n"); - } - - TEST(XMLWriter, objectWithElementWithEmptyAttrs) { - std::stringstream out; - { - XMLWriter t(false, out); - XMLAttrs attrs = {}; - t.openElement("foobar", attrs); - } - - ASSERT_EQ(out.str(), "\n"); - } - - TEST(XMLWriter, objectWithElementWithAttrsEscaping) { - std::stringstream out; - { - XMLWriter t(false, out); - XMLAttrs attrs = { - { "", "" } - }; - t.openElement("foobar", attrs); - } - - // XXX: While "" is escaped, "" isn't which I think is a bug. - ASSERT_EQ(out.str(), "\n=\"<value>\">"); - } - - TEST(XMLWriter, objectWithElementWithAttrsIndented) { - std::stringstream out; - { - XMLWriter t(true, out); - XMLAttrs attrs = { - { "foo", "bar" } - }; - t.openElement("foobar", attrs); - } - - ASSERT_EQ(out.str(), "\n\n\n"); - } - - TEST(XMLWriter, writeEmptyElement) { - std::stringstream out; - { - XMLWriter t(false, out); - t.writeEmptyElement("foobar"); - } - - ASSERT_EQ(out.str(), "\n"); - } - - TEST(XMLWriter, writeEmptyElementWithAttributes) { - std::stringstream out; - { - XMLWriter t(false, out); - XMLAttrs attrs = { - { "foo", "bar" } - }; - t.writeEmptyElement("foobar", attrs); - - } - - ASSERT_EQ(out.str(), "\n"); - } - -} diff --git a/tests/unit/libexpr-support/local.mk b/tests/unit/libexpr-support/local.mk new file mode 100644 index 000000000..6b3ad64ee --- /dev/null +++ b/tests/unit/libexpr-support/local.mk @@ -0,0 +1,19 @@ +libraries += libexpr-test-support + +libexpr-test-support_NAME = libnixexpr-test-support + +libexpr-test-support_DIR := $(d) + +libexpr-test-support_INSTALL_DIR := + +libexpr-test-support_SOURCES := \ + $(wildcard $(d)/tests/*.cc) \ + $(wildcard $(d)/tests/value/*.cc) + +libexpr-test-support_CXXFLAGS += $(libexpr-tests_EXTRA_INCLUDES) + +libexpr-test-support_LIBS = \ + libstore-test-support libutil-test-support \ + libexpr libstore libutil + +libexpr-test-support_LDFLAGS := -lrapidcheck diff --git a/tests/unit/libexpr-support/tests/libexpr.hh b/tests/unit/libexpr-support/tests/libexpr.hh new file mode 100644 index 000000000..b8e65aafe --- /dev/null +++ b/tests/unit/libexpr-support/tests/libexpr.hh @@ -0,0 +1,140 @@ +#pragma once +///@file + +#include +#include + +#include "value.hh" +#include "nixexpr.hh" +#include "eval.hh" +#include "eval-inline.hh" +#include "store-api.hh" + +#include "tests/libstore.hh" + +namespace nix { + class LibExprTest : public LibStoreTest { + public: + static void SetUpTestSuite() { + LibStoreTest::SetUpTestSuite(); + initGC(); + } + + protected: + LibExprTest() + : LibStoreTest() + , state({}, store) + { + } + Value eval(std::string input, bool forceValue = true) { + Value v; + Expr * e = state.parseExprFromString(input, state.rootPath(CanonPath::root)); + assert(e); + state.eval(e, v); + if (forceValue) + state.forceValue(v, noPos); + return v; + } + + Symbol createSymbol(const char * value) { + return state.symbols.create(value); + } + + EvalState state; + }; + + MATCHER(IsListType, "") { + return arg != nList; + } + + MATCHER(IsList, "") { + return arg.type() == nList; + } + + MATCHER(IsString, "") { + return arg.type() == nString; + } + + MATCHER(IsNull, "") { + return arg.type() == nNull; + } + + MATCHER(IsThunk, "") { + return arg.type() == nThunk; + } + + MATCHER(IsAttrs, "") { + return arg.type() == nAttrs; + } + + MATCHER_P(IsStringEq, s, fmt("The string is equal to \"%1%\"", s)) { + if (arg.type() != nString) { + return false; + } + return std::string_view(arg.string.s) == s; + } + + MATCHER_P(IsIntEq, v, fmt("The string is equal to \"%1%\"", v)) { + if (arg.type() != nInt) { + return false; + } + return arg.integer == v; + } + + MATCHER_P(IsFloatEq, v, fmt("The float is equal to \"%1%\"", v)) { + if (arg.type() != nFloat) { + return false; + } + return arg.fpoint == v; + } + + MATCHER(IsTrue, "") { + if (arg.type() != nBool) { + return false; + } + return arg.boolean == true; + } + + MATCHER(IsFalse, "") { + if (arg.type() != nBool) { + return false; + } + return arg.boolean == false; + } + + MATCHER_P(IsPathEq, p, fmt("Is a path equal to \"%1%\"", p)) { + if (arg.type() != nPath) { + *result_listener << "Expected a path got " << arg.type(); + return false; + } else if (std::string_view(arg.string.s) != p) { + *result_listener << "Expected a path that equals \"" << p << "\" but got: " << arg.string.s; + return false; + } + return true; + } + + + MATCHER_P(IsListOfSize, n, fmt("Is a list of size [%1%]", n)) { + if (arg.type() != nList) { + *result_listener << "Expected list got " << arg.type(); + return false; + } else if (arg.listSize() != (size_t)n) { + *result_listener << "Expected as list of size " << n << " got " << arg.listSize(); + return false; + } + return true; + } + + MATCHER_P(IsAttrsOfSize, n, fmt("Is a set of size [%1%]", n)) { + if (arg.type() != nAttrs) { + *result_listener << "Expected set got " << arg.type(); + return false; + } else if (arg.attrs->size() != (size_t)n) { + *result_listener << "Expected a set with " << n << " attributes but got " << arg.attrs->size(); + return false; + } + return true; + } + + +} /* namespace nix */ diff --git a/tests/unit/libexpr-support/tests/value/context.cc b/tests/unit/libexpr-support/tests/value/context.cc new file mode 100644 index 000000000..8658bdaef --- /dev/null +++ b/tests/unit/libexpr-support/tests/value/context.cc @@ -0,0 +1,30 @@ +#include + +#include "tests/path.hh" +#include "tests/value/context.hh" + +namespace rc { +using namespace nix; + +Gen Arbitrary::arbitrary() +{ + return gen::just(NixStringContextElem::DrvDeep { + .drvPath = *gen::arbitrary(), + }); +} + +Gen Arbitrary::arbitrary() +{ + switch (*gen::inRange(0, std::variant_size_v)) { + case 0: + return gen::just(*gen::arbitrary()); + case 1: + return gen::just(*gen::arbitrary()); + case 2: + return gen::just(*gen::arbitrary()); + default: + assert(false); + } +} + +} diff --git a/tests/unit/libexpr-support/tests/value/context.hh b/tests/unit/libexpr-support/tests/value/context.hh new file mode 100644 index 000000000..8c68c78bb --- /dev/null +++ b/tests/unit/libexpr-support/tests/value/context.hh @@ -0,0 +1,31 @@ +#pragma once +///@file + +#include + +#include "value/context.hh" + +namespace rc { +using namespace nix; + +template<> +struct Arbitrary { + static Gen arbitrary(); +}; + +template<> +struct Arbitrary { + static Gen arbitrary(); +}; + +template<> +struct Arbitrary { + static Gen arbitrary(); +}; + +template<> +struct Arbitrary { + static Gen arbitrary(); +}; + +} diff --git a/tests/unit/libexpr/derived-path.cc b/tests/unit/libexpr/derived-path.cc new file mode 100644 index 000000000..d5fc6f201 --- /dev/null +++ b/tests/unit/libexpr/derived-path.cc @@ -0,0 +1,68 @@ +#include +#include +#include + +#include "tests/derived-path.hh" +#include "tests/libexpr.hh" + +namespace nix { + +// Testing of trivial expressions +class DerivedPathExpressionTest : public LibExprTest {}; + +// FIXME: `RC_GTEST_FIXTURE_PROP` isn't calling `SetUpTestSuite` because it is +// no a real fixture. +// +// See https://github.com/emil-e/rapidcheck/blob/master/doc/gtest.md#rc_gtest_fixture_propfixture-name-args +TEST_F(DerivedPathExpressionTest, force_init) +{ +} + +#ifndef COVERAGE + +RC_GTEST_FIXTURE_PROP( + DerivedPathExpressionTest, + prop_opaque_path_round_trip, + (const SingleDerivedPath::Opaque & o)) +{ + auto * v = state.allocValue(); + state.mkStorePathString(o.path, *v); + auto d = state.coerceToSingleDerivedPath(noPos, *v, ""); + RC_ASSERT(SingleDerivedPath { o } == d); +} + +// TODO use DerivedPath::Built for parameter once it supports a single output +// path only. + +RC_GTEST_FIXTURE_PROP( + DerivedPathExpressionTest, + prop_derived_path_built_placeholder_round_trip, + (const SingleDerivedPath::Built & b)) +{ + /** + * We set these in tests rather than the regular globals so we don't have + * to worry about race conditions if the tests run concurrently. + */ + ExperimentalFeatureSettings mockXpSettings; + mockXpSettings.set("experimental-features", "ca-derivations"); + + auto * v = state.allocValue(); + state.mkOutputString(*v, b, std::nullopt, mockXpSettings); + auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, ""); + RC_ASSERT(SingleDerivedPath { b } == d); +} + +RC_GTEST_FIXTURE_PROP( + DerivedPathExpressionTest, + prop_derived_path_built_out_path_round_trip, + (const SingleDerivedPath::Built & b, const StorePath & outPath)) +{ + auto * v = state.allocValue(); + state.mkOutputString(*v, b, outPath); + auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, ""); + RC_ASSERT(SingleDerivedPath { b } == d); +} + +#endif + +} /* namespace nix */ diff --git a/tests/unit/libexpr/error_traces.cc b/tests/unit/libexpr/error_traces.cc new file mode 100644 index 000000000..285651256 --- /dev/null +++ b/tests/unit/libexpr/error_traces.cc @@ -0,0 +1,1298 @@ +#include +#include + +#include "tests/libexpr.hh" + +namespace nix { + + using namespace testing; + + // Testing eval of PrimOp's + class ErrorTraceTest : public LibExprTest { }; + + TEST_F(ErrorTraceTest, TraceBuilder) { + ASSERT_THROW( + state.error("Not much").debugThrow(), + EvalError + ); + + ASSERT_THROW( + state.error("Not much").withTrace(noPos, "No more").debugThrow(), + EvalError + ); + + ASSERT_THROW( + try { + try { + state.error("Not much").withTrace(noPos, "No more").debugThrow(); + } catch (Error & e) { + e.addTrace(state.positions[noPos], "Something", ""); + throw; + } + } catch (BaseError & e) { + ASSERT_EQ(PrintToString(e.info().msg), + PrintToString(hintfmt("Not much"))); + auto trace = e.info().traces.rbegin(); + ASSERT_EQ(e.info().traces.size(), 2); + ASSERT_EQ(PrintToString(trace->hint), + PrintToString(hintfmt("No more"))); + trace++; + ASSERT_EQ(PrintToString(trace->hint), + PrintToString(hintfmt("Something"))); + throw; + } + , EvalError + ); + } + + TEST_F(ErrorTraceTest, NestedThrows) { + try { + state.error("Not much").withTrace(noPos, "No more").debugThrow(); + } catch (BaseError & e) { + try { + state.error("Not much more").debugThrow(); + } catch (Error & e2) { + e.addTrace(state.positions[noPos], "Something", ""); + //e2.addTrace(state.positions[noPos], "Something", ""); + ASSERT_TRUE(e.info().traces.size() == 2); + ASSERT_TRUE(e2.info().traces.size() == 0); + ASSERT_FALSE(&e.info() == &e2.info()); + } + } + } + +#define ASSERT_TRACE1(args, type, message) \ + ASSERT_THROW( \ + std::string expr(args); \ + std::string name = expr.substr(0, expr.find(" ")); \ + try { \ + Value v = eval("builtins." args); \ + state.forceValueDeep(v); \ + } catch (BaseError & e) { \ + ASSERT_EQ(PrintToString(e.info().msg), \ + PrintToString(message)); \ + ASSERT_EQ(e.info().traces.size(), 1) << "while testing " args << std::endl << e.what(); \ + auto trace = e.info().traces.rbegin(); \ + ASSERT_EQ(PrintToString(trace->hint), \ + PrintToString(hintfmt("while calling the '%s' builtin", name))); \ + throw; \ + } \ + , type \ + ) + +#define ASSERT_TRACE2(args, type, message, context) \ + ASSERT_THROW( \ + std::string expr(args); \ + std::string name = expr.substr(0, expr.find(" ")); \ + try { \ + Value v = eval("builtins." args); \ + state.forceValueDeep(v); \ + } catch (BaseError & e) { \ + ASSERT_EQ(PrintToString(e.info().msg), \ + PrintToString(message)); \ + ASSERT_EQ(e.info().traces.size(), 2) << "while testing " args << std::endl << e.what(); \ + auto trace = e.info().traces.rbegin(); \ + ASSERT_EQ(PrintToString(trace->hint), \ + PrintToString(context)); \ + ++trace; \ + ASSERT_EQ(PrintToString(trace->hint), \ + PrintToString(hintfmt("while calling the '%s' builtin", name))); \ + throw; \ + } \ + , type \ + ) + + TEST_F(ErrorTraceTest, genericClosure) { + ASSERT_TRACE2("genericClosure 1", + TypeError, + hintfmt("value is %s while a set was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.genericClosure")); + + ASSERT_TRACE2("genericClosure {}", + TypeError, + hintfmt("attribute '%s' missing", "startSet"), + hintfmt("in the attrset passed as argument to builtins.genericClosure")); + + ASSERT_TRACE2("genericClosure { startSet = 1; }", + TypeError, + hintfmt("value is %s while a list was expected", "an integer"), + hintfmt("while evaluating the 'startSet' attribute passed as argument to builtins.genericClosure")); + + ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = true; }", + TypeError, + hintfmt("value is %s while a function was expected", "a Boolean"), + hintfmt("while evaluating the 'operator' attribute passed as argument to builtins.genericClosure")); + + ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = item: true; }", + TypeError, + hintfmt("value is %s while a list was expected", "a Boolean"), + hintfmt("while evaluating the return value of the `operator` passed to builtins.genericClosure")); + + ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = item: [ true ]; }", + TypeError, + hintfmt("value is %s while a set was expected", "a Boolean"), + hintfmt("while evaluating one of the elements generated by (or initially passed to) builtins.genericClosure")); + + ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = item: [ {} ]; }", + TypeError, + hintfmt("attribute '%s' missing", "key"), + hintfmt("in one of the attrsets generated by (or initially passed to) builtins.genericClosure")); + + ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = item: [{ key = ''a''; }]; }", + EvalError, + hintfmt("cannot compare %s with %s", "a string", "an integer"), + hintfmt("while comparing the `key` attributes of two genericClosure elements")); + + ASSERT_TRACE2("genericClosure { startSet = [ true ]; operator = item: [{ key = ''a''; }]; }", + TypeError, + hintfmt("value is %s while a set was expected", "a Boolean"), + hintfmt("while evaluating one of the elements generated by (or initially passed to) builtins.genericClosure")); + + } + + + TEST_F(ErrorTraceTest, replaceStrings) { + ASSERT_TRACE2("replaceStrings 0 0 {}", + TypeError, + hintfmt("value is %s while a list was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.replaceStrings")); + + ASSERT_TRACE2("replaceStrings [] 0 {}", + TypeError, + hintfmt("value is %s while a list was expected", "an integer"), + hintfmt("while evaluating the second argument passed to builtins.replaceStrings")); + + ASSERT_TRACE1("replaceStrings [ 0 ] [] {}", + EvalError, + hintfmt("'from' and 'to' arguments passed to builtins.replaceStrings have different lengths")); + + ASSERT_TRACE2("replaceStrings [ 1 ] [ \"new\" ] {}", + TypeError, + hintfmt("value is %s while a string was expected", "an integer"), + hintfmt("while evaluating one of the strings to replace passed to builtins.replaceStrings")); + + ASSERT_TRACE2("replaceStrings [ \"oo\" ] [ true ] \"foo\"", + TypeError, + hintfmt("value is %s while a string was expected", "a Boolean"), + hintfmt("while evaluating one of the replacement strings passed to builtins.replaceStrings")); + + ASSERT_TRACE2("replaceStrings [ \"old\" ] [ \"new\" ] {}", + TypeError, + hintfmt("value is %s while a string was expected", "a set"), + hintfmt("while evaluating the third argument passed to builtins.replaceStrings")); + + } + + + TEST_F(ErrorTraceTest, scopedImport) { + } + + + TEST_F(ErrorTraceTest, import) { + } + + + TEST_F(ErrorTraceTest, typeOf) { + } + + + TEST_F(ErrorTraceTest, isNull) { + } + + + TEST_F(ErrorTraceTest, isFunction) { + } + + + TEST_F(ErrorTraceTest, isInt) { + } + + + TEST_F(ErrorTraceTest, isFloat) { + } + + + TEST_F(ErrorTraceTest, isString) { + } + + + TEST_F(ErrorTraceTest, isBool) { + } + + + TEST_F(ErrorTraceTest, isPath) { + } + + + TEST_F(ErrorTraceTest, break) { + } + + + TEST_F(ErrorTraceTest, abort) { + } + + + TEST_F(ErrorTraceTest, throw) { + } + + + TEST_F(ErrorTraceTest, addErrorContext) { + } + + + TEST_F(ErrorTraceTest, ceil) { + ASSERT_TRACE2("ceil \"foo\"", + TypeError, + hintfmt("value is %s while a float was expected", "a string"), + hintfmt("while evaluating the first argument passed to builtins.ceil")); + + } + + + TEST_F(ErrorTraceTest, floor) { + ASSERT_TRACE2("floor \"foo\"", + TypeError, + hintfmt("value is %s while a float was expected", "a string"), + hintfmt("while evaluating the first argument passed to builtins.floor")); + + } + + + TEST_F(ErrorTraceTest, tryEval) { + } + + + TEST_F(ErrorTraceTest, getEnv) { + ASSERT_TRACE2("getEnv [ ]", + TypeError, + hintfmt("value is %s while a string was expected", "a list"), + hintfmt("while evaluating the first argument passed to builtins.getEnv")); + + } + + + TEST_F(ErrorTraceTest, seq) { + } + + + TEST_F(ErrorTraceTest, deepSeq) { + } + + + TEST_F(ErrorTraceTest, trace) { + } + + + TEST_F(ErrorTraceTest, placeholder) { + ASSERT_TRACE2("placeholder []", + TypeError, + hintfmt("value is %s while a string was expected", "a list"), + hintfmt("while evaluating the first argument passed to builtins.placeholder")); + + } + + + TEST_F(ErrorTraceTest, toPath) { + ASSERT_TRACE2("toPath []", + TypeError, + hintfmt("cannot coerce %s to a string", "a list"), + hintfmt("while evaluating the first argument passed to builtins.toPath")); + + ASSERT_TRACE2("toPath \"foo\"", + EvalError, + hintfmt("string '%s' doesn't represent an absolute path", "foo"), + hintfmt("while evaluating the first argument passed to builtins.toPath")); + + } + + + TEST_F(ErrorTraceTest, storePath) { + ASSERT_TRACE2("storePath true", + TypeError, + hintfmt("cannot coerce %s to a string", "a Boolean"), + hintfmt("while evaluating the first argument passed to builtins.storePath")); + + } + + + TEST_F(ErrorTraceTest, pathExists) { + ASSERT_TRACE2("pathExists []", + TypeError, + hintfmt("cannot coerce %s to a string", "a list"), + hintfmt("while realising the context of a path")); + + ASSERT_TRACE2("pathExists \"zorglub\"", + EvalError, + hintfmt("string '%s' doesn't represent an absolute path", "zorglub"), + hintfmt("while realising the context of a path")); + + } + + + TEST_F(ErrorTraceTest, baseNameOf) { + ASSERT_TRACE2("baseNameOf []", + TypeError, + hintfmt("cannot coerce %s to a string", "a list"), + hintfmt("while evaluating the first argument passed to builtins.baseNameOf")); + + } + + + TEST_F(ErrorTraceTest, dirOf) { + } + + + TEST_F(ErrorTraceTest, readFile) { + } + + + TEST_F(ErrorTraceTest, findFile) { + } + + + TEST_F(ErrorTraceTest, hashFile) { + } + + + TEST_F(ErrorTraceTest, readDir) { + } + + + TEST_F(ErrorTraceTest, toXML) { + } + + + TEST_F(ErrorTraceTest, toJSON) { + } + + + TEST_F(ErrorTraceTest, fromJSON) { + } + + + TEST_F(ErrorTraceTest, toFile) { + } + + + TEST_F(ErrorTraceTest, filterSource) { + ASSERT_TRACE2("filterSource [] []", + TypeError, + hintfmt("cannot coerce %s to a string", "a list"), + hintfmt("while evaluating the second argument (the path to filter) passed to builtins.filterSource")); + + ASSERT_TRACE2("filterSource [] \"foo\"", + EvalError, + hintfmt("string '%s' doesn't represent an absolute path", "foo"), + hintfmt("while evaluating the second argument (the path to filter) passed to builtins.filterSource")); + + ASSERT_TRACE2("filterSource [] ./.", + TypeError, + hintfmt("value is %s while a function was expected", "a list"), + hintfmt("while evaluating the first argument passed to builtins.filterSource")); + + // Usupported by store "dummy" + + // ASSERT_TRACE2("filterSource (_: 1) ./.", + // TypeError, + // hintfmt("attempt to call something which is not a function but %s", "an integer"), + // hintfmt("while adding path '/home/layus/projects/nix'")); + + // ASSERT_TRACE2("filterSource (_: _: 1) ./.", + // TypeError, + // hintfmt("value is %s while a Boolean was expected", "an integer"), + // hintfmt("while evaluating the return value of the path filter function")); + + } + + + TEST_F(ErrorTraceTest, path) { + } + + + TEST_F(ErrorTraceTest, attrNames) { + ASSERT_TRACE2("attrNames []", + TypeError, + hintfmt("value is %s while a set was expected", "a list"), + hintfmt("while evaluating the argument passed to builtins.attrNames")); + + } + + + TEST_F(ErrorTraceTest, attrValues) { + ASSERT_TRACE2("attrValues []", + TypeError, + hintfmt("value is %s while a set was expected", "a list"), + hintfmt("while evaluating the argument passed to builtins.attrValues")); + + } + + + TEST_F(ErrorTraceTest, getAttr) { + ASSERT_TRACE2("getAttr [] []", + TypeError, + hintfmt("value is %s while a string was expected", "a list"), + hintfmt("while evaluating the first argument passed to builtins.getAttr")); + + ASSERT_TRACE2("getAttr \"foo\" []", + TypeError, + hintfmt("value is %s while a set was expected", "a list"), + hintfmt("while evaluating the second argument passed to builtins.getAttr")); + + ASSERT_TRACE2("getAttr \"foo\" {}", + TypeError, + hintfmt("attribute '%s' missing", "foo"), + hintfmt("in the attribute set under consideration")); + + } + + + TEST_F(ErrorTraceTest, unsafeGetAttrPos) { + } + + + TEST_F(ErrorTraceTest, hasAttr) { + ASSERT_TRACE2("hasAttr [] []", + TypeError, + hintfmt("value is %s while a string was expected", "a list"), + hintfmt("while evaluating the first argument passed to builtins.hasAttr")); + + ASSERT_TRACE2("hasAttr \"foo\" []", + TypeError, + hintfmt("value is %s while a set was expected", "a list"), + hintfmt("while evaluating the second argument passed to builtins.hasAttr")); + + } + + + TEST_F(ErrorTraceTest, isAttrs) { + } + + + TEST_F(ErrorTraceTest, removeAttrs) { + ASSERT_TRACE2("removeAttrs \"\" \"\"", + TypeError, + hintfmt("value is %s while a set was expected", "a string"), + hintfmt("while evaluating the first argument passed to builtins.removeAttrs")); + + ASSERT_TRACE2("removeAttrs \"\" [ 1 ]", + TypeError, + hintfmt("value is %s while a set was expected", "a string"), + hintfmt("while evaluating the first argument passed to builtins.removeAttrs")); + + ASSERT_TRACE2("removeAttrs \"\" [ \"1\" ]", + TypeError, + hintfmt("value is %s while a set was expected", "a string"), + hintfmt("while evaluating the first argument passed to builtins.removeAttrs")); + + } + + + TEST_F(ErrorTraceTest, listToAttrs) { + ASSERT_TRACE2("listToAttrs 1", + TypeError, + hintfmt("value is %s while a list was expected", "an integer"), + hintfmt("while evaluating the argument passed to builtins.listToAttrs")); + + ASSERT_TRACE2("listToAttrs [ 1 ]", + TypeError, + hintfmt("value is %s while a set was expected", "an integer"), + hintfmt("while evaluating an element of the list passed to builtins.listToAttrs")); + + ASSERT_TRACE2("listToAttrs [ {} ]", + TypeError, + hintfmt("attribute '%s' missing", "name"), + hintfmt("in a {name=...; value=...;} pair")); + + ASSERT_TRACE2("listToAttrs [ { name = 1; } ]", + TypeError, + hintfmt("value is %s while a string was expected", "an integer"), + hintfmt("while evaluating the `name` attribute of an element of the list passed to builtins.listToAttrs")); + + ASSERT_TRACE2("listToAttrs [ { name = \"foo\"; } ]", + TypeError, + hintfmt("attribute '%s' missing", "value"), + hintfmt("in a {name=...; value=...;} pair")); + + } + + + TEST_F(ErrorTraceTest, intersectAttrs) { + ASSERT_TRACE2("intersectAttrs [] []", + TypeError, + hintfmt("value is %s while a set was expected", "a list"), + hintfmt("while evaluating the first argument passed to builtins.intersectAttrs")); + + ASSERT_TRACE2("intersectAttrs {} []", + TypeError, + hintfmt("value is %s while a set was expected", "a list"), + hintfmt("while evaluating the second argument passed to builtins.intersectAttrs")); + + } + + + TEST_F(ErrorTraceTest, catAttrs) { + ASSERT_TRACE2("catAttrs [] {}", + TypeError, + hintfmt("value is %s while a string was expected", "a list"), + hintfmt("while evaluating the first argument passed to builtins.catAttrs")); + + ASSERT_TRACE2("catAttrs \"foo\" {}", + TypeError, + hintfmt("value is %s while a list was expected", "a set"), + hintfmt("while evaluating the second argument passed to builtins.catAttrs")); + + ASSERT_TRACE2("catAttrs \"foo\" [ 1 ]", + TypeError, + hintfmt("value is %s while a set was expected", "an integer"), + hintfmt("while evaluating an element in the list passed as second argument to builtins.catAttrs")); + + ASSERT_TRACE2("catAttrs \"foo\" [ { foo = 1; } 1 { bar = 5;} ]", + TypeError, + hintfmt("value is %s while a set was expected", "an integer"), + hintfmt("while evaluating an element in the list passed as second argument to builtins.catAttrs")); + + } + + + TEST_F(ErrorTraceTest, functionArgs) { + ASSERT_TRACE1("functionArgs {}", + TypeError, + hintfmt("'functionArgs' requires a function")); + + } + + + TEST_F(ErrorTraceTest, mapAttrs) { + ASSERT_TRACE2("mapAttrs [] []", + TypeError, + hintfmt("value is %s while a set was expected", "a list"), + hintfmt("while evaluating the second argument passed to builtins.mapAttrs")); + + // XXX: defered + // ASSERT_TRACE2("mapAttrs \"\" { foo.bar = 1; }", + // TypeError, + // hintfmt("attempt to call something which is not a function but %s", "a string"), + // hintfmt("while evaluating the attribute 'foo'")); + + // ASSERT_TRACE2("mapAttrs (x: x + \"1\") { foo.bar = 1; }", + // TypeError, + // hintfmt("attempt to call something which is not a function but %s", "a string"), + // hintfmt("while evaluating the attribute 'foo'")); + + // ASSERT_TRACE2("mapAttrs (x: y: x + 1) { foo.bar = 1; }", + // TypeError, + // hintfmt("cannot coerce %s to a string", "an integer"), + // hintfmt("while evaluating a path segment")); + + } + + + TEST_F(ErrorTraceTest, zipAttrsWith) { + ASSERT_TRACE2("zipAttrsWith [] [ 1 ]", + TypeError, + hintfmt("value is %s while a function was expected", "a list"), + hintfmt("while evaluating the first argument passed to builtins.zipAttrsWith")); + + ASSERT_TRACE2("zipAttrsWith (_: 1) [ 1 ]", + TypeError, + hintfmt("value is %s while a set was expected", "an integer"), + hintfmt("while evaluating a value of the list passed as second argument to builtins.zipAttrsWith")); + + // XXX: How to properly tell that the fucntion takes two arguments ? + // The same question also applies to sort, and maybe others. + // Due to lazyness, we only create a thunk, and it fails later on. + // ASSERT_TRACE2("zipAttrsWith (_: 1) [ { foo = 1; } ]", + // TypeError, + // hintfmt("attempt to call something which is not a function but %s", "an integer"), + // hintfmt("while evaluating the attribute 'foo'")); + + // XXX: Also deferred deeply + // ASSERT_TRACE2("zipAttrsWith (a: b: a + b) [ { foo = 1; } { foo = 2; } ]", + // TypeError, + // hintfmt("cannot coerce %s to a string", "a list"), + // hintfmt("while evaluating a path segment")); + + } + + + TEST_F(ErrorTraceTest, isList) { + } + + + TEST_F(ErrorTraceTest, elemAt) { + ASSERT_TRACE2("elemAt \"foo\" (-1)", + TypeError, + hintfmt("value is %s while a list was expected", "a string"), + hintfmt("while evaluating the first argument passed to builtins.elemAt")); + + ASSERT_TRACE1("elemAt [] (-1)", + Error, + hintfmt("list index %d is out of bounds", -1)); + + ASSERT_TRACE1("elemAt [\"foo\"] 3", + Error, + hintfmt("list index %d is out of bounds", 3)); + + } + + + TEST_F(ErrorTraceTest, head) { + ASSERT_TRACE2("head 1", + TypeError, + hintfmt("value is %s while a list was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.elemAt")); + + ASSERT_TRACE1("head []", + Error, + hintfmt("list index %d is out of bounds", 0)); + + } + + + TEST_F(ErrorTraceTest, tail) { + ASSERT_TRACE2("tail 1", + TypeError, + hintfmt("value is %s while a list was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.tail")); + + ASSERT_TRACE1("tail []", + Error, + hintfmt("'tail' called on an empty list")); + + } + + + TEST_F(ErrorTraceTest, map) { + ASSERT_TRACE2("map 1 \"foo\"", + TypeError, + hintfmt("value is %s while a list was expected", "a string"), + hintfmt("while evaluating the second argument passed to builtins.map")); + + ASSERT_TRACE2("map 1 [ 1 ]", + TypeError, + hintfmt("value is %s while a function was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.map")); + + } + + + TEST_F(ErrorTraceTest, filter) { + ASSERT_TRACE2("filter 1 \"foo\"", + TypeError, + hintfmt("value is %s while a list was expected", "a string"), + hintfmt("while evaluating the second argument passed to builtins.filter")); + + ASSERT_TRACE2("filter 1 [ \"foo\" ]", + TypeError, + hintfmt("value is %s while a function was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.filter")); + + ASSERT_TRACE2("filter (_: 5) [ \"foo\" ]", + TypeError, + hintfmt("value is %s while a Boolean was expected", "an integer"), + hintfmt("while evaluating the return value of the filtering function passed to builtins.filter")); + + } + + + TEST_F(ErrorTraceTest, elem) { + ASSERT_TRACE2("elem 1 \"foo\"", + TypeError, + hintfmt("value is %s while a list was expected", "a string"), + hintfmt("while evaluating the second argument passed to builtins.elem")); + + } + + + TEST_F(ErrorTraceTest, concatLists) { + ASSERT_TRACE2("concatLists 1", + TypeError, + hintfmt("value is %s while a list was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.concatLists")); + + ASSERT_TRACE2("concatLists [ 1 ]", + TypeError, + hintfmt("value is %s while a list was expected", "an integer"), + hintfmt("while evaluating a value of the list passed to builtins.concatLists")); + + ASSERT_TRACE2("concatLists [ [1] \"foo\" ]", + TypeError, + hintfmt("value is %s while a list was expected", "a string"), + hintfmt("while evaluating a value of the list passed to builtins.concatLists")); + + } + + + TEST_F(ErrorTraceTest, length) { + ASSERT_TRACE2("length 1", + TypeError, + hintfmt("value is %s while a list was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.length")); + + ASSERT_TRACE2("length \"foo\"", + TypeError, + hintfmt("value is %s while a list was expected", "a string"), + hintfmt("while evaluating the first argument passed to builtins.length")); + + } + + + TEST_F(ErrorTraceTest, foldlPrime) { + ASSERT_TRACE2("foldl' 1 \"foo\" true", + TypeError, + hintfmt("value is %s while a function was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.foldlStrict")); + + ASSERT_TRACE2("foldl' (_: 1) \"foo\" true", + TypeError, + hintfmt("value is %s while a list was expected", "a Boolean"), + hintfmt("while evaluating the third argument passed to builtins.foldlStrict")); + + ASSERT_TRACE1("foldl' (_: 1) \"foo\" [ true ]", + TypeError, + hintfmt("attempt to call something which is not a function but %s", "an integer")); + + ASSERT_TRACE2("foldl' (a: b: a && b) \"foo\" [ true ]", + TypeError, + hintfmt("value is %s while a Boolean was expected", "a string"), + hintfmt("in the left operand of the AND (&&) operator")); + + } + + + TEST_F(ErrorTraceTest, any) { + ASSERT_TRACE2("any 1 \"foo\"", + TypeError, + hintfmt("value is %s while a function was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.any")); + + ASSERT_TRACE2("any (_: 1) \"foo\"", + TypeError, + hintfmt("value is %s while a list was expected", "a string"), + hintfmt("while evaluating the second argument passed to builtins.any")); + + ASSERT_TRACE2("any (_: 1) [ \"foo\" ]", + TypeError, + hintfmt("value is %s while a Boolean was expected", "an integer"), + hintfmt("while evaluating the return value of the function passed to builtins.any")); + + } + + + TEST_F(ErrorTraceTest, all) { + ASSERT_TRACE2("all 1 \"foo\"", + TypeError, + hintfmt("value is %s while a function was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.all")); + + ASSERT_TRACE2("all (_: 1) \"foo\"", + TypeError, + hintfmt("value is %s while a list was expected", "a string"), + hintfmt("while evaluating the second argument passed to builtins.all")); + + ASSERT_TRACE2("all (_: 1) [ \"foo\" ]", + TypeError, + hintfmt("value is %s while a Boolean was expected", "an integer"), + hintfmt("while evaluating the return value of the function passed to builtins.all")); + + } + + + TEST_F(ErrorTraceTest, genList) { + ASSERT_TRACE2("genList 1 \"foo\"", + TypeError, + hintfmt("value is %s while an integer was expected", "a string"), + hintfmt("while evaluating the second argument passed to builtins.genList")); + + ASSERT_TRACE2("genList 1 2", + TypeError, + hintfmt("value is %s while a function was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.genList", "an integer")); + + // XXX: defered + // ASSERT_TRACE2("genList (x: x + \"foo\") 2 #TODO", + // TypeError, + // hintfmt("cannot add %s to an integer", "a string"), + // hintfmt("while evaluating anonymous lambda")); + + ASSERT_TRACE1("genList false (-3)", + EvalError, + hintfmt("cannot create list of size %d", -3)); + + } + + + TEST_F(ErrorTraceTest, sort) { + ASSERT_TRACE2("sort 1 \"foo\"", + TypeError, + hintfmt("value is %s while a list was expected", "a string"), + hintfmt("while evaluating the second argument passed to builtins.sort")); + + ASSERT_TRACE2("sort 1 [ \"foo\" ]", + TypeError, + hintfmt("value is %s while a function was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.sort")); + + ASSERT_TRACE1("sort (_: 1) [ \"foo\" \"bar\" ]", + TypeError, + hintfmt("attempt to call something which is not a function but %s", "an integer")); + + ASSERT_TRACE2("sort (_: _: 1) [ \"foo\" \"bar\" ]", + TypeError, + hintfmt("value is %s while a Boolean was expected", "an integer"), + hintfmt("while evaluating the return value of the sorting function passed to builtins.sort")); + + // XXX: Trace too deep, need better asserts + // ASSERT_TRACE1("sort (a: b: a <= b) [ \"foo\" {} ] # TODO", + // TypeError, + // hintfmt("cannot compare %s with %s", "a string", "a set")); + + // ASSERT_TRACE1("sort (a: b: a <= b) [ {} {} ] # TODO", + // TypeError, + // hintfmt("cannot compare %s with %s; values of that type are incomparable", "a set", "a set")); + + } + + + TEST_F(ErrorTraceTest, partition) { + ASSERT_TRACE2("partition 1 \"foo\"", + TypeError, + hintfmt("value is %s while a function was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.partition")); + + ASSERT_TRACE2("partition (_: 1) \"foo\"", + TypeError, + hintfmt("value is %s while a list was expected", "a string"), + hintfmt("while evaluating the second argument passed to builtins.partition")); + + ASSERT_TRACE2("partition (_: 1) [ \"foo\" ]", + TypeError, + hintfmt("value is %s while a Boolean was expected", "an integer"), + hintfmt("while evaluating the return value of the partition function passed to builtins.partition")); + + } + + + TEST_F(ErrorTraceTest, groupBy) { + ASSERT_TRACE2("groupBy 1 \"foo\"", + TypeError, + hintfmt("value is %s while a function was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.groupBy")); + + ASSERT_TRACE2("groupBy (_: 1) \"foo\"", + TypeError, + hintfmt("value is %s while a list was expected", "a string"), + hintfmt("while evaluating the second argument passed to builtins.groupBy")); + + ASSERT_TRACE2("groupBy (x: x) [ \"foo\" \"bar\" 1 ]", + TypeError, + hintfmt("value is %s while a string was expected", "an integer"), + hintfmt("while evaluating the return value of the grouping function passed to builtins.groupBy")); + + } + + + TEST_F(ErrorTraceTest, concatMap) { + ASSERT_TRACE2("concatMap 1 \"foo\"", + TypeError, + hintfmt("value is %s while a function was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.concatMap")); + + ASSERT_TRACE2("concatMap (x: 1) \"foo\"", + TypeError, + hintfmt("value is %s while a list was expected", "a string"), + hintfmt("while evaluating the second argument passed to builtins.concatMap")); + + ASSERT_TRACE2("concatMap (x: 1) [ \"foo\" ] # TODO", + TypeError, + hintfmt("value is %s while a list was expected", "an integer"), + hintfmt("while evaluating the return value of the function passed to buitlins.concatMap")); + + ASSERT_TRACE2("concatMap (x: \"foo\") [ 1 2 ] # TODO", + TypeError, + hintfmt("value is %s while a list was expected", "a string"), + hintfmt("while evaluating the return value of the function passed to buitlins.concatMap")); + + } + + + TEST_F(ErrorTraceTest, add) { + ASSERT_TRACE2("add \"foo\" 1", + TypeError, + hintfmt("value is %s while an integer was expected", "a string"), + hintfmt("while evaluating the first argument of the addition")); + + ASSERT_TRACE2("add 1 \"foo\"", + TypeError, + hintfmt("value is %s while an integer was expected", "a string"), + hintfmt("while evaluating the second argument of the addition")); + + } + + + TEST_F(ErrorTraceTest, sub) { + ASSERT_TRACE2("sub \"foo\" 1", + TypeError, + hintfmt("value is %s while an integer was expected", "a string"), + hintfmt("while evaluating the first argument of the subtraction")); + + ASSERT_TRACE2("sub 1 \"foo\"", + TypeError, + hintfmt("value is %s while an integer was expected", "a string"), + hintfmt("while evaluating the second argument of the subtraction")); + + } + + + TEST_F(ErrorTraceTest, mul) { + ASSERT_TRACE2("mul \"foo\" 1", + TypeError, + hintfmt("value is %s while an integer was expected", "a string"), + hintfmt("while evaluating the first argument of the multiplication")); + + ASSERT_TRACE2("mul 1 \"foo\"", + TypeError, + hintfmt("value is %s while an integer was expected", "a string"), + hintfmt("while evaluating the second argument of the multiplication")); + + } + + + TEST_F(ErrorTraceTest, div) { + ASSERT_TRACE2("div \"foo\" 1 # TODO: an integer was expected -> a number", + TypeError, + hintfmt("value is %s while an integer was expected", "a string"), + hintfmt("while evaluating the first operand of the division")); + + ASSERT_TRACE2("div 1 \"foo\"", + TypeError, + hintfmt("value is %s while a float was expected", "a string"), + hintfmt("while evaluating the second operand of the division")); + + ASSERT_TRACE1("div \"foo\" 0", + EvalError, + hintfmt("division by zero")); + + } + + + TEST_F(ErrorTraceTest, bitAnd) { + ASSERT_TRACE2("bitAnd 1.1 2", + TypeError, + hintfmt("value is %s while an integer was expected", "a float"), + hintfmt("while evaluating the first argument passed to builtins.bitAnd")); + + ASSERT_TRACE2("bitAnd 1 2.2", + TypeError, + hintfmt("value is %s while an integer was expected", "a float"), + hintfmt("while evaluating the second argument passed to builtins.bitAnd")); + + } + + + TEST_F(ErrorTraceTest, bitOr) { + ASSERT_TRACE2("bitOr 1.1 2", + TypeError, + hintfmt("value is %s while an integer was expected", "a float"), + hintfmt("while evaluating the first argument passed to builtins.bitOr")); + + ASSERT_TRACE2("bitOr 1 2.2", + TypeError, + hintfmt("value is %s while an integer was expected", "a float"), + hintfmt("while evaluating the second argument passed to builtins.bitOr")); + + } + + + TEST_F(ErrorTraceTest, bitXor) { + ASSERT_TRACE2("bitXor 1.1 2", + TypeError, + hintfmt("value is %s while an integer was expected", "a float"), + hintfmt("while evaluating the first argument passed to builtins.bitXor")); + + ASSERT_TRACE2("bitXor 1 2.2", + TypeError, + hintfmt("value is %s while an integer was expected", "a float"), + hintfmt("while evaluating the second argument passed to builtins.bitXor")); + + } + + + TEST_F(ErrorTraceTest, lessThan) { + ASSERT_TRACE1("lessThan 1 \"foo\"", + EvalError, + hintfmt("cannot compare %s with %s", "an integer", "a string")); + + ASSERT_TRACE1("lessThan {} {}", + EvalError, + hintfmt("cannot compare %s with %s; values of that type are incomparable", "a set", "a set")); + + ASSERT_TRACE2("lessThan [ 1 2 ] [ \"foo\" ]", + EvalError, + hintfmt("cannot compare %s with %s", "an integer", "a string"), + hintfmt("while comparing two list elements")); + + } + + + TEST_F(ErrorTraceTest, toString) { + ASSERT_TRACE2("toString { a = 1; }", + TypeError, + hintfmt("cannot coerce %s to a string", "a set"), + hintfmt("while evaluating the first argument passed to builtins.toString")); + + } + + + TEST_F(ErrorTraceTest, substring) { + ASSERT_TRACE2("substring {} \"foo\" true", + TypeError, + hintfmt("value is %s while an integer was expected", "a set"), + hintfmt("while evaluating the first argument (the start offset) passed to builtins.substring")); + + ASSERT_TRACE2("substring 3 \"foo\" true", + TypeError, + hintfmt("value is %s while an integer was expected", "a string"), + hintfmt("while evaluating the second argument (the substring length) passed to builtins.substring")); + + ASSERT_TRACE2("substring 0 3 {}", + TypeError, + hintfmt("cannot coerce %s to a string", "a set"), + hintfmt("while evaluating the third argument (the string) passed to builtins.substring")); + + ASSERT_TRACE1("substring (-3) 3 \"sometext\"", + EvalError, + hintfmt("negative start position in 'substring'")); + + } + + + TEST_F(ErrorTraceTest, stringLength) { + ASSERT_TRACE2("stringLength {} # TODO: context is missing ???", + TypeError, + hintfmt("cannot coerce %s to a string", "a set"), + hintfmt("while evaluating the argument passed to builtins.stringLength")); + + } + + + TEST_F(ErrorTraceTest, hashString) { + ASSERT_TRACE2("hashString 1 {}", + TypeError, + hintfmt("value is %s while a string was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.hashString")); + + ASSERT_TRACE1("hashString \"foo\" \"content\"", + UsageError, + hintfmt("unknown hash algorithm '%s'", "foo")); + + ASSERT_TRACE2("hashString \"sha256\" {}", + TypeError, + hintfmt("value is %s while a string was expected", "a set"), + hintfmt("while evaluating the second argument passed to builtins.hashString")); + + } + + + TEST_F(ErrorTraceTest, match) { + ASSERT_TRACE2("match 1 {}", + TypeError, + hintfmt("value is %s while a string was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.match")); + + ASSERT_TRACE2("match \"foo\" {}", + TypeError, + hintfmt("value is %s while a string was expected", "a set"), + hintfmt("while evaluating the second argument passed to builtins.match")); + + ASSERT_TRACE1("match \"(.*\" \"\"", + EvalError, + hintfmt("invalid regular expression '%s'", "(.*")); + + } + + + TEST_F(ErrorTraceTest, split) { + ASSERT_TRACE2("split 1 {}", + TypeError, + hintfmt("value is %s while a string was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.split")); + + ASSERT_TRACE2("split \"foo\" {}", + TypeError, + hintfmt("value is %s while a string was expected", "a set"), + hintfmt("while evaluating the second argument passed to builtins.split")); + + ASSERT_TRACE1("split \"f(o*o\" \"1foo2\"", + EvalError, + hintfmt("invalid regular expression '%s'", "f(o*o")); + + } + + + TEST_F(ErrorTraceTest, concatStringsSep) { + ASSERT_TRACE2("concatStringsSep 1 {}", + TypeError, + hintfmt("value is %s while a string was expected", "an integer"), + hintfmt("while evaluating the first argument (the separator string) passed to builtins.concatStringsSep")); + + ASSERT_TRACE2("concatStringsSep \"foo\" {}", + TypeError, + hintfmt("value is %s while a list was expected", "a set"), + hintfmt("while evaluating the second argument (the list of strings to concat) passed to builtins.concatStringsSep")); + + ASSERT_TRACE2("concatStringsSep \"foo\" [ 1 2 {} ] # TODO: coerce to string is buggy", + TypeError, + hintfmt("cannot coerce %s to a string", "an integer"), + hintfmt("while evaluating one element of the list of strings to concat passed to builtins.concatStringsSep")); + + } + + + TEST_F(ErrorTraceTest, parseDrvName) { + ASSERT_TRACE2("parseDrvName 1", + TypeError, + hintfmt("value is %s while a string was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.parseDrvName")); + + } + + + TEST_F(ErrorTraceTest, compareVersions) { + ASSERT_TRACE2("compareVersions 1 {}", + TypeError, + hintfmt("value is %s while a string was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.compareVersions")); + + ASSERT_TRACE2("compareVersions \"abd\" {}", + TypeError, + hintfmt("value is %s while a string was expected", "a set"), + hintfmt("while evaluating the second argument passed to builtins.compareVersions")); + + } + + + TEST_F(ErrorTraceTest, splitVersion) { + ASSERT_TRACE2("splitVersion 1", + TypeError, + hintfmt("value is %s while a string was expected", "an integer"), + hintfmt("while evaluating the first argument passed to builtins.splitVersion")); + + } + + + TEST_F(ErrorTraceTest, traceVerbose) { + } + + + /* // Needs different ASSERTs + TEST_F(ErrorTraceTest, derivationStrict) { + ASSERT_TRACE2("derivationStrict \"\"", + TypeError, + hintfmt("value is %s while a set was expected", "a string"), + hintfmt("while evaluating the argument passed to builtins.derivationStrict")); + + ASSERT_TRACE2("derivationStrict {}", + TypeError, + hintfmt("attribute '%s' missing", "name"), + hintfmt("in the attrset passed as argument to builtins.derivationStrict")); + + ASSERT_TRACE2("derivationStrict { name = 1; }", + TypeError, + hintfmt("value is %s while a string was expected", "an integer"), + hintfmt("while evaluating the `name` attribute passed to builtins.derivationStrict")); + + ASSERT_TRACE2("derivationStrict { name = \"foo\"; }", + TypeError, + hintfmt("required attribute 'builder' missing"), + hintfmt("while evaluating derivation 'foo'")); + + ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; __structuredAttrs = 15; }", + TypeError, + hintfmt("value is %s while a Boolean was expected", "an integer"), + hintfmt("while evaluating the `__structuredAttrs` attribute passed to builtins.derivationStrict")); + + ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; __ignoreNulls = 15; }", + TypeError, + hintfmt("value is %s while a Boolean was expected", "an integer"), + hintfmt("while evaluating the `__ignoreNulls` attribute passed to builtins.derivationStrict")); + + ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; outputHashMode = 15; }", + TypeError, + hintfmt("invalid value '15' for 'outputHashMode' attribute"), + hintfmt("while evaluating the attribute 'outputHashMode' of derivation 'foo'")); + + ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; outputHashMode = \"custom\"; }", + TypeError, + hintfmt("invalid value 'custom' for 'outputHashMode' attribute"), + hintfmt("while evaluating the attribute 'outputHashMode' of derivation 'foo'")); + + ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = {}; }", + TypeError, + hintfmt("cannot coerce %s to a string", "a set"), + hintfmt("while evaluating the attribute 'system' of derivation 'foo'")); + + ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = {}; }", + TypeError, + hintfmt("cannot coerce %s to a string", "a set"), + hintfmt("while evaluating the attribute 'outputs' of derivation 'foo'")); + + ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"drv\"; }", + TypeError, + hintfmt("invalid derivation output name 'drv'"), + hintfmt("while evaluating the attribute 'outputs' of derivation 'foo'")); + + ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = []; }", + TypeError, + hintfmt("derivation cannot have an empty set of outputs"), + hintfmt("while evaluating the attribute 'outputs' of derivation 'foo'")); + + ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = [ \"drv\" ]; }", + TypeError, + hintfmt("invalid derivation output name 'drv'"), + hintfmt("while evaluating the attribute 'outputs' of derivation 'foo'")); + + ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = [ \"out\" \"out\" ]; }", + TypeError, + hintfmt("duplicate derivation output 'out'"), + hintfmt("while evaluating the attribute 'outputs' of derivation 'foo'")); + + ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; __contentAddressed = \"true\"; }", + TypeError, + hintfmt("value is %s while a Boolean was expected", "a string"), + hintfmt("while evaluating the attribute '__contentAddressed' of derivation 'foo'")); + + ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; __impure = \"true\"; }", + TypeError, + hintfmt("value is %s while a Boolean was expected", "a string"), + hintfmt("while evaluating the attribute '__impure' of derivation 'foo'")); + + ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; __impure = \"true\"; }", + TypeError, + hintfmt("value is %s while a Boolean was expected", "a string"), + hintfmt("while evaluating the attribute '__impure' of derivation 'foo'")); + + ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; args = \"foo\"; }", + TypeError, + hintfmt("value is %s while a list was expected", "a string"), + hintfmt("while evaluating the attribute 'args' of derivation 'foo'")); + + ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; args = [ {} ]; }", + TypeError, + hintfmt("cannot coerce %s to a string", "a set"), + hintfmt("while evaluating an element of the argument list")); + + ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; args = [ \"a\" {} ]; }", + TypeError, + hintfmt("cannot coerce %s to a string", "a set"), + hintfmt("while evaluating an element of the argument list")); + + ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; FOO = {}; }", + TypeError, + hintfmt("cannot coerce %s to a string", "a set"), + hintfmt("while evaluating the attribute 'FOO' of derivation 'foo'")); + + } + */ + +} /* namespace nix */ diff --git a/tests/unit/libexpr/flakeref.cc b/tests/unit/libexpr/flakeref.cc new file mode 100644 index 000000000..2b7809b93 --- /dev/null +++ b/tests/unit/libexpr/flakeref.cc @@ -0,0 +1,22 @@ +#include + +#include "flake/flakeref.hh" + +namespace nix { + +/* ----------- tests for flake/flakeref.hh --------------------------------------------------*/ + + /* ---------------------------------------------------------------------------- + * to_string + * --------------------------------------------------------------------------*/ + + TEST(to_string, doesntReencodeUrl) { + auto s = "http://localhost:8181/test/+3d.tar.gz"; + auto flakeref = parseFlakeRef(s); + auto parsed = flakeref.to_string(); + auto expected = "http://localhost:8181/test/%2B3d.tar.gz"; + + ASSERT_EQ(parsed, expected); + } + +} diff --git a/tests/unit/libexpr/json.cc b/tests/unit/libexpr/json.cc new file mode 100644 index 000000000..7586bdd9b --- /dev/null +++ b/tests/unit/libexpr/json.cc @@ -0,0 +1,68 @@ +#include "tests/libexpr.hh" +#include "value-to-json.hh" + +namespace nix { +// Testing the conversion to JSON + + class JSONValueTest : public LibExprTest { + protected: + std::string getJSONValue(Value& value) { + std::stringstream ss; + NixStringContext ps; + printValueAsJSON(state, true, value, noPos, ss, ps); + return ss.str(); + } + }; + + TEST_F(JSONValueTest, null) { + Value v; + v.mkNull(); + ASSERT_EQ(getJSONValue(v), "null"); + } + + TEST_F(JSONValueTest, BoolFalse) { + Value v; + v.mkBool(false); + ASSERT_EQ(getJSONValue(v),"false"); + } + + TEST_F(JSONValueTest, BoolTrue) { + Value v; + v.mkBool(true); + ASSERT_EQ(getJSONValue(v), "true"); + } + + TEST_F(JSONValueTest, IntPositive) { + Value v; + v.mkInt(100); + ASSERT_EQ(getJSONValue(v), "100"); + } + + TEST_F(JSONValueTest, IntNegative) { + Value v; + v.mkInt(-100); + ASSERT_EQ(getJSONValue(v), "-100"); + } + + TEST_F(JSONValueTest, String) { + Value v; + v.mkString("test"); + ASSERT_EQ(getJSONValue(v), "\"test\""); + } + + TEST_F(JSONValueTest, StringQuotes) { + Value v; + + v.mkString("test\""); + ASSERT_EQ(getJSONValue(v), "\"test\\\"\""); + } + + // The dummy store doesn't support writing files. Fails with this exception message: + // C++ exception with description "error: operation 'addToStoreFromDump' is + // not supported by store 'dummy'" thrown in the test body. + TEST_F(JSONValueTest, DISABLED_Path) { + Value v; + v.mkPath("test"); + ASSERT_EQ(getJSONValue(v), "\"/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x\""); + } +} /* namespace nix */ diff --git a/tests/unit/libexpr/local.mk b/tests/unit/libexpr/local.mk new file mode 100644 index 000000000..068dd7a17 --- /dev/null +++ b/tests/unit/libexpr/local.mk @@ -0,0 +1,32 @@ +check: libexpr-tests_RUN + +programs += libexpr-tests + +libexpr-tests_NAME := libnixexpr-tests + +libexpr-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data + +libexpr-tests_DIR := $(d) + +libexpr-tests_INSTALL_DIR := + +libexpr-tests_SOURCES := \ + $(wildcard $(d)/*.cc) \ + $(wildcard $(d)/value/*.cc) + +libexpr-tests_EXTRA_INCLUDES = \ + -I tests/unit/libexpr-support \ + -I tests/unit/libstore-support \ + -I tests/unit/libutil-support \ + -I src/libexpr \ + -I src/libfetchers \ + -I src/libstore \ + -I src/libutil + +libexpr-tests_CXXFLAGS += $(libexpr-tests_EXTRA_INCLUDES) + +libexpr-tests_LIBS = \ + libexpr-test-support libstore-test-support libutils-test-support \ + libexpr libfetchers libstore libutil + +libexpr-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock diff --git a/tests/unit/libexpr/primops.cc b/tests/unit/libexpr/primops.cc new file mode 100644 index 000000000..ce3b5d11f --- /dev/null +++ b/tests/unit/libexpr/primops.cc @@ -0,0 +1,832 @@ +#include +#include + +#include "tests/libexpr.hh" + +namespace nix { + class CaptureLogger : public Logger + { + std::ostringstream oss; + + public: + CaptureLogger() {} + + std::string get() const { + return oss.str(); + } + + void log(Verbosity lvl, std::string_view s) override { + oss << s << std::endl; + } + + void logEI(const ErrorInfo & ei) override { + showErrorInfo(oss, ei, loggerSettings.showTrace.get()); + } + }; + + class CaptureLogging { + Logger * oldLogger; + std::unique_ptr tempLogger; + public: + CaptureLogging() : tempLogger(std::make_unique()) { + oldLogger = logger; + logger = tempLogger.get(); + } + + ~CaptureLogging() { + logger = oldLogger; + } + + std::string get() const { + return tempLogger->get(); + } + }; + + + // Testing eval of PrimOp's + class PrimOpTest : public LibExprTest {}; + + + TEST_F(PrimOpTest, throw) { + ASSERT_THROW(eval("throw \"foo\""), ThrownError); + } + + TEST_F(PrimOpTest, abort) { + ASSERT_THROW(eval("abort \"abort\""), Abort); + } + + TEST_F(PrimOpTest, ceil) { + auto v = eval("builtins.ceil 1.9"); + ASSERT_THAT(v, IsIntEq(2)); + } + + TEST_F(PrimOpTest, floor) { + auto v = eval("builtins.floor 1.9"); + ASSERT_THAT(v, IsIntEq(1)); + } + + TEST_F(PrimOpTest, tryEvalFailure) { + auto v = eval("builtins.tryEval (throw \"\")"); + ASSERT_THAT(v, IsAttrsOfSize(2)); + auto s = createSymbol("success"); + auto p = v.attrs->get(s); + ASSERT_NE(p, nullptr); + ASSERT_THAT(*p->value, IsFalse()); + } + + TEST_F(PrimOpTest, tryEvalSuccess) { + auto v = eval("builtins.tryEval 123"); + ASSERT_THAT(v, IsAttrs()); + auto s = createSymbol("success"); + auto p = v.attrs->get(s); + ASSERT_NE(p, nullptr); + ASSERT_THAT(*p->value, IsTrue()); + s = createSymbol("value"); + p = v.attrs->get(s); + ASSERT_NE(p, nullptr); + ASSERT_THAT(*p->value, IsIntEq(123)); + } + + TEST_F(PrimOpTest, getEnv) { + setenv("_NIX_UNIT_TEST_ENV_VALUE", "test value", 1); + auto v = eval("builtins.getEnv \"_NIX_UNIT_TEST_ENV_VALUE\""); + ASSERT_THAT(v, IsStringEq("test value")); + } + + TEST_F(PrimOpTest, seq) { + ASSERT_THROW(eval("let x = throw \"test\"; in builtins.seq x { }"), ThrownError); + } + + TEST_F(PrimOpTest, seqNotDeep) { + auto v = eval("let x = { z = throw \"test\"; }; in builtins.seq x { }"); + ASSERT_THAT(v, IsAttrs()); + } + + TEST_F(PrimOpTest, deepSeq) { + ASSERT_THROW(eval("let x = { z = throw \"test\"; }; in builtins.deepSeq x { }"), ThrownError); + } + + TEST_F(PrimOpTest, trace) { + CaptureLogging l; + auto v = eval("builtins.trace \"test string 123\" 123"); + ASSERT_THAT(v, IsIntEq(123)); + auto text = l.get(); + ASSERT_NE(text.find("test string 123"), std::string::npos); + } + + TEST_F(PrimOpTest, placeholder) { + auto v = eval("builtins.placeholder \"out\""); + ASSERT_THAT(v, IsStringEq("/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9")); + } + + TEST_F(PrimOpTest, baseNameOf) { + auto v = eval("builtins.baseNameOf /some/path"); + ASSERT_THAT(v, IsStringEq("path")); + } + + TEST_F(PrimOpTest, dirOf) { + auto v = eval("builtins.dirOf /some/path"); + ASSERT_THAT(v, IsPathEq("/some")); + } + + TEST_F(PrimOpTest, attrValues) { + auto v = eval("builtins.attrValues { x = \"foo\"; a = 1; }"); + ASSERT_THAT(v, IsListOfSize(2)); + ASSERT_THAT(*v.listElems()[0], IsIntEq(1)); + ASSERT_THAT(*v.listElems()[1], IsStringEq("foo")); + } + + TEST_F(PrimOpTest, getAttr) { + auto v = eval("builtins.getAttr \"x\" { x = \"foo\"; }"); + ASSERT_THAT(v, IsStringEq("foo")); + } + + TEST_F(PrimOpTest, getAttrNotFound) { + // FIXME: TypeError is really bad here, also the error wording is worse + // than on Nix <=2.3 + ASSERT_THROW(eval("builtins.getAttr \"y\" { }"), TypeError); + } + + TEST_F(PrimOpTest, unsafeGetAttrPos) { + // The `y` attribute is at position + const char* expr = "builtins.unsafeGetAttrPos \"y\" { y = \"x\"; }"; + auto v = eval(expr); + ASSERT_THAT(v, IsNull()); + } + + TEST_F(PrimOpTest, hasAttr) { + auto v = eval("builtins.hasAttr \"x\" { x = 1; }"); + ASSERT_THAT(v, IsTrue()); + } + + TEST_F(PrimOpTest, hasAttrNotFound) { + auto v = eval("builtins.hasAttr \"x\" { }"); + ASSERT_THAT(v, IsFalse()); + } + + TEST_F(PrimOpTest, isAttrs) { + auto v = eval("builtins.isAttrs {}"); + ASSERT_THAT(v, IsTrue()); + } + + TEST_F(PrimOpTest, isAttrsFalse) { + auto v = eval("builtins.isAttrs null"); + ASSERT_THAT(v, IsFalse()); + } + + TEST_F(PrimOpTest, removeAttrs) { + auto v = eval("builtins.removeAttrs { x = 1; } [\"x\"]"); + ASSERT_THAT(v, IsAttrsOfSize(0)); + } + + TEST_F(PrimOpTest, removeAttrsRetains) { + auto v = eval("builtins.removeAttrs { x = 1; y = 2; } [\"x\"]"); + ASSERT_THAT(v, IsAttrsOfSize(1)); + ASSERT_NE(v.attrs->find(createSymbol("y")), nullptr); + } + + TEST_F(PrimOpTest, listToAttrsEmptyList) { + auto v = eval("builtins.listToAttrs []"); + ASSERT_THAT(v, IsAttrsOfSize(0)); + ASSERT_EQ(v.type(), nAttrs); + ASSERT_EQ(v.attrs->size(), 0); + } + + TEST_F(PrimOpTest, listToAttrsNotFieldName) { + ASSERT_THROW(eval("builtins.listToAttrs [{}]"), Error); + } + + TEST_F(PrimOpTest, listToAttrs) { + auto v = eval("builtins.listToAttrs [ { name = \"key\"; value = 123; } ]"); + ASSERT_THAT(v, IsAttrsOfSize(1)); + auto key = v.attrs->find(createSymbol("key")); + ASSERT_NE(key, nullptr); + ASSERT_THAT(*key->value, IsIntEq(123)); + } + + TEST_F(PrimOpTest, intersectAttrs) { + auto v = eval("builtins.intersectAttrs { a = 1; b = 2; } { b = 3; c = 4; }"); + ASSERT_THAT(v, IsAttrsOfSize(1)); + auto b = v.attrs->find(createSymbol("b")); + ASSERT_NE(b, nullptr); + ASSERT_THAT(*b->value, IsIntEq(3)); + } + + TEST_F(PrimOpTest, catAttrs) { + auto v = eval("builtins.catAttrs \"a\" [{a = 1;} {b = 0;} {a = 2;}]"); + ASSERT_THAT(v, IsListOfSize(2)); + ASSERT_THAT(*v.listElems()[0], IsIntEq(1)); + ASSERT_THAT(*v.listElems()[1], IsIntEq(2)); + } + + TEST_F(PrimOpTest, functionArgs) { + auto v = eval("builtins.functionArgs ({ x, y ? 123}: 1)"); + ASSERT_THAT(v, IsAttrsOfSize(2)); + + auto x = v.attrs->find(createSymbol("x")); + ASSERT_NE(x, nullptr); + ASSERT_THAT(*x->value, IsFalse()); + + auto y = v.attrs->find(createSymbol("y")); + ASSERT_NE(y, nullptr); + ASSERT_THAT(*y->value, IsTrue()); + } + + TEST_F(PrimOpTest, mapAttrs) { + auto v = eval("builtins.mapAttrs (name: value: value * 10) { a = 1; b = 2; }"); + ASSERT_THAT(v, IsAttrsOfSize(2)); + + auto a = v.attrs->find(createSymbol("a")); + ASSERT_NE(a, nullptr); + ASSERT_THAT(*a->value, IsThunk()); + state.forceValue(*a->value, noPos); + ASSERT_THAT(*a->value, IsIntEq(10)); + + auto b = v.attrs->find(createSymbol("b")); + ASSERT_NE(b, nullptr); + ASSERT_THAT(*b->value, IsThunk()); + state.forceValue(*b->value, noPos); + ASSERT_THAT(*b->value, IsIntEq(20)); + } + + TEST_F(PrimOpTest, isList) { + auto v = eval("builtins.isList []"); + ASSERT_THAT(v, IsTrue()); + } + + TEST_F(PrimOpTest, isListFalse) { + auto v = eval("builtins.isList null"); + ASSERT_THAT(v, IsFalse()); + } + + TEST_F(PrimOpTest, elemtAt) { + auto v = eval("builtins.elemAt [0 1 2 3] 3"); + ASSERT_THAT(v, IsIntEq(3)); + } + + TEST_F(PrimOpTest, elemtAtOutOfBounds) { + ASSERT_THROW(eval("builtins.elemAt [0 1 2 3] 5"), Error); + } + + TEST_F(PrimOpTest, head) { + auto v = eval("builtins.head [ 3 2 1 0 ]"); + ASSERT_THAT(v, IsIntEq(3)); + } + + TEST_F(PrimOpTest, headEmpty) { + ASSERT_THROW(eval("builtins.head [ ]"), Error); + } + + TEST_F(PrimOpTest, headWrongType) { + ASSERT_THROW(eval("builtins.head { }"), Error); + } + + TEST_F(PrimOpTest, tail) { + auto v = eval("builtins.tail [ 3 2 1 0 ]"); + ASSERT_THAT(v, IsListOfSize(3)); + for (const auto [n, elem] : enumerate(v.listItems())) + ASSERT_THAT(*elem, IsIntEq(2 - static_cast(n))); + } + + TEST_F(PrimOpTest, tailEmpty) { + ASSERT_THROW(eval("builtins.tail []"), Error); + } + + TEST_F(PrimOpTest, map) { + auto v = eval("map (x: \"foo\" + x) [ \"bar\" \"bla\" \"abc\" ]"); + ASSERT_THAT(v, IsListOfSize(3)); + auto elem = v.listElems()[0]; + ASSERT_THAT(*elem, IsThunk()); + state.forceValue(*elem, noPos); + ASSERT_THAT(*elem, IsStringEq("foobar")); + + elem = v.listElems()[1]; + ASSERT_THAT(*elem, IsThunk()); + state.forceValue(*elem, noPos); + ASSERT_THAT(*elem, IsStringEq("foobla")); + + elem = v.listElems()[2]; + ASSERT_THAT(*elem, IsThunk()); + state.forceValue(*elem, noPos); + ASSERT_THAT(*elem, IsStringEq("fooabc")); + } + + TEST_F(PrimOpTest, filter) { + auto v = eval("builtins.filter (x: x == 2) [ 3 2 3 2 3 2 ]"); + ASSERT_THAT(v, IsListOfSize(3)); + for (const auto elem : v.listItems()) + ASSERT_THAT(*elem, IsIntEq(2)); + } + + TEST_F(PrimOpTest, elemTrue) { + auto v = eval("builtins.elem 3 [ 1 2 3 4 5 ]"); + ASSERT_THAT(v, IsTrue()); + } + + TEST_F(PrimOpTest, elemFalse) { + auto v = eval("builtins.elem 6 [ 1 2 3 4 5 ]"); + ASSERT_THAT(v, IsFalse()); + } + + TEST_F(PrimOpTest, concatLists) { + auto v = eval("builtins.concatLists [[1 2] [3 4]]"); + ASSERT_THAT(v, IsListOfSize(4)); + for (const auto [i, elem] : enumerate(v.listItems())) + ASSERT_THAT(*elem, IsIntEq(static_cast(i)+1)); + } + + TEST_F(PrimOpTest, length) { + auto v = eval("builtins.length [ 1 2 3 ]"); + ASSERT_THAT(v, IsIntEq(3)); + } + + TEST_F(PrimOpTest, foldStrict) { + auto v = eval("builtins.foldl' (a: b: a + b) 0 [1 2 3]"); + ASSERT_THAT(v, IsIntEq(6)); + } + + TEST_F(PrimOpTest, anyTrue) { + auto v = eval("builtins.any (x: x == 2) [ 1 2 3 ]"); + ASSERT_THAT(v, IsTrue()); + } + + TEST_F(PrimOpTest, anyFalse) { + auto v = eval("builtins.any (x: x == 5) [ 1 2 3 ]"); + ASSERT_THAT(v, IsFalse()); + } + + TEST_F(PrimOpTest, allTrue) { + auto v = eval("builtins.all (x: x > 0) [ 1 2 3 ]"); + ASSERT_THAT(v, IsTrue()); + } + + TEST_F(PrimOpTest, allFalse) { + auto v = eval("builtins.all (x: x <= 0) [ 1 2 3 ]"); + ASSERT_THAT(v, IsFalse()); + } + + TEST_F(PrimOpTest, genList) { + auto v = eval("builtins.genList (x: x + 1) 3"); + ASSERT_EQ(v.type(), nList); + ASSERT_EQ(v.listSize(), 3); + for (const auto [i, elem] : enumerate(v.listItems())) { + ASSERT_THAT(*elem, IsThunk()); + state.forceValue(*elem, noPos); + ASSERT_THAT(*elem, IsIntEq(static_cast(i)+1)); + } + } + + TEST_F(PrimOpTest, sortLessThan) { + auto v = eval("builtins.sort builtins.lessThan [ 483 249 526 147 42 77 ]"); + ASSERT_EQ(v.type(), nList); + ASSERT_EQ(v.listSize(), 6); + + const std::vector numbers = { 42, 77, 147, 249, 483, 526 }; + for (const auto [n, elem] : enumerate(v.listItems())) + ASSERT_THAT(*elem, IsIntEq(numbers[n])); + } + + TEST_F(PrimOpTest, partition) { + auto v = eval("builtins.partition (x: x > 10) [1 23 9 3 42]"); + ASSERT_THAT(v, IsAttrsOfSize(2)); + + auto right = v.attrs->get(createSymbol("right")); + ASSERT_NE(right, nullptr); + ASSERT_THAT(*right->value, IsListOfSize(2)); + ASSERT_THAT(*right->value->listElems()[0], IsIntEq(23)); + ASSERT_THAT(*right->value->listElems()[1], IsIntEq(42)); + + auto wrong = v.attrs->get(createSymbol("wrong")); + ASSERT_NE(wrong, nullptr); + ASSERT_EQ(wrong->value->type(), nList); + ASSERT_EQ(wrong->value->listSize(), 3); + ASSERT_THAT(*wrong->value, IsListOfSize(3)); + ASSERT_THAT(*wrong->value->listElems()[0], IsIntEq(1)); + ASSERT_THAT(*wrong->value->listElems()[1], IsIntEq(9)); + ASSERT_THAT(*wrong->value->listElems()[2], IsIntEq(3)); + } + + TEST_F(PrimOpTest, concatMap) { + auto v = eval("builtins.concatMap (x: x ++ [0]) [ [1 2] [3 4] ]"); + ASSERT_EQ(v.type(), nList); + ASSERT_EQ(v.listSize(), 6); + + const std::vector numbers = { 1, 2, 0, 3, 4, 0 }; + for (const auto [n, elem] : enumerate(v.listItems())) + ASSERT_THAT(*elem, IsIntEq(numbers[n])); + } + + TEST_F(PrimOpTest, addInt) { + auto v = eval("builtins.add 3 5"); + ASSERT_THAT(v, IsIntEq(8)); + } + + TEST_F(PrimOpTest, addFloat) { + auto v = eval("builtins.add 3.0 5.0"); + ASSERT_THAT(v, IsFloatEq(8.0)); + } + + TEST_F(PrimOpTest, addFloatToInt) { + auto v = eval("builtins.add 3.0 5"); + ASSERT_THAT(v, IsFloatEq(8.0)); + + v = eval("builtins.add 3 5.0"); + ASSERT_THAT(v, IsFloatEq(8.0)); + } + + TEST_F(PrimOpTest, subInt) { + auto v = eval("builtins.sub 5 2"); + ASSERT_THAT(v, IsIntEq(3)); + } + + TEST_F(PrimOpTest, subFloat) { + auto v = eval("builtins.sub 5.0 2.0"); + ASSERT_THAT(v, IsFloatEq(3.0)); + } + + TEST_F(PrimOpTest, subFloatFromInt) { + auto v = eval("builtins.sub 5.0 2"); + ASSERT_THAT(v, IsFloatEq(3.0)); + + v = eval("builtins.sub 4 2.0"); + ASSERT_THAT(v, IsFloatEq(2.0)); + } + + TEST_F(PrimOpTest, mulInt) { + auto v = eval("builtins.mul 3 5"); + ASSERT_THAT(v, IsIntEq(15)); + } + + TEST_F(PrimOpTest, mulFloat) { + auto v = eval("builtins.mul 3.0 5.0"); + ASSERT_THAT(v, IsFloatEq(15.0)); + } + + TEST_F(PrimOpTest, mulFloatMixed) { + auto v = eval("builtins.mul 3 5.0"); + ASSERT_THAT(v, IsFloatEq(15.0)); + + v = eval("builtins.mul 2.0 5"); + ASSERT_THAT(v, IsFloatEq(10.0)); + } + + TEST_F(PrimOpTest, divInt) { + auto v = eval("builtins.div 5 (-1)"); + ASSERT_THAT(v, IsIntEq(-5)); + } + + TEST_F(PrimOpTest, divIntZero) { + ASSERT_THROW(eval("builtins.div 5 0"), EvalError); + } + + TEST_F(PrimOpTest, divFloat) { + auto v = eval("builtins.div 5.0 (-1)"); + ASSERT_THAT(v, IsFloatEq(-5.0)); + } + + TEST_F(PrimOpTest, divFloatZero) { + ASSERT_THROW(eval("builtins.div 5.0 0.0"), EvalError); + } + + TEST_F(PrimOpTest, bitOr) { + auto v = eval("builtins.bitOr 1 2"); + ASSERT_THAT(v, IsIntEq(3)); + } + + TEST_F(PrimOpTest, bitXor) { + auto v = eval("builtins.bitXor 3 2"); + ASSERT_THAT(v, IsIntEq(1)); + } + + TEST_F(PrimOpTest, lessThanFalse) { + auto v = eval("builtins.lessThan 3 1"); + ASSERT_THAT(v, IsFalse()); + } + + TEST_F(PrimOpTest, lessThanTrue) { + auto v = eval("builtins.lessThan 1 3"); + ASSERT_THAT(v, IsTrue()); + } + + TEST_F(PrimOpTest, toStringAttrsThrows) { + ASSERT_THROW(eval("builtins.toString {}"), EvalError); + } + + TEST_F(PrimOpTest, toStringLambdaThrows) { + ASSERT_THROW(eval("builtins.toString (x: x)"), EvalError); + } + + class ToStringPrimOpTest : + public PrimOpTest, + public testing::WithParamInterface> + {}; + + TEST_P(ToStringPrimOpTest, toString) { + const auto [input, output] = GetParam(); + auto v = eval(input); + ASSERT_THAT(v, IsStringEq(output)); + } + +#define CASE(input, output) (std::make_tuple(std::string_view("builtins.toString " input), std::string_view(output))) + INSTANTIATE_TEST_SUITE_P( + toString, + ToStringPrimOpTest, + testing::Values( + CASE(R"("foo")", "foo"), + CASE(R"(1)", "1"), + CASE(R"([1 2 3])", "1 2 3"), + CASE(R"(.123)", "0.123000"), + CASE(R"(true)", "1"), + CASE(R"(false)", ""), + CASE(R"(null)", ""), + CASE(R"({ v = "bar"; __toString = self: self.v; })", "bar"), + CASE(R"({ v = "bar"; __toString = self: self.v; outPath = "foo"; })", "bar"), + CASE(R"({ outPath = "foo"; })", "foo"), + CASE(R"(./test)", "/test") + ) + ); +#undef CASE + + TEST_F(PrimOpTest, substring){ + auto v = eval("builtins.substring 0 3 \"nixos\""); + ASSERT_THAT(v, IsStringEq("nix")); + } + + TEST_F(PrimOpTest, substringSmallerString){ + auto v = eval("builtins.substring 0 3 \"n\""); + ASSERT_THAT(v, IsStringEq("n")); + } + + TEST_F(PrimOpTest, substringEmptyString){ + auto v = eval("builtins.substring 1 3 \"\""); + ASSERT_THAT(v, IsStringEq("")); + } + + TEST_F(PrimOpTest, stringLength) { + auto v = eval("builtins.stringLength \"123\""); + ASSERT_THAT(v, IsIntEq(3)); + } + TEST_F(PrimOpTest, hashStringMd5) { + auto v = eval("builtins.hashString \"md5\" \"asdf\""); + ASSERT_THAT(v, IsStringEq("912ec803b2ce49e4a541068d495ab570")); + } + + TEST_F(PrimOpTest, hashStringSha1) { + auto v = eval("builtins.hashString \"sha1\" \"asdf\""); + ASSERT_THAT(v, IsStringEq("3da541559918a808c2402bba5012f6c60b27661c")); + } + + TEST_F(PrimOpTest, hashStringSha256) { + auto v = eval("builtins.hashString \"sha256\" \"asdf\""); + ASSERT_THAT(v, IsStringEq("f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b")); + } + + TEST_F(PrimOpTest, hashStringSha512) { + auto v = eval("builtins.hashString \"sha512\" \"asdf\""); + ASSERT_THAT(v, IsStringEq("401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b3727429080fb337591abd3e44453b954555b7a0812e1081c39b740293f765eae731f5a65ed1")); + } + + TEST_F(PrimOpTest, hashStringInvalidHashType) { + ASSERT_THROW(eval("builtins.hashString \"foobar\" \"asdf\""), Error); + } + + TEST_F(PrimOpTest, nixPath) { + auto v = eval("builtins.nixPath"); + ASSERT_EQ(v.type(), nList); + // We can't test much more as currently the EvalSettings are a global + // that we can't easily swap / replace + } + + TEST_F(PrimOpTest, langVersion) { + auto v = eval("builtins.langVersion"); + ASSERT_EQ(v.type(), nInt); + } + + TEST_F(PrimOpTest, storeDir) { + auto v = eval("builtins.storeDir"); + ASSERT_THAT(v, IsStringEq(settings.nixStore)); + } + + TEST_F(PrimOpTest, nixVersion) { + auto v = eval("builtins.nixVersion"); + ASSERT_THAT(v, IsStringEq(nixVersion)); + } + + TEST_F(PrimOpTest, currentSystem) { + auto v = eval("builtins.currentSystem"); + ASSERT_THAT(v, IsStringEq(settings.thisSystem.get())); + } + + TEST_F(PrimOpTest, derivation) { + auto v = eval("derivation"); + ASSERT_EQ(v.type(), nFunction); + ASSERT_TRUE(v.isLambda()); + ASSERT_NE(v.lambda.fun, nullptr); + ASSERT_TRUE(v.lambda.fun->hasFormals()); + } + + TEST_F(PrimOpTest, currentTime) { + auto v = eval("builtins.currentTime"); + ASSERT_EQ(v.type(), nInt); + ASSERT_TRUE(v.integer > 0); + } + + TEST_F(PrimOpTest, splitVersion) { + auto v = eval("builtins.splitVersion \"1.2.3git\""); + ASSERT_THAT(v, IsListOfSize(4)); + + const std::vector strings = { "1", "2", "3", "git" }; + for (const auto [n, p] : enumerate(v.listItems())) + ASSERT_THAT(*p, IsStringEq(strings[n])); + } + + class CompareVersionsPrimOpTest : + public PrimOpTest, + public testing::WithParamInterface> + {}; + + TEST_P(CompareVersionsPrimOpTest, compareVersions) { + auto [expression, expectation] = GetParam(); + auto v = eval(expression); + ASSERT_THAT(v, IsIntEq(expectation)); + } + +#define CASE(a, b, expected) (std::make_tuple("builtins.compareVersions \"" #a "\" \"" #b "\"", expected)) + INSTANTIATE_TEST_SUITE_P( + compareVersions, + CompareVersionsPrimOpTest, + testing::Values( + // The first two are weird cases. Intuition tells they should + // be the same but they aren't. + CASE(1.0, 1.0.0, -1), + CASE(1.0.0, 1.0, 1), + // the following are from the nix-env manual: + CASE(1.0, 2.3, -1), + CASE(2.1, 2.3, -1), + CASE(2.3, 2.3, 0), + CASE(2.5, 2.3, 1), + CASE(3.1, 2.3, 1), + CASE(2.3.1, 2.3, 1), + CASE(2.3.1, 2.3a, 1), + CASE(2.3pre1, 2.3, -1), + CASE(2.3pre3, 2.3pre12, -1), + CASE(2.3a, 2.3c, -1), + CASE(2.3pre1, 2.3c, -1), + CASE(2.3pre1, 2.3q, -1) + ) + ); +#undef CASE + + + class ParseDrvNamePrimOpTest : + public PrimOpTest, + public testing::WithParamInterface> + {}; + + TEST_P(ParseDrvNamePrimOpTest, parseDrvName) { + auto [input, expectedName, expectedVersion] = GetParam(); + const auto expr = fmt("builtins.parseDrvName \"%1%\"", input); + auto v = eval(expr); + ASSERT_THAT(v, IsAttrsOfSize(2)); + + auto name = v.attrs->find(createSymbol("name")); + ASSERT_TRUE(name); + ASSERT_THAT(*name->value, IsStringEq(expectedName)); + + auto version = v.attrs->find(createSymbol("version")); + ASSERT_TRUE(version); + ASSERT_THAT(*version->value, IsStringEq(expectedVersion)); + } + + INSTANTIATE_TEST_SUITE_P( + parseDrvName, + ParseDrvNamePrimOpTest, + testing::Values( + std::make_tuple("nix-0.12pre12876", "nix", "0.12pre12876"), + std::make_tuple("a-b-c-1234pre5+git", "a-b-c", "1234pre5+git") + ) + ); + + TEST_F(PrimOpTest, replaceStrings) { + // FIXME: add a test that verifies the string context is as expected + auto v = eval("builtins.replaceStrings [\"oo\" \"a\"] [\"a\" \"i\"] \"foobar\""); + ASSERT_EQ(v.type(), nString); + ASSERT_EQ(v.string.s, std::string_view("fabir")); + } + + TEST_F(PrimOpTest, concatStringsSep) { + // FIXME: add a test that verifies the string context is as expected + auto v = eval("builtins.concatStringsSep \"%\" [\"foo\" \"bar\" \"baz\"]"); + ASSERT_EQ(v.type(), nString); + ASSERT_EQ(std::string_view(v.string.s), "foo%bar%baz"); + } + + TEST_F(PrimOpTest, split1) { + // v = [ "" [ "a" ] "c" ] + auto v = eval("builtins.split \"(a)b\" \"abc\""); + ASSERT_THAT(v, IsListOfSize(3)); + + ASSERT_THAT(*v.listElems()[0], IsStringEq("")); + + ASSERT_THAT(*v.listElems()[1], IsListOfSize(1)); + ASSERT_THAT(*v.listElems()[1]->listElems()[0], IsStringEq("a")); + + ASSERT_THAT(*v.listElems()[2], IsStringEq("c")); + } + + TEST_F(PrimOpTest, split2) { + // v is expected to be a list [ "" [ "a" ] "b" [ "c"] "" ] + auto v = eval("builtins.split \"([ac])\" \"abc\""); + ASSERT_THAT(v, IsListOfSize(5)); + + ASSERT_THAT(*v.listElems()[0], IsStringEq("")); + + ASSERT_THAT(*v.listElems()[1], IsListOfSize(1)); + ASSERT_THAT(*v.listElems()[1]->listElems()[0], IsStringEq("a")); + + ASSERT_THAT(*v.listElems()[2], IsStringEq("b")); + + ASSERT_THAT(*v.listElems()[3], IsListOfSize(1)); + ASSERT_THAT(*v.listElems()[3]->listElems()[0], IsStringEq("c")); + + ASSERT_THAT(*v.listElems()[4], IsStringEq("")); + } + + TEST_F(PrimOpTest, split3) { + auto v = eval("builtins.split \"(a)|(c)\" \"abc\""); + ASSERT_THAT(v, IsListOfSize(5)); + + // First list element + ASSERT_THAT(*v.listElems()[0], IsStringEq("")); + + // 2nd list element is a list [ "" null ] + ASSERT_THAT(*v.listElems()[1], IsListOfSize(2)); + ASSERT_THAT(*v.listElems()[1]->listElems()[0], IsStringEq("a")); + ASSERT_THAT(*v.listElems()[1]->listElems()[1], IsNull()); + + // 3rd element + ASSERT_THAT(*v.listElems()[2], IsStringEq("b")); + + // 4th element is a list: [ null "c" ] + ASSERT_THAT(*v.listElems()[3], IsListOfSize(2)); + ASSERT_THAT(*v.listElems()[3]->listElems()[0], IsNull()); + ASSERT_THAT(*v.listElems()[3]->listElems()[1], IsStringEq("c")); + + // 5th element is the empty string + ASSERT_THAT(*v.listElems()[4], IsStringEq("")); + } + + TEST_F(PrimOpTest, split4) { + auto v = eval("builtins.split \"([[:upper:]]+)\" \" FOO \""); + ASSERT_THAT(v, IsListOfSize(3)); + auto first = v.listElems()[0]; + auto second = v.listElems()[1]; + auto third = v.listElems()[2]; + + ASSERT_THAT(*first, IsStringEq(" ")); + + ASSERT_THAT(*second, IsListOfSize(1)); + ASSERT_THAT(*second->listElems()[0], IsStringEq("FOO")); + + ASSERT_THAT(*third, IsStringEq(" ")); + } + + TEST_F(PrimOpTest, match1) { + auto v = eval("builtins.match \"ab\" \"abc\""); + ASSERT_THAT(v, IsNull()); + } + + TEST_F(PrimOpTest, match2) { + auto v = eval("builtins.match \"abc\" \"abc\""); + ASSERT_THAT(v, IsListOfSize(0)); + } + + TEST_F(PrimOpTest, match3) { + auto v = eval("builtins.match \"a(b)(c)\" \"abc\""); + ASSERT_THAT(v, IsListOfSize(2)); + ASSERT_THAT(*v.listElems()[0], IsStringEq("b")); + ASSERT_THAT(*v.listElems()[1], IsStringEq("c")); + } + + TEST_F(PrimOpTest, match4) { + auto v = eval("builtins.match \"[[:space:]]+([[:upper:]]+)[[:space:]]+\" \" FOO \""); + ASSERT_THAT(v, IsListOfSize(1)); + ASSERT_THAT(*v.listElems()[0], IsStringEq("FOO")); + } + + TEST_F(PrimOpTest, attrNames) { + auto v = eval("builtins.attrNames { x = 1; y = 2; z = 3; a = 2; }"); + ASSERT_THAT(v, IsListOfSize(4)); + + // ensure that the list is sorted + const std::vector expected { "a", "x", "y", "z" }; + for (const auto [n, elem] : enumerate(v.listItems())) + ASSERT_THAT(*elem, IsStringEq(expected[n])); + } + + TEST_F(PrimOpTest, genericClosure_not_strict) { + // Operator should not be used when startSet is empty + auto v = eval("builtins.genericClosure { startSet = []; }"); + ASSERT_THAT(v, IsListOfSize(0)); + } +} /* namespace nix */ diff --git a/tests/unit/libexpr/search-path.cc b/tests/unit/libexpr/search-path.cc new file mode 100644 index 000000000..dbe7ab95f --- /dev/null +++ b/tests/unit/libexpr/search-path.cc @@ -0,0 +1,90 @@ +#include +#include + +#include "search-path.hh" + +namespace nix { + +TEST(SearchPathElem, parse_justPath) { + ASSERT_EQ( + SearchPath::Elem::parse("foo"), + (SearchPath::Elem { + .prefix = SearchPath::Prefix { .s = "" }, + .path = SearchPath::Path { .s = "foo" }, + })); +} + +TEST(SearchPathElem, parse_emptyPrefix) { + ASSERT_EQ( + SearchPath::Elem::parse("=foo"), + (SearchPath::Elem { + .prefix = SearchPath::Prefix { .s = "" }, + .path = SearchPath::Path { .s = "foo" }, + })); +} + +TEST(SearchPathElem, parse_oneEq) { + ASSERT_EQ( + SearchPath::Elem::parse("foo=bar"), + (SearchPath::Elem { + .prefix = SearchPath::Prefix { .s = "foo" }, + .path = SearchPath::Path { .s = "bar" }, + })); +} + +TEST(SearchPathElem, parse_twoEqs) { + ASSERT_EQ( + SearchPath::Elem::parse("foo=bar=baz"), + (SearchPath::Elem { + .prefix = SearchPath::Prefix { .s = "foo" }, + .path = SearchPath::Path { .s = "bar=baz" }, + })); +} + + +TEST(SearchPathElem, suffixIfPotentialMatch_justPath) { + SearchPath::Prefix prefix { .s = "" }; + ASSERT_EQ(prefix.suffixIfPotentialMatch("any/thing"), std::optional { "any/thing" }); +} + +TEST(SearchPathElem, suffixIfPotentialMatch_misleadingPrefix1) { + SearchPath::Prefix prefix { .s = "foo" }; + ASSERT_EQ(prefix.suffixIfPotentialMatch("fooX"), std::nullopt); +} + +TEST(SearchPathElem, suffixIfPotentialMatch_misleadingPrefix2) { + SearchPath::Prefix prefix { .s = "foo" }; + ASSERT_EQ(prefix.suffixIfPotentialMatch("fooX/bar"), std::nullopt); +} + +TEST(SearchPathElem, suffixIfPotentialMatch_partialPrefix) { + SearchPath::Prefix prefix { .s = "fooX" }; + ASSERT_EQ(prefix.suffixIfPotentialMatch("foo"), std::nullopt); +} + +TEST(SearchPathElem, suffixIfPotentialMatch_exactPrefix) { + SearchPath::Prefix prefix { .s = "foo" }; + ASSERT_EQ(prefix.suffixIfPotentialMatch("foo"), std::optional { "" }); +} + +TEST(SearchPathElem, suffixIfPotentialMatch_multiKey) { + SearchPath::Prefix prefix { .s = "foo/bar" }; + ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/bar/baz"), std::optional { "baz" }); +} + +TEST(SearchPathElem, suffixIfPotentialMatch_trailingSlash) { + SearchPath::Prefix prefix { .s = "foo" }; + ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/"), std::optional { "" }); +} + +TEST(SearchPathElem, suffixIfPotentialMatch_trailingDoubleSlash) { + SearchPath::Prefix prefix { .s = "foo" }; + ASSERT_EQ(prefix.suffixIfPotentialMatch("foo//"), std::optional { "/" }); +} + +TEST(SearchPathElem, suffixIfPotentialMatch_trailingPath) { + SearchPath::Prefix prefix { .s = "foo" }; + ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/bar/baz"), std::optional { "bar/baz" }); +} + +} diff --git a/tests/unit/libexpr/trivial.cc b/tests/unit/libexpr/trivial.cc new file mode 100644 index 000000000..171727ac7 --- /dev/null +++ b/tests/unit/libexpr/trivial.cc @@ -0,0 +1,196 @@ +#include "tests/libexpr.hh" + +namespace nix { + // Testing of trivial expressions + class TrivialExpressionTest : public LibExprTest {}; + + TEST_F(TrivialExpressionTest, true) { + auto v = eval("true"); + ASSERT_THAT(v, IsTrue()); + } + + TEST_F(TrivialExpressionTest, false) { + auto v = eval("false"); + ASSERT_THAT(v, IsFalse()); + } + + TEST_F(TrivialExpressionTest, null) { + auto v = eval("null"); + ASSERT_THAT(v, IsNull()); + } + + TEST_F(TrivialExpressionTest, 1) { + auto v = eval("1"); + ASSERT_THAT(v, IsIntEq(1)); + } + + TEST_F(TrivialExpressionTest, 1plus1) { + auto v = eval("1+1"); + ASSERT_THAT(v, IsIntEq(2)); + } + + TEST_F(TrivialExpressionTest, minus1) { + auto v = eval("-1"); + ASSERT_THAT(v, IsIntEq(-1)); + } + + TEST_F(TrivialExpressionTest, 1minus1) { + auto v = eval("1-1"); + ASSERT_THAT(v, IsIntEq(0)); + } + + TEST_F(TrivialExpressionTest, lambdaAdd) { + auto v = eval("let add = a: b: a + b; in add 1 2"); + ASSERT_THAT(v, IsIntEq(3)); + } + + TEST_F(TrivialExpressionTest, list) { + auto v = eval("[]"); + ASSERT_THAT(v, IsListOfSize(0)); + } + + TEST_F(TrivialExpressionTest, attrs) { + auto v = eval("{}"); + ASSERT_THAT(v, IsAttrsOfSize(0)); + } + + TEST_F(TrivialExpressionTest, float) { + auto v = eval("1.234"); + ASSERT_THAT(v, IsFloatEq(1.234)); + } + + TEST_F(TrivialExpressionTest, updateAttrs) { + auto v = eval("{ a = 1; } // { b = 2; a = 3; }"); + ASSERT_THAT(v, IsAttrsOfSize(2)); + auto a = v.attrs->find(createSymbol("a")); + ASSERT_NE(a, nullptr); + ASSERT_THAT(*a->value, IsIntEq(3)); + + auto b = v.attrs->find(createSymbol("b")); + ASSERT_NE(b, nullptr); + ASSERT_THAT(*b->value, IsIntEq(2)); + } + + TEST_F(TrivialExpressionTest, hasAttrOpFalse) { + auto v = eval("{} ? a"); + ASSERT_THAT(v, IsFalse()); + } + + TEST_F(TrivialExpressionTest, hasAttrOpTrue) { + auto v = eval("{ a = 123; } ? a"); + ASSERT_THAT(v, IsTrue()); + } + + TEST_F(TrivialExpressionTest, withFound) { + auto v = eval("with { a = 23; }; a"); + ASSERT_THAT(v, IsIntEq(23)); + } + + TEST_F(TrivialExpressionTest, withNotFound) { + ASSERT_THROW(eval("with {}; a"), Error); + } + + TEST_F(TrivialExpressionTest, withOverride) { + auto v = eval("with { a = 23; }; with { a = 42; }; a"); + ASSERT_THAT(v, IsIntEq(42)); + } + + TEST_F(TrivialExpressionTest, letOverWith) { + auto v = eval("let a = 23; in with { a = 1; }; a"); + ASSERT_THAT(v, IsIntEq(23)); + } + + TEST_F(TrivialExpressionTest, multipleLet) { + auto v = eval("let a = 23; in let a = 42; in a"); + ASSERT_THAT(v, IsIntEq(42)); + } + + TEST_F(TrivialExpressionTest, defaultFunctionArgs) { + auto v = eval("({ a ? 123 }: a) {}"); + ASSERT_THAT(v, IsIntEq(123)); + } + + TEST_F(TrivialExpressionTest, defaultFunctionArgsOverride) { + auto v = eval("({ a ? 123 }: a) { a = 5; }"); + ASSERT_THAT(v, IsIntEq(5)); + } + + TEST_F(TrivialExpressionTest, defaultFunctionArgsCaptureBack) { + auto v = eval("({ a ? 123 }@args: args) {}"); + ASSERT_THAT(v, IsAttrsOfSize(0)); + } + + TEST_F(TrivialExpressionTest, defaultFunctionArgsCaptureFront) { + auto v = eval("(args@{ a ? 123 }: args) {}"); + ASSERT_THAT(v, IsAttrsOfSize(0)); + } + + TEST_F(TrivialExpressionTest, assertThrows) { + ASSERT_THROW(eval("let x = arg: assert arg == 1; 123; in x 2"), Error); + } + + TEST_F(TrivialExpressionTest, assertPassed) { + auto v = eval("let x = arg: assert arg == 1; 123; in x 1"); + ASSERT_THAT(v, IsIntEq(123)); + } + + class AttrSetMergeTrvialExpressionTest : + public TrivialExpressionTest, + public testing::WithParamInterface + {}; + + TEST_P(AttrSetMergeTrvialExpressionTest, attrsetMergeLazy) { + // Usually Nix rejects duplicate keys in an attrset but it does allow + // so if it is an attribute set that contains disjoint sets of keys. + // The below is equivalent to `{a.b = 1; a.c = 2; }`. + // The attribute set `a` will be a Thunk at first as the attribuets + // have to be merged (or otherwise computed) and that is done in a lazy + // manner. + + auto expr = GetParam(); + auto v = eval(expr); + ASSERT_THAT(v, IsAttrsOfSize(1)); + + auto a = v.attrs->find(createSymbol("a")); + ASSERT_NE(a, nullptr); + + ASSERT_THAT(*a->value, IsThunk()); + state.forceValue(*a->value, noPos); + + ASSERT_THAT(*a->value, IsAttrsOfSize(2)); + + auto b = a->value->attrs->find(createSymbol("b")); + ASSERT_NE(b, nullptr); + ASSERT_THAT(*b->value, IsIntEq(1)); + + auto c = a->value->attrs->find(createSymbol("c")); + ASSERT_NE(c, nullptr); + ASSERT_THAT(*c->value, IsIntEq(2)); + } + + INSTANTIATE_TEST_SUITE_P( + attrsetMergeLazy, + AttrSetMergeTrvialExpressionTest, + testing::Values( + "{ a.b = 1; a.c = 2; }", + "{ a = { b = 1; }; a = { c = 2; }; }" + ) + ); + + TEST_F(TrivialExpressionTest, functor) { + auto v = eval("{ __functor = self: arg: self.v + arg; v = 10; } 5"); + ASSERT_THAT(v, IsIntEq(15)); + } + + TEST_F(TrivialExpressionTest, bindOr) { + auto v = eval("{ or = 1; }"); + ASSERT_THAT(v, IsAttrsOfSize(1)); + auto b = v.attrs->find(createSymbol("or")); + ASSERT_NE(b, nullptr); + ASSERT_THAT(*b->value, IsIntEq(1)); + } + + TEST_F(TrivialExpressionTest, orCantBeUsed) { + ASSERT_THROW(eval("let or = 1; in or"), Error); + } +} /* namespace nix */ diff --git a/tests/unit/libexpr/value/context.cc b/tests/unit/libexpr/value/context.cc new file mode 100644 index 000000000..761286dbd --- /dev/null +++ b/tests/unit/libexpr/value/context.cc @@ -0,0 +1,132 @@ +#include +#include +#include + +#include "tests/path.hh" +#include "tests/libexpr.hh" +#include "tests/value/context.hh" + +namespace nix { + +// Test a few cases of invalid string context elements. + +TEST(NixStringContextElemTest, empty_invalid) { + EXPECT_THROW( + NixStringContextElem::parse(""), + BadNixStringContextElem); +} + +TEST(NixStringContextElemTest, single_bang_invalid) { + EXPECT_THROW( + NixStringContextElem::parse("!"), + BadNixStringContextElem); +} + +TEST(NixStringContextElemTest, double_bang_invalid) { + EXPECT_THROW( + NixStringContextElem::parse("!!/"), + BadStorePath); +} + +TEST(NixStringContextElemTest, eq_slash_invalid) { + EXPECT_THROW( + NixStringContextElem::parse("=/"), + BadStorePath); +} + +TEST(NixStringContextElemTest, slash_invalid) { + EXPECT_THROW( + NixStringContextElem::parse("/"), + BadStorePath); +} + +/** + * Round trip (string <-> data structure) test for + * `NixStringContextElem::Opaque`. + */ +TEST(NixStringContextElemTest, opaque) { + std::string_view opaque = "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x"; + auto elem = NixStringContextElem::parse(opaque); + auto * p = std::get_if(&elem.raw); + ASSERT_TRUE(p); + ASSERT_EQ(p->path, StorePath { opaque }); + ASSERT_EQ(elem.to_string(), opaque); +} + +/** + * Round trip (string <-> data structure) test for + * `NixStringContextElem::DrvDeep`. + */ +TEST(NixStringContextElemTest, drvDeep) { + std::string_view drvDeep = "=g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv"; + auto elem = NixStringContextElem::parse(drvDeep); + auto * p = std::get_if(&elem.raw); + ASSERT_TRUE(p); + ASSERT_EQ(p->drvPath, StorePath { drvDeep.substr(1) }); + ASSERT_EQ(elem.to_string(), drvDeep); +} + +/** + * Round trip (string <-> data structure) test for a simpler + * `NixStringContextElem::Built`. + */ +TEST(NixStringContextElemTest, built_opaque) { + std::string_view built = "!foo!g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv"; + auto elem = NixStringContextElem::parse(built); + auto * p = std::get_if(&elem.raw); + ASSERT_TRUE(p); + ASSERT_EQ(p->output, "foo"); + ASSERT_EQ(*p->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque { + .path = StorePath { built.substr(5) }, + })); + ASSERT_EQ(elem.to_string(), built); +} + +/** + * Round trip (string <-> data structure) test for a more complex, + * inductive `NixStringContextElem::Built`. + */ +TEST(NixStringContextElemTest, built_built) { + /** + * We set these in tests rather than the regular globals so we don't have + * to worry about race conditions if the tests run concurrently. + */ + ExperimentalFeatureSettings mockXpSettings; + mockXpSettings.set("experimental-features", "dynamic-derivations ca-derivations"); + + std::string_view built = "!foo!bar!g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv"; + auto elem = NixStringContextElem::parse(built, mockXpSettings); + auto * p = std::get_if(&elem.raw); + ASSERT_TRUE(p); + ASSERT_EQ(p->output, "foo"); + auto * drvPath = std::get_if(&*p->drvPath); + ASSERT_TRUE(drvPath); + ASSERT_EQ(drvPath->output, "bar"); + ASSERT_EQ(*drvPath->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque { + .path = StorePath { built.substr(9) }, + })); + ASSERT_EQ(elem.to_string(), built); +} + +/** + * Without the right experimental features enabled, we cannot parse a + * complex inductive string context element. + */ +TEST(NixStringContextElemTest, built_built_xp) { + ASSERT_THROW( + NixStringContextElem::parse("!foo!bar!g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv"), MissingExperimentalFeature); +} + +#ifndef COVERAGE + +RC_GTEST_PROP( + NixStringContextElemTest, + prop_round_rip, + (const NixStringContextElem & o)) +{ + RC_ASSERT(o == NixStringContextElem::parse(o.to_string())); +} + +#endif + +} diff --git a/tests/unit/libexpr/value/print.cc b/tests/unit/libexpr/value/print.cc new file mode 100644 index 000000000..5e96e12ec --- /dev/null +++ b/tests/unit/libexpr/value/print.cc @@ -0,0 +1,236 @@ +#include "tests/libexpr.hh" + +#include "value.hh" + +namespace nix { + +using namespace testing; + +struct ValuePrintingTests : LibExprTest +{ + template + void test(Value v, std::string_view expected, A... args) + { + std::stringstream out; + v.print(state.symbols, out, args...); + ASSERT_EQ(out.str(), expected); + } +}; + +TEST_F(ValuePrintingTests, tInt) +{ + Value vInt; + vInt.mkInt(10); + test(vInt, "10"); +} + +TEST_F(ValuePrintingTests, tBool) +{ + Value vBool; + vBool.mkBool(true); + test(vBool, "true"); +} + +TEST_F(ValuePrintingTests, tString) +{ + Value vString; + vString.mkString("some-string"); + test(vString, "\"some-string\""); +} + +TEST_F(ValuePrintingTests, tPath) +{ + Value vPath; + vPath.mkString("/foo"); + test(vPath, "\"/foo\""); +} + +TEST_F(ValuePrintingTests, tNull) +{ + Value vNull; + vNull.mkNull(); + test(vNull, "null"); +} + +TEST_F(ValuePrintingTests, tAttrs) +{ + Value vOne; + vOne.mkInt(1); + + Value vTwo; + vTwo.mkInt(2); + + BindingsBuilder builder(state, state.allocBindings(10)); + builder.insert(state.symbols.create("one"), &vOne); + builder.insert(state.symbols.create("two"), &vTwo); + + Value vAttrs; + vAttrs.mkAttrs(builder.finish()); + + test(vAttrs, "{ one = 1; two = 2; }"); +} + +TEST_F(ValuePrintingTests, tList) +{ + Value vOne; + vOne.mkInt(1); + + Value vTwo; + vTwo.mkInt(2); + + Value vList; + state.mkList(vList, 5); + vList.bigList.elems[0] = &vOne; + vList.bigList.elems[1] = &vTwo; + vList.bigList.size = 3; + + test(vList, "[ 1 2 (nullptr) ]"); +} + +TEST_F(ValuePrintingTests, vThunk) +{ + Value vThunk; + vThunk.mkThunk(nullptr, nullptr); + + test(vThunk, ""); +} + +TEST_F(ValuePrintingTests, vApp) +{ + Value vApp; + vApp.mkApp(nullptr, nullptr); + + test(vApp, ""); +} + +TEST_F(ValuePrintingTests, vLambda) +{ + Value vLambda; + vLambda.mkLambda(nullptr, nullptr); + + test(vLambda, ""); +} + +TEST_F(ValuePrintingTests, vPrimOp) +{ + Value vPrimOp; + vPrimOp.mkPrimOp(nullptr); + + test(vPrimOp, ""); +} + +TEST_F(ValuePrintingTests, vPrimOpApp) +{ + Value vPrimOpApp; + vPrimOpApp.mkPrimOpApp(nullptr, nullptr); + + test(vPrimOpApp, ""); +} + +TEST_F(ValuePrintingTests, vExternal) +{ + struct MyExternal : ExternalValueBase + { + public: + std::string showType() const override + { + return ""; + } + std::string typeOf() const override + { + return ""; + } + virtual std::ostream & print(std::ostream & str) const override + { + str << "testing-external!"; + return str; + } + } myExternal; + Value vExternal; + vExternal.mkExternal(&myExternal); + + test(vExternal, "testing-external!"); +} + +TEST_F(ValuePrintingTests, vFloat) +{ + Value vFloat; + vFloat.mkFloat(2.0); + + test(vFloat, "2"); +} + +TEST_F(ValuePrintingTests, vBlackhole) +{ + Value vBlackhole; + vBlackhole.mkBlackhole(); + test(vBlackhole, "«potential infinite recursion»"); +} + +TEST_F(ValuePrintingTests, depthAttrs) +{ + Value vOne; + vOne.mkInt(1); + + Value vTwo; + vTwo.mkInt(2); + + BindingsBuilder builder(state, state.allocBindings(10)); + builder.insert(state.symbols.create("one"), &vOne); + builder.insert(state.symbols.create("two"), &vTwo); + + Value vAttrs; + vAttrs.mkAttrs(builder.finish()); + + BindingsBuilder builder2(state, state.allocBindings(10)); + builder2.insert(state.symbols.create("one"), &vOne); + builder2.insert(state.symbols.create("two"), &vTwo); + builder2.insert(state.symbols.create("nested"), &vAttrs); + + Value vNested; + vNested.mkAttrs(builder2.finish()); + + test(vNested, "{ nested = «too deep»; one = «too deep»; two = «too deep»; }", false, 1); + test(vNested, "{ nested = { one = «too deep»; two = «too deep»; }; one = 1; two = 2; }", false, 2); + test(vNested, "{ nested = { one = 1; two = 2; }; one = 1; two = 2; }", false, 3); + test(vNested, "{ nested = { one = 1; two = 2; }; one = 1; two = 2; }", false, 4); +} + +TEST_F(ValuePrintingTests, depthList) +{ + Value vOne; + vOne.mkInt(1); + + Value vTwo; + vTwo.mkInt(2); + + BindingsBuilder builder(state, state.allocBindings(10)); + builder.insert(state.symbols.create("one"), &vOne); + builder.insert(state.symbols.create("two"), &vTwo); + + Value vAttrs; + vAttrs.mkAttrs(builder.finish()); + + BindingsBuilder builder2(state, state.allocBindings(10)); + builder2.insert(state.symbols.create("one"), &vOne); + builder2.insert(state.symbols.create("two"), &vTwo); + builder2.insert(state.symbols.create("nested"), &vAttrs); + + Value vNested; + vNested.mkAttrs(builder2.finish()); + + Value vList; + state.mkList(vList, 5); + vList.bigList.elems[0] = &vOne; + vList.bigList.elems[1] = &vTwo; + vList.bigList.elems[2] = &vNested; + vList.bigList.size = 3; + + test(vList, "[ «too deep» «too deep» «too deep» ]", false, 1); + test(vList, "[ 1 2 { nested = «too deep»; one = «too deep»; two = «too deep»; } ]", false, 2); + test(vList, "[ 1 2 { nested = { one = «too deep»; two = «too deep»; }; one = 1; two = 2; } ]", false, 3); + test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", false, 4); + test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", false, 5); +} + +} // namespace nix diff --git a/tests/unit/libstore-support/local.mk b/tests/unit/libstore-support/local.mk new file mode 100644 index 000000000..2738278d8 --- /dev/null +++ b/tests/unit/libstore-support/local.mk @@ -0,0 +1,17 @@ +libraries += libstore-test-support + +libstore-test-support_NAME = libnixstore-test-support + +libstore-test-support_DIR := $(d) + +libstore-test-support_INSTALL_DIR := + +libstore-test-support_SOURCES := $(wildcard $(d)/tests/*.cc) + +libstore-test-support_CXXFLAGS += $(libstore-tests_EXTRA_INCLUDES) + +libstore-test-support_LIBS = \ + libutil-test-support \ + libstore libutil + +libstore-test-support_LDFLAGS := -lrapidcheck diff --git a/tests/unit/libstore-support/tests/derived-path.cc b/tests/unit/libstore-support/tests/derived-path.cc new file mode 100644 index 000000000..091706dba --- /dev/null +++ b/tests/unit/libstore-support/tests/derived-path.cc @@ -0,0 +1,57 @@ +#include + +#include + +#include "tests/derived-path.hh" + +namespace rc { +using namespace nix; + +Gen Arbitrary::arbitrary() +{ + return gen::just(DerivedPath::Opaque { + .path = *gen::arbitrary(), + }); +} + +Gen Arbitrary::arbitrary() +{ + return gen::just(SingleDerivedPath::Built { + .drvPath = make_ref(*gen::arbitrary()), + .output = (*gen::arbitrary()).name, + }); +} + +Gen Arbitrary::arbitrary() +{ + return gen::just(DerivedPath::Built { + .drvPath = make_ref(*gen::arbitrary()), + .outputs = *gen::arbitrary(), + }); +} + +Gen Arbitrary::arbitrary() +{ + switch (*gen::inRange(0, std::variant_size_v)) { + case 0: + return gen::just(*gen::arbitrary()); + case 1: + return gen::just(*gen::arbitrary()); + default: + assert(false); + } +} + +Gen Arbitrary::arbitrary() +{ + switch (*gen::inRange(0, std::variant_size_v)) { + case 0: + return gen::just(*gen::arbitrary()); + case 1: + return gen::just(*gen::arbitrary()); + default: + assert(false); + } +} + +} diff --git a/tests/unit/libstore-support/tests/derived-path.hh b/tests/unit/libstore-support/tests/derived-path.hh new file mode 100644 index 000000000..98d61f228 --- /dev/null +++ b/tests/unit/libstore-support/tests/derived-path.hh @@ -0,0 +1,39 @@ +#pragma once +///@file + +#include + +#include + +#include "tests/path.hh" +#include "tests/outputs-spec.hh" + +namespace rc { +using namespace nix; + +template<> +struct Arbitrary { + static Gen arbitrary(); +}; + +template<> +struct Arbitrary { + static Gen arbitrary(); +}; + +template<> +struct Arbitrary { + static Gen arbitrary(); +}; + +template<> +struct Arbitrary { + static Gen arbitrary(); +}; + +template<> +struct Arbitrary { + static Gen arbitrary(); +}; + +} diff --git a/tests/unit/libstore-support/tests/libstore.hh b/tests/unit/libstore-support/tests/libstore.hh new file mode 100644 index 000000000..ef93457b5 --- /dev/null +++ b/tests/unit/libstore-support/tests/libstore.hh @@ -0,0 +1,26 @@ +#pragma once +///@file + +#include +#include + +#include "store-api.hh" + +namespace nix { + +class LibStoreTest : public ::testing::Test { + public: + static void SetUpTestSuite() { + initLibStore(); + } + + protected: + LibStoreTest() + : store(openStore("dummy://")) + { } + + ref store; +}; + + +} /* namespace nix */ diff --git a/tests/unit/libstore-support/tests/outputs-spec.cc b/tests/unit/libstore-support/tests/outputs-spec.cc new file mode 100644 index 000000000..e9d602203 --- /dev/null +++ b/tests/unit/libstore-support/tests/outputs-spec.cc @@ -0,0 +1,24 @@ +#include "tests/outputs-spec.hh" + +#include + +namespace rc { +using namespace nix; + +Gen Arbitrary::arbitrary() +{ + switch (*gen::inRange(0, std::variant_size_v)) { + case 0: + return gen::just((OutputsSpec) OutputsSpec::All { }); + case 1: + return gen::just((OutputsSpec) OutputsSpec::Names { + *gen::nonEmpty(gen::container(gen::map( + gen::arbitrary(), + [](StorePathName n) { return n.name; }))), + }); + default: + assert(false); + } +} + +} diff --git a/tests/unit/libstore-support/tests/outputs-spec.hh b/tests/unit/libstore-support/tests/outputs-spec.hh new file mode 100644 index 000000000..f5bf9042d --- /dev/null +++ b/tests/unit/libstore-support/tests/outputs-spec.hh @@ -0,0 +1,18 @@ +#pragma once +///@file + +#include + +#include + +#include "tests/path.hh" + +namespace rc { +using namespace nix; + +template<> +struct Arbitrary { + static Gen arbitrary(); +}; + +} diff --git a/tests/unit/libstore-support/tests/path.cc b/tests/unit/libstore-support/tests/path.cc new file mode 100644 index 000000000..e5f169e94 --- /dev/null +++ b/tests/unit/libstore-support/tests/path.cc @@ -0,0 +1,82 @@ +#include + +#include + +#include "path-regex.hh" +#include "store-api.hh" + +#include "tests/hash.hh" +#include "tests/path.hh" + +namespace nix { + +void showValue(const StorePath & p, std::ostream & os) +{ + os << p.to_string(); +} + +} + +namespace rc { +using namespace nix; + +Gen Arbitrary::arbitrary() +{ + auto len = *gen::inRange( + 1, + StorePath::MaxPathLen - StorePath::HashLen); + + std::string pre; + pre.reserve(len); + + for (size_t c = 0; c < len; ++c) { + switch (auto i = *gen::inRange(0, 10 + 2 * 26 + 6)) { + case 0 ... 9: + pre += '0' + i; + case 10 ... 35: + pre += 'A' + (i - 10); + break; + case 36 ... 61: + pre += 'a' + (i - 36); + break; + case 62: + pre += '+'; + break; + case 63: + pre += '-'; + break; + case 64: + // names aren't permitted to start with a period, + // so just fall through to the next case here + if (c != 0) { + pre += '.'; + break; + } + case 65: + pre += '_'; + break; + case 66: + pre += '?'; + break; + case 67: + pre += '='; + break; + default: + assert(false); + } + } + + return gen::just(StorePathName { + .name = std::move(pre), + }); +} + +Gen Arbitrary::arbitrary() +{ + return gen::just(StorePath { + *gen::arbitrary(), + (*gen::arbitrary()).name, + }); +} + +} // namespace rc diff --git a/tests/unit/libstore-support/tests/path.hh b/tests/unit/libstore-support/tests/path.hh new file mode 100644 index 000000000..4751b3373 --- /dev/null +++ b/tests/unit/libstore-support/tests/path.hh @@ -0,0 +1,32 @@ +#pragma once +///@file + +#include + +#include + +namespace nix { + +struct StorePathName { + std::string name; +}; + +// For rapidcheck +void showValue(const StorePath & p, std::ostream & os); + +} + +namespace rc { +using namespace nix; + +template<> +struct Arbitrary { + static Gen arbitrary(); +}; + +template<> +struct Arbitrary { + static Gen arbitrary(); +}; + +} diff --git a/tests/unit/libstore/derivation.cc b/tests/unit/libstore/derivation.cc new file mode 100644 index 000000000..c360c9707 --- /dev/null +++ b/tests/unit/libstore/derivation.cc @@ -0,0 +1,369 @@ +#include +#include + +#include "experimental-features.hh" +#include "derivations.hh" + +#include "tests/libstore.hh" + +namespace nix { + +class DerivationTest : public LibStoreTest +{ +public: + /** + * We set these in tests rather than the regular globals so we don't have + * to worry about race conditions if the tests run concurrently. + */ + ExperimentalFeatureSettings mockXpSettings; +}; + +class CaDerivationTest : public DerivationTest +{ + void SetUp() override + { + mockXpSettings.set("experimental-features", "ca-derivations"); + } +}; + +class DynDerivationTest : public DerivationTest +{ + void SetUp() override + { + mockXpSettings.set("experimental-features", "dynamic-derivations ca-derivations"); + } +}; + +class ImpureDerivationTest : public DerivationTest +{ + void SetUp() override + { + mockXpSettings.set("experimental-features", "impure-derivations"); + } +}; + +TEST_F(DerivationTest, BadATerm_version) { + ASSERT_THROW( + parseDerivation( + *store, + R"(DrvWithVersion("invalid-version",[],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",["cat","dog"])],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")]))", + "whatever", + mockXpSettings), + FormatError); +} + +TEST_F(DynDerivationTest, BadATerm_oldVersionDynDeps) { + ASSERT_THROW( + parseDerivation( + *store, + R"(Derive([],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",(["cat","dog"],[("cat",["kitten"]),("goose",["gosling"])]))],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")]))", + "dyn-dep-derivation", + mockXpSettings), + FormatError); +} + +#define TEST_JSON(FIXTURE, NAME, STR, VAL, DRV_NAME, OUTPUT_NAME) \ + TEST_F(FIXTURE, DerivationOutput_ ## NAME ## _to_json) { \ + using nlohmann::literals::operator "" _json; \ + ASSERT_EQ( \ + STR ## _json, \ + (DerivationOutput { VAL }).toJSON( \ + *store, \ + DRV_NAME, \ + OUTPUT_NAME)); \ + } \ + \ + TEST_F(FIXTURE, DerivationOutput_ ## NAME ## _from_json) { \ + using nlohmann::literals::operator "" _json; \ + ASSERT_EQ( \ + DerivationOutput { VAL }, \ + DerivationOutput::fromJSON( \ + *store, \ + DRV_NAME, \ + OUTPUT_NAME, \ + STR ## _json, \ + mockXpSettings)); \ + } + +TEST_JSON(DerivationTest, inputAddressed, + R"({ + "path": "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name" + })", + (DerivationOutput::InputAddressed { + .path = store->parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"), + }), + "drv-name", "output-name") + +TEST_JSON(DerivationTest, caFixedFlat, + R"({ + "hashAlgo": "sha256", + "hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f", + "path": "/nix/store/rhcg9h16sqvlbpsa6dqm57sbr2al6nzg-drv-name-output-name" + })", + (DerivationOutput::CAFixed { + .ca = { + .method = FileIngestionMethod::Flat, + .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="), + }, + }), + "drv-name", "output-name") + +TEST_JSON(DerivationTest, caFixedNAR, + R"({ + "hashAlgo": "r:sha256", + "hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f", + "path": "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name" + })", + (DerivationOutput::CAFixed { + .ca = { + .method = FileIngestionMethod::Recursive, + .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="), + }, + }), + "drv-name", "output-name") + +TEST_JSON(DynDerivationTest, caFixedText, + R"({ + "hashAlgo": "text:sha256", + "hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f", + "path": "/nix/store/6s1zwabh956jvhv4w9xcdb5jiyanyxg1-drv-name-output-name" + })", + (DerivationOutput::CAFixed { + .ca = { + .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="), + }, + }), + "drv-name", "output-name") + +TEST_JSON(CaDerivationTest, caFloating, + R"({ + "hashAlgo": "r:sha256" + })", + (DerivationOutput::CAFloating { + .method = FileIngestionMethod::Recursive, + .hashType = htSHA256, + }), + "drv-name", "output-name") + +TEST_JSON(DerivationTest, deferred, + R"({ })", + DerivationOutput::Deferred { }, + "drv-name", "output-name") + +TEST_JSON(ImpureDerivationTest, impure, + R"({ + "hashAlgo": "r:sha256", + "impure": true + })", + (DerivationOutput::Impure { + .method = FileIngestionMethod::Recursive, + .hashType = htSHA256, + }), + "drv-name", "output-name") + +#undef TEST_JSON + +#define TEST_JSON(FIXTURE, NAME, STR, VAL) \ + TEST_F(FIXTURE, Derivation_ ## NAME ## _to_json) { \ + using nlohmann::literals::operator "" _json; \ + ASSERT_EQ( \ + STR ## _json, \ + (VAL).toJSON(*store)); \ + } \ + \ + TEST_F(FIXTURE, Derivation_ ## NAME ## _from_json) { \ + using nlohmann::literals::operator "" _json; \ + ASSERT_EQ( \ + (VAL), \ + Derivation::fromJSON( \ + *store, \ + STR ## _json, \ + mockXpSettings)); \ + } + +#define TEST_ATERM(FIXTURE, NAME, STR, VAL, DRV_NAME) \ + TEST_F(FIXTURE, Derivation_ ## NAME ## _to_aterm) { \ + ASSERT_EQ( \ + STR, \ + (VAL).unparse(*store, false)); \ + } \ + \ + TEST_F(FIXTURE, Derivation_ ## NAME ## _from_aterm) { \ + auto parsed = parseDerivation( \ + *store, \ + STR, \ + DRV_NAME, \ + mockXpSettings); \ + ASSERT_EQ( \ + (VAL).toJSON(*store), \ + parsed.toJSON(*store)); \ + ASSERT_EQ( \ + (VAL), \ + parsed); \ + } + +Derivation makeSimpleDrv(const Store & store) { + Derivation drv; + drv.name = "simple-derivation"; + drv.inputSrcs = { + store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"), + }; + drv.inputDrvs = { + .map = { + { + store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"), + { + .value = { + "cat", + "dog", + }, + }, + }, + }, + }; + drv.platform = "wasm-sel4"; + drv.builder = "foo"; + drv.args = { + "bar", + "baz", + }; + drv.env = { + { + "BIG_BAD", + "WOLF", + }, + }; + return drv; +} + +TEST_JSON(DerivationTest, simple, + R"({ + "name": "simple-derivation", + "inputSrcs": [ + "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1" + ], + "inputDrvs": { + "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": { + "dynamicOutputs": {}, + "outputs": [ + "cat", + "dog" + ] + } + }, + "system": "wasm-sel4", + "builder": "foo", + "args": [ + "bar", + "baz" + ], + "env": { + "BIG_BAD": "WOLF" + }, + "outputs": {} + })", + makeSimpleDrv(*store)) + +TEST_ATERM(DerivationTest, simple, + R"(Derive([],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",["cat","dog"])],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")]))", + makeSimpleDrv(*store), + "simple-derivation") + +Derivation makeDynDepDerivation(const Store & store) { + Derivation drv; + drv.name = "dyn-dep-derivation"; + drv.inputSrcs = { + store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"), + }; + drv.inputDrvs = { + .map = { + { + store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"), + DerivedPathMap::ChildNode { + .value = { + "cat", + "dog", + }, + .childMap = { + { + "cat", + DerivedPathMap::ChildNode { + .value = { + "kitten", + }, + }, + }, + { + "goose", + DerivedPathMap::ChildNode { + .value = { + "gosling", + }, + }, + }, + }, + }, + }, + }, + }; + drv.platform = "wasm-sel4"; + drv.builder = "foo"; + drv.args = { + "bar", + "baz", + }; + drv.env = { + { + "BIG_BAD", + "WOLF", + }, + }; + return drv; +} + +TEST_JSON(DynDerivationTest, dynDerivationDeps, + R"({ + "name": "dyn-dep-derivation", + "inputSrcs": [ + "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1" + ], + "inputDrvs": { + "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": { + "dynamicOutputs": { + "cat": { + "dynamicOutputs": {}, + "outputs": ["kitten"] + }, + "goose": { + "dynamicOutputs": {}, + "outputs": ["gosling"] + } + }, + "outputs": [ + "cat", + "dog" + ] + } + }, + "system": "wasm-sel4", + "builder": "foo", + "args": [ + "bar", + "baz" + ], + "env": { + "BIG_BAD": "WOLF" + }, + "outputs": {} + })", + makeDynDepDerivation(*store)) + +TEST_ATERM(DynDerivationTest, dynDerivationDeps, + R"(DrvWithVersion("xp-dyn-drv",[],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",(["cat","dog"],[("cat",["kitten"]),("goose",["gosling"])]))],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")]))", + makeDynDepDerivation(*store), + "dyn-dep-derivation") + +#undef TEST_JSON +#undef TEST_ATERM + +} diff --git a/tests/unit/libstore/derived-path.cc b/tests/unit/libstore/derived-path.cc new file mode 100644 index 000000000..c62d79a78 --- /dev/null +++ b/tests/unit/libstore/derived-path.cc @@ -0,0 +1,100 @@ +#include + +#include +#include + +#include "tests/derived-path.hh" +#include "tests/libstore.hh" + +namespace nix { + +class DerivedPathTest : public LibStoreTest +{ +}; + +/** + * Round trip (string <-> data structure) test for + * `DerivedPath::Opaque`. + */ +TEST_F(DerivedPathTest, opaque) { + std::string_view opaque = "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x"; + auto elem = DerivedPath::parse(*store, opaque); + auto * p = std::get_if(&elem); + ASSERT_TRUE(p); + ASSERT_EQ(p->path, store->parseStorePath(opaque)); + ASSERT_EQ(elem.to_string(*store), opaque); +} + +/** + * Round trip (string <-> data structure) test for a simpler + * `DerivedPath::Built`. + */ +TEST_F(DerivedPathTest, built_opaque) { + std::string_view built = "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv^bar,foo"; + auto elem = DerivedPath::parse(*store, built); + auto * p = std::get_if(&elem); + ASSERT_TRUE(p); + ASSERT_EQ(p->outputs, ((OutputsSpec) OutputsSpec::Names { "foo", "bar" })); + ASSERT_EQ(*p->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque { + .path = store->parseStorePath(built.substr(0, 49)), + })); + ASSERT_EQ(elem.to_string(*store), built); +} + +/** + * Round trip (string <-> data structure) test for a more complex, + * inductive `DerivedPath::Built`. + */ +TEST_F(DerivedPathTest, built_built) { + /** + * We set these in tests rather than the regular globals so we don't have + * to worry about race conditions if the tests run concurrently. + */ + ExperimentalFeatureSettings mockXpSettings; + mockXpSettings.set("experimental-features", "dynamic-derivations ca-derivations"); + + std::string_view built = "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv^foo^bar,baz"; + auto elem = DerivedPath::parse(*store, built, mockXpSettings); + auto * p = std::get_if(&elem); + ASSERT_TRUE(p); + ASSERT_EQ(p->outputs, ((OutputsSpec) OutputsSpec::Names { "bar", "baz" })); + auto * drvPath = std::get_if(&*p->drvPath); + ASSERT_TRUE(drvPath); + ASSERT_EQ(drvPath->output, "foo"); + ASSERT_EQ(*drvPath->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque { + .path = store->parseStorePath(built.substr(0, 49)), + })); + ASSERT_EQ(elem.to_string(*store), built); +} + +/** + * Without the right experimental features enabled, we cannot parse a + * complex inductive derived path. + */ +TEST_F(DerivedPathTest, built_built_xp) { + ASSERT_THROW( + DerivedPath::parse(*store, "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv^foo^bar,baz"), + MissingExperimentalFeature); +} + +#ifndef COVERAGE + +RC_GTEST_FIXTURE_PROP( + DerivedPathTest, + prop_legacy_round_rip, + (const DerivedPath & o)) +{ + RC_ASSERT(o == DerivedPath::parseLegacy(*store, o.to_string_legacy(*store))); +} + +RC_GTEST_FIXTURE_PROP( + DerivedPathTest, + prop_round_rip, + (const DerivedPath & o)) +{ + RC_ASSERT(o == DerivedPath::parse(*store, o.to_string(*store))); +} + +#endif + +} diff --git a/tests/unit/libstore/downstream-placeholder.cc b/tests/unit/libstore/downstream-placeholder.cc new file mode 100644 index 000000000..fd29530ac --- /dev/null +++ b/tests/unit/libstore/downstream-placeholder.cc @@ -0,0 +1,41 @@ +#include + +#include "downstream-placeholder.hh" + +namespace nix { + +TEST(DownstreamPlaceholder, unknownCaOutput) { + /** + * We set these in tests rather than the regular globals so we don't have + * to worry about race conditions if the tests run concurrently. + */ + ExperimentalFeatureSettings mockXpSettings; + mockXpSettings.set("experimental-features", "ca-derivations"); + + ASSERT_EQ( + DownstreamPlaceholder::unknownCaOutput( + StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv" }, + "out", + mockXpSettings).render(), + "/0c6rn30q4frawknapgwq386zq358m8r6msvywcvc89n6m5p2dgbz"); +} + +TEST(DownstreamPlaceholder, unknownDerivation) { + /** + * Same reason as above + */ + ExperimentalFeatureSettings mockXpSettings; + mockXpSettings.set("experimental-features", "dynamic-derivations ca-derivations"); + + ASSERT_EQ( + DownstreamPlaceholder::unknownDerivation( + DownstreamPlaceholder::unknownCaOutput( + StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv.drv" }, + "out", + mockXpSettings), + "out", + mockXpSettings).render(), + "/0gn6agqxjyyalf0dpihgyf49xq5hqxgw100f0wydnj6yqrhqsb3w"); +} + +} diff --git a/tests/unit/libstore/local.mk b/tests/unit/libstore/local.mk new file mode 100644 index 000000000..fb7385ec1 --- /dev/null +++ b/tests/unit/libstore/local.mk @@ -0,0 +1,27 @@ +check: libstore-tests_RUN + +programs += libstore-tests + +libstore-tests_NAME = libnixstore-tests + +libstore-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data + +libstore-tests_DIR := $(d) + +libstore-tests_INSTALL_DIR := + +libstore-tests_SOURCES := $(wildcard $(d)/*.cc) + +libstore-tests_EXTRA_INCLUDES = \ + -I tests/unit/libstore-support \ + -I tests/unit/libutil-support \ + -I src/libstore \ + -I src/libutil + +libstore-tests_CXXFLAGS += $(libstore-tests_EXTRA_INCLUDES) + +libstore-tests_LIBS = \ + libstore-test-support libutil-test-support \ + libstore libutil + +libstore-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) diff --git a/tests/unit/libstore/machines.cc b/tests/unit/libstore/machines.cc new file mode 100644 index 000000000..72b2c3ac6 --- /dev/null +++ b/tests/unit/libstore/machines.cc @@ -0,0 +1,169 @@ +#include "machines.hh" +#include "globals.hh" + +#include + +using testing::Contains; +using testing::ElementsAre; +using testing::EndsWith; +using testing::Eq; +using testing::Field; +using testing::SizeIs; + +using nix::absPath; +using nix::FormatError; +using nix::getMachines; +using nix::Machine; +using nix::Machines; +using nix::pathExists; +using nix::Settings; +using nix::settings; + +class Environment : public ::testing::Environment { + public: + void SetUp() override { settings.thisSystem = "TEST_ARCH-TEST_OS"; } +}; + +testing::Environment* const foo_env = + testing::AddGlobalTestEnvironment(new Environment); + +TEST(machines, getMachinesWithEmptyBuilders) { + settings.builders = ""; + Machines actual = getMachines(); + ASSERT_THAT(actual, SizeIs(0)); +} + +TEST(machines, getMachinesUriOnly) { + settings.builders = "nix@scratchy.labs.cs.uu.nl"; + Machines actual = getMachines(); + ASSERT_THAT(actual, SizeIs(1)); + EXPECT_THAT(actual[0], Field(&Machine::storeUri, Eq("ssh://nix@scratchy.labs.cs.uu.nl"))); + EXPECT_THAT(actual[0], Field(&Machine::systemTypes, ElementsAre("TEST_ARCH-TEST_OS"))); + EXPECT_THAT(actual[0], Field(&Machine::sshKey, SizeIs(0))); + EXPECT_THAT(actual[0], Field(&Machine::maxJobs, Eq(1))); + EXPECT_THAT(actual[0], Field(&Machine::speedFactor, Eq(1))); + EXPECT_THAT(actual[0], Field(&Machine::supportedFeatures, SizeIs(0))); + EXPECT_THAT(actual[0], Field(&Machine::mandatoryFeatures, SizeIs(0))); + EXPECT_THAT(actual[0], Field(&Machine::sshPublicHostKey, SizeIs(0))); +} + +TEST(machines, getMachinesDefaults) { + settings.builders = "nix@scratchy.labs.cs.uu.nl - - - - - - -"; + Machines actual = getMachines(); + ASSERT_THAT(actual, SizeIs(1)); + EXPECT_THAT(actual[0], Field(&Machine::storeUri, Eq("ssh://nix@scratchy.labs.cs.uu.nl"))); + EXPECT_THAT(actual[0], Field(&Machine::systemTypes, ElementsAre("TEST_ARCH-TEST_OS"))); + EXPECT_THAT(actual[0], Field(&Machine::sshKey, SizeIs(0))); + EXPECT_THAT(actual[0], Field(&Machine::maxJobs, Eq(1))); + EXPECT_THAT(actual[0], Field(&Machine::speedFactor, Eq(1))); + EXPECT_THAT(actual[0], Field(&Machine::supportedFeatures, SizeIs(0))); + EXPECT_THAT(actual[0], Field(&Machine::mandatoryFeatures, SizeIs(0))); + EXPECT_THAT(actual[0], Field(&Machine::sshPublicHostKey, SizeIs(0))); +} + +TEST(machines, getMachinesWithNewLineSeparator) { + settings.builders = "nix@scratchy.labs.cs.uu.nl\nnix@itchy.labs.cs.uu.nl"; + Machines actual = getMachines(); + ASSERT_THAT(actual, SizeIs(2)); + EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@scratchy.labs.cs.uu.nl")))); + EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@itchy.labs.cs.uu.nl")))); +} + +TEST(machines, getMachinesWithSemicolonSeparator) { + settings.builders = "nix@scratchy.labs.cs.uu.nl ; nix@itchy.labs.cs.uu.nl"; + Machines actual = getMachines(); + EXPECT_THAT(actual, SizeIs(2)); + EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@scratchy.labs.cs.uu.nl")))); + EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@itchy.labs.cs.uu.nl")))); +} + +TEST(machines, getMachinesWithCorrectCompleteSingleBuilder) { + settings.builders = "nix@scratchy.labs.cs.uu.nl i686-linux " + "/home/nix/.ssh/id_scratchy_auto 8 3 kvm " + "benchmark SSH+HOST+PUBLIC+KEY+BASE64+ENCODED=="; + Machines actual = getMachines(); + ASSERT_THAT(actual, SizeIs(1)); + EXPECT_THAT(actual[0], Field(&Machine::storeUri, EndsWith("nix@scratchy.labs.cs.uu.nl"))); + EXPECT_THAT(actual[0], Field(&Machine::systemTypes, ElementsAre("i686-linux"))); + EXPECT_THAT(actual[0], Field(&Machine::sshKey, Eq("/home/nix/.ssh/id_scratchy_auto"))); + EXPECT_THAT(actual[0], Field(&Machine::maxJobs, Eq(8))); + EXPECT_THAT(actual[0], Field(&Machine::speedFactor, Eq(3))); + EXPECT_THAT(actual[0], Field(&Machine::supportedFeatures, ElementsAre("kvm"))); + EXPECT_THAT(actual[0], Field(&Machine::mandatoryFeatures, ElementsAre("benchmark"))); + EXPECT_THAT(actual[0], Field(&Machine::sshPublicHostKey, Eq("SSH+HOST+PUBLIC+KEY+BASE64+ENCODED=="))); +} + +TEST(machines, + getMachinesWithCorrectCompleteSingleBuilderWithTabColumnDelimiter) { + settings.builders = + "nix@scratchy.labs.cs.uu.nl\ti686-linux\t/home/nix/.ssh/" + "id_scratchy_auto\t8\t3\tkvm\tbenchmark\tSSH+HOST+PUBLIC+" + "KEY+BASE64+ENCODED=="; + Machines actual = getMachines(); + ASSERT_THAT(actual, SizeIs(1)); + EXPECT_THAT(actual[0], Field(&Machine::storeUri, EndsWith("nix@scratchy.labs.cs.uu.nl"))); + EXPECT_THAT(actual[0], Field(&Machine::systemTypes, ElementsAre("i686-linux"))); + EXPECT_THAT(actual[0], Field(&Machine::sshKey, Eq("/home/nix/.ssh/id_scratchy_auto"))); + EXPECT_THAT(actual[0], Field(&Machine::maxJobs, Eq(8))); + EXPECT_THAT(actual[0], Field(&Machine::speedFactor, Eq(3))); + EXPECT_THAT(actual[0], Field(&Machine::supportedFeatures, ElementsAre("kvm"))); + EXPECT_THAT(actual[0], Field(&Machine::mandatoryFeatures, ElementsAre("benchmark"))); + EXPECT_THAT(actual[0], Field(&Machine::sshPublicHostKey, Eq("SSH+HOST+PUBLIC+KEY+BASE64+ENCODED=="))); +} + +TEST(machines, getMachinesWithMultiOptions) { + settings.builders = "nix@scratchy.labs.cs.uu.nl Arch1,Arch2 - - - " + "SupportedFeature1,SupportedFeature2 " + "MandatoryFeature1,MandatoryFeature2"; + Machines actual = getMachines(); + ASSERT_THAT(actual, SizeIs(1)); + EXPECT_THAT(actual[0], Field(&Machine::storeUri, EndsWith("nix@scratchy.labs.cs.uu.nl"))); + EXPECT_THAT(actual[0], Field(&Machine::systemTypes, ElementsAre("Arch1", "Arch2"))); + EXPECT_THAT(actual[0], Field(&Machine::supportedFeatures, ElementsAre("SupportedFeature1", "SupportedFeature2"))); + EXPECT_THAT(actual[0], Field(&Machine::mandatoryFeatures, ElementsAre("MandatoryFeature1", "MandatoryFeature2"))); +} + +TEST(machines, getMachinesWithIncorrectFormat) { + settings.builders = "nix@scratchy.labs.cs.uu.nl - - eight"; + EXPECT_THROW(getMachines(), FormatError); + settings.builders = "nix@scratchy.labs.cs.uu.nl - - -1"; + EXPECT_THROW(getMachines(), FormatError); + settings.builders = "nix@scratchy.labs.cs.uu.nl - - 8 three"; + EXPECT_THROW(getMachines(), FormatError); + settings.builders = "nix@scratchy.labs.cs.uu.nl - - 8 -3"; + EXPECT_THROW(getMachines(), FormatError); + settings.builders = "nix@scratchy.labs.cs.uu.nl - - 8 3 - - BAD_BASE64"; + EXPECT_THROW(getMachines(), FormatError); +} + +TEST(machines, getMachinesWithCorrectFileReference) { + auto path = absPath("tests/unit/libstore/test-data/machines.valid"); + ASSERT_TRUE(pathExists(path)); + + settings.builders = std::string("@") + path; + Machines actual = getMachines(); + ASSERT_THAT(actual, SizeIs(3)); + EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@scratchy.labs.cs.uu.nl")))); + EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@itchy.labs.cs.uu.nl")))); + EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@poochie.labs.cs.uu.nl")))); +} + +TEST(machines, getMachinesWithCorrectFileReferenceToEmptyFile) { + auto path = "/dev/null"; + ASSERT_TRUE(pathExists(path)); + + settings.builders = std::string("@") + path; + Machines actual = getMachines(); + ASSERT_THAT(actual, SizeIs(0)); +} + +TEST(machines, getMachinesWithIncorrectFileReference) { + settings.builders = std::string("@") + absPath("/not/a/file"); + Machines actual = getMachines(); + ASSERT_THAT(actual, SizeIs(0)); +} + +TEST(machines, getMachinesWithCorrectFileReferenceToIncorrectFile) { + settings.builders = std::string("@") + absPath("tests/unit/libstore/test-data/machines.bad_format"); + EXPECT_THROW(getMachines(), FormatError); +} diff --git a/tests/unit/libstore/nar-info-disk-cache.cc b/tests/unit/libstore/nar-info-disk-cache.cc new file mode 100644 index 000000000..b4bdb8329 --- /dev/null +++ b/tests/unit/libstore/nar-info-disk-cache.cc @@ -0,0 +1,123 @@ +#include "nar-info-disk-cache.hh" + +#include +#include +#include "sqlite.hh" +#include + + +namespace nix { + +TEST(NarInfoDiskCacheImpl, create_and_read) { + // This is a large single test to avoid some setup overhead. + + int prio = 12345; + bool wantMassQuery = true; + + Path tmpDir = createTempDir(); + AutoDelete delTmpDir(tmpDir); + Path dbPath(tmpDir + "/test-narinfo-disk-cache.sqlite"); + + int savedId; + int barId; + SQLite db; + SQLiteStmt getIds; + + { + auto cache = getTestNarInfoDiskCache(dbPath); + + // Set up "background noise" and check that different caches receive different ids + { + auto bc1 = cache->createCache("https://bar", "/nix/storedir", wantMassQuery, prio); + auto bc2 = cache->createCache("https://xyz", "/nix/storedir", false, 12); + ASSERT_NE(bc1, bc2); + barId = bc1; + } + + // Check that the fields are saved and returned correctly. This does not test + // the select statement yet, because of in-memory caching. + savedId = cache->createCache("http://foo", "/nix/storedir", wantMassQuery, prio);; + { + auto r = cache->upToDateCacheExists("http://foo"); + ASSERT_TRUE(r); + ASSERT_EQ(r->priority, prio); + ASSERT_EQ(r->wantMassQuery, wantMassQuery); + ASSERT_EQ(savedId, r->id); + } + + // We're going to pay special attention to the id field because we had a bug + // that changed it. + db = SQLite(dbPath); + getIds.create(db, "select id from BinaryCaches where url = 'http://foo'"); + + { + auto q(getIds.use()); + ASSERT_TRUE(q.next()); + ASSERT_EQ(savedId, q.getInt(0)); + ASSERT_FALSE(q.next()); + } + + // Pretend that the caches are older, but keep one up to date, as "background noise" + db.exec("update BinaryCaches set timestamp = timestamp - 1 - 7 * 24 * 3600 where url <> 'https://xyz';"); + + // This shows that the in-memory cache works + { + auto r = cache->upToDateCacheExists("http://foo"); + ASSERT_TRUE(r); + ASSERT_EQ(r->priority, prio); + ASSERT_EQ(r->wantMassQuery, wantMassQuery); + } + } + + { + // We can't clear the in-memory cache, so we use a new cache object. This is + // more realistic anyway. + auto cache2 = getTestNarInfoDiskCache(dbPath); + + { + auto r = cache2->upToDateCacheExists("http://foo"); + ASSERT_FALSE(r); + } + + // "Update", same data, check that the id number is reused + cache2->createCache("http://foo", "/nix/storedir", wantMassQuery, prio); + + { + auto r = cache2->upToDateCacheExists("http://foo"); + ASSERT_TRUE(r); + ASSERT_EQ(r->priority, prio); + ASSERT_EQ(r->wantMassQuery, wantMassQuery); + ASSERT_EQ(r->id, savedId); + } + + { + auto q(getIds.use()); + ASSERT_TRUE(q.next()); + auto currentId = q.getInt(0); + ASSERT_FALSE(q.next()); + ASSERT_EQ(currentId, savedId); + } + + // Check that the fields can be modified, and the id remains the same + { + auto r0 = cache2->upToDateCacheExists("https://bar"); + ASSERT_FALSE(r0); + + cache2->createCache("https://bar", "/nix/storedir", !wantMassQuery, prio + 10); + auto r = cache2->upToDateCacheExists("https://bar"); + ASSERT_EQ(r->wantMassQuery, !wantMassQuery); + ASSERT_EQ(r->priority, prio + 10); + ASSERT_EQ(r->id, barId); + } + + // // Force update (no use case yet; we only retrieve cache metadata when stale based on timestamp) + // { + // cache2->createCache("https://bar", "/nix/storedir", wantMassQuery, prio + 20); + // auto r = cache2->upToDateCacheExists("https://bar"); + // ASSERT_EQ(r->wantMassQuery, wantMassQuery); + // ASSERT_EQ(r->priority, prio + 20); + // } + } +} + +} diff --git a/tests/unit/libstore/outputs-spec.cc b/tests/unit/libstore/outputs-spec.cc new file mode 100644 index 000000000..456196be1 --- /dev/null +++ b/tests/unit/libstore/outputs-spec.cc @@ -0,0 +1,214 @@ +#include "tests/outputs-spec.hh" + +#include +#include +#include + +namespace nix { + +#ifndef NDEBUG +TEST(OutputsSpec, no_empty_names) { + ASSERT_DEATH(OutputsSpec::Names { std::set { } }, ""); +} +#endif + +#define TEST_DONT_PARSE(NAME, STR) \ + TEST(OutputsSpec, bad_ ## NAME) { \ + std::optional OutputsSpecOpt = \ + OutputsSpec::parseOpt(STR); \ + ASSERT_FALSE(OutputsSpecOpt); \ + } + +TEST_DONT_PARSE(empty, "") +TEST_DONT_PARSE(garbage, "&*()") +TEST_DONT_PARSE(double_star, "**") +TEST_DONT_PARSE(star_first, "*,foo") +TEST_DONT_PARSE(star_second, "foo,*") + +#undef TEST_DONT_PARSE + +TEST(OutputsSpec, all) { + std::string_view str = "*"; + OutputsSpec expected = OutputsSpec::All { }; + ASSERT_EQ(OutputsSpec::parse(str), expected); + ASSERT_EQ(expected.to_string(), str); +} + +TEST(OutputsSpec, names_out) { + std::string_view str = "out"; + OutputsSpec expected = OutputsSpec::Names { "out" }; + ASSERT_EQ(OutputsSpec::parse(str), expected); + ASSERT_EQ(expected.to_string(), str); +} + +TEST(OutputsSpec, names_underscore) { + std::string_view str = "a_b"; + OutputsSpec expected = OutputsSpec::Names { "a_b" }; + ASSERT_EQ(OutputsSpec::parse(str), expected); + ASSERT_EQ(expected.to_string(), str); +} + +TEST(OutputsSpec, names_numberic) { + std::string_view str = "01"; + OutputsSpec expected = OutputsSpec::Names { "01" }; + ASSERT_EQ(OutputsSpec::parse(str), expected); + ASSERT_EQ(expected.to_string(), str); +} + +TEST(OutputsSpec, names_out_bin) { + OutputsSpec expected = OutputsSpec::Names { "out", "bin" }; + ASSERT_EQ(OutputsSpec::parse("out,bin"), expected); + // N.B. This normalization is OK. + ASSERT_EQ(expected.to_string(), "bin,out"); +} + +#define TEST_SUBSET(X, THIS, THAT) \ + X((OutputsSpec { THIS }).isSubsetOf(THAT)); + +TEST(OutputsSpec, subsets_all_all) { + TEST_SUBSET(ASSERT_TRUE, OutputsSpec::All { }, OutputsSpec::All { }); +} + +TEST(OutputsSpec, subsets_names_all) { + TEST_SUBSET(ASSERT_TRUE, OutputsSpec::Names { "a" }, OutputsSpec::All { }); +} + +TEST(OutputsSpec, subsets_names_names_eq) { + TEST_SUBSET(ASSERT_TRUE, OutputsSpec::Names { "a" }, OutputsSpec::Names { "a" }); +} + +TEST(OutputsSpec, subsets_names_names_noneq) { + TEST_SUBSET(ASSERT_TRUE, OutputsSpec::Names { "a" }, (OutputsSpec::Names { "a", "b" })); +} + +TEST(OutputsSpec, not_subsets_all_names) { + TEST_SUBSET(ASSERT_FALSE, OutputsSpec::All { }, OutputsSpec::Names { "a" }); +} + +TEST(OutputsSpec, not_subsets_names_names) { + TEST_SUBSET(ASSERT_FALSE, (OutputsSpec::Names { "a", "b" }), (OutputsSpec::Names { "a" })); +} + +#undef TEST_SUBSET + +#define TEST_UNION(RES, THIS, THAT) \ + ASSERT_EQ(OutputsSpec { RES }, (OutputsSpec { THIS }).union_(THAT)); + +TEST(OutputsSpec, union_all_all) { + TEST_UNION(OutputsSpec::All { }, OutputsSpec::All { }, OutputsSpec::All { }); +} + +TEST(OutputsSpec, union_all_names) { + TEST_UNION(OutputsSpec::All { }, OutputsSpec::All { }, OutputsSpec::Names { "a" }); +} + +TEST(OutputsSpec, union_names_all) { + TEST_UNION(OutputsSpec::All { }, OutputsSpec::Names { "a" }, OutputsSpec::All { }); +} + +TEST(OutputsSpec, union_names_names) { + TEST_UNION((OutputsSpec::Names { "a", "b" }), OutputsSpec::Names { "a" }, OutputsSpec::Names { "b" }); +} + +#undef TEST_UNION + +#define TEST_DONT_PARSE(NAME, STR) \ + TEST(ExtendedOutputsSpec, bad_ ## NAME) { \ + std::optional extendedOutputsSpecOpt = \ + ExtendedOutputsSpec::parseOpt(STR); \ + ASSERT_FALSE(extendedOutputsSpecOpt); \ + } + +TEST_DONT_PARSE(carot_empty, "^") +TEST_DONT_PARSE(prefix_carot_empty, "foo^") +TEST_DONT_PARSE(garbage, "^&*()") +TEST_DONT_PARSE(double_star, "^**") +TEST_DONT_PARSE(star_first, "^*,foo") +TEST_DONT_PARSE(star_second, "^foo,*") + +#undef TEST_DONT_PARSE + +TEST(ExtendedOutputsSpec, defeault) { + std::string_view str = "foo"; + auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(str); + ASSERT_EQ(prefix, "foo"); + ExtendedOutputsSpec expected = ExtendedOutputsSpec::Default { }; + ASSERT_EQ(extendedOutputsSpec, expected); + ASSERT_EQ(std::string { prefix } + expected.to_string(), str); +} + +TEST(ExtendedOutputsSpec, all) { + std::string_view str = "foo^*"; + auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(str); + ASSERT_EQ(prefix, "foo"); + ExtendedOutputsSpec expected = OutputsSpec::All { }; + ASSERT_EQ(extendedOutputsSpec, expected); + ASSERT_EQ(std::string { prefix } + expected.to_string(), str); +} + +TEST(ExtendedOutputsSpec, out) { + std::string_view str = "foo^out"; + auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(str); + ASSERT_EQ(prefix, "foo"); + ExtendedOutputsSpec expected = OutputsSpec::Names { "out" }; + ASSERT_EQ(extendedOutputsSpec, expected); + ASSERT_EQ(std::string { prefix } + expected.to_string(), str); +} + +TEST(ExtendedOutputsSpec, out_bin) { + auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse("foo^out,bin"); + ASSERT_EQ(prefix, "foo"); + ExtendedOutputsSpec expected = OutputsSpec::Names { "out", "bin" }; + ASSERT_EQ(extendedOutputsSpec, expected); + ASSERT_EQ(std::string { prefix } + expected.to_string(), "foo^bin,out"); +} + +TEST(ExtendedOutputsSpec, many_carrot) { + auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse("foo^bar^out,bin"); + ASSERT_EQ(prefix, "foo^bar"); + ExtendedOutputsSpec expected = OutputsSpec::Names { "out", "bin" }; + ASSERT_EQ(extendedOutputsSpec, expected); + ASSERT_EQ(std::string { prefix } + expected.to_string(), "foo^bar^bin,out"); +} + + +#define TEST_JSON(TYPE, NAME, STR, VAL) \ + \ + TEST(TYPE, NAME ## _to_json) { \ + using nlohmann::literals::operator "" _json; \ + ASSERT_EQ( \ + STR ## _json, \ + ((nlohmann::json) TYPE { VAL })); \ + } \ + \ + TEST(TYPE, NAME ## _from_json) { \ + using nlohmann::literals::operator "" _json; \ + ASSERT_EQ( \ + TYPE { VAL }, \ + (STR ## _json).get()); \ + } + +TEST_JSON(OutputsSpec, all, R"(["*"])", OutputsSpec::All { }) +TEST_JSON(OutputsSpec, name, R"(["a"])", OutputsSpec::Names { "a" }) +TEST_JSON(OutputsSpec, names, R"(["a","b"])", (OutputsSpec::Names { "a", "b" })) + +TEST_JSON(ExtendedOutputsSpec, def, R"(null)", ExtendedOutputsSpec::Default { }) +TEST_JSON(ExtendedOutputsSpec, all, R"(["*"])", ExtendedOutputsSpec::Explicit { OutputsSpec::All { } }) +TEST_JSON(ExtendedOutputsSpec, name, R"(["a"])", ExtendedOutputsSpec::Explicit { OutputsSpec::Names { "a" } }) +TEST_JSON(ExtendedOutputsSpec, names, R"(["a","b"])", (ExtendedOutputsSpec::Explicit { OutputsSpec::Names { "a", "b" } })) + +#undef TEST_JSON + +#ifndef COVERAGE + +RC_GTEST_PROP( + OutputsSpec, + prop_round_rip, + (const OutputsSpec & o)) +{ + RC_ASSERT(o == OutputsSpec::parse(o.to_string())); +} + +#endif + +} diff --git a/tests/unit/libstore/path.cc b/tests/unit/libstore/path.cc new file mode 100644 index 000000000..30631b5fd --- /dev/null +++ b/tests/unit/libstore/path.cc @@ -0,0 +1,89 @@ +#include + +#include +#include +#include + +#include "path-regex.hh" +#include "store-api.hh" + +#include "tests/hash.hh" +#include "tests/libstore.hh" +#include "tests/path.hh" + +namespace nix { + +#define STORE_DIR "/nix/store/" +#define HASH_PART "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q" + +class StorePathTest : public LibStoreTest +{ +}; + +static std::regex nameRegex { std::string { nameRegexStr } }; + +#define TEST_DONT_PARSE(NAME, STR) \ + TEST_F(StorePathTest, bad_ ## NAME) { \ + std::string_view str = \ + STORE_DIR HASH_PART "-" STR; \ + ASSERT_THROW( \ + store->parseStorePath(str), \ + BadStorePath); \ + std::string name { STR }; \ + EXPECT_FALSE(std::regex_match(name, nameRegex)); \ + } + +TEST_DONT_PARSE(empty, "") +TEST_DONT_PARSE(garbage, "&*()") +TEST_DONT_PARSE(double_star, "**") +TEST_DONT_PARSE(star_first, "*,foo") +TEST_DONT_PARSE(star_second, "foo,*") +TEST_DONT_PARSE(bang, "foo!o") +TEST_DONT_PARSE(dotfile, ".gitignore") + +#undef TEST_DONT_PARSE + +#define TEST_DO_PARSE(NAME, STR) \ + TEST_F(StorePathTest, good_ ## NAME) { \ + std::string_view str = \ + STORE_DIR HASH_PART "-" STR; \ + auto p = store->parseStorePath(str); \ + std::string name { p.name() }; \ + EXPECT_TRUE(std::regex_match(name, nameRegex)); \ + } + +// 0-9 a-z A-Z + - . _ ? = + +TEST_DO_PARSE(numbers, "02345") +TEST_DO_PARSE(lower_case, "foo") +TEST_DO_PARSE(upper_case, "FOO") +TEST_DO_PARSE(plus, "foo+bar") +TEST_DO_PARSE(dash, "foo-dev") +TEST_DO_PARSE(underscore, "foo_bar") +TEST_DO_PARSE(period, "foo.txt") +TEST_DO_PARSE(question_mark, "foo?why") +TEST_DO_PARSE(equals_sign, "foo=foo") + +#undef TEST_DO_PARSE + +#ifndef COVERAGE + +RC_GTEST_FIXTURE_PROP( + StorePathTest, + prop_regex_accept, + (const StorePath & p)) +{ + RC_ASSERT(std::regex_match(std::string { p.name() }, nameRegex)); +} + +RC_GTEST_FIXTURE_PROP( + StorePathTest, + prop_round_rip, + (const StorePath & p)) +{ + RC_ASSERT(p == store->parseStorePath(store->printStorePath(p))); +} + +#endif + +} diff --git a/tests/unit/libstore/references.cc b/tests/unit/libstore/references.cc new file mode 100644 index 000000000..d91d1cedd --- /dev/null +++ b/tests/unit/libstore/references.cc @@ -0,0 +1,45 @@ +#include "references.hh" + +#include + +namespace nix { + +TEST(references, scan) +{ + std::string hash1 = "dc04vv14dak1c1r48qa0m23vr9jy8sm0"; + std::string hash2 = "zc842j0rz61mjsp3h3wp5ly71ak6qgdn"; + + { + RefScanSink scanner(StringSet{hash1}); + auto s = "foobar"; + scanner(s); + ASSERT_EQ(scanner.getResult(), StringSet{}); + } + + { + RefScanSink scanner(StringSet{hash1}); + auto s = "foobar" + hash1 + "xyzzy"; + scanner(s); + ASSERT_EQ(scanner.getResult(), StringSet{hash1}); + } + + { + RefScanSink scanner(StringSet{hash1, hash2}); + auto s = "foobar" + hash1 + "xyzzy" + hash2; + scanner(((std::string_view) s).substr(0, 10)); + scanner(((std::string_view) s).substr(10, 5)); + scanner(((std::string_view) s).substr(15, 5)); + scanner(((std::string_view) s).substr(20)); + ASSERT_EQ(scanner.getResult(), StringSet({hash1, hash2})); + } + + { + RefScanSink scanner(StringSet{hash1, hash2}); + auto s = "foobar" + hash1 + "xyzzy" + hash2; + for (auto & i : s) + scanner(std::string(1, i)); + ASSERT_EQ(scanner.getResult(), StringSet({hash1, hash2})); + } +} + +} diff --git a/tests/unit/libstore/test-data/machines.bad_format b/tests/unit/libstore/test-data/machines.bad_format new file mode 100644 index 000000000..7255a1216 --- /dev/null +++ b/tests/unit/libstore/test-data/machines.bad_format @@ -0,0 +1 @@ +nix@scratchy.labs.cs.uu.nl - - eight diff --git a/tests/unit/libstore/test-data/machines.valid b/tests/unit/libstore/test-data/machines.valid new file mode 100644 index 000000000..1a6c8017c --- /dev/null +++ b/tests/unit/libstore/test-data/machines.valid @@ -0,0 +1,3 @@ +nix@scratchy.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 8 1 kvm +nix@itchy.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 8 2 +nix@poochie.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 1 2 kvm benchmark c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFDQVFDWWV5R1laNTNzd1VjMUZNSHBWL1BCcXlKaFR5S1JoRkpWWVRpRHlQN2h5c1JGa0w4VDlLOGdhL2Y2L3c3QjN2SjNHSFRIUFkybENiUEdZbGNLd2h6M2ZRbFNNOEViNi95b3ZLajdvM1FsMEx5Y0dzdGJvRmcwWkZKNldncUxsR0ltS0NobUlxOGZ3TW5ZTWUxbnRQeTBUZFZjSU1tOTV3YzF3SjBMd2c3cEVMRmtHazdkeTVvYnM4a3lGZ0pORDVRSmFwQWJjeWp4Z1QzdzdMcktNZ2xzeWhhd01JNVpkMGZsQTVudW5OZ3pid3plYVhLaUsyTW0vdGJXYTU1YTd4QmNYdHpIZGlPSWdSajJlRWxaMGh5bk10YjBmcklsdmxIcEtLaVFaZ3pQdCtIVXQ2bXpRMkRVME52MGYyYnNSU0krOGpJU2pQcmdlcVVHRldMUzVIUTg2N2xSMlpiaWtyclhZNTdqbVFEZk5DRHY1VFBHZU9UekFEd2pjMDc2aFZ3VFJCd3VTZFhtaWNxTS95b3lrWitkV1dnZ25MenE5QU1tdlNZcDhmZkZDcS9CSDBZNUFXWTFHay9vS3hMVTNaOWt3ZDd2UWNFQWFCQ2dxdnVZRGdTaHE1RlhndDM3OVZESWtEL05ZSTg2QXVvajVDRmVNTzlRM2pJSlRadlh6c1VldjVoSnA2djcxSVh5ODVtbTY5R20zcXdicVE1SjVQZDU1Um56SitpaW5BNjZxTEFSc0Y4amNsSnd5ekFXclBoYU9DRVY2bjVMeVhVazhzMW9EVVR4V1pWN25rVkFTbHJ0MllGcjN5dzdjRTRXQVhsemhHcDhocmdLMVVkMUlyeDVnZWRaSnBWcy9uNWVybmJFMUxmb2x5UHUvRUFIWlh6VGd4dHVDUFNobXc9PQo= diff --git a/tests/unit/libutil-support/local.mk b/tests/unit/libutil-support/local.mk new file mode 100644 index 000000000..d085eda4e --- /dev/null +++ b/tests/unit/libutil-support/local.mk @@ -0,0 +1,15 @@ +libraries += libutil-test-support + +libutil-test-support_NAME = libnixutil-test-support + +libutil-test-support_DIR := $(d) + +libutil-test-support_INSTALL_DIR := + +libutil-test-support_SOURCES := $(wildcard $(d)/tests/*.cc) + +libutil-test-support_CXXFLAGS += $(libutil-tests_EXTRA_INCLUDES) + +libutil-test-support_LIBS = libutil + +libutil-test-support_LDFLAGS := -lrapidcheck diff --git a/tests/unit/libutil-support/tests/hash.cc b/tests/unit/libutil-support/tests/hash.cc new file mode 100644 index 000000000..577e9890e --- /dev/null +++ b/tests/unit/libutil-support/tests/hash.cc @@ -0,0 +1,20 @@ +#include + +#include + +#include "hash.hh" + +#include "tests/hash.hh" + +namespace rc { +using namespace nix; + +Gen Arbitrary::arbitrary() +{ + Hash hash(htSHA1); + for (size_t i = 0; i < hash.hashSize; ++i) + hash.hash[i] = *gen::arbitrary(); + return gen::just(hash); +} + +} diff --git a/tests/unit/libutil-support/tests/hash.hh b/tests/unit/libutil-support/tests/hash.hh new file mode 100644 index 000000000..1f9fa59ae --- /dev/null +++ b/tests/unit/libutil-support/tests/hash.hh @@ -0,0 +1,16 @@ +#pragma once +///@file + +#include + +#include + +namespace rc { +using namespace nix; + +template<> +struct Arbitrary { + static Gen arbitrary(); +}; + +} diff --git a/tests/unit/libutil/canon-path.cc b/tests/unit/libutil/canon-path.cc new file mode 100644 index 000000000..fc94ccc3d --- /dev/null +++ b/tests/unit/libutil/canon-path.cc @@ -0,0 +1,162 @@ +#include "canon-path.hh" + +#include + +namespace nix { + + TEST(CanonPath, basic) { + { + CanonPath p("/"); + ASSERT_EQ(p.abs(), "/"); + ASSERT_EQ(p.rel(), ""); + ASSERT_EQ(p.baseName(), std::nullopt); + ASSERT_EQ(p.dirOf(), std::nullopt); + ASSERT_FALSE(p.parent()); + } + + { + CanonPath p("/foo//"); + ASSERT_EQ(p.abs(), "/foo"); + ASSERT_EQ(p.rel(), "foo"); + ASSERT_EQ(*p.baseName(), "foo"); + ASSERT_EQ(*p.dirOf(), ""); // FIXME: do we want this? + ASSERT_EQ(p.parent()->abs(), "/"); + } + + { + CanonPath p("foo/bar"); + ASSERT_EQ(p.abs(), "/foo/bar"); + ASSERT_EQ(p.rel(), "foo/bar"); + ASSERT_EQ(*p.baseName(), "bar"); + ASSERT_EQ(*p.dirOf(), "/foo"); + ASSERT_EQ(p.parent()->abs(), "/foo"); + } + + { + CanonPath p("foo//bar/"); + ASSERT_EQ(p.abs(), "/foo/bar"); + ASSERT_EQ(p.rel(), "foo/bar"); + ASSERT_EQ(*p.baseName(), "bar"); + ASSERT_EQ(*p.dirOf(), "/foo"); + } + } + + TEST(CanonPath, pop) { + CanonPath p("foo/bar/x"); + ASSERT_EQ(p.abs(), "/foo/bar/x"); + p.pop(); + ASSERT_EQ(p.abs(), "/foo/bar"); + p.pop(); + ASSERT_EQ(p.abs(), "/foo"); + p.pop(); + ASSERT_EQ(p.abs(), "/"); + } + + TEST(CanonPath, removePrefix) { + CanonPath p1("foo/bar"); + CanonPath p2("foo/bar/a/b/c"); + ASSERT_EQ(p2.removePrefix(p1).abs(), "/a/b/c"); + ASSERT_EQ(p1.removePrefix(p1).abs(), "/"); + ASSERT_EQ(p1.removePrefix(CanonPath("/")).abs(), "/foo/bar"); + } + + TEST(CanonPath, iter) { + { + CanonPath p("a//foo/bar//"); + std::vector ss; + for (auto & c : p) ss.push_back(c); + ASSERT_EQ(ss, std::vector({"a", "foo", "bar"})); + } + + { + CanonPath p("/"); + std::vector ss; + for (auto & c : p) ss.push_back(c); + ASSERT_EQ(ss, std::vector()); + } + } + + TEST(CanonPath, concat) { + { + CanonPath p1("a//foo/bar//"); + CanonPath p2("xyzzy/bla"); + ASSERT_EQ((p1 + p2).abs(), "/a/foo/bar/xyzzy/bla"); + } + + { + CanonPath p1("/"); + CanonPath p2("/a/b"); + ASSERT_EQ((p1 + p2).abs(), "/a/b"); + } + + { + CanonPath p1("/a/b"); + CanonPath p2("/"); + ASSERT_EQ((p1 + p2).abs(), "/a/b"); + } + + { + CanonPath p("/foo/bar"); + ASSERT_EQ((p + "x").abs(), "/foo/bar/x"); + } + + { + CanonPath p("/"); + ASSERT_EQ((p + "foo" + "bar").abs(), "/foo/bar"); + } + } + + TEST(CanonPath, within) { + ASSERT_TRUE(CanonPath("foo").isWithin(CanonPath("foo"))); + ASSERT_FALSE(CanonPath("foo").isWithin(CanonPath("bar"))); + ASSERT_FALSE(CanonPath("foo").isWithin(CanonPath("fo"))); + ASSERT_TRUE(CanonPath("foo/bar").isWithin(CanonPath("foo"))); + ASSERT_FALSE(CanonPath("foo").isWithin(CanonPath("foo/bar"))); + ASSERT_TRUE(CanonPath("/foo/bar/default.nix").isWithin(CanonPath("/"))); + ASSERT_TRUE(CanonPath("/").isWithin(CanonPath("/"))); + } + + TEST(CanonPath, sort) { + ASSERT_FALSE(CanonPath("foo") < CanonPath("foo")); + ASSERT_TRUE (CanonPath("foo") < CanonPath("foo/bar")); + ASSERT_TRUE (CanonPath("foo/bar") < CanonPath("foo!")); + ASSERT_FALSE(CanonPath("foo!") < CanonPath("foo")); + ASSERT_TRUE (CanonPath("foo") < CanonPath("foo!")); + } + + TEST(CanonPath, allowed) { + std::set allowed { + CanonPath("foo/bar"), + CanonPath("foo!"), + CanonPath("xyzzy"), + CanonPath("a/b/c"), + }; + + ASSERT_TRUE (CanonPath("foo/bar").isAllowed(allowed)); + ASSERT_TRUE (CanonPath("foo/bar/bla").isAllowed(allowed)); + ASSERT_TRUE (CanonPath("foo").isAllowed(allowed)); + ASSERT_FALSE(CanonPath("bar").isAllowed(allowed)); + ASSERT_FALSE(CanonPath("bar/a").isAllowed(allowed)); + ASSERT_TRUE (CanonPath("a").isAllowed(allowed)); + ASSERT_TRUE (CanonPath("a/b").isAllowed(allowed)); + ASSERT_TRUE (CanonPath("a/b/c").isAllowed(allowed)); + ASSERT_TRUE (CanonPath("a/b/c/d").isAllowed(allowed)); + ASSERT_TRUE (CanonPath("a/b/c/d/e").isAllowed(allowed)); + ASSERT_FALSE(CanonPath("a/b/a").isAllowed(allowed)); + ASSERT_FALSE(CanonPath("a/b/d").isAllowed(allowed)); + ASSERT_FALSE(CanonPath("aaa").isAllowed(allowed)); + ASSERT_FALSE(CanonPath("zzz").isAllowed(allowed)); + ASSERT_TRUE (CanonPath("/").isAllowed(allowed)); + } + + TEST(CanonPath, makeRelative) { + CanonPath d("/foo/bar"); + ASSERT_EQ(d.makeRelative(CanonPath("/foo/bar")), "."); + ASSERT_EQ(d.makeRelative(CanonPath("/foo")), ".."); + ASSERT_EQ(d.makeRelative(CanonPath("/")), "../.."); + ASSERT_EQ(d.makeRelative(CanonPath("/foo/bar/xyzzy")), "xyzzy"); + ASSERT_EQ(d.makeRelative(CanonPath("/foo/bar/xyzzy/bla")), "xyzzy/bla"); + ASSERT_EQ(d.makeRelative(CanonPath("/foo/xyzzy/bla")), "../xyzzy/bla"); + ASSERT_EQ(d.makeRelative(CanonPath("/xyzzy/bla")), "../../xyzzy/bla"); + } +} diff --git a/tests/unit/libutil/chunked-vector.cc b/tests/unit/libutil/chunked-vector.cc new file mode 100644 index 000000000..868d11f6f --- /dev/null +++ b/tests/unit/libutil/chunked-vector.cc @@ -0,0 +1,54 @@ +#include "chunked-vector.hh" + +#include + +namespace nix { + TEST(ChunkedVector, InitEmpty) { + auto v = ChunkedVector(100); + ASSERT_EQ(v.size(), 0); + } + + TEST(ChunkedVector, GrowsCorrectly) { + auto v = ChunkedVector(100); + for (auto i = 1; i < 20; i++) { + v.add(i); + ASSERT_EQ(v.size(), i); + } + } + + TEST(ChunkedVector, AddAndGet) { + auto v = ChunkedVector(100); + for (auto i = 1; i < 20; i++) { + auto [i2, idx] = v.add(i); + auto & i3 = v[idx]; + ASSERT_EQ(i, i2); + ASSERT_EQ(&i2, &i3); + } + } + + TEST(ChunkedVector, ForEach) { + auto v = ChunkedVector(100); + for (auto i = 1; i < 20; i++) { + v.add(i); + } + int count = 0; + v.forEach([&count](int elt) { + count++; + }); + ASSERT_EQ(count, v.size()); + } + + TEST(ChunkedVector, OverflowOK) { + // Similar to the AddAndGet, but intentionnally use a small + // initial ChunkedVector to force it to overflow + auto v = ChunkedVector(2); + for (auto i = 1; i < 20; i++) { + auto [i2, idx] = v.add(i); + auto & i3 = v[idx]; + ASSERT_EQ(i, i2); + ASSERT_EQ(&i2, &i3); + } + } + +} + diff --git a/tests/unit/libutil/closure.cc b/tests/unit/libutil/closure.cc new file mode 100644 index 000000000..7597e7807 --- /dev/null +++ b/tests/unit/libutil/closure.cc @@ -0,0 +1,70 @@ +#include "closure.hh" +#include + +namespace nix { + +using namespace std; + +map> testGraph = { + { "A", { "B", "C", "G" } }, + { "B", { "A" } }, // Loops back to A + { "C", { "F" } }, // Indirect reference + { "D", { "A" } }, // Not reachable, but has backreferences + { "E", {} }, // Just not reachable + { "F", {} }, + { "G", { "G" } }, // Self reference +}; + +TEST(closure, correctClosure) { + set aClosure; + set expectedClosure = {"A", "B", "C", "F", "G"}; + computeClosure( + {"A"}, + aClosure, + [&](const string currentNode, function> &)> processEdges) { + promise> promisedNodes; + promisedNodes.set_value(testGraph[currentNode]); + processEdges(promisedNodes); + } + ); + + ASSERT_EQ(aClosure, expectedClosure); +} + +TEST(closure, properlyHandlesDirectExceptions) { + struct TestExn {}; + set aClosure; + EXPECT_THROW( + computeClosure( + {"A"}, + aClosure, + [&](const string currentNode, function> &)> processEdges) { + throw TestExn(); + } + ), + TestExn + ); +} + +TEST(closure, properlyHandlesExceptionsInPromise) { + struct TestExn {}; + set aClosure; + EXPECT_THROW( + computeClosure( + {"A"}, + aClosure, + [&](const string currentNode, function> &)> processEdges) { + promise> promise; + try { + throw TestExn(); + } catch (...) { + promise.set_exception(std::current_exception()); + } + processEdges(promise); + } + ), + TestExn + ); +} + +} diff --git a/tests/unit/libutil/compression.cc b/tests/unit/libutil/compression.cc new file mode 100644 index 000000000..bbbf3500f --- /dev/null +++ b/tests/unit/libutil/compression.cc @@ -0,0 +1,96 @@ +#include "compression.hh" +#include + +namespace nix { + + /* ---------------------------------------------------------------------------- + * compress / decompress + * --------------------------------------------------------------------------*/ + + TEST(compress, compressWithUnknownMethod) { + ASSERT_THROW(compress("invalid-method", "something-to-compress"), UnknownCompressionMethod); + } + + TEST(compress, noneMethodDoesNothingToTheInput) { + auto o = compress("none", "this-is-a-test"); + + ASSERT_EQ(o, "this-is-a-test"); + } + + TEST(decompress, decompressNoneCompressed) { + auto method = "none"; + auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + auto o = decompress(method, str); + + ASSERT_EQ(o, str); + } + + TEST(decompress, decompressEmptyCompressed) { + // Empty-method decompression used e.g. by S3 store + // (Content-Encoding == ""). + auto method = ""; + auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + auto o = decompress(method, str); + + ASSERT_EQ(o, str); + } + + TEST(decompress, decompressXzCompressed) { + auto method = "xz"; + auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + auto o = decompress(method, compress(method, str)); + + ASSERT_EQ(o, str); + } + + TEST(decompress, decompressBzip2Compressed) { + auto method = "bzip2"; + auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + auto o = decompress(method, compress(method, str)); + + ASSERT_EQ(o, str); + } + + TEST(decompress, decompressBrCompressed) { + auto method = "br"; + auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + auto o = decompress(method, compress(method, str)); + + ASSERT_EQ(o, str); + } + + TEST(decompress, decompressInvalidInputThrowsCompressionError) { + auto method = "bzip2"; + auto str = "this is a string that does not qualify as valid bzip2 data"; + + ASSERT_THROW(decompress(method, str), CompressionError); + } + + /* ---------------------------------------------------------------------------- + * compression sinks + * --------------------------------------------------------------------------*/ + + TEST(makeCompressionSink, noneSinkDoesNothingToInput) { + StringSink strSink; + auto inputString = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + auto sink = makeCompressionSink("none", strSink); + (*sink)(inputString); + sink->finish(); + + ASSERT_STREQ(strSink.s.c_str(), inputString); + } + + TEST(makeCompressionSink, compressAndDecompress) { + StringSink strSink; + auto inputString = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + auto decompressionSink = makeDecompressionSink("bzip2", strSink); + auto sink = makeCompressionSink("bzip2", *decompressionSink); + + (*sink)(inputString); + sink->finish(); + decompressionSink->finish(); + + ASSERT_STREQ(strSink.s.c_str(), inputString); + } + +} diff --git a/tests/unit/libutil/config.cc b/tests/unit/libutil/config.cc new file mode 100644 index 000000000..886e70da5 --- /dev/null +++ b/tests/unit/libutil/config.cc @@ -0,0 +1,295 @@ +#include "config.hh" +#include "args.hh" + +#include +#include +#include + +namespace nix { + + /* ---------------------------------------------------------------------------- + * Config + * --------------------------------------------------------------------------*/ + + TEST(Config, setUndefinedSetting) { + Config config; + ASSERT_EQ(config.set("undefined-key", "value"), false); + } + + TEST(Config, setDefinedSetting) { + Config config; + std::string value; + Setting foo{&config, value, "name-of-the-setting", "description"}; + ASSERT_EQ(config.set("name-of-the-setting", "value"), true); + } + + TEST(Config, getDefinedSetting) { + Config config; + std::string value; + std::map settings; + Setting foo{&config, value, "name-of-the-setting", "description"}; + + config.getSettings(settings, /* overriddenOnly = */ false); + const auto iter = settings.find("name-of-the-setting"); + ASSERT_NE(iter, settings.end()); + ASSERT_EQ(iter->second.value, ""); + ASSERT_EQ(iter->second.description, "description\n"); + } + + TEST(Config, getDefinedOverriddenSettingNotSet) { + Config config; + std::string value; + std::map settings; + Setting foo{&config, value, "name-of-the-setting", "description"}; + + config.getSettings(settings, /* overriddenOnly = */ true); + const auto e = settings.find("name-of-the-setting"); + ASSERT_EQ(e, settings.end()); + } + + TEST(Config, getDefinedSettingSet1) { + Config config; + std::string value; + std::map settings; + Setting setting{&config, value, "name-of-the-setting", "description"}; + + setting.assign("value"); + + config.getSettings(settings, /* overriddenOnly = */ false); + const auto iter = settings.find("name-of-the-setting"); + ASSERT_NE(iter, settings.end()); + ASSERT_EQ(iter->second.value, "value"); + ASSERT_EQ(iter->second.description, "description\n"); + } + + TEST(Config, getDefinedSettingSet2) { + Config config; + std::map settings; + Setting setting{&config, "", "name-of-the-setting", "description"}; + + ASSERT_TRUE(config.set("name-of-the-setting", "value")); + + config.getSettings(settings, /* overriddenOnly = */ false); + const auto e = settings.find("name-of-the-setting"); + ASSERT_NE(e, settings.end()); + ASSERT_EQ(e->second.value, "value"); + ASSERT_EQ(e->second.description, "description\n"); + } + + TEST(Config, addSetting) { + class TestSetting : public AbstractSetting { + public: + TestSetting() : AbstractSetting("test", "test", {}) {} + void set(const std::string & value, bool append) override {} + std::string to_string() const override { return {}; } + bool isAppendable() override { return false; } + }; + + Config config; + TestSetting setting; + + ASSERT_FALSE(config.set("test", "value")); + config.addSetting(&setting); + ASSERT_TRUE(config.set("test", "value")); + ASSERT_FALSE(config.set("extra-test", "value")); + } + + TEST(Config, withInitialValue) { + const StringMap initials = { + { "key", "value" }, + }; + Config config(initials); + + { + std::map settings; + config.getSettings(settings, /* overriddenOnly = */ false); + ASSERT_EQ(settings.find("key"), settings.end()); + } + + Setting setting{&config, "default-value", "key", "description"}; + + { + std::map settings; + config.getSettings(settings, /* overriddenOnly = */ false); + ASSERT_EQ(settings["key"].value, "value"); + } + } + + TEST(Config, resetOverridden) { + Config config; + config.resetOverridden(); + } + + TEST(Config, resetOverriddenWithSetting) { + Config config; + Setting setting{&config, "", "name-of-the-setting", "description"}; + + { + std::map settings; + + setting.set("foo"); + ASSERT_EQ(setting.get(), "foo"); + config.getSettings(settings, /* overriddenOnly = */ true); + ASSERT_TRUE(settings.empty()); + } + + { + std::map settings; + + setting.override("bar"); + ASSERT_TRUE(setting.overridden); + ASSERT_EQ(setting.get(), "bar"); + config.getSettings(settings, /* overriddenOnly = */ true); + ASSERT_FALSE(settings.empty()); + } + + { + std::map settings; + + config.resetOverridden(); + ASSERT_FALSE(setting.overridden); + config.getSettings(settings, /* overriddenOnly = */ true); + ASSERT_TRUE(settings.empty()); + } + } + + TEST(Config, toJSONOnEmptyConfig) { + ASSERT_EQ(Config().toJSON().dump(), "{}"); + } + + TEST(Config, toJSONOnNonEmptyConfig) { + using nlohmann::literals::operator "" _json; + Config config; + Setting setting{ + &config, + "", + "name-of-the-setting", + "description", + }; + setting.assign("value"); + + ASSERT_EQ(config.toJSON(), + R"#({ + "name-of-the-setting": { + "aliases": [], + "defaultValue": "", + "description": "description\n", + "documentDefault": true, + "value": "value", + "experimentalFeature": null + } + })#"_json); + } + + TEST(Config, toJSONOnNonEmptyConfigWithExperimentalSetting) { + using nlohmann::literals::operator "" _json; + Config config; + Setting setting{ + &config, + "", + "name-of-the-setting", + "description", + {}, + true, + Xp::Flakes, + }; + setting.assign("value"); + + ASSERT_EQ(config.toJSON(), + R"#({ + "name-of-the-setting": { + "aliases": [], + "defaultValue": "", + "description": "description\n", + "documentDefault": true, + "value": "value", + "experimentalFeature": "flakes" + } + })#"_json); + } + + TEST(Config, setSettingAlias) { + Config config; + Setting setting{&config, "", "some-int", "best number", { "another-int" }}; + ASSERT_TRUE(config.set("some-int", "1")); + ASSERT_EQ(setting.get(), "1"); + ASSERT_TRUE(config.set("another-int", "2")); + ASSERT_EQ(setting.get(), "2"); + ASSERT_TRUE(config.set("some-int", "3")); + ASSERT_EQ(setting.get(), "3"); + } + + /* FIXME: The reapplyUnknownSettings method doesn't seem to do anything + * useful (these days). Whenever we add a new setting to Config the + * unknown settings are always considered. In which case is this function + * actually useful? Is there some way to register a Setting without calling + * addSetting? */ + TEST(Config, DISABLED_reapplyUnknownSettings) { + Config config; + ASSERT_FALSE(config.set("name-of-the-setting", "unknownvalue")); + Setting setting{&config, "default", "name-of-the-setting", "description"}; + ASSERT_EQ(setting.get(), "default"); + config.reapplyUnknownSettings(); + ASSERT_EQ(setting.get(), "unknownvalue"); + } + + TEST(Config, applyConfigEmpty) { + Config config; + std::map settings; + config.applyConfig(""); + config.getSettings(settings); + ASSERT_TRUE(settings.empty()); + } + + TEST(Config, applyConfigEmptyWithComment) { + Config config; + std::map settings; + config.applyConfig("# just a comment"); + config.getSettings(settings); + ASSERT_TRUE(settings.empty()); + } + + TEST(Config, applyConfigAssignment) { + Config config; + std::map settings; + Setting setting{&config, "", "name-of-the-setting", "description"}; + config.applyConfig( + "name-of-the-setting = value-from-file #useful comment\n" + "# name-of-the-setting = foo\n" + ); + config.getSettings(settings); + ASSERT_FALSE(settings.empty()); + ASSERT_EQ(settings["name-of-the-setting"].value, "value-from-file"); + } + + TEST(Config, applyConfigWithReassignedSetting) { + Config config; + std::map settings; + Setting setting{&config, "", "name-of-the-setting", "description"}; + config.applyConfig( + "name-of-the-setting = first-value\n" + "name-of-the-setting = second-value\n" + ); + config.getSettings(settings); + ASSERT_FALSE(settings.empty()); + ASSERT_EQ(settings["name-of-the-setting"].value, "second-value"); + } + + TEST(Config, applyConfigFailsOnMissingIncludes) { + Config config; + std::map settings; + Setting setting{&config, "", "name-of-the-setting", "description"}; + + ASSERT_THROW(config.applyConfig( + "name-of-the-setting = value-from-file\n" + "# name-of-the-setting = foo\n" + "include /nix/store/does/not/exist.nix" + ), Error); + } + + TEST(Config, applyConfigInvalidThrows) { + Config config; + ASSERT_THROW(config.applyConfig("value == key"), UsageError); + ASSERT_THROW(config.applyConfig("value "), UsageError); + } +} diff --git a/tests/unit/libutil/git.cc b/tests/unit/libutil/git.cc new file mode 100644 index 000000000..5b5715fc2 --- /dev/null +++ b/tests/unit/libutil/git.cc @@ -0,0 +1,33 @@ +#include "git.hh" +#include + +namespace nix { + + TEST(GitLsRemote, parseSymrefLineWithReference) { + auto line = "ref: refs/head/main HEAD"; + auto res = git::parseLsRemoteLine(line); + ASSERT_TRUE(res.has_value()); + ASSERT_EQ(res->kind, git::LsRemoteRefLine::Kind::Symbolic); + ASSERT_EQ(res->target, "refs/head/main"); + ASSERT_EQ(res->reference, "HEAD"); + } + + TEST(GitLsRemote, parseSymrefLineWithNoReference) { + auto line = "ref: refs/head/main"; + auto res = git::parseLsRemoteLine(line); + ASSERT_TRUE(res.has_value()); + ASSERT_EQ(res->kind, git::LsRemoteRefLine::Kind::Symbolic); + ASSERT_EQ(res->target, "refs/head/main"); + ASSERT_EQ(res->reference, std::nullopt); + } + + TEST(GitLsRemote, parseObjectRefLine) { + auto line = "abc123 refs/head/main"; + auto res = git::parseLsRemoteLine(line); + ASSERT_TRUE(res.has_value()); + ASSERT_EQ(res->kind, git::LsRemoteRefLine::Kind::Object); + ASSERT_EQ(res->target, "abc123"); + ASSERT_EQ(res->reference, "refs/head/main"); + } +} + diff --git a/tests/unit/libutil/hash.cc b/tests/unit/libutil/hash.cc new file mode 100644 index 000000000..1f40edc95 --- /dev/null +++ b/tests/unit/libutil/hash.cc @@ -0,0 +1,77 @@ +#include + +#include + +#include "hash.hh" + +namespace nix { + + /* ---------------------------------------------------------------------------- + * hashString + * --------------------------------------------------------------------------*/ + + TEST(hashString, testKnownMD5Hashes1) { + // values taken from: https://tools.ietf.org/html/rfc1321 + auto s1 = ""; + auto hash = hashString(HashType::htMD5, s1); + ASSERT_EQ(hash.to_string(Base::Base16, true), "md5:d41d8cd98f00b204e9800998ecf8427e"); + } + + TEST(hashString, testKnownMD5Hashes2) { + // values taken from: https://tools.ietf.org/html/rfc1321 + auto s2 = "abc"; + auto hash = hashString(HashType::htMD5, s2); + ASSERT_EQ(hash.to_string(Base::Base16, true), "md5:900150983cd24fb0d6963f7d28e17f72"); + } + + TEST(hashString, testKnownSHA1Hashes1) { + // values taken from: https://tools.ietf.org/html/rfc3174 + auto s = "abc"; + auto hash = hashString(HashType::htSHA1, s); + ASSERT_EQ(hash.to_string(Base::Base16, true),"sha1:a9993e364706816aba3e25717850c26c9cd0d89d"); + } + + TEST(hashString, testKnownSHA1Hashes2) { + // values taken from: https://tools.ietf.org/html/rfc3174 + auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + auto hash = hashString(HashType::htSHA1, s); + ASSERT_EQ(hash.to_string(Base::Base16, true),"sha1:84983e441c3bd26ebaae4aa1f95129e5e54670f1"); + } + + TEST(hashString, testKnownSHA256Hashes1) { + // values taken from: https://tools.ietf.org/html/rfc4634 + auto s = "abc"; + + auto hash = hashString(HashType::htSHA256, s); + ASSERT_EQ(hash.to_string(Base::Base16, true), + "sha256:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); + } + + TEST(hashString, testKnownSHA256Hashes2) { + // values taken from: https://tools.ietf.org/html/rfc4634 + auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + auto hash = hashString(HashType::htSHA256, s); + ASSERT_EQ(hash.to_string(Base::Base16, true), + "sha256:248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"); + } + + TEST(hashString, testKnownSHA512Hashes1) { + // values taken from: https://tools.ietf.org/html/rfc4634 + auto s = "abc"; + auto hash = hashString(HashType::htSHA512, s); + ASSERT_EQ(hash.to_string(Base::Base16, true), + "sha512:ddaf35a193617abacc417349ae20413112e6fa4e89a9" + "7ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd" + "454d4423643ce80e2a9ac94fa54ca49f"); + } + TEST(hashString, testKnownSHA512Hashes2) { + // values taken from: https://tools.ietf.org/html/rfc4634 + auto s = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; + + auto hash = hashString(HashType::htSHA512, s); + ASSERT_EQ(hash.to_string(Base::Base16, true), + "sha512:8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa1" + "7299aeadb6889018501d289e4900f7e4331b99dec4b5433a" + "c7d329eeb6dd26545e96e55b874be909"); + } +} diff --git a/tests/unit/libutil/hilite.cc b/tests/unit/libutil/hilite.cc new file mode 100644 index 000000000..1ff5980d5 --- /dev/null +++ b/tests/unit/libutil/hilite.cc @@ -0,0 +1,66 @@ +#include "hilite.hh" + +#include + +namespace nix { +/* ----------- tests for fmt.hh -------------------------------------------------*/ + + TEST(hiliteMatches, noHighlight) { + ASSERT_STREQ(hiliteMatches("Hello, world!", std::vector(), "(", ")").c_str(), "Hello, world!"); + } + + TEST(hiliteMatches, simpleHighlight) { + std::string str = "Hello, world!"; + std::regex re = std::regex("world"); + auto matches = std::vector(std::sregex_iterator(str.begin(), str.end(), re), std::sregex_iterator()); + ASSERT_STREQ( + hiliteMatches(str, matches, "(", ")").c_str(), + "Hello, (world)!" + ); + } + + TEST(hiliteMatches, multipleMatches) { + std::string str = "Hello, world, world, world, world, world, world, Hello!"; + std::regex re = std::regex("world"); + auto matches = std::vector(std::sregex_iterator(str.begin(), str.end(), re), std::sregex_iterator()); + ASSERT_STREQ( + hiliteMatches(str, matches, "(", ")").c_str(), + "Hello, (world), (world), (world), (world), (world), (world), Hello!" + ); + } + + TEST(hiliteMatches, overlappingMatches) { + std::string str = "world, Hello, world, Hello, world, Hello, world, Hello, world!"; + std::regex re = std::regex("Hello, world"); + std::regex re2 = std::regex("world, Hello"); + auto v = std::vector(std::sregex_iterator(str.begin(), str.end(), re), std::sregex_iterator()); + for(auto it = std::sregex_iterator(str.begin(), str.end(), re2); it != std::sregex_iterator(); ++it) { + v.push_back(*it); + } + ASSERT_STREQ( + hiliteMatches(str, v, "(", ")").c_str(), + "(world, Hello, world, Hello, world, Hello, world, Hello, world)!" + ); + } + + TEST(hiliteMatches, complexOverlappingMatches) { + std::string str = "legacyPackages.x86_64-linux.git-crypt"; + std::vector regexes = { + std::regex("t-cry"), + std::regex("ux\\.git-cry"), + std::regex("git-c"), + std::regex("pt"), + }; + std::vector matches; + for(auto regex : regexes) + { + for(auto it = std::sregex_iterator(str.begin(), str.end(), regex); it != std::sregex_iterator(); ++it) { + matches.push_back(*it); + } + } + ASSERT_STREQ( + hiliteMatches(str, matches, "(", ")").c_str(), + "legacyPackages.x86_64-lin(ux.git-crypt)" + ); + } +} diff --git a/tests/unit/libutil/local.mk b/tests/unit/libutil/local.mk new file mode 100644 index 000000000..6de96c0dc --- /dev/null +++ b/tests/unit/libutil/local.mk @@ -0,0 +1,23 @@ +check: libutil-tests_RUN + +programs += libutil-tests + +libutil-tests_NAME = libnixutil-tests + +libutil-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data + +libutil-tests_DIR := $(d) + +libutil-tests_INSTALL_DIR := + +libutil-tests_SOURCES := $(wildcard $(d)/*.cc) + +libutil-tests_EXTRA_INCLUDES = \ + -I tests/unit/libutil-support \ + -I src/libutil + +libutil-tests_CXXFLAGS += $(libutil-tests_EXTRA_INCLUDES) + +libutil-tests_LIBS = libutil-test-support libutil + +libutil-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) diff --git a/tests/unit/libutil/logging.cc b/tests/unit/libutil/logging.cc new file mode 100644 index 000000000..2ffdc2e9b --- /dev/null +++ b/tests/unit/libutil/logging.cc @@ -0,0 +1,370 @@ +#if 0 + +#include "logging.hh" +#include "nixexpr.hh" +#include "util.hh" +#include + +#include + +namespace nix { + + /* ---------------------------------------------------------------------------- + * logEI + * --------------------------------------------------------------------------*/ + + const char *test_file = + "previous line of code\n" + "this is the problem line of code\n" + "next line of code\n"; + const char *one_liner = + "this is the other problem line of code"; + + TEST(logEI, catpuresBasicProperties) { + + MakeError(TestError, Error); + ErrorInfo::programName = std::optional("error-unit-test"); + + try { + throw TestError("an error for testing purposes"); + } catch (Error &e) { + testing::internal::CaptureStderr(); + logger->logEI(e.info()); + auto str = testing::internal::GetCapturedStderr(); + + ASSERT_STREQ(str.c_str(),"\x1B[31;1merror:\x1B[0m\x1B[34;1m --- TestError --- error-unit-test\x1B[0m\nan error for testing purposes\n"); + } + } + + TEST(logEI, jsonOutput) { + SymbolTable testTable; + auto problem_file = testTable.create("random.nix"); + testing::internal::CaptureStderr(); + + makeJSONLogger(*logger)->logEI({ + .name = "error name", + .msg = hintfmt("this hint has %1% templated %2%!!", + "yellow", + "values"), + .errPos = Pos(foFile, problem_file, 02, 13) + }); + + auto str = testing::internal::GetCapturedStderr(); + ASSERT_STREQ(str.c_str(), "@nix {\"action\":\"msg\",\"column\":13,\"file\":\"random.nix\",\"level\":0,\"line\":2,\"msg\":\"\\u001b[31;1merror:\\u001b[0m\\u001b[34;1m --- error name --- error-unit-test\\u001b[0m\\n\\u001b[34;1mat: \\u001b[33;1m(2:13)\\u001b[34;1m in file: \\u001b[0mrandom.nix\\n\\nerror without any code lines.\\n\\nthis hint has \\u001b[33;1myellow\\u001b[0m templated \\u001b[33;1mvalues\\u001b[0m!!\",\"raw_msg\":\"this hint has \\u001b[33;1myellow\\u001b[0m templated \\u001b[33;1mvalues\\u001b[0m!!\"}\n"); + } + + TEST(logEI, appendingHintsToPreviousError) { + + MakeError(TestError, Error); + ErrorInfo::programName = std::optional("error-unit-test"); + + try { + auto e = Error("initial error"); + throw TestError(e.info()); + } catch (Error &e) { + ErrorInfo ei = e.info(); + ei.msg = hintfmt("%s; subsequent error message.", normaltxt(e.info().msg.str())); + + testing::internal::CaptureStderr(); + logger->logEI(ei); + auto str = testing::internal::GetCapturedStderr(); + + ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- TestError --- error-unit-test\x1B[0m\ninitial error; subsequent error message.\n"); + } + + } + + TEST(logEI, picksUpSysErrorExitCode) { + + MakeError(TestError, Error); + ErrorInfo::programName = std::optional("error-unit-test"); + + try { + auto x = readFile(-1); + } + catch (SysError &e) { + testing::internal::CaptureStderr(); + logError(e.info()); + auto str = testing::internal::GetCapturedStderr(); + + ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- SysError --- error-unit-test\x1B[0m\nstatting file: \x1B[33;1mBad file descriptor\x1B[0m\n"); + } + } + + TEST(logEI, loggingErrorOnInfoLevel) { + testing::internal::CaptureStderr(); + + logger->logEI({ .level = lvlInfo, + .name = "Info name", + }); + + auto str = testing::internal::GetCapturedStderr(); + ASSERT_STREQ(str.c_str(), "\x1B[32;1minfo:\x1B[0m\x1B[34;1m --- Info name --- error-unit-test\x1B[0m\nInfo description\n"); + } + + TEST(logEI, loggingErrorOnTalkativeLevel) { + verbosity = lvlTalkative; + + testing::internal::CaptureStderr(); + + logger->logEI({ .level = lvlTalkative, + .name = "Talkative name", + }); + + auto str = testing::internal::GetCapturedStderr(); + ASSERT_STREQ(str.c_str(), "\x1B[32;1mtalk:\x1B[0m\x1B[34;1m --- Talkative name --- error-unit-test\x1B[0m\nTalkative description\n"); + } + + TEST(logEI, loggingErrorOnChattyLevel) { + verbosity = lvlChatty; + + testing::internal::CaptureStderr(); + + logger->logEI({ .level = lvlChatty, + .name = "Chatty name", + }); + + auto str = testing::internal::GetCapturedStderr(); + ASSERT_STREQ(str.c_str(), "\x1B[32;1mchat:\x1B[0m\x1B[34;1m --- Chatty name --- error-unit-test\x1B[0m\nTalkative description\n"); + } + + TEST(logEI, loggingErrorOnDebugLevel) { + verbosity = lvlDebug; + + testing::internal::CaptureStderr(); + + logger->logEI({ .level = lvlDebug, + .name = "Debug name", + }); + + auto str = testing::internal::GetCapturedStderr(); + ASSERT_STREQ(str.c_str(), "\x1B[33;1mdebug:\x1B[0m\x1B[34;1m --- Debug name --- error-unit-test\x1B[0m\nDebug description\n"); + } + + TEST(logEI, loggingErrorOnVomitLevel) { + verbosity = lvlVomit; + + testing::internal::CaptureStderr(); + + logger->logEI({ .level = lvlVomit, + .name = "Vomit name", + }); + + auto str = testing::internal::GetCapturedStderr(); + ASSERT_STREQ(str.c_str(), "\x1B[32;1mvomit:\x1B[0m\x1B[34;1m --- Vomit name --- error-unit-test\x1B[0m\nVomit description\n"); + } + + /* ---------------------------------------------------------------------------- + * logError + * --------------------------------------------------------------------------*/ + + TEST(logError, logErrorWithoutHintOrCode) { + testing::internal::CaptureStderr(); + + logError({ + .name = "name", + }); + + auto str = testing::internal::GetCapturedStderr(); + ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- name --- error-unit-test\x1B[0m\nerror description\n"); + } + + TEST(logError, logErrorWithPreviousAndNextLinesOfCode) { + SymbolTable testTable; + auto problem_file = testTable.create(test_file); + + testing::internal::CaptureStderr(); + + logError({ + .name = "error name", + .msg = hintfmt("this hint has %1% templated %2%!!", + "yellow", + "values"), + .errPos = Pos(foString, problem_file, 02, 13), + }); + + auto str = testing::internal::GetCapturedStderr(); + ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name --- error-unit-test\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(2:13)\x1B[34;1m from string\x1B[0m\n\nerror with code lines\n\n 1| previous line of code\n 2| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n 3| next line of code\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n"); + } + + TEST(logError, logErrorWithInvalidFile) { + SymbolTable testTable; + auto problem_file = testTable.create("invalid filename"); + testing::internal::CaptureStderr(); + + logError({ + .name = "error name", + .msg = hintfmt("this hint has %1% templated %2%!!", + "yellow", + "values"), + .errPos = Pos(foFile, problem_file, 02, 13) + }); + + auto str = testing::internal::GetCapturedStderr(); + ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name --- error-unit-test\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(2:13)\x1B[34;1m in file: \x1B[0minvalid filename\n\nerror without any code lines.\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n"); + } + + TEST(logError, logErrorWithOnlyHintAndName) { + testing::internal::CaptureStderr(); + + logError({ + .name = "error name", + .msg = hintfmt("hint %1%", "only"), + }); + + auto str = testing::internal::GetCapturedStderr(); + ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name --- error-unit-test\x1B[0m\nhint \x1B[33;1monly\x1B[0m\n"); + + } + + /* ---------------------------------------------------------------------------- + * logWarning + * --------------------------------------------------------------------------*/ + + TEST(logWarning, logWarningWithNameDescriptionAndHint) { + testing::internal::CaptureStderr(); + + logWarning({ + .name = "name", + .msg = hintfmt("there was a %1%", "warning"), + }); + + auto str = testing::internal::GetCapturedStderr(); + ASSERT_STREQ(str.c_str(), "\x1B[33;1mwarning:\x1B[0m\x1B[34;1m --- name --- error-unit-test\x1B[0m\nwarning description\n\nthere was a \x1B[33;1mwarning\x1B[0m\n"); + } + + TEST(logWarning, logWarningWithFileLineNumAndCode) { + + SymbolTable testTable; + auto problem_file = testTable.create(test_file); + + testing::internal::CaptureStderr(); + + logWarning({ + .name = "warning name", + .msg = hintfmt("this hint has %1% templated %2%!!", + "yellow", + "values"), + .errPos = Pos(foStdin, problem_file, 2, 13), + }); + + + auto str = testing::internal::GetCapturedStderr(); + ASSERT_STREQ(str.c_str(), "\x1B[33;1mwarning:\x1B[0m\x1B[34;1m --- warning name --- error-unit-test\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(2:13)\x1B[34;1m from stdin\x1B[0m\n\nwarning description\n\n 1| previous line of code\n 2| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n 3| next line of code\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n"); + } + + /* ---------------------------------------------------------------------------- + * traces + * --------------------------------------------------------------------------*/ + + TEST(addTrace, showTracesWithShowTrace) { + SymbolTable testTable; + auto problem_file = testTable.create(test_file); + auto oneliner_file = testTable.create(one_liner); + auto invalidfilename = testTable.create("invalid filename"); + + auto e = AssertionError(ErrorInfo { + .name = "wat", + .msg = hintfmt("it has been %1% days since our last error", "zero"), + .errPos = Pos(foString, problem_file, 2, 13), + }); + + e.addTrace(Pos(foStdin, oneliner_file, 1, 19), "while trying to compute %1%", 42); + e.addTrace(std::nullopt, "while doing something without a %1%", "pos"); + e.addTrace(Pos(foFile, invalidfilename, 100, 1), "missing %s", "nix file"); + + testing::internal::CaptureStderr(); + + loggerSettings.showTrace.assign(true); + + logError(e.info()); + + auto str = testing::internal::GetCapturedStderr(); + ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- AssertionError --- error-unit-test\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(2:13)\x1B[34;1m from string\x1B[0m\n\nshow-traces\n\n 1| previous line of code\n 2| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n 3| next line of code\n\nit has been \x1B[33;1mzero\x1B[0m days since our last error\n\x1B[34;1m---- show-trace ----\x1B[0m\n\x1B[34;1mtrace: \x1B[0mwhile trying to compute \x1B[33;1m42\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(1:19)\x1B[34;1m from stdin\x1B[0m\n\n 1| this is the other problem line of code\n | \x1B[31;1m^\x1B[0m\n\n\x1B[34;1mtrace: \x1B[0mwhile doing something without a \x1B[33;1mpos\x1B[0m\n\x1B[34;1mtrace: \x1B[0mmissing \x1B[33;1mnix file\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(100:1)\x1B[34;1m in file: \x1B[0minvalid filename\n"); + } + + TEST(addTrace, hideTracesWithoutShowTrace) { + SymbolTable testTable; + auto problem_file = testTable.create(test_file); + auto oneliner_file = testTable.create(one_liner); + auto invalidfilename = testTable.create("invalid filename"); + + auto e = AssertionError(ErrorInfo { + .name = "wat", + .msg = hintfmt("it has been %1% days since our last error", "zero"), + .errPos = Pos(foString, problem_file, 2, 13), + }); + + e.addTrace(Pos(foStdin, oneliner_file, 1, 19), "while trying to compute %1%", 42); + e.addTrace(std::nullopt, "while doing something without a %1%", "pos"); + e.addTrace(Pos(foFile, invalidfilename, 100, 1), "missing %s", "nix file"); + + testing::internal::CaptureStderr(); + + loggerSettings.showTrace.assign(false); + + logError(e.info()); + + auto str = testing::internal::GetCapturedStderr(); + ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- AssertionError --- error-unit-test\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(2:13)\x1B[34;1m from string\x1B[0m\n\nhide traces\n\n 1| previous line of code\n 2| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n 3| next line of code\n\nit has been \x1B[33;1mzero\x1B[0m days since our last error\n"); + } + + + /* ---------------------------------------------------------------------------- + * hintfmt + * --------------------------------------------------------------------------*/ + + TEST(hintfmt, percentStringWithoutArgs) { + + const char *teststr = "this is 100%s correct!"; + + ASSERT_STREQ( + hintfmt(teststr).str().c_str(), + teststr); + + } + + TEST(hintfmt, fmtToHintfmt) { + + ASSERT_STREQ( + hintfmt(fmt("the color of this this text is %1%", "not yellow")).str().c_str(), + "the color of this this text is not yellow"); + + } + + TEST(hintfmt, tooFewArguments) { + + ASSERT_STREQ( + hintfmt("only one arg %1% %2%", "fulfilled").str().c_str(), + "only one arg " ANSI_WARNING "fulfilled" ANSI_NORMAL " "); + + } + + TEST(hintfmt, tooManyArguments) { + + ASSERT_STREQ( + hintfmt("what about this %1% %2%", "%3%", "one", "two").str().c_str(), + "what about this " ANSI_WARNING "%3%" ANSI_NORMAL " " ANSI_YELLOW "one" ANSI_NORMAL); + + } + + /* ---------------------------------------------------------------------------- + * ErrPos + * --------------------------------------------------------------------------*/ + + TEST(errpos, invalidPos) { + + // contains an invalid symbol, which we should not dereference! + Pos invalid; + + // constructing without access violation. + ErrPos ep(invalid); + + // assignment without access violation. + ep = invalid; + + } + +} + +#endif diff --git a/tests/unit/libutil/lru-cache.cc b/tests/unit/libutil/lru-cache.cc new file mode 100644 index 000000000..091d3d5ed --- /dev/null +++ b/tests/unit/libutil/lru-cache.cc @@ -0,0 +1,130 @@ +#include "lru-cache.hh" +#include + +namespace nix { + + /* ---------------------------------------------------------------------------- + * size + * --------------------------------------------------------------------------*/ + + TEST(LRUCache, sizeOfEmptyCacheIsZero) { + LRUCache c(10); + ASSERT_EQ(c.size(), 0); + } + + TEST(LRUCache, sizeOfSingleElementCacheIsOne) { + LRUCache c(10); + c.upsert("foo", "bar"); + ASSERT_EQ(c.size(), 1); + } + + /* ---------------------------------------------------------------------------- + * upsert / get + * --------------------------------------------------------------------------*/ + + TEST(LRUCache, getFromEmptyCache) { + LRUCache c(10); + auto val = c.get("x"); + ASSERT_EQ(val.has_value(), false); + } + + TEST(LRUCache, getExistingValue) { + LRUCache c(10); + c.upsert("foo", "bar"); + auto val = c.get("foo"); + ASSERT_EQ(val, "bar"); + } + + TEST(LRUCache, getNonExistingValueFromNonEmptyCache) { + LRUCache c(10); + c.upsert("foo", "bar"); + auto val = c.get("another"); + ASSERT_EQ(val.has_value(), false); + } + + TEST(LRUCache, upsertOnZeroCapacityCache) { + LRUCache c(0); + c.upsert("foo", "bar"); + auto val = c.get("foo"); + ASSERT_EQ(val.has_value(), false); + } + + TEST(LRUCache, updateExistingValue) { + LRUCache c(1); + c.upsert("foo", "bar"); + + auto val = c.get("foo"); + ASSERT_EQ(val.value_or("error"), "bar"); + ASSERT_EQ(c.size(), 1); + + c.upsert("foo", "changed"); + val = c.get("foo"); + ASSERT_EQ(val.value_or("error"), "changed"); + ASSERT_EQ(c.size(), 1); + } + + TEST(LRUCache, overwriteOldestWhenCapacityIsReached) { + LRUCache c(3); + c.upsert("one", "eins"); + c.upsert("two", "zwei"); + c.upsert("three", "drei"); + + ASSERT_EQ(c.size(), 3); + ASSERT_EQ(c.get("one").value_or("error"), "eins"); + + // exceed capacity + c.upsert("another", "whatever"); + + ASSERT_EQ(c.size(), 3); + // Retrieving "one" makes it the most recent element thus + // two will be the oldest one and thus replaced. + ASSERT_EQ(c.get("two").has_value(), false); + ASSERT_EQ(c.get("another").value(), "whatever"); + } + + /* ---------------------------------------------------------------------------- + * clear + * --------------------------------------------------------------------------*/ + + TEST(LRUCache, clearEmptyCache) { + LRUCache c(10); + c.clear(); + ASSERT_EQ(c.size(), 0); + } + + TEST(LRUCache, clearNonEmptyCache) { + LRUCache c(10); + c.upsert("one", "eins"); + c.upsert("two", "zwei"); + c.upsert("three", "drei"); + ASSERT_EQ(c.size(), 3); + c.clear(); + ASSERT_EQ(c.size(), 0); + } + + /* ---------------------------------------------------------------------------- + * erase + * --------------------------------------------------------------------------*/ + + TEST(LRUCache, eraseFromEmptyCache) { + LRUCache c(10); + ASSERT_EQ(c.erase("foo"), false); + ASSERT_EQ(c.size(), 0); + } + + TEST(LRUCache, eraseMissingFromNonEmptyCache) { + LRUCache c(10); + c.upsert("one", "eins"); + ASSERT_EQ(c.erase("foo"), false); + ASSERT_EQ(c.size(), 1); + ASSERT_EQ(c.get("one").value_or("error"), "eins"); + } + + TEST(LRUCache, eraseFromNonEmptyCache) { + LRUCache c(10); + c.upsert("one", "eins"); + ASSERT_EQ(c.erase("one"), true); + ASSERT_EQ(c.size(), 0); + ASSERT_EQ(c.get("one").value_or("empty"), "empty"); + } +} diff --git a/tests/unit/libutil/pool.cc b/tests/unit/libutil/pool.cc new file mode 100644 index 000000000..127e42dda --- /dev/null +++ b/tests/unit/libutil/pool.cc @@ -0,0 +1,127 @@ +#include "pool.hh" +#include + +namespace nix { + + struct TestResource + { + + TestResource() { + static int counter = 0; + num = counter++; + } + + int dummyValue = 1; + bool good = true; + int num; + }; + + /* ---------------------------------------------------------------------------- + * Pool + * --------------------------------------------------------------------------*/ + + TEST(Pool, freshPoolHasZeroCountAndSpecifiedCapacity) { + auto isGood = [](const ref & r) { return r->good; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t)1, createResource, isGood); + + ASSERT_EQ(pool.count(), 0); + ASSERT_EQ(pool.capacity(), 1); + } + + TEST(Pool, freshPoolCanGetAResource) { + auto isGood = [](const ref & r) { return r->good; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t)1, createResource, isGood); + ASSERT_EQ(pool.count(), 0); + + TestResource r = *(pool.get()); + + ASSERT_EQ(pool.count(), 1); + ASSERT_EQ(pool.capacity(), 1); + ASSERT_EQ(r.dummyValue, 1); + ASSERT_EQ(r.good, true); + } + + TEST(Pool, capacityCanBeIncremented) { + auto isGood = [](const ref & r) { return r->good; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t)1, createResource, isGood); + ASSERT_EQ(pool.capacity(), 1); + pool.incCapacity(); + ASSERT_EQ(pool.capacity(), 2); + } + + TEST(Pool, capacityCanBeDecremented) { + auto isGood = [](const ref & r) { return r->good; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t)1, createResource, isGood); + ASSERT_EQ(pool.capacity(), 1); + pool.decCapacity(); + ASSERT_EQ(pool.capacity(), 0); + } + + TEST(Pool, flushBadDropsOutOfScopeResources) { + auto isGood = [](const ref & r) { return false; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t)1, createResource, isGood); + + { + auto _r = pool.get(); + ASSERT_EQ(pool.count(), 1); + } + + pool.flushBad(); + ASSERT_EQ(pool.count(), 0); + } + + // Test that the resources we allocate are being reused when they are still good. + TEST(Pool, reuseResource) { + auto isGood = [](const ref & r) { return true; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t)1, createResource, isGood); + + // Compare the instance counter between the two handles. We expect them to be equal + // as the pool should hand out the same (still) good one again. + int counter = -1; + { + Pool::Handle h = pool.get(); + counter = h->num; + } // the first handle goes out of scope + + { // the second handle should contain the same resource (with the same counter value) + Pool::Handle h = pool.get(); + ASSERT_EQ(h->num, counter); + } + } + + // Test that the resources we allocate are being thrown away when they are no longer good. + TEST(Pool, badResourceIsNotReused) { + auto isGood = [](const ref & r) { return false; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t)1, createResource, isGood); + + // Compare the instance counter between the two handles. We expect them + // to *not* be equal as the pool should hand out a new instance after + // the first one was returned. + int counter = -1; + { + Pool::Handle h = pool.get(); + counter = h->num; + } // the first handle goes out of scope + + { + // the second handle should contain a different resource (with a + //different counter value) + Pool::Handle h = pool.get(); + ASSERT_NE(h->num, counter); + } + } +} diff --git a/tests/unit/libutil/references.cc b/tests/unit/libutil/references.cc new file mode 100644 index 000000000..a517d9aa1 --- /dev/null +++ b/tests/unit/libutil/references.cc @@ -0,0 +1,46 @@ +#include "references.hh" +#include + +namespace nix { + +using std::string; + +struct RewriteParams { + string originalString, finalString; + StringMap rewrites; + + friend std::ostream& operator<<(std::ostream& os, const RewriteParams& bar) { + StringSet strRewrites; + for (auto & [from, to] : bar.rewrites) + strRewrites.insert(from + "->" + to); + return os << + "OriginalString: " << bar.originalString << std::endl << + "Rewrites: " << concatStringsSep(",", strRewrites) << std::endl << + "Expected result: " << bar.finalString; + } +}; + +class RewriteTest : public ::testing::TestWithParam { +}; + +TEST_P(RewriteTest, IdentityRewriteIsIdentity) { + RewriteParams param = GetParam(); + StringSink rewritten; + auto rewriter = RewritingSink(param.rewrites, rewritten); + rewriter(param.originalString); + rewriter.flush(); + ASSERT_EQ(rewritten.s, param.finalString); +} + +INSTANTIATE_TEST_CASE_P( + references, + RewriteTest, + ::testing::Values( + RewriteParams{ "foooo", "baroo", {{"foo", "bar"}, {"bar", "baz"}}}, + RewriteParams{ "foooo", "bazoo", {{"fou", "bar"}, {"foo", "baz"}}}, + RewriteParams{ "foooo", "foooo", {}} + ) +); + +} + diff --git a/tests/unit/libutil/suggestions.cc b/tests/unit/libutil/suggestions.cc new file mode 100644 index 000000000..279994abc --- /dev/null +++ b/tests/unit/libutil/suggestions.cc @@ -0,0 +1,43 @@ +#include "suggestions.hh" +#include + +namespace nix { + + struct LevenshteinDistanceParam { + std::string s1, s2; + int distance; + }; + + class LevenshteinDistanceTest : + public testing::TestWithParam { + }; + + TEST_P(LevenshteinDistanceTest, CorrectlyComputed) { + auto params = GetParam(); + + ASSERT_EQ(levenshteinDistance(params.s1, params.s2), params.distance); + ASSERT_EQ(levenshteinDistance(params.s2, params.s1), params.distance); + } + + INSTANTIATE_TEST_SUITE_P(LevenshteinDistance, LevenshteinDistanceTest, + testing::Values( + LevenshteinDistanceParam{"foo", "foo", 0}, + LevenshteinDistanceParam{"foo", "", 3}, + LevenshteinDistanceParam{"", "", 0}, + LevenshteinDistanceParam{"foo", "fo", 1}, + LevenshteinDistanceParam{"foo", "oo", 1}, + LevenshteinDistanceParam{"foo", "fao", 1}, + LevenshteinDistanceParam{"foo", "abc", 3} + ) + ); + + TEST(Suggestions, Trim) { + auto suggestions = Suggestions::bestMatches({"foooo", "bar", "fo", "gao"}, "foo"); + auto onlyOne = suggestions.trim(1); + ASSERT_EQ(onlyOne.suggestions.size(), 1); + ASSERT_TRUE(onlyOne.suggestions.begin()->suggestion == "fo"); + + auto closest = suggestions.trim(999, 2); + ASSERT_EQ(closest.suggestions.size(), 3); + } +} diff --git a/tests/unit/libutil/tests.cc b/tests/unit/libutil/tests.cc new file mode 100644 index 000000000..f3c1e8248 --- /dev/null +++ b/tests/unit/libutil/tests.cc @@ -0,0 +1,659 @@ +#include "util.hh" +#include "types.hh" + +#include +#include + +#include + +namespace nix { + +/* ----------- tests for util.hh ------------------------------------------------*/ + + /* ---------------------------------------------------------------------------- + * absPath + * --------------------------------------------------------------------------*/ + + TEST(absPath, doesntChangeRoot) { + auto p = absPath("/"); + + ASSERT_EQ(p, "/"); + } + + + + + TEST(absPath, turnsEmptyPathIntoCWD) { + char cwd[PATH_MAX+1]; + auto p = absPath(""); + + ASSERT_EQ(p, getcwd((char*)&cwd, PATH_MAX)); + } + + TEST(absPath, usesOptionalBasePathWhenGiven) { + char _cwd[PATH_MAX+1]; + char* cwd = getcwd((char*)&_cwd, PATH_MAX); + + auto p = absPath("", cwd); + + ASSERT_EQ(p, cwd); + } + + TEST(absPath, isIdempotent) { + char _cwd[PATH_MAX+1]; + char* cwd = getcwd((char*)&_cwd, PATH_MAX); + auto p1 = absPath(cwd); + auto p2 = absPath(p1); + + ASSERT_EQ(p1, p2); + } + + + TEST(absPath, pathIsCanonicalised) { + auto path = "/some/path/with/trailing/dot/."; + auto p1 = absPath(path); + auto p2 = absPath(p1); + + ASSERT_EQ(p1, "/some/path/with/trailing/dot"); + ASSERT_EQ(p1, p2); + } + + /* ---------------------------------------------------------------------------- + * canonPath + * --------------------------------------------------------------------------*/ + + TEST(canonPath, removesTrailingSlashes) { + auto path = "/this/is/a/path//"; + auto p = canonPath(path); + + ASSERT_EQ(p, "/this/is/a/path"); + } + + TEST(canonPath, removesDots) { + auto path = "/this/./is/a/path/./"; + auto p = canonPath(path); + + ASSERT_EQ(p, "/this/is/a/path"); + } + + TEST(canonPath, removesDots2) { + auto path = "/this/a/../is/a////path/foo/.."; + auto p = canonPath(path); + + ASSERT_EQ(p, "/this/is/a/path"); + } + + TEST(canonPath, requiresAbsolutePath) { + ASSERT_ANY_THROW(canonPath(".")); + ASSERT_ANY_THROW(canonPath("..")); + ASSERT_ANY_THROW(canonPath("../")); + ASSERT_DEATH({ canonPath(""); }, "path != \"\""); + } + + /* ---------------------------------------------------------------------------- + * dirOf + * --------------------------------------------------------------------------*/ + + TEST(dirOf, returnsEmptyStringForRoot) { + auto p = dirOf("/"); + + ASSERT_EQ(p, "/"); + } + + TEST(dirOf, returnsFirstPathComponent) { + auto p1 = dirOf("/dir/"); + ASSERT_EQ(p1, "/dir"); + auto p2 = dirOf("/dir"); + ASSERT_EQ(p2, "/"); + auto p3 = dirOf("/dir/.."); + ASSERT_EQ(p3, "/dir"); + auto p4 = dirOf("/dir/../"); + ASSERT_EQ(p4, "/dir/.."); + } + + /* ---------------------------------------------------------------------------- + * baseNameOf + * --------------------------------------------------------------------------*/ + + TEST(baseNameOf, emptyPath) { + auto p1 = baseNameOf(""); + ASSERT_EQ(p1, ""); + } + + TEST(baseNameOf, pathOnRoot) { + auto p1 = baseNameOf("/dir"); + ASSERT_EQ(p1, "dir"); + } + + TEST(baseNameOf, relativePath) { + auto p1 = baseNameOf("dir/foo"); + ASSERT_EQ(p1, "foo"); + } + + TEST(baseNameOf, pathWithTrailingSlashRoot) { + auto p1 = baseNameOf("/"); + ASSERT_EQ(p1, ""); + } + + TEST(baseNameOf, trailingSlash) { + auto p1 = baseNameOf("/dir/"); + ASSERT_EQ(p1, "dir"); + } + + /* ---------------------------------------------------------------------------- + * isInDir + * --------------------------------------------------------------------------*/ + + TEST(isInDir, trivialCase) { + auto p1 = isInDir("/foo/bar", "/foo"); + ASSERT_EQ(p1, true); + } + + TEST(isInDir, notInDir) { + auto p1 = isInDir("/zes/foo/bar", "/foo"); + ASSERT_EQ(p1, false); + } + + // XXX: hm, bug or feature? :) Looking at the implementation + // this might be problematic. + TEST(isInDir, emptyDir) { + auto p1 = isInDir("/zes/foo/bar", ""); + ASSERT_EQ(p1, true); + } + + /* ---------------------------------------------------------------------------- + * isDirOrInDir + * --------------------------------------------------------------------------*/ + + TEST(isDirOrInDir, trueForSameDirectory) { + ASSERT_EQ(isDirOrInDir("/nix", "/nix"), true); + ASSERT_EQ(isDirOrInDir("/", "/"), true); + } + + TEST(isDirOrInDir, trueForEmptyPaths) { + ASSERT_EQ(isDirOrInDir("", ""), true); + } + + TEST(isDirOrInDir, falseForDisjunctPaths) { + ASSERT_EQ(isDirOrInDir("/foo", "/bar"), false); + } + + TEST(isDirOrInDir, relativePaths) { + ASSERT_EQ(isDirOrInDir("/foo/..", "/foo"), true); + } + + // XXX: while it is possible to use "." or ".." in the + // first argument this doesn't seem to work in the second. + TEST(isDirOrInDir, DISABLED_shouldWork) { + ASSERT_EQ(isDirOrInDir("/foo/..", "/foo/."), true); + + } + + /* ---------------------------------------------------------------------------- + * pathExists + * --------------------------------------------------------------------------*/ + + TEST(pathExists, rootExists) { + ASSERT_TRUE(pathExists("/")); + } + + TEST(pathExists, cwdExists) { + ASSERT_TRUE(pathExists(".")); + } + + TEST(pathExists, bogusPathDoesNotExist) { + ASSERT_FALSE(pathExists("/schnitzel/darmstadt/pommes")); + } + + /* ---------------------------------------------------------------------------- + * concatStringsSep + * --------------------------------------------------------------------------*/ + + TEST(concatStringsSep, buildCommaSeparatedString) { + Strings strings; + strings.push_back("this"); + strings.push_back("is"); + strings.push_back("great"); + + ASSERT_EQ(concatStringsSep(",", strings), "this,is,great"); + } + + TEST(concatStringsSep, buildStringWithEmptySeparator) { + Strings strings; + strings.push_back("this"); + strings.push_back("is"); + strings.push_back("great"); + + ASSERT_EQ(concatStringsSep("", strings), "thisisgreat"); + } + + TEST(concatStringsSep, buildSingleString) { + Strings strings; + strings.push_back("this"); + + ASSERT_EQ(concatStringsSep(",", strings), "this"); + } + + /* ---------------------------------------------------------------------------- + * hasPrefix + * --------------------------------------------------------------------------*/ + + TEST(hasPrefix, emptyStringHasNoPrefix) { + ASSERT_FALSE(hasPrefix("", "foo")); + } + + TEST(hasPrefix, emptyStringIsAlwaysPrefix) { + ASSERT_TRUE(hasPrefix("foo", "")); + ASSERT_TRUE(hasPrefix("jshjkfhsadf", "")); + } + + TEST(hasPrefix, trivialCase) { + ASSERT_TRUE(hasPrefix("foobar", "foo")); + } + + /* ---------------------------------------------------------------------------- + * hasSuffix + * --------------------------------------------------------------------------*/ + + TEST(hasSuffix, emptyStringHasNoSuffix) { + ASSERT_FALSE(hasSuffix("", "foo")); + } + + TEST(hasSuffix, trivialCase) { + ASSERT_TRUE(hasSuffix("foo", "foo")); + ASSERT_TRUE(hasSuffix("foobar", "bar")); + } + + /* ---------------------------------------------------------------------------- + * base64Encode + * --------------------------------------------------------------------------*/ + + TEST(base64Encode, emptyString) { + ASSERT_EQ(base64Encode(""), ""); + } + + TEST(base64Encode, encodesAString) { + ASSERT_EQ(base64Encode("quod erat demonstrandum"), "cXVvZCBlcmF0IGRlbW9uc3RyYW5kdW0="); + } + + TEST(base64Encode, encodeAndDecode) { + auto s = "quod erat demonstrandum"; + auto encoded = base64Encode(s); + auto decoded = base64Decode(encoded); + + ASSERT_EQ(decoded, s); + } + + TEST(base64Encode, encodeAndDecodeNonPrintable) { + char s[256]; + std::iota(std::rbegin(s), std::rend(s), 0); + + auto encoded = base64Encode(s); + auto decoded = base64Decode(encoded); + + EXPECT_EQ(decoded.length(), 255); + ASSERT_EQ(decoded, s); + } + + /* ---------------------------------------------------------------------------- + * base64Decode + * --------------------------------------------------------------------------*/ + + TEST(base64Decode, emptyString) { + ASSERT_EQ(base64Decode(""), ""); + } + + TEST(base64Decode, decodeAString) { + ASSERT_EQ(base64Decode("cXVvZCBlcmF0IGRlbW9uc3RyYW5kdW0="), "quod erat demonstrandum"); + } + + TEST(base64Decode, decodeThrowsOnInvalidChar) { + ASSERT_THROW(base64Decode("cXVvZCBlcm_0IGRlbW9uc3RyYW5kdW0="), Error); + } + + /* ---------------------------------------------------------------------------- + * getLine + * --------------------------------------------------------------------------*/ + + TEST(getLine, all) { + { + auto [line, rest] = getLine("foo\nbar\nxyzzy"); + ASSERT_EQ(line, "foo"); + ASSERT_EQ(rest, "bar\nxyzzy"); + } + + { + auto [line, rest] = getLine("foo\r\nbar\r\nxyzzy"); + ASSERT_EQ(line, "foo"); + ASSERT_EQ(rest, "bar\r\nxyzzy"); + } + + { + auto [line, rest] = getLine("foo\n"); + ASSERT_EQ(line, "foo"); + ASSERT_EQ(rest, ""); + } + + { + auto [line, rest] = getLine("foo"); + ASSERT_EQ(line, "foo"); + ASSERT_EQ(rest, ""); + } + + { + auto [line, rest] = getLine(""); + ASSERT_EQ(line, ""); + ASSERT_EQ(rest, ""); + } + } + + /* ---------------------------------------------------------------------------- + * toLower + * --------------------------------------------------------------------------*/ + + TEST(toLower, emptyString) { + ASSERT_EQ(toLower(""), ""); + } + + TEST(toLower, nonLetters) { + auto s = "!@(*$#)(@#=\\234_"; + ASSERT_EQ(toLower(s), s); + } + + // std::tolower() doesn't handle unicode characters. In the context of + // store paths this isn't relevant but doesn't hurt to record this behavior + // here. + TEST(toLower, umlauts) { + auto s = "ÄÖÜ"; + ASSERT_EQ(toLower(s), "ÄÖÜ"); + } + + /* ---------------------------------------------------------------------------- + * string2Float + * --------------------------------------------------------------------------*/ + + TEST(string2Float, emptyString) { + ASSERT_EQ(string2Float(""), std::nullopt); + } + + TEST(string2Float, trivialConversions) { + ASSERT_EQ(string2Float("1.0"), 1.0); + + ASSERT_EQ(string2Float("0.0"), 0.0); + + ASSERT_EQ(string2Float("-100.25"), -100.25); + } + + /* ---------------------------------------------------------------------------- + * string2Int + * --------------------------------------------------------------------------*/ + + TEST(string2Int, emptyString) { + ASSERT_EQ(string2Int(""), std::nullopt); + } + + TEST(string2Int, trivialConversions) { + ASSERT_EQ(string2Int("1"), 1); + + ASSERT_EQ(string2Int("0"), 0); + + ASSERT_EQ(string2Int("-100"), -100); + } + + /* ---------------------------------------------------------------------------- + * statusOk + * --------------------------------------------------------------------------*/ + + TEST(statusOk, zeroIsOk) { + ASSERT_EQ(statusOk(0), true); + ASSERT_EQ(statusOk(1), false); + } + + + /* ---------------------------------------------------------------------------- + * rewriteStrings + * --------------------------------------------------------------------------*/ + + TEST(rewriteStrings, emptyString) { + StringMap rewrites; + rewrites["this"] = "that"; + + ASSERT_EQ(rewriteStrings("", rewrites), ""); + } + + TEST(rewriteStrings, emptyRewrites) { + StringMap rewrites; + + ASSERT_EQ(rewriteStrings("this and that", rewrites), "this and that"); + } + + TEST(rewriteStrings, successfulRewrite) { + StringMap rewrites; + rewrites["this"] = "that"; + + ASSERT_EQ(rewriteStrings("this and that", rewrites), "that and that"); + } + + TEST(rewriteStrings, doesntOccur) { + StringMap rewrites; + rewrites["foo"] = "bar"; + + ASSERT_EQ(rewriteStrings("this and that", rewrites), "this and that"); + } + + /* ---------------------------------------------------------------------------- + * replaceStrings + * --------------------------------------------------------------------------*/ + + TEST(replaceStrings, emptyString) { + ASSERT_EQ(replaceStrings("", "this", "that"), ""); + ASSERT_EQ(replaceStrings("this and that", "", ""), "this and that"); + } + + TEST(replaceStrings, successfulReplace) { + ASSERT_EQ(replaceStrings("this and that", "this", "that"), "that and that"); + } + + TEST(replaceStrings, doesntOccur) { + ASSERT_EQ(replaceStrings("this and that", "foo", "bar"), "this and that"); + } + + /* ---------------------------------------------------------------------------- + * trim + * --------------------------------------------------------------------------*/ + + TEST(trim, emptyString) { + ASSERT_EQ(trim(""), ""); + } + + TEST(trim, removesWhitespace) { + ASSERT_EQ(trim("foo"), "foo"); + ASSERT_EQ(trim(" foo "), "foo"); + ASSERT_EQ(trim(" foo bar baz"), "foo bar baz"); + ASSERT_EQ(trim(" \t foo bar baz\n"), "foo bar baz"); + } + + /* ---------------------------------------------------------------------------- + * chomp + * --------------------------------------------------------------------------*/ + + TEST(chomp, emptyString) { + ASSERT_EQ(chomp(""), ""); + } + + TEST(chomp, removesWhitespace) { + ASSERT_EQ(chomp("foo"), "foo"); + ASSERT_EQ(chomp("foo "), "foo"); + ASSERT_EQ(chomp(" foo "), " foo"); + ASSERT_EQ(chomp(" foo bar baz "), " foo bar baz"); + ASSERT_EQ(chomp("\t foo bar baz\n"), "\t foo bar baz"); + } + + /* ---------------------------------------------------------------------------- + * quoteStrings + * --------------------------------------------------------------------------*/ + + TEST(quoteStrings, empty) { + Strings s = { }; + Strings expected = { }; + + ASSERT_EQ(quoteStrings(s), expected); + } + + TEST(quoteStrings, emptyStrings) { + Strings s = { "", "", "" }; + Strings expected = { "''", "''", "''" }; + ASSERT_EQ(quoteStrings(s), expected); + + } + + TEST(quoteStrings, trivialQuote) { + Strings s = { "foo", "bar", "baz" }; + Strings expected = { "'foo'", "'bar'", "'baz'" }; + + ASSERT_EQ(quoteStrings(s), expected); + } + + TEST(quoteStrings, quotedStrings) { + Strings s = { "'foo'", "'bar'", "'baz'" }; + Strings expected = { "''foo''", "''bar''", "''baz''" }; + + ASSERT_EQ(quoteStrings(s), expected); + } + + /* ---------------------------------------------------------------------------- + * tokenizeString + * --------------------------------------------------------------------------*/ + + TEST(tokenizeString, empty) { + Strings expected = { }; + + ASSERT_EQ(tokenizeString(""), expected); + } + + TEST(tokenizeString, tokenizeSpacesWithDefaults) { + auto s = "foo bar baz"; + Strings expected = { "foo", "bar", "baz" }; + + ASSERT_EQ(tokenizeString(s), expected); + } + + TEST(tokenizeString, tokenizeTabsWithDefaults) { + auto s = "foo\tbar\tbaz"; + Strings expected = { "foo", "bar", "baz" }; + + ASSERT_EQ(tokenizeString(s), expected); + } + + TEST(tokenizeString, tokenizeTabsSpacesWithDefaults) { + auto s = "foo\t bar\t baz"; + Strings expected = { "foo", "bar", "baz" }; + + ASSERT_EQ(tokenizeString(s), expected); + } + + TEST(tokenizeString, tokenizeTabsSpacesNewlineWithDefaults) { + auto s = "foo\t\n bar\t\n baz"; + Strings expected = { "foo", "bar", "baz" }; + + ASSERT_EQ(tokenizeString(s), expected); + } + + TEST(tokenizeString, tokenizeTabsSpacesNewlineRetWithDefaults) { + auto s = "foo\t\n\r bar\t\n\r baz"; + Strings expected = { "foo", "bar", "baz" }; + + ASSERT_EQ(tokenizeString(s), expected); + + auto s2 = "foo \t\n\r bar \t\n\r baz"; + Strings expected2 = { "foo", "bar", "baz" }; + + ASSERT_EQ(tokenizeString(s2), expected2); + } + + TEST(tokenizeString, tokenizeWithCustomSep) { + auto s = "foo\n,bar\n,baz\n"; + Strings expected = { "foo\n", "bar\n", "baz\n" }; + + ASSERT_EQ(tokenizeString(s, ","), expected); + } + + /* ---------------------------------------------------------------------------- + * get + * --------------------------------------------------------------------------*/ + + TEST(get, emptyContainer) { + StringMap s = { }; + auto expected = nullptr; + + ASSERT_EQ(get(s, "one"), expected); + } + + TEST(get, getFromContainer) { + StringMap s; + s["one"] = "yi"; + s["two"] = "er"; + auto expected = "yi"; + + ASSERT_EQ(*get(s, "one"), expected); + } + + TEST(getOr, emptyContainer) { + StringMap s = { }; + auto expected = "yi"; + + ASSERT_EQ(getOr(s, "one", "yi"), expected); + } + + TEST(getOr, getFromContainer) { + StringMap s; + s["one"] = "yi"; + s["two"] = "er"; + auto expected = "yi"; + + ASSERT_EQ(getOr(s, "one", "nope"), expected); + } + + /* ---------------------------------------------------------------------------- + * filterANSIEscapes + * --------------------------------------------------------------------------*/ + + TEST(filterANSIEscapes, emptyString) { + auto s = ""; + auto expected = ""; + + ASSERT_EQ(filterANSIEscapes(s), expected); + } + + TEST(filterANSIEscapes, doesntChangePrintableChars) { + auto s = "09 2q304ruyhr slk2-19024 kjsadh sar f"; + + ASSERT_EQ(filterANSIEscapes(s), s); + } + + TEST(filterANSIEscapes, filtersColorCodes) { + auto s = "\u001b[30m A \u001b[31m B \u001b[32m C \u001b[33m D \u001b[0m"; + + ASSERT_EQ(filterANSIEscapes(s, true, 2), " A" ); + ASSERT_EQ(filterANSIEscapes(s, true, 3), " A " ); + ASSERT_EQ(filterANSIEscapes(s, true, 4), " A " ); + ASSERT_EQ(filterANSIEscapes(s, true, 5), " A B" ); + ASSERT_EQ(filterANSIEscapes(s, true, 8), " A B C" ); + } + + TEST(filterANSIEscapes, expandsTabs) { + auto s = "foo\tbar\tbaz"; + + ASSERT_EQ(filterANSIEscapes(s, true), "foo bar baz" ); + } + + TEST(filterANSIEscapes, utf8) { + ASSERT_EQ(filterANSIEscapes("foobar", true, 5), "fooba"); + ASSERT_EQ(filterANSIEscapes("fóóbär", true, 6), "fóóbär"); + ASSERT_EQ(filterANSIEscapes("fóóbär", true, 5), "fóóbä"); + ASSERT_EQ(filterANSIEscapes("fóóbär", true, 3), "fóó"); + ASSERT_EQ(filterANSIEscapes("f€€bär", true, 4), "f€€b"); + ASSERT_EQ(filterANSIEscapes("f𐍈𐍈bär", true, 4), "f𐍈𐍈b"); + } + +} diff --git a/tests/unit/libutil/url.cc b/tests/unit/libutil/url.cc new file mode 100644 index 000000000..a908631e6 --- /dev/null +++ b/tests/unit/libutil/url.cc @@ -0,0 +1,338 @@ +#include "url.hh" +#include + +namespace nix { + +/* ----------- tests for url.hh --------------------------------------------------*/ + + std::string print_map(std::map m) { + std::map::iterator it; + std::string s = "{ "; + for (it = m.begin(); it != m.end(); ++it) { + s += "{ "; + s += it->first; + s += " = "; + s += it->second; + s += " } "; + } + s += "}"; + return s; + } + + + std::ostream& operator<<(std::ostream& os, const ParsedURL& p) { + return os << "\n" + << "url: " << p.url << "\n" + << "base: " << p.base << "\n" + << "scheme: " << p.scheme << "\n" + << "authority: " << p.authority.value() << "\n" + << "path: " << p.path << "\n" + << "query: " << print_map(p.query) << "\n" + << "fragment: " << p.fragment << "\n"; + } + + TEST(parseURL, parsesSimpleHttpUrl) { + auto s = "http://www.example.org/file.tar.gz"; + auto parsed = parseURL(s); + + ParsedURL expected { + .url = "http://www.example.org/file.tar.gz", + .base = "http://www.example.org/file.tar.gz", + .scheme = "http", + .authority = "www.example.org", + .path = "/file.tar.gz", + .query = (StringMap) { }, + .fragment = "", + }; + + ASSERT_EQ(parsed, expected); + } + + TEST(parseURL, parsesSimpleHttpsUrl) { + auto s = "https://www.example.org/file.tar.gz"; + auto parsed = parseURL(s); + + ParsedURL expected { + .url = "https://www.example.org/file.tar.gz", + .base = "https://www.example.org/file.tar.gz", + .scheme = "https", + .authority = "www.example.org", + .path = "/file.tar.gz", + .query = (StringMap) { }, + .fragment = "", + }; + + ASSERT_EQ(parsed, expected); + } + + TEST(parseURL, parsesSimpleHttpUrlWithQueryAndFragment) { + auto s = "https://www.example.org/file.tar.gz?download=fast&when=now#hello"; + auto parsed = parseURL(s); + + ParsedURL expected { + .url = "https://www.example.org/file.tar.gz", + .base = "https://www.example.org/file.tar.gz", + .scheme = "https", + .authority = "www.example.org", + .path = "/file.tar.gz", + .query = (StringMap) { { "download", "fast" }, { "when", "now" } }, + .fragment = "hello", + }; + + ASSERT_EQ(parsed, expected); + } + + TEST(parseURL, parsesSimpleHttpUrlWithComplexFragment) { + auto s = "http://www.example.org/file.tar.gz?field=value#?foo=bar%23"; + auto parsed = parseURL(s); + + ParsedURL expected { + .url = "http://www.example.org/file.tar.gz", + .base = "http://www.example.org/file.tar.gz", + .scheme = "http", + .authority = "www.example.org", + .path = "/file.tar.gz", + .query = (StringMap) { { "field", "value" } }, + .fragment = "?foo=bar#", + }; + + ASSERT_EQ(parsed, expected); + } + + TEST(parseURL, parsesFilePlusHttpsUrl) { + auto s = "file+https://www.example.org/video.mp4"; + auto parsed = parseURL(s); + + ParsedURL expected { + .url = "file+https://www.example.org/video.mp4", + .base = "https://www.example.org/video.mp4", + .scheme = "file+https", + .authority = "www.example.org", + .path = "/video.mp4", + .query = (StringMap) { }, + .fragment = "", + }; + + ASSERT_EQ(parsed, expected); + } + + TEST(parseURL, rejectsAuthorityInUrlsWithFileTransportation) { + auto s = "file://www.example.org/video.mp4"; + ASSERT_THROW(parseURL(s), Error); + } + + TEST(parseURL, parseIPv4Address) { + auto s = "http://127.0.0.1:8080/file.tar.gz?download=fast&when=now#hello"; + auto parsed = parseURL(s); + + ParsedURL expected { + .url = "http://127.0.0.1:8080/file.tar.gz", + .base = "https://127.0.0.1:8080/file.tar.gz", + .scheme = "http", + .authority = "127.0.0.1:8080", + .path = "/file.tar.gz", + .query = (StringMap) { { "download", "fast" }, { "when", "now" } }, + .fragment = "hello", + }; + + ASSERT_EQ(parsed, expected); + } + + TEST(parseURL, parseScopedRFC4007IPv6Address) { + auto s = "http://[fe80::818c:da4d:8975:415c\%enp0s25]:8080"; + auto parsed = parseURL(s); + + ParsedURL expected { + .url = "http://[fe80::818c:da4d:8975:415c\%enp0s25]:8080", + .base = "http://[fe80::818c:da4d:8975:415c\%enp0s25]:8080", + .scheme = "http", + .authority = "[fe80::818c:da4d:8975:415c\%enp0s25]:8080", + .path = "", + .query = (StringMap) { }, + .fragment = "", + }; + + ASSERT_EQ(parsed, expected); + + } + + TEST(parseURL, parseIPv6Address) { + auto s = "http://[2a02:8071:8192:c100:311d:192d:81ac:11ea]:8080"; + auto parsed = parseURL(s); + + ParsedURL expected { + .url = "http://[2a02:8071:8192:c100:311d:192d:81ac:11ea]:8080", + .base = "http://[2a02:8071:8192:c100:311d:192d:81ac:11ea]:8080", + .scheme = "http", + .authority = "[2a02:8071:8192:c100:311d:192d:81ac:11ea]:8080", + .path = "", + .query = (StringMap) { }, + .fragment = "", + }; + + ASSERT_EQ(parsed, expected); + + } + + TEST(parseURL, parseEmptyQueryParams) { + auto s = "http://127.0.0.1:8080/file.tar.gz?&&&&&"; + auto parsed = parseURL(s); + ASSERT_EQ(parsed.query, (StringMap) { }); + } + + TEST(parseURL, parseUserPassword) { + auto s = "http://user:pass@www.example.org:8080/file.tar.gz"; + auto parsed = parseURL(s); + + ParsedURL expected { + .url = "http://user:pass@www.example.org/file.tar.gz", + .base = "http://user:pass@www.example.org/file.tar.gz", + .scheme = "http", + .authority = "user:pass@www.example.org:8080", + .path = "/file.tar.gz", + .query = (StringMap) { }, + .fragment = "", + }; + + + ASSERT_EQ(parsed, expected); + } + + TEST(parseURL, parseFileURLWithQueryAndFragment) { + auto s = "file:///none/of//your/business"; + auto parsed = parseURL(s); + + ParsedURL expected { + .url = "", + .base = "", + .scheme = "file", + .authority = "", + .path = "/none/of//your/business", + .query = (StringMap) { }, + .fragment = "", + }; + + ASSERT_EQ(parsed, expected); + + } + + TEST(parseURL, parsedUrlsIsEqualToItself) { + auto s = "http://www.example.org/file.tar.gz"; + auto url = parseURL(s); + + ASSERT_TRUE(url == url); + } + + TEST(parseURL, parseFTPUrl) { + auto s = "ftp://ftp.nixos.org/downloads/nixos.iso"; + auto parsed = parseURL(s); + + ParsedURL expected { + .url = "ftp://ftp.nixos.org/downloads/nixos.iso", + .base = "ftp://ftp.nixos.org/downloads/nixos.iso", + .scheme = "ftp", + .authority = "ftp.nixos.org", + .path = "/downloads/nixos.iso", + .query = (StringMap) { }, + .fragment = "", + }; + + ASSERT_EQ(parsed, expected); + } + + TEST(parseURL, parsesAnythingInUriFormat) { + auto s = "whatever://github.com/NixOS/nixpkgs.git"; + auto parsed = parseURL(s); + } + + TEST(parseURL, parsesAnythingInUriFormatWithoutDoubleSlash) { + auto s = "whatever:github.com/NixOS/nixpkgs.git"; + auto parsed = parseURL(s); + } + + TEST(parseURL, emptyStringIsInvalidURL) { + ASSERT_THROW(parseURL(""), Error); + } + + /* ---------------------------------------------------------------------------- + * decodeQuery + * --------------------------------------------------------------------------*/ + + TEST(decodeQuery, emptyStringYieldsEmptyMap) { + auto d = decodeQuery(""); + ASSERT_EQ(d, (StringMap) { }); + } + + TEST(decodeQuery, simpleDecode) { + auto d = decodeQuery("yi=one&er=two"); + ASSERT_EQ(d, ((StringMap) { { "yi", "one" }, { "er", "two" } })); + } + + TEST(decodeQuery, decodeUrlEncodedArgs) { + auto d = decodeQuery("arg=%3D%3D%40%3D%3D"); + ASSERT_EQ(d, ((StringMap) { { "arg", "==@==" } })); + } + + TEST(decodeQuery, decodeArgWithEmptyValue) { + auto d = decodeQuery("arg="); + ASSERT_EQ(d, ((StringMap) { { "arg", ""} })); + } + + /* ---------------------------------------------------------------------------- + * percentDecode + * --------------------------------------------------------------------------*/ + + TEST(percentDecode, decodesUrlEncodedString) { + std::string s = "==@=="; + std::string d = percentDecode("%3D%3D%40%3D%3D"); + ASSERT_EQ(d, s); + } + + TEST(percentDecode, multipleDecodesAreIdempotent) { + std::string once = percentDecode("%3D%3D%40%3D%3D"); + std::string twice = percentDecode(once); + + ASSERT_EQ(once, twice); + } + + TEST(percentDecode, trailingPercent) { + std::string s = "==@==%"; + std::string d = percentDecode("%3D%3D%40%3D%3D%25"); + + ASSERT_EQ(d, s); + } + + + /* ---------------------------------------------------------------------------- + * percentEncode + * --------------------------------------------------------------------------*/ + + TEST(percentEncode, encodesUrlEncodedString) { + std::string s = percentEncode("==@=="); + std::string d = "%3D%3D%40%3D%3D"; + ASSERT_EQ(d, s); + } + + TEST(percentEncode, keepArgument) { + std::string a = percentEncode("abd / def"); + std::string b = percentEncode("abd / def", "/"); + ASSERT_EQ(a, "abd%20%2F%20def"); + ASSERT_EQ(b, "abd%20/%20def"); + } + + TEST(percentEncode, inverseOfDecode) { + std::string original = "%3D%3D%40%3D%3D"; + std::string once = percentEncode(original); + std::string back = percentDecode(once); + + ASSERT_EQ(back, original); + } + + TEST(percentEncode, trailingPercent) { + std::string s = percentEncode("==@==%"); + std::string d = "%3D%3D%40%3D%3D%25"; + + ASSERT_EQ(d, s); + } + +} diff --git a/tests/unit/libutil/xml-writer.cc b/tests/unit/libutil/xml-writer.cc new file mode 100644 index 000000000..adcde25c9 --- /dev/null +++ b/tests/unit/libutil/xml-writer.cc @@ -0,0 +1,105 @@ +#include "xml-writer.hh" +#include +#include + +namespace nix { + + /* ---------------------------------------------------------------------------- + * XMLWriter + * --------------------------------------------------------------------------*/ + + TEST(XMLWriter, emptyObject) { + std::stringstream out; + { + XMLWriter t(false, out); + } + + ASSERT_EQ(out.str(), "\n"); + } + + TEST(XMLWriter, objectWithEmptyElement) { + std::stringstream out; + { + XMLWriter t(false, out); + t.openElement("foobar"); + } + + ASSERT_EQ(out.str(), "\n"); + } + + TEST(XMLWriter, objectWithElementWithAttrs) { + std::stringstream out; + { + XMLWriter t(false, out); + XMLAttrs attrs = { + { "foo", "bar" } + }; + t.openElement("foobar", attrs); + } + + ASSERT_EQ(out.str(), "\n"); + } + + TEST(XMLWriter, objectWithElementWithEmptyAttrs) { + std::stringstream out; + { + XMLWriter t(false, out); + XMLAttrs attrs = {}; + t.openElement("foobar", attrs); + } + + ASSERT_EQ(out.str(), "\n"); + } + + TEST(XMLWriter, objectWithElementWithAttrsEscaping) { + std::stringstream out; + { + XMLWriter t(false, out); + XMLAttrs attrs = { + { "", "" } + }; + t.openElement("foobar", attrs); + } + + // XXX: While "" is escaped, "" isn't which I think is a bug. + ASSERT_EQ(out.str(), "\n=\"<value>\">"); + } + + TEST(XMLWriter, objectWithElementWithAttrsIndented) { + std::stringstream out; + { + XMLWriter t(true, out); + XMLAttrs attrs = { + { "foo", "bar" } + }; + t.openElement("foobar", attrs); + } + + ASSERT_EQ(out.str(), "\n\n\n"); + } + + TEST(XMLWriter, writeEmptyElement) { + std::stringstream out; + { + XMLWriter t(false, out); + t.writeEmptyElement("foobar"); + } + + ASSERT_EQ(out.str(), "\n"); + } + + TEST(XMLWriter, writeEmptyElementWithAttributes) { + std::stringstream out; + { + XMLWriter t(false, out); + XMLAttrs attrs = { + { "foo", "bar" } + }; + t.writeEmptyElement("foobar", attrs); + + } + + ASSERT_EQ(out.str(), "\n"); + } + +} -- cgit v1.2.3