LogPrinterV6   A
last analyzed

Complexity

Total Complexity 30

Size/Duplication

Total Lines 300
Duplicated Lines 44.67 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 30
lcom 1
cbo 5
dl 134
loc 300
ccs 0
cts 168
cp 0
rs 10
c 0
b 0
f 0

18 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A addError() 12 12 1
A addWarning() 0 12 1
A addFailure() 0 12 1
A addIncompleteTest() 12 12 1
A addRiskyTest() 12 12 1
A addSkippedTest() 12 12 1
A startTestSuite() 11 11 1
A endTestSuite() 0 5 1
A startTest() 11 11 2
A endTest() 0 6 2
A writeCase() 18 18 2
A writeArray() 10 10 2
A writeToLog() 8 8 3
A getLogFilename() 14 14 4
A getLogDirectory() 14 14 3
A convertToUtf8() 0 8 2
A getStackTrace() 0 4 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Paraunit\Parser\JSON;
6
7
use Paraunit\Configuration\EnvVariables;
8
use PHPUnit\Framework\AssertionFailedError;
9
use PHPUnit\Framework\SelfDescribing;
10
use PHPUnit\Framework\Test;
11
use PHPUnit\Framework\TestCase;
12
use PHPUnit\Framework\TestFailure;
13
use PHPUnit\Framework\TestListener;
14
use PHPUnit\Framework\TestSuite;
15
use PHPUnit\Framework\Warning;
16
use PHPUnit\Util;
17
18
/**
19
 * This class duplicates the original one because in PHPUnit 7 the signatures of the TestListener interface are : void
20
 *
21
 * Class LogPrinter
22
 * @package Paraunit\Parser\JSON
23
 */
