mirror of
https://github.com/KjellKod/g3log.git
synced 2025-03-04 07:27:25 +01:00
commented out some unit test. corrected other's. rigth now I am pondering to
always keeping the file-handle known in the bglogger. --- Alternatively there is no zink at startup except colored out maybe?
This commit is contained in:
parent
3c67023389
commit
05018e389a
@ -99,7 +99,7 @@ ENDIF(MSVC)
|
||||
|
||||
|
||||
# GENERIC STEPS
|
||||
file(GLOB SRC_FILES ${LOG_SRC}/*.h ${LOG_SRC}/*.hpp ${LOG_SRC}/*.cpp )
|
||||
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()
|
||||
|
@ -26,289 +26,73 @@
|
||||
#include "crashhandler.h"
|
||||
#include "g2time.h"
|
||||
#include "g2future.h"
|
||||
#include "g2filesink.h"
|
||||
#include "std2_make_unique.hpp"
|
||||
|
||||
using namespace g2;
|
||||
using namespace g2::internal;
|
||||
|
||||
namespace
|
||||
{
|
||||
static const std::string date_formatted = "%Y/%m/%d";
|
||||
static const std::string time_formatted = "%H:%M:%S";
|
||||
static const std::string file_name_time_formatted = "%Y%m%d-%H%M%S";
|
||||
|
||||
// check for filename validity - filename should not be part of PATH
|
||||
bool isValidFilename(const std::string prefix_filename)
|
||||
{
|
||||
|
||||
std::string illegal_characters("/,|<>:#$%{}()[]\'\"^!?+* ");
|
||||
size_t pos = prefix_filename.find_first_of(illegal_characters,0);
|
||||
if(pos != std::string::npos)
|
||||
{
|
||||
std::cerr << "Illegal character [" << prefix_filename.at(pos) << "] in logname prefix: " << "[" << prefix_filename << "]" << std::endl;
|
||||
return false;
|
||||
}
|
||||
else if (prefix_filename.empty())
|
||||
{
|
||||
std::cerr << "Empty filename prefix is not allowed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Clean up the path if put in by mistake in the prefix
|
||||
std::string prefixSanityFix(std::string prefix)
|
||||
{
|
||||
prefix.erase(std::remove_if(prefix.begin(), prefix.end(), ::isspace), prefix.end());
|
||||
prefix.erase(std::remove( prefix.begin(), prefix.end(), '/'), prefix.end()); // '/'
|
||||
prefix.erase(std::remove( prefix.begin(), prefix.end(), '\\'), prefix.end()); // '\\'
|
||||
prefix.erase(std::remove( prefix.begin(), prefix.end(), '.'), prefix.end()); // '.'
|
||||
if(!isValidFilename(prefix))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return prefix;
|
||||
}
|
||||
|
||||
|
||||
std::string pathSanityFix(std::string path, std::string file_name) {
|
||||
// Unify the delimeters,. maybe sketchy solution but it seems to work
|
||||
// on at least win7 + ubuntu. All bets are off for older windows
|
||||
std::replace(path.begin(), path.end(), '\\', '/');
|
||||
|
||||
// clean up in case of multiples
|
||||
auto contains_end = [&](std::string& in) -> bool {
|
||||
size_t size = in.size();
|
||||
if(!size) return false;
|
||||
char end = in[size-1];
|
||||
return (end == '/' || end == ' ');
|
||||
};
|
||||
|
||||
while(contains_end(path)) { path.erase(path.size()-1); }
|
||||
if(!path.empty()) {
|
||||
path.insert(path.end(), '/');
|
||||
}
|
||||
path.insert(path.size(), file_name);
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
std::string createLogFileName(const std::string& verified_prefix)
|
||||
{
|
||||
std::stringstream oss_name;
|
||||
oss_name.fill('0');
|
||||
oss_name << verified_prefix << ".g2log.";
|
||||
oss_name << g2::localtime_formatted(g2::systemtime_now(), file_name_time_formatted);
|
||||
oss_name << ".log";
|
||||
return oss_name.str();
|
||||
}
|
||||
|
||||
|
||||
bool openLogFile(const std::string& complete_file_with_path, std::ofstream& outstream)
|
||||
{
|
||||
std::ios_base::openmode mode = std::ios_base::out; // for clarity: it's really overkill since it's an ofstream
|
||||
mode |= std::ios_base::trunc;
|
||||
outstream.open(complete_file_with_path, mode);
|
||||
if(!outstream.is_open())
|
||||
{
|
||||
std::ostringstream ss_error;
|
||||
ss_error << "FILE ERROR: could not open log file:[" << complete_file_with_path << "]";
|
||||
ss_error << "\n\t\t std::ios_base state = " << outstream.rdstate();
|
||||
std::cerr << ss_error.str().c_str() << std::endl << std::flush;
|
||||
outstream.close();
|
||||
return false;
|
||||
}
|
||||
std::ostringstream ss_entry;
|
||||
// Day Month Date Time Year: is written as "%a %b %d %H:%M:%S %Y" and formatted output as : Wed Sep 19 08:28:16 2012
|
||||
ss_entry << "\t\tg2log created log file at: "<< g2::localtime_formatted(g2::systemtime_now(), "%a %b %d %H:%M:%S %Y") << "\n";
|
||||
ss_entry << "\t\tLOG format: [YYYY/MM/DD hh:mm:ss.uuu* LEVEL FILE:LINE] message\n\n"; // TODO: if(header)
|
||||
outstream << ss_entry.str() << std::flush;
|
||||
outstream.fill('0');
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<std::ofstream> createLogFile(const std::string& file_with_full_path)
|
||||
{
|
||||
std::unique_ptr<std::ofstream> out(new std::ofstream);
|
||||
std::ofstream& stream(*(out.get()));
|
||||
bool success_with_open_file = openLogFile(file_with_full_path, stream);
|
||||
if(false == success_with_open_file)
|
||||
{
|
||||
out.release(); // nullptr contained ptr<file> signals error in creating the log file
|
||||
}
|
||||
return out;
|
||||
}
|
||||
} // end anonymous namespace
|
||||
|
||||
|
||||
/** The Real McCoy Background worker, while g2LogWorker gives the
|
||||
* asynchronous API to put job in the background the g2LogWorkerImpl
|
||||
* does the actual background thread work */
|
||||
struct g2LogWorkerImpl
|
||||
{
|
||||
g2LogWorkerImpl(const std::string& log_prefix, const std::string& log_directory);
|
||||
~g2LogWorkerImpl();
|
||||
|
||||
void backgroundFileWrite(g2::internal::LogEntry message);
|
||||
void backgroundExitFatal(g2::internal::FatalMessage fatal_message);
|
||||
std::string backgroundChangeLogFile(const std::string& directory);
|
||||
std::string backgroundFileName();
|
||||
|
||||
std::string log_file_with_path_;
|
||||
std::string log_prefix_backup_; // needed in case of future log file changes of directory
|
||||
std::unique_ptr<kjellkod::Active> bg_;
|
||||
std::unique_ptr<std::ofstream> outptr_;
|
||||
steady_time_point steady_start_time_;
|
||||
|
||||
private:
|
||||
g2LogWorkerImpl& operator=(const g2LogWorkerImpl&); // c++11 feature not yet in vs2010 = delete;
|
||||
g2LogWorkerImpl(const g2LogWorkerImpl& other); // c++11 feature not yet in vs2010 = delete;
|
||||
std::ofstream& filestream(){return *(outptr_.get());}
|
||||
typedef std::shared_ptr<g2::internal::SinkWrapper> SinkWrapperPtr;
|
||||
|
||||
g2LogWorkerImpl(){}
|
||||
~g2LogWorkerImpl(){ _bg.reset(); _sinks.clear(); }
|
||||
|
||||
std::unique_ptr<kjellkod::Active> _bg;
|
||||
std::vector<SinkWrapperPtr> _sinks;
|
||||
std::shared_ptr<g2::SinkHandle<g2FileSink>> _default_sink_handle;
|
||||
void bgSave(g2::internal::LogEntry msg) {
|
||||
for(auto& sink : _sinks) {
|
||||
sink->send(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void bgFatal(g2::internal::FatalMessage fatal_message){
|
||||
auto entry = fatal_message.message_;
|
||||
bgSave(entry);
|
||||
_sinks.clear(); // flush all queues
|
||||
exitWithDefaultSignalHandler(fatal_message.signal_id_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Private API implementation : g2LogWorkerImpl
|
||||
g2LogWorkerImpl::g2LogWorkerImpl(const std::string& log_prefix, const std::string& log_directory)
|
||||
: log_file_with_path_(log_directory)
|
||||
, log_prefix_backup_(log_prefix)
|
||||
, bg_(kjellkod::Active::createActive())
|
||||
, outptr_(new std::ofstream)
|
||||
, steady_start_time_(std::chrono::steady_clock::now()) // TODO: ha en timer function steadyTimer som har koll på start
|
||||
{
|
||||
log_prefix_backup_ = prefixSanityFix(log_prefix);
|
||||
if(!isValidFilename(log_prefix_backup_))
|
||||
{
|
||||
// illegal prefix, refuse to start
|
||||
std::cerr << "g2log: forced abort due to illegal log prefix [" << log_prefix <<"]" << std::endl << std::flush;
|
||||
abort();
|
||||
}
|
||||
|
||||
std::string file_name = createLogFileName(log_prefix_backup_);
|
||||
log_file_with_path_ = pathSanityFix(log_file_with_path_, file_name);
|
||||
outptr_ = createLogFile(log_file_with_path_);
|
||||
if(!outptr_) {
|
||||
std::cerr << "Cannot write logfile to location, attempting current directory" << std::endl;
|
||||
log_file_with_path_ = file_name;
|
||||
outptr_ = createLogFile(log_file_with_path_);
|
||||
}
|
||||
assert((outptr_) && "cannot open log file at startup");
|
||||
}
|
||||
|
||||
|
||||
g2LogWorkerImpl::~g2LogWorkerImpl()
|
||||
{
|
||||
std::ostringstream ss_exit;
|
||||
bg_.reset(); // flush the log queue
|
||||
ss_exit << "\n\t\tg2log file shutdown at: " << g2::localtime_formatted(g2::systemtime_now(), time_formatted);
|
||||
filestream() << ss_exit.str() << std::flush;
|
||||
}
|
||||
|
||||
|
||||
void g2LogWorkerImpl::backgroundFileWrite(LogEntry message)
|
||||
{
|
||||
using namespace std;
|
||||
std::ofstream& out(filestream());
|
||||
auto system_time = g2::systemtime_now();
|
||||
auto steady_time = std::chrono::steady_clock::now();
|
||||
out << "\n" << g2::localtime_formatted(system_time, date_formatted);
|
||||
out << " " << g2::localtime_formatted(system_time, time_formatted); // TODO: time kommer från LogEntry
|
||||
out << "." << chrono::duration_cast<std::chrono::microseconds>(steady_time - steady_start_time_).count(); //microseconds TODO: ta in min g2clocka här StopWatch
|
||||
out << "\t" << message << std::flush;
|
||||
}
|
||||
|
||||
|
||||
void g2LogWorkerImpl::backgroundExitFatal(FatalMessage fatal_message)
|
||||
{
|
||||
backgroundFileWrite(fatal_message.message_);
|
||||
backgroundFileWrite("Log flushed successfully to disk \nExiting");
|
||||
std::cerr << "g2log exiting after receiving fatal event" << std::endl;
|
||||
std::cerr << "Log file at: [" << log_file_with_path_ << "]\n" << std::endl << std::flush;
|
||||
filestream().close();
|
||||
exitWithDefaultSignalHandler(fatal_message.signal_id_);
|
||||
perror("g2log exited after receiving FATAL trigger. Flush message status: "); // should never reach this point
|
||||
}
|
||||
|
||||
|
||||
std::string g2LogWorkerImpl::backgroundChangeLogFile(const std::string& directory)
|
||||
{
|
||||
std::string file_name = createLogFileName(log_prefix_backup_);
|
||||
std::string prospect_log = directory + file_name;
|
||||
std::unique_ptr<std::ofstream> log_stream = createLogFile(prospect_log);
|
||||
if(nullptr == log_stream)
|
||||
{
|
||||
backgroundFileWrite("Unable to change log file. Illegal filename or busy? Unsuccessful log name was:" + prospect_log);
|
||||
return ""; // no success
|
||||
}
|
||||
|
||||
std::ostringstream ss_change;
|
||||
ss_change << "\n\tChanging log file from : " << log_file_with_path_;
|
||||
ss_change << "\n\tto new location: " << prospect_log << "\n";
|
||||
backgroundFileWrite(ss_change.str().c_str());
|
||||
ss_change.str("");
|
||||
|
||||
// setting the new log as active
|
||||
std::string old_log = log_file_with_path_;
|
||||
log_file_with_path_ = prospect_log;
|
||||
outptr_ = std::move(log_stream);
|
||||
ss_change << "\n\tNew log file. The previous log file was at: ";
|
||||
ss_change << old_log;
|
||||
backgroundFileWrite(ss_change.str());
|
||||
return log_file_with_path_;
|
||||
}
|
||||
|
||||
std::string g2LogWorkerImpl::backgroundFileName()
|
||||
{
|
||||
return log_file_with_path_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// ***** BELOW g2LogWorker *****
|
||||
// Public API implementation
|
||||
//
|
||||
// Default constructor will have one sink: g2filesink.
|
||||
g2LogWorker::g2LogWorker(const std::string& log_prefix, const std::string& log_directory)
|
||||
: pimpl_(new g2LogWorkerImpl(log_prefix, log_directory))
|
||||
, log_file_with_path_(pimpl_->log_file_with_path_)
|
||||
{
|
||||
assert((pimpl_ != nullptr) && "shouild never happen");
|
||||
}
|
||||
: _pimpl(std2::make_unique<g2LogWorkerImpl>())
|
||||
{
|
||||
// auto unique = std::unique_ptr<g2FileSink>(new g2FileSink(log_prefix, log_directory));
|
||||
// auto handle = addSink<g2FileSink>(std::move(unique), &g2FileSink::writeToFile);
|
||||
// _pimpl._file_handle.reset(handle.release());
|
||||
}
|
||||
|
||||
g2LogWorker::~g2LogWorker()
|
||||
{
|
||||
pimpl_.reset();
|
||||
std::cerr << "\nExiting, log location: " << log_file_with_path_ << std::endl << std::flush;
|
||||
_pimpl.reset();
|
||||
}
|
||||
|
||||
void g2LogWorker::save(g2::internal::LogEntry msg)
|
||||
{
|
||||
pimpl_->bg_->send(std::bind(&g2LogWorkerImpl::backgroundFileWrite, pimpl_.get(), msg));
|
||||
_pimpl->_bg->send([this, msg]{ _pimpl->bgSave(msg); });
|
||||
//std::bind(&g2LogWorkerImpl::backgroundFileWrite, _pimpl.get(), msg));
|
||||
}
|
||||
|
||||
void g2LogWorker::fatal(g2::internal::FatalMessage fatal_message)
|
||||
{
|
||||
pimpl_->bg_->send(std::bind(&g2LogWorkerImpl::backgroundExitFatal, pimpl_.get(), fatal_message));
|
||||
_pimpl->_bg->send([this, fatal_message]{ _pimpl->bgFatal(fatal_message); });
|
||||
//std::bind(&g2LogWorkerImpl::backgroundExitFatal, _pimpl.get(), fatal_message));
|
||||
}
|
||||
|
||||
|
||||
std::future<std::string> g2LogWorker::changeLogFile(const std::string& log_directory)
|
||||
{
|
||||
kjellkod::Active* bgWorker = pimpl_->bg_.get();
|
||||
//auto future_result = g2::spawn_task(std::bind(&g2LogWorkerImpl::backgroundChangeLogFile, pimpl_.get(), log_directory), bgWorker);
|
||||
auto bg_call = [this, log_directory]() {return pimpl_->backgroundChangeLogFile(log_directory);};
|
||||
auto future_result = g2::spawn_task(bg_call, bgWorker);
|
||||
return std::move(future_result);
|
||||
void g2LogWorker::addWrappedSink(std::shared_ptr<g2::internal::SinkWrapper> sink) {
|
||||
auto bg_addsink_call = [this, sink] { _pimpl->_sinks.push_back(sink); };
|
||||
auto token_done = g2::spawn_task(bg_addsink_call, _pimpl->_bg.get());
|
||||
token_done.wait();
|
||||
}
|
||||
|
||||
std::future<std::string> g2LogWorker::logFileName()
|
||||
{
|
||||
kjellkod::Active* bgWorker = pimpl_->bg_.get();
|
||||
auto bg_call=[&](){return pimpl_->backgroundFileName();};
|
||||
auto future_result = g2::spawn_task(bg_call ,bgWorker);
|
||||
return std::move(future_result);
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<g2::SinkHandle<g2FileSink>> g2LogWorker::getFileSinkHandle()
|
||||
{
|
||||
return _pimpl->_default_sink_handle;
|
||||
}
|
@ -15,10 +15,15 @@
|
||||
#include <memory>
|
||||
#include <future>
|
||||
#include <string>
|
||||
#include "std2_make_unique.hpp"
|
||||
|
||||
#include "g2log.h"
|
||||
#include "g2sinkwrapper.h"
|
||||
#include "g2sinkhandle.h"
|
||||
|
||||
|
||||
struct g2LogWorkerImpl;
|
||||
struct g2FileSink;
|
||||
|
||||
/**
|
||||
* \param log_prefix is the 'name' of the binary, this give the log name 'LOG-'name'-...
|
||||
@ -37,18 +42,33 @@ public:
|
||||
/// Will abort the application!
|
||||
void fatal(g2::internal::FatalMessage fatal_message);
|
||||
|
||||
template<typename T, typename DefaultLogCall>
|
||||
std::unique_ptr<g2::SinkHandle<T>> addSink(std::unique_ptr<T> real_sink, DefaultLogCall call)
|
||||
{
|
||||
using namespace g2;
|
||||
using namespace g2::internal;
|
||||
auto shared_sink = std::shared_ptr<T>(real_sink.release());
|
||||
auto sink = std::make_shared<Sink<T>>(shared_sink, call);
|
||||
auto add_result = addWrappedSink(sink);
|
||||
return std2::make_unique<SinkHandle<T>>(sink);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// DEPRECATED - SHOULD BE Called through a sink handler instead
|
||||
/// Attempt to change the current log file to another name/location.
|
||||
/// returns filename with full path if successful, else empty string
|
||||
std::future<std::string> changeLogFile(const std::string& log_directory);
|
||||
|
||||
//std::future<std::string> changeLogFile(const std::string& log_directory);
|
||||
/// Probably only needed for unit-testing or specific log management post logging
|
||||
/// request to get log name is processed in FIFO order just like any other background job.
|
||||
std::future<std::string> logFileName();
|
||||
//std::future<std::string> logFileName();
|
||||
std::shared_ptr<g2::SinkHandle<g2FileSink>> getFileSinkHandle();
|
||||
|
||||
private:
|
||||
std::unique_ptr<g2LogWorkerImpl> pimpl_;
|
||||
const std::string log_file_with_path_;
|
||||
void addWrappedSink(std::shared_ptr<g2::internal::SinkWrapper> wrapper);
|
||||
|
||||
std::unique_ptr<g2LogWorkerImpl> _pimpl;
|
||||
|
||||
g2LogWorker(const g2LogWorker&); // c++11 feature not yet in vs2010 = delete;
|
||||
g2LogWorker& operator=(const g2LogWorker&); // c++11 feature not yet in vs2010 = delete;
|
||||
|
@ -15,6 +15,9 @@
|
||||
* auto an_int_array = make_unique<int[]>(11, 22, 33);
|
||||
* ********************************************* */
|
||||
|
||||
#ifndef STD2_MAKE_UNIQUE_HPP_
|
||||
#define STD2_MAKE_UNIQUE_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
@ -42,5 +45,5 @@ namespace std2 {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,137 +1,137 @@
|
||||
/** ==========================================================================
|
||||
* 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>
|
||||
#include <memory>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <future>
|
||||
#include <queue>
|
||||
|
||||
|
||||
#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;
|
||||
LogFileCleaner* g_cleaner_ptr = nullptr;
|
||||
|
||||
|
||||
|
||||
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::ifstream in;
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
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) {
|
||||
|
||||
LOG(INFO) << "test_filechange, Retrieving file name: ";
|
||||
ASSERT_NE(g_logger_ptr, nullptr);
|
||||
std::future<std::string> f_get_old_name = g_logger_ptr->logFileName();
|
||||
ASSERT_TRUE(f_get_old_name.valid());
|
||||
ASSERT_FALSE(f_get_old_name.get().empty());
|
||||
}
|
||||
|
||||
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) {
|
||||
auto old_log = g_logger_ptr->logFileName().get();
|
||||
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) {
|
||||
std::string drive = ((count % 2) == 0) ? "./_threadEven_" : "./_threaOdd_";
|
||||
threads.push_back(std::thread(changeDirectoryOrName, drive));
|
||||
}
|
||||
for (auto& thread : threads)
|
||||
thread.join();
|
||||
|
||||
// check that all logs were created
|
||||
ASSERT_EQ(size + max, g_cleaner_ptr->size());
|
||||
}
|
||||
|
||||
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;
|
||||
std::future<std::string> perhaps_a_name = g_logger_ptr->changeLogFile("XY:/"); // does not exist
|
||||
ASSERT_TRUE(perhaps_a_name.get().empty());
|
||||
std::cerr << "****" << std::endl;
|
||||
std::string post_illegal = g_logger_ptr->logFileName().get();
|
||||
ASSERT_STREQ(original.c_str(), post_illegal.c_str());
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
LogFileCleaner cleaner;
|
||||
g_cleaner_ptr = &cleaner;
|
||||
int return_value = 1;
|
||||
|
||||
std::string last_log_file;
|
||||
{
|
||||
g2LogWorker logger("ReplaceLogFile", name_path_2);
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
g_logger_ptr = &logger; // ugly but fine for this test
|
||||
g2::initializeLogging(g_logger_ptr);
|
||||
cleaner.addLogToClean(g_logger_ptr->logFileName().get());
|
||||
return_value = RUN_ALL_TESTS();
|
||||
last_log_file = g_logger_ptr->logFileName().get();
|
||||
//g2::shutDownLogging();
|
||||
}
|
||||
std::cout << "FINISHED WITH THE TESTING" << std::endl;
|
||||
// cleaning up
|
||||
cleaner.addLogToClean(last_log_file);
|
||||
return return_value;
|
||||
}
|
||||
///** ==========================================================================
|
||||
// * 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>
|
||||
//#include <memory>
|
||||
//#include <fstream>
|
||||
//#include <string>
|
||||
//#include <memory>
|
||||
//#include <future>
|
||||
//#include <queue>
|
||||
//
|
||||
//
|
||||
//#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;
|
||||
// LogFileCleaner* g_cleaner_ptr = nullptr;
|
||||
//
|
||||
//
|
||||
//
|
||||
// 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::ifstream in;
|
||||
// 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;
|
||||
// }
|
||||
//
|
||||
// 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);
|
||||
// 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) {
|
||||
//
|
||||
// LOG(INFO) << "test_filechange, Retrieving file name: ";
|
||||
// ASSERT_NE(g_logger_ptr, nullptr);
|
||||
// std::future<std::string> f_get_old_name = g_logger_ptr->logFileName();
|
||||
// ASSERT_TRUE(f_get_old_name.valid());
|
||||
// ASSERT_FALSE(f_get_old_name.get().empty());
|
||||
//}
|
||||
//
|
||||
//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) {
|
||||
// auto old_log = g_logger_ptr->logFileName().get();
|
||||
// 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) {
|
||||
// std::string drive = ((count % 2) == 0) ? "./_threadEven_" : "./_threaOdd_";
|
||||
// threads.push_back(std::thread(changeDirectoryOrName, drive));
|
||||
// }
|
||||
// for (auto& thread : threads)
|
||||
// thread.join();
|
||||
//
|
||||
// // check that all logs were created
|
||||
// ASSERT_EQ(size + max, g_cleaner_ptr->size());
|
||||
//}
|
||||
//
|
||||
//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;
|
||||
// std::future<std::string> perhaps_a_name = g_logger_ptr->changeLogFile("XY:/"); // does not exist
|
||||
// ASSERT_TRUE(perhaps_a_name.get().empty());
|
||||
// std::cerr << "****" << std::endl;
|
||||
// std::string post_illegal = g_logger_ptr->logFileName().get();
|
||||
// ASSERT_STREQ(original.c_str(), post_illegal.c_str());
|
||||
//}
|
||||
//
|
||||
//int main(int argc, char *argv[]) {
|
||||
// LogFileCleaner cleaner;
|
||||
// g_cleaner_ptr = &cleaner;
|
||||
// int return_value = 1;
|
||||
//
|
||||
// std::string last_log_file;
|
||||
// {
|
||||
// g2LogWorker logger("ReplaceLogFile", name_path_2);
|
||||
// testing::InitGoogleTest(&argc, argv);
|
||||
// g_logger_ptr = &logger; // ugly but fine for this test
|
||||
// g2::initializeLogging(g_logger_ptr);
|
||||
// cleaner.addLogToClean(g_logger_ptr->logFileName().get());
|
||||
// return_value = RUN_ALL_TESTS();
|
||||
// last_log_file = g_logger_ptr->logFileName().get();
|
||||
// //g2::shutDownLogging();
|
||||
// }
|
||||
// std::cout << "FINISHED WITH THE TESTING" << std::endl;
|
||||
// // cleaning up
|
||||
// cleaner.addLogToClean(last_log_file);
|
||||
// return return_value;
|
||||
//}
|
||||
|
@ -121,9 +121,13 @@ namespace g2 {
|
||||
auto h1 = worker.addSink(CoutSink::createSink(), &CoutSink::save);
|
||||
auto h2 = worker.addSink(std2::make_unique<StringSink>(), &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());
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "testing_helpers.h"
|
||||
#include "g2log.h"
|
||||
#include "g2logworker.h"
|
||||
#include "g2filesink.h"
|
||||
#include "std2_make_unique.hpp"
|
||||
|
||||
using namespace std;
|
||||
@ -25,8 +26,9 @@ RestoreLogger::RestoreLogger(std::string directory)
|
||||
oldworker = g2::shutDownLogging();
|
||||
g2::initializeLogging(logger_.get());
|
||||
g2::internal::changeFatalInitHandlerForUnitTesting();
|
||||
|
||||
std::future<std::string> filename(logger_->logFileName());
|
||||
|
||||
auto filehandler = logger_->getFileSinkHandle();
|
||||
auto filename = filehandler->call(&g2FileSink::logFileName);
|
||||
if (!filename.valid()) ADD_FAILURE();
|
||||
log_file_ = filename.get();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user