]> git.mxchange.org Git - friendica.git/blob - tests/src/Core/Logger/AbstractLoggerTest.php
Improved logging
[friendica.git] / tests / src / Core / Logger / AbstractLoggerTest.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2023, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 namespace Friendica\Test\src\Core\Logger;
23
24 use Friendica\Core\Config\Capability\IManageConfigValues;
25 use Friendica\Test\MockedTest;
26 use Friendica\Core\Logger\Util\Introspection;
27 use Mockery\MockInterface;
28 use Psr\Log\LoggerInterface;
29 use Psr\Log\LogLevel;
30
31 abstract class AbstractLoggerTest extends MockedTest
32 {
33         use LoggerDataTrait;
34
35         const LOGLINE = '/.* \[.*]: .* {.*\"file\":\".*\".*,.*\"line\":\d*,.*\"function\":\".*\".*,.*\"uid\":\".*\".*}/';
36
37         const FILE = 'test';
38         const LINE = 666;
39         const FUNC = 'myfunction';
40
41         /**
42          * @var Introspection|MockInterface
43          */
44         protected $introspection;
45         /**
46          * @var IManageConfigValues|MockInterface
47          */
48         protected $config;
49
50         /**
51          * Returns the content of the current logger instance
52          *
53          * @return string
54          */
55         abstract protected function getContent();
56
57         /**
58          * Returns the current logger instance
59          *
60          * @param string $level the default loglevel
61          *
62          * @return LoggerInterface
63          */
64         abstract protected function getInstance($level = LogLevel::DEBUG);
65
66         protected function setUp(): void
67         {
68                 parent::setUp();
69
70                 $this->introspection = \Mockery::mock(Introspection::class);
71                 $this->introspection->shouldReceive('getRecord')->andReturn([
72                         'file'     => self::FILE,
73                         'line'     => self::LINE,
74                         'function' => self::FUNC
75                 ]);
76
77                 $this->config = \Mockery::mock(IManageConfigValues::class);
78         }
79
80         public function assertLogline($string)
81         {
82                 self::assertMatchesRegularExpression(self::LOGLINE, $string);
83         }
84
85         public function assertLoglineNums($assertNum, $string)
86         {
87                 self::assertEquals($assertNum, preg_match_all(self::LOGLINE, $string));
88         }
89
90         /**
91          * Test if the logger works correctly
92          */
93         public function testNormal()
94         {
95                 $logger = $this->getInstance();
96                 $logger->emergency('working!');
97                 $logger->alert('working too!');
98                 $logger->debug('and now?');
99                 $logger->notice('message', ['an' => 'context']);
100
101                 $text = $this->getContent();
102                 self::assertLogline($text);
103                 self::assertLoglineNums(4, $text);
104         }
105
106         /**
107          * Test if a log entry is correctly interpolated
108          */
109         public function testPsrInterpolate()
110         {
111                 $logger = $this->getInstance();
112
113                 $logger->emergency('A {psr} test', ['psr' => 'working']);
114                 $logger->alert('An {array} test', ['array' => ['it', 'is', 'working']]);
115                 $text = $this->getContent();
116                 self::assertStringContainsString('A working test', $text);
117                 self::assertStringContainsString('An ["it","is","working"] test', $text);
118         }
119
120         /**
121          * Test if a log entry contains all necessary information
122          */
123         public function testContainsInformation()
124         {
125                 $logger = $this->getInstance();
126                 $logger->emergency('A test');
127
128                 $text = $this->getContent();
129                 self::assertStringContainsString('"file":"' . self::FILE . '"', $text);
130                 self::assertStringContainsString('"line":' . self::LINE, $text);
131                 self::assertStringContainsString('"function":"' . self::FUNC . '"', $text);
132         }
133
134         /**
135          * Test if the minimum level is working
136          */
137         public function testMinimumLevel()
138         {
139                 $logger = $this->getInstance(LogLevel::NOTICE);
140
141                 $logger->emergency('working');
142                 $logger->alert('working');
143                 $logger->error('working');
144                 $logger->warning('working');
145                 $logger->notice('working');
146                 $logger->info('not working');
147                 $logger->debug('not working');
148
149                 $text = $this->getContent();
150
151                 self::assertLoglineNums(5, $text);
152         }
153
154         /**
155          * Test with different logging data
156          * @dataProvider dataTests
157          */
158         public function testDifferentTypes($function, $message, array $context)
159         {
160                 $logger = $this->getInstance();
161                 $logger->$function($message, $context);
162
163                 $text = $this->getContent();
164
165                 self::assertLogline($text);
166
167                 self::assertStringContainsString(@json_encode($context, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), $text);
168         }
169
170         /**
171          * Test a message with an exception
172          */
173         public function testExceptionHandling()
174         {
175                 $e = new \Exception("Test String", 123);
176                 $eFollowUp = new \Exception("FollowUp", 456, $e);
177
178                 $assertion = $eFollowUp->__toString();
179
180                 $logger = $this->getInstance();
181                 $logger->alert('test', ['e' => $eFollowUp]);
182                 $text = $this->getContent();
183
184                 self::assertLogline($text);
185
186                 self::assertStringContainsString(@json_encode($assertion, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), $this->getContent());
187         }
188
189         public function testNoObjectHandling()
190         {
191                 $logger = $this->getInstance();
192                 $logger->alert('test', ['e' => ['test' => 'test']]);
193                 $text = $this->getContent();
194
195                 self::assertLogline($text);
196
197                 self::assertStringContainsString('test', $this->getContent());
198         }
199 }