/*
 * 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 "logunit.h"

#include <log4cxx/logger.h>
#include <log4cxx/logmanager.h>
#include <log4cxx/simplelayout.h>
#include "vectorappender.h"
#include <log4cxx/asyncappender.h>
#include "appenderskeletontestcase.h"
#include <log4cxx/helpers/pool.h>
#include <apr_strings.h>
#include "testchar.h"
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/helpers/synchronized.h>
#include <log4cxx/spi/location/locationinfo.h>
#include <log4cxx/xml/domconfigurator.h>
#include <log4cxx/file.h>

using namespace log4cxx;
using namespace log4cxx::helpers;
using namespace log4cxx::spi;

class NullPointerAppender : public AppenderSkeleton
{
	public:
		NullPointerAppender()
		{
		}


		/**
		 * @{inheritDoc}
		 */
		void append(const spi::LoggingEventPtr&, log4cxx::helpers::Pool&)
		{
			throw NullPointerException(LOG4CXX_STR("Intentional NullPointerException"));
		}

		void close()
		{
		}

		bool requiresLayout() const
		{
			return false;
		}
};

/**
 * Vector appender that can be explicitly blocked.
 */
class BlockableVectorAppender : public VectorAppender
{
	private:
		Mutex blocker;
	public:
		/**
		 * Create new instance.
		 */
		BlockableVectorAppender() : blocker(pool)
		{
		}

		/**
		 * {@inheritDoc}
		 */
		void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p)
		{
			synchronized sync(blocker);
			VectorAppender::append(event, p);

			//
			//   if fatal, echo messages for testLoggingInDispatcher
			//
			if (event->getLevel() == Level::getInfo())
			{
				LoggerPtr logger = Logger::getLoggerLS(event->getLoggerName());
				LOG4CXX_LOGLS(logger, Level::getError(), event->getMessage());
				LOG4CXX_LOGLS(logger, Level::getWarn(), event->getMessage());
				LOG4CXX_LOGLS(logger, Level::getInfo(), event->getMessage());
				LOG4CXX_LOGLS(logger, Level::getDebug(), event->getMessage());
			}
		}

		Mutex& getBlocker()
		{
			return blocker;
		}

};

typedef helpers::ObjectPtrT<BlockableVectorAppender> BlockableVectorAppenderPtr;

#if APR_HAS_THREADS
/**
 * Tests of AsyncAppender.
 */
class AsyncAppenderTestCase : public AppenderSkeletonTestCase
{
        LOGUNIT_TEST_SUITE(AsyncAppenderTestCase);
                //
                //    tests inherited from AppenderSkeletonTestCase
                //
                LOGUNIT_TEST(testDefaultThreshold);
                LOGUNIT_TEST(testSetOptionThreshold);

                LOGUNIT_TEST(closeTest);
                LOGUNIT_TEST(test2);
                LOGUNIT_TEST(test3);
                //
                //   TODO: test fails on Linux.
                //LOGUNIT_TEST(testBadAppender);
                LOGUNIT_TEST(testLocationInfoTrue);
                LOGUNIT_TEST(testConfiguration);
        LOGUNIT_TEST_SUITE_END();


public:
        void setUp() {
           AppenderSkeletonTestCase::setUp();
        }

        void tearDown()
        {
                LogManager::shutdown();
                AppenderSkeletonTestCase::tearDown();
        }

        AppenderSkeleton* createAppenderSkeleton() const {
          return new AsyncAppender();
        }

        // this test checks whether it is possible to write to a closed AsyncAppender
        void closeTest() 
        {
                LoggerPtr root = Logger::getRootLogger();
                LayoutPtr layout = new SimpleLayout();
                VectorAppenderPtr vectorAppender = new VectorAppender();
                AsyncAppenderPtr asyncAppender = new AsyncAppender();
                asyncAppender->setName(LOG4CXX_STR("async-CloseTest"));
                asyncAppender->addAppender(vectorAppender);
                root->addAppender(asyncAppender);

                root->debug(LOG4CXX_TEST_STR("m1"));
                asyncAppender->close();
                root->debug(LOG4CXX_TEST_STR("m2"));

                const std::vector<spi::LoggingEventPtr>& v = vectorAppender->getVector();
                LOGUNIT_ASSERT_EQUAL((size_t) 1, v.size());
        }

        // this test checks whether appenders embedded within an AsyncAppender are also
        // closed
        void test2()
        {
                LoggerPtr root = Logger::getRootLogger();
                LayoutPtr layout = new SimpleLayout();
                VectorAppenderPtr vectorAppender = new VectorAppender();
                AsyncAppenderPtr asyncAppender = new AsyncAppender();
                asyncAppender->setName(LOG4CXX_STR("async-test2"));
                asyncAppender->addAppender(vectorAppender);
                root->addAppender(asyncAppender);

                root->debug(LOG4CXX_TEST_STR("m1"));
                asyncAppender->close();
                root->debug(LOG4CXX_TEST_STR("m2"));

                const std::vector<spi::LoggingEventPtr>& v = vectorAppender->getVector();
                LOGUNIT_ASSERT_EQUAL((size_t) 1, v.size());
                LOGUNIT_ASSERT(vectorAppender->isClosed());
        }

