about summary refs log tree commit diff
path: root/nixpkgs/pkgs/test
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/pkgs/test')
-rw-r--r--nixpkgs/pkgs/test/cc-wrapper/cc-main.c7
-rw-r--r--nixpkgs/pkgs/test/cc-wrapper/cflags-main.c10
-rw-r--r--nixpkgs/pkgs/test/cc-wrapper/core-foundation-main.c7
-rw-r--r--nixpkgs/pkgs/test/cc-wrapper/cxx-main.cc7
-rw-r--r--nixpkgs/pkgs/test/cc-wrapper/default.nix104
-rw-r--r--nixpkgs/pkgs/test/cc-wrapper/foo.c4
-rw-r--r--nixpkgs/pkgs/test/cc-wrapper/ldflags-main.c12
-rw-r--r--nixpkgs/pkgs/test/cc-wrapper/multilib.nix37
-rw-r--r--nixpkgs/pkgs/test/cc-wrapper/nostdinc-main.c8
-rw-r--r--nixpkgs/pkgs/test/cc-wrapper/sanitizers.c8
-rw-r--r--nixpkgs/pkgs/test/cc-wrapper/stdio.h1
-rw-r--r--nixpkgs/pkgs/test/config.nix24
-rw-r--r--nixpkgs/pkgs/test/coq/default.nix6
-rw-r--r--nixpkgs/pkgs/test/coq/overrideCoqDerivation/default.nix40
-rw-r--r--nixpkgs/pkgs/test/cross/default.nix154
-rw-r--r--nixpkgs/pkgs/test/cuda/cuda-library-samples/extension.nix3
-rw-r--r--nixpkgs/pkgs/test/cuda/cuda-library-samples/generic.nix71
-rw-r--r--nixpkgs/pkgs/test/cuda/cuda-samples/extension.nix23
-rw-r--r--nixpkgs/pkgs/test/cuda/cuda-samples/generic.nix61
-rw-r--r--nixpkgs/pkgs/test/cuda/default.nix28
-rw-r--r--nixpkgs/pkgs/test/cue/default.nix24
-rw-r--r--nixpkgs/pkgs/test/default.nix96
-rw-r--r--nixpkgs/pkgs/test/dhall/buildDhallUrl/default.nix14
-rw-r--r--nixpkgs/pkgs/test/dhall/default.nix6
-rw-r--r--nixpkgs/pkgs/test/dhall/generateDhallDirectoryPackage/default.nix17
-rw-r--r--nixpkgs/pkgs/test/dotnet/default.nix5
-rw-r--r--nixpkgs/pkgs/test/dotnet/project-references/application/Application.cs1
-rw-r--r--nixpkgs/pkgs/test/dotnet/project-references/application/Application.csproj10
-rw-r--r--nixpkgs/pkgs/test/dotnet/project-references/default.nix38
-rw-r--r--nixpkgs/pkgs/test/dotnet/project-references/library/Library.cs8
-rw-r--r--nixpkgs/pkgs/test/dotnet/project-references/library/Library.csproj5
-rw-r--r--nixpkgs/pkgs/test/dotnet/project-references/nuget-deps.nix5
-rw-r--r--nixpkgs/pkgs/test/haskell/cabalSdist/default.nix28
-rw-r--r--nixpkgs/pkgs/test/haskell/cabalSdist/local/CHANGELOG.md5
-rw-r--r--nixpkgs/pkgs/test/haskell/cabalSdist/local/app/Main.hs4
-rw-r--r--nixpkgs/pkgs/test/haskell/cabalSdist/local/generated.nix12
-rw-r--r--nixpkgs/pkgs/test/haskell/cabalSdist/local/local.cabal13
-rw-r--r--nixpkgs/pkgs/test/haskell/default.nix10
-rw-r--r--nixpkgs/pkgs/test/haskell/documentationTarball/default.nix21
-rw-r--r--nixpkgs/pkgs/test/haskell/incremental/default.nix35
-rw-r--r--nixpkgs/pkgs/test/haskell/setBuildTarget/Bar.hs4
-rw-r--r--nixpkgs/pkgs/test/haskell/setBuildTarget/Foo.hs4
-rw-r--r--nixpkgs/pkgs/test/haskell/setBuildTarget/Setup.hs2
-rw-r--r--nixpkgs/pkgs/test/haskell/setBuildTarget/default.nix43
-rw-r--r--nixpkgs/pkgs/test/haskell/setBuildTarget/haskell-setBuildTarget.cabal16
-rw-r--r--nixpkgs/pkgs/test/haskell/shellFor/default.nix57
-rw-r--r--nixpkgs/pkgs/test/haskell/upstreamStackHpackVersion/default.nix151
-rw-r--r--nixpkgs/pkgs/test/hooks/default.nix8
-rw-r--r--nixpkgs/pkgs/test/install-shell-files/default.nix125
-rw-r--r--nixpkgs/pkgs/test/kernel.nix73
-rw-r--r--nixpkgs/pkgs/test/ld-library-path/default.nix88
-rw-r--r--nixpkgs/pkgs/test/macos-sierra-shared/default.nix90
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/add-flags.c23
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/add-flags.cmdline3
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/add-flags.env8
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/argv0.c7
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/argv0.cmdline1
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/argv0.env2
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/basic.c7
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/basic.cmdline0
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/basic.env2
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/chdir.c11
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/chdir.cmdline1
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/chdir.env2
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/combination.c53
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/combination.cmdline6
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/combination.env8
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/cross.nix23
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/default.nix61
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/env.c14
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/env.cmdline4
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/env.env6
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/envcheck.c22
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/inherit-argv0.c6
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/inherit-argv0.cmdline1
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/inherit-argv0.env2
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/invalid-env.c14
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/invalid-env.cmdline2
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/overlength-strings.c25
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/overlength-strings.cmdline1
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/overlength-strings.env3
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/prefix.c26
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/prefix.cmdline2
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/prefix.env3
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/suffix.c26
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/suffix.cmdline2
-rw-r--r--nixpkgs/pkgs/test/make-binary-wrapper/suffix.env3
-rw-r--r--nixpkgs/pkgs/test/make-hardcode-gsettings-patch/default.nix58
-rw-r--r--nixpkgs/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project-patched/main.c85
-rw-r--r--nixpkgs/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project/main.c49
-rw-r--r--nixpkgs/pkgs/test/make-wrapper/default.nix139
-rw-r--r--nixpkgs/pkgs/test/nixos-functions/default.nix31
-rw-r--r--nixpkgs/pkgs/test/overriding.nix66
-rw-r--r--nixpkgs/pkgs/test/php/default.nix116
-rw-r--r--nixpkgs/pkgs/test/simple/builder.sh43
-rw-r--r--nixpkgs/pkgs/test/stdenv-inputs/bar.c3
-rw-r--r--nixpkgs/pkgs/test/stdenv-inputs/cc-main.c7
-rw-r--r--nixpkgs/pkgs/test/stdenv-inputs/default.nix68
-rw-r--r--nixpkgs/pkgs/test/stdenv-inputs/foo.c3
-rw-r--r--nixpkgs/pkgs/test/stdenv-inputs/include-main.c13
-rw-r--r--nixpkgs/pkgs/test/stdenv-inputs/lib-main.c14
-rw-r--r--nixpkgs/pkgs/test/stdenv/default.nix293
-rw-r--r--nixpkgs/pkgs/test/stdenv/gcc-stageCompare.nix32
-rw-r--r--nixpkgs/pkgs/test/stdenv/hooks.nix136
-rw-r--r--nixpkgs/pkgs/test/stdenv/patch-shebangs.nix115
-rw-r--r--nixpkgs/pkgs/test/texlive/default.nix514
-rw-r--r--nixpkgs/pkgs/test/vim/default.nix26
107 files changed, 3824 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/test/cc-wrapper/cc-main.c b/nixpkgs/pkgs/test/cc-wrapper/cc-main.c
new file mode 100644
index 000000000000..06f28bc33c69
--- /dev/null
+++ b/nixpkgs/pkgs/test/cc-wrapper/cc-main.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+  fprintf(stderr, "ok\n");
+  return 0;
+}
diff --git a/nixpkgs/pkgs/test/cc-wrapper/cflags-main.c b/nixpkgs/pkgs/test/cc-wrapper/cflags-main.c
new file mode 100644
index 000000000000..9491232b5387
--- /dev/null
+++ b/nixpkgs/pkgs/test/cc-wrapper/cflags-main.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+#include <foo.h>
+
+int main(int argc, char **argv)
+{
+  if (foo() != 42)
+    return 1;
+  fprintf(stderr, "ok\n");
+  return 0;
+}
diff --git a/nixpkgs/pkgs/test/cc-wrapper/core-foundation-main.c b/nixpkgs/pkgs/test/cc-wrapper/core-foundation-main.c
new file mode 100644
index 000000000000..fb3bd3126191
--- /dev/null
+++ b/nixpkgs/pkgs/test/cc-wrapper/core-foundation-main.c
@@ -0,0 +1,7 @@
+#include <CoreFoundation/CoreFoundation.h>
+
+int main(int argc, char** argv)
+{
+  CFShow(CFSTR("ok"));
+  return 0;
+}
diff --git a/nixpkgs/pkgs/test/cc-wrapper/cxx-main.cc b/nixpkgs/pkgs/test/cc-wrapper/cxx-main.cc
new file mode 100644
index 000000000000..83f704617a46
--- /dev/null
+++ b/nixpkgs/pkgs/test/cc-wrapper/cxx-main.cc
@@ -0,0 +1,7 @@
+#include <iostream>
+
+int main(int argc, char **argv)
+{
+  std::cerr << "ok" << std::endl;
+  return 0;
+}
diff --git a/nixpkgs/pkgs/test/cc-wrapper/default.nix b/nixpkgs/pkgs/test/cc-wrapper/default.nix
new file mode 100644
index 000000000000..43e8e7a21426
--- /dev/null
+++ b/nixpkgs/pkgs/test/cc-wrapper/default.nix
@@ -0,0 +1,104 @@
+{ lib, stdenv, glibc, buildPackages }:
+
+let
+  # Sanitizers are not supported on Darwin.
+  # Sanitizer headers aren't available in older libc++ stdenvs due to a bug
+  sanitizersWorking = (stdenv.buildPlatform == stdenv.hostPlatform) && !stdenv.isDarwin && !stdenv.hostPlatform.isMusl && (
+    (stdenv.cc.isClang && lib.versionAtLeast (lib.getVersion stdenv.cc.name) "5.0.0")
+    || (stdenv.cc.isGNU && stdenv.isLinux)
+  );
+  staticLibc = lib.optionalString (stdenv.hostPlatform.libc == "glibc") "-L ${glibc.static}/lib";
+  emulator = stdenv.hostPlatform.emulator buildPackages;
+in stdenv.mkDerivation {
+  name = "cc-wrapper-test";
+
+  buildCommand = ''
+    set -o pipefail
+
+    NIX_DEBUG=1 $CC -v
+    NIX_DEBUG=1 $CXX -v
+
+    printf "checking whether compiler builds valid C binaries... " >&2
+    $CC -o cc-check ${./cc-main.c}
+    ${emulator} ./cc-check
+
+    printf "checking whether compiler builds valid C++ binaries... " >&2
+    $CXX -o cxx-check ${./cxx-main.cc}
+    ${emulator} ./cxx-check
+
+    ${lib.optionalString (stdenv.isDarwin && stdenv.cc.isClang) ''
+      printf "checking whether compiler can build with CoreFoundation.framework... " >&2
+      mkdir -p foo/lib
+      $CC -framework CoreFoundation -o core-foundation-check ${./core-foundation-main.c}
+      ${emulator} ./core-foundation-check
+    ''}
+
+
+    ${lib.optionalString (!stdenv.isDarwin) ''
+      printf "checking whether compiler builds valid static C binaries... " >&2
+      $CC ${staticLibc} -static -o cc-static ${./cc-main.c}
+      ${emulator} ./cc-static
+      ${lib.optionalString (stdenv.cc.isGNU && lib.versionAtLeast (lib.getVersion stdenv.cc.name) "8.0.0") ''
+        printf "checking whether compiler builds valid static pie C binaries... " >&2
+        $CC ${staticLibc} -static-pie -o cc-static-pie ${./cc-main.c}
+        ${emulator} ./cc-static-pie
+      ''}
+    ''}
+
+    ${# See: https://github.com/llvm/llvm-project/commit/ed1d07282cc9d8e4c25d585e03e5c8a1b6f63a74
+      # `gcc` does not support this so we gate the test on `clang`
+      lib.optionalString stdenv.cc.isClang ''
+        printf "checking whether cc-wrapper accepts -- followed by positional (file) args..." >&2
+        mkdir -p positional
+
+        # Make sure `--` is not parsed as a "non flag arg"; we should get an
+        # input file error here and *not* a linker error.
+        { ! $CC --; } |& grep -q "no input files"
+
+        # And that positional file args _must_ be files (this is just testing
+        # that we remembered to put the `--` back in the args to the compiler):
+        { ! $CC -c -- -o foo ${./foo.c}; } \
+          |& grep -q "no such file or directory: '-o'"
+
+        # Now check that we accept single and multiple positional file args:
+        $CC -c -DVALUE=42 -o positional/foo.o -- ${./foo.c}
+        $CC -o positional/main -- positional/foo.o ${./ldflags-main.c}
+        ${emulator} ./positional/main
+    ''}
+
+    printf "checking whether compiler uses NIX_CFLAGS_COMPILE... " >&2
+    mkdir -p foo/include
+    cp ${./foo.c} foo/include/foo.h
+    NIX_CFLAGS_COMPILE="-Ifoo/include -DVALUE=42" $CC -o cflags-check ${./cflags-main.c}
+    ${emulator} ./cflags-check
+
+    printf "checking whether compiler uses NIX_LDFLAGS... " >&2
+    mkdir -p foo/lib
+    $CC -shared \
+      ${lib.optionalString stdenv.isDarwin "-Wl,-install_name,@rpath/libfoo.dylib"} \
+      -DVALUE=42 \
+      -o foo/lib/libfoo${stdenv.hostPlatform.extensions.sharedLibrary} \
+      ${./foo.c}
+
+    NIX_LDFLAGS="-L$NIX_BUILD_TOP/foo/lib -rpath $NIX_BUILD_TOP/foo/lib" $CC -lfoo -o ldflags-check ${./ldflags-main.c}
+    ${emulator} ./ldflags-check
+
+    printf "Check whether -nostdinc and -nostdinc++ is handled correctly" >&2
+    mkdir -p std-include
+    cp ${./stdio.h} std-include/stdio.h
+    NIX_DEBUG=1 $CC -I std-include -nostdinc -o nostdinc-main ${./nostdinc-main.c}
+    ${emulator} ./nostdinc-main
+    $CXX -I std-include -nostdinc++ -o nostdinc-main++ ${./nostdinc-main.c}
+    ${emulator} ./nostdinc-main++
+
+    ${lib.optionalString sanitizersWorking ''
+      printf "checking whether sanitizers are fully functional... ">&2
+      $CC -o sanitizers -fsanitize=address,undefined ${./sanitizers.c}
+      ASAN_OPTIONS=use_sigaltstack=0 ${emulator} ./sanitizers
+    ''}
+
+    touch $out
+  '';
+
+  meta.platforms = lib.platforms.all;
+}
diff --git a/nixpkgs/pkgs/test/cc-wrapper/foo.c b/nixpkgs/pkgs/test/cc-wrapper/foo.c
new file mode 100644
index 000000000000..8be674be3103
--- /dev/null
+++ b/nixpkgs/pkgs/test/cc-wrapper/foo.c
@@ -0,0 +1,4 @@
+unsigned int foo(void)
+{
+  return VALUE;
+}
diff --git a/nixpkgs/pkgs/test/cc-wrapper/ldflags-main.c b/nixpkgs/pkgs/test/cc-wrapper/ldflags-main.c
new file mode 100644
index 000000000000..89832b3bbad2
--- /dev/null
+++ b/nixpkgs/pkgs/test/cc-wrapper/ldflags-main.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+extern unsigned int foo(void);
+
+int main(int argc, char **argv)
+{
+  if (foo() != 42) {
+    return 1;
+  }
+  fprintf(stderr, "ok\n");
+  return 0;
+}
diff --git a/nixpkgs/pkgs/test/cc-wrapper/multilib.nix b/nixpkgs/pkgs/test/cc-wrapper/multilib.nix
new file mode 100644
index 000000000000..a26880681f22
--- /dev/null
+++ b/nixpkgs/pkgs/test/cc-wrapper/multilib.nix
@@ -0,0 +1,37 @@
+{ lib, stdenv }:
+
+stdenv.mkDerivation {
+  name = "cc-multilib-test";
+
+  # XXX: "depend" on cc-wrapper test?
+
+  # TODO: Have tests report pointer size or something; ensure they are what we asked for
+  buildCommand = ''
+    NIX_DEBUG=1 $CC -v
+    NIX_DEBUG=1 $CXX -v
+
+    printf "checking whether compiler builds valid C binaries...\n " >&2
+    $CC -o cc-check ${./cc-main.c}
+    ./cc-check
+
+    printf "checking whether compiler builds valid 32bit C binaries...\n " >&2
+    $CC -m32 -o c32-check ${./cc-main.c}
+    ./c32-check
+
+    printf "checking whether compiler builds valid 64bit C binaries...\n " >&2
+    $CC -m64 -o c64-check ${./cc-main.c}
+    ./c64-check
+
+    printf "checking whether compiler builds valid 32bit C++ binaries...\n " >&2
+    $CXX -m32 -o cxx32-check ${./cxx-main.cc}
+    ./cxx32-check
+
+    printf "checking whether compiler builds valid 64bit C++ binaries...\n " >&2
+    $CXX -m64 -o cxx64-check ${./cxx-main.cc}
+    ./cxx64-check
+
+    touch $out
+  '';
+
+  meta.platforms = lib.platforms.x86_64;
+}
diff --git a/nixpkgs/pkgs/test/cc-wrapper/nostdinc-main.c b/nixpkgs/pkgs/test/cc-wrapper/nostdinc-main.c
new file mode 100644
index 000000000000..f71d155b1b27
--- /dev/null
+++ b/nixpkgs/pkgs/test/cc-wrapper/nostdinc-main.c
@@ -0,0 +1,8 @@
+// This one should not come from libc because of -nostdinc
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+  // provided by our own stdio.h
+  foo();
+  return 0;
+}
diff --git a/nixpkgs/pkgs/test/cc-wrapper/sanitizers.c b/nixpkgs/pkgs/test/cc-wrapper/sanitizers.c
new file mode 100644
index 000000000000..93dd78a903ce
--- /dev/null
+++ b/nixpkgs/pkgs/test/cc-wrapper/sanitizers.c
@@ -0,0 +1,8 @@
+#include <sanitizer/asan_interface.h>
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+  fprintf(stderr, "ok\n");
+  return 0;
+}
diff --git a/nixpkgs/pkgs/test/cc-wrapper/stdio.h b/nixpkgs/pkgs/test/cc-wrapper/stdio.h
new file mode 100644
index 000000000000..4bddf1d9d486
--- /dev/null
+++ b/nixpkgs/pkgs/test/cc-wrapper/stdio.h
@@ -0,0 +1 @@
+static void foo(void) {}
diff --git a/nixpkgs/pkgs/test/config.nix b/nixpkgs/pkgs/test/config.nix
new file mode 100644
index 000000000000..734e1aace148
--- /dev/null
+++ b/nixpkgs/pkgs/test/config.nix
@@ -0,0 +1,24 @@
+{ lib, ... }:
+lib.recurseIntoAttrs {
+
+  # https://github.com/NixOS/nixpkgs/issues/175196
+  allowPkgsInPermittedInsecurePackages =
+    let pkgs = import ../.. {
+          config = {
+            permittedInsecurePackages =
+              tempAllow pkgs.authy "2.1.0" [ "electron-9.4.4" ];
+          };
+        };
+        # A simplification of `tempAllow` that doesn't check the version, but
+        # has the same strictness characteristics. Actually checking a version
+        # here would add undue maintenance.
+        #
+        # Original:
+        #     tempAllow = p: v: pa:
+        #       lib.optionals (lib.assertMsg (p.version == v) "${p.name} is no longer at version ${v}, consider removing the tempAllow") pa;
+        #
+        tempAllow = p: v: pa: builtins.seq v builtins.seq p.version pa;
+
+    in pkgs.hello;
+
+}
diff --git a/nixpkgs/pkgs/test/coq/default.nix b/nixpkgs/pkgs/test/coq/default.nix
new file mode 100644
index 000000000000..cf59dd473b4c
--- /dev/null
+++ b/nixpkgs/pkgs/test/coq/default.nix
@@ -0,0 +1,6 @@
+{ lib, callPackage }:
+
+lib.recurseIntoAttrs {
+  overrideCoqDerivation = callPackage ./overrideCoqDerivation { };
+}
+
diff --git a/nixpkgs/pkgs/test/coq/overrideCoqDerivation/default.nix b/nixpkgs/pkgs/test/coq/overrideCoqDerivation/default.nix
new file mode 100644
index 000000000000..c251c498e609
--- /dev/null
+++ b/nixpkgs/pkgs/test/coq/overrideCoqDerivation/default.nix
@@ -0,0 +1,40 @@
+{ lib, coq, mkCoqPackages, runCommand }:
+
+let
+
+  # This is just coq, but with dontFilter set to true. We need to set
+  # dontFilter to true here so that _all_ packages are visibile in coqPackages.
+  # There may be some versions of the top-level coq and coqPackages that don't
+  # build QuickChick, which is what we are using for this test below.
+  coqWithAllPackages = coq // { dontFilter = true; };
+
+  coqPackages = mkCoqPackages coqWithAllPackages;
+
+  # This is the main test.  This uses overrideCoqDerivation to
+  # override arguments to mkCoqDerivation.
+  #
+  # Here, we override the defaultVersion and release arguments to
+  # mkCoqDerivation.
+  overriddenQuickChick =
+    coqPackages.lib.overrideCoqDerivation
+      {
+        defaultVersion = "9999";
+        release."9999".sha256 = lib.fakeSha256;
+      }
+      coqPackages.QuickChick;
+in
+
+runCommand
+  "coq-overrideCoqDerivation-test-0.1"
+  { meta.maintainers = with lib.maintainers; [cdepillabout]; }
+  ''
+    # Confirm that the computed version number for the overridden QuickChick does
+    # actually become 9999, as set above.
+    if [ "${overriddenQuickChick.version}" -eq "9999" ]; then
+      echo "overriddenQuickChick version was successfully set to 9999"
+      touch $out
+    else
+      echo "ERROR: overriddenQuickChick version was supposed to be 9999, but was actually: ${overriddenQuickChick.version}"
+      exit 1
+    fi
+  ''
diff --git a/nixpkgs/pkgs/test/cross/default.nix b/nixpkgs/pkgs/test/cross/default.nix
new file mode 100644
index 000000000000..ff83aedca123
--- /dev/null
+++ b/nixpkgs/pkgs/test/cross/default.nix
@@ -0,0 +1,154 @@
+{ pkgs, lib }:
+
+let
+
+  testedSystems = lib.filterAttrs (name: value: let
+    platform = lib.systems.elaborate value;
+  in platform.isLinux || platform.isWindows
+  ) lib.systems.examples;
+
+  getExecutable = pkgs: pkgFun: exec:
+    "${pkgFun pkgs}${exec}${pkgs.stdenv.hostPlatform.extensions.executable}";
+
+  compareTest = { emulator, pkgFun, hostPkgs, crossPkgs, exec, args ? [] }: let
+    pkgName = (pkgFun hostPkgs).name;
+    args' = lib.concatStringsSep " " args;
+  in crossPkgs.runCommand "test-${pkgName}-${crossPkgs.hostPlatform.config}" {
+    nativeBuildInputs = [ pkgs.dos2unix ];
+  } ''
+    # Just in case we are using wine, get rid of that annoying extra
+    # stuff.
+    export WINEDEBUG=-all
+
+    HOME=$(pwd)
+    mkdir -p $out
+
+    # We need to remove whitespace, unfortunately
+    # Windows programs use \r but Unix programs use \n
+
+    echo Running native-built program natively
+
+    # find expected value natively
+    ${getExecutable hostPkgs pkgFun exec} ${args'} \
+      | dos2unix > $out/expected
+
+    echo Running cross-built program in emulator
+
+    # run emulator to get actual value
+    ${emulator} ${getExecutable crossPkgs pkgFun exec} ${args'} \
+      | dos2unix > $out/actual
+
+    echo Comparing results...
+
+    if [ "$(cat $out/actual)" != "$(cat $out/expected)" ]; then
+      echo "${pkgName} did not output expected value:"
+      cat $out/expected
+      echo "instead it output:"
+      cat $out/actual
+      exit 1
+    else
+      echo "${pkgName} test passed"
+      echo "both produced output:"
+      cat $out/actual
+    fi
+  '';
+
+  mapMultiPlatformTest = crossSystemFun: test: lib.mapAttrs (name: system: test rec {
+    crossPkgs = import pkgs.path {
+      localSystem = { inherit (pkgs.stdenv.hostPlatform) config; };
+      crossSystem = crossSystemFun system;
+    };
+
+    emulator = crossPkgs.hostPlatform.emulator pkgs;
+
+    # Apply some transformation on windows to get dlls in the right
+    # place. Unfortunately mingw doesn’t seem to be able to do linking
+    # properly.
+    platformFun = pkg: if crossPkgs.hostPlatform.isWindows then
+      pkgs.buildEnv {
+        name = "${pkg.name}-winlinks";
+        paths = [pkg] ++ pkg.buildInputs;
+      } else pkg;
+  }) testedSystems;
+
+  tests = {
+
+    file = {platformFun, crossPkgs, emulator}: compareTest {
+      inherit emulator crossPkgs;
+      hostPkgs = pkgs;
+      exec = "/bin/file";
+      args = [
+        "${pkgs.file}/share/man/man1/file.1.gz"
+        "${pkgs.dejavu_fonts}/share/fonts/truetype/DejaVuMathTeXGyre.ttf"
+      ];
+      pkgFun = pkgs: platformFun pkgs.file;
+    };
+
+    hello = {platformFun, crossPkgs, emulator}: compareTest {
+      inherit emulator crossPkgs;
+      hostPkgs = pkgs;
+      exec = "/bin/hello";
+      pkgFun = pkgs: pkgs.hello;
+    };
+
+    pkg-config = {platformFun, crossPkgs, emulator}: crossPkgs.runCommand
+      "test-pkg-config-${crossPkgs.hostPlatform.config}"
+    {
+      depsBuildBuild = [ crossPkgs.pkgsBuildBuild.pkg-config ];
+      nativeBuildInputs = [ crossPkgs.pkgsBuildHost.pkg-config crossPkgs.buildPackages.zlib ];
+      depsBuildTarget = [ crossPkgs.pkgsBuildTarget.pkg-config ];
+      buildInputs = [ crossPkgs.zlib ];
+      NIX_DEBUG = 7;
+    } ''
+       mkdir $out
+       ${crossPkgs.pkgsBuildBuild.pkg-config.targetPrefix}pkg-config --cflags zlib > "$out/for-build"
+       ${crossPkgs.pkgsBuildHost.pkg-config.targetPrefix}pkg-config --cflags zlib > "$out/for-host"
+       ! diff "$out/for-build" "$out/for-host"
+    '';
+  };
+
+  # see https://github.com/NixOS/nixpkgs/issues/213453
+  # this is a good test of a lot of tricky glibc/libgcc corner cases
+  mbuffer = let
+    mbuffer = pkgs.pkgsCross.aarch64-multiplatform.mbuffer;
+    emulator = with lib.systems; (elaborate examples.aarch64-multiplatform).emulator pkgs;
+  in
+    pkgs.runCommand "test-mbuffer" {} ''
+      echo hello | ${emulator} ${mbuffer}/bin/mbuffer
+      touch $out
+    '';
+
+  # This is meant to be a carefully curated list of builds/packages
+  # that tend to break when refactoring our cross-compilation
+  # infrastructure.
+  #
+  # It should strike a balance between being small enough to fit in
+  # a single eval (i.e. not so large that hydra-eval-jobs is needed)
+  # so we can ask @ofborg to check it, yet should have good examples
+  # of things that often break.  So, no buckshot `mapTestOnCross`
+  # calls here.
+  sanity = [
+    mbuffer
+    #pkgs.pkgsCross.gnu64.bash # https://github.com/NixOS/nixpkgs/issues/243164
+    pkgs.gcc_multi.cc
+    pkgs.pkgsMusl.stdenv
+    pkgs.pkgsLLVM.stdenv
+    pkgs.pkgsStatic.bash
+    pkgs.pkgsCross.arm-embedded.stdenv
+    pkgs.pkgsCross.sheevaplug.stdenv  # for armv5tel
+    pkgs.pkgsCross.raspberryPi.stdenv  # for armv6l
+    pkgs.pkgsCross.armv7l-hf-multiplatform.stdenv
+    pkgs.pkgsCross.m68k.stdenv
+    pkgs.pkgsCross.aarch64-multiplatform.pkgsBuildTarget.gcc
+    pkgs.pkgsCross.powernv.pkgsBuildTarget.gcc
+    pkgs.pkgsCross.mips64el-linux-gnuabi64.stdenv
+    pkgs.pkgsCross.mips64el-linux-gnuabin32.stdenv
+    pkgs.pkgsCross.mingwW64.stdenv
+  ];
+
+in {
+  gcc = (lib.mapAttrs (_: mapMultiPlatformTest (system: system // {useLLVM = false;})) tests);
+  llvm = (lib.mapAttrs (_: mapMultiPlatformTest (system: system // {useLLVM = true;})) tests);
+
+  inherit mbuffer sanity;
+}
diff --git a/nixpkgs/pkgs/test/cuda/cuda-library-samples/extension.nix b/nixpkgs/pkgs/test/cuda/cuda-library-samples/extension.nix
new file mode 100644
index 000000000000..4c721a9e9e1b
--- /dev/null
+++ b/nixpkgs/pkgs/test/cuda/cuda-library-samples/extension.nix
@@ -0,0 +1,3 @@
+final: prev: {
+  cuda-library-samples = final.callPackage ./generic.nix { };
+}
diff --git a/nixpkgs/pkgs/test/cuda/cuda-library-samples/generic.nix b/nixpkgs/pkgs/test/cuda/cuda-library-samples/generic.nix
new file mode 100644
index 000000000000..e9a481c94a7a
--- /dev/null
+++ b/nixpkgs/pkgs/test/cuda/cuda-library-samples/generic.nix
@@ -0,0 +1,71 @@
+{ lib, backendStdenv, fetchFromGitHub
+, cmake, addOpenGLRunpath
+, cudatoolkit
+, cutensor
+}:
+
+let
+  rev = "5aab680905d853bce0dbad4c488e4f7e9f7b2302";
+  src = fetchFromGitHub {
+    owner = "NVIDIA";
+    repo = "CUDALibrarySamples";
+    inherit rev;
+    sha256 = "0gwgbkq05ygrfgg5hk07lmap7n7ampxv0ha1axrv8qb748ph81xs";
+  };
+  commonAttrs = {
+    version = lib.strings.substring 0 7 rev + "-" + lib.versions.majorMinor cudatoolkit.version;
+    nativeBuildInputs = [ cmake addOpenGLRunpath ];
+    buildInputs = [ cudatoolkit ];
+    postFixup = ''
+      for exe in $out/bin/*; do
+        addOpenGLRunpath $exe
+      done
+    '';
+    meta = {
+      description = "examples of using libraries using CUDA";
+      longDescription = ''
+        CUDA Library Samples contains examples demonstrating the use of
+        features in the math and image processing libraries cuBLAS, cuTENSOR,
+        cuSPARSE, cuSOLVER, cuFFT, cuRAND, NPP and nvJPEG.
+      '';
+      license = lib.licenses.bsd3;
+      maintainers = with lib.maintainers; [ obsidian-systems-maintenance ];
+    };
+  };
+in
+
+{
+  cublas = backendStdenv.mkDerivation (commonAttrs // {
+    pname = "cuda-library-samples-cublas";
+
+    src = "${src}/cuBLASLt";
+  });
+
+  cusolver = backendStdenv.mkDerivation (commonAttrs // {
+    pname = "cuda-library-samples-cusolver";
+
+    src = "${src}/cuSOLVER";
+
+    sourceRoot = "cuSOLVER/gesv";
+  });
+
+  cutensor = backendStdenv.mkDerivation (commonAttrs // {
+    pname = "cuda-library-samples-cutensor";
+
+    src = "${src}/cuTENSOR";
+
+    buildInputs = [ cutensor ];
+
+    cmakeFlags = [
+      "-DCUTENSOR_EXAMPLE_BINARY_INSTALL_DIR=${builtins.placeholder "out"}/bin"
+    ];
+
+    # CUTENSOR_ROOT is double escaped
+    postPatch = ''
+      substituteInPlace CMakeLists.txt \
+        --replace "\''${CUTENSOR_ROOT}/include" "${cutensor.dev}/include"
+    '';
+
+    CUTENSOR_ROOT = cutensor;
+  });
+}
diff --git a/nixpkgs/pkgs/test/cuda/cuda-samples/extension.nix b/nixpkgs/pkgs/test/cuda/cuda-samples/extension.nix
new file mode 100644
index 000000000000..05861ee5e0eb
--- /dev/null
+++ b/nixpkgs/pkgs/test/cuda/cuda-samples/extension.nix
@@ -0,0 +1,23 @@
+final: prev: let
+
+  sha256 = {
+    "10.0" = "1zvh4xsdyc59m87brpcmssxsjlp9dkynh4asnkcmc3g94f53l0jw";
+    "10.1" = "1s8ka0hznrni36ajhzf2gqpdrl8kd8fi047qijxks5l2abc093qd";
+    "10.2" = "01p1innzgh9siacpld6nsqimj8jkg93rk4gj8q4crn62pa5vhd94";
+    "11.0" = "1n3vjc8c7zdig2xgl5fppavrphqzhdiv9m9nk6smh4f99fwi0705";
+    "11.1" = "1kjixk50i8y1bkiwbdn5lkv342crvkmbvy1xl5j3lsa1ica21kwh";
+    "11.2" = "1p1qjvfbm28l933mmnln02rqrf0cy9kbpsyb488d1haiqzvrazl1";
+    "11.3" = "0kbibb6pgz8j5iq6284axcnmycaha9bw8qlmdp6yfwmnahq1v0yz";
+    "11.4" = "082dkk5y34wyvjgj2p5j1d00rk8xaxb9z0mhvz16bd469r1bw2qk";
+    "11.5" = "sha256-AKRZbke0K59lakhTi8dX2cR2aBuWPZkiQxyKaZTvHrI=";
+    "11.6" = "sha256-AsLNmAplfuQbXg9zt09tXAuFJ524EtTYsQuUlV1tPkE=";
+    "11.7" = throw "The tag 11.7 of cuda-samples does not exist";
+    "11.8" = "sha256-7+1P8+wqTKUGbCUBXGMDO9PkxYr2+PLDx9W2hXtXbuc=";
+    "12.0" = "sha256-Lj2kbdVFrJo5xPYPMiE4BS7Z8gpU5JLKXVJhZABUe/g=";
+  }.${prev.cudaVersion};
+
+in {
+  cuda-samples = final.callPackage ./generic.nix {
+    inherit sha256;
+  };
+}
diff --git a/nixpkgs/pkgs/test/cuda/cuda-samples/generic.nix b/nixpkgs/pkgs/test/cuda/cuda-samples/generic.nix
new file mode 100644
index 000000000000..267eca10d8e8
--- /dev/null
+++ b/nixpkgs/pkgs/test/cuda/cuda-samples/generic.nix
@@ -0,0 +1,61 @@
+{ lib
+, cudaPackages
+, fetchFromGitHub
+, fetchpatch
+, addOpenGLRunpath
+, cudatoolkit
+, pkg-config
+, sha256
+, glfw3
+, freeimage
+}:
+cudaPackages.backendStdenv.mkDerivation rec {
+  pname = "cuda-samples";
+  version = lib.versions.majorMinor cudatoolkit.version;
+
+  src = fetchFromGitHub {
+    owner = "NVIDIA";
+    repo = pname;
+    rev = "v${version}";
+    inherit sha256;
+  };
+
+  nativeBuildInputs = [ pkg-config addOpenGLRunpath glfw3 freeimage ];
+
+  buildInputs = [ cudatoolkit ];
+
+  # See https://github.com/NVIDIA/cuda-samples/issues/75.
+  patches = lib.optionals (version == "11.3") [
+    (fetchpatch {
+      url = "https://github.com/NVIDIA/cuda-samples/commit/5c3ec60faeb7a3c4ad9372c99114d7bb922fda8d.patch";
+      sha256 = "sha256-0XxdmNK9MPpHwv8+qECJTvXGlFxc+fIbta4ynYprfpU=";
+    })
+  ];
+
+  enableParallelBuilding = true;
+
+  preConfigure = ''
+    export CUDA_PATH=${cudatoolkit}
+  '';
+
+  installPhase = ''
+    runHook preInstall
+
+    install -Dm755 -t $out/bin bin/${cudaPackages.backendStdenv.hostPlatform.parsed.cpu.name}/${cudaPackages.backendStdenv.hostPlatform.parsed.kernel.name}/release/*
+
+    runHook postInstall
+  '';
+
+  postFixup = ''
+    for exe in $out/bin/*; do
+      addOpenGLRunpath $exe
+    done
+  '';
+
+  meta = {
+    description = "Samples for CUDA Developers which demonstrates features in CUDA Toolkit";
+    # CUDA itself is proprietary, but these sample apps are not.
+    license = lib.licenses.bsd3;
+    maintainers = with lib.maintainers; [ obsidian-systems-maintenance ];
+  };
+}
diff --git a/nixpkgs/pkgs/test/cuda/default.nix b/nixpkgs/pkgs/test/cuda/default.nix
new file mode 100644
index 000000000000..7989e4e2b7d2
--- /dev/null
+++ b/nixpkgs/pkgs/test/cuda/default.nix
@@ -0,0 +1,28 @@
+{ callPackage }:
+
+rec {
+  cuda-samplesPackages = callPackage ./cuda-samples { };
+  inherit (cuda-samplesPackages)
+    cuda-samples_cudatoolkit_10
+    cuda-samples_cudatoolkit_10_0
+    cuda-samples_cudatoolkit_10_1
+    cuda-samples_cudatoolkit_10_2
+    cuda-samples_cudatoolkit_11
+    cuda-samples_cudatoolkit_11_0
+    cuda-samples_cudatoolkit_11_1
+    cuda-samples_cudatoolkit_11_2
+    cuda-samples_cudatoolkit_11_3
+    cuda-samples_cudatoolkit_11_4;
+
+  cuda-library-samplesPackages = callPackage ./cuda-library-samples { };
+  inherit (cuda-library-samplesPackages)
+    cuda-library-samples_cudatoolkit_10
+    cuda-library-samples_cudatoolkit_10_1
+    cuda-library-samples_cudatoolkit_10_2
+    cuda-library-samples_cudatoolkit_11
+    cuda-library-samples_cudatoolkit_11_0
+    cuda-library-samples_cudatoolkit_11_1
+    cuda-library-samples_cudatoolkit_11_2
+    cuda-library-samples_cudatoolkit_11_3
+    cuda-library-samples_cudatoolkit_11_4;
+}
diff --git a/nixpkgs/pkgs/test/cue/default.nix b/nixpkgs/pkgs/test/cue/default.nix
new file mode 100644
index 000000000000..2cc8bf34bb04
--- /dev/null
+++ b/nixpkgs/pkgs/test/cue/default.nix
@@ -0,0 +1,24 @@
+{ writeCueValidator, runCommand, writeText, ... }:
+
+let
+  validator = writeCueValidator
+    (writeText "schema.cue" ''
+      #Def1: {
+        field1: string
+      }
+    '')
+    { document = "#Def1"; };
+in runCommand "cue-validation" {} ''
+  cat > valid.json <<EOF
+  { "field1": "abc" }
+  EOF
+  cat > invalid.json <<EOF
+  { "field2": "abc" }
+  EOF
+  ${validator} valid.json
+  if ${validator} invalid.json; then
+    echo "this example should fail"
+    exit 1
+  fi
+  touch $out
+''
diff --git a/nixpkgs/pkgs/test/default.nix b/nixpkgs/pkgs/test/default.nix
new file mode 100644
index 000000000000..6bfa1c4393c4
--- /dev/null
+++ b/nixpkgs/pkgs/test/default.nix
@@ -0,0 +1,96 @@
+{ pkgs, callPackage }:
+
+with pkgs;
+
+{
+  cc-wrapper = callPackage ./cc-wrapper { };
+  cc-wrapper-gcc = callPackage ./cc-wrapper { stdenv = gccStdenv; };
+  cc-wrapper-gcc7 = callPackage ./cc-wrapper { stdenv = gcc7Stdenv; };
+  cc-wrapper-gcc8 = callPackage ./cc-wrapper { stdenv = gcc8Stdenv; };
+  cc-wrapper-gcc9 = callPackage ./cc-wrapper { stdenv = gcc9Stdenv; };
+  cc-wrapper-clang = callPackage ./cc-wrapper { stdenv = llvmPackages.stdenv; };
+  cc-wrapper-libcxx = callPackage ./cc-wrapper { stdenv = llvmPackages.libcxxStdenv; };
+  cc-wrapper-clang-5 = callPackage ./cc-wrapper { stdenv = llvmPackages_5.stdenv; };
+  cc-wrapper-libcxx-5 = callPackage ./cc-wrapper { stdenv = llvmPackages_5.libcxxStdenv; };
+  cc-wrapper-clang-6 = callPackage ./cc-wrapper { stdenv = llvmPackages_6.stdenv; };
+  cc-wrapper-libcxx-6 = callPackage ./cc-wrapper { stdenv = llvmPackages_6.libcxxStdenv; };
+  cc-wrapper-clang-7 = callPackage ./cc-wrapper { stdenv = llvmPackages_7.stdenv; };
+  cc-wrapper-libcxx-7 = callPackage ./cc-wrapper { stdenv = llvmPackages_7.libcxxStdenv; };
+  cc-wrapper-clang-8 = callPackage ./cc-wrapper { stdenv = llvmPackages_8.stdenv; };
+  cc-wrapper-libcxx-8 = callPackage ./cc-wrapper { stdenv = llvmPackages_8.libcxxStdenv; };
+  cc-wrapper-clang-9 = callPackage ./cc-wrapper { stdenv = llvmPackages_9.stdenv; };
+  cc-wrapper-libcxx-9 = callPackage ./cc-wrapper { stdenv = llvmPackages_9.libcxxStdenv; };
+  stdenv-inputs = callPackage ./stdenv-inputs { };
+  stdenv = callPackage ./stdenv { };
+
+  config = callPackage ./config.nix { };
+
+  haskell = callPackage ./haskell { };
+
+  hooks = callPackage ./hooks { };
+
+  cc-multilib-gcc = callPackage ./cc-wrapper/multilib.nix { stdenv = gccMultiStdenv; };
+  cc-multilib-clang = callPackage ./cc-wrapper/multilib.nix { stdenv = clangMultiStdenv; };
+
+  fetchurl = callPackages ../build-support/fetchurl/tests.nix { };
+  fetchpatch = callPackages ../build-support/fetchpatch/tests.nix { };
+  fetchpatch2 = callPackages ../build-support/fetchpatch/tests.nix { fetchpatch = fetchpatch2; };
+  fetchzip = callPackages ../build-support/fetchzip/tests.nix { };
+  fetchgit = callPackages ../build-support/fetchgit/tests.nix { };
+  fetchFirefoxAddon = callPackages ../build-support/fetchfirefoxaddon/tests.nix { };
+
+  install-shell-files = callPackage ./install-shell-files {};
+
+  kernel-config = callPackage ./kernel.nix {};
+
+  ld-library-path = callPackage ./ld-library-path {};
+
+  macOSSierraShared = callPackage ./macos-sierra-shared {};
+
+  cross = callPackage ./cross {};
+
+  php = recurseIntoAttrs (callPackages ./php {});
+
+  pkg-config = recurseIntoAttrs (callPackage ../top-level/pkg-config/tests.nix { });
+
+  buildRustCrate = callPackage ../build-support/rust/build-rust-crate/test { };
+  importCargoLock = callPackage ../build-support/rust/test/import-cargo-lock { };
+
+  vim = callPackage ./vim {};
+
+  nixos-functions = callPackage ./nixos-functions {};
+
+  overriding = callPackage ./overriding.nix { };
+
+  texlive = callPackage ./texlive {};
+
+  cuda = callPackage ./cuda { };
+
+  trivial-builders = callPackage ../build-support/trivial-builders/test/default.nix {};
+
+  writers = callPackage ../build-support/writers/test.nix {};
+
+  testers = callPackage ../build-support/testers/test/default.nix {};
+
+  dhall = callPackage ./dhall { };
+
+  cue-validation = callPackage ./cue {};
+
+  coq = callPackage ./coq {};
+
+  dotnet = recurseIntoAttrs (callPackages ./dotnet { });
+
+  makeHardcodeGsettingsPatch = callPackage ./make-hardcode-gsettings-patch { };
+
+  makeWrapper = callPackage ./make-wrapper { };
+  makeBinaryWrapper = callPackage ./make-binary-wrapper {
+    makeBinaryWrapper = pkgs.makeBinaryWrapper.override {
+      # Enable sanitizers in the tests only, to avoid the performance cost in regular usage.
+      # The sanitizers cause errors on aarch64-darwin, see https://github.com/NixOS/nixpkgs/pull/150079#issuecomment-994132734
+      sanitizers = pkgs.lib.optionals (! (pkgs.stdenv.isDarwin && pkgs.stdenv.isAarch64))
+        [ "undefined" "address" ];
+    };
+  };
+
+  pkgs-lib = recurseIntoAttrs (import ../pkgs-lib/tests { inherit pkgs; });
+}
diff --git a/nixpkgs/pkgs/test/dhall/buildDhallUrl/default.nix b/nixpkgs/pkgs/test/dhall/buildDhallUrl/default.nix
new file mode 100644
index 000000000000..a75101a303d6
--- /dev/null
+++ b/nixpkgs/pkgs/test/dhall/buildDhallUrl/default.nix
@@ -0,0 +1,14 @@
+{ dhallPackages, lib }:
+
+# This file tests that dhallPackages.buildDhallUrl is able to successfully
+# build a Nix Dhall package for a given remote Dhall import.
+#
+# TODO: It would be nice to extend this test to make sure that the resulting
+# Nix Dhall package is has the expected contents.
+
+dhallPackages.buildDhallUrl {
+  url = "https://raw.githubusercontent.com/cdepillabout/example-dhall-nix/e6a675c72ecd4dd23d254a02aea8181fe875747f/mydhallfile.dhall";
+  hash = "sha256-434x+QjHRzuprBdw0h6wmwB1Zj6yZqQb533me8XdO4c=";
+  dhallHash = "sha256-434x+QjHRzuprBdw0h6wmwB1Zj6yZqQb533me8XdO4c=";
+  source = true;
+}
diff --git a/nixpkgs/pkgs/test/dhall/default.nix b/nixpkgs/pkgs/test/dhall/default.nix
new file mode 100644
index 000000000000..4c7eba6c9579
--- /dev/null
+++ b/nixpkgs/pkgs/test/dhall/default.nix
@@ -0,0 +1,6 @@
+{ lib, callPackage }:
+
+lib.recurseIntoAttrs {
+  buildDhallUrl = callPackage ./buildDhallUrl { };
+  generateDhallDirectoryPackage = callPackage ./generateDhallDirectoryPackage { };
+}
diff --git a/nixpkgs/pkgs/test/dhall/generateDhallDirectoryPackage/default.nix b/nixpkgs/pkgs/test/dhall/generateDhallDirectoryPackage/default.nix
new file mode 100644
index 000000000000..4771e1629806
--- /dev/null
+++ b/nixpkgs/pkgs/test/dhall/generateDhallDirectoryPackage/default.nix
@@ -0,0 +1,17 @@
+{ dhallPackages, fetchFromGitHub }:
+
+# This file tests that dhallPackages.generateDhallDirectoryPackage works.
+#
+# TODO: It would be nice to extend this test to make sure that the resulting
+# Nix file has the expected contents, but it might be tough to do that easily
+# without IFD.
+
+dhallPackages.generateDhallDirectoryPackage {
+  src = fetchFromGitHub {
+    owner = "cdepillabout";
+    repo = "example-dhall-nix";
+    rev = "e6a675c72ecd4dd23d254a02aea8181fe875747f";
+    sha256 = "sha256-c/EZq76s/+hmLkaeJWKqgh2KrHuJRYI6kWry0E0YQ6s=";
+  };
+  file = "mydhallfile.dhall";
+}
diff --git a/nixpkgs/pkgs/test/dotnet/default.nix b/nixpkgs/pkgs/test/dotnet/default.nix
new file mode 100644
index 000000000000..7592b09d76e3
--- /dev/null
+++ b/nixpkgs/pkgs/test/dotnet/default.nix
@@ -0,0 +1,5 @@
+{ callPackage }:
+
+{
+  project-references = callPackage ./project-references { };
+}
diff --git a/nixpkgs/pkgs/test/dotnet/project-references/application/Application.cs b/nixpkgs/pkgs/test/dotnet/project-references/application/Application.cs
new file mode 100644
index 000000000000..ae2c956a4df7
--- /dev/null
+++ b/nixpkgs/pkgs/test/dotnet/project-references/application/Application.cs
@@ -0,0 +1 @@
+ProjectReferencesTest.Library.Hello();
diff --git a/nixpkgs/pkgs/test/dotnet/project-references/application/Application.csproj b/nixpkgs/pkgs/test/dotnet/project-references/application/Application.csproj
new file mode 100644
index 000000000000..6507637a5535
--- /dev/null
+++ b/nixpkgs/pkgs/test/dotnet/project-references/application/Application.csproj
@@ -0,0 +1,10 @@
+<Project Sdk="Microsoft.NET.Sdk">
+    <PropertyGroup>
+        <OutputType>exe</OutputType>
+    </PropertyGroup>
+
+    <ItemGroup>
+        <ProjectReference Include="../library/Library.csproj" />
+        <PackageReference Include="ProjectReferencesTest.Library" Version="*" Condition=" '$(ContinuousIntegrationBuild)'=='true' " />
+    </ItemGroup>
+</Project>
diff --git a/nixpkgs/pkgs/test/dotnet/project-references/default.nix b/nixpkgs/pkgs/test/dotnet/project-references/default.nix
new file mode 100644
index 000000000000..f40b9196c209
--- /dev/null
+++ b/nixpkgs/pkgs/test/dotnet/project-references/default.nix
@@ -0,0 +1,38 @@
+# Tests the `projectReferences = [ ... ];` feature of buildDotnetModule.
+# The `library` derivation exposes a .nupkg, which is then consumed by the `application` derivation.
+# https://nixos.org/manual/nixpkgs/unstable/index.html#packaging-a-dotnet-application
+
+{ lib
+, dotnet-sdk
+, buildDotnetModule
+, runCommand
+}:
+
+let
+  nugetDeps = ./nuget-deps.nix;
+
+  # Specify the TargetFramework via an environment variable so that we don't
+  # have to update the .csproj files when updating dotnet-sdk
+  TargetFramework = "net${lib.versions.majorMinor (lib.getVersion dotnet-sdk)}";
+
+  library = buildDotnetModule {
+    name = "project-references-test-library";
+    src = ./library;
+    inherit nugetDeps TargetFramework;
+
+    packNupkg = true;
+  };
+
+  application = buildDotnetModule {
+    name = "project-references-test-application";
+    src = ./application;
+    inherit nugetDeps TargetFramework;
+
+    projectReferences = [ library ];
+  };
+in
+
+runCommand "project-references-test" { } ''
+  ${application}/bin/Application
+  touch $out
+''
diff --git a/nixpkgs/pkgs/test/dotnet/project-references/library/Library.cs b/nixpkgs/pkgs/test/dotnet/project-references/library/Library.cs
new file mode 100644
index 000000000000..a4af4a0fea2d
--- /dev/null
+++ b/nixpkgs/pkgs/test/dotnet/project-references/library/Library.cs
@@ -0,0 +1,8 @@
+namespace ProjectReferencesTest;
+public static class Library
+{
+    public static void Hello()
+    {
+        System.Console.WriteLine("Hello, World!");
+    }
+}
diff --git a/nixpkgs/pkgs/test/dotnet/project-references/library/Library.csproj b/nixpkgs/pkgs/test/dotnet/project-references/library/Library.csproj
new file mode 100644
index 000000000000..b9a71276d24a
--- /dev/null
+++ b/nixpkgs/pkgs/test/dotnet/project-references/library/Library.csproj
@@ -0,0 +1,5 @@
+<Project Sdk="Microsoft.NET.Sdk">
+    <PropertyGroup>
+        <PackageId>ProjectReferencesTest.Library</PackageId>
+    </PropertyGroup>
+</Project>
diff --git a/nixpkgs/pkgs/test/dotnet/project-references/nuget-deps.nix b/nixpkgs/pkgs/test/dotnet/project-references/nuget-deps.nix
new file mode 100644
index 000000000000..f3a17967e25c
--- /dev/null
+++ b/nixpkgs/pkgs/test/dotnet/project-references/nuget-deps.nix
@@ -0,0 +1,5 @@
+# This file was automatically generated by passthru.fetch-deps.
+# Please dont edit it manually, your changes might get overwritten!
+
+{ fetchNuGet }: [
+]
diff --git a/nixpkgs/pkgs/test/haskell/cabalSdist/default.nix b/nixpkgs/pkgs/test/haskell/cabalSdist/default.nix
new file mode 100644
index 000000000000..1031e51e4f14
--- /dev/null
+++ b/nixpkgs/pkgs/test/haskell/cabalSdist/default.nix
@@ -0,0 +1,28 @@
+{ lib, haskellPackages, runCommand }:
+
+let
+  localRaw = haskellPackages.callPackage ./local/generated.nix {};
+in
+lib.recurseIntoAttrs rec {
+
+  helloFromCabalSdist = haskellPackages.buildFromCabalSdist haskellPackages.hello;
+
+  # A more complicated example with a cabal hook.
+  hercules-ci-cnix-store = haskellPackages.buildFromCabalSdist haskellPackages.hercules-ci-cnix-store;
+
+  localFromCabalSdist = haskellPackages.buildFromCabalSdist localRaw;
+
+  assumptionLocalHasDirectReference = runCommand "localHasDirectReference" {
+    drvPath = builtins.unsafeDiscardOutputDependency localRaw.drvPath;
+  } ''
+    grep ${./local} $drvPath >/dev/null
+    touch $out
+  '';
+
+  localHasNoDirectReference = runCommand "localHasNoDirectReference" {
+    drvPath = builtins.unsafeDiscardOutputDependency localFromCabalSdist.drvPath;
+  } ''
+    grep -v ${./local} $drvPath >/dev/null
+    touch $out
+  '';
+}
diff --git a/nixpkgs/pkgs/test/haskell/cabalSdist/local/CHANGELOG.md b/nixpkgs/pkgs/test/haskell/cabalSdist/local/CHANGELOG.md
new file mode 100644
index 000000000000..53cc3ae43d8a
--- /dev/null
+++ b/nixpkgs/pkgs/test/haskell/cabalSdist/local/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for local
+
+## 0.1.0.0 -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/nixpkgs/pkgs/test/haskell/cabalSdist/local/app/Main.hs b/nixpkgs/pkgs/test/haskell/cabalSdist/local/app/Main.hs
new file mode 100644
index 000000000000..65ae4a05d5db
--- /dev/null
+++ b/nixpkgs/pkgs/test/haskell/cabalSdist/local/app/Main.hs
@@ -0,0 +1,4 @@
+module Main where
+
+main :: IO ()
+main = putStrLn "Hello, Haskell!"
diff --git a/nixpkgs/pkgs/test/haskell/cabalSdist/local/generated.nix b/nixpkgs/pkgs/test/haskell/cabalSdist/local/generated.nix
new file mode 100644
index 000000000000..bfa299962bcb
--- /dev/null
+++ b/nixpkgs/pkgs/test/haskell/cabalSdist/local/generated.nix
@@ -0,0 +1,12 @@
+# nix run ../../../../..#cabal2nix -- ./.
+{ mkDerivation, base, lib }:
+mkDerivation {
+  pname = "local";
+  version = "0.1.0.0";
+  src = ./.;
+  isLibrary = false;
+  isExecutable = true;
+  executableHaskellDepends = [ base ];
+  description = "Nixpkgs test case";
+  license = lib.licenses.mit;
+}
diff --git a/nixpkgs/pkgs/test/haskell/cabalSdist/local/local.cabal b/nixpkgs/pkgs/test/haskell/cabalSdist/local/local.cabal
new file mode 100644
index 000000000000..1670aa3af631
--- /dev/null
+++ b/nixpkgs/pkgs/test/haskell/cabalSdist/local/local.cabal
@@ -0,0 +1,13 @@
+cabal-version:      2.4
+name:               local
+version:            0.1.0.0
+
+synopsis: Nixpkgs test case
+license:  MIT
+extra-source-files: CHANGELOG.md
+
+executable local
+    main-is:          Main.hs
+    build-depends:    base
+    hs-source-dirs:   app
+    default-language: Haskell2010
diff --git a/nixpkgs/pkgs/test/haskell/default.nix b/nixpkgs/pkgs/test/haskell/default.nix
new file mode 100644
index 000000000000..8f1f21d65b51
--- /dev/null
+++ b/nixpkgs/pkgs/test/haskell/default.nix
@@ -0,0 +1,10 @@
+{ lib, callPackage }:
+
+lib.recurseIntoAttrs {
+  shellFor = callPackage ./shellFor { };
+  cabalSdist = callPackage ./cabalSdist { };
+  documentationTarball = callPackage ./documentationTarball { };
+  setBuildTarget = callPackage ./setBuildTarget { };
+  incremental = callPackage ./incremental { };
+  upstreamStackHpackVersion = callPackage ./upstreamStackHpackVersion { };
+}
diff --git a/nixpkgs/pkgs/test/haskell/documentationTarball/default.nix b/nixpkgs/pkgs/test/haskell/documentationTarball/default.nix
new file mode 100644
index 000000000000..337510281012
--- /dev/null
+++ b/nixpkgs/pkgs/test/haskell/documentationTarball/default.nix
@@ -0,0 +1,21 @@
+{ pkgs, haskellPackages }:
+
+let
+  drv = haskellPackages.vector;
+  docs = pkgs.haskell.lib.compose.documentationTarball drv;
+
+in pkgs.runCommand "test haskell.lib.compose.documentationTarball" {
+  meta = {
+    inherit (docs.meta) platforms;
+  };
+} ''
+  tar xvzf "${docs}/${drv.name}-docs.tar.gz"
+
+  # Check for Haddock html
+  find "${drv.name}-docs" | grep -q "Data-Vector.html"
+
+  # Check for source html
+  find "${drv.name}-docs" | grep -q  "src/Data.Vector.html"
+
+  touch "$out"
+''
diff --git a/nixpkgs/pkgs/test/haskell/incremental/default.nix b/nixpkgs/pkgs/test/haskell/incremental/default.nix
new file mode 100644
index 000000000000..4509939ba4f4
--- /dev/null
+++ b/nixpkgs/pkgs/test/haskell/incremental/default.nix
@@ -0,0 +1,35 @@
+# Demonstration of incremental builds for Haskell. Useful for speeding up CI.
+#
+# See: https://www.haskellforall.com/2022/12/nixpkgs-support-for-incremental-haskell.html
+# See: https://felixspringer.xyz/homepage/blog/incrementalHaskellBuildsWithNix
+
+{ haskell, lib }:
+
+let
+  inherit (haskell.lib.compose) overrideCabal;
+
+  # Incremental builds work with GHC >=9.4.
+  temporary = haskell.packages.ghc944.temporary;
+
+  # This will do a full build of `temporary`, while writing the intermediate build products
+  # (compiled modules, etc.) to the `intermediates` output.
+  temporary-full-build-with-incremental-output = overrideCabal (drv: {
+    doInstallIntermediates = true;
+    enableSeparateIntermediatesOutput = true;
+  }) temporary;
+
+  # This will do an incremental build of `temporary` by copying the previously
+  # compiled modules and intermediate build products into the source tree
+  # before running the build.
+  #
+  # GHC will then naturally pick up and reuse these products, making this build
+  # complete much more quickly than the previous one.
+  temporary-incremental-build = overrideCabal (drv: {
+    previousIntermediates = temporary-full-build-with-incremental-output.intermediates;
+  }) temporary;
+in
+  temporary-incremental-build.overrideAttrs (old: {
+    meta = {
+      maintainers = lib.teams.mercury.members;
+    };
+  })
diff --git a/nixpkgs/pkgs/test/haskell/setBuildTarget/Bar.hs b/nixpkgs/pkgs/test/haskell/setBuildTarget/Bar.hs
new file mode 100644
index 000000000000..010014082c7d
--- /dev/null
+++ b/nixpkgs/pkgs/test/haskell/setBuildTarget/Bar.hs
@@ -0,0 +1,4 @@
+module Main where
+
+main :: IO ()
+main = putStrLn "Hello, Bar!"
diff --git a/nixpkgs/pkgs/test/haskell/setBuildTarget/Foo.hs b/nixpkgs/pkgs/test/haskell/setBuildTarget/Foo.hs
new file mode 100644
index 000000000000..fec7bb11fe6c
--- /dev/null
+++ b/nixpkgs/pkgs/test/haskell/setBuildTarget/Foo.hs
@@ -0,0 +1,4 @@
+module Main where
+
+main :: IO ()
+main = putStrLn "Hello, Foo!"
diff --git a/nixpkgs/pkgs/test/haskell/setBuildTarget/Setup.hs b/nixpkgs/pkgs/test/haskell/setBuildTarget/Setup.hs
new file mode 100644
index 000000000000..9a994af677b0
--- /dev/null
+++ b/nixpkgs/pkgs/test/haskell/setBuildTarget/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/nixpkgs/pkgs/test/haskell/setBuildTarget/default.nix b/nixpkgs/pkgs/test/haskell/setBuildTarget/default.nix
new file mode 100644
index 000000000000..f0c78c510449
--- /dev/null
+++ b/nixpkgs/pkgs/test/haskell/setBuildTarget/default.nix
@@ -0,0 +1,43 @@
+{ pkgs, haskellPackages }:
+
+let
+  # This can be regenerated by running `cabal2nix .` in the current directory.
+  pkgDef =
+    { mkDerivation, base, lib }:
+      mkDerivation {
+        pname = "haskell-setBuildTarget";
+        version = "0.1.0.0";
+        src = ./.;
+        isLibrary = false;
+        isExecutable = true;
+        executableHaskellDepends = [ base ];
+        license = lib.licenses.bsd3;
+      };
+
+  drv = haskellPackages.callPackage pkgDef {};
+
+  test  = target: excluded:
+    let only = pkgs.haskell.lib.compose.setBuildTarget target drv;
+    in ''
+         if [[ ! -f "${only}/bin/${target}" ]]; then
+           echo "${target} was not built"
+           exit 1
+         fi
+
+         if [[ -f "${only}/bin/${excluded}" ]]; then
+           echo "${excluded} was built, when it should not have been"
+           exit 1
+         fi
+     '';
+
+in
+pkgs.runCommand "test haskell.lib.compose.setBuildTarget" {
+  meta = {
+    inherit (drv.meta) platforms;
+  };
+} ''
+  ${test "foo" "bar"}
+  ${test "bar" "foo"}
+  touch "$out"
+''
+
diff --git a/nixpkgs/pkgs/test/haskell/setBuildTarget/haskell-setBuildTarget.cabal b/nixpkgs/pkgs/test/haskell/setBuildTarget/haskell-setBuildTarget.cabal
new file mode 100644
index 000000000000..7395e139451c
--- /dev/null
+++ b/nixpkgs/pkgs/test/haskell/setBuildTarget/haskell-setBuildTarget.cabal
@@ -0,0 +1,16 @@
+cabal-version:       >=1.10
+name:                haskell-setBuildTarget
+version:             0.1.0.0
+author:              Isaac Shapira
+maintainer:          fresheyeball@protonmail.com
+build-type:          Simple
+
+executable foo
+  main-is:             Foo.hs
+  build-depends:       base
+  default-language:    Haskell2010
+
+executable bar
+  main-is:             Bar.hs
+  build-depends:       base
+  default-language:    Haskell2010
diff --git a/nixpkgs/pkgs/test/haskell/shellFor/default.nix b/nixpkgs/pkgs/test/haskell/shellFor/default.nix
new file mode 100644
index 000000000000..83daf079cc0f
--- /dev/null
+++ b/nixpkgs/pkgs/test/haskell/shellFor/default.nix
@@ -0,0 +1,57 @@
+{ lib, writeText, haskellPackages, cabal-install }:
+
+(haskellPackages.shellFor {
+  packages = p: [ p.constraints p.linear ];
+  # WARNING: When updating this, make sure that the libraries passed to
+  # `extraDependencies` are not actually transitive dependencies of libraries in
+  # `packages` above.  We explicitly want to test that it is possible to specify
+  # `extraDependencies` that are not in the closure of `packages`.
+  extraDependencies = p: { libraryHaskellDepends = [ p.conduit ]; };
+  nativeBuildInputs = [ cabal-install ];
+  phases = [ "unpackPhase" "buildPhase" "installPhase" ];
+  unpackPhase = ''
+    sourceRoot=$(pwd)/scratch
+    mkdir -p "$sourceRoot"
+    cd "$sourceRoot"
+    tar -xf ${haskellPackages.constraints.src}
+    tar -xf ${haskellPackages.linear.src}
+    cp ${writeText "cabal.project" "packages: constraints* linear*"} cabal.project
+  '';
+  buildPhase = ''
+    export HOME=$(mktemp -d)
+    mkdir -p $HOME/.cabal
+    touch $HOME/.cabal/config
+
+    # Check that the extraDependencies.libraryHaskellDepends arg is correctly
+    # picked up. This uses ghci to interpret a small Haskell program that uses
+    # a package from extraDependencies.
+    ghci <<EOF
+    :set -XOverloadedStrings
+    :m + Conduit
+    runResourceT $ connect (yield "done") (sinkFile "outfile")
+    EOF
+
+    if [[ "done" != "$(cat outfile)" ]]; then
+      echo "ERROR: extraDependencies appear not to be available in the environment"
+      exit 1
+    fi
+
+    # Check packages arg
+    cabal v2-build --offline --verbose constraints linear --ghc-options="-O0 -j$NIX_BUILD_CORES"
+  '';
+  installPhase = ''
+    touch $out
+  '';
+}).overrideAttrs (oldAttrs: {
+  meta =
+    let
+      oldMeta = oldAttrs.meta or {};
+      oldMaintainers = oldMeta.maintainers or [];
+      additionalMaintainers = with lib.maintainers; [ cdepillabout ];
+      allMaintainers = oldMaintainers ++ additionalMaintainers;
+    in
+    oldMeta // {
+      maintainers = allMaintainers;
+      inherit (cabal-install.meta) platforms;
+    };
+})
diff --git a/nixpkgs/pkgs/test/haskell/upstreamStackHpackVersion/default.nix b/nixpkgs/pkgs/test/haskell/upstreamStackHpackVersion/default.nix
new file mode 100644
index 000000000000..ddf267702592
--- /dev/null
+++ b/nixpkgs/pkgs/test/haskell/upstreamStackHpackVersion/default.nix
@@ -0,0 +1,151 @@
+
+# This derivation confirms that the version of hpack used by stack in Nixpkgs
+# is the exact same version as the upstream stack release.
+#
+# It is important to make sure the version of hpack used by stack in Nixpkgs
+# matches with the version of hpack used by the upstream stack release.  This
+# is because hpack works slightly differently based on the version, and it can
+# be frustrating to use hpack in a team setting when members are using different
+# versions. See for more info: https://github.com/NixOS/nixpkgs/issues/223390
+#
+# This test is written as a fixed-output derivation, because we need to access
+# accesses the internet to download the upstream stack release.
+
+{ cacert, curl, lib, stack, stdenv }:
+
+let
+  # Find the hpack derivation that is a dependency of stack.  Throw exception
+  # if hpack cannot be found.
+  hpack =
+    lib.findFirst
+      (v: v.pname or "" == "hpack")
+      (throw "could not find stack's hpack dependency")
+      stack.passthru.getCabalDeps.executableHaskellDepends;
+
+  # This is a statically linked version of stack, so it should be usable within
+  # the Nixpkgs builder (at least on x86_64-linux).
+  stackDownloadUrl =
+    "https://github.com/commercialhaskell/stack/releases/download/v${stack.version}/stack-${stack.version}-linux-x86_64-static.tar.gz";
+
+  # This test code has been explicitly pulled out of the derivation below so
+  # that it can be hashed and added to the `name` of the derivation.  This is
+  # so that this test derivation won't be cached if the body of the test is
+  # modified.
+  #
+  # WARNING: When modifying this script, make sure you don't introduce any
+  # paths to the Nix store within it.  We only want this derivation to be re-run
+  # when the stack version (or the version of its hpack dependency) changes in
+  # Nixpkgs.
+  testScript = ''
+    curl=(
+      curl
+      --location
+      --max-redirs 20
+      --retry 3
+      --disable-epsv
+      --cookie-jar cookies
+      --user-agent "curl "
+      --insecure
+    )
+
+    # Fetch the statically-linked upstream Stack binary.
+    "''${curl[@]}" "${stackDownloadUrl}" > ./stack.tar.gz
+    tar xf ./stack.tar.gz
+
+    upstream_stack_version_output="$(./stack-${stack.version}-linux-x86_64-static/stack --version)"
+    echo "upstream \`stack --version\` output: $upstream_stack_version_output"
+
+    nixpkgs_stack_version_output="$(stack --version)"
+    echo "nixpkgs \`stack --version\` output: $nixpkgs_stack_version_output"
+
+    # Confirm that the upstream stack version is the same as the stack version
+    # in Nixpkgs. This check isn't strictly necessary, but it is a good sanity
+    # check.
+
+    if [[ "$upstream_stack_version_output" =~ "Version "([0-9]+((\.[0-9]+)+)) ]]; then
+      upstream_stack_version="''${BASH_REMATCH[1]}"
+
+      echo "parsed upstream stack version: $upstream_stack_version"
+      echo "stack version from nixpkgs: ${stack.version}"
+
+      if [[ "${stack.version}" != "$upstream_stack_version" ]]; then
+        echo "ERROR: stack version in Nixpkgs (${stack.version}) does not match the upstream version for some reason: $upstream_stack_version"
+        exit 1
+      fi
+    else
+      echo "ERROR: Upstream stack version cannot be found in --version output: $upstream_stack_version"
+      exit 1
+    fi
+
+    # Confirm that the hpack version used in the upstream stack release is the
+    # same as the hpack version used by the Nixpkgs stack binary.
+
+    if [[ "$upstream_stack_version_output" =~ hpack-([0-9]+((\.[0-9]+)+)) ]]; then
+      upstream_hpack_version="''${BASH_REMATCH[1]}"
+
+      echo "parsed upstream stack's hpack version: $upstream_hpack_version"
+      echo "Nixpkgs stack's hpack version: ${hpack.version}"
+
+      if [[ "${hpack.version}" != "$upstream_hpack_version" ]]; then
+        echo "ERROR: stack's hpack version in Nixpkgs (${hpack.version}) does not match the upstream stack's hpack version: $upstream_hpack_version"
+        echo "The stack derivation in Nixpkgs needs to be fixed up so that it depends on hpack-$upstream_hpack_version, instead of ${hpack.name}"
+        exit 1
+      fi
+    else
+      echo "ERROR: Upstream stack's hpack version cannot be found in --version output: $upstream_hpack_version"
+      exit 1
+    fi
+
+    # Output a string with a known hash.
+    echo "success" > $out
+  '';
+
+  testScriptHash = builtins.hashString "sha256" testScript;
+in
+
+stdenv.mkDerivation {
+
+  # This name is very important.
+  #
+  # The idea here is that want this derivation to be re-run everytime the
+  # version of stack (or the version of its hpack dependency) changes in
+  # Nixpkgs.  We also want to re-run this derivation whenever the test script
+  # is changed.
+  #
+  # Nix/Hydra will re-run derivations if their name changes (even if they are a
+  # FOD and they have the same hash).
+  #
+  # The name of this derivation contains the stack version string, the hpack
+  # version string, and a hash of the test script.  So Nix will know to
+  # re-run this version when (and only when) one of those values change.
+  name = "upstream-stack-hpack-version-test-${stack.name}-${hpack.name}-${testScriptHash}";
+
+  # This is the sha256 hash for the string "success", which is output upon this
+  # test succeeding.
+  outputHash = "sha256-gbK9TqmMjbZlVPvI12N6GmmhMPMx/rcyt1yqtMSGj9U=";
+  outputHashMode = "flat";
+  outputHashAlgo = "sha256";
+
+  nativeBuildInputs = [ curl stack ];
+
+  impureEnvVars = lib.fetchers.proxyImpureEnvVars;
+
+  buildCommand = ''
+    # Make sure curl can access HTTPS sites, like GitHub.
+    #
+    # Note that we absolutely don't want the Nix store path of the cacert
+    # derivation in the testScript, because we don't want to rebuild this
+    # derivation when only the cacert derivation changes.
+    export SSL_CERT_FILE="${cacert}/etc/ssl/certs/ca-bundle.crt"
+  '' + testScript;
+
+  meta = with lib; {
+    description = "Test that the stack in Nixpkgs uses the same version of Hpack as the upstream stack release";
+    maintainers = with maintainers; [ cdepillabout ];
+
+    # This derivation internally runs a statically-linked version of stack from
+    # upstream.  This statically-linked version of stack is only available for
+    # x86_64-linux, so this test can only be run on x86_64-linux.
+    platforms = [ "x86_64-linux" ];
+  };
+}
diff --git a/nixpkgs/pkgs/test/hooks/default.nix b/nixpkgs/pkgs/test/hooks/default.nix
new file mode 100644
index 000000000000..aabf939b6865
--- /dev/null
+++ b/nixpkgs/pkgs/test/hooks/default.nix
@@ -0,0 +1,8 @@
+# To run these tests:
+# nix-build -A tests.hooks
+
+{ stdenv, tests, lib }:
+
+{
+  default-stdenv-hooks = lib.recurseIntoAttrs tests.stdenv.hooks;
+}
diff --git a/nixpkgs/pkgs/test/install-shell-files/default.nix b/nixpkgs/pkgs/test/install-shell-files/default.nix
new file mode 100644
index 000000000000..aef5acc1de6b
--- /dev/null
+++ b/nixpkgs/pkgs/test/install-shell-files/default.nix
@@ -0,0 +1,125 @@
+{ lib, runCommandLocal, recurseIntoAttrs, installShellFiles }:
+
+let
+  runTest = name: env: buildCommand:
+    runCommandLocal "install-shell-files--${name}" ({
+      nativeBuildInputs = [ installShellFiles ];
+      meta.platforms = lib.platforms.all;
+    } // env) buildCommand;
+in
+
+recurseIntoAttrs {
+  # installManPage
+
+  install-manpage = runTest "install-manpage" {} ''
+    mkdir -p doc
+    echo foo > doc/foo.1
+    echo bar > doc/bar.2.gz
+    echo baz > doc/baz.3
+
+    installManPage doc/*
+
+    cmp doc/foo.1 $out/share/man/man1/foo.1
+    cmp doc/bar.2.gz $out/share/man/man2/bar.2.gz
+    cmp doc/baz.3 $out/share/man/man3/baz.3
+  '';
+  install-manpage-outputs = runTest "install-manpage-outputs" {
+    outputs = [ "out" "man" "devman" ];
+  } ''
+    mkdir -p doc
+    echo foo > doc/foo.1
+    echo bar > doc/bar.3
+
+    installManPage doc/*
+
+    # assert they didn't go into $out
+    [[ ! -f $out/share/man/man1/foo.1 && ! -f $out/share/man/man3/bar.3 ]]
+
+    # foo.1 alone went into man
+    cmp doc/foo.1 ''${!outputMan:?}/share/man/man1/foo.1
+    [[ ! -f ''${!outputMan:?}/share/man/man3/bar.3 ]]
+
+    # bar.3 alone went into devman
+    cmp doc/bar.3 ''${!outputDevman:?}/share/man/man3/bar.3
+    [[ ! -f ''${!outputDevman:?}/share/man/man1/foo.1 ]]
+
+    touch $out
+  '';
+
+  # installShellCompletion
+
+  install-completion = runTest "install-completion" {} ''
+    echo foo > foo
+    echo bar > bar
+    echo baz > baz
+    echo qux > qux.zsh
+    echo quux > quux
+
+    installShellCompletion --bash foo bar --zsh baz qux.zsh --fish quux
+
+    cmp foo $out/share/bash-completion/completions/foo
+    cmp bar $out/share/bash-completion/completions/bar
+    cmp baz $out/share/zsh/site-functions/_baz
+    cmp qux.zsh $out/share/zsh/site-functions/_qux
+    cmp quux $out/share/fish/vendor_completions.d/quux
+  '';
+  install-completion-output = runTest "install-completion-output" {
+    outputs = [ "out" "bin" ];
+  } ''
+    echo foo > foo
+
+    installShellCompletion --bash foo
+
+    # assert it didn't go into $out
+    [[ ! -f $out/share/bash-completion/completions/foo ]]
+
+    cmp foo ''${!outputBin:?}/share/bash-completion/completions/foo
+
+    touch $out
+  '';
+  install-completion-name = runTest "install-completion-name" {} ''
+    echo foo > foo
+    echo bar > bar
+    echo baz > baz
+
+    installShellCompletion --bash --name foobar.bash foo --zsh --name _foobar bar --fish baz
+
+    cmp foo $out/share/bash-completion/completions/foobar.bash
+    cmp bar $out/share/zsh/site-functions/_foobar
+    cmp baz $out/share/fish/vendor_completions.d/baz
+  '';
+  install-completion-inference = runTest "install-completion-inference" {} ''
+    echo foo > foo.bash
+    echo bar > bar.zsh
+    echo baz > baz.fish
+
+    installShellCompletion foo.bash bar.zsh baz.fish
+
+    cmp foo.bash $out/share/bash-completion/completions/foo.bash
+    cmp bar.zsh $out/share/zsh/site-functions/_bar
+    cmp baz.fish $out/share/fish/vendor_completions.d/baz.fish
+  '';
+  install-completion-cmd = runTest "install-completion-cmd" {} ''
+    echo foo > foo.bash
+    echo bar > bar.zsh
+    echo baz > baz.fish
+    echo qux > qux.fish
+
+    installShellCompletion --cmd foobar --bash foo.bash --zsh bar.zsh --fish baz.fish --name qux qux.fish
+
+    cmp foo.bash $out/share/bash-completion/completions/foobar.bash
+    cmp bar.zsh $out/share/zsh/site-functions/_foobar
+    cmp baz.fish $out/share/fish/vendor_completions.d/foobar.fish
+    cmp qux.fish $out/share/fish/vendor_completions.d/qux
+  '';
+  install-completion-fifo = runTest "install-completion-fifo" {} ''
+    installShellCompletion \
+      --bash --name foo.bash <(echo foo) \
+      --zsh --name _foo <(echo bar) \
+      --fish --name foo.fish <(echo baz)
+
+    [[ $(<$out/share/bash-completion/completions/foo.bash) == foo ]] || { echo "foo.bash comparison failed"; exit 1; }
+    [[ $(<$out/share/zsh/site-functions/_foo) == bar ]] || { echo "_foo comparison failed"; exit 1; }
+    [[ $(<$out/share/fish/vendor_completions.d/foo.fish) == baz ]] || { echo "foo.fish comparison failed"; exit 1; }
+  '';
+}
diff --git a/nixpkgs/pkgs/test/kernel.nix b/nixpkgs/pkgs/test/kernel.nix
new file mode 100644
index 000000000000..2ccd188b1edb
--- /dev/null
+++ b/nixpkgs/pkgs/test/kernel.nix
@@ -0,0 +1,73 @@
+# to run these tests:
+# nix-instantiate --eval --strict . -A tests.kernel-config
+#
+# make sure to use NON EXISTING kernel settings else they may conflict with
+# common-config.nix
+{ lib, pkgs }:
+
+with lib;
+with kernel;
+
+let
+  lts_kernel = pkgs.linuxPackages.kernel;
+
+  # to see the result once the module transformed the lose structured config
+  getConfig = structuredConfig:
+    (lts_kernel.override {
+      structuredExtraConfig = structuredConfig;
+    }).configfile.structuredConfig;
+
+  mandatoryVsOptionalConfig = mkMerge [
+    { NIXOS_FAKE_USB_DEBUG = yes;}
+    { NIXOS_FAKE_USB_DEBUG = option yes; }
+  ];
+
+  freeformConfig = mkMerge [
+    { NIXOS_FAKE_MMC_BLOCK_MINORS = freeform "32"; } # same as default, won't trigger any error
+    { NIXOS_FAKE_MMC_BLOCK_MINORS = freeform "64"; } # will trigger an error but the message is not great:
+  ];
+
+  mkDefaultWorksConfig = mkMerge [
+    { "NIXOS_TEST_BOOLEAN"  = yes; }
+    { "NIXOS_TEST_BOOLEAN"  = lib.mkDefault no; }
+  ];
+
+  allOptionalRemainOptional = mkMerge [
+    { NIXOS_FAKE_USB_DEBUG = option yes;}
+    { NIXOS_FAKE_USB_DEBUG = option yes;}
+  ];
+
+in
+runTests {
+  testEasy = {
+    expr = (getConfig { NIXOS_FAKE_USB_DEBUG = yes;}).NIXOS_FAKE_USB_DEBUG;
+    expected = { tristate = "y"; optional = false; freeform = null; };
+  };
+
+  # mandatory flag should win over optional
+  testMandatoryCheck = {
+    expr = (getConfig mandatoryVsOptionalConfig).NIXOS_FAKE_USB_DEBUG.optional;
+    expected = false;
+  };
+
+  testYesWinsOverNo = {
+    expr = (getConfig mkDefaultWorksConfig)."NIXOS_TEST_BOOLEAN".tristate;
+    expected = "y";
+  };
+
+  testAllOptionalRemainOptional = {
+    expr = (getConfig allOptionalRemainOptional)."NIXOS_FAKE_USB_DEBUG".optional;
+    expected = true;
+  };
+
+  # check that freeform options are unique
+  # Should trigger
+  # > The option `settings.NIXOS_FAKE_MMC_BLOCK_MINORS.freeform' has conflicting definitions, in `<unknown-file>' and `<unknown-file>'
+  testTreeform = let
+    res = builtins.tryEval ( (getConfig freeformConfig).NIXOS_FAKE_MMC_BLOCK_MINORS.freeform);
+  in {
+    expr = res.success;
+    expected = false;
+  };
+
+}
diff --git a/nixpkgs/pkgs/test/ld-library-path/default.nix b/nixpkgs/pkgs/test/ld-library-path/default.nix
new file mode 100644
index 000000000000..74c52cef2532
--- /dev/null
+++ b/nixpkgs/pkgs/test/ld-library-path/default.nix
@@ -0,0 +1,88 @@
+{ lib, stdenv }:
+
+# This tests that libraries listed in LD_LIBRARY_PATH take precedence over those listed in RPATH.
+
+let
+  # A simple test library: libgreeting.so which exports a single function getGreeting() returning the good old hello greeting.
+  libgreeting = stdenv.mkDerivation {
+    name = "libgreeting";
+
+    code = ''
+      const char* getGreeting() { return "Hello, world!"; }
+    '';
+
+    unpackPhase = ''
+      echo "$code" > libgreeting.c
+    '';
+
+    installPhase = ''
+      mkdir -p $out/lib
+      $CC -c -fpic libgreeting.c
+      $CC -shared libgreeting.o -o $out/lib/libgreeting.so
+    '';
+  };
+
+  # A variant of libgreeting.so that returns a different message.
+  libgoodbye = libgreeting.overrideAttrs (_: {
+    name = "libgoodbye";
+    code = ''
+      const char* getGreeting() { return "Goodbye, world!"; }
+    '';
+  });
+
+  # A simple consumer of libgreeting.so that just prints the greeting to stdout.
+  testProgram = stdenv.mkDerivation {
+    name = "greeting-test";
+
+    buildInputs = [ libgreeting ];
+
+    code = ''
+      #include <stdio.h>
+
+      extern const char* getGreeting(void);
+
+      int main() {
+        puts(getGreeting());
+      }
+    '';
+
+    unpackPhase = ''
+      echo "$code" > greeting-test.c
+    '';
+
+    installPhase = ''
+      mkdir -p $out/bin
+      $CC -c greeting-test.c
+      $CC greeting-test.o -lgreeting -o $out/bin/greeting-test
+
+      # Now test the installed binaries right after compiling them. In particular,
+      # don't do this in installCheckPhase because fixupPhase has been run by then!
+      (
+        export PATH=$out/bin
+        set -x
+
+        # Verify that our unmodified binary works as expected.
+        [ "$(greeting-test)" = "Hello, world!" ]
+
+        # And finally, test that a library in LD_LIBRARY_PATH takes precedence over the linked-in library.
+        [ "$(LD_LIBRARY_PATH=${libgoodbye}/lib greeting-test)" = "Goodbye, world!" ]
+      )
+    '';
+
+  };
+in stdenv.mkDerivation {
+  name = "test-LD_LIBRARY_PATH";
+  nativeBuildInputs = [ testProgram ];
+
+  buildCommand = ''
+    # And for good measure, repeat the tests again from a separate derivation,
+    # as fixupPhase done by the stdenv can (and has!) affect the result.
+
+    [ "$(greeting-test)" = "Hello, world!" ]
+    [ "$(LD_LIBRARY_PATH=${libgoodbye}/lib greeting-test)" = "Goodbye, world!" ]
+
+    touch $out
+  '';
+
+  meta.platforms = lib.platforms.linux;
+}
diff --git a/nixpkgs/pkgs/test/macos-sierra-shared/default.nix b/nixpkgs/pkgs/test/macos-sierra-shared/default.nix
new file mode 100644
index 000000000000..810d5d97829b
--- /dev/null
+++ b/nixpkgs/pkgs/test/macos-sierra-shared/default.nix
@@ -0,0 +1,90 @@
+{ lib, clangStdenv, clang-sierraHack-stdenv, stdenvNoCC }:
+
+let
+  makeBigExe = stdenv: prefix: rec {
+
+    count = 320;
+
+    sillyLibs = lib.genList (i: stdenv.mkDerivation rec {
+      name = "${prefix}-fluff-${toString i}";
+      unpackPhase = ''
+        src=$PWD
+        cat << 'EOF' > ${name}.c
+        unsigned int asdf_${toString i}(void) {
+          return ${toString i};
+        }
+        EOF
+      '';
+      buildPhase = ''
+        $CC -std=c99 -shared ${name}.c -o lib${name}.dylib -Wl,-install_name,$out/lib/lib${name}.dylib
+      '';
+      installPhase = ''
+        mkdir -p "$out/lib"
+        mv lib${name}.dylib "$out/lib"
+      '';
+      meta.platforms = lib.platforms.darwin;
+    }) count;
+
+    finalExe = stdenv.mkDerivation {
+      name = "${prefix}-final-asdf";
+      unpackPhase = ''
+        src=$PWD
+        cat << 'EOF' > main.cxx
+
+        #include <cstdlib>
+        #include <iostream>
+
+        ${toString (lib.genList (i: "extern \"C\" unsigned int asdf_${toString i}(void); ") count)}
+
+        unsigned int (*funs[])(void) = {
+          ${toString (lib.genList (i: "asdf_${toString i},") count)}
+        };
+
+        int main(int argc, char **argv) {
+          bool ret;
+          unsigned int i = 0;
+          for (auto f : funs) {
+            if (f() != i++) {
+              std::cerr << "Failed to get expected response from function #" << i << std::endl;
+              return EXIT_FAILURE;
+            }
+          }
+          return EXIT_SUCCESS;
+        }
+        EOF
+      '';
+      buildPhase = ''
+        $CXX -std=c++11 main.cxx ${toString (map (x: "-l${x.name}") sillyLibs)} -o ${prefix}-asdf
+      '';
+      buildInputs = sillyLibs;
+      installPhase = ''
+        mkdir -p "$out/bin"
+        mv ${prefix}-asdf "$out/bin"
+      '';
+      meta.platforms = lib.platforms.darwin;
+    };
+
+  };
+
+  good = makeBigExe clang-sierraHack-stdenv "good";
+
+  bad  = makeBigExe clangStdenv             "bad";
+
+in stdenvNoCC.mkDerivation {
+  name = "macos-sierra-shared-test";
+  buildInputs = [ good.finalExe bad.finalExe ];
+  # TODO(@Ericson2314): Be impure or require exact MacOS version of builder?
+  buildCommand = ''
+    if bad-asdf &> /dev/null
+    then echo "WARNING: bad-asdf did not fail, not running on sierra?" >&2
+    else echo "bad-asdf should fail on sierra, OK" >&2
+    fi
+
+    # Must succeed on all supported MacOS versions
+    good-asdf
+    echo "good-asdf should succeed on sierra, OK"
+
+    touch $out
+  '';
+  meta.platforms = lib.platforms.darwin;
+}
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/add-flags.c b/nixpkgs/pkgs/test/make-binary-wrapper/add-flags.c
new file mode 100644
index 000000000000..3ae8678d4421
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/add-flags.c
@@ -0,0 +1,23 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <assert.h>
+
+int main(int argc, char **argv) {
+    char **argv_tmp = calloc(4 + argc + 2 + 1, sizeof(*argv_tmp));
+    assert(argv_tmp != NULL);
+    argv_tmp[0] = argv[0];
+    argv_tmp[1] = "-x";
+    argv_tmp[2] = "-y";
+    argv_tmp[3] = "-z";
+    argv_tmp[4] = "-abc";
+    for (int i = 1; i < argc; ++i) {
+        argv_tmp[4 + i] = argv[i];
+    }
+    argv_tmp[4 + argc + 0] = "-foo";
+    argv_tmp[4 + argc + 1] = "-bar";
+    argv_tmp[4 + argc + 2] = NULL;
+    argv = argv_tmp;
+
+    argv[0] = "/send/me/flags";
+    return execv("/send/me/flags", argv);
+}
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/add-flags.cmdline b/nixpkgs/pkgs/test/make-binary-wrapper/add-flags.cmdline
new file mode 100644
index 000000000000..f42d26f3adf0
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/add-flags.cmdline
@@ -0,0 +1,3 @@
+    --append-flags "-foo -bar" \
+    --add-flags "-x -y -z" \
+    --add-flags -abc
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/add-flags.env b/nixpkgs/pkgs/test/make-binary-wrapper/add-flags.env
new file mode 100644
index 000000000000..3626b8cf97b0
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/add-flags.env
@@ -0,0 +1,8 @@
+CWD=SUBST_CWD
+SUBST_ARGV0
+-x
+-y
+-z
+-abc
+-foo
+-bar
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/argv0.c b/nixpkgs/pkgs/test/make-binary-wrapper/argv0.c
new file mode 100644
index 000000000000..70c36889dc89
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/argv0.c
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv) {
+    argv[0] = "alternative-name";
+    return execv("/send/me/flags", argv);
+}
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/argv0.cmdline b/nixpkgs/pkgs/test/make-binary-wrapper/argv0.cmdline
new file mode 100644
index 000000000000..1cadce8312a4
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/argv0.cmdline
@@ -0,0 +1 @@
+    --argv0 alternative-name
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/argv0.env b/nixpkgs/pkgs/test/make-binary-wrapper/argv0.env
new file mode 100644
index 000000000000..04c13d32ee6d
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/argv0.env
@@ -0,0 +1,2 @@
+CWD=SUBST_CWD
+alternative-name
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/basic.c b/nixpkgs/pkgs/test/make-binary-wrapper/basic.c
new file mode 100644
index 000000000000..1c1266181377
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/basic.c
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv) {
+    argv[0] = "/send/me/flags";
+    return execv("/send/me/flags", argv);
+}
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/basic.cmdline b/nixpkgs/pkgs/test/make-binary-wrapper/basic.cmdline
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/basic.cmdline
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/basic.env b/nixpkgs/pkgs/test/make-binary-wrapper/basic.env
new file mode 100644
index 000000000000..b0da31959447
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/basic.env
@@ -0,0 +1,2 @@
+CWD=SUBST_CWD
+SUBST_ARGV0
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/chdir.c b/nixpkgs/pkgs/test/make-binary-wrapper/chdir.c
new file mode 100644
index 000000000000..9e0b7e2c7f52
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/chdir.c
@@ -0,0 +1,11 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define assert_success(e) do { if ((e) < 0) { perror(#e); abort(); } } while (0)
+
+int main(int argc, char **argv) {
+    assert_success(chdir("./tmp/foo"));
+    argv[0] = "/send/me/flags";
+    return execv("/send/me/flags", argv);
+}
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/chdir.cmdline b/nixpkgs/pkgs/test/make-binary-wrapper/chdir.cmdline
new file mode 100644
index 000000000000..d6ab081e8d35
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/chdir.cmdline
@@ -0,0 +1 @@
+    --chdir ./tmp/foo
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/chdir.env b/nixpkgs/pkgs/test/make-binary-wrapper/chdir.env
new file mode 100644
index 000000000000..ea1c61054e50
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/chdir.env
@@ -0,0 +1,2 @@
+CWD=SUBST_CWD/tmp/foo
+SUBST_ARGV0
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/combination.c b/nixpkgs/pkgs/test/make-binary-wrapper/combination.c
new file mode 100644
index 000000000000..8ce8a4722a0b
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/combination.c
@@ -0,0 +1,53 @@
+#define _GNU_SOURCE         /* See feature_test_macros(7) */
+#include <unistd.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+
+#define assert_success(e) do { if ((e) < 0) { perror(#e); abort(); } } while (0)
+
+void set_env_prefix(char *env, char *sep, char *prefix) {
+    char *existing = getenv(env);
+    if (existing) {
+        char *val;
+        assert_success(asprintf(&val, "%s%s%s", prefix, sep, existing));
+        assert_success(setenv(env, val, 1));
+        free(val);
+    } else {
+        assert_success(setenv(env, prefix, 1));
+    }
+}
+
+void set_env_suffix(char *env, char *sep, char *suffix) {
+    char *existing = getenv(env);
+    if (existing) {
+        char *val;
+        assert_success(asprintf(&val, "%s%s%s", existing, sep, suffix));
+        assert_success(setenv(env, val, 1));
+        free(val);
+    } else {
+        assert_success(setenv(env, suffix, 1));
+    }
+}
+
+int main(int argc, char **argv) {
+    assert_success(setenv("MESSAGE", "HELLO", 0));
+    set_env_prefix("PATH", ":", "/usr/bin/");
+    set_env_suffix("PATH", ":", "/usr/local/bin/");
+    putenv("MESSAGE2=WORLD");
+
+    char **argv_tmp = calloc(3 + argc + 0 + 1, sizeof(*argv_tmp));
+    assert(argv_tmp != NULL);
+    argv_tmp[0] = argv[0];
+    argv_tmp[1] = "-x";
+    argv_tmp[2] = "-y";
+    argv_tmp[3] = "-z";
+    for (int i = 1; i < argc; ++i) {
+        argv_tmp[3 + i] = argv[i];
+    }
+    argv_tmp[3 + argc + 0] = NULL;
+    argv = argv_tmp;
+
+    argv[0] = "my-wrapper";
+    return execv("/send/me/flags", argv);
+}
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/combination.cmdline b/nixpkgs/pkgs/test/make-binary-wrapper/combination.cmdline
new file mode 100644
index 000000000000..fb3861235c8b
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/combination.cmdline
@@ -0,0 +1,6 @@
+    --argv0 my-wrapper \
+    --set-default MESSAGE HELLO \
+    --prefix PATH : /usr/bin/ \
+    --suffix PATH : /usr/local/bin/ \
+    --add-flags "-x -y -z" \
+    --set MESSAGE2 WORLD
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/combination.env b/nixpkgs/pkgs/test/make-binary-wrapper/combination.env
new file mode 100644
index 000000000000..886420c01d1e
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/combination.env
@@ -0,0 +1,8 @@
+MESSAGE=HELLO
+PATH=/usr/bin/:/usr/local/bin/
+MESSAGE2=WORLD
+CWD=SUBST_CWD
+my-wrapper
+-x
+-y
+-z
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/cross.nix b/nixpkgs/pkgs/test/make-binary-wrapper/cross.nix
new file mode 100644
index 000000000000..36758086b92b
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/cross.nix
@@ -0,0 +1,23 @@
+{ stdenv
+, runCommand
+, makeBinaryWrapper
+, binutils
+, expectedArch ? stdenv.hostPlatform.parsed.cpu.name
+}:
+
+runCommand "make-binary-wrapper-test-cross" {
+  nativeBuildInputs = [
+    makeBinaryWrapper
+    binutils
+  ];
+  inherit expectedArch;
+} ''
+  touch prog
+  chmod +x prog
+  makeWrapper prog $out
+  read -r _ arch < <($READELF --file-header $out | grep Machine:)
+  if [[ ''${arch,,} != *"''${expectedArch,,}"* ]]; then
+    echo "expected $expectedArch, got $arch"
+    exit 1
+  fi
+''
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/default.nix b/nixpkgs/pkgs/test/make-binary-wrapper/default.nix
new file mode 100644
index 000000000000..4c6fffd100a7
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/default.nix
@@ -0,0 +1,61 @@
+{ lib
+, stdenv
+, pkgsCross
+, makeBinaryWrapper
+, writeText
+, runCommand
+, runCommandCC
+}:
+
+let
+  env = { nativeBuildInputs = [ makeBinaryWrapper ]; };
+  envCheck = runCommandCC "envcheck" env ''
+    cc -Wall -Werror -Wpedantic -o $out ${./envcheck.c}
+  '';
+  makeGoldenTest = testname: runCommand "make-binary-wrapper-test-${testname}" env ''
+    mkdir -p tmp/foo # for the chdir test
+
+    params=$(<"${./.}/${testname}.cmdline")
+    eval "makeCWrapper /send/me/flags $params" > wrapper.c
+
+    diff wrapper.c "${./.}/${testname}.c"
+
+    if [ -f "${./.}/${testname}.env" ]; then
+      eval "makeWrapper ${envCheck} wrapped $params"
+      env -i ./wrapped > env.txt
+      sed "s#SUBST_ARGV0#${envCheck}#;s#SUBST_CWD#$PWD#" \
+        "${./.}/${testname}.env" > golden-env.txt
+      if ! diff env.txt golden-env.txt; then
+        echo "env/argv should be:"
+        cat golden-env.txt
+        echo "env/argv output is:"
+        cat env.txt
+        exit 1
+      fi
+    else
+      # without a golden env, we expect the wrapper compilation to fail
+      ! eval "makeWrapper ${envCheck} wrapped $params" &> error.txt
+    fi
+
+    cp wrapper.c $out
+  '';
+  tests = lib.genAttrs [
+    "add-flags"
+    "argv0"
+    "basic"
+    "chdir"
+    "combination"
+    "env"
+    "inherit-argv0"
+    "invalid-env"
+    "overlength-strings"
+    "prefix"
+    "suffix"
+  ] makeGoldenTest // lib.optionalAttrs (! stdenv.isDarwin) {
+    cross = pkgsCross.${if stdenv.buildPlatform.isAarch64 then "gnu64" else "aarch64-multiplatform"}.callPackage ./cross.nix { };
+  };
+in
+
+writeText "make-binary-wrapper-tests" ''
+  ${lib.concatStringsSep "\n" (builtins.attrValues tests)}
+'' // tests
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/env.c b/nixpkgs/pkgs/test/make-binary-wrapper/env.c
new file mode 100644
index 000000000000..7e0422dee3bd
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/env.c
@@ -0,0 +1,14 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define assert_success(e) do { if ((e) < 0) { perror(#e); abort(); } } while (0)
+
+int main(int argc, char **argv) {
+    putenv("PART1=HELLO");
+    assert_success(setenv("PART2", "WORLD", 0));
+    assert_success(unsetenv("SOME_OTHER_VARIABLE"));
+    putenv("PART3=\"!!\n\"");
+    argv[0] = "/send/me/flags";
+    return execv("/send/me/flags", argv);
+}
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/env.cmdline b/nixpkgs/pkgs/test/make-binary-wrapper/env.cmdline
new file mode 100644
index 000000000000..3c89f33e2dce
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/env.cmdline
@@ -0,0 +1,4 @@
+    --set PART1 HELLO \
+    --set-default PART2 WORLD \
+    --unset SOME_OTHER_VARIABLE \
+    --set PART3 $'"!!\n"'
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/env.env b/nixpkgs/pkgs/test/make-binary-wrapper/env.env
new file mode 100644
index 000000000000..c7661e165e09
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/env.env
@@ -0,0 +1,6 @@
+PART1=HELLO
+PART2=WORLD
+PART3="!!
+"
+CWD=SUBST_CWD
+SUBST_ARGV0
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/envcheck.c b/nixpkgs/pkgs/test/make-binary-wrapper/envcheck.c
new file mode 100644
index 000000000000..848fbdaa80f2
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/envcheck.c
@@ -0,0 +1,22 @@
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int main(int argc, char **argv, char **envp) {
+  for (char **env = envp; *env != 0; ++env) {
+    puts(*env);
+  }
+
+   char cwd[PATH_MAX];
+   if (getcwd(cwd, sizeof(cwd))) {
+     printf("CWD=%s\n", cwd);
+   } else {
+     perror("getcwd() error");
+     return 1;
+   }
+
+  for (int i=0; i < argc; ++i) {
+    puts(argv[i]);
+  }
+  return 0;
+}
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/inherit-argv0.c b/nixpkgs/pkgs/test/make-binary-wrapper/inherit-argv0.c
new file mode 100644
index 000000000000..e1c2bc926aa7
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/inherit-argv0.c
@@ -0,0 +1,6 @@
+#include <unistd.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv) {
+    return execv("/send/me/flags", argv);
+}
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/inherit-argv0.cmdline b/nixpkgs/pkgs/test/make-binary-wrapper/inherit-argv0.cmdline
new file mode 100644
index 000000000000..088076799835
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/inherit-argv0.cmdline
@@ -0,0 +1 @@
+    --inherit-argv0
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/inherit-argv0.env b/nixpkgs/pkgs/test/make-binary-wrapper/inherit-argv0.env
new file mode 100644
index 000000000000..c46ca95eefbc
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/inherit-argv0.env
@@ -0,0 +1,2 @@
+CWD=SUBST_CWD
+./wrapped
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/invalid-env.c b/nixpkgs/pkgs/test/make-binary-wrapper/invalid-env.c
new file mode 100644
index 000000000000..4dfd36fb68a0
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/invalid-env.c
@@ -0,0 +1,14 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define assert_success(e) do { if ((e) < 0) { perror(#e); abort(); } } while (0)
+
+int main(int argc, char **argv) {
+    putenv("==TEST1");
+    #error Illegal environment variable name `=` (cannot contain `=`)
+    assert_success(setenv("", "TEST2", 0));
+    #error Environment variable name can't be empty.
+    argv[0] = "/send/me/flags";
+    return execv("/send/me/flags", argv);
+}
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/invalid-env.cmdline b/nixpkgs/pkgs/test/make-binary-wrapper/invalid-env.cmdline
new file mode 100644
index 000000000000..a03b001e754e
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/invalid-env.cmdline
@@ -0,0 +1,2 @@
+    --set "=" "TEST1" \
+    --set-default "" "TEST2"
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/overlength-strings.c b/nixpkgs/pkgs/test/make-binary-wrapper/overlength-strings.c
new file mode 100644
index 000000000000..579705d33e94
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/overlength-strings.c
@@ -0,0 +1,25 @@
+#define _GNU_SOURCE         /* See feature_test_macros(7) */
+#include <unistd.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+
+#define assert_success(e) do { if ((e) < 0) { perror(#e); abort(); } } while (0)
+
+void set_env_prefix(char *env, char *sep, char *prefix) {
+    char *existing = getenv(env);
+    if (existing) {
+        char *val;
+        assert_success(asprintf(&val, "%s%s%s", prefix, sep, existing));
+        assert_success(setenv(env, val, 1));
+        free(val);
+    } else {
+        assert_success(setenv(env, prefix, 1));
+    }
+}
+
+int main(int argc, char **argv) {
+    set_env_prefix("PATH", ":", "/nix/store/00000000000000000000000000000000-loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong");
+    argv[0] = "/send/me/flags";
+    return execv("/send/me/flags", argv);
+}
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/overlength-strings.cmdline b/nixpkgs/pkgs/test/make-binary-wrapper/overlength-strings.cmdline
new file mode 100644
index 000000000000..686abbb1cdb9
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/overlength-strings.cmdline
@@ -0,0 +1 @@
+    --prefix PATH : /nix/store/00000000000000000000000000000000-loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/overlength-strings.env b/nixpkgs/pkgs/test/make-binary-wrapper/overlength-strings.env
new file mode 100644
index 000000000000..83a02f5f8343
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/overlength-strings.env
@@ -0,0 +1,3 @@
+PATH=/nix/store/00000000000000000000000000000000-loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong
+CWD=SUBST_CWD
+SUBST_ARGV0
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/prefix.c b/nixpkgs/pkgs/test/make-binary-wrapper/prefix.c
new file mode 100644
index 000000000000..ea8fbdc64a84
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/prefix.c
@@ -0,0 +1,26 @@
+#define _GNU_SOURCE         /* See feature_test_macros(7) */
+#include <unistd.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+
+#define assert_success(e) do { if ((e) < 0) { perror(#e); abort(); } } while (0)
+
+void set_env_prefix(char *env, char *sep, char *prefix) {
+    char *existing = getenv(env);
+    if (existing) {
+        char *val;
+        assert_success(asprintf(&val, "%s%s%s", prefix, sep, existing));
+        assert_success(setenv(env, val, 1));
+        free(val);
+    } else {
+        assert_success(setenv(env, prefix, 1));
+    }
+}
+
+int main(int argc, char **argv) {
+    set_env_prefix("PATH", ":", "/usr/bin/");
+    set_env_prefix("PATH", ":", "/usr/local/bin/");
+    argv[0] = "/send/me/flags";
+    return execv("/send/me/flags", argv);
+}
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/prefix.cmdline b/nixpkgs/pkgs/test/make-binary-wrapper/prefix.cmdline
new file mode 100644
index 000000000000..99cebf9503f4
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/prefix.cmdline
@@ -0,0 +1,2 @@
+    --prefix PATH : /usr/bin/ \
+    --prefix PATH : /usr/local/bin/
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/prefix.env b/nixpkgs/pkgs/test/make-binary-wrapper/prefix.env
new file mode 100644
index 000000000000..033676457c57
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/prefix.env
@@ -0,0 +1,3 @@
+PATH=/usr/local/bin/:/usr/bin/
+CWD=SUBST_CWD
+SUBST_ARGV0
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/suffix.c b/nixpkgs/pkgs/test/make-binary-wrapper/suffix.c
new file mode 100644
index 000000000000..d33f86c070ca
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/suffix.c
@@ -0,0 +1,26 @@
+#define _GNU_SOURCE         /* See feature_test_macros(7) */
+#include <unistd.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+
+#define assert_success(e) do { if ((e) < 0) { perror(#e); abort(); } } while (0)
+
+void set_env_suffix(char *env, char *sep, char *suffix) {
+    char *existing = getenv(env);
+    if (existing) {
+        char *val;
+        assert_success(asprintf(&val, "%s%s%s", existing, sep, suffix));
+        assert_success(setenv(env, val, 1));
+        free(val);
+    } else {
+        assert_success(setenv(env, suffix, 1));
+    }
+}
+
+int main(int argc, char **argv) {
+    set_env_suffix("PATH", ":", "/usr/bin/");
+    set_env_suffix("PATH", ":", "/usr/local/bin/");
+    argv[0] = "/send/me/flags";
+    return execv("/send/me/flags", argv);
+}
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/suffix.cmdline b/nixpkgs/pkgs/test/make-binary-wrapper/suffix.cmdline
new file mode 100644
index 000000000000..95d291f3c169
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/suffix.cmdline
@@ -0,0 +1,2 @@
+    --suffix PATH : /usr/bin/ \
+    --suffix PATH : /usr/local/bin/
diff --git a/nixpkgs/pkgs/test/make-binary-wrapper/suffix.env b/nixpkgs/pkgs/test/make-binary-wrapper/suffix.env
new file mode 100644
index 000000000000..3ce4cc54de41
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-binary-wrapper/suffix.env
@@ -0,0 +1,3 @@
+PATH=/usr/bin/:/usr/local/bin/
+CWD=SUBST_CWD
+SUBST_ARGV0
diff --git a/nixpkgs/pkgs/test/make-hardcode-gsettings-patch/default.nix b/nixpkgs/pkgs/test/make-hardcode-gsettings-patch/default.nix
new file mode 100644
index 000000000000..6c5d2318c6d8
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-hardcode-gsettings-patch/default.nix
@@ -0,0 +1,58 @@
+{ runCommandLocal
+, git
+, clang-tools
+, makeHardcodeGsettingsPatch
+}:
+
+let
+  mkTest =
+    {
+      name,
+      expected,
+      src,
+      schemaIdToVariableMapping,
+    }:
+
+    let
+      patch = makeHardcodeGsettingsPatch {
+        inherit src schemaIdToVariableMapping;
+      };
+    in
+    runCommandLocal
+      "makeHardcodeGsettingsPatch-tests-${name}"
+
+      {
+        nativeBuildInputs = [
+          git
+          clang-tools
+        ];
+      }
+
+      ''
+        cp -r --no-preserve=all "${src}" src
+        cp -r --no-preserve=all "${expected}" src-expected
+
+        pushd src
+        patch < "${patch}"
+        popd
+
+        find src -name '*.c' -print0 | while read -d $'\0' sourceFile; do
+          sourceFile=''${sourceFile#src/}
+          clang-format -style='{BasedOnStyle: InheritParentConfig, ColumnLimit: 240}' -i "src/$sourceFile" "src-expected/$sourceFile"
+          git diff --no-index "src/$sourceFile" "src-expected/$sourceFile" | cat
+        done
+        touch "$out"
+      '';
+in
+{
+  basic = mkTest {
+    name = "basic";
+    src = ./fixtures/example-project;
+    schemaIdToVariableMapping = {
+      "org.gnome.evolution-data-server.addressbook" = "EDS";
+      "org.gnome.evolution.calendar" = "EVO";
+      "org.gnome.seahorse.nautilus.window" = "SEANAUT";
+    };
+    expected = ./fixtures/example-project-patched;
+  };
+}
diff --git a/nixpkgs/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project-patched/main.c b/nixpkgs/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project-patched/main.c
new file mode 100644
index 000000000000..7822a42b840a
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project-patched/main.c
@@ -0,0 +1,85 @@
+#include <gio/gio.h>
+#include <glib-object.h>
+
+void schema_id_literal() {
+  GSettings *settings;
+  {
+    g_autoptr(GSettingsSchemaSource) schema_source;
+    g_autoptr(GSettingsSchema) schema;
+    schema_source = g_settings_schema_source_new_from_directory("@EDS@", g_settings_schema_source_get_default(), TRUE, NULL);
+    schema = g_settings_schema_source_lookup(schema_source, "org.gnome.evolution-data-server.addressbook", FALSE);
+    settings = g_settings_new_full(schema, NULL, NULL);
+  }
+  g_object_unref(settings);
+}
+
+#define SELF_UID_PATH_ID "org.gnome.evolution-data-server.addressbook"
+int schema_id_from_constant() {
+  GSettings *settings;
+  {
+    g_autoptr(GSettingsSchemaSource) schema_source;
+    g_autoptr(GSettingsSchema) schema;
+    schema_source = g_settings_schema_source_new_from_directory("@EDS@", g_settings_schema_source_get_default(), TRUE, NULL);
+    schema = g_settings_schema_source_lookup(schema_source, SELF_UID_PATH_ID, FALSE);
+    settings = g_settings_new_full(schema, NULL, NULL);
+  }
+  g_object_unref(settings);
+}
+
+void schema_id_autoptr() {
+  g_autoptr(GSettings) settings = NULL;
+  {
+    g_autoptr(GSettingsSchemaSource) schema_source;
+    g_autoptr(GSettingsSchema) schema;
+    schema_source = g_settings_schema_source_new_from_directory("@EVO@", g_settings_schema_source_get_default(), TRUE, NULL);
+    schema = g_settings_schema_source_lookup(schema_source, "org.gnome.evolution.calendar", FALSE);
+    settings = g_settings_new_full(schema, NULL, NULL);
+  }
+}
+
+void schema_id_with_backend() {
+  GSettings *settings;
+  {
+    g_autoptr(GSettingsSchemaSource) schema_source;
+    g_autoptr(GSettingsSchema) schema;
+    schema_source = g_settings_schema_source_new_from_directory("@EDS@", g_settings_schema_source_get_default(), TRUE, NULL);
+    schema = g_settings_schema_source_lookup(schema_source, "org.gnome.evolution-data-server.addressbook", FALSE);
+    settings = g_settings_new_full(schema, g_settings_backend_get_default(), NULL);
+  }
+  g_object_unref(settings);
+}
+
+void schema_id_with_backend_and_path() {
+  GSettings *settings;
+  {
+    g_autoptr(GSettingsSchemaSource) schema_source;
+    g_autoptr(GSettingsSchema) schema;
+    schema_source = g_settings_schema_source_new_from_directory("@SEANAUT@", g_settings_schema_source_get_default(), TRUE, NULL);
+    schema = g_settings_schema_source_lookup(schema_source, "org.gnome.seahorse.nautilus.window", FALSE);
+    settings = g_settings_new_full(schema, g_settings_backend_get_default(), "/org/gnome/seahorse/nautilus/windows/123/");
+  }
+  g_object_unref(settings);
+}
+
+void schema_id_with_path() {
+  GSettings *settings;
+  {
+    g_autoptr(GSettingsSchemaSource) schema_source;
+    g_autoptr(GSettingsSchema) schema;
+    schema_source = g_settings_schema_source_new_from_directory("@SEANAUT@", g_settings_schema_source_get_default(), TRUE, NULL);
+    schema = g_settings_schema_source_lookup(schema_source, "org.gnome.seahorse.nautilus.window", FALSE);
+    settings = g_settings_new_full(schema, NULL, "/org/gnome/seahorse/nautilus/windows/123/");
+  }
+  g_object_unref(settings);
+}
+
+int main() {
+  schema_id_literal();
+  schema_id_from_constant();
+  schema_id_autoptr();
+  schema_id_with_backend();
+  schema_id_with_backend_and_path();
+  schema_id_with_path();
+
+  return 0;
+}
diff --git a/nixpkgs/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project/main.c b/nixpkgs/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project/main.c
new file mode 100644
index 000000000000..afcb3686ec84
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project/main.c
@@ -0,0 +1,49 @@
+#include <gio/gio.h>
+#include <glib-object.h>
+
+void schema_id_literal() {
+  GSettings *settings;
+  settings = g_settings_new("org.gnome.evolution-data-server.addressbook");
+  g_object_unref(settings);
+}
+
+#define SELF_UID_PATH_ID "org.gnome.evolution-data-server.addressbook"
+int schema_id_from_constant() {
+  GSettings *settings;
+  settings = g_settings_new(SELF_UID_PATH_ID);
+  g_object_unref(settings);
+}
+
+void schema_id_autoptr() {
+  g_autoptr(GSettings) settings = NULL;
+  settings = g_settings_new("org.gnome.evolution.calendar");
+}
+
+void schema_id_with_backend() {
+  GSettings *settings;
+  settings = g_settings_new_with_backend("org.gnome.evolution-data-server.addressbook", g_settings_backend_get_default());
+  g_object_unref(settings);
+}
+
+void schema_id_with_backend_and_path() {
+  GSettings *settings;
+  settings = g_settings_new_with_backend_and_path("org.gnome.seahorse.nautilus.window", g_settings_backend_get_default(), "/org/gnome/seahorse/nautilus/windows/123/");
+  g_object_unref(settings);
+}
+
+void schema_id_with_path() {
+  GSettings *settings;
+  settings = g_settings_new_with_path("org.gnome.seahorse.nautilus.window", "/org/gnome/seahorse/nautilus/windows/123/");
+  g_object_unref(settings);
+}
+
+int main() {
+  schema_id_literal();
+  schema_id_from_constant();
+  schema_id_autoptr();
+  schema_id_with_backend();
+  schema_id_with_backend_and_path();
+  schema_id_with_path();
+
+  return 0;
+}
diff --git a/nixpkgs/pkgs/test/make-wrapper/default.nix b/nixpkgs/pkgs/test/make-wrapper/default.nix
new file mode 100644
index 000000000000..5cc7cee5a864
--- /dev/null
+++ b/nixpkgs/pkgs/test/make-wrapper/default.nix
@@ -0,0 +1,139 @@
+{ lib
+, writeText
+, writeCBin
+, writeShellScript
+, makeWrapper
+, runCommand
+, which
+, ...
+}:
+
+let
+  # Testfiles
+  foofile = writeText "foofile" "foo";
+  barfile = writeText "barfile" "bar";
+
+  # Wrapped binaries
+  wrappedArgv0 = writeCBin "wrapped-argv0" ''
+    #include <stdio.h>
+    #include <stdlib.h>
+
+    void main(int argc, char** argv) {
+      printf("argv0=%s", argv[0]);
+      exit(0);
+    }
+  '';
+  wrappedBinaryVar = writeShellScript "wrapped-var" ''
+    echo "VAR=$VAR"
+  '';
+  wrappedBinaryArgs = writeShellScript "wrapped-args" ''
+    echo "$@"
+  '';
+
+  mkWrapperBinary = { name, args, wrapped ? wrappedBinaryVar }: runCommand name
+    {
+      nativeBuildInputs = [ makeWrapper ];
+    } ''
+    mkdir -p $out/bin
+    makeWrapper "${wrapped}" "$out/bin/${name}" ${lib.escapeShellArgs args}
+  '';
+
+  mkTest = cmd: toExpect: ''
+    output="$(${cmd})"
+    if [[ "$output" != '${toExpect}' ]]; then
+      echo "test failed: the output of ${cmd} was '$output', expected '${toExpect}'"
+      echo "the wrapper contents:"
+      for i in ${cmd}; do
+        if [[ $i =~ ^test- ]]; then
+          cat $(which $i)
+        fi
+      done
+      exit 1
+    fi
+  '';
+in
+runCommand "make-wrapper-test"
+{
+  nativeBuildInputs = [
+    which
+    (mkWrapperBinary { name = "test-argv0"; args = [ "--argv0" "foo" ]; wrapped = "${wrappedArgv0}/bin/wrapped-argv0"; })
+    (mkWrapperBinary { name = "test-set"; args = [ "--set" "VAR" "abc" ]; })
+    (mkWrapperBinary { name = "test-set-default"; args = [ "--set-default" "VAR" "abc" ]; })
+    (mkWrapperBinary { name = "test-unset"; args = [ "--unset" "VAR" ]; })
+    (mkWrapperBinary { name = "test-run"; args = [ "--run" "echo bar" ]; })
+    (mkWrapperBinary { name = "test-run-and-set"; args = [ "--run" "export VAR=foo" "--set" "VAR" "bar" ]; })
+    (mkWrapperBinary { name = "test-args"; args = [ "--add-flags" "abc" "--append-flags" "xyz" ]; wrapped = wrappedBinaryArgs; })
+    (mkWrapperBinary { name = "test-prefix"; args = [ "--prefix" "VAR" ":" "abc" ]; })
+    (mkWrapperBinary { name = "test-prefix-noglob"; args = [ "--prefix" "VAR" ":" "./*" ]; })
+    (mkWrapperBinary { name = "test-suffix"; args = [ "--suffix" "VAR" ":" "abc" ]; })
+    (mkWrapperBinary { name = "test-prefix-and-suffix"; args = [ "--prefix" "VAR" ":" "foo" "--suffix" "VAR" ":" "bar" ]; })
+    (mkWrapperBinary { name = "test-prefix-multi"; args = [ "--prefix" "VAR" ":" "abc:foo:foo" ]; })
+    (mkWrapperBinary { name = "test-suffix-each"; args = [ "--suffix-each" "VAR" ":" "foo bar:def" ]; })
+    (mkWrapperBinary { name = "test-prefix-each"; args = [ "--prefix-each" "VAR" ":" "foo bar:def" ]; })
+    (mkWrapperBinary { name = "test-suffix-contents"; args = [ "--suffix-contents" "VAR" ":" "${foofile} ${barfile}" ]; })
+    (mkWrapperBinary { name = "test-prefix-contents"; args = [ "--prefix-contents" "VAR" ":" "${foofile} ${barfile}" ]; })
+  ];
+}
+  (
+    # --argv0 works
+    mkTest "test-argv0" "argv0=foo"
+
+    # --set works
+    + mkTest "test-set" "VAR=abc"
+    # --set overwrites the variable
+    + mkTest "VAR=foo test-set" "VAR=abc"
+    # --set-default works
+    + mkTest "test-set-default" "VAR=abc"
+    # --set-default doesn"t overwrite the variable
+    + mkTest "VAR=foo test-set-default" "VAR=foo"
+    # --unset works
+    + mkTest "VAR=foo test-unset" "VAR="
+
+    # --add-flags and --append-flags work
+    + mkTest "test-args" "abc xyz"
+    # given flags are kept
+    + mkTest "test-args foo" "abc foo xyz"
+
+    # --run works
+    + mkTest "test-run" "bar\nVAR="
+    # --run & --set works
+    + mkTest "test-run-and-set" "VAR=bar"
+
+    # --prefix works
+    + mkTest "VAR=foo test-prefix" "VAR=abc:foo"
+    # sets variable if not set yet
+    + mkTest "test-prefix" "VAR=abc"
+    # prepends value only once
+    + mkTest "VAR=abc test-prefix" "VAR=abc"
+    # Moves value to the front if it already existed
+    + mkTest "VAR=foo:abc test-prefix" "VAR=abc:foo"
+    + mkTest "VAR=abc:foo:bar test-prefix-multi" "VAR=abc:foo:bar"
+    # Doesn't overwrite parts of the string
+    + mkTest "VAR=test:abcde:test test-prefix" "VAR=abc:test:abcde:test"
+    # Only append the value once when given multiple times in a parameter
+    # to makeWrapper
+    + mkTest "test-prefix" "VAR=abc"
+    # --prefix doesn't expand globs
+    + mkTest "VAR=f?oo test-prefix-noglob" "VAR=./*:f?oo"
+
+
+    # --suffix works
+    + mkTest "VAR=foo test-suffix" "VAR=foo:abc"
+    # sets variable if not set yet
+    + mkTest "test-suffix" "VAR=abc"
+    # adds the same value only once
+    + mkTest "VAR=abc test-suffix" "VAR=abc"
+    + mkTest "VAR=abc:foo test-suffix" "VAR=abc:foo"
+    # --prefix in combination with --suffix
+    + mkTest "VAR=abc test-prefix-and-suffix" "VAR=foo:abc:bar"
+
+    # --suffix-each works
+    + mkTest "VAR=abc test-suffix-each" "VAR=abc:foo:bar:def"
+    # --prefix-each works
+    + mkTest "VAR=abc test-prefix-each" "VAR=bar:def:foo:abc"
+    # --suffix-contents works
+    + mkTest "VAR=abc test-suffix-contents" "VAR=abc:foo:bar"
+    # --prefix-contents works
+    + mkTest "VAR=abc test-prefix-contents" "VAR=bar:foo:abc"
+    + "touch $out"
+  )
diff --git a/nixpkgs/pkgs/test/nixos-functions/default.nix b/nixpkgs/pkgs/test/nixos-functions/default.nix
new file mode 100644
index 000000000000..bdd5e3c6d8b4
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixos-functions/default.nix
@@ -0,0 +1,31 @@
+/*
+
+This file is a test that makes sure that the `pkgs.nixos` and
+`pkgs.testers.nixosTest` functions work. It's far from a perfect test suite,
+but better than not checking them at all on hydra.
+
+To run this test:
+
+    nixpkgs$ nix-build -A tests.nixos-functions
+
+ */
+{ pkgs, lib, stdenv, ... }:
+
+let
+  dummyVersioning = {
+    revision = "test";
+    versionSuffix = "test";
+    label = "test";
+  };
+in lib.optionalAttrs stdenv.hostPlatform.isLinux (
+  pkgs.recurseIntoAttrs {
+
+    nixos-test = (pkgs.nixos {
+      system.nixos = dummyVersioning;
+      boot.loader.grub.enable = false;
+      fileSystems."/".device = "/dev/null";
+      system.stateVersion = lib.trivial.release;
+    }).toplevel;
+
+  }
+)
diff --git a/nixpkgs/pkgs/test/overriding.nix b/nixpkgs/pkgs/test/overriding.nix
new file mode 100644
index 000000000000..f2519088f138
--- /dev/null
+++ b/nixpkgs/pkgs/test/overriding.nix
@@ -0,0 +1,66 @@
+{ lib, pkgs, stdenvNoCC }:
+
+let
+  tests =
+    let
+      p = pkgs.python3Packages.xpybutil.overridePythonAttrs (_: { dontWrapPythonPrograms = true; });
+    in
+    [
+      ({
+        name = "overridePythonAttrs";
+        expr = !lib.hasInfix "wrapPythonPrograms" p.postFixup;
+        expected = true;
+      })
+      ({
+        name = "repeatedOverrides-pname";
+        expr = repeatedOverrides.pname == "a-better-hello-with-blackjack";
+        expected = true;
+      })
+      ({
+        name = "repeatedOverrides-entangled-pname";
+        expr = repeatedOverrides.entangled.pname == "a-better-figlet-with-blackjack";
+        expected = true;
+      })
+      ({
+        name = "overriding-using-only-attrset";
+        expr = (pkgs.hello.overrideAttrs { pname = "hello-overriden"; }).pname == "hello-overriden";
+        expected = true;
+      })
+      ({
+        name = "overriding-using-only-attrset-no-final-attrs";
+        expr = ((stdenvNoCC.mkDerivation { pname = "hello-no-final-attrs"; }).overrideAttrs { pname = "hello-no-final-attrs-overridden"; }).pname == "hello-no-final-attrs-overridden";
+        expected = true;
+      })
+    ];
+
+  addEntangled = origOverrideAttrs: f:
+    origOverrideAttrs (
+      lib.composeExtensions f (self: super: {
+        passthru = super.passthru // {
+          entangled = super.passthru.entangled.overrideAttrs f;
+          overrideAttrs = addEntangled self.overrideAttrs;
+        };
+      })
+    );
+
+  entangle = pkg1: pkg2: pkg1.overrideAttrs (self: super: {
+    passthru = super.passthru // {
+      entangled = pkg2;
+      overrideAttrs = addEntangled self.overrideAttrs;
+    };
+  });
+
+  example = entangle pkgs.hello pkgs.figlet;
+
+  overrides1 = example.overrideAttrs (_: super: { pname = "a-better-${super.pname}"; });
+
+  repeatedOverrides = overrides1.overrideAttrs (_: super: { pname = "${super.pname}-with-blackjack"; });
+in
+
+stdenvNoCC.mkDerivation {
+  name = "test-overriding";
+  passthru = { inherit tests; };
+  buildCommand = ''
+    touch $out
+  '' + lib.concatMapStringsSep "\n" (t: "([[ ${lib.boolToString t.expr} == ${lib.boolToString t.expected} ]] && echo '${t.name} success') || (echo '${t.name} fail' && exit 1)") tests;
+}
diff --git a/nixpkgs/pkgs/test/php/default.nix b/nixpkgs/pkgs/test/php/default.nix
new file mode 100644
index 000000000000..3c6c8f61b6db
--- /dev/null
+++ b/nixpkgs/pkgs/test/php/default.nix
@@ -0,0 +1,116 @@
+{ lib
+, php
+, runCommand
+}:
+
+let
+  runTest = name: body: runCommand name { } ''
+    testFailed=
+    checking() {
+      echo -n "Checking $1... " > /dev/stderr
+    }
+    ok() {
+      echo ok > /dev/stderr
+    }
+    nok() {
+      echo fail > /dev/stderr
+      testFailed=1
+    }
+
+    ${body}
+
+    if test -n "$testFailed"; then
+      exit 1
+    fi
+
+    touch $out
+  '';
+
+  check = cond: if cond then "ok" else "nok";
+in
+{
+  withExtensions-enables-previously-disabled-extensions = runTest "php-test-withExtensions-enables-previously-disabled-extensions" ''
+    php="${php}"
+
+    checking "that imagick is not present by default"
+    $php/bin/php -r 'exit(extension_loaded("imagick") ? 1 : 0);' && ok || nok
+
+    phpWithImagick="${php.withExtensions ({ all, ... }: [ all.imagick ])}"
+    checking "that imagick extension is present when enabled"
+    $phpWithImagick/bin/php -r 'exit(extension_loaded("imagick") ? 0 : 1);' && ok || nok
+  '';
+
+  overrideAttrs-preserves-enabled-extensions =
+    let
+      customPhp =
+        (php.withExtensions ({ all, ... }: [ all.imagick ])).overrideAttrs (attrs: {
+          postInstall = attrs.postInstall or "" + ''
+            touch "$out/oApee-was-here"
+          '';
+        });
+    in
+    runTest "php-test-overrideAttrs-preserves-enabled-extensions" ''
+      php="${customPhp}"
+      phpUnwrapped="${customPhp.unwrapped}"
+
+      checking "if overrides took hold"
+      test -f "$phpUnwrapped/oApee-was-here" && ok || nok
+
+      checking "if imagick extension is still present"
+      $php/bin/php -r 'exit(extension_loaded("imagick") ? 0 : 1);' && ok || nok
+
+      checking "if imagick extension is linked against the overridden PHP"
+      echo $php
+      $php/bin/php -r 'exit(extension_loaded("imagick") ? 0 : 1);' && ok || nok
+    '';
+
+  unwrapped-overrideAttrs-stacks =
+    let
+      customPhp =
+        lib.pipe php.unwrapped [
+          (pkg: pkg.overrideAttrs (attrs: {
+            postInstall = attrs.postInstall or "" + ''
+              touch "$out/oAs-first"
+            '';
+          }))
+
+          (pkg: pkg.overrideAttrs (attrs: {
+            postInstall = attrs.postInstall or "" + ''
+              touch "$out/oAs-second"
+            '';
+          }))
+        ];
+    in
+    runTest "php-test-unwrapped-overrideAttrs-stacks" ''
+      checking "if first override remained"
+      ${check (builtins.match ".*oAs-first.*" customPhp.postInstall != null)}
+
+      checking "if second override is there"
+      ${check (builtins.match ".*oAs-second.*" customPhp.postInstall != null)}
+    '';
+
+  wrapped-overrideAttrs-stacks =
+    let
+      customPhp =
+        lib.pipe php [
+          (pkg: pkg.overrideAttrs (attrs: {
+            postInstall = attrs.postInstall or "" + ''
+              touch "$out/oAs-first"
+            '';
+          }))
+
+          (pkg: pkg.overrideAttrs (attrs: {
+            postInstall = attrs.postInstall or "" + ''
+              touch "$out/oAs-second"
+            '';
+          }))
+        ];
+    in
+    runTest "php-test-wrapped-overrideAttrs-stacks" ''
+      checking "if first override remained"
+      ${check (builtins.match ".*oAs-first.*" customPhp.unwrapped.postInstall != null)}
+
+      checking "if second override is there"
+      ${check (builtins.match ".*oAs-second.*" customPhp.unwrapped.postInstall != null)}
+    '';
+}
diff --git a/nixpkgs/pkgs/test/simple/builder.sh b/nixpkgs/pkgs/test/simple/builder.sh
new file mode 100644
index 000000000000..908faec3c388
--- /dev/null
+++ b/nixpkgs/pkgs/test/simple/builder.sh
@@ -0,0 +1,43 @@
+if [ -e .attrs.sh ]; then source .attrs.sh; fi
+set -x
+
+export NIX_DEBUG=1
+
+source $stdenv/setup
+
+export NIX_ENFORCE_PURITY=1
+
+mkdir $out
+mkdir $out/bin
+
+cat > hello.c <<EOF
+#include <stdio.h>
+
+int main(int argc, char * * argv)
+{
+    printf("Hello World!\n");
+    return 0;
+}
+EOF
+
+#gcc -I/nix/store/foo -I /nix/store/foo -I/usr/lib -I /usr/lib hello.c -o $out/bin/hello
+gcc -I`pwd` -L /nix/store/abcd/lib -isystem /usr/lib hello.c -o $out/bin/hello
+
+$out/bin/hello
+
+cat > hello2.cc <<EOF
+#include <iostream>
+
+int main(int argc, char * * argv)
+{
+    std::cout << "Hello World!\n";
+    std::cout << VALUE << std::endl;
+    return 0;
+}
+EOF
+
+g++ hello2.cc -o $out/bin/hello2 -DVALUE="1 + 2 * 3"
+
+$out/bin/hello2
+
+ld -v
diff --git a/nixpkgs/pkgs/test/stdenv-inputs/bar.c b/nixpkgs/pkgs/test/stdenv-inputs/bar.c
new file mode 100644
index 000000000000..2d7299c2d462
--- /dev/null
+++ b/nixpkgs/pkgs/test/stdenv-inputs/bar.c
@@ -0,0 +1,3 @@
+unsigned int bar(void) {
+  return 42;
+}
diff --git a/nixpkgs/pkgs/test/stdenv-inputs/cc-main.c b/nixpkgs/pkgs/test/stdenv-inputs/cc-main.c
new file mode 100644
index 000000000000..06f28bc33c69
--- /dev/null
+++ b/nixpkgs/pkgs/test/stdenv-inputs/cc-main.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+  fprintf(stderr, "ok\n");
+  return 0;
+}
diff --git a/nixpkgs/pkgs/test/stdenv-inputs/default.nix b/nixpkgs/pkgs/test/stdenv-inputs/default.nix
new file mode 100644
index 000000000000..6a2e441d0191
--- /dev/null
+++ b/nixpkgs/pkgs/test/stdenv-inputs/default.nix
@@ -0,0 +1,68 @@
+{ lib, stdenv }:
+
+let
+  foo = stdenv.mkDerivation {
+    name = "foo-test";
+
+    dontUnpack = true;
+
+    installPhase = ''
+      mkdir -p $out/bin $out/include $out/lib
+      $CC -o $out/bin/foo ${./cc-main.c}
+      chmod +x $out/bin/foo
+      cp ${./foo.c} $out/include/foo.h
+      $CC -shared \
+        ${lib.optionalString stdenv.isDarwin "-Wl,-install_name,$out/lib/libfoo.dylib"} \
+        -o $out/lib/libfoo${stdenv.hostPlatform.extensions.sharedLibrary} \
+        ${./foo.c}
+    '';
+  };
+
+  bar = stdenv.mkDerivation {
+    name = "bar-test";
+    outputs = [ "out" "dev" ];
+
+    dontUnpack = true;
+
+    installPhase = ''
+      mkdir -p $out/bin $dev/include $dev/lib
+      $CC -o $out/bin/bar ${./cc-main.c}
+      chmod +x $out/bin/bar
+      cp ${./bar.c} $dev/include/bar.h
+      $CC -shared \
+        ${lib.optionalString stdenv.isDarwin "-Wl,-install_name,$dev/lib/libbar.dylib"} \
+        -o $dev/lib/libbar${stdenv.hostPlatform.extensions.sharedLibrary} \
+        ${./bar.c}
+    '';
+  };
+in
+
+stdenv.mkDerivation {
+  name = "stdenv-inputs-test";
+  phases = [ "buildPhase" ];
+
+  buildInputs = [ foo bar ];
+
+  buildPhase = ''
+    env
+
+    printf "checking whether binaries are available... " >&2
+    foo && bar
+
+    printf "checking whether compiler can find headers... " >&2
+    $CC -o include-check ${./include-main.c}
+    ./include-check
+
+    printf "checking whether compiler can find headers... " >&2
+    $CC -o include-check ${./include-main.c}
+    ./include-check
+
+    printf "checking whether compiler can find libraries... " >&2
+    $CC -lfoo -lbar -o lib-check ${./lib-main.c}
+    ./lib-check
+
+    touch $out
+  '';
+
+  meta.platforms = lib.platforms.all;
+}
diff --git a/nixpkgs/pkgs/test/stdenv-inputs/foo.c b/nixpkgs/pkgs/test/stdenv-inputs/foo.c
new file mode 100644
index 000000000000..0253a26d5d2c
--- /dev/null
+++ b/nixpkgs/pkgs/test/stdenv-inputs/foo.c
@@ -0,0 +1,3 @@
+unsigned int foo(void) {
+  return 42;
+}
diff --git a/nixpkgs/pkgs/test/stdenv-inputs/include-main.c b/nixpkgs/pkgs/test/stdenv-inputs/include-main.c
new file mode 100644
index 000000000000..35e5ee0d90f7
--- /dev/null
+++ b/nixpkgs/pkgs/test/stdenv-inputs/include-main.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <foo.h>
+#include <bar.h>
+
+int main(int argc, char **argv)
+{
+  if (foo() != 42)
+    return 1;
+  if (bar() != 42)
+    return 1;
+  fprintf(stderr, "ok\n");
+  return 0;
+}
diff --git a/nixpkgs/pkgs/test/stdenv-inputs/lib-main.c b/nixpkgs/pkgs/test/stdenv-inputs/lib-main.c
new file mode 100644
index 000000000000..c9488fe43e55
--- /dev/null
+++ b/nixpkgs/pkgs/test/stdenv-inputs/lib-main.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+extern unsigned int foo(void);
+extern unsigned int bar(void);
+
+int main(int argc, char **argv)
+{
+  if (foo() != 42)
+    return 1;
+  if (bar() != 42)
+    return 1;
+  fprintf(stderr, "ok\n");
+  return 0;
+}
diff --git a/nixpkgs/pkgs/test/stdenv/default.nix b/nixpkgs/pkgs/test/stdenv/default.nix
new file mode 100644
index 000000000000..0fa87cccc219
--- /dev/null
+++ b/nixpkgs/pkgs/test/stdenv/default.nix
@@ -0,0 +1,293 @@
+# To run these tests:
+# nix-build -A tests.stdenv
+
+{ stdenv
+, pkgs
+, lib
+, testers
+}:
+
+let
+  # early enough not to rebuild gcc but late enough to have patchelf
+  earlyPkgs = stdenv.__bootPackages.stdenv.__bootPackages;
+  earlierPkgs = stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages;
+  # use a early stdenv so when hacking on stdenv this test can be run quickly
+  bootStdenv = stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv;
+  pkgsStructured = import pkgs.path { config = { structuredAttrsByDefault = true; }; inherit (stdenv.hostPlatform) system; };
+  bootStdenvStructuredAttrsByDefault = pkgsStructured.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv;
+
+  runCommand = earlierPkgs.runCommand;
+
+
+  ccWrapperSubstitutionsTest = { name, stdenv', extraAttrs ? { } }:
+
+    stdenv'.cc.overrideAttrs (previousAttrs: ({
+      inherit name;
+
+      postFixup = previousAttrs.postFixup + ''
+        declare -p wrapperName
+        echo "env.wrapperName = $wrapperName"
+        [[ $wrapperName == "CC_WRAPPER" ]] || (echo "'\$wrapperName' was not 'CC_WRAPPER'" && false)
+        declare -p suffixSalt
+        echo "env.suffixSalt = $suffixSalt"
+        [[ $suffixSalt == "${stdenv'.cc.suffixSalt}" ]] || (echo "'\$suffxSalt' was not '${stdenv'.cc.suffixSalt}'" && false)
+
+        grep -q "@out@" $out/bin/cc || echo "@out@ in $out/bin/cc was substituted"
+        grep -q "@suffixSalt@" $out/bin/cc && (echo "$out/bin/cc contains unsubstituted variables" && false)
+
+        touch $out
+      '';
+    } // extraAttrs));
+
+  testEnvAttrset = { name, stdenv', extraAttrs ? { } }:
+    stdenv'.mkDerivation
+      ({
+        inherit name;
+        env = {
+          string = "testing-string";
+        };
+
+        passAsFile = [ "buildCommand" ];
+        buildCommand = ''
+          declare -p string
+          echo "env.string = $string"
+          [[ $string == "testing-string" ]] || (echo "'\$string' was not 'testing-string'" && false)
+          [[ "$(declare -p string)" == 'declare -x string="testing-string"' ]] || (echo "'\$string' was not exported" && false)
+          touch $out
+        '';
+      } // extraAttrs);
+
+  testPrependAndAppendToVar = { name, stdenv', extraAttrs ? { } }:
+    stdenv'.mkDerivation
+      ({
+        inherit name;
+        env = {
+          string = "testing-string";
+        };
+
+        passAsFile = [ "buildCommand" ] ++ lib.optionals (extraAttrs ? extraTest) [ "extraTest" ];
+        buildCommand = ''
+          declare -p string
+          appendToVar string hello
+          # test that quoted strings work
+          prependToVar string "world"
+          declare -p string
+
+          declare -A associativeArray=(["X"]="Y")
+          [[ $(appendToVar associativeArray "fail" 2>&1) =~ "trying to use" ]] || (echo "prependToVar did not catch prepending associativeArray" && false)
+          [[ $(prependToVar associativeArray "fail" 2>&1) =~ "trying to use" ]] || (echo "prependToVar did not catch prepending associativeArray" && false)
+
+          [[ $string == "world testing-string hello" ]] || (echo "'\$string' was not 'world testing-string hello'" && false)
+
+          # test appending to a unset variable
+          appendToVar nonExistant created hello
+          typeset -p nonExistant
+          if [[ -n $__structuredAttrs ]]; then
+            [[ "''${nonExistant[@]}" == "created hello" ]]
+          else
+            # there's a extra " " in front here and a extra " " in the end of prependToVar
+            # shouldn't matter because these functions will mostly be used for $*Flags and the Flag variable will in most cases already exit
+            [[ "$nonExistant" == " created hello" ]]
+          fi
+
+          eval "$extraTest"
+
+          touch $out
+        '';
+      } // extraAttrs);
+
+in
+
+{
+  # tests for hooks in `stdenv.defaultNativeBuildInputs`
+  hooks = lib.recurseIntoAttrs (import ./hooks.nix { stdenv = bootStdenv; pkgs = earlyPkgs; inherit lib; });
+
+  outputs-no-out = runCommand "outputs-no-out-assert" {
+    result = earlierPkgs.testers.testBuildFailure (bootStdenv.mkDerivation {
+      NIX_DEBUG = 1;
+      name = "outputs-no-out";
+      outputs = ["foo"];
+      buildPhase = ":";
+      installPhase = ''
+        touch $foo
+      '';
+    });
+
+    # Assumption: the first output* variable to be configured is
+    #   _overrideFirst outputDev "dev" "out"
+    expectedMsg = "error: _assignFirst: could not find a non-empty variable whose name to assign to outputDev.\n       The following variables were all unset or empty:\n           dev out";
+  } ''
+    grep -F "$expectedMsg" $result/testBuildFailure.log >/dev/null
+    touch $out
+  '';
+
+  test-env-attrset = testEnvAttrset { name = "test-env-attrset"; stdenv' = bootStdenv; };
+
+  # Test compatibility with derivations using `env` as a regular variable.
+  test-env-derivation = bootStdenv.mkDerivation rec {
+    name = "test-env-derivation";
+    env = bootStdenv.mkDerivation {
+      name = "foo";
+      buildCommand = ''
+        mkdir "$out"
+        touch "$out/bar"
+      '';
+    };
+
+    passAsFile = [ "buildCommand" ];
+    buildCommand = ''
+      declare -p env
+      [[ $env == "${env}" ]]
+      touch "$out"
+    '';
+  };
+
+  test-inputDerivation = let
+    inherit (stdenv.mkDerivation {
+      dep1 = derivation { name = "dep1"; builder = "/bin/sh"; args = [ "-c" ": > $out" ]; system = builtins.currentSystem; };
+      dep2 = derivation { name = "dep2"; builder = "/bin/sh"; args = [ "-c" ": > $out" ]; system = builtins.currentSystem; };
+      passAsFile = [ "dep2" ];
+    }) inputDerivation;
+  in
+    runCommand "test-inputDerivation" {
+      exportReferencesGraph = [ "graph" inputDerivation ];
+    } ''
+      grep ${inputDerivation.dep1} graph
+      grep ${inputDerivation.dep2} graph
+      touch $out
+    '';
+
+  test-prepend-append-to-var = testPrependAndAppendToVar {
+    name = "test-prepend-append-to-var";
+    stdenv' = bootStdenv;
+  };
+
+  test-structured-env-attrset = testEnvAttrset {
+    name = "test-structured-env-attrset";
+    stdenv' = bootStdenv;
+    extraAttrs = { __structuredAttrs = true; };
+  };
+
+  test-cc-wrapper-substitutions = ccWrapperSubstitutionsTest {
+    name = "test-cc-wrapper-substitutions";
+    stdenv' = bootStdenv;
+  };
+
+  structuredAttrsByDefault = lib.recurseIntoAttrs {
+
+    hooks = lib.recurseIntoAttrs (import ./hooks.nix { stdenv = bootStdenvStructuredAttrsByDefault; pkgs = earlyPkgs; inherit lib; });
+
+    test-cc-wrapper-substitutions = ccWrapperSubstitutionsTest {
+      name = "test-cc-wrapper-substitutions-structuredAttrsByDefault";
+      stdenv' = bootStdenvStructuredAttrsByDefault;
+    };
+
+    test-structured-env-attrset = testEnvAttrset {
+      name = "test-structured-env-attrset-structuredAttrsByDefault";
+      stdenv' = bootStdenvStructuredAttrsByDefault;
+    };
+
+    test-prepend-append-to-var = testPrependAndAppendToVar {
+      name = "test-prepend-append-to-var-structuredAttrsByDefault";
+      stdenv' = bootStdenvStructuredAttrsByDefault;
+      extraAttrs = {
+        # will be a bash indexed array in attrs.sh
+        # declare -a list=('a' 'b' )
+        # and a json array in attrs.json
+        # "list":["a","b"]
+        list = [ "a" "b" ];
+        # will be a bash associative array(dictionary) in attrs.sh
+        # declare -A array=(['a']='1' ['b']='2' )
+        # and a json object in attrs.json
+        # {"array":{"a":"1","b":"2"}
+        array = { a = "1"; b = "2"; };
+        extraTest = ''
+          declare -p array
+          array+=(["c"]="3")
+          declare -p array
+
+          [[ "''${array[c]}" == "3" ]] || (echo "c element of '\$array' was not '3'" && false)
+
+          declare -p list
+          prependToVar list hello
+          # test that quoted strings work
+          appendToVar list "world"
+          declare -p list
+
+          [[ "''${list[0]}" == "hello" ]] || (echo "first element of '\$list' was not 'hello'" && false)
+          [[ "''${list[1]}" == "a" ]] || (echo "first element of '\$list' was not 'a'" && false)
+          [[ "''${list[-1]}" == "world" ]] || (echo "last element of '\$list' was not 'world'" && false)
+        '';
+      };
+    };
+
+    test-golden-example-structuredAttrs =
+      let
+        goldenSh = earlyPkgs.writeText "goldenSh" ''
+          declare -A EXAMPLE_ATTRS=(['foo']='bar' )
+          declare EXAMPLE_BOOL_FALSE=
+          declare EXAMPLE_BOOL_TRUE=1
+          declare EXAMPLE_INT=123
+          declare EXAMPLE_INT_NEG=-123
+          declare -a EXAMPLE_LIST=('foo' 'bar' )
+          declare EXAMPLE_STR='foo bar'
+        '';
+        goldenJson = earlyPkgs.writeText "goldenSh" ''
+          {
+            "EXAMPLE_ATTRS": {
+              "foo": "bar"
+            },
+            "EXAMPLE_BOOL_FALSE": false,
+            "EXAMPLE_BOOL_TRUE": true,
+            "EXAMPLE_INT": 123,
+            "EXAMPLE_INT_NEG": -123,
+            "EXAMPLE_LIST": [
+              "foo",
+              "bar"
+            ],
+            "EXAMPLE_NESTED_ATTRS": {
+              "foo": {
+                "bar": "baz"
+              }
+            },
+            "EXAMPLE_NESTED_LIST": [
+              [
+                "foo",
+                "bar"
+              ],
+              [
+                "baz"
+              ]
+            ],
+            "EXAMPLE_STR": "foo bar"
+          }
+        '';
+      in
+      bootStdenvStructuredAttrsByDefault.mkDerivation {
+        name = "test-golden-example-structuredAttrsByDefault";
+        nativeBuildInputs = [ earlyPkgs.jq ];
+
+        EXAMPLE_BOOL_TRUE = true;
+        EXAMPLE_BOOL_FALSE = false;
+        EXAMPLE_INT = 123;
+        EXAMPLE_INT_NEG = -123;
+        EXAMPLE_STR = "foo bar";
+        EXAMPLE_LIST = [ "foo" "bar" ];
+        EXAMPLE_NESTED_LIST = [ [ "foo" "bar" ] [ "baz" ] ];
+        EXAMPLE_ATTRS = { foo = "bar"; };
+        EXAMPLE_NESTED_ATTRS = { foo.bar = "baz"; };
+
+        inherit goldenSh;
+        inherit goldenJson;
+
+        buildCommand = ''
+          mkdir -p $out
+          cat $NIX_ATTRS_SH_FILE | grep "EXAMPLE" | grep -v -E 'installPhase|jq' > $out/sh
+          jq 'with_entries(select(.key|match("EXAMPLE")))' $NIX_ATTRS_JSON_FILE > $out/json
+          diff $out/sh $goldenSh
+          diff $out/json $goldenJson
+        '';
+      };
+
+  };
+}
diff --git a/nixpkgs/pkgs/test/stdenv/gcc-stageCompare.nix b/nixpkgs/pkgs/test/stdenv/gcc-stageCompare.nix
new file mode 100644
index 000000000000..e5c2ed5921b3
--- /dev/null
+++ b/nixpkgs/pkgs/test/stdenv/gcc-stageCompare.nix
@@ -0,0 +1,32 @@
+# This test *must* be run prior to releasing any build of either stdenv or the
+# gcc that it exports!  This check should also be part of CI for any PR that
+# causes a rebuild of `stdenv.cc`.
+#
+# When we used gcc's internal bootstrap it did this check as part of (and
+# serially with) the gcc derivation.  Now that we bootstrap externally this
+# check can be done in parallel with any/all of stdenv's referrers.  But we
+# must remember to do the check.
+#
+
+{ stdenv
+, pkgs
+, lib
+}:
+
+assert stdenv.cc.isGNU;
+with pkgs;
+# rebuild gcc using the "final" stdenv
+let gcc-stageCompare = (gcc-unwrapped.override {
+      reproducibleBuild = true;
+      profiledCompiler = false;
+      stdenv = overrideCC stdenv (wrapCCWith {
+        cc = stdenv.cc;
+      });
+    }).overrideAttrs(_: {
+      NIX_OUTPATH_USED_AS_RANDOM_SEED = stdenv.cc.cc.out;
+    });
+in (runCommand "gcc-stageCompare" {} ''
+  diff -sr ${pkgs.gcc-unwrapped.checksum}/checksums ${gcc-stageCompare.checksum}/checksums && touch $out
+'').overrideAttrs (a: {
+  meta = (a.meta or { }) // { platforms = lib.platforms.linux; };
+})
diff --git a/nixpkgs/pkgs/test/stdenv/hooks.nix b/nixpkgs/pkgs/test/stdenv/hooks.nix
new file mode 100644
index 000000000000..eb1b3f61bda6
--- /dev/null
+++ b/nixpkgs/pkgs/test/stdenv/hooks.nix
@@ -0,0 +1,136 @@
+{ stdenv, pkgs, lib }:
+
+# ordering should match defaultNativeBuildInputs
+
+{
+  # TODO: add audit-tmpdir
+  compress-man-pages =
+    let
+      manFile = pkgs.writeText "small-man" ''
+        .TH HELLO "1" "May 2022" "hello 2.12.1" "User Commands"
+        .SH NAME
+        hello - friendly greeting program
+      '';
+    in
+    stdenv.mkDerivation {
+      name = "test-compress-man-pages";
+      buildCommand = ''
+        mkdir -p $out/share/man
+        cp ${manFile} $out/share/man/small-man.1
+        compressManPages $out
+        [[ -e $out/share/man/small-man.1.gz ]]
+      '';
+    };
+  make-symlinks-relative = stdenv.mkDerivation {
+    name = "test-make-symlinks-relative";
+    outputs = [ "out" "man" ];
+    buildCommand = ''
+      mkdir -p $out/{bar,baz}
+      mkdir -p $man/share/{x,y}
+      source1="$out/bar/foo"
+      destination1="$out/baz/foo"
+      source2="$man/share/x/file1"
+      destination2="$man/share/y/file2"
+      echo foo > $source1
+      echo foo > $source2
+      ln -s $source1 $destination1
+      ln -s $source2 $destination2
+      echo "symlink before patching: $(readlink $destination1)"
+      echo "symlink before patching: $(readlink $destination2)"
+
+      _makeSymlinksRelativeInAllOutputs
+
+      echo "symlink after patching: $(readlink $destination1)"
+      ([[ -e $destination1 ]] && echo "symlink isn't broken") || (echo "symlink is broken" && exit 1)
+      ([[ $(readlink $destination1) == "../bar/foo" ]] && echo "absolute symlink was made relative") || (echo "symlink was not made relative" && exit 1)
+      echo "symlink after patching: $(readlink $destination2)"
+      ([[ -e $destination2 ]] && echo "symlink isn't broken") || (echo "symlink is broken" && exit 1)
+      ([[ $(readlink $destination2) == "../x/file1" ]] && echo "absolute symlink was made relative") || (echo "symlink was not made relative" && exit 1)
+    '';
+  };
+  move-docs = stdenv.mkDerivation {
+    name = "test-move-docs";
+    buildCommand = ''
+      mkdir -p $out/{man,doc,info}
+      touch $out/{man,doc,info}/foo
+      cat $out/{man,doc,info}/foo
+
+      _moveToShare
+
+      (cat $out/share/{man,doc,info}/foo 2>/dev/null && echo "man,doc,info were moved") || (echo "man,doc,info were not moved" && exit 1)
+    '';
+  };
+  move-lib64 = stdenv.mkDerivation {
+    name = "test-move-lib64";
+    buildCommand = ''
+      mkdir -p $out/lib64
+      touch $out/lib64/foo
+      cat $out/lib64/foo
+
+      _moveLib64
+
+      # check symlink
+      [[ -h $out/lib64 ]]
+      ([[ -e $out/lib64 ]] && echo "symlink isn't broken") || (echo "symlink is broken" && exit 1)
+      [[ -e $out/lib/foo ]]
+    '';
+  };
+  move-sbin = stdenv.mkDerivation {
+    name = "test-move-sbin";
+    buildCommand = ''
+      mkdir -p $out/sbin
+      touch $out/sbin/foo
+      cat $out/sbin/foo
+
+      _moveSbin
+
+      # check symlink
+      [[ -h $out/sbin ]]
+      ([[ -e $out/sbin ]] && echo "symlink isn't broken") || (echo "symlink is broken" && exit 1)
+      [[ -e $out/bin/foo ]]
+    '';
+  };
+  # TODO: add multiple-outputs
+  patch-shebangs = import ./patch-shebangs.nix { inherit stdenv lib pkgs; };
+  prune-libtool-files =
+    let
+      libFoo = pkgs.writeText "libFoo" ''
+        # Generated by libtool (GNU libtool) 2.4.6
+        old_library='''
+        dependency_libs=' -Lbar.la -Lbaz.la'
+      '';
+    in
+    stdenv.mkDerivation {
+      name = "test-prune-libtool-files";
+      buildCommand = ''
+        mkdir -p $out/lib
+        cp ${libFoo} $out/lib/libFoo.la
+        _pruneLibtoolFiles
+        grep "^dependency_libs=''' #pruned" $out/lib/libFoo.la
+        # confirm file doesn't only contain the above
+        grep "^old_library='''" $out/lib/libFoo.la
+      '';
+    };
+  reproducible-builds = stdenv.mkDerivation {
+    name = "test-reproducible-builds";
+    buildCommand = ''
+      # can't be tested more precisely because the value of random-seed changes depending on the output
+      [[ $NIX_CFLAGS_COMPILE =~ "-frandom-seed=" ]]
+      touch $out
+    '';
+  };
+  set-source-date-epoch-to-latest = stdenv.mkDerivation {
+    name = "test-set-source-date-epoch-to-latest";
+    buildCommand = ''
+      sourceRoot=$NIX_BUILD_TOP/source
+      mkdir -p $sourceRoot
+      touch --date=1/1/2015 $sourceRoot/foo
+
+      _updateSourceDateEpochFromSourceRoot
+
+      [[ $SOURCE_DATE_EPOCH == "1420070400" ]]
+      touch $out
+    '';
+  };
+  # TODO: add strip
+}
diff --git a/nixpkgs/pkgs/test/stdenv/patch-shebangs.nix b/nixpkgs/pkgs/test/stdenv/patch-shebangs.nix
new file mode 100644
index 000000000000..888d4a53a273
--- /dev/null
+++ b/nixpkgs/pkgs/test/stdenv/patch-shebangs.nix
@@ -0,0 +1,115 @@
+{ lib, stdenv, pkgs }:
+
+# since the tests are using a early stdenv, the stdenv will have dontPatchShebangs=1, so it has to be unset
+# https://github.com/NixOS/nixpkgs/blob/768a982bfc9d29a6bd3beb963ed4b054451ce3d0/pkgs/stdenv/linux/default.nix#L148-L153
+
+# strictDeps has to be disabled because the shell isn't in buildInputs
+
+let
+  tests = {
+    bad-shebang = stdenv.mkDerivation {
+      name = "bad-shebang";
+      strictDeps = false;
+      dontUnpack = true;
+      installPhase = ''
+        mkdir -p $out/bin
+        echo "#!/bin/bash" > $out/bin/test
+        echo "echo -n hello" >> $out/bin/test
+        chmod +x $out/bin/test
+        dontPatchShebangs=
+      '';
+      passthru = {
+        assertion = "grep '^#!${stdenv.shell}' $out/bin/test > /dev/null";
+      };
+    };
+
+    ignores-nix-store = stdenv.mkDerivation {
+      name = "ignores-nix-store";
+      strictDeps = false;
+      dontUnpack = true;
+      installPhase = ''
+        mkdir -p $out/bin
+        echo "#!$NIX_STORE/path/to/bash" > $out/bin/test
+        echo "echo -n hello" >> $out/bin/test
+        chmod +x $out/bin/test
+        dontPatchShebangs=
+      '';
+      passthru = {
+        assertion = "grep \"^#!$NIX_STORE/path/to/bash\" $out/bin/test > /dev/null";
+      };
+    };
+
+    updates-nix-store = stdenv.mkDerivation {
+      name = "updates-nix-store";
+      strictDeps = false;
+      dontUnpack = true;
+      installPhase = ''
+        mkdir -p $out/bin
+        echo "#!$NIX_STORE/path/to/bash" > $out/bin/test
+        echo "echo -n hello" >> $out/bin/test
+        chmod +x $out/bin/test
+        patchShebangs --update $out/bin/test
+        dontPatchShebangs=1
+      '';
+      passthru = {
+        assertion = "grep '^#!${stdenv.shell}' $out/bin/test > /dev/null";
+      };
+    };
+
+    split-string = stdenv.mkDerivation {
+      name = "split-string";
+      strictDeps = false;
+      dontUnpack = true;
+      installPhase = ''
+        mkdir -p $out/bin
+        echo "#!/usr/bin/env -S bash --posix" > $out/bin/test
+        echo "echo -n hello" >> $out/bin/test
+        chmod +x $out/bin/test
+        dontPatchShebangs=
+      '';
+      passthru = {
+        assertion = "grep -v '^#!${pkgs.coreutils}/bin/env -S ${stdenv.shell} --posix' $out/bin/test > /dev/null";
+      };
+    };
+
+  };
+in
+stdenv.mkDerivation {
+  name = "test-patch-shebangs";
+  passthru = { inherit (tests) bad-shebang ignores-nix-store updates-nix-store split-string; };
+  buildCommand = ''
+    validate() {
+      local name=$1
+      local testout=$2
+      local assertion=$3
+
+      echo -n "... $name: " >&2
+
+      local rc=0
+      (out=$testout eval "$assertion") || rc=1
+
+      if [ "$rc" -eq 0 ]; then
+        echo "yes" >&2
+      else
+        echo "no" >&2
+      fi
+
+      return "$rc"
+    }
+
+    echo "checking whether patchShebangs works properly... ">&2
+
+    fail=
+    ${lib.concatStringsSep "\n" (lib.mapAttrsToList (_: test: ''
+      validate "${test.name}" "${test}" ${lib.escapeShellArg test.assertion} || fail=1
+    '') tests)}
+
+    if [ "$fail" ]; then
+      echo "failed"
+      exit 1
+    else
+      echo "succeeded"
+      touch $out
+    fi
+  '';
+}
diff --git a/nixpkgs/pkgs/test/texlive/default.nix b/nixpkgs/pkgs/test/texlive/default.nix
new file mode 100644
index 000000000000..32a503b51bdd
--- /dev/null
+++ b/nixpkgs/pkgs/test/texlive/default.nix
@@ -0,0 +1,514 @@
+{ lib, stdenv, buildEnv, runCommand, fetchurl, file, texlive, writeShellScript, writeText }:
+
+{
+
+  tlpdbNix = runCommand "texlive-test-tlpdb-nix" {
+    nixpkgsTlpdbNix = ../../tools/typesetting/tex/texlive/tlpdb.nix;
+    tlpdbNix = texlive.tlpdb.nix;
+  }
+  ''
+    mkdir -p "$out"
+    diff -u "''${nixpkgsTlpdbNix}" "''${tlpdbNix}" | tee "$out/tlpdb.nix.patch"
+  '';
+
+  opentype-fonts = runCommand "texlive-test-opentype" {
+    nativeBuildInputs = [
+      (with texlive; combine { inherit scheme-medium libertinus-fonts; })
+    ];
+    input = builtins.toFile "opentype-testfile.tex" ''
+      \documentclass{article}
+      \usepackage{fontspec}
+      \setmainfont{Libertinus Serif}
+      \begin{document}
+        \LaTeX{} is great
+      \end{document}
+    '';
+  }
+  ''
+    export HOME="$(mktemp -d)"
+    # We use the same testfile to test two completely different
+    # font discovery mechanisms, both of which were once broken:
+    #  - lualatex uses its own luaotfload script (#220228)
+    #  - xelatex uses fontconfig (#228196)
+    # both of the following two commands need to succeed.
+    lualatex -halt-on-error "$input"
+    xelatex -halt-on-error "$input"
+    echo success > $out
+  '';
+
+  chktex = runCommand "texlive-test-chktex" {
+    nativeBuildInputs = [
+      (with texlive; combine { inherit scheme-infraonly chktex; })
+    ];
+    input = builtins.toFile "chktex-sample.tex" ''
+      \documentclass{article}
+      \begin{document}
+        \LaTeX is great
+      \end{document}
+    '';
+  } ''
+    chktex -v -nall -w1 "$input" 2>&1 | tee "$out"
+    grep "One warning printed" "$out"
+  '';
+
+  dvipng = lib.recurseIntoAttrs {
+    # https://github.com/NixOS/nixpkgs/issues/75605
+    basic = runCommand "texlive-test-dvipng-basic" {
+      nativeBuildInputs = [ file texlive.combined.scheme-medium ];
+      input = fetchurl {
+        name = "test_dvipng.tex";
+        url = "http://git.savannah.nongnu.org/cgit/dvipng.git/plain/test_dvipng.tex?id=b872753590a18605260078f56cbd6f28d39dc035";
+        sha256 = "1pjpf1jvwj2pv5crzdgcrzvbmn7kfmgxa39pcvskl4pa0c9hl88n";
+      };
+    } ''
+      cp "$input" ./document.tex
+
+      latex document.tex
+      dvipng -T tight -strict -picky document.dvi
+      for f in document*.png; do
+        file "$f" | tee output
+        grep PNG output
+      done
+
+      mkdir "$out"
+      mv document*.png "$out"/
+    '';
+
+    # test dvipng's limited capability to render postscript specials via GS
+    ghostscript = runCommand "texlive-test-ghostscript" {
+      nativeBuildInputs = [ file (with texlive; combine { inherit scheme-small dvipng; }) ];
+      input = builtins.toFile "postscript-sample.tex" ''
+        \documentclass{minimal}
+        \begin{document}
+          Ni
+          \special{ps:
+            newpath
+            0 0 moveto
+            7 7 rlineto
+            0 7 moveto
+            7 -7 rlineto
+            stroke
+            showpage
+          }
+        \end{document}
+      '';
+      gs_trap = writeShellScript "gs_trap.sh" ''
+        exit 1
+      '';
+    } ''
+      cp "$gs_trap" ./gs
+      export PATH=$PWD:$PATH
+      # check that the trap works
+      gs && exit 1
+
+      cp "$input" ./document.tex
+
+      latex document.tex
+      dvipng -T 1in,1in -strict -picky document.dvi
+      for f in document*.png; do
+        file "$f" | tee output
+        grep PNG output
+      done
+
+      mkdir "$out"
+      mv document*.png "$out"/
+    '';
+  };
+
+  # https://github.com/NixOS/nixpkgs/issues/75070
+  dvisvgm = runCommand "texlive-test-dvisvgm" {
+    nativeBuildInputs = [ file texlive.combined.scheme-medium ];
+    input = builtins.toFile "dvisvgm-sample.tex" ''
+      \documentclass{article}
+      \begin{document}
+        mwe
+      \end{document}
+    '';
+  } ''
+    cp "$input" ./document.tex
+
+    latex document.tex
+    dvisvgm document.dvi -n -o document_dvi.svg
+    cat document_dvi.svg
+    file document_dvi.svg | grep SVG
+
+    pdflatex document.tex
+    dvisvgm -P document.pdf -n -o document_pdf.svg
+    cat document_pdf.svg
+    file document_pdf.svg | grep SVG
+
+    mkdir "$out"
+    mv document*.svg "$out"/
+  '';
+
+  texdoc = runCommand "texlive-test-texdoc" {
+    nativeBuildInputs = [
+      (with texlive; combine {
+        inherit scheme-infraonly luatex texdoc;
+        pkgFilter = pkg: lib.elem pkg.tlType [ "run" "bin" "doc" ];
+      })
+    ];
+  } ''
+    texdoc --version
+
+    texdoc --debug --list texdoc | tee "$out"
+    grep texdoc.pdf "$out"
+  '';
+
+  # test that language files are generated as expected
+  hyphen-base = runCommand "texlive-test-hyphen-base" {
+    hyphenBase = lib.head texlive.hyphen-base.pkgs;
+    schemeFull = texlive.combined.scheme-full;
+    schemeInfraOnly = texlive.combined.scheme-infraonly;
+  } ''
+    mkdir -p "$out"/{scheme-infraonly,scheme-full}
+
+    # create language files with no hyphenation patterns
+    cat "$hyphenBase"/tex/generic/config/language.us >language.dat
+    cat "$hyphenBase"/tex/generic/config/language.us.def >language.def
+    cat "$hyphenBase"/tex/generic/config/language.us.lua >language.dat.lua
+
+    cat >>language.dat.lua <<EOF
+    }
+    EOF
+
+    cat >>language.def <<EOF
+    %%% No changes may be made beyond this point.
+
+    \uselanguage {USenglish}             %%% This MUST be the last line of the file.
+    EOF
+
+    for fname in language.{dat,def,dat.lua} ; do
+      diff --ignore-matching-lines='^\(%\|--\) Generated by ' -u \
+        {"$hyphenBase","$schemeFull"/share/texmf-var}/tex/generic/config/"$fname" \
+        | tee "$out/scheme-full/$fname.patch"
+      diff --ignore-matching-lines='^\(%\|--\) Generated by ' -u \
+        {,"$schemeInfraOnly"/share/texmf-var/tex/generic/config/}"$fname" \
+        | tee "$out/scheme-infraonly/$fname.patch"
+    done
+  '';
+
+  # test that fmtutil.cnf is fully regenerated on scheme-full
+  fmtutilCnf = runCommand "texlive-test-fmtutil.cnf" {
+    kpathsea = lib.head texlive.kpathsea.pkgs;
+    schemeFull = texlive.combined.scheme-full;
+  } ''
+    mkdir -p "$out"
+
+    diff --ignore-matching-lines='^# Generated by ' -u \
+      {"$kpathsea","$schemeFull"/share/texmf-var}/web2c/fmtutil.cnf \
+      | tee "$out/fmtutil.cnf.patch"
+  '';
+
+  # verify that the restricted mode gets enabled when
+  # needed (detected by checking if it disallows --gscmd)
+  repstopdf = runCommand "texlive-test-repstopdf" {
+    nativeBuildInputs = [ (texlive.combine { inherit (texlive) scheme-infraonly epstopdf; }) ];
+  } ''
+    ! (epstopdf --gscmd echo /dev/null 2>&1 || true) | grep forbidden >/dev/null
+    (repstopdf --gscmd echo /dev/null 2>&1 || true) | grep forbidden >/dev/null
+    mkdir "$out"
+  '';
+
+  # verify that the restricted mode gets enabled when
+  # needed (detected by checking if it disallows --gscmd)
+  rpdfcrop = runCommand "texlive-test-rpdfcrop" {
+    nativeBuildInputs = [ (texlive.combine { inherit (texlive) scheme-infraonly pdfcrop; }) ];
+  } ''
+    ! (pdfcrop --gscmd echo $(command -v pdfcrop) 2>&1 || true) | grep 'restricted mode' >/dev/null
+    (rpdfcrop --gscmd echo $(command -v pdfcrop) 2>&1 || true) | grep 'restricted mode' >/dev/null
+    mkdir "$out"
+  '';
+
+  # check that all binaries run successfully, in the following sense:
+  # (1) run --version, -v, --help, -h successfully; or
+  # (2) run --help, -h, or no argument with error code but show help text; or
+  # (3) run successfully on a test.tex or similar file
+  # we ignore the binaries that cannot be tested as above, and are either
+  # compiled binaries or trivial shell wrappers
+  binaries = let
+      # TODO known broken binaries
+      broken = [
+        # *.inc files in source container rather than run
+        "texaccents"
+
+        # 'Error initialising QuantumRenderer: no suitable pipeline found'
+        "tlcockpit"
+      ] ++ lib.optional stdenv.isDarwin "epspdftk";  # wish shebang is a script, not a binary!
+
+      # (1) binaries requiring -v
+      shortVersion = [ "devnag" "diadia" "pmxchords" "ptex2pdf" "simpdftex" "ttf2afm" ];
+      # (1) binaries requiring --help or -h
+      help = [ "arlatex" "bundledoc" "cachepic" "checklistings" "dvipos" "extractres" "fig4latex" "fragmaster"
+        "kpsewhere" "latex-git-log" "ltxfileinfo" "mendex" "perltex" "pn2pdf" "psbook" "psnup" "psresize" "purifyeps"
+        "simpdftex" "tex2xindy" "texluac" "texluajitc" "urlbst" "yplan" ];
+      shortHelp = [ "adhocfilelist" "authorindex" "bbl2bib" "bibdoiadd" "bibmradd" "biburl2doi" "bibzbladd" "ctanupload"
+        "disdvi" "dvibook" "dviconcat" "getmapdl" "latex2man" "listings-ext.sh" "pygmentex" ];
+      # (2) binaries that return non-zero exit code even if correctly asked for help
+      ignoreExitCode = [ "authorindex" "dvibook" "dviconcat" "dvipos" "extractres" "fig4latex" "fragmaster" "latex2man"
+        "latex-git-log" "listings-ext.sh" "psbook" "psnup" "psresize" "purifyeps" "tex2xindy"  "texluac"
+        "texluajitc" ];
+      # (2) binaries that print help on no argument, returning non-zero exit code
+      noArg = [ "a2ping" "bg5+latex" "bg5+pdflatex" "bg5latex" "bg5pdflatex" "cef5latex" "cef5pdflatex" "ceflatex"
+        "cefpdflatex" "cefslatex" "cefspdflatex" "chkdvifont" "dvi2fax" "dvired" "dviselect" "dvitodvi" "epsffit"
+        "findhyph" "gbklatex" "gbkpdflatex" "komkindex" "kpsepath" "listbib" "listings-ext" "mag" "mathspic" "mf2pt1"
+        "mk4ht" "mkt1font" "mkgrkindex" "musixflx" "pdf2ps" "pdftosrc" "pdfxup" "pedigree" "pfb2pfa" "pk2bm" "prepmx"
+        "ps2pk" "psselect" "pstops" "rubibtex" "rubikrotation" "sjislatex" "sjispdflatex" "srcredact" "t4ht"
+        "teckit_compile" "tex4ht" "texdiff" "texdirflatten" "texplate" "tie" "ttf2kotexfont" "ttfdump" "vlna" "vpl2ovp"
+        "vpl2vpl" "yplan" ];
+      # (3) binaries requiring a .tex file
+      contextTest = [ "htcontext" ];
+      latexTest = [ "de-macro" "e2pall" "htlatex" "htxelatex" "makeindex" "pslatex" "rumakeindex" "tpic2pdftex"
+        "wordcount" "xhlatex" ];
+      texTest = [ "fontinst" "htmex" "httex" "httexi" "htxetex" ];
+      # tricky binaries or scripts that are obviously working but are hard to test
+      # (e.g. because they expect user input no matter the arguments)
+      # (printafm comes from ghostscript, not texlive)
+      ignored = [
+        # compiled binaries
+        "dt2dv" "dv2dt" "dvi2tty" "dvidvi" "dvispc" "otp2ocp" "outocp" "pmxab"
+
+        # GUI scripts that accept no argument or crash without a graphics server; please test manualy
+        "epspdftk" "texdoctk" "tlshell" "xasy"
+
+        # requires Cinderella, not open source and not distributed via Nixpkgs
+        "ketcindy"
+      ];
+      # binaries that need a combined scheme and cannot work standalone
+      needScheme = [
+        # pfarrei: require working kpse to find lua module
+        "a5toa4"
+
+        # bibexport: requires kpsewhich
+        "bibexport"
+
+        # crossrefware: require bibtexperllibs under TEXMFROOT
+        "bbl2bib" "bibdoiadd" "bibmradd" "biburl2doi" "bibzbladd" "checkcites" "ltx2crossrefxml"
+
+        # require other texlive binaries in PATH
+        "allcm" "allec" "chkweb" "fontinst" "ht*" "installfont-tl" "kanji-config-updmap-sys" "kanji-config-updmap-user"
+        "kpse*" "latexfileversion" "mkocp" "mkofm" "mtxrunjit" "pdftex-quiet" "pslatex" "rumakeindex" "texconfig"
+        "texconfig-sys" "texexec" "texlinks" "texmfstart" "typeoutfileinfo" "wordcount" "xdvi" "xhlatex"
+
+        # misc luatex binaries searching for luatex in PATH
+        "citeproc-lua" "context" "contextjit" "ctanbib" "digestif" "epspdf" "l3build" "luafindfont" "luaotfload-tool"
+        "luatools" "make4ht" "pmxchords" "tex4ebook" "texdoc" "texlogsieve" "xindex"
+
+        # requires full TEXMFROOT (e.g. for config)
+        "mktexfmt" "mktexmf" "mktexpk" "mktextfm" "psnup" "psresize" "pstops" "tlmgr" "updmap" "webquiz"
+
+        # texlive-scripts: requires texlive.infra's TeXLive::TLUtils under TEXMFROOT
+        "fmtutil" "fmtutil-sys" "fmtutil-user"
+
+        # texlive-scripts: not used in nixpkgs, need updmap in PATH
+        "updmap-sys" "updmap-user"
+      ];
+
+      # simple test files
+      contextTestTex = writeText "context-test.tex" ''
+        \starttext
+          A simple test file.
+        \stoptext
+      '';
+      latexTestTex = writeText "latex-test.tex" ''
+        \documentclass{article}
+        \begin{document}
+          A simple test file.
+        \end{document}
+      '';
+      texTestTex = writeText "tex-test.tex" ''
+        Hello.
+        \bye
+      '';
+
+      # link all binaries in single derivation
+      allPackages = with lib; concatLists (catAttrs "pkgs" (filter isAttrs (attrValues texlive)));
+      binPackages = lib.filter (p: p.tlType == "bin") allPackages;
+      binaries = buildEnv { name = "texlive-binaries"; paths = binPackages; };
+    in
+    runCommand "texlive-test-binaries"
+      {
+        inherit binaries contextTestTex latexTestTex texTestTex;
+        texliveScheme = texlive.combined.scheme-full;
+      }
+      ''
+        loadables="$(command -v bash)"
+        loadables="''${loadables%/bin/bash}/lib/bash"
+        enable -f "$loadables/realpath" realpath
+        mkdir -p "$out"
+        export HOME="$(mktemp -d)"
+        declare -i binCount=0 ignoredCount=0 brokenCount=0 failedCount=0
+        cp "$contextTestTex" context-test.tex
+        cp "$latexTestTex" latex-test.tex
+        cp "$texTestTex" tex-test.tex
+
+        testBin () {
+          path="$(realpath "$bin")"
+          path="''${path##*/}"
+          if [[ -z "$ignoreExitCode" ]] ; then
+            PATH="$path" "$bin" $args >"$out/$base.log" 2>&1
+            ret=$?
+            if [[ $ret == 0 ]] && grep -i 'command not found' "$out/$base.log" >/dev/null ; then
+              echo "command not found when running '$base''${args:+ $args}'"
+              return 1
+            fi
+            return $ret
+          else
+            PATH="$path" "$bin" $args >"$out/$base.log" 2>&1
+            ret=$?
+            if [[ $ret == 0 ]] && grep -i 'command not found' "$out/$base.log" >/dev/null ; then
+              echo "command not found when running '$base''${args:+ $args}'"
+              return 1
+            fi
+            if ! grep -Ei '(Example:|Options:|Syntax:|Usage:|improper command|SYNOPSIS)' "$out/$base.log" >/dev/null ; then
+              echo "did not find usage info when running '$base''${args:+ $args}'"
+              return $ret
+            fi
+          fi
+        }
+
+        for bin in "$binaries"/bin/* ; do
+          base="''${bin##*/}"
+          args=
+          ignoreExitCode=
+          binCount=$((binCount + 1))
+          case "$base" in
+            ${lib.concatStringsSep "|" ignored})
+              ignoredCount=$((ignoredCount + 1))
+              continue ;;
+            ${lib.concatStringsSep "|" broken})
+              brokenCount=$((brokenCount + 1))
+              continue ;;
+            ${lib.concatStringsSep "|" help})
+              args=--help ;;
+            ${lib.concatStringsSep "|" shortHelp})
+              args=-h ;;
+            ${lib.concatStringsSep "|" noArg})
+              ;;
+            ${lib.concatStringsSep "|" contextTest})
+              args=context-test.tex ;;
+            ${lib.concatStringsSep "|" latexTest})
+              args=latex-test.tex ;;
+            ${lib.concatStringsSep "|" texTest})
+              args=tex-test.tex ;;
+            ${lib.concatStringsSep "|" shortVersion})
+              args=-v ;;
+            ebong)
+              touch empty
+              args=empty ;;
+            ht)
+              args='latex latex-test.tex' ;;
+            pdf2dsc)
+              args='--help --help --help' ;;
+            typeoutfileinfo)
+              args=/dev/null ;;
+            *)
+              args=--version ;;
+          esac
+
+          case "$base" in
+            ${lib.concatStringsSep "|" (ignoreExitCode ++ noArg)})
+              ignoreExitCode=1 ;;
+          esac
+
+          case "$base" in
+            ${lib.concatStringsSep "|" needScheme})
+              bin="$texliveScheme/bin/$base"
+              if [[ ! -f "$bin" ]] ; then
+                ignoredCount=$((ignoredCount + 1))
+                continue
+              fi ;;
+          esac
+
+          if testBin ; then : ; else # preserve exit code
+            echo "failed '$base''${args:+ $args}' (exit code: $?)"
+            sed 's/^/  > /' < "$out/$base.log"
+            failedCount=$((failedCount + 1))
+          fi
+        done
+
+        echo "tested $binCount binaries: $ignoredCount ignored, $brokenCount broken, $failedCount failed"
+        [[ $failedCount = 0 ]]
+      '';
+
+  # check that all scripts have a Nix shebang
+  shebangs = let
+      allPackages = with lib; concatLists (catAttrs "pkgs" (filter isAttrs (attrValues texlive)));
+      binPackages = lib.filter (p: p.tlType == "bin") allPackages;
+    in
+    runCommand "texlive-test-shebangs" { }
+      (''
+        echo "checking that all texlive scripts shebangs are in '$NIX_STORE'"
+        declare -i scriptCount=0 invalidCount=0
+      '' +
+      (lib.concatMapStrings
+        (pkg: ''
+          for bin in '${pkg.outPath}'/bin/* ; do
+            grep -I -q . "$bin" || continue  # ignore binary files
+            scriptCount=$((scriptCount + 1))
+            read -r cmdline < "$bin"
+            read -r interp <<< "$cmdline"
+            if [[ "$interp" != "#!$NIX_STORE"/* && "$interp" != "#! $NIX_STORE"/* ]] ; then
+              echo "error: non-nix shebang '$interp' in script '$bin'"
+              invalidCount=$((invalidCount + 1))
+            fi
+          done
+        '')
+        binPackages)
+      + ''
+        echo "checked $scriptCount scripts, found $invalidCount non-nix shebangs"
+        [[ $invalidCount -gt 0 ]] && exit 1
+        mkdir -p "$out"
+      ''
+      );
+
+  # verify that the precomputed licensing information in default.nix
+  # does indeed match the metadata of the individual packages.
+  #
+  # This is part of the test suite (and not the normal evaluation) to save
+  # time for "normal" evaluations. To be more in line with the other tests, this
+  # also builds a derivation, even though it is essentially an eval-time assertion.
+  licenses =
+    let
+        concatLicenses = builtins.foldl' (acc: el: if builtins.elem el acc then acc else acc ++ [ el ]);
+        # converts a license to its attribute name in lib.licenses
+        licenseToAttrName = license:
+          builtins.head (builtins.attrNames
+            (lib.filterAttrs (n: v: license == v) lib.licenses));
+        lt = (a: b: a < b);
+
+        savedLicenses = scheme: scheme.meta.license;
+        savedLicensesAttrNames = scheme: map licenseToAttrName (savedLicenses scheme);
+
+        correctLicenses = scheme: builtins.foldl'
+                (acc: pkg: concatLicenses acc (lib.toList (pkg.meta.license or [])))
+                []
+                scheme.passthru.packages;
+        correctLicensesAttrNames = scheme:
+          lib.sort lt
+            (map licenseToAttrName (correctLicenses scheme));
+
+        hasLicenseMismatch = scheme:
+          (lib.isDerivation scheme) &&
+          (savedLicensesAttrNames scheme) != (correctLicensesAttrNames scheme);
+        incorrectSchemes = lib.filterAttrs
+          (n: hasLicenseMismatch)
+          texlive.combined;
+        prettyPrint = name: scheme:
+          ''
+            license info for ${name} is incorrect! Note that order is enforced.
+            saved: [ ${lib.concatStringsSep " " (savedLicensesAttrNames scheme)} ]
+            correct: [ ${lib.concatStringsSep " " (correctLicensesAttrNames scheme)} ]
+          '';
+        errorText = lib.concatStringsSep "\n\n" (lib.mapAttrsToList prettyPrint incorrectSchemes);
+      in
+        runCommand "texlive-test-license" {
+          inherit errorText;
+        }
+        (if (incorrectSchemes == {})
+        then "echo everything is fine! > $out"
+        else ''
+          echo "$errorText"
+          false
+        '');
+}
diff --git a/nixpkgs/pkgs/test/vim/default.nix b/nixpkgs/pkgs/test/vim/default.nix
new file mode 100644
index 000000000000..4d8e59a306a8
--- /dev/null
+++ b/nixpkgs/pkgs/test/vim/default.nix
@@ -0,0 +1,26 @@
+{ vimUtils, vim-full, writeText, vimPlugins
+, lib, fetchFromGitHub
+, pkgs
+}:
+let
+  inherit (vimUtils) buildVimPluginFrom2Nix;
+
+  packages.myVimPackage.start = with vimPlugins; [ vim-nix ];
+
+in
+  pkgs.recurseIntoAttrs (rec {
+  vim_empty_config = vimUtils.vimrcFile { beforePlugins = ""; customRC = ""; };
+
+  ### vim tests
+  ##################
+
+  test_vim_with_vim_nix_using_plug = vim-full.customize {
+    name = "vim-with-vim-addon-nix-using-plug";
+    vimrcConfig.plug.plugins = with vimPlugins; [ vim-nix ];
+  };
+
+  test_vim_with_vim_nix = vim-full.customize {
+    name = "vim-with-vim-addon-nix";
+    vimrcConfig.packages.myVimPackage.start = with vimPlugins; [ vim-nix ];
+  };
+})