| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <vector> |
| |
| #include <log4cxx/rolling/rollingfileappender.h> |
| #include <log4cxx/basicconfigurator.h> |
| #include <log4cxx/logger.h> |
| #include <log4cxx/consoleappender.h> |
| #include <log4cxx/logmanager.h> |
| #include <log4cxx/patternlayout.h> |
| #include <log4cxx/rolling/timebasedrollingpolicy.h> |
| #include <log4cxx/helpers/simpledateformat.h> |
| #include <log4cxx/helpers/date.h> |
| #include <iostream> |
| #include <log4cxx/helpers/stringhelper.h> |
| #include "../util/compare.h" |
| #include "../logunit.h" |
| |
| #include <apr_strings.h> |
| #include <apr_time.h> |
| #include <random> |
| #ifndef INT64_C |
| #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")) |
| #define PATTERN_LAYOUT LOG4CXX_STR("%c{1} - %m%n") |
| |
| #define DIR_PRE_OUTPUT "output/rolling/tbr-" |
| #define DIR_PRE_WITNESS "witness/rolling/tbr-" |
| |
| using namespace log4cxx; |
| using namespace log4cxx::helpers; |
| using namespace log4cxx::rolling; |
| |
| /** |
| * A rather exhaustive set of tests. Tests include leaving the ActiveFileName |
| * argument blank, or setting it, with and without compression, and tests |
| * with or without stopping/restarting the RollingFileAppender. |
| * |
| * The regression tests log a few times using a RollingFileAppender. Then, |
| * they predict the names of the files which sould be generated and compare |
| * them with witness files. |
| * |
| * <pre> |
| Compression ActiveFileName Stop/Restart |
| Test1 NO BLANK NO |
| Test2 NO BLANK YES |
| Test3 YES BLANK NO |
| Test4 NO SET YES |
| Test5 NO SET NO |
| Test6 YES SET NO |
| * </pre> |
| */ |
| LOGUNIT_CLASS(TimeBasedRollingTest) |
| { |
| LOGUNIT_TEST_SUITE(TimeBasedRollingTest); |
| LOGUNIT_TEST(test1); |
| LOGUNIT_TEST(test2); |
| LOGUNIT_TEST(test3); |
| LOGUNIT_TEST(test4); |
| LOGUNIT_TEST(test5); |
| LOGUNIT_TEST(test6); |
| LOGUNIT_TEST(test7); |
| LOGUNIT_TEST(rollIntoDir); |
| LOGUNIT_TEST_SUITE_END(); |
| |
| private: |
| LoggerPtr logger; |
| log4cxx_time_t current_time; |
| |
| /** |
| * 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 "output" as directory. |
| * </p> |
| * <p> |
| * Using {@code startInFuture} the caller can specify if the first created file name uses "now" |
| * or already starts one second in the future. This depends on what the caller wants to check: |
| * If it is the existence of specially named files and the caller uses some generic log file to |
| * start with, it's most likely that the first file name to checks needs to be in the future, |
| * because new files are only created with subsequent log statements. The first goes to the |
| * generically named file, afterwards the test sleeps a bit and the next statement is creating |
| * the first file to check for. During the time between those two calls the current second and |
| * therefore "now" could have easily past and the first file name will never be found, because |
| * the rolling appender creates it with a newer "now", at least one second in the future. |
| * </p> |
| * @param[in,out] pool |
| * @param[in] prefix |
| * @param[in] fnames |
| * @param[in,opt] compressed |
| * @param[in,opt] startInFuture |
| */ |
| template<size_t N> |
| void buildTsFnames( |
| Pool& pool, |
| const LogString& prefix, |
| LogString (&fnames)[N], |
| bool compressed = false, |
| bool startInFuture = false) |
| { |
| SimpleDateFormat sdf(DATE_PATTERN_STR); |
| log4cxx_time_t now(current_time); |
| LogString ext(compressed ? LOG4CXX_STR(".gz") : LOG4CXX_STR("")); |
| |
| now += startInFuture ? APR_USEC_PER_SEC : 0; |
| |
| for (size_t i = 0; i < N; ++i) |
| { |
| fnames[i].assign(LogString(LOG4CXX_STR("" DIR_PRE_OUTPUT)) + prefix); |
| sdf.format(fnames[i], now, pool); |
| fnames[i].append(ext); |
| |
| 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 to work each caller needs to provide us the |
| * additional information and we redefine LOG4CXX_LOCATION to use that provided data instead of |
| * that from 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 |
| * for logging and sleeping per test in this file. |
| * </p> |
| * <p> |
| * The given wait factor is always multiplied with 1 second and the result is waited for, so a |
| * caller needs to e.g. provide {@code 0.5} if it needs log statements to distribute over given |
| * files, resulting in two statements per file. If the caller needs indivdual file to check for |
| * their existence, {@code 1} can be provided, which ensures that we wait for at least the next |
| * second. |
| * </p> |
| * <p> |
| * It is important the the caller provides aus with {@code __LOG4CXX_FUNC__} instead of only |
| * {@code __FUNC__} or such, because the latter is compiler specific and log4cxx already deals |
| * with such things. |
| * </p> |
| * <p> |
| * We had macro wrappers around this method dealing with such things in the past, but as args |
| * where added, those become more and more difficult to maintain properly and therefore removed. |
| * </p> |
| * @param[in,out] pool |
| * @param[in] howOften |
| * @param[in] srcFunc |
| * @param[in] srcLine |
| * @param[in,opt] startWith |
| * @param[in] waitFactor |
| */ |
| void logMsgAndSleep( |
| Pool& pool, |
| size_t howOften, |
| std::string srcFunc, |
| size_t srcLine, |
| size_t startWith = 0, |
| float waitFactor = 0.5) |
| { |
| #undef LOG4CXX_LOCATION |
| #define LOG4CXX_LOCATION ::log4cxx::spi::LocationInfo( \ |
| __FILE__, \ |
| __FILE__, \ |
| srcFunc.c_str(), \ |
| srcLine) |
| |
| for (size_t i = startWith; i < startWith + howOften; ++i) |
| { |
| std::string message("Hello---"); |
| message.append(pool.itoa(i)); |
| |
| LOG4CXX_DEBUG(logger, message); |
| current_time += (APR_USEC_PER_SEC * waitFactor); |
| } |
| |
| #undef LOG4CXX_LOCATION |
| #define LOG4CXX_LOCATION ::log4cxx::spi::LocationInfo( \ |
| __FILE__, \ |
| __FILE__, \ |
| __LOG4CXX_FUNC__, \ |
| __LINE__) |
| } |
| |
| /** |
| * Check witness by comparing file contents. |
| * <p> |
| * This method checks the witness for some test by comparing the contents of the given file used |
| * by that test. To find the corresponding witness, the prefix of the test needs to be provided, |
| * which is some unique part of the file name to use, while we hard code the parent dir and |
| * other non changing parts of the name. |
| * </p> |
| * <p> |
| * We don't use a wrapper macro this time because the src line should 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] fname |
| * @param[in] witnessIdx |
| * @param[in] srcLine |
| */ |
| void compareWitness( |
| Pool& pool, |
| const LogString& prefix, |
| const LogString& fname, |
| size_t witnessIdx, |
| size_t srcLine) |
| { |
| LogString witness(LOG4CXX_STR("" DIR_PRE_WITNESS)); |
| witness.append(prefix); |
| StringHelper::toString(witnessIdx, pool, witness); |
| |
| //std::wcerr << L"Comparing file: " << fname << L"\n"; |
| //std::wcerr << L"Comparing witness: " << witness << L"\n"; |
| LOGUNIT_ASSERT_SRCL(Compare::compare(fname, File(witness)), srcLine); |
| } |
| |
| /** |
| * Check witnesses by comparing file contents. |
| * <p> |
| * This method is a wrapper around {@link compareWitness}, used to iterate over all files from a |
| * given test. |
| * </p> |
| * @param[in,out] pool |
| * @param[in] prefix |
| * @param[in] fnames |
| * @param[in] srcLine |
| */ |
| template<size_t N> |
| void compareWitnesses( |
| Pool& pool, |
| const LogString& prefix, |
| LogString (&fnames)[N], |
| size_t srcLine) |
| { |
| for (int i = 0; i < N; ++i) |
| { |
| this->compareWitness(pool, prefix, fnames[i], i, srcLine); |
| } |
| } |
| |
| /** |
| * Check existing files. |
| * <p> |
| * This method checks that the first N - 1 files of the given array actually exist and compares |
| * the last one by content to some witness. |
| * </p> |
| * <p> |
| * We don't use a wrapper macro this time because the src line should 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] fnames |
| * @param[in] witnessIdx |
| * @param[in] srcLine |
| */ |
| template<size_t N> |
| void checkFilesExist( |
| Pool& pool, |
| const LogString& prefix, |
| LogString (&fnames)[N], |
| size_t witnessIdx, |
| size_t srcLine) |
| { |
| for (int i = 0; i < N - 1; ++i) |
| { |
| //std::wcerr << L"Check: " << fnames[i] << L"\n"; |
| LOGUNIT_ASSERT_EQUAL_SRCL(true, exists(pool, File(fnames[i])), srcLine); |
| } |
| |
| this->compareWitness(pool, prefix, fnames[witnessIdx], witnessIdx, 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() |
| { |
| current_time += APR_USEC_PER_SEC; |
| } |
| |
| /** |
| * 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() |
| { |
| std::cout << "Advancing one second\n"; |
| delayUntilNextSecond(); |
| } |
| |
| /** |
| * Delete generic log file. |
| * <p> |
| * Some tests use generic log file names which may already be available during subsequent calls |
| * to the test and influence their behavior, e.g. because RollingFileAppender uses the last |
| * modification time of already existing files to create its internal name. Such a date might be |
| * from the arbitrary past, but most of the tests assume operations like rollovers within a few |
| * seconds around "new". Those assumptions will fail for older existing files. This method can |
| * be used to delete those files, while documenting the problem at the same time. |
| * </p> |
| * @param[in,out] pool |
| * @param[in] path |
| */ |
| void delGenericLogFile( |
| Pool& pool, |
| LogString path) |
| { |
| deleteFile(pool, File(path)); |
| } |
| |
| /** |
| * Set the current time for each individual test methhod run. |
| * <p> |
| * There's at least one test running multiple other tests WITHIN the same lifecycle of |
| * {@code setUp} and {@code tearDown}, but each of the test methods need the same current time |
| * to start with. So this method can be used to set that and is simply used by {@code setUp} |
| * as well. |
| * </p> |
| */ |
| void setUpCurrTime() |
| { |
| //current_time = log4cxx::helpers::Date::currentTime(); // Start at "about" now. |
| //current_time -= (current_time % APR_USEC_PER_SEC); // Go to the top of the second |
| //current_time++; // Need to not be at the top of a second for rollover logic to work correctly |
| current_time = 1; // Start at about unix epoch |
| } |
| |
| public: |
| log4cxx_time_t currentTime() |
| { |
| return current_time; |
| } |
| |
| void setUp() |
| { |
| BasicConfigurator::configure(std::make_shared<PatternLayout> ( |
| LOG4CXX_STR("%d{ABSOLUTE} [%t] %level %c{2}#%M:%L - %m%n") |
| )); |
| this->logger = LogManager::getLogger("org.apache.log4j.TimeBasedRollingTest"); |
| this->setUpCurrTime(); |
| helpers::Date::setGetCurrentTimeFunction( std::bind( &TimeBasedRollingTest::currentTime, this ) ); |
| } |
| |
| void tearDown() |
| { |
| LogManager::shutdown(); |
| } |
| |
| /** |
| * Test rolling without compression, activeFileName left blank, no stop/start. |
| */ |
| void test1() |
| { |
| Pool pool; |
| const size_t nrOfFnames(4); |
| LogString fnames[nrOfFnames]; |
| |
| PatternLayoutPtr layout( new PatternLayout(PATTERN_LAYOUT)); |
| RollingFileAppenderPtr rfa( new RollingFileAppender()); |
| rfa->setAppend(false); |
| rfa->setLayout(layout); |
| |
| TimeBasedRollingPolicyPtr tbrp(new TimeBasedRollingPolicy()); |
| tbrp->setFileNamePattern(LOG4CXX_STR("" DIR_PRE_OUTPUT "test1-%d{" DATE_PATTERN "}")); |
| tbrp->activateOptions(pool); |
| rfa->setRollingPolicy(tbrp); |
| rfa->activateOptions(pool); |
| logger->addAppender(rfa); |
| |
| this->buildTsFnames<4>(pool, LOG4CXX_STR("test1-"), fnames); |
| this->delayUntilNextSecondWithMsg(); |
| this->logMsgAndSleep( pool, nrOfFnames + 1, __LOG4CXX_FUNC__, __LINE__); |
| this->compareWitnesses<4>( pool, LOG4CXX_STR("test1."), fnames, __LINE__); |
| } |
| |
| |
| /** |
| * No compression, with stop/restart, activeFileName left blank. |
| */ |
| void test2() |
| { |
| Pool pool; |
| const size_t nrOfFnames(4); |
| LogString fnames[nrOfFnames]; |
| |
| PatternLayoutPtr layout1(new PatternLayout(PATTERN_LAYOUT)); |
| RollingFileAppenderPtr rfa1( new RollingFileAppender()); |
| rfa1->setAppend(false); |
| rfa1->setLayout(layout1); |
| |
| TimeBasedRollingPolicyPtr tbrp1(new TimeBasedRollingPolicy()); |
| tbrp1->setFileNamePattern(LOG4CXX_STR("" DIR_PRE_OUTPUT "test2-%d{" DATE_PATTERN "}")); |
| tbrp1->activateOptions(pool); |
| rfa1->setRollingPolicy(tbrp1); |
| rfa1->activateOptions(pool); |
| logger->addAppender(rfa1); |
| |
| this->buildTsFnames<4>(pool, LOG4CXX_STR("test2-"), fnames); |
| this->delayUntilNextSecondWithMsg(); |
| this->logMsgAndSleep(pool, 3, __LOG4CXX_FUNC__, __LINE__); |
| |
| logger->removeAppender(rfa1); |
| rfa1->close(); |
| |
| PatternLayoutPtr layout2(new PatternLayout(PATTERN_LAYOUT)); |
| RollingFileAppenderPtr rfa2( new RollingFileAppender()); |
| rfa2->setLayout(layout2); |
| |
| TimeBasedRollingPolicyPtr tbrp2 = TimeBasedRollingPolicyPtr(new TimeBasedRollingPolicy()); |
| tbrp2->setFileNamePattern(LOG4CXX_STR("" DIR_PRE_OUTPUT "test2-%d{" DATE_PATTERN "}")); |
| tbrp2->activateOptions(pool); |
| rfa2->setRollingPolicy(tbrp2); |
| rfa2->activateOptions(pool); |
| rfa2->setAppend(false); |
| logger->addAppender(rfa2); |
| |
| this->logMsgAndSleep( pool, 2, __LOG4CXX_FUNC__, __LINE__, 3); |
| this->compareWitnesses<4>( pool, LOG4CXX_STR("test2."), fnames, __LINE__); |
| } |
| |
| |
| /** |
| * With compression, activeFileName left blank, no stop/restart. |
| */ |
| void test3() |
| { |
| Pool pool; |
| const size_t nrOfFnames(4); |
| LogString fnames[nrOfFnames]; |
| |
| PatternLayoutPtr layout( new PatternLayout(PATTERN_LAYOUT)); |
| RollingFileAppenderPtr rfa( new RollingFileAppender()); |
| rfa->setAppend(false); |
| rfa->setLayout(layout); |
| |
| TimeBasedRollingPolicyPtr tbrp = TimeBasedRollingPolicyPtr(new TimeBasedRollingPolicy()); |
| tbrp->setFileNamePattern(LogString(LOG4CXX_STR("" DIR_PRE_OUTPUT "test3-%d{" DATE_PATTERN "}.gz"))); |
| tbrp->activateOptions(pool); |
| rfa->setRollingPolicy(tbrp); |
| rfa->activateOptions(pool); |
| logger->addAppender(rfa); |
| |
| this->buildTsFnames<4>(pool, LOG4CXX_STR("test3-"), fnames, true); |
| fnames[nrOfFnames - 1].resize(fnames[nrOfFnames - 1].size() - 3); |
| this->delayUntilNextSecondWithMsg(); |
| this->logMsgAndSleep( pool, nrOfFnames + 1, __LOG4CXX_FUNC__, __LINE__); |
| this->checkFilesExist<4>( pool, LOG4CXX_STR("test3."), fnames, nrOfFnames - 1, __LINE__); |
| } |
| |
| /** |
| * Without compression, activeFileName set, with stop/restart |
| * |
| * Note: because this test stops and restarts, it is not possible to use the |
| * date pattern in the filenames, as log4cxx will use the file's last modified |
| * time when rolling over and determining the new filename. |
| */ |
| void test4() |
| { |
| Pool pool; |
| const size_t nrOfFnames(4); |
| const size_t nrOfLogMsgs(((nrOfFnames - 1) * 2) - 1); |
| LogString fnames[nrOfFnames]; |
| |
| PatternLayoutPtr layout1(new PatternLayout(PATTERN_LAYOUT)); |
| RollingFileAppenderPtr rfa1( new RollingFileAppender()); |
| rfa1->setLayout(layout1); |
| |
| TimeBasedRollingPolicyPtr tbrp1 = TimeBasedRollingPolicyPtr(new TimeBasedRollingPolicy()); |
| tbrp1->setFileNamePattern(LOG4CXX_STR("" DIR_PRE_OUTPUT "test4-%d{" DATE_PATTERN "}")); |
| tbrp1->activateOptions(pool); |
| rfa1->setFile(LOG4CXX_STR("" DIR_PRE_OUTPUT "test4.log")); |
| rfa1->setRollingPolicy(tbrp1); |
| rfa1->activateOptions(pool); |
| logger->addAppender(rfa1); |
| |
| this->delGenericLogFile(pool, rfa1->getFile()); |
| this->buildTsFnames<4>(pool, LOG4CXX_STR("test4-"), fnames); |
| fnames[0].assign(rfa1->getFile()); |
| this->delayUntilNextSecondWithMsg(); |
| this->logMsgAndSleep(pool, nrOfLogMsgs, __LOG4CXX_FUNC__, __LINE__); |
| |
| logger->removeAppender(rfa1); |
| rfa1->close(); |
| |
| PatternLayoutPtr layout2(new PatternLayout(PATTERN_LAYOUT)); |
| RollingFileAppenderPtr rfa2( new RollingFileAppender()); |
| rfa2->setLayout(layout2); |
| |
| TimeBasedRollingPolicyPtr tbrp2 = TimeBasedRollingPolicyPtr(new TimeBasedRollingPolicy()); |
| tbrp2->setFileNamePattern(LOG4CXX_STR("" DIR_PRE_OUTPUT "test4-%d{" DATE_PATTERN "}")); |
| tbrp2->activateOptions(pool); |
| rfa2->setFile(rfa1->getFile()); |
| rfa2->setRollingPolicy(tbrp2); |
| rfa2->activateOptions(pool); |
| logger->addAppender(rfa2); |
| |
| // The one file not checked is the active file from the old appender reused by the new one |
| // and rolled over afterwards. The problem is that because the reused file exists already, |
| // it doesn't get an expected fname, but the last write time instead. Though, should be safe |
| // enough to not check that special file. |
| this->logMsgAndSleep(pool, 2, __LOG4CXX_FUNC__, __LINE__, nrOfLogMsgs); |
| this->compareWitness(pool, LOG4CXX_STR("test4."), fnames[0], 0, __LINE__); |
| this->compareWitness(pool, LOG4CXX_STR("test4."), fnames[1], 1, __LINE__); |
| this->compareWitness(pool, LOG4CXX_STR("test4."), fnames[2], 2, __LINE__); |
| } |
| |
| /** |
| * No compression, activeFileName set, without stop/restart. |
| */ |
| void test5() |
| { |
| Pool pool; |
| const size_t nrOfFnames(4); |
| const size_t nrOfLogMsgs((nrOfFnames * 2) - 1); |
| LogString fnames[nrOfFnames]; |
| |
| PatternLayoutPtr layout( new PatternLayout(PATTERN_LAYOUT)); |
| RollingFileAppenderPtr rfa( new RollingFileAppender()); |
| rfa->setLayout(layout); |
| |
| TimeBasedRollingPolicyPtr tbrp = TimeBasedRollingPolicyPtr(new TimeBasedRollingPolicy()); |
| tbrp->setFileNamePattern(LOG4CXX_STR("" DIR_PRE_OUTPUT "test5-%d{" DATE_PATTERN "}")); |
| rfa->setFile(LOG4CXX_STR("" DIR_PRE_OUTPUT "test5.log")); |
| |
| tbrp->activateOptions(pool); |
| rfa->setRollingPolicy(tbrp); |
| rfa->activateOptions(pool); |
| logger->addAppender(rfa); |
| |
| this->delGenericLogFile(pool, rfa->getFile()); |
| this->buildTsFnames<4>(pool, LOG4CXX_STR("test5-"), fnames); |
| fnames[0].assign(rfa->getFile()); |
| |
| this->delayUntilNextSecondWithMsg(); |
| this->logMsgAndSleep( pool, nrOfLogMsgs, __LOG4CXX_FUNC__, __LINE__); |
| this->compareWitnesses<4>( pool, LOG4CXX_STR("test5."), fnames, __LINE__); |
| } |
| |
| /** |
| * With compression, activeFileName set, no stop/restart. |
| */ |
| void test6() |
| { |
| Pool pool; |
| const size_t nrOfFnames(4); |
| const size_t nrOfLogMsgs((nrOfFnames * 2) - 1); |
| LogString fnames[nrOfFnames]; |
| |
| PatternLayoutPtr layout( new PatternLayout(PATTERN_LAYOUT)); |
| RollingFileAppenderPtr rfa( new RollingFileAppender()); |
| rfa->setAppend(false); |
| rfa->setLayout(layout); |
| |
| TimeBasedRollingPolicyPtr tbrp = TimeBasedRollingPolicyPtr(new TimeBasedRollingPolicy()); |
| tbrp->setFileNamePattern(LogString(LOG4CXX_STR("" DIR_PRE_OUTPUT "test6-%d{" DATE_PATTERN "}.gz"))); |
| rfa->setFile(LOG4CXX_STR("" DIR_PRE_OUTPUT "test6.log")); |
| tbrp->activateOptions(pool); |
| rfa->setRollingPolicy(tbrp); |
| rfa->activateOptions(pool); |
| logger->addAppender(rfa); |
| |
| this->delGenericLogFile(pool, rfa->getFile()); |
| this->buildTsFnames<4>(pool, LOG4CXX_STR("test6-"), fnames, true); |
| fnames[0].assign(rfa->getFile()); |
| |
| this->delayUntilNextSecondWithMsg(); |
| this->logMsgAndSleep( pool, nrOfLogMsgs, __LOG4CXX_FUNC__, __LINE__); |
| this->checkFilesExist( pool, LOG4CXX_STR("test6."), fnames, 0, __LINE__); |
| } |
| |
| /** |
| * Repeat some tests with generic file names. |
| * <p> |
| * This test calls some tests which use generic file names and will only work properly if those |
| * got deleted before running the test during setup. |
| * </p> |
| */ |
| void test7() |
| { |
| typedef void (TimeBasedRollingTest::*Test)(); |
| typedef std::vector<Test> Tests; |
| |
| Tests tests(10); |
| size_t numTest = 0; |
| |
| tests.at(4) = &TimeBasedRollingTest::test4; |
| tests.at(5) = &TimeBasedRollingTest::test5; |
| tests.at(6) = &TimeBasedRollingTest::test6; |
| |
| for (size_t numTest = 1; numTest < tests.size(); ++numTest) |
| { |
| Test test(tests.at(numTest)); |
| if (!test) |
| { |
| continue; |
| } |
| |
| this->setUpCurrTime(); |
| (this->*test)(); |
| } |
| } |
| |
| void rollIntoDir() |
| { |
| Pool pool; |
| const size_t nrOfFnames(4); |
| const size_t nrOfLogMsgs((nrOfFnames * 2) - 1); |
| LogString fnames[nrOfFnames]; |
| |
| PatternLayoutPtr layout( new PatternLayout(PATTERN_LAYOUT)); |
| RollingFileAppenderPtr rfa( new RollingFileAppender()); |
| rfa->setLayout(layout); |
| rfa->setFile(LOG4CXX_STR("" DIR_PRE_OUTPUT "rollIntoDir.log")); |
| |
| std::random_device dev; |
| std::mt19937 rng(dev()); |
| std::uniform_int_distribution<std::mt19937::result_type> dist(1,100000); |
| LogString filenamePattern = LOG4CXX_STR("" DIR_PRE_OUTPUT); |
| LogString dirNumber; |
| StringHelper::toString(dist(rng), dirNumber); |
| LogString directoryName = LOG4CXX_STR("tbr-rollIntoDir-"); |
| directoryName.append( dirNumber ); |
| filenamePattern.append( directoryName ); |
| LogString filenamePatternPrefix = filenamePattern; |
| filenamePattern.append( LOG4CXX_STR("/file-%d{" DATE_PATTERN "}") ); |
| |
| TimeBasedRollingPolicyPtr tbrp(new TimeBasedRollingPolicy()); |
| tbrp->setFileNamePattern(filenamePattern); |
| tbrp->activateOptions(pool); |
| rfa->setRollingPolicy(tbrp); |
| rfa->activateOptions(pool); |
| logger->addAppender(rfa); |
| |
| const logchar* prefix = directoryName.append(LOG4CXX_STR("/file-")).data(); |
| |
| this->delGenericLogFile(pool, rfa->getFile()); |
| this->buildTsFnames<4>(pool, prefix, fnames); |
| fnames[0].assign(rfa->getFile()); |
| |
| this->delayUntilNextSecondWithMsg(); |
| this->logMsgAndSleep( pool, nrOfLogMsgs, __LOG4CXX_FUNC__, __LINE__); |
| this->checkFilesExist( pool, LOG4CXX_STR("test6."), fnames, 0, __LINE__); |
| } |
| |
| }; |
| |
| LOGUNIT_TEST_SUITE_REGISTRATION(TimeBasedRollingTest); |