Add unit tests

This commit is contained in:
Alexey Rybalchenko 2020-07-09 15:05:15 +02:00
parent 1b421d34ff
commit 686e457724
10 changed files with 676 additions and 211 deletions

View File

@ -90,8 +90,20 @@ set_target_properties(FairLogger PROPERTIES
) )
if(BUILD_TESTING) if(BUILD_TESTING)
add_executable(loggerTest test/loggerTest.cxx) add_executable(loggerTest test/logger.cxx)
target_link_libraries(loggerTest FairLogger pthread) target_link_libraries(loggerTest FairLogger)
add_executable(macrosTest test/macros.cxx)
target_link_libraries(macrosTest FairLogger)
add_executable(nologTest test/nolog.cxx)
target_link_libraries(nologTest FairLogger)
add_executable(severityTest test/severity.cxx)
target_link_libraries(severityTest FairLogger)
add_executable(sinksTest test/sinks.cxx)
target_link_libraries(sinksTest FairLogger)
add_executable(threadsTest test/threads.cxx)
target_link_libraries(threadsTest FairLogger pthread)
add_executable(verbosityTest test/verbosity.cxx)
target_link_libraries(verbosityTest FairLogger)
endif() endif()
################################################################################ ################################################################################
@ -131,7 +143,13 @@ install_cmake_package()
# Testing ###################################################################### # Testing ######################################################################
if(BUILD_TESTING) if(BUILD_TESTING)
add_test(NAME loggerTest COMMAND $<TARGET_FILE:loggerTest>) add_test(NAME logger COMMAND $<TARGET_FILE:loggerTest>)
add_test(NAME macros COMMAND $<TARGET_FILE:macrosTest>)
add_test(NAME nolog COMMAND $<TARGET_FILE:nologTest>)
add_test(NAME severity COMMAND $<TARGET_FILE:severityTest>)
add_test(NAME sinks COMMAND $<TARGET_FILE:sinksTest>)
add_test(NAME threads COMMAND $<TARGET_FILE:threadsTest>)
add_test(NAME verbosity COMMAND $<TARGET_FILE:verbosityTest>)
endif() endif()
################################################################################ ################################################################################

99
test/Common.h Normal file
View File

