4 * This file is part of the Monolog package.
6 * (c) Jordi Boggiano <j.boggiano@seld.be>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Monolog\Handler;
15 use PHPUnit_Framework_Error_Deprecated;
18 * @covers Monolog\Handler\RotatingFileHandler
20 class RotatingFileHandlerTest extends TestCase
23 * This var should be private but then the anonymous function
24 * in the `setUp` method won't be able to set it. `$this` cant't
25 * be used in the anonymous function in `setUp` because PHP 5.3
26 * does not support it.
30 public function setUp()
32 $dir = __DIR__.'/Fixtures';
34 if (!is_writable($dir)) {
35 $this->markTestSkipped($dir.' must be writable to test the RotatingFileHandler.');
37 $this->lastError = null;
39 // workaround with &$self used for PHP 5.3
40 set_error_handler(function($code, $message) use (&$self) {
41 $self->lastError = array(
43 'message' => $message,
48 private function assertErrorWasTriggered($code, $message)
50 if (empty($this->lastError)) {
53 'Failed asserting that error with code `%d` and message `%s` was triggered',
59 $this->assertEquals($code, $this->lastError['code'], sprintf('Expected an error with code %d to be triggered, got `%s` instead', $code, $this->lastError['code']));
60 $this->assertEquals($message, $this->lastError['message'], sprintf('Expected an error with message `%d` to be triggered, got `%s` instead', $message, $this->lastError['message']));
63 public function testRotationCreatesNewFile()
65 touch(__DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400).'.rot');
67 $handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot');
68 $handler->setFormatter($this->getIdentityFormatter());
69 $handler->handle($this->getRecord());
71 $log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot';
72 $this->assertTrue(file_exists($log));
73 $this->assertEquals('test', file_get_contents($log));
77 * @dataProvider rotationTests
79 public function testRotation($createFile, $dateFormat, $timeCallback)
81 touch($old1 = __DIR__.'/Fixtures/foo-'.date($dateFormat, $timeCallback(-1)).'.rot');
82 touch($old2 = __DIR__.'/Fixtures/foo-'.date($dateFormat, $timeCallback(-2)).'.rot');
83 touch($old3 = __DIR__.'/Fixtures/foo-'.date($dateFormat, $timeCallback(-3)).'.rot');
84 touch($old4 = __DIR__.'/Fixtures/foo-'.date($dateFormat, $timeCallback(-4)).'.rot');
86 $log = __DIR__.'/Fixtures/foo-'.date($dateFormat).'.rot';
92 $handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot', 2);
93 $handler->setFormatter($this->getIdentityFormatter());
94 $handler->setFilenameFormat('{filename}-{date}', $dateFormat);
95 $handler->handle($this->getRecord());
99 $this->assertTrue(file_exists($log));
100 $this->assertTrue(file_exists($old1));
101 $this->assertEquals($createFile, file_exists($old2));
102 $this->assertEquals($createFile, file_exists($old3));
103 $this->assertEquals($createFile, file_exists($old4));
104 $this->assertEquals('test', file_get_contents($log));
107 public function rotationTests()
110 $dayCallback = function($ago) use ($now) {
111 return $now + 86400 * $ago;
113 $monthCallback = function($ago) {
114 return gmmktime(0, 0, 0, date('n') + $ago, date('d'), date('Y'));
116 $yearCallback = function($ago) {
117 return gmmktime(0, 0, 0, date('n'), date('d'), date('Y') + $ago);
121 'Rotation is triggered when the file of the current day is not present'
122 => array(true, RotatingFileHandler::FILE_PER_DAY, $dayCallback),
123 'Rotation is not triggered when the file of the current day is already present'
124 => array(false, RotatingFileHandler::FILE_PER_DAY, $dayCallback),
126 'Rotation is triggered when the file of the current month is not present'
127 => array(true, RotatingFileHandler::FILE_PER_MONTH, $monthCallback),
128 'Rotation is not triggered when the file of the current month is already present'
129 => array(false, RotatingFileHandler::FILE_PER_MONTH, $monthCallback),
131 'Rotation is triggered when the file of the current year is not present'
132 => array(true, RotatingFileHandler::FILE_PER_YEAR, $yearCallback),
133 'Rotation is not triggered when the file of the current year is already present'
134 => array(false, RotatingFileHandler::FILE_PER_YEAR, $yearCallback),
139 * @dataProvider dateFormatProvider
141 public function testAllowOnlyFixedDefinedDateFormats($dateFormat, $valid)
143 $handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot', 2);
144 $handler->setFilenameFormat('{filename}-{date}', $dateFormat);
146 $this->assertErrorWasTriggered(
148 'Invalid date format - format must be one of RotatingFileHandler::FILE_PER_DAY ("Y-m-d"), '.
149 'RotatingFileHandler::FILE_PER_MONTH ("Y-m") or RotatingFileHandler::FILE_PER_YEAR ("Y"), '.
150 'or you can set one of the date formats using slashes, underscores and/or dots instead of dashes.'
155 public function dateFormatProvider()
158 array(RotatingFileHandler::FILE_PER_DAY, true),
159 array(RotatingFileHandler::FILE_PER_MONTH, true),
160 array(RotatingFileHandler::FILE_PER_YEAR, true),
161 array('m-d-Y', false),
162 array('Y-m-d-h-i', false)
167 * @dataProvider filenameFormatProvider
169 public function testDisallowFilenameFormatsWithoutDate($filenameFormat, $valid)
171 $handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot', 2);
172 $handler->setFilenameFormat($filenameFormat, RotatingFileHandler::FILE_PER_DAY);
174 $this->assertErrorWasTriggered(
176 'Invalid filename format - format should contain at least `{date}`, because otherwise rotating is impossible.'
181 public function filenameFormatProvider()
184 array('{filename}', false),
185 array('{filename}-{date}', true),
186 array('{date}', true),
187 array('foobar-{date}', true),
188 array('foo-{date}-bar', true),
189 array('{date}-foobar', true),
190 array('foobar', false),
194 public function testReuseCurrentFile()
196 $log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot';
197 file_put_contents($log, "foo");
198 $handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot');
199 $handler->setFormatter($this->getIdentityFormatter());
200 $handler->handle($this->getRecord());
201 $this->assertEquals('footest', file_get_contents($log));
204 public function tearDown()
206 foreach (glob(__DIR__.'/Fixtures/*.rot') as $file) {
209 restore_error_handler();