summaryrefslogtreecommitdiffstats
path: root/pkgs/build-support/testers/default.nix
blob: 5d9f568d2ed34e4a64640f97a3b7d620d47bb62b (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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
{
  lib,
  buildPackages,
  callPackage,
  pkgs,
  pkgsLinux,

  diffoscopeMinimal,
  runCommand,
  runCommandWith,
  stdenv,
  stdenvNoCC,
  replaceVars,
  testers,
}:
# Documentation is in doc/build-helpers/testers.chapter.md
{
  # See https://nixos.org/manual/nixpkgs/unstable/#tester-lycheeLinkCheck
  # or doc/build-helpers/testers.chapter.md
  inherit (callPackage ./lychee.nix { }) lycheeLinkCheck;

  # See https://nixos.org/manual/nixpkgs/unstable/#tester-testBuildFailure
  # or doc/build-helpers/testers.chapter.md
  testBuildFailure =
    drv:
    drv.overrideAttrs (orig: {
      builder = buildPackages.bash;
      args = [
        (replaceVars ./expect-failure.sh {
          coreutils = buildPackages.coreutils;
          vars = lib.toShellVars {
            outputNames = (orig.outputs or [ "out" ]);
          };
        })
        orig.realBuilder or stdenv.shell
      ]
      ++ orig.args or [
        "-e"
        ../../stdenv/generic/source-stdenv.sh
        (orig.builder or ../../stdenv/generic/default-builder.sh)
      ];
    });

  # See https://nixos.org/manual/nixpkgs/unstable/#tester-testBuildFailurePrime
  # or doc/build-helpers/testers.chapter.md
  testBuildFailure' = callPackage ./testBuildFailurePrime { };

  # See https://nixos.org/manual/nixpkgs/unstable/#tester-testEqualDerivation
  # or doc/build-helpers/testers.chapter.md
  testEqualDerivation = callPackage ./test-equal-derivation.nix { };

  # See https://nixos.org/manual/nixpkgs/unstable/#tester-testEqualContents
  # or doc/build-helpers/testers.chapter.md
  testEqualContents =
    {
      assertion,
      actual,
      expected,
      postFailureMessage ? null,
      checkMetadata ? true,
    }:
    runCommand "equal-contents-${lib.strings.toLower assertion}"
      {
        inherit
          assertion
          actual
          expected
          postFailureMessage
          ;
        excludeMetadata = if checkMetadata then "no" else "yes";
        nativeBuildInputs = [ diffoscopeMinimal ];
      }
      ''
        echo "Checking:"
        printf '%s\n' "$assertion"
        if ! diffoscope --no-progress --text-color=always --exclude-directory-metadata="$excludeMetadata" -- "$actual" "$expected"
        then
          echo
          echo 'Contents must be equal, but were not!'
          if [[ -n "''${postFailureMessage:-}" ]]; then
            echo
            echo "$postFailureMessage"
          fi
          echo
          echo "+: expected,   at $expected"
          echo "-: unexpected, at $actual"
          false
        else
          echo "expected $expected and actual $actual match."
          echo OK
          touch -- "$out"
        fi
      '';

  # See https://nixos.org/manual/nixpkgs/unstable/#tester-testEqualArrayOrMap
  # or doc/build-helpers/testers.chapter.md
  testEqualArrayOrMap = callPackage ./testEqualArrayOrMap { };

  # See https://nixos.org/manual/nixpkgs/unstable/#tester-testVersion
  # or doc/build-helpers/testers.chapter.md
  testVersion =
    {
      package,
      command ? "${package.meta.mainProgram or package.pname or package.name} --version",
      version ? package.version,
    }:
    runCommand "${package.name}-test-version"
      {
        nativeBuildInputs = [ package ];
        meta.timeout = 60;
      }
      ''
        if output=$(${command} 2>&1 | sed -e 's|${builtins.storeDir}/[^/ ]*/|{{storeDir}}/|g'); then
          if grep -Fw -- "${version}" - <<< "$output"; then
            touch $out
          else
            echo "Version string '${version}' not found!" >&2
            echo "The output was:" >&2
            echo "$output" >&2
            exit 1
          fi
        else
          echo -n ${lib.escapeShellArg command} >&2
          echo " returned a non-zero exit code." >&2
          echo "$output" >&2
          exit 1
        fi
      '';

  # See https://nixos.org/manual/nixpkgs/unstable/#tester-invalidateFetcherByDrvHash
  # or doc/build-helpers/testers.chapter.md
  invalidateFetcherByDrvHash =
    f: args:
    let
      optionalFix = if lib.isFunction args then lib.id else lib.fix;
      unsalted = f args;
      drvPath = unsalted.drvPath;
      # It's safe to discard the context, because we don't access the path.
      salt = builtins.unsafeDiscardStringContext (lib.substring 0 12 (baseNameOf drvPath));
      saltName = name: "${name}-salted-${salt}";
      getSaltedNames =
        args:
        if args.pname or null != null then
          { pname = saltName args.pname; }
        else
          { name = saltName args.name or "source"; };
      # New derivation incorporating the original drv hash in the name
      saltedByArgs = f (optionalFix (lib.extends (lib.toExtension getSaltedNames) (lib.toFunction args)));
      saltedByOverrideAttrs = unsalted.overrideAttrs (previousAttrs: getSaltedNames previousAttrs);
      saltedByOverrideAttrsForced = unsalted.overrideAttrs (previousAttrs: {
        name = saltName unsalted.name;
      });
      # Make sure we did change the derivation.
      # If the fetcher ignores `pname` and `name` and provide a broken `overrideAttrs`,
      # `invalidateFetcherByDrvHash` doesn't work.
      checked =
        if saltedByArgs.drvPath != drvPath then
          saltedByArgs
        else if saltedByOverrideAttrs.drvPath != drvPath then
          saltedByOverrideAttrs
        else if saltedByOverrideAttrsForced.drvPath != drvPath then
          saltedByOverrideAttrsForced
        else
          throw "invalidateFetcherByDrvHash: Neither adding pname/name to the fetcher args nor overriding with overrideAttrs change the result drvPath.";
    in
    checked;

  # See https://nixos.org/manual/nixpkgs/unstable/#tester-runCommand
  runCommand = testers.invalidateFetcherByDrvHash (
    {
      hash ? pkgs.emptyFile.outputHash,
      name,
      script,
      stdenv ? stdenvNoCC,
      ...
    }@args:

    runCommandWith {
      inherit name stdenv;

      derivationArgs = {
        outputHash = hash;
        outputHashMode = "recursive";
      }
      // lib.removeAttrs args [
        "hash"
        "name"
        "script"
        "stdenv"
      ];
    } script
  );

  # See https://nixos.org/manual/nixpkgs/unstable/#tester-runNixOSTest
  # or doc/build-helpers/testers.chapter.md
  runNixOSTest =
    let
      nixos = import ../../../nixos/lib {
        inherit lib;
      };
    in
    testModule:
    nixos.runTest {
      _file = "pkgs.runNixOSTest implementation";
      imports = [
        (lib.setDefaultModuleLocation "the argument that was passed to pkgs.runNixOSTest" testModule)
      ];
      hostPkgs = pkgs;
      node.pkgs = pkgsLinux;
    };

  # See https://nixos.org/manual/nixpkgs/unstable/#tester-invalidateFetcherByDrvHash
  # or doc/build-helpers/testers.chapter.md
  nixosTest =
    let
      /*
        The nixos/lib/testing-python.nix module, preapplied with arguments that
        make sense for this evaluation of Nixpkgs.
      */
      nixosTesting = (
        import ../../../nixos/lib/testing-python.nix {
          inherit (stdenv.hostPlatform) system;
          inherit pkgs;
          extraConfigurations = [
            (
              { lib, ... }:
              {
                config.nixpkgs.pkgs = lib.mkDefault pkgsLinux;
              }
            )
          ];
        }
      );
    in
    test:
    let
      loadedTest = if builtins.typeOf test == "path" then import test else test;
      calledTest = lib.toFunction loadedTest pkgs;
    in
    nixosTesting.simpleTest calledTest;

  hasPkgConfigModule =
    { moduleName, ... }@args:
    lib.warn
      "testers.hasPkgConfigModule has been deprecated in favor of testers.hasPkgConfigModules. It accepts a list of strings via the moduleNames argument instead of a single moduleName."
      (
        testers.hasPkgConfigModules (
          removeAttrs args [ "moduleName" ]
          // {
            moduleNames = [ moduleName ];
          }
        )
      );
  hasPkgConfigModules = callPackage ./hasPkgConfigModules/tester.nix { };

  hasCmakeConfigModules = callPackage ./hasCmakeConfigModules/tester.nix { };

  testMetaPkgConfig = callPackage ./testMetaPkgConfig/tester.nix { };

  shellcheck = callPackage ./shellcheck/tester.nix { };

  shfmt = callPackage ./shfmt { };

  modularServiceCompliance = callPackage ./modular-service-compliance.nix { };
}