mirror of
https://github.com/KjellKod/g3log.git
synced 2024-12-12 18:30:25 +01:00
unit test refactoring. g2log, safe to do shutdownlogging multiple times
This commit is contained in:
parent
3e2f092924
commit
c015191b83
@ -77,7 +77,9 @@ IF(UNIX)
|
||||
set(SRC_PLATFORM_SPECIFIC ${LOG_SRC}/crashhandler_unix.cpp)
|
||||
ENDIF(UNIX)
|
||||
|
||||
if (MSVC)
|
||||
|
||||
# Visual Studio 2011 -- std::thread etc are included with the Visual Studio package, so justthread dependencies are removed
|
||||
IF(MSVC)
|
||||
# VC11 bug: http://code.google.com/p/googletest/issues/detail?id=408
|
||||
# add_definition(-D_VARIADIC_MAX=10)
|
||||
# https://github.com/anhstudios/swganh/pull/186/files
|
||||
@ -85,59 +87,32 @@ IF(UNIX)
|
||||
MESSAGE(STATUS "- MSVC: Set variadic max to 10 for MSVC compatibility")
|
||||
# Remember to set set target properties if using GTEST similar to done below on target "unit_test"
|
||||
# "set_target_properties(unit_test PROPERTIES COMPILE_DEFINITIONS "GTEST_USE_OWN_TR1_TUPLE=0")
|
||||
endif ()
|
||||
|
||||
|
||||
#Visual Studio 2010 -- must use justthread. For now hardcoded for x64
|
||||
IF(MSVC10)
|
||||
MESSAGE("")
|
||||
MESSAGE("Windows: Please run the command [cmake -DCMAKE_BUILD_TYPE=Release -G \"Visual Studio 10\" ..]")
|
||||
MESSAGE("if cmake finishes OK, do 'msbuild g2log_by_kjellkod.sln /p:Configuration=Release'")
|
||||
MESSAGE("then run 'Release\\g2log-FATAL-example.exe' or whatever performance test you feel like trying")
|
||||
MESSAGE("")
|
||||
set(PLATFORM_LINK_LIBRIES $ENV{PROGRAMFILES}/JustSoftwareSolutions/JustThread/lib/justthread_vc10_mdd.lib)
|
||||
#set(PLATFORM_LINK_LIBRIES $ENV{PROGRAMFILES}/JustSoftwareSolutions/JustThread/lib/justthread_vc10x64_mdd.lib)
|
||||
set(SRC_PLATFORM_SPECIFIC ${LOG_SRC}/crashhandler_win.cpp)
|
||||
include_directories("$ENV{PROGRAMFILES}/JustSoftwareSolutions/JustThread/include")
|
||||
ENDIF(MSVC10)
|
||||
|
||||
# Visual Studio 2011 -- std::thread etc are included with the Visual Studio package, so justthread dependencies are removed
|
||||
IF(MSVC11)
|
||||
MESSAGE("")
|
||||
MESSAGE("Windows: Please run the command [cmake -DCMAKE_BUILD_TYPE=Release -G \"Visual Studio 11\" ..]")
|
||||
MESSAGE("if cmake finishes OK, do 'msbuild g2log_by_kjellkod.sln /p:Configuration=Release'")
|
||||
MESSAGE("then run 'Release\\g2log-FATAL-example.exe' or whatever performance test you feel like trying")
|
||||
MESSAGE("")
|
||||
set(SRC_PLATFORM_SPECIFIC ${LOG_SRC}/crashhandler_win.cpp)
|
||||
ENDIF(MSVC11)
|
||||
ENDIF(MSVC)
|
||||
|
||||
|
||||
|
||||
|
||||
# GENERIC STEPS
|
||||
set(CPP_H_FILES g2logworker.cpp g2logworker.h
|
||||
g2log.cpp g2log.h g2time.cpp g2time.h
|
||||
g2future.h std2_make_unique.hpp)
|
||||
FOREACH(file ${CPP_H_FILES})
|
||||
set(SRC_FILES ${SRC_FILES} ${LOG_SRC}/${file})
|
||||
ENDFOREACH(file ${CPP_H_FILES})
|
||||
file(GLOB SRC_FILES ${LOG_SRC}/*.h ${LOG_SRC}/*.hpp ${LOG_SRC}/*.cpp )
|
||||
if(MSVC)
|
||||
list(REMOVE_ITEM SRC_FILES ${LOG_SRC}/crashhandler_unix.cpp)
|
||||
else()
|
||||
list(REMOVE_ITEM SRC_FILES ${LOG_SRC}/crashhandler_win.cpp)
|
||||
endif(MSVC)
|
||||
|
||||
set(SRC_FILES ${SRC_FILES} ${SRC_PLATFORM_SPECIFIC})
|
||||
|
||||
#
|
||||
# set(SRC_CPP ${LOG_SRC}/g2logworker.cpp ${LOG_SRC}/g2log.cpp ${LOG_SRC}/g2time.cpp)
|
||||
# set(SRC_H ${LOG_SRC}/g2logworker.h ${LOG_SRC}/g2log.h ${LOG_SRC}/crashhandler.h ${LOG_SRC}/g2time.h ${LOG_SRC}/g2future.h ${LOG_SRC}/std2_make_unique.hpp)
|
||||
# set(SRC_FILES ${SRC_CPP} ${SRC_H} ${SRC_PLATFORM_SPECIFIC})
|
||||
|
||||
|
||||
# add a ActiveObject library
|
||||
add_library(lib_activeobject ${LOG_SRC}/active.cpp ${LOG_SRC}/active.h ${LOG_SRC}/shared_queue.h)
|
||||
set_target_properties(lib_activeobject PROPERTIES LINKER_LANGUAGE CXX)
|
||||
|
||||
|
||||
# add a g2log library
|
||||
include_directories(src)
|
||||
# Create the g2log library
|
||||
include_directories(${LOG_SRC})
|
||||
MESSAGE(" g2logger files: [${SRC_FILES}]")
|
||||
add_library(lib_g2logger ${SRC_FILES})
|
||||
set_target_properties(lib_g2logger PROPERTIES LINKER_LANGUAGE CXX)
|
||||
target_link_libraries(lib_g2logger lib_activeobject)
|
||||
|
||||
|
||||
|
||||
@ -152,21 +127,19 @@ ENDIF(MSVC11)
|
||||
# before it can be "cmake'd" and compiled --- leaving it as OFF for now
|
||||
# ============================================================================
|
||||
# 1. a simple test example 'g2log-FATAL-example'
|
||||
option (USE_SIMPLE_EXAMPLE
|
||||
"Create simple binaries that runs a few LOG calls" ON)
|
||||
|
||||
option (USE_SIMPLE_EXAMPLE "Simple (fatal-crash) example " ON)
|
||||
|
||||
# 2. performance test (average + worst case) for KjellKod's g2log
|
||||
option (USE_G2LOG_PERFORMANCE
|
||||
"Create performance tests for g2log" OFF)
|
||||
option (USE_G2LOG_PERFORMANCE "g2log performance test" OFF)
|
||||
|
||||
# 3. performance test for Google's glog
|
||||
option (USE_GOOGLE_GLOG_PERFORMANCE
|
||||
"Create performance tests for Google's glog (remember to install glog, snapshot available at g2log/3rdParty/glog)" ON)
|
||||
# remember to install glog, snapshot available at g2log/3rdParty/glog
|
||||
option (USE_GOOGLE_GLOG_PERFORMANCE "Google's glog performance test" OFF)
|
||||
|
||||
|
||||
# 4. unit test for g2log
|
||||
option (USE_G2LOG_UNIT_TEST
|
||||
"Create unit test for g2log (remember to unzip Google's gtest framework, available at g2log/3rdParty/gtest)" ON)
|
||||
# remember to unzip gtest at g2log/3rdParty/gtest
|
||||
option (USE_G2LOG_UNIT_TEST "g2log unit tests" ON)
|
||||
|
||||
|
||||
|
||||
@ -182,7 +155,7 @@ ENDIF(MSVC11)
|
||||
MESSAGE(" g2log-FATAL-example option ON")
|
||||
include_directories (${DIR_EXAMPLE})
|
||||
add_executable(g2log-FATAL-example ${DIR_EXAMPLE}/main.cpp)
|
||||
target_link_libraries(g2log-FATAL-example lib_activeobject lib_g2logger ${PLATFORM_LINK_LIBRIES})
|
||||
target_link_libraries(g2log-FATAL-example lib_g2logger ${PLATFORM_LINK_LIBRIES})
|
||||
endif (USE_SIMPLE_EXAMPLE)
|
||||
|
||||
|
||||
@ -197,13 +170,13 @@ ENDIF(MSVC11)
|
||||
${DIR_PERFORMANCE}/main_threaded_mean.cpp ${DIR_PERFORMANCE}/performance.h)
|
||||
# Turn on G2LOG performance flag
|
||||
set_target_properties(g2log-performance-threaded_mean PROPERTIES COMPILE_DEFINITIONS "G2LOG_PERFORMANCE=1")
|
||||
target_link_libraries(g2log-performance-threaded_mean lib_activeobject lib_g2logger ${PLATFORM_LINK_LIBRIES})
|
||||
target_link_libraries(g2log-performance-threaded_mean lib_g2logger ${PLATFORM_LINK_LIBRIES})
|
||||
|
||||
# WORST CASE PERFORMANCE TEST
|
||||
add_executable(g2log-performance-threaded_worst ${DIR_PERFORMANCE}/main_threaded_worst.cpp ${DIR_PERFORMANCE}/performance.h)
|
||||
# Turn on G2LOG performance flag
|
||||
set_target_properties(g2log-performance-threaded_worst PROPERTIES COMPILE_DEFINITIONS "G2LOG_PERFORMANCE=1")
|
||||
target_link_libraries(g2log-performance-threaded_worst lib_activeobject lib_g2logger ${PLATFORM_LINK_LIBRIES})
|
||||
target_link_libraries(g2log-performance-threaded_worst lib_g2logger ${PLATFORM_LINK_LIBRIES})
|
||||
endif (USE_G2LOG_PERFORMANCE)
|
||||
|
||||
|
||||
@ -219,12 +192,12 @@ ENDIF(MSVC11)
|
||||
# create the the GOOGLE MEAN_PERFORMANCE executable
|
||||
add_executable(google_glog-performance-threaded_mean ${DIR_PERFORMANCE}/main_threaded_mean.cpp ${DIR_PERFORMANCE}/performance.h)
|
||||
set_target_properties(google_glog-performance-threaded_mean PROPERTIES COMPILE_DEFINITIONS "GOOGLE_GLOG_PERFORMANCE=1")
|
||||
target_link_libraries(google_glog-performance-threaded_mean lib_activeobject ${GLOG_LIB} ${PLATFORM_LINK_LIBRIES})
|
||||
target_link_libraries(google_glog-performance-threaded_mean ${GLOG_LIB} ${PLATFORM_LINK_LIBRIES})
|
||||
|
||||
# create the the GOOGLE MEAN_PERFORMANCE executable
|
||||
add_executable(google_glog-performance-threaded_worst ${DIR_PERFORMANCE}/main_threaded_worst.cpp ${DIR_PERFORMANCE}/performance.h)
|
||||
set_target_properties(google_glog-performance-threaded_worst PROPERTIES COMPILE_DEFINITIONS "GOOGLE_GLOG_PERFORMANCE=1")
|
||||
target_link_libraries(google_glog-performance-threaded_worst lib_activeobject ${GLOG_LIB} ${PLATFORM_LINK_LIBRIES})
|
||||
target_link_libraries(google_glog-performance-threaded_worst ${GLOG_LIB} ${PLATFORM_LINK_LIBRIES})
|
||||
endif(UNIX)
|
||||
|
||||
# GLOG on Linux is easy - but for Windows trickier,. and it doesn't work (as of yet)
|
||||
@ -234,8 +207,6 @@ ENDIF(MSVC11)
|
||||
MESSAGE("*** You have to do this yourself: ref CMakeLists.txt")
|
||||
MESSAGE("******************************************************")
|
||||
MESSAGE("")
|
||||
#set(GLOG_DIR ../3rdParty/glog/glog-0.3.1)
|
||||
#include_directories(${GLOG_DIR}/src/windows)
|
||||
endif(WIN32)
|
||||
endif (USE_GOOGLE_GLOG_PERFORMANCE)
|
||||
|
||||
@ -244,7 +215,6 @@ ENDIF(MSVC11)
|
||||
# =========================
|
||||
if (USE_G2LOG_UNIT_TEST)
|
||||
MESSAGE(" g2log unit testing option ON")
|
||||
# SETUP for GTEST
|
||||
set(GTEST_DIR ../3rdParty/gtest/gtest-1.6.0__stripped)
|
||||
set(GTEST_INCLUDE_DIRECTORIES ${GTEST_DIR}/include ${GTEST_DIR} ${GTEST_DIR}/src)
|
||||
include_directories(${GTEST_INCLUDE_DIRECTORIES})
|
||||
@ -255,29 +225,38 @@ ENDIF(MSVC11)
|
||||
# and this: http://stackoverflow.com/questions/2257464/google-test-and-visual-studio-2010-rc
|
||||
|
||||
|
||||
|
||||
SET(tests_to_run test_filechange test_io test_configuration test_sink)
|
||||
SET(helper ${DIR_UNIT_TEST}/testing_helpers.h ${DIR_UNIT_TEST}/testing_helpers.cpp)
|
||||
include_directories(${DIR_UNIT_TEST})
|
||||
|
||||
FOREACH(test ${tests_to_run} )
|
||||
# SET(all_tests ${all_tests} ${DIR_UNIT_TEST}/${test}.cpp )
|
||||
SET(all_tests ${all_tests} ${DIR_UNIT_TEST}/${test}.cpp )
|
||||
IF(${test} STREQUAL "test_filechange")
|
||||
add_executable(${test} ${DIR_UNIT_TEST}/${test}.cpp)
|
||||
add_executable(${test} ${DIR_UNIT_TEST}/${test}.cpp ${helper})
|
||||
ELSE()
|
||||
add_executable(${test} ../test_main/test_main.cpp ${DIR_UNIT_TEST}/${test}.cpp ${helper})
|
||||
ENDIF(${test} STREQUAL "test_filechange")
|
||||
|
||||
set_target_properties(${test} PROPERTIES COMPILE_DEFINITIONS "_VARIADIC_MAX=10")
|
||||
set_target_properties(${test} PROPERTIES COMPILE_DEFINITIONS "GTEST_USE_OWN_TR1_TUPLE=0")
|
||||
target_link_libraries(${test} lib_activeobject lib_g2logger gtest_160_lib ${PLATFORM_LINK_LIBRIES})
|
||||
target_link_libraries(${test} lib_g2logger gtest_160_lib ${PLATFORM_LINK_LIBRIES})
|
||||
ENDFOREACH(test)
|
||||
|
||||
add_executable(test_ALL ${all_tests} ${DIR_UNIT_TEST}/test_filechange.cpp ${helper})
|
||||
set_target_properties(test_ALL PROPERTIES COMPILE_DEFINITIONS "_VARIADIC_MAX=10")
|
||||
set_target_properties(test_ALL PROPERTIES COMPILE_DEFINITIONS "GTEST_USE_OWN_TR1_TUPLE=0")
|
||||
target_link_libraries(test_ALL lib_g2logger gtest_160_lib ${PLATFORM_LINK_LIBRIES})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# add_executable(test_ALL ${all_tests})
|
||||
#
|
||||
# set_target_properties(${test_ALL} PROPERTIES COMPILE_DEFINITIONS "_VARIADIC_MAX=10")
|
||||
# set_target_properties(${test_ALL} PROPERTIES COMPILE_DEFINITIONS "GTEST_USE_OWN_TR1_TUPLE=0")
|
||||
# target_link_libraries(${test_ALL} lib_activeobject lib_g2logger gtest_160_lib ${PLATFORM_LINK_LIBRIES})
|
||||
# target_link_libraries(${test_ALL} lib_g2logger gtest_160_lib ${PLATFORM_LINK_LIBRIES})
|
||||
|
||||
endif (USE_G2LOG_UNIT_TEST)
|
||||
|
||||
|
@ -74,10 +74,9 @@ void initializeLogging(g2LogWorker *bgworker)
|
||||
}
|
||||
}
|
||||
|
||||
g2LogWorker* shutDownLogging()
|
||||
g2LogWorker* shutDownLogging() // safe to call multiple times
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(internal::g_logging_init_mutex);
|
||||
CHECK(internal::isLoggingInitialized());
|
||||
g2LogWorker *backup = internal::g_logger_instance;
|
||||
internal::g_logger_instance = nullptr;
|
||||
return backup;
|
||||
|
@ -1,8 +1,8 @@
|
||||
/** ==========================================================================
|
||||
* 2012 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
|
||||
* with no warranties. This code is yours to share, use and modify with no
|
||||
* strings attached and no restrictions or obligations.
|
||||
* ============================================================================*/
|
||||
* 2012 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
|
||||
* with no warranties. This code is yours to share, use and modify with no
|
||||
* strings attached and no restrictions or obligations.
|
||||
* ============================================================================*/
|
||||
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
@ -12,103 +12,64 @@
|
||||
#include <memory>
|
||||
#include <future>
|
||||
#include <queue>
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
|
||||
|
||||
#include <thread>
|
||||
#include "g2log.h"
|
||||
#include "g2logworker.h"
|
||||
#include "testing_helpers.h"
|
||||
|
||||
using namespace testing_helper__cleaner;
|
||||
|
||||
|
||||
namespace { // anonymous
|
||||
const char* name_path_1 = "./some_fake_DirectoryOrName_1_";
|
||||
const char* name_path_2 = "./some_fake_DirectoryOrName_3_";
|
||||
|
||||
g2LogWorker* g_logger_ptr = nullptr;
|
||||
const char* name_path_1 = "./some_fake_DirectoryOrName_1_";
|
||||
const char* name_path_2 = "./some_fake_DirectoryOrName_3_";
|
||||
g2LogWorker* g_logger_ptr = nullptr;
|
||||
LogFileCleaner* g_cleaner_ptr = nullptr;
|
||||
|
||||
|
||||
bool isTextAvailableInContent(const std::string &total_text,std::string msg_to_find)
|
||||
{
|
||||
|
||||
bool isTextAvailableInContent(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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string readFileToText(std::string filename)
|
||||
{
|
||||
std::string readFileToText(std::string filename) {
|
||||
std::ifstream in;
|
||||
in.open(filename.c_str(),std::ios_base::in);
|
||||
if(!in.is_open())
|
||||
{
|
||||
in.open(filename.c_str(), std::ios_base::in);
|
||||
if (!in.is_open()) {
|
||||
return ""; // error just return empty string - test will 'fault'
|
||||
}
|
||||
std::ostringstream oss;
|
||||
oss << in.rdbuf();
|
||||
std::string content(oss.str());
|
||||
return content;
|
||||
}
|
||||
|
||||
bool removeFile(std::string path_to_file)
|
||||
{
|
||||
return (0 == std::remove(path_to_file.c_str()));
|
||||
}
|
||||
|
||||
class LogFileCleaner // RAII cluttering files cleanup
|
||||
{
|
||||
private:
|
||||
std::vector<std::string> logs_to_clean_;
|
||||
std::mutex g_mutex;
|
||||
public:
|
||||
size_t size(){return logs_to_clean_.size();}
|
||||
virtual ~LogFileCleaner() {
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
{
|
||||
for (std::string p : logs_to_clean_)
|
||||
{
|
||||
if(false == removeFile(p))
|
||||
{
|
||||
ADD_FAILURE() << "UNABLE to remove: " << p.c_str() << std::endl;
|
||||
}
|
||||
}
|
||||
logs_to_clean_.clear();
|
||||
} // mutex
|
||||
}
|
||||
|
||||
void addLogToClean(std::string path_to_log) {
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
{
|
||||
if (std::find(logs_to_clean_.begin(), logs_to_clean_.end(), path_to_log.c_str()) == logs_to_clean_.end())
|
||||
logs_to_clean_.push_back(path_to_log);
|
||||
}
|
||||
}
|
||||
}; LogFileCleaner* g_cleaner_ptr = nullptr;
|
||||
|
||||
std::string changeDirectoryOrName(std::string new_file_to_create)
|
||||
{
|
||||
std::string changeDirectoryOrName(std::string new_file_to_create) {
|
||||
static std::mutex m;
|
||||
static int count;
|
||||
std::lock_guard<std::mutex> lock(m);
|
||||
{
|
||||
std::string add_count = std::to_string(++count) + "_";
|
||||
auto new_log = g_logger_ptr->changeLogFile(new_file_to_create+add_count).get();
|
||||
if(!new_log.empty()) g_cleaner_ptr->addLogToClean(new_log);
|
||||
auto new_log = g_logger_ptr->changeLogFile(new_file_to_create + add_count).get();
|
||||
if (!new_log.empty()) g_cleaner_ptr->addLogToClean(new_log);
|
||||
return new_log;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // anonymous
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// TODO: this must change. Initialization of this is done here! and not in a special test_main.cpp
|
||||
// which MAY be OK ... however it is also very redundant with test_io
|
||||
|
||||
|
||||
|
||||
TEST(TestOf_GetFileName, Expecting_ValidLogFile)
|
||||
{
|
||||
TEST(TestOf_GetFileName, Expecting_ValidLogFile) {
|
||||
|
||||
LOG(INFO) << "test_filechange, Retrieving file name: ";
|
||||
ASSERT_NE(g_logger_ptr, nullptr);
|
||||
@ -117,41 +78,32 @@ TEST(TestOf_GetFileName, Expecting_ValidLogFile)
|
||||
ASSERT_FALSE(f_get_old_name.get().empty());
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST(TestOf_ChangingLogFile, Expecting_NewLogFileUsed)
|
||||
{
|
||||
TEST(TestOf_ChangingLogFile, Expecting_NewLogFileUsed) {
|
||||
auto old_log = g_logger_ptr->logFileName().get();
|
||||
std::string name = changeDirectoryOrName(name_path_1);
|
||||
auto new_log = g_logger_ptr->changeLogFile(name).get();
|
||||
}
|
||||
|
||||
|
||||
TEST(TestOf_ManyThreadsChangingLogFileName, Expecting_EqualNumberLogsCreated)
|
||||
{
|
||||
TEST(TestOf_ManyThreadsChangingLogFileName, Expecting_EqualNumberLogsCreated) {
|
||||
auto old_log = g_logger_ptr->logFileName().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<std::thread> threads;
|
||||
auto max = 2;
|
||||
auto size = g_cleaner_ptr->size();
|
||||
for(auto count = 0; count < max; ++count)
|
||||
{
|
||||
for (auto count = 0; count < max; ++count) {
|
||||
std::string drive = ((count % 2) == 0) ? "./_threadEven_" : "./_threaOdd_";
|
||||
threads.push_back(std::thread(changeDirectoryOrName, drive));
|
||||
}
|
||||
for(auto& thread : threads)
|
||||
for (auto& thread : threads)
|
||||
thread.join();
|
||||
|
||||
// check that all logs were created
|
||||
ASSERT_EQ(size+max, g_cleaner_ptr->size());
|
||||
ASSERT_EQ(size + max, g_cleaner_ptr->size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST(TestOf_IllegalLogFileName, Expecting_NoChangeToOriginalFileName)
|
||||
{
|
||||
TEST(TestOf_IllegalLogFileName, Expecting_NoChangeToOriginalFileName) {
|
||||
std::string original = g_logger_ptr->logFileName().get();
|
||||
std::cerr << "Below WILL print 'FiLE ERROR'. This is part of the testing and perfectly OK" << std::endl;
|
||||
std::cerr << "****" << std::endl;
|
||||
@ -162,11 +114,7 @@ TEST(TestOf_IllegalLogFileName, Expecting_NoChangeToOriginalFileName)
|
||||
ASSERT_STREQ(original.c_str(), post_illegal.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int main(int argc, char *argv[]) {
|
||||
LogFileCleaner cleaner;
|
||||
g_cleaner_ptr = &cleaner;
|
||||
int return_value = 1;
|
||||
@ -180,7 +128,7 @@ int main(int argc, char *argv[])
|
||||
cleaner.addLogToClean(g_logger_ptr->logFileName().get());
|
||||
return_value = RUN_ALL_TESTS();
|
||||
last_log_file = g_logger_ptr->logFileName().get();
|
||||
g2::shutDownLogging();
|
||||
//g2::shutDownLogging();
|
||||
}
|
||||
std::cout << "FINISHED WITH THE TESTING" << std::endl;
|
||||
// cleaning up
|
||||
|
@ -1,8 +1,8 @@
|
||||
/** ==========================================================================
|
||||
* 2011 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
|
||||
* with no warranties. This code is yours to share, use and modify with no
|
||||
* strings attached and no restrictions or obligations.
|
||||
* ============================================================================*/
|
||||
* 2011 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
|
||||
* with no warranties. This code is yours to share, use and modify with no
|
||||
* strings attached and no restrictions or obligations.
|
||||
* ============================================================================*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "g2log.h"
|
||||
@ -13,26 +13,23 @@
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <cstdio>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
const int k_wait_time = 5; // 5s wait between LOG/CHECK FATAL till we say it's too long time
|
||||
const std::string log_directory = "./";
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
std::string readFileToText(std::string filename)
|
||||
{
|
||||
std::string readFileToText(std::string filename) {
|
||||
std::ifstream in;
|
||||
in.open(filename.c_str(),std::ios_base::in);
|
||||
if(!in.is_open())
|
||||
{
|
||||
in.open(filename.c_str(), std::ios_base::in);
|
||||
if (!in.is_open()) {
|
||||
return ""; // error just return empty string - test will 'fault'
|
||||
}
|
||||
std::ostringstream oss;
|
||||
@ -49,8 +46,15 @@ namespace
|
||||
|
||||
|
||||
// LOG
|
||||
TEST(LOGTest, LOG)
|
||||
TEST(IO_RestoreLogger, Expecting_Fine_To_ShutDownMultipleTimes)
|
||||
{
|
||||
RestoreLogger logger1("");
|
||||
std::this_thread::sleep_for( std::chrono::milliseconds(1000));
|
||||
RestoreLogger logger2("./");
|
||||
}
|
||||
|
||||
|
||||
TEST(LOGTest, LOG) {
|
||||
std::string file_content;
|
||||
{
|
||||
RestoreLogger logger(log_directory);
|
||||
@ -73,8 +77,8 @@ namespace {
|
||||
}
|
||||
|
||||
// printf-type log
|
||||
TEST(LogTest, LOG_F)
|
||||
{
|
||||
|
||||
TEST(LogTest, LOG_F) {
|
||||
std::string file_content;
|
||||
{
|
||||
RestoreLogger logger(log_directory);
|
||||
@ -96,8 +100,8 @@ TEST(LogTest, LOG_F)
|
||||
|
||||
|
||||
// stream-type log
|
||||
TEST(LogTest, LOG)
|
||||
{
|
||||
|
||||
TEST(LogTest, LOG) {
|
||||
std::string file_content;
|
||||
{
|
||||
RestoreLogger logger(log_directory);
|
||||
@ -113,9 +117,7 @@ TEST(LogTest, LOG)
|
||||
ASSERT_TRUE(verifyContent(file_content, t_warning2));
|
||||
}
|
||||
|
||||
|
||||
TEST(LogTest, LOG_F_IF)
|
||||
{
|
||||
TEST(LogTest, LOG_F_IF) {
|
||||
std::string file_content;
|
||||
{
|
||||
RestoreLogger logger(log_directory);
|
||||
@ -129,8 +131,7 @@ TEST(LogTest, LOG_F_IF)
|
||||
ASSERT_FALSE(verifyContent(file_content, t_debug2));
|
||||
}
|
||||
|
||||
TEST(LogTest, LOG_IF)
|
||||
{
|
||||
TEST(LogTest, LOG_IF) {
|
||||
std::string file_content;
|
||||
{
|
||||
RestoreLogger logger(log_directory);
|
||||
@ -144,125 +145,90 @@ TEST(LogTest, LOG_IF)
|
||||
ASSERT_FALSE(verifyContent(file_content, t_debug2));
|
||||
}
|
||||
|
||||
TEST(LogTest, LOGF__FATAL)
|
||||
{
|
||||
TEST(LogTest, LOGF__FATAL) {
|
||||
RestoreLogger logger(log_directory);
|
||||
try
|
||||
{
|
||||
LOGF(FATAL, "This message should throw %d",0);
|
||||
}
|
||||
catch (std::exception const &e)
|
||||
{
|
||||
try {
|
||||
LOGF(FATAL, "This message should throw %d", 0);
|
||||
} catch (std::exception const &e) {
|
||||
logger.reset();
|
||||
std::string file_content = readFileToText(logger.logFile());
|
||||
std::cerr << file_content << std::endl << std::flush;
|
||||
if(verifyContent(e.what(), "EXIT trigger caused by ") &&
|
||||
if (verifyContent(e.what(), "EXIT trigger caused by ") &&
|
||||
verifyContent(file_content, "FATAL") &&
|
||||
verifyContent(file_content, "This message should throw"))
|
||||
{
|
||||
verifyContent(file_content, "This message should throw")) {
|
||||
SUCCEED();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
ADD_FAILURE() << "Didn't throw exception as expected";
|
||||
}
|
||||
}
|
||||
ADD_FAILURE() << "Didn't throw exception at ALL";
|
||||
}
|
||||
|
||||
|
||||
TEST(LogTest, LOG_FATAL)
|
||||
{
|
||||
TEST(LogTest, LOG_FATAL) {
|
||||
RestoreLogger logger(log_directory);
|
||||
try
|
||||
{
|
||||
try {
|
||||
LOG(FATAL) << "This message should throw";
|
||||
}
|
||||
catch (std::exception const &e)
|
||||
{
|
||||
} catch (std::exception const &e) {
|
||||
logger.reset();
|
||||
std::string file_content = readFileToText(logger.logFile());
|
||||
if(verifyContent(e.what(), "EXIT trigger caused by ") &&
|
||||
if (verifyContent(e.what(), "EXIT trigger caused by ") &&
|
||||
verifyContent(file_content, "FATAL") &&
|
||||
verifyContent(file_content, "This message should throw"))
|
||||
{
|
||||
verifyContent(file_content, "This message should throw")) {
|
||||
SUCCEED();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
ADD_FAILURE() << "Didn't throw exception as expected";
|
||||
}
|
||||
}
|
||||
ADD_FAILURE() << "Didn't throw exception at ALL";
|
||||
}
|
||||
|
||||
|
||||
TEST(LogTest, LOGF_IF__FATAL)
|
||||
{
|
||||
TEST(LogTest, LOGF_IF__FATAL) {
|
||||
RestoreLogger logger(log_directory);
|
||||
try
|
||||
{
|
||||
LOGF_IF(FATAL, (2<3), "This message%sshould throw"," ");
|
||||
}
|
||||
catch (std::exception const &e)
|
||||
{
|
||||
try {
|
||||
LOGF_IF(FATAL, (2 < 3), "This message%sshould throw", " ");
|
||||
} catch (std::exception const &e) {
|
||||
logger.reset();
|
||||
std::string file_content = readFileToText(logger.logFile());
|
||||
if(verifyContent(e.what(), "EXIT trigger caused by ") &&
|
||||
if (verifyContent(e.what(), "EXIT trigger caused by ") &&
|
||||
verifyContent(file_content, "FATAL") &&
|
||||
verifyContent(file_content, "This message should throw"))
|
||||
{
|
||||
verifyContent(file_content, "This message should throw")) {
|
||||
SUCCEED();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
ADD_FAILURE() << "Didn't throw exception as expected";
|
||||
}
|
||||
}
|
||||
ADD_FAILURE() << "Didn't throw exception at ALL";
|
||||
}
|
||||
|
||||
|
||||
TEST(LogTest, LOG_IF__FATAL)
|
||||
{
|
||||
TEST(LogTest, LOG_IF__FATAL) {
|
||||
RestoreLogger logger(log_directory);
|
||||
try
|
||||
{
|
||||
try {
|
||||
LOG_IF(WARNING, (0 != t_info.compare(t_info))) << "This message should NOT be written";
|
||||
LOG_IF(FATAL, (0 != t_info.compare(t_info2))) << "This message should throw";
|
||||
}
|
||||
catch (std::exception const &e)
|
||||
{
|
||||
} catch (std::exception const &e) {
|
||||
logger.reset();
|
||||
std::string file_content = readFileToText(logger.logFile());
|
||||
if(verifyContent(e.what(), "EXIT trigger caused by ") &&
|
||||
if (verifyContent(e.what(), "EXIT trigger caused by ") &&
|
||||
verifyContent(file_content, "FATAL") &&
|
||||
verifyContent(file_content, "This message should throw") &&
|
||||
(false == verifyContent(file_content, "This message should NOT be written")))
|
||||
{
|
||||
(false == verifyContent(file_content, "This message should NOT be written"))) {
|
||||
SUCCEED();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
ADD_FAILURE() << "Didn't throw exception as expected";
|
||||
}
|
||||
}
|
||||
ADD_FAILURE() << "Didn't throw exception at ALL";
|
||||
}
|
||||
|
||||
TEST(LogTest, LOG_IF__FATAL__NO_THROW)
|
||||
{
|
||||
TEST(LogTest, LOG_IF__FATAL__NO_THROW) {
|
||||
RestoreLogger logger(log_directory);
|
||||
try
|
||||
{
|
||||
LOG_IF(FATAL, (2>3)) << "This message%sshould NOT throw";
|
||||
}
|
||||
catch (std::exception const &e)
|
||||
{
|
||||
try {
|
||||
LOG_IF(FATAL, (2 > 3)) << "This message%sshould NOT throw";
|
||||
} catch (std::exception const &e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
logger.reset();
|
||||
ADD_FAILURE() << "Didn't throw exception as expected";
|
||||
@ -273,20 +239,16 @@ TEST(LogTest, LOG_IF__FATAL__NO_THROW)
|
||||
|
||||
|
||||
// CHECK_F
|
||||
TEST(CheckTest, CHECK_F__thisWILL_PrintErrorMsg)
|
||||
{
|
||||
|
||||
TEST(CheckTest, CHECK_F__thisWILL_PrintErrorMsg) {
|
||||
RestoreLogger logger(log_directory);
|
||||
try
|
||||
{
|
||||
try {
|
||||
CHECK(1 == 2);
|
||||
}
|
||||
catch (std::exception const &e)
|
||||
{
|
||||
} catch (std::exception const &e) {
|
||||
logger.reset();
|
||||
std::string file_content = readFileToText(logger.logFile());
|
||||
if(verifyContent(e.what(), "EXIT trigger caused by ") &&
|
||||
verifyContent(file_content, "FATAL"))
|
||||
{
|
||||
if (verifyContent(e.what(), "EXIT trigger caused by ") &&
|
||||
verifyContent(file_content, "FATAL")) {
|
||||
SUCCEED();
|
||||
return;
|
||||
}
|
||||
@ -294,26 +256,20 @@ TEST(CheckTest, CHECK_F__thisWILL_PrintErrorMsg)
|
||||
ADD_FAILURE() << "Didn't throw exception as expected";
|
||||
}
|
||||
|
||||
|
||||
TEST(CHECK_F_Test, CHECK_F__thisWILL_PrintErrorMsg)
|
||||
{
|
||||
TEST(CHECK_F_Test, CHECK_F__thisWILL_PrintErrorMsg) {
|
||||
RestoreLogger logger(log_directory);
|
||||
std::string msg = "This message is added to throw %s and %s";
|
||||
std::string msg2 = "This message is added to throw message and log";
|
||||
std::string arg1 = "message";
|
||||
std::string arg2 = "log";
|
||||
try
|
||||
{
|
||||
try {
|
||||
CHECK_F(1 >= 2, msg.c_str(), arg1.c_str(), arg2.c_str());
|
||||
}
|
||||
catch (std::exception const &e)
|
||||
{
|
||||
} catch (std::exception const &e) {
|
||||
logger.reset();
|
||||
std::string file_content = readFileToText(logger.logFile());
|
||||
if(verifyContent(e.what(), "EXIT trigger caused by ") &&
|
||||
if (verifyContent(e.what(), "EXIT trigger caused by ") &&
|
||||
verifyContent(file_content, "FATAL") &&
|
||||
verifyContent(file_content, msg2))
|
||||
{
|
||||
verifyContent(file_content, msg2)) {
|
||||
SUCCEED();
|
||||
return;
|
||||
}
|
||||
@ -321,25 +277,20 @@ TEST(CHECK_F_Test, CHECK_F__thisWILL_PrintErrorMsg)
|
||||
ADD_FAILURE() << "Didn't throw exception as expected";
|
||||
}
|
||||
|
||||
TEST(CHECK_Test, CHECK__thisWILL_PrintErrorMsg)
|
||||
{
|
||||
TEST(CHECK_Test, CHECK__thisWILL_PrintErrorMsg) {
|
||||
RestoreLogger logger(log_directory);
|
||||
std::string msg = "This message is added to throw %s and %s";
|
||||
std::string msg2 = "This message is added to throw message and log";
|
||||
std::string arg1 = "message";
|
||||
std::string arg2 = "log";
|
||||
try
|
||||
{
|
||||
try {
|
||||
CHECK(1 >= 2) << msg2;
|
||||
}
|
||||
catch (std::exception const &e)
|
||||
{
|
||||
} catch (std::exception const &e) {
|
||||
logger.reset();
|
||||
std::string file_content = readFileToText(logger.logFile());
|
||||
if(verifyContent(e.what(), "EXIT trigger caused by ") &&
|
||||
if (verifyContent(e.what(), "EXIT trigger caused by ") &&
|
||||
verifyContent(file_content, "FATAL") &&
|
||||
verifyContent(file_content, msg2))
|
||||
{
|
||||
verifyContent(file_content, msg2)) {
|
||||
SUCCEED();
|
||||
return;
|
||||
}
|
||||
@ -347,21 +298,16 @@ TEST(CHECK_Test, CHECK__thisWILL_PrintErrorMsg)
|
||||
ADD_FAILURE() << "Didn't throw exception as expected";
|
||||
}
|
||||
|
||||
|
||||
TEST(CHECK, CHECK_ThatWontThrow)
|
||||
{
|
||||
TEST(CHECK, CHECK_ThatWontThrow) {
|
||||
RestoreLogger logger(log_directory);
|
||||
std::string msg = "This %s should never appear in the %s";
|
||||
std::string msg2 = "This message should never appear in the log";
|
||||
std::string arg1 = "message";
|
||||
std::string arg2 = "log";
|
||||
try
|
||||
{
|
||||
try {
|
||||
CHECK(1 == 1);
|
||||
CHECK_F(1==1, msg.c_str(), "message", "log");
|
||||
}
|
||||
catch (std::exception const &e)
|
||||
{
|
||||
CHECK_F(1 == 1, msg.c_str(), "message", "log");
|
||||
} catch (std::exception const &e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
ADD_FAILURE() << "Should never have thrown";
|
||||
}
|
||||
|
@ -3,18 +3,26 @@
|
||||
#include "testing_helpers.h"
|
||||
#include "g2log.h"
|
||||
#include "g2logworker.h"
|
||||
#include "std2_make_unique.hpp"
|
||||
|
||||
using namespace std;
|
||||
namespace {
|
||||
g2LogWorker* oldworker = nullptr;
|
||||
}
|
||||
|
||||
ScopedCout::ScopedCout(std::stringstream* buffer)
|
||||
: _old_cout(std::cout.rdbuf()) {
|
||||
cout.rdbuf(buffer->rdbuf());
|
||||
}
|
||||
|
||||
ScopedCout::~ScopedCout() { cout.rdbuf(_old_cout);}
|
||||
ScopedCout::~ScopedCout() {
|
||||
cout.rdbuf(_old_cout);
|
||||
}
|
||||
|
||||
RestoreLogger::RestoreLogger(std::string directory)
|
||||
: logger_(new g2LogWorker("UNIT_TEST_LOGGER", directory)) {
|
||||
: logger_(std2::make_unique<g2LogWorker>("UNIT_TEST_LOGGER", directory)) {
|
||||
|
||||
oldworker = g2::shutDownLogging();
|
||||
g2::initializeLogging(logger_.get());
|
||||
g2::internal::changeFatalInitHandlerForUnitTesting();
|
||||
|
||||
@ -26,6 +34,7 @@ RestoreLogger::RestoreLogger(std::string directory)
|
||||
RestoreLogger::~RestoreLogger() {
|
||||
reset();
|
||||
g2::shutDownLogging();
|
||||
if (nullptr != oldworker) g2::initializeLogging(oldworker);
|
||||
if (0 != remove(log_file_.c_str()))
|
||||
ADD_FAILURE();
|
||||
}
|
||||
@ -33,3 +42,38 @@ RestoreLogger::~RestoreLogger() {
|
||||
void RestoreLogger::reset() {
|
||||
logger_.reset();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace testing_helper__cleaner {
|
||||
|
||||
bool removeFile(std::string path_to_file) {
|
||||
return (0 == std::remove(path_to_file.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
size_t LogFileCleaner::size() {
|
||||
return logs_to_clean_.size();
|
||||
}
|
||||
|
||||
LogFileCleaner::~LogFileCleaner() {
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
{
|
||||
for (std::string p : logs_to_clean_) {
|
||||
if (false == testing_helper__cleaner::removeFile(p)) {
|
||||
ADD_FAILURE() << "UNABLE to remove: " << p.c_str() << std::endl;
|
||||
}
|
||||
}
|
||||
logs_to_clean_.clear();
|
||||
} // mutex
|
||||
}
|
||||
|
||||
void LogFileCleaner::addLogToClean(std::string path_to_log) {
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
{
|
||||
if (std::find(logs_to_clean_.begin(), logs_to_clean_.end(), path_to_log.c_str()) == logs_to_clean_.end())
|
||||
logs_to_clean_.push_back(path_to_log);
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <algorithm>
|
||||
class g2LogWorker;
|
||||
|
||||
|
||||
@ -20,30 +22,54 @@ class g2LogWorker;
|
||||
// ScopedCout guard(&buffer);
|
||||
// cout << "Hello World";
|
||||
// ASSERT_STREQ(buffer.str().c_str(), "Hello World");
|
||||
class ScopedCout
|
||||
{
|
||||
|
||||
class ScopedCout {
|
||||
std::streambuf* _old_cout;
|
||||
public:
|
||||
public:
|
||||
explicit ScopedCout(std::stringstream* buffer);
|
||||
~ScopedCout();
|
||||
};
|
||||
|
||||
|
||||
namespace testing_helper__cleaner {
|
||||
bool removeFile(std::string path_to_file);
|
||||
}
|
||||
|
||||
class LogFileCleaner // RAII cluttering files cleanup
|
||||
{
|
||||
private:
|
||||
std::vector<std::string> logs_to_clean_;
|
||||
std::mutex g_mutex;
|
||||
public:
|
||||
size_t size();
|
||||
|
||||
LogFileCleaner() {
|
||||
}
|
||||
virtual ~LogFileCleaner();
|
||||
void addLogToClean(std::string path_to_log);
|
||||
};
|
||||
|
||||
|
||||
|
||||
// RAII temporarily replace of logger
|
||||
// and restoration of original logger at scope end
|
||||
struct RestoreLogger
|
||||
{
|
||||
|
||||
struct RestoreLogger {
|
||||
explicit RestoreLogger(std::string directory);
|
||||
~RestoreLogger();
|
||||
void reset();
|
||||
|
||||
std::unique_ptr<g2LogWorker> logger_;
|
||||
std::string logFile(){return log_file_;}
|
||||
|
||||
std::string logFile() {
|
||||
return log_file_;
|
||||
}
|
||||
private:
|
||||
std::string log_file_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* TEST_HELPER__RESTORE_LOGGER_H */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user