testers.testEqualContents: init

Changed files
+177 -1
doc
pkgs
build-support
testers
+24
doc/builders/testers.chapter.md
···
`buildPackages.coreutils` and possibly more. These are not added to `PATH`
or any other environment variable, so they should be hard to observe.
+
## `testEqualContents` {#tester-equalContents}
+
+
Check that two paths have the same contents.
+
+
Example:
+
+
```nix
+
testers.testEqualContents {
+
assertion = "sed -e performs replacement";
+
expected = writeText "expected" ''
+
foo baz baz
+
'';
+
actual = runCommand "actual" {
+
# not really necessary for a package that's in stdenv
+
nativeBuildInputs = [ gnused ];
+
base = writeText "base" ''
+
foo bar baz
+
'';
+
} ''
+
sed -e 's/bar/baz/g' $base >$out
+
'';
+
}
+
```
+
## `testEqualDerivation` {#tester-testEqualDerivation}
Checks that two packages produce the exact same build instructions.
+38
pkgs/build-support/testers/default.nix
···
testEqualDerivation = callPackage ./test-equal-derivation.nix { };
+
# See https://nixos.org/manual/nixpkgs/unstable/#tester-testEqualContents
+
# or doc/builders/testers.chapter.md
+
testEqualContents = {
+
assertion,
+
actual,
+
expected,
+
}: runCommand "equal-contents-${lib.strings.toLower assertion}" {
+
inherit assertion actual expected;
+
} ''
+
echo "Checking:"
+
echo "$assertion"
+
if ! diff -U5 -r "$actual" "$expected" --color=always
+
then
+
echo
+
echo 'Contents must be equal, but were not!'
+
echo
+
echo "+: expected, at $expected"
+
echo "-: unexpected, at $actual"
+
exit 1
+
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
+
fi
+
'';
+
testVersion =
{ package,
command ? "${package.meta.mainProgram or package.pname or package.name} --version",
+115 -1
pkgs/build-support/testers/test/default.nix
···
# Checking our note that dev is the default output
echo $failed/_ | grep -- '-dev/_' >/dev/null
-
+
echo 'All good.'
touch $out
'';
};
+
testEqualContents = lib.recurseIntoAttrs {
+
happy = 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
+
'';
+
};
+
+
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
+
'';
+
+
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
+
'';
+
});
+
} ''
+
(
+
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
+
) || {
+
echo "Test failed: could not find pattern in build log $log"
+
exit 1
+
}
+
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
+
'';
+
};
}