7b1632ec71
Adds a bunch (notably certain overlapping) tests for catchable situations. This should cover many scenarios, argument is catchable, element in argument is catchable, function returns catchable in the middle of the processing, etc. Co-authored-by: Aspen Smith <root@gws.fyi> Change-Id: Icd722cf8dbc91a24f45cd540a328711e5826f76c Reviewed-on: https://cl.tvl.fyi/c/depot/+/10621 Reviewed-by: aspen <root@gws.fyi> Tested-by: BuildkiteCI
223 lines
7.3 KiB
Nix
223 lines
7.3 KiB
Nix
# SPDX-License-Identifier: LGPL-2.1-only
|
|
# SPDX-FileCopyrightText: © 2022 The TVL Contributors
|
|
# SPDX-FileCopyrightText: © 2004-2022 The Nix Contributors
|
|
#
|
|
# Execute language tests found in tvix_tests and nix_tests
|
|
# using the C++ Nix implementation. Based on NixOS/nix:tests/lang.sh.
|
|
{ depot, pkgs, lib, ... }:
|
|
|
|
let
|
|
testRoot = ../eval/src/tests;
|
|
|
|
inherit (pkgs.buildPackages) nix nix_latest;
|
|
|
|
parseTest = dir: baseName:
|
|
let
|
|
tokens = builtins.match "(eval|parse)-(okay|fail).+\\.nix" baseName;
|
|
in
|
|
if tokens == null
|
|
then null
|
|
else {
|
|
type = builtins.elemAt tokens 0;
|
|
expectedSuccess = (builtins.elemAt tokens 1) == "okay";
|
|
fileName = "${dir}/${baseName}";
|
|
};
|
|
|
|
allLangTests =
|
|
lib.concatMap
|
|
(
|
|
dir:
|
|
lib.pipe
|
|
(builtins.readDir (testRoot + "/${dir}"))
|
|
[
|
|
builtins.attrNames
|
|
(builtins.map (parseTest dir))
|
|
(builtins.filter (t: t != null))
|
|
]
|
|
) [ "nix_tests" "nix_tests/notyetpassing" "tvix_tests" "tvix_tests/notyetpassing" ];
|
|
|
|
skippedLangTests = {
|
|
# TODO(sterni): set up NIX_PATH in sandbox
|
|
"eval-okay-search-path.nix" = true;
|
|
# Floating point precision differs between tvix and Nix
|
|
"eval-okay-fromjson.nix" = true;
|
|
# C++ Nix can't TCO
|
|
"eval-okay-tail-call-1.nix" = true;
|
|
# Ordering change after 2.3
|
|
"eval-okay-xml.nix" = [ nix ];
|
|
# Missing builtins in Nix 2.3
|
|
"eval-okay-ceil.nix" = [ nix ];
|
|
"eval-okay-floor-ceil.nix" = [ nix ];
|
|
"eval-okay-floor.nix" = [ nix ];
|
|
"eval-okay-groupBy.nix" = [ nix ];
|
|
"eval-okay-zipAttrsWith.nix" = [ nix ];
|
|
"eval-okay-builtins-group-by-propagate-catchable.nix" = [ nix ];
|
|
# Comparable lists are not in Nix 2.3
|
|
"eval-okay-sort.nix" = [ nix ];
|
|
"eval-okay-compare-lists.nix" = [ nix ];
|
|
"eval-okay-value-pointer-compare.nix" = [ nix ];
|
|
"eval-okay-builtins-genericClosure-pointer-equality.nix" = [ nix ];
|
|
"eval-okay-list-comparison.nix" = [ nix ];
|
|
# getAttrPos gains support for functionArgs-returned sets after 2.3
|
|
"eval-okay-getattrpos-functionargs.nix" = [ nix ];
|
|
# groupBy appeared (long) after 2.3
|
|
"eval-okay-builtins-groupby-thunk.nix" = [ nix ];
|
|
# import is no longer considered a curried primop in Nix > 2.3
|
|
"eval-okay-import-display.nix" = [ nix ];
|
|
# Cycle detection and formatting changed sometime after Nix 2.3
|
|
"eval-okay-cycle-display-cpp-nix-2.13.nix" = [ nix ];
|
|
# builtins.replaceStrings becomes lazier in Nix 2.16
|
|
"eval-okay-replacestrings.nix" = [ nix ];
|
|
# builtins.readFileType is added in Nix 2.15
|
|
"eval-okay-readFileType.nix" = [ nix ];
|
|
# builtins.fromTOML gains support for timestamps in Nix 2.16
|
|
"eval-okay-fromTOML-timestamps.nix" = [ nix ];
|
|
# identifier formatting changed in Nix 2.17 due to cppnix commit
|
|
# b72bc4a972fe568744d98b89d63adcd504cb586c
|
|
"eval-okay-identifier-formatting.nix" = [ nix ];
|
|
|
|
# Different catchable behavior between nix 2.3 and 2.18
|
|
"eval-okay-builtins-map-propagate-catchable.nix" = [ nix_latest ];
|
|
"eval-okay-builtins-gen-list-propagate-catchable.nix" = [ nix_latest ];
|
|
"eval-okay-builtins-replace-strings-propagate-catchable.nix" =
|
|
[ nix_latest ];
|
|
|
|
# TODO(sterni): support diffing working directory and home relative paths
|
|
# like C++ Nix test suite (using string replacement).
|
|
"eval-okay-path-antiquotation.nix" = true;
|
|
};
|
|
|
|
runCppNixLangTests = cpp-nix:
|
|
let
|
|
testCommand = { fileName, type, expectedSuccess, ... }:
|
|
let
|
|
testBase = lib.removeSuffix ".nix" fileName;
|
|
expFile =
|
|
let
|
|
possibleFiles =
|
|
builtins.filter
|
|
(path: builtins.pathExists (testRoot + "/${path}"))
|
|
(builtins.map
|
|
(ext: "${testBase}.${ext}")
|
|
[ "exp" "exp.xml" ]);
|
|
in
|
|
if possibleFiles == [ ] then null else builtins.head possibleFiles;
|
|
outFile = "${testBase}.out";
|
|
|
|
# Skip if skippedLangTests prescribes it (possibly just for the current nix)
|
|
# or if we are missing an exp file for an eval-okay test.
|
|
skip =
|
|
let
|
|
doSkip = skippedLangTests.${builtins.baseNameOf fileName} or false;
|
|
in
|
|
if type == "eval" && expectedSuccess && (expFile == null) then true
|
|
else if builtins.isBool doSkip then doSkip
|
|
else builtins.any (drv: cpp-nix == drv) doSkip;
|
|
|
|
flagsFile = "${testBase}.flags";
|
|
|
|
instantiateFlags =
|
|
lib.escapeShellArgs
|
|
(
|
|
[ "--${type}" fileName ]
|
|
++ lib.optionals (type == "eval") [ "--strict" ]
|
|
++ lib.optionals (expFile != null && lib.hasSuffix "xml" expFile)
|
|
[
|
|
"--no-location"
|
|
"--xml"
|
|
]
|
|
)
|
|
+ lib.optionalString (builtins.pathExists (testRoot + "/${flagsFile}"))
|
|
" $(cat '${flagsFile}')";
|
|
in
|
|
|
|
if skip
|
|
then "echo \"SKIP ${type} ${fileName}\"\n"
|
|
else ''
|
|
thisTestPassed=true
|
|
|
|
echo "RUN ${type} ${fileName} ${
|
|
lib.optionalString (!expectedSuccess) "(expecting failure)"
|
|
}"
|
|
|
|
if ! expect ${if expectedSuccess then "0" else "1"} \
|
|
nix-instantiate ${instantiateFlags} \
|
|
${if expectedSuccess then "1" else "2"}> \
|
|
${if expFile != null then outFile else "/dev/null"};
|
|
then
|
|
echo -n "FAIL"
|
|
thisTestPassed=false
|
|
fi
|
|
'' + lib.optionalString (expFile != null) ''
|
|
if ! diff --color=always -u '${outFile}' '${expFile}'; then
|
|
thisTestPassed=false
|
|
fi
|
|
'' + ''
|
|
if $thisTestPassed; then
|
|
echo -n "PASS"
|
|
else
|
|
echo -n "FAIL"
|
|
passed=false
|
|
fi
|
|
|
|
echo " ${type} ${fileName}"
|
|
|
|
unset thisTestPassed
|
|
'';
|
|
in
|
|
|
|
pkgs.stdenv.mkDerivation {
|
|
name = "cpp-${cpp-nix.name}-run-lang-tests";
|
|
|
|
nativeBuildInputs = [ cpp-nix ];
|
|
|
|
# Obtain tests via the unpackPhase
|
|
src = testRoot;
|
|
dontConfigure = true;
|
|
|
|
# Environment expected by the test suite
|
|
TEST_VAR = "foo";
|
|
|
|
buildPhase = ''
|
|
# Make nix-instantiate happy in the sandbox
|
|
export NIX_STORE_DIR="$(realpath "$(mktemp -d store.XXXXXXXXXX)")"
|
|
export NIX_STATE_DIR="$(realpath "$(mktemp -d state.XXXXXXXXXX)")"
|
|
|
|
# Helper function to check expected exit code
|
|
expect() {
|
|
local expected res
|
|
expected="$1"
|
|
shift
|
|
set +e
|
|
"$@"
|
|
res="$?"
|
|
set -e
|
|
[[ $res -eq $expected ]]
|
|
}
|
|
|
|
# Track test results so far
|
|
passed=true
|
|
|
|
source "$testCommandsPath"
|
|
'';
|
|
|
|
# Actually runs into the argv limit
|
|
passAsFile = [ "testCommands" ];
|
|
testCommands = lib.concatMapStrings testCommand allLangTests;
|
|
|
|
installPhase = ''
|
|
if $passed; then
|
|
touch $out
|
|
else
|
|
echo "Some test(s) failed!"
|
|
exit 1
|
|
fi
|
|
'';
|
|
};
|
|
|
|
in
|
|
|
|
depot.nix.readTree.drvTargets {
|
|
"nix-2.3" = runCppNixLangTests nix;
|
|
"nix-${lib.versions.majorMinor nix_latest.version}" = runCppNixLangTests nix_latest;
|
|
}
|