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);