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

use PHPUnit\Framework\TestCase;

/**
 * @group main
 */
class LoggerTest extends TestCase {
	
	private $testConfig1 = array (
		'rootLogger' =>	array (
			'level' => 'ERROR',
			'appenders' => array (
				'default',
			),
		),
		'appenders' => array (
			'default' => array (
				'class' => 'LoggerAppenderEcho',
			),
		),
		'loggers' => array (
			'mylogger' => array (
				'additivity' => 'false',
				'level' => 'DEBUG',
				'appenders' => array (
					'default',
				),
			),
		),
	);
	
	// For testing additivity
	private $testConfig2 = array (
		'appenders' => array (
			'default' => array (
				'class' => 'LoggerAppenderEcho',
			),
		),
		'rootLogger' => array(
			'appenders' => array('default'),
		),
		'loggers' => array (
			'foo' => array (
				'appenders' => array (
					'default',
				),
			),
			'foo.bar' => array (
				'appenders' => array (
					'default',
				),
			),
			'foo.bar.baz' => array (
				'appenders' => array (
					'default',
				),
			),
		),
	);
	
	// For testing additivity
	private $testConfig3 = array (
		'appenders' => array (
			'default' => array (
				'class' => 'LoggerAppenderEcho',
			),
		),
		'rootLogger' => array(
			'appenders' => array('default'),
		),
		'loggers' => array (
			'foo' => array (
				'appenders' => array (
					'default',
				),
			),
			'foo.bar' => array (
				'appenders' => array (
					'default',
				),
			),
			'foo.bar.baz' => array (
				'level' => 'ERROR',
				'appenders' => array (
					'default',
				),
			),
		),
	);
	
	protected function setUp() {
		Logger::clear();
		Logger::resetConfiguration();
	}
	
	protected function tearDown() {
		Logger::clear();
		Logger::resetConfiguration();
	}
	
	public function testLoggerExist() {
		$l = Logger::getLogger('test');
		self::assertEquals($l->getName(), 'test');
		self::assertTrue(Logger::exists('test'));
	}
	
	public function testCanGetRootLogger() {
		$l = Logger::getRootLogger();
		self::assertEquals($l->getName(), 'root');
	}
	
	public function testCanGetASpecificLogger() {
		$l = Logger::getLogger('test');
		self::assertEquals($l->getName(), 'test');
	}
	
	public function testCanLogToAllLevels() {
		Logger::configure($this->testConfig1);
		
		$logger = Logger::getLogger('mylogger');
		ob_start();
		$logger->info('this is an info');
		$logger->warn('this is a warning');
		$logger->error('this is an error');
		$logger->debug('this is a debug message');
		$logger->fatal('this is a fatal message');
		$v = ob_get_contents();
		ob_end_clean();
		
		$e = 'INFO - this is an info'.PHP_EOL;
		$e .= 'WARN - this is a warning'.PHP_EOL;
		$e .= 'ERROR - this is an error'.PHP_EOL;
		$e .= 'DEBUG - this is a debug message'.PHP_EOL;
		$e .= 'FATAL - this is a fatal message'.PHP_EOL;
		
		self::assertEquals($v, $e);
	}
	
	public function testIsEnabledFor() {
		Logger::configure($this->testConfig1);
		
		$logger = Logger::getLogger('mylogger');
		
		self::assertFalse($logger->isTraceEnabled());
		self::assertTrue($logger->isDebugEnabled());
		self::assertTrue($logger->isInfoEnabled());
		self::assertTrue($logger->isWarnEnabled());
		self::assertTrue($logger->isErrorEnabled());
		self::assertTrue($logger->isFatalEnabled());
		
		$logger = Logger::getRootLogger();
		
		self::assertFalse($logger->isTraceEnabled());
		self::assertFalse($logger->isDebugEnabled());
		self::assertFalse($logger->isInfoEnabled());
		self::assertFalse($logger->isWarnEnabled());
		self::assertTrue($logger->isErrorEnabled());
		self::assertTrue($logger->isFatalEnabled());
	}
	
	public function testGetCurrentLoggers() {
		Logger::clear();
		Logger::resetConfiguration();
		
		self::assertEquals(0, count(Logger::getCurrentLoggers()));
		
		Logger::configure($this->testConfig1);
		self::assertEquals(1, count(Logger::getCurrentLoggers()));
		$list = Logger::getCurrentLoggers();
		self::assertEquals('mylogger', $list[0]->getName());
	}
	
	public function testAdditivity() {
		Logger::configure($this->testConfig2);
	
		$logger = Logger::getLogger('foo.bar.baz');
		ob_start();
		$logger->info('test');
		$actual = ob_get_contents();
		ob_end_clean();
	
		// The message should get logged 4 times: once by every logger in the 
		//  hierarchy (including root)
		$expected = str_repeat('INFO - test' . PHP_EOL, 4);
		self::assertSame($expected, $actual);
	}
	
	public function testAdditivity2() {
		Logger::configure($this->testConfig3);
	
		$logger = Logger::getLogger('foo.bar.baz');
		ob_start();
		$logger->info('test');
		$actual = ob_get_contents();
		ob_end_clean();
	
		// The message should get logged 3 times: once by every logger in the
		//  hierarchy, except foo.bar.baz which is set to level ERROR
		$expected = str_repeat('INFO - test' . PHP_EOL, 3);
		self::assertSame($expected, $actual);
	}
}
