forked from lix-project/lix
91b6833686
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>
370 lines
14 KiB
C++
370 lines
14 KiB
C++
#if 0
|
|
|
|
#include "logging.hh"
|
|
#include "nixexpr.hh"
|
|
#include <fstream>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
namespace nix {
|
|
|
|
/* ----------------------------------------------------------------------------
|
|
* logEI
|
|
* --------------------------------------------------------------------------*/
|
|
|
|
const char *test_file =
|
|
"previous line of code\n"
|
|
"this is the problem line of code\n"
|
|
"next line of code\n";
|
|
const char *one_liner =
|
|
"this is the other problem line of code";
|
|
|
|
TEST(logEI, catpuresBasicProperties) {
|
|
|
|
MakeError(TestError, Error);
|
|
ErrorInfo::programName = std::optional("error-unit-test");
|
|
|
|
try {
|
|
throw TestError("an error for testing purposes");
|
|
} catch (Error &e) {
|
|
testing::internal::CaptureStderr();
|
|
logger->logEI(e.info());
|
|
auto str = testing::internal::GetCapturedStderr();
|
|
|
|
ASSERT_STREQ(str.c_str(),"\x1B[31;1merror:\x1B[0m\x1B[34;1m --- TestError --- error-unit-test\x1B[0m\nan error for testing purposes\n");
|
|
}
|
|
}
|
|
|
|
TEST(logEI, jsonOutput) {
|
|
SymbolTable testTable;
|
|
auto problem_file = testTable.create("random.nix");
|
|
testing::internal::CaptureStderr();
|
|
|
|
makeJSONLogger(*logger)->logEI({
|
|
.name = "error name",
|
|
.msg = hintfmt("this hint has %1% templated %2%!!",
|
|
"yellow",
|
|
"values"),
|
|
.errPos = Pos(foFile, problem_file, 02, 13)
|
|
});
|
|
|
|
auto str = testing::internal::GetCapturedStderr();
|
|
ASSERT_STREQ(str.c_str(), "@nix {\"action\":\"msg\",\"column\":13,\"file\":\"random.nix\",\"level\":0,\"line\":2,\"msg\":\"\\u001b[31;1merror:\\u001b[0m\\u001b[34;1m --- error name --- error-unit-test\\u001b[0m\\n\\u001b[34;1mat: \\u001b[33;1m(2:13)\\u001b[34;1m in file: \\u001b[0mrandom.nix\\n\\nerror without any code lines.\\n\\nthis hint has \\u001b[33;1myellow\\u001b[0m templated \\u001b[33;1mvalues\\u001b[0m!!\",\"raw_msg\":\"this hint has \\u001b[33;1myellow\\u001b[0m templated \\u001b[33;1mvalues\\u001b[0m!!\"}\n");
|
|
}
|
|
|
|
TEST(logEI, appendingHintsToPreviousError) {
|
|
|
|
MakeError(TestError, Error);
|
|
ErrorInfo::programName = std::optional("error-unit-test");
|
|
|
|
try {
|
|
auto e = Error("initial error");
|
|
throw TestError(e.info());
|
|
} catch (Error &e) {
|
|
ErrorInfo ei = e.info();
|
|
ei.msg = hintfmt("%s; subsequent error message.", normaltxt(e.info().msg.str()));
|
|
|
|
testing::internal::CaptureStderr();
|
|
logger->logEI(ei);
|
|
auto str = testing::internal::GetCapturedStderr();
|
|
|
|
ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- TestError --- error-unit-test\x1B[0m\ninitial error; subsequent error message.\n");
|
|
}
|
|
|
|
}
|
|
|
|
TEST(logEI, picksUpSysErrorExitCode) {
|
|
|
|
MakeError(TestError, Error);
|
|
ErrorInfo::programName = std::optional("error-unit-test");
|
|
|
|
try {
|
|
auto x = readFile(-1);
|
|
}
|
|
catch (SysError &e) {
|
|
testing::internal::CaptureStderr();
|
|
logError(e.info());
|
|
auto str = testing::internal::GetCapturedStderr();
|
|
|
|
ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- SysError --- error-unit-test\x1B[0m\nstatting file: \x1B[33;1mBad file descriptor\x1B[0m\n");
|
|
}
|
|
}
|
|
|
|
TEST(logEI, loggingErrorOnInfoLevel) {
|
|
testing::internal::CaptureStderr();
|
|
|
|
logger->logEI({ .level = lvlInfo,
|
|
.name = "Info name",
|
|
});
|
|
|
|
auto str = testing::internal::GetCapturedStderr();
|
|
ASSERT_STREQ(str.c_str(), "\x1B[32;1minfo:\x1B[0m\x1B[34;1m --- Info name --- error-unit-test\x1B[0m\nInfo description\n");
|
|
}
|
|
|
|
TEST(logEI, loggingErrorOnTalkativeLevel) {
|
|
verbosity = lvlTalkative;
|
|
|
|
testing::internal::CaptureStderr();
|
|
|
|
logger->logEI({ .level = lvlTalkative,
|
|
.name = "Talkative name",
|
|
});
|
|
|
|
auto str = testing::internal::GetCapturedStderr();
|
|
ASSERT_STREQ(str.c_str(), "\x1B[32;1mtalk:\x1B[0m\x1B[34;1m --- Talkative name --- error-unit-test\x1B[0m\nTalkative description\n");
|
|
}
|
|
|
|
TEST(logEI, loggingErrorOnChattyLevel) {
|
|
verbosity = lvlChatty;
|
|
|
|
testing::internal::CaptureStderr();
|
|
|
|
logger->logEI({ .level = lvlChatty,
|
|
.name = "Chatty name",
|
|
});
|
|
|
|
auto str = testing::internal::GetCapturedStderr();
|
|
ASSERT_STREQ(str.c_str(), "\x1B[32;1mchat:\x1B[0m\x1B[34;1m --- Chatty name --- error-unit-test\x1B[0m\nTalkative description\n");
|
|
}
|
|
|
|
TEST(logEI, loggingErrorOnDebugLevel) {
|
|
verbosity = lvlDebug;
|
|
|
|
testing::internal::CaptureStderr();
|
|
|
|
logger->logEI({ .level = lvlDebug,
|
|
.name = "Debug name",
|
|
});
|
|
|
|
auto str = testing::internal::GetCapturedStderr();
|
|
ASSERT_STREQ(str.c_str(), "\x1B[33;1mdebug:\x1B[0m\x1B[34;1m --- Debug name --- error-unit-test\x1B[0m\nDebug description\n");
|
|
}
|
|
|
|
TEST(logEI, loggingErrorOnVomitLevel) {
|
|
verbosity = lvlVomit;
|
|
|
|
testing::internal::CaptureStderr();
|
|
|
|
logger->logEI({ .level = lvlVomit,
|
|
.name = "Vomit name",
|
|
});
|
|
|
|
auto str = testing::internal::GetCapturedStderr();
|
|
ASSERT_STREQ(str.c_str(), "\x1B[32;1mvomit:\x1B[0m\x1B[34;1m --- Vomit name --- error-unit-test\x1B[0m\nVomit description\n");
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------------
|
|
* logError
|
|
* --------------------------------------------------------------------------*/
|
|
|
|
TEST(logError, logErrorWithoutHintOrCode) {
|
|
testing::internal::CaptureStderr();
|
|
|
|
logError({
|
|
.name = "name",
|
|
});
|
|
|
|
auto str = testing::internal::GetCapturedStderr();
|
|
ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- name --- error-unit-test\x1B[0m\nerror description\n");
|
|
}
|
|
|
|
TEST(logError, logErrorWithPreviousAndNextLinesOfCode) {
|
|
SymbolTable testTable;
|
|
auto problem_file = testTable.create(test_file);
|
|
|
|
testing::internal::CaptureStderr();
|
|
|
|
logError({
|
|
.name = "error name",
|
|
.msg = hintfmt("this hint has %1% templated %2%!!",
|
|
"yellow",
|
|
"values"),
|
|
.errPos = Pos(foString, problem_file, 02, 13),
|
|
});
|
|
|
|
auto str = testing::internal::GetCapturedStderr();
|
|
ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name --- error-unit-test\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(2:13)\x1B[34;1m from string\x1B[0m\n\nerror with code lines\n\n 1| previous line of code\n 2| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n 3| next line of code\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n");
|
|
}
|
|
|
|
TEST(logError, logErrorWithInvalidFile) {
|
|
SymbolTable testTable;
|
|
auto problem_file = testTable.create("invalid filename");
|
|
testing::internal::CaptureStderr();
|
|
|
|
logError({
|
|
.name = "error name",
|
|
.msg = hintfmt("this hint has %1% templated %2%!!",
|
|
"yellow",
|
|
"values"),
|
|
.errPos = Pos(foFile, problem_file, 02, 13)
|
|
});
|
|
|
|
auto str = testing::internal::GetCapturedStderr();
|
|
ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name --- error-unit-test\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(2:13)\x1B[34;1m in file: \x1B[0minvalid filename\n\nerror without any code lines.\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n");
|
|
}
|
|
|
|
TEST(logError, logErrorWithOnlyHintAndName) {
|
|
testing::internal::CaptureStderr();
|
|
|
|
logError({
|
|
.name = "error name",
|
|
.msg = hintfmt("hint %1%", "only"),
|
|
});
|
|
|
|
auto str = testing::internal::GetCapturedStderr();
|
|
ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name --- error-unit-test\x1B[0m\nhint \x1B[33;1monly\x1B[0m\n");
|
|
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------------
|
|
* logWarning
|
|
* --------------------------------------------------------------------------*/
|
|
|
|
TEST(logWarning, logWarningWithNameDescriptionAndHint) {
|
|
testing::internal::CaptureStderr();
|
|
|
|
logWarning({
|
|
.name = "name",
|
|
.msg = hintfmt("there was a %1%", "warning"),
|
|
});
|
|
|
|
auto str = testing::internal::GetCapturedStderr();
|
|
ASSERT_STREQ(str.c_str(), "\x1B[33;1mwarning:\x1B[0m\x1B[34;1m --- name --- error-unit-test\x1B[0m\nwarning description\n\nthere was a \x1B[33;1mwarning\x1B[0m\n");
|
|
}
|
|
|
|
TEST(logWarning, logWarningWithFileLineNumAndCode) {
|
|
|
|
SymbolTable testTable;
|
|
auto problem_file = testTable.create(test_file);
|
|
|
|
testing::internal::CaptureStderr();
|
|
|
|
logWarning({
|
|
.name = "warning name",
|
|
.msg = hintfmt("this hint has %1% templated %2%!!",
|
|
"yellow",
|
|
"values"),
|
|
.errPos = Pos(foStdin, problem_file, 2, 13),
|
|
});
|
|
|
|
|
|
auto str = testing::internal::GetCapturedStderr();
|
|
ASSERT_STREQ(str.c_str(), "\x1B[33;1mwarning:\x1B[0m\x1B[34;1m --- warning name --- error-unit-test\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(2:13)\x1B[34;1m from stdin\x1B[0m\n\nwarning description\n\n 1| previous line of code\n 2| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n 3| next line of code\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n");
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------------
|
|
* traces
|
|
* --------------------------------------------------------------------------*/
|
|
|
|
TEST(addTrace, showTracesWithShowTrace) {
|
|
SymbolTable testTable;
|
|
auto problem_file = testTable.create(test_file);
|
|
auto oneliner_file = testTable.create(one_liner);
|
|
auto invalidfilename = testTable.create("invalid filename");
|
|
|
|
auto e = AssertionError(ErrorInfo {
|
|
.name = "wat",
|
|
.msg = hintfmt("it has been %1% days since our last error", "zero"),
|
|
.errPos = Pos(foString, problem_file, 2, 13),
|
|
});
|
|
|
|
e.addTrace(Pos(foStdin, oneliner_file, 1, 19), "while trying to compute %1%", 42);
|
|
e.addTrace(std::nullopt, "while doing something without a %1%", "pos");
|
|
e.addTrace(Pos(foFile, invalidfilename, 100, 1), "missing %s", "nix file");
|
|
|
|
testing::internal::CaptureStderr();
|
|
|
|
loggerSettings.showTrace.assign(true);
|
|
|
|
logError(e.info());
|
|
|
|
auto str = testing::internal::GetCapturedStderr();
|
|
ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- AssertionError --- error-unit-test\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(2:13)\x1B[34;1m from string\x1B[0m\n\nshow-traces\n\n 1| previous line of code\n 2| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n 3| next line of code\n\nit has been \x1B[33;1mzero\x1B[0m days since our last error\n\x1B[34;1m---- show-trace ----\x1B[0m\n\x1B[34;1mtrace: \x1B[0mwhile trying to compute \x1B[33;1m42\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(1:19)\x1B[34;1m from stdin\x1B[0m\n\n 1| this is the other problem line of code\n | \x1B[31;1m^\x1B[0m\n\n\x1B[34;1mtrace: \x1B[0mwhile doing something without a \x1B[33;1mpos\x1B[0m\n\x1B[34;1mtrace: \x1B[0mmissing \x1B[33;1mnix file\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(100:1)\x1B[34;1m in file: \x1B[0minvalid filename\n");
|
|
}
|
|
|
|
TEST(addTrace, hideTracesWithoutShowTrace) {
|
|
SymbolTable testTable;
|
|
auto problem_file = testTable.create(test_file);
|
|
auto oneliner_file = testTable.create(one_liner);
|
|
auto invalidfilename = testTable.create("invalid filename");
|
|
|
|
auto e = AssertionError(ErrorInfo {
|
|
.name = "wat",
|
|
.msg = hintfmt("it has been %1% days since our last error", "zero"),
|
|
.errPos = Pos(foString, problem_file, 2, 13),
|
|
});
|
|
|
|
e.addTrace(Pos(foStdin, oneliner_file, 1, 19), "while trying to compute %1%", 42);
|
|
e.addTrace(std::nullopt, "while doing something without a %1%", "pos");
|
|
e.addTrace(Pos(foFile, invalidfilename, 100, 1), "missing %s", "nix file");
|
|
|
|
testing::internal::CaptureStderr();
|
|
|
|
loggerSettings.showTrace.assign(false);
|
|
|
|
logError(e.info());
|
|
|
|
auto str = testing::internal::GetCapturedStderr();
|
|
ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- AssertionError --- error-unit-test\x1B[0m\n\x1B[34;1mat: \x1B[33;1m(2:13)\x1B[34;1m from string\x1B[0m\n\nhide traces\n\n 1| previous line of code\n 2| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n 3| next line of code\n\nit has been \x1B[33;1mzero\x1B[0m days since our last error\n");
|
|
}
|
|
|
|
|
|
/* ----------------------------------------------------------------------------
|
|
* hintfmt
|
|
* --------------------------------------------------------------------------*/
|
|
|
|
TEST(hintfmt, percentStringWithoutArgs) {
|
|
|
|
const char *teststr = "this is 100%s correct!";
|
|
|
|
ASSERT_STREQ(
|
|
hintfmt(teststr).str().c_str(),
|
|
teststr);
|
|
|
|
}
|
|
|
|
TEST(hintfmt, fmtToHintfmt) {
|
|
|
|
ASSERT_STREQ(
|
|
hintfmt(fmt("the color of this this text is %1%", "not yellow")).str().c_str(),
|
|
"the color of this this text is not yellow");
|
|
|
|
}
|
|
|
|
TEST(hintfmt, tooFewArguments) {
|
|
|
|
ASSERT_STREQ(
|
|
hintfmt("only one arg %1% %2%", "fulfilled").str().c_str(),
|
|
"only one arg " ANSI_WARNING "fulfilled" ANSI_NORMAL " ");
|
|
|
|
}
|
|
|
|
TEST(hintfmt, tooManyArguments) {
|
|
|
|
ASSERT_STREQ(
|
|
hintfmt("what about this %1% %2%", "%3%", "one", "two").str().c_str(),
|
|
"what about this " ANSI_WARNING "%3%" ANSI_NORMAL " " ANSI_YELLOW "one" ANSI_NORMAL);
|
|
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------------
|
|
* ErrPos
|
|
* --------------------------------------------------------------------------*/
|
|
|
|
TEST(errpos, invalidPos) {
|
|
|
|
// contains an invalid symbol, which we should not dereference!
|
|
Pos invalid;
|
|
|
|
// constructing without access violation.
|
|
ErrPos ep(invalid);
|
|
|
|
// assignment without access violation.
|
|
ep = invalid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|