2022-08-16 14:33:50 +02:00
|
|
|
use pretty_assertions::assert_eq;
|
2022-08-10 17:53:50 +02:00
|
|
|
|
|
|
|
use test_generator::test_resources;
|
|
|
|
|
2022-10-13 05:07:18 +02:00
|
|
|
fn eval_test(code_path: &str, expect_success: bool) {
|
2022-08-10 19:02:05 +02:00
|
|
|
let base = code_path
|
|
|
|
.strip_suffix("nix")
|
|
|
|
.expect("test files always end in .nix");
|
|
|
|
let exp_path = format!("{}exp", base);
|
2022-10-19 19:19:03 +02:00
|
|
|
let exp_xml_path = std::path::PathBuf::from(format!("{}exp.xml", base));
|
2022-08-10 19:02:05 +02:00
|
|
|
|
|
|
|
let code = std::fs::read_to_string(code_path).expect("should be able to read test code");
|
|
|
|
|
2022-10-19 19:19:03 +02:00
|
|
|
if exp_xml_path.exists() {
|
|
|
|
// We can't test them at the moment because we don't have XML output yet.
|
|
|
|
// Checking for success / failure only is a bit disingenious.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
refactor(tvix/eval): streamline construction of globals/builtins
Previously the construction of globals (a compiler-only concept) and
builtins (a (now) user-facing API) was intermingled between multiple
different modules, and kind of difficult to understand.
The complexity of this had grown in large part due to the
implementation of `builtins.import`, which required the notorious
"knot-tying" trick using Rc::new_cyclic (see cl/7097) for constructing
the set of globals.
As part of the new `Evaluation` API users should have the ability to
bring their own builtins, and control explicitly whether or not impure
builtins are available (regardless of whether they're compiled in or
not).
To streamline the construction and allow the new API features to work,
this commit restructures things by making these changes:
1. The `tvix_eval::builtins` module is now only responsible for
exporting sets of builtins. It no longer has any knowledge of
whether or not certain sets (e.g. only pure, or pure+impure) are
enabled, and it has no control over which builtins are globally
available (this is now handled in the compiler).
2. The compiler module is now responsible for both constructing the
final attribute set of builtins from the set of builtins supplied
by a user, as well as for populating its globals (that is
identifiers which are available at the top-level scope).
3. The `Evaluation` API now carries a `builtins` field which is
populated with the pure builtins by default, and can be extended by
users.
4. The `import` feature has been moved into the compiler, as a
special case. In general, builtins no longer have the ability to
reference the "fix point" of the globals set.
This should not change any functionality, and in fact preserves minor
differences between Tvix/Nix that we already had (such as
`builtins.builtins` not existing).
Change-Id: Icdf5dd50eb81eb9260d89269d6e08b1e67811a2c
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7738
Reviewed-by: sterni <sternenseemann@systemli.org>
Autosubmit: tazjin <tazjin@tvl.su>
Tested-by: BuildkiteCI
Reviewed-by: flokli <flokli@flokli.de>
2023-01-03 20:30:49 +01:00
|
|
|
let eval = crate::Evaluation::new_impure(&code, Some(code_path.into()));
|
2022-12-12 15:38:28 +01:00
|
|
|
|
|
|
|
let result = eval.evaluate();
|
2022-12-08 22:31:45 +01:00
|
|
|
|
|
|
|
if expect_success && !result.errors.is_empty() {
|
|
|
|
panic!(
|
|
|
|
"{code_path}: evaluation of eval-okay test should succeed, but failed with {:?}",
|
|
|
|
result.errors,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if !expect_success && !result.errors.is_empty() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let result_str = result.value.unwrap().to_string();
|
|
|
|
|
|
|
|
if let Ok(exp) = std::fs::read_to_string(exp_path) {
|
|
|
|
if expect_success {
|
|
|
|
assert_eq!(
|
|
|
|
result_str,
|
|
|
|
exp.trim(),
|
|
|
|
"{code_path}: result value representation (left) must match expectation (right)"
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
assert_ne!(
|
|
|
|
result_str,
|
|
|
|
exp.trim(),
|
|
|
|
"{code_path}: test passed unexpectedly! consider moving it out of notyetpassing"
|
|
|
|
);
|
2022-10-13 05:07:18 +02:00
|
|
|
}
|
2022-12-20 15:22:56 +01:00
|
|
|
} else if expect_success {
|
|
|
|
panic!("{code_path}: should be able to read test expectation");
|
2022-12-08 22:31:45 +01:00
|
|
|
} else {
|
2022-12-20 15:22:56 +01:00
|
|
|
panic!(
|
|
|
|
"{code_path}: test should have failed, but succeeded with output {}",
|
|
|
|
result_str
|
|
|
|
);
|
2022-10-13 05:07:18 +02:00
|
|
|
}
|
2022-08-10 19:02:05 +02:00
|
|
|
}
|
|
|
|
|
2022-08-10 18:31:18 +02:00
|
|
|
// identity-* tests contain Nix code snippets which should evaluate to
|
|
|
|
// themselves exactly (i.e. literals).
|
|
|
|
#[test_resources("src/tests/tvix_tests/identity-*.nix")]
|
|
|
|
fn identity(code_path: &str) {
|
|
|
|
let code = std::fs::read_to_string(code_path).expect("should be able to read test code");
|
|
|
|
|
2022-12-12 15:38:28 +01:00
|
|
|
let mut eval = crate::Evaluation::new(&code, None);
|
|
|
|
eval.io_handle = Box::new(crate::StdIO);
|
|
|
|
|
|
|
|
let result = eval.evaluate();
|
2022-12-08 22:31:45 +01:00
|
|
|
assert!(
|
|
|
|
result.errors.is_empty(),
|
|
|
|
"evaluation of identity test failed: {:?}",
|
|
|
|
result.errors
|
|
|
|
);
|
|
|
|
|
|
|
|
let result_str = result.value.unwrap().to_string();
|
2022-08-10 18:31:18 +02:00
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
result_str,
|
2022-08-16 14:33:50 +02:00
|
|
|
code.trim(),
|
|
|
|
"result value representation (left) must match expectation (right)"
|
2022-08-10 18:31:18 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-08-10 17:53:50 +02:00
|
|
|
// eval-okay-* tests contain a snippet of Nix code, and an expectation
|
|
|
|
// of the produced string output of the evaluator.
|
|
|
|
//
|
|
|
|
// These evaluations are always supposed to succeed, i.e. all snippets
|
|
|
|
// are guaranteed to be valid Nix code.
|
2022-08-10 19:02:05 +02:00
|
|
|
#[test_resources("src/tests/tvix_tests/eval-okay-*.nix")]
|
|
|
|
fn eval_okay(code_path: &str) {
|
2022-10-13 05:07:18 +02:00
|
|
|
eval_test(code_path, true)
|
2022-08-10 19:02:05 +02:00
|
|
|
}
|
2022-08-10 18:31:18 +02:00
|
|
|
|
2022-10-18 06:31:36 +02:00
|
|
|
// eval-okay-* tests from the original Nix test suite.
|
2022-08-10 18:18:01 +02:00
|
|
|
#[cfg(feature = "nix_tests")]
|
2022-08-10 17:53:50 +02:00
|
|
|
#[test_resources("src/tests/nix_tests/eval-okay-*.nix")]
|
2022-08-10 18:31:18 +02:00
|
|
|
fn nix_eval_okay(code_path: &str) {
|
2022-10-13 05:07:18 +02:00
|
|
|
eval_test(code_path, true)
|
|
|
|
}
|
|
|
|
|
2022-10-18 06:31:36 +02:00
|
|
|
// eval-okay-* tests from the original Nix test suite which do not yet pass for tvix
|
|
|
|
//
|
|
|
|
// Eventually there will be none of these left, and this function
|
|
|
|
// will disappear :) Until then, to run these tests, use `cargo test
|
|
|
|
// --features expected_failures`.
|
|
|
|
//
|
|
|
|
// Please don't submit failing tests unless they're in
|
|
|
|
// notyetpassing; this makes the test suite much more useful for
|
|
|
|
// regression testing, since there should always be zero non-ignored
|
|
|
|
// failing tests.
|
|
|
|
//
|
|
|
|
// Unfortunately test_generator is unmaintained, so the PRs to make
|
|
|
|
// it understand #[ignored] has been sitting for two years, so we
|
|
|
|
// can't use `cargo test --include-ignored`, which is the normal way
|
|
|
|
// of handling this situation.
|
|
|
|
//
|
|
|
|
// https://github.com/frehberg/test-generator/pull/10
|
|
|
|
// https://github.com/frehberg/test-generator/pull/8
|
|
|
|
#[test_resources("src/tests/nix_tests/notyetpassing/eval-okay-*.nix")]
|
|
|
|
fn nix_eval_okay_currently_failing(code_path: &str) {
|
|
|
|
eval_test(code_path, false)
|
|
|
|
}
|
|
|
|
|
2023-01-04 13:41:22 +01:00
|
|
|
#[test_resources("src/tests/tvix_tests/notyetpassing/eval-okay-*.nix")]
|
|
|
|
fn eval_okay_currently_failing(code_path: &str) {
|
|
|
|
eval_test(code_path, false)
|
|
|
|
}
|
|
|
|
|
2022-10-13 05:07:18 +02:00
|
|
|
// eval-fail-* tests contain a snippet of Nix code, which is
|
|
|
|
// expected to fail evaluation. The exact type of failure
|
|
|
|
// (assertion, parse error, etc) is not currently checked.
|
|
|
|
#[test_resources("src/tests/tvix_tests/eval-fail-*.nix")]
|
|
|
|
fn eval_fail(code_path: &str) {
|
|
|
|
eval_test(code_path, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
// eval-fail-* tests from the original Nix test suite.
|
|
|
|
#[cfg(feature = "nix_tests")]
|
|
|
|
#[test_resources("src/tests/nix_tests/eval-fail-*.nix")]
|
|
|
|
fn nix_eval_fail(code_path: &str) {
|
|
|
|
eval_test(code_path, false)
|
2022-08-10 17:53:50 +02:00
|
|
|
}
|