-
Notifications
You must be signed in to change notification settings - Fork 272
/
testing_helpers.cpp
162 lines (136 loc) · 5.22 KB
/
testing_helpers.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/** ==========================================================================
* 2013 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.
*
* For more information see g3log/LICENSE or refer refer to http://unlicense.org
* ============================================================================*/
#include <g3log/g3log.hpp>
#include <g3log/logmessage.hpp>
#include <g3log/logworker.hpp>
#include "testing_helpers.h"
#include <gtest/gtest.h>
#include <fstream>
#include <iostream>
using namespace std;
using namespace g3;
namespace testing_helpers {
std::string g_mockFatal_message = {};
int g_mockFatal_signal = -1;
bool g_mockFatalWasCalled = false;
const size_t kFlushToDiskWithThisInterval = 2;
std::string mockFatalMessage() {
return g_mockFatal_message;
}
int mockFatalSignal() {
return g_mockFatal_signal;
}
bool mockFatalWasCalled() {
return g_mockFatalWasCalled;
}
void mockFatalCall(FatalMessagePtr fatal_message) {
g_mockFatal_message = fatal_message.get()->toString();
g_mockFatal_signal = fatal_message.get()->_signal_id;
g_mockFatalWasCalled = true;
LogMessagePtr message{fatal_message.release()};
g3::internal::pushMessageToLogger(message); //fatal_message.copyToLogMessage());
}
void clearMockFatal() {
g_mockFatal_message.clear();
g_mockFatal_signal = -1;
g_mockFatalWasCalled = false;
}
bool removeFile(std::string path_to_file) {
return (0 == std::remove(path_to_file.c_str()));
}
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::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();
return oss.str();
// RAII of std::ifstream will automatically close the file
}
size_t LogFileCleaner::size() {
return logs_to_clean_.size();
}
LogFileCleaner::~LogFileCleaner() {
std::lock_guard<std::mutex> lock(g_mutex);
{
for (const auto& file : logs_to_clean_) {
if (!removeFile(file)) {
ADD_FAILURE() << "UNABLE to remove: " << file << 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);
}
}
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<g3::FileSink>("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();
_log_file = filename.get();
#ifdef G3_DYNAMIC_LOGGING
g3::only_change_at_initialization::addLogLevel(INFO, true);
g3::only_change_at_initialization::addLogLevel(G3LOG_DEBUG, true);
g3::only_change_at_initialization::addLogLevel(WARNING, true);
g3::only_change_at_initialization::addLogLevel(FATAL, true);
#endif
}
RestoreFileLogger::~RestoreFileLogger() {
g3::internal::shutDownLogging(); // is done at reset. Added for test clarity
reset();
if (!removeFile(_log_file))
ADD_FAILURE();
}
std::string RestoreFileLogger::logFile() {
if (_scope) {
// beware for race condition
// example:
// LOG(INFO) << ...
// auto file = logger.logFile()
// auto content = ReadContentFromFile(file)
// ... it is not guaranteed that the content will contain (yet) the LOG(INFO)
std::future<std::string> filename = _handle->call(&g3::FileSink::fileName);
_log_file = filename.get();
}
return _log_file;
}
// 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<std::string> filename = _handle->call(&g3::FileSink::fileName);
reset(); // flush all queues to sinks
EXPECT_TRUE(filename.valid());
auto file = filename.get();
return readFileToText(file);
}
} // namespace testing_helpers