summary refs log tree commit diff
path: root/pkgs/build-support/trivial-builders/test-overriding.nix
blob: ddd5dc050752556f7be3dbfc421c80db1e2fc233 (plain) (blame)
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
# Check that overriding works for trivial-builders like
# `writeShellScript` via `overrideAttrs`. This is useful
# to override the `checkPhase`, e. g. when you want
# to enable extglob in `writeShellScript`.
#
# Run using `nix-build -A tests.trivial-overriding`.
{ lib
, runtimeShell
, runCommand
, callPackage
, writeShellScript
, writeTextFile
, writeShellScriptBin
}:

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

  # Reuse the old `checkPhase` of `writeShellScript`, but enable extglob.
  allowExtglob = old: {
    checkPhase = ''
      # make sure we don't change the settings for
      # the rest of the derivation's build
      (
        export BASHOPTS
        shopt -s extglob
        ${old.checkPhase}
      )
    '';
  };

  # 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 = old: {
    # write old checkPhase into a shell script, so we can check for
    # the phase to fail even though we have `set -e`.
    checkPhase = ''
      if source ${writeShellScript "old-check-phase" old.checkPhase} 2>/dev/null; then
        exit 1
      fi
    '';
  };

  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;
  };

  mkCase = f: type: isBin:
    let
      drv = (f type).overrideAttrs
        (if type == "succ" then allowExtglob else assertFail);
    in if isBin then "${drv}/bin/${drv.name}" else drv;

  writeTextOverrides = {
    # Enabling globbing in checkPhase
    simpleSucc = mkCase simpleCase "succ" false;
    # Ensure it's possible to fail; in this case globbing 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 (builtins.baseNameOf script);
    in writeShellScript "run-${name}" ''
      if [ "$(${script})" != "success" ]; then
        echo "Failed in ${script}"
        exit 1
      fi
    '';
in

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