@ -0,0 +1,99 @@
/********************************************************************************
* Copyright (C) 2014-2020 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#ifndef FAIR_LOGGER_TEST_COMMON_H
#define FAIR_LOGGER_TEST_COMMON_H
#include <fstream>
#include <functional>
#include <iostream>
#include <regex>
#include <stdexcept>
#include <sstream>
#include <string>
#include <stdio.h> // fflush
#include <unistd.h> // dup, dup2, close
namespace fair
{
namespace logger
{
namespace test
{
template<typename ... T>
auto ToStr(T&&... t) -> std::string
{
std::stringstream ss;
(void)std::initializer_list<int>{(ss << t, 0)...};
return ss.str();
}
template<int S>
class StreamCapturer
{
public:
explicit StreamCapturer()
: mFd(S)
, mOriginalFd(dup(S)) // create a copy of the given file descriptor
{
char name[] = "/tmp/fairlogger_test_capture.XXXXXX";
const int capturedFd = mkstemp(name); // create a unique temporary file
if (capturedFd == -1) {
std::cout << "Could not create tmp file " << name << " for test; does the test have access to the /tmp directory?" << std::endl;
throw std::runtime_error("Could not create tmp file for test; does the test have access to the /tmp directory?");
}
mTmpFile = name;
fflush(nullptr); // flushes all open output streams
dup2(capturedFd, mFd);
close(capturedFd);
}
std::string GetCapture()
{
fflush(nullptr); // flushes all open output streams
std::ifstream t(mTmpFile);
std::stringstream buffer;
buffer << t.rdbuf();
return buffer.str();
}
~StreamCapturer()
{
dup2(mOriginalFd, mFd);
close(mOriginalFd);
remove(mTmpFile.c_str());
}
private:
const int mFd;
int mOriginalFd;
std::string mTmpFile;
};
void CheckOutput(std::string const& expected, std::function<void()> f)
{
std::string output;
{
StreamCapturer<1> c;
f();
output = c.GetCapture();
}
const std::regex e(expected);
if (!std::regex_match(output, e)) {
throw std::runtime_error(std::string("MISMATCH:\n##### expected (regex):\n" + expected + "\n##### found:\n" + output));
}
}
} // namespace test
} // namespace logger
} // namespace fair
#endif // FAIR_LOGGER_TEST_COMMON_H

58
test/logger.cxx Normal file
View File

@ -0,0 +1,58 @@
/********************************************************************************
* Copyright (C) 2014-2020 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include <Logger.h>
#include <iostream>
using namespace std;
using namespace fair;
void printEverySeverity()
{
static int i = 1;
LOG(nolog) << "nolog message, counter: " << i++;
LOG(trace) << "trace message, counter: " << i++;
LOG(debug4) << "debug4 message, counter: " << i++;
LOG(debug3) << "debug3 message, counter: " << i++;
LOG(debug2) << "debug2 message, counter: " << i++;
LOG(debug1) << "debug1 message, counter: " << i++;
LOG(debug) << "debug message, counter: " << i++;
LOG(info) << "info message, counter: " << i++;
LOG(state) << "state message, counter: " << i++;
LOG(warn) << "warning message, counter: " << i++;
LOG(error) << "error message, counter: " << i++;
LOG(fatal) << "fatal message, counter: " << i++;
}
void printAllVerbositiesWithSeverity(Severity sev)
{
Logger::SetConsoleSeverity(sev);
for (uint32_t i = 0; i < Logger::fVerbosityNames.size(); ++i) {
cout << "##### testing severity '" << Logger::fSeverityNames.at(static_cast<int>(sev)) << "' with verbosity '" << Logger::fVerbosityNames.at(i) << "'" << endl;
Logger::SetVerbosity(static_cast<Verbosity>(i));
printEverySeverity();
}
}
int main()
{
Logger::SetConsoleColor(true);
Logger::SetVerbosity(Verbosity::veryhigh);
cout << "##### GetConsoleSeverity = " << Logger::SeverityName(Logger::GetConsoleSeverity()) << endl;
cout << "##### testing severities..." << endl;
for (uint32_t i = 0; i < Logger::fSeverityNames.size(); ++i) {
printAllVerbositiesWithSeverity(static_cast<Severity>(i));
}
return 0;
}

View File

@ -1,208 +0,0 @@
/********************************************************************************
* Copyright (C) 2014-2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include <Logger.h>
#include <iostream>
#include <vector>
#include <thread>
using namespace std;
using namespace fair;
void printEverySeverity()
{
static int i = 1;
LOG(nolog) << "nolog message " << i++;
LOG(error) << "error message " << i++;
LOG(warn) << "warning message " << i++;
LOG(state) << "state message " << i++;
LOG(info) << "info message " << i++;
LOG(debug) << "debug message " << i++;
LOG(debug1) << "debug1 message " << i++;
LOG(debug2) << "debug2 message " << i++;
LOG(debug3) << "debug3 message " << i++;
LOG(debug4) << "debug4 message " << i++;
LOG(trace) << "trace message " << i++;
}
void printAllVerbositiesWithSeverity(Severity sev)
{
Logger::SetConsoleSeverity(sev);
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'verylow' verbosity..." << endl;
Logger::SetVerbosity(Verbosity::verylow);
printEverySeverity();
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'low' verbosity..." << endl;
Logger::SetVerbosity(Verbosity::low);
printEverySeverity();
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'medium' verbosity..." << endl;
Logger::SetVerbosity(Verbosity::medium);
printEverySeverity();
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'high' verbosity..." << endl;
Logger::SetVerbosity(Verbosity::high);
printEverySeverity();
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'veryhigh' verbosity..." << endl;
Logger::SetVerbosity(Verbosity::veryhigh);
printEverySeverity();
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'user1' verbosity..." << endl;
Logger::SetVerbosity(Verbosity::user1);
printEverySeverity();
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'user2' verbosity..." << endl;
Logger::SetVerbosity(Verbosity::user2);
printEverySeverity();
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'user3' verbosity..." << endl;
Logger::SetVerbosity(Verbosity::user3);
printEverySeverity();
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'user4' verbosity..." << endl;
Logger::SetVerbosity(Verbosity::user4);
printEverySeverity();
}
void silentlyPrintAllVerbositiesWithSeverity(Severity sev)
{
Logger::SetConsoleSeverity(sev);
Logger::SetVerbosity(Verbosity::verylow);
printEverySeverity();
Logger::SetVerbosity(Verbosity::low);
printEverySeverity();
Logger::SetVerbosity(Verbosity::medium);
printEverySeverity();
Logger::SetVerbosity(Verbosity::high);
printEverySeverity();
Logger::SetVerbosity(Verbosity::veryhigh);
printEverySeverity();
Logger::SetVerbosity(Verbosity::user1);
printEverySeverity();
Logger::SetVerbosity(Verbosity::user2);
printEverySeverity();
Logger::SetVerbosity(Verbosity::user3);
printEverySeverity();
Logger::SetVerbosity(Verbosity::user4);
printEverySeverity();
}
int main()
{
Logger::SetConsoleColor(true);
auto spec = VerbositySpec::Make(VerbositySpec::Info::file_line_function,
VerbositySpec::Info::process_name,
VerbositySpec::Info::process_name);
cout << "Defining custom verbosity \"user2\"" << endl;
Logger::DefineVerbosity(Verbosity::user2, spec);
cout << "cout: testing severities..." << endl;
printAllVerbositiesWithSeverity(Severity::trace);
printAllVerbositiesWithSeverity(Severity::debug4);
printAllVerbositiesWithSeverity(Severity::debug3);
printAllVerbositiesWithSeverity(Severity::debug2);
printAllVerbositiesWithSeverity(Severity::debug1);
printAllVerbositiesWithSeverity(Severity::debug);
printAllVerbositiesWithSeverity(Severity::info);
printAllVerbositiesWithSeverity(Severity::state);
printAllVerbositiesWithSeverity(Severity::warn);
printAllVerbositiesWithSeverity(Severity::error);
printAllVerbositiesWithSeverity(Severity::nolog);
cout << endl;
cout << "cout: setting severity to 'info' and verbosity to 'medium'" << endl;
Logger::SetConsoleSeverity(Severity::info);
Logger::SetVerbosity(Verbosity::medium);
cout << "cout: is logging trace: " << fair::Logger::Logging(Severity::trace) << endl;
cout << "cout: is logging debug4: " << fair::Logger::Logging(Severity::debug) << endl;
cout << "cout: is logging debug3: " << fair::Logger::Logging(Severity::debug) << endl;
cout << "cout: is logging debug2: " << fair::Logger::Logging(Severity::debug) << endl;
cout << "cout: is logging debug1: " << fair::Logger::Logging(Severity::debug) << endl;
cout << "cout: is logging debug: " << fair::Logger::Logging(Severity::debug) << endl;
cout << "cout: is logging info: " << fair::Logger::Logging(Severity::info) << endl;
cout << "cout: is logging state: " << fair::Logger::Logging(Severity::state) << endl;
cout << "cout: is logging warn: " << fair::Logger::Logging(Severity::warn) << endl;
cout << "cout: is logging error: " << fair::Logger::Logging(Severity::error) << endl;
cout << "cout: is logging fatal: " << fair::Logger::Logging(Severity::fatal) << endl;
cout << "cout: is logging nolog: " << fair::Logger::Logging(Severity::nolog) << endl;
for (int i = 0; i < 1000000; ++i) {
silentlyPrintAllVerbositiesWithSeverity(Severity::nolog);
}
cout << endl;
cout << "cout: setting severity to 'trace' and verbosity to 'veryhigh'" << endl;
Logger::SetConsoleSeverity(Severity::trace);
Logger::SetVerbosity(Verbosity::veryhigh);
cout << endl;
cout << "cout: testing conditional logging..." << endl;
int x = 0;
LOG(info) << "x = " << x << " (initial)";
LOG_IF(info, (x == 0)) << "incrementing x to " << ++x;
LOG(info) << "x = " << x << " (after increment)";
LOG_IF(info, (x == 0)) << "this should not be printed and x not incremented: " << ++x;
LOG(info) << "x = " << x << " (after conditional increment)";
cout << endl;
cout << "cout: setting severity to 'nolog'" << endl;
Logger::SetConsoleSeverity(Severity::nolog);
cout << "cout: ----------------------------" << endl;
cout << "cout: open log file with severity 'error'" << endl;
Logger::InitFileSink(Severity::error, "test_log", true);
printEverySeverity();
cout << "cout: closing log file" << endl;
Logger::RemoveFileSink();
cout << "cout: setting severity to 'nolog'" << endl;
Logger::SetConsoleSeverity(Severity::nolog);
cout << "cout: ----------------------------" << endl;
cout << "cout: adding custom sink with error severity" << endl << endl;
Logger::AddCustomSink("CustomSink", "error", [](const string& content, const LogMetaData& metadata)
{
cout << "CustomSink: content: " << content << endl;
cout << "CustomSink: available metadata: " << endl;
cout << "CustomSink: \tstd::time_t timestamp: " << metadata.timestamp << endl;
cout << "CustomSink: \tstd::chrono::microseconds us: " << metadata.us.count() << endl;
cout << "CustomSink: \tstd::string process_name: " << metadata.process_name << endl;
cout << "CustomSink: \tstd::string file: " << metadata.file << endl;
cout << "CustomSink: \tstd::string line: " << metadata.line << endl;
cout << "CustomSink: \tstd::string func: " << metadata.func << endl;
cout << "CustomSink: \tstd::string severity_name: " << metadata.severity_name << endl;
cout << "CustomSink: \tfair::Severity severity: " << static_cast<int>(metadata.severity) << endl;
});
printEverySeverity();
cout << endl << "cout: removing custom sink with info severity" << endl;
Logger::AddCustomSink("CustomSink", Severity::error, [](const string& /*content*/, const LogMetaData& /*metadata*/){});
Logger::RemoveCustomSink("CustomSink");
Logger::RemoveCustomSink("bla");
cout << "cout: setting severity to 'trace'" << endl;
Logger::SetConsoleSeverity(Severity::trace);
LOGP(info, "Hello {} {}!", "world", ":-)");
LOGF(info, "Hello %s %s!", "world", ":-)");
cout << "cout: setting verbosity to 'high'" << endl;
Logger::SetVerbosity(Verbosity::high);
LOGV(info, verylow) << "I should be printed with very low verbosity";
cout << "cout: pushing 4 new lines with LOGN() in info verbosity" << endl;
LOGN(info);
LOGN(info);
LOGN(info);
LOGN(info);
return 0;
}

