diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..f5b2f89 --- /dev/null +++ b/.clang-format @@ -0,0 +1,83 @@ +# Google C/C++ Code Style settings +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html +# Author: Kehan Xue, kehan.xue (at) gmail.com +Language: Cpp +BasedOnStyle: Google +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: None +AlignOperands: Align +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never # To avoid conflict, set this "Never" and each "if statement" should include brace when coding +AllowShortLambdasOnASingleLine: Inline +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +PackConstructorInitializers: Never +BreakBeforeBraces: Attach +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterStruct: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +BreakBeforeBinaryOperators: None +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: AfterColon +BreakInheritanceList: BeforeColon +ColumnLimit: 0 +CompactNamespaces: false +ContinuationIndentWidth: 3 +Cpp11BracedListStyle: true +DerivePointerAlignment: false # Make sure the * or & align on the left +EmptyLineBeforeAccessModifier: LogicalBlock +FixNamespaceComments: true +IncludeBlocks: Preserve +IndentCaseLabels: false +IndentPPDirectives: None +IndentWidth: 3 +KeepEmptyLinesAtTheStartOfBlocks: true +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: All +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PointerAlignment: Left +ReflowComments: false +# SeparateDefinitionBlocks: Always # Only support since clang-format 14 +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: c++11 +TabWidth: 3 +UseTab: Never \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..09894bb --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "cmake.configureOnOpen": false, + "editor.formatOnSave": true +} diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index a95fcdb..1232346 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -3,16 +3,18 @@ `ADD CONTENT HERE TO DESCRIBE THE PURPOSE OF THE PULL REQUEST` + +# Formatting +- [ ] I am following the formatting style of the existing codebase. + +_a clang-format configuration file is available in the root of g3log_ + # Testing - [ ] This new/modified code was covered by unit tests. - - [ ] (insight) Was all tests written using TDD (Test Driven Development) style? - - [ ] The CI (Windows, Linux, OSX) are working without issues. - - [ ] Was new functionality documented? - - [ ] The testing steps 1 - 2 below were followed _step 1_ diff --git a/docs/building.md b/docs/building.md index cae52f5..0883b7b 100644 --- a/docs/building.md +++ b/docs/building.md @@ -213,7 +213,7 @@ will install the g3log library to `CPACK_PACKAGING_INSTALL_PREFIX`. ## Testing -By default, tests will not be built. To enable unit testing, you should turn on `ADD_G3LOG_UNIT_TEST`. +By default, tests will be built. To disable unit testing, you should turn off `ADD_G3LOG_UNIT_TEST`. Suppose the build process has completed, then you can run the tests with: ``` diff --git a/example/main_contract.cpp b/example/main_contract.cpp index e921cfd..950e1dd 100644 --- a/example/main_contract.cpp +++ b/example/main_contract.cpp @@ -9,34 +9,29 @@ #include #include #include -#include #include +#include - -namespace -{ +namespace { #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) const std::string path_to_log_file = "./"; #else const std::string path_to_log_file = "/tmp/"; #endif -} +} // namespace -namespace example_fatal -{ - void killWithContractIfNonEqual(int first, int second) - { +namespace example_fatal { + void killWithContractIfNonEqual(int first, int second) { CHECK(first == second) << "Test to see if contract works: onetwothree: " << 123 << ". This should be at the end of the log, and will exit this example"; } -} // example fatal +} // namespace example_fatal -int main(int argc, char **argv) -{ +int main(int argc, char** argv) { double pi_d = 3.1415926535897932384626433832795; float pi_f = 3.1415926535897932384626433832795f; auto worker = g3::LogWorker::createLogWorker(); - auto handle= worker->addDefaultLogger(argv[0], path_to_log_file); + auto handle = worker->addDefaultLogger(argv[0], path_to_log_file); g3::initializeLogging(worker.get()); std::future log_file_name = handle->call(&g3::FileSink::fileName); @@ -49,11 +44,11 @@ int main(int argc, char **argv) changeFormatting.wait(); changeHeader.wait(); - std::cout << "* This is an example of g3log. It WILL exit by a failed CHECK(...)" << std::endl; std::cout << "* that acts as a FATAL trigger. Please see the generated log and " << std::endl; std::cout << "* compare to the code at:\n* \t g3log/test_example/main_contract.cpp" << std::endl; - std::cout << "*\n* Log file: [" << log_file_name.get() << "]\n\n" << std::endl; + std::cout << "*\n* Log file: [" << log_file_name.get() << "]\n\n" + << std::endl; LOGF(INFO, "Hi log %d", 123); LOG(INFO) << "Test SLOG INFO"; @@ -72,4 +67,3 @@ int main(int argc, char **argv) int larger = 2; example_fatal::killWithContractIfNonEqual(smaller, larger); } - diff --git a/example/main_fatal_choice.cpp b/example/main_fatal_choice.cpp index 9fe5c75..50c3359 100644 --- a/example/main_fatal_choice.cpp +++ b/example/main_fatal_choice.cpp @@ -9,14 +9,14 @@ #include #include -#include #include -#include -#include -#include #include -#include #include +#include +#include +#include +#include +#include #ifndef _MSC_VER #define NOEXCEPT noexcept @@ -24,17 +24,15 @@ #define NOEXCEPT throw() #endif -namespace -{ +namespace { #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) const std::string path_to_log_file = "./"; #else const std::string path_to_log_file = "/tmp/"; #endif - void ToLower(std::string &str) - { - for (auto &character : str) { + void ToLower(std::string& str) { + for (auto& character : str) { character = std::tolower(character); } } @@ -75,7 +73,7 @@ namespace int gShouldBeZero = 1; void DivisionByZero() { - LOG(G3LOG_DEBUG) << " trigger exit Executing DivisionByZero: gShouldBeZero: " << gShouldBeZero; + LOG(G3LOG_DEBUG) << " trigger exit Executing DivisionByZero: gShouldBeZero: " << gShouldBeZero; LOG(INFO) << "Division by zero is a big no-no"; int value = 3; auto test = value / gShouldBeZero; @@ -96,10 +94,9 @@ namespace LOG(WARNING) << "Expected to have died by now..."; } - void AccessViolation() { LOG(G3LOG_DEBUG) << " trigger exit"; - char *ptr = 0; + char* ptr = 0; LOG(INFO) << "Death by access violation is imminent"; *ptr = 0; LOG(WARNING) << "Expected to have died by now..."; @@ -119,8 +116,7 @@ namespace f2.wait(); } - - using deathfunc = void (*) (void); + using deathfunc = void (*)(void); void Death_x10000(deathfunc func, std::string funcname) NOEXCEPT { LOG(G3LOG_DEBUG) << " trigger exit"; std::vector> asyncs; @@ -136,19 +132,20 @@ namespace std::cout << __FUNCTION__ << " unexpected result. Death by " << funcname << " did not crash and exit the system" << std::endl; } - void Throw() NOEXCEPT { LOG(G3LOG_DEBUG) << " trigger exit"; std::future empty; - empty.get(); + empty.get(); // --> thows future_error http://en.cppreference.com/w/cpp/thread/future_error // example of std::exceptions can be found here: http://en.cppreference.com/w/cpp/error/exception } - void SegFaultAttempt_x10000() NOEXCEPT { - - deathfunc f = []{char* ptr = 0; *ptr = 1; }; + + deathfunc f = [] { + char* ptr = 0; + *ptr = 1; + }; Death_x10000(f, "throw uncaught exception... and then some sigsegv calls"); } @@ -169,28 +166,57 @@ namespace CallActualExitFunction(fatal_function); } - - void ExecuteDeathFunction(const bool runInNewThread, int fatalChoice) { LOG(G3LOG_DEBUG) << "trigger exit"; auto exitFunction = &NoExitFunction; switch (fatalChoice) { - case 1: exitFunction = &RaiseSIGABRT; break; - case 2: exitFunction = &RaiseSIGFPE; break; - case 3: exitFunction = &RaiseSIGSEGV; break; - case 4: exitFunction = &RaiseSIGILL; break; - case 5: exitFunction = &RAiseSIGTERM; break; - case 6: exitFunction = &DivisionByZero; gShouldBeZero = 0; DivisionByZero(); break; - case 7: exitFunction = &IllegalPrintf; break; - case 8: exitFunction = &OutOfBoundsArrayIndexing; break; - case 9: exitFunction = &AccessViolation; break; - case 10: exitFunction = &RaiseSIGABRTAndAccessViolation; break; - case 11: exitFunction = &Throw; break; - case 12: exitFunction = &FailedCHECK; break; - case 13: exitFunction = &AccessViolation_x10000; break; - case 14: exitFunction = &SegFaultAttempt_x10000; break; - default: break; + case 1: + exitFunction = &RaiseSIGABRT; + break; + case 2: + exitFunction = &RaiseSIGFPE; + break; + case 3: + exitFunction = &RaiseSIGSEGV; + break; + case 4: + exitFunction = &RaiseSIGILL; + break; + case 5: + exitFunction = &RAiseSIGTERM; + break; + case 6: + exitFunction = &DivisionByZero; + gShouldBeZero = 0; + DivisionByZero(); + break; + case 7: + exitFunction = &IllegalPrintf; + break; + case 8: + exitFunction = &OutOfBoundsArrayIndexing; + break; + case 9: + exitFunction = &AccessViolation; + break; + case 10: + exitFunction = &RaiseSIGABRTAndAccessViolation; + break; + case 11: + exitFunction = &Throw; + break; + case 12: + exitFunction = &FailedCHECK; + break; + case 13: + exitFunction = &AccessViolation_x10000; + break; + case 14: + exitFunction = &SegFaultAttempt_x10000; + break; + default: + break; } if (runInNewThread) { auto dieInNearFuture = std::async(std::launch::async, CallExitFunction, exitFunction); @@ -200,12 +226,10 @@ namespace } std::string unexpected = "Expected to exit by FATAL event. That did not happen (printf choice in Windows?)."; - unexpected.append("Choice was: ").append(std::to_string(fatalChoice)).append(", async?: ") - .append(std::to_string(runInNewThread)).append("\n\n***** TEST WILL RUN AGAIN *****\n\n"); + unexpected.append("Choice was: ").append(std::to_string(fatalChoice)).append(", async?: ").append(std::to_string(runInNewThread)).append("\n\n***** TEST WILL RUN AGAIN *****\n\n"); - std::cerr << unexpected << std::endl; + std::cerr << unexpected << std::endl; LOG(WARNING) << unexpected; - } bool AskForAsyncDeath() { @@ -224,8 +248,6 @@ namespace return ("yes" == option); } - - int ChoiceOfFatalExit() { std::string option; int choice = {0}; @@ -257,7 +279,7 @@ namespace choice = std::stoi(option); if (choice <= 0 || choice > 14) { std::cout << "Invalid choice: [" << option << "\n\n"; - } else { + } else { return choice; } } catch (...) { @@ -275,11 +297,11 @@ namespace const int exitChoice = ChoiceOfFatalExit(); ForwardChoiceForFatalExit(runInNewThread, exitChoice); } -} // namespace +} // namespace void breakHere() { std::ostringstream oss; - oss << "Fatal hook function: " << __FUNCTION__ << ":" << __LINE__ << " was called"; + oss << "Fatal hook function: " << __FUNCTION__ << ":" << __LINE__ << " was called"; oss << " through g3::setFatalPreLoggingHook(). setFatalPreLoggingHook should be called AFTER g3::initializeLogging()" << std::endl; LOG(G3LOG_DEBUG) << oss.str(); #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) @@ -287,10 +309,9 @@ void breakHere() { #endif } -int main(int argc, char **argv) -{ +int main(int argc, char** argv) { auto worker = g3::LogWorker::createLogWorker(); - auto handle= worker->addDefaultLogger(argv[0], path_to_log_file); + auto handle = worker->addDefaultLogger(argv[0], path_to_log_file); g3::initializeLogging(worker.get()); g3::setFatalPreLoggingHook(&breakHere); std::future log_file_name = handle->call(&g3::FileSink::fileName); @@ -298,8 +319,8 @@ int main(int argc, char **argv) std::cout << "**** G3LOG FATAL EXAMPLE ***\n\n" << "Choose your type of fatal exit, then " << " read the generated log and backtrace.\n" - << "The logfile is generated at: [" << log_file_name.get() << "]\n\n" << std::endl; - + << "The logfile is generated at: [" << log_file_name.get() << "]\n\n" + << std::endl; LOGF(G3LOG_DEBUG, "Fatal exit example starts now, it's as easy as %d", 123); LOG(INFO) << "Feel free to read the source code also in g3log/example/main_fatal_choice.cpp"; @@ -311,6 +332,4 @@ int main(int argc, char **argv) LOG(WARNING) << "Expected to exit by fatal event, this code line should never be reached"; CHECK(false) << "Forced death"; return 0; - } - diff --git a/example/main_sigsegv.cpp b/example/main_sigsegv.cpp index 8000a11..044b747 100644 --- a/example/main_sigsegv.cpp +++ b/example/main_sigsegv.cpp @@ -10,62 +10,54 @@ #include #include -#include #include #include -namespace -{ +#include +namespace { #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) const std::string path_to_log_file = "./"; #else const std::string path_to_log_file = "/tmp/"; #endif -} +} // namespace -namespace example_fatal -{ +namespace example_fatal { // on Ubunti this caused get a compiler warning with gcc4.6 // from gcc 4.7.2 (at least) it causes a crash (as expected) // On windows it'll probably crash too. - void tryToKillWithIllegalPrintout() - { - std::cout << "\n\n***** Be ready this last example may 'abort' if on Windows/Linux_gcc4.7 " << std::endl << std::flush; - std::cout << "************************************************************\n\n" << std::endl << std::flush; + void tryToKillWithIllegalPrintout() { + std::cout << "\n\n***** Be ready this last example may 'abort' if on Windows/Linux_gcc4.7 " << std::endl + << std::flush; + std::cout << "************************************************************\n\n" + << std::endl + << std::flush; std::this_thread::sleep_for(std::chrono::seconds(1)); const std::string logging = "logging"; LOGF(G3LOG_DEBUG, "ILLEGAL PRINTF_SYNTAX EXAMPLE. WILL GENERATE compiler warning.\n\nbadly formatted message:[Printf-type %s is the number 1 for many %s]", logging.c_str()); } - // The function above 'tryToKillWithIllegalPrintout' IS system / compiler dependent. Older compilers sometimes did NOT generate a SIGSEGV // fault as expected by the illegal printf-format usage. just in case we exit by zero division" - void killByZeroDivision(int value) - { - int zero = 0; // trying to fool the compiler to automatically warn + void killByZeroDivision(int value) { + int zero = 0; // trying to fool the compiler to automatically warn LOG(INFO) << "This is a bad operation [value/zero] : " << value / zero; } - void tryToKillWithAccessingIllegalPointer(std::unique_ptr badStringPtr) { auto badPtr = std::move(badStringPtr); LOG(INFO) << "Function calls through a nullptr object will trigger SIGSEGV"; badStringPtr->append("crashing"); } +} // namespace example_fatal -} // example fatal - - - -int main(int argc, char **argv) -{ +int main(int argc, char** argv) { double pi_d = 3.1415926535897932384626433832795; float pi_f = 3.1415926535897932384626433832795f; using namespace g3; - - std::unique_ptr logworker {LogWorker::createLogWorker()}; + std::unique_ptr logworker{LogWorker::createLogWorker()}; auto sinkHandle = logworker->addSink(std::make_unique(argv[0], path_to_log_file), &FileSink::fileWrite); @@ -74,8 +66,8 @@ int main(int argc, char **argv) std::cout << "* This is an example of g3log. It WILL exit by a FATAL trigger" << std::endl; std::cout << "* Please see the generated log and compare to the code at" << std::endl; std::cout << "* g3log/test_example/main.cpp" << std::endl; - std::cout << "*\n* Log file: [" << log_file_name.get() << "]\n\n" << std::endl; - + std::cout << "*\n* Log file: [" << log_file_name.get() << "]\n\n" + << std::endl; LOGF(INFO, "Hi log %d", 123); LOG(INFO) << "Test SLOG INFO"; @@ -111,8 +103,8 @@ int main(int argc, char **argv) std::unique_ptr badStringPtr; example_fatal::tryToKillWithAccessingIllegalPointer(std::move(badStringPtr)); - // what happened? OK. let us just exit with SIGFPE - int value = 1; // system dependent but it SHOULD never reach this line + // what happened? OK. let us just exit with SIGFPE + int value = 1; // system dependent but it SHOULD never reach this line example_fatal::killByZeroDivision(value); return 0; } diff --git a/src/crashhandler_unix.cpp b/src/crashhandler_unix.cpp index df18b23..dacb575 100644 --- a/src/crashhandler_unix.cpp +++ b/src/crashhandler_unix.cpp @@ -7,27 +7,26 @@ * ============================================================================*/ #include "g3log/crashhandler.hpp" -#include "g3log/logmessage.hpp" #include "g3log/logcapture.hpp" #include "g3log/loglevels.hpp" +#include "g3log/logmessage.hpp" #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) #error "crashhandler_unix.cpp used but it's a windows system" #endif - -#include -#include -#include -#include #include -#include -#include -#include -#include +#include +#include #include +#include +#include +#include +#include #include #include +#include +#include // Linux/Clang, OSX/Clang, OSX/gcc #if (defined(__clang__) || defined(__APPLE__)) @@ -36,10 +35,9 @@ #include #endif - namespace { - std::atomic gBlockForFatal {true}; + std::atomic gBlockForFatal{true}; const std::map kSignals = { {SIGABRT, "SIGABRT"}, @@ -62,9 +60,9 @@ namespace { // ALL thanks to this thread at StackOverflow. Pretty much borrowed from: // Ref: http://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes void signalHandler(int signal_number, siginfo_t* /*info*/, void* /*unused_context*/) { - + using namespace g3::internal; - + // Only one signal will be allowed past this point if (false == shouldDoExit()) { while (shouldBlockForFatalHandling()) { @@ -81,7 +79,7 @@ namespace { fatal_stream << "\n***** SIGNAL " << fatal_reason << "(" << signal_number << ")" << std::endl; LogCapture trigger(FATAL_SIGNAL, static_cast(signal_number), dump.c_str()); trigger.stream() << fatal_stream.str(); - } // message sent to g3LogWorker + } // message sent to g3LogWorker // wait to die } @@ -92,17 +90,17 @@ namespace { #if !(defined(DISABLE_FATAL_SIGNALHANDLING)) struct sigaction action; sigemptyset(&action.sa_mask); - action.sa_sigaction = &signalHandler; // callback to crashHandler for fatal signals + action.sa_sigaction = &signalHandler; // callback to crashHandler for fatal signals // sigaction to use sa_sigaction file. ref: http://www.linuxprogrammingblog.com/code-examples/sigaction action.sa_flags = SA_SIGINFO; // do it verbose style - install all signal actions for (const auto& sig_pair : gSignals) { struct sigaction old_action; - memset(&old_action, 0, sizeof (old_action)); + memset(&old_action, 0, sizeof(old_action)); if (sigaction(sig_pair.first, &action, &old_action) < 0) { - std::string signalerror = "sigaction - " + sig_pair.second; + std::string signalerror = "sigaction - " + sig_pair.second; perror(signalerror.c_str()); } else { gSavedSigActions[sig_pair.first] = old_action; @@ -111,14 +109,7 @@ namespace { #endif } - - -} // end anonymous namespace - - - - - +} // end anonymous namespace // Redirecting and using signals. In case of fatal signals g3log should log the fatal signal // and flush the log queue and then "rethrow" the signal to exit @@ -149,7 +140,7 @@ namespace g3 { const size_t max_dump_size = 50; void* dump[max_dump_size]; const size_t size = backtrace(dump, max_dump_size); - char** messages = backtrace_symbols(dump, static_cast(size)); // overwrite sigaction with caller's address + char** messages = backtrace_symbols(dump, static_cast(size)); // overwrite sigaction with caller's address // dump stack: skip first frame, since that is here std::ostringstream oss; @@ -160,26 +151,21 @@ namespace g3 { /// first look for format that includes brackets "(mangled_name+offset)"" const auto firstBracket = strMessage.find_last_of('('); const auto secondBracket = strMessage.find_last_of(')'); - if (firstBracket != strMessage.npos && secondBracket != strMessage.npos) - { - const auto betweenBrackets = strMessage.substr(firstBracket + 1, secondBracket - firstBracket - 1); - const auto plusSign = betweenBrackets.find_first_of('+'); - if (plusSign != betweenBrackets.npos) - { - mangled_name = betweenBrackets.substr(0, plusSign); - offset = betweenBrackets.substr(plusSign + 1, betweenBrackets.npos); - } - } - else - { - /// we did not found brackets, looking for "_mangled_name + offset" - const auto plusSign = strMessage.find_first_of('+'); - const auto lastUnderscore = strMessage.rfind(" _"); - if (plusSign != strMessage.npos && lastUnderscore != strMessage.npos) - { - mangled_name = strMessage.substr(lastUnderscore + 1, plusSign - lastUnderscore - 2); - offset = strMessage.substr(plusSign + 2, strMessage.npos); - } + if (firstBracket != strMessage.npos && secondBracket != strMessage.npos) { + const auto betweenBrackets = strMessage.substr(firstBracket + 1, secondBracket - firstBracket - 1); + const auto plusSign = betweenBrackets.find_first_of('+'); + if (plusSign != betweenBrackets.npos) { + mangled_name = betweenBrackets.substr(0, plusSign); + offset = betweenBrackets.substr(plusSign + 1, betweenBrackets.npos); + } + } else { + /// we did not found brackets, looking for "_mangled_name + offset" + const auto plusSign = strMessage.find_first_of('+'); + const auto lastUnderscore = strMessage.rfind(" _"); + if (plusSign != strMessage.npos && lastUnderscore != strMessage.npos) { + mangled_name = strMessage.substr(lastUnderscore + 1, plusSign - lastUnderscore - 2); + offset = strMessage.substr(plusSign + 2, strMessage.npos); + } } // if the line could be processed, attempt to demangle the symbol @@ -188,71 +174,72 @@ namespace g3 { char* real_name = abi::__cxa_demangle(mangled_name.c_str(), 0, 0, &status); // if demangling is successful, output the demangled function name if (status == 0) { - oss << "\tstack dump [" << idx << "] " << real_name << " + " << offset<< std::endl; - }// otherwise, output the mangled function name + oss << "\tstack dump [" << idx << "] " << real_name << " + " << offset << std::endl; + } // otherwise, output the mangled function name else { - oss << "\tstack dump [" << idx << "] " << mangled_name << " + " << offset<< std::endl; + oss << "\tstack dump [" << idx << "] " << mangled_name << " + " << offset << std::endl; } - free(real_name); // mallocated by abi::__cxa_demangle(...) + free(real_name); // mallocated by abi::__cxa_demangle(...) } else { // no demangling done -- just dump the whole line oss << "\tstack dump [" << idx << "] " << strMessage << std::endl; } - } // END: for(size_t idx = 1; idx < size && messages != nullptr; ++idx) + } // END: for(size_t idx = 1; idx < size && messages != nullptr; ++idx) free(messages); return oss.str(); } - - /// string representation of signal ID std::string exitReasonName(const LEVELS& level, g3::SignalType fatal_id) { int signal_number = static_cast(fatal_id); switch (signal_number) { - case SIGABRT: return "SIGABRT"; - break; - case SIGFPE: return "SIGFPE"; - break; - case SIGSEGV: return "SIGSEGV"; - break; - case SIGILL: return "SIGILL"; - break; - case SIGTERM: return "SIGTERM"; - break; - default: - std::ostringstream oss; - oss << "UNKNOWN SIGNAL(" << signal_number << ") for " << level.text; - return oss.str(); + case SIGABRT: + return "SIGABRT"; + break; + case SIGFPE: + return "SIGFPE"; + break; + case SIGSEGV: + return "SIGSEGV"; + break; + case SIGILL: + return "SIGILL"; + break; + case SIGTERM: + return "SIGTERM"; + break; + default: + std::ostringstream oss; + oss << "UNKNOWN SIGNAL(" << signal_number << ") for " << level.text; + return oss.str(); } } - - // Triggered by g3log->g3LogWorker after receiving a FATAL trigger // which is LOG(FATAL), CHECK(false) or a fatal signal our signalhandler caught. // --- If LOG(FATAL) or CHECK(false) the signal_number will be SIGABRT void exitWithDefaultSignalHandler(const LEVELS& level, g3::SignalType fatal_signal_id) { const int signal_number = static_cast(fatal_signal_id); - - // Restore all saved signal handlers. If handling a signal which causes exiting + + // Restore all saved signal handlers. If handling a signal which causes exiting // than let the original signal handlers to handle other signals. for (const auto& sig : gSignals) { restoreSignalHandler(sig.first); } - - std::cerr << "\n\n" << __FUNCTION__ << ":" << __LINE__ << ". Exiting due to " << level.text << ", " << signal_number << " \n\n" << std::flush; + std::cerr << "\n\n" + << __FUNCTION__ << ":" << __LINE__ << ". Exiting due to " << level.text << ", " << signal_number << " \n\n" + << std::flush; raise(signal_number); // When running as PID1 the above kill doesn't have any effect (execution simply passes through it, contrary - // to a non-PID1 process where execution stops at kill and switches over to signal handling). Also as PID1 + // to a non-PID1 process where execution stops at kill and switches over to signal handling). Also as PID1 // we must unblock the thread that received the original signal otherwise the process will never terminate. gBlockForFatal = false; exit(signal_number); - } // restores the signal handler back to default @@ -262,10 +249,7 @@ namespace g3 { #endif } - - - } // end g3::internal - + } // namespace internal std::string signalToStr(int signal_number) { std::string signal_name; @@ -281,7 +265,6 @@ namespace g3 { return signal_name; } - void restoreSignalHandler(int signal_number) { #if !(defined(DISABLE_FATAL_SIGNALHANDLING)) auto old_action_it = gSavedSigActions.find(signal_number); @@ -298,7 +281,6 @@ namespace g3 { #endif } - // This will override the default signal handler setup and instead // install a custom set of signals to handle void overrideSetupSignals(const std::map overrideSignals) { @@ -309,14 +291,13 @@ namespace g3 { } gSignals = overrideSignals; - installCrashHandler(); // installs all the signal handling for gSignals + installCrashHandler(); // installs all the signal handling for gSignals } - // installs the signal handling for whatever signal set that is currently active // If you want to setup your own signal handling then // You should instead call overrideSetupSignals() void installCrashHandler() { installSignalHandler(); } -} // end namespace g3 +} // end namespace g3 diff --git a/src/crashhandler_windows.cpp b/src/crashhandler_windows.cpp index d93890d..d4a5b39 100644 --- a/src/crashhandler_windows.cpp +++ b/src/crashhandler_windows.cpp @@ -10,20 +10,20 @@ #error "crashhandler_windows.cpp used but not on a windows system" #endif +#include // getpid #include +#include #include #include -#include -#include // getpid -#include "g3log/g3log.hpp" #include "g3log/crashhandler.hpp" -#include "g3log/stacktrace_windows.hpp" +#include "g3log/g3log.hpp" #include "g3log/logcapture.hpp" +#include "g3log/stacktrace_windows.hpp" #define getpid _getpid namespace { - std::atomic gBlockForFatal {true}; + std::atomic gBlockForFatal{true}; LPTOP_LEVEL_EXCEPTION_FILTER g_previous_unexpected_exception_handler = nullptr; #if !(defined(DISABLE_FATAL_SIGNALHANDLING)) @@ -34,8 +34,6 @@ namespace { void* g_vector_exception_handler = nullptr; #endif - - // called for fatal signals SIGABRT, SIGFPE, SIGSEGV, SIGILL, SIGTERM void signalHandler(int signal_number) { using namespace g3::internal; @@ -45,7 +43,6 @@ namespace { fatal_stream << "\n***** Received fatal signal " << g3::internal::exitReasonName(g3::internal::FATAL_SIGNAL, signal_number); fatal_stream << "(" << signal_number << ")\tPID: " << getpid() << std::endl; - LogCapture trigger(FATAL_SIGNAL, static_cast(signal_number), dump.c_str()); trigger.stream() << fatal_stream.str(); @@ -59,9 +56,7 @@ namespace { #if (!defined(NDEBUG) && defined(DEBUG_BREAK_AT_FATAL_SIGNAL)) __debugbreak(); #endif - } // scope exit - message sent to LogWorker, wait to die... - - + } // scope exit - message sent to LogWorker, wait to die... // Unhandled exception catching LONG WINAPI exceptionHandling(EXCEPTION_POINTERS* info, const std::string& handler) { @@ -84,14 +79,12 @@ namespace { return EXCEPTION_CONTINUE_SEARCH; } - // Unhandled exception catching LONG WINAPI unexpectedExceptionHandling(EXCEPTION_POINTERS* info) { g3::internal::restoreFatalHandlingToDefault(); return exceptionHandling(info, "Unexpected Exception Handler"); } - /// Setup through (Windows API) AddVectoredExceptionHandler /// Ref: http://blogs.msdn.com/b/zhanli/archive/2010/06/25/c-tips-addvectoredexceptionhandler-addvectoredcontinuehandler-and-setunhandledexceptionfilter.aspx #if !(defined(DISABLE_VECTORED_EXCEPTIONHANDLING)) @@ -108,8 +101,7 @@ namespace { } } #endif -} // end anonymous namespace - +} // end anonymous namespace namespace g3 { namespace internal { @@ -119,7 +111,6 @@ namespace g3 { return gBlockForFatal; } - /// Generate stackdump. Or in case a stackdump was pre-generated and /// non-empty just use that one. i.e. the latter case is only for /// Windows and test purposes @@ -131,8 +122,6 @@ namespace g3 { return stacktrace::stackdump(); } - - /// string representation of signal ID or Windows exception id std::string exitReasonName(const LEVELS& level, g3::SignalType fatal_id) { if (level == g3::internal::FATAL_EXCEPTION) { @@ -140,19 +129,28 @@ namespace g3 { } switch (fatal_id) { - case SIGABRT: return "SIGABRT"; break; - case SIGFPE: return "SIGFPE"; break; - case SIGSEGV: return "SIGSEGV"; break; - case SIGILL: return "SIGILL"; break; - case SIGTERM: return "SIGTERM"; break; - default: - std::ostringstream oss; - oss << "UNKNOWN SIGNAL(" << fatal_id << ")"; - return oss.str(); + case SIGABRT: + return "SIGABRT"; + break; + case SIGFPE: + return "SIGFPE"; + break; + case SIGSEGV: + return "SIGSEGV"; + break; + case SIGILL: + return "SIGILL"; + break; + case SIGTERM: + return "SIGTERM"; + break; + default: + std::ostringstream oss; + oss << "UNKNOWN SIGNAL(" << fatal_id << ")"; + return oss.str(); } } - // Triggered by g3log::LogWorker after receiving a FATAL trigger // which is LOG(FATAL), CHECK(false) or a fatal signal our signalhandler caught. // --- If LOG(FATAL) or CHECK(false) the signal_number will be SIGABRT @@ -173,17 +171,15 @@ namespace g3 { raise(signal_number); } - // Restore back to default fatal event handling void restoreFatalHandlingToDefault() { #if !(defined(DISABLE_FATAL_SIGNALHANDLING)) - SetUnhandledExceptionFilter (g_previous_unexpected_exception_handler); + SetUnhandledExceptionFilter(g_previous_unexpected_exception_handler); #if !(defined(DISABLE_VECTORED_EXCEPTIONHANDLING)) - RemoveVectoredExceptionHandler (g_vector_exception_handler); + RemoveVectoredExceptionHandler(g_vector_exception_handler); #endif - if (SIG_ERR == signal(SIGABRT, SIG_DFL)) perror("signal - SIGABRT"); @@ -201,14 +197,11 @@ namespace g3 { #endif } - void installSignalHandler() { g3::installSignalHandlerForThread(); } - - } // end g3::internal - + } // namespace internal /// SIGFPE, SIGILL, and SIGSEGV handling must be installed per thread /// on Windows. This is automatically done if you do at least one LOG(...) call @@ -245,4 +238,4 @@ namespace g3 { #endif } -} // end namespace g3 +} // end namespace g3 diff --git a/src/filesink.cpp b/src/filesink.cpp index a7e0f26..2e559d0 100644 --- a/src/filesink.cpp +++ b/src/filesink.cpp @@ -7,23 +7,22 @@ * ============================================================================*/ #include "g3log/filesink.hpp" -#include "filesinkhelper.ipp" #include #include +#include "filesinkhelper.ipp" namespace g3 { using namespace internal; - FileSink::FileSink(const std::string &log_prefix, const std::string &log_directory, const std::string& logger_id, size_t write_to_log_every_x_message) - : _log_details_func(&LogMessage::DefaultLogDetailsToString) - ,_log_file_with_path(log_directory) - , _log_prefix_backup(log_prefix) - , _outptr(new std::ofstream) - , _header("\t\tLOG format: [YYYY/MM/DD hh:mm:ss uuu* LEVEL FILE->FUNCTION:LINE] message\n\n\t\t(uuu*: microseconds fractions of the seconds value)\n\n") - , _firstEntry(true) - , _write_counter(0) - , _write_to_log_every_x_message(write_to_log_every_x_message) - { + FileSink::FileSink(const std::string& log_prefix, const std::string& log_directory, const std::string& logger_id, size_t write_to_log_every_x_message) : + _log_details_func(&LogMessage::DefaultLogDetailsToString), + _log_file_with_path(log_directory), + _log_prefix_backup(log_prefix), + _outptr(new std::ofstream), + _header("\t\tLOG format: [YYYY/MM/DD hh:mm:ss uuu* LEVEL FILE->FUNCTION:LINE] message\n\n\t\t(uuu*: microseconds fractions of the seconds value)\n\n"), + _firstEntry(true), + _write_counter(0), + _write_to_log_every_x_message(write_to_log_every_x_message) { _log_prefix_backup = prefixSanityFix(log_prefix); if (!isValidFilename(_log_prefix_backup)) { std::cerr << "g3log: forced abort due to illegal log prefix [" << log_prefix << "]" << std::endl; @@ -42,7 +41,6 @@ namespace g3 { assert(_outptr && "cannot open log file at startup"); } - FileSink::~FileSink() { std::string exit_msg = {"g3log g3FileSink shutdown at: "}; auto now = std::chrono::system_clock::now(); @@ -57,12 +55,12 @@ namespace g3 { // The actual log receiving function void FileSink::fileWrite(LogMessageMover message) { - if (_firstEntry ) { - addLogFileHeader(); + if (_firstEntry) { + addLogFileHeader(); _firstEntry = false; } - auto data = message.get().toString(_log_details_func); + auto data = message.get().toString(_log_details_func); _write_buffer.append(data); if (++_write_counter % _write_to_log_every_x_message == 0) { @@ -71,7 +69,7 @@ namespace g3 { } } - std::string FileSink::changeLogFile(const std::string &directory, const std::string &logger_id) { + std::string FileSink::changeLogFile(const std::string& directory, const std::string& logger_id) { auto now = std::chrono::system_clock::now(); auto now_formatted = g3::localtime_formatted(now, {internal::date_formatted + " " + internal::time_formatted}); @@ -80,8 +78,9 @@ namespace g3 { std::string prospect_log = directory + file_name; std::unique_ptr log_stream = createLogFile(prospect_log); if (nullptr == log_stream) { - filestream() << "\n" << now_formatted << " Unable to change log file. Illegal filename or busy? Unsuccessful log name was: " << prospect_log; - return {}; // no success + filestream() << "\n" + << now_formatted << " Unable to change log file. Illegal filename or busy? Unsuccessful log name was: " << prospect_log; + return {}; // no success } addLogFileHeader(); @@ -115,4 +114,4 @@ namespace g3 { void FileSink::addLogFileHeader() { filestream() << header(_header); } -} // g3 +} // namespace g3 diff --git a/src/g2log.hpp b/src/g2log.hpp index 0c6c932..2ab9ee9 100644 --- a/src/g2log.hpp +++ b/src/g2log.hpp @@ -16,8 +16,7 @@ // Btw: replacing g2log for g3log include is easy on Linux // find . -name "*.cpp*" -print | xargs sed -i -e 's/\g2log\.hpp/\g3log\/g3log\.hpp/g' -#include -#include -#include #include - +#include +#include +#include diff --git a/src/g3log.cpp b/src/g3log.cpp index f93bb71..4299d9b 100644 --- a/src/g3log.cpp +++ b/src/g3log.cpp @@ -19,38 +19,32 @@ * ********************************************* */ #include "g3log/g3log.hpp" -#include "g3log/logworker.hpp" #include "g3log/crashhandler.hpp" -#include "g3log/logmessage.hpp" #include "g3log/loglevels.hpp" +#include "g3log/logmessage.hpp" +#include "g3log/logworker.hpp" - -#include -#include -#include -#include #include #include +#include +#include +#include #include +#include namespace { std::once_flag g_initialize_flag; - g3::LogWorker* g_logger_instance = nullptr; // instantiated and OWNED somewhere else (main) + g3::LogWorker* g_logger_instance = nullptr; // instantiated and OWNED somewhere else (main) std::mutex g_logging_init_mutex; std::unique_ptr g_first_uninitialized_msg = {nullptr}; std::once_flag g_set_first_uninitialized_flag; std::once_flag g_save_first_uninitialized_flag; - const std::function g_pre_fatal_hook_that_does_nothing = [] { /*does nothing */}; + const std::function g_pre_fatal_hook_that_does_nothing = [] { /*does nothing */ }; std::function g_fatal_pre_logging_hook; - std::atomic g_fatal_hook_recursive_counter = {0}; -} - - - - +} // namespace namespace g3 { // signalhandler and internal clock is only needed to install once @@ -76,7 +70,7 @@ namespace g3 { // Save the first uninitialized message, if any std::call_once(g_save_first_uninitialized_flag, [&bgworker] { if (g_first_uninitialized_msg) { - bgworker->save(LogMessagePtr {std::move(g_first_uninitialized_msg)}); + bgworker->save(LogMessagePtr{std::move(g_first_uninitialized_msg)}); } }); @@ -88,34 +82,29 @@ namespace g3 { g_fatal_hook_recursive_counter.store(0); } - /** * default does nothing, @ref ::g_pre_fatal_hook_that_does_nothing * It will be called just before sending the fatal message, @ref pushFatalmessageToLogger * It will be reset to do nothing in ::initializeLogging(...) * so please call this function, if you ever need to, after initializeLogging(...) */ - void setFatalPreLoggingHook(std::function pre_fatal_hook) { + void setFatalPreLoggingHook(std::function pre_fatal_hook) { static std::mutex m; std::lock_guard lock(m); g_fatal_pre_logging_hook = pre_fatal_hook; } - - - // By default this function pointer goes to \ref pushFatalMessageToLogger; - std::function g_fatal_to_g3logworker_function_ptr = internal::pushFatalMessageToLogger; + std::function g_fatal_to_g3logworker_function_ptr = internal::pushFatalMessageToLogger; /** REPLACE fatalCallToLogger for fatalCallForUnitTest * This function switches the function pointer so that only * 'unitTest' mock-fatal calls are made. * */ - void setFatalExitHandler(std::function fatal_call) { + void setFatalExitHandler(std::function fatal_call) { g_fatal_to_g3logworker_function_ptr = fatal_call; } - namespace internal { bool isLoggingInitialized() { @@ -129,7 +118,6 @@ namespace g3 { void shutDownLogging() { std::lock_guard lock(g_logging_init_mutex); g_logger_instance = nullptr; - } /** Same as the Shutdown above but called by the destructor of the LogWorker, thus ensuring that no further @@ -150,25 +138,21 @@ namespace g3 { return true; } - - - /** explicitly copy of all input. This is makes it possibly to use g3log across dynamically loaded libraries * i.e. (dlopen + dlsym) */ void saveMessage(const char* entry, const char* file, int line, const char* function, const LEVELS& level, const char* boolean_expression, int fatal_signal, const char* stack_trace) { - LEVELS msgLevel {level}; - LogMessagePtr message {std::make_unique(file, line, function, msgLevel)}; + LEVELS msgLevel{level}; + LogMessagePtr message{std::make_unique(file, line, function, msgLevel)}; message.get()->write().append(entry); message.get()->setExpression(boolean_expression); - if (internal::wasFatal(level)) { auto fatalhook = g_fatal_pre_logging_hook; // In case the fatal_pre logging actually will cause a crash in its turn // let's not do recursive crashing! setFatalPreLoggingHook(g_pre_fatal_hook_that_does_nothing); - ++g_fatal_hook_recursive_counter; // thread safe counter + ++g_fatal_hook_recursive_counter; // thread safe counter // "benign" race here. If two threads crashes, with recursive crashes // then it's possible that the "other" fatal stack trace will be shown // that's OK since it was anyhow the first crash detected @@ -177,12 +161,14 @@ namespace g3 { message.get()->write().append(stack_trace); if (g_fatal_hook_recursive_counter.load() > 1) { - message.get()->write() - .append("\n\n\nWARNING\n" - "A recursive crash detected. It is likely the hook set with 'setFatalPreLoggingHook(...)' is responsible\n\n") - .append("---First crash stacktrace: ").append(first_stack_trace).append("\n---End of first stacktrace\n"); + message.get()->write().append( + "\n\n\nWARNING\n" + "A recursive crash detected. It is likely the hook set with 'setFatalPreLoggingHook(...)' is responsible\n\n") + .append("---First crash stacktrace: ") + .append(first_stack_trace) + .append("\n---End of first stacktrace\n"); } - FatalMessagePtr fatal_message { std::make_unique(*(message._move_only.get()), fatal_signal) }; + FatalMessagePtr fatal_message{std::make_unique(*(message._move_only.get()), fatal_signal)}; // At destruction, flushes fatal message to g3LogWorker // either we will stay here until the background worker has received the fatal // message, flushed the crash message to the sinks and exits with the same fatal signal @@ -201,7 +187,7 @@ namespace g3 { * The first initialized log entry will also save the first uninitialized log message, if any * @param log_entry to save to logger */ - void pushMessageToLogger(LogMessagePtr incoming) { // todo rename to Push SavedMessage To Worker + void pushMessageToLogger(LogMessagePtr incoming) { // todo rename to Push SavedMessage To Worker // Uninitialized messages are ignored but does not CHECK/crash the logger if (!internal::isLoggingInitialized()) { std::call_once(g_set_first_uninitialized_flag, [&] { @@ -210,7 +196,7 @@ namespace g3 { err.append(g_first_uninitialized_msg->message()); std::string& str = g_first_uninitialized_msg->write(); str.clear(); - str.append(err); // replace content + str.append(err); // replace content std::cerr << str << std::endl; }); return; @@ -230,7 +216,8 @@ namespace g3 { std::ostringstream error; error << "FATAL CALL but logger is NOT initialized\n" << "CAUSE: " << message.get()->reason() - << "\nMessage: \n" << message.get()->toString() << std::flush; + << "\nMessage: \n" + << message.get()->toString() << std::flush; std::cerr << error.str() << std::flush; internal::exitWithDefaultSignalHandler(message.get()->_level, message.get()->_signal_id); } @@ -246,9 +233,8 @@ namespace g3 { * define the behaviour. */ void fatalCall(FatalMessagePtr message) { - g_fatal_to_g3logworker_function_ptr(FatalMessagePtr {std::move(message)}); + g_fatal_to_g3logworker_function_ptr(FatalMessagePtr{std::move(message)}); } - - } // internal -} // g3 + } // namespace internal +} // namespace g3 diff --git a/src/g3log/active.hpp b/src/g3log/active.hpp index c3b9b34..3711f9d 100644 --- a/src/g3log/active.hpp +++ b/src/g3log/active.hpp @@ -19,19 +19,20 @@ #pragma once -#include #include #include +#include #include "g3log/shared_queue.hpp" namespace kjellkod { - typedef std::function Callback; + typedef std::function Callback; class Active { - private: - Active() : done_(false) {} // Construction ONLY through factory createActive(); - Active(const Active &) = delete; - Active &operator=(const Active &) = delete; + private: + Active() : + done_(false) {} // Construction ONLY through factory createActive(); + Active(const Active&) = delete; + Active& operator=(const Active&) = delete; void run() { while (!done_) { @@ -45,10 +46,9 @@ namespace kjellkod { std::thread thd_; bool done_; - - public: + public: virtual ~Active() { - send([this]() noexcept { done_ = true;}); + send([this]() noexcept { done_ = true; }); thd_.join(); } @@ -64,6 +64,4 @@ namespace kjellkod { } }; - - -} // kjellkod +} // namespace kjellkod diff --git a/src/g3log/atomicbool.hpp b/src/g3log/atomicbool.hpp index 022cd6e..d6e51fb 100644 --- a/src/g3log/atomicbool.hpp +++ b/src/g3log/atomicbool.hpp @@ -6,7 +6,6 @@ * For more information see g3log/LICENSE or refer refer to http://unlicense.org * ============================================================================*/ - #pragma once #include @@ -14,13 +13,18 @@ namespace g3 { /// As suggested in: http://stackoverflow.com/questions/13193484/how-to-declare-a-vector-of-atomic-in-c struct atomicbool { - private: + private: std::atomic value_; - public: - atomicbool(): value_ {false} {} - atomicbool(bool value): value_ {value} {} - atomicbool(const std::atomic& value) : value_ {value.load(std::memory_order_acquire)} {} - atomicbool(const atomicbool& other): value_ {other.value_.load(std::memory_order_acquire)} {} + + public: + atomicbool() : + value_{false} {} + atomicbool(bool value) : + value_{value} {} + atomicbool(const std::atomic& value) : + value_{value.load(std::memory_order_acquire)} {} + atomicbool(const atomicbool& other) : + value_{other.value_.load(std::memory_order_acquire)} {} atomicbool& operator=(const atomicbool& other) { value_.store(other.value_.load(std::memory_order_acquire), std::memory_order_release); @@ -32,12 +36,12 @@ namespace g3 { return *this; } - bool operator==(const atomicbool& rhs) const { + bool operator==(const atomicbool& rhs) const { return (value_.load(std::memory_order_acquire) == rhs.value_.load(std::memory_order_acquire)); } - bool value() {return value_.load(std::memory_order_acquire);} - std::atomic& get() {return value_;} + bool value() { return value_.load(std::memory_order_acquire); } + std::atomic& get() { return value_; } }; -} // g3 -// explicit whitespace/EOF for VS15 \ No newline at end of file +} // namespace g3 + // explicit whitespace/EOF for VS15 \ No newline at end of file diff --git a/src/g3log/crashhandler.hpp b/src/g3log/crashhandler.hpp index db6f942..a3fbdb1 100644 --- a/src/g3log/crashhandler.hpp +++ b/src/g3log/crashhandler.hpp @@ -8,10 +8,10 @@ * For more information see g3log/LICENSE or refer refer to http://unlicense.org * ============================================================================*/ #include -#include #include -#include "g3log/loglevels.hpp" +#include #include "g3log/generated_definitions.hpp" +#include "g3log/loglevels.hpp" // kjell. Separera på crashhandler.hpp och crashhanlder_internal.hpp // implementationsfilen kan vara den samma @@ -28,7 +28,6 @@ namespace g3 { SIGTERM TERMINATION (ANSI) */ void installCrashHandler(); - #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) typedef unsigned long SignalType; /// SIGFPE, SIGILL, and SIGSEGV handling must be installed per thread @@ -43,7 +42,6 @@ namespace g3 { // restore to whatever signal handler was used before signal handler installation void restoreSignalHandler(int signal_number); - /// Overrides the existing signal handling for custom signals /// For example: usage of zcmq relies on its own signal handler for SIGTERM /// so users of g3log with zcmq should then use the @ref overrideSetupSignals @@ -55,14 +53,12 @@ namespace g3 { void overrideSetupSignals(const std::map overrideSignals); #endif - namespace internal { /// Resets the fatal signal/exception handling back to default /// which might be needed in case it was previously overridden /// The default signals are: SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM void restoreFatalHandlingToDefault(); - /** return whether or any fatal handling is still ongoing * this is used by g3log::fatalCallToLogger * only in the case of Windows exceptions (not fatal signals) @@ -81,5 +77,5 @@ namespace g3 { * This is an internal only function. Do not use it elsewhere. It is triggered * from g3log, g3LogWorker after flushing messages to file */ void exitWithDefaultSignalHandler(const LEVELS& level, g3::SignalType signal_number); - } // end g3::internal -} // g3 + } // namespace internal +} // namespace g3 diff --git a/src/g3log/filesink.hpp b/src/g3log/filesink.hpp index 455d5a7..af39e51 100644 --- a/src/g3log/filesink.hpp +++ b/src/g3log/filesink.hpp @@ -7,28 +7,27 @@ * ============================================================================*/ #pragma once -#include #include +#include #include "g3log/logmessage.hpp" namespace g3 { class FileSink { - public: - FileSink(const std::string &log_prefix, const std::string &log_directory, const std::string &logger_id="g3log", size_t write_to_log_every_x_message = 100); + public: + FileSink(const std::string& log_prefix, const std::string& log_directory, const std::string& logger_id = "g3log", size_t write_to_log_every_x_message = 100); virtual ~FileSink(); void fileWrite(LogMessageMover message); - std::string changeLogFile(const std::string &directory, const std::string &logger_id); + std::string changeLogFile(const std::string& directory, const std::string& logger_id); std::string fileName(); void overrideLogDetails(LogMessage::LogDetailsFunc func); void overrideLogHeader(const std::string& change); - - private: + private: LogMessage::LogDetailsFunc _log_details_func; std::string _log_file_with_path; - std::string _log_prefix_backup; // needed in case of future log file changes of directory + std::string _log_prefix_backup; // needed in case of future log file changes of directory std::unique_ptr _outptr; std::string _header; bool _firstEntry; @@ -37,14 +36,11 @@ namespace g3 { size_t _write_to_log_every_x_message; void addLogFileHeader(); - std::ofstream &filestream() { + std::ofstream& filestream() { return *(_outptr.get()); } - - FileSink &operator=(const FileSink &) = delete; - FileSink(const FileSink &other) = delete; - + FileSink& operator=(const FileSink&) = delete; + FileSink(const FileSink& other) = delete; }; -} // g3 - +} // namespace g3 diff --git a/src/g3log/future.hpp b/src/g3log/future.hpp index 3bec01f..568a163 100644 --- a/src/g3log/future.hpp +++ b/src/g3log/future.hpp @@ -23,8 +23,6 @@ * PUBLIC DOMAIN and NOT under copywrite protection. * ********************************************* */ - - #include #include "g3log/active.hpp" #include "g3log/moveoncopy.hpp" @@ -42,8 +40,7 @@ namespace g3 { // auto msg_call=[=](){return ("Hello from the Background");}; // auto future_msg = g3::spawn_task(msg_lambda, bgWorker.get()); template - std::future> spawn_task(Func func, BgWorker *worker) - { + std::future> spawn_task(Func func, BgWorker* worker) { typedef std::invoke_result_t result_type; typedef std::packaged_task task_type; @@ -60,4 +57,4 @@ namespace g3 { worker->send(MoveOnCopy(std::move(task))); return result; } -} // end namespace g3 +} // end namespace g3 diff --git a/src/g3log/g3log.hpp b/src/g3log/g3log.hpp index 1a2dc81..2a8539c 100644 --- a/src/g3log/g3log.hpp +++ b/src/g3log/g3log.hpp @@ -18,22 +18,21 @@ * 5. Various Q&A at StackOverflow * ********************************************* */ - #pragma once -#include "g3log/loglevels.hpp" -#include "g3log/logcapture.hpp" -#include "g3log/logmessage.hpp" #include "g3log/generated_definitions.hpp" +#include "g3log/logcapture.hpp" +#include "g3log/loglevels.hpp" +#include "g3log/logmessage.hpp" -#include #include +#include -#if defined(_MSC_VER) && (defined(WINDOWS_FUNCSIG)) // Microsoft +#if defined(_MSC_VER) && (defined(WINDOWS_FUNCSIG)) // Microsoft #define G3LOG_PRETTY_FUNCTION __FUNCSIG__ -#elif defined(__GNUC__) && defined(PRETTY_FUNCTION) // GCC compatible +#elif defined(__GNUC__) && defined(PRETTY_FUNCTION) // GCC compatible #define G3LOG_PRETTY_FUNCTION __PRETTY_FUNCTION__ -#else +#else #define G3LOG_PRETTY_FUNCTION __FUNCTION__ #endif @@ -43,7 +42,6 @@ #define thread_local __declspec(thread) #endif - /** namespace for LOG() and CHECK() frameworks * History lesson: Why the names 'g3' and 'g3log'?: * The framework was made in my own free time as PUBLIC DOMAIN but the @@ -62,8 +60,7 @@ namespace g3 { /** Should be called at very first startup of the software with \ref g3LogWorker * pointer. Ownership of the \ref g3LogWorker is the responsibility of the caller */ - void initializeLogging(LogWorker *logger); - + void initializeLogging(LogWorker* logger); /** setFatalPreLoggingHook() provides an optional extra step before the fatalExitHandler is called * @@ -80,7 +77,7 @@ namespace g3 { * * Linux: g3::setFatalPreLoggingHook([]{ raise(SIGTRAP); }); */ - void setFatalPreLoggingHook(std::function pre_fatal_hook); + void setFatalPreLoggingHook(std::function pre_fatal_hook); /** If the @ref setFatalPreLoggingHook is not enough and full fatal exit handling is needed then * use "setFatalExithandler". Please see g3log.cpp and crashhandler_windows.cpp or crashhandler_unix for @@ -88,16 +85,15 @@ namespace g3 { */ void setFatalExitHandler(std::function fatal_call); - #ifdef G3_DYNAMIC_MAX_MESSAGE_SIZE - // only_change_at_initialization namespace is for changes to be done only during initialization. More specifically - // items here would be called prior to calling other parts of g3log - namespace only_change_at_initialization { - // Sets the MaxMessageSize to be used when capturing log messages. Currently this value is set to 2KB. Messages - // Longer than this are bound to 2KB with the string "[...truncated...]" at the end. This function allows - // this limit to be changed. - void setMaxMessageSize(size_t max_size); - } + // only_change_at_initialization namespace is for changes to be done only during initialization. More specifically + // items here would be called prior to calling other parts of g3log + namespace only_change_at_initialization { + // Sets the MaxMessageSize to be used when capturing log messages. Currently this value is set to 2KB. Messages + // Longer than this are bound to 2KB with the string "[...truncated...]" at the end. This function allows + // this limit to be changed. + void setMaxMessageSize(size_t max_size); + } // namespace only_change_at_initialization #endif /* G3_DYNAMIC_MAX_MESSAGE_SIZE */ // internal namespace is for completely internal or semi-hidden from the g3 namespace due to that it is unlikely @@ -107,13 +103,12 @@ namespace g3 { bool isLoggingInitialized(); // Save the created LogMessage to any existing sinks - void saveMessage(const char *message, const char *file, int line, const char *function, const LEVELS &level, - const char *boolean_expression, int fatal_signal, const char *stack_trace); + void saveMessage(const char* message, const char* file, int line, const char* function, const LEVELS& level, + const char* boolean_expression, int fatal_signal, const char* stack_trace); // forwards the message to all sinks void pushMessageToLogger(LogMessagePtr log_entry); - // forwards a FATAL message to all sinks,. after which the g3logworker // will trigger crashhandler / g3::internal::exitWithDefaultSignalHandler // @@ -122,7 +117,6 @@ namespace g3 { // "setFatalExitHandler" void pushFatalMessageToLogger(FatalMessagePtr message); - // Saves the created FatalMessage to any existing sinks and exits with // the originating fatal signal,. or SIGABRT if it originated from a broken contract. // By default forwards to: pushFatalMessageToLogger, see "setFatalExitHandler" to override @@ -136,11 +130,11 @@ namespace g3 { void shutDownLogging(); // Shutdown logging, but ONLY if the active logger corresponds to the one currently initialized - bool shutDownLoggingForActiveOnly(LogWorker *active); - - } // internal -} // g3 + bool shutDownLoggingForActiveOnly(LogWorker* active); + } // namespace internal +} // namespace g3 + // clang-format off #define INTERNAL_LOG_MESSAGE(level) LogCapture(__FILE__, __LINE__, static_cast(G3LOG_PRETTY_FUNCTION), level) #define INTERNAL_CONTRACT_MESSAGE(boolean_expression) \ @@ -228,3 +222,4 @@ And here is possible output // (ref test_io.cpp) #define CHECK_F(boolean_expression, printf_like_message, ...) \ if (true == (boolean_expression)) {} else INTERNAL_CONTRACT_MESSAGE(#boolean_expression).capturef(printf_like_message, ##__VA_ARGS__) + // clang-format on \ No newline at end of file diff --git a/src/g3log/logcapture.hpp b/src/g3log/logcapture.hpp index 159eeba..a28101a 100644 --- a/src/g3log/logcapture.hpp +++ b/src/g3log/logcapture.hpp @@ -8,15 +8,15 @@ #pragma once -#include "g3log/loglevels.hpp" #include "g3log/crashhandler.hpp" +#include "g3log/loglevels.hpp" -#include -#include -#include #include +#include +#include +#include #ifdef _MSC_VER -# include +#include #endif /** @@ -27,8 +27,7 @@ */ struct LogCapture { /// Called from crash handler when a fatal signal has occurred (SIGSEGV etc) - LogCapture(const LEVELS &level, g3::SignalType fatal_signal, const char *dump = nullptr); - + LogCapture(const LEVELS& level, g3::SignalType fatal_signal, const char* dump = nullptr); /** * @file, line, function are given in g3log.hpp from macros @@ -36,48 +35,41 @@ struct LogCapture { * @expression for CHECK calls * @fatal_signal for failed CHECK:SIGABRT or fatal signal caught in the signal handler */ - LogCapture(const char *file, const int line, const char *function, const LEVELS &level, const char *expression = "", g3::SignalType fatal_signal = SIGABRT, const char *dump = nullptr); - + LogCapture(const char* file, const int line, const char* function, const LEVELS& level, const char* expression = "", g3::SignalType fatal_signal = SIGABRT, const char* dump = nullptr); // At destruction the message will be forwarded to the g3log worker. // In the case of dynamically (at runtime) loaded libraries, the important thing to know is that // all strings are copied, so the original are not destroyed at the receiving end, only the copy - virtual ~LogCapture() noexcept (false); + virtual ~LogCapture() noexcept(false); - - - -#ifdef _MSC_VER -# if _MSC_VER >= 1400 -# define G3LOG_FORMAT_STRING _Printf_format_string_ -# else -# define G3LOG_FORMAT_STRING __format_string -# endif - - void capturef(G3LOG_FORMAT_STRING const char *printf_like_message, ...); +#ifdef _MSC_VER +#if _MSC_VER >= 1400 +#define G3LOG_FORMAT_STRING _Printf_format_string_ #else -# define G3LOG_FORMAT_STRING +#define G3LOG_FORMAT_STRING __format_string +#endif + + void capturef(G3LOG_FORMAT_STRING const char* printf_like_message, ...); +#else +#define G3LOG_FORMAT_STRING // Use "-Wall" to generate warnings in case of illegal printf format. // Ref: http://www.unixwiz.net/techtips/gnu-c-attributes.html - [[gnu::format(printf, 2, 3)]] void capturef(G3LOG_FORMAT_STRING const char *printf_like_message, ...); // 2,3 ref: http://www.codemaestro.com/reviews/18 + [[gnu::format(printf, 2, 3)]] void capturef(G3LOG_FORMAT_STRING const char* printf_like_message, ...); // 2,3 ref: http://www.codemaestro.com/reviews/18 #endif /// prettifying API for this completely open struct - std::ostringstream &stream() { + std::ostringstream& stream() { return _stream; } - - std::ostringstream _stream; std::string _stack_trace; const char* _file; const int _line; const char* _function; - const LEVELS &_level; + const LEVELS& _level; const char* _expression; const g3::SignalType _fatal_signal; - }; //} // g3 diff --git a/src/g3log/loglevels.hpp b/src/g3log/loglevels.hpp index b72bcb7..998ca30 100644 --- a/src/g3log/loglevels.hpp +++ b/src/g3log/loglevels.hpp @@ -22,22 +22,26 @@ #endif #endif -#include #include -#include #include #include +#include +#include // Levels for logging, made so that it would be easy to change, remove, add levels -- KjellKod struct LEVELS { // force internal copy of the const char*. This is a simple safeguard for when g3log is used in a // "dynamic, runtime loading of shared libraries" - LEVELS(const LEVELS& other): value(other.value), text(other.text.c_str()) {} + LEVELS(const LEVELS& other) : + value(other.value), + text(other.text.c_str()) {} - LEVELS(int id, const std::string& idtext) : value(id), text(idtext) {} + LEVELS(int id, const std::string& idtext) : + value(id), + text(idtext) {} - bool operator==(const LEVELS& rhs) const { + bool operator==(const LEVELS& rhs) const { return (value == rhs.value && text == rhs.text); } @@ -51,13 +55,11 @@ struct LEVELS { swap(first.text, second.text); } - LEVELS& operator=(LEVELS other) { swap(*this, other); return *this; } - int value; std::string text; }; @@ -89,14 +91,12 @@ namespace g3 { static const int kWarningValue = 500; static const int kFatalValue = 1000; static const int kInternalFatalValue = 2000; -} // g3 +} // namespace g3 const LEVELS G3LOG_DEBUG{g3::kDebugValue, "DEBUG"}, - INFO {g3::kInfoValue, "INFO"}, - WARNING {g3::kWarningValue, "WARNING"}, - FATAL {g3::kFatalValue, "FATAL"}; - - + INFO{g3::kInfoValue, "INFO"}, + WARNING{g3::kWarningValue, "WARNING"}, + FATAL{g3::kFatalValue, "FATAL"}; namespace g3 { // Logging level and atomic status collection struct @@ -105,10 +105,18 @@ namespace g3 { LEVELS level; // default operator needed for std::map compliance - LoggingLevel(): status(false), level(INFO) {}; - LoggingLevel(const LoggingLevel& lvl) : status(lvl.status), level(lvl.level) {} - LoggingLevel(const LEVELS& lvl): status(true), level(lvl) {}; - LoggingLevel(const LEVELS& lvl, bool enabled): status(enabled), level(lvl) {}; + LoggingLevel() : + status(false), + level(INFO){}; + LoggingLevel(const LoggingLevel& lvl) : + status(lvl.status), + level(lvl.level) {} + LoggingLevel(const LEVELS& lvl) : + status(true), + level(lvl){}; + LoggingLevel(const LEVELS& lvl, bool enabled) : + status(enabled), + level(lvl){}; ~LoggingLevel() = default; LoggingLevel& operator=(const LoggingLevel& other) { @@ -117,26 +125,22 @@ namespace g3 { return *this; } - bool operator==(const LoggingLevel& rhs) const { + bool operator==(const LoggingLevel& rhs) const { return (status == rhs.status && level == rhs.level); } - }; -} // g3 - - - +} // namespace g3 namespace g3 { namespace internal { - const LEVELS CONTRACT {g3::kInternalFatalValue, {"CONTRACT"}}, - FATAL_SIGNAL {g3::kInternalFatalValue + 1, {"FATAL_SIGNAL"}}, - FATAL_EXCEPTION {kInternalFatalValue + 2, {"FATAL_EXCEPTION"}}; + const LEVELS CONTRACT{g3::kInternalFatalValue, {"CONTRACT"}}, + FATAL_SIGNAL{g3::kInternalFatalValue + 1, {"FATAL_SIGNAL"}}, + FATAL_EXCEPTION{kInternalFatalValue + 2, {"FATAL_EXCEPTION"}}; /// helper function to tell the logger if a log message was fatal. If it is it will force /// a shutdown after all log entries are saved to the sinks bool wasFatal(const LEVELS& level); - } + } // namespace internal #ifdef G3_DYNAMIC_LOGGING // Only safe if done at initialization in a single-thread context @@ -152,8 +156,7 @@ namespace g3 { /// remove any added logging levels so that the only ones left are /// {DEBUG,INFO,WARNING,FATAL} void reset(); - } // only_change_at_initialization - + } // namespace only_change_at_initialization namespace log_levels { /// Enable log level >= log_level. @@ -169,24 +172,24 @@ namespace g3 { void disableAll(); void enableAll(); - - /// print all levels with their disabled or enabled status - std::string to_string(std::map levelsToPrint); + /// print all levels with their disabled or enabled status + std::string to_string(std::map levelsToPrint); /// print snapshot of system levels with their /// disabled or enabled status std::string to_string(); - /// Snapshot view of the current logging levels' status std::map getAll(); - enum class status {Absent, Enabled, Disabled}; + enum class status { Absent, + Enabled, + Disabled }; status getStatus(LEVELS level); -} // log_levels + } // namespace log_levels #endif /// Enabled status for the given logging level bool logLevel(const LEVELS& level); -} // g3 +} // namespace g3 diff --git a/src/g3log/logmessage.hpp b/src/g3log/logmessage.hpp index 1258539..9fc2d23 100644 --- a/src/g3log/logmessage.hpp +++ b/src/g3log/logmessage.hpp @@ -8,17 +8,15 @@ #pragma once - - -#include "g3log/loglevels.hpp" -#include "g3log/time.hpp" -#include "g3log/moveoncopy.hpp" #include "g3log/crashhandler.hpp" +#include "g3log/loglevels.hpp" +#include "g3log/moveoncopy.hpp" +#include "g3log/time.hpp" -#include -#include -#include #include +#include +#include +#include namespace g3 { @@ -51,14 +49,14 @@ namespace g3 { // default look is Y/M/D H:M:S std::string timestamp(const std::string& time_format = {internal::date_formatted + " " + internal::time_formatted}) const; - std::string message() const { + std::string message() const { return _message; } std::string& write() const { return _message; } - std::string expression() const { + std::string expression() const { return _expression; } bool wasFatal() const { @@ -71,10 +69,8 @@ namespace g3 { _expression = std::move(expression); } - LogMessage& operator=(LogMessage other); - LogMessage(std::string file, const int line, std::string function, const LEVELS level); explicit LogMessage(const std::string& fatalOsSignalCrashMessage); @@ -82,32 +78,26 @@ namespace g3 { LogMessage(LogMessage&& other); virtual ~LogMessage() {} - // helper log printing functions used by "toString()" static std::string splitFileName(const std::string& str); static std::string fatalSignalToString(const LogMessage& msg); // windows only: fatalExceptionToString - static std::string fatalExceptionToString(const LogMessage& msg); + static std::string fatalExceptionToString(const LogMessage& msg); static std::string fatalLogToString(const LogMessage& msg); static std::string fatalCheckToString(const LogMessage& msg); - static std::string normalToString(const LogMessage& msg); - - + static std::string normalToString(const LogMessage& msg); // the default formatting option static std::string DefaultLogDetailsToString(const LogMessage& msg); - // this function can be used by the logging sink to add thread ID - // see this concept and it is easy to make your own custom formatting + // this function can be used by the logging sink to add thread ID + // see this concept and it is easy to make your own custom formatting static std::string FullLogDetailsToString(const LogMessage& msg); - using LogDetailsFunc = std::string (*) (const LogMessage&); + using LogDetailsFunc = std::string (*)(const LogMessage&); std::string toString(LogDetailsFunc formattingFunc = DefaultLogDetailsToString) const; - - void overrideLogDetailsFunc(LogDetailsFunc func) const; - - + void overrideLogDetailsFunc(LogDetailsFunc func) const; // // Complete access to the raw data in case the helper functions above @@ -121,11 +111,9 @@ namespace g3 { int _line; std::string _function; LEVELS _level; - std::string _expression; // only with content for CHECK(...) calls + std::string _expression; // only with content for CHECK(...) calls mutable std::string _message; - - friend void swap(LogMessage& first, LogMessage& second) { using std::swap; swap(first._timestamp, second._timestamp); @@ -137,12 +125,8 @@ namespace g3 { swap(first._expression, second._expression); swap(first._message, second._message); } - }; - - - /** Trigger for flushing the message queue and exiting the application * A thread that causes a FatalMessage will sleep forever until the * application has exited (after message flush) */ @@ -158,8 +142,7 @@ namespace g3 { const SignalType _signal_id; }; - typedef MoveOnCopy> FatalMessagePtr; typedef MoveOnCopy> LogMessagePtr; typedef MoveOnCopy LogMessageMover; -} // g3 +} // namespace g3 diff --git a/src/g3log/logworker.hpp b/src/g3log/logworker.hpp index 0a46e07..844d91f 100644 --- a/src/g3log/logworker.hpp +++ b/src/g3log/logworker.hpp @@ -11,18 +11,17 @@ * * PUBLIC DOMAIN and Not copyrighted. First published at KjellKod.cc * ********************************************* */ -#include "g3log/g3log.hpp" -#include "g3log/sinkwrapper.hpp" -#include "g3log/sinkhandle.hpp" -#include "g3log/filesink.hpp" -#include "g3log/logmessage.hpp" #include +#include "g3log/filesink.hpp" +#include "g3log/g3log.hpp" +#include "g3log/logmessage.hpp" +#include "g3log/sinkhandle.hpp" +#include "g3log/sinkwrapper.hpp" #include #include #include - namespace g3 { class LogWorker; struct LogWorkerImpl; @@ -32,7 +31,7 @@ namespace g3 { struct LogWorkerImpl final { typedef std::shared_ptr SinkWrapperPtr; std::vector _sinks; - std::unique_ptr _bg; // do not change declaration order. _bg must be destroyed before sinks + std::unique_ptr _bg; // do not change declaration order. _bg must be destroyed before sinks LogWorkerImpl(); ~LogWorkerImpl() = default; @@ -44,7 +43,6 @@ namespace g3 { LogWorkerImpl& operator=(const LogWorkerImpl&) = delete; }; - /// Front end of the LogWorker. API that is useful is /// addSink( sink, default_call ) which returns a handle to the sink. See below and README for usage example /// save( msg ) : internal use @@ -57,15 +55,13 @@ namespace g3 { LogWorker(const LogWorker&) = delete; LogWorker& operator=(const LogWorker&) = delete; - - public: + public: ~LogWorker(); /// Creates the LogWorker with no sinks. See example below on @ref addSink for how to use it /// if you want to use the default file logger then see below for @ref addDefaultLogger static std::unique_ptr createLogWorker(); - /** A convenience function to add the default g3::FileSink to the log worker @param log_prefix that you want @@ -89,26 +85,26 @@ namespace g3 { /// @param real_sink unique_ptr ownership is passed to the log worker /// @param call the default call that should receive either a std::string or a LogMessageMover message /// @return handle to the sink for API access. See usage example below at @ref addDefaultLogger - template + template std::unique_ptr> addSink(std::unique_ptr real_sink, DefaultLogCall call) { using namespace g3; using namespace g3::internal; - auto sink = std::make_shared> (std::move(real_sink), call); + auto sink = std::make_shared>(std::move(real_sink), call); addWrappedSink(sink); - return std::make_unique> (sink); + return std::make_unique>(sink); } - /// Removes a sink. This is a synchronous call. /// You are guaranteed that the sink is removed by the time the call returns /// @param sink_handle the ownership of the sink handle is given - template + template void removeSink(std::unique_ptr> sink_handle) { if (sink_handle) { // sink_handle->sink().use_count() is 1 at this point // i.e. this would be safe as long as no other weak_ptr to shared_ptr conversion // was made by the client: assert(sink_handle->sink().use_count() == 0); - auto weak_ptr_sink = sink_handle->sink(); { + auto weak_ptr_sink = sink_handle->sink(); + { auto bg_removesink_call = [this, weak_ptr_sink] { auto shared_sink = weak_ptr_sink.lock(); if (shared_sink) { @@ -127,13 +123,13 @@ namespace g3 { /// This will clear/remove all the sinks. If a sink shared_ptr was retrieved via the sink /// handle then the sink will be removed internally but will live on in the client's instance void removeAllSinks() { - auto bg_clear_sink_call = [this]() noexcept { _impl._sinks.clear(); }; + auto bg_clear_sink_call = [this]() noexcept { + _impl._sinks.clear(); + }; auto token_cleared = g3::spawn_task(bg_clear_sink_call, _impl._bg.get()); token_cleared.wait(); } - - /// internal: /// pushes in background thread (asynchronously) input messages to log file void save(LogMessagePtr entry); @@ -143,7 +139,5 @@ namespace g3 { /// this way it's ensured that all existing entries were flushed before 'fatal' /// Will abort the application! void fatal(FatalMessagePtr fatal_message); - - }; -} // g3 +} // namespace g3 diff --git a/src/g3log/moveoncopy.hpp b/src/g3log/moveoncopy.hpp index 4c11b5f..32a44b3 100644 --- a/src/g3log/moveoncopy.hpp +++ b/src/g3log/moveoncopy.hpp @@ -14,20 +14,23 @@ namespace g3 { // not CopyConstructible or CopyAssignable. To put them in a std container they need // to be wrapped and their internals "moved" when tried to be copied. - template + template struct MoveOnCopy { mutable Moveable _move_only; - explicit MoveOnCopy(Moveable &&m) : _move_only(std::move(m)) {} - MoveOnCopy(MoveOnCopy const &t) : _move_only(std::move(t._move_only)) {} - MoveOnCopy(MoveOnCopy &&t) : _move_only(std::move(t._move_only)) {} + explicit MoveOnCopy(Moveable&& m) : + _move_only(std::move(m)) {} + MoveOnCopy(MoveOnCopy const& t) : + _move_only(std::move(t._move_only)) {} + MoveOnCopy(MoveOnCopy&& t) : + _move_only(std::move(t._move_only)) {} - MoveOnCopy &operator=(MoveOnCopy const &other) { + MoveOnCopy& operator=(MoveOnCopy const& other) { _move_only = std::move(other._move_only); return *this; } - MoveOnCopy &operator=(MoveOnCopy && other) { + MoveOnCopy& operator=(MoveOnCopy&& other) { _move_only = std::move(other._move_only); return *this; } @@ -36,13 +39,13 @@ namespace g3 { _move_only(); } - Moveable &get() { + Moveable& get() { return _move_only; } - + Moveable release() { return std::move(_move_only); } }; -} // g3 +} // namespace g3 diff --git a/src/g3log/shared_queue.hpp b/src/g3log/shared_queue.hpp index 27da74b..82a73d9 100644 --- a/src/g3log/shared_queue.hpp +++ b/src/g3log/shared_queue.hpp @@ -16,24 +16,23 @@ #pragma once -#include -#include -#include #include +#include +#include +#include /** Multiple producer, multiple consumer thread safe queue * Since 'return by reference' is used this queue won't throw */ -template -class shared_queue -{ +template +class shared_queue { std::queue queue_; mutable std::mutex m_; std::condition_variable data_cond_; - shared_queue &operator=(const shared_queue &) = delete; - shared_queue(const shared_queue &other) = delete; + shared_queue& operator=(const shared_queue&) = delete; + shared_queue(const shared_queue& other) = delete; -public: + public: shared_queue() = default; void push(T item) { @@ -45,7 +44,7 @@ public: } /// \return immediately, with true if successful retrieval - bool try_and_pop(T &popped_item) { + bool try_and_pop(T& popped_item) { std::lock_guard lock(m_); if (queue_.empty()) { return false; @@ -56,10 +55,9 @@ public: } /// Try to retrieve, if no items, wait till an item is available and try again - void wait_and_pop(T &popped_item) { + void wait_and_pop(T& popped_item) { std::unique_lock lock(m_); - while (queue_.empty()) - { + while (queue_.empty()) { data_cond_.wait(lock); // This 'while' loop is equal to // data_cond_.wait(lock, [](bool result){return !queue_.empty();}); diff --git a/src/g3log/sink.hpp b/src/g3log/sink.hpp index 14c0ea6..61f8850 100644 --- a/src/g3log/sink.hpp +++ b/src/g3log/sink.hpp @@ -8,19 +8,18 @@ #pragma once - -#include "g3log/sinkwrapper.hpp" #include "g3log/active.hpp" #include "g3log/future.hpp" #include "g3log/logmessage.hpp" +#include "g3log/sinkwrapper.hpp" -#include #include +#include #include namespace g3 { namespace internal { - typedef std::function AsyncMessageCall; + typedef std::function AsyncMessageCall; /// The asynchronous Sink has an active object, incoming requests for actions // will be processed in the background by the specific object the Sink represents. @@ -34,33 +33,32 @@ namespace g3 { // Ref: send(Call call, Args... args) deals with calls // to the real sink's API - template + template struct Sink : public SinkWrapper { std::unique_ptr _real_sink; std::unique_ptr _bg; AsyncMessageCall _default_log_call; - template - Sink(std::unique_ptr sink, DefaultLogCall call) - : SinkWrapper(), - _real_sink {std::move(sink)}, - _bg(kjellkod::Active::createActive()), - _default_log_call(std::bind(call, _real_sink.get(), std::placeholders::_1)) { + template + Sink(std::unique_ptr sink, DefaultLogCall call) : + SinkWrapper(), + _real_sink{std::move(sink)}, + _bg(kjellkod::Active::createActive()), + _default_log_call(std::bind(call, _real_sink.get(), std::placeholders::_1)) { } - - Sink(std::unique_ptr sink, void(T::*Call)(std::string) ) - : SinkWrapper(), - _real_sink {std::move(sink)}, - _bg(kjellkod::Active::createActive()) { + Sink(std::unique_ptr sink, void (T::*Call)(std::string)) : + SinkWrapper(), + _real_sink{std::move(sink)}, + _bg(kjellkod::Active::createActive()) { std::function adapter = std::bind(Call, _real_sink.get(), std::placeholders::_1); - _default_log_call = [ = ](LogMessageMover m) { + _default_log_call = [=](LogMessageMover m) { adapter(m.get().toString()); }; } virtual ~Sink() { - _bg.reset(); // TODO: to remove + _bg.reset(); // TODO: to remove } void send(LogMessageMover msg) override { @@ -69,10 +67,10 @@ namespace g3 { }); } - template - auto async(Call call, Args &&... args)-> std::future> { + template + auto async(Call call, Args&&... args) -> std::future> { return g3::spawn_task(std::bind(call, _real_sink.get(), std::forward(args)...), _bg.get()); } }; - } // internal -} // g3 + } // namespace internal +} // namespace g3 diff --git a/src/g3log/sinkhandle.hpp b/src/g3log/sinkhandle.hpp index 34c53b4..34848d2 100644 --- a/src/g3log/sinkhandle.hpp +++ b/src/g3log/sinkhandle.hpp @@ -22,22 +22,21 @@ namespace g3 { // The real sink will be owned by g3log. If the real sink is deleted // calls to sink's API through the SinkHandle will return an exception embedded // in the resulting future. Ref: SinkHandle::call - template + template class SinkHandle { std::weak_ptr> _sink; - public: - SinkHandle(std::shared_ptr> sink) - : _sink(sink) {} + public: + SinkHandle(std::shared_ptr> sink) : + _sink(sink) {} ~SinkHandle() = default; - // Asynchronous call to the real sink. If the real sink is already deleted // the returned future will contain a bad_weak_ptr exception instead of the // call result. - template - auto call(AsyncCall func , Args&& ... args) -> std::future> { + template + auto call(AsyncCall func, Args&&... args) -> std::future> { try { std::shared_ptr> sink(_sink); return sink->async(func, std::forward(args)...); @@ -57,6 +56,4 @@ namespace g3 { } }; -} // g3 - - +} // namespace g3 diff --git a/src/g3log/sinkwrapper.hpp b/src/g3log/sinkwrapper.hpp index 0cc1c1b..f9c8fc2 100644 --- a/src/g3log/sinkwrapper.hpp +++ b/src/g3log/sinkwrapper.hpp @@ -14,9 +14,8 @@ namespace g3 { namespace internal { struct SinkWrapper { - virtual ~SinkWrapper() { } + virtual ~SinkWrapper() {} virtual void send(LogMessageMover msg) = 0; }; - } -} - + } // namespace internal +} // namespace g3 diff --git a/src/g3log/stacktrace_windows.hpp b/src/g3log/stacktrace_windows.hpp index 257abde..8d3d889 100644 --- a/src/g3log/stacktrace_windows.hpp +++ b/src/g3log/stacktrace_windows.hpp @@ -11,7 +11,6 @@ * For more information see g3log/LICENSE or refer refer to http://unlicense.org * ============================================================================*/ - #pragma once #if !(defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) #error "stacktrace_win.cpp used but not on a windows system" @@ -19,8 +18,8 @@ #include "g3log/crashhandler.hpp" -#include #include +#include namespace stacktrace { /// return the text description of a Windows exception code @@ -34,9 +33,9 @@ namespace stacktrace { std::string stackdump(); /// helper function: retrieve stackdump, starting from an exception pointer - std::string stackdump(EXCEPTION_POINTERS *info); + std::string stackdump(EXCEPTION_POINTERS* info); /// main stackdump function. retrieve stackdump, from the given context - std::string stackdump(CONTEXT *context); + std::string stackdump(CONTEXT* context); -} // stacktrace +} // namespace stacktrace diff --git a/src/g3log/stlpatch_future.hpp b/src/g3log/stlpatch_future.hpp index d00992c..b7f3016 100644 --- a/src/g3log/stlpatch_future.hpp +++ b/src/g3log/stlpatch_future.hpp @@ -11,45 +11,42 @@ * Ref: workarounds at http://connect.microsoft.com/VisualStudio/feedback/details/791185/std-packaged-task-t-where-t-is-void-or-a-reference-class-are-not-movable * ============================================================================*/ - - #pragma once #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(__MINGW32__) && (_MSC_VER <= 1800) namespace std { - template - class packaged_task - { + template + class packaged_task { promise _my_promise; function _my_func; - public: + public: packaged_task() { } - template - explicit packaged_task(_Fty2 &&_Fnarg) - : _my_func(_Fnarg) { + template + explicit packaged_task(_Fty2&& _Fnarg) : + _my_func(_Fnarg) { } - packaged_task(packaged_task &&_Other) - : _my_promise(move(_Other._my_promise)), - _my_func(move(_Other._my_func)) { + packaged_task(packaged_task&& _Other) : + _my_promise(move(_Other._my_promise)), + _my_func(move(_Other._my_func)) { } - packaged_task &operator=(packaged_task && _Other) { + packaged_task& operator=(packaged_task&& _Other) { _my_promise = move(_Other._my_promise); _my_func = move(_Other._my_func); return (*this); } - packaged_task(const packaged_task &) = delete; - packaged_task &operator=(const packaged_task &) = delete; + packaged_task(const packaged_task&) = delete; + packaged_task& operator=(const packaged_task&) = delete; ~packaged_task() { } - void swap(packaged_task &_Other) { + void swap(packaged_task& _Other) { swap(_my_promise, _Other._my_promise); swap(_my_func, _Other._my_func); } @@ -77,5 +74,5 @@ namespace std { } }; -}; // namespace std -#endif // defined(WIN32) ... +}; // namespace std +#endif // defined(WIN32) ... diff --git a/src/g3log/time.hpp b/src/g3log/time.hpp index 6598e00..fd675d4 100644 --- a/src/g3log/time.hpp +++ b/src/g3log/time.hpp @@ -13,9 +13,9 @@ * PUBLIC DOMAIN and Not under copywrite protection. First published for g3log at KjellKod.cc * ********************************************* */ +#include #include #include -#include // FYI: // namespace g3::internal ONLY in g3time.cpp @@ -28,7 +28,10 @@ namespace g3 { typedef std::chrono::microseconds microseconds; namespace internal { - enum class Fractional {Millisecond, Microsecond, Nanosecond, NanosecondDefault}; + enum class Fractional { Millisecond, + Microsecond, + Nanosecond, + NanosecondDefault }; Fractional getFractional(const std::string& format_buffer, size_t pos); std::string to_string(const g3::system_time_point& ts, Fractional fractional); std::string localtime_formatted_fractions(const g3::system_time_point& ts, std::string format_buffer); @@ -38,8 +41,7 @@ namespace g3 { // %6: microseconds: 6 digits: 000001 --- default for the time_format // %f9, %f: nanoseconds, 9 digits: 000000001 static const std::string time_formatted = "%H:%M:%S %f6"; - } // internal - + } // namespace internal // This mimics the original "std::put_time(const std::tm* tmb, const charT* fmt)" // This is needed since latest version (at time of writing) of gcc4.7 does not implement this library function yet. @@ -55,26 +57,22 @@ namespace g3 { * WARNING: At time of writing there is only so-so compiler support for * std::put_time. A possible fix if your c++11 library is not updated is to * modify this to use std::strftime instead */ - std::string localtime_formatted(const system_time_point& ts, const std::string& time_format) ; + std::string localtime_formatted(const system_time_point& ts, const std::string& time_format); - inline system_time_point to_system_time(const high_resolution_time_point& ts) - { - // On some (windows) systems, the system_clock does not provide the highest possible time - // resolution. Thus g3log uses high_resolution_clock for message time stamps. However, - // unlike system_clock, high_resolution_clock cannot be converted to a time and date as - // it usually measures reflects the time since power-up. - // Thus, hrs_now and sys_now are recorded once when the program starts to be able to convert - // timestamps to dime and date using to_system_time(). The precision of the absolute time is - // of course that of system_clock() with some error added due to the non-simultaneous initialization - // of the two static variables but relative times within one log will be as precise as - // high_resolution_clock. - using namespace std::chrono; - static const auto hrs_now = high_resolution_clock::now(); - static const auto sys_now = system_clock::now(); + inline system_time_point to_system_time(const high_resolution_time_point& ts) { + // On some (windows) systems, the system_clock does not provide the highest possible time + // resolution. Thus g3log uses high_resolution_clock for message time stamps. However, + // unlike system_clock, high_resolution_clock cannot be converted to a time and date as + // it usually measures reflects the time since power-up. + // Thus, hrs_now and sys_now are recorded once when the program starts to be able to convert + // timestamps to dime and date using to_system_time(). The precision of the absolute time is + // of course that of system_clock() with some error added due to the non-simultaneous initialization + // of the two static variables but relative times within one log will be as precise as + // high_resolution_clock. + using namespace std::chrono; + static const auto hrs_now = high_resolution_clock::now(); + static const auto sys_now = system_clock::now(); - return time_point_cast(sys_now + (ts - hrs_now)); + return time_point_cast(sys_now + (ts - hrs_now)); } -} - - - +} // namespace g3 diff --git a/src/logcapture.cpp b/src/logcapture.cpp index 2e2604c..ad448c9 100644 --- a/src/logcapture.cpp +++ b/src/logcapture.cpp @@ -7,8 +7,8 @@ * ============================================================================*/ #include "g3log/logcapture.hpp" -#include "g3log/g3log.hpp" #include "g3log/crashhandler.hpp" +#include "g3log/g3log.hpp" #ifdef G3_DYNAMIC_MAX_MESSAGE_SIZE #include @@ -21,7 +21,9 @@ #define SIGNAL_HANDLER_VERIFY() g3::installSignalHandlerForThread() #else // Does nothing --- enforces that semicolon must be written -#define SIGNAL_HANDLER_VERIFY() do {} while(0) +#define SIGNAL_HANDLER_VERIFY() \ + do { \ + } while (0) #endif #ifdef G3_DYNAMIC_MAX_MESSAGE_SIZE @@ -30,7 +32,7 @@ static int MaxMessageSize = 2048; void g3::only_change_at_initialization::setMaxMessageSize(size_t max_size) { MaxMessageSize = max_size; - } +} #endif /* G3_DYNAMIC_MAX_MESSAGE_SIZE */ /** logCapture is a simple struct for capturing log/fatal entries. At destruction the @@ -38,15 +40,15 @@ void g3::only_change_at_initialization::setMaxMessageSize(size_t max_size) { * As a safety precaution: No memory allocated here will be moved into the background * worker in case of dynamic loaded library reasons instead the arguments are copied * inside of g3log.cpp::saveMessage*/ -LogCapture::~LogCapture() noexcept (false) { +LogCapture::~LogCapture() noexcept(false) { using namespace g3::internal; SIGNAL_HANDLER_VERIFY(); saveMessage(_stream.str().c_str(), _file, _line, _function, _level, _expression, _fatal_signal, _stack_trace.c_str()); } - /// Called from crash handler when a fatal signal has occurred (SIGSEGV etc) -LogCapture::LogCapture(const LEVELS &level, g3::SignalType fatal_signal, const char *dump) : LogCapture("", 0, "", level, "", fatal_signal, dump) { +LogCapture::LogCapture(const LEVELS& level, g3::SignalType fatal_signal, const char* dump) : + LogCapture("", 0, "", level, "", fatal_signal, dump) { } /** @@ -55,9 +57,14 @@ LogCapture::LogCapture(const LEVELS &level, g3::SignalType fatal_signal, const c * @expression for CHECK calls * @fatal_signal for failed CHECK:SIGABRT or fatal signal caught in the signal handler */ -LogCapture::LogCapture(const char *file, const int line, const char *function, const LEVELS &level, - const char *expression, g3::SignalType fatal_signal, const char *dump) - : _file(file), _line(line), _function(function), _level(level), _expression(expression), _fatal_signal(fatal_signal) { +LogCapture::LogCapture(const char* file, const int line, const char* function, const LEVELS& level, + const char* expression, g3::SignalType fatal_signal, const char* dump) : + _file(file), + _line(line), + _function(function), + _level(level), + _expression(expression), + _fatal_signal(fatal_signal) { if (g3::internal::wasFatal(level)) { _stack_trace = std::string{"\n*******\tSTACKDUMP *******\n"}; @@ -65,17 +72,15 @@ LogCapture::LogCapture(const char *file, const int line, const char *function, c } } - - /** * capturef, used for "printf" like API in CHECKF, LOGF, LOGF_IF * See also for the attribute formatting ref: http://www.codemaestro.com/reviews/18 */ -void LogCapture::capturef(const char *printf_like_message, ...) { +void LogCapture::capturef(const char* printf_like_message, ...) { static const std::string kTruncatedWarningText = "[...truncated...]"; #ifdef G3_DYNAMIC_MAX_MESSAGE_SIZE std::vector finished_message_backing(MaxMessageSize); - char *finished_message = finished_message_backing.data(); + char* finished_message = finished_message_backing.data(); auto finished_message_len = MaxMessageSize; #else static const int kMaxMessageSize = 2048; @@ -106,5 +111,3 @@ void LogCapture::capturef(const char *printf_like_message, ...) { stream() << finished_message; } } - - diff --git a/src/loglevels.cpp b/src/loglevels.cpp index 03ba36e..a148e8f 100644 --- a/src/loglevels.cpp +++ b/src/loglevels.cpp @@ -19,15 +19,14 @@ namespace g3 { #ifdef G3_DYNAMIC_LOGGING const std::map g_log_level_defaults = { - {G3LOG_DEBUG.value,{G3LOG_DEBUG}}, + {G3LOG_DEBUG.value, {G3LOG_DEBUG}}, {INFO.value, {INFO}}, {WARNING.value, {WARNING}}, - {FATAL.value, {FATAL}} - }; + {FATAL.value, {FATAL}}}; std::map g_log_levels = g_log_level_defaults; #endif - } // internal + } // namespace internal #ifdef G3_DYNAMIC_LOGGING namespace only_change_at_initialization { @@ -37,7 +36,6 @@ namespace g3 { internal::g_log_levels[value] = {lvl, enabled}; } - void addLogLevel(LEVELS level) { addLogLevel(level, true); } @@ -45,8 +43,7 @@ namespace g3 { void reset() { g3::internal::g_log_levels = g3::internal::g_log_level_defaults; } - } // only_change_at_initialization - + } // namespace only_change_at_initialization namespace log_levels { @@ -59,12 +56,10 @@ namespace g3 { } else { enable(v.second.level); } - } } } - void set(LEVELS level, bool enabled) { auto it = internal::g_log_levels.find(level.value); if (it != internal::g_log_levels.end()) { @@ -72,7 +67,6 @@ namespace g3 { } } - void disable(LEVELS level) { set(level, false); } @@ -81,7 +75,6 @@ namespace g3 { set(level, true); } - void disableAll() { for (auto& v : internal::g_log_levels) { v.second.status = false; @@ -94,7 +87,6 @@ namespace g3 { } } - std::string to_string(std::map levelsToPrint) { std::string levels; for (auto& v : levelsToPrint) { @@ -107,7 +99,6 @@ namespace g3 { return to_string(internal::g_log_levels); } - std::map getAll() { return internal::g_log_levels; } @@ -120,13 +111,11 @@ namespace g3 { } return (it->second.status.get().load() ? status::Enabled : status::Disabled); - } - } // log_levels + } // namespace log_levels #endif - bool logLevel(const LEVELS& log_level) { #ifdef G3_DYNAMIC_LOGGING int level = log_level.value; @@ -136,4 +125,4 @@ namespace g3 { return true; #endif } -} // g3 +} // namespace g3 diff --git a/src/logmessage.cpp b/src/logmessage.cpp index d69302a..5e6faa9 100644 --- a/src/logmessage.cpp +++ b/src/logmessage.cpp @@ -7,12 +7,9 @@ * ============================================================================*/ #include "g3log/logmessage.hpp" +#include #include "g3log/crashhandler.hpp" #include "g3log/time.hpp" -#include - - - namespace g3 { @@ -22,27 +19,20 @@ namespace g3 { return str.substr(found + 1); } - // helper for fatal signal - std::string LogMessage::fatalSignalToString(const LogMessage& msg) { - std::string out; // clear any previous text and formatting - out.append(msg.timestamp() - + "\n\n***** FATAL SIGNAL RECEIVED ******* \n" - + msg.message() + '\n'); + std::string LogMessage::fatalSignalToString(const LogMessage& msg) { + std::string out; // clear any previous text and formatting + out.append(msg.timestamp() + "\n\n***** FATAL SIGNAL RECEIVED ******* \n" + msg.message() + '\n'); return out; } - // helper for fatal exception (windows only) - std::string LogMessage::fatalExceptionToString(const LogMessage& msg) { - std::string out; // clear any previous text and formatting - out.append(msg.timestamp() - + "\n\n***** FATAL EXCEPTION RECEIVED ******* \n" - + msg.message() + '\n'); + std::string LogMessage::fatalExceptionToString(const LogMessage& msg) { + std::string out; // clear any previous text and formatting + out.append(msg.timestamp() + "\n\n***** FATAL EXCEPTION RECEIVED ******* \n" + msg.message() + '\n'); return out; } - // helper for fatal LOG std::string LogMessage::fatalLogToString(const LogMessage& msg) { auto out = msg._logDetailsToStringFunc(msg); @@ -55,39 +45,23 @@ namespace g3 { std::string LogMessage::fatalCheckToString(const LogMessage& msg) { auto out = msg._logDetailsToStringFunc(msg); static const std::string contractExitReason = {"EXIT trigger caused by broken Contract:"}; - out.append("\n\t*******\t " + contractExitReason + " CHECK(" + msg.expression() + ")\n\t" - + '"' + msg. message() + '"'); + out.append("\n\t*******\t " + contractExitReason + " CHECK(" + msg.expression() + ")\n\t" + '"' + msg.message() + '"'); return out; } // helper for setting the normal log details in an entry std::string LogMessage::DefaultLogDetailsToString(const LogMessage& msg) { std::string out; - out.append(msg.timestamp() + "\t" - + msg.level() - + " [" - + msg.file() - + "->" - + msg.function() - + ":" + msg.line() + "]\t"); + out.append(msg.timestamp() + "\t" + msg.level() + " [" + msg.file() + "->" + msg.function() + ":" + msg.line() + "]\t"); return out; } - std::string LogMessage::FullLogDetailsToString(const LogMessage& msg) { std::string out; - out.append(msg.timestamp() + "\t" - + msg.level() - + " [" - + msg.threadID() - + " " - + msg.file() - + "->"+ msg.function() - + ":" + msg.line() + "]\t"); + out.append(msg.timestamp() + "\t" + msg.level() + " [" + msg.threadID() + " " + msg.file() + "->" + msg.function() + ":" + msg.line() + "]\t"); return out; } - // helper for normal std::string LogMessage::normalToString(const LogMessage& msg) { auto out = msg._logDetailsToStringFunc(msg); @@ -95,16 +69,12 @@ namespace g3 { return out; } + // end static functions section - - // end static functions section - - void LogMessage::overrideLogDetailsFunc(LogDetailsFunc func) const{ + void LogMessage::overrideLogDetailsFunc(LogDetailsFunc func) const { _logDetailsToStringFunc = func; } - - // Format the log message according to it's type std::string LogMessage::toString(LogDetailsFunc formattingFunc) const { overrideLogDetailsFunc(formattingFunc); @@ -137,89 +107,82 @@ namespace g3 { return out; } - - std::string LogMessage::timestamp(const std::string& time_look) const { return g3::localtime_formatted(to_system_time(_timestamp), time_look); } - -// By copy, not by reference. See this explanation for details: -// http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom + // By copy, not by reference. See this explanation for details: + // http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom LogMessage& LogMessage::operator=(LogMessage other) { swap(*this, other); return *this; } - LogMessage::LogMessage(std::string file, const int line, - std::string function, const LEVELS level) - : _logDetailsToStringFunc(LogMessage::DefaultLogDetailsToString) - , _timestamp(std::chrono::high_resolution_clock::now()) - , _call_thread_id(std::this_thread::get_id()) + std::string function, const LEVELS level) : + _logDetailsToStringFunc(LogMessage::DefaultLogDetailsToString), + _timestamp(std::chrono::high_resolution_clock::now()), + _call_thread_id(std::this_thread::get_id()) #if defined(G3_LOG_FULL_FILENAME) - , _file(file) + , + _file(file) #else - , _file(LogMessage::splitFileName(file)) + , + _file(LogMessage::splitFileName(file)) #endif - , _file_path(file) - , _line(line) - , _function(std::move(function)) - , _level(level) { + , + _file_path(file), + _line(line), + _function(std::move(function)), + _level(level) { } - - LogMessage::LogMessage(const std::string& fatalOsSignalCrashMessage) - : LogMessage( {""}, 0, {""}, internal::FATAL_SIGNAL) { + LogMessage::LogMessage(const std::string& fatalOsSignalCrashMessage) : + LogMessage({""}, 0, {""}, internal::FATAL_SIGNAL) { _message.append(fatalOsSignalCrashMessage); } - LogMessage::LogMessage(const LogMessage& other) - : _logDetailsToStringFunc(other._logDetailsToStringFunc) - , _timestamp(other._timestamp) - , _call_thread_id(other._call_thread_id) - , _file(other._file) - , _file_path(other._file_path) - , _line(other._line) - , _function(other._function) - , _level(other._level) - , _expression(other._expression) - , _message(other._message) { + LogMessage::LogMessage(const LogMessage& other) : + _logDetailsToStringFunc(other._logDetailsToStringFunc), + _timestamp(other._timestamp), + _call_thread_id(other._call_thread_id), + _file(other._file), + _file_path(other._file_path), + _line(other._line), + _function(other._function), + _level(other._level), + _expression(other._expression), + _message(other._message) { } - LogMessage::LogMessage(LogMessage&& other) - : _logDetailsToStringFunc(other._logDetailsToStringFunc) - , _timestamp(other._timestamp) - , _call_thread_id(other._call_thread_id) - , _file(std::move(other._file)) - , _file_path(std::move(other._file_path)) - , _line(other._line) - , _function(std::move(other._function)) - , _level(other._level) - , _expression(std::move(other._expression)) - , _message(std::move(other._message)) { + LogMessage::LogMessage(LogMessage&& other) : + _logDetailsToStringFunc(other._logDetailsToStringFunc), + _timestamp(other._timestamp), + _call_thread_id(other._call_thread_id), + _file(std::move(other._file)), + _file_path(std::move(other._file_path)), + _line(other._line), + _function(std::move(other._function)), + _level(other._level), + _expression(std::move(other._expression)), + _message(std::move(other._message)) { } - - std::string LogMessage::threadID() const { std::ostringstream oss; oss << _call_thread_id; return oss.str(); } + FatalMessage::FatalMessage(const LogMessage& details, g3::SignalType signal_id) : + LogMessage(details), + _signal_id(signal_id) {} + FatalMessage::FatalMessage(const FatalMessage& other) : + LogMessage(other), + _signal_id(other._signal_id) {} - FatalMessage::FatalMessage(const LogMessage& details, g3::SignalType signal_id) - : LogMessage(details), _signal_id(signal_id) { } - - - - FatalMessage::FatalMessage(const FatalMessage& other) - : LogMessage(other), _signal_id(other._signal_id) {} - - - LogMessage FatalMessage::copyToLogMessage() const { + LogMessage FatalMessage::copyToLogMessage() const { return LogMessage(*this); } @@ -227,5 +190,4 @@ namespace g3 { return internal::exitReasonName(_level, _signal_id); } - -} // g3 +} // namespace g3 diff --git a/src/logworker.cpp b/src/logworker.cpp index 7a0e384..4bda245 100644 --- a/src/logworker.cpp +++ b/src/logworker.cpp @@ -7,17 +7,18 @@ * ============================================================================*/ #include "g3log/logworker.hpp" -#include "g3log/logmessage.hpp" #include "g3log/active.hpp" -#include "g3log/g3log.hpp" -#include "g3log/future.hpp" #include "g3log/crashhandler.hpp" +#include "g3log/future.hpp" +#include "g3log/g3log.hpp" +#include "g3log/logmessage.hpp" #include namespace g3 { - LogWorkerImpl::LogWorkerImpl() : _bg(kjellkod::Active::createActive()) { } + LogWorkerImpl::LogWorkerImpl() : + _bg(kjellkod::Active::createActive()) {} void LogWorkerImpl::bgSave(g3::LogMessagePtr msgPtr) { std::unique_ptr uniqueMsg(std::move(msgPtr.get())); @@ -28,7 +29,7 @@ namespace g3 { } if (_sinks.empty()) { - std::string err_msg {"g3logworker has no sinks. Message: ["}; + std::string err_msg{"g3logworker has no sinks. Message: ["}; err_msg.append(uniqueMsg.get()->toString()).append("]\n"); std::cerr << err_msg; } @@ -43,16 +44,13 @@ namespace g3 { const auto level = msgPtr.get()->_level; const auto fatal_id = msgPtr.get()->_signal_id; - std::unique_ptr uniqueMsg(std::move(msgPtr.get())); uniqueMsg->write().append("\nExiting after fatal event (").append(uniqueMsg->level()); - // Change output in case of a fatal signal (or windows exception) std::string exiting = {"Fatal type: "}; - uniqueMsg->write().append("). ").append(exiting).append(" ").append(reason) - .append("\nLog content flushed successfully to sink\n\n"); + uniqueMsg->write().append("). ").append(exiting).append(" ").append(reason).append("\nLog content flushed successfully to sink\n\n"); std::cerr << uniqueMsg->toString() << std::flush; for (auto& sink : _sinks) { @@ -60,10 +58,9 @@ namespace g3 { sink->send(LogMessageMover(std::move(msg))); } - // This clear is absolutely necessary // All sinks are forced to receive the fatal message above before we continue - _sinks.clear(); // flush all queues + _sinks.clear(); // flush all queues internal::exitWithDefaultSignalHandler(level, fatal_id); // should never reach this point @@ -102,15 +99,17 @@ namespace g3 { } void LogWorker::save(LogMessagePtr msg) { - _impl._bg->send([this, msg] {_impl.bgSave(msg); }); + _impl._bg->send([this, msg] { _impl.bgSave(msg); }); } void LogWorker::fatal(FatalMessagePtr fatal_message) { - _impl._bg->send([this, fatal_message] {_impl.bgFatal(fatal_message); }); + _impl._bg->send([this, fatal_message] { _impl.bgFatal(fatal_message); }); } void LogWorker::addWrappedSink(std::shared_ptr sink) { - auto bg_addsink_call = [this, sink] {_impl._sinks.push_back(sink);}; + auto bg_addsink_call = [this, sink] { + _impl._sinks.push_back(sink); + }; auto token_done = g3::spawn_task(bg_addsink_call, _impl._bg.get()); token_done.wait(); } @@ -119,8 +118,8 @@ namespace g3 { return std::unique_ptr(new LogWorker); } - std::unique_ptrLogWorker::addDefaultLogger(const std::string& log_prefix, const std::string& log_directory, const std::string& default_id) { + std::unique_ptr LogWorker::addDefaultLogger(const std::string& log_prefix, const std::string& log_directory, const std::string& default_id) { return addSink(std::make_unique(log_prefix, log_directory, default_id), &FileSink::fileWrite); } -} // g3 +} // namespace g3 diff --git a/src/stacktrace_windows.cpp b/src/stacktrace_windows.cpp index 427e4aa..f9b483e 100644 --- a/src/stacktrace_windows.cpp +++ b/src/stacktrace_windows.cpp @@ -14,60 +14,37 @@ #include "g3log/stacktrace_windows.hpp" -#include #include +#include +#include +#include #include #include -#include -#include #include -#include +#include #pragma comment(lib, "dbghelp.lib") - #if !(defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) #error "stacktrace_win.cpp used but not on a windows system" #endif - - -#define g3_MAP_PAIR_STRINGIFY(x) {x, #x} +#define g3_MAP_PAIR_STRINGIFY(x) \ + { x, #x } namespace { thread_local size_t g_thread_local_recursive_crash_check = 0; const std::map kExceptionsAsText = { - g3_MAP_PAIR_STRINGIFY(EXCEPTION_ACCESS_VIOLATION) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_ARRAY_BOUNDS_EXCEEDED) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_DATATYPE_MISALIGNMENT) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_DENORMAL_OPERAND) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_DIVIDE_BY_ZERO) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_INEXACT_RESULT) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_INEXACT_RESULT) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_INVALID_OPERATION) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_OVERFLOW) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_STACK_CHECK) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_UNDERFLOW) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_ILLEGAL_INSTRUCTION) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_IN_PAGE_ERROR) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_INT_DIVIDE_BY_ZERO) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_INT_OVERFLOW) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_INVALID_DISPOSITION) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_NONCONTINUABLE_EXCEPTION) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_PRIV_INSTRUCTION) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_STACK_OVERFLOW) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_BREAKPOINT) - , g3_MAP_PAIR_STRINGIFY(EXCEPTION_SINGLE_STEP) + g3_MAP_PAIR_STRINGIFY(EXCEPTION_ACCESS_VIOLATION), g3_MAP_PAIR_STRINGIFY(EXCEPTION_ARRAY_BOUNDS_EXCEEDED), g3_MAP_PAIR_STRINGIFY(EXCEPTION_DATATYPE_MISALIGNMENT), g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_DENORMAL_OPERAND), g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_DIVIDE_BY_ZERO), g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_INEXACT_RESULT), g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_INEXACT_RESULT), g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_INVALID_OPERATION), g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_OVERFLOW), g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_STACK_CHECK), g3_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_UNDERFLOW), g3_MAP_PAIR_STRINGIFY(EXCEPTION_ILLEGAL_INSTRUCTION), g3_MAP_PAIR_STRINGIFY(EXCEPTION_IN_PAGE_ERROR), g3_MAP_PAIR_STRINGIFY(EXCEPTION_INT_DIVIDE_BY_ZERO), g3_MAP_PAIR_STRINGIFY(EXCEPTION_INT_OVERFLOW), g3_MAP_PAIR_STRINGIFY(EXCEPTION_INVALID_DISPOSITION), g3_MAP_PAIR_STRINGIFY(EXCEPTION_NONCONTINUABLE_EXCEPTION), g3_MAP_PAIR_STRINGIFY(EXCEPTION_PRIV_INSTRUCTION), g3_MAP_PAIR_STRINGIFY(EXCEPTION_STACK_OVERFLOW), g3_MAP_PAIR_STRINGIFY(EXCEPTION_BREAKPOINT), g3_MAP_PAIR_STRINGIFY(EXCEPTION_SINGLE_STEP) }; - // Using the given context, fill in all the stack frames. // Which then later can be interpreted to human readable text - void captureStackTrace(CONTEXT *context, std::vector &frame_pointers) { + void captureStackTrace(CONTEXT* context, std::vector& frame_pointers) { DWORD machine_type = 0; - STACKFRAME64 frame = {}; // force zeroing + STACKFRAME64 frame = {}; // force zeroing frame.AddrPC.Mode = AddrModeFlat; frame.AddrFrame.Mode = AddrModeFlat; frame.AddrStack.Mode = AddrModeFlat; @@ -92,8 +69,7 @@ namespace { frame.AddrPC.Offset = context->Esp; machine_type = IMAGE_FILE_MACHINE_I386; #endif - for (size_t index = 0; index < frame_pointers.size(); ++index) - { + for (size_t index = 0; index < frame_pointers.size(); ++index) { if (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(), @@ -110,18 +86,16 @@ namespace { } } - - // extract readable text from a given stack frame. All thanks to // using SymFromAddr and SymGetLineFromAddr64 with the stack pointer - std::string getSymbolInformation(const size_t index, const std::vector &frame_pointers) { + std::string getSymbolInformation(const size_t index, const std::vector& frame_pointers) { auto addr = frame_pointers[index]; std::string frame_dump = "stack dump [" + std::to_string(index) + "]\t"; DWORD64 displacement64; DWORD displacement; alignas(SYMBOL_INFO) char symbol_buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; - SYMBOL_INFO *symbol = reinterpret_cast(symbol_buffer); + SYMBOL_INFO* symbol = reinterpret_cast(symbol_buffer); symbol->SizeOfStruct = sizeof(SYMBOL_INFO); symbol->MaxNameLen = MAX_SYM_NAME; @@ -140,10 +114,9 @@ namespace { return frame_dump; } - // Retrieves all the symbols for the stack frames, fills them within a text representation and returns it - std::string convertFramesToText(std::vector &frame_pointers) { - std::string dump; // slightly more efficient than ostringstream + std::string convertFramesToText(std::vector& frame_pointers) { + std::string dump; // slightly more efficient than ostringstream const size_t kSize = frame_pointers.size(); for (size_t index = 0; index < kSize && frame_pointers[index]; ++index) { dump += getSymbolInformation(index, frame_pointers); @@ -151,10 +124,7 @@ namespace { } return dump; } -} // anonymous - - - +} // namespace namespace stacktrace { const std::string kUnknown = {"UNKNOWN EXCEPTION"}; @@ -162,7 +132,7 @@ namespace stacktrace { /// From MSDN GetExceptionCode http://msdn.microsoft.com/en-us/library/windows/desktop/ms679356(v=vs.85).aspx std::string exceptionIdToText(g3::SignalType id) { const auto iter = kExceptionsAsText.find(id); - if ( iter == kExceptionsAsText.end()) { + if (iter == kExceptionsAsText.end()) { std::string unknown = {kUnknown + ":" + std::to_string(id)}; return unknown; } @@ -185,17 +155,15 @@ namespace stacktrace { } /// helper function: retrieve stackdump, starting from an exception pointer - std::string stackdump(EXCEPTION_POINTERS *info) { + std::string stackdump(EXCEPTION_POINTERS* info) { auto context = info->ContextRecord; return stackdump(context); - } - /// main stackdump function. retrieve stackdump, from the given context - std::string stackdump(CONTEXT *context) { + std::string stackdump(CONTEXT* context) { - if (g_thread_local_recursive_crash_check >= 2) { // In Debug scenarios we allow one extra pass + if (g_thread_local_recursive_crash_check >= 2) { // In Debug scenarios we allow one extra pass std::string recursive_crash = {"\n\n\n***** Recursive crash detected"}; recursive_crash.append(", cannot continue stackdump traversal. *****\n\n\n"); return recursive_crash; @@ -208,16 +176,15 @@ namespace stacktrace { const BOOL kLoadSymModules = TRUE; const auto initialized = SymInitialize(GetCurrentProcess(), nullptr, kLoadSymModules); if (TRUE != initialized) { - return { "Error: Cannot call SymInitialize(...) for retrieving symbols in stack" }; + return {"Error: Cannot call SymInitialize(...) for retrieving symbols in stack"}; } - std::shared_ptr RaiiSymCleaner(nullptr, [&](void *) { + std::shared_ptr RaiiSymCleaner(nullptr, [&](void*) { SymCleanup(GetCurrentProcess()); - }); // Raii sym cleanup - + }); // Raii sym cleanup constexpr size_t kmax_frame_dump_size = 64; - std::vector frame_pointers(kmax_frame_dump_size); + std::vector frame_pointers(kmax_frame_dump_size); // C++11: size set and values are zeroed assert(frame_pointers.size() == kmax_frame_dump_size); @@ -226,4 +193,4 @@ namespace stacktrace { } } -} // stacktrace +} // namespace stacktrace diff --git a/src/time.cpp b/src/time.cpp index bdf91f0..a94d394 100644 --- a/src/time.cpp +++ b/src/time.cpp @@ -8,30 +8,38 @@ #include "g3log/time.hpp" +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include #ifdef __MACH__ #include #endif namespace g3 { namespace internal { - const std::string kFractionalIdentier = "%f"; + const std::string kFractionalIdentier = "%f"; const size_t kFractionalIdentierSize = 2; Fractional getFractional(const std::string& format_buffer, size_t pos) { - char ch = (format_buffer.size() > pos + kFractionalIdentierSize ? format_buffer.at(pos + kFractionalIdentierSize) : '\0'); + char ch = (format_buffer.size() > pos + kFractionalIdentierSize ? format_buffer.at(pos + kFractionalIdentierSize) : '\0'); Fractional type = Fractional::NanosecondDefault; switch (ch) { - case '3': type = Fractional::Millisecond; break; - case '6': type = Fractional::Microsecond; break; - case '9': type = Fractional::Nanosecond; break; - default: type = Fractional::NanosecondDefault; break; + case '3': + type = Fractional::Millisecond; + break; + case '6': + type = Fractional::Microsecond; + break; + case '9': + type = Fractional::Nanosecond; + break; + default: + type = Fractional::NanosecondDefault; + break; } return type; } @@ -46,25 +54,24 @@ namespace g3 { duration -= sec_duration; auto ns = std::chrono::duration_cast(duration).count(); - auto zeroes = 9; // default ns - auto digitsToCut = 1; // default ns, divide by 1 makes no change + auto zeroes = 9; // default ns + auto digitsToCut = 1; // default ns, divide by 1 makes no change switch (fractional) { - case Fractional::Millisecond : { - zeroes = 3; - digitsToCut = 1000000; - break; - } - case Fractional::Microsecond : { - zeroes = 6; - digitsToCut = 1000; - break; - } - case Fractional::Nanosecond : - case Fractional::NanosecondDefault: - default: - zeroes = 9; - digitsToCut = 1; - + case Fractional::Millisecond: { + zeroes = 3; + digitsToCut = 1000000; + break; + } + case Fractional::Microsecond: { + zeroes = 6; + digitsToCut = 1000; + break; + } + case Fractional::Nanosecond: + case Fractional::NanosecondDefault: + default: + zeroes = 9; + digitsToCut = 1; } ns /= digitsToCut; @@ -76,8 +83,8 @@ namespace g3 { // iterating through every "%f" instance in the format string auto identifierExtraSize = 0; for (size_t pos = 0; - (pos = format_buffer.find(g3::internal::kFractionalIdentier, pos)) != std::string::npos; - pos += g3::internal::kFractionalIdentierSize + identifierExtraSize) { + (pos = format_buffer.find(g3::internal::kFractionalIdentier, pos)) != std::string::npos; + pos += g3::internal::kFractionalIdentierSize + identifierExtraSize) { // figuring out whether this is nano, micro or milli identifier auto type = g3::internal::getFractional(format_buffer, pos); auto value = g3::internal::to_string(ts, type); @@ -92,10 +99,8 @@ namespace g3 { return format_buffer; } - } // internal -} // g3 - - + } // namespace internal +} // namespace g3 namespace g3 { // This mimics the original "std::put_time(const std::tm* tmb, const charT* fmt)" @@ -106,11 +111,11 @@ namespace g3 { std::ostringstream oss; oss.fill('0'); // BOGUS hack done for VS2012: C++11 non-conformant since it SHOULD take a "const struct tm* " - oss << std::put_time(const_cast (tmb), c_time_format); + oss << std::put_time(const_cast(tmb), c_time_format); return oss.str(); -#else // LINUX +#else // LINUX const size_t size = 1024; - char buffer[size]; // IMPORTANT: check now and then for when gcc will implement std::put_time. + char buffer[size]; // IMPORTANT: check now and then for when gcc will implement std::put_time. // ... also ... This is way more buffer space then we need auto success = std::strftime(buffer, size, c_time_format, tmb); @@ -127,23 +132,20 @@ namespace g3 { #endif } - - tm localtime(std::time_t ts) { struct tm tm_snapshot; #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) - localtime_s(&tm_snapshot, &ts); // windsows + localtime_s(&tm_snapshot, &ts); // windsows #else - localtime_r(&ts, &tm_snapshot); // POSIX + localtime_r(&ts, &tm_snapshot); // POSIX #endif return tm_snapshot; } - std::string localtime_formatted(const g3::system_time_point& ts, const std::string& time_format) { auto format_buffer = internal::localtime_formatted_fractions(ts, time_format); auto time_point = std::chrono::system_clock::to_time_t(ts); std::tm t = localtime(time_point); - return g3::put_time(&t, format_buffer.c_str()); // format example: //"%Y/%m/%d %H:%M:%S"); + return g3::put_time(&t, format_buffer.c_str()); // format example: //"%Y/%m/%d %H:%M:%S"); } -} // g3 +} // namespace g3 diff --git a/sublime.formatting b/sublime.formatting deleted file mode 100644 index 2a157ae..0000000 --- a/sublime.formatting +++ /dev/null @@ -1,24 +0,0 @@ -{ - "AStyleFormatter": - { - "options_default": - { - "indent": "spaces", - "indent-modifiers": false, - "indent-namespaces": true, - "indent-preproc-block": true, - "indent-spaces": 3, - "style": "googles" - } - }, - "color_scheme": "Packages/Color Scheme - Default/Twilight.tmTheme", - "font_size": 11, - "highlight_modified_tabs": true, - "ignored_packages": - [ - "Vintage" - ], - "tab_size": 3, - "translate_tabs_to_spaces": true, - "word_wrap": true -} diff --git a/test_main/test_main.cpp b/test_main/test_main.cpp index cc58ac8..3311961 100644 --- a/test_main/test_main.cpp +++ b/test_main/test_main.cpp @@ -7,11 +7,9 @@ #include #include -int main(int argc, char *argv[]) -{ +int main(int argc, char* argv[]) { testing::InitGoogleTest(&argc, argv); int return_value = RUN_ALL_TESTS(); std::cout << "FINISHED WITH THE TESTING" << std::endl; return return_value; } - diff --git a/test_performance/main_threaded_mean.cpp b/test_performance/main_threaded_mean.cpp index 27e7a64..c710091 100644 --- a/test_performance/main_threaded_mean.cpp +++ b/test_performance/main_threaded_mean.cpp @@ -7,10 +7,10 @@ * ============================================================================*/ // through CMakeLists.txt #define of GOOGLE_GLOG_PERFORMANCE and G3LOG_PERFORMANCE -#include "performance.h" -#include -#include #include +#include +#include +#include "performance.h" #if defined(G3LOG_PERFORMANCE) const std::string title = "G3LOG"; @@ -27,8 +27,7 @@ const std::string g_path = "/tmp/"; #endif using namespace g3_test; -int main(int argc, char **argv) -{ +int main(int argc, char** argv) { #ifdef G3_DYNAMIC_LOGGING std::cerr << "G3_DYNAMIC_LOGGING is enabled" << std::endl; #else @@ -36,61 +35,57 @@ int main(int argc, char **argv) #endif size_t number_of_threads = 0; - if (argc == 2) - { + if (argc == 2) { number_of_threads = atoi(argv[1]); } - if (argc != 2 || number_of_threads == 0) - { + if (argc != 2 || number_of_threads == 0) { std::cerr << "USAGE is: " << argv[0] << " number_threads" << std::endl; return 1; } std::ostringstream thread_count_oss; thread_count_oss << number_of_threads; - const std::string g_prefix_log_name = title + "-performance-" + thread_count_oss.str() + "threads-MEAN_LOG"; - const std::string g_measurement_dump = g_path + g_prefix_log_name + "_RESULT.txt"; + const std::string g_prefix_log_name = title + "-performance-" + thread_count_oss.str() + "threads-MEAN_LOG"; + const std::string g_measurement_dump = g_path + g_prefix_log_name + "_RESULT.txt"; std::ostringstream oss; const uint64_t us_to_s = 1000000; - oss << "\n\n" << title << " performance " << number_of_threads << " threads MEAN times\n"; + oss << "\n\n" + << title << " performance " << number_of_threads << " threads MEAN times\n"; oss << "Each thread running #: " << g_loop << " * " << g_iterations << " iterations of log entries" << std::endl; // worst mean case is about 10us per log entry const uint64_t xtra_margin = 2; - oss << "*** It can take som time. Please wait: Approximate wait time on MY PC was: " << number_of_threads* (uint64_t) (g_iterations * 10 * xtra_margin / us_to_s ) << " seconds" << std::endl; + oss << "*** It can take som time. Please wait: Approximate wait time on MY PC was: " << number_of_threads * (uint64_t)(g_iterations * 10 * xtra_margin / us_to_s) << " seconds" << std::endl; writeTextToFile(g_measurement_dump, oss.str(), kAppend); - oss.str(""); // clear the stream + oss.str(""); // clear the stream #if defined(G3LOG_PERFORMANCE) auto worker = g3::LogWorker::createLogWorker(); - auto handle= worker->addDefaultLogger(g_prefix_log_name, g_path); + auto handle = worker->addDefaultLogger(g_prefix_log_name, g_path); g3::initializeLogging(worker.get()); - #elif defined(GOOGLE_GLOG_PERFORMANCE) google::InitGoogleLogging(argv[0]); #endif auto start_time = std::chrono::high_resolution_clock::now(); - std::thread *threads = new std::thread[number_of_threads]; + std::thread* threads = new std::thread[number_of_threads]; // kiss: just loop, create threads, store them then join // could probably do this more elegant with lambdas - for (size_t idx = 0; idx < number_of_threads; ++idx) - { + for (size_t idx = 0; idx < number_of_threads; ++idx) { std::ostringstream count; count << idx + 1; - std::string thread_name = title + "_T" + count.str(); + std::string thread_name = title + "_T" + count.str(); std::cout << "Creating thread: " << thread_name << std::endl; threads[idx] = std::thread(doLogWrites, thread_name); } - for (size_t idx = 0; idx < number_of_threads; ++idx) - { + for (size_t idx = 0; idx < number_of_threads; ++idx) { threads[idx].join(); } auto application_end_time = std::chrono::high_resolution_clock::now(); - delete [] threads; + delete[] threads; #if defined(G3LOG_PERFORMANCE) - worker.reset(); // will flush anything in the queue to file + worker.reset(); // will flush anything in the queue to file #elif defined(GOOGLE_GLOG_PERFORMANCE) google::ShutdownGoogleLogging(); #endif @@ -99,9 +94,10 @@ int main(int argc, char **argv) uint64_t application_time_us = std::chrono::duration_cast(application_end_time - start_time).count(); uint64_t total_time_us = std::chrono::duration_cast(worker_end_time - start_time).count(); - oss << "\n" << number_of_threads << "*" << g_iterations << " log entries took: [" << total_time_us / 1000000 << " s] to write to disk" << std::endl; + oss << "\n" + << number_of_threads << "*" << g_iterations << " log entries took: [" << total_time_us / 1000000 << " s] to write to disk" << std::endl; oss << "[Application(" << number_of_threads << "):\t\t:" << application_time_us / 1000 << " ms]" << std::endl; - oss << "[Background thread to finish\t:" << total_time_us / uint64_t(1000 ) << " ms]" << std::endl; + oss << "[Background thread to finish\t:" << total_time_us / uint64_t(1000) << " ms]" << std::endl; oss << "\nAverage time per log entry:" << std::endl; oss << "[Application: " << application_time_us / (number_of_threads * g_iterations) << " us]" << std::endl; oss << "[Background+Application: " << total_time_us / (number_of_threads * g_iterations) << " us]" << std::endl; diff --git a/test_performance/main_threaded_worst.cpp b/test_performance/main_threaded_worst.cpp index 82ac4f1..1f7a828 100644 --- a/test_performance/main_threaded_worst.cpp +++ b/test_performance/main_threaded_worst.cpp @@ -9,83 +9,69 @@ // through CMakeLists.txt #define of GOOGLE_GLOG_PERFORMANCE and G3LOG_PERFORMANCE #include "performance.h" -#include -#include -#include #include #include +#include +#include +#include #if defined(G3LOG_PERFORMANCE) -const std::string title { - "G3LOG" -}; +const std::string title{ + "G3LOG"}; #elif defined(GOOGLE_GLOG_PERFORMANCE) -const std::string title { - "GOOGLE__GLOG" -}; +const std::string title{ + "GOOGLE__GLOG"}; #else #error G3LOG_PERFORMANCE or GOOGLE_GLOG_PERFORMANCE was not defined #endif - #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) -const std::string g_path { - "./" -}; +const std::string g_path{ + "./"}; #else -const std::string g_path { - "/tmp/" -}; +const std::string g_path{ + "/tmp/"}; #endif - - using namespace g3_test; - // // OK: The code below isn't pretty but it works. Lots and lots of log entries // to keep track of! // -int main(int argc, char** argv) -{ - size_t number_of_threads {0}; - if (argc == 2) - { +int main(int argc, char** argv) { + size_t number_of_threads{0}; + if (argc == 2) { number_of_threads = atoi(argv[1]); } - if (argc != 2 || number_of_threads == 0) - { + if (argc != 2 || number_of_threads == 0) { std::cerr << "USAGE is: " << argv[0] << " number_threads" << std::endl; return 1; } std::ostringstream thread_count_oss; thread_count_oss << number_of_threads; - const std::string g_prefix_log_name = title + "-performance-" + thread_count_oss.str() + "threads-WORST_LOG"; - const std::string g_measurement_dump = g_path + g_prefix_log_name + "_RESULT.txt"; - const std::string g_measurement_bucket_dump = g_path + g_prefix_log_name + "_RESULT_buckets.txt"; - const uint64_t us_to_ms { - 1000 - }; - const uint64_t us_to_s { - 1000000 - }; - + const std::string g_prefix_log_name = title + "-performance-" + thread_count_oss.str() + "threads-WORST_LOG"; + const std::string g_measurement_dump = g_path + g_prefix_log_name + "_RESULT.txt"; + const std::string g_measurement_bucket_dump = g_path + g_prefix_log_name + "_RESULT_buckets.txt"; + const uint64_t us_to_ms{ + 1000}; + const uint64_t us_to_s{ + 1000000}; std::ostringstream oss; - oss << "\n\n" << title << " performance " << number_of_threads << " threads WORST (PEAK) times\n"; + oss << "\n\n" + << title << " performance " << number_of_threads << " threads WORST (PEAK) times\n"; oss << "Each thread running #: " << g_loop << " * " << g_iterations << " iterations of log entries" << std::endl; // worst mean case is about 10us per log entry - const uint64_t xtra_margin { - 2 - }; + const uint64_t xtra_margin{ + 2}; oss << "*** It can take som time. Please wait: Approximate wait time on MY PC was: " << number_of_threads * (uint64_t)(g_iterations * 10 * xtra_margin / us_to_s) << " seconds" << std::endl; writeTextToFile(g_measurement_dump, oss.str(), kAppend); - oss.str(""); // clear the stream + oss.str(""); // clear the stream #if defined(G3LOG_PERFORMANCE) auto worker = g3::LogWorker::createLogWorker(); - auto handle= worker->addDefaultLogger(g_prefix_log_name, g_path); + auto handle = worker->addDefaultLogger(g_prefix_log_name, g_path); g3::initializeLogging(worker.get()); #elif defined(GOOGLE_GLOG_PERFORMANCE) @@ -97,31 +83,27 @@ int main(int argc, char** argv) // kiss: just loop, create threads, store them then join // could probably do this more elegant with lambdas - for (uint64_t idx = 0; idx < number_of_threads; ++idx) - { + for (uint64_t idx = 0; idx < number_of_threads; ++idx) { threads_result[idx].reserve(g_iterations); } auto start_time = std::chrono::high_resolution_clock::now(); - for (uint64_t idx = 0; idx < number_of_threads; ++idx) - { + for (uint64_t idx = 0; idx < number_of_threads; ++idx) { std::ostringstream count; count << idx + 1; - std::string thread_name = title + "_T" + count.str(); + std::string thread_name = title + "_T" + count.str(); std::cout << "Creating thread: " << thread_name << std::endl; threads[idx] = std::thread(measurePeakDuringLogWrites, thread_name, std::ref(threads_result[idx])); } // wait for thread finishing - for (uint64_t idx = 0; idx < number_of_threads; ++idx) - { + for (uint64_t idx = 0; idx < number_of_threads; ++idx) { threads[idx].join(); } auto application_end_time = std::chrono::high_resolution_clock::now(); - delete [] threads; - + delete[] threads; #if defined(G3LOG_PERFORMANCE) - worker.reset(); // will flush anything in the queue to file + worker.reset(); // will flush anything in the queue to file #elif defined(GOOGLE_GLOG_PERFORMANCE) google::ShutdownGoogleLogging(); #endif @@ -130,17 +112,17 @@ int main(int argc, char** argv) uint64_t application_time_us = std::chrono::duration_cast(application_end_time - start_time).count(); uint64_t total_time_us = std::chrono::duration_cast(worker_end_time - start_time).count(); - oss << "\n" << number_of_threads << "*" << g_iterations << " log entries took: [" << total_time_us / us_to_s << " s] to write to disk" << std::endl; + oss << "\n" + << number_of_threads << "*" << g_iterations << " log entries took: [" << total_time_us / us_to_s << " s] to write to disk" << std::endl; oss << "[Application(" << number_of_threads << "_threads+overhead time for measurement):\t" << application_time_us / us_to_ms << " ms]" << std::endl; oss << "[Background thread to finish:\t\t\t\t" << total_time_us / us_to_ms << " ms]" << std::endl; oss << "\nAverage time per log entry:" << std::endl; oss << "[Application: " << application_time_us / (number_of_threads * g_iterations) << " us]" << std::endl; - for (uint64_t idx = 0; idx < number_of_threads; ++idx) - { - std::vector &t_result = threads_result[idx]; + for (uint64_t idx = 0; idx < number_of_threads; ++idx) { + std::vector& t_result = threads_result[idx]; uint64_t worstUs = (*std::max_element(t_result.begin(), t_result.end())); - oss << "[Application t" << idx + 1 << " worst took: " << worstUs / uint64_t(1000) << " ms (" << worstUs << " us)] " << std::endl; + oss << "[Application t" << idx + 1 << " worst took: " << worstUs / uint64_t(1000) << " ms (" << worstUs << " us)] " << std::endl; } writeTextToFile(g_measurement_dump, oss.str(), kAppend); std::cout << "Result can be found at:" << g_measurement_dump << std::endl; @@ -148,21 +130,19 @@ int main(int argc, char** argv) // now split the result in buckets of 10ms each so that it's obvious how the peaks go std::vector all_measurements; all_measurements.reserve(g_iterations * number_of_threads); - for (uint64_t idx = 0; idx < number_of_threads; ++idx) - { - std::vector &t_result = threads_result[idx]; + for (uint64_t idx = 0; idx < number_of_threads; ++idx) { + std::vector& t_result = threads_result[idx]; all_measurements.insert(all_measurements.end(), t_result.begin(), t_result.end()); } - delete [] threads_result; // finally get rid of them + delete[] threads_result; // finally get rid of them - std::sort (all_measurements.begin(), all_measurements.end()); + std::sort(all_measurements.begin(), all_measurements.end()); std::map value_amounts; std::map value_amounts_for_0ms_bucket; - for (auto iter = all_measurements.begin(); iter != all_measurements.end(); ++iter) - { - uint64_t value = (*iter) / us_to_ms; // convert to ms - ++value_amounts[value]; // asuming uint64_t is default 0 when initialized + for (auto iter = all_measurements.begin(); iter != all_measurements.end(); ++iter) { + uint64_t value = (*iter) / us_to_ms; // convert to ms + ++value_amounts[value]; // asuming uint64_t is default 0 when initialized if (0 == value) { ++value_amounts_for_0ms_bucket[*iter]; @@ -172,11 +152,12 @@ int main(int argc, char** argv) oss.str(""); oss << "Number of values rounded to milliseconds and put to [millisecond bucket] were dumped to file: " << g_measurement_bucket_dump << std::endl; if (1 == value_amounts.size()) { - oss << "Format: bucket of us inside bucket0 for ms\nFormat:bucket_of_ms, number_of_values_in_bucket\n\n" << std::endl; + oss << "Format: bucket of us inside bucket0 for ms\nFormat:bucket_of_ms, number_of_values_in_bucket\n\n" + << std::endl; oss << "\n"; - } - else { - oss << "Format:bucket_of_ms, number_of_values_in_bucket\n\n" << std::endl; + } else { + oss << "Format:bucket_of_ms, number_of_values_in_bucket\n\n" + << std::endl; } std::cout << oss.str() << std::endl; @@ -191,12 +172,10 @@ int main(int argc, char** argv) oss << "\n\n***** Millisecond bucket measurement ****\n"; } - for (auto ms_bucket : value_amounts) - { + for (auto ms_bucket : value_amounts) { oss << ms_bucket.first << "\t, " << ms_bucket.second << std::endl; } - writeTextToFile(g_measurement_bucket_dump, oss.str(), kAppend, false); - + writeTextToFile(g_measurement_bucket_dump, oss.str(), kAppend, false); return 0; } diff --git a/test_unit/Test.cmake b/test_unit/Test.cmake index 691e1c2..3a28639 100644 --- a/test_unit/Test.cmake +++ b/test_unit/Test.cmake @@ -11,17 +11,13 @@ # ============================================================================ # TEST OPTIONS: Turn OFF the ones that is of no interest to you - # ---- by default all is OFF: except 'g3log-FATAL-example ----- - # ---- the reason for this is that - # ----- 1) the performance tests were only thoroughly tested on Ubuntu, not windows- - # (g3log windows/linux, but Google's glog only on linux) - # - # 2) The unit test were tested windows/linux + # ---- by default unit tests and g3log-FATAL-example are enabled. + # Performance tests are turned off by default since they were not tested on Windows. # ============================================================================ # Unit test for g3log (cmake -DUSE_G3LOG_UNIT_TEST=ON ..) - option (ADD_G3LOG_UNIT_TEST "g3log unit tests" OFF) + option (ADD_G3LOG_UNIT_TEST "g3log unit tests" ON) # 4. create the unit tests for g3log --- ONLY TESTED THE UNIT TEST ON LINUX diff --git a/test_unit/test_concept_sink.cpp b/test_unit/test_concept_sink.cpp index d3f5236..9977ec3 100644 --- a/test_unit/test_concept_sink.cpp +++ b/test_unit/test_concept_sink.cpp @@ -8,19 +8,19 @@ #include +#include +#include #include #include -#include #include -#include -#include +#include -#include "testing_helpers.h" -#include "g3log/sink.hpp" -#include "g3log/sinkwrapper.hpp" -#include "g3log/sinkhandle.hpp" -#include "g3log/logmessage.hpp" #include "g3log/generated_definitions.hpp" +#include "g3log/logmessage.hpp" +#include "g3log/sink.hpp" +#include "g3log/sinkhandle.hpp" +#include "g3log/sinkwrapper.hpp" +#include "testing_helpers.h" using namespace std; using namespace testing_helpers; @@ -29,24 +29,25 @@ class CoutSink { stringstream buffer; unique_ptr scope_ptr; - CoutSink() : scope_ptr(std::make_unique(std::cout, &buffer)) {} - public: + CoutSink() : + scope_ptr(std::make_unique(std::cout, &buffer)) {} + + public: void clear() { buffer.str(""); } std::string string() { return buffer.str(); } void save(g3::LogMessageMover msg) { std::cout << msg.get().message(); } virtual ~CoutSink() final {} - static std::unique_ptr createSink() { return std::unique_ptr(new CoutSink);} + static std::unique_ptr createSink() { return std::unique_ptr(new CoutSink); } }; struct StringSink { std::string raw; - void append(g3::LogMessageMover entry) { raw.append(entry.get().message());} + void append(g3::LogMessageMover entry) { raw.append(entry.get().message()); } std::string string() { return raw; } }; - namespace { typedef std::shared_ptr SinkWrapperPtr; } @@ -54,7 +55,7 @@ namespace { namespace g3 { class Worker { - std::vector _container; // should be hidden in a pimple with a bg active object + std::vector _container; // should be hidden in a pimple with a bg active object std::unique_ptr _bg; void bgSave(std::string msg) { @@ -65,11 +66,10 @@ namespace g3 { } } - public: - - Worker() : _bg { - kjellkod::Active::createActive() - } { + public: + Worker() : + _bg{ + kjellkod::Active::createActive()} { } ~Worker() { @@ -82,35 +82,31 @@ namespace g3 { _bg->send([this, msg] { bgSave(msg); }); } - - template - std::unique_ptr< SinkHandle > addSink(std::unique_ptr unique, DefaultLogCall call) { - auto sink = std::make_shared < internal::Sink > (std::move(unique), call); - auto add_sink_call = [this, sink] { _container.push_back(sink); }; + template + std::unique_ptr> addSink(std::unique_ptr unique, DefaultLogCall call) { + auto sink = std::make_shared>(std::move(unique), call); + auto add_sink_call = [this, sink] { + _container.push_back(sink); + }; auto wait_result = g3::spawn_task(add_sink_call, _bg.get()); wait_result.wait(); - auto handle = std::make_unique< SinkHandle >(sink); + auto handle = std::make_unique>(sink); return handle; } }; -} // g3 - - - +} // namespace g3 using namespace g3; using namespace g3::internal; - TEST(ConceptSink, CreateHandle) { Worker worker; auto handle = worker.addSink(CoutSink::createSink(), &CoutSink::save); ASSERT_NE(nullptr, handle.get()); } - TEST(ConceptSink, OneSink__VerifyMsgIn) { Worker worker; auto handle = worker.addSink(CoutSink::createSink(), &CoutSink::save); @@ -122,19 +118,16 @@ TEST(ConceptSink, OneSink__VerifyMsgIn) { ASSERT_NE(pos, std::string::npos); } - TEST(ConceptSink, DualSink__VerifyMsgIn) { Worker worker; auto h1 = worker.addSink(CoutSink::createSink(), &CoutSink::save); auto h2 = worker.addSink(std::make_unique(), &StringSink::append); worker.save("Hello World!"); - std::this_thread::sleep_for(std::chrono::milliseconds(100)); auto first = h1->call(&CoutSink::string); auto second = h2->call(&StringSink::string); - ASSERT_EQ("Hello World!", first.get()); ASSERT_EQ("Hello World!", second.get()); } @@ -151,10 +144,10 @@ TEST(ConceptSink, DeletedSink__Exptect_badweak_ptr___exception) { namespace { using AtomicBooleanPtr = std::shared_ptr>; - using AtomicIntegerPtr = std::shared_ptr> ; - using BoolList = std::vector ; + using AtomicIntegerPtr = std::shared_ptr>; + using BoolList = std::vector; using IntVector = std::vector; -} +} // namespace TEST(ConceptSink, OneHundredSinks_part1) { BoolList flags; @@ -162,8 +155,8 @@ TEST(ConceptSink, OneHundredSinks_part1) { size_t NumberOfItems = 100; for (size_t index = 0; index < NumberOfItems; ++index) { - flags.push_back(make_shared < atomic> (false)); - counts.push_back(make_shared < atomic> (0)); + flags.push_back(make_shared>(false)); + counts.push_back(make_shared>(0)); } { @@ -190,10 +183,9 @@ TEST(ConceptSink, OneHundredSinks_part1) { cout << "test one hundred sinks is finished\n"; } - TEST(ConceptSink, OneHundredSinks_part2) { - using BoolPtrVector = std::vector ; - using IntPtrVector = vector ; + using BoolPtrVector = std::vector; + using IntPtrVector = vector; BoolPtrVector flags; IntPtrVector counts; @@ -207,18 +199,18 @@ TEST(ConceptSink, OneHundredSinks_part2) { auto worker = g3::LogWorker::createLogWorker(); size_t index = 0; for (auto& flag : flags) { - auto& count = counts[index++]; + auto& count = counts[index++]; // ignore the handle worker->addSink(std::make_unique(flag, count), &ScopedSetTrue::ReceiveMsg); } // 100 logs - for (int index = 0; index < NumberOfItems; ++index) { - LogMessagePtr message{std::make_unique("test", 0, "test", DEBUG)}; - message.get()->write().append("Hello to 100 receivers :)"); - worker->save(message); - } - } // RAII exit + for (int index = 0; index < NumberOfItems; ++index) { + LogMessagePtr message{std::make_unique("test", 0, "test", DEBUG)}; + message.get()->write().append("Hello to 100 receivers :)"); + worker->save(message); + } + } // RAII exit // at the curly brace above the ScopedLogger will go out of scope and all the // 100 logging receivers will get their message to exit after all messages are @@ -229,18 +221,17 @@ TEST(ConceptSink, OneHundredSinks_part2) { for (auto& flag : flags) { auto& count = counts[index++]; EXPECT_TRUE(flag->load()); - EXPECT_EQ(NumberOfItems, count->load()); + EXPECT_EQ(NumberOfItems, count->load()); } } - TEST(ConceptSink, OneSinkWithHandleOutOfScope) { AtomicBooleanPtr flag = make_shared>(false); AtomicIntegerPtr count = make_shared>(0); { auto worker = g3::LogWorker::createLogWorker(); { - auto handle = worker->addSink(std::make_unique(flag, count), &ScopedSetTrue::ReceiveMsg); + auto handle = worker->addSink(std::make_unique(flag, count), &ScopedSetTrue::ReceiveMsg); } EXPECT_FALSE(flag->load()); EXPECT_TRUE(0 == count->load()); diff --git a/test_unit/test_cpp_future_concepts.cpp b/test_unit/test_cpp_future_concepts.cpp index 9a4aae1..68f7d90 100644 --- a/test_unit/test_cpp_future_concepts.cpp +++ b/test_unit/test_cpp_future_concepts.cpp @@ -9,95 +9,85 @@ #include #include -#include -#include -#include #include #include +#include #include -#include "g3log/time.hpp" +#include +#include #include "g3log/future.hpp" +#include "g3log/time.hpp" - -std::future sillyFutureReturn() -{ - std::packaged_task task([](){return std::string("Hello Future");}); // wrap the function - std::future result = task.get_future(); // get a future - std::thread(std::move(task)).detach(); // launch on a thread - std::cout << "Waiting..."; - result.wait(); - return result; // already wasted +std::future sillyFutureReturn() { + std::packaged_task task([]() { return std::string("Hello Future"); }); // wrap the function + std::future result = task.get_future(); // get a future + std::thread(std::move(task)).detach(); // launch on a thread + std::cout << "Waiting..."; + result.wait(); + return result; // already wasted } - -TEST(Configuration, FutureSilly) -{ - std::string hello = sillyFutureReturn().get(); - ASSERT_STREQ(hello.c_str(), "Hello Future"); +TEST(Configuration, FutureSilly) { + std::string hello = sillyFutureReturn().get(); + ASSERT_STREQ(hello.c_str(), "Hello Future"); } -struct MsgType -{ - std::string msg_; - MsgType(std::string m): msg_(m){}; - std::string msg(){return msg_;} +struct MsgType { + std::string msg_; + MsgType(std::string m) : + msg_(m){}; + std::string msg() { return msg_; } }; - -TEST(TestOf_CopyableCall, Expecting_SmoothSailing) -{ - using namespace kjellkod; - const std::string str("Hello from struct"); - MsgType type(str); - std::unique_ptr bgWorker(Active::createActive()); - std::future fstring = - g3::spawn_task(std::bind(&MsgType::msg, type), bgWorker.get()); - ASSERT_STREQ(str.c_str(), fstring.get().c_str()); +TEST(TestOf_CopyableCall, Expecting_SmoothSailing) { + using namespace kjellkod; + const std::string str("Hello from struct"); + MsgType type(str); + std::unique_ptr bgWorker(Active::createActive()); + std::future fstring = + g3::spawn_task(std::bind(&MsgType::msg, type), bgWorker.get()); + ASSERT_STREQ(str.c_str(), fstring.get().c_str()); } +TEST(TestOf_CopyableLambdaCall, Expecting_AllFine) { + using namespace kjellkod; + std::unique_ptr bgWorker(Active::createActive()); + // lambda task + const std::string str_standalone("Hello from standalone"); + auto msg_lambda = [=]() { + return (str_standalone + str_standalone); + }; + std::string expected(str_standalone + str_standalone); -TEST(TestOf_CopyableLambdaCall, Expecting_AllFine) -{ - using namespace kjellkod; - std::unique_ptr bgWorker(Active::createActive()); - - // lambda task - const std::string str_standalone("Hello from standalone"); - auto msg_lambda=[=](){return (str_standalone+str_standalone);}; - std::string expected(str_standalone+str_standalone); - - auto fstring_standalone = g3::spawn_task(msg_lambda, bgWorker.get()); - ASSERT_STREQ(expected.c_str(), fstring_standalone.get().c_str()); + auto fstring_standalone = g3::spawn_task(msg_lambda, bgWorker.get()); + ASSERT_STREQ(expected.c_str(), fstring_standalone.get().c_str()); } +template +std::future> ObsoleteSpawnTask(F f) { + typedef std::invoke_result_t result_type; + typedef std::packaged_task task_type; + task_type task(std::move(f)); + std::future result = task.get_future(); - -template -std::future> ObsoleteSpawnTask(F f) -{ - typedef std::invoke_result_t result_type; - typedef std::packaged_task task_type; - - task_type task(std::move(f)); - std::future result = task.get_future(); - - std::vector> vec; - vec.push_back(g3::MoveOnCopy(std::move(task))); - std::thread(std::move(vec.back())).detach(); - result.wait(); - return std::move(result); + std::vector> vec; + vec.push_back(g3::MoveOnCopy(std::move(task))); + std::thread(std::move(vec.back())).detach(); + result.wait(); + return std::move(result); } -TEST(TestOf_ObsoleteSpawnTaskWithStringReturn, Expecting_FutureString) -{ - std::string str("Hello"); - std::string expected(str+str); - auto msg_lambda=[=](){return (str+str);}; - auto future_string = ObsoleteSpawnTask(msg_lambda); +TEST(TestOf_ObsoleteSpawnTaskWithStringReturn, Expecting_FutureString) { + std::string str("Hello"); + std::string expected(str + str); + auto msg_lambda = [=]() { + return (str + str); + }; + auto future_string = ObsoleteSpawnTask(msg_lambda); - ASSERT_STREQ(expected.c_str(), future_string.get().c_str()); + ASSERT_STREQ(expected.c_str(), future_string.get().c_str()); } // gcc thread example below // tests code below copied from mail-list conversion between @@ -105,67 +95,55 @@ TEST(TestOf_ObsoleteSpawnTaskWithStringReturn, Expecting_FutureString) // http://gcc.gnu.org/ml/gcc-help/2011-11/msg00052.html // -------------------------------------------------------------- -namespace WORKING -{ - using namespace g3; +namespace WORKING { + using namespace g3; #include -#include #include +#include #include #include - std::vector> vec; + std::vector> vec; - template - std::future> spawn_task(F f) - { - typedef std::invoke_result_t result_type; - typedef std::packaged_task task_type; + template + std::future> spawn_task(F f) { + typedef std::invoke_result_t result_type; + typedef std::packaged_task task_type; - task_type task(std::move(f)); - std::future res = task.get_future(); + task_type task(std::move(f)); + std::future res = task.get_future(); - vec.push_back( - MoveOnCopy( - std::move(task))); + vec.push_back( + MoveOnCopy( + std::move(task))); - std::thread([]() - { - auto task = std::move(vec.back()); - vec.pop_back(); - task(); - } - ).detach(); + std::thread([]() { + auto task = std::move(vec.back()); + vec.pop_back(); + task(); + }).detach(); - return std::move(res); - } + return std::move(res); + } + double get_res() { + return 42.2; + } + std::string msg3() { + return "msg3"; + } +} // namespace WORKING - double get_res() - { - return 42.2; - } +TEST(Yalla, Testar) { + using namespace WORKING; + auto f = spawn_task(get_res); + ASSERT_EQ(42.2, f.get()); - std::string msg3(){return "msg3";} -} // WORKING + auto f2 = spawn_task(msg3); + ASSERT_EQ("msg3", f2.get()); -TEST(Yalla, Testar) -{ - using namespace WORKING; - auto f = spawn_task(get_res); - ASSERT_EQ(42.2, f.get()); - - auto f2 = spawn_task(msg3); - ASSERT_EQ("msg3", f2.get()); - - - ASSERT_TRUE(true); + ASSERT_TRUE(true); } - - - - - diff --git a/test_unit/test_crashhandler_windows.cpp b/test_unit/test_crashhandler_windows.cpp index 1e64782..a494a6b 100644 --- a/test_unit/test_crashhandler_windows.cpp +++ b/test_unit/test_crashhandler_windows.cpp @@ -6,13 +6,11 @@ * For more information see g3log/LICENSE or refer refer to http://unlicense.org * ============================================================================*/ - #include #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) -#include "g3log/stacktrace_windows.hpp" #include - +#include "g3log/stacktrace_windows.hpp" TEST(CrashHandler_Windows, ExceptionType) { EXPECT_EQ(stacktrace::exceptionIdToText(123), "UNKNOWN EXCEPTION:123"); diff --git a/test_unit/test_filechange.cpp b/test_unit/test_filechange.cpp index b984f50..5821055 100644 --- a/test_unit/test_filechange.cpp +++ b/test_unit/test_filechange.cpp @@ -6,15 +6,12 @@ * For more information see g3log/LICENSE or refer refer to http://unlicense.org * ============================================================================*/ - #include -#include #include -#include -#include #include +#include #include - +#include #include #include "g3log/g3log.hpp" @@ -23,8 +20,7 @@ using namespace testing_helpers; - -namespace { // anonymous +namespace { // anonymous const char* name_path_1 = "./(some_fake_DirectoryOrName_1_)"; const std::string kReplaceFileName = "(ReplaceLogFile)"; g3::LogWorker* g_logger_ptr = nullptr; @@ -53,7 +49,8 @@ namespace { // anonymous std::string setLogName(std::string new_file_to_create, std::string logger_id = "g3log") { auto future_new_log = g_filesink_handler->call(&g3::FileSink::changeLogFile, new_file_to_create, logger_id); auto new_log = future_new_log.get(); - if (!new_log.empty()) g_cleaner_ptr->addLogToClean(new_log); + if (!new_log.empty()) + g_cleaner_ptr->addLogToClean(new_log); return new_log; } @@ -61,7 +58,7 @@ namespace { // anonymous return g_filesink_handler->call(&g3::FileSink::fileName).get(); } -} // anonymous +} // namespace TEST(TestOf_GetFileName, Expecting_ValidLogFile) { @@ -101,7 +98,8 @@ TEST(TestOf_ChangingLogFile_NoId, Expecting_NewLogFileUsed2) { TEST(TestOf_ManyThreadsChangingLogFileName, Expecting_EqualNumberLogsCreated) { auto old_log = g_filesink_handler->call(&g3::FileSink::fileName).get(); - if (!old_log.empty()) g_cleaner_ptr->addLogToClean(old_log); + if (!old_log.empty()) + g_cleaner_ptr->addLogToClean(old_log); LOG(INFO) << "SoManyThreadsAllDoingChangeFileName"; std::vector threads; @@ -121,7 +119,7 @@ TEST(TestOf_ManyThreadsChangingLogFileName, Expecting_EqualNumberLogsCreated) { TEST(TestOf_IllegalLogFileName, Expecting_NoChangeToOriginalFileName) { std::string original = getLogName(); - auto perhaps_a_name = setLogName("XY:/"); // does not exist + auto perhaps_a_name = setLogName("XY:/"); // does not exist ASSERT_TRUE(perhaps_a_name.empty()); std::string post_illegal = getLogName(); ASSERT_STREQ(original.c_str(), post_illegal.c_str()); @@ -130,19 +128,18 @@ TEST(TestOf_IllegalLogFileName, Expecting_NoChangeToOriginalFileName) { TEST(TestOf_SinkHandleDifferentId, Expecting_DifferentId) { auto sink = std::make_unique("AnotherLogFile", name_path_1, "logger_id"); auto name = sink->fileName(); - ASSERT_STREQ( name.substr(0, 26).c_str(), "./AnotherLogFile.logger_id"); + ASSERT_STREQ(name.substr(0, 26).c_str(), "./AnotherLogFile.logger_id"); g_cleaner_ptr->addLogToClean(name); } -TEST(TestOf_LegalLogFileNam, With_parenthesis) { +TEST(TestOf_LegalLogFileNam, With_parenthesis) { std::string original = getLogName(); - auto perhaps_a_name = setLogName("(test)"); // does not exist + auto perhaps_a_name = setLogName("(test)"); // does not exist EXPECT_NE(original, perhaps_a_name); std::string post_legal = getLogName(); EXPECT_TRUE(std::string::npos != post_legal.find("(test)")) << "filename was: " << post_legal; } - int main(int argc, char* argv[]) { LogFileCleaner cleaner; g_cleaner_ptr = &cleaner; @@ -162,7 +159,6 @@ int main(int argc, char* argv[]) { std::cout << "log file at: " << last_log_file << std::endl; cleaner.addLogToClean(last_log_file); - g3::initializeLogging(g_logger_ptr); LOG(INFO) << "test_filechange demo*" << std::endl; diff --git a/test_unit/test_io.cpp b/test_unit/test_io.cpp index f6ca1b5..93b2585 100644 --- a/test_unit/test_io.cpp +++ b/test_unit/test_io.cpp @@ -8,19 +8,19 @@ #include #include "g3log/g3log.hpp" +#include "g3log/generated_definitions.hpp" +#include "g3log/loglevels.hpp" #include "g3log/logworker.hpp" #include "testing_helpers.h" -#include "g3log/loglevels.hpp" -#include "g3log/generated_definitions.hpp" +#include +#include +#include +#include +#include #include #include -#include #include -#include -#include -#include -#include namespace { const std::string log_directory = "./"; @@ -36,12 +36,10 @@ namespace { ++g_fatal_counter; } -} // end anonymous namespace - +} // end anonymous namespace using namespace testing_helpers; - /// THIS MUST BE THE FIRST UNIT TEST TO RUN! If any unit test run before this /// one then it could fail. For dynamic levels all levels are turned on only AT /// instantiation so we do different test for dynamic logging levels @@ -71,18 +69,18 @@ TEST(Initialization, No_Logger_Initialized___Expecting_LOG_calls_to_be_Still_OKi std::string err_msg1 = "Hey. I am not instantiated but I still should not crash. (I am g3log)"; std::string err_msg3_ignored = "This uninitialized message should be ignored"; try { - LOG(INFO) << err_msg1; // nothing happened. level not ON - LOG(INFO) << err_msg3_ignored; // nothing happened. level not ON + LOG(INFO) << err_msg1; // nothing happened. level not ON + LOG(INFO) << err_msg3_ignored; // nothing happened. level not ON } catch (std::exception& e) { ADD_FAILURE() << "Should never have thrown even if it is not instantiated. Ignored exception: " << e.what(); } - RestoreFileLogger logger(log_directory); // now instantiate the logger + RestoreFileLogger logger(log_directory); // now instantiate the logger std::string good_msg1 = "This message could have pulled in the uninitialized_call message"; LOG(INFO) << good_msg1; - auto content = logger.resetAndRetrieveContent(); // this synchronizes with the LOG(INFO) call if debug level would be ON. + auto content = logger.resetAndRetrieveContent(); // this synchronizes with the LOG(INFO) call if debug level would be ON. ASSERT_TRUE(verifyContent(content, err_msg1)) << "Content: [" << content << "]"; ASSERT_FALSE(verifyContent(content, err_msg3_ignored)) << "Content: [" << content << "]"; ASSERT_TRUE(verifyContent(content, good_msg1)) << "Content: [" << content << "]"; @@ -105,16 +103,16 @@ TEST(Initialization, No_Logger_Initialized___Expecting_LOG_calls_to_be_Still_OKi ADD_FAILURE() << "Should never have thrown even if it is not instantiated: " << e.what(); } - RestoreFileLogger logger(log_directory); // now instantiate the logger + RestoreFileLogger logger(log_directory); // now instantiate the logger std::string good_msg1 = "This message will pull in also the uninitialized_call message"; LOG(INFO) << good_msg1; - auto content = logger.resetAndRetrieveContent(); // this synchronizes with the LOG(INFO) call. + auto content = logger.resetAndRetrieveContent(); // this synchronizes with the LOG(INFO) call. ASSERT_TRUE(verifyContent(content, err_msg1)) << "Content: [" << content << "]"; ASSERT_FALSE(verifyContent(content, err_msg3_ignored)) << "Content: [" << content << "]"; ASSERT_TRUE(verifyContent(content, good_msg1)) << "Content: [" << content << "]"; } -#endif // #ifdef G3_DYNAMIC_LOGGING +#endif // #ifdef G3_DYNAMIC_LOGGING TEST(Basics, Levels_StdFind) { std::vector levels = {INFO, WARNING, FATAL}; @@ -140,7 +138,6 @@ TEST(Basics, Levels_StdFind) { EXPECT_FALSE(wasNotFoundIterator != levels.end()); } - TEST(Basics, Levels_Operator) { auto info = INFO; auto warning = WARNING; @@ -159,10 +156,10 @@ TEST(Basics, Shutdown) { LOG(INFO) << "First message buffered, then flushed"; LOG(INFO) << "Second message still in the buffer"; LOG(INFO) << "Not yet shutdown. This message should make it"; - logger.reset(); // force flush of logger (which will trigger a shutdown) + logger.reset(); // force flush of logger (which will trigger a shutdown) LOG(INFO) << "Logger is shutdown,. this message will not make it (but it's safe to try)"; - file_content = readFileToText(logger.logFile()); // logger is already reset - SCOPED_TRACE("LOG_INFO"); // Scope exit be prepared for destructor failure + file_content = readFileToText(logger.logFile()); // logger is already reset + SCOPED_TRACE("LOG_INFO"); // Scope exit be prepared for destructor failure } EXPECT_TRUE(verifyContent(file_content, "First message buffered, then flushed")); EXPECT_TRUE(verifyContent(file_content, "Second message still in the buffer")); @@ -175,11 +172,11 @@ TEST(Basics, Shutdownx2) { { RestoreFileLogger logger(log_directory); LOG(INFO) << "Not yet shutdown. This message should make it"; - logger.reset(); // force flush of logger (which will trigger a shutdown) - g3::internal::shutDownLogging(); // already called in reset, but safe to call again + logger.reset(); // force flush of logger (which will trigger a shutdown) + g3::internal::shutDownLogging(); // already called in reset, but safe to call again LOG(INFO) << "Logger is shutdown,. this message will not make it (but it's safe to try)"; - file_content = readFileToText(logger.logFile()); // already reset - SCOPED_TRACE("LOG_INFO"); // Scope exit be prepared for destructor failure + file_content = readFileToText(logger.logFile()); // already reset + SCOPED_TRACE("LOG_INFO"); // Scope exit be prepared for destructor failure } EXPECT_TRUE(verifyContent(file_content, "Not yet shutdown. This message should make it")); EXPECT_FALSE(verifyContent(file_content, "Logger is shutdown,. this message will not make it (but it's safe to try)")); @@ -193,9 +190,10 @@ TEST(Basics, ShutdownActiveLogger) { EXPECT_TRUE(g3::internal::shutDownLoggingForActiveOnly(logger._scope->get())); LOG(INFO) << "Logger is shutdown,. this message will not make it (but it's safe to try)"; file_content = logger.resetAndRetrieveContent(); - SCOPED_TRACE("LOG_INFO"); // Scope exit be prepared for destructor failure + SCOPED_TRACE("LOG_INFO"); // Scope exit be prepared for destructor failure } - EXPECT_TRUE(verifyContent(file_content, "Not yet shutdown. This message should make it")) << "\n\n\n***************************\n" << file_content; + EXPECT_TRUE(verifyContent(file_content, "Not yet shutdown. This message should make it")) << "\n\n\n***************************\n" + << file_content; EXPECT_FALSE(verifyContent(file_content, "Logger is shutdown,. this message will not make it (but it's safe to try)")); } @@ -208,13 +206,12 @@ TEST(Basics, DoNotShutdownActiveLogger) { EXPECT_FALSE(g3::internal::shutDownLoggingForActiveOnly(duplicateLogWorker.get())); LOG(INFO) << "Logger is (NOT) shutdown,. this message WILL make it"; file_content = logger.resetAndRetrieveContent(); - SCOPED_TRACE("LOG_INFO"); // Scope exit be prepared for destructor failure + SCOPED_TRACE("LOG_INFO"); // Scope exit be prepared for destructor failure } EXPECT_TRUE(verifyContent(file_content, "Not yet shutdown. This message should make it")); EXPECT_TRUE(verifyContent(file_content, "Logger is (NOT) shutdown,. this message WILL make it")) << file_content; } - TEST(LOGTest, LOG) { std::string file_content; { @@ -222,20 +219,17 @@ TEST(LOGTest, LOG) { EXPECT_TRUE(g3::logLevel(INFO)); EXPECT_TRUE(g3::logLevel(FATAL)); LOG(INFO) << "test LOG(INFO)"; - logger.reset(); // force flush of logger + logger.reset(); // force flush of logger file_content = readFileToText(logger.logFile()); - SCOPED_TRACE("LOG_INFO"); // Scope exit be prepared for destructor failure + SCOPED_TRACE("LOG_INFO"); // Scope exit be prepared for destructor failure } EXPECT_TRUE(verifyContent(file_content, "test LOG(INFO)")); EXPECT_TRUE(g3::logLevel(INFO)); EXPECT_TRUE(g3::logLevel(FATAL)); } - - // printf-type log - TEST(LogTest, LOG_F) { std::string file_content; { @@ -245,18 +239,15 @@ TEST(LogTest, LOG_F) { LOGF(INFO, std::string(t_info + "%d").c_str(), 123); LOGF(G3LOG_DEBUG, std::string(t_debug + "%f").c_str(), 1.123456); LOGF(WARNING, std::string(t_warning + "%s").c_str(), "yello"); - logger.reset(); // force flush of logger + logger.reset(); // force flush of logger file_content = readFileToText(logger.logFile()); - SCOPED_TRACE("LOG_INFO"); // Scope exit be prepared for destructor failure + SCOPED_TRACE("LOG_INFO"); // Scope exit be prepared for destructor failure } ASSERT_TRUE(verifyContent(file_content, t_info2)); ASSERT_TRUE(verifyContent(file_content, t_debug3)); ASSERT_TRUE(verifyContent(file_content, t_warning3)); } - - - // stream-type log TEST(LogTest, LOG) { std::string file_content; @@ -265,9 +256,9 @@ TEST(LogTest, LOG) { LOG(INFO) << t_info << 123; LOG(G3LOG_DEBUG) << t_debug << std::setprecision(7) << 1.123456f; LOG(WARNING) << t_warning << "yello"; - logger.reset(); // force flush of logger + logger.reset(); // force flush of logger file_content = readFileToText(logger.logFile()); - SCOPED_TRACE("LOG_INFO"); // Scope exit be prepared for destructor failure + SCOPED_TRACE("LOG_INFO"); // Scope exit be prepared for destructor failure } ASSERT_TRUE(verifyContent(file_content, t_info2)); ASSERT_TRUE(verifyContent(file_content, t_debug3)); @@ -278,12 +269,12 @@ TEST(LogTest, LOG_after_if) { std::string file_content; { RestoreFileLogger logger(log_directory); - if(false == file_content.empty()) + if (false == file_content.empty()) LOG(INFO) << "This-should-NOT-show-up"; else - LOG(INFO) << "This-should-show-up"; + LOG(INFO) << "This-should-show-up"; - logger.reset(); // force flush of logger + logger.reset(); // force flush of logger file_content = readFileToText(logger.logFile()); } @@ -291,18 +282,17 @@ TEST(LogTest, LOG_after_if) { ASSERT_TRUE(verifyContent(file_content, "This-should-show-up")); } - TEST(LogTest, LOG_after_if_with_parentesis) { std::string file_content; { RestoreFileLogger logger(log_directory); - if(false == file_content.empty()) { + if (false == file_content.empty()) { LOG(INFO) << "This-should-NOT-show-up"; } else { - LOG(INFO) << "This-should-show-up"; + LOG(INFO) << "This-should-show-up"; } - logger.reset(); // force flush of logger + logger.reset(); // force flush of logger file_content = readFileToText(logger.logFile()); } @@ -310,32 +300,29 @@ TEST(LogTest, LOG_after_if_with_parentesis) { ASSERT_TRUE(verifyContent(file_content, "This-should-show-up")); } - - TEST(LogTest, LOG_F_IF) { std::string file_content; { RestoreFileLogger logger(log_directory); LOGF_IF(INFO, (2 == 2), std::string(t_info + "%d").c_str(), 123); LOGF_IF(G3LOG_DEBUG, (2 != 2), std::string(t_debug + "%f").c_str(), 1.123456); - logger.reset(); // force flush of logger + logger.reset(); // force flush of logger file_content = readFileToText(logger.logFile()); - SCOPED_TRACE("LOG_IF"); // Scope exit be prepared for destructor failure + SCOPED_TRACE("LOG_IF"); // Scope exit be prepared for destructor failure } ASSERT_TRUE(verifyContent(file_content, t_info2)); ASSERT_FALSE(verifyContent(file_content, t_debug3)); } - TEST(LogTest, LOG_IF) { std::string file_content; { RestoreFileLogger logger(log_directory); LOG_IF(INFO, (2 == 2)) << t_info << 123; LOG_IF(G3LOG_DEBUG, (2 != 2)) << t_debug << std::setprecision(7) << 1.123456f; - logger.reset(); // force flush of logger + logger.reset(); // force flush of logger file_content = readFileToText(logger.logFile()); - SCOPED_TRACE("LOG_IF"); // Scope exit be prepared for destructor failure + SCOPED_TRACE("LOG_IF"); // Scope exit be prepared for destructor failure } EXPECT_TRUE(verifyContent(file_content, t_info2)); EXPECT_FALSE(verifyContent(file_content, t_debug3)); @@ -365,39 +352,38 @@ TEST(LogTest, FatalSIGTERM__UsingDefaultHandler) { EXPECT_EQ(g_fatal_counter.load(), size_t{1}); } -#if !(defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) +#if !(defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) namespace { std::atomic customFatalCounter = {0}; std::atomic lastEncounteredSignal = {0}; void customSignalHandler(int signal_number, siginfo_t* info, void* unused_context) { lastEncounteredSignal.store(signal_number); - ++customFatalCounter; + ++customFatalCounter; } void installCustomSIGTERM() { struct sigaction action; - memset(&action, 0, sizeof(action)); - sigemptyset(&action.sa_mask); - action.sa_sigaction = &customSignalHandler; - action.sa_flags = SA_SIGINFO; - sigaction(SIGTERM, &action, nullptr); + memset(&action, 0, sizeof(action)); + sigemptyset(&action.sa_mask); + action.sa_sigaction = &customSignalHandler; + action.sa_flags = SA_SIGINFO; + sigaction(SIGTERM, &action, nullptr); } - - std::atomic oldSigTermCheck = {false}; + std::atomic oldSigTermCheck = {false}; void customOldSignalHandler(int signal_number, siginfo_t* info, void* unused_context) { lastEncounteredSignal.store(signal_number); oldSigTermCheck.store(true); } void installCustomOldSIGTERM() { struct sigaction action; - memset(&action, 0, sizeof(action)); - sigemptyset(&action.sa_mask); - action.sa_sigaction = &customOldSignalHandler; - action.sa_flags = SA_SIGINFO; - sigaction(SIGTERM, &action, nullptr); + memset(&action, 0, sizeof(action)); + sigemptyset(&action.sa_mask); + action.sa_sigaction = &customOldSignalHandler; + action.sa_flags = SA_SIGINFO; + sigaction(SIGTERM, &action, nullptr); } -} // anonymous +} // namespace // Override of signal handling and testing of it should be fairly easy to port to windows // ref: https://github.com/KjellKod/g3log/blob/master/src/crashhandler_windows.cpp @@ -420,15 +406,14 @@ namespace { // //void installCustomSIGTERM() { // ASSERT_TRUE(SIG_ERR != signal(SIGTERM, customSignalHandler)); -//} - +//} TEST(LogTest, FatalSIGTERM__UsingCustomHandler) { RestoreFileLogger logger(log_directory); g_fatal_counter.store(0); g3::setFatalPreLoggingHook(fatalCounter); installCustomSIGTERM(); - g3::overrideSetupSignals({ {SIGABRT, "SIGABRT"}, {SIGFPE, "SIGFPE"}, {SIGILL, "SIGILL"}}); + g3::overrideSetupSignals({{SIGABRT, "SIGABRT"}, {SIGFPE, "SIGFPE"}, {SIGILL, "SIGILL"}}); installCustomSIGTERM(); EXPECT_EQ(customFatalCounter.load(), size_t{0}); @@ -449,8 +434,8 @@ TEST(LogTest, FatalSIGTERM__VerifyingOldCustomHandler) { g3::setFatalPreLoggingHook(fatalCounter); installCustomOldSIGTERM(); - g3::overrideSetupSignals({ {SIGABRT, "SIGABRT"}, {SIGFPE, "SIGFPE"}, {SIGILL, "SIGILL"}, {SIGTERM, "SIGTERM"}}); - g3::restoreSignalHandler(SIGTERM); // revert SIGTERM installation + g3::overrideSetupSignals({{SIGABRT, "SIGABRT"}, {SIGFPE, "SIGFPE"}, {SIGILL, "SIGILL"}, {SIGTERM, "SIGTERM"}}); + g3::restoreSignalHandler(SIGTERM); // revert SIGTERM installation EXPECT_EQ(customFatalCounter.load(), size_t{0}); EXPECT_EQ(lastEncounteredSignal.load(), 0); @@ -459,13 +444,9 @@ TEST(LogTest, FatalSIGTERM__VerifyingOldCustomHandler) { logger.reset(); EXPECT_EQ(g_fatal_counter.load(), size_t{0}); EXPECT_EQ(lastEncounteredSignal.load(), SIGTERM); - EXPECT_TRUE(oldSigTermCheck.load()); + EXPECT_TRUE(oldSigTermCheck.load()); } - - - - #endif #endif @@ -490,19 +471,15 @@ TEST(LogTest, LOG_preFatalLogging_hook) { } } - - TEST(LogTest, LOG_FATAL) { RestoreFileLogger logger(log_directory); ASSERT_FALSE(mockFatalWasCalled()); - - LOG(FATAL) << "This message is fatal"; EXPECT_TRUE(mockFatalWasCalled()); EXPECT_TRUE(verifyContent(mockFatalMessage(), "EXIT trigger caused by ")); EXPECT_TRUE(verifyContent(mockFatalMessage(), "This message is fatal")) - << "\ncontent: [[" << mockFatalMessage() << "]]"; + << "\ncontent: [[" << mockFatalMessage() << "]]"; EXPECT_TRUE(verifyContent(mockFatalMessage(), "FATAL")); logger.reset(); @@ -516,7 +493,8 @@ TEST(LogTest, LOGF_IF__FATAL) { EXPECT_FALSE(mockFatalWasCalled()); LOGF_IF(FATAL, (2 < 3), "This message %s be worse", "could"); EXPECT_TRUE(mockFatalWasCalled()); - EXPECT_TRUE(verifyContent(mockFatalMessage(), "EXIT trigger caused by ")) << "\n" << mockFatalMessage(); + EXPECT_TRUE(verifyContent(mockFatalMessage(), "EXIT trigger caused by ")) << "\n" + << mockFatalMessage(); EXPECT_TRUE(verifyContent(mockFatalMessage(), "FATAL")); EXPECT_TRUE(verifyContent(mockFatalMessage(), "This message could be worse")); @@ -549,7 +527,6 @@ TEST(LogTest, LOG_IF__FATAL__NO_THROW) { ASSERT_FALSE(mockFatalWasCalled()); } - // CHECK_F TEST(CheckTest, CHECK_F__thisWILL_PrintErrorMsg) { RestoreFileLogger logger(log_directory); @@ -563,10 +540,9 @@ TEST(CheckTest, CHECK_F__thisWILL_PrintErrorMsg) { logger.reset(); std::string file_content = readFileToText(logger.logFile()); EXPECT_TRUE(verifyContent(mockFatalMessage(), "EXIT trigger caused by ")); - EXPECT_TRUE(verifyContent(file_content, "CONTRACT")) << "**** " << mockFatalMessage(); + EXPECT_TRUE(verifyContent(file_content, "CONTRACT")) << "**** " << mockFatalMessage(); } - TEST(CHECK_F_Test, CHECK_F__thisWILL_PrintErrorMsg) { RestoreFileLogger logger(log_directory); std::string msg = "This message is added to throw %s and %s"; @@ -580,7 +556,6 @@ TEST(CHECK_F_Test, CHECK_F__thisWILL_PrintErrorMsg) { EXPECT_TRUE(verifyContent(file_content, "CONTRACT")); } - TEST(CHECK_Test, CHECK__thisWILL_PrintErrorMsg) { RestoreFileLogger logger(log_directory); std::string msg = "This message is added to throw message and log"; @@ -610,24 +585,24 @@ TEST(CHECK, CHECK_runtimeError) { RestoreFileLogger logger(log_directory); g3::setFatalExitHandler([](g3::FatalMessagePtr msg) { - throw std::runtime_error("fatal test handler"); + throw std::runtime_error("fatal test handler"); }); class dynamic_int_array { - std::unique_ptr data_; - const int size_; - public: - explicit dynamic_int_array(int size) - : data_{std::make_unique(size)} - , size_(size) - {} + std::unique_ptr data_; + const int size_; - int& at(int i) { - CHECK(i < size_); + public: + explicit dynamic_int_array(int size) : + data_{std::make_unique(size)}, + size_(size) {} - // unreachable if i >= size_ - return data_[i]; - } + int& at(int i) { + CHECK(i < size_); + + // unreachable if i >= size_ + return data_[i]; + } }; dynamic_int_array arr{3}; @@ -637,22 +612,25 @@ TEST(CHECK, CHECK_runtimeError) { TEST(CustomLogLevels, AddANonFatal) { RestoreFileLogger logger(log_directory); - const LEVELS MYINFO {WARNING.value + 1, {"MY_INFO_LEVEL"}}; + const LEVELS MYINFO{WARNING.value + 1, {"MY_INFO_LEVEL"}}; #ifdef G3_DYNAMIC_LOGGING g3::only_change_at_initialization::addLogLevel(MYINFO, true); #endif + // clang-format off LOG(MYINFO) << "Testing my own custom level"; auto line = __LINE__; + // clang-format on logger.reset(); std::string file_content = readFileToText(logger.logFile()); std::string expected; expected += "MY_INFO_LEVEL [test_io.cpp->" + std::string(G3LOG_PRETTY_FUNCTION) + ":" + std::to_string(line); EXPECT_TRUE(verifyContent(file_content, expected)) << file_content - << "\n\nExpected: \n" << expected; + << "\n\nExpected: \n" + << expected; } TEST(CustomLogLevels, AddFatal) { RestoreFileLogger logger(log_directory); - const LEVELS DEADLY {FATAL.value + 1, {"DEADLY"}}; + const LEVELS DEADLY{FATAL.value + 1, {"DEADLY"}}; EXPECT_TRUE(g3::internal::wasFatal(DEADLY)); g_fatal_counter.store(0); ASSERT_FALSE(mockFatalWasCalled()); @@ -660,8 +638,9 @@ TEST(CustomLogLevels, AddFatal) { #ifdef G3_DYNAMIC_LOGGING g3::only_change_at_initialization::addLogLevel(DEADLY, true); #endif - + // clang-format off LOG(DEADLY) << "Testing my own custom level"; auto line = __LINE__; + // clang-format on logger.reset(); ASSERT_TRUE(mockFatalWasCalled()); EXPECT_EQ(size_t{1}, g_fatal_counter.load()); @@ -670,18 +649,17 @@ TEST(CustomLogLevels, AddFatal) { std::string expected; expected += "DEADLY [test_io.cpp->" + std::string(G3LOG_PRETTY_FUNCTION) + ":" + std::to_string(line); EXPECT_TRUE(verifyContent(file_content, expected)) << file_content - << "\n\nExpected: \n" << expected; - g_fatal_counter.store(0); // restore + << "\n\nExpected: \n" + << expected; + g_fatal_counter.store(0); // restore } - #ifdef G3_DYNAMIC_LOGGING namespace { // Restore dynamic levels if turned off struct RestoreDynamicLoggingLevels { - RestoreDynamicLoggingLevels() { - }; + RestoreDynamicLoggingLevels(){}; ~RestoreDynamicLoggingLevels() { g3::only_change_at_initialization::reset(); g3::only_change_at_initialization::addLogLevel(G3LOG_DEBUG, false); @@ -690,12 +668,11 @@ namespace { g3::only_change_at_initialization::addLogLevel(FATAL, false); } }; -} // anonymous - +} // namespace TEST(CustomLogLevels, AddANonFatal__ThenReset) { RestoreFileLogger logger(log_directory); - const LEVELS MYINFO {WARNING.value + 2, {"MY_INFO_LEVEL"}}; + const LEVELS MYINFO{WARNING.value + 2, {"MY_INFO_LEVEL"}}; EXPECT_FALSE(g3::logLevel(MYINFO)); g3::only_change_at_initialization::addLogLevel(MYINFO, true); EXPECT_TRUE(g3::logLevel(MYINFO)); @@ -703,78 +680,87 @@ TEST(CustomLogLevels, AddANonFatal__ThenReset) { EXPECT_FALSE(g3::logLevel(MYINFO)); } - TEST(CustomLogLevels, AddANonFatal__DidNotAddItToEnabledValue1) { RestoreFileLogger logger(log_directory); - const LEVELS MYINFO {WARNING.value + 2, {"MY_INFO_LEVEL"}}; + const LEVELS MYINFO{WARNING.value + 2, {"MY_INFO_LEVEL"}}; + // clang-format off LOG(MYINFO) << "Testing my own custom level"; auto line = __LINE__; + // clang-format on logger.reset(); std::string file_content = readFileToText(logger.logFile()); std::string expected; expected += "MY_INFO_LEVEL [test_io.cpp:" + std::to_string(line); EXPECT_FALSE(verifyContent(file_content, expected)) << file_content - << "\n\nExpected: \n" << expected << "\nLevels:\n" << g3::log_levels::to_string(); + << "\n\nExpected: \n" + << expected << "\nLevels:\n" + << g3::log_levels::to_string(); } TEST(CustomLogLevels, AddANonFatal__DidNotAddItToEnabledValue2) { RestoreFileLogger logger(log_directory); - const LEVELS MYINFO {WARNING.value + 2, {"MY_INFO_LEVEL"}}; + const LEVELS MYINFO{WARNING.value + 2, {"MY_INFO_LEVEL"}}; EXPECT_FALSE(g3::logLevel(MYINFO)); + // clang-format off LOG(MYINFO) << "Testing my own custom level"; auto line = __LINE__; + // clang-format on logger.reset(); std::string file_content = readFileToText(logger.logFile()); std::string expected; expected += "MY_INFO_LEVEL [test_io.cpp:" + std::to_string(line); EXPECT_FALSE(verifyContent(file_content, expected)) << file_content - << "\n\nExpected: \n" << expected << "\nLevels:\n" << g3::log_levels::to_string(); + << "\n\nExpected: \n" + << expected << "\nLevels:\n" + << g3::log_levels::to_string(); } TEST(CustomLogLevels, AddANonFatal__DidtAddItToEnabledValue) { RestoreFileLogger logger(log_directory); - const LEVELS MYINFO {WARNING.value + 3, {"MY_INFO_LEVEL"}}; + const LEVELS MYINFO{WARNING.value + 3, {"MY_INFO_LEVEL"}}; g3::only_change_at_initialization::addLogLevel(MYINFO, true); + // clang-format off LOG(MYINFO) << "Testing my own custom level"; auto line = __LINE__; + // clang-format on logger.reset(); std::string file_content = readFileToText(logger.logFile()); std::string expected; expected += "MY_INFO_LEVEL [test_io.cpp->" + std::string(G3LOG_PRETTY_FUNCTION) + ":" + std::to_string(line); EXPECT_TRUE(verifyContent(file_content, expected)) << file_content - << "\n\nExpected: \n" << expected; + << "\n\nExpected: \n" + << expected; } - TEST(DynamicLogging, DynamicLogging_IS_ENABLED) { RestoreDynamicLoggingLevels raiiLevelRestore; ASSERT_TRUE(g3::logLevel(G3LOG_DEBUG)); ASSERT_TRUE(g3::logLevel(INFO)); ASSERT_TRUE(g3::logLevel(WARNING)); - ASSERT_TRUE(g3::logLevel(FATAL)); // Yes FATAL can be turned off. Thereby rendering it ineffective. + ASSERT_TRUE(g3::logLevel(FATAL)); // Yes FATAL can be turned off. Thereby rendering it ineffective. g3::only_change_at_initialization::addLogLevel(G3LOG_DEBUG, false); ASSERT_FALSE(g3::logLevel(G3LOG_DEBUG)); ASSERT_TRUE(g3::logLevel(INFO)); ASSERT_TRUE(g3::logLevel(WARNING)); - ASSERT_TRUE(g3::logLevel(FATAL)); // Yes FATAL can be turned off. Thereby rendering it ineffective. + ASSERT_TRUE(g3::logLevel(FATAL)); // Yes FATAL can be turned off. Thereby rendering it ineffective. g3::only_change_at_initialization::addLogLevel(INFO, false); ASSERT_FALSE(g3::logLevel(G3LOG_DEBUG)); ASSERT_FALSE(g3::logLevel(INFO)); ASSERT_TRUE(g3::logLevel(WARNING)); - ASSERT_TRUE(g3::logLevel(FATAL)); // Yes FATAL can be turned off. Thereby rendering it ineffective. + ASSERT_TRUE(g3::logLevel(FATAL)); // Yes FATAL can be turned off. Thereby rendering it ineffective. g3::only_change_at_initialization::addLogLevel(WARNING, false); ASSERT_FALSE(g3::logLevel(G3LOG_DEBUG)); ASSERT_FALSE(g3::logLevel(INFO)); ASSERT_FALSE(g3::logLevel(WARNING)); - ASSERT_TRUE(g3::logLevel(FATAL)); // Yes FATAL can be turned off. Thereby rendering it ineffective. + ASSERT_TRUE(g3::logLevel(FATAL)); // Yes FATAL can be turned off. Thereby rendering it ineffective. g3::only_change_at_initialization::addLogLevel(FATAL, false); ASSERT_FALSE(g3::logLevel(G3LOG_DEBUG)); ASSERT_FALSE(g3::logLevel(INFO)); ASSERT_FALSE(g3::logLevel(WARNING)); - ASSERT_FALSE(g3::logLevel(FATAL)); // Yes FATAL can be turned off. Thereby rendering it ineffective. + ASSERT_FALSE(g3::logLevel(FATAL)); // Yes FATAL can be turned off. Thereby rendering it ineffective. } TEST(DynamicLogging, DynamicLogging_No_Logs_If_Disabled) { { @@ -828,7 +814,6 @@ TEST(DynamicLogging, DynamicLogging_No_Fatal_If_Disabled) { clearMockFatal(); EXPECT_FALSE(mockFatalWasCalled()); - g3::only_change_at_initialization::addLogLevel(FATAL, false); std::string msg3 = "This is NOT fatal (not crash, since it is unit test. FATAL is disabled"; LOG(FATAL) << msg3; @@ -836,7 +821,6 @@ TEST(DynamicLogging, DynamicLogging_No_Fatal_If_Disabled) { EXPECT_TRUE(mockFatalMessage().empty()); } - TEST(DynamicLogging, DynamicLogging_Check_WillAlsoBeTurnedOffWhen_Fatal_Is_Disabled) { RestoreFileLogger logger(log_directory); RestoreDynamicLoggingLevels raiiLevelRestore; @@ -858,16 +842,10 @@ TEST(DynamicLogging, DynamicLogging_Check_WillAlsoBeTurnedOffWhen_Fatal_Is_Disab EXPECT_FALSE(mockFatalWasCalled()); } - - - #else TEST(DynamicLogging, DynamicLogging_IS_NOT_ENABLED) { ASSERT_TRUE(g3::logLevel(G3LOG_DEBUG)); //g3::addLogLevel(G3LOG_DEBUG, false); this line will not compile since G3_DYNAMIC_LOGGING is not enabled. Kept for show. //ASSERT_FALSE(g3::logLevel(G3LOG_DEBUG)); } -#endif // Dynamic logging - - - +#endif // Dynamic logging diff --git a/test_unit/test_linux_dynamic_loaded_sharedlib.cpp b/test_unit/test_linux_dynamic_loaded_sharedlib.cpp index 639aea7..0ec6c45 100644 --- a/test_unit/test_linux_dynamic_loaded_sharedlib.cpp +++ b/test_unit/test_linux_dynamic_loaded_sharedlib.cpp @@ -6,22 +6,22 @@ * For more information see g3log/LICENSE or refer refer to http://unlicense.org * ============================================================================*/ - +#include #include #include -#include #include #include #include #include -#include "tester_sharedlib.h" #include +#include "tester_sharedlib.h" struct LogMessageCounter { std::vector& bank; - LogMessageCounter(std::vector& storeMessages) : bank(storeMessages) { + LogMessageCounter(std::vector& storeMessages) : + bank(storeMessages) { } void countMessages(std::string msg) { @@ -31,18 +31,18 @@ struct LogMessageCounter { TEST(DynamicLoadOfLibrary, JustLoadAndExit) { std::vector receiver; - - { // scope to flush logs at logworker exit + + { // scope to flush logs at logworker exit auto worker = g3::LogWorker::createLogWorker(); auto handle = worker->addSink(std::make_unique(std::ref(receiver)), &LogMessageCounter::countMessages); - + // add another sink just for more throughput of data auto fileHandle = worker->addSink(std::make_unique("runtimeLoadOfDynamiclibs", "/tmp"), &g3::FileSink::fileWrite); g3::initializeLogging(worker.get()); void* libHandle = dlopen("libtester_sharedlib.so", RTLD_LAZY | RTLD_GLOBAL); EXPECT_FALSE(nullptr == libHandle); - LibraryFactory* factory = reinterpret_cast ((dlsym(libHandle, "testRealFactory"))); + LibraryFactory* factory = reinterpret_cast((dlsym(libHandle, "testRealFactory"))); EXPECT_FALSE(nullptr == factory); SomeLibrary* loadedLibrary = factory->CreateLibrary(); @@ -52,7 +52,7 @@ TEST(DynamicLoadOfLibrary, JustLoadAndExit) { delete loadedLibrary; dlclose(libHandle); - } // scope exit. All log entries must be flushed now - const size_t numberOfMessages = 2 + 300 + 1; // 2 library construction, 300 loop, 1 destoyed library + } // scope exit. All log entries must be flushed now + const size_t numberOfMessages = 2 + 300 + 1; // 2 library construction, 300 loop, 1 destoyed library EXPECT_EQ(receiver.size(), numberOfMessages); } diff --git a/test_unit/test_message.cpp b/test_unit/test_message.cpp index 466241d..cab74fc 100644 --- a/test_unit/test_message.cpp +++ b/test_unit/test_message.cpp @@ -7,14 +7,14 @@ * ============================================================================*/ #include +#include +#include +#include +#include #include +#include #include #include -#include -#include -#include -#include -#include namespace { // https://www.epochconverter.com/ // epoc value for: Thu, 27 Apr 2017 06:22:49 GMT @@ -27,9 +27,7 @@ namespace { const LEVELS kLevel = INFO; const std::string testdirectory = "./"; - -} - +} // namespace TEST(Message, DefaultLogDetals_toString) { using namespace g3; @@ -47,7 +45,6 @@ TEST(Message, Default_toString) { testing_helpers::verifyContent(output, details); } - TEST(Message, UseOverride_4_DetailsWithThreadID_toString) { using namespace g3; LogMessage msg{kFile, kLine, kFunction, kLevel}; @@ -79,25 +76,21 @@ TEST(Message, UseLogCall_4_DetailsWithThreadID_toString) { std::cout << output << std::endl; } - - TEST(Message, DefaultFormattingToLogFile) { using namespace g3; std::string file_content; { testing_helpers::RestoreFileLogger logger(testdirectory); LOG(WARNING) << "testing"; - logger.reset(); // force flush of logger (which will trigger a shutdown) - file_content = testing_helpers::readFileToText(logger.logFile()); // logger is already reset + logger.reset(); // force flush of logger (which will trigger a shutdown) + file_content = testing_helpers::readFileToText(logger.logFile()); // logger is already reset } - + std::ostringstream thread_id_oss; thread_id_oss << " [" << std::this_thread::get_id() << " "; EXPECT_FALSE(testing_helpers::verifyContent(file_content, thread_id_oss.str())); } - - TEST(Message, FullFormattingToLogFile) { using namespace g3; std::string file_content; @@ -106,17 +99,15 @@ TEST(Message, FullFormattingToLogFile) { logger._handle->call(&FileSink::overrideLogDetails, &LogMessage::FullLogDetailsToString); LOG(WARNING) << "testing"; - logger.reset(); // force flush of logger (which will trigger a shutdown) - file_content = testing_helpers::readFileToText(logger.logFile()); // logger is already reset + logger.reset(); // force flush of logger (which will trigger a shutdown) + file_content = testing_helpers::readFileToText(logger.logFile()); // logger is already reset } - + std::ostringstream thread_id_oss; thread_id_oss << " [" << std::this_thread::get_id() << " "; EXPECT_TRUE(testing_helpers::verifyContent(file_content, thread_id_oss.str())); } - - TEST(Message, CppSupport) { // ref: http://www.cplusplus.com/reference/clibrary/ctime/strftime/ // ref: http://en.cppreference.com/w/cpp/io/manip/put_time @@ -125,27 +116,26 @@ TEST(Message, CppSupport) { // --- For formatting options to std::put_time that are NOT YET implemented on Windows fatal errors/assert will occurr // --- the last example is such an example. try { - std::cout << g3::localtime_formatted(std::chrono::system_clock::now(), "%a %b %d %H:%M:%S %Y") << std::endl; + std::cout << g3::localtime_formatted(std::chrono::system_clock::now(), "%a %b %d %H:%M:%S %Y") << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); - std::cout << g3::localtime_formatted(std::chrono::system_clock::now(), "%%Y/%%m/%%d %%H:%%M:%%S = %Y/%m/%d %H:%M:%S") << std::endl; + std::cout << g3::localtime_formatted(std::chrono::system_clock::now(), "%%Y/%%m/%%d %%H:%%M:%%S = %Y/%m/%d %H:%M:%S") << std::endl; #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) std::cerr << "Formatting options skipped due to VS2012, C++11 non-conformance for" << std::endl; - std::cerr << " some formatting options. The skipped code was:\n\t\t %EX %Ec, \n(see http://en.cppreference.com/w/cpp/io/manip/put_time for details)" << std::endl; + std::cerr << " some formatting options. The skipped code was:\n\t\t %EX %Ec, \n(see http://en.cppreference.com/w/cpp/io/manip/put_time for details)" << std::endl; #else - std::cout << "C++11 new formatting options:\n" << g3::localtime_formatted(std::chrono::system_clock::now(), "%%EX: %EX\n%%z: %z\n%%Ec: %Ec") << std::endl; + std::cout << "C++11 new formatting options:\n" + << g3::localtime_formatted(std::chrono::system_clock::now(), "%%EX: %EX\n%%z: %z\n%%Ec: %Ec") << std::endl; #endif } -// This does not work. Other kinds of fatal exits (on Windows) seems to be used instead of exceptions -// Maybe a signal handler catch would be better? --- TODO: Make it better, both failing and correct + // This does not work. Other kinds of fatal exits (on Windows) seems to be used instead of exceptions + // Maybe a signal handler catch would be better? --- TODO: Make it better, both failing and correct catch (...) { ADD_FAILURE() << "On this platform the library does not support given (C++11?) specifiers"; return; } - ASSERT_TRUE(true); // no exception. all good + ASSERT_TRUE(true); // no exception. all good } - - TEST(Message, GetFractional_Empty_buffer_ExpectDefaults) { auto fractional = g3::internal::getFractional("", 0); const auto expected = g3::internal::Fractional::NanosecondDefault; @@ -200,8 +190,6 @@ TEST(Message, GetFractional_All) { EXPECT_EQ(fractional, expected); } - - TEST(Message, FractionalToString_SizeCheck) { auto value = g3::internal::to_string(kTimePoint_2017_April_27th, g3::internal::Fractional::Nanosecond); EXPECT_EQ("000000000", value); @@ -211,7 +199,7 @@ TEST(Message, FractionalToString_SizeCheck) { // us value = g3::internal::to_string(kTimePoint_2017_April_27th, g3::internal::Fractional::Microsecond); EXPECT_EQ("000000", value); -// ms + // ms value = g3::internal::to_string(kTimePoint_2017_April_27th, g3::internal::Fractional::Millisecond); EXPECT_EQ("000", value); } @@ -233,16 +221,13 @@ TEST(Message, FractionalToString12NanoPadded) { EXPECT_EQ("000000000", value); } - TEST(Message, FractionalToStringMicroPadded) { auto value = g3::internal::to_string(k1970_January_1st, g3::internal::Fractional::Microsecond); EXPECT_EQ("000000", value); value = g3::internal::to_string(k1970_January_1st, g3::internal::Fractional::Microsecond); EXPECT_EQ("000000", value); - } - TEST(Message, FractionalToStringMilliPadded) { auto value = g3::internal::to_string(k1970_January_1st, g3::internal::Fractional::Millisecond); EXPECT_EQ("000", value); @@ -250,7 +235,6 @@ TEST(Message, FractionalToStringMilliPadded) { EXPECT_EQ("000", value); } - #if !(defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) TEST(Message, localtime_formatted) { @@ -262,19 +246,17 @@ TEST(Message, localtime_formatted) { else unsetenv("TZ"); tzset(); - }); tz = getenv("TZ"); setenv("TZ", "", 1); tzset(); - auto time_point = std::chrono::system_clock::from_time_t(k2017_April_27th); - auto format = g3::localtime_formatted(time_point, "%Y-%m-%d %H:%M:%S"); // %Y/%m/%d + auto format = g3::localtime_formatted(time_point, "%Y-%m-%d %H:%M:%S"); // %Y/%m/%d std::string expected = {"2017-04-27 06:22:27"}; EXPECT_EQ(expected, format); - auto us_format = g3::localtime_formatted(time_point, g3::internal::time_formatted); // "%H:%M:%S %f6"; + auto us_format = g3::localtime_formatted(time_point, g3::internal::time_formatted); // "%H:%M:%S %f6"; EXPECT_EQ("06:22:27 000000", us_format); auto ns_format = g3::localtime_formatted(time_point, "%H:%M:%S %f"); @@ -282,51 +264,45 @@ TEST(Message, localtime_formatted) { auto ms_format = g3::localtime_formatted(time_point, "%H:%M:%S %f3"); EXPECT_EQ("06:22:27 000", ms_format); - } -#endif // timezone +#endif // timezone #if defined(CHANGE_G3LOG_DEBUG_TO_DBUG) TEST(Level, G3LogDebug_is_DBUG) { - LOG(DBUG) << "DBUG equals G3LOG_DEBUG"; - LOG(G3LOG_DEBUG) << "G3LOG_DEBUG equals DBUG"; + LOG(DBUG) << "DBUG equals G3LOG_DEBUG"; + LOG(G3LOG_DEBUG) << "G3LOG_DEBUG equals DBUG"; } #else TEST(Level, G3LogDebug_is_DEBUG) { - LOG(DEBUG) << "DEBUG equals G3LOG_DEBUG"; - LOG(G3LOG_DEBUG) << "G3LOG_DEBUG equals DEBUG"; + LOG(DEBUG) << "DEBUG equals G3LOG_DEBUG"; + LOG(G3LOG_DEBUG) << "G3LOG_DEBUG equals DEBUG"; } #endif - #ifdef G3_DYNAMIC_LOGGING namespace { using LevelsContainer = std::map; const LevelsContainer g_test_log_level_defaults = { - {G3LOG_DEBUG.value, {G3LOG_DEBUG}}, + {G3LOG_DEBUG.value, {G3LOG_DEBUG}}, {INFO.value, {INFO}}, {WARNING.value, {WARNING}}, - {FATAL.value, {FATAL}} - }; + {FATAL.value, {FATAL}}}; const LevelsContainer g_test_all_disabled = { - {G3LOG_DEBUG.value, {G3LOG_DEBUG,false}}, + {G3LOG_DEBUG.value, {G3LOG_DEBUG, false}}, {INFO.value, {INFO, false}}, {WARNING.value, {WARNING, false}}, - {FATAL.value, {FATAL, false}} - }; + {FATAL.value, {FATAL, false}}}; - - bool mapCompare (LevelsContainer const& lhs, LevelsContainer const& rhs) { - auto pred = [] (auto a, auto b) { + bool mapCompare(LevelsContainer const& lhs, LevelsContainer const& rhs) { + auto pred = [](auto a, auto b) { return (a.first == b.first) && (a.second == b.second); }; - return lhs.size() == rhs.size() - && std::equal(lhs.begin(), lhs.end(), rhs.begin(), pred); + return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin(), pred); } -} // anonymous +} // namespace TEST(Level, Default) { g3::only_change_at_initialization::reset(); auto defaults = g3::log_levels::getAll(); @@ -349,8 +325,7 @@ TEST(Level, DefaultChanged_only_change_at_initialization) { {G3LOG_DEBUG.value, {G3LOG_DEBUG, true}}, {INFO.value, {INFO, false}}, {WARNING.value, {WARNING, true}}, - {FATAL.value, {FATAL, true}} - }; + {FATAL.value, {FATAL, true}}}; EXPECT_TRUE(mapCompare(defaults, defaultsWithInfoChangged)); } @@ -369,8 +344,7 @@ TEST(Level, DefaultChanged_log_levels) { {G3LOG_DEBUG.value, {G3LOG_DEBUG, true}}, {INFO.value, {INFO, false}}, {WARNING.value, {WARNING, true}}, - {FATAL.value, {FATAL, true}} - }; + {FATAL.value, {FATAL, true}}}; EXPECT_TRUE(mapCompare(defaults, defaultsWithInfoChangged)); } @@ -386,20 +360,14 @@ TEST(Level, Reset) { g3::only_change_at_initialization::reset(); all_levels = g3::log_levels::getAll(); EXPECT_TRUE(mapCompare(all_levels, g_test_log_level_defaults)); - - - } - - TEST(Level, AllDisabled) { g3::only_change_at_initialization::reset(); std::shared_ptr RaiiLeveReset(nullptr, [&](void*) { g3::only_change_at_initialization::reset(); }); - auto all_levels = g3::log_levels::getAll(); EXPECT_EQ(all_levels.size(), g_test_all_disabled.size()); EXPECT_FALSE(mapCompare(all_levels, g_test_all_disabled)); @@ -409,79 +377,64 @@ TEST(Level, AllDisabled) { EXPECT_TRUE(mapCompare(all_levels, g_test_all_disabled)); } - TEST(Level, setHighestLogLevel_high_end) { g3::only_change_at_initialization::reset(); std::shared_ptr RaiiLeveReset(nullptr, [&](void*) { g3::only_change_at_initialization::reset(); }); - g3::log_levels::enableAll(); g3::log_levels::disable(FATAL); g3::log_levels::setHighest(FATAL); - LevelsContainer expected = { {G3LOG_DEBUG.value, {G3LOG_DEBUG, false}}, {INFO.value, {INFO, false}}, {WARNING.value, {WARNING, false}}, - {FATAL.value, {FATAL, true}} - }; + {FATAL.value, {FATAL, true}}}; auto all_levels = g3::log_levels::getAll(); EXPECT_TRUE(mapCompare(all_levels, expected)) << g3::log_levels::to_string(); } - TEST(Level, setHighestLogLevel_low_end) { g3::only_change_at_initialization::reset(); std::shared_ptr RaiiLeveReset(nullptr, [&](void*) { g3::only_change_at_initialization::reset(); }); - g3::log_levels::disableAll(); g3::log_levels::setHighest(G3LOG_DEBUG); - LevelsContainer expected = { - {G3LOG_DEBUG.value,{G3LOG_DEBUG, true}}, + {G3LOG_DEBUG.value, {G3LOG_DEBUG, true}}, {INFO.value, {INFO, true}}, {WARNING.value, {WARNING, true}}, - {FATAL.value, {FATAL, true}} - }; + {FATAL.value, {FATAL, true}}}; auto all_levels = g3::log_levels::getAll(); EXPECT_TRUE(mapCompare(all_levels, expected)) << g3::log_levels::to_string(); } - TEST(Level, setHighestLogLevel_middle) { g3::only_change_at_initialization::reset(); std::shared_ptr RaiiLeveReset(nullptr, [&](void*) { g3::only_change_at_initialization::reset(); }); - g3::log_levels::enableAll(); g3::log_levels::setHighest(WARNING); - LevelsContainer expected = { {G3LOG_DEBUG.value, {G3LOG_DEBUG, false}}, {INFO.value, {INFO, false}}, {WARNING.value, {WARNING, true}}, - {FATAL.value, {FATAL, true}} - }; + {FATAL.value, {FATAL, true}}}; auto all_levels = g3::log_levels::getAll(); EXPECT_TRUE(mapCompare(all_levels, expected)); } - - - TEST(Level, setHighestLogLevel_StepWiseDisableAll) { g3::only_change_at_initialization::reset(); std::shared_ptr RaiiLeveReset(nullptr, [&](void*) { @@ -492,8 +445,7 @@ TEST(Level, setHighestLogLevel_StepWiseDisableAll) { {G3LOG_DEBUG.value, {G3LOG_DEBUG, true}}, {INFO.value, {INFO, true}}, {WARNING.value, {WARNING, true}}, - {FATAL.value, {FATAL, true}} - }; + {FATAL.value, {FATAL, true}}}; auto all_levels = g3::log_levels::getAll(); EXPECT_TRUE(mapCompare(all_levels, g_test_log_level_defaults)); @@ -503,11 +455,9 @@ TEST(Level, setHighestLogLevel_StepWiseDisableAll) { g3::log_levels::setHighest(lvl.second.level); all_levels = g3::log_levels::getAll(); - ASSERT_TRUE(mapCompare(all_levels, changing_levels)) << - "counter: " << counter << "\nsystem:\n" << - g3::log_levels::to_string(all_levels) << - "\nexpected:\n" << - g3::log_levels::to_string(changing_levels); + ASSERT_TRUE(mapCompare(all_levels, changing_levels)) << "counter: " << counter << "\nsystem:\n" + << g3::log_levels::to_string(all_levels) << "\nexpected:\n" + << g3::log_levels::to_string(changing_levels); ++counter; if (counter != changing_levels.size()) { @@ -516,26 +466,20 @@ TEST(Level, setHighestLogLevel_StepWiseDisableAll) { } } - // in the end all except the last should be disabled auto mostly_disabled = g_test_all_disabled; mostly_disabled[FATAL.value].status = true; EXPECT_TRUE(mapCompare(changing_levels, mostly_disabled)); all_levels = g3::log_levels::getAll(); - EXPECT_TRUE(mapCompare(all_levels, mostly_disabled)) << - "\nsystem:\n" << - g3::log_levels::to_string(all_levels) << - "\nexpected:\n" << - g3::log_levels::to_string(mostly_disabled); + EXPECT_TRUE(mapCompare(all_levels, mostly_disabled)) << "\nsystem:\n" + << g3::log_levels::to_string(all_levels) << "\nexpected:\n" + << g3::log_levels::to_string(mostly_disabled); } TEST(Level, Print) { g3::only_change_at_initialization::reset(); - std::string expected = std::string{"name: DEBUG level: 100 status: 1\n"} - + "name: INFO level: 300 status: 1\n" - + "name: WARNING level: 500 status: 1\n" - + "name: FATAL level: 1000 status: 1\n"; + std::string expected = std::string{"name: DEBUG level: 100 status: 1\n"} + "name: INFO level: 300 status: 1\n" + "name: WARNING level: 500 status: 1\n" + "name: FATAL level: 1000 status: 1\n"; EXPECT_EQ(g3::log_levels::to_string(), expected); } @@ -544,19 +488,16 @@ TEST(Level, AddOneEnabled_option1) { g3::only_change_at_initialization::reset(); }); - - LEVELS MYINFO {WARNING.value + 1, "MyInfoLevel"}; + LEVELS MYINFO{WARNING.value + 1, "MyInfoLevel"}; g3::only_change_at_initialization::addLogLevel(MYINFO, true); auto modified = g_test_log_level_defaults; modified[MYINFO.value] = MYINFO; auto all_levels = g3::log_levels::getAll(); - EXPECT_TRUE(mapCompare(modified, all_levels)) << "\nsystem:\n" << - g3::log_levels::to_string(all_levels) << - "\nexpected:\n" << - g3::log_levels::to_string(modified); - + EXPECT_TRUE(mapCompare(modified, all_levels)) << "\nsystem:\n" + << g3::log_levels::to_string(all_levels) << "\nexpected:\n" + << g3::log_levels::to_string(modified); } TEST(Level, AddOneEnabled_option2) { @@ -564,30 +505,24 @@ TEST(Level, AddOneEnabled_option2) { g3::only_change_at_initialization::reset(); }); - - LEVELS MYINFO {WARNING.value + 1, "MyInfoLevel"}; + LEVELS MYINFO{WARNING.value + 1, "MyInfoLevel"}; g3::only_change_at_initialization::addLogLevel(MYINFO); auto modified = g_test_log_level_defaults; modified[MYINFO.value] = MYINFO; auto all_levels = g3::log_levels::getAll(); - EXPECT_TRUE(mapCompare(modified, all_levels)) << "\nsystem:\n" << - g3::log_levels::to_string(all_levels) << - "\nexpected:\n" << - g3::log_levels::to_string(modified); - + EXPECT_TRUE(mapCompare(modified, all_levels)) << "\nsystem:\n" + << g3::log_levels::to_string(all_levels) << "\nexpected:\n" + << g3::log_levels::to_string(modified); } - - - TEST(Level, Addlevel_using_addLevel) { std::shared_ptr RaiiLeveReset(nullptr, [&](void*) { g3::only_change_at_initialization::reset(); }); - LEVELS MYINFO {WARNING.value + 1, "MyInfoLevel"}; + LEVELS MYINFO{WARNING.value + 1, "MyInfoLevel"}; auto status = g3::log_levels::getStatus(MYINFO); EXPECT_EQ(status, g3::log_levels::status::Absent); @@ -601,7 +536,7 @@ TEST(Level, Addlevel_using_addLogLevel_disabled) { g3::only_change_at_initialization::reset(); }); - LEVELS MYINFO {WARNING.value + 1, "MyInfoLevel"}; + LEVELS MYINFO{WARNING.value + 1, "MyInfoLevel"}; auto status = g3::log_levels::getStatus(MYINFO); EXPECT_EQ(status, g3::log_levels::status::Absent); @@ -615,7 +550,7 @@ TEST(Level, Addlevel__disabled) { g3::only_change_at_initialization::reset(); }); - LEVELS MYINFO {WARNING.value + 1, "MyInfoLevel"}; + LEVELS MYINFO{WARNING.value + 1, "MyInfoLevel"}; auto status = g3::log_levels::getStatus(MYINFO); EXPECT_EQ(status, g3::log_levels::status::Absent); @@ -637,15 +572,13 @@ TEST(Level, Addlevel__enabled) { g3::only_change_at_initialization::reset(); }); - LEVELS MYINFO {WARNING.value + 1, "MyInfoLevel"}; + LEVELS MYINFO{WARNING.value + 1, "MyInfoLevel"}; auto status = g3::log_levels::getStatus(MYINFO); EXPECT_EQ(status, g3::log_levels::status::Absent); - g3::only_change_at_initialization::addLogLevel(MYINFO); status = g3::log_levels::getStatus(MYINFO); EXPECT_EQ(status, g3::log_levels::status::Enabled); } -#endif // G3_DYNAMIC_LOGGING - +#endif // G3_DYNAMIC_LOGGING diff --git a/test_unit/test_sink.cpp b/test_unit/test_sink.cpp index 434033f..e200161 100644 --- a/test_unit/test_sink.cpp +++ b/test_unit/test_sink.cpp @@ -7,26 +7,25 @@ * ============================================================================*/ #include -#include #include -#include -#include -#include #include -#include #include #include -#include "testing_helpers.h" +#include +#include +#include +#include +#include #include "g3log/logmessage.hpp" #include "g3log/logworker.hpp" - +#include "testing_helpers.h" using namespace testing_helpers; using namespace std; TEST(Sink, OneSink) { using namespace g3; - AtomicBoolPtr flag = make_shared < atomic> (false); - AtomicIntPtr count = make_shared < atomic> (0); + AtomicBoolPtr flag = make_shared>(false); + AtomicIntPtr count = make_shared>(0); { auto worker = g3::LogWorker::createLogWorker(); auto handle = worker->addSink(std::make_unique(flag, count), &ScopedSetTrue::ReceiveMsg); @@ -40,12 +39,10 @@ TEST(Sink, OneSink) { EXPECT_TRUE(1 == count->load()); } - - TEST(Sink, OneSinkRemove) { using namespace g3; - AtomicBoolPtr flag = make_shared < atomic> (false); - AtomicIntPtr count = make_shared < atomic> (0); + AtomicBoolPtr flag = make_shared>(false); + AtomicIntPtr count = make_shared>(0); { auto worker = g3::LogWorker::createLogWorker(); auto handle = worker->addSink(std::make_unique(flag, count), &ScopedSetTrue::ReceiveMsg); @@ -67,14 +64,14 @@ TEST(Sink, OneSinkRemove) { } // just compile test -TEST(Sink, DefaultSinkRemove){ +TEST(Sink, DefaultSinkRemove) { using namespace g3; - AtomicBoolPtr flag = make_shared < atomic> (false); - AtomicIntPtr count = make_shared < atomic> (0); + AtomicBoolPtr flag = make_shared>(false); + AtomicIntPtr count = make_shared>(0); { auto worker = g3::LogWorker::createLogWorker(); - auto handle1 = worker->addDefaultLogger("test1", "./"); - auto handle2 = worker->addDefaultLogger("test2", "./"); + auto handle1 = worker->addDefaultLogger("test1", "./"); + auto handle2 = worker->addDefaultLogger("test2", "./"); worker->removeSink(std::move(handle1)); worker->removeAllSinks(); } @@ -82,8 +79,8 @@ TEST(Sink, DefaultSinkRemove){ TEST(Sink, NullSinkRemove) { using namespace g3; - AtomicBoolPtr flag = make_shared < atomic> (false); - AtomicIntPtr count = make_shared < atomic> (0); + AtomicBoolPtr flag = make_shared>(false); + AtomicIntPtr count = make_shared>(0); { auto worker = g3::LogWorker::createLogWorker(); std::unique_ptr> nullsink; @@ -91,13 +88,11 @@ TEST(Sink, NullSinkRemove) { } } - - namespace { - using AtomicBoolPtr = std::shared_ptr>; - using AtomicIntPtr = std::shared_ptr>; - using BoolList = vector; - using IntVector = vector; + using AtomicBoolPtr = std::shared_ptr>; + using AtomicIntPtr = std::shared_ptr>; + using BoolList = vector; + using IntVector = vector; size_t countDestroyedFlags(BoolList& flags) { size_t destroyed_count = 0; @@ -125,8 +120,7 @@ namespace { return total_count; } - -} +} // namespace TEST(ConceptSink, OneHundredSinks) { using namespace g3; @@ -135,13 +129,13 @@ TEST(ConceptSink, OneHundredSinks) { size_t kNumberOfItems = 100; for (size_t index = 0; index < kNumberOfItems; ++index) { - flags.push_back(make_shared < atomic> (false)); - counts.push_back(make_shared < atomic> (0)); + flags.push_back(make_shared>(false)); + counts.push_back(make_shared>(0)); } { RestoreFileLogger logger{"./"}; - g3::LogWorker* worker = logger._scope->get(); //g3LogWorker::createLogWorker(); + g3::LogWorker* worker = logger._scope->get(); //g3LogWorker::createLogWorker(); size_t index = 0; for (auto& flag : flags) { auto& count = counts[index++]; @@ -180,7 +174,6 @@ void AddManySinks(size_t kNumberOfSinks, BoolList& flags, IntVector& counts, flags.push_back(make_shared>(false)); counts.push_back(make_shared>(0)); sink_handles.push_back(worker->addSink(std::make_unique(flags[idx], counts[idx]), &ScopedSetTrue::ReceiveMsg)); - } } @@ -192,7 +185,7 @@ TEST(ConceptSink, OneHundredSinksRemoved) { std::vector sink_handles; { RestoreFileLogger logger{"./"}; - g3::LogWorker* worker = logger._scope->get(); //think: g3LogWorker::createLogWorker(); + g3::LogWorker* worker = logger._scope->get(); //think: g3LogWorker::createLogWorker(); AddManySinks(kNumberOfItems, flags, counts, sink_handles, worker); LogMessagePtr message{std::make_unique("test", 0, "test", DEBUG)}; auto& write = message.get()->write(); @@ -217,7 +210,7 @@ TEST(ConceptSink, OneHundredRemoveAllSinks) { std::vector sink_handles; { RestoreFileLogger logger{"./"}; - g3::LogWorker* worker = logger._scope->get(); //think: g3LogWorker::createLogWorker(); + g3::LogWorker* worker = logger._scope->get(); //think: g3LogWorker::createLogWorker(); AddManySinks(kNumberOfItems, flags, counts, sink_handles, worker); LogMessagePtr message{std::make_unique("test", 0, "test", DEBUG)}; @@ -232,12 +225,13 @@ TEST(ConceptSink, OneHundredRemoveAllSinks) { } } - struct VoidReceiver { std::atomic* _atomicCounter; - explicit VoidReceiver(std::atomic* counter) : _atomicCounter(counter) {} + explicit VoidReceiver(std::atomic* counter) : + _atomicCounter(counter) {} - void receiveMsg(std::string msg) { /*ignored*/} + void receiveMsg(std::string msg) { /*ignored*/ + } void incrementAtomic() { (*_atomicCounter)++; } @@ -267,20 +261,21 @@ TEST(ConceptSink, VoidCall__TwoCalls_ExpectingTwoAdd) { { std::unique_ptr worker{g3::LogWorker::createLogWorker()}; auto handle = worker->addSink(std::make_unique(&counter), &VoidReceiver::receiveMsg); - auto voidFuture1 = handle->call(&VoidReceiver::incrementAtomic); - auto voidFuture2 = handle->call(&VoidReceiver::incrementAtomic); + auto voidFuture1 = handle->call(&VoidReceiver::incrementAtomic); + auto voidFuture2 = handle->call(&VoidReceiver::incrementAtomic); voidFuture1.wait(); EXPECT_TRUE(counter >= 1); } EXPECT_EQ(counter, 2); } - struct IntReceiver { std::atomic* _atomicCounter; - explicit IntReceiver(std::atomic* counter) : _atomicCounter(counter) {} + explicit IntReceiver(std::atomic* counter) : + _atomicCounter(counter) {} - void receiveMsgDoNothing(std::string msg) { /*ignored*/} + void receiveMsgDoNothing(std::string msg) { /*ignored*/ + } void receiveMsgIncrementAtomic(std::string msg) { incrementAtomic(); } int incrementAtomic() { (*_atomicCounter)++; @@ -300,14 +295,11 @@ TEST(ConceptSink, IntCall__TwoCalls_ExpectingTwoAdd) { auto intFuture2 = handle->call(&IntReceiver::incrementAtomic); EXPECT_EQ(intFuture2.get(), 2); - } EXPECT_EQ(counter, 2); } - - -void DoLogCalls(std::atomic* doWhileTrue, size_t counter) { +void DoLogCalls(std::atomic* doWhileTrue, size_t counter) { while (doWhileTrue->load()) { LOG(INFO) << "Calling from #" << counter; std::cout << "-"; @@ -315,12 +307,12 @@ void DoLogCalls(std::atomic* doWhileTrue, size_t counter) { } } -void DoSlowLogCalls(std::atomic* doWhileTrue, size_t counter) { +void DoSlowLogCalls(std::atomic* doWhileTrue, size_t counter) { size_t messages = 0; while (doWhileTrue->load()) { LOG(INFO) << "Calling from #" << counter; ++messages; - int random = rand() % 10 + 1; // Range 1-10 + int random = rand() % 10 + 1; // Range 1-10 std::this_thread::sleep_for(std::chrono::microseconds(random)); } @@ -328,11 +320,10 @@ void DoSlowLogCalls(std::atomic* doWhileTrue, size_t counter) { std::cout << out; } - - - TEST(ConceptSink, CannotCallSpawnTaskOnNullptrWorker) { - auto FailedHelloWorld = [] { std::cout << "Hello World" << std::endl; }; + auto FailedHelloWorld = [] { + std::cout << "Hello World" << std::endl; + }; kjellkod::Active* active = nullptr; auto failed = g3::spawn_task(FailedHelloWorld, active); EXPECT_ANY_THROW(failed.get()); @@ -364,7 +355,7 @@ TEST(ConceptSink, AggressiveThreadCallsDuringAddAndRemoveSink) { std::atomic atomicCounter{0}; - std::cout << "Add sinks, remove sinks, " << numberOfCycles << " times\n\tWhile " << numberOfThreads << " threads are continously doing LOG calls" << std::endl; + std::cout << "Add sinks, remove sinks, " << numberOfCycles << " times\n\tWhile " << numberOfThreads << " threads are continously doing LOG calls" << std::endl; for (size_t create = 0; create < numberOfCycles; ++create) { worker->removeAllSinks(); sink_handles.clear(); @@ -380,7 +371,7 @@ TEST(ConceptSink, AggressiveThreadCallsDuringAddAndRemoveSink) { std::this_thread::yield(); } - } // g3log worker exists: 1) shutdownlogging 2) flush of queues and shutdown of sinks + } // g3log worker exists: 1) shutdownlogging 2) flush of queues and shutdown of sinks worker.reset(); // exit the threads keepRunning = false; @@ -390,7 +381,6 @@ TEST(ConceptSink, AggressiveThreadCallsDuringAddAndRemoveSink) { std::cout << "\nAll threads are joined " << std::endl; } - // This test is commented out but kept here for documentation purposes. // Actually shutting down and re-initializing the logger is not the intention of g3log. // the are several initial setups that happen ONCE and the logger relies on the client @@ -424,7 +414,6 @@ TEST(ConceptSink, AggressiveThreadCallsDuringAddAndRemoveSink) { // for (size_t create = 0; create < numberOfCycles; ++create) { // std::cout << "."; - // std::unique_ptr worker{g3::LogWorker::createLogWorker()}; // auto handle = worker->addSink(std::make_unique(&atomicCounter), &IntReceiver::receiveMsgIncrementAtomic); // g3::initializeLogging(worker.get()); diff --git a/test_unit/tester_sharedlib.cpp b/test_unit/tester_sharedlib.cpp index 000ce68..4c41ece 100644 --- a/test_unit/tester_sharedlib.cpp +++ b/test_unit/tester_sharedlib.cpp @@ -6,10 +6,9 @@ * For more information see g3log/LICENSE or refer refer to http://unlicense.org * ============================================================================*/ - +#include "tester_sharedlib.h" #include #include -#include "tester_sharedlib.h" struct RuntimeLoadedLib : public SomeLibrary { @@ -34,4 +33,3 @@ struct RealLibraryFactory : public LibraryFactory { }; RealLibraryFactory testRealFactory; - diff --git a/test_unit/testing_helpers.cpp b/test_unit/testing_helpers.cpp index acb1ae6..c886a87 100644 --- a/test_unit/testing_helpers.cpp +++ b/test_unit/testing_helpers.cpp @@ -6,17 +6,15 @@ * For more information see g3log/LICENSE or refer refer to http://unlicense.org * ============================================================================*/ - #include -#include #include +#include #include "testing_helpers.h" - #include -#include #include +#include using namespace std; using namespace g3; @@ -27,7 +25,7 @@ namespace testing_helpers { int g_mockFatal_signal = -1; bool g_mockFatalWasCalled = false; const size_t kFlushToDiskWithThisInterval = 2; - + std::string mockFatalMessage() { return g_mockFatal_message; } @@ -45,7 +43,7 @@ namespace testing_helpers { g_mockFatal_signal = fatal_message.get()->_signal_id; g_mockFatalWasCalled = true; LogMessagePtr message{fatal_message.release()}; - g3::internal::pushMessageToLogger(message); //fatal_message.copyToLogMessage()); + g3::internal::pushMessageToLogger(message); //fatal_message.copyToLogMessage()); } void clearMockFatal() { @@ -58,7 +56,7 @@ namespace testing_helpers { return (0 == std::remove(path_to_file.c_str())); } - bool verifyContent(const std::string &total_text, std::string msg_to_find) { + bool verifyContent(const std::string& total_text, std::string msg_to_find) { std::string content(total_text); size_t location = content.find(msg_to_find); return (location != std::string::npos); @@ -68,9 +66,7 @@ namespace testing_helpers { std::ifstream in; in.open(filename.c_str(), std::ios_base::in); if (!in.is_open()) { - return - { - }; // error just return empty string - test will 'fault' + return {}; // error just return empty string - test will 'fault' } std::ostringstream oss; oss << in.rdbuf(); @@ -82,7 +78,6 @@ namespace testing_helpers { return logs_to_clean_.size(); } - LogFileCleaner::~LogFileCleaner() { std::lock_guard lock(g_mutex); { @@ -92,7 +87,7 @@ namespace testing_helpers { } } logs_to_clean_.clear(); - } // mutex + } // mutex } void LogFileCleaner::addLogToClean(std::string path_to_log) { @@ -103,23 +98,25 @@ namespace testing_helpers { } } - ScopedLogger::ScopedLogger() : _currentWorker(g3::LogWorker::createLogWorker()) {} + ScopedLogger::ScopedLogger() : + _currentWorker(g3::LogWorker::createLogWorker()) {} ScopedLogger::~ScopedLogger() {} g3::LogWorker* ScopedLogger::get() { return _currentWorker.get(); } - RestoreFileLogger::RestoreFileLogger(std::string directory) - : _scope(new ScopedLogger), _handle(_scope->get()->addSink(std::make_unique("UNIT_TEST_LOGGER", - directory, "g3log", kFlushToDiskWithThisInterval), &g3::FileSink::fileWrite)) { + RestoreFileLogger::RestoreFileLogger(std::string directory) : + _scope(new ScopedLogger), + _handle(_scope->get()->addSink(std::make_unique("UNIT_TEST_LOGGER", directory, "g3log", kFlushToDiskWithThisInterval), &g3::FileSink::fileWrite)) { using namespace g3; g3::initializeLogging(_scope->_currentWorker.get()); clearMockFatal(); setFatalExitHandler(&mockFatalCall); auto filename = _handle->call(&FileSink::fileName); - if (!filename.valid()) ADD_FAILURE(); + if (!filename.valid()) + ADD_FAILURE(); _log_file = filename.get(); #ifdef G3_DYNAMIC_LOGGING @@ -131,18 +128,18 @@ namespace testing_helpers { } RestoreFileLogger::~RestoreFileLogger() { - g3::internal::shutDownLogging(); // is done at reset. Added for test clarity + g3::internal::shutDownLogging(); // is done at reset. Added for test clarity reset(); if (!removeFile(_log_file)) - ADD_FAILURE(); + ADD_FAILURE(); } std::string RestoreFileLogger::logFile() { if (_scope) { // beware for race condition - // example: - // LOG(INFO) << ... + // example: + // LOG(INFO) << ... // auto file = logger.logFile() // auto content = ReadContentFromFile(file) // ... it is not guaranteed that the content will contain (yet) the LOG(INFO) @@ -152,14 +149,14 @@ namespace testing_helpers { return _log_file; } - // Beware of race between LOG(...) and this function. - // since LOG(...) passes two queues but the handle::call only passes one queue + // Beware of race between LOG(...) and this function. + // since LOG(...) passes two queues but the handle::call only passes one queue // the handle::call can happen faster std::string RestoreFileLogger::resetAndRetrieveContent() { std::future filename = _handle->call(&g3::FileSink::fileName); - reset(); // flush all queues to sinks + reset(); // flush all queues to sinks EXPECT_TRUE(filename.valid()); auto file = filename.get(); return readFileToText(file); } -} // testing_helpers +} // namespace testing_helpers