        // this test checks whether appenders embedded within an AsyncAppender are also
        // closed
        void test3()
        {
                size_t LEN = 200;
                LoggerPtr root = Logger::getRootLogger();
                VectorAppenderPtr vectorAppender = new VectorAppender();
                AsyncAppenderPtr asyncAppender = new AsyncAppender();
                asyncAppender->setName(LOG4CXX_STR("async-test3"));
                asyncAppender->addAppender(vectorAppender);
                root->addAppender(asyncAppender);

                for (size_t i = 0; i < LEN; i++) {
                        LOG4CXX_DEBUG(root, "message" << i);
                }

                asyncAppender->close();
                root->debug(LOG4CXX_TEST_STR("m2"));

                const std::vector<spi::LoggingEventPtr>& v = vectorAppender->getVector();
                LOGUNIT_ASSERT_EQUAL(LEN, v.size());
                LOGUNIT_ASSERT_EQUAL(true, vectorAppender->isClosed());
        }
        
    /**
     * Tests that a bad appender will switch async back to sync.
     */
    void testBadAppender() {
        AppenderPtr nullPointerAppender = new NullPointerAppender();
        AsyncAppenderPtr asyncAppender = new AsyncAppender();
        asyncAppender->addAppender(nullPointerAppender);
        asyncAppender->setBufferSize(5);
        Pool p;
        asyncAppender->activateOptions(p);
        LoggerPtr root = Logger::getRootLogger();
        root->addAppender(asyncAppender);
        LOG4CXX_INFO(root, "Message");
        Thread::sleep(10);
        try {
           LOG4CXX_INFO(root, "Message");
           LOGUNIT_FAIL("Should have thrown exception");
        } catch(NullPointerException&) {
        }
    }
    
    /**
     * Tests non-blocking behavior.
     */
    void testLocationInfoTrue() {
        BlockableVectorAppenderPtr blockableAppender = new BlockableVectorAppender();
        AsyncAppenderPtr async = new AsyncAppender();
        async->addAppender(blockableAppender);
        async->setBufferSize(5);
        async->setLocationInfo(true);
        async->setBlocking(false);
        Pool p;
        async->activateOptions(p);
        LoggerPtr rootLogger = Logger::getRootLogger();
        rootLogger->addAppender(async);
        {
            synchronized sync(blockableAppender->getBlocker());
            for (int i = 0; i < 140; i++) {
                   LOG4CXX_INFO(rootLogger, "Hello, World");
                   Thread::sleep(1);
            }
            LOG4CXX_ERROR(rootLogger, "That's all folks.");
        }
        async->close();
        const std::vector<spi::LoggingEventPtr>& events = blockableAppender->getVector();
        LOGUNIT_ASSERT(events.size() > 0);
        LoggingEventPtr initialEvent = events[0];
        LoggingEventPtr discardEvent = events[events.size() - 1];
        LOGUNIT_ASSERT(initialEvent->getMessage() == LOG4CXX_STR("Hello, World"));
        LOGUNIT_ASSERT(discardEvent->getMessage().substr(0,10) == LOG4CXX_STR("Discarded "));
        LOGUNIT_ASSERT_EQUAL(log4cxx::spi::LocationInfo::getLocationUnavailable().getClassName(), 
            discardEvent->getLocationInformation().getClassName()); 
    }
    
        void testConfiguration() {
              log4cxx::xml::DOMConfigurator::configure("input/xml/asyncAppender1.xml");
              AsyncAppenderPtr asyncAppender(Logger::getRootLogger()->getAppender(LOG4CXX_STR("ASYNC")));
              LOGUNIT_ASSERT(!(asyncAppender == 0));
              LOGUNIT_ASSERT_EQUAL(100, asyncAppender->getBufferSize());
              LOGUNIT_ASSERT_EQUAL(false, asyncAppender->getBlocking());
              LOGUNIT_ASSERT_EQUAL(true, asyncAppender->getLocationInfo());
              AppenderList nestedAppenders(asyncAppender->getAllAppenders());
              //   TODO:
              //   test seems to work okay, but have not found a working way to 
              //      get a reference to the nested vector appender 
              //
//              LOGUNIT_ASSERT_EQUAL((size_t) 1, nestedAppenders.size());
//              VectorAppenderPtr vectorAppender(nestedAppenders[0]);
//              LOGUNIT_ASSERT(0 != vectorAppender);
              LoggerPtr root(Logger::getRootLogger()); 
              
              size_t LEN = 20;
              for (size_t i = 0; i < LEN; i++) {
                        LOG4CXX_DEBUG(root, "message" << i);
              }
              
              asyncAppender->close();
//              const std::vector<spi::LoggingEventPtr>& v = vectorAppender->getVector();
//              LOGUNIT_ASSERT_EQUAL(LEN, v.size());
//              LOGUNIT_ASSERT_EQUAL(true, vectorAppender->isClosed());
        }


};        

LOGUNIT_TEST_SUITE_REGISTRATION(AsyncAppenderTestCase);
#endif
