Merge pull request #328208 from tie/testers-equal-diffoscope

testers.testEqualContents: use diffoscope instead of diffing find output
This commit is contained in:
Robert Hensing 2024-07-20 21:24:10 +02:00 committed by GitHub
commit 2fc90534e0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 124 additions and 117 deletions

View File

@ -1,4 +1,4 @@
{ pkgs, pkgsLinux, buildPackages, lib, callPackage, runCommand, stdenv, substituteAll, testers }:
{ pkgs, pkgsLinux, buildPackages, diffoscopeMinimal, lib, callPackage, runCommand, stdenv, substituteAll, testers }:
# Documentation is in doc/build-helpers/testers.chapter.md
{
# See https://nixos.org/manual/nixpkgs/unstable/#tester-lycheeLinkCheck
@ -27,33 +27,22 @@
expected,
}: runCommand "equal-contents-${lib.strings.toLower assertion}" {
inherit assertion actual expected;
nativeBuildInputs = [ diffoscopeMinimal ];
} ''
echo "Checking:"
echo "$assertion"
if ! diff -U5 -r "$actual" "$expected" --color=always
printf '%s\n' "$assertion"
if ! diffoscope --no-progress --text-color=always --exclude-directory-metadata=no -- "$actual" "$expected"
then
echo
echo 'Contents must be equal, but were not!'
echo
echo "+: expected, at $expected"
echo "-: unexpected, at $actual"
exit 1
false
else
find "$expected" -type f -executable > expected-executables | sort
find "$actual" -type f -executable > actual-executables | sort
if ! diff -U0 actual-executables expected-executables --color=always
then
echo
echo "Contents must be equal, but some files' executable bits don't match"
echo
echo "+: make this file executable in the actual contents"
echo "-: make this file non-executable in the actual contents"
exit 1
else
echo "expected $expected and actual $actual match."
echo 'OK'
touch $out
fi
echo "expected $expected and actual $actual match."
echo OK
touch -- "$out"
fi
'';

View File