60
test/macros.cxx Normal file
View File

@ -0,0 +1,60 @@
/********************************************************************************
* Copyright (C) 2014-2020 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include "Common.h"
#include <Logger.h>
#include <iostream>
using namespace std;
using namespace fair;
using namespace fair::logger::test;
int main()
{
try {
Logger::SetConsoleColor(false);
Logger::SetConsoleSeverity(Severity::fatal);
Logger::SetVerbosity(Verbosity::verylow);
int x = 0;
CheckOutput("^incrementing x to 1\n$", [&]() { LOG_IF(fatal, true) << "incrementing x to " << ++x; });
if (x != 1) {
throw runtime_error(ToStr("expected x to be 1, but it is: ", x));
}
CheckOutput("^$", [&]() { LOG_IF(fatal, false) << "incrementing x to " << ++x; });
if (x != 1) {
throw runtime_error(ToStr("expected x to be 1, but it is: ", x));
}
CheckOutput("^Hello world :-\\)!\n$", []() { LOGP(fatal, "Hello {} {}!", "world", ":-)"); });
CheckOutput("^Hello world :-\\)!\n$", []() { LOGF(fatal, "Hello %s %s!", "world", ":-)"); });
CheckOutput(ToStr(R"(^\[FATAL])", " content\n$"), []() { LOGV(fatal, low) << "content"; });
CheckOutput("^\n\n\n\n$", []() {
LOGN(fatal);
LOGN(fatal);
LOGN(fatal);
LOGN(fatal);
});
Logger::SetVerbosity(Verbosity::veryhigh);
CheckOutput(ToStr(R"(^\[.*]\[\d{2}:\d{2}:\d{2}\.\d{6}]\[FATAL]\[a:4:b])", " c\n$"), []() {
LOGD(Severity::fatal, "a", "4", "b") << "c";
});
} catch (runtime_error& rte) {
cout << rte.what() << endl;
return 1;
}
return 0;
}

60
test/nolog.cxx Normal file
View File

@ -0,0 +1,60 @@
/********************************************************************************
* Copyright (C) 2014-2020 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include <Logger.h>
using namespace std;
using namespace fair;
void printEverySeverity()
{
LOG(nolog) << "nolog message, counter: ";
LOG(trace) << "trace message, counter: ";
LOG(debug4) << "debug4 message, counter: ";
LOG(debug3) << "debug3 message, counter: ";
LOG(debug2) << "debug2 message, counter: ";
LOG(debug1) << "debug1 message, counter: ";
LOG(debug) << "debug message, counter: ";
LOG(info) << "info message, counter: " ;
LOG(state) << "state message, counter: ";
LOG(warn) << "warning message, counter: ";
LOG(error) << "error message, counter: ";
}
void silentlyPrintAllVerbositiesWithSeverity(Severity sev)
{
Logger::SetConsoleSeverity(sev);
Logger::SetVerbosity(Verbosity::verylow);
printEverySeverity();
Logger::SetVerbosity(Verbosity::low);
printEverySeverity();
Logger::SetVerbosity(Verbosity::medium);
printEverySeverity();
Logger::SetVerbosity(Verbosity::high);
printEverySeverity();
Logger::SetVerbosity(Verbosity::veryhigh);
printEverySeverity();
Logger::SetVerbosity(Verbosity::user1);
printEverySeverity();
Logger::SetVerbosity(Verbosity::user2);
printEverySeverity();
Logger::SetVerbosity(Verbosity::user3);
printEverySeverity();
Logger::SetVerbosity(Verbosity::user4);
printEverySeverity();
}
int main()
{
for (int i = 0; i < 1000000; ++i) {
silentlyPrintAllVerbositiesWithSeverity(Severity::nolog);
}
return 0;
}

99
test/severity.cxx Normal file
View File

@ -0,0 +1,99 @@
/********************************************************************************
* Copyright (C) 2014-2020 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include "Common.h"
#include <Logger.h>
#include <cstdint>
#include <iostream>
#include <stdexcept>
#include <string>
using namespace std;
using namespace fair;
using namespace fair::logger::test;
uint32_t printEverySeverity(uint32_t i)
{
LOG(nolog) << "nolog message, counter: " << i++;
LOG(trace) << "trace message, counter: " << i++;
LOG(debug4) << "debug4 message, counter: " << i++;
LOG(debug3) << "debug3 message, counter: " << i++;
LOG(debug2) << "debug2 message, counter: " << i++;
LOG(debug1) << "debug1 message, counter: " << i++;
LOG(debug) << "debug message, counter: " << i++;
LOG(info) << "info message, counter: " << i++;
LOG(state) << "state message, counter: " << i++;
LOG(warn) << "warning message, counter: " << i++;
LOG(error) << "error message, counter: " << i++;
LOG(fatal) << "fatal message, counter: " << i++;
return i;
}
void CheckSeverity(Severity severity)
{
Logger::SetConsoleSeverity(severity);
auto sev = Logger::GetConsoleSeverity();
cout << "##### testing severity '" << Logger::SeverityName(sev) << "' (" << static_cast<int>(sev) << "), Logging(): " << std::boolalpha << Logger::Logging(sev) << endl;
for (uint32_t i = 0; i < Logger::fSeverityNames.size(); ++i) {
if (sev == Severity::nolog) {
if (i == 11) {
if (!Logger::Logging(static_cast<Severity>(i))) {
throw runtime_error(ToStr("expecting to be logging ", Logger::fSeverityNames.at(i), " during ", Logger::fSeverityNames.at(static_cast<int>(sev)), ", but it is not."));
}
} else {
if (Logger::Logging(static_cast<Severity>(i))) {
throw runtime_error(ToStr("expecting to NOT be logging ", Logger::fSeverityNames.at(i), " during ", Logger::fSeverityNames.at(static_cast<int>(sev)), ", but it is."));
}
}
} else {
if (i >= static_cast<unsigned int>(sev)) {
if (!Logger::Logging(static_cast<Severity>(i))) {
throw runtime_error(ToStr("expecting to be logging ", Logger::fSeverityNames.at(i), " during ", Logger::fSeverityNames.at(static_cast<int>(sev)), ", but it is not."));
}
} else {
if (Logger::Logging(static_cast<Severity>(i))) {
throw runtime_error(ToStr("expecting to NOT be logging ", Logger::fSeverityNames.at(i), " during ", Logger::fSeverityNames.at(static_cast<int>(sev)), ", but it is."));
}
}
}
}
uint32_t i = 0;
i = printEverySeverity(i);
if (sev == Severity::nolog) {
if (i != 1) {
throw runtime_error(ToStr("expected: i==1, found: i==", i));
}
} else {
if (i != Logger::fSeverityNames.size() - static_cast<int>(sev)) {
throw runtime_error(ToStr("expected: i==", Logger::fSeverityNames.size() - static_cast<int>(sev) - 1, ", found: i==", i));
}
}
}
int main()
{
Logger::SetConsoleColor(true);
try {
cout << "##### testing " << Logger::fSeverityNames.size() << " severities..." << endl;
for (uint32_t i = 0; i < Logger::fSeverityNames.size(); ++i) {
CheckSeverity(static_cast<Severity>(i));
}
} catch (runtime_error& rte) {
cout << rte.what() << endl;
return 1;
}
return 0;
}

134
test/sinks.cxx Normal file
View File

@ -0,0 +1,134 @@
/********************************************************************************
* Copyright (C) 2014-2020 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include "Common.h"
#include <Logger.h>
#include <fstream>
#include <iostream>
#include <random>
#include <sstream>
using namespace std;
using namespace fair;
using namespace fair::logger::test;
int main()
{
Logger::SetConsoleColor(false);
Logger::SetVerbosity(Verbosity::low);
Logger::SetConsoleSeverity(Severity::nolog);
try {
#ifdef FAIR_MIN_SEVERITY
if (static_cast<int>(Severity::FAIR_MIN_SEVERITY) > static_cast<int>(Severity::warn)) {
cout << "test requires at least FAIR_MIN_SEVERITY == warn to run, skipping" << endl;
return 0;
}
#endif
if (Logger::Logging(Severity::warn)) { cout << "Logger expected to NOT log warn, but it reports to do so" << endl; return 1; }
if (Logger::Logging(Severity::error)) { cout << "Logger expected to NOT log error, but it reports to do so" << endl; return 1; }
if (!Logger::Logging(Severity::fatal)) { cout << "Logger expected to log fatal, but it reports not to" << endl; return 1; }
cout << "##### adding file sink with warn severity" << endl;
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> distrib(1, 65536);
string name = Logger::InitFileSink(Severity::warn, string("test_log_" + to_string(distrib(gen))), true);
CheckOutput("^\\[FATAL] fatal\n$", [](){
LOG(state) << "state";
LOG(warn) << "warning";
LOG(error) << "error";
LOG(fatal) << "fatal";
});
if (Logger::Logging(Severity::state)) { cout << "Logger expected to NOT log warn, but it reports to do so" << endl; return 1; }
if (!Logger::Logging(Severity::warn)) { cout << "Logger expected to log warn, but it reports not to" << endl; return 1; }
if (!Logger::Logging(Severity::error)) { cout << "Logger expected to log error, but it reports not to" << endl; return 1; }
if (!Logger::Logging(Severity::fatal)) { cout << "Logger expected to log fatal, but it reports not to" << endl; return 1; }
ifstream t(name);
stringstream buffer;
buffer << t.rdbuf();
string fileContent = buffer.str();
if (fileContent != "[WARN] warning\n[ERROR] error\n[FATAL] fatal\n") {
throw runtime_error(ToStr("unexpected file sink output. expected:\n[WARN] warning\n[ERROR] error\n[FATAL] fatal\nfound:\n", fileContent));
}
cout << "##### removing file sink with warn severity" << endl;
Logger::RemoveFileSink();
if (Logger::Logging(Severity::warn)) { cout << "Logger expected to NOT log warn, but it reports to do so" << endl; return 1; }
if (Logger::Logging(Severity::error)) { cout << "Logger expected to NOT log error, but it reports to do so" << endl; return 1; }
if (!Logger::Logging(Severity::fatal)) { cout << "Logger expected to log fatal, but it reports not to" << endl; return 1; }
cout << "##### adding custom sink with warn severity" << endl;
Logger::AddCustomSink("CustomSink", "warn", [](const string& content, const LogMetaData& metadata)
{
cout << "CustomSink " << content << endl;
if (metadata.severity != Severity::warn && metadata.severity != Severity::error && metadata.severity != Severity::fatal) {
throw runtime_error(ToStr("unexpected severity message arrived at custom sink that accepts only warn,error,fatal: ", Logger::fSeverityNames.at(static_cast<int>(metadata.severity))));
}
if (metadata.severity_name != "WARN" && metadata.severity_name != "ERROR" && metadata.severity_name != "FATAL") {
throw runtime_error(ToStr("unexpected severity name arrived at custom sink that accepts only warn,error,fatal: ", metadata.severity_name));
}
});
CheckOutput("^CustomSink warning\nCustomSink error\nCustomSink fatal\n\\[FATAL] fatal\n$", [](){
LOG(state) << "state";
LOG(warn) << "warning";
LOG(error) << "error";
LOG(fatal) << "fatal";
});
if (Logger::Logging(Severity::state)) { cout << "Logger expected to NOT log warn, but it reports to do so" << endl; return 1; }
if (!Logger::Logging(Severity::warn)) { cout << "Logger expected to log warn, but it reports not to" << endl; return 1; }
if (!Logger::Logging(Severity::error)) { cout << "Logger expected to log error, but it reports not to" << endl; return 1; }
if (!Logger::Logging(Severity::fatal)) { cout << "Logger expected to log fatal, but it reports not to" << endl; return 1; }
cout << "##### removing custom sink with error severity" << endl;
bool caught = false;
try {
Logger::AddCustomSink("CustomSink", Severity::error, [](const string& /*content*/, const LogMetaData& /*metadata*/){});
} catch (runtime_error& rte) {
caught = true;
}
if (!caught) {
throw runtime_error("expected to throw a runtime_error upon adding sink with same key, but none was thrown");
}
Logger::RemoveCustomSink("CustomSink");
if (Logger::Logging(Severity::warn)) { cout << "Logger expected to NOT log warn, but it reports to do so" << endl; return 1; }
if (Logger::Logging(Severity::error)) { cout << "Logger expected to NOT log error, but it reports to do so" << endl; return 1; }
if (!Logger::Logging(Severity::fatal)) { cout << "Logger expected to log fatal, but it reports not to" << endl; return 1; }
caught = false;
try {
Logger::RemoveCustomSink("bla");
} catch (runtime_error& rte) {
caught = true;
}
if (!caught) {
throw runtime_error("expected to throw a runtime_error upon removing non-existent sink, but none was thrown");
}
} catch (runtime_error& rte) {
cout << rte.what() << endl;
return 1;
}
return 0;
}

