You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4cxx-dev@logging.apache.org by ts...@apache.org on 2015/10/09 15:01:20 UTC
svn commit: r1707714 -
/incubator/log4cxx/trunk/src/test/cpp/rolling/timebasedrollingtest.cpp
Author: tschoening
Date: Fri Oct 9 13:01:20 2015
New Revision: 1707714
URL: http://svn.apache.org/viewvc?rev=1707714&view=rev
Log:
LOGCXX-457: I've reworked test1 to reduce the amount of duplicated code: All tests seem to produce file names in the same way, log some messages and most of them check results using file content comparison. The test still succeeds and I formerly got an access violation in fprintf if not all tests succeeded, which is gone now as well.
Modified:
incubator/log4cxx/trunk/src/test/cpp/rolling/timebasedrollingtest.cpp
Modified: incubator/log4cxx/trunk/src/test/cpp/rolling/timebasedrollingtest.cpp
URL: http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/test/cpp/rolling/timebasedrollingtest.cpp?rev=1707714&r1=1707713&r2=1707714&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/test/cpp/rolling/timebasedrollingtest.cpp (original)
+++ incubator/log4cxx/trunk/src/test/cpp/rolling/timebasedrollingtest.cpp Fri Oct 9 13:01:20 2015
@@ -33,6 +33,13 @@
#define INT64_C(x) x ## LL
#endif
+// We often need one and the same date pattern, but in different contexts, to either easily embed it
+// into other string literals or as an object. While macros are hard to debug, embedding into string
+// literals is easier this way, because the compiler can automatically collaps them, and if we have
+// one macro already, a second for a similar purpose shouldn't hurt as well.
+#define DATE_PATTERN "yyyy-MM-dd_HH_mm_ss"
+#define DATE_PATTERN_STR LogString(LOG4CXX_STR("yyyy-MM-dd_HH_mm_ss"))
+
using namespace log4cxx;
using namespace log4cxx::helpers;
using namespace log4cxx::rolling;
@@ -55,7 +62,6 @@ using namespace log4cxx::rolling;
Test5 NO SET NO
Test6 YES SET NO
* </pre>
- *
*/
LOGUNIT_CLASS(TimeBasedRollingTest) {
@@ -68,65 +74,192 @@ LOGUNIT_CLASS(TimeBasedRollingTest) {
LOGUNIT_TEST(test6);
LOGUNIT_TEST_SUITE_END();
- static LoggerPtr logger;
-
-public:
-
- void setUp() {
- LoggerPtr root(Logger::getRootLogger());
- root->addAppender(
- new ConsoleAppender(new PatternLayout(
- LOG4CXX_STR("%d{ABSOLUTE} [%t] %level %c{2}#%M:%L - %m%n"))));
- }
-
- void tearDown() {
- LogManager::shutdown();
- }
-
- /**
- * Test rolling without compression, activeFileName left blank, no stop/start
- */
- void test1() {
- PatternLayoutPtr layout(new PatternLayout(LOG4CXX_STR("%c{1} - %m%n")));
- RollingFileAppenderPtr rfa(new RollingFileAppender());
- rfa->setLayout(layout);
-
- LogString datePattern(LOG4CXX_STR("yyyy-MM-dd_HH_mm_ss"));
-
- TimeBasedRollingPolicyPtr tbrp(new TimeBasedRollingPolicy());
- tbrp->setFileNamePattern(LOG4CXX_STR("output/test1-%d{yyyy-MM-dd_HH_mm_ss}"));
- Pool p;
- tbrp->activateOptions(p);
- rfa->setRollingPolicy(tbrp);
- rfa->activateOptions(p);
- logger->addAppender(rfa);
-
- SimpleDateFormat sdf(datePattern);
- LogString filenames[4];
+private:
+ static LoggerPtr logger;
- Pool pool;
- apr_time_t now = apr_time_now();
- { for (int i = 0; i < 4; i++) {
- filenames[i] = LOG4CXX_STR("output/test1-");
- sdf.format(filenames[i], now, p);
- now += APR_USEC_PER_SEC;
- } }
+ /**
+ * Build file names with timestamps.
+ * <p>
+ * This method builds some file names based on a hard coded date pattern, while the important
+ * thing is that the used time is "now" for the first and one additional second into the future
+ * for each subsequent file name. The method is used to build names which are expected to get
+ * created by loggers afterwards, so the existence of those files can be checked easily.
+ * </p>
+ * <p>
+ * The given {@code prefix} is for the file name only, we hard code "outpout" as directory.
+ * </p>
+ * @param[in,out] pool
+ * @param[in] prefix
+ * @param[in] fileNames
+ */
+ template<size_t N>
+ void buildTsFileNames(Pool& pool, const logchar* prefix, LogString (&fileNames)[N])
+ {
+ SimpleDateFormat sdf(DATE_PATTERN_STR);
+ apr_time_t now(apr_time_now());
+
+ for (size_t i = 0; i < N; ++i)
+ {
+ fileNames[i] = LogString(LOG4CXX_STR("output/")) + prefix;
+ sdf.format(fileNames[i], now, pool);
+ now += APR_USEC_PER_SEC;
+ }
+ }
+
+ /**
+ * Log some msg and sleep.
+ * <p>
+ * Most tests need to log some message to some files and sleep afterwards, to spread the msgs
+ * over time and timestamp based named files. This method handles this for all tests to not need
+ * to replicate the same code AND deals with the fact that the logigng statements should contain
+ * the original src function and line. For that we define a macro wrapper for this function to
+ * easily provide us the needed additional information and redefine LOG4CXX_LOCATION to use our
+ * provided data instead of those fomr the compiler when a log statement is issued. While this
+ * is a bit ugly, because we need to duplicate the definition of LOG4CXX_LOCATION, it is easier
+ * than to duplicate the code per test in this file.
+ * </p>
+ * @param[in,out] pool
+ * @param[in] howOften
+ * @param[in] srcFunc
+ * @param[in] srcLine
+ */
+ void logSomeMsgAndSleep(Pool& pool, size_t howOften, std::string srcFunc, size_t srcLine)
+ {
+#undef LOG4CXX_LOCATION
+#define LOG4CXX_LOCATION ::log4cxx::spi::LocationInfo( \
+ __FILE__, \
+ srcFunc.c_str(), \
+ srcLine)
+
+ for (size_t i = 0; i <= howOften; ++i)
+ {
+ std::string message("Hello---");
+ message.append(pool.itoa(i));
+
+ LOG4CXX_DEBUG(logger, message);
+ apr_sleep(APR_USEC_PER_SEC / 2);
+ }
+
+#undef LOG4CXX_LOCATION
+#define LOG4CXX_LOCATION ::log4cxx::spi::LocationInfo( \
+ __FILE__, \
+ __LOG4CXX_FUNC__, \
+ __LINE__)
+ }
- delayUntilNextSecondWithMsg();
+/**
+ * Wrapper for logging some messages.
+ * <p>
+ * This macro is used to easily provide the src function and line to the method logging into test
+ * files. A macro is used because the name of the macro for the source function differs between
+ * compilers and we already provide our own name for that.
+ * </p>
+ */
+#define LOG_SOME_MSG_AND_SLEEP(pool, howOften) \
+ this->logSomeMsgAndSleep(pool, howOften, __LOG4CXX_FUNC__, __LINE__)
- { for (int i = 0; i < 5; i++) {
- std::string message("Hello---");
- message.append(pool.itoa(i));
- LOG4CXX_DEBUG(logger, message);
- apr_sleep(APR_USEC_PER_SEC/2);
- } }
+ /**
+ * Check witnesses for some test.
+ * <p>
+ * This method checks the witnesses for some test, given by the {@code prefix} arg, which should
+ * correspond to some file, while we hard code the parent dir and such of that file.
+ * </p>
+ * <p>
+ * We don't use a wrapper macro this time because the src line schould have the same name in all
+ * compilers and is easily to add for the caller.
+ * </p>
+ * @param[in,out] pool
+ * @param[in] prefix
+ * @param[in] fileNames
+ * @param[in] srcLine
+ */
+ template<size_t N>
+ void checkWitnesses( Pool& pool,
+ const logchar* prefix,
+ LogString (&fileNames)[N],
+ size_t srcLine)
+ {
+ for (int i = 0; i < N; ++i)
+ {
+ LogString witness(LOG4CXX_STR("witness/rolling/tbr-"));
+ witness.append(prefix);
+
+ StringHelper::toString(i, pool, witness);
+ LOGUNIT_ASSERT_SRCL(Compare::compare(fileNames[i], File(witness)), srcLine);
+ }
+ }
+
+ /**
+ * Let the current second pass.
+ * <p>
+ * This method assures that the current second and some additional time gets passed before
+ * returning.
+ * </p>
+ * @param[in,opt] millis
+ */
+ void delayUntilNextSecond(size_t millis = 100)
+ {
+ apr_time_t now = apr_time_now();
+ apr_time_t next = ((now / APR_USEC_PER_SEC) + 1) * APR_USEC_PER_SEC + millis * 1000L;
+
+ apr_sleep(next - now);
+ }
+
+ /**
+ * Let the current second pass with some msg.
+ * <p>
+ * This method works exactly like {@link delayUntilNextSecond(size_t)}, but additionally prints
+ * a message before and after the wait on STDOUT for debugging purposes.
+ * </p>
+ * @param[in,opt] millis
+ */
+ void delayUntilNextSecondWithMsg(size_t millis = 100)
+ {
+ std::cout << "Waiting until next second and " << millis << " millis.";
+ delayUntilNextSecond(millis);
+ std::cout << "Done waiting.";
+ }
- for (int i = 0; i < 4; i++) {
- LogString witness(LOG4CXX_STR("witness/rolling/tbr-test1."));
- StringHelper::toString(i, pool, witness);
- LOGUNIT_ASSERT(Compare::compare(filenames[i], File(witness)));
- }
- }
+public:
+ void setUp()
+ {
+ LoggerPtr root(Logger::getRootLogger());
+ root->addAppender(
+ new ConsoleAppender(
+ new PatternLayout(
+ LOG4CXX_STR("%d{ABSOLUTE} [%t] %level %c{2}#%M:%L - %m%n"))));
+ }
+
+ void tearDown()
+ {
+ LogManager::shutdown();
+ }
+
+ /**
+ * Test rolling without compression, activeFileName left blank, no stop/start
+ */
+ void test1()
+ {
+ Pool pool;
+ const size_t nrOfFileNames = 4;
+ LogString fileNames[nrOfFileNames];
+
+ PatternLayoutPtr layout(new PatternLayout(LOG4CXX_STR("%c{1} - %m%n")));
+ RollingFileAppenderPtr rfa(new RollingFileAppender());
+ rfa->setLayout(layout);
+
+ TimeBasedRollingPolicyPtr tbrp(new TimeBasedRollingPolicy());
+ tbrp->setFileNamePattern(LOG4CXX_STR("output/test1-%d{" DATE_PATTERN "}"));
+ tbrp->activateOptions(pool);
+ rfa->setRollingPolicy(tbrp);
+ rfa->activateOptions(pool);
+ logger->addAppender(rfa);
+
+ this->buildTsFileNames(pool, LOG4CXX_STR("test1-"), fileNames);
+ delayUntilNextSecondWithMsg();
+ LOG_SOME_MSG_AND_SLEEP(pool, nrOfFileNames);
+ this->checkWitnesses(pool, LOG4CXX_STR("test1."), fileNames, __LINE__);
+ }
/**
* No compression, with stop/restart, activeFileName left blank
@@ -407,24 +540,8 @@ public:
LOGUNIT_ASSERT_EQUAL(true, Compare::compare(File(filenames[3]), File(LOG4CXX_STR("witness/rolling/tbr-test6.3"))));
}
-
- void delayUntilNextSecond(size_t millis = 100)
- {
- apr_time_t now = apr_time_now();
- apr_time_t next = ((now / APR_USEC_PER_SEC) + 1) * APR_USEC_PER_SEC + millis * 1000L;
-
- apr_sleep(next - now);
- }
-
- void delayUntilNextSecondWithMsg(size_t millis = 100)
- {
- std::cout << "Waiting until next second and 100 millis.";
- delayUntilNextSecond(millis);
- std::cout << "Done waiting.";
- }
};
-
LoggerPtr TimeBasedRollingTest::logger(Logger::getLogger("org.apache.log4j.TimeBasedRollingTest"));
LOGUNIT_TEST_SUITE_REGISTRATION(TimeBasedRollingTest);