summaryrefslogtreecommitdiffstats
path: root/pkgs/build-support/make-impure-test.nix
blob: 10dd7ef1867ed87ad498dd02f1de378a70ed56bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*
  Create tests that run in the nix sandbox with additional access to selected host paths

  This is for example useful for testing hardware where a tests needs access to
  /sys and optionally more.

  The following example shows a test that accesses the GPU:

  Example:
    makeImpureTest {
      name = "opencl";
      testedPackage = "mypackage"; # Or testPath = "mypackage.impureTests.opencl.testDerivation"

      sandboxPaths = [ "/sys" "/dev/dri" ]; # Defaults to ["/sys"]
      prepareRunCommands = ""; # (Optional) Setup for the runScript
      nixFlags = []; # (Optional) nix-build options for the runScript

      testScript = "...";
    }

  Save as `test.nix` next to a package and reference it from the package:
    passthru.impureTests = { opencl = callPackage ./test.nix {}; };

  `makeImpureTest` will return here a script that contains the actual nix-build command including all necessary sandbox flags.

  It can be executed like this:
    $(nix-build -A mypackage.impureTests)

  Rerun an already cached test:
    $(nix-build -A mypackage.impureTests) --check
*/
{
  lib,
  stdenv,
  writeShellScript,

  name,
  testedPackage ? null,
  testPath ? "${testedPackage}.impureTests.${name}.testDerivation",
  sandboxPaths ? [ "/sys" ],
  prepareRunCommands ? "",
  nixFlags ? [ ],
  testScript,
  ...
}@args:

let
  sandboxPathsTests = map (path: "[[ ! -e '${path}' ]]") sandboxPaths;
  sandboxPathsTest = lib.concatStringsSep " || " sandboxPathsTests;
  sandboxPathsList = lib.concatStringsSep " " sandboxPaths;

  testDerivation = stdenv.mkDerivation (
    lib.recursiveUpdate
      {
        name = "test-run-${name}";

        requiredSystemFeatures = [ "nixos-test" ];

        buildCommand = ''
          mkdir -p $out

          if ${sandboxPathsTest}; then
            echo 'Run this test as *root* with `--option extra-sandbox-paths '"'${sandboxPathsList}'"'`'
            exit 1
          fi

          # Run test
          ${testScript}
        '';

        passthru.runScript = runScript;
      }
      (
        removeAttrs args [
          "lib"
          "stdenv"
          "writeShellScript"

          "name"
          "testedPackage"
          "testPath"
          "sandboxPaths"
          "prepareRunCommands"
          "nixFlags"
          "testScript"
        ]
      )
  );

  runScript = writeShellScript "run-script-${name}" ''
    set -euo pipefail

    ${prepareRunCommands}

    sudo --preserve-env=NIXPKGS_ALLOW_UNFREE nix-build --option extra-sandbox-paths '${sandboxPathsList}' ${lib.escapeShellArgs nixFlags} -A ${testPath} "$@"
  '';
in
# The main output is the run script, inject the derivation for the actual test
runScript.overrideAttrs (old: {
  passthru = { inherit testDerivation; };
})