/*
 * 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/helpers/messagebuffer.h>
#include <iomanip>
#include "../insertwide.h"
#include "../logunit.h"
#include <log4cxx/logstring.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/logger.h>
#include <log4cxx/propertyconfigurator.h>
#include "util/compare.h"

#if LOG4CXX_CFSTRING_API
	#include <CoreFoundation/CFString.h>
#endif

using namespace log4cxx;
using namespace log4cxx::helpers;

/**
 *  Test MessageBuffer.
 */
LOGUNIT_CLASS(MessageBufferTest)
{
	LOGUNIT_TEST_SUITE(MessageBufferTest);
	LOGUNIT_TEST(testInsertChar);
	LOGUNIT_TEST(testInsertConstStr);
	LOGUNIT_TEST(testInsertStr);
	LOGUNIT_TEST(testInsertString);
	LOGUNIT_TEST(testInsertNull);
	LOGUNIT_TEST(testInsertInt);
	LOGUNIT_TEST(testInsertManipulator);
	LOGUNIT_TEST(testBaseChange);
#if LOG4CXX_WCHAR_T_API
	LOGUNIT_TEST(testInsertConstWStr);
	LOGUNIT_TEST(testInsertWString);
	LOGUNIT_TEST(testInsertWStr);
#endif
#if LOG4CXX_UNICHAR_API
	LOGUNIT_TEST(testInsertConstUStr);
	LOGUNIT_TEST(testInsertUString);
#endif
#if LOG4CXX_CFSTRING_API
	LOGUNIT_TEST(testInsertCFString);
#endif
	LOGUNIT_TEST_SUITE_END();


#ifdef _DEBUG
	struct Fixture
	{
		Fixture() {
			helpers::LogLog::setInternalDebugging(true);
		}
	} suiteFixture;
#endif

public:
	void testInsertChar()
	{
		MessageBuffer buf;
		std::string greeting("Hello, World");
		CharMessageBuffer& retval = buf << "Hello, Worl" << 'd';
		LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
		LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
	}

	void testInsertConstStr()
	{
		MessageBuffer buf;
		std::string greeting("Hello, World");
		CharMessageBuffer& retval = buf << "Hello" << ", World";
		LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
		LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
	}

	void testInsertStr()
	{
		MessageBuffer buf;
		std::string greeting("Hello, World");
		char* part1 = (char*) malloc(10 * sizeof(wchar_t));
		strcpy(part1, "Hello");
		char* part2 = (char*) malloc(10 * sizeof(wchar_t));
		strcpy(part2, ", World");
		CharMessageBuffer& retval = buf << part1 << part2;
		free(part1);
		free(part2);
		LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
		LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
	}

	void testInsertString()
	{
		MessageBuffer buf;
		std::string greeting("Hello, World");
		CharMessageBuffer& retval = buf << std::string("Hello") << std::string(", World");
		LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
		LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
	}

	void testInsertNull()
	{
		MessageBuffer buf;
		std::string greeting("Hello, null");
		CharMessageBuffer& retval = buf << "Hello, " << (const char*) 0;
		LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
		LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
	}

	void testInsertInt()
	{
		MessageBuffer buf;
		std::string greeting("Hello, 5");
		std::ostream& retval = buf << "Hello, " << 5;
		LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
		LOGUNIT_ASSERT_EQUAL(true, buf.hasStream());
	}

	void testInsertManipulator()
	{
		MessageBuffer buf;
		std::string greeting("pi=3.142");
		std::ostream& retval = buf << "pi=" << std::setprecision(4) << 3.1415926;
		LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
		LOGUNIT_ASSERT_EQUAL(true, buf.hasStream());
	}

	void testBaseChange()
	{
		LoggerPtr root;
		LoggerPtr logger;

		root = Logger::getRootLogger();
		logger = Logger::getLogger(LOG4CXX_STR("java.org.apache.log4j.PatternLayoutTest"));

		PropertyConfigurator::configure(LOG4CXX_FILE("input/messagebuffer1.properties"));

		int num = 220;
		LOG4CXX_INFO(logger, "number in hex: " << std::hex << num);
		LOG4CXX_INFO(logger, "number in dec: " << num);

		LOGUNIT_ASSERT(Compare::compare(LOG4CXX_STR("output/messagebuffer"), LOG4CXX_FILE("witness/messagebuffer.1")));

		auto rep = root->getLoggerRepository();

		if (rep)
		{
			rep->resetConfiguration();
		}
	}

#if LOG4CXX_WCHAR_T_API
	void testInsertConstWStr()
	{
		MessageBuffer buf;
		std::wstring greeting(L"Hello, World");
		WideMessageBuffer& retval = buf << L"Hello" << L", World";
		LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
		LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
	}

	void testInsertWString()
	{
		MessageBuffer buf;
		std::wstring greeting(L"Hello, World");
		WideMessageBuffer& retval = buf << std::wstring(L"Hello") << std::wstring(L", World");
		LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
		LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
	}

	void testInsertWStr()
	{
		MessageBuffer buf;
		std::wstring greeting(L"Hello, World");
		wchar_t* part1 = (wchar_t*) malloc(10 * sizeof(wchar_t));
		wcscpy(part1, L"Hello");
		wchar_t* part2 = (wchar_t*) malloc(10 * sizeof(wchar_t));
		wcscpy(part2, L", World");
		WideMessageBuffer& retval = buf << part1 << part2;
		free(part1);
		free(part2);
		LOGUNIT_ASSERT_EQUAL(greeting, buf.str(retval));
		LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
	}
#endif

#if LOG4CXX_UNICHAR_API
	void testInsertConstUStr()
	{
		MessageBuffer buf;
		const log4cxx::UniChar hello[] = { 'H', 'e', 'l', 'l', 'o', 0 };
		const log4cxx::UniChar world[] = { ',', ' ', 'W', 'o', 'r', 'l', 'd', 0 };
		const log4cxx::UniChar greeting[] = { 'H', 'e', 'l', 'l', 'o',
				',', ' ', 'W', 'o', 'r', 'l', 'd', 0
			};
		UniCharMessageBuffer& retval = buf << hello << world;
		LOGUNIT_ASSERT_EQUAL(std::basic_string<log4cxx::UniChar>(greeting), buf.str(retval));
		LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
	}

	void testInsertUString()
	{
		MessageBuffer buf;
		const log4cxx::UniChar hello[] = { 'H', 'e', 'l', 'l', 'o', 0 };
		const log4cxx::UniChar world[] = { ',', ' ', 'W', 'o', 'r', 'l', 'd', 0 };
		const log4cxx::UniChar greeting[] = { 'H', 'e', 'l', 'l', 'o',
				',', ' ', 'W', 'o', 'r', 'l', 'd', 0
			};
		UniCharMessageBuffer& retval = buf << std::basic_string<log4cxx::UniChar>(hello)
			<< std::basic_string<log4cxx::UniChar>(world);
		LOGUNIT_ASSERT_EQUAL(std::basic_string<log4cxx::UniChar>(greeting), buf.str(retval));
		LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
	}

#endif

#if LOG4CXX_UNICHAR_API && LOG4CXX_CFSTRING_API
	void testInsertCFString()
	{
		MessageBuffer buf;
		const log4cxx::UniChar greeting[] = { 'H', 'e', 'l', 'l', 'o',
				',', ' ', 'W', 'o', 'r', 'l', 'd', 0
			};
		UniCharMessageBuffer& retval = buf << CFSTR("Hello")
			<< CFSTR(", World");
		LOGUNIT_ASSERT_EQUAL(std::basic_string<log4cxx::UniChar>(greeting), buf.str(retval));
		LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
	}
#elif LOG4CXX_CFSTRING_API
	void testInsertCFString()
	{
		MessageBuffer buf;
		const log4cxx::logchar greeting[] = { 'H', 'e', 'l', 'l', 'o',
				',', ' ', 'W', 'o', 'r', 'l', 'd', 0
			};
		CharMessageBuffer& retval = buf << CFSTR("Hello")
			<< CFSTR(", World");
		LOGUNIT_ASSERT_EQUAL(std::basic_string<log4cxx::logchar>(greeting), buf.str(retval));
		LOGUNIT_ASSERT_EQUAL(false, buf.hasStream());
	}
#endif

};

LOGUNIT_TEST_SUITE_REGISTRATION(MessageBufferTest);

