<?php
/**
 * 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.
 * 
 * @category   tests   
 * @package    log4php
 * @subpackage appenders
 * @license    http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
 * @link       http://logging.apache.org/log4php
 */

/**
 * @group appenders
 */
class LoggerAppenderEchoTest extends PHPUnit_Framework_TestCase {

	private $config1 = array(
		'rootLogger' => array(
			'appenders' => array('default'),
		),
		'appenders' => array(
			'default' => array(
				'class' => 'LoggerAppenderEcho',
				'layout' => array(
					'class' => 'LoggerLayoutSimple'
				),
			)
		)
	);
	
	private $config2 = array(
		'rootLogger' => array(
			'appenders' => array('default'),
		),
		'appenders' => array(
			'default' => array(
				'class' => 'LoggerAppenderEcho',
				'layout' => array(
					'class' => 'LoggerLayoutSimple'
				),
				'params' => array(
					'htmlLineBreaks' => true
				)
			)
		)
	);
	
	private $config3 = array(
		'rootLogger' => array(
			'appenders' => array('default'),
		),
		'appenders' => array(
			'default' => array(
				'class' => 'LoggerAppenderEcho',
				'layout' => array(
					'class' => 'LoggerLayoutSimple'
				),
				'params' => array(
					'htmlLineBreaks' => 'foo'
				)
			)
		)
	);
	
	public function testAppend() {
		Logger::configure($this->config1);
		$log = Logger::getRootLogger();

		$hlb = $log->getAppender('default')->getHtmlLineBreaks();
		$this->assertSame(false, $hlb);
		
		ob_start();
		$log->info("This is a test");
		$log->debug("And this too");
		$actual = ob_get_clean();
		$expected = "INFO - This is a test" . PHP_EOL . "DEBUG - And this too". PHP_EOL;
		
		$this->assertSame($expected, $actual);
	}
	
	public function testHtmlLineBreaks() {
		Logger::configure($this->config2);
		$log = Logger::getRootLogger();
		
		$hlb = $log->getAppender('default')->getHtmlLineBreaks();
		$this->assertSame(true, $hlb);
		
		ob_start();
		$log->info("This is a test" . PHP_EOL . "With more than one line");
		$log->debug("And this too");
		$actual = ob_get_clean();
		$expected = "INFO - This is a test<br />" . PHP_EOL . "With more than one line<br />" . PHP_EOL . "DEBUG - And this too<br />" . PHP_EOL;
		
		$this->assertSame($expected, $actual);
	}
	
// 	public function testHtmlLineBreaksInvalidOption() {
// 		Logger::configure($this->config3);
// 	}
	
	
	public function testEcho() {
		$appender = new LoggerAppenderEcho("myname ");
		
		$layout = new LoggerLayoutSimple();
		$appender->setLayout($layout);
		$appender->activateOptions();
		$event = new LoggerLoggingEvent("LoggerAppenderEchoTest", new Logger("TEST"), LoggerLevel::getLevelError(), "testmessage");
		
		$expected = "ERROR - testmessage" . PHP_EOL;
		ob_start();
		$appender->append($event);
		$actual = ob_get_clean();
		
		self::assertEquals($expected, $actual);
	}
	
	public function testRequiresLayout() {
		$appender = new LoggerAppenderEcho(); 
		self::assertTrue($appender->requiresLayout());
	}
	
	public function testEchoHtml() {
		$appender = new LoggerAppenderEcho("myname ");
		$appender->setHtmlLineBreaks(true);
		
		$layout = new LoggerLayoutSimple();
		$appender->setLayout($layout);
		$appender->activateOptions();
		
		// Single line message
		$event = new LoggerLoggingEvent("LoggerAppenderEchoTest", new Logger("TEST"), LoggerLevel::getLevelError(), "testmessage");
		
		$expected = "ERROR - testmessage<br />" . PHP_EOL;
		ob_start();
		$appender->append($event);
		$actual = ob_get_clean();
		self::assertEquals($expected, $actual);
		
		// Multi-line message
		$msg = "This message\nis in several lines\r\nto test various line breaks.";
		$expected = "ERROR - This message<br />\nis in several lines<br />\r\nto test various line breaks.<br />" . PHP_EOL;
		
		$event = new LoggerLoggingEvent("LoggerAppenderEchoTest", new Logger("TEST"), LoggerLevel::getLevelError(), $msg);
		ob_start();
		$appender->append($event);
		$actual = ob_get_clean();
		self::assertEquals($expected, $actual);
	}

}
