summaryrefslogtreecommitdiffstats
path: root/pkgs/build-support/trivial-builders/test-overriding.nix
blob: dbb756579de7b096cdd281a69659d97c366f5f2b (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
# Check that overriding works for trivial-builders like
# `writeShellScript` via `overrideAttrs`. This is useful
# to override the `checkPhase`, e. g. if you want
# to disable extglob in `writeShellScript`.
#
# Run using `nix-build -A tests.trivial-builders.overriding`.
{
  lib,
  stdenv,
  runtimeShell,
  runCommand,
  callPackage,
  writeShellScript,
  writeTextFile,
  writeShellScriptBin,
}:

let
  extglobScript = ''
    shopt -s extglob
    touch success
    echo @(success|failure)
    rm success
  '';

  simpleCase = case: writeShellScript "test-trivial-overriding-${case}" extglobScript;

  callPackageCase =
    case:
    callPackage (
      { writeShellScript }: writeShellScript "test-trivial-callpackage-overriding-${case}" extglobScript
    ) { };

  binCase = case: writeShellScriptBin "test-trivial-overriding-bin-${case}" extglobScript;

  # building this derivation would fail without overriding
  textFileCase = writeTextFile {
    name = "test-trivial-overriding-text-file";
    checkPhase = "false";
    text = ''
      #!${runtimeShell}
      echo success
    '';
    executable = true;
  };

  disallowExtglob =
    x:
    x.overrideAttrs (_: {
      checkPhase = ''
        ${stdenv.shell} -n "$target"
      '';
    });

  # Run old checkPhase, but only succeed if it fails.
  # This HACK is required because we can't introspect build failures
  # in nix: With `assertFail` we want to make sure that the default
  # `checkPhase` would fail if extglob was used in the script.
  assertFail =
    x:
    x.overrideAttrs (old: {
      checkPhase = ''
        if
          ${old.checkPhase}
        then exit 1; fi
      '';
    });

  mkCase =
    case: outcome: isBin:
    let
      drv = lib.pipe outcome (
        [ case ]
        ++ lib.optionals (outcome == "fail") [
          disallowExtglob
          assertFail
        ]
      );
    in
    if isBin then "${drv}/bin/${drv.name}" else drv;

  writeTextOverrides = {
    # Make sure extglob works by default
    simpleSucc = mkCase simpleCase "succ" false;
    # Ensure it's possible to fail; in this case extglob is not enabled
    simpleFail = mkCase simpleCase "fail" false;
    # Do the same checks after wrapping with callPackage
    # to make sure callPackage doesn't mess with the override
    callpSucc = mkCase callPackageCase "succ" false;
    callpFail = mkCase callPackageCase "fail" false;
    # Do the same check using `writeShellScriptBin`
    binSucc = mkCase binCase "succ" true;
    binFail = mkCase binCase "fail" true;
    # Check that we can also override plain writeTextFile
    textFileSuccess = textFileCase.overrideAttrs (_: {
      checkPhase = "true";
    });
  };

  # `runTest` forces nix to build the script of our test case and
  # run its `checkPhase` which is our main interest. Additionally
  # it executes the script and thus makes sure that extglob also
  # works at run time.
  runTest =
    script:
    let
      name = script.name or (baseNameOf script);
    in
    writeShellScript "run-${name}" ''
      if [ "$(${script})" != "success" ]; then
        echo "Failed in ${name}"
        exit 1
      fi
    '';
in

runCommand "test-writeShellScript-overriding"
  {
    passthru = { inherit writeTextOverrides; };
  }
  ''
    ${lib.concatMapStrings (test: ''
      ${runTest test}
    '') (lib.attrValues writeTextOverrides)}
    touch "$out"
  ''