24
class LogPrinterV6 extends Util\Printer implements TestListener
25
{
26
    const STATUS_ERROR = 'error';
27
    const STATUS_WARNING = 'warning';
28
    const STATUS_FAIL = 'fail';
29
    const STATUS_PASS = 'pass';
30
31
    const MESSAGE_INCOMPLETE_TEST = 'Incomplete Test: ';
32
    const MESSAGE_RISKY_TEST = 'Risky Test: ';
33
    const MESSAGE_SKIPPED_TEST = 'Skipped Test: ';
34
35
    /** @var resource */
36
    private $logFile;
37
38
    /** @var string */
39
    private $currentTestSuiteName;
40
41
    /** @var string */
42
    private $currentTestName;
43
44
    /** @var bool */
45
    private $currentTestPass;
46
47
    public function __construct()
48
    {
49
        $this->logFile = fopen($this->getLogFilename(), 'wt');
50
        $this->autoFlush = true;
51
    }
52
53
    /**
54
     * An error occurred.
55
     *
56
     * @param Test $test
57
     * @param \Exception $exception
58
     * @param float $time
59
     */
60 View Code Duplication
    public function addError(Test $test, \Exception $exception, $time)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
61
    {
62
        $this->writeCase(
63
            self::STATUS_ERROR,
64
            $time,
65
            $this->getStackTrace($exception),
66
            TestFailure::exceptionToString($exception),
67
            $test
68
        );
69
70
        $this->currentTestPass = false;
71
    }
72
73
    /**
74
     * A warning occurred.
75
     *
76
     * @param Test $test
77
     * @param Warning $warning
78
     * @param float $time
79
     */
80
    public function addWarning(Test $test, Warning $warning, $time)
81
    {
82
        $this->writeCase(
83
            self::STATUS_WARNING,
84
            $time,
85
            $this->getStackTrace($warning),
86
            TestFailure::exceptionToString($warning),
87
            $test
88
        );
89
90
        $this->currentTestPass = false;
91
    }
92
93
    /**
94
     * A failure occurred.
95
     *
96
     * @param Test $test
97
     * @param AssertionFailedError $error
98
     * @param float $time
99
     */
100
    public function addFailure(Test $test, AssertionFailedError $error, $time)
101
    {
102
        $this->writeCase(
103
            self::STATUS_FAIL,
104
            $time,
105
            $this->getStackTrace($error),
106
            TestFailure::exceptionToString($error),
107
            $test
108
        );
109
110
        $this->currentTestPass = false;
111
    }
112
113
    /**
114
     * Incomplete test.
115
     *
116
     * @param Test $test
117
     * @param \Exception $error
118
     * @param float $time
119
     */
120 View Code Duplication
    public function addIncompleteTest(Test $test, \Exception $error, $time)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
121
    {
122
        $this->writeCase(
123
            self::STATUS_ERROR,
124
            $time,
125
            $this->getStackTrace($error),
126
            self::MESSAGE_INCOMPLETE_TEST . $error->getMessage(),
127
            $test
128
        );
129
130
        $this->currentTestPass = false;
131
    }
132
133
    /**
134
     * Risky test.
135
     *
136
     * @param Test $test
137
     * @param \Exception $exception
138
     * @param float $time
139
     */
140 View Code Duplication
    public function addRiskyTest(Test $test, \Exception $exception, $time)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
141
    {
142
        $this->writeCase(
143
            self::STATUS_ERROR,
144
            $time,
145
            $this->getStackTrace($exception),
146
            self::MESSAGE_RISKY_TEST . $exception->getMessage(),
147
            $test
148
        );
149
150
        $this->currentTestPass = false;
151
    }
152
153
    /**
154
     * Skipped test.
155
     *
156
     * @param Test $test
157
     * @param \Exception $exception
158
     * @param float $time
159
     */
160 View Code Duplication
    public function addSkippedTest(Test $test, \Exception $exception, $time)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
161
    {
162
        $this->writeCase(
163
            self::STATUS_ERROR,
164
            $time,
165
            $this->getStackTrace($exception),
166
            self::MESSAGE_SKIPPED_TEST . $exception->getMessage(),
167
            $test
168
        );
169
170
        $this->currentTestPass = false;
171
    }
172
173
    /**
174
     * A testsuite started.
175
     *
176
     * @param TestSuite $suite
177
     * @throws \RuntimeException
178
     */
179 View Code Duplication
    public function startTestSuite(TestSuite $suite)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
180
    {
181
        $this->currentTestSuiteName = $suite->getName();
182
        $this->currentTestName = '';
183
184
        $this->writeArray([
185
            'event' => 'suiteStart',
186
            'suite' => $this->currentTestSuiteName,
187
            'tests' => count($suite),
188
        ]);
189
    }
190
191
    public function endTestSuite(TestSuite $suite)
192
    {
193
        $this->currentTestSuiteName = '';
194
        $this->currentTestName = '';
195
    }
196
197 View Code Duplication
    public function startTest(Test $test)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
198
    {
199
        $this->currentTestName = $test instanceof SelfDescribing ? $test->toString() : \get_class($test);
200
        $this->currentTestPass = true;
201
202
        $this->writeArray([
203
            'event' => 'testStart',
204
            'suite' => $this->currentTestSuiteName,
205
            'test' => $this->currentTestName,
206
        ]);
207
    }
208
209
    /**
210
     * A test ended.
211
     *
212
     * @param Test $test
213
     * @param float $time
214
     */
215
    public function endTest(Test $test, $time)
216
    {
217
        if ($this->currentTestPass) {
218
            $this->writeCase(self::STATUS_PASS, $time, '', '', $test);
219
        }
220
    }
221
222
    /**
223
     * @param string $status
224
     * @param float $time
225
     * @param string $trace
226
     * @param string $message
227
     * @param Test|TestCase|null $test
228
     */
229 View Code Duplication
    private function writeCase(string $status, float $time, string $trace, $message = '', $test = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
230
    {
231
        $output = '';
232
        if ($test instanceof TestCase) {
233
            $output = $test->getActualOutput();
234
        }
235
236
        $this->writeArray([
237
            'event' => 'test',
238
            'suite' => $this->currentTestSuiteName,
239
            'test' => $this->currentTestName,
240
            'status' => $status,
241
            'time' => $time,
242
            'trace' => $trace,
243
            'message' => $this->convertToUtf8($message),
244
            'output' => $output,
245
        ]);
246
    }
247
248
    /**
249
     * @param array $buffer
250
     */
251 View Code Duplication
    private function writeArray($buffer)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
252
    {
253
        array_walk_recursive($buffer, function (&$input) {
254
            if (is_string($input)) {
255
                $input = $this->convertToUtf8($input);
256
            }
257
        });
258
259
        $this->writeToLog(json_encode($buffer, JSON_PRETTY_PRINT));
260
    }
261
262 View Code Duplication
    private function writeToLog($buffer)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
263
    {
264
        // ignore everything that is not a JSON object
265
        if ($buffer != '' && $buffer[0] === '{') {
266
            \fwrite($this->logFile, $buffer);
267
            \fflush($this->logFile);
268
        }
269
    }
270
271
    /**
272
     * @return string
273
     * @throws \RuntimeException
274
     * @throws \InvalidArgumentException
275
     */
276 View Code Duplication
    private function getLogFilename(): string
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
277
    {
278
        $logDir = $this->getLogDirectory();
279
        if (! @mkdir($logDir, 0777, true) && ! is_dir($logDir)) {
280
            throw new \RuntimeException('Cannot create folder for JSON logs');
281
        }
282
283
        $logFilename = getenv(EnvVariables::PROCESS_UNIQUE_ID);
284
        if ($logFilename === false) {
285
            throw new \InvalidArgumentException('Log filename not received: environment variable not set');
286
        }
287
288
        return $logDir . $logFilename . '.json.log';
289
    }
290
291
    /**
292
     * @return string
293
     * @throws \InvalidArgumentException
294
     */
295 View Code Duplication
    private function getLogDirectory(): string
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
296
    {
297
        $logDirectory = getenv(EnvVariables::LOG_DIR);
298
299
        if ($logDirectory === false) {
300
            throw new \InvalidArgumentException('Log directory not received: environment variable not set');
301
        }
302
303
        if (substr($logDirectory, -1) !== DIRECTORY_SEPARATOR) {
304
            $logDirectory .= DIRECTORY_SEPARATOR;
305
        }
306
307
        return $logDirectory;
308
    }
309
310
    private function convertToUtf8($string): string
311
    {
312
        if (! \mb_detect_encoding($string, 'UTF-8', true)) {
313
            return \mb_convert_encoding($string, 'UTF-8');
314
        }
315
316
        return $string;
317
    }
318
319
    private function getStackTrace($error): string
320
    {
321
        return Util\Filter::getFilteredStacktrace($error);
322
    }
323
}
324