/*
 * 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/patternlayout.h>
#include <log4cxx/fileappender.h>
#include <log4cxx/helpers/optionconverter.h>
#include <thread>
#include <vector>
#include <random>
#include <mutex>

using namespace log4cxx;

//#define TEST_WITH_FLUENT_BIT
#ifdef TEST_WITH_FLUENT_BIT
#include <log4cxx/net/xmlsocketappender.h>
#include <log4cxx/jsonlayout.h>
class MyAppender : public net::XMLSocketAppender
{
public:
	MyAppender() : net::XMLSocketAppender(LOG4CXX_STR("127.0.0.1"), 5170)
	{
		auto layout = std::make_shared<JSONLayout>();
		layout->setThreadInfo(true);
		setLayout(layout);
	}
};
#else
class MyAppender : public FileAppender
{
public:
	MyAppender()
	{
		auto tempDir = helpers::OptionConverter::getSystemProperty(LOG4CXX_STR("TEMP"), LOG4CXX_STR("/tmp"));
		setFile(tempDir + LOG4CXX_STR("/") + LOG4CXX_STR("multithread_test.log"));
		setLayout(std::make_shared<PatternLayout>(LOG4CXX_STR("%d [%t] %-5p %.16c - %m%n")));
		setAppend(false);
		setBufferedIO(true);
		helpers::Pool p;
		activateOptions(p);
	}
};
#endif

static void multithread_logger( int times )
{
	/*
	 * An explanation on this test: according to LOGCXX-322, calling
	 * exit(0) (or equivalent) from a secondary thread causes a segfault.
	 *
	 * In order to do this somewhat reliably, we generate a pseudo-random
	 * number in each thread that will call the exit() function from that thread.
	 * Sadly this is not a 100% reliable way of generating a hit on std::exit,
	 * but given enough iterations and enough threads it seems to be working just
	 * fine.
	 */

	static std::once_flag exiting;
	LoggerPtr logger = LogManager::getLogger( "test.multithreaded" );
	std::random_device rd;
	std::mt19937 gen(rd());
	std::uniform_int_distribution<> distribution( 100, times );

	for ( int x = 0; x < times; x++ )
	{
		LOG4CXX_INFO( logger, "This is test message " << x );

		if ( distribution(gen) == x )
		{
			LOG4CXX_INFO( logger, "Exiting");
			std::call_once(exiting, std::exit, 0);
		}
	}
}

LOGUNIT_CLASS(MultithreadTest)
{
	LOGUNIT_TEST_SUITE(MultithreadTest);
	LOGUNIT_TEST(testMultithreadedLoggers);
	LOGUNIT_TEST_SUITE_END();

public:
	void setUp()
	{
		Logger::getRootLogger()->removeAllAppenders();
		Logger::getRootLogger()->addAppender( std::make_shared<MyAppender>() );
	}

	void tearDown()
	{
	}

	void testMultithreadedLoggers()
	{
		std::vector<std::thread> threads;

		for ( int x = 0; x < 6; x++ )
		{
			std::thread thr( multithread_logger, 20000 );
			threads.push_back( std::move(thr) );
		}

		for ( std::thread& thr : threads )
		{
			if ( thr.joinable() )
			{
				thr.join();
			}
		}
	}
};

LOGUNIT_TEST_SUITE_REGISTRATION(MultithreadTest);
