diff options
author | Alyssa Ross <hi@alyssa.is> | 2023-06-16 06:56:35 +0000 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2023-06-16 06:56:35 +0000 |
commit | 99fcaeccb89621dd492203ce1f2d551c06f228ed (patch) | |
tree | 41cb730ae07383004789779b0f6e11cb3f4642a3 /nixpkgs/pkgs/build-support/testers | |
parent | 59c5f5ac8682acc13bb22bc29c7cf02f7d75f01f (diff) | |
parent | 75a5ebf473cd60148ba9aec0d219f72e5cf52519 (diff) | |
download | nixlib-99fcaeccb89621dd492203ce1f2d551c06f228ed.tar nixlib-99fcaeccb89621dd492203ce1f2d551c06f228ed.tar.gz nixlib-99fcaeccb89621dd492203ce1f2d551c06f228ed.tar.bz2 nixlib-99fcaeccb89621dd492203ce1f2d551c06f228ed.tar.lz nixlib-99fcaeccb89621dd492203ce1f2d551c06f228ed.tar.xz nixlib-99fcaeccb89621dd492203ce1f2d551c06f228ed.tar.zst nixlib-99fcaeccb89621dd492203ce1f2d551c06f228ed.zip |
Merge branch 'nixos-unstable' of https://github.com/NixOS/nixpkgs
Conflicts: nixpkgs/nixos/modules/config/console.nix nixpkgs/nixos/modules/services/mail/mailman.nix nixpkgs/nixos/modules/services/mail/public-inbox.nix nixpkgs/nixos/modules/services/mail/rss2email.nix nixpkgs/nixos/modules/services/networking/ssh/sshd.nix nixpkgs/pkgs/applications/networking/instant-messengers/dino/default.nix nixpkgs/pkgs/applications/networking/irc/weechat/default.nix nixpkgs/pkgs/applications/window-managers/sway/default.nix nixpkgs/pkgs/build-support/go/module.nix nixpkgs/pkgs/build-support/rust/build-rust-package/default.nix nixpkgs/pkgs/development/interpreters/python/default.nix nixpkgs/pkgs/development/node-packages/overrides.nix nixpkgs/pkgs/development/tools/b4/default.nix nixpkgs/pkgs/servers/dict/dictd-db.nix nixpkgs/pkgs/servers/mail/public-inbox/default.nix nixpkgs/pkgs/tools/security/pinentry/default.nix nixpkgs/pkgs/tools/text/unoconv/default.nix nixpkgs/pkgs/top-level/all-packages.nix
Diffstat (limited to 'nixpkgs/pkgs/build-support/testers')
6 files changed, 426 insertions, 3 deletions
diff --git a/nixpkgs/pkgs/build-support/testers/default.nix b/nixpkgs/pkgs/build-support/testers/default.nix index 020352836c89..190ce72d0e63 100644 --- a/nixpkgs/pkgs/build-support/testers/default.nix +++ b/nixpkgs/pkgs/build-support/testers/default.nix @@ -1,8 +1,60 @@ -{ pkgs, lib, callPackage, runCommand, stdenv }: +{ pkgs, buildPackages, lib, callPackage, runCommand, stdenv, substituteAll, }: # Documentation is in doc/builders/testers.chapter.md { + # See https://nixos.org/manual/nixpkgs/unstable/#tester-testBuildFailure + # or doc/builders/testers.chapter.md + testBuildFailure = drv: drv.overrideAttrs (orig: { + builder = buildPackages.bash; + args = [ + (substituteAll { coreutils = buildPackages.coreutils; src = ./expect-failure.sh; }) + orig.realBuilder or stdenv.shell + ] ++ orig.args or ["-e" (orig.builder or ../../stdenv/generic/default-builder.sh)]; + }); + + # See https://nixos.org/manual/nixpkgs/unstable/#tester-testEqualDerivation + # or doc/builders/testers.chapter.md 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 + ''; + + # See https://nixos.org/manual/nixpkgs/unstable/#tester-testVersion + # or doc/builders/testers.chapter.md testVersion = { package, command ? "${package.meta.mainProgram or package.pname or package.name} --version", @@ -43,6 +95,20 @@ in checked; # See doc/builders/testers.chapter.md or + # https://nixos.org/manual/nixpkgs/unstable/#tester-runNixOSTest + runNixOSTest = + let nixos = import ../../../nixos/lib {}; + in testModule: + nixos.runTest { + _file = "pkgs.runNixOSTest implementation"; + imports = [ + (lib.setDefaultModuleLocation "the argument that was passed to pkgs.runNixOSTest" testModule) + ]; + hostPkgs = pkgs; + node.pkgs = pkgs; + }; + + # See doc/builders/testers.chapter.md or # https://nixos.org/manual/nixpkgs/unstable/#tester-invalidateFetcherByDrvHash nixosTest = let @@ -67,6 +133,9 @@ else test; calledTest = lib.toFunction loadedTest pkgs; in - nixosTesting.makeTest calledTest; + nixosTesting.simpleTest calledTest; + + hasPkgConfigModule = callPackage ./hasPkgConfigModule/tester.nix { }; + testMetaPkgConfig = callPackage ./testMetaPkgConfig/tester.nix { }; } diff --git a/nixpkgs/pkgs/build-support/testers/expect-failure.sh b/nixpkgs/pkgs/build-support/testers/expect-failure.sh new file mode 100644 index 000000000000..9c725d48bf34 --- /dev/null +++ b/nixpkgs/pkgs/build-support/testers/expect-failure.sh @@ -0,0 +1,71 @@ +# Run a builder, flip exit code, save log and fix outputs +# +# Sub-goals: +# - Delegate to another original builder passed via args +# - Save the build log to output for further checks +# - Make the derivation succeed if the original builder fails +# - Make the derivation fail if the original builder returns exit code 0 +# +# Requirements: +# This runs before, without and after stdenv. Do not modify the environment; +# especially not before invoking the original builder. For example, use +# "@" substitutions instead of PATH. +# Do not export any variables. + +# Stricter bash +set -eu + +# ------------------------ +# Run the original builder + +echo "testBuildFailure: Expecting non-zero exit from builder and args: ${*@Q}" + +("$@" 2>&1) | @coreutils@/bin/tee $TMPDIR/testBuildFailure.log \ + | while IFS= read -r ln; do + echo "original builder: $ln" + done + +r=${PIPESTATUS[0]} +if [[ $r = 0 ]]; then + echo "testBuildFailure: The builder did not fail, but a failure was expected!" + exit 1 +fi +echo "testBuildFailure: Original builder produced exit code: $r" + +# ----------------------------------------- +# Write the build log to the default output +# +# # from stdenv setup.sh +getAllOutputNames() { + if [ -n "$__structuredAttrs" ]; then + echo "${!outputs[*]}" + else + echo "$outputs" + fi +} + +outs=( $(getAllOutputNames) ) +defOut=${outs[0]} +defOutPath=${!defOut} + +if [[ ! -d $defOutPath ]]; then + if [[ -e $defOutPath ]]; then + @coreutils@/bin/mv $defOutPath $TMPDIR/out-node + @coreutils@/bin/mkdir $defOutPath + @coreutils@/bin/mv $TMPDIR/out-node $defOutPath/result + fi +fi + +@coreutils@/bin/mkdir -p $defOutPath +@coreutils@/bin/mv $TMPDIR/testBuildFailure.log $defOutPath/testBuildFailure.log +echo $r >$defOutPath/testBuildFailure.exit + +# ------------------------------------------------------ +# Put empty directories in place for any missing outputs + +for outputName in ${outputs:-out}; do + outputPath="${!outputName}" + if [[ ! -e "${outputPath}" ]]; then + @coreutils@/bin/mkdir "${outputPath}"; + fi +done diff --git a/nixpkgs/pkgs/build-support/testers/hasPkgConfigModule/tester.nix b/nixpkgs/pkgs/build-support/testers/hasPkgConfigModule/tester.nix new file mode 100644 index 000000000000..c8342cdd5c3b --- /dev/null +++ b/nixpkgs/pkgs/build-support/testers/hasPkgConfigModule/tester.nix @@ -0,0 +1,47 @@ +# Static arguments +{ runCommand, pkg-config }: + +# Tester arguments +{ package, + moduleName, + testName ? "check-pkg-config-${moduleName}", +}: + +runCommand testName { + nativeBuildInputs = [ pkg-config ]; + buildInputs = [ package ]; + inherit moduleName; + meta = { + description = "Test whether ${package.name} exposes pkg-config module ${moduleName}"; + } + # Make sure licensing info etc is preserved, as this is a concern for e.g. cache.nixos.org, + # as hydra can't check this meta info in dependencies. + # The test itself is just Nixpkgs, with MIT license. + // builtins.intersectAttrs + { + available = throw "unused"; + broken = throw "unused"; + insecure = throw "unused"; + license = throw "unused"; + maintainers = throw "unused"; + platforms = throw "unused"; + unfree = throw "unused"; + unsupported = throw "unused"; + } + package.meta; + } '' + echo "checking pkg-config module $moduleName in $buildInputs" + set +e + version="$(pkg-config --modversion $moduleName)" + r=$? + set -e + if [[ $r = 0 ]]; then + echo "✅ pkg-config module $moduleName exists and has version $version" + echo "$version" > $out + else + echo "These modules were available in the input propagation closure:" + pkg-config --list-all + echo "❌ pkg-config module $moduleName was not found" + false + fi + '' diff --git a/nixpkgs/pkgs/build-support/testers/hasPkgConfigModule/tests.nix b/nixpkgs/pkgs/build-support/testers/hasPkgConfigModule/tests.nix new file mode 100644 index 000000000000..8005c3f93709 --- /dev/null +++ b/nixpkgs/pkgs/build-support/testers/hasPkgConfigModule/tests.nix @@ -0,0 +1,36 @@ +# cd nixpkgs +# nix-build -A tests.testers.hasPkgConfigModule +{ lib, testers, zlib, runCommand }: + +lib.recurseIntoAttrs { + + zlib-has-zlib = testers.hasPkgConfigModule { + package = zlib; + moduleName = "zlib"; + }; + + zlib-does-not-have-ylib = runCommand "zlib-does-not-have-ylib" { + failed = testers.testBuildFailure ( + testers.hasPkgConfigModule { + package = zlib; + moduleName = "ylib"; + } + ); + } '' + echo 'it logs a relevant error message' + { + grep -F "pkg-config module ylib was not found" $failed/testBuildFailure.log + } + + echo 'it logs which pkg-config modules are available, to be helpful' + { + # grep -v: the string zlib does also occur in a store path in an earlier message, which isn't particularly helpful + grep -v "checking pkg-config module" < $failed/testBuildFailure.log \ + | grep -F "zlib" + } + + # done + touch $out + ''; + +} diff --git a/nixpkgs/pkgs/build-support/testers/test/default.nix b/nixpkgs/pkgs/build-support/testers/test/default.nix index 30e778cf652e..fc4df4964f39 100644 --- a/nixpkgs/pkgs/build-support/testers/test/default.nix +++ b/nixpkgs/pkgs/build-support/testers/test/default.nix @@ -1,4 +1,4 @@ -{ testers, lib, pkgs, ... }: +{ testers, lib, pkgs, hello, runCommand, ... }: let pkgs-with-overlay = pkgs.extend(final: prev: { proof-of-overlay-hello = prev.hello; @@ -12,6 +12,19 @@ let in lib.recurseIntoAttrs { + hasPkgConfigModule = pkgs.callPackage ../hasPkgConfigModule/tests.nix { }; + + runNixOSTest-example = pkgs-with-overlay.testers.runNixOSTest ({ lib, ... }: { + name = "runNixOSTest-test"; + nodes.machine = { pkgs, ... }: { + system.nixos = dummyVersioning; + environment.systemPackages = [ pkgs.proof-of-overlay-hello pkgs.figlet ]; + }; + testScript = '' + machine.succeed("hello | figlet >/dev/console") + ''; + }); + # Check that the wiring of nixosTest is correct. # Correct operation of the NixOS test driver should be asserted elsewhere. nixosTest-example = pkgs-with-overlay.testers.nixosTest ({ lib, pkgs, figlet, ... }: { @@ -24,4 +37,177 @@ lib.recurseIntoAttrs { machine.succeed("hello | figlet >/dev/console") ''; }); + + testBuildFailure = lib.recurseIntoAttrs { + happy = runCommand "testBuildFailure-happy" { + failed = testers.testBuildFailure (runCommand "fail" {} '' + echo ok-ish >$out + + echo failing though + echo also stderr 1>&2 + echo 'line\nwith-\bbackslashes' + printf "incomplete line - no newline" + + exit 3 + ''); + } '' + grep -F 'ok-ish' $failed/result + + grep -F 'failing though' $failed/testBuildFailure.log + grep -F 'also stderr' $failed/testBuildFailure.log + grep -F 'line\nwith-\bbackslashes' $failed/testBuildFailure.log + grep -F 'incomplete line - no newline' $failed/testBuildFailure.log + + [[ 3 = $(cat $failed/testBuildFailure.exit) ]] + + touch $out + ''; + + helloDoesNotFail = runCommand "testBuildFailure-helloDoesNotFail" { + failed = testers.testBuildFailure (testers.testBuildFailure hello); + + # Add hello itself as a prerequisite, so we don't try to run this test if + # there's an actual failure in hello. + inherit hello; + } '' + echo "Checking $failed/testBuildFailure.log" + grep -F 'testBuildFailure: The builder did not fail, but a failure was expected' $failed/testBuildFailure.log >/dev/null + [[ 1 = $(cat $failed/testBuildFailure.exit) ]] + touch $out + echo 'All good.' + ''; + + multiOutput = runCommand "testBuildFailure-multiOutput" { + failed = testers.testBuildFailure (runCommand "fail" { + # dev will be the default output + outputs = ["dev" "doc" "out"]; + } '' + echo i am failing + exit 1 + ''); + } '' + grep -F 'i am failing' $failed/testBuildFailure.log >/dev/null + [[ 1 = $(cat $failed/testBuildFailure.exit) ]] + + # 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 + ''; + }; } diff --git a/nixpkgs/pkgs/build-support/testers/testMetaPkgConfig/tester.nix b/nixpkgs/pkgs/build-support/testers/testMetaPkgConfig/tester.nix new file mode 100644 index 000000000000..bee97ace1409 --- /dev/null +++ b/nixpkgs/pkgs/build-support/testers/testMetaPkgConfig/tester.nix @@ -0,0 +1,14 @@ +{ lib, runCommand, testers }: + +package: + +runCommand "check-meta-pkg-config-modules-for-${package.name}" { + meta = { + description = "Test whether ${package.name} exposes all pkg-config modules ${toString package.meta.pkgConfigModules}"; + }; + dependsOn = map + (moduleName: testers.hasPkgConfigModule { inherit package moduleName; }) + package.meta.pkgConfigModules; +} '' + echo "found all of ${toString package.meta.pkgConfigModules}" > "$out" +'' |