Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1{ 2 lib, 3 stdenv, 4 pkgs, 5}: 6 7# since the tests are using a early stdenv, the stdenv will have dontPatchShebangs=1, so it has to be unset 8# https://github.com/NixOS/nixpkgs/blob/768a982bfc9d29a6bd3beb963ed4b054451ce3d0/pkgs/stdenv/linux/default.nix#L148-L153 9 10# strictDeps has to be disabled because the shell isn't in buildInputs 11 12let 13 tests = { 14 bad-shebang = stdenv.mkDerivation { 15 name = "bad-shebang"; 16 strictDeps = false; 17 dontUnpack = true; 18 installPhase = '' 19 mkdir -p $out/bin 20 echo "#!/bin/bash" > $out/bin/test 21 echo "echo -n hello" >> $out/bin/test 22 chmod +x $out/bin/test 23 dontPatchShebangs= 24 ''; 25 passthru = { 26 assertion = "grep '^#!${stdenv.shell}' $out/bin/test > /dev/null"; 27 }; 28 }; 29 30 ignores-nix-store = stdenv.mkDerivation { 31 name = "ignores-nix-store"; 32 strictDeps = false; 33 dontUnpack = true; 34 installPhase = '' 35 mkdir -p $out/bin 36 echo "#!$NIX_STORE/path/to/bash" > $out/bin/test 37 echo "echo -n hello" >> $out/bin/test 38 chmod +x $out/bin/test 39 dontPatchShebangs= 40 ''; 41 passthru = { 42 assertion = "grep \"^#!$NIX_STORE/path/to/bash\" $out/bin/test > /dev/null"; 43 }; 44 }; 45 46 updates-nix-store = stdenv.mkDerivation { 47 name = "updates-nix-store"; 48 strictDeps = false; 49 dontUnpack = true; 50 installPhase = '' 51 mkdir -p $out/bin 52 echo "#!$NIX_STORE/path/to/bash" > $out/bin/test 53 echo "echo -n hello" >> $out/bin/test 54 chmod +x $out/bin/test 55 patchShebangs --update $out/bin/test 56 dontPatchShebangs=1 57 ''; 58 passthru = { 59 assertion = "grep '^#!${stdenv.shell}' $out/bin/test > /dev/null"; 60 }; 61 }; 62 63 split-string = stdenv.mkDerivation { 64 name = "split-string"; 65 strictDeps = false; 66 dontUnpack = true; 67 installPhase = '' 68 mkdir -p $out/bin 69 echo "#!/usr/bin/env -S bash --posix" > $out/bin/test 70 echo "echo -n hello" >> $out/bin/test 71 chmod +x $out/bin/test 72 dontPatchShebangs= 73 ''; 74 passthru = { 75 assertion = "grep -v '^#!${pkgs.coreutils}/bin/env -S ${stdenv.shell} --posix' $out/bin/test > /dev/null"; 76 }; 77 }; 78 79 without-trailing-newline = stdenv.mkDerivation { 80 name = "without-trailing-newline"; 81 strictDeps = false; 82 dontUnpack = true; 83 installPhase = '' 84 mkdir -p $out/bin 85 printf "#!/bin/bash" > $out/bin/test 86 chmod +x $out/bin/test 87 dontPatchShebangs= 88 ''; 89 passthru = { 90 assertion = "grep '^#!${stdenv.shell}' $out/bin/test > /dev/null"; 91 }; 92 }; 93 94 dont-patch-builtins = stdenv.mkDerivation { 95 name = "dont-patch-builtins"; 96 strictDeps = false; 97 dontUnpack = true; 98 installPhase = '' 99 mkdir -p $out/bin 100 echo "#!/usr/bin/builtin" > $out/bin/test 101 chmod +x $out/bin/test 102 dontPatchShebangs= 103 ''; 104 passthru = { 105 assertion = "grep '^#!/usr/bin/builtin' $out/bin/test > /dev/null"; 106 }; 107 }; 108 109 read-only-script = 110 (derivation { 111 name = "read-only-script"; 112 system = stdenv.buildPlatform.system; 113 builder = "${stdenv.__bootPackages.stdenv.__bootPackages.bashNonInteractive}/bin/bash"; 114 initialPath = [ 115 stdenv.__bootPackages.stdenv.__bootPackages.coreutils 116 ]; 117 strictDeps = false; 118 args = [ 119 "-c" 120 '' 121 set -euo pipefail 122 . ${../../stdenv/generic/setup.sh} 123 . ${../../build-support/setup-hooks/patch-shebangs.sh} 124 mkdir -p $out/bin 125 echo "#!/bin/bash" > $out/bin/test 126 echo "echo -n hello" >> $out/bin/test 127 chmod 555 $out/bin/test 128 patchShebangs $out/bin/test 129 '' 130 ]; 131 assertion = "grep '^#!${stdenv.shell}' $out/bin/test > /dev/null"; 132 }) 133 // { 134 meta = { }; 135 }; 136 137 preserves-read-only = 138 (derivation { 139 name = "preserves-read-only"; 140 system = stdenv.buildPlatform.system; 141 builder = "${stdenv.__bootPackages.stdenv.__bootPackages.bashNonInteractive}/bin/bash"; 142 initialPath = [ 143 stdenv.__bootPackages.stdenv.__bootPackages.coreutils 144 ]; 145 strictDeps = false; 146 args = [ 147 "-c" 148 '' 149 set -euo pipefail 150 . ${../../stdenv/generic/setup.sh} 151 . ${../../build-support/setup-hooks/patch-shebangs.sh} 152 mkdir -p $out/bin 153 echo "#!/bin/bash" > $out/bin/test 154 echo "echo -n hello" >> $out/bin/test 155 chmod 555 $out/bin/test 156 original_perms=$(stat -c %a $out/bin/test) 157 patchShebangs $out/bin/test 158 new_perms=$(stat -c %a $out/bin/test) 159 if ! [ "$original_perms" = "$new_perms" ]; then 160 echo "Permissions changed from $original_perms to $new_perms" 161 exit 1 162 fi 163 '' 164 ]; 165 assertion = "grep '^#!${stdenv.shell}' $out/bin/test > /dev/null"; 166 }) 167 // { 168 meta = { }; 169 }; 170 171 # Preserve times, see: https://github.com/NixOS/nixpkgs/pull/33281 172 preserves-timestamp = 173 (derivation { 174 name = "preserves-timestamp"; 175 system = stdenv.buildPlatform.system; 176 builder = "${stdenv.__bootPackages.stdenv.__bootPackages.bashNonInteractive}/bin/bash"; 177 initialPath = [ 178 stdenv.__bootPackages.stdenv.__bootPackages.coreutils 179 ]; 180 strictDeps = false; 181 args = [ 182 "-c" 183 '' 184 set -euo pipefail 185 . ${../../stdenv/generic/setup.sh} 186 . ${../../build-support/setup-hooks/patch-shebangs.sh} 187 mkdir -p $out/bin 188 echo "#!/bin/bash" > $out/bin/test 189 echo "echo -n hello" >> $out/bin/test 190 chmod +x $out/bin/test 191 # Set a specific timestamp (2000-01-01 00:00:00) 192 touch -t 200001010000 $out/bin/test 193 original_timestamp=$(stat -c %Y $out/bin/test) 194 patchShebangs $out/bin/test 195 new_timestamp=$(stat -c %Y $out/bin/test) 196 if ! [ "$original_timestamp" = "$new_timestamp" ]; then 197 echo "Timestamp changed from $original_timestamp to $new_timestamp" 198 exit 1 199 fi 200 '' 201 ]; 202 assertion = "grep '^#!${stdenv.shell}' $out/bin/test > /dev/null"; 203 }) 204 // { 205 meta = { }; 206 }; 207 208 preserves-binary-data = 209 (derivation { 210 name = "preserves-binary-data"; 211 system = stdenv.buildPlatform.system; 212 builder = "${stdenv.__bootPackages.stdenv.__bootPackages.bashNonInteractive}/bin/bash"; 213 initialPath = [ 214 stdenv.__bootPackages.stdenv.__bootPackages.coreutils 215 ]; 216 strictDeps = false; 217 args = [ 218 "-c" 219 '' 220 set -euo pipefail 221 . ${../../stdenv/generic/setup.sh} 222 . ${../../build-support/setup-hooks/patch-shebangs.sh} 223 mkdir -p $out/bin 224 # Create a script with binary data after the shebang 225 echo "#!/bin/bash" > $out/bin/test 226 echo "echo 'script start'" >> $out/bin/test 227 # Add some binary data (null bytes and other non-printable chars) 228 printf '\x00\x01\x02\xff\xfe' >> $out/bin/test 229 echo >> $out/bin/test 230 echo "echo 'script end'" >> $out/bin/test 231 chmod +x $out/bin/test 232 patchShebangs $out/bin/test 233 # Verify binary data is still present by checking file size and content 234 if ! printf '\x00\x01\x02\xff\xfe' | cmp -s - <(sed -n '3p' $out/bin/test | tr -d '\n'); then 235 echo "Binary data corrupted during patching" 236 exit 1 237 fi 238 '' 239 ]; 240 assertion = "grep '^#!${stdenv.shell}' $out/bin/test > /dev/null"; 241 }) 242 // { 243 meta = { }; 244 }; 245 }; 246in 247stdenv.mkDerivation { 248 name = "test-patch-shebangs"; 249 passthru = { 250 inherit (tests) 251 bad-shebang 252 ignores-nix-store 253 updates-nix-store 254 split-string 255 without-trailing-newline 256 dont-patch-builtins 257 read-only-script 258 preserves-read-only 259 preserves-timestamp 260 preserves-binary-data 261 ; 262 }; 263 buildCommand = '' 264 validate() { 265 local name=$1 266 local testout=$2 267 local assertion=$3 268 269 echo -n "... $name: " >&2 270 271 local rc=0 272 (out=$testout eval "$assertion") || rc=1 273 274 if [ "$rc" -eq 0 ]; then 275 echo "yes" >&2 276 else 277 echo "no" >&2 278 fi 279 280 return "$rc" 281 } 282 283 echo "checking whether patchShebangs works properly... ">&2 284 285 fail= 286 ${lib.concatStringsSep "\n" ( 287 lib.mapAttrsToList (_: test: '' 288 validate "${test.name}" "${test}" ${lib.escapeShellArg test.assertion} || fail=1 289 '') tests 290 )} 291 292 if [ "$fail" ]; then 293 echo "failed" 294 exit 1 295 else 296 echo "succeeded" 297 touch $out 298 fi 299 ''; 300}