From 8e697940fbdc47752fbccd41c01f4a4cacd38fba Mon Sep 17 00:00:00 2001 From: Daniel Seifert Date: Wed, 12 Feb 2025 10:42:02 +0100 Subject: [PATCH] complete tests --- src/SpecialHandlersTrait.php | 24 +-- tests/LoggerFactoryTest.php | 122 +----------- tests/ProcessorsTestTrait.php | 135 ++++++++++++++ tests/SensitiveFilterProcessorTest.php | 150 +++++++++++++++ tests/SpecialHandlersTestTrait.php | 246 +++++++++++++++++++++++++ 5 files changed, 547 insertions(+), 130 deletions(-) create mode 100644 tests/ProcessorsTestTrait.php create mode 100644 tests/SensitiveFilterProcessorTest.php create mode 100644 tests/SpecialHandlersTestTrait.php diff --git a/src/SpecialHandlersTrait.php b/src/SpecialHandlersTrait.php index d869990..1266c18 100644 --- a/src/SpecialHandlersTrait.php +++ b/src/SpecialHandlersTrait.php @@ -43,7 +43,7 @@ trait SpecialHandlersTrait } public function setBuffering( - AbstractHandler $handler, + HandlerInterface $handler, int $bufferLimit = 0, int $loglevel = Logger::DEBUG ): BufferHandler { @@ -52,7 +52,7 @@ trait SpecialHandlersTrait } public function setLogItemsOnErrorOnly( - AbstractHandler $handler, + HandlerInterface $handler, int $activationLevel = Logger::ERROR ): FingersCrossedHandler { return new FingersCrossedHandler( @@ -63,7 +63,7 @@ trait SpecialHandlersTrait } public function makeUnique( - AbstractHandler $handler, + HandlerInterface $handler, int $deduplicationLevel = Logger::ERROR, int $time = 60 ): DeduplicationHandler { @@ -73,10 +73,10 @@ trait SpecialHandlersTrait /** * @param array $specialHandlerFlags - * @param AbstractHandler $handler - * @return AbstractHandler + * @param HandlerInterface $handler + * @return HandlerInterface */ - protected function applyBufferHandler(array $specialHandlerFlags, AbstractHandler $handler): AbstractHandler + protected function applyBufferHandler(array $specialHandlerFlags, HandlerInterface $handler): HandlerInterface { if (in_array(self::SPECIAL_HANDLERS_BUFFERING, $specialHandlerFlags, true)) { $handler = $this->setBuffering($handler); @@ -95,10 +95,10 @@ trait SpecialHandlersTrait /** * @param array $specialHandlerFlags - * @param AbstractHandler $handler - * @return AbstractHandler + * @param HandlerInterface $handler + * @return HandlerInterface */ - protected function applyLogOnErrorOnlyHandler(array $specialHandlerFlags, AbstractHandler $handler): AbstractHandler + protected function applyLogOnErrorOnlyHandler(array $specialHandlerFlags, HandlerInterface $handler): HandlerInterface { if (in_array(self::SPECIAL_HANDLERS_LOG_ON_ERROR_ONLY, $specialHandlerFlags, true)) { $handler = $this->setLogItemsOnErrorOnly($handler); @@ -115,10 +115,10 @@ trait SpecialHandlersTrait /** * @param array $specialHandlerFlags - * @param AbstractHandler $handler - * @return AbstractHandler + * @param HandlerInterface $handler + * @return HandlerInterface */ - protected function applyMakeUniqueHandler(array $specialHandlerFlags, AbstractHandler $handler): AbstractHandler + protected function applyMakeUniqueHandler(array $specialHandlerFlags, HandlerInterface $handler): HandlerInterface { if (in_array(self::SPECIAL_HANDLERS_MAKE_UNIQUE, $specialHandlerFlags, true)) { /** @phpstan-ignore argument.type */ diff --git a/tests/LoggerFactoryTest.php b/tests/LoggerFactoryTest.php index a55268e..b13c969 100644 --- a/tests/LoggerFactoryTest.php +++ b/tests/LoggerFactoryTest.php @@ -17,9 +17,6 @@ namespace D3\LoggerFactory\tests; use D3\LoggerFactory\LoggerFactory; use Generator; -use Monolog\Handler\BufferHandler; -use Monolog\Handler\DeduplicationHandler; -use Monolog\Handler\FingersCrossedHandler; use Monolog\Handler\RotatingFileHandler; use Monolog\Handler\StreamHandler; use Monolog\Logger; @@ -32,6 +29,9 @@ use RuntimeException; */ class LoggerFactoryTest extends ApiTestCase { + use SpecialHandlersTestTrait; + use ProcessorsTestTrait; + /** * @test * @return void @@ -67,7 +67,6 @@ class LoggerFactoryTest extends ApiTestCase $this->assertInstanceOf(Logger::class, $logger); $this->assertInstanceOf($expectedHandlerClass, $logger->getHandlers()[0]); - $this->assertSame($logLevel, $logger->getHandlers()[0]->getLevel()); } public static function getFileLoggerDataProvider(): Generator @@ -139,7 +138,7 @@ class LoggerFactoryTest extends ApiTestCase $logger = $this->callMethod( $sut, 'getCombinedOxidAndFileLogger', - ['nameFixture', 'file/path.log', 1, 5] + ['nameFixture', 'file/path.log', Logger::INFO, 5] ); $this->assertInstanceOf(Logger::class, $logger); @@ -166,117 +165,4 @@ class LoggerFactoryTest extends ApiTestCase ) ); } - - /** - * @test - * @covers \D3\LoggerFactory\LoggerFactory::applySpecialHandlers - * @throws ReflectionException - * @dataProvider applySpecialHandlersDataProvider - */ - public function testApplySpecialHandlers(array $options, string $expectedClass): void - { - $sut = LoggerFactory::create(); - - $handler = $this->getMockBuilder(StreamHandler::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->assertInstanceOf( - $expectedClass, - $this->callMethod( - $sut, - 'applySpecialHandlers', - [$handler, $options] - ) - ); - } - - public static function applySpecialHandlersDataProvider(): Generator - { - yield 'empty config' => [[], StreamHandler::class]; - yield 'simple buffering' => [[LoggerFactory::SPECIAL_HANDLERS_BUFFERING], BufferHandler::class]; - yield 'advanced buffering' => [ - [LoggerFactory::SPECIAL_HANDLERS_BUFFERING => [LoggerFactory::BUFFERING_OPTION_LIMIT => 10]], - BufferHandler::class, - ]; - yield 'simple logOnErrorOnly' => [[LoggerFactory::SPECIAL_HANDLERS_LOG_ON_ERROR_ONLY], FingersCrossedHandler::class]; - yield 'advanced logOnErrorOnly' => [ - [LoggerFactory::SPECIAL_HANDLERS_LOG_ON_ERROR_ONLY => [LoggerFactory::LOGONERRORONLY_LEVEL => Logger::DEBUG]], - FingersCrossedHandler::class, - ]; - yield 'simple deduplicate' => [[LoggerFactory::SPECIAL_HANDLERS_MAKE_UNIQUE], DeduplicationHandler::class]; - yield 'advanced deduplicate' => [ - [LoggerFactory::SPECIAL_HANDLERS_MAKE_UNIQUE => [LoggerFactory::MAKEUNIQUE_OPTION_TIME => 30]], - DeduplicationHandler::class, - ]; - } - - /** - * @test - * @throws ReflectionException - * @covers \D3\LoggerFactory\LoggerFactory::setBuffering - */ - public function testSetBuffering(): void - { - $sut = LoggerFactory::create(); - - $handler = $this->getMockBuilder(StreamHandler::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->assertInstanceOf( - BufferHandler::class, - $this->callMethod( - $sut, - 'setBuffering', - [$handler] - ) - ); - } - - /** - * @test - * @throws ReflectionException - * @covers \D3\LoggerFactory\LoggerFactory::setLogItemsOnErrorOnly - */ - public function testSetLogItemsOnErrorOnly(): void - { - $sut = LoggerFactory::create(); - - $handler = $this->getMockBuilder(StreamHandler::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->assertInstanceOf( - FingersCrossedHandler::class, - $this->callMethod( - $sut, - 'setLogItemsOnErrorOnly', - [$handler] - ) - ); - } - - /** - * @test - * @throws ReflectionException - * @covers \D3\LoggerFactory\LoggerFactory::makeUnique - */ - public function testMakeUnique(): void - { - $sut = LoggerFactory::create(); - - $handler = $this->getMockBuilder(StreamHandler::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->assertInstanceOf( - DeduplicationHandler::class, - $this->callMethod( - $sut, - 'makeUnique', - [$handler] - ) - ); - } } diff --git a/tests/ProcessorsTestTrait.php b/tests/ProcessorsTestTrait.php new file mode 100644 index 0000000..f7d6127 --- /dev/null +++ b/tests/ProcessorsTestTrait.php @@ -0,0 +1,135 @@ + + * @link https://www.oxidmodule.com + */ + +namespace D3\LoggerFactory\tests; + +use D3\LoggerFactory\LoggerFactory; +use Generator; +use Monolog\Logger; +use PHPUnit\Framework\MockObject\MockObject; +use ReflectionException; + +/** + * @coversNothing + */ +trait ProcessorsTestTrait +{ + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\LoggerFactory\LoggerFactory::applyProcessors + */ + public function testApplyProcessors(): void + { + $logger = $this->getMockBuilder(Logger::class) + ->disableOriginalConstructor() + ->getMock(); + + $sut = $this->getMockBuilder(LoggerFactory::class) + ->onlyMethods(['applyUidProcessor', 'applyFilterSensitiveProcessor']) + ->getMock(); + $sut->expects($this->once())->method('applyUidProcessor'); + $sut->expects($this->once())->method('applyFilterSensitiveProcessor'); + + $this->assertInstanceOf( + Logger::class, + $this->callMethod( + $sut, + 'applyProcessors', + [$logger, []] + ) + ); + } + + /** + * @test + * + * @param array $configuration + * @param int $expectedCount + * + * @return void + * @throws ReflectionException + * @covers \D3\LoggerFactory\LoggerFactory::applyUidProcessor + * @dataProvider applyUidProcessorDataProvider + */ + public function testApplyUidProcessor(array $configuration, int $expectedCount): void + { + /** @var Logger|MockObject $logger */ + $logger = LoggerFactory::create()->getFileLogger('foo', 'logg.file'); + + $sut = LoggerFactory::create(); + + $this->callMethod( + $sut, + 'applyUidProcessor', + [$configuration, $logger] + ); + + $this->assertCount( + $expectedCount, + $logger->getProcessors() + ); + } + + public static function applyUidProcessorDataProvider(): Generator + { + yield 'simple configuration' => [[LoggerFactory::PROCESSOR_UNIQUE_ID], 1]; + yield 'advanced configuration' => [[LoggerFactory::PROCESSOR_UNIQUE_ID => ''], 1]; + yield 'no configuration' => [[], 0]; + } + + /** + * @test + * + * @param array $configuration + * @param int $expectedCount + * + * @return void + * @throws ReflectionException + * @covers \D3\LoggerFactory\LoggerFactory::applyFilterSensitiveProcessor + * @dataProvider applyFilterProcessorDataProvider + */ + public function testApplyFilterProcessor(array $configuration, int $expectedCount, bool $expectException): void + { + /** @var Logger|MockObject $logger */ + $logger = LoggerFactory::create()->getFileLogger('foo', 'logg.file'); + + $sut = LoggerFactory::create(); + + if ($expectException) { + $this->expectException(\RuntimeException::class); + } + + $this->callMethod( + $sut, + 'applyFilterSensitiveProcessor', + [$configuration, $logger] + ); + + $this->assertCount( + $expectedCount, + $logger->getProcessors() + ); + } + + public static function applyFilterProcessorDataProvider(): Generator + { + yield 'simple configuration' => [[LoggerFactory::PROCESSOR_FILTERSENSITIVE], 0, false]; + yield 'advanced configuration' => [[LoggerFactory::PROCESSOR_FILTERSENSITIVE => [LoggerFactory::FILTERSENSITIVE_SECRETS => ['foo']]], 1, false]; + yield 'misconfiguration' => [[LoggerFactory::PROCESSOR_FILTERSENSITIVE => [LoggerFactory::FILTERSENSITIVE_SECRETS => 'foo']], 0, true]; + yield 'no configuration' => [[], 0, false]; + } +} \ No newline at end of file diff --git a/tests/SensitiveFilterProcessorTest.php b/tests/SensitiveFilterProcessorTest.php new file mode 100644 index 0000000..a1fc184 --- /dev/null +++ b/tests/SensitiveFilterProcessorTest.php @@ -0,0 +1,150 @@ + + * @link https://www.oxidmodule.com + */ + +namespace D3\LoggerFactory\tests; + +use D3\LoggerFactory\SensitiveFilterProcessor; +use Generator; +use ReflectionException; + +/** + * @coversNothing + */ +class SensitiveFilterProcessorTest extends ApiTestCase +{ + /** + * @test + * @param string|null $replacementArgument + * @param string $expectedReplacement + * + * @return void + * @throws ReflectionException + * @covers \D3\LoggerFactory\SensitiveFilterProcessor::__construct + * @dataProvider constructDataProvider + */ + public function testConstruct(?string $replacementArgument, string $expectedReplacement) + { + $sut = $this->getMockBuilder(SensitiveFilterProcessor::class) + ->onlyMethods(['convertStringsToRegex']) + ->disableOriginalConstructor() + ->getMock(); + $sut->expects($this->once())->method('convertStringsToRegex'); + + $this->callMethod( + $sut, + '__construct', + [['foo'], $replacementArgument] + ); + + $this->assertSame( + $expectedReplacement, + $this->getValue( + $sut, + 'replacement' + ) + ); + } + + public static function constructDataProvider(): Generator + { + yield 'default replacement' => [null, '*****']; + } + + /** + * @test + * @throws ReflectionException + * @dataProvider convertStringsToRegexDataProvider + * @covers \D3\LoggerFactory\SensitiveFilterProcessor::convertStringsToRegex + * @covers \D3\LoggerFactory\SensitiveFilterProcessor::stringIsRegexp + */ + public function testConvertStringsToRegex( + array $input, + array $expected + ): void { + $sutMock = $this->getMockBuilder(SensitiveFilterProcessor::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->callMethod( + $sutMock, + 'convertStringsToRegex', + [$input] + ); + + $this->assertSame( + $expected, + $this->getValue( + $sutMock, + 'secrets' + ) + ); + } + + public static function convertStringsToRegexDataProvider(): Generator + { + yield 'simple' => [['abc'], ['/abc/i']]; + yield 'multiple' => [['def', 'ghi'], ['/def/i', '/ghi/i']]; + yield 'urlencoded' => [['1&c'], ['/1&c/i', '/1%26c/i']]; + yield 'delimiter' => [['de/fg'], ['/de\/fg/i', '/de%2Ffg/i']]; + yield 'regex' => [['/abc/mi'], ['/abc/mi']]; + yield 'mixed' => [['/abc/mi', 'def', '/ghi/mi'], ['/abc/mi', '/def/i', '/ghi/mi']]; + } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\LoggerFactory\SensitiveFilterProcessor::__invoke + */ + public function testInvoke() + { + $sut = new SensitiveFilterProcessor(['secret1', 'password'], '###'); + + $record = [ + 'key1' => null, + 'key2' => 'value+secret1+value+password', + 'password' => 'secret1', + 'key4' => [ + 'subkey1' => null, + 'subkey2' => 'value+password+value+secret1', + 'subkey3' => [ + 'subsubkey3' => 'value+password+value+secret1', + ], + ] + ]; + + $expected = [ + 'key1' => null, + 'key2' => 'value+###+value+###', + 'password' => '###', + 'key4' => [ + 'subkey1' => null, + 'subkey2' => 'value+###+value+###', + 'subkey3' => [ + 'subsubkey3' => 'value+###+value+###', + ], + ] + ]; + + $this->assertSame( + $expected, + $this->callMethod( + $sut, + '__invoke', + [$record] + ) + ); + } +} \ No newline at end of file diff --git a/tests/SpecialHandlersTestTrait.php b/tests/SpecialHandlersTestTrait.php new file mode 100644 index 0000000..4fc34d6 --- /dev/null +++ b/tests/SpecialHandlersTestTrait.php @@ -0,0 +1,246 @@ + + * @link https://www.oxidmodule.com + */ + +namespace D3\LoggerFactory\tests; + +use D3\LoggerFactory\LoggerFactory; +use Generator; +use Monolog\Handler\BufferHandler; +use Monolog\Handler\DeduplicationHandler; +use Monolog\Handler\FingersCrossedHandler; +use Monolog\Handler\HandlerInterface; +use Monolog\Handler\StreamHandler; +use Monolog\Logger; +use ReflectionException; + +/** + * @coversNothing + */ +trait SpecialHandlersTestTrait +{ + /** + * @test + * @covers \D3\LoggerFactory\LoggerFactory::applySpecialHandlers + * @throws ReflectionException + */ + public function testApplySpecialHandlers(): void + { + $sut = $this->getMockBuilder(LoggerFactory::class) + ->onlyMethods(['applyBufferHandler', 'applyLogOnErrorOnlyHandler', 'applyMakeUniqueHandler']) + ->getMock(); + $sut->expects($this->once())->method('applyBufferHandler'); + $sut->expects($this->once())->method('applyLogOnErrorOnlyHandler'); + $sut->expects($this->once())->method('applyMakeUniqueHandler'); + + $handler = $this->getMockBuilder(StreamHandler::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->assertInstanceOf( + HandlerInterface::class, + $this->callMethod( + $sut, + 'applySpecialHandlers', + [$handler, []] + ) + ); + } + + /** + * @test + * @throws ReflectionException + * @covers \D3\LoggerFactory\LoggerFactory::setBuffering + */ + public function testSetBuffering(): void + { + $sut = LoggerFactory::create(); + + $handler = $this->getMockBuilder(StreamHandler::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->assertInstanceOf( + BufferHandler::class, + $this->callMethod( + $sut, + 'setBuffering', + [$handler] + ) + ); + } + + /** + * @test + * @throws ReflectionException + * @covers \D3\LoggerFactory\LoggerFactory::setLogItemsOnErrorOnly + */ + public function testSetLogItemsOnErrorOnly(): void + { + $sut = LoggerFactory::create(); + + $handler = $this->getMockBuilder(StreamHandler::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->assertInstanceOf( + FingersCrossedHandler::class, + $this->callMethod( + $sut, + 'setLogItemsOnErrorOnly', + [$handler] + ) + ); + } + + /** + * @test + * @throws ReflectionException + * @covers \D3\LoggerFactory\LoggerFactory::makeUnique + */ + public function testMakeUnique(): void + { + $sut = LoggerFactory::create(); + + $handler = $this->getMockBuilder(StreamHandler::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->assertInstanceOf( + DeduplicationHandler::class, + $this->callMethod( + $sut, + 'makeUnique', + [$handler] + ) + ); + } + + /** + * @test + * + * @param array $configuration + * @param string $expectedClass + * + * @return void + * @throws ReflectionException + * @covers \D3\LoggerFactory\LoggerFactory::applyBufferHandler + * @dataProvider applyBufferHandlerDataProvider + */ + public function testApplyBufferHandler(array $configuration, string $expectedClass): void + { + $handler = $this->getMockBuilder(StreamHandler::class) + ->disableOriginalConstructor() + ->getMock(); + + $sut = LoggerFactory::create(); + + $this->assertInstanceOf( + $expectedClass, + $this->callMethod( + $sut, + 'applyBufferHandler', + [$configuration, $handler] + ) + ); + } + + public static function applyBufferHandlerDataProvider(): Generator + { + yield 'empty config' => [[], StreamHandler::class]; + yield 'simple buffering' => [[LoggerFactory::SPECIAL_HANDLERS_BUFFERING], BufferHandler::class]; + yield 'advanced buffering' => [ + [LoggerFactory::SPECIAL_HANDLERS_BUFFERING => [LoggerFactory::BUFFERING_OPTION_LIMIT => 10]], + BufferHandler::class, + ]; + } + + /** + * @test + * + * @param array $configuration + * @param string $expectedClass + * + * @return void + * @throws ReflectionException + * @covers \D3\LoggerFactory\LoggerFactory::applyLogOnErrorOnlyHandler + * @dataProvider applyLogOnErrorOnlyHandlerDataProvider + */ + public function testApplyLogOnErrorOnlyHandler(array $configuration, string $expectedClass): void + { + $handler = $this->getMockBuilder(StreamHandler::class) + ->disableOriginalConstructor() + ->getMock(); + + $sut = LoggerFactory::create(); + + $this->assertInstanceOf( + $expectedClass, + $this->callMethod( + $sut, + 'applyLogOnErrorOnlyHandler', + [$configuration, $handler] + ) + ); + } + + public static function applyLogOnErrorOnlyHandlerDataProvider(): Generator + { + yield 'empty config' => [[], StreamHandler::class]; + yield 'simple logOnErrorOnly' => [[LoggerFactory::SPECIAL_HANDLERS_LOG_ON_ERROR_ONLY], FingersCrossedHandler::class]; + yield 'advanced logOnErrorOnly' => [ + [LoggerFactory::SPECIAL_HANDLERS_LOG_ON_ERROR_ONLY => [LoggerFactory::LOGONERRORONLY_LEVEL => Logger::DEBUG]], + FingersCrossedHandler::class, + ]; + } + + /** + * @test + * + * @param array $configuration + * @param string $expectedClass + * + * @return void + * @throws ReflectionException + * @covers \D3\LoggerFactory\LoggerFactory::applyMakeUniqueHandler + * @dataProvider applyMakeUniqueHandlerDataProvider + */ + public function testApplyMakeUniqueHandler(array $configuration, string $expectedClass): void + { + $handler = $this->getMockBuilder(StreamHandler::class) + ->disableOriginalConstructor() + ->getMock(); + + $sut = LoggerFactory::create(); + + $this->assertInstanceOf( + $expectedClass, + $this->callMethod( + $sut, + 'applyMakeUniqueHandler', + [$configuration, $handler] + ) + ); + } + + public static function applyMakeUniqueHandlerDataProvider(): Generator + { + yield 'empty config' => [[], StreamHandler::class]; + yield 'simple deduplicate' => [[LoggerFactory::SPECIAL_HANDLERS_MAKE_UNIQUE], DeduplicationHandler::class]; + yield 'advanced deduplicate' => [ + [LoggerFactory::SPECIAL_HANDLERS_MAKE_UNIQUE => [LoggerFactory::MAKEUNIQUE_OPTION_TIME => 30]], + DeduplicationHandler::class, + ]; + } +} \ No newline at end of file