GEODE-8929: fix 'leaked disk space' issue in logger (#743)
- Logger wasn't calculating the size of existing files when
initializing. Thus the disk usage could grow by up to the space limit
set by the app at each iteration (run).
- Added new test to start/stop logger several times and verify we're
never exceeding disk space limits in toto.
- passing nullptr for file name to Log::Init() wasn't writing to a
default file, now it writes to 'geode-native.log' in CWD.
- logging test for (#) in filename wasn't cleaning up its log file
- added test code to clean up any default-named log files
- Run all unit tests with "test" filename, and with default filename
(geode-native.log)
- Add specific case to check for "leaked" disk space when specifying
nullptr to get the default file name.
diff --git a/cppcache/src/Log.cpp b/cppcache/src/Log.cpp
index aaf71b9..d6d431c 100644
--- a/cppcache/src/Log.cpp
+++ b/cppcache/src/Log.cpp
@@ -105,8 +105,8 @@
void Log::init(LogLevel level, const char* logFileName, int32_t logFileLimit,
int64_t logDiskSpaceLimit) {
auto logFileNameString =
- logFileName ? std::string(logFileName) : std::string();
- init(level, std::string(logFileNameString), logFileLimit, logDiskSpaceLimit);
+ logFileName ? std::string(logFileName) : std::string("geode-native.log");
+ init(level, logFileNameString, logFileLimit, logDiskSpaceLimit);
}
void Log::rollLogFile() {
@@ -138,6 +138,19 @@
boost::filesystem::remove(fileToRemove);
g_rollFiles.erase(index);
g_spaceUsed -= fileSize;
+ } else {
+ throw IllegalStateException(
+ "Failed to free sufficient disk space for logs");
+ }
+}
+
+void Log::calculateUsedDiskSpace() {
+ g_spaceUsed = 0;
+ if (boost::filesystem::exists(g_fullpath)) {
+ g_spaceUsed = boost::filesystem::file_size(g_fullpath);
+ for (auto const& item : g_rollFiles) {
+ g_spaceUsed += boost::filesystem::file_size(item.second);
+ }
}
}
@@ -231,6 +244,10 @@
buildRollFileMapping();
setRollFileIndex();
+ calculateUsedDiskSpace();
+ while (g_spaceUsed > g_diskSpaceLimit) {
+ removeOldestRolledLogFile();
+ }
if (boost::filesystem::exists(g_fullpath) && logFileLimit > 0) {
rollLogFile();
@@ -239,8 +256,9 @@
} catch (const boost::exception&) {
auto msg = std::string("Unable to log to file '") + logFileName + "'";
throw IllegalArgumentException(msg.c_str());
- } catch (const std::exception&) {
- auto msg = std::string("Unable to log to file '") + logFileName + "'";
+ } catch (const std::exception& ex) {
+ auto msg = std::string("Unable to log to file '") + logFileName +
+ "': " + ex.what();
throw IllegalArgumentException(msg.c_str());
}
}
diff --git a/cppcache/src/util/Log.hpp b/cppcache/src/util/Log.hpp
index ae33fef..b9e17d6 100644
--- a/cppcache/src/util/Log.hpp
+++ b/cppcache/src/util/Log.hpp
@@ -213,6 +213,8 @@
static void setSizeLimits(int32_t logFileLimit, int64_t logDiskSpaceLimit);
static void logInternal(LogLevel level, const std::string& msg);
+
+ static void calculateUsedDiskSpace();
};
} // namespace client
diff --git a/cppcache/test/LoggingTest.cpp b/cppcache/test/LoggingTest.cpp
index ce68ef9..5e62cd5 100644
--- a/cppcache/test/LoggingTest.cpp
+++ b/cppcache/test/LoggingTest.cpp
@@ -44,8 +44,6 @@
const auto LENGTH_OF_BANNER = 16;
-auto testLogFileName = std::string("LoggingTest.log");
-
const char* __1KStringLiteral =
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AA"
@@ -75,32 +73,39 @@
"AA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
+auto testFileNames = {"LoggingTest.log", "geode-native.log"};
+
class LoggingTest : public testing::Test {
void scrubTestLogFiles() {
- // Close logger, just in case
- apache::geode::client::Log::close();
+ for (auto name : testFileNames) {
+ // Close logger, just in case
+ apache::geode::client::Log::close();
- if (boost::filesystem::exists(testLogFileName)) {
- boost::filesystem::remove(testLogFileName);
- }
+ if (boost::filesystem::exists(name)) {
+ boost::filesystem::remove(name);
+ }
- std::map<int32_t, boost::filesystem::path> rolledFiles;
- LoggingTest::findRolledFiles(boost::filesystem::current_path().string(),
- rolledFiles);
- for (auto& item : rolledFiles) {
- boost::filesystem::remove(item.second);
+ std::map<int32_t, boost::filesystem::path> rolledFiles;
+ LoggingTest::findRolledFiles(boost::filesystem::current_path().string(),
+ name, rolledFiles);
+ for (auto& item : rolledFiles) {
+ boost::filesystem::remove(item.second);
+ }
}
}
- virtual void SetUp() { scrubTestLogFiles(); }
+ virtual void SetUp() {
+ // scrubTestLogFiles();
+ }
virtual void TearDown() { scrubTestLogFiles(); }
public:
static void writeRolledLogFile(const boost::filesystem::path& logdir,
- int32_t rollIndex) {
+ const char* filename, int32_t rollIndex) {
+ auto baseName = boost::filesystem::path(filename).stem().string();
auto rolledPath =
- logdir / boost::filesystem::path("LoggingTest-" +
+ logdir / boost::filesystem::path(baseName + "-" +
std::to_string(rollIndex) + ".log");
auto rolledFile = fopen(rolledPath.string().c_str(), "w");
fwrite("Test", 1, 4, rolledFile);
@@ -144,31 +149,33 @@
}
static void verifyLineCountAtLevel(LogLevel level) {
- apache::geode::client::Log::init(level, testLogFileName);
+ for (auto logFilename : testFileNames) {
+ apache::geode::client::Log::init(level, logFilename);
- LOGERROR("Error Message");
- LOGWARN("Warning Message");
- LOGINFO("Info Message");
- LOGCONFIG("Config Message");
- LOGFINE("Fine Message");
- LOGFINER("Finer Message");
- LOGFINEST("Finest Message");
- LOGDEBUG("Debug Message");
+ LOGERROR("Error Message");
+ LOGWARN("Warning Message");
+ LOGINFO("Info Message");
+ LOGCONFIG("Config Message");
+ LOGFINE("Fine Message");
+ LOGFINER("Finer Message");
+ LOGFINEST("Finest Message");
+ LOGDEBUG("Debug Message");
- int lines = LoggingTest::numOfLinesInFile(testLogFileName.c_str());
+ int lines = LoggingTest::numOfLinesInFile(logFilename);
- ASSERT_TRUE(lines == LoggingTest::expectedWithBanner(level));
+ ASSERT_TRUE(lines == LoggingTest::expectedWithBanner(level));
- apache::geode::client::Log::close();
- boost::filesystem::remove(testLogFileName.c_str());
+ apache::geode::client::Log::close();
+ boost::filesystem::remove(logFilename);
+ }
}
static void findRolledFiles(
- const std::string& logFilePath,
+ const std::string& logFilePath, const boost::filesystem::path& filename,
std::map<int32_t, boost::filesystem::path>& rolledFiles) {
const auto basePath =
boost::filesystem::absolute(boost::filesystem::path(logFilePath)) /
- testLogFileName;
+ filename;
const auto filterstring = basePath.stem().string() + "-(\\d+)\\.log$";
const std::regex my_filter(filterstring);
@@ -179,11 +186,11 @@
basePath.parent_path().string());
i != end_itr; ++i) {
if (boost::filesystem::is_regular_file(i->status())) {
- std::string filename = i->path().filename().string();
+ std::string rootFilename = i->path().filename().string();
std::regex testPattern(filterstring);
std::match_results<std::string::const_iterator> testMatches;
- if (std::regex_search(std::string::const_iterator(filename.begin()),
- filename.cend(), testMatches, testPattern)) {
+ if (std::regex_search(std::string::const_iterator(rootFilename.begin()),
+ rootFilename.cend(), testMatches, testPattern)) {
auto index = std::atoi(
std::string(testMatches[1].first, testMatches[1].second).c_str());
rolledFiles[index] = i->path();
@@ -191,6 +198,46 @@
}
}
}
+
+ static size_t calculateUsedDiskSpace(const std::string& logFilePath) {
+ std::map<int32_t, boost::filesystem::path> rolledLogFiles{};
+ findRolledFiles(boost::filesystem::current_path().string(),
+ boost::filesystem::path(logFilePath), rolledLogFiles);
+
+ auto usedSpace = boost::filesystem::file_size(logFilePath);
+ for (auto const& item : rolledLogFiles) {
+ usedSpace += boost::filesystem::file_size(item.second);
+ }
+
+ return usedSpace;
+ }
+
+ void verifyDiskSpaceNotLeakedForFile(const char* filename) {
+ const int NUMBER_OF_ITERATIONS = 4 * __1K__;
+ const int DISK_SPACE_LIMIT = 2 * __1M__;
+
+ std::string logfileName = filename ? filename : "geode-native.log";
+
+ // Start/stop logger several times, make sure it's picking up any/all
+ // existing logs in its disk space calculations.
+ for (auto j = 0; j < 5; j++) {
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Debug, logfileName, 1, 2));
+ for (auto i = 0; i < NUMBER_OF_ITERATIONS; i++) {
+ LOGDEBUG(__1KStringLiteral);
+ }
+ apache::geode::client::Log::close();
+
+ // Original file should still be around
+ ASSERT_TRUE(boost::filesystem::exists(logfileName));
+
+ // We wrote 4x the log file limit, and 2x the disk space limit, so
+ // there should be one 'rolled' file. Its name should be of the form
+ // <base>-n.log, where n is some reasonable number.
+ auto usedSpace = calculateUsedDiskSpace(logfileName);
+ ASSERT_TRUE(usedSpace < DISK_SPACE_LIMIT);
+ }
+ }
};
/**
@@ -198,40 +245,67 @@
* filename, file size limit, and disk space limit
*/
TEST_F(LoggingTest, logInit) {
- // Check all valid levels
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::None, testLogFileName.c_str(), 1, 4));
- apache::geode::client::Log::close();
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Error, testLogFileName.c_str(), 1, 4));
- apache::geode::client::Log::close();
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Warning, testLogFileName.c_str(), 1, 4));
- apache::geode::client::Log::close();
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Info, testLogFileName.c_str(), 1, 4));
- apache::geode::client::Log::close();
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Default, testLogFileName.c_str(), 1, 4));
- apache::geode::client::Log::close();
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Config, testLogFileName.c_str(), 1, 4));
- apache::geode::client::Log::close();
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Fine, testLogFileName.c_str(), 1, 4));
- apache::geode::client::Log::close();
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Finer, testLogFileName.c_str(), 1, 4));
- apache::geode::client::Log::close();
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Finest, testLogFileName.c_str(), 1, 4));
- apache::geode::client::Log::close();
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Debug, testLogFileName.c_str(), 1, 4));
- apache::geode::client::Log::close();
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::All, testLogFileName.c_str(), 1, 4));
- apache::geode::client::Log::close();
+ for (auto logFilename : testFileNames) {
+ // Check all valid levels
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::None, logFilename, 1, 4));
+ apache::geode::client::Log::close();
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Error, logFilename, 1, 4));
+ apache::geode::client::Log::close();
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Warning, logFilename, 1, 4));
+ apache::geode::client::Log::close();
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Info, logFilename, 1, 4));
+ apache::geode::client::Log::close();
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Default, logFilename, 1, 4));
+ apache::geode::client::Log::close();
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Config, logFilename, 1, 4));
+ apache::geode::client::Log::close();
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Fine, logFilename, 1, 4));
+ apache::geode::client::Log::close();
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Finer, logFilename, 1, 4));
+ apache::geode::client::Log::close();
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Finest, logFilename, 1, 4));
+ apache::geode::client::Log::close();
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Debug, logFilename, 1, 4));
+ apache::geode::client::Log::close();
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::All, logFilename, 1, 4));
+ apache::geode::client::Log::close();
+ // Specify a disk space limit smaller than the file size limit
+ ASSERT_THROW(
+ apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Config, logFilename, __1K__, 4),
+ apache::geode::client::IllegalArgumentException);
+
+ // Specify a file size limit above max allowed
+ ASSERT_THROW(
+ apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Config, logFilename, __1G__),
+ apache::geode::client::IllegalArgumentException);
+
+ // Specify a disk space limit above max allowed
+ ASSERT_THROW(
+ apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Config, logFilename, 1, __1G__),
+ apache::geode::client::IllegalArgumentException);
+
+ // Init twice without closing
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::All, logFilename, 1, 4));
+ ASSERT_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::All, logFilename, 1, 4),
+ apache::geode::client::IllegalStateException);
+ apache::geode::client::Log::close();
+ }
// Init with valid filename
ASSERT_NO_THROW(apache::geode::client::Log::init(
@@ -242,6 +316,7 @@
ASSERT_NO_THROW(apache::geode::client::Log::init(
apache::geode::client::LogLevel::Config, "LoggingTest (#).log"));
apache::geode::client::Log::close();
+ boost::filesystem::remove("LoggingTest (#).log");
// Init with invalid filename
ASSERT_THROW(apache::geode::client::Log::init(
@@ -255,263 +330,247 @@
ASSERT_NO_THROW(apache::geode::client::Log::init(
apache::geode::client::LogLevel::Config, nullptr, 0, 4));
apache::geode::client::Log::close();
-
- // Specify a disk space limit smaller than the file size limit
- ASSERT_THROW(
- apache::geode::client::Log::init(apache::geode::client::LogLevel::Config,
- testLogFileName, __1K__, 4),
- apache::geode::client::IllegalArgumentException);
-
- // Specify a file size limit above max allowed
- ASSERT_THROW(
- apache::geode::client::Log::init(apache::geode::client::LogLevel::Config,
- testLogFileName, __1G__),
- apache::geode::client::IllegalArgumentException);
-
- // Specify a disk space limit above max allowed
- ASSERT_THROW(
- apache::geode::client::Log::init(apache::geode::client::LogLevel::Config,
- testLogFileName, 1, __1G__),
- apache::geode::client::IllegalArgumentException);
-
- // Init twice without closing
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::All, testLogFileName.c_str(), 1, 4));
- ASSERT_THROW(
- apache::geode::client::Log::init(apache::geode::client::LogLevel::All,
- testLogFileName.c_str(), 1, 4),
- apache::geode::client::IllegalStateException);
- apache::geode::client::Log::close();
}
TEST_F(LoggingTest, logToFileAtEachLevel) {
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Debug, testLogFileName));
- LOGDEBUG("This is a debug string");
- LOGDEBUG("This is a formatted debug string (%d)", __1K__);
- apache::geode::client::Log::close();
- ASSERT_TRUE(boost::filesystem::exists(testLogFileName));
- ASSERT_TRUE(boost::filesystem::file_size(testLogFileName) > 0);
- boost::filesystem::remove(testLogFileName);
- ASSERT_FALSE(boost::filesystem::exists(testLogFileName));
+ for (auto logFilename : testFileNames) {
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Debug, logFilename));
+ LOGDEBUG("This is a debug string");
+ LOGDEBUG("This is a formatted debug string (%d)", __1K__);
+ apache::geode::client::Log::close();
+ ASSERT_TRUE(boost::filesystem::exists(logFilename));
+ ASSERT_TRUE(boost::filesystem::file_size(logFilename) > 0);
+ boost::filesystem::remove(logFilename);
+ ASSERT_FALSE(boost::filesystem::exists(logFilename));
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Finest, testLogFileName));
- LOGFINEST("This is a 'finest' string");
- LOGFINEST("This is a formatted 'finest' string (%d)", __1K__);
- apache::geode::client::Log::close();
- ASSERT_TRUE(boost::filesystem::exists(testLogFileName));
- ASSERT_TRUE(boost::filesystem::file_size(testLogFileName) > 0);
- boost::filesystem::remove(testLogFileName);
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Finest, logFilename));
+ LOGFINEST("This is a 'finest' string");
+ LOGFINEST("This is a formatted 'finest' string (%d)", __1K__);
+ apache::geode::client::Log::close();
+ ASSERT_TRUE(boost::filesystem::exists(logFilename));
+ ASSERT_TRUE(boost::filesystem::file_size(logFilename) > 0);
+ boost::filesystem::remove(logFilename);
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Finer, testLogFileName));
- LOGFINER("This is a 'finer' string");
- LOGFINER("This is a formatted 'finer' string (%d)", __1K__);
- apache::geode::client::Log::close();
- ASSERT_TRUE(boost::filesystem::exists(testLogFileName));
- ASSERT_TRUE(boost::filesystem::file_size(testLogFileName) > 0);
- boost::filesystem::remove(testLogFileName);
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Finer, logFilename));
+ LOGFINER("This is a 'finer' string");
+ LOGFINER("This is a formatted 'finer' string (%d)", __1K__);
+ apache::geode::client::Log::close();
+ ASSERT_TRUE(boost::filesystem::exists(logFilename));
+ ASSERT_TRUE(boost::filesystem::file_size(logFilename) > 0);
+ boost::filesystem::remove(logFilename);
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Fine, testLogFileName));
- LOGFINE("This is a 'fine' string");
- LOGFINE("This is a formatted 'fine' string (%d)", __1K__);
- apache::geode::client::Log::close();
- ASSERT_TRUE(boost::filesystem::exists(testLogFileName));
- ASSERT_TRUE(boost::filesystem::file_size(testLogFileName) > 0);
- boost::filesystem::remove(testLogFileName);
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Fine, logFilename));
+ LOGFINE("This is a 'fine' string");
+ LOGFINE("This is a formatted 'fine' string (%d)", __1K__);
+ apache::geode::client::Log::close();
+ ASSERT_TRUE(boost::filesystem::exists(logFilename));
+ ASSERT_TRUE(boost::filesystem::file_size(logFilename) > 0);
+ boost::filesystem::remove(logFilename);
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Config, testLogFileName));
- LOGCONFIG("This is a 'config' string");
- LOGCONFIG("This is a formatted 'config' string (%d)", __1K__);
- apache::geode::client::Log::close();
- ASSERT_TRUE(boost::filesystem::exists(testLogFileName));
- ASSERT_TRUE(boost::filesystem::file_size(testLogFileName) > 0);
- boost::filesystem::remove(testLogFileName);
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Config, logFilename));
+ LOGCONFIG("This is a 'config' string");
+ LOGCONFIG("This is a formatted 'config' string (%d)", __1K__);
+ apache::geode::client::Log::close();
+ ASSERT_TRUE(boost::filesystem::exists(logFilename));
+ ASSERT_TRUE(boost::filesystem::file_size(logFilename) > 0);
+ boost::filesystem::remove(logFilename);
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Info, testLogFileName));
- LOGINFO("This is a 'finer' string");
- LOGINFO("This is a formatted 'finer' string (%d)", __1K__);
- apache::geode::client::Log::close();
- ASSERT_TRUE(boost::filesystem::exists(testLogFileName));
- ASSERT_TRUE(boost::filesystem::file_size(testLogFileName) > 0);
- boost::filesystem::remove(testLogFileName);
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Info, logFilename));
+ LOGINFO("This is a 'finer' string");
+ LOGINFO("This is a formatted 'finer' string (%d)", __1K__);
+ apache::geode::client::Log::close();
+ ASSERT_TRUE(boost::filesystem::exists(logFilename));
+ ASSERT_TRUE(boost::filesystem::file_size(logFilename) > 0);
+ boost::filesystem::remove(logFilename);
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Warning, testLogFileName));
- LOGWARN("This is a 'warning' string");
- LOGWARN("This is a formatted 'warning' string (%d)", __1K__);
- apache::geode::client::Log::close();
- ASSERT_TRUE(boost::filesystem::exists(testLogFileName));
- ASSERT_TRUE(boost::filesystem::file_size(testLogFileName) > 0);
- boost::filesystem::remove(testLogFileName);
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Warning, logFilename));
+ LOGWARN("This is a 'warning' string");
+ LOGWARN("This is a formatted 'warning' string (%d)", __1K__);
+ apache::geode::client::Log::close();
+ ASSERT_TRUE(boost::filesystem::exists(logFilename));
+ ASSERT_TRUE(boost::filesystem::file_size(logFilename) > 0);
+ boost::filesystem::remove(logFilename);
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Error, testLogFileName));
- LOGERROR("This is a 'error' string");
- LOGERROR("This is a formatted 'error' string (%d)", __1K__);
- apache::geode::client::Log::close();
- ASSERT_TRUE(boost::filesystem::exists(testLogFileName));
- ASSERT_TRUE(boost::filesystem::file_size(testLogFileName) > 0);
- boost::filesystem::remove(testLogFileName);
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Error, logFilename));
+ LOGERROR("This is a 'error' string");
+ LOGERROR("This is a formatted 'error' string (%d)", __1K__);
+ apache::geode::client::Log::close();
+ ASSERT_TRUE(boost::filesystem::exists(logFilename));
+ ASSERT_TRUE(boost::filesystem::file_size(logFilename) > 0);
+ boost::filesystem::remove(logFilename);
+ }
}
TEST_F(LoggingTest, verifyFileSizeLimit) {
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Debug, testLogFileName, 1, 5));
- for (auto i = 0; i < 4 * __1K__; i++) {
- LOGDEBUG(__1KStringLiteral);
- }
- apache::geode::client::Log::close();
+ for (auto logFilename : testFileNames) {
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Debug, logFilename, 1, 5));
+ for (auto i = 0; i < 4 * __1K__; i++) {
+ LOGDEBUG(__1KStringLiteral);
+ }
+ apache::geode::client::Log::close();
- // Original file should still be around
- ASSERT_TRUE(boost::filesystem::exists(testLogFileName));
+ // Original file should still be around
+ ASSERT_TRUE(boost::filesystem::exists(logFilename));
- // Check for 'rolled' log files. With a 1MB file size limit and each logged
- // string having a length of 1K chars, we should have at least one less
- // rolled log file than the number of strings logged, i.e. 3 rolled files
- // for 4K strings in this case. spdlog rolled files look like
- // <<basename>>.<<#>>.<<extension>>, so for LoggingTest.log we should find
- // LoggingTest.1.log, LoggingTest.2.log, etc.
- auto base = boost::filesystem::path(testLogFileName).stem();
- auto ext = boost::filesystem::path(testLogFileName).extension();
+ // Check for 'rolled' log files. With a 1MB file size limit and each logged
+ // string having a length of 1K chars, we should have at least one less
+ // rolled log file than the number of strings logged, i.e. 3 rolled files
+ // for 4K strings in this case. spdlog rolled files look like
+ // <<basename>>.<<#>>.<<extension>>, so for LoggingTest.log we should find
+ // LoggingTest.1.log, LoggingTest.2.log, etc.
+ auto base = boost::filesystem::path(logFilename).stem();
+ auto ext = boost::filesystem::path(logFilename).extension();
- // File size limit is treated as a "soft" limit. If the last message in the
- // log puts the file size over the limit, the file is rolled and the message
- // is preserved intact, rather than truncated or split across files. We'll
- // assume the file size never exceeds 110% of the specified limit.
- auto adjustedFileSizeLimit =
- static_cast<uint32_t>(static_cast<uint64_t>(__1M__) * 11 / 10);
+ // File size limit is treated as a "soft" limit. If the last message in the
+ // log puts the file size over the limit, the file is rolled and the message
+ // is preserved intact, rather than truncated or split across files. We'll
+ // assume the file size never exceeds 110% of the specified limit.
+ auto adjustedFileSizeLimit =
+ static_cast<uint32_t>(static_cast<uint64_t>(__1M__) * 11 / 10);
- for (auto i = 0; i < 4; i++) {
- auto rolledLogFileName =
- base.string() + "-" + std::to_string(i) + ext.string();
+ for (auto i = 0; i < 4; i++) {
+ auto rolledLogFileName =
+ base.string() + "-" + std::to_string(i) + ext.string();
- ASSERT_TRUE(boost::filesystem::exists(rolledLogFileName));
- ASSERT_TRUE(adjustedFileSizeLimit >
- boost::filesystem::file_size(rolledLogFileName));
+ ASSERT_TRUE(boost::filesystem::exists(rolledLogFileName));
+ ASSERT_TRUE(adjustedFileSizeLimit >
+ boost::filesystem::file_size(rolledLogFileName));
+ }
}
}
TEST_F(LoggingTest, verifyDiskSpaceLimit) {
- const int NUMBER_OF_ITERATIONS = 4 * __1K__;
- const int DISK_SPACE_LIMIT = 2 * __1M__;
+ for (auto logFilename : testFileNames) {
+ const int NUMBER_OF_ITERATIONS = 4 * __1K__;
+ const int DISK_SPACE_LIMIT = 2 * __1M__;
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Debug, testLogFileName, 1, 2));
- for (auto i = 0; i < NUMBER_OF_ITERATIONS; i++) {
- LOGDEBUG(__1KStringLiteral);
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Debug, logFilename, 1, 2));
+ for (auto i = 0; i < NUMBER_OF_ITERATIONS; i++) {
+ LOGDEBUG(__1KStringLiteral);
+ }
+ apache::geode::client::Log::close();
+
+ // Original file should still be around
+ ASSERT_TRUE(boost::filesystem::exists(logFilename));
+
+ auto size = boost::filesystem::file_size(logFilename);
+ auto numRolledFilesFound = 0;
+ auto base = boost::filesystem::path(logFilename).stem();
+ auto ext = boost::filesystem::path(logFilename).extension();
+
+ // We wrote 4x the log file limit, and 2x the disk space limit, so
+ // there should be one 'rolled' file. Its name should be of the form
+ // <base>-n.log, where n is some reasonable number.
+ std::map<int32_t, boost::filesystem::path> rolledFiles;
+ LoggingTest::findRolledFiles(boost::filesystem::current_path().string(),
+ logFilename, rolledFiles);
+ ASSERT_TRUE(rolledFiles.size() == 1);
+
+ auto rolledFile = rolledFiles.begin()->second;
+ size += boost::filesystem::file_size(rolledFile);
+
+ ASSERT_TRUE(size <= DISK_SPACE_LIMIT);
}
- apache::geode::client::Log::close();
-
- // Original file should still be around
- ASSERT_TRUE(boost::filesystem::exists(testLogFileName));
-
- auto size = boost::filesystem::file_size(testLogFileName);
- auto numRolledFilesFound = 0;
- auto base = boost::filesystem::path(testLogFileName).stem();
- auto ext = boost::filesystem::path(testLogFileName).extension();
-
- // We wrote 4x the log file limit, and 2x the disk space limit, so
- // there should be one 'rolled' file. Its name should be of the form
- // <base>-n.log, where n is some reasonable number.
- std::map<int32_t, boost::filesystem::path> rolledFiles;
- LoggingTest::findRolledFiles(boost::filesystem::current_path().string(),
- rolledFiles);
- ASSERT_TRUE(rolledFiles.size() == 1);
-
- auto rolledFile = rolledFiles.begin()->second;
- size += boost::filesystem::file_size(rolledFile);
-
- ASSERT_TRUE(size <= DISK_SPACE_LIMIT);
}
TEST_F(LoggingTest, verifyWithExistingRolledFile) {
- LoggingTest::writeRolledLogFile(boost::filesystem::current_path(), 11);
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Debug, testLogFileName, 1, 5));
- for (auto i = 0; i < 2 * __1K__; i++) {
- LOGDEBUG(__1KStringLiteral);
- }
- apache::geode::client::Log::close();
+ for (auto logFilename : testFileNames) {
+ LoggingTest::writeRolledLogFile(boost::filesystem::current_path(),
+ logFilename, 11);
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Debug, logFilename, 1, 5));
+ for (auto i = 0; i < 2 * __1K__; i++) {
+ LOGDEBUG(__1KStringLiteral);
+ }
+ apache::geode::client::Log::close();
- // Original file should still be around
- ASSERT_TRUE(boost::filesystem::exists(testLogFileName));
+ // Original file should still be around
+ ASSERT_TRUE(boost::filesystem::exists(logFilename));
- // Check for 'rolled' log files. With a 1MB file size limit and each logged
- // string having a length of 1K chars, we should have at least one less
- // rolled log file than the number of strings logged, i.e. 3 rolled files
- // for 4K strings in this case. spdlog rolled files look like
- // <<basename>>.<<#>>.<<extension>>, so for LoggingTest.log we should find
- // LoggingTest.1.log, LoggingTest.2.log, etc.
- auto base = boost::filesystem::path(testLogFileName).stem();
- auto ext = boost::filesystem::path(testLogFileName).extension();
+ // Check for 'rolled' log files. With a 1MB file size limit and each logged
+ // string having a length of 1K chars, we should have at least one less
+ // rolled log file than the number of strings logged, i.e. 3 rolled files
+ // for 4K strings in this case. spdlog rolled files look like
+ // <<basename>>.<<#>>.<<extension>>, so for LoggingTest.log we should find
+ // LoggingTest.1.log, LoggingTest.2.log, etc.
+ auto base = boost::filesystem::path(logFilename).stem();
+ auto ext = boost::filesystem::path(logFilename).extension();
- // File size limit is treated as a "soft" limit. If the last message in the
- // log puts the file size over the limit, the file is rolled and the message
- // is preserved intact, rather than truncated or split across files. We'll
- // assume the file size never exceeds 110% of the specified limit.
- auto adjustedFileSizeLimit =
- static_cast<uint32_t>(static_cast<uint64_t>(__1M__) * 11 / 10);
+ // File size limit is treated as a "soft" limit. If the last message in the
+ // log puts the file size over the limit, the file is rolled and the message
+ // is preserved intact, rather than truncated or split across files. We'll
+ // assume the file size never exceeds 110% of the specified limit.
+ auto adjustedFileSizeLimit =
+ static_cast<uint32_t>(static_cast<uint64_t>(__1M__) * 11 / 10);
- auto rolledLogFileName =
- base.string() + "-" + std::to_string(12) + ext.string();
+ auto rolledLogFileName =
+ base.string() + "-" + std::to_string(12) + ext.string();
- ASSERT_TRUE(boost::filesystem::exists(rolledLogFileName));
- ASSERT_TRUE(adjustedFileSizeLimit >
- boost::filesystem::file_size(rolledLogFileName));
-}
-
-void verifyWithPath(const boost::filesystem::path& path, int32_t fileSizeLimit,
- int64_t diskSpaceLimit) {
- auto relativePath = path / boost::filesystem::path(testLogFileName);
-
- ASSERT_NO_THROW(apache::geode::client::Log::init(
- apache::geode::client::LogLevel::Debug, relativePath.string(),
- fileSizeLimit, diskSpaceLimit));
- for (auto i = 0; i < ((3 * fileSizeLimit) / 2) * __1K__; i++) {
- LOGDEBUG(__1KStringLiteral);
- }
- apache::geode::client::Log::close();
-
- // Original file should still be around
- ASSERT_TRUE(boost::filesystem::exists(relativePath));
-
- // Check for 'rolled' log files. With a 1MB file size limit and each logged
- // string having a length of 1K chars, we should have at least one less
- // rolled log file than the number of strings logged, i.e. 3 rolled files
- // for 4K strings in this case. spdlog rolled files look like
- // <<basename>>.<<#>>.<<extension>>, so for LoggingTest.log we should find
- // LoggingTest.1.log, LoggingTest.2.log, etc.
- auto base = boost::filesystem::path(relativePath).stem();
- auto ext = boost::filesystem::path(relativePath).extension();
-
- // File size limit is treated as a "soft" limit. If the last message in the
- // log puts the file size over the limit, the file is rolled and the message
- // is preserved intact, rather than truncated or split across files. We'll
- // assume the file size never exceeds 110% of the specified limit.
- auto adjustedFileSizeLimit = static_cast<uint32_t>(
- static_cast<uint64_t>(__1M__ * fileSizeLimit) * 11 / 10);
-
- auto rolledLogFileName =
- relativePath.parent_path() /
- boost::filesystem::path(base.string() + "-" + std::to_string(0) +
- ext.string());
-
- if (fileSizeLimit == diskSpaceLimit) {
- // If the limits are equal, we should *never* roll logs, just delete the
- // current file and start over
- ASSERT_FALSE(boost::filesystem::exists(rolledLogFileName));
- } else {
ASSERT_TRUE(boost::filesystem::exists(rolledLogFileName));
ASSERT_TRUE(adjustedFileSizeLimit >
boost::filesystem::file_size(rolledLogFileName));
}
- ASSERT_TRUE(adjustedFileSizeLimit >
- boost::filesystem::file_size(relativePath));
+}
+
+void verifyWithPath(const boost::filesystem::path& path, int32_t fileSizeLimit,
+ int64_t diskSpaceLimit) {
+ for (auto logFilename : testFileNames) {
+ auto relativePath = path / boost::filesystem::path(logFilename);
+
+ ASSERT_NO_THROW(apache::geode::client::Log::init(
+ apache::geode::client::LogLevel::Debug, relativePath.string(),
+ fileSizeLimit, diskSpaceLimit));
+ for (auto i = 0; i < ((3 * fileSizeLimit) / 2) * __1K__; i++) {
+ LOGDEBUG(__1KStringLiteral);
+ }
+ apache::geode::client::Log::close();
+
+ // Original file should still be around
+ ASSERT_TRUE(boost::filesystem::exists(relativePath));
+
+ // Check for 'rolled' log files. With a 1MB file size limit and each logged
+ // string having a length of 1K chars, we should have at least one less
+ // rolled log file than the number of strings logged, i.e. 3 rolled files
+ // for 4K strings in this case. spdlog rolled files look like
+ // <<basename>>.<<#>>.<<extension>>, so for LoggingTest.log we should find
+ // LoggingTest.1.log, LoggingTest.2.log, etc.
+ auto base = boost::filesystem::path(relativePath).stem();
+ auto ext = boost::filesystem::path(relativePath).extension();
+
+ // File size limit is treated as a "soft" limit. If the last message in the
+ // log puts the file size over the limit, the file is rolled and the message
+ // is preserved intact, rather than truncated or split across files. We'll
+ // assume the file size never exceeds 110% of the specified limit.
+ auto adjustedFileSizeLimit = static_cast<uint32_t>(
+ static_cast<uint64_t>(__1M__ * fileSizeLimit) * 11 / 10);
+
+ auto rolledLogFileName =
+ relativePath.parent_path() /
+ boost::filesystem::path(base.string() + "-" + std::to_string(0) +
+ ext.string());
+
+ if (fileSizeLimit == diskSpaceLimit) {
+ // If the limits are equal, we should *never* roll logs, just delete the
+ // current file and start over
+ ASSERT_FALSE(boost::filesystem::exists(rolledLogFileName));
+ } else {
+ ASSERT_TRUE(boost::filesystem::exists(rolledLogFileName));
+ ASSERT_TRUE(adjustedFileSizeLimit >
+ boost::filesystem::file_size(rolledLogFileName));
+ }
+ ASSERT_TRUE(adjustedFileSizeLimit >
+ boost::filesystem::file_size(relativePath));
+ }
}
TEST_F(LoggingTest, verifyWithRelativePathFromCWD) {
@@ -574,23 +633,25 @@
LogLevel::Finest,
LogLevel::Debug,
}) {
- apache::geode::client::Log::init(level, testLogFileName);
+ for (auto logFilename : testFileNames) {
+ apache::geode::client::Log::init(level, logFilename);
- LOGERROR("Error Message");
- LOGWARN("Warning Message");
- LOGINFO("Info Message");
- LOGCONFIG("Config Message");
- LOGFINE("Fine Message");
- LOGFINER("Finer Message");
- LOGFINEST("Finest Message");
- LOGDEBUG("Debug Message");
+ LOGERROR("Error Message");
+ LOGWARN("Warning Message");
+ LOGINFO("Info Message");
+ LOGCONFIG("Config Message");
+ LOGFINE("Fine Message");
+ LOGFINER("Finer Message");
+ LOGFINEST("Finest Message");
+ LOGDEBUG("Debug Message");
- int lines = LoggingTest::numOfLinesInFile(testLogFileName.c_str());
+ int lines = LoggingTest::numOfLinesInFile(logFilename);
- ASSERT_TRUE(lines == LoggingTest::expectedWithBanner(level));
+ ASSERT_TRUE(lines == LoggingTest::expectedWithBanner(level));
- apache::geode::client::Log::close();
- boost::filesystem::remove(testLogFileName);
+ apache::geode::client::Log::close();
+ boost::filesystem::remove(logFilename);
+ }
}
}
@@ -612,4 +673,14 @@
TEST_F(LoggingTest, countLinesNone) { verifyLineCountAtLevel(LogLevel::None); }
+TEST_F(LoggingTest, verifyDiskSpaceNotLeaked) {
+ for (auto logFilename : testFileNames) {
+ verifyDiskSpaceNotLeakedForFile(logFilename);
+ }
+}
+
+TEST_F(LoggingTest, verifyDiskSpaceNotLeakedWithDefaultLogName) {
+ verifyDiskSpaceNotLeakedForFile(nullptr);
+}
+
} // namespace