67
test/threads.cxx Normal file
View File

@ -0,0 +1,67 @@
/********************************************************************************
* Copyright (C) 2014-2020 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include "Common.h"
#include <Logger.h>
#include <iostream>
#include <thread>
#include <vector>
using namespace std;
using namespace fair;
using namespace fair::logger::test;
void f()
{
LOG(fatal) << "a" << "b" << "c" << "d" << "e" << "f" << "g" << "h" << "i" << "j" << "k" << "l" << "m" << "n" << "o" << "p" << "q" << "r" << "s" << "t" << "u" << "v" << "w" << "x" << "y" << "z";
}
int main()
{
try {
Logger::SetConsoleColor(false);
Logger::SetConsoleSeverity(Severity::fatal);
Logger::SetVerbosity(Verbosity::veryhigh);
CheckOutput(
R"(^\[.*]\[\d{2}:\d{2}:\d{2}\.\d{6}]\[FATAL]\[.*:\d+:.*] abcdefghijklmnopqrstuvwxyz
\[.*]\[\d{2}:\d{2}:\d{2}\.\d{6}]\[FATAL]\[.*:\d+:.*] abcdefghijklmnopqrstuvwxyz
\[.*]\[\d{2}:\d{2}:\d{2}\.\d{6}]\[FATAL]\[.*:\d+:.*] abcdefghijklmnopqrstuvwxyz
\[.*]\[\d{2}:\d{2}:\d{2}\.\d{6}]\[FATAL]\[.*:\d+:.*] abcdefghijklmnopqrstuvwxyz
\[.*]\[\d{2}:\d{2}:\d{2}\.\d{6}]\[FATAL]\[.*:\d+:.*] abcdefghijklmnopqrstuvwxyz
$)", []() {
thread t1(f);
thread t2(f);
thread t3(f);
thread t4(f);
thread t5(f);
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
});
thread t1(f);
thread t2(f);
thread t3(f);
thread t4(f);
thread t5(f);
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
} catch (runtime_error& rte) {
cout << rte.what() << endl;
return 1;
}
return 0;
}

78
test/verbosity.cxx Normal file
View File

@ -0,0 +1,78 @@
/********************************************************************************
* Copyright (C) 2014-2020 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include "Common.h"
#include <Logger.h>
#include <iostream>
#include <string>
using namespace std;
using namespace fair;
using namespace fair::logger::test;
int main()
{
Logger::SetConsoleColor(false);
Logger::SetConsoleSeverity(Severity::fatal);
try {
auto spec1 = VerbositySpec::Make(VerbositySpec::Info::file_line_function, VerbositySpec::Info::process_name);
auto spec2 = VerbositySpec::Make(VerbositySpec::Info::process_name, VerbositySpec::Info::file_line_function);
Logger::DefineVerbosity(Verbosity::user1, spec1);
Logger::SetVerbosity(Verbosity::user1); // spec1 on user1
CheckOutput(ToStr(R"(^\[.*:\d{2}:.*]\[.*])", " content\n$"), []() { LOG(fatal) << "content"; });
Logger::DefineVerbosity(Verbosity::user1, spec2);
Logger::SetVerbosity(Verbosity::user1); // spec2 on user1
CheckOutput(ToStr(R"(^\[.*]\[.*:\d{2}:.*])", " content\n$"), []() { LOG(fatal) << "content"; });
Logger::DefineVerbosity(Verbosity::user2, spec1);
Logger::SetVerbosity(Verbosity::user2); // spec1 on user2
CheckOutput(ToStr(R"(^\[.*:\d{2}:.*]\[.*])", " content\n$"), []() { LOG(fatal) << "content"; });
Logger::SetVerbosity(Verbosity::verylow); // content
CheckOutput("^content\n$", []() { LOG(fatal) << "content"; });
Logger::SetVerbosity(Verbosity::low); // [severity] content
CheckOutput(ToStr(R"(^\[FATAL])", " content\n$"), []() { LOG(fatal) << "content"; });
Logger::SetVerbosity(Verbosity::medium); // [HH:MM:SS][severity] content
CheckOutput(ToStr(R"(^\[\d{2}:\d{2}:\d{2}]\[FATAL])", " content\n$"), []() { LOG(fatal) << "content"; });
Logger::SetVerbosity(Verbosity::high); // [process_name][HH:MM:SS][severity] content
CheckOutput(ToStr(R"(^\[.*]\[\d{2}:\d{2}:\d{2}]\[FATAL])", " content\n$"), []() { LOG(fatal) << "content"; });
Logger::SetVerbosity(Verbosity::veryhigh); // [process_name][HH:MM:SS:µS][severity][file:line:function] content
CheckOutput(ToStr(R"(^\[.*]\[\d{2}:\d{2}:\d{2}\.\d{6}]\[FATAL]\[.*:\d+:.*])", " content\n$"), []() { LOG(fatal) << "content"; });
Logger::SetConsoleColor(true);
Logger::SetVerbosity(Verbosity::verylow); // content
CheckOutput("^content\n$", []() { LOG(fatal) << "content"; });
Logger::SetVerbosity(Verbosity::low); // [severity] content
CheckOutput("^\\[\033\\[01;31mFATAL\033\\[0m] content\n$", []() { LOG(fatal) << "content"; });
Logger::SetVerbosity(Verbosity::medium); // [HH:MM:SS][severity] content
CheckOutput("^\\[\033\\[01;36m\\d{2}:\\d{2}:\\d{2}\033\\[0m]\\[\033\\[01;31mFATAL\033\\[0m] content\n$", []() { LOG(fatal) << "content"; });
Logger::SetVerbosity(Verbosity::high); // [process_name][HH:MM:SS][severity] content
CheckOutput("^\\[\033\\[01;34m.*\033\\[0m]\\[\033\\[01;36m\\d{2}:\\d{2}:\\d{2}\033\\[0m]\\[\033\\[01;31mFATAL\033\\[0m] content\n$", []() { LOG(fatal) << "content"; });
Logger::SetVerbosity(Verbosity::veryhigh); // [process_name][HH:MM:SS:µS][severity][file:line:function] content
CheckOutput("^\\[\033\\[01;34m.*\033\\[0m]\\[\033\\[01;36m\\d{2}:\\d{2}:\\d{2}\\.\\d{6}\033\\[0m]\\[\033\\[01;31mFATAL\033\\[0m]\\[\033\\[01;34m.*\033\\[0m:\033\\[01;33m\\d+\033\\[0m:\033\\[01;34m.*\033\\[0m] content\n$", []() { LOG(fatal) << "content"; });
} catch (runtime_error& rte) {
cout << rte.what() << endl;
return 1;
}
return 0;
}