mirror of
https://github.com/CHN-beta/nixpkgs.git
synced 2026-01-11 18:32:23 +08:00
330 lines
11 KiB
Nix
330 lines
11 KiB
Nix
{
|
|
lib,
|
|
pkgs,
|
|
stdenv,
|
|
}:
|
|
|
|
let
|
|
inherit (lib.strings) concatStringsSep optionalString;
|
|
inherit (pkgs) runCommand;
|
|
inherit (pkgs.testers) testBuildFailure;
|
|
|
|
mkDanglingSymlink = absolute: ''
|
|
ln -s${optionalString (!absolute) "r"} "$out/dangling" "$out/dangling-symlink"
|
|
'';
|
|
|
|
mkReflexiveSymlink = absolute: ''
|
|
ln -s${optionalString (!absolute) "r"} "$out/reflexive-symlink" "$out/reflexive-symlink"
|
|
'';
|
|
|
|
# Some platforms implement permissions for symlinks, while others - including Linux - ignore them.
|
|
# As a result, testing this hook's handling of unreadable symlinks requires careful attention to
|
|
# which kind of platform we're on. See the comments by `lib.optionalAttrs` below for details.
|
|
hasSymlinkPermissions = with stdenv.hostPlatform; isDarwin || isBSD;
|
|
mkUnreadableSymlink = absolute: ''
|
|
touch "$out/unreadable-symlink-target"
|
|
(
|
|
umask 777
|
|
ln -s${optionalString (!absolute) "r"} "$out/unreadable-symlink-target" "$out/unreadable-symlink"
|
|
)
|
|
'';
|
|
|
|
mkValidSymlink = absolute: ''
|
|
touch "$out/valid"
|
|
ln -s${optionalString (!absolute) "r"} "$out/valid" "$out/valid-symlink"
|
|
'';
|
|
|
|
mkValidSymlinkOutsideNixStore = absolute: ''
|
|
ln -s${optionalString (!absolute) "r"} "/etc/my_file" "$out/valid-symlink"
|
|
'';
|
|
|
|
testBuilder =
|
|
{
|
|
name,
|
|
commands ? [ ],
|
|
derivationArgs ? { },
|
|
}:
|
|
stdenv.mkDerivation (
|
|
{
|
|
inherit name;
|
|
strictDeps = true;
|
|
dontUnpack = true;
|
|
dontPatch = true;
|
|
dontConfigure = true;
|
|
dontBuild = true;
|
|
installPhase = ''
|
|
mkdir -p "$out"
|
|
|
|
''
|
|
+ concatStringsSep "\n" commands;
|
|
}
|
|
// derivationArgs
|
|
);
|
|
in
|
|
{
|
|
fail-dangling-symlink-relative =
|
|
runCommand "fail-dangling-symlink-relative"
|
|
{
|
|
failed = testBuildFailure (testBuilder {
|
|
name = "fail-dangling-symlink-relative-inner";
|
|
commands = [ (mkDanglingSymlink false) ];
|
|
});
|
|
}
|
|
''
|
|
(( 1 == "$(cat "$failed/testBuildFailure.exit")" ))
|
|
grep -F 'found 1 dangling symlinks, 0 reflexive symlinks and 0 unreadable symlinks' "$failed/testBuildFailure.log"
|
|
touch $out
|
|
'';
|
|
|
|
pass-dangling-symlink-relative-allowed = testBuilder {
|
|
name = "pass-dangling-symlink-relative-allowed";
|
|
commands = [ (mkDanglingSymlink false) ];
|
|
derivationArgs.dontCheckForBrokenSymlinks = true;
|
|
};
|
|
|
|
fail-dangling-symlink-absolute =
|
|
runCommand "fail-dangling-symlink-absolute"
|
|
{
|
|
failed = testBuildFailure (testBuilder {
|
|
name = "fail-dangling-symlink-absolute-inner";
|
|
commands = [ (mkDanglingSymlink true) ];
|
|
});
|
|
}
|
|
''
|
|
(( 1 == "$(cat "$failed/testBuildFailure.exit")" ))
|
|
grep -F 'found 1 dangling symlinks, 0 reflexive symlinks and 0 unreadable symlinks' "$failed/testBuildFailure.log"
|
|
touch $out
|
|
'';
|
|
|
|
pass-dangling-symlink-absolute-allowed = testBuilder {
|
|
name = "pass-dangling-symlink-absolute-allowed";
|
|
commands = [ (mkDanglingSymlink true) ];
|
|
derivationArgs.dontCheckForBrokenSymlinks = true;
|
|
};
|
|
|
|
fail-reflexive-symlink-relative =
|
|
runCommand "fail-reflexive-symlink-relative"
|
|
{
|
|
failed = testBuildFailure (testBuilder {
|
|
name = "fail-reflexive-symlink-relative-inner";
|
|
commands = [ (mkReflexiveSymlink false) ];
|
|
});
|
|
}
|
|
''
|
|
(( 1 == "$(cat "$failed/testBuildFailure.exit")" ))
|
|
grep -F 'found 0 dangling symlinks, 1 reflexive symlinks and 0 unreadable symlinks' "$failed/testBuildFailure.log"
|
|
touch $out
|
|
'';
|
|
|
|
pass-reflexive-symlink-relative-allowed = testBuilder {
|
|
name = "pass-reflexive-symlink-relative-allowed";
|
|
commands = [ (mkReflexiveSymlink false) ];
|
|
derivationArgs.dontCheckForBrokenSymlinks = true;
|
|
};
|
|
|
|
fail-reflexive-symlink-absolute =
|
|
runCommand "fail-reflexive-symlink-absolute"
|
|
{
|
|
failed = testBuildFailure (testBuilder {
|
|
name = "fail-reflexive-symlink-absolute-inner";
|
|
commands = [ (mkReflexiveSymlink true) ];
|
|
});
|
|
}
|
|
''
|
|
(( 1 == "$(cat "$failed/testBuildFailure.exit")" ))
|
|
grep -F 'found 0 dangling symlinks, 1 reflexive symlinks and 0 unreadable symlinks' "$failed/testBuildFailure.log"
|
|
touch $out
|
|
'';
|
|
|
|
pass-reflexive-symlink-absolute-allowed = testBuilder {
|
|
name = "pass-reflexive-symlink-absolute-allowed";
|
|
commands = [ (mkReflexiveSymlink true) ];
|
|
derivationArgs.dontCheckForBrokenSymlinks = true;
|
|
};
|
|
|
|
# Leave the unreadable symlink out of the combined 'broken' test since it doesn't work on all platforms.
|
|
fail-broken-symlinks-relative =
|
|
runCommand "fail-broken-symlinks-relative"
|
|
{
|
|
failed = testBuildFailure (testBuilder {
|
|
name = "fail-broken-symlinks-relative-inner";
|
|
commands = [
|
|
(mkDanglingSymlink false)
|
|
(mkReflexiveSymlink false)
|
|
];
|
|
});
|
|
}
|
|
''
|
|
(( 1 == "$(cat "$failed/testBuildFailure.exit")" ))
|
|
grep -F 'found 1 dangling symlinks, 1 reflexive symlinks and 0 unreadable symlinks' "$failed/testBuildFailure.log"
|
|
touch $out
|
|
'';
|
|
|
|
pass-broken-symlinks-relative-allowed = testBuilder {
|
|
name = "pass-broken-symlinks-relative-allowed";
|
|
commands = [
|
|
(mkDanglingSymlink false)
|
|
(mkReflexiveSymlink false)
|
|
];
|
|
derivationArgs.dontCheckForBrokenSymlinks = true;
|
|
};
|
|
|
|
fail-broken-symlinks-absolute =
|
|
runCommand "fail-broken-symlinks-absolute"
|
|
{
|
|
failed = testBuildFailure (testBuilder {
|
|
name = "fail-broken-symlinks-absolute-inner";
|
|
commands = [
|
|
(mkDanglingSymlink true)
|
|
(mkReflexiveSymlink true)
|
|
];
|
|
});
|
|
}
|
|
''
|
|
(( 1 == "$(cat "$failed/testBuildFailure.exit")" ))
|
|
grep -F 'found 1 dangling symlinks, 1 reflexive symlinks and 0 unreadable symlinks' "$failed/testBuildFailure.log"
|
|
touch $out
|
|
'';
|
|
|
|
pass-broken-symlinks-absolute-allowed = testBuilder {
|
|
name = "pass-broken-symlinks-absolute-allowed";
|
|
commands = [
|
|
(mkDanglingSymlink true)
|
|
(mkReflexiveSymlink true)
|
|
];
|
|
derivationArgs.dontCheckForBrokenSymlinks = true;
|
|
};
|
|
|
|
# The `all-broken` tests include unreadable symlinks along with the other kinds of broken links.
|
|
# They should be run/skipped on the same sets platforms as the corresponding `unreadable` tests.
|
|
# See below.
|
|
|
|
pass-valid-symlink-relative = testBuilder {
|
|
name = "pass-valid-symlink-relative";
|
|
commands = [ (mkValidSymlink false) ];
|
|
};
|
|
|
|
pass-valid-symlink-absolute = testBuilder {
|
|
name = "pass-valid-symlink-absolute";
|
|
commands = [ (mkValidSymlink true) ];
|
|
};
|
|
|
|
pass-valid-symlink-outside-nix-store-relative = testBuilder {
|
|
name = "pass-valid-symlink-outside-nix-store-relative";
|
|
commands = [ (mkValidSymlinkOutsideNixStore false) ];
|
|
};
|
|
|
|
pass-valid-symlink-outside-nix-store-absolute = testBuilder {
|
|
name = "pass-valid-symlink-outside-nix-store-absolute";
|
|
commands = [ (mkValidSymlinkOutsideNixStore true) ];
|
|
};
|
|
}
|
|
# Skip these tests if symlink permissions are not supported, since the hook won't have anything to report.
|
|
// lib.optionalAttrs hasSymlinkPermissions {
|
|
fail-unreadable-symlink-relative =
|
|
runCommand "fail-unreadable-symlink-relative"
|
|
{
|
|
failed = testBuildFailure (testBuilder {
|
|
name = "fail-unreadable-symlink-relative-inner";
|
|
commands = [ (mkUnreadableSymlink false) ];
|
|
});
|
|
}
|
|
''
|
|
(( 1 == "$(cat "$failed/testBuildFailure.exit")" ))
|
|
grep -F 'found 0 dangling symlinks, 0 reflexive symlinks and 1 unreadable symlinks' "$failed/testBuildFailure.log"
|
|
touch $out
|
|
'';
|
|
|
|
fail-unreadable-symlink-absolute =
|
|
runCommand "fail-unreadable-symlink-absolute"
|
|
{
|
|
failed = testBuildFailure (testBuilder {
|
|
name = "fail-unreadable-symlink-absolute-inner";
|
|
commands = [ (mkUnreadableSymlink true) ];
|
|
});
|
|
}
|
|
''
|
|
(( 1 == "$(cat "$failed/testBuildFailure.exit")" ))
|
|
grep -F 'found 0 dangling symlinks, 0 reflexive symlinks and 1 unreadable symlinks' "$failed/testBuildFailure.log"
|
|
touch $out
|
|
'';
|
|
|
|
fail-all-broken-symlinks-relative =
|
|
runCommand "fail-all-broken-symlinks-relative"
|
|
{
|
|
failed = testBuildFailure (testBuilder {
|
|
name = "fail-all-broken-symlinks-relative-inner";
|
|
commands = [
|
|
(mkDanglingSymlink false)
|
|
(mkReflexiveSymlink false)
|
|
(mkUnreadableSymlink false)
|
|
];
|
|
});
|
|
}
|
|
''
|
|
(( 1 == "$(cat "$failed/testBuildFailure.exit")" ))
|
|
if ! grep -F 'found 1 dangling symlinks, 1 reflexive symlinks and 1 unreadable symlinks' "$failed/testBuildFailure.log"; then
|
|
grep -F 'symlink permissions not supported' "$failed/testBuildFailure.log"
|
|
grep -F 'found 1 dangling symlinks, 1 reflexive symlinks and 0 unreadable symlinks' "$failed/testBuildFailure.log"
|
|
fi
|
|
touch $out
|
|
'';
|
|
|
|
fail-all-broken-symlinks-absolute =
|
|
runCommand "fail-all-broken-symlinks-absolute"
|
|
{
|
|
failed = testBuildFailure (testBuilder {
|
|
name = "fail-all-broken-symlinks-absolute-inner";
|
|
commands = [
|
|
(mkDanglingSymlink true)
|
|
(mkReflexiveSymlink true)
|
|
(mkUnreadableSymlink true)
|
|
];
|
|
});
|
|
}
|
|
''
|
|
(( 1 == "$(cat "$failed/testBuildFailure.exit")" ))
|
|
if ! grep -F 'found 1 dangling symlinks, 1 reflexive symlinks and 1 unreadable symlinks' "$failed/testBuildFailure.log"; then
|
|
grep -F 'symlink permissions not supported' "$failed/testBuildFailure.log"
|
|
grep -F 'found 1 dangling symlinks, 1 reflexive symlinks and 0 unreadable symlinks' "$failed/testBuildFailure.log"
|
|
fi
|
|
touch $out
|
|
'';
|
|
|
|
}
|
|
# These tests will break on platforms that do use symlink permissions, because even though this hook will be okay, later ones will error out.
|
|
# They should be safe to run on other platforms, just to make sure the hook isn't completely broken. It won't have anything to report, though.
|
|
// lib.optionalAttrs (!hasSymlinkPermissions) {
|
|
pass-unreadable-symlink-relative-allowed = testBuilder {
|
|
name = "pass-unreadable-symlink-relative-allowed";
|
|
commands = [ (mkUnreadableSymlink false) ];
|
|
derivationArgs.dontCheckForBrokenSymlinks = true;
|
|
};
|
|
|
|
pass-unreadable-symlink-absolute-allowed = testBuilder {
|
|
name = "pass-unreadable-symlink-absolute-allowed";
|
|
commands = [ (mkUnreadableSymlink true) ];
|
|
derivationArgs.dontCheckForBrokenSymlinks = true;
|
|
};
|
|
|
|
pass-all-broken-symlinks-relative-allowed = testBuilder {
|
|
name = "pass-all-broken-symlinks-relative-allowed";
|
|
commands = [
|
|
(mkDanglingSymlink false)
|
|
(mkReflexiveSymlink false)
|
|
(mkUnreadableSymlink false)
|
|
];
|
|
derivationArgs.dontCheckForBrokenSymlinks = true;
|
|
};
|
|
|
|
pass-all-broken-symlinks-absolute-allowed = testBuilder {
|
|
name = "pass-all-broken-symlinks-absolute-allowed";
|
|
commands = [
|
|
(mkDanglingSymlink true)
|
|
(mkReflexiveSymlink true)
|
|
(mkUnreadableSymlink true)
|
|
];
|
|
derivationArgs.dontCheckForBrokenSymlinks = true;
|
|
};
|
|
}
|