#include <gtest/gtest.h>
#include <cstring>
#include <iostream>
#include <fstream>
#include <sstream>
#include <thread>
#include <list>
using std::cout;
using std::endl;
using std::vector;
using std::thread;
using std::string;
using std::stringstream;
using std::ifstream;
using std::ofstream;
using std::shared_ptr;
using std::system_error;
using std::make_shared;
using std::istreambuf_iterator;
using std::set;
struct LoggerTest : public testing::Test
{
shared_ptr<stringstream> strings;
string fname;
shared_ptr<ofstream> files;
Logger log;
string m_curdir;
LoggerTest()
{
system_error err;
fs::remove_all("sandbox", &err);
strings.reset(new stringstream());
fname = "ofstream_test";
files.reset(new ofstream(fname));
log.add_cout();
log.add(strings);
log.add(files);
}
virtual ~LoggerTest()
{
system_error err;
fs::remove_all("sandbox", &err);
}
std::string read_file()
{
ifstream f(fname);
istreambuf_iterator<char> it{f}, end;
string ss{it, end};
return ss;
}
void validate(const string& logs)
{
ASSERT_EQ(strings->str(), logs);
ASSERT_EQ(read_file(), logs);
}
};
TEST(LoggerTestBasic, move_and_construct)
{
stringstream ver;
auto s = make_shared<stringstream>();
Logger log(s);
log.add_cout();
log.add(s);
log << "Original 1" << endl;
ver << "Original 1" << endl;
Logger cc(log);
cc << "Copy constructed" << endl;
ver << "Copy constructed" << endl;
log << "Original 2" << endl;
ver << "Original 2" << endl;
Logger ca = log;
ca << "Copy assigned" << endl;
ver << "Copy assigned" << endl;
log << "Original 3" << endl;
ver << "Original 3" << endl;
Logger mc(std::move(cc));
mc << "Move constructed" << endl;
ver << "Move constructed" << endl;
cc << "Original 4 (won't see this)" << endl;
Logger ma = std::move(ca);
ma << "Move assigned" << endl;
ver << "Move assigned" << endl;
ca << "Original 5 (won't see this)" << endl;
cout << "** start readback from log stringstream" << endl;
cout << s->str();
cout << "** end readback from log stringstream" << endl;
cout << "** start readback from verify stringstream" << endl;
cout << ver.str();
cout << "** end readback from verify stringstream" << endl;
ASSERT_EQ(s->str(), ver.str());
}
TEST_F(LoggerTest, id)
{
log.id("test");
log << "line" << endl;
validate("[test] line\n");
}
TEST_F(LoggerTest, timestamp)
{
log.timestamp_iso();
log << "line" << endl;
ASSERT_EQ(strings->str().size(), 26);
ASSERT_EQ(strings->str().substr(20), " line\n");
}
TEST_F(LoggerTest, multiline)
{
stringstream s;
log.multiline(5);
log.id(1);
log << "m 1" << endl;
s << "[1] m 1" << endl;
log << " m 2" << endl;
s << " m 2" << endl;
log << " m 3" << endl;
s << " m 3" << endl;
log << " m 4" << endl;
s << " m 4" << endl;
log << " m 5" << endl;
s << " m 5" << endl;
log << " m 6" << endl;
s << "[1] m 6" << endl;
validate(s.str());
}
TEST_F(LoggerTest, multithread_multi_loggers)
{
auto f = [&](int n)
{
Logger tlog(strings);
tlog.add(files);
tlog.add_cout();
tlog.id(n);
for (int i = 1; i <= 5; i++)
{
tlog << "this is log number " << i << " from thread number " << n << endl;
}
};
vector<thread> tv;
for (int n = 1; n <= 5; n++)
{
tv.emplace_back(f, n);
}
log.id(0);
for (int i = 1; i <= 5; i++)
{
log << "this is log number " << i << " from thread number " << 0 << endl;
}
for (auto& t : tv)
{
t.join();
}
string line;
set<string> ordered_strings;
while (getline(*strings, line))
{
ordered_strings.insert(line);
}
stringstream
fs(read_file());
set<string> ordered_files;
while (getline(
fs, line))
{
ordered_files.insert(line);
}
cout << "* ordered stringstream" << endl;
for (auto& s : ordered_strings)
{
cout << s << endl;
}
cout << "* ordered filestream" << endl;
for (auto& s : ordered_strings)
{
cout << s << endl;
}
ASSERT_EQ(ordered_strings, ordered_files);
int cur_thread = 0;
int cur_line = 1;
cout << "validate the ordered logs:" << endl;
for (auto& s : ordered_strings)
{
cout << s << endl;
stringstream val;
val << "[" << cur_thread << "] this is log number " << cur_line << " from thread number " << cur_thread;
ASSERT_EQ(val.str(), s);
cur_line++;
if (cur_line > 5)
{
cur_thread++;
cur_line = 1;
}
}
ASSERT_EQ(cur_thread, 6);
ASSERT_EQ(cur_line, 1);
}
Common file system utilities.
static std::string get_current_dir(std::system_error *=nullptr)
Get working directory.
static void change_dir(const std::string &, std::system_error *=nullptr)
Change working directory.
static void create_dir(const std::string &, std::system_error *=nullptr)
Create a directory.
Thread-safe stream logger.
Common file system utilities.
TEST(inet_example, client_server_stream_test)
[Inet client server]