#include "logtest.h"
#include "panda/log/console.h"
#include "panda/log/log.h"
#include "panda/log/multi.h"
#include <iostream>
#define TEST(name) TEST_CASE("log: " name, "[log]")
TEST("set_level") {
Ctx c;
set_level(Level::VerboseDebug);
panda_log_verbose_debug("");
c.check_called();
panda_log_critical("");
c.check_called();
set_level(Level::Debug);
panda_log_verbose_debug("");
REQUIRE(c.cnt == 0);
panda_log_debug("");
c.check_called();
}
TEST("should_log") {
Ctx c;
set_level(Level::Debug);
REQUIRE_FALSE(panda_should_log(Level::VerboseDebug));
REQUIRE(panda_should_log(Level::Debug));
set_level(Level::Error);
REQUIRE_FALSE(panda_should_log(Level::Debug));
REQUIRE(panda_should_log(Level::Critical));
}
TEST("streaming params") {
Ctx c;
panda_log_warning("1" << "2" << "3");
CHECK(c.str == "123");
}
TEST("code-eval logging") {
Ctx c;
bool val = false;
panda_log_debug([&]{
val = true;
});
REQUIRE_FALSE(val);
panda_log_warning([&]{
log << "text";
val = true;
});
CHECK(c.str == "text");
panda_log(Level::Error, [&]{
log << "hello";
});
CHECK(c.str == "hello");
REQUIRE(val);
}
TEST("empty log") {
Ctx c;
SECTION("case 1") {
panda_log(Level::Error);
}
SECTION("case 2") {
panda_log_error();
}
c.check_called();
CHECK(c.str == "==> MARK <==");
}
struct Hello {};
static std::ostream& operator<< (std::ostream& os, const Hello&) {
os << "{hello:1}";
return os;
}
TEST("prettify_json") {
Ctx c;
string_view s = "{epta:1, suka:2}";
panda_log_warning(prettify_json{s});
CHECK(c.str != s);
panda_log_warning(prettify_json{Hello()});
CHECK(c.str != "{hello:1}");
}
//TEST("VLA capture") {
// // check if it compiles, gcc has bug with VLA capture
// // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102272
// int size = 10;
// int a[size];
// panda_log_error(a[1]);
//}
TEST("synopsis") {
set_logger([](const string& msg, const Info&) {
std::cout << msg << std::endl;
});
set_formatter("%1t %c[%L/%1M]%C %f:%l,%F(): %m");
set_level(Level::Info);
panda_log_info("info message");
panda_log_warning("hello");
panda_log(Level::Error, "Achtung!");
panda_log_debug("here"); // will not be logged, because min level is INFO, and message will NOT be evaluated
Module my_log_module("CustomName");
panda_log_error(my_log_module, "custom only"); // use certain log module for logging
int data[] = {1,42,5};
//callback will not be called if log level is insufficient
panda_log_notice([&] {
for (auto v : data) {
log << (v + 1);
}
});
// macro uses name panda_log_module as logging module
// first found by C++ name lookup is used
// you may want to define panda_log_module in your application namespace
{
Module panda_log_module("my_module", Level::Error); // local variables have the highest priority
panda_log_error("anything"); // logged with module "my_module"
panda_log_warning("warn"); // will not be logged / evaluated
}
// choose a backend for logging
set_logger(new ConsoleLogger());
// or log to multiple backends
set_logger(new MultiLogger({
MultiLogger::Channel(new ConsoleLogger()),
MultiLogger::Channel([](const string&, const Info&) {
// custom logging function
})
}));
}