Now that it isn't just used for `Value`, it doesn't really belong in there. Rename `static-string-data.hh` to share the same prefix to keep them close together when sorting lines, also.
676 lines
17 KiB
C++
676 lines
17 KiB
C++
#include "nix/expr/tests/libexpr.hh"
|
|
#include "nix/expr/string-data-static.hh"
|
|
|
|
#include "nix/expr/value.hh"
|
|
#include "nix/expr/print.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, 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.mkStringNoCopy("some-string"_sds);
|
|
test(vString, "\"some-string\"");
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, tPath)
|
|
{
|
|
Value vPath;
|
|
vPath.mkStringNoCopy("/foo"_sds);
|
|
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.buildBindings(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);
|
|
|
|
auto list = state.buildList(3);
|
|
list.elems[0] = &vOne;
|
|
list.elems[1] = &vTwo;
|
|
Value vList;
|
|
vList.mkList(list);
|
|
|
|
test(vList, "[ 1 2 «nullptr» ]");
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, vThunk)
|
|
{
|
|
Value vThunk;
|
|
vThunk.mkThunk(nullptr, nullptr);
|
|
|
|
test(vThunk, "«thunk»");
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, vApp)
|
|
{
|
|
Value vApp;
|
|
vApp.mkApp(nullptr, nullptr);
|
|
|
|
test(vApp, "«thunk»");
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, vLambda)
|
|
{
|
|
Env env{.up = nullptr, .values = {}};
|
|
PosTable::Origin origin = state.positions.addOrigin(std::monostate(), 1);
|
|
auto posIdx = state.positions.add(origin, 0);
|
|
auto body = ExprInt(0);
|
|
|
|
ExprLambda eLambda(posIdx, createSymbol("a"), &body);
|
|
|
|
Value vLambda;
|
|
vLambda.mkLambda(&env, &eLambda);
|
|
|
|
test(vLambda, "«lambda @ «none»:1:1»");
|
|
|
|
eLambda.setName(createSymbol("puppy"));
|
|
|
|
test(vLambda, "«lambda puppy @ «none»:1:1»");
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, vPrimOp)
|
|
{
|
|
Value vPrimOp;
|
|
PrimOp primOp{.name = "puppy"};
|
|
vPrimOp.mkPrimOp(&primOp);
|
|
|
|
test(vPrimOp, "«primop puppy»");
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, vPrimOpApp)
|
|
{
|
|
PrimOp primOp{.name = "puppy"};
|
|
Value vPrimOp;
|
|
vPrimOp.mkPrimOp(&primOp);
|
|
|
|
Value vPrimOpApp;
|
|
vPrimOpApp.mkPrimOpApp(&vPrimOp, nullptr);
|
|
|
|
test(vPrimOpApp, "«partially applied primop puppy»");
|
|
}
|
|
|
|
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 builderEmpty = state.buildBindings(0);
|
|
Value vAttrsEmpty;
|
|
vAttrsEmpty.mkAttrs(builderEmpty.finish());
|
|
|
|
BindingsBuilder builder = state.buildBindings(10);
|
|
builder.insert(state.symbols.create("one"), &vOne);
|
|
builder.insert(state.symbols.create("two"), &vTwo);
|
|
builder.insert(state.symbols.create("nested"), &vAttrsEmpty);
|
|
|
|
Value vAttrs;
|
|
vAttrs.mkAttrs(builder.finish());
|
|
|
|
BindingsBuilder builder2 = state.buildBindings(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 = { ... }; one = 1; two = 2; }", PrintOptions{.maxDepth = 1});
|
|
test(
|
|
vNested,
|
|
"{ nested = { nested = { ... }; one = 1; two = 2; }; one = 1; two = 2; }",
|
|
PrintOptions{.maxDepth = 2});
|
|
test(vNested, "{ nested = { nested = { }; one = 1; two = 2; }; one = 1; two = 2; }", PrintOptions{.maxDepth = 3});
|
|
test(vNested, "{ nested = { nested = { }; one = 1; two = 2; }; one = 1; two = 2; }", PrintOptions{.maxDepth = 4});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, depthList)
|
|
{
|
|
Value vOne;
|
|
vOne.mkInt(1);
|
|
|
|
Value vTwo;
|
|
vTwo.mkInt(2);
|
|
|
|
BindingsBuilder builder = state.buildBindings(10);
|
|
builder.insert(state.symbols.create("one"), &vOne);
|
|
builder.insert(state.symbols.create("two"), &vTwo);
|
|
|
|
Value vAttrs;
|
|
vAttrs.mkAttrs(builder.finish());
|
|
|
|
BindingsBuilder builder2 = state.buildBindings(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());
|
|
|
|
auto list = state.buildList(3);
|
|
list.elems[0] = &vOne;
|
|
list.elems[1] = &vTwo;
|
|
list.elems[2] = &vNested;
|
|
Value vList;
|
|
vList.mkList(list);
|
|
|
|
test(vList, "[ 1 2 { ... } ]", PrintOptions{.maxDepth = 1});
|
|
test(vList, "[ 1 2 { nested = { ... }; one = 1; two = 2; } ]", PrintOptions{.maxDepth = 2});
|
|
test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", PrintOptions{.maxDepth = 3});
|
|
test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", PrintOptions{.maxDepth = 4});
|
|
test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", PrintOptions{.maxDepth = 5});
|
|
}
|
|
|
|
struct StringPrintingTests : LibExprTest
|
|
{
|
|
template<class... A>
|
|
void test(std::string_view literal, std::string_view expected, unsigned int maxLength, A... args)
|
|
{
|
|
Value v;
|
|
v.mkString(literal);
|
|
|
|
std::stringstream out;
|
|
printValue(state, out, v, PrintOptions{.maxStringLength = maxLength});
|
|
ASSERT_EQ(out.str(), expected);
|
|
}
|
|
};
|
|
|
|
TEST_F(StringPrintingTests, maxLengthTruncation)
|
|
{
|
|
test("abcdefghi", "\"abcdefghi\"", 10);
|
|
test("abcdefghij", "\"abcdefghij\"", 10);
|
|
test("abcdefghijk", "\"abcdefghij\" «1 byte elided»", 10);
|
|
test("abcdefghijkl", "\"abcdefghij\" «2 bytes elided»", 10);
|
|
test("abcdefghijklm", "\"abcdefghij\" «3 bytes elided»", 10);
|
|
}
|
|
|
|
// Check that printing an attrset shows 'important' attributes like `type`
|
|
// first, but only reorder the attrs when we have a maxAttrs budget.
|
|
TEST_F(ValuePrintingTests, attrsTypeFirst)
|
|
{
|
|
Value vType;
|
|
vType.mkStringNoCopy("puppy"_sds);
|
|
|
|
Value vApple;
|
|
vApple.mkStringNoCopy("apple"_sds);
|
|
|
|
BindingsBuilder builder = state.buildBindings(10);
|
|
builder.insert(state.symbols.create("type"), &vType);
|
|
builder.insert(state.symbols.create("apple"), &vApple);
|
|
|
|
Value vAttrs;
|
|
vAttrs.mkAttrs(builder.finish());
|
|
|
|
test(vAttrs, "{ type = \"puppy\"; apple = \"apple\"; }", PrintOptions{.maxAttrs = 100});
|
|
|
|
test(vAttrs, "{ apple = \"apple\"; type = \"puppy\"; }", PrintOptions{});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsInt)
|
|
{
|
|
Value v;
|
|
v.mkInt(10);
|
|
|
|
test(v, ANSI_CYAN "10" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsFloat)
|
|
{
|
|
Value v;
|
|
v.mkFloat(1.6);
|
|
|
|
test(v, ANSI_CYAN "1.6" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsBool)
|
|
{
|
|
Value v;
|
|
v.mkBool(true);
|
|
|
|
test(v, ANSI_CYAN "true" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsString)
|
|
{
|
|
Value v;
|
|
v.mkStringNoCopy("puppy"_sds);
|
|
|
|
test(v, ANSI_MAGENTA "\"puppy\"" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsStringElided)
|
|
{
|
|
Value v;
|
|
v.mkStringNoCopy("puppy"_sds);
|
|
|
|
test(
|
|
v,
|
|
ANSI_MAGENTA "\"pup\" " ANSI_FAINT "«2 bytes elided»" ANSI_NORMAL,
|
|
PrintOptions{.ansiColors = true, .maxStringLength = 3});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsPath)
|
|
{
|
|
Value v;
|
|
v.mkPath(state.rootPath(CanonPath("puppy")));
|
|
|
|
test(v, ANSI_GREEN "/puppy" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsNull)
|
|
{
|
|
Value v;
|
|
v.mkNull();
|
|
|
|
test(v, ANSI_CYAN "null" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsAttrs)
|
|
{
|
|
Value vOne;
|
|
vOne.mkInt(1);
|
|
|
|
Value vTwo;
|
|
vTwo.mkInt(2);
|
|
|
|
BindingsBuilder builder = state.buildBindings(10);
|
|
builder.insert(state.symbols.create("one"), &vOne);
|
|
builder.insert(state.symbols.create("two"), &vTwo);
|
|
|
|
Value vAttrs;
|
|
vAttrs.mkAttrs(builder.finish());
|
|
|
|
test(
|
|
vAttrs,
|
|
"{ one = " ANSI_CYAN "1" ANSI_NORMAL "; two = " ANSI_CYAN "2" ANSI_NORMAL "; }",
|
|
PrintOptions{.ansiColors = true});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsDerivation)
|
|
{
|
|
Value vDerivation;
|
|
vDerivation.mkStringNoCopy("derivation"_sds);
|
|
|
|
BindingsBuilder builder = state.buildBindings(10);
|
|
builder.insert(state.s.type, &vDerivation);
|
|
|
|
Value vAttrs;
|
|
vAttrs.mkAttrs(builder.finish());
|
|
|
|
test(
|
|
vAttrs,
|
|
ANSI_GREEN "«derivation»" ANSI_NORMAL,
|
|
PrintOptions{.ansiColors = true, .force = true, .derivationPaths = true});
|
|
|
|
test(
|
|
vAttrs,
|
|
"{ type = " ANSI_MAGENTA "\"derivation\"" ANSI_NORMAL "; }",
|
|
PrintOptions{.ansiColors = true, .force = true});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsError)
|
|
{
|
|
Value throw_ = state.getBuiltin("throw");
|
|
Value message;
|
|
message.mkStringNoCopy("uh oh!"_sds);
|
|
Value vError;
|
|
vError.mkApp(&throw_, &message);
|
|
|
|
test(
|
|
vError,
|
|
ANSI_RED "«error: uh oh!»" ANSI_NORMAL,
|
|
PrintOptions{
|
|
.ansiColors = true,
|
|
.force = true,
|
|
});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsDerivationError)
|
|
{
|
|
Value throw_ = state.getBuiltin("throw");
|
|
Value message;
|
|
message.mkStringNoCopy("uh oh!"_sds);
|
|
Value vError;
|
|
vError.mkApp(&throw_, &message);
|
|
|
|
Value vDerivation;
|
|
vDerivation.mkStringNoCopy("derivation"_sds);
|
|
|
|
BindingsBuilder builder = state.buildBindings(10);
|
|
builder.insert(state.s.type, &vDerivation);
|
|
builder.insert(state.s.drvPath, &vError);
|
|
|
|
Value vAttrs;
|
|
vAttrs.mkAttrs(builder.finish());
|
|
|
|
test(
|
|
vAttrs,
|
|
"{ drvPath = " ANSI_RED "«error: uh oh!»" ANSI_NORMAL "; type = " ANSI_MAGENTA "\"derivation\"" ANSI_NORMAL
|
|
"; }",
|
|
PrintOptions{.ansiColors = true, .force = true});
|
|
|
|
test(
|
|
vAttrs,
|
|
ANSI_RED "«error: uh oh!»" ANSI_NORMAL,
|
|
PrintOptions{
|
|
.ansiColors = true,
|
|
.force = true,
|
|
.derivationPaths = true,
|
|
});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsAssert)
|
|
{
|
|
ExprVar eFalse(state.symbols.create("false"));
|
|
eFalse.bindVars(state, state.staticBaseEnv);
|
|
ExprInt eInt(1);
|
|
|
|
ExprAssert expr(noPos, &eFalse, &eInt);
|
|
|
|
Value v;
|
|
state.mkThunk_(v, &expr);
|
|
|
|
test(v, ANSI_RED "«error: assertion 'false' failed»" ANSI_NORMAL, PrintOptions{.ansiColors = true, .force = true});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsList)
|
|
{
|
|
Value vOne;
|
|
vOne.mkInt(1);
|
|
|
|
Value vTwo;
|
|
vTwo.mkInt(2);
|
|
|
|
auto list = state.buildList(3);
|
|
list.elems[0] = &vOne;
|
|
list.elems[1] = &vTwo;
|
|
Value vList;
|
|
vList.mkList(list);
|
|
|
|
test(
|
|
vList,
|
|
"[ " ANSI_CYAN "1" ANSI_NORMAL " " ANSI_CYAN "2" ANSI_NORMAL " " ANSI_MAGENTA "«nullptr»" ANSI_NORMAL " ]",
|
|
PrintOptions{.ansiColors = true});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsLambda)
|
|
{
|
|
Env env{.up = nullptr, .values = {}};
|
|
PosTable::Origin origin = state.positions.addOrigin(std::monostate(), 1);
|
|
auto posIdx = state.positions.add(origin, 0);
|
|
auto body = ExprInt(0);
|
|
|
|
ExprLambda eLambda(posIdx, createSymbol("a"), &body);
|
|
|
|
Value vLambda;
|
|
vLambda.mkLambda(&env, &eLambda);
|
|
|
|
test(vLambda, ANSI_BLUE "«lambda @ «none»:1:1»" ANSI_NORMAL, PrintOptions{.ansiColors = true, .force = true});
|
|
|
|
eLambda.setName(createSymbol("puppy"));
|
|
|
|
test(vLambda, ANSI_BLUE "«lambda puppy @ «none»:1:1»" ANSI_NORMAL, PrintOptions{.ansiColors = true, .force = true});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsPrimOp)
|
|
{
|
|
PrimOp primOp{.name = "puppy"};
|
|
Value v;
|
|
v.mkPrimOp(&primOp);
|
|
|
|
test(v, ANSI_BLUE "«primop puppy»" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsPrimOpApp)
|
|
{
|
|
PrimOp primOp{.name = "puppy"};
|
|
Value vPrimOp;
|
|
vPrimOp.mkPrimOp(&primOp);
|
|
|
|
Value v;
|
|
v.mkPrimOpApp(&vPrimOp, nullptr);
|
|
|
|
test(v, ANSI_BLUE "«partially applied primop puppy»" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsThunk)
|
|
{
|
|
Value v;
|
|
v.mkThunk(nullptr, nullptr);
|
|
|
|
test(v, ANSI_MAGENTA "«thunk»" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsBlackhole)
|
|
{
|
|
Value v;
|
|
v.mkBlackhole();
|
|
|
|
test(v, ANSI_RED "«potential infinite recursion»" ANSI_NORMAL, PrintOptions{.ansiColors = true});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsAttrsRepeated)
|
|
{
|
|
BindingsBuilder emptyBuilder = state.buildBindings(1);
|
|
|
|
Value vEmpty;
|
|
vEmpty.mkAttrs(emptyBuilder.finish());
|
|
|
|
BindingsBuilder builder = state.buildBindings(10);
|
|
builder.insert(state.symbols.create("a"), &vEmpty);
|
|
builder.insert(state.symbols.create("b"), &vEmpty);
|
|
|
|
Value vAttrs;
|
|
vAttrs.mkAttrs(builder.finish());
|
|
|
|
test(vAttrs, "{ a = { }; b = " ANSI_MAGENTA "«repeated»" ANSI_NORMAL "; }", PrintOptions{.ansiColors = true});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsListRepeated)
|
|
{
|
|
BindingsBuilder emptyBuilder = state.buildBindings(1);
|
|
|
|
Value vEmpty;
|
|
vEmpty.mkAttrs(emptyBuilder.finish());
|
|
|
|
auto list = state.buildList(2);
|
|
list.elems[0] = &vEmpty;
|
|
list.elems[1] = &vEmpty;
|
|
Value vList;
|
|
vList.mkList(list);
|
|
|
|
test(vList, "[ { } " ANSI_MAGENTA "«repeated»" ANSI_NORMAL " ]", PrintOptions{.ansiColors = true});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, listRepeated)
|
|
{
|
|
BindingsBuilder emptyBuilder = state.buildBindings(1);
|
|
|
|
Value vEmpty;
|
|
vEmpty.mkAttrs(emptyBuilder.finish());
|
|
|
|
auto list = state.buildList(2);
|
|
list.elems[0] = &vEmpty;
|
|
list.elems[1] = &vEmpty;
|
|
Value vList;
|
|
vList.mkList(list);
|
|
|
|
test(vList, "[ { } «repeated» ]", PrintOptions{});
|
|
test(vList, "[ { } { } ]", PrintOptions{.trackRepeated = false});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsAttrsElided)
|
|
{
|
|
Value vOne;
|
|
vOne.mkInt(1);
|
|
|
|
Value vTwo;
|
|
vTwo.mkInt(2);
|
|
|
|
BindingsBuilder builder = state.buildBindings(10);
|
|
builder.insert(state.symbols.create("one"), &vOne);
|
|
builder.insert(state.symbols.create("two"), &vTwo);
|
|
|
|
Value vAttrs;
|
|
vAttrs.mkAttrs(builder.finish());
|
|
|
|
test(
|
|
vAttrs,
|
|
"{ one = " ANSI_CYAN "1" ANSI_NORMAL "; " ANSI_FAINT "«1 attribute elided»" ANSI_NORMAL " }",
|
|
PrintOptions{.ansiColors = true, .maxAttrs = 1});
|
|
|
|
Value vThree;
|
|
vThree.mkInt(3);
|
|
|
|
builder.insert(state.symbols.create("three"), &vThree);
|
|
Value vAttrs2;
|
|
vAttrs2.mkAttrs(builder.finish());
|
|
|
|
test(
|
|
vAttrs2,
|
|
"{ one = " ANSI_CYAN "1" ANSI_NORMAL "; " ANSI_FAINT "«2 attributes elided»" ANSI_NORMAL " }",
|
|
PrintOptions{.ansiColors = true, .maxAttrs = 1});
|
|
}
|
|
|
|
TEST_F(ValuePrintingTests, ansiColorsListElided)
|
|
{
|
|
Value vOne;
|
|
vOne.mkInt(1);
|
|
|
|
Value vTwo;
|
|
vTwo.mkInt(2);
|
|
|
|
{
|
|
auto list = state.buildList(2);
|
|
list.elems[0] = &vOne;
|
|
list.elems[1] = &vTwo;
|
|
Value vList;
|
|
vList.mkList(list);
|
|
|
|
test(
|
|
vList,
|
|
"[ " ANSI_CYAN "1" ANSI_NORMAL " " ANSI_FAINT "«1 item elided»" ANSI_NORMAL " ]",
|
|
PrintOptions{.ansiColors = true, .maxListItems = 1});
|
|
}
|
|
|
|
Value vThree;
|
|
vThree.mkInt(3);
|
|
|
|
{
|
|
auto list = state.buildList(3);
|
|
list.elems[0] = &vOne;
|
|
list.elems[1] = &vTwo;
|
|
list.elems[2] = &vThree;
|
|
Value vList;
|
|
vList.mkList(list);
|
|
|
|
test(
|
|
vList,
|
|
"[ " ANSI_CYAN "1" ANSI_NORMAL " " ANSI_FAINT "«2 items elided»" ANSI_NORMAL " ]",
|
|
PrintOptions{.ansiColors = true, .maxListItems = 1});
|
|
}
|
|
}
|
|
|
|
} // namespace nix
|