diff options
author | John Ericson <John.Ericson@Obsidian.Systems> | 2023-08-25 10:20:28 -0400 |
---|---|---|
committer | John Ericson <John.Ericson@Obsidian.Systems> | 2023-12-01 13:05:03 -0500 |
commit | f7f37035c81fa825a4dfc2df1ad2589013ac6380 (patch) | |
tree | bfcfef3efeb73cb0c3c6d812280191d03bda1233 /src/libexpr | |
parent | 30dcc19d1f30fc203be460134c4578509cce704f (diff) |
Move tests to separate directories, and document
Today, with the tests inside a `tests` intermingled with the
corresponding library's source code, we have a few problems:
- We have to be careful that wildcards don't end up with tests being
built as part of Nix proper, or test headers being installed as part
of Nix proper.
- Tests in libraries but not executables is not right:
- It means each executable runs the previous unit tests again, because
it needs the libraries.
- It doesn't work right on Windows, which doesn't want you to load a
DLL just for the side global variable . It could be made to work
with the dlopen equivalent, but that's gross!
This reorg solves these problems.
There is a remaining problem which is that sibbling headers (like
`hash.hh` the test header vs `hash.hh` the main `libnixutil` header) end
up shadowing each other. This PR doesn't solve that. That is left as
future work for a future PR.
Co-authored-by: Valentin Gagarin <valentin.gagarin@tweag.io>
(cherry picked from commit 91b6833686a6a6d9eac7f3f66393ec89ef1d3b57)
(cherry picked from commit a61e42adb528b3d40ce43e07c79368d779a8b624)
Diffstat (limited to 'src/libexpr')
-rw-r--r-- | src/libexpr/tests/derived-path.cc | 68 | ||||
-rw-r--r-- | src/libexpr/tests/error_traces.cc | 1298 | ||||
-rw-r--r-- | src/libexpr/tests/flakeref.cc | 22 | ||||
-rw-r--r-- | src/libexpr/tests/json.cc | 68 | ||||
-rw-r--r-- | src/libexpr/tests/libexpr.hh | 140 | ||||
-rw-r--r-- | src/libexpr/tests/local.mk | 19 | ||||
-rw-r--r-- | src/libexpr/tests/primops.cc | 832 | ||||
-rw-r--r-- | src/libexpr/tests/search-path.cc | 90 | ||||
-rw-r--r-- | src/libexpr/tests/trivial.cc | 196 | ||||
-rw-r--r-- | src/libexpr/tests/value/context.cc | 162 | ||||
-rw-r--r-- | src/libexpr/tests/value/context.hh | 31 | ||||
-rw-r--r-- | src/libexpr/tests/value/print.cc | 236 |
12 files changed, 0 insertions, 3162 deletions
diff --git a/src/libexpr/tests/derived-path.cc b/src/libexpr/tests/derived-path.cc deleted file mode 100644 index d5fc6f201..000000000 --- a/src/libexpr/tests/derived-path.cc +++ /dev/null @@ -1,68 +0,0 @@ -#include <nlohmann/json.hpp> -#include <gtest/gtest.h> -#include <rapidcheck/gtest.h> - -#include "tests/derived-path.hh" -#include "tests/libexpr.hh" - -namespace nix { - -// Testing of trivial expressions -class DerivedPathExpressionTest : public LibExprTest {}; - -// FIXME: `RC_GTEST_FIXTURE_PROP` isn't calling `SetUpTestSuite` because it is -// no a real fixture. -// -// See https://github.com/emil-e/rapidcheck/blob/master/doc/gtest.md#rc_gtest_fixture_propfixture-name-args -TEST_F(DerivedPathExpressionTest, force_init) -{ -} - -#ifndef COVERAGE - -RC_GTEST_FIXTURE_PROP( - DerivedPathExpressionTest, - prop_opaque_path_round_trip, - (const SingleDerivedPath::Opaque & o)) -{ - auto * v = state.allocValue(); - state.mkStorePathString(o.path, *v); - auto d = state.coerceToSingleDerivedPath(noPos, *v, ""); - RC_ASSERT(SingleDerivedPath { o } == d); -} - -// TODO use DerivedPath::Built for parameter once it supports a single output -// path only. - -RC_GTEST_FIXTURE_PROP( - DerivedPathExpressionTest, - prop_derived_path_built_placeholder_round_trip, - (const SingleDerivedPath::Built & b)) -{ - /** - * We set these in tests rather than the regular globals so we don't have - * to worry about race conditions if the tests run concurrently. - */ - ExperimentalFeatureSettings mockXpSettings; - mockXpSettings.set("experimental-features", "ca-derivations"); - - auto * v = state.allocValue(); - state.mkOutputString(*v, b, std::nullopt, mockXpSettings); - auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, ""); - RC_ASSERT(SingleDerivedPath { b } == d); -} - -RC_GTEST_FIXTURE_PROP( - DerivedPathExpressionTest, - prop_derived_path_built_out_path_round_trip, - (const SingleDerivedPath::Built & b, const StorePath & outPath)) -{ - auto * v = state.allocValue(); - state.mkOutputString(*v, b, outPath); - auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, ""); - RC_ASSERT(SingleDerivedPath { b } == d); -} - -#endif - -} /* namespace nix */ diff --git a/src/libexpr/tests/error_traces.cc b/src/libexpr/tests/error_traces.cc deleted file mode 100644 index 285651256..000000000 --- a/src/libexpr/tests/error_traces.cc +++ /dev/null @@ -1,1298 +0,0 @@ -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include "tests/libexpr.hh" - -namespace nix { - - using namespace testing; - - // Testing eval of PrimOp's - class ErrorTraceTest : public LibExprTest { }; - - TEST_F(ErrorTraceTest, TraceBuilder) { - ASSERT_THROW( - state.error("Not much").debugThrow<EvalError>(), - EvalError - ); - - ASSERT_THROW( - state.error("Not much").withTrace(noPos, "No more").debugThrow<EvalError>(), - EvalError - ); - - ASSERT_THROW( - try { - try { - state.error("Not much").withTrace(noPos, "No more").debugThrow<EvalError>(); - } catch (Error & e) { - e.addTrace(state.positions[noPos], "Something", ""); - throw; - } - } catch (BaseError & e) { - ASSERT_EQ(PrintToString(e.info().msg), - PrintToString(hintfmt("Not much"))); - auto trace = e.info().traces.rbegin(); - ASSERT_EQ(e.info().traces.size(), 2); - ASSERT_EQ(PrintToString(trace->hint), - PrintToString(hintfmt("No more"))); - trace++; - ASSERT_EQ(PrintToString(trace->hint), - PrintToString(hintfmt("Something"))); - throw; - } - , EvalError - ); - } - - TEST_F(ErrorTraceTest, NestedThrows) { - try { - state.error("Not much").withTrace(noPos, "No more").debugThrow<EvalError>(); - } catch (BaseError & e) { - try { - state.error("Not much more").debugThrow<EvalError>(); - } catch (Error & e2) { - e.addTrace(state.positions[noPos], "Something", ""); - //e2.addTrace(state.positions[noPos], "Something", ""); - ASSERT_TRUE(e.info().traces.size() == 2); - ASSERT_TRUE(e2.info().traces.size() == 0); - ASSERT_FALSE(&e.info() == &e2.info()); - } - } - } - -#define ASSERT_TRACE1(args, type, message) \ - ASSERT_THROW( \ - std::string expr(args); \ - std::string name = expr.substr(0, expr.find(" ")); \ - try { \ - Value v = eval("builtins." args); \ - state.forceValueDeep(v); \ - } catch (BaseError & e) { \ - ASSERT_EQ(PrintToString(e.info().msg), \ - PrintToString(message)); \ - ASSERT_EQ(e.info().traces.size(), 1) << "while testing " args << std::endl << e.what(); \ - auto trace = e.info().traces.rbegin(); \ - ASSERT_EQ(PrintToString(trace->hint), \ - PrintToString(hintfmt("while calling the '%s' builtin", name))); \ - throw; \ - } \ - , type \ - ) - -#define ASSERT_TRACE2(args, type, message, context) \ - ASSERT_THROW( \ - std::string expr(args); \ - std::string name = expr.substr(0, expr.find(" ")); \ - try { \ - Value v = eval("builtins." args); \ - state.forceValueDeep(v); \ - } catch (BaseError & e) { \ - ASSERT_EQ(PrintToString(e.info().msg), \ - PrintToString(message)); \ - ASSERT_EQ(e.info().traces.size(), 2) << "while testing " args << std::endl << e.what(); \ - auto trace = e.info().traces.rbegin(); \ - ASSERT_EQ(PrintToString(trace->hint), \ - PrintToString(context)); \ - ++trace; \ - ASSERT_EQ(PrintToString(trace->hint), \ - PrintToString(hintfmt("while calling the '%s' builtin", name))); \ - throw; \ - } \ - , type \ - ) - - TEST_F(ErrorTraceTest, genericClosure) { - ASSERT_TRACE2("genericClosure 1", - TypeError, - hintfmt("value is %s while a set was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure {}", - TypeError, - hintfmt("attribute '%s' missing", "startSet"), - hintfmt("in the attrset passed as argument to builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure { startSet = 1; }", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating the 'startSet' attribute passed as argument to builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = true; }", - TypeError, - hintfmt("value is %s while a function was expected", "a Boolean"), - hintfmt("while evaluating the 'operator' attribute passed as argument to builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = item: true; }", - TypeError, - hintfmt("value is %s while a list was expected", "a Boolean"), - hintfmt("while evaluating the return value of the `operator` passed to builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = item: [ true ]; }", - TypeError, - hintfmt("value is %s while a set was expected", "a Boolean"), - hintfmt("while evaluating one of the elements generated by (or initially passed to) builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = item: [ {} ]; }", - TypeError, - hintfmt("attribute '%s' missing", "key"), - hintfmt("in one of the attrsets generated by (or initially passed to) builtins.genericClosure")); - - ASSERT_TRACE2("genericClosure { startSet = [{ key = 1;}]; operator = item: [{ key = ''a''; }]; }", - EvalError, - hintfmt("cannot compare %s with %s", "a string", "an integer"), - hintfmt("while comparing the `key` attributes of two genericClosure elements")); - - ASSERT_TRACE2("genericClosure { startSet = [ true ]; operator = item: [{ key = ''a''; }]; }", - TypeError, - hintfmt("value is %s while a set was expected", "a Boolean"), - hintfmt("while evaluating one of the elements generated by (or initially passed to) builtins.genericClosure")); - - } - - - TEST_F(ErrorTraceTest, replaceStrings) { - ASSERT_TRACE2("replaceStrings 0 0 {}", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.replaceStrings")); - - ASSERT_TRACE2("replaceStrings [] 0 {}", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating the second argument passed to builtins.replaceStrings")); - - ASSERT_TRACE1("replaceStrings [ 0 ] [] {}", - EvalError, - hintfmt("'from' and 'to' arguments passed to builtins.replaceStrings have different lengths")); - - ASSERT_TRACE2("replaceStrings [ 1 ] [ \"new\" ] {}", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating one of the strings to replace passed to builtins.replaceStrings")); - - ASSERT_TRACE2("replaceStrings [ \"oo\" ] [ true ] \"foo\"", - TypeError, - hintfmt("value is %s while a string was expected", "a Boolean"), - hintfmt("while evaluating one of the replacement strings passed to builtins.replaceStrings")); - - ASSERT_TRACE2("replaceStrings [ \"old\" ] [ \"new\" ] {}", - TypeError, - hintfmt("value is %s while a string was expected", "a set"), - hintfmt("while evaluating the third argument passed to builtins.replaceStrings")); - - } - - - TEST_F(ErrorTraceTest, scopedImport) { - } - - - TEST_F(ErrorTraceTest, import) { - } - - - TEST_F(ErrorTraceTest, typeOf) { - } - - - TEST_F(ErrorTraceTest, isNull) { - } - - - TEST_F(ErrorTraceTest, isFunction) { - } - - - TEST_F(ErrorTraceTest, isInt) { - } - - - TEST_F(ErrorTraceTest, isFloat) { - } - - - TEST_F(ErrorTraceTest, isString) { - } - - - TEST_F(ErrorTraceTest, isBool) { - } - - - TEST_F(ErrorTraceTest, isPath) { - } - - - TEST_F(ErrorTraceTest, break) { - } - - - TEST_F(ErrorTraceTest, abort) { - } - - - TEST_F(ErrorTraceTest, throw) { - } - - - TEST_F(ErrorTraceTest, addErrorContext) { - } - - - TEST_F(ErrorTraceTest, ceil) { - ASSERT_TRACE2("ceil \"foo\"", - TypeError, - hintfmt("value is %s while a float was expected", "a string"), - hintfmt("while evaluating the first argument passed to builtins.ceil")); - - } - - - TEST_F(ErrorTraceTest, floor) { - ASSERT_TRACE2("floor \"foo\"", - TypeError, - hintfmt("value is %s while a float was expected", "a string"), - hintfmt("while evaluating the first argument passed to builtins.floor")); - - } - - - TEST_F(ErrorTraceTest, tryEval) { - } - - - TEST_F(ErrorTraceTest, getEnv) { - ASSERT_TRACE2("getEnv [ ]", - TypeError, - hintfmt("value is %s while a string was expected", "a list"), - hintfmt("while evaluating the first argument passed to builtins.getEnv")); - - } - - - TEST_F(ErrorTraceTest, seq) { - } - - - TEST_F(ErrorTraceTest, deepSeq) { - } - - - TEST_F(ErrorTraceTest, trace) { - } - - - TEST_F(ErrorTraceTest, placeholder) { - ASSERT_TRACE2("placeholder []", - TypeError, - hintfmt("value is %s while a string was expected", "a list"), - hintfmt("while evaluating the first argument passed to builtins.placeholder")); - - } - - - TEST_F(ErrorTraceTest, toPath) { - ASSERT_TRACE2("toPath []", - TypeError, - hintfmt("cannot coerce %s to a string", "a list"), - hintfmt("while evaluating the first argument passed to builtins.toPath")); - - ASSERT_TRACE2("toPath \"foo\"", - EvalError, - hintfmt("string '%s' doesn't represent an absolute path", "foo"), - hintfmt("while evaluating the first argument passed to builtins.toPath")); - - } - - - TEST_F(ErrorTraceTest, storePath) { - ASSERT_TRACE2("storePath true", - TypeError, - hintfmt("cannot coerce %s to a string", "a Boolean"), - hintfmt("while evaluating the first argument passed to builtins.storePath")); - - } - - - TEST_F(ErrorTraceTest, pathExists) { - ASSERT_TRACE2("pathExists []", - TypeError, - hintfmt("cannot coerce %s to a string", "a list"), - hintfmt("while realising the context of a path")); - - ASSERT_TRACE2("pathExists \"zorglub\"", - EvalError, - hintfmt("string '%s' doesn't represent an absolute path", "zorglub"), - hintfmt("while realising the context of a path")); - - } - - - TEST_F(ErrorTraceTest, baseNameOf) { - ASSERT_TRACE2("baseNameOf []", - TypeError, - hintfmt("cannot coerce %s to a string", "a list"), - hintfmt("while evaluating the first argument passed to builtins.baseNameOf")); - - } - - - TEST_F(ErrorTraceTest, dirOf) { - } - - - TEST_F(ErrorTraceTest, readFile) { - } - - - TEST_F(ErrorTraceTest, findFile) { - } - - - TEST_F(ErrorTraceTest, hashFile) { - } - - - TEST_F(ErrorTraceTest, readDir) { - } - - - TEST_F(ErrorTraceTest, toXML) { - } - - - TEST_F(ErrorTraceTest, toJSON) { - } - - - TEST_F(ErrorTraceTest, fromJSON) { - } - - - TEST_F(ErrorTraceTest, toFile) { - } - - - TEST_F(ErrorTraceTest, filterSource) { - ASSERT_TRACE2("filterSource [] []", - TypeError, - hintfmt("cannot coerce %s to a string", "a list"), - hintfmt("while evaluating the second argument (the path to filter) passed to builtins.filterSource")); - - ASSERT_TRACE2("filterSource [] \"foo\"", - EvalError, - hintfmt("string '%s' doesn't represent an absolute path", "foo"), - hintfmt("while evaluating the second argument (the path to filter) passed to builtins.filterSource")); - - ASSERT_TRACE2("filterSource [] ./.", - TypeError, - hintfmt("value is %s while a function was expected", "a list"), - hintfmt("while evaluating the first argument passed to builtins.filterSource")); - - // Usupported by store "dummy" - - // ASSERT_TRACE2("filterSource (_: 1) ./.", - // TypeError, - // hintfmt("attempt to call something which is not a function but %s", "an integer"), - // hintfmt("while adding path '/home/layus/projects/nix'")); - - // ASSERT_TRACE2("filterSource (_: _: 1) ./.", - // TypeError, - // hintfmt("value is %s while a Boolean was expected", "an integer"), - // hintfmt("while evaluating the return value of the path filter function")); - - } - - - TEST_F(ErrorTraceTest, path) { - } - - - TEST_F(ErrorTraceTest, attrNames) { - ASSERT_TRACE2("attrNames []", - TypeError, - hintfmt("value is %s while a set was expected", "a list"), - hintfmt("while evaluating the argument passed to builtins.attrNames")); - - } - - - TEST_F(ErrorTraceTest, attrValues) { - ASSERT_TRACE2("attrValues []", - TypeError, - hintfmt("value is %s while a set was expected", "a list"), - hintfmt("while evaluating the argument passed to builtins.attrValues")); - - } - - - TEST_F(ErrorTraceTest, getAttr) { - ASSERT_TRACE2("getAttr [] []", - TypeError, - hintfmt("value is %s while a string was expected", "a list"), - hintfmt("while evaluating the first argument passed to builtins.getAttr")); - - ASSERT_TRACE2("getAttr \"foo\" []", - TypeError, - hintfmt("value is %s while a set was expected", "a list"), - hintfmt("while evaluating the second argument passed to builtins.getAttr")); - - ASSERT_TRACE2("getAttr \"foo\" {}", - TypeError, - hintfmt("attribute '%s' missing", "foo"), - hintfmt("in the attribute set under consideration")); - - } - - - TEST_F(ErrorTraceTest, unsafeGetAttrPos) { - } - - - TEST_F(ErrorTraceTest, hasAttr) { - ASSERT_TRACE2("hasAttr [] []", - TypeError, - hintfmt("value is %s while a string was expected", "a list"), - hintfmt("while evaluating the first argument passed to builtins.hasAttr")); - - ASSERT_TRACE2("hasAttr \"foo\" []", - TypeError, - hintfmt("value is %s while a set was expected", "a list"), - hintfmt("while evaluating the second argument passed to builtins.hasAttr")); - - } - - - TEST_F(ErrorTraceTest, isAttrs) { - } - - - TEST_F(ErrorTraceTest, removeAttrs) { - ASSERT_TRACE2("removeAttrs \"\" \"\"", - TypeError, - hintfmt("value is %s while a set was expected", "a string"), - hintfmt("while evaluating the first argument passed to builtins.removeAttrs")); - - ASSERT_TRACE2("removeAttrs \"\" [ 1 ]", - TypeError, - hintfmt("value is %s while a set was expected", "a string"), - hintfmt("while evaluating the first argument passed to builtins.removeAttrs")); - - ASSERT_TRACE2("removeAttrs \"\" [ \"1\" ]", - TypeError, - hintfmt("value is %s while a set was expected", "a string"), - hintfmt("while evaluating the first argument passed to builtins.removeAttrs")); - - } - - - TEST_F(ErrorTraceTest, listToAttrs) { - ASSERT_TRACE2("listToAttrs 1", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating the argument passed to builtins.listToAttrs")); - - ASSERT_TRACE2("listToAttrs [ 1 ]", - TypeError, - hintfmt("value is %s while a set was expected", "an integer"), - hintfmt("while evaluating an element of the list passed to builtins.listToAttrs")); - - ASSERT_TRACE2("listToAttrs [ {} ]", - TypeError, - hintfmt("attribute '%s' missing", "name"), - hintfmt("in a {name=...; value=...;} pair")); - - ASSERT_TRACE2("listToAttrs [ { name = 1; } ]", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the `name` attribute of an element of the list passed to builtins.listToAttrs")); - - ASSERT_TRACE2("listToAttrs [ { name = \"foo\"; } ]", - TypeError, - hintfmt("attribute '%s' missing", "value"), - hintfmt("in a {name=...; value=...;} pair")); - - } - - - TEST_F(ErrorTraceTest, intersectAttrs) { - ASSERT_TRACE2("intersectAttrs [] []", - TypeError, - hintfmt("value is %s while a set was expected", "a list"), - hintfmt("while evaluating the first argument passed to builtins.intersectAttrs")); - - ASSERT_TRACE2("intersectAttrs {} []", - TypeError, - hintfmt("value is %s while a set was expected", "a list"), - hintfmt("while evaluating the second argument passed to builtins.intersectAttrs")); - - } - - - TEST_F(ErrorTraceTest, catAttrs) { - ASSERT_TRACE2("catAttrs [] {}", - TypeError, - hintfmt("value is %s while a string was expected", "a list"), - hintfmt("while evaluating the first argument passed to builtins.catAttrs")); - - ASSERT_TRACE2("catAttrs \"foo\" {}", - TypeError, - hintfmt("value is %s while a list was expected", "a set"), - hintfmt("while evaluating the second argument passed to builtins.catAttrs")); - - ASSERT_TRACE2("catAttrs \"foo\" [ 1 ]", - TypeError, - hintfmt("value is %s while a set was expected", "an integer"), - hintfmt("while evaluating an element in the list passed as second argument to builtins.catAttrs")); - - ASSERT_TRACE2("catAttrs \"foo\" [ { foo = 1; } 1 { bar = 5;} ]", - TypeError, - hintfmt("value is %s while a set was expected", "an integer"), - hintfmt("while evaluating an element in the list passed as second argument to builtins.catAttrs")); - - } - - - TEST_F(ErrorTraceTest, functionArgs) { - ASSERT_TRACE1("functionArgs {}", - TypeError, - hintfmt("'functionArgs' requires a function")); - - } - - - TEST_F(ErrorTraceTest, mapAttrs) { - ASSERT_TRACE2("mapAttrs [] []", - TypeError, - hintfmt("value is %s while a set was expected", "a list"), - hintfmt("while evaluating the second argument passed to builtins.mapAttrs")); - - // XXX: defered - // ASSERT_TRACE2("mapAttrs \"\" { foo.bar = 1; }", - // TypeError, - // hintfmt("attempt to call something which is not a function but %s", "a string"), - // hintfmt("while evaluating the attribute 'foo'")); - - // ASSERT_TRACE2("mapAttrs (x: x + \"1\") { foo.bar = 1; }", - // TypeError, - // hintfmt("attempt to call something which is not a function but %s", "a string"), - // hintfmt("while evaluating the attribute 'foo'")); - - // ASSERT_TRACE2("mapAttrs (x: y: x + 1) { foo.bar = 1; }", - // TypeError, - // hintfmt("cannot coerce %s to a string", "an integer"), - // hintfmt("while evaluating a path segment")); - - } - - - TEST_F(ErrorTraceTest, zipAttrsWith) { - ASSERT_TRACE2("zipAttrsWith [] [ 1 ]", - TypeError, - hintfmt("value is %s while a function was expected", "a list"), - hintfmt("while evaluating the first argument passed to builtins.zipAttrsWith")); - - ASSERT_TRACE2("zipAttrsWith (_: 1) [ 1 ]", - TypeError, - hintfmt("value is %s while a set was expected", "an integer"), - hintfmt("while evaluating a value of the list passed as second argument to builtins.zipAttrsWith")); - - // XXX: How to properly tell that the fucntion takes two arguments ? - // The same question also applies to sort, and maybe others. - // Due to lazyness, we only create a thunk, and it fails later on. - // ASSERT_TRACE2("zipAttrsWith (_: 1) [ { foo = 1; } ]", - // TypeError, - // hintfmt("attempt to call something which is not a function but %s", "an integer"), - // hintfmt("while evaluating the attribute 'foo'")); - - // XXX: Also deferred deeply - // ASSERT_TRACE2("zipAttrsWith (a: b: a + b) [ { foo = 1; } { foo = 2; } ]", - // TypeError, - // hintfmt("cannot coerce %s to a string", "a list"), - // hintfmt("while evaluating a path segment")); - - } - - - TEST_F(ErrorTraceTest, isList) { - } - - - TEST_F(ErrorTraceTest, elemAt) { - ASSERT_TRACE2("elemAt \"foo\" (-1)", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the first argument passed to builtins.elemAt")); - - ASSERT_TRACE1("elemAt [] (-1)", - Error, - hintfmt("list index %d is out of bounds", -1)); - - ASSERT_TRACE1("elemAt [\"foo\"] 3", - Error, - hintfmt("list index %d is out of bounds", 3)); - - } - - - TEST_F(ErrorTraceTest, head) { - ASSERT_TRACE2("head 1", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.elemAt")); - - ASSERT_TRACE1("head []", - Error, - hintfmt("list index %d is out of bounds", 0)); - - } - - - TEST_F(ErrorTraceTest, tail) { - ASSERT_TRACE2("tail 1", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.tail")); - - ASSERT_TRACE1("tail []", - Error, - hintfmt("'tail' called on an empty list")); - - } - - - TEST_F(ErrorTraceTest, map) { - ASSERT_TRACE2("map 1 \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.map")); - - ASSERT_TRACE2("map 1 [ 1 ]", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.map")); - - } - - - TEST_F(ErrorTraceTest, filter) { - ASSERT_TRACE2("filter 1 \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.filter")); - - ASSERT_TRACE2("filter 1 [ \"foo\" ]", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.filter")); - - ASSERT_TRACE2("filter (_: 5) [ \"foo\" ]", - TypeError, - hintfmt("value is %s while a Boolean was expected", "an integer"), - hintfmt("while evaluating the return value of the filtering function passed to builtins.filter")); - - } - - - TEST_F(ErrorTraceTest, elem) { - ASSERT_TRACE2("elem 1 \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.elem")); - - } - - - TEST_F(ErrorTraceTest, concatLists) { - ASSERT_TRACE2("concatLists 1", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.concatLists")); - - ASSERT_TRACE2("concatLists [ 1 ]", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating a value of the list passed to builtins.concatLists")); - - ASSERT_TRACE2("concatLists [ [1] \"foo\" ]", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating a value of the list passed to builtins.concatLists")); - - } - - - TEST_F(ErrorTraceTest, length) { - ASSERT_TRACE2("length 1", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.length")); - - ASSERT_TRACE2("length \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the first argument passed to builtins.length")); - - } - - - TEST_F(ErrorTraceTest, foldlPrime) { - ASSERT_TRACE2("foldl' 1 \"foo\" true", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.foldlStrict")); - - ASSERT_TRACE2("foldl' (_: 1) \"foo\" true", - TypeError, - hintfmt("value is %s while a list was expected", "a Boolean"), - hintfmt("while evaluating the third argument passed to builtins.foldlStrict")); - - ASSERT_TRACE1("foldl' (_: 1) \"foo\" [ true ]", - TypeError, - hintfmt("attempt to call something which is not a function but %s", "an integer")); - - ASSERT_TRACE2("foldl' (a: b: a && b) \"foo\" [ true ]", - TypeError, - hintfmt("value is %s while a Boolean was expected", "a string"), - hintfmt("in the left operand of the AND (&&) operator")); - - } - - - TEST_F(ErrorTraceTest, any) { - ASSERT_TRACE2("any 1 \"foo\"", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.any")); - - ASSERT_TRACE2("any (_: 1) \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.any")); - - ASSERT_TRACE2("any (_: 1) [ \"foo\" ]", - TypeError, - hintfmt("value is %s while a Boolean was expected", "an integer"), - hintfmt("while evaluating the return value of the function passed to builtins.any")); - - } - - - TEST_F(ErrorTraceTest, all) { - ASSERT_TRACE2("all 1 \"foo\"", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.all")); - - ASSERT_TRACE2("all (_: 1) \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.all")); - - ASSERT_TRACE2("all (_: 1) [ \"foo\" ]", - TypeError, - hintfmt("value is %s while a Boolean was expected", "an integer"), - hintfmt("while evaluating the return value of the function passed to builtins.all")); - - } - - - TEST_F(ErrorTraceTest, genList) { - ASSERT_TRACE2("genList 1 \"foo\"", - TypeError, - hintfmt("value is %s while an integer was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.genList")); - - ASSERT_TRACE2("genList 1 2", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.genList", "an integer")); - - // XXX: defered - // ASSERT_TRACE2("genList (x: x + \"foo\") 2 #TODO", - // TypeError, - // hintfmt("cannot add %s to an integer", "a string"), - // hintfmt("while evaluating anonymous lambda")); - - ASSERT_TRACE1("genList false (-3)", - EvalError, - hintfmt("cannot create list of size %d", -3)); - - } - - - TEST_F(ErrorTraceTest, sort) { - ASSERT_TRACE2("sort 1 \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.sort")); - - ASSERT_TRACE2("sort 1 [ \"foo\" ]", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.sort")); - - ASSERT_TRACE1("sort (_: 1) [ \"foo\" \"bar\" ]", - TypeError, - hintfmt("attempt to call something which is not a function but %s", "an integer")); - - ASSERT_TRACE2("sort (_: _: 1) [ \"foo\" \"bar\" ]", - TypeError, - hintfmt("value is %s while a Boolean was expected", "an integer"), - hintfmt("while evaluating the return value of the sorting function passed to builtins.sort")); - - // XXX: Trace too deep, need better asserts - // ASSERT_TRACE1("sort (a: b: a <= b) [ \"foo\" {} ] # TODO", - // TypeError, - // hintfmt("cannot compare %s with %s", "a string", "a set")); - - // ASSERT_TRACE1("sort (a: b: a <= b) [ {} {} ] # TODO", - // TypeError, - // hintfmt("cannot compare %s with %s; values of that type are incomparable", "a set", "a set")); - - } - - - TEST_F(ErrorTraceTest, partition) { - ASSERT_TRACE2("partition 1 \"foo\"", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.partition")); - - ASSERT_TRACE2("partition (_: 1) \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.partition")); - - ASSERT_TRACE2("partition (_: 1) [ \"foo\" ]", - TypeError, - hintfmt("value is %s while a Boolean was expected", "an integer"), - hintfmt("while evaluating the return value of the partition function passed to builtins.partition")); - - } - - - TEST_F(ErrorTraceTest, groupBy) { - ASSERT_TRACE2("groupBy 1 \"foo\"", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.groupBy")); - - ASSERT_TRACE2("groupBy (_: 1) \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.groupBy")); - - ASSERT_TRACE2("groupBy (x: x) [ \"foo\" \"bar\" 1 ]", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the return value of the grouping function passed to builtins.groupBy")); - - } - - - TEST_F(ErrorTraceTest, concatMap) { - ASSERT_TRACE2("concatMap 1 \"foo\"", - TypeError, - hintfmt("value is %s while a function was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.concatMap")); - - ASSERT_TRACE2("concatMap (x: 1) \"foo\"", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the second argument passed to builtins.concatMap")); - - ASSERT_TRACE2("concatMap (x: 1) [ \"foo\" ] # TODO", - TypeError, - hintfmt("value is %s while a list was expected", "an integer"), - hintfmt("while evaluating the return value of the function passed to buitlins.concatMap")); - - ASSERT_TRACE2("concatMap (x: \"foo\") [ 1 2 ] # TODO", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the return value of the function passed to buitlins.concatMap")); - - } - - - TEST_F(ErrorTraceTest, add) { - ASSERT_TRACE2("add \"foo\" 1", - TypeError, - hintfmt("value is %s while an integer was expected", "a string"), - hintfmt("while evaluating the first argument of the addition")); - - ASSERT_TRACE2("add 1 \"foo\"", - TypeError, - hintfmt("value is %s while an integer was expected", "a string"), - hintfmt("while evaluating the second argument of the addition")); - - } - - - TEST_F(ErrorTraceTest, sub) { - ASSERT_TRACE2("sub \"foo\" 1", - TypeError, - hintfmt("value is %s while an integer was expected", "a string"), - hintfmt("while evaluating the first argument of the subtraction")); - - ASSERT_TRACE2("sub 1 \"foo\"", - TypeError, - hintfmt("value is %s while an integer was expected", "a string"), - hintfmt("while evaluating the second argument of the subtraction")); - - } - - - TEST_F(ErrorTraceTest, mul) { - ASSERT_TRACE2("mul \"foo\" 1", - TypeError, - hintfmt("value is %s while an integer was expected", "a string"), - hintfmt("while evaluating the first argument of the multiplication")); - - ASSERT_TRACE2("mul 1 \"foo\"", - TypeError, - hintfmt("value is %s while an integer was expected", "a string"), - hintfmt("while evaluating the second argument of the multiplication")); - - } - - - TEST_F(ErrorTraceTest, div) { - ASSERT_TRACE2("div \"foo\" 1 # TODO: an integer was expected -> a number", - TypeError, - hintfmt("value is %s while an integer was expected", "a string"), - hintfmt("while evaluating the first operand of the division")); - - ASSERT_TRACE2("div 1 \"foo\"", - TypeError, - hintfmt("value is %s while a float was expected", "a string"), - hintfmt("while evaluating the second operand of the division")); - - ASSERT_TRACE1("div \"foo\" 0", - EvalError, - hintfmt("division by zero")); - - } - - - TEST_F(ErrorTraceTest, bitAnd) { - ASSERT_TRACE2("bitAnd 1.1 2", - TypeError, - hintfmt("value is %s while an integer was expected", "a float"), - hintfmt("while evaluating the first argument passed to builtins.bitAnd")); - - ASSERT_TRACE2("bitAnd 1 2.2", - TypeError, - hintfmt("value is %s while an integer was expected", "a float"), - hintfmt("while evaluating the second argument passed to builtins.bitAnd")); - - } - - - TEST_F(ErrorTraceTest, bitOr) { - ASSERT_TRACE2("bitOr 1.1 2", - TypeError, - hintfmt("value is %s while an integer was expected", "a float"), - hintfmt("while evaluating the first argument passed to builtins.bitOr")); - - ASSERT_TRACE2("bitOr 1 2.2", - TypeError, - hintfmt("value is %s while an integer was expected", "a float"), - hintfmt("while evaluating the second argument passed to builtins.bitOr")); - - } - - - TEST_F(ErrorTraceTest, bitXor) { - ASSERT_TRACE2("bitXor 1.1 2", - TypeError, - hintfmt("value is %s while an integer was expected", "a float"), - hintfmt("while evaluating the first argument passed to builtins.bitXor")); - - ASSERT_TRACE2("bitXor 1 2.2", - TypeError, - hintfmt("value is %s while an integer was expected", "a float"), - hintfmt("while evaluating the second argument passed to builtins.bitXor")); - - } - - - TEST_F(ErrorTraceTest, lessThan) { - ASSERT_TRACE1("lessThan 1 \"foo\"", - EvalError, - hintfmt("cannot compare %s with %s", "an integer", "a string")); - - ASSERT_TRACE1("lessThan {} {}", - EvalError, - hintfmt("cannot compare %s with %s; values of that type are incomparable", "a set", "a set")); - - ASSERT_TRACE2("lessThan [ 1 2 ] [ \"foo\" ]", - EvalError, - hintfmt("cannot compare %s with %s", "an integer", "a string"), - hintfmt("while comparing two list elements")); - - } - - - TEST_F(ErrorTraceTest, toString) { - ASSERT_TRACE2("toString { a = 1; }", - TypeError, - hintfmt("cannot coerce %s to a string", "a set"), - hintfmt("while evaluating the first argument passed to builtins.toString")); - - } - - - TEST_F(ErrorTraceTest, substring) { - ASSERT_TRACE2("substring {} \"foo\" true", - TypeError, - hintfmt("value is %s while an integer was expected", "a set"), - hintfmt("while evaluating the first argument (the start offset) passed to builtins.substring")); - - ASSERT_TRACE2("substring 3 \"foo\" true", - TypeError, - hintfmt("value is %s while an integer was expected", "a string"), - hintfmt("while evaluating the second argument (the substring length) passed to builtins.substring")); - - ASSERT_TRACE2("substring 0 3 {}", - TypeError, - hintfmt("cannot coerce %s to a string", "a set"), - hintfmt("while evaluating the third argument (the string) passed to builtins.substring")); - - ASSERT_TRACE1("substring (-3) 3 \"sometext\"", - EvalError, - hintfmt("negative start position in 'substring'")); - - } - - - TEST_F(ErrorTraceTest, stringLength) { - ASSERT_TRACE2("stringLength {} # TODO: context is missing ???", - TypeError, - hintfmt("cannot coerce %s to a string", "a set"), - hintfmt("while evaluating the argument passed to builtins.stringLength")); - - } - - - TEST_F(ErrorTraceTest, hashString) { - ASSERT_TRACE2("hashString 1 {}", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.hashString")); - - ASSERT_TRACE1("hashString \"foo\" \"content\"", - UsageError, - hintfmt("unknown hash algorithm '%s'", "foo")); - - ASSERT_TRACE2("hashString \"sha256\" {}", - TypeError, - hintfmt("value is %s while a string was expected", "a set"), - hintfmt("while evaluating the second argument passed to builtins.hashString")); - - } - - - TEST_F(ErrorTraceTest, match) { - ASSERT_TRACE2("match 1 {}", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.match")); - - ASSERT_TRACE2("match \"foo\" {}", - TypeError, - hintfmt("value is %s while a string was expected", "a set"), - hintfmt("while evaluating the second argument passed to builtins.match")); - - ASSERT_TRACE1("match \"(.*\" \"\"", - EvalError, - hintfmt("invalid regular expression '%s'", "(.*")); - - } - - - TEST_F(ErrorTraceTest, split) { - ASSERT_TRACE2("split 1 {}", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.split")); - - ASSERT_TRACE2("split \"foo\" {}", - TypeError, - hintfmt("value is %s while a string was expected", "a set"), - hintfmt("while evaluating the second argument passed to builtins.split")); - - ASSERT_TRACE1("split \"f(o*o\" \"1foo2\"", - EvalError, - hintfmt("invalid regular expression '%s'", "f(o*o")); - - } - - - TEST_F(ErrorTraceTest, concatStringsSep) { - ASSERT_TRACE2("concatStringsSep 1 {}", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the first argument (the separator string) passed to builtins.concatStringsSep")); - - ASSERT_TRACE2("concatStringsSep \"foo\" {}", - TypeError, - hintfmt("value is %s while a list was expected", "a set"), - hintfmt("while evaluating the second argument (the list of strings to concat) passed to builtins.concatStringsSep")); - - ASSERT_TRACE2("concatStringsSep \"foo\" [ 1 2 {} ] # TODO: coerce to string is buggy", - TypeError, - hintfmt("cannot coerce %s to a string", "an integer"), - hintfmt("while evaluating one element of the list of strings to concat passed to builtins.concatStringsSep")); - - } - - - TEST_F(ErrorTraceTest, parseDrvName) { - ASSERT_TRACE2("parseDrvName 1", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.parseDrvName")); - - } - - - TEST_F(ErrorTraceTest, compareVersions) { - ASSERT_TRACE2("compareVersions 1 {}", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.compareVersions")); - - ASSERT_TRACE2("compareVersions \"abd\" {}", - TypeError, - hintfmt("value is %s while a string was expected", "a set"), - hintfmt("while evaluating the second argument passed to builtins.compareVersions")); - - } - - - TEST_F(ErrorTraceTest, splitVersion) { - ASSERT_TRACE2("splitVersion 1", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the first argument passed to builtins.splitVersion")); - - } - - - TEST_F(ErrorTraceTest, traceVerbose) { - } - - - /* // Needs different ASSERTs - TEST_F(ErrorTraceTest, derivationStrict) { - ASSERT_TRACE2("derivationStrict \"\"", - TypeError, - hintfmt("value is %s while a set was expected", "a string"), - hintfmt("while evaluating the argument passed to builtins.derivationStrict")); - - ASSERT_TRACE2("derivationStrict {}", - TypeError, - hintfmt("attribute '%s' missing", "name"), - hintfmt("in the attrset passed as argument to builtins.derivationStrict")); - - ASSERT_TRACE2("derivationStrict { name = 1; }", - TypeError, - hintfmt("value is %s while a string was expected", "an integer"), - hintfmt("while evaluating the `name` attribute passed to builtins.derivationStrict")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; }", - TypeError, - hintfmt("required attribute 'builder' missing"), - hintfmt("while evaluating derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; __structuredAttrs = 15; }", - TypeError, - hintfmt("value is %s while a Boolean was expected", "an integer"), - hintfmt("while evaluating the `__structuredAttrs` attribute passed to builtins.derivationStrict")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; __ignoreNulls = 15; }", - TypeError, - hintfmt("value is %s while a Boolean was expected", "an integer"), - hintfmt("while evaluating the `__ignoreNulls` attribute passed to builtins.derivationStrict")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; outputHashMode = 15; }", - TypeError, - hintfmt("invalid value '15' for 'outputHashMode' attribute"), - hintfmt("while evaluating the attribute 'outputHashMode' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; outputHashMode = \"custom\"; }", - TypeError, - hintfmt("invalid value 'custom' for 'outputHashMode' attribute"), - hintfmt("while evaluating the attribute 'outputHashMode' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = {}; }", - TypeError, - hintfmt("cannot coerce %s to a string", "a set"), - hintfmt("while evaluating the attribute 'system' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = {}; }", - TypeError, - hintfmt("cannot coerce %s to a string", "a set"), - hintfmt("while evaluating the attribute 'outputs' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"drv\"; }", - TypeError, - hintfmt("invalid derivation output name 'drv'"), - hintfmt("while evaluating the attribute 'outputs' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = []; }", - TypeError, - hintfmt("derivation cannot have an empty set of outputs"), - hintfmt("while evaluating the attribute 'outputs' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = [ \"drv\" ]; }", - TypeError, - hintfmt("invalid derivation output name 'drv'"), - hintfmt("while evaluating the attribute 'outputs' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = [ \"out\" \"out\" ]; }", - TypeError, - hintfmt("duplicate derivation output 'out'"), - hintfmt("while evaluating the attribute 'outputs' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; __contentAddressed = \"true\"; }", - TypeError, - hintfmt("value is %s while a Boolean was expected", "a string"), - hintfmt("while evaluating the attribute '__contentAddressed' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; __impure = \"true\"; }", - TypeError, - hintfmt("value is %s while a Boolean was expected", "a string"), - hintfmt("while evaluating the attribute '__impure' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; __impure = \"true\"; }", - TypeError, - hintfmt("value is %s while a Boolean was expected", "a string"), - hintfmt("while evaluating the attribute '__impure' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; args = \"foo\"; }", - TypeError, - hintfmt("value is %s while a list was expected", "a string"), - hintfmt("while evaluating the attribute 'args' of derivation 'foo'")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; args = [ {} ]; }", - TypeError, - hintfmt("cannot coerce %s to a string", "a set"), - hintfmt("while evaluating an element of the argument list")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; args = [ \"a\" {} ]; }", - TypeError, - hintfmt("cannot coerce %s to a string", "a set"), - hintfmt("while evaluating an element of the argument list")); - - ASSERT_TRACE2("derivationStrict { name = \"foo\"; builder = 1; system = 1; outputs = \"out\"; FOO = {}; }", - TypeError, - hintfmt("cannot coerce %s to a string", "a set"), - hintfmt("while evaluating the attribute 'FOO' of derivation 'foo'")); - - } - */ - -} /* namespace nix */ diff --git a/src/libexpr/tests/flakeref.cc b/src/libexpr/tests/flakeref.cc deleted file mode 100644 index 2b7809b93..000000000 --- a/src/libexpr/tests/flakeref.cc +++ /dev/null @@ -1,22 +0,0 @@ -#include <gtest/gtest.h> - -#include "flake/flakeref.hh" - -namespace nix { - -/* ----------- tests for flake/flakeref.hh --------------------------------------------------*/ - - /* ---------------------------------------------------------------------------- - * to_string - * --------------------------------------------------------------------------*/ - - TEST(to_string, doesntReencodeUrl) { - auto s = "http://localhost:8181/test/+3d.tar.gz"; - auto flakeref = parseFlakeRef(s); - auto parsed = flakeref.to_string(); - auto expected = "http://localhost:8181/test/%2B3d.tar.gz"; - - ASSERT_EQ(parsed, expected); - } - -} diff --git a/src/libexpr/tests/json.cc b/src/libexpr/tests/json.cc deleted file mode 100644 index 7586bdd9b..000000000 --- a/src/libexpr/tests/json.cc +++ /dev/null @@ -1,68 +0,0 @@ -#include "tests/libexpr.hh" -#include "value-to-json.hh" - -namespace nix { -// Testing the conversion to JSON - - class JSONValueTest : public LibExprTest { - protected: - std::string getJSONValue(Value& value) { - std::stringstream ss; - NixStringContext ps; - printValueAsJSON(state, true, value, noPos, ss, ps); - return ss.str(); - } - }; - - TEST_F(JSONValueTest, null) { - Value v; - v.mkNull(); - ASSERT_EQ(getJSONValue(v), "null"); - } - - TEST_F(JSONValueTest, BoolFalse) { - Value v; - v.mkBool(false); - ASSERT_EQ(getJSONValue(v),"false"); - } - - TEST_F(JSONValueTest, BoolTrue) { - Value v; - v.mkBool(true); - ASSERT_EQ(getJSONValue(v), "true"); - } - - TEST_F(JSONValueTest, IntPositive) { - Value v; - v.mkInt(100); - ASSERT_EQ(getJSONValue(v), "100"); - } - - TEST_F(JSONValueTest, IntNegative) { - Value v; - v.mkInt(-100); - ASSERT_EQ(getJSONValue(v), "-100"); - } - - TEST_F(JSONValueTest, String) { - Value v; - v.mkString("test"); - ASSERT_EQ(getJSONValue(v), "\"test\""); - } - - TEST_F(JSONValueTest, StringQuotes) { - Value v; - - v.mkString("test\""); - ASSERT_EQ(getJSONValue(v), "\"test\\\"\""); - } - - // The dummy store doesn't support writing files. Fails with this exception message: - // C++ exception with description "error: operation 'addToStoreFromDump' is - // not supported by store 'dummy'" thrown in the test body. - TEST_F(JSONValueTest, DISABLED_Path) { - Value v; - v.mkPath("test"); - ASSERT_EQ(getJSONValue(v), "\"/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x\""); - } -} /* namespace nix */ diff --git a/src/libexpr/tests/libexpr.hh b/src/libexpr/tests/libexpr.hh deleted file mode 100644 index b8e65aafe..000000000 --- a/src/libexpr/tests/libexpr.hh +++ /dev/null @@ -1,140 +0,0 @@ -#pragma once -///@file - -#include <gtest/gtest.h> -#include <gmock/gmock.h> - -#include "value.hh" -#include "nixexpr.hh" -#include "eval.hh" -#include "eval-inline.hh" -#include "store-api.hh" - -#include "tests/libstore.hh" - -namespace nix { - class LibExprTest : public LibStoreTest { - public: - static void SetUpTestSuite() { - LibStoreTest::SetUpTestSuite(); - initGC(); - } - - protected: - LibExprTest() - : LibStoreTest() - , state({}, store) - { - } - Value eval(std::string input, bool forceValue = true) { - Value v; - Expr * e = state.parseExprFromString(input, state.rootPath(CanonPath::root)); - assert(e); - state.eval(e, v); - if (forceValue) - state.forceValue(v, noPos); - return v; - } - - Symbol createSymbol(const char * value) { - return state.symbols.create(value); - } - - EvalState state; - }; - - MATCHER(IsListType, "") { - return arg != nList; - } - - MATCHER(IsList, "") { - return arg.type() == nList; - } - - MATCHER(IsString, "") { - return arg.type() == nString; - } - - MATCHER(IsNull, "") { - return arg.type() == nNull; - } - - MATCHER(IsThunk, "") { - return arg.type() == nThunk; - } - - MATCHER(IsAttrs, "") { - return arg.type() == nAttrs; - } - - MATCHER_P(IsStringEq, s, fmt("The string is equal to \"%1%\"", s)) { - if (arg.type() != nString) { - return false; - } - return std::string_view(arg.string.s) == s; - } - - MATCHER_P(IsIntEq, v, fmt("The string is equal to \"%1%\"", v)) { - if (arg.type() != nInt) { - return false; - } - return arg.integer == v; - } - - MATCHER_P(IsFloatEq, v, fmt("The float is equal to \"%1%\"", v)) { - if (arg.type() != nFloat) { - return false; - } - return arg.fpoint == v; - } - - MATCHER(IsTrue, "") { - if (arg.type() != nBool) { - return false; - } - return arg.boolean == true; - } - - MATCHER(IsFalse, "") { - if (arg.type() != nBool) { - return false; - } - return arg.boolean == false; - } - - MATCHER_P(IsPathEq, p, fmt("Is a path equal to \"%1%\"", p)) { - if (arg.type() != nPath) { - *result_listener << "Expected a path got " << arg.type(); - return false; - } else if (std::string_view(arg.string.s) != p) { - *result_listener << "Expected a path that equals \"" << p << "\" but got: " << arg.string.s; - return false; - } - return true; - } - - - MATCHER_P(IsListOfSize, n, fmt("Is a list of size [%1%]", n)) { - if (arg.type() != nList) { - *result_listener << "Expected list got " << arg.type(); - return false; - } else if (arg.listSize() != (size_t)n) { - *result_listener << "Expected as list of size " << n << " got " << arg.listSize(); - return false; - } - return true; - } - - MATCHER_P(IsAttrsOfSize, n, fmt("Is a set of size [%1%]", n)) { - if (arg.type() != nAttrs) { - *result_listener << "Expected set got " << arg.type(); - return false; - } else if (arg.attrs->size() != (size_t)n) { - *result_listener << "Expected a set with " << n << " attributes but got " << arg.attrs->size(); - return false; - } - return true; - } - - -} /* namespace nix */ diff --git a/src/libexpr/tests/local.mk b/src/libexpr/tests/local.mk deleted file mode 100644 index c56848a14..000000000 --- a/src/libexpr/tests/local.mk +++ /dev/null @@ -1,19 +0,0 @@ -check: libexpr-tests_RUN - -programs += libexpr-tests - -libexpr-tests_NAME := libnixexpr-tests - -libexpr-tests_DIR := $(d) - -libexpr-tests_INSTALL_DIR := - -libexpr-tests_SOURCES := \ - $(wildcard $(d)/*.cc) \ - $(wildcard $(d)/value/*.cc) - -libexpr-tests_CXXFLAGS += -I src/libexpr -I src/libutil -I src/libstore -I src/libexpr/tests -I src/libfetchers - -libexpr-tests_LIBS = libstore-tests libutils-tests libexpr libutil libstore libfetchers - -libexpr-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock diff --git a/src/libexpr/tests/primops.cc b/src/libexpr/tests/primops.cc deleted file mode 100644 index ce3b5d11f..000000000 --- a/src/libexpr/tests/primops.cc +++ /dev/null @@ -1,832 +0,0 @@ -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include "tests/libexpr.hh" - -namespace nix { - class CaptureLogger : public Logger - { - std::ostringstream oss; - - public: - CaptureLogger() {} - - std::string get() const { - return oss.str(); - } - - void log(Verbosity lvl, std::string_view s) override { - oss << s << std::endl; - } - - void logEI(const ErrorInfo & ei) override { - showErrorInfo(oss, ei, loggerSettings.showTrace.get()); - } - }; - - class CaptureLogging { - Logger * oldLogger; - std::unique_ptr<CaptureLogger> tempLogger; - public: - CaptureLogging() : tempLogger(std::make_unique<CaptureLogger>()) { - oldLogger = logger; - logger = tempLogger.get(); - } - - ~CaptureLogging() { - logger = oldLogger; - } - - std::string get() const { - return tempLogger->get(); - } - }; - - - // Testing eval of PrimOp's - class PrimOpTest : public LibExprTest {}; - - - TEST_F(PrimOpTest, throw) { - ASSERT_THROW(eval("throw \"foo\""), ThrownError); - } - - TEST_F(PrimOpTest, abort) { - ASSERT_THROW(eval("abort \"abort\""), Abort); - } - - TEST_F(PrimOpTest, ceil) { - auto v = eval("builtins.ceil 1.9"); - ASSERT_THAT(v, IsIntEq(2)); - } - - TEST_F(PrimOpTest, floor) { - auto v = eval("builtins.floor 1.9"); - ASSERT_THAT(v, IsIntEq(1)); - } - - TEST_F(PrimOpTest, tryEvalFailure) { - auto v = eval("builtins.tryEval (throw \"\")"); - ASSERT_THAT(v, IsAttrsOfSize(2)); - auto s = createSymbol("success"); - auto p = v.attrs->get(s); - ASSERT_NE(p, nullptr); - ASSERT_THAT(*p->value, IsFalse()); - } - - TEST_F(PrimOpTest, tryEvalSuccess) { - auto v = eval("builtins.tryEval 123"); - ASSERT_THAT(v, IsAttrs()); - auto s = createSymbol("success"); - auto p = v.attrs->get(s); - ASSERT_NE(p, nullptr); - ASSERT_THAT(*p->value, IsTrue()); - s = createSymbol("value"); - p = v.attrs->get(s); - ASSERT_NE(p, nullptr); - ASSERT_THAT(*p->value, IsIntEq(123)); - } - - TEST_F(PrimOpTest, getEnv) { - setenv("_NIX_UNIT_TEST_ENV_VALUE", "test value", 1); - auto v = eval("builtins.getEnv \"_NIX_UNIT_TEST_ENV_VALUE\""); - ASSERT_THAT(v, IsStringEq("test value")); - } - - TEST_F(PrimOpTest, seq) { - ASSERT_THROW(eval("let x = throw \"test\"; in builtins.seq x { }"), ThrownError); - } - - TEST_F(PrimOpTest, seqNotDeep) { - auto v = eval("let x = { z = throw \"test\"; }; in builtins.seq x { }"); - ASSERT_THAT(v, IsAttrs()); - } - - TEST_F(PrimOpTest, deepSeq) { - ASSERT_THROW(eval("let x = { z = throw \"test\"; }; in builtins.deepSeq x { }"), ThrownError); - } - - TEST_F(PrimOpTest, trace) { - CaptureLogging l; - auto v = eval("builtins.trace \"test string 123\" 123"); - ASSERT_THAT(v, IsIntEq(123)); - auto text = l.get(); - ASSERT_NE(text.find("test string 123"), std::string::npos); - } - - TEST_F(PrimOpTest, placeholder) { - auto v = eval("builtins.placeholder \"out\""); - ASSERT_THAT(v, IsStringEq("/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9")); - } - - TEST_F(PrimOpTest, baseNameOf) { - auto v = eval("builtins.baseNameOf /some/path"); - ASSERT_THAT(v, IsStringEq("path")); - } - - TEST_F(PrimOpTest, dirOf) { - auto v = eval("builtins.dirOf /some/path"); - ASSERT_THAT(v, IsPathEq("/some")); - } - - TEST_F(PrimOpTest, attrValues) { - auto v = eval("builtins.attrValues { x = \"foo\"; a = 1; }"); - ASSERT_THAT(v, IsListOfSize(2)); - ASSERT_THAT(*v.listElems()[0], IsIntEq(1)); - ASSERT_THAT(*v.listElems()[1], IsStringEq("foo")); - } - - TEST_F(PrimOpTest, getAttr) { - auto v = eval("builtins.getAttr \"x\" { x = \"foo\"; }"); - ASSERT_THAT(v, IsStringEq("foo")); - } - - TEST_F(PrimOpTest, getAttrNotFound) { - // FIXME: TypeError is really bad here, also the error wording is worse - // than on Nix <=2.3 - ASSERT_THROW(eval("builtins.getAttr \"y\" { }"), TypeError); - } - - TEST_F(PrimOpTest, unsafeGetAttrPos) { - // The `y` attribute is at position - const char* expr = "builtins.unsafeGetAttrPos \"y\" { y = \"x\"; }"; - auto v = eval(expr); - ASSERT_THAT(v, IsNull()); - } - - TEST_F(PrimOpTest, hasAttr) { - auto v = eval("builtins.hasAttr \"x\" { x = 1; }"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(PrimOpTest, hasAttrNotFound) { - auto v = eval("builtins.hasAttr \"x\" { }"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(PrimOpTest, isAttrs) { - auto v = eval("builtins.isAttrs {}"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(PrimOpTest, isAttrsFalse) { - auto v = eval("builtins.isAttrs null"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(PrimOpTest, removeAttrs) { - auto v = eval("builtins.removeAttrs { x = 1; } [\"x\"]"); - ASSERT_THAT(v, IsAttrsOfSize(0)); - } - - TEST_F(PrimOpTest, removeAttrsRetains) { - auto v = eval("builtins.removeAttrs { x = 1; y = 2; } [\"x\"]"); - ASSERT_THAT(v, IsAttrsOfSize(1)); - ASSERT_NE(v.attrs->find(createSymbol("y")), nullptr); - } - - TEST_F(PrimOpTest, listToAttrsEmptyList) { - auto v = eval("builtins.listToAttrs []"); - ASSERT_THAT(v, IsAttrsOfSize(0)); - ASSERT_EQ(v.type(), nAttrs); - ASSERT_EQ(v.attrs->size(), 0); - } - - TEST_F(PrimOpTest, listToAttrsNotFieldName) { - ASSERT_THROW(eval("builtins.listToAttrs [{}]"), Error); - } - - TEST_F(PrimOpTest, listToAttrs) { - auto v = eval("builtins.listToAttrs [ { name = \"key\"; value = 123; } ]"); - ASSERT_THAT(v, IsAttrsOfSize(1)); - auto key = v.attrs->find(createSymbol("key")); - ASSERT_NE(key, nullptr); - ASSERT_THAT(*key->value, IsIntEq(123)); - } - - TEST_F(PrimOpTest, intersectAttrs) { - auto v = eval("builtins.intersectAttrs { a = 1; b = 2; } { b = 3; c = 4; }"); - ASSERT_THAT(v, IsAttrsOfSize(1)); - auto b = v.attrs->find(createSymbol("b")); - ASSERT_NE(b, nullptr); - ASSERT_THAT(*b->value, IsIntEq(3)); - } - - TEST_F(PrimOpTest, catAttrs) { - auto v = eval("builtins.catAttrs \"a\" [{a = 1;} {b = 0;} {a = 2;}]"); - ASSERT_THAT(v, IsListOfSize(2)); - ASSERT_THAT(*v.listElems()[0], IsIntEq(1)); - ASSERT_THAT(*v.listElems()[1], IsIntEq(2)); - } - - TEST_F(PrimOpTest, functionArgs) { - auto v = eval("builtins.functionArgs ({ x, y ? 123}: 1)"); - ASSERT_THAT(v, IsAttrsOfSize(2)); - - auto x = v.attrs->find(createSymbol("x")); - ASSERT_NE(x, nullptr); - ASSERT_THAT(*x->value, IsFalse()); - - auto y = v.attrs->find(createSymbol("y")); - ASSERT_NE(y, nullptr); - ASSERT_THAT(*y->value, IsTrue()); - } - - TEST_F(PrimOpTest, mapAttrs) { - auto v = eval("builtins.mapAttrs (name: value: value * 10) { a = 1; b = 2; }"); - ASSERT_THAT(v, IsAttrsOfSize(2)); - - auto a = v.attrs->find(createSymbol("a")); - ASSERT_NE(a, nullptr); - ASSERT_THAT(*a->value, IsThunk()); - state.forceValue(*a->value, noPos); - ASSERT_THAT(*a->value, IsIntEq(10)); - - auto b = v.attrs->find(createSymbol("b")); - ASSERT_NE(b, nullptr); - ASSERT_THAT(*b->value, IsThunk()); - state.forceValue(*b->value, noPos); - ASSERT_THAT(*b->value, IsIntEq(20)); - } - - TEST_F(PrimOpTest, isList) { - auto v = eval("builtins.isList []"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(PrimOpTest, isListFalse) { - auto v = eval("builtins.isList null"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(PrimOpTest, elemtAt) { - auto v = eval("builtins.elemAt [0 1 2 3] 3"); - ASSERT_THAT(v, IsIntEq(3)); - } - - TEST_F(PrimOpTest, elemtAtOutOfBounds) { - ASSERT_THROW(eval("builtins.elemAt [0 1 2 3] 5"), Error); - } - - TEST_F(PrimOpTest, head) { - auto v = eval("builtins.head [ 3 2 1 0 ]"); - ASSERT_THAT(v, IsIntEq(3)); - } - - TEST_F(PrimOpTest, headEmpty) { - ASSERT_THROW(eval("builtins.head [ ]"), Error); - } - - TEST_F(PrimOpTest, headWrongType) { - ASSERT_THROW(eval("builtins.head { }"), Error); - } - - TEST_F(PrimOpTest, tail) { - auto v = eval("builtins.tail [ 3 2 1 0 ]"); - ASSERT_THAT(v, IsListOfSize(3)); - for (const auto [n, elem] : enumerate(v.listItems())) - ASSERT_THAT(*elem, IsIntEq(2 - static_cast<int>(n))); - } - - TEST_F(PrimOpTest, tailEmpty) { - ASSERT_THROW(eval("builtins.tail []"), Error); - } - - TEST_F(PrimOpTest, map) { - auto v = eval("map (x: \"foo\" + x) [ \"bar\" \"bla\" \"abc\" ]"); - ASSERT_THAT(v, IsListOfSize(3)); - auto elem = v.listElems()[0]; - ASSERT_THAT(*elem, IsThunk()); - state.forceValue(*elem, noPos); - ASSERT_THAT(*elem, IsStringEq("foobar")); - - elem = v.listElems()[1]; - ASSERT_THAT(*elem, IsThunk()); - state.forceValue(*elem, noPos); - ASSERT_THAT(*elem, IsStringEq("foobla")); - - elem = v.listElems()[2]; - ASSERT_THAT(*elem, IsThunk()); - state.forceValue(*elem, noPos); - ASSERT_THAT(*elem, IsStringEq("fooabc")); - } - - TEST_F(PrimOpTest, filter) { - auto v = eval("builtins.filter (x: x == 2) [ 3 2 3 2 3 2 ]"); - ASSERT_THAT(v, IsListOfSize(3)); - for (const auto elem : v.listItems()) - ASSERT_THAT(*elem, IsIntEq(2)); - } - - TEST_F(PrimOpTest, elemTrue) { - auto v = eval("builtins.elem 3 [ 1 2 3 4 5 ]"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(PrimOpTest, elemFalse) { - auto v = eval("builtins.elem 6 [ 1 2 3 4 5 ]"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(PrimOpTest, concatLists) { - auto v = eval("builtins.concatLists [[1 2] [3 4]]"); - ASSERT_THAT(v, IsListOfSize(4)); - for (const auto [i, elem] : enumerate(v.listItems())) - ASSERT_THAT(*elem, IsIntEq(static_cast<int>(i)+1)); - } - - TEST_F(PrimOpTest, length) { - auto v = eval("builtins.length [ 1 2 3 ]"); - ASSERT_THAT(v, IsIntEq(3)); - } - - TEST_F(PrimOpTest, foldStrict) { - auto v = eval("builtins.foldl' (a: b: a + b) 0 [1 2 3]"); - ASSERT_THAT(v, IsIntEq(6)); - } - - TEST_F(PrimOpTest, anyTrue) { - auto v = eval("builtins.any (x: x == 2) [ 1 2 3 ]"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(PrimOpTest, anyFalse) { - auto v = eval("builtins.any (x: x == 5) [ 1 2 3 ]"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(PrimOpTest, allTrue) { - auto v = eval("builtins.all (x: x > 0) [ 1 2 3 ]"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(PrimOpTest, allFalse) { - auto v = eval("builtins.all (x: x <= 0) [ 1 2 3 ]"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(PrimOpTest, genList) { - auto v = eval("builtins.genList (x: x + 1) 3"); - ASSERT_EQ(v.type(), nList); - ASSERT_EQ(v.listSize(), 3); - for (const auto [i, elem] : enumerate(v.listItems())) { - ASSERT_THAT(*elem, IsThunk()); - state.forceValue(*elem, noPos); - ASSERT_THAT(*elem, IsIntEq(static_cast<int>(i)+1)); - } - } - - TEST_F(PrimOpTest, sortLessThan) { - auto v = eval("builtins.sort builtins.lessThan [ 483 249 526 147 42 77 ]"); - ASSERT_EQ(v.type(), nList); - ASSERT_EQ(v.listSize(), 6); - - const std::vector<int> numbers = { 42, 77, 147, 249, 483, 526 }; - for (const auto [n, elem] : enumerate(v.listItems())) - ASSERT_THAT(*elem, IsIntEq(numbers[n])); - } - - TEST_F(PrimOpTest, partition) { - auto v = eval("builtins.partition (x: x > 10) [1 23 9 3 42]"); - ASSERT_THAT(v, IsAttrsOfSize(2)); - - auto right = v.attrs->get(createSymbol("right")); - ASSERT_NE(right, nullptr); - ASSERT_THAT(*right->value, IsListOfSize(2)); - ASSERT_THAT(*right->value->listElems()[0], IsIntEq(23)); - ASSERT_THAT(*right->value->listElems()[1], IsIntEq(42)); - - auto wrong = v.attrs->get(createSymbol("wrong")); - ASSERT_NE(wrong, nullptr); - ASSERT_EQ(wrong->value->type(), nList); - ASSERT_EQ(wrong->value->listSize(), 3); - ASSERT_THAT(*wrong->value, IsListOfSize(3)); - ASSERT_THAT(*wrong->value->listElems()[0], IsIntEq(1)); - ASSERT_THAT(*wrong->value->listElems()[1], IsIntEq(9)); - ASSERT_THAT(*wrong->value->listElems()[2], IsIntEq(3)); - } - - TEST_F(PrimOpTest, concatMap) { - auto v = eval("builtins.concatMap (x: x ++ [0]) [ [1 2] [3 4] ]"); - ASSERT_EQ(v.type(), nList); - ASSERT_EQ(v.listSize(), 6); - - const std::vector<int> numbers = { 1, 2, 0, 3, 4, 0 }; - for (const auto [n, elem] : enumerate(v.listItems())) - ASSERT_THAT(*elem, IsIntEq(numbers[n])); - } - - TEST_F(PrimOpTest, addInt) { - auto v = eval("builtins.add 3 5"); - ASSERT_THAT(v, IsIntEq(8)); - } - - TEST_F(PrimOpTest, addFloat) { - auto v = eval("builtins.add 3.0 5.0"); - ASSERT_THAT(v, IsFloatEq(8.0)); - } - - TEST_F(PrimOpTest, addFloatToInt) { - auto v = eval("builtins.add 3.0 5"); - ASSERT_THAT(v, IsFloatEq(8.0)); - - v = eval("builtins.add 3 5.0"); - ASSERT_THAT(v, IsFloatEq(8.0)); - } - - TEST_F(PrimOpTest, subInt) { - auto v = eval("builtins.sub 5 2"); - ASSERT_THAT(v, IsIntEq(3)); - } - - TEST_F(PrimOpTest, subFloat) { - auto v = eval("builtins.sub 5.0 2.0"); - ASSERT_THAT(v, IsFloatEq(3.0)); - } - - TEST_F(PrimOpTest, subFloatFromInt) { - auto v = eval("builtins.sub 5.0 2"); - ASSERT_THAT(v, IsFloatEq(3.0)); - - v = eval("builtins.sub 4 2.0"); - ASSERT_THAT(v, IsFloatEq(2.0)); - } - - TEST_F(PrimOpTest, mulInt) { - auto v = eval("builtins.mul 3 5"); - ASSERT_THAT(v, IsIntEq(15)); - } - - TEST_F(PrimOpTest, mulFloat) { - auto v = eval("builtins.mul 3.0 5.0"); - ASSERT_THAT(v, IsFloatEq(15.0)); - } - - TEST_F(PrimOpTest, mulFloatMixed) { - auto v = eval("builtins.mul 3 5.0"); - ASSERT_THAT(v, IsFloatEq(15.0)); - - v = eval("builtins.mul 2.0 5"); - ASSERT_THAT(v, IsFloatEq(10.0)); - } - - TEST_F(PrimOpTest, divInt) { - auto v = eval("builtins.div 5 (-1)"); - ASSERT_THAT(v, IsIntEq(-5)); - } - - TEST_F(PrimOpTest, divIntZero) { - ASSERT_THROW(eval("builtins.div 5 0"), EvalError); - } - - TEST_F(PrimOpTest, divFloat) { - auto v = eval("builtins.div 5.0 (-1)"); - ASSERT_THAT(v, IsFloatEq(-5.0)); - } - - TEST_F(PrimOpTest, divFloatZero) { - ASSERT_THROW(eval("builtins.div 5.0 0.0"), EvalError); - } - - TEST_F(PrimOpTest, bitOr) { - auto v = eval("builtins.bitOr 1 2"); - ASSERT_THAT(v, IsIntEq(3)); - } - - TEST_F(PrimOpTest, bitXor) { - auto v = eval("builtins.bitXor 3 2"); - ASSERT_THAT(v, IsIntEq(1)); - } - - TEST_F(PrimOpTest, lessThanFalse) { - auto v = eval("builtins.lessThan 3 1"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(PrimOpTest, lessThanTrue) { - auto v = eval("builtins.lessThan 1 3"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(PrimOpTest, toStringAttrsThrows) { - ASSERT_THROW(eval("builtins.toString {}"), EvalError); - } - - TEST_F(PrimOpTest, toStringLambdaThrows) { - ASSERT_THROW(eval("builtins.toString (x: x)"), EvalError); - } - - class ToStringPrimOpTest : - public PrimOpTest, - public testing::WithParamInterface<std::tuple<std::string, std::string_view>> - {}; - - TEST_P(ToStringPrimOpTest, toString) { - const auto [input, output] = GetParam(); - auto v = eval(input); - ASSERT_THAT(v, IsStringEq(output)); - } - -#define CASE(input, output) (std::make_tuple(std::string_view("builtins.toString " input), std::string_view(output))) - INSTANTIATE_TEST_SUITE_P( - toString, - ToStringPrimOpTest, - testing::Values( - CASE(R"("foo")", "foo"), - CASE(R"(1)", "1"), - CASE(R"([1 2 3])", "1 2 3"), - CASE(R"(.123)", "0.123000"), - CASE(R"(true)", "1"), - CASE(R"(false)", ""), - CASE(R"(null)", ""), - CASE(R"({ v = "bar"; __toString = self: self.v; })", "bar"), - CASE(R"({ v = "bar"; __toString = self: self.v; outPath = "foo"; })", "bar"), - CASE(R"({ outPath = "foo"; })", "foo"), - CASE(R"(./test)", "/test") - ) - ); -#undef CASE - - TEST_F(PrimOpTest, substring){ - auto v = eval("builtins.substring 0 3 \"nixos\""); - ASSERT_THAT(v, IsStringEq("nix")); - } - - TEST_F(PrimOpTest, substringSmallerString){ - auto v = eval("builtins.substring 0 3 \"n\""); - ASSERT_THAT(v, IsStringEq("n")); - } - - TEST_F(PrimOpTest, substringEmptyString){ - auto v = eval("builtins.substring 1 3 \"\""); - ASSERT_THAT(v, IsStringEq("")); - } - - TEST_F(PrimOpTest, stringLength) { - auto v = eval("builtins.stringLength \"123\""); - ASSERT_THAT(v, IsIntEq(3)); - } - TEST_F(PrimOpTest, hashStringMd5) { - auto v = eval("builtins.hashString \"md5\" \"asdf\""); - ASSERT_THAT(v, IsStringEq("912ec803b2ce49e4a541068d495ab570")); - } - - TEST_F(PrimOpTest, hashStringSha1) { - auto v = eval("builtins.hashString \"sha1\" \"asdf\""); - ASSERT_THAT(v, IsStringEq("3da541559918a808c2402bba5012f6c60b27661c")); - } - - TEST_F(PrimOpTest, hashStringSha256) { - auto v = eval("builtins.hashString \"sha256\" \"asdf\""); - ASSERT_THAT(v, IsStringEq("f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b")); - } - - TEST_F(PrimOpTest, hashStringSha512) { - auto v = eval("builtins.hashString \"sha512\" \"asdf\""); - ASSERT_THAT(v, IsStringEq("401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b3727429080fb337591abd3e44453b954555b7a0812e1081c39b740293f765eae731f5a65ed1")); - } - - TEST_F(PrimOpTest, hashStringInvalidHashType) { - ASSERT_THROW(eval("builtins.hashString \"foobar\" \"asdf\""), Error); - } - - TEST_F(PrimOpTest, nixPath) { - auto v = eval("builtins.nixPath"); - ASSERT_EQ(v.type(), nList); - // We can't test much more as currently the EvalSettings are a global - // that we can't easily swap / replace - } - - TEST_F(PrimOpTest, langVersion) { - auto v = eval("builtins.langVersion"); - ASSERT_EQ(v.type(), nInt); - } - - TEST_F(PrimOpTest, storeDir) { - auto v = eval("builtins.storeDir"); - ASSERT_THAT(v, IsStringEq(settings.nixStore)); - } - - TEST_F(PrimOpTest, nixVersion) { - auto v = eval("builtins.nixVersion"); - ASSERT_THAT(v, IsStringEq(nixVersion)); - } - - TEST_F(PrimOpTest, currentSystem) { - auto v = eval("builtins.currentSystem"); - ASSERT_THAT(v, IsStringEq(settings.thisSystem.get())); - } - - TEST_F(PrimOpTest, derivation) { - auto v = eval("derivation"); - ASSERT_EQ(v.type(), nFunction); - ASSERT_TRUE(v.isLambda()); - ASSERT_NE(v.lambda.fun, nullptr); - ASSERT_TRUE(v.lambda.fun->hasFormals()); - } - - TEST_F(PrimOpTest, currentTime) { - auto v = eval("builtins.currentTime"); - ASSERT_EQ(v.type(), nInt); - ASSERT_TRUE(v.integer > 0); - } - - TEST_F(PrimOpTest, splitVersion) { - auto v = eval("builtins.splitVersion \"1.2.3git\""); - ASSERT_THAT(v, IsListOfSize(4)); - - const std::vector<std::string_view> strings = { "1", "2", "3", "git" }; - for (const auto [n, p] : enumerate(v.listItems())) - ASSERT_THAT(*p, IsStringEq(strings[n])); - } - - class CompareVersionsPrimOpTest : - public PrimOpTest, - public testing::WithParamInterface<std::tuple<std::string, const int>> - {}; - - TEST_P(CompareVersionsPrimOpTest, compareVersions) { - auto [expression, expectation] = GetParam(); - auto v = eval(expression); - ASSERT_THAT(v, IsIntEq(expectation)); - } - -#define CASE(a, b, expected) (std::make_tuple("builtins.compareVersions \"" #a "\" \"" #b "\"", expected)) - INSTANTIATE_TEST_SUITE_P( - compareVersions, - CompareVersionsPrimOpTest, - testing::Values( - // The first two are weird cases. Intuition tells they should - // be the same but they aren't. - CASE(1.0, 1.0.0, -1), - CASE(1.0.0, 1.0, 1), - // the following are from the nix-env manual: - CASE(1.0, 2.3, -1), - CASE(2.1, 2.3, -1), - CASE(2.3, 2.3, 0), - CASE(2.5, 2.3, 1), - CASE(3.1, 2.3, 1), - CASE(2.3.1, 2.3, 1), - CASE(2.3.1, 2.3a, 1), - CASE(2.3pre1, 2.3, -1), - CASE(2.3pre3, 2.3pre12, -1), - CASE(2.3a, 2.3c, -1), - CASE(2.3pre1, 2.3c, -1), - CASE(2.3pre1, 2.3q, -1) - ) - ); -#undef CASE - - - class ParseDrvNamePrimOpTest : - public PrimOpTest, - public testing::WithParamInterface<std::tuple<std::string, std::string_view, std::string_view>> - {}; - - TEST_P(ParseDrvNamePrimOpTest, parseDrvName) { - auto [input, expectedName, expectedVersion] = GetParam(); - const auto expr = fmt("builtins.parseDrvName \"%1%\"", input); - auto v = eval(expr); - ASSERT_THAT(v, IsAttrsOfSize(2)); - - auto name = v.attrs->find(createSymbol("name")); - ASSERT_TRUE(name); - ASSERT_THAT(*name->value, IsStringEq(expectedName)); - - auto version = v.attrs->find(createSymbol("version")); - ASSERT_TRUE(version); - ASSERT_THAT(*version->value, IsStringEq(expectedVersion)); - } - - INSTANTIATE_TEST_SUITE_P( - parseDrvName, - ParseDrvNamePrimOpTest, - testing::Values( - std::make_tuple("nix-0.12pre12876", "nix", "0.12pre12876"), - std::make_tuple("a-b-c-1234pre5+git", "a-b-c", "1234pre5+git") - ) - ); - - TEST_F(PrimOpTest, replaceStrings) { - // FIXME: add a test that verifies the string context is as expected - auto v = eval("builtins.replaceStrings [\"oo\" \"a\"] [\"a\" \"i\"] \"foobar\""); - ASSERT_EQ(v.type(), nString); - ASSERT_EQ(v.string.s, std::string_view("fabir")); - } - - TEST_F(PrimOpTest, concatStringsSep) { - // FIXME: add a test that verifies the string context is as expected - auto v = eval("builtins.concatStringsSep \"%\" [\"foo\" \"bar\" \"baz\"]"); - ASSERT_EQ(v.type(), nString); - ASSERT_EQ(std::string_view(v.string.s), "foo%bar%baz"); - } - - TEST_F(PrimOpTest, split1) { - // v = [ "" [ "a" ] "c" ] - auto v = eval("builtins.split \"(a)b\" \"abc\""); - ASSERT_THAT(v, IsListOfSize(3)); - - ASSERT_THAT(*v.listElems()[0], IsStringEq("")); - - ASSERT_THAT(*v.listElems()[1], IsListOfSize(1)); - ASSERT_THAT(*v.listElems()[1]->listElems()[0], IsStringEq("a")); - - ASSERT_THAT(*v.listElems()[2], IsStringEq("c")); - } - - TEST_F(PrimOpTest, split2) { - // v is expected to be a list [ "" [ "a" ] "b" [ "c"] "" ] - auto v = eval("builtins.split \"([ac])\" \"abc\""); - ASSERT_THAT(v, IsListOfSize(5)); - - ASSERT_THAT(*v.listElems()[0], IsStringEq("")); - - ASSERT_THAT(*v.listElems()[1], IsListOfSize(1)); - ASSERT_THAT(*v.listElems()[1]->listElems()[0], IsStringEq("a")); - - ASSERT_THAT(*v.listElems()[2], IsStringEq("b")); - - ASSERT_THAT(*v.listElems()[3], IsListOfSize(1)); - ASSERT_THAT(*v.listElems()[3]->listElems()[0], IsStringEq("c")); - - ASSERT_THAT(*v.listElems()[4], IsStringEq("")); - } - - TEST_F(PrimOpTest, split3) { - auto v = eval("builtins.split \"(a)|(c)\" \"abc\""); - ASSERT_THAT(v, IsListOfSize(5)); - - // First list element - ASSERT_THAT(*v.listElems()[0], IsStringEq("")); - - // 2nd list element is a list [ "" null ] - ASSERT_THAT(*v.listElems()[1], IsListOfSize(2)); - ASSERT_THAT(*v.listElems()[1]->listElems()[0], IsStringEq("a")); - ASSERT_THAT(*v.listElems()[1]->listElems()[1], IsNull()); - - // 3rd element - ASSERT_THAT(*v.listElems()[2], IsStringEq("b")); - - // 4th element is a list: [ null "c" ] - ASSERT_THAT(*v.listElems()[3], IsListOfSize(2)); - ASSERT_THAT(*v.listElems()[3]->listElems()[0], IsNull()); - ASSERT_THAT(*v.listElems()[3]->listElems()[1], IsStringEq("c")); - - // 5th element is the empty string - ASSERT_THAT(*v.listElems()[4], IsStringEq("")); - } - - TEST_F(PrimOpTest, split4) { - auto v = eval("builtins.split \"([[:upper:]]+)\" \" FOO \""); - ASSERT_THAT(v, IsListOfSize(3)); - auto first = v.listElems()[0]; - auto second = v.listElems()[1]; - auto third = v.listElems()[2]; - - ASSERT_THAT(*first, IsStringEq(" ")); - - ASSERT_THAT(*second, IsListOfSize(1)); - ASSERT_THAT(*second->listElems()[0], IsStringEq("FOO")); - - ASSERT_THAT(*third, IsStringEq(" ")); - } - - TEST_F(PrimOpTest, match1) { - auto v = eval("builtins.match \"ab\" \"abc\""); - ASSERT_THAT(v, IsNull()); - } - - TEST_F(PrimOpTest, match2) { - auto v = eval("builtins.match \"abc\" \"abc\""); - ASSERT_THAT(v, IsListOfSize(0)); - } - - TEST_F(PrimOpTest, match3) { - auto v = eval("builtins.match \"a(b)(c)\" \"abc\""); - ASSERT_THAT(v, IsListOfSize(2)); - ASSERT_THAT(*v.listElems()[0], IsStringEq("b")); - ASSERT_THAT(*v.listElems()[1], IsStringEq("c")); - } - - TEST_F(PrimOpTest, match4) { - auto v = eval("builtins.match \"[[:space:]]+([[:upper:]]+)[[:space:]]+\" \" FOO \""); - ASSERT_THAT(v, IsListOfSize(1)); - ASSERT_THAT(*v.listElems()[0], IsStringEq("FOO")); - } - - TEST_F(PrimOpTest, attrNames) { - auto v = eval("builtins.attrNames { x = 1; y = 2; z = 3; a = 2; }"); - ASSERT_THAT(v, IsListOfSize(4)); - - // ensure that the list is sorted - const std::vector<std::string_view> expected { "a", "x", "y", "z" }; - for (const auto [n, elem] : enumerate(v.listItems())) - ASSERT_THAT(*elem, IsStringEq(expected[n])); - } - - TEST_F(PrimOpTest, genericClosure_not_strict) { - // Operator should not be used when startSet is empty - auto v = eval("builtins.genericClosure { startSet = []; }"); - ASSERT_THAT(v, IsListOfSize(0)); - } -} /* namespace nix */ diff --git a/src/libexpr/tests/search-path.cc b/src/libexpr/tests/search-path.cc deleted file mode 100644 index dbe7ab95f..000000000 --- a/src/libexpr/tests/search-path.cc +++ /dev/null @@ -1,90 +0,0 @@ -#include <gtest/gtest.h> -#include <gmock/gmock.h> - -#include "search-path.hh" - -namespace nix { - -TEST(SearchPathElem, parse_justPath) { - ASSERT_EQ( - SearchPath::Elem::parse("foo"), - (SearchPath::Elem { - .prefix = SearchPath::Prefix { .s = "" }, - .path = SearchPath::Path { .s = "foo" }, - })); -} - -TEST(SearchPathElem, parse_emptyPrefix) { - ASSERT_EQ( - SearchPath::Elem::parse("=foo"), - (SearchPath::Elem { - .prefix = SearchPath::Prefix { .s = "" }, - .path = SearchPath::Path { .s = "foo" }, - })); -} - -TEST(SearchPathElem, parse_oneEq) { - ASSERT_EQ( - SearchPath::Elem::parse("foo=bar"), - (SearchPath::Elem { - .prefix = SearchPath::Prefix { .s = "foo" }, - .path = SearchPath::Path { .s = "bar" }, - })); -} - -TEST(SearchPathElem, parse_twoEqs) { - ASSERT_EQ( - SearchPath::Elem::parse("foo=bar=baz"), - (SearchPath::Elem { - .prefix = SearchPath::Prefix { .s = "foo" }, - .path = SearchPath::Path { .s = "bar=baz" }, - })); -} - - -TEST(SearchPathElem, suffixIfPotentialMatch_justPath) { - SearchPath::Prefix prefix { .s = "" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("any/thing"), std::optional { "any/thing" }); -} - -TEST(SearchPathElem, suffixIfPotentialMatch_misleadingPrefix1) { - SearchPath::Prefix prefix { .s = "foo" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("fooX"), std::nullopt); -} - -TEST(SearchPathElem, suffixIfPotentialMatch_misleadingPrefix2) { - SearchPath::Prefix prefix { .s = "foo" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("fooX/bar"), std::nullopt); -} - -TEST(SearchPathElem, suffixIfPotentialMatch_partialPrefix) { - SearchPath::Prefix prefix { .s = "fooX" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("foo"), std::nullopt); -} - -TEST(SearchPathElem, suffixIfPotentialMatch_exactPrefix) { - SearchPath::Prefix prefix { .s = "foo" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("foo"), std::optional { "" }); -} - -TEST(SearchPathElem, suffixIfPotentialMatch_multiKey) { - SearchPath::Prefix prefix { .s = "foo/bar" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/bar/baz"), std::optional { "baz" }); -} - -TEST(SearchPathElem, suffixIfPotentialMatch_trailingSlash) { - SearchPath::Prefix prefix { .s = "foo" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/"), std::optional { "" }); -} - -TEST(SearchPathElem, suffixIfPotentialMatch_trailingDoubleSlash) { - SearchPath::Prefix prefix { .s = "foo" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("foo//"), std::optional { "/" }); -} - -TEST(SearchPathElem, suffixIfPotentialMatch_trailingPath) { - SearchPath::Prefix prefix { .s = "foo" }; - ASSERT_EQ(prefix.suffixIfPotentialMatch("foo/bar/baz"), std::optional { "bar/baz" }); -} - -} diff --git a/src/libexpr/tests/trivial.cc b/src/libexpr/tests/trivial.cc deleted file mode 100644 index 171727ac7..000000000 --- a/src/libexpr/tests/trivial.cc +++ /dev/null @@ -1,196 +0,0 @@ -#include "tests/libexpr.hh" - -namespace nix { - // Testing of trivial expressions - class TrivialExpressionTest : public LibExprTest {}; - - TEST_F(TrivialExpressionTest, true) { - auto v = eval("true"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(TrivialExpressionTest, false) { - auto v = eval("false"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(TrivialExpressionTest, null) { - auto v = eval("null"); - ASSERT_THAT(v, IsNull()); - } - - TEST_F(TrivialExpressionTest, 1) { - auto v = eval("1"); - ASSERT_THAT(v, IsIntEq(1)); - } - - TEST_F(TrivialExpressionTest, 1plus1) { - auto v = eval("1+1"); - ASSERT_THAT(v, IsIntEq(2)); - } - - TEST_F(TrivialExpressionTest, minus1) { - auto v = eval("-1"); - ASSERT_THAT(v, IsIntEq(-1)); - } - - TEST_F(TrivialExpressionTest, 1minus1) { - auto v = eval("1-1"); - ASSERT_THAT(v, IsIntEq(0)); - } - - TEST_F(TrivialExpressionTest, lambdaAdd) { - auto v = eval("let add = a: b: a + b; in add 1 2"); - ASSERT_THAT(v, IsIntEq(3)); - } - - TEST_F(TrivialExpressionTest, list) { - auto v = eval("[]"); - ASSERT_THAT(v, IsListOfSize(0)); - } - - TEST_F(TrivialExpressionTest, attrs) { - auto v = eval("{}"); - ASSERT_THAT(v, IsAttrsOfSize(0)); - } - - TEST_F(TrivialExpressionTest, float) { - auto v = eval("1.234"); - ASSERT_THAT(v, IsFloatEq(1.234)); - } - - TEST_F(TrivialExpressionTest, updateAttrs) { - auto v = eval("{ a = 1; } // { b = 2; a = 3; }"); - ASSERT_THAT(v, IsAttrsOfSize(2)); - auto a = v.attrs->find(createSymbol("a")); - ASSERT_NE(a, nullptr); - ASSERT_THAT(*a->value, IsIntEq(3)); - - auto b = v.attrs->find(createSymbol("b")); - ASSERT_NE(b, nullptr); - ASSERT_THAT(*b->value, IsIntEq(2)); - } - - TEST_F(TrivialExpressionTest, hasAttrOpFalse) { - auto v = eval("{} ? a"); - ASSERT_THAT(v, IsFalse()); - } - - TEST_F(TrivialExpressionTest, hasAttrOpTrue) { - auto v = eval("{ a = 123; } ? a"); - ASSERT_THAT(v, IsTrue()); - } - - TEST_F(TrivialExpressionTest, withFound) { - auto v = eval("with { a = 23; }; a"); - ASSERT_THAT(v, IsIntEq(23)); - } - - TEST_F(TrivialExpressionTest, withNotFound) { - ASSERT_THROW(eval("with {}; a"), Error); - } - - TEST_F(TrivialExpressionTest, withOverride) { - auto v = eval("with { a = 23; }; with { a = 42; }; a"); - ASSERT_THAT(v, IsIntEq(42)); - } - - TEST_F(TrivialExpressionTest, letOverWith) { - auto v = eval("let a = 23; in with { a = 1; }; a"); - ASSERT_THAT(v, IsIntEq(23)); - } - - TEST_F(TrivialExpressionTest, multipleLet) { - auto v = eval("let a = 23; in let a = 42; in a"); - ASSERT_THAT(v, IsIntEq(42)); - } - - TEST_F(TrivialExpressionTest, defaultFunctionArgs) { - auto v = eval("({ a ? 123 }: a) {}"); - ASSERT_THAT(v, IsIntEq(123)); - } - - TEST_F(TrivialExpressionTest, defaultFunctionArgsOverride) { - auto v = eval("({ a ? 123 }: a) { a = 5; }"); - ASSERT_THAT(v, IsIntEq(5)); - } - - TEST_F(TrivialExpressionTest, defaultFunctionArgsCaptureBack) { - auto v = eval("({ a ? 123 }@args: args) {}"); - ASSERT_THAT(v, IsAttrsOfSize(0)); - } - - TEST_F(TrivialExpressionTest, defaultFunctionArgsCaptureFront) { - auto v = eval("(args@{ a ? 123 }: args) {}"); - ASSERT_THAT(v, IsAttrsOfSize(0)); - } - - TEST_F(TrivialExpressionTest, assertThrows) { - ASSERT_THROW(eval("let x = arg: assert arg == 1; 123; in x 2"), Error); - } - - TEST_F(TrivialExpressionTest, assertPassed) { - auto v = eval("let x = arg: assert arg == 1; 123; in x 1"); - ASSERT_THAT(v, IsIntEq(123)); - } - - class AttrSetMergeTrvialExpressionTest : - public TrivialExpressionTest, - public testing::WithParamInterface<const char*> - {}; - - TEST_P(AttrSetMergeTrvialExpressionTest, attrsetMergeLazy) { - // Usually Nix rejects duplicate keys in an attrset but it does allow - // so if it is an attribute set that contains disjoint sets of keys. - // The below is equivalent to `{a.b = 1; a.c = 2; }`. - // The attribute set `a` will be a Thunk at first as the attribuets - // have to be merged (or otherwise computed) and that is done in a lazy - // manner. - - auto expr = GetParam(); - auto v = eval(expr); - ASSERT_THAT(v, IsAttrsOfSize(1)); - - auto a = v.attrs->find(createSymbol("a")); - ASSERT_NE(a, nullptr); - - ASSERT_THAT(*a->value, IsThunk()); - state.forceValue(*a->value, noPos); - - ASSERT_THAT(*a->value, IsAttrsOfSize(2)); - - auto b = a->value->attrs->find(createSymbol("b")); - ASSERT_NE(b, nullptr); - ASSERT_THAT(*b->value, IsIntEq(1)); - - auto c = a->value->attrs->find(createSymbol("c")); - ASSERT_NE(c, nullptr); - ASSERT_THAT(*c->value, IsIntEq(2)); - } - - INSTANTIATE_TEST_SUITE_P( - attrsetMergeLazy, - AttrSetMergeTrvialExpressionTest, - testing::Values( - "{ a.b = 1; a.c = 2; }", - "{ a = { b = 1; }; a = { c = 2; }; }" - ) - ); - - TEST_F(TrivialExpressionTest, functor) { - auto v = eval("{ __functor = self: arg: self.v + arg; v = 10; } 5"); - ASSERT_THAT(v, IsIntEq(15)); - } - - TEST_F(TrivialExpressionTest, bindOr) { - auto v = eval("{ or = 1; }"); - ASSERT_THAT(v, IsAttrsOfSize(1)); - auto b = v.attrs->find(createSymbol("or")); - ASSERT_NE(b, nullptr); - ASSERT_THAT(*b->value, IsIntEq(1)); - } - - TEST_F(TrivialExpressionTest, orCantBeUsed) { - ASSERT_THROW(eval("let or = 1; in or"), Error); - } -} /* namespace nix */ diff --git a/src/libexpr/tests/value/context.cc b/src/libexpr/tests/value/context.cc deleted file mode 100644 index 92d4889ab..000000000 --- a/src/libexpr/tests/value/context.cc +++ /dev/null @@ -1,162 +0,0 @@ -#include <nlohmann/json.hpp> -#include <gtest/gtest.h> -#include <rapidcheck/gtest.h> - -#include "tests/path.hh" -#include "tests/libexpr.hh" -#include "tests/value/context.hh" - -namespace nix { - -// Test a few cases of invalid string context elements. - -TEST(NixStringContextElemTest, empty_invalid) { - EXPECT_THROW( - NixStringContextElem::parse(""), - BadNixStringContextElem); -} - -TEST(NixStringContextElemTest, single_bang_invalid) { - EXPECT_THROW( - NixStringContextElem::parse("!"), - BadNixStringContextElem); -} - -TEST(NixStringContextElemTest, double_bang_invalid) { - EXPECT_THROW( - NixStringContextElem::parse("!!/"), - BadStorePath); -} - -TEST(NixStringContextElemTest, eq_slash_invalid) { - EXPECT_THROW( - NixStringContextElem::parse("=/"), - BadStorePath); -} - -TEST(NixStringContextElemTest, slash_invalid) { - EXPECT_THROW( - NixStringContextElem::parse("/"), - BadStorePath); -} - -/** - * Round trip (string <-> data structure) test for - * `NixStringContextElem::Opaque`. - */ -TEST(NixStringContextElemTest, opaque) { - std::string_view opaque = "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x"; - auto elem = NixStringContextElem::parse(opaque); - auto * p = std::get_if<NixStringContextElem::Opaque>(&elem.raw); - ASSERT_TRUE(p); - ASSERT_EQ(p->path, StorePath { opaque }); - ASSERT_EQ(elem.to_string(), opaque); -} - -/** - * Round trip (string <-> data structure) test for - * `NixStringContextElem::DrvDeep`. - */ -TEST(NixStringContextElemTest, drvDeep) { - std::string_view drvDeep = "=g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv"; - auto elem = NixStringContextElem::parse(drvDeep); - auto * p = std::get_if<NixStringContextElem::DrvDeep>(&elem.raw); - ASSERT_TRUE(p); - ASSERT_EQ(p->drvPath, StorePath { drvDeep.substr(1) }); - ASSERT_EQ(elem.to_string(), drvDeep); -} - -/** - * Round trip (string <-> data structure) test for a simpler - * `NixStringContextElem::Built`. - */ -TEST(NixStringContextElemTest, built_opaque) { - std::string_view built = "!foo!g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv"; - auto elem = NixStringContextElem::parse(built); - auto * p = std::get_if<NixStringContextElem::Built>(&elem.raw); - ASSERT_TRUE(p); - ASSERT_EQ(p->output, "foo"); - ASSERT_EQ(*p->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque { - .path = StorePath { built.substr(5) }, - })); - ASSERT_EQ(elem.to_string(), built); -} - -/** - * Round trip (string <-> data structure) test for a more complex, - * inductive `NixStringContextElem::Built`. - */ -TEST(NixStringContextElemTest, built_built) { - /** - * We set these in tests rather than the regular globals so we don't have - * to worry about race conditions if the tests run concurrently. - */ - ExperimentalFeatureSettings mockXpSettings; - mockXpSettings.set("experimental-features", "dynamic-derivations ca-derivations"); - - std::string_view built = "!foo!bar!g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv"; - auto elem = NixStringContextElem::parse(built, mockXpSettings); - auto * p = std::get_if<NixStringContextElem::Built>(&elem.raw); - ASSERT_TRUE(p); - ASSERT_EQ(p->output, "foo"); - auto * drvPath = std::get_if<SingleDerivedPath::Built>(&*p->drvPath); - ASSERT_TRUE(drvPath); - ASSERT_EQ(drvPath->output, "bar"); - ASSERT_EQ(*drvPath->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque { - .path = StorePath { built.substr(9) }, - })); - ASSERT_EQ(elem.to_string(), built); -} - -/** - * Without the right experimental features enabled, we cannot parse a - * complex inductive string context element. - */ -TEST(NixStringContextElemTest, built_built_xp) { - ASSERT_THROW( - NixStringContextElem::parse("!foo!bar!g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv"), MissingExperimentalFeature); -} - -} - -namespace rc { -using namespace nix; - -Gen<NixStringContextElem::DrvDeep> Arbitrary<NixStringContextElem::DrvDeep>::arbitrary() -{ - return gen::just(NixStringContextElem::DrvDeep { - .drvPath = *gen::arbitrary<StorePath>(), - }); -} - -Gen<NixStringContextElem> Arbitrary<NixStringContextElem>::arbitrary() -{ - switch (*gen::inRange<uint8_t>(0, std::variant_size_v<NixStringContextElem::Raw>)) { - case 0: - return gen::just<NixStringContextElem>(*gen::arbitrary<NixStringContextElem::Opaque>()); - case 1: - return gen::just<NixStringContextElem>(*gen::arbitrary<NixStringContextElem::DrvDeep>()); - case 2: - return gen::just<NixStringContextElem>(*gen::arbitrary<NixStringContextElem::Built>()); - default: - assert(false); - } -} - -} - -namespace nix { - -#ifndef COVERAGE - -RC_GTEST_PROP( - NixStringContextElemTest, - prop_round_rip, - (const NixStringContextElem & o)) -{ - RC_ASSERT(o == NixStringContextElem::parse(o.to_string())); -} - -#endif - -} diff --git a/src/libexpr/tests/value/context.hh b/src/libexpr/tests/value/context.hh deleted file mode 100644 index c0bc97ba3..000000000 --- a/src/libexpr/tests/value/context.hh +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -///@file - -#include <rapidcheck/gen/Arbitrary.h> - -#include <value/context.hh> - -namespace rc { -using namespace nix; - -template<> -struct Arbitrary<NixStringContextElem::Opaque> { - static Gen<NixStringContextElem::Opaque> arbitrary(); -}; - -template<> -struct Arbitrary<NixStringContextElem::Built> { - static Gen<NixStringContextElem::Built> arbitrary(); -}; - -template<> -struct Arbitrary<NixStringContextElem::DrvDeep> { - static Gen<NixStringContextElem::DrvDeep> arbitrary(); -}; - -template<> -struct Arbitrary<NixStringContextElem> { - static Gen<NixStringContextElem> arbitrary(); -}; - -} diff --git a/src/libexpr/tests/value/print.cc b/src/libexpr/tests/value/print.cc deleted file mode 100644 index 5e96e12ec..000000000 --- a/src/libexpr/tests/value/print.cc +++ /dev/null @@ -1,236 +0,0 @@ -#include "tests/libexpr.hh" - -#include "value.hh" - -namespace nix { - -using namespace testing; - -struct ValuePrintingTests : LibExprTest -{ - template<class... A> - void test(Value v, std::string_view expected, A... args) - { - std::stringstream out; - v.print(state.symbols, out, args...); - ASSERT_EQ(out.str(), expected); - } -}; - -TEST_F(ValuePrintingTests, tInt) -{ - Value vInt; - vInt.mkInt(10); - test(vInt, "10"); -} - -TEST_F(ValuePrintingTests, tBool) -{ - Value vBool; - vBool.mkBool(true); - test(vBool, "true"); -} - -TEST_F(ValuePrintingTests, tString) -{ - Value vString; - vString.mkString("some-string"); - test(vString, "\"some-string\""); -} - -TEST_F(ValuePrintingTests, tPath) -{ - Value vPath; - vPath.mkString("/foo"); - test(vPath, "\"/foo\""); -} - -TEST_F(ValuePrintingTests, tNull) -{ - Value vNull; - vNull.mkNull(); - test(vNull, "null"); -} - -TEST_F(ValuePrintingTests, tAttrs) -{ - Value vOne; - vOne.mkInt(1); - - Value vTwo; - vTwo.mkInt(2); - - BindingsBuilder builder(state, state.allocBindings(10)); - builder.insert(state.symbols.create("one"), &vOne); - builder.insert(state.symbols.create("two"), &vTwo); - - Value vAttrs; - vAttrs.mkAttrs(builder.finish()); - - test(vAttrs, "{ one = 1; two = 2; }"); -} - -TEST_F(ValuePrintingTests, tList) -{ - Value vOne; - vOne.mkInt(1); - - Value vTwo; - vTwo.mkInt(2); - - Value vList; - state.mkList(vList, 5); - vList.bigList.elems[0] = &vOne; - vList.bigList.elems[1] = &vTwo; - vList.bigList.size = 3; - - test(vList, "[ 1 2 (nullptr) ]"); -} - -TEST_F(ValuePrintingTests, vThunk) -{ - Value vThunk; - vThunk.mkThunk(nullptr, nullptr); - - test(vThunk, "<CODE>"); -} - -TEST_F(ValuePrintingTests, vApp) -{ - Value vApp; - vApp.mkApp(nullptr, nullptr); - - test(vApp, "<CODE>"); -} - -TEST_F(ValuePrintingTests, vLambda) -{ - Value vLambda; - vLambda.mkLambda(nullptr, nullptr); - - test(vLambda, "<LAMBDA>"); -} - -TEST_F(ValuePrintingTests, vPrimOp) -{ - Value vPrimOp; - vPrimOp.mkPrimOp(nullptr); - - test(vPrimOp, "<PRIMOP>"); -} - -TEST_F(ValuePrintingTests, vPrimOpApp) -{ - Value vPrimOpApp; - vPrimOpApp.mkPrimOpApp(nullptr, nullptr); - - test(vPrimOpApp, "<PRIMOP-APP>"); -} - -TEST_F(ValuePrintingTests, vExternal) -{ - struct MyExternal : ExternalValueBase - { - public: - std::string showType() const override - { - return ""; - } - std::string typeOf() const override - { - return ""; - } - virtual std::ostream & print(std::ostream & str) const override - { - str << "testing-external!"; - return str; - } - } myExternal; - Value vExternal; - vExternal.mkExternal(&myExternal); - - test(vExternal, "testing-external!"); -} - -TEST_F(ValuePrintingTests, vFloat) -{ - Value vFloat; - vFloat.mkFloat(2.0); - - test(vFloat, "2"); -} - -TEST_F(ValuePrintingTests, vBlackhole) -{ - Value vBlackhole; - vBlackhole.mkBlackhole(); - test(vBlackhole, "«potential infinite recursion»"); -} - -TEST_F(ValuePrintingTests, depthAttrs) -{ - Value vOne; - vOne.mkInt(1); - - Value vTwo; - vTwo.mkInt(2); - - BindingsBuilder builder(state, state.allocBindings(10)); - builder.insert(state.symbols.create("one"), &vOne); - builder.insert(state.symbols.create("two"), &vTwo); - - Value vAttrs; - vAttrs.mkAttrs(builder.finish()); - - BindingsBuilder builder2(state, state.allocBindings(10)); - builder2.insert(state.symbols.create("one"), &vOne); - builder2.insert(state.symbols.create("two"), &vTwo); - builder2.insert(state.symbols.create("nested"), &vAttrs); - - Value vNested; - vNested.mkAttrs(builder2.finish()); - - test(vNested, "{ nested = «too deep»; one = «too deep»; two = «too deep»; }", false, 1); - test(vNested, "{ nested = { one = «too deep»; two = «too deep»; }; one = 1; two = 2; }", false, 2); - test(vNested, "{ nested = { one = 1; two = 2; }; one = 1; two = 2; }", false, 3); - test(vNested, "{ nested = { one = 1; two = 2; }; one = 1; two = 2; }", false, 4); -} - -TEST_F(ValuePrintingTests, depthList) -{ - Value vOne; - vOne.mkInt(1); - - Value vTwo; - vTwo.mkInt(2); - - BindingsBuilder builder(state, state.allocBindings(10)); - builder.insert(state.symbols.create("one"), &vOne); - builder.insert(state.symbols.create("two"), &vTwo); - - Value vAttrs; - vAttrs.mkAttrs(builder.finish()); - - BindingsBuilder builder2(state, state.allocBindings(10)); - builder2.insert(state.symbols.create("one"), &vOne); - builder2.insert(state.symbols.create("two"), &vTwo); - builder2.insert(state.symbols.create("nested"), &vAttrs); - - Value vNested; - vNested.mkAttrs(builder2.finish()); - - Value vList; - state.mkList(vList, 5); - vList.bigList.elems[0] = &vOne; - vList.bigList.elems[1] = &vTwo; - vList.bigList.elems[2] = &vNested; - vList.bigList.size = 3; - - test(vList, "[ «too deep» «too deep» «too deep» ]", false, 1); - test(vList, "[ 1 2 { nested = «too deep»; one = «too deep»; two = «too deep»; } ]", false, 2); - test(vList, "[ 1 2 { nested = { one = «too deep»; two = «too deep»; }; one = 1; two = 2; } ]", false, 3); - test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", false, 4); - test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", false, 5); -} - -} // namespace nix |