/*
 * 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/xml/xmllayout.h>
#include <log4cxx/htmllayout.h>
#include <log4cxx/fileappender.h>
#include <log4cxx/mdc.h>

#include "../util/transformer.h"
#include "../util/compare.h"
#include "../util/xmltimestampfilter.h"
#include "../util/xmllineattributefilter.h"
#include "../util/xmlthreadfilter.h"
#include "../util/filenamefilter.h"
#include <iostream>
#include <log4cxx/helpers/stringhelper.h>
#include "../testchar.h"
#include <log4cxx/spi/loggerrepository.h>
#include <apr_xml.h>
#include <log4cxx/ndc.h>
#include <log4cxx/mdc.h>
#include "../xml/xlevel.h"
#include <log4cxx/helpers/bytebuffer.h>
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/helpers/loglog.h>

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

#if defined(__LOG4CXX_FUNC__)
	#undef __LOG4CXX_FUNC__
	#define __LOG4CXX_FUNC__ "X::X()"
#else
	#error __LOG4CXX_FUNC__ expected to be defined
#endif
/**
 * Test for XMLLayout.
 *
 */
LOGUNIT_CLASS(XMLLayoutTest)
{
	LOGUNIT_TEST_SUITE(XMLLayoutTest);
	LOGUNIT_TEST(testGetContentType);
	LOGUNIT_TEST(testIgnoresThrowable);
	LOGUNIT_TEST(testGetHeader);
	LOGUNIT_TEST(testGetFooter);
	LOGUNIT_TEST(testFormat);
	LOGUNIT_TEST(testFormatWithNDC);
	LOGUNIT_TEST(testGetSetLocationInfo);
	LOGUNIT_TEST(testActivateOptions);
	LOGUNIT_TEST(testProblemCharacters);
	LOGUNIT_TEST(testNDCWithCDATA);
	LOGUNIT_TEST(testHTMLLayout);
	LOGUNIT_TEST_SUITE_END();


public:
	/**
	 * Clear MDC and NDC before test.
	 */
	void setUp()
	{
		NDC::clear();
		MDC::clear();
	}

	/**
	 * Clear MDC and NDC after test.
	 */
	void tearDown()
	{
		setUp();
	}


public:
	/**
	 * Tests getContentType.
	 */
	void testGetContentType()
	{
		LogString expected(LOG4CXX_STR("text/plain"));
		LogString actual(XMLLayout().getContentType());
		LOGUNIT_ASSERT(expected == actual);
	}

	/**
	 * Tests ignoresThrowable.
	 */
	void testIgnoresThrowable()
	{
		LOGUNIT_ASSERT_EQUAL(false, XMLLayout().ignoresThrowable());
	}

	/**
	 * Tests getHeader.
	 */
	void testGetHeader()
	{
		Pool p;
		LogString header;
		XMLLayout().appendHeader(header, p);
		LOGUNIT_ASSERT_EQUAL((size_t) 0, header.size());
	}

	/**
	 * Tests getFooter.
	 */
	void testGetFooter()
	{
		Pool p;
		LogString footer;
		XMLLayout().appendFooter(footer, p);
		LOGUNIT_ASSERT_EQUAL((size_t) 0, footer.size());
	}

private:
	/**
	 * Parses the string as the body of an XML document and returns the document element.
	 * @param source source string.
	 * @return document element.
	 * @throws Exception if parser can not be constructed or source is not a valid XML document.
	 */
	static apr_xml_elem* parse(const LogString & source, Pool & p)
	{
		char backing[3000];
		ByteBuffer buf(backing, sizeof(backing));
		CharsetEncoderPtr encoder(CharsetEncoder::getUTF8Encoder());
		LogString header(LOG4CXX_STR("<log4j:eventSet xmlns:log4j='http://jakarta.apache.org/log4j/'>"));
		LogString::const_iterator iter(header.begin());
		encoder->encode(header, iter, buf);
		LOGUNIT_ASSERT(iter == header.end());
		iter = source.begin();
		encoder->encode(source, iter, buf);
		LOGUNIT_ASSERT(iter == source.end());
		LogString footer(LOG4CXX_STR("</log4j:eventSet>"));
		iter = footer.begin();
		encoder->encode(footer, iter, buf);
		buf.flip();
		apr_pool_t* apr_pool = p.getAPRPool();
		apr_xml_parser* parser = apr_xml_parser_create(apr_pool);
		LOGUNIT_ASSERT(parser != 0);
		apr_status_t stat = apr_xml_parser_feed(parser, buf.data(), buf.remaining());
		LOGUNIT_ASSERT(stat == APR_SUCCESS);
		apr_xml_doc* doc = 0;
		stat = apr_xml_parser_done(parser, &doc);
		LOGUNIT_ASSERT(doc != 0);
		apr_xml_elem* eventSet = doc->root;
		LOGUNIT_ASSERT(eventSet != 0);
		apr_xml_elem* event = eventSet->first_child;
		LOGUNIT_ASSERT(event != 0);
		return event;
	}

	std::string getAttribute(apr_xml_elem * elem, const char* attrName)
	{
		for (apr_xml_attr* attr = elem->attr;
			attr != NULL;
			attr = attr->next)
		{
			if (strcmp(attr->name, attrName) == 0)
			{
				return attr->value;
			}
		}

		return "";
	}

	std::string getText(apr_xml_elem * elem)
	{
		std::string dMessage;

		for (apr_text* t = elem->first_cdata.first;
			t != NULL;
			t = t->next)
		{
			dMessage.append(t->text);
		}

		return dMessage;
	}
	/**
	 * Checks a log4j:event element against expectations.
	 * @param element element, may not be null.
	 * @param event event, may not be null.
	 */
	void checkEventElement(
		apr_xml_elem * element, LoggingEventPtr & event)
	{
		std::string tagName("event");
		LOGUNIT_ASSERT_EQUAL(tagName, (std::string) element->name);
		LOG4CXX_ENCODE_CHAR(cLoggerName, event->getLoggerName());
		LOGUNIT_ASSERT_EQUAL(cLoggerName, getAttribute(element, "logger"));
		LOG4CXX_ENCODE_CHAR(cLevelName, event->getLevel()->toString());
		LOGUNIT_ASSERT_EQUAL(cLevelName, getAttribute(element, "level"));
	}

	/**
	 * Checks a log4j:message element against expectations.
	 * @param element element, may not be null.
	 * @param message expected message.
	 */
	void checkMessageElement(
		apr_xml_elem * element, std::string message)
	{
		std::string tagName = "message";
		LOGUNIT_ASSERT_EQUAL(tagName, (std::string) element->name);
		LOGUNIT_ASSERT_EQUAL(message, getText(element));
	}

	/**
	 * Checks a log4j:message element against expectations.
	 * @param element element, may not be null.
	 * @param message expected message.
	 */
	void checkNDCElement(apr_xml_elem * element, std::string message)
	{
		std::string tagName = "NDC";
		LOGUNIT_ASSERT_EQUAL(tagName, (std::string) element->name);
		std::string dMessage = getText(element);
		LOGUNIT_ASSERT_EQUAL(message, dMessage);
	}


	/**
	 * Checks a log4j:properties element against expectations.
	 * @param element element, may not be null.
	 * @param key key.
	 * @param value value.
	 */
	void checkPropertiesElement(
		apr_xml_elem * element, std::string key, std::string value)
	{
		std::string tagName = "properties";
		std::string dataTag = "data";
		int childNodeCount = 0;
		LOGUNIT_ASSERT_EQUAL(tagName, (std::string) element->name);

		for (apr_xml_elem* child = element->first_child;
			child != NULL;
			child = child->next)
		{
			LOGUNIT_ASSERT_EQUAL(dataTag, (std::string) child->name);
			LOGUNIT_ASSERT_EQUAL(key, getAttribute(child, "name"));
			LOGUNIT_ASSERT_EQUAL(value, getAttribute(child, "value"));
			childNodeCount++;
		}

		LOGUNIT_ASSERT_EQUAL(1, childNodeCount);
	}

public:
	/**
	 * Tests formatted results.
	 * @throws Exception if parser can not be constructed or source is not a valid XML document.
	 */
	void testFormat()
	{
		LogString logger = LOG4CXX_STR("org.apache.log4j.xml.XMLLayoutTest");
		LoggingEventPtr event = LoggingEventPtr(
				new LoggingEvent(
					logger, Level::getInfo(), LOG4CXX_STR("Hello, World"), LOG4CXX_LOCATION));
		Pool p;
		XMLLayout layout;
		LogString result;
		layout.format(result, event, p);
		apr_xml_elem* parsedResult = parse(result, p);
		checkEventElement(parsedResult, event);

		int childElementCount = 0;

		for (
			apr_xml_elem* node = parsedResult->first_child;
			node != NULL;
			node = node->next)
		{
			childElementCount++;
			checkMessageElement(node, "Hello, World");
		}

		LOGUNIT_ASSERT_EQUAL(1, childElementCount);
	}


	/**
	 * Tests formatted results with an exception.
	 * @throws Exception if parser can not be constructed or source is not a valid XML document.
	 */
	void testFormatWithNDC()
	{
		LogString logger = LOG4CXX_STR("org.apache.log4j.xml.XMLLayoutTest");
		NDC::push("\001NDC goes here\004");

		LoggingEventPtr event = LoggingEventPtr(
				new LoggingEvent(
					logger, Level::getInfo(), LOG4CXX_STR("Hello, World"), LOG4CXX_LOCATION));
		Pool p;
		XMLLayout layout;
		LogString result;
		layout.format(result, event, p);
		NDC::pop();

		apr_xml_elem* parsedResult = parse(result, p);
		checkEventElement(parsedResult, event);

		int childElementCount = 0;

		for (
			apr_xml_elem* node = parsedResult->first_child; node != NULL;
			node = node->next)
		{
			childElementCount++;

			if (childElementCount == 1)
			{
				checkMessageElement(node, "Hello, World");
			}
			else
			{
				checkNDCElement(node, "&#x1;NDC goes here&#x4;");
			}
		}

		LOGUNIT_ASSERT_EQUAL(2, childElementCount);
	}

	/**
	 * Tests getLocationInfo and setLocationInfo.
	 */
	void testGetSetLocationInfo()
	{
		XMLLayout layout;
		LOGUNIT_ASSERT_EQUAL(false, layout.getLocationInfo());
		layout.setLocationInfo(true);
		LOGUNIT_ASSERT_EQUAL(true, layout.getLocationInfo());
		layout.setLocationInfo(false);
		LOGUNIT_ASSERT_EQUAL(false, layout.getLocationInfo());
	}

	/**
	 * Tests activateOptions().
	 */
	void testActivateOptions()
	{
		Pool p;
		XMLLayout layout;
		layout.activateOptions(p);
	}

	/**
	 * Tests problematic characters in multiple fields.
	 * @throws Exception if parser can not be constructed or source is not a valid XML document.
	 */
	void testProblemCharacters()
	{
		// '\"<räksmörgås.josefsson.org>&\"'
		std::string problemName = "'\"<\162\303\244\153\163\155\303\266\162\147\303\245\163\056\152\157\163\145\146\163\163\157\156\056\157\162\147>&\"'";
		LOG4CXX_DECODE_CHAR(problemNameLS, problemName);
		auto loggerNameLS = problemNameLS;
		auto levelNameLS = problemNameLS;
		Transcoder::encode(0xD822, problemNameLS); // Add an invalid character that should be stripped from attribute values
		auto keyLS = problemNameLS;
		auto expectedKeyValue = problemName;
#if LOG4CXX_LOGCHAR_IS_WCHAR && !defined(__STDC_ISO_10646__)
		// encodeUTF16 adds 0xD822, but decodeUTF16 cannot convert 0xD822
		// Expat translates the Unicode replacement character to the following
		expectedKeyValue += "\xEF\xBF\xBD";
#endif
		std::string problemMessage = "'\001\"<Hello >\"\004'";
		std::string expectedCdataValue = "'&#x1;\"<Hello >\"&#x4;'";
		std::string expectedAttributeValue = "'\"<Hello >\"'"; // Invalid characters stripped
		LOG4CXX_DECODE_CHAR(problemMessageLS, problemMessage);
		LevelPtr level = LevelPtr(new XLevel(6000, levelNameLS, 7));
		NDC::push(problemName);
		MDC::clear();
		MDC::put(keyLS, problemMessageLS);
		auto event = std::make_shared<LoggingEvent>
				(loggerNameLS, level, problemMessageLS, LOG4CXX_LOCATION);
		XMLLayout layout;
		layout.setProperties(true);
		Pool p;
		LogString result;
		layout.format(result, event, p);
		MDC::clear();

		apr_xml_elem* parsedResult = parse(result, p);
		checkEventElement(parsedResult, event);

		int childElementCount = 0;

		for (
			apr_xml_elem* node = parsedResult->first_child; node != NULL;
			node = node->next)
		{
			childElementCount++;

			switch (childElementCount)
			{
				case 1:
					checkMessageElement(node, expectedCdataValue);
					break;

				case 2:
					checkNDCElement(node, problemName);
					break;

				case 3:
					checkPropertiesElement(node, expectedKeyValue.c_str(), expectedAttributeValue.c_str());
					break;

				default:
					break;
			}

		}

		LOGUNIT_ASSERT_EQUAL(3, childElementCount);
	}

	/**
	  * Tests CDATA element within NDC content.  See bug 37560.
	  */
	void testNDCWithCDATA()
	{
		LogString logger = LOG4CXX_STR("com.example.bar");
		LevelPtr level = Level::getInfo();
		std::string ndcMessage = "<envelope><faultstring><![CDATA[The EffectiveDate]]></faultstring><envelope>";
		NDC::push(ndcMessage);
		LoggingEventPtr event = LoggingEventPtr(
				new LoggingEvent(
					logger, level, LOG4CXX_STR("Hello, World"), LOG4CXX_LOCATION));
		XMLLayout layout;
		Pool p;
		LogString result;
		layout.format(result, event, p);
		NDC::clear();
		apr_xml_elem* parsedResult = parse(result, p);
		int ndcCount = 0;

		for (apr_xml_elem* node = parsedResult->first_child;
			node != NULL;
			node = node->next)
		{
			if (strcmp(node->name, "NDC") == 0)
			{
				ndcCount++;
				LOGUNIT_ASSERT_EQUAL(ndcMessage, getText(node));
			}
		}

		LOGUNIT_ASSERT_EQUAL(1, ndcCount);
	}

	/**
	 * Tests problematic characters in multiple fields.
	 * @throws Exception if parser can not be constructed or source is not a valid XML document.
	 */
	void testHTMLLayout()
	{
		LogString problemName = LOG4CXX_STR("com.example.bar<>&\"'");
		auto level = std::make_shared<XLevel>(6000, problemName, 7);
		NDC context(problemName);
		auto event = std::make_shared<LoggingEvent>(problemName, level, problemName, LOG4CXX_LOCATION);

		HTMLLayout layout;
		Pool p;
		LogString html(LOG4CXX_STR("<body>"));
		layout.format(html, event, p);
		html += LOG4CXX_STR("</body>");

		LogLog::debug(html);
		char backing[3000];
		ByteBuffer buf(backing, sizeof(backing));
		CharsetEncoderPtr encoder(CharsetEncoder::getUTF8Encoder());
		LogString::const_iterator iter{ html.begin() };
		encoder->encode(html, iter, buf);
		LOGUNIT_ASSERT(iter == html.end());
		buf.flip();
		auto parser = apr_xml_parser_create(p.getAPRPool());
		LOGUNIT_ASSERT(parser != 0);
		auto stat = apr_xml_parser_feed(parser, buf.data(), buf.remaining());
		LOGUNIT_ASSERT(stat == APR_SUCCESS);
		apr_xml_doc* doc = 0;
		stat = apr_xml_parser_done(parser, &doc);
		LOGUNIT_ASSERT(doc != 0);
		auto parsedResult = doc->root;
		LOGUNIT_ASSERT(parsedResult != 0);

		int childElementCount = 0;
		for ( auto node = parsedResult->first_child
		    ; node != NULL
		    ; node = node->next)
		{
			++childElementCount;
			LOGUNIT_ASSERT_EQUAL(std::string("tr"), std::string(node->name));
		}
		LOGUNIT_ASSERT(1 < childElementCount);
	}

};


LOGUNIT_TEST_SUITE_REGISTRATION(XMLLayoutTest);

