aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Burdette <bburdette@gmail.com>2020-06-24 18:31:28 -0600
committerBen Burdette <bburdette@gmail.com>2020-06-24 18:31:28 -0600
commit9c0e1fd4f1151f4780c1ff3db82322d8b28d2d8b (patch)
treeff3d33ed21cd910552be469a8cc6495f064c1d87
parent6359d71d6b6110ce3608cfd289cae5143e78f123 (diff)
add trace test; error formatting refinements
-rw-r--r--src/libutil/error.cc86
-rw-r--r--src/libutil/error.hh2
-rw-r--r--src/libutil/tests/logging.cc33
3 files changed, 89 insertions, 32 deletions
diff --git a/src/libutil/error.cc b/src/libutil/error.cc
index b5edfa710..1185a0204 100644
--- a/src/libutil/error.cc
+++ b/src/libutil/error.cc
@@ -185,6 +185,31 @@ void printCodeLines(std::ostream &out,
}
}
+void printAtPos(const string &prefix, const ErrPos &pos, std::ostream &out)
+{
+ {
+ switch (pos.origin) {
+ case foFile: {
+ out << prefix << ANSI_BLUE << "at: " << ANSI_YELLOW << showErrPos(pos) <<
+ ANSI_BLUE << " in file: " << ANSI_NORMAL << pos.file;
+ break;
+ }
+ case foString: {
+ out << prefix << ANSI_BLUE << "at: " << ANSI_YELLOW << showErrPos(pos) <<
+ ANSI_BLUE << " from command line argument" << ANSI_NORMAL;
+ break;
+ }
+ case foStdin: {
+ out << prefix << ANSI_BLUE << "at: " << ANSI_YELLOW << showErrPos(pos) <<
+ ANSI_BLUE << " from stdin" << ANSI_NORMAL;
+ break;
+ }
+ default:
+ throw Error("invalid FileOrigin in errPos");
+ }
+ }
+}
+
std::ostream& operator<<(std::ostream &out, const ErrorInfo &einfo)
{
auto errwidth = std::max<size_t>(getWindowSize().second, 20);
@@ -240,8 +265,12 @@ std::ostream& operator<<(std::ostream &out, const ErrorInfo &einfo)
}
}
- auto ndl = prefix.length() + levelString.length() + 3 + einfo.name.length() + einfo.programName.value_or("").length();
- auto dashwidth = ndl > (errwidth - 3) ? 3 : errwidth - ndl;
+ auto ndl = prefix.length()
+ + filterANSIEscapes(levelString, true).length()
+ + 7
+ + einfo.name.length()
+ + einfo.programName.value_or("").length();
+ auto dashwidth = std::max<int>(errwidth - ndl, 3);
std::string dashes(dashwidth, '-');
@@ -262,29 +291,8 @@ std::ostream& operator<<(std::ostream &out, const ErrorInfo &einfo)
bool nl = false; // intersperse newline between sections.
if (einfo.errPos.has_value()) {
- switch (einfo.errPos->origin) {
- case foFile: {
- out << prefix << std::endl;
- auto &pos = *einfo.errPos;
- out << prefix << ANSI_BLUE << "at: " << ANSI_YELLOW << showErrPos(pos) <<
- ANSI_BLUE << " in file: " << ANSI_NORMAL << pos.file;
- break;
- }
- case foString: {
- out << prefix << std::endl;
- out << prefix << ANSI_BLUE << "at: " << ANSI_YELLOW << showErrPos(*einfo.errPos) <<
- ANSI_BLUE << " from command line argument" << ANSI_NORMAL;
- break;
- }
- case foStdin: {
- out << prefix << std::endl;
- out << prefix << ANSI_BLUE << "at: " << ANSI_YELLOW << showErrPos(*einfo.errPos) <<
- ANSI_BLUE << " from stdin" << ANSI_NORMAL;
- break;
- }
- default:
- throw Error("invalid FileOrigin in errPos");
- }
+ out << prefix << std::endl;
+ printAtPos(prefix, *einfo.errPos, out);
nl = true;
}
@@ -320,13 +328,33 @@ std::ostream& operator<<(std::ostream &out, const ErrorInfo &einfo)
for (auto iter = einfo.traces.rbegin(); iter != einfo.traces.rend(); ++iter)
{
try {
- auto pos = *iter->pos;
if (nl)
out << std::endl << prefix;
- out << std::endl << prefix;
+
+ const string tracetitle(" show-trace output ");
+
+ int fill = errwidth - tracetitle.length();
+ int lw = 0;
+ int rw = 0;
+ const int min_dashes = 3;
+ if (fill > min_dashes * 2) {
+ if (fill % 2 != 0) {
+ lw = fill / 2;
+ rw = lw + 1;
+ }
+ else
+ {
+ lw = rw = fill / 2;
+ }
+ }
+ else
+ lw = rw = min_dashes;
+
+ out << ANSI_BLUE << std::string(lw, '-') << tracetitle << std::string(rw, '-') << std::endl << prefix;
out << iter->hint.str() << std::endl;
- out << ANSI_BLUE << "at: " << ANSI_YELLOW << showErrPos(pos) <<
- ANSI_BLUE << " in file: " << ANSI_NORMAL << pos.file << std::endl;
+
+ auto pos = *iter->pos;
+ printAtPos(prefix, pos, out);
nl = true;
auto loc = getCodeLines(pos);
if (loc.has_value())
diff --git a/src/libutil/error.hh b/src/libutil/error.hh
index 09fc57fee..d79ff8f8c 100644
--- a/src/libutil/error.hh
+++ b/src/libutil/error.hh
@@ -173,6 +173,8 @@ public:
}
BaseError & addTrace(std::optional<ErrPos> e, hintformat hint);
+
+ bool hasTrace() const { return !err.traces.empty(); }
};
#define MakeError(newClass, superClass) \
diff --git a/src/libutil/tests/logging.cc b/src/libutil/tests/logging.cc
index 0bbec482f..6d0431133 100644
--- a/src/libutil/tests/logging.cc
+++ b/src/libutil/tests/logging.cc
@@ -11,12 +11,12 @@ namespace nix {
* logEI
* --------------------------------------------------------------------------*/
- const char *test_file =
+ 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 problem line of code";
+ const char *one_liner =
+ "this is the other problem line of code";
TEST(logEI, catpuresBasicProperties) {
@@ -246,6 +246,33 @@ namespace nix {
}
/* ----------------------------------------------------------------------------
+ * traces
+ * --------------------------------------------------------------------------*/
+
+ TEST(addTrace, showTracesWithShowTrace) {
+ SymbolTable testTable;
+ auto problem_file = testTable.create(test_file);
+
+ auto oneliner_file = testTable.create(one_liner);
+
+ auto e = AssertionError(ErrorInfo {
+ .name = "wat",
+ .description = "a well-known problem occurred",
+ .hint = 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);
+
+ testing::internal::CaptureStderr();
+
+ 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 command line argument\x1B[0m\n\na well-known problem occurred\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 output ---\nwhile 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 1| this is the other problem line of code\n | \x1B[31;1m^\x1B[0m\n");
+ }
+
+ /* ----------------------------------------------------------------------------
* hintfmt
* --------------------------------------------------------------------------*/