| /* | |
| * 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 <log4cxx/net/telnetappender.h> | |
| #include <log4cxx/basicconfigurator.h> | |
| #include <log4cxx/file.h> | |
| #include <log4cxx/patternlayout.h> | |
| #include "../appenderskeletontestcase.h" | |
| #include <log4cxx/helpers/inetaddress.h> | |
| #include <log4cxx/helpers/stringhelper.h> | |
| #include <log4cxx/helpers/loglog.h> | |
| #include <log4cxx/helpers/fileoutputstream.h> | |
| #include <log4cxx/helpers/pool.h> | |
| #include <log4cxx/config/propertysetter.h> | |
| #include <log4cxx/helpers/transcoder.h> | |
| #include <log4cxx/helpers/exception.h> | |
| #include <log4cxx/helpers/socket.h> | |
| #include <log4cxx/spi/configurator.h> | |
| #include <apr_thread_proc.h> | |
| #include <apr_time.h> | |
| using namespace log4cxx; | |
| using namespace log4cxx::helpers; | |
| using namespace log4cxx::net; | |
| /** | |
| Unit tests of log4cxx::TelnetAppender | |
| */ | |
| class TelnetAppenderTestCase : public AppenderSkeletonTestCase | |
| { | |
| LOGUNIT_TEST_SUITE(TelnetAppenderTestCase); | |
| // | |
| // tests inherited from AppenderSkeletonTestCase | |
| // | |
| LOGUNIT_TEST(testDefaultThreshold); | |
| LOGUNIT_TEST(testSetOptionThreshold); | |
| LOGUNIT_TEST(testActivateClose); | |
| LOGUNIT_TEST(testActivateSleepClose); | |
| LOGUNIT_TEST(testActivateWriteClose); | |
| LOGUNIT_TEST(testConnectNoRead); | |
| LOGUNIT_TEST(testActivateWriteNoClose); | |
| LOGUNIT_TEST(testInvalidMaxConnectionsOptionFallsBack); | |
| LOGUNIT_TEST_SUITE_END(); | |
| enum { TEST_PORT = 1723 }; | |
| static LayoutPtr createLayout() | |
| { | |
| PatternLayoutPtr pl = std::make_shared<PatternLayout>(); | |
| pl->setConversionPattern( LOG4CXX_STR("%r [%t] %-5p - %m%n") ); | |
| return pl; | |
| } | |
| public: | |
| AppenderSkeleton* createAppenderSkeleton() const | |
| { | |
| return new log4cxx::net::TelnetAppender(); | |
| } | |
| void testActivateClose() | |
| { | |
| TelnetAppenderPtr appender(new TelnetAppender()); | |
| appender->setLayout(createLayout()); | |
| appender->setPort(TEST_PORT); | |
| appender->activateOptions(); | |
| appender->close(); | |
| } | |
| void testActivateSleepClose() | |
| { | |
| TelnetAppenderPtr appender(new TelnetAppender()); | |
| appender->setLayout(createLayout()); | |
| appender->setPort(TEST_PORT); | |
| appender->activateOptions(); | |
| apr_sleep(100000); // 100 milliseconds | |
| appender->close(); | |
| } | |
| void testActivateWriteClose() | |
| { | |
| auto internalDebugging = helpers::LogLog::isDebugEnabled(); | |
| if (!internalDebugging) | |
| helpers::LogLog::setInternalDebugging(true); | |
| auto appender = std::make_shared<TelnetAppender>(); | |
| appender->setLayout(createLayout()); | |
| appender->setPort(TEST_PORT); | |
| appender->setReuseAddress(true); | |
| appender->setNonBlocking(true); | |
| appender->activateOptions(); | |
| BasicConfigurator::configure(appender); | |
| auto root = Logger::getRootLogger(); | |
| apr_sleep(200000); // 200 milliseconds | |
| for (int i = 0; i < 100000; ++i) | |
| { | |
| LOG4CXX_INFO(root, "Hello, World " << i); | |
| } | |
| appender->close(); | |
| root->removeAppender(appender); | |
| if (!internalDebugging) | |
| helpers::LogLog::setInternalDebugging(false); | |
| } | |
| void testActivateWriteNoClose() | |
| { | |
| auto appender = std::make_shared<TelnetAppender>(); | |
| appender->setPort(TEST_PORT); | |
| appender->setMaxConnections(1); | |
| appender->setReuseAddress(true); | |
| appender->setHostname(LOG4CXX_STR("127.0.0.1")); | |
| appender->activateOptions(); | |
| BasicConfigurator::configure(appender); | |
| auto root = Logger::getRootLogger(); | |
| for (int i = 0; i < 50; i++) | |
| { | |
| //#define ALLOW_TESTING_WITH_TELNET | |
| #ifdef ALLOW_TESTING_WITH_TELNET | |
| std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) ); | |
| #endif | |
| LOG4CXX_INFO(root, "Hello, World " << i); | |
| } | |
| } | |
| void testInvalidMaxConnectionsOptionFallsBack() | |
| { | |
| auto appender = std::make_shared<TelnetAppender>(); | |
| config::PropertySetter setter(appender); | |
| setter.setProperty(LOG4CXX_STR("MaxConnections"), LOG4CXX_STR("9999999999999999999999")); | |
| LOGUNIT_ASSERT_EQUAL(20, appender->getMaxConnections()); | |
| setter.setProperty(LOG4CXX_STR("MaxConnections"), LOG4CXX_STR("-2147483649")); | |
| LOGUNIT_ASSERT_EQUAL(20, appender->getMaxConnections()); | |
| setter.setProperty(LOG4CXX_STR("MaxConnections"), LOG4CXX_STR("16")); | |
| LOGUNIT_ASSERT_EQUAL(16, appender->getMaxConnections()); | |
| } | |
| void testConnectNoRead() | |
| { | |
| auto thisProgram = GetExecutableFileName(); | |
| helpers::Pool p; | |
| bool thisProgramExists = File(thisProgram).exists(); | |
| LOGUNIT_ASSERT(thisProgramExists); | |
| const char* args[] = {thisProgram.c_str(), "testActivateWriteClose", 0}; | |
| apr_procattr_t* attr = NULL; | |
| helpers::FileOutputStream output(LOG4CXX_STR("output/testConnectNoRead.log"), false); | |
| setTestAttributes(&attr, output.getFilePtr(), p); | |
| apr_proc_t pid; | |
| startTestInstance(&pid, attr, args, p); | |
| apr_sleep(100000); // 100 milliseconds | |
| auto addr = helpers::InetAddress::getByName(LOG4CXX_STR("127.0.0.1")); | |
| auto s = helpers::Socket::create(addr, TEST_PORT); // Opens a connection | |
| int exitCode; | |
| apr_exit_why_e reason; | |
| apr_proc_wait(&pid, &exitCode, &reason, APR_WAIT); | |
| if (exitCode != 0 && helpers::LogLog::isDebugEnabled()) | |
| { | |
| helpers::LogLog::debug(helpers::SubProcessFailure::makeMessage(LOG4CXX_STR("child"), exitCode, reason)); | |
| } | |
| LOGUNIT_ASSERT_EQUAL(exitCode, 0); | |
| } | |
| private: | |
| void setTestAttributes(apr_procattr_t** attr, apr_file_t* output, helpers::Pool& p) | |
| { | |
| if (apr_procattr_create(attr, p.getAPRPool()) != APR_SUCCESS) | |
| { | |
| LOGUNIT_FAIL("apr_procattr_create"); | |
| } | |
| if (apr_procattr_cmdtype_set(*attr, APR_PROGRAM_ENV) != APR_SUCCESS) | |
| { | |
| LOGUNIT_FAIL("apr_procattr_cmdtype_set"); | |
| } | |
| if (apr_procattr_child_out_set(*attr, output, NULL) != APR_SUCCESS) | |
| { | |
| LOGUNIT_FAIL("apr_procattr_child_out_set"); | |
| } | |
| if (apr_procattr_child_err_set(*attr, output, NULL) != APR_SUCCESS) | |
| { | |
| LOGUNIT_FAIL("apr_procattr_child_err_set"); | |
| } | |
| } | |
| void startTestInstance(apr_proc_t* pid, apr_procattr_t* attr, const char** argv, helpers::Pool& p) | |
| { | |
| if (apr_proc_create(pid, argv[0], argv, NULL, attr, p.getAPRPool()) != APR_SUCCESS) | |
| { | |
| LOGUNIT_FAIL("apr_proc_create"); | |
| } | |
| } | |
| std::string GetExecutableFileName() | |
| { | |
| auto lsProgramFilePath = spi::Configurator::properties().getProperty(LOG4CXX_STR("PROGRAM_FILE_PATH")); | |
| LOG4CXX_ENCODE_CHAR(programFilePath, lsProgramFilePath); | |
| return programFilePath; | |
| } | |
| }; | |
| LOGUNIT_TEST_SUITE_REGISTRATION(TelnetAppenderTestCase); |