diff options
Diffstat (limited to 'tests/lib/Log')
-rw-r--r-- | tests/lib/Log/ExceptionSerializerTest.php | 67 | ||||
-rw-r--r-- | tests/lib/Log/FileTest.php | 93 | ||||
-rw-r--r-- | tests/lib/Log/LogFactoryTest.php | 149 | ||||
-rw-r--r-- | tests/lib/Log/PsrLoggerAdapterTest.php | 82 |
4 files changed, 391 insertions, 0 deletions
diff --git a/tests/lib/Log/ExceptionSerializerTest.php b/tests/lib/Log/ExceptionSerializerTest.php new file mode 100644 index 00000000000..6d5bc5cf19f --- /dev/null +++ b/tests/lib/Log/ExceptionSerializerTest.php @@ -0,0 +1,67 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace lib\Log; + +use OC\Log\ExceptionSerializer; +use OC\SystemConfig; +use Test\TestCase; + +class ExceptionSerializerTest extends TestCase { + private ExceptionSerializer $serializer; + + public function setUp(): void { + parent::setUp(); + + $config = $this->createMock(SystemConfig::class); + $this->serializer = new ExceptionSerializer($config); + } + + private function emit($arguments) { + \call_user_func_array([$this, 'bind'], $arguments); + } + + private function bind(array &$myValues): void { + throw new \Exception('my exception'); + } + + private function customMagicAuthThing(string $login, string $parole): void { + throw new \Exception('expected custom auth exception'); + } + + /** + * this test ensures that the serializer does not overwrite referenced + * variables. It is crafted after a scenario we experienced: the DAV server + * emitting the "validateTokens" event, of which later on a handled + * exception was passed to the logger. The token was replaced, the original + * variable overwritten. + */ + public function testSerializer(): void { + try { + $secret = ['Secret']; + $this->emit([&$secret]); + } catch (\Exception $e) { + $serializedData = $this->serializer->serializeException($e); + $this->assertSame(['Secret'], $secret); + $this->assertSame(ExceptionSerializer::SENSITIVE_VALUE_PLACEHOLDER, $serializedData['Trace'][0]['args'][0]); + } + } + + public function testSerializerWithRegisteredMethods(): void { + $this->serializer->enlistSensitiveMethods(self::class, ['customMagicAuthThing']); + try { + $this->customMagicAuthThing('u57474', 'Secret'); + } catch (\Exception $e) { + $serializedData = $this->serializer->serializeException($e); + $this->assertSame('customMagicAuthThing', $serializedData['Trace'][0]['function']); + $this->assertSame(ExceptionSerializer::SENSITIVE_VALUE_PLACEHOLDER, $serializedData['Trace'][0]['args'][0]); + $this->assertFalse(isset($serializedData['Trace'][0]['args'][1])); + } + } +} diff --git a/tests/lib/Log/FileTest.php b/tests/lib/Log/FileTest.php new file mode 100644 index 00000000000..3f030665fb4 --- /dev/null +++ b/tests/lib/Log/FileTest.php @@ -0,0 +1,93 @@ +<?php + +/** + * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace Test\Log; + +use OC\Log\File; +use OC\SystemConfig; +use OCP\IConfig; +use OCP\ILogger; +use OCP\Server; +use Test\TestCase; + +/** + * Class FileTest + */ +class FileTest extends TestCase { + private $restore_logfile; + private $restore_logdateformat; + + /** @var File */ + protected $logFile; + + protected function setUp(): void { + parent::setUp(); + $config = Server::get(SystemConfig::class); + $this->restore_logfile = $config->getValue('logfile'); + $this->restore_logdateformat = $config->getValue('logdateformat'); + + $config->setValue('logfile', $config->getValue('datadirectory') . '/logtest.log'); + $this->logFile = new File($config->getValue('datadirectory') . '/logtest.log', '', $config); + } + protected function tearDown(): void { + $config = Server::get(SystemConfig::class); + if (isset($this->restore_logfile)) { + $config->getValue('logfile', $this->restore_logfile); + } else { + $config->deleteValue('logfile'); + } + if (isset($this->restore_logdateformat)) { + $config->getValue('logdateformat', $this->restore_logdateformat); + } else { + $config->deleteValue('logdateformat'); + } + $this->logFile = new File($this->restore_logfile, '', $config); + parent::tearDown(); + } + + public function testLogging(): void { + $config = Server::get(IConfig::class); + # delete old logfile + unlink($config->getSystemValue('logfile')); + + # set format & write log line + $config->setSystemValue('logdateformat', 'u'); + $this->logFile->write('code', ['something' => 'extra', 'message' => 'Testing logging'], ILogger::ERROR); + + # read log line + $handle = @fopen($config->getSystemValue('logfile'), 'r'); + $line = fread($handle, 1000); + fclose($handle); + + # check log has data content + $values = (array)json_decode($line, true); + $this->assertArrayNotHasKey('message', $values['data']); + $this->assertEquals('extra', $values['data']['something']); + $this->assertEquals('Testing logging', $values['message']); + } + + public function testMicrosecondsLogTimestamp(): void { + $config = Server::get(IConfig::class); + # delete old logfile + unlink($config->getSystemValue('logfile')); + + # set format & write log line + $config->setSystemValue('logdateformat', 'u'); + $this->logFile->write('test', 'message', ILogger::ERROR); + + # read log line + $handle = @fopen($config->getSystemValue('logfile'), 'r'); + $line = fread($handle, 1000); + fclose($handle); + + # check timestamp has microseconds part + $values = (array)json_decode($line); + $microseconds = $values['time']; + $this->assertNotEquals(0, $microseconds); + } +} diff --git a/tests/lib/Log/LogFactoryTest.php b/tests/lib/Log/LogFactoryTest.php new file mode 100644 index 00000000000..b1adbd0e823 --- /dev/null +++ b/tests/lib/Log/LogFactoryTest.php @@ -0,0 +1,149 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace Test\Log; + +use OC\Log\Errorlog; +use OC\Log\File; +use OC\Log\LogFactory; +use OC\Log\Syslog; +use OC\Log\Systemdlog; +use OC\SystemConfig; +use OCP\AppFramework\QueryException; +use OCP\IServerContainer; +use Test\TestCase; + +/** + * Class LogFactoryTest + * + * @package Test\Log + */ +class LogFactoryTest extends TestCase { + /** @var IServerContainer|\PHPUnit\Framework\MockObject\MockObject */ + protected $c; + + /** @var LogFactory */ + protected $factory; + + /** @var SystemConfig|\PHPUnit\Framework\MockObject\MockObject */ + protected $systemConfig; + + protected function setUp(): void { + parent::setUp(); + + $this->c = $this->createMock(IServerContainer::class); + $this->systemConfig = $this->createMock(SystemConfig::class); + + $this->factory = new LogFactory($this->c, $this->systemConfig); + } + + public static function fileTypeProvider(): array { + return [ + [ + 'file' + ], + [ + 'nextcloud' + ], + [ + 'owncloud' + ], + [ + 'krzxkyr_default' + ] + ]; + } + + /** + * @param string $type + * @throws QueryException + */ + #[\PHPUnit\Framework\Attributes\DataProvider('fileTypeProvider')] + public function testFile(string $type): void { + $datadir = \OC::$SERVERROOT . '/data'; + $defaultLog = $datadir . '/nextcloud.log'; + + $this->systemConfig->expects($this->exactly(3)) + ->method('getValue') + ->willReturnMap([ + ['datadirectory', $datadir, $datadir], + ['logfile', $defaultLog, $defaultLog], + ['logfilemode', 0640, 0640], + ]); + + $log = $this->factory->get($type); + $this->assertInstanceOf(File::class, $log); + } + + public static function logFilePathProvider():array { + return [ + [ + '/dev/null', + '/dev/null' + ], + [ + '/xdev/youshallfallback', + \OC::$SERVERROOT . '/data/nextcloud.log' + ] + ]; + } + + /** + * @throws QueryException + */ + #[\PHPUnit\Framework\Attributes\DataProvider('logFilePathProvider')] + public function testFileCustomPath($path, $expected): void { + $datadir = \OC::$SERVERROOT . '/data'; + $defaultLog = $datadir . '/nextcloud.log'; + + $this->systemConfig->expects($this->exactly(3)) + ->method('getValue') + ->willReturnMap([ + ['datadirectory', $datadir, $datadir], + ['logfile', $defaultLog, $path], + ['logfilemode', 0640, 0640], + ]); + + $log = $this->factory->get('file'); + $this->assertInstanceOf(File::class, $log); + $this->assertSame($expected, $log->getLogFilePath()); + } + + /** + * @throws QueryException + */ + public function testErrorLog(): void { + $log = $this->factory->get('errorlog'); + $this->assertInstanceOf(Errorlog::class, $log); + } + + /** + * @throws QueryException + */ + public function testSystemLog(): void { + $this->c->expects($this->once()) + ->method('resolve') + ->with(Syslog::class) + ->willReturn($this->createMock(Syslog::class)); + + $log = $this->factory->get('syslog'); + $this->assertInstanceOf(Syslog::class, $log); + } + + /** + * @throws QueryException + */ + public function testSystemdLog(): void { + $this->c->expects($this->once()) + ->method('resolve') + ->with(Systemdlog::class) + ->willReturn($this->createMock(Systemdlog::class)); + + $log = $this->factory->get('systemd'); + $this->assertInstanceOf(Systemdlog::class, $log); + } +} diff --git a/tests/lib/Log/PsrLoggerAdapterTest.php b/tests/lib/Log/PsrLoggerAdapterTest.php new file mode 100644 index 00000000000..c11af7a12c2 --- /dev/null +++ b/tests/lib/Log/PsrLoggerAdapterTest.php @@ -0,0 +1,82 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace Test\Log; + +use OC\Log; +use OC\Log\PsrLoggerAdapter; +use OCP\ILogger; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\InvalidArgumentException; +use Psr\Log\LogLevel; +use Test\TestCase; + +class PsrLoggerAdapterTest extends TestCase { + protected Log&MockObject $logger; + protected PsrLoggerAdapter $loggerAdapter; + + protected function setUp(): void { + parent::setUp(); + + $this->logger = $this->createMock(Log::class); + $this->loggerAdapter = new PsrLoggerAdapter($this->logger); + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataPsrLoggingLevels')] + public function testLoggingWithPsrLogLevels(string $level, int $expectedLevel): void { + $this->logger->expects(self::once()) + ->method('log') + ->with($expectedLevel, 'test message', ['app' => 'test']); + $this->loggerAdapter->log($level, 'test message', ['app' => 'test']); + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataPsrLoggingLevels')] + public function testLogLevelToInt(string $level, int $expectedLevel): void { + $this->assertEquals($expectedLevel, PsrLoggerAdapter::logLevelToInt($level)); + } + + public static function dataPsrLoggingLevels(): array { + return [ + [LogLevel::ALERT, ILogger::ERROR], + [LogLevel::CRITICAL, ILogger::ERROR], + [LogLevel::DEBUG, ILogger::DEBUG], + [LogLevel::EMERGENCY, ILogger::FATAL], + [LogLevel::ERROR, ILogger::ERROR], + [LogLevel::INFO, ILogger::INFO], + [LogLevel::NOTICE, ILogger::INFO], + [LogLevel::WARNING, ILogger::WARN], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataInvalidLoggingLevel')] + public function testInvalidLoggingLevel($level): void { + $this->logger->expects(self::never()) + ->method('log'); + $this->expectException(InvalidArgumentException::class); + + $this->loggerAdapter->log($level, 'valid message'); + } + + public static function dataInvalidLoggingLevel(): array { + return [ + // invalid string + ['this is not a level'], + // int out of range + [ILogger::DEBUG - 1], + [ILogger::FATAL + 1], + // float is not allowed + [1.2345], + // boolean is not a level + [true], + [false], + // + [null], + ]; + } +} |