You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by sw...@apache.org on 2022/10/03 06:39:49 UTC

[logging-log4cxx] branch next_stable updated: Document DefaultConfigurator actual behaviour (#137)

This is an automated email from the ASF dual-hosted git repository.

swebb2066 pushed a commit to branch next_stable
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git


The following commit(s) were added to refs/heads/next_stable by this push:
     new 633b8575 Document DefaultConfigurator actual behaviour (#137)
633b8575 is described below

commit 633b8575165d158e00c38e8261bb5f3d1b312df6
Author: Stephen Webb <st...@ieee.org>
AuthorDate: Mon Oct 3 17:39:44 2022 +1100

    Document DefaultConfigurator actual behaviour (#137)
    
    * Allow program specification of DefaultConfigurator attributes (as a result, autoconfiguretestcase no longer needs special environment variables)
    
    * Make '#ifdef _DEBUG' true in tests in a Debug build on a non-Windows platform
---
 src/main/cpp/defaultconfigurator.cpp           | 46 +++++++++++++----
 src/main/include/log4cxx/defaultconfigurator.h | 40 ++++++++++-----
 src/test/cpp/CMakeLists.txt                    | 26 +++++-----
 src/test/cpp/autoconfiguretestcase.cpp         | 71 +++++++++++++++++++++++---
 4 files changed, 141 insertions(+), 42 deletions(-)

diff --git a/src/main/cpp/defaultconfigurator.cpp b/src/main/cpp/defaultconfigurator.cpp
index eb6c26a8..db01845d 100644
--- a/src/main/cpp/defaultconfigurator.cpp
+++ b/src/main/cpp/defaultconfigurator.cpp
@@ -28,16 +28,37 @@ using namespace log4cxx;
 using namespace log4cxx::spi;
 using namespace log4cxx::helpers;
 
+namespace 
+{
+	LogString DefaultConfiguratorPath;
+	int DefaultConfiguratorWatchSeconds = 0;
+}
+
+void DefaultConfigurator::setConfigurationFileName(const LogString& path)
+{
+	DefaultConfiguratorPath = path;
+}
+
+
+void DefaultConfigurator::setConfigurationWatchSeconds(int seconds)
+{
+	DefaultConfiguratorWatchSeconds = seconds;
+}
+
+static const int MillisecondsPerSecond = 1000;
+
 void DefaultConfigurator::configure(LoggerRepositoryPtr repository)
 {
 	repository->setConfigured(true);
 	const LogString configuratorClassName(getConfiguratorClass());
 
-	LogString configurationOptionStr(getConfigurationFileName());
+	LogString configurationFileName = DefaultConfiguratorPath;
+	if (configurationFileName.empty())
+		configurationFileName = getConfigurationFileName();
 	Pool pool;
 	File configuration;
 
-	if (configurationOptionStr.empty())
+	if (configurationFileName.empty())
 	{
 		const char* names[] = { "log4cxx.xml", "log4cxx.properties", "log4j.xml", "log4j.properties", 0 };
 
@@ -54,7 +75,7 @@ void DefaultConfigurator::configure(LoggerRepositoryPtr repository)
 	}
 	else
 	{
-		configuration.setPath(configurationOptionStr);
+		configuration.setPath(configurationFileName);
 	}
 
 	if (configuration.exists(pool))
@@ -69,18 +90,21 @@ void DefaultConfigurator::configure(LoggerRepositoryPtr repository)
 			configuration,
 			configuratorClassName,
 			repo,
-			getConfigurationWatchDelay());
+			0 < DefaultConfiguratorWatchSeconds
+				? DefaultConfiguratorWatchSeconds * MillisecondsPerSecond
+				: getConfigurationWatchDelay()
+			);
 	}
 	else
 	{
-		if (configurationOptionStr.empty())
+		if (configurationFileName.empty())
 		{
 			LogLog::debug(LOG4CXX_STR("Could not find default configuration file."));
 		}
 		else
 		{
 			LogString msg(LOG4CXX_STR("Could not find configuration file: ["));
-			msg += configurationOptionStr;
+			msg += configurationFileName;
 			msg += LOG4CXX_STR("].");
 			LogLog::debug(msg);
 		}
@@ -106,12 +130,12 @@ const LogString DefaultConfigurator::getConfigurationFileName()
 {
 	static const LogString LOG4CXX_DEFAULT_CONFIGURATION_KEY(LOG4CXX_STR("LOG4CXX_CONFIGURATION"));
 	static const LogString LOG4J_DEFAULT_CONFIGURATION_KEY(LOG4CXX_STR("log4j.configuration"));
-	const LogString log4jConfigurationOptionStr(
+	const LogString log4jConfigurationFileName(
 		OptionConverter::getSystemProperty(LOG4J_DEFAULT_CONFIGURATION_KEY, LOG4CXX_STR("")));
-	const LogString configurationOptionStr(
+	const LogString configurationFileName(
 		OptionConverter::getSystemProperty(LOG4CXX_DEFAULT_CONFIGURATION_KEY,
-			log4jConfigurationOptionStr));
-	return configurationOptionStr;
+			log4jConfigurationFileName));
+	return configurationFileName;
 }
 
 
@@ -121,7 +145,7 @@ int DefaultConfigurator::getConfigurationWatchDelay()
 	LogString optionStr = OptionConverter::getSystemProperty(LOG4CXX_DEFAULT_CONFIGURATION_WATCH_KEY, LogString());
 	int milliseconds = 0;
 	if (!optionStr.empty())
-		milliseconds = StringHelper::toInt(optionStr) * 1000;
+		milliseconds = StringHelper::toInt(optionStr) * MillisecondsPerSecond;
 	return milliseconds;
 }
 
diff --git a/src/main/include/log4cxx/defaultconfigurator.h b/src/main/include/log4cxx/defaultconfigurator.h
index d5d3f554..9c296b62 100644
--- a/src/main/include/log4cxx/defaultconfigurator.h
+++ b/src/main/include/log4cxx/defaultconfigurator.h
@@ -19,14 +19,10 @@
 #define _LOG4CXX_DEFAULT_CONFIGURATOR_H
 
 #include <log4cxx/spi/configurator.h>
+#include <log4cxx/spi/loggerrepository.h>
 
 namespace log4cxx
 {
-namespace spi
-{
-class LoggerRepository;
-typedef std::shared_ptr<LoggerRepository> LoggerRepositoryPtr;
-}
 
 /**
  *   Configures the repository from environmental settings and files.
@@ -39,19 +35,39 @@ class LOG4CXX_EXPORT DefaultConfigurator
 
 	public:
 		/**
-		Add a ConsoleAppender that uses PatternLayout
-		using the PatternLayout#TTCC_CONVERSION_PATTERN and
-		prints to <code>stdout</code> to the root logger.*/
-		static void configure(log4cxx::spi::LoggerRepositoryPtr repository);
+		Configure \c repository.
+
+		If the configuration file name has not been provided by a call to setConfigurationFileName(),
+		the environment variables 'LOG4CXX_CONFIGURATION' and 'log4j.configuration' are examined.
+
+		If the configuration file name has not been provided by any of the previous approaches
+		the current directory is examined for a file named either
+		"log4cxx.xml", "log4cxx.properties", "log4j.xml" or "log4j.properties".
+
+		If a positive number has been provided by a call to setConfigurationWatchSeconds()
+		or the environment variables 'LOG4CXX_CONFIGURATION_WATCH_SECONDS' contains a positive number
+		a background thread is started that will periodically check for a change to the configuration file
+		and apply any configuration changes found.
+		.*/
+		static void configure(spi::LoggerRepositoryPtr repository);
+
+		/**
+		Make \c path the configuration file used by configure().
+		*/
+		static void setConfigurationFileName(const LogString& path);
+
+		/**
+		Make \c seconds the time a background thread will delay before checking
+		for a change to the configuration file used by configure().
+		*/
+		static void setConfigurationWatchSeconds(int seconds);
 
 	private:
 		static const LogString getConfigurationFileName();
 		static const LogString getConfiguratorClass();
 		static int getConfigurationWatchDelay();
 
-
-
-}; // class DefaultConfigurator
+};	 // class DefaultConfigurator
 }  // namespace log4cxx
 
 #endif //_LOG4CXX_DEFAULT_CONFIGURATOR_H
