Skip to content

logger: add -expect types prefix-log, prefix-warning, prefix-error #5183

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 51 additions & 34 deletions kernel/log.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ std::vector<std::string> log_scratchpads;
std::map<std::string, std::set<std::string>> log_hdump;
std::vector<std::regex> log_warn_regexes, log_nowarn_regexes, log_werror_regexes;
dict<std::string, LogExpectedItem> log_expect_log, log_expect_warning, log_expect_error;
dict<std::string, LogExpectedItem> log_expect_prefix_log, log_expect_prefix_warning, log_expect_prefix_error;
std::set<std::string> log_warnings, log_experimentals, log_experimentals_ignored;
int log_warnings_count = 0;
int log_warnings_count_noexpect = 0;
Expand Down Expand Up @@ -178,7 +179,7 @@ void logv(const char *format, va_list ap)
{
log_warn_regex_recusion_guard = true;

if (log_warn_regexes.empty() && log_expect_log.empty())
if (log_warn_regexes.empty() && log_expect_log.empty() && log_expect_prefix_log.empty())
{
linebuffer.clear();
}
Expand All @@ -191,9 +192,9 @@ void logv(const char *format, va_list ap)
if (std::regex_search(linebuffer, re))
log_warning("Found log message matching -W regex:\n%s", str.c_str());

for (auto &item : log_expect_log)
if (std::regex_search(linebuffer, item.second.pattern))
item.second.current_count++;
for (auto &[_, item] : log_expect_log)
if (std::regex_search(linebuffer, item.pattern))
item.current_count++;

linebuffer.clear();
}
Expand Down Expand Up @@ -266,9 +267,15 @@ static void logv_warning_with_prefix(const char *prefix,
log_error("%s", message.c_str());

bool warning_match = false;
for (auto &item : log_expect_warning)
if (std::regex_search(message, item.second.pattern)) {
item.second.current_count++;
for (auto &[_, item] : log_expect_warning)
if (std::regex_search(message, item.pattern)) {
item.current_count++;
warning_match = true;
}

for (auto &[_, item] : log_expect_prefix_warning)
if (std::regex_search(string(prefix) + message, item.pattern)) {
item.current_count++;
warning_match = true;
}

Expand Down Expand Up @@ -355,9 +362,13 @@ static void logv_error_with_prefix(const char *prefix,

log_make_debug = bak_log_make_debug;

for (auto &item : log_expect_error)
if (std::regex_search(log_last_error, item.second.pattern))
item.second.current_count++;
for (auto &[_, item] : log_expect_error)
if (std::regex_search(log_last_error, item.pattern))
item.current_count++;

for (auto &[_, item] : log_expect_prefix_error)
if (std::regex_search(string(prefix) + string(log_last_error), item.pattern))
item.current_count++;

log_check_expected();

Expand Down Expand Up @@ -711,38 +722,39 @@ void log_check_expected()
// copy out all of the expected logs so that they cannot be re-checked
// or match against themselves
dict<std::string, LogExpectedItem> expect_log, expect_warning, expect_error;
dict<std::string, LogExpectedItem> expect_prefix_log, expect_prefix_warning, expect_prefix_error;
std::swap(expect_warning, log_expect_warning);
std::swap(expect_log, log_expect_log);
std::swap(expect_error, log_expect_error);
std::swap(expect_prefix_warning, log_expect_prefix_warning);
std::swap(expect_prefix_log, log_expect_prefix_log);
std::swap(expect_prefix_error, log_expect_prefix_error);

for (auto &item : expect_warning) {
if (item.second.current_count == 0) {
log_warn_regexes.clear();
log_error("Expected warning pattern '%s' not found !\n", item.first.c_str());
}
if (item.second.current_count != item.second.expected_count) {
log_warn_regexes.clear();
log_error("Expected warning pattern '%s' found %d time(s), instead of %d time(s) !\n",
item.first.c_str(), item.second.current_count, item.second.expected_count);
}
}

for (auto &item : expect_log) {
if (item.second.current_count == 0) {
auto check = [&](const std::string kind, std::string pattern, LogExpectedItem item) {
if (item.current_count == 0) {
log_warn_regexes.clear();
log_error("Expected log pattern '%s' not found !\n", item.first.c_str());
log_error("Expected %s pattern '%s' not found !\n", kind.c_str(), pattern.c_str());
}
if (item.second.current_count != item.second.expected_count) {
if (item.current_count != item.expected_count) {
log_warn_regexes.clear();
log_error("Expected log pattern '%s' found %d time(s), instead of %d time(s) !\n",
item.first.c_str(), item.second.current_count, item.second.expected_count);
log_error("Expected %s pattern '%s' found %d time(s), instead of %d time(s) !\n",
kind.c_str(), pattern.c_str(), item.current_count, item.expected_count);
}
}

for (auto &item : expect_error)
if (item.second.current_count == item.second.expected_count) {
};

for (auto &[pattern, item] : expect_warning)
check("warning", pattern, item);
for (auto &[pattern, item] : expect_prefix_warning)
check("prefixed warning", pattern, item);
for (auto &[pattern, item] : expect_log)
check("log", pattern, item);
for (auto &[pattern, item] : expect_prefix_log)
check("prefixed log", pattern, item);

auto check_err = [&](const std::string kind, std::string pattern, LogExpectedItem item) {
if (item.current_count == item.expected_count) {
log_warn_regexes.clear();
log("Expected error pattern '%s' found !!!\n", item.first.c_str());
log("Expected %s pattern '%s' found !!!\n", kind.c_str(), pattern.c_str());
yosys_shutdown();
#ifdef EMSCRIPTEN
throw 0;
Expand All @@ -753,8 +765,13 @@ void log_check_expected()
#endif
} else {
log_warn_regexes.clear();
log_error("Expected error pattern '%s' not found !\n", item.first.c_str());
log_error("Expected %s pattern '%s' not found !\n", kind.c_str(), pattern.c_str());
}
};
for (auto &[pattern, item] : expect_error)
check_err("error", pattern, item);
for (auto &[pattern, item] : expect_prefix_error)
check_err("prefixed error", pattern, item);
}

// ---------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions kernel/log.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ struct LogExpectedItem
};

extern dict<std::string, LogExpectedItem> log_expect_log, log_expect_warning, log_expect_error;
extern dict<std::string, LogExpectedItem> log_expect_prefix_log, log_expect_prefix_warning, log_expect_prefix_error;
void log_check_expected();

const char *log_signal(const RTLIL::SigSpec &sig, bool autoint = true);
Expand Down
17 changes: 13 additions & 4 deletions passes/cmds/logger.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ struct LoggerPass : public Pass {
log(" -expect <type> <regex> <expected_count>\n");
log(" expect log, warning or error to appear. matched errors will terminate\n");
log(" with exit code 0.\n");
log(" Types prefix-log, prefix-warning and prefix-error match the entire\n");
log(" logged string, including filename if present.\n");
log("\n");
log(" -expect-no-warnings\n");
log(" gives error in case there is at least one warning that is not expected.\n");
Expand Down Expand Up @@ -151,26 +153,33 @@ struct LoggerPass : public Pass {
}
if (args[argidx] == "-expect" && argidx+3 < args.size()) {
std::string type = args[++argidx];
if (type!="error" && type!="warning" && type!="log")
if (type!="error" && type!="warning" && type!="log"
&& type!="prefix-error" && type!="prefix-warning" && type!="prefix-log")
log_cmd_error("Expect command require type to be 'log', 'warning' or 'error' !\n");
if (type=="error" && log_expect_error.size()>0)
if ((type=="error" || type=="prefix-error") && log_expect_error.size()>0)
log_cmd_error("Only single error message can be expected !\n");
std::string pattern = args[++argidx];
if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2);
if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2);
int count = atoi(args[++argidx].c_str());
if (count<=0)
log_cmd_error("Number of expected messages must be higher then 0 !\n");
if (type=="error" && count!=1)
if ((type=="error" || type=="prefix-error") && count!=1)
log_cmd_error("Expected error message occurrences must be 1 !\n");
log("Added regex '%s' to expected %s messages list.\n",
pattern.c_str(), type.c_str());
try {
if (type == "error")
log_expect_error[pattern] = LogExpectedItem(YS_REGEX_COMPILE(pattern), count);
else if (type == "prefix-error")
log_expect_prefix_error[pattern] = LogExpectedItem(YS_REGEX_COMPILE(pattern), count);
else if (type == "warning")
log_expect_warning[pattern] = LogExpectedItem(YS_REGEX_COMPILE(pattern), count);
else if (type == "prefix-warning")
log_expect_prefix_warning[pattern] = LogExpectedItem(YS_REGEX_COMPILE(pattern), count);
else if (type == "log")
log_expect_log[pattern] = LogExpectedItem(YS_REGEX_COMPILE(pattern), count);
else if (type == "prefix-log")
log_expect_prefix_log[pattern] = LogExpectedItem(YS_REGEX_COMPILE(pattern), count);
else log_abort();
}
catch (const std::regex_error& e) {
Expand Down
7 changes: 7 additions & 0 deletions tests/verilog/constparser_f.ys
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
logger -expect prefix-error "<<EOT:2: ERROR: Digit larger than 1 used in in base-2 constant." 1
read_verilog <<EOT
module test (y);
output signed [2:0] y = 1'bf;
endmodule
EOT
dump
3 changes: 3 additions & 0 deletions tests/verilog/constparser_f_file.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module test (y);
output signed [2:0] y = 1'bf;
endmodule
2 changes: 2 additions & 0 deletions tests/verilog/constparser_f_file.ys
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
logger -expect prefix-error "./constparser_f_file.sv:2: ERROR: Digit larger than 1 used in in base-2 constant." 1
read_verilog -sv ./constparser_f_file.sv
6 changes: 6 additions & 0 deletions tests/verilog/constparser_g.ys
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
logger -expect prefix-error "<<EOT:2: ERROR: syntax error, unexpected invalid token, expecting TOK_BASED_CONSTVAL" 1
read_verilog <<EOT
module test (y);
output signed [2:0] y = 1'bg;
endmodule
EOT
Loading