@ -1,4 +1,4 @@
{ testers, lib, pkgs, hello, runCommand, ... }:
{ testers, lib, pkgs, hello, runCommand, emptyFile, emptyDirectory, ... }:
let
pkgs-with-overlay = pkgs.extend(final: prev: {
proof-of-overlay-hello = prev.hello;
@ -99,117 +99,135 @@ lib.recurseIntoAttrs {
};
testEqualContents = lib.recurseIntoAttrs {
happy = testers.testEqualContents {
equalDir = testers.testEqualContents {
assertion = "The same directory contents at different paths are recognized as equal";
expected = runCommand "expected" {} ''
mkdir -p $out/c
echo a >$out/a
echo b >$out/b
echo d >$out/c/d
expected = runCommand "expected" { } ''
mkdir -p -- "$out/c"
echo a >"$out/a"
echo b >"$out/b"
echo d >"$out/c/d"
echo e >"$out/e"
chmod a+x -- "$out/e"
'';
actual = runCommand "actual" {} ''
mkdir -p $out/c
echo a >$out/a
echo b >$out/b
echo d >$out/c/d
actual = runCommand "actual" { } ''
mkdir -p -- "$out/c"
echo a >"$out/a"
echo b >"$out/b"
echo d >"$out/c/d"
echo e >"$out/e"
chmod a+x -- "$out/e"
'';
};
unequalExe =
runCommand "testEqualContents-unequalExe" {
log = testers.testBuildFailure (testers.testEqualContents {
assertion = "The same directory contents at different paths are recognized as equal";
expected = runCommand "expected" {} ''
mkdir -p $out/c
echo a >$out/a
chmod a+x $out/a
echo b >$out/b
echo d >$out/c/d
'';
actual = runCommand "actual" {} ''
mkdir -p $out/c
echo a >$out/a
echo b >$out/b
chmod a+x $out/b
echo d >$out/c/d
'';
});
} ''
(
set -x
grep -F -- "executable bits don't match" $log/testBuildFailure.log
grep -E -- '+.*-actual/a' $log/testBuildFailure.log
grep -E -- '-.*-actual/b' $log/testBuildFailure.log
grep -F -- "--- actual-executables" $log/testBuildFailure.log
grep -F -- "+++ expected-executables" $log/testBuildFailure.log
) || {
echo "Test failed: could not find pattern in build log $log"
exit 1
}
echo 'All good.'
touch $out
fileMissing = testers.testBuildFailure (
testers.testEqualContents {
assertion = "Directories with different file list are not recognized as equal";
expected = runCommand "expected" { } ''
mkdir -p -- "$out/c"
echo a >"$out/a"
echo b >"$out/b"
echo d >"$out/c/d"
'';
actual = runCommand "actual" { } ''
mkdir -p -- "$out/c"
echo a >"$out/a"
echo d >"$out/c/d"
'';
}
);
equalExe = testers.testEqualContents {
assertion = "The same executable file contents at different paths are recognized as equal";
expected = runCommand "expected" { } ''
echo test >"$out"
chmod a+x -- "$out"
'';
actual = runCommand "actual" { } ''
echo test >"$out"
chmod a+x -- "$out"
'';
};
unequalExe = testers.testBuildFailure (
testers.testEqualContents {
assertion = "Different file mode bits are not recognized as equal";
expected = runCommand "expected" { } ''
touch -- "$out"
chmod a+x -- "$out"
'';
actual = runCommand "actual" { } ''
touch -- "$out"
'';
}
);
unequalExeInDir = testers.testBuildFailure (
testers.testEqualContents {
assertion = "Different file mode bits are not recognized as equal in directory";
expected = runCommand "expected" { } ''
mkdir -p -- "$out/a"
echo b >"$out/b"
chmod a+x -- "$out/b"
'';
actual = runCommand "actual" { } ''
mkdir -p -- "$out/a"
echo b >"$out/b"
'';
}
);
nonExistentPath = testers.testBuildFailure (
testers.testEqualContents {
assertion = "Non existent paths are not recognized as equal";
expected = "${emptyDirectory}/foo";
actual = "${emptyDirectory}/bar";
}
);
emptyFileAndDir = testers.testBuildFailure (
testers.testEqualContents {
assertion = "Empty file and directory are not recognized as equal";
expected = emptyFile;
actual = emptyDirectory;
}
);
fileDiff =
runCommand "testEqualContents-fileDiff" {
log = testers.testBuildFailure (testers.testEqualContents {
assertion = "The same directory contents at different paths are recognized as equal";
expected = runCommand "expected" {} ''
mkdir -p $out/c
echo a >$out/a
echo b >$out/b
echo d >$out/c/d
'';
actual = runCommand "actual" {} ''
mkdir -p $out/c
echo a >$out/a
echo B >$out/b
echo d >$out/c/d
'';
});
} ''
let
log = testers.testBuildFailure (
testers.testEqualContents {
assertion = "Different files are not recognized as equal in subdirectories";
expected = runCommand "expected" { } ''
mkdir -p -- "$out/b"
echo a >"$out/a"
echo EXPECTED >"$out/b/c"
'';
actual = runCommand "actual" { } ''
mkdir -p "$out/b"
echo a >"$out/a"
echo ACTUAL >"$out/b/c"
'';
}
);
in
runCommand "testEqualContents-fileDiff" { inherit log; } ''
(
set -x
grep -F -- "Contents must be equal but were not" $log/testBuildFailure.log
grep -E -- '+++ .*-actual/b' $log/testBuildFailure.log
grep -E -- '--- .*-actual/b' $log/testBuildFailure.log
grep -F -- "-B" $log/testBuildFailure.log
grep -F -- "+b" $log/testBuildFailure.log
# Note: use `&&` operator to chain commands because errexit (set -e)
# does not work in this context (even when set explicitly and with
# inherit_errexit), otherwise the subshell exits with the status of
# the last run command and ignores preceding failures.
grep -F -- 'Contents must be equal, but were not!' "$log/testBuildFailure.log" &&
grep -E -- '\+\+\+ .*-expected/b/c' "$log/testBuildFailure.log" &&
grep -E -- '--- .*-actual/b/c' "$log/testBuildFailure.log" &&
grep -F -- -ACTUAL "$log/testBuildFailure.log" &&
grep -F -- +EXPECTED "$log/testBuildFailure.log"
) || {
echo "Test failed: could not find pattern in build log $log"
exit 1
false
}
echo 'All good.'
touch $out
'';
fileMissing =
runCommand "testEqualContents-fileMissing" {
log = testers.testBuildFailure (testers.testEqualContents {
assertion = "The same directory contents at different paths are recognized as equal";
expected = runCommand "expected" {} ''
mkdir -p $out/c
echo a >$out/a
echo b >$out/b
echo d >$out/c/d
'';
actual = runCommand "actual" {} ''
mkdir -p $out/c
echo a >$out/a
echo d >$out/c/d
'';
});
} ''
(
set -x
grep -F -- "Contents must be equal but were not" $log/testBuildFailure.log
grep -E -- 'Only in .*-expected: b' $log/testBuildFailure.log
) || {
echo "Test failed: could not find pattern in build log $log"
exit 1
}
echo 'All good.'
touch $out
touch -- "$out"
'';
};
}