diff --git a/src/test/cpp/CMakeLists.txt b/src/test/cpp/CMakeLists.txt
index 60e9f096..0189b583 100644
--- a/src/test/cpp/CMakeLists.txt
+++ b/src/test/cpp/CMakeLists.txt
@@ -105,11 +105,18 @@ if( WIN32 )
   foreach( ENTRY ${PATH_FOR_TESTS}${NORMAL_PATH} )
 	  set(ESCAPED_PATH "${ESCAPED_PATH}${ENTRY}\\\;")
   endforeach()
-endif( WIN32 )
+elseif(CMAKE_BUILD_TYPE)
+  string(TOUPPER ${CMAKE_BUILD_TYPE} UPPER_BUILD_TYPE)
+  if (UPPER_BUILD_TYPE STREQUAL "DEBUG")
+    set(TEST_COMPILE_DEFINITIONS _DEBUG)
+  endif()
+else()
+  set(TEST_COMPILE_DEFINITIONS _DEBUG)
+endif()
 
 get_filename_component(UNIT_TEST_WORKING_DIR ../resources ABSOLUTE)
 foreach(testName IN LISTS ALL_LOG4CXX_TESTS)
-    target_compile_definitions(${testName} PRIVATE ${LOG4CXX_COMPILE_DEFINITIONS} ${APR_COMPILE_DEFINITIONS} ${APR_UTIL_COMPILE_DEFINITIONS} )
+    target_compile_definitions(${testName} PRIVATE ${TEST_COMPILE_DEFINITIONS} ${LOG4CXX_COMPILE_DEFINITIONS} ${APR_COMPILE_DEFINITIONS} ${APR_UTIL_COMPILE_DEFINITIONS} )
     target_include_directories(${testName} PRIVATE ${CMAKE_CURRENT_LIST_DIR} $<TARGET_PROPERTY:log4cxx,INCLUDE_DIRECTORIES>)
     target_link_libraries(${testName} PRIVATE testingFramework testingUtilities log4cxx ${APR_LIBRARIES} ${APR_SYSTEM_LIBS} Threads::Threads)
     add_test(NAME ${testName}
@@ -132,13 +139,6 @@ foreach(testName IN LISTS ALL_LOG4CXX_TESTS)
             set_tests_properties(socketservertestcase PROPERTIES
                 ENVIRONMENT "SOCKET_SERVER_PARAMETER_FILE=${START_SOCKET_SERVER_PARAMETER_FILE};PATH=${ESCAPED_PATH}"
             )
-        elseif(${testName} STREQUAL autoconfiguretestcase)
-            set_target_properties(${testName} PROPERTIES
-              VS_DEBUGGER_ENVIRONMENT "LOG4CXX_CONFIGURATION=${UNIT_TEST_WORKING_DIR}/input/autoConfigureTest.properties\nPATH=${ESCAPED_PATH}"
-            )
-            set_tests_properties(autoconfiguretestcase PROPERTIES
-                ENVIRONMENT "LOG4CXX_CONFIGURATION=${UNIT_TEST_WORKING_DIR}/input/autoConfigureTest.properties;LOG4CXX_CONFIGURATION_WATCH_SECONDS=1;PATH=${ESCAPED_PATH}"
-            )
         elseif(${testName} STREQUAL optionconvertertestcase)
             set_target_properties(${testName} PROPERTIES
               VS_DEBUGGER_ENVIRONMENT "TOTO=wonderful\nkey1=value1\nkey2=value2\nPATH=${ESCAPED_PATH}"
@@ -166,13 +166,13 @@ foreach(testName IN LISTS ALL_LOG4CXX_TESTS)
             set_tests_properties(socketservertestcase PROPERTIES
                 ENVIRONMENT "SOCKET_SERVER_PARAMETER_FILE=${START_SOCKET_SERVER_PARAMETER_FILE}"
             )
-        elseif(${testName} STREQUAL autoconfiguretestcase)
-            set_tests_properties(autoconfiguretestcase PROPERTIES
-                ENVIRONMENT "LOG4CXX_CONFIGURATION=${UNIT_TEST_WORKING_DIR}/input/autoConfigureTest.properties"
+        elseif(${testName} STREQUAL optionconvertertestcase)
+            set_tests_properties(optionconvertertestcase PROPERTIES
+                ENVIRONMENT "TOTO=wonderful;key1=value1;key2=value2"
             )
         else()
            set_tests_properties(${testName} PROPERTIES
-                ENVIRONMENT "TOTO=wonderful;key1=value1;key2=value2"
+                ENVIRONMENT "key1=value1;key2=value2"
            )
         endif()
     endif()
diff --git a/src/test/cpp/autoconfiguretestcase.cpp b/src/test/cpp/autoconfiguretestcase.cpp
index 99546660..629ef630 100644
--- a/src/test/cpp/autoconfiguretestcase.cpp
+++ b/src/test/cpp/autoconfiguretestcase.cpp
@@ -17,9 +17,17 @@
 #include "logunit.h"
 #include <log4cxx/logger.h>
 #include <log4cxx/logmanager.h>
+#include <log4cxx/defaultconfigurator.h>
+#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/helpers/fileinputstream.h>
+#include <log4cxx/helpers/fileoutputstream.h>
 #include <log4cxx/helpers/loglog.h>
-#include <log4cxx/file.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/stringhelper.h>
 #include <thread>
+#include <apr_file_io.h>
+#include <apr_file_info.h>
+#include "apr_time.h"
 
 #define LOGUNIT_TEST_THREADS(testName, threadCount) \
 	class testName ## ThreadTestRegistration { \
@@ -45,9 +53,11 @@ using namespace log4cxx;
 LOGUNIT_CLASS(AutoConfigureTestCase)
 {
 	LOGUNIT_TEST_SUITE(AutoConfigureTestCase);
+	LOGUNIT_TEST(copyPropertyFile);
 	LOGUNIT_TEST_THREADS(test1, 4);
 	LOGUNIT_TEST(test2);
-	LOGUNIT_TEST(stop);
+	LOGUNIT_TEST(test3);
+	LOGUNIT_TEST(shutdown);
 	LOGUNIT_TEST_SUITE_END();
 #ifdef _DEBUG
 	struct Fixture
@@ -56,9 +66,35 @@ LOGUNIT_CLASS(AutoConfigureTestCase)
 			helpers::LogLog::setInternalDebugging(true);
 		}
 	} suiteFixture;
+	apr_time_t m_initTime = apr_time_now();
 #endif
+	helpers::Pool m_pool;
+	char m_buf[2048];
+	LogString m_configFile = LOG4CXX_STR("autoConfigureTest.properties");
 public:
-	void test1()
+
+	void copyPropertyFile()
+	{
+		LOGUNIT_ASSERT(File(LOG4CXX_STR("input/autoConfigureTest.properties")).exists(m_pool));
+		LOGUNIT_ASSERT(apr_file_copy
+			( "input/autoConfigureTest.properties"
+			, "autoConfigureTest.properties"
+			, APR_FPROT_UREAD | APR_FPROT_UWRITE
+			, m_pool.getAPRPool()
+			) == APR_SUCCESS);
+
+		DefaultConfigurator::setConfigurationFileName(m_configFile);
+		DefaultConfigurator::setConfigurationWatchSeconds(1);
+		LOGUNIT_ASSERT(File(m_configFile).exists(m_pool));
+	}
+
+	void shutdown()
+	{
+		LogManager::shutdown();
+		LOGUNIT_ASSERT(apr_file_remove("autoConfigureTest.properties", m_pool.getAPRPool()) == APR_SUCCESS);
+	}
+
+	void test1()	
 	{
 		auto debugLogger = LogManager::getLogger(LOG4CXX_STR("AutoConfig.test1"));
 		LOGUNIT_ASSERT(debugLogger);
@@ -70,14 +106,37 @@ public:
 
 	void test2()
 	{
-		auto debugLogger = Logger::getLogger(LOG4CXX_STR("AutoConfig.test2"));
+		auto debugLogger = LogManager::getLogger(LOG4CXX_STR("AutoConfig.test2"));
 		LOGUNIT_ASSERT(debugLogger);
 		LOGUNIT_ASSERT(debugLogger->isDebugEnabled());
 	}
 
-	void stop()
+	void test3()
 	{
-		LogManager::shutdown();
+		// wait 2 sec to ensure the modification time is different to that held in the WatchDog
+		apr_sleep(2000000);
+		auto debugLogger = LogManager::getLogger(LOG4CXX_STR("AutoConfig.test3"));
+		LOGUNIT_ASSERT(debugLogger);
+		LOGUNIT_ASSERT(!debugLogger->isDebugEnabled());
+
+		// Append a configuration for test3 logger
+		helpers::ByteBuffer bbuf(m_buf, sizeof(m_buf));
+		int sz = 0;
+		for (const char* p = "\nlog4j.logger.AutoConfig.test3=DEBUG\n"; *p; ++p)
+		{
+			bbuf.put(*p);
+			++sz;
+		}
+		bbuf.position(0);
+		bbuf.limit(sz);
+		helpers::FileOutputStream of(m_configFile, true);
+		of.write(bbuf, m_pool);
+		of.flush(m_pool);
+		of.close(m_pool);
+
+		// wait 1.5 sec for the change to be noticed
+		apr_sleep(1500000);
+		LOGUNIT_ASSERT(debugLogger->isDebugEnabled());
 	}
 };