Completed
Push — master ( 01e071...007090 )
by Ehsan
01:46 queued 13s
created

TestRunner::doRun()   F

Complexity

Conditions 87
Paths > 20000

Size

Total Lines 498
Code Lines 280

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 87
eloc 280
nc 4294967295
nop 3
dl 0
loc 498
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * This file is part of PHPUnit.
4
 *
5
 * (c) Sebastian Bergmann <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace PHPUnit\TextUI;
12
13
use PHPUnit\Framework\Error\Notice;
14
use PHPUnit\Framework\Error\Warning;
15
use PHPUnit\Framework\Exception;
16
use PHPUnit\Framework\TestSuite;
17
use PHPUnit\Framework\TestResult;
18
use PHPUnit\Framework\TestListener;
19
use PHPUnit\Framework\Test;
20
use PHPUnit\Runner\BaseTestRunner;
21
use PHPUnit\Runner\Filter\Factory;
22
use PHPUnit\Runner\Version;
23
use PHPUnit\Runner\TestSuiteLoader;
24
use PHPUnit\Runner\StandardTestSuiteLoader;
25
use PHPUnit\Runner\Filter\NameFilterIterator;
26
use PHPUnit\Runner\Filter\ExcludeGroupFilterIterator;
27
use PHPUnit\Runner\Filter\IncludeGroupFilterIterator;
28
use PHPUnit\Util\Configuration;
29
use PHPUnit\Util\Log\JUnit;
30
use PHPUnit\Util\Log\TeamCity;
31
use PHPUnit\Util\Printer;
32
use PHPUnit\Util\TestDox\HtmlResultPrinter;
33
use PHPUnit\Util\TestDox\TextResultPrinter;
34
use PHPUnit\Util\TestDox\XmlResultPrinter;
35
use ReflectionClass;
36
use SebastianBergmann;
37
use SebastianBergmann\CodeCoverage\CodeCoverage;
38
use SebastianBergmann\CodeCoverage\Exception as CodeCoverageException;
39
use SebastianBergmann\CodeCoverage\Filter as CodeCoverageFilter;
40
use SebastianBergmann\CodeCoverage\Report\Clover as CloverReport;
41
use SebastianBergmann\CodeCoverage\Report\Crap4j as Crap4jReport;
42
use SebastianBergmann\CodeCoverage\Report\Html\Facade as HtmlReport;
43
use SebastianBergmann\CodeCoverage\Report\PHP as PhpReport;
44
use SebastianBergmann\CodeCoverage\Report\Text as TextReport;
45
use SebastianBergmann\CodeCoverage\Report\Xml\Facade as XmlReport;
46
use SebastianBergmann\Environment\Runtime;
47
48
/**
49
 * A TestRunner for the Command Line Interface (CLI)
50
 * PHP SAPI Module.
51
 */
52
class TestRunner extends BaseTestRunner
53
{
54
    const SUCCESS_EXIT   = 0;
55
    const FAILURE_EXIT   = 1;
56
    const EXCEPTION_EXIT = 2;
57
58
    /**
59
     * @var CodeCoverageFilter
60
     */
61
    protected $codeCoverageFilter;
62
63
    /**
64
     * @var TestSuiteLoader
65
     */
66
    protected $loader;
67
68
    /**
69
     * @var ResultPrinter
70
     */
71
    protected $printer;
72
73
    /**
74
     * @var bool
75
     */
76
    protected static $versionStringPrinted = false;
77
78
    /**
79
     * @var Runtime
80
     */
81
    private $runtime;
82
83
    /**
84
     * @var bool
85
     */
86
    private $messagePrinted = false;
87
88
    /**
89
     * @param TestSuiteLoader    $loader
90
     * @param CodeCoverageFilter $filter
91
     */
92
    public function __construct(TestSuiteLoader $loader = null, CodeCoverageFilter $filter = null)
93
    {
94
        if ($filter === null) {
95
            $filter = new CodeCoverageFilter;
96
        }
97
98
        $this->codeCoverageFilter = $filter;
99
        $this->loader             = $loader;
100
        $this->runtime            = new Runtime;
101
    }
102
103
    /**
104
     * @param Test|ReflectionClass $test
105
     * @param array                $arguments
106
     *
107
     * @return TestResult
108
     *
109
     * @throws Exception
110
     */
111
    public static function run($test, array $arguments = [])
112
    {
113
        if ($test instanceof ReflectionClass) {
114
            $test = new TestSuite($test);
115
        }
116
117
        if ($test instanceof Test) {
118
            $aTestRunner = new self;
119
120
            return $aTestRunner->doRun(
121
                $test,
122
                $arguments
123
            );
124
        }
125
126
        throw new Exception('No test case or test suite found.');
127
    }
128
129
    /**
130
     * @return TestResult
131
     */
132
    protected function createTestResult()
133
    {
134
        return new TestResult;
135
    }
136
137
    /**
138
     * @param TestSuite $suite
139
     * @param array     $arguments
140
     */
141
    private function processSuiteFilters(TestSuite $suite, array $arguments)
142
    {
143
        if (!$arguments['filter'] &&
144
            empty($arguments['groups']) &&
145
            empty($arguments['excludeGroups'])) {
146
            return;
147
        }
148
149
        $filterFactory = new Factory;
150
151
        if (!empty($arguments['excludeGroups'])) {
152
            $filterFactory->addFilter(
153
                new ReflectionClass(ExcludeGroupFilterIterator::class),
154
                $arguments['excludeGroups']
155
            );
156
        }
157
158
        if (!empty($arguments['groups'])) {
159
            $filterFactory->addFilter(
160
                new ReflectionClass(IncludeGroupFilterIterator::class),
161
                $arguments['groups']
162
            );
163
        }
164
165
        if ($arguments['filter']) {
166
            $filterFactory->addFilter(
167
                new ReflectionClass(NameFilterIterator::class),
168
                $arguments['filter']
169
            );
170
        }
171
172
        $suite->injectFilter($filterFactory);
173
    }
174
175
    /**
176
     * @param Test  $suite
177
     * @param array $arguments
178
     * @param bool  $exit
179
     *
180
     * @return TestResult
181
     */
182
    public function doRun(Test $suite, array $arguments = [], $exit = true)
183
    {
184
        if (isset($arguments['configuration'])) {
185
            $GLOBALS['__PHPUNIT_CONFIGURATION_FILE'] = $arguments['configuration'];
186
        }
187
188
        $this->handleConfiguration($arguments);
189
190
        $this->processSuiteFilters($suite, $arguments);
191
192
        if (isset($arguments['bootstrap'])) {
193
            $GLOBALS['__PHPUNIT_BOOTSTRAP'] = $arguments['bootstrap'];
194
        }
195
196
        if ($arguments['backupGlobals'] === true) {
197
            $suite->setBackupGlobals(true);
198
        }
199
200
        if ($arguments['backupStaticAttributes'] === true) {
201
            $suite->setBackupStaticAttributes(true);
202
        }
203
204
        if ($arguments['beStrictAboutChangesToGlobalState'] === true) {
205
            $suite->setbeStrictAboutChangesToGlobalState(true);
206
        }
207
208
        if (\is_int($arguments['repeat']) && $arguments['repeat'] > 0) {
209
            $_suite = new TestSuite;
210
211
            foreach (\range(1, $arguments['repeat']) as $step) {
212
                $_suite->addTest($suite);
213
            }
214
215
            $suite = $_suite;
216
            unset($_suite);
217
        }
218
219
        $result = $this->createTestResult();
220
221
        if (!$arguments['convertErrorsToExceptions']) {
222
            $result->convertErrorsToExceptions(false);
223
        }
224
225
        if (!$arguments['convertNoticesToExceptions']) {
226
            Notice::$enabled = false;
227
        }
228
229
        if (!$arguments['convertWarningsToExceptions']) {
230
            Warning::$enabled = false;
231
        }
232
233
        if ($arguments['stopOnError']) {
234
            $result->stopOnError(true);
235
        }
236
237
        if ($arguments['stopOnFailure']) {
238
            $result->stopOnFailure(true);
239
        }
240
241
        if ($arguments['stopOnWarning']) {
242
            $result->stopOnWarning(true);
243
        }
244
245
        if ($arguments['stopOnIncomplete']) {
246
            $result->stopOnIncomplete(true);
247
        }
248
249
        if ($arguments['stopOnRisky']) {
250
            $result->stopOnRisky(true);
251
        }
252
253
        if ($arguments['stopOnSkipped']) {
254
            $result->stopOnSkipped(true);
255
        }
256
257
        if ($arguments['registerMockObjectsFromTestArgumentsRecursively']) {
258
            $result->setRegisterMockObjectsFromTestArgumentsRecursively(true);
259
        }
260
261
        if ($this->printer === null) {
262
            if (isset($arguments['printer']) &&
263
                $arguments['printer'] instanceof Printer) {
264
                $this->printer = $arguments['printer'];
265
            } else {
266
                $printerClass = ResultPrinter::class;
267
268
                if (isset($arguments['printer']) && \is_string($arguments['printer']) && \class_exists($arguments['printer'], false)) {
269
                    $class = new ReflectionClass($arguments['printer']);
270
271
                    if ($class->isSubclassOf(ResultPrinter::class)) {
272
                        $printerClass = $arguments['printer'];
273
                    }
274
                }
275
276
                $this->printer = new $printerClass(
277
                    isset($arguments['stderr']) ? 'php://stderr' : null,
278
                    $arguments['verbose'],
279
                    $arguments['colors'],
280
                    $arguments['debug'],
281
                    $arguments['columns'],
282
                    $arguments['reverseList']
283
                );
284
            }
285
        }
286
287
        $this->printer->write(
288
            Version::getVersionString() . "\n"
289
        );
290
291
        self::$versionStringPrinted = true;
292
293
        if ($arguments['verbose']) {
294
            $runtime = $this->runtime->getNameWithVersion();
295
296
            if ($this->runtime->hasXdebug()) {
297
                $runtime .= \sprintf(
298
                    ' with Xdebug %s',
299
                    \phpversion('xdebug')
300
                );
301
            }
302
303
            $this->writeMessage('Runtime', $runtime);
304
305
            if (isset($arguments['configuration'])) {
306
                $this->writeMessage(
307
                    'Configuration',
308
                    $arguments['configuration']->getFilename()
309
                );
310
            }
311
312
            foreach ($arguments['loadedExtensions'] as $extension) {
313
                $this->writeMessage(
314
                    'Extension',
315
                    $extension
316
                );
317
            }
318
319
            foreach ($arguments['notLoadedExtensions'] as $extension) {
320
                $this->writeMessage(
321
                    'Extension',
322
                    $extension
323
                );
324
            }
325
        }
326
327
        foreach ($arguments['listeners'] as $listener) {
328
            $result->addListener($listener);
329
        }
330
331
        $result->addListener($this->printer);
332
333
        if (isset($arguments['testdoxHTMLFile'])) {
334
            $result->addListener(
335
                new HtmlResultPrinter(
336
                    $arguments['testdoxHTMLFile'],
337
                    $arguments['testdoxGroups'],
338
                    $arguments['testdoxExcludeGroups']
339
                )
340
            );
341
        }
342
343
        if (isset($arguments['testdoxTextFile'])) {
344
            $result->addListener(
345
                new TextResultPrinter(
346
                    $arguments['testdoxTextFile'],
347
                    $arguments['testdoxGroups'],
348
                    $arguments['testdoxExcludeGroups']
349
                )
350
            );
351
        }
352
353
        if (isset($arguments['testdoxXMLFile'])) {
354
            $result->addListener(
355
                new XmlResultPrinter(
356
                    $arguments['testdoxXMLFile']
357
                )
358
            );
359
        }
360
361
        $codeCoverageReports = 0;
362
363
        if (isset($arguments['coverageClover'])) {
364
            $codeCoverageReports++;
365
        }
366
367
        if (isset($arguments['coverageCrap4J'])) {
368
            $codeCoverageReports++;
369
        }
370
371
        if (isset($arguments['coverageHtml'])) {
372
            $codeCoverageReports++;
373
        }
374
375
        if (isset($arguments['coveragePHP'])) {
376
            $codeCoverageReports++;
377
        }
378
379
        if (isset($arguments['coverageText'])) {
380
            $codeCoverageReports++;
381
        }
382
383
        if (isset($arguments['coverageXml'])) {
384
            $codeCoverageReports++;
385
        }
386
387
        if (isset($arguments['noCoverage'])) {
388
            $codeCoverageReports = 0;
389
        }
390
391
        if ($codeCoverageReports > 0 && !$this->runtime->canCollectCodeCoverage()) {
392
            $this->writeMessage('Error', 'No code coverage driver is available');
393
394
            $codeCoverageReports = 0;
395
        }
396
397
        if ($codeCoverageReports > 0) {
398
            $codeCoverage = new CodeCoverage(
399
                null,
400
                $this->codeCoverageFilter
401
            );
402
403
            $codeCoverage->setUnintentionallyCoveredSubclassesWhitelist(
404
                [SebastianBergmann\Comparator\Comparator::class]
405
            );
406
407
            $codeCoverage->setCheckForUnintentionallyCoveredCode(
408
                $arguments['strictCoverage']
409
            );
410
411
            $codeCoverage->setCheckForMissingCoversAnnotation(
412
                $arguments['strictCoverage']
413
            );
414
415
            if (isset($arguments['forceCoversAnnotation'])) {
416
                $codeCoverage->setForceCoversAnnotation(
417
                    $arguments['forceCoversAnnotation']
418
                );
419
            }
420
421
            if (isset($arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'])) {
422
                $codeCoverage->setIgnoreDeprecatedCode(
423
                    $arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage']
424
                );
425
            }
426
427
            if (isset($arguments['disableCodeCoverageIgnore'])) {
428
                $codeCoverage->setDisableIgnoredLines(true);
429
            }
430
431
            if (isset($arguments['whitelist'])) {
432
                $this->codeCoverageFilter->addDirectoryToWhitelist($arguments['whitelist']);
433
            }
434
435
            if (isset($arguments['configuration'])) {
436
                $filterConfiguration = $arguments['configuration']->getFilterConfiguration();
437
438
                if (empty($filterConfiguration['whitelist'])) {
439
                    $this->writeMessage('Error', 'No whitelist is configured, no code coverage will be generated.');
440
441
                    $codeCoverageReports = 0;
442
443
                    unset($codeCoverage);
444
                } else {
445
                    $codeCoverage->setAddUncoveredFilesFromWhitelist(
446
                        $filterConfiguration['whitelist']['addUncoveredFilesFromWhitelist']
447
                    );
448
449
                    $codeCoverage->setProcessUncoveredFilesFromWhitelist(
450
                        $filterConfiguration['whitelist']['processUncoveredFilesFromWhitelist']
451
                    );
452
453
                    foreach ($filterConfiguration['whitelist']['include']['directory'] as $dir) {
454
                        $this->codeCoverageFilter->addDirectoryToWhitelist(
455
                            $dir['path'],
456
                            $dir['suffix'],
457
                            $dir['prefix']
458
                        );
459
                    }
460
461
                    foreach ($filterConfiguration['whitelist']['include']['file'] as $file) {
462
                        $this->codeCoverageFilter->addFileToWhitelist($file);
463
                    }
464
465
                    foreach ($filterConfiguration['whitelist']['exclude']['directory'] as $dir) {
466
                        $this->codeCoverageFilter->removeDirectoryFromWhitelist(
467
                            $dir['path'],
468
                            $dir['suffix'],
469
                            $dir['prefix']
470
                        );
471
                    }
472
473
                    foreach ($filterConfiguration['whitelist']['exclude']['file'] as $file) {
474
                        $this->codeCoverageFilter->removeFileFromWhitelist($file);
475
                    }
476
                }
477
            }
478
479
            if (isset($codeCoverage) && !$this->codeCoverageFilter->hasWhitelist()) {
480
                $this->writeMessage('Error', 'Incorrect whitelist config, no code coverage will be generated.');
481
482
                $codeCoverageReports = 0;
483
484
                unset($codeCoverage);
485
            }
486
        }
487
488
        $this->printer->write("\n");
489
490
        if (isset($codeCoverage)) {
491
            $result->setCodeCoverage($codeCoverage);
492
493
            if ($codeCoverageReports > 1 && isset($arguments['cacheTokens'])) {
494
                $codeCoverage->setCacheTokens($arguments['cacheTokens']);
495
            }
496
        }
497
498
        if (isset($arguments['teamcityLogfile'])) {
499
            $result->addListener(
500
                new TeamCity($arguments['teamcityLogfile'])
501
            );
502
        }
503
504
        if (isset($arguments['junitLogfile'])) {
505
            $result->addListener(
506
                new JUnit(
507
                    $arguments['junitLogfile'],
508
                    $arguments['reportUselessTests']
509
                )
510
            );
511
        }
512
513
        $result->beStrictAboutTestsThatDoNotTestAnything($arguments['reportUselessTests']);
514
        $result->beStrictAboutOutputDuringTests($arguments['disallowTestOutput']);
515
        $result->beStrictAboutTodoAnnotatedTests($arguments['disallowTodoAnnotatedTests']);
516
        $result->beStrictAboutResourceUsageDuringSmallTests($arguments['beStrictAboutResourceUsageDuringSmallTests']);
517
        $result->enforceTimeLimit($arguments['enforceTimeLimit']);
518
        $result->setTimeoutForSmallTests($arguments['timeoutForSmallTests']);
519
        $result->setTimeoutForMediumTests($arguments['timeoutForMediumTests']);
520
        $result->setTimeoutForLargeTests($arguments['timeoutForLargeTests']);
521
522
        if ($suite instanceof TestSuite) {
523
            $suite->setRunTestInSeparateProcess($arguments['processIsolation']);
524
        }
525
526
        $suite->run($result);
527
528
        unset($suite);
529
        $result->flushListeners();
530
531
        if ($this->printer instanceof ResultPrinter) {
532
            $this->printer->printResult($result);
533
        }
534
535
        if (isset($codeCoverage)) {
536
            if (isset($arguments['coverageClover'])) {
537
                $this->printer->write(
538
                    "\nGenerating code coverage report in Clover XML format ..."
539
                );
540
541
                try {
542
                    $writer = new CloverReport;
543
                    $writer->process($codeCoverage, $arguments['coverageClover']);
544
545
                    $this->printer->write(" done\n");
546
                    unset($writer);
547
                } catch (CodeCoverageException $e) {
548
                    $this->printer->write(
549
                        " failed\n" . $e->getMessage() . "\n"
550
                    );
551
                }
552
            }
553
554
            if (isset($arguments['coverageCrap4J'])) {
555
                $this->printer->write(
556
                    "\nGenerating Crap4J report XML file ..."
557
                );
558
559
                try {
560
                    $writer = new Crap4jReport($arguments['crap4jThreshold']);
561
                    $writer->process($codeCoverage, $arguments['coverageCrap4J']);
562
563
                    $this->printer->write(" done\n");
564
                    unset($writer);
565
                } catch (CodeCoverageException $e) {
566
                    $this->printer->write(
567
                        " failed\n" . $e->getMessage() . "\n"
568
                    );
569
                }
570
            }
571
572
            if (isset($arguments['coverageHtml'])) {
573
                $this->printer->write(
574
                    "\nGenerating code coverage report in HTML format ..."
575
                );
576
577
                try {
578
                    $writer = new HtmlReport(
579
                        $arguments['reportLowUpperBound'],
580
                        $arguments['reportHighLowerBound'],
581
                        \sprintf(
582
                            ' and <a href="https://phpunit.de/">PHPUnit %s</a>',
583
                            Version::id()
584
                        )
585
                    );
586
587
                    $writer->process($codeCoverage, $arguments['coverageHtml']);
588
589
                    $this->printer->write(" done\n");
590
                    unset($writer);
591
                } catch (CodeCoverageException $e) {
592
                    $this->printer->write(
593
                        " failed\n" . $e->getMessage() . "\n"
594
                    );
595
                }
596
            }
597
598
            if (isset($arguments['coveragePHP'])) {
599
                $this->printer->write(
600
                    "\nGenerating code coverage report in PHP format ..."
601
                );
602
603
                try {
604
                    $writer = new PhpReport;
605
                    $writer->process($codeCoverage, $arguments['coveragePHP']);
606
607
                    $this->printer->write(" done\n");
608
                    unset($writer);
609
                } catch (CodeCoverageException $e) {
610
                    $this->printer->write(
611
                        " failed\n" . $e->getMessage() . "\n"
612
                    );
613
                }
614
            }
615
616
            if (isset($arguments['coverageText'])) {
617
                if ($arguments['coverageText'] == 'php://stdout') {
618
                    $outputStream = $this->printer;
619
                    $colors       = $arguments['colors'] && $arguments['colors'] != ResultPrinter::COLOR_NEVER;
620
                } else {
621
                    $outputStream = new Printer($arguments['coverageText']);
622
                    $colors       = false;
623
                }
624
625
                $processor = new TextReport(
626
                    $arguments['reportLowUpperBound'],
627
                    $arguments['reportHighLowerBound'],
628
                    $arguments['coverageTextShowUncoveredFiles'],
629
                    $arguments['coverageTextShowOnlySummary']
630
                );
631
632
                $outputStream->write(
633
                    $processor->process($codeCoverage, $colors)
634
                );
635
            }
636
637
            if (isset($arguments['coverageXml'])) {
638
                $this->printer->write(
639
                    "\nGenerating code coverage report in PHPUnit XML format ..."
640
                );
641
642
                try {
643
                    $writer = new XmlReport(Version::id());
644
                    $writer->process($codeCoverage, $arguments['coverageXml']);
645
646
                    $this->printer->write(" done\n");
647
                    unset($writer);
648
                } catch (CodeCoverageException $e) {
649
                    $this->printer->write(
650
                        " failed\n" . $e->getMessage() . "\n"
651
                    );
652
                }
653
            }
654
        }
655
656
        if ($exit) {
657
            if ($result->wasSuccessful()) {
658
                if ($arguments['failOnRisky'] && !$result->allHarmless()) {
659
                    exit(self::FAILURE_EXIT);
660
                }
661
662
                if ($arguments['failOnWarning'] && $result->warningCount() > 0) {
663
                    exit(self::FAILURE_EXIT);
664
                }
665
666
                exit(self::SUCCESS_EXIT);
667
            }
668
669
            if ($result->errorCount() > 0) {
670
                exit(self::EXCEPTION_EXIT);
671
            }
672
673
            if ($result->failureCount() > 0) {
674
                exit(self::FAILURE_EXIT);
675
            }
676
        }
677
678
        return $result;
679
    }
680
681
    /**
682
     * @param ResultPrinter $resultPrinter
683
     */
684
    public function setPrinter(ResultPrinter $resultPrinter)
685
    {
686
        $this->printer = $resultPrinter;
687
    }
688
689
    /**
690
     * Override to define how to handle a failed loading of
691
     * a test suite.
692
     *
693
     * @param string $message
694
     */
695
    protected function runFailed($message)
696
    {
697
        $this->write($message . PHP_EOL);
698
        exit(self::FAILURE_EXIT);
699
    }
700
701
    /**
702
     * @param string $buffer
703
     */
704
    protected function write($buffer)
705
    {
706
        if (PHP_SAPI != 'cli' && PHP_SAPI != 'phpdbg') {
707
            $buffer = \htmlspecialchars($buffer);
708
        }
709
710
        if ($this->printer !== null) {
711
            $this->printer->write($buffer);
712
        } else {
713
            print $buffer;
714
        }
715
    }
716
717
    /**
718
     * Returns the loader to be used.
719
     *
720
     * @return TestSuiteLoader
721
     */
722
    public function getLoader()
723
    {
724
        if ($this->loader === null) {
725
            $this->loader = new StandardTestSuiteLoader;
726
        }
727
728
        return $this->loader;
729
    }
730
731
    /**
732
     * @param array $arguments
733
     */
734
    protected function handleConfiguration(array &$arguments)
735
    {
736
        if (isset($arguments['configuration']) &&
737
            !$arguments['configuration'] instanceof Configuration) {
738
            $arguments['configuration'] = Configuration::getInstance(
739
                $arguments['configuration']
740
            );
741
        }
742
743
        $arguments['debug']     = $arguments['debug'] ?? false;
744
        $arguments['filter']    = $arguments['filter'] ?? false;
745
        $arguments['listeners'] = $arguments['listeners'] ?? [];
746
747
        if (isset($arguments['configuration'])) {
748
            $arguments['configuration']->handlePHPConfiguration();
749
750
            $phpunitConfiguration = $arguments['configuration']->getPHPUnitConfiguration();
751
752
            if (isset($phpunitConfiguration['backupGlobals']) && !isset($arguments['backupGlobals'])) {
753
                $arguments['backupGlobals'] = $phpunitConfiguration['backupGlobals'];
754
            }
755
756
            if (isset($phpunitConfiguration['backupStaticAttributes']) && !isset($arguments['backupStaticAttributes'])) {
757
                $arguments['backupStaticAttributes'] = $phpunitConfiguration['backupStaticAttributes'];
758
            }
759
760
            if (isset($phpunitConfiguration['beStrictAboutChangesToGlobalState']) && !isset($arguments['beStrictAboutChangesToGlobalState'])) {
761
                $arguments['beStrictAboutChangesToGlobalState'] = $phpunitConfiguration['beStrictAboutChangesToGlobalState'];
762
            }
763
764
            if (isset($phpunitConfiguration['bootstrap']) && !isset($arguments['bootstrap'])) {
765
                $arguments['bootstrap'] = $phpunitConfiguration['bootstrap'];
766
            }
767
768
            if (isset($phpunitConfiguration['cacheTokens']) && !isset($arguments['cacheTokens'])) {
769
                $arguments['cacheTokens'] = $phpunitConfiguration['cacheTokens'];
770
            }
771
772
            if (isset($phpunitConfiguration['colors']) && !isset($arguments['colors'])) {
773
                $arguments['colors'] = $phpunitConfiguration['colors'];
774
            }
775
776
            if (isset($phpunitConfiguration['convertErrorsToExceptions']) && !isset($arguments['convertErrorsToExceptions'])) {
777
                $arguments['convertErrorsToExceptions'] = $phpunitConfiguration['convertErrorsToExceptions'];
778
            }
779
780
            if (isset($phpunitConfiguration['convertNoticesToExceptions']) && !isset($arguments['convertNoticesToExceptions'])) {
781
                $arguments['convertNoticesToExceptions'] = $phpunitConfiguration['convertNoticesToExceptions'];
782
            }
783
784
            if (isset($phpunitConfiguration['convertWarningsToExceptions']) && !isset($arguments['convertWarningsToExceptions'])) {
785
                $arguments['convertWarningsToExceptions'] = $phpunitConfiguration['convertWarningsToExceptions'];
786
            }
787
788
            if (isset($phpunitConfiguration['processIsolation']) && !isset($arguments['processIsolation'])) {
789
                $arguments['processIsolation'] = $phpunitConfiguration['processIsolation'];
790
            }
791
792
            if (isset($phpunitConfiguration['stopOnError']) && !isset($arguments['stopOnError'])) {
793
                $arguments['stopOnError'] = $phpunitConfiguration['stopOnError'];
794
            }
795
796
            if (isset($phpunitConfiguration['stopOnFailure']) && !isset($arguments['stopOnFailure'])) {
797
                $arguments['stopOnFailure'] = $phpunitConfiguration['stopOnFailure'];
798
            }
799
800
            if (isset($phpunitConfiguration['stopOnWarning']) && !isset($arguments['stopOnWarning'])) {
801
                $arguments['stopOnWarning'] = $phpunitConfiguration['stopOnWarning'];
802
            }
803
804
            if (isset($phpunitConfiguration['stopOnIncomplete']) && !isset($arguments['stopOnIncomplete'])) {
805
                $arguments['stopOnIncomplete'] = $phpunitConfiguration['stopOnIncomplete'];
806
            }
807
808
            if (isset($phpunitConfiguration['stopOnRisky']) && !isset($arguments['stopOnRisky'])) {
809
                $arguments['stopOnRisky'] = $phpunitConfiguration['stopOnRisky'];
810
            }
811
812
            if (isset($phpunitConfiguration['stopOnSkipped']) && !isset($arguments['stopOnSkipped'])) {
813
                $arguments['stopOnSkipped'] = $phpunitConfiguration['stopOnSkipped'];
814
            }
815
816
            if (isset($phpunitConfiguration['failOnWarning']) && !isset($arguments['failOnWarning'])) {
817
                $arguments['failOnWarning'] = $phpunitConfiguration['failOnWarning'];
818
            }
819
820
            if (isset($phpunitConfiguration['failOnRisky']) && !isset($arguments['failOnRisky'])) {
821
                $arguments['failOnRisky'] = $phpunitConfiguration['failOnRisky'];
822
            }
823
824
            if (isset($phpunitConfiguration['timeoutForSmallTests']) && !isset($arguments['timeoutForSmallTests'])) {
825
                $arguments['timeoutForSmallTests'] = $phpunitConfiguration['timeoutForSmallTests'];
826
            }
827
828
            if (isset($phpunitConfiguration['timeoutForMediumTests']) && !isset($arguments['timeoutForMediumTests'])) {
829
                $arguments['timeoutForMediumTests'] = $phpunitConfiguration['timeoutForMediumTests'];
830
            }
831
832
            if (isset($phpunitConfiguration['timeoutForLargeTests']) && !isset($arguments['timeoutForLargeTests'])) {
833
                $arguments['timeoutForLargeTests'] = $phpunitConfiguration['timeoutForLargeTests'];
834
            }
835
836
            if (isset($phpunitConfiguration['reportUselessTests']) && !isset($arguments['reportUselessTests'])) {
837
                $arguments['reportUselessTests'] = $phpunitConfiguration['reportUselessTests'];
838
            }
839
840
            if (isset($phpunitConfiguration['strictCoverage']) && !isset($arguments['strictCoverage'])) {
841
                $arguments['strictCoverage'] = $phpunitConfiguration['strictCoverage'];
842
            }
843
844
            if (isset($phpunitConfiguration['ignoreDeprecatedCodeUnitsFromCodeCoverage']) && !isset($arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'])) {
845
                $arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'] = $phpunitConfiguration['ignoreDeprecatedCodeUnitsFromCodeCoverage'];
846
            }
847
848
            if (isset($phpunitConfiguration['disallowTestOutput']) && !isset($arguments['disallowTestOutput'])) {
849
                $arguments['disallowTestOutput'] = $phpunitConfiguration['disallowTestOutput'];
850
            }
851
852
            if (isset($phpunitConfiguration['enforceTimeLimit']) && !isset($arguments['enforceTimeLimit'])) {
853
                $arguments['enforceTimeLimit'] = $phpunitConfiguration['enforceTimeLimit'];
854
            }
855
856
            if (isset($phpunitConfiguration['disallowTodoAnnotatedTests']) && !isset($arguments['disallowTodoAnnotatedTests'])) {
857
                $arguments['disallowTodoAnnotatedTests'] = $phpunitConfiguration['disallowTodoAnnotatedTests'];
858
            }
859
860
            if (isset($phpunitConfiguration['beStrictAboutResourceUsageDuringSmallTests']) && !isset($arguments['beStrictAboutResourceUsageDuringSmallTests'])) {
861
                $arguments['beStrictAboutResourceUsageDuringSmallTests'] = $phpunitConfiguration['beStrictAboutResourceUsageDuringSmallTests'];
862
            }
863
864
            if (isset($phpunitConfiguration['verbose']) && !isset($arguments['verbose'])) {
865
                $arguments['verbose'] = $phpunitConfiguration['verbose'];
866
            }
867
868
            if (isset($phpunitConfiguration['reverseDefectList']) && !isset($arguments['reverseList'])) {
869
                $arguments['reverseList'] = $phpunitConfiguration['reverseDefectList'];
870
            }
871
872
            if (isset($phpunitConfiguration['forceCoversAnnotation']) && !isset($arguments['forceCoversAnnotation'])) {
873
                $arguments['forceCoversAnnotation'] = $phpunitConfiguration['forceCoversAnnotation'];
874
            }
875
876
            if (isset($phpunitConfiguration['disableCodeCoverageIgnore']) && !isset($arguments['disableCodeCoverageIgnore'])) {
877
                $arguments['disableCodeCoverageIgnore'] = $phpunitConfiguration['disableCodeCoverageIgnore'];
878
            }
879
880
            if (isset($phpunitConfiguration['registerMockObjectsFromTestArgumentsRecursively']) && !isset($arguments['registerMockObjectsFromTestArgumentsRecursively'])) {
881
                $arguments['registerMockObjectsFromTestArgumentsRecursively'] = $phpunitConfiguration['registerMockObjectsFromTestArgumentsRecursively'];
882
            }
883
884
            $groupCliArgs = [];
885
886
            if (!empty($arguments['groups'])) {
887
                $groupCliArgs = $arguments['groups'];
888
            }
889
890
            $groupConfiguration = $arguments['configuration']->getGroupConfiguration();
891
892
            if (!empty($groupConfiguration['include']) && !isset($arguments['groups'])) {
893
                $arguments['groups'] = $groupConfiguration['include'];
894
            }
895
896
            if (!empty($groupConfiguration['exclude']) && !isset($arguments['excludeGroups'])) {
897
                $arguments['excludeGroups'] = \array_diff($groupConfiguration['exclude'], $groupCliArgs);
898
            }
899
900
            foreach ($arguments['configuration']->getListenerConfiguration() as $listener) {
901
                if (!\class_exists($listener['class'], false) &&
902
                    $listener['file'] !== '') {
903
                    require_once $listener['file'];
904
                }
905
906
                if (!\class_exists($listener['class'])) {
907
                    throw new Exception(
908
                        \sprintf(
909
                            'Class "%s" does not exist',
910
                            $listener['class']
911
                        )
912
                    );
913
                }
914
915
                $listenerClass = new ReflectionClass($listener['class']);
916
917
                if (!$listenerClass->implementsInterface(TestListener::class)) {
918
                    throw new Exception(
919
                        \sprintf(
920
                            'Class "%s" does not implement the PHPUnit\Framework\TestListener interface',
921
                            $listener['class']
922
                        )
923
                    );
924
                }
925
926
                if (\count($listener['arguments']) == 0) {
927
                    $listener = new $listener['class'];
928
                } else {
929
                    $listener = $listenerClass->newInstanceArgs(
930
                        $listener['arguments']
931
                    );
932
                }
933
934
                $arguments['listeners'][] = $listener;
935
            }
936
937
            $loggingConfiguration = $arguments['configuration']->getLoggingConfiguration();
938
939
            if (isset($loggingConfiguration['coverage-clover']) && !isset($arguments['coverageClover'])) {
940
                $arguments['coverageClover'] = $loggingConfiguration['coverage-clover'];
941
            }
942
943
            if (isset($loggingConfiguration['coverage-crap4j']) && !isset($arguments['coverageCrap4J'])) {
944
                $arguments['coverageCrap4J'] = $loggingConfiguration['coverage-crap4j'];
945
946
                if (isset($loggingConfiguration['crap4jThreshold']) && !isset($arguments['crap4jThreshold'])) {
947
                    $arguments['crap4jThreshold'] = $loggingConfiguration['crap4jThreshold'];
948
                }
949
            }
950
951
            if (isset($loggingConfiguration['coverage-html']) && !isset($arguments['coverageHtml'])) {
952
                if (isset($loggingConfiguration['lowUpperBound']) && !isset($arguments['reportLowUpperBound'])) {
953
                    $arguments['reportLowUpperBound'] = $loggingConfiguration['lowUpperBound'];
954
                }
955
956
                if (isset($loggingConfiguration['highLowerBound']) && !isset($arguments['reportHighLowerBound'])) {
957
                    $arguments['reportHighLowerBound'] = $loggingConfiguration['highLowerBound'];
958
                }
959
960
                $arguments['coverageHtml'] = $loggingConfiguration['coverage-html'];
961
            }
962
963
            if (isset($loggingConfiguration['coverage-php']) && !isset($arguments['coveragePHP'])) {
964
                $arguments['coveragePHP'] = $loggingConfiguration['coverage-php'];
965
            }
966
967
            if (isset($loggingConfiguration['coverage-text']) && !isset($arguments['coverageText'])) {
968
                $arguments['coverageText'] = $loggingConfiguration['coverage-text'];
969
970
                if (isset($loggingConfiguration['coverageTextShowUncoveredFiles'])) {
971
                    $arguments['coverageTextShowUncoveredFiles'] = $loggingConfiguration['coverageTextShowUncoveredFiles'];
972
                } else {
973
                    $arguments['coverageTextShowUncoveredFiles'] = false;
974
                }
975
976
                if (isset($loggingConfiguration['coverageTextShowOnlySummary'])) {
977
                    $arguments['coverageTextShowOnlySummary'] = $loggingConfiguration['coverageTextShowOnlySummary'];
978
                } else {
979
                    $arguments['coverageTextShowOnlySummary'] = false;
980
                }
981
            }
982
983
            if (isset($loggingConfiguration['coverage-xml']) && !isset($arguments['coverageXml'])) {
984
                $arguments['coverageXml'] = $loggingConfiguration['coverage-xml'];
985
            }
986
987
            if (isset($loggingConfiguration['plain'])) {
988
                $arguments['listeners'][] = new ResultPrinter(
989
                    $loggingConfiguration['plain'],
990
                    true
991
                );
992
            }
993
994
            if (isset($loggingConfiguration['teamcity']) && !isset($arguments['teamcityLogfile'])) {
995
                $arguments['teamcityLogfile'] = $loggingConfiguration['teamcity'];
996
            }
997
998
            if (isset($loggingConfiguration['junit']) && !isset($arguments['junitLogfile'])) {
999
                $arguments['junitLogfile'] = $loggingConfiguration['junit'];
1000
            }
1001
1002
            if (isset($loggingConfiguration['testdox-html']) && !isset($arguments['testdoxHTMLFile'])) {
1003
                $arguments['testdoxHTMLFile'] = $loggingConfiguration['testdox-html'];
1004
            }
1005
1006
            if (isset($loggingConfiguration['testdox-text']) && !isset($arguments['testdoxTextFile'])) {
1007
                $arguments['testdoxTextFile'] = $loggingConfiguration['testdox-text'];
1008
            }
1009
1010
            if (isset($loggingConfiguration['testdox-xml']) && !isset($arguments['testdoxXMLFile'])) {
1011
                $arguments['testdoxXMLFile'] = $loggingConfiguration['testdox-xml'];
1012
            }
1013
1014
            $testdoxGroupConfiguration = $arguments['configuration']->getTestdoxGroupConfiguration();
1015
1016
            if (isset($testdoxGroupConfiguration['include']) &&
1017
                !isset($arguments['testdoxGroups'])) {
1018
                $arguments['testdoxGroups'] = $testdoxGroupConfiguration['include'];
1019
            }
1020
1021
            if (isset($testdoxGroupConfiguration['exclude']) &&
1022
                !isset($arguments['testdoxExcludeGroups'])) {
1023
                $arguments['testdoxExcludeGroups'] = $testdoxGroupConfiguration['exclude'];
1024
            }
1025
        }
1026
1027
        $arguments['addUncoveredFilesFromWhitelist']                  = $arguments['addUncoveredFilesFromWhitelist'] ?? true;
1028
        $arguments['backupGlobals']                                   = $arguments['backupGlobals'] ?? null;
1029
        $arguments['backupStaticAttributes']                          = $arguments['backupStaticAttributes'] ?? null;
1030
        $arguments['beStrictAboutChangesToGlobalState']               = $arguments['beStrictAboutChangesToGlobalState'] ?? null;
1031
        $arguments['beStrictAboutResourceUsageDuringSmallTests']      = $arguments['beStrictAboutResourceUsageDuringSmallTests'] ?? false;
1032
        $arguments['cacheTokens']                                     = $arguments['cacheTokens'] ?? false;
1033
        $arguments['colors']                                          = $arguments['colors'] ?? ResultPrinter::COLOR_DEFAULT;
1034
        $arguments['columns']                                         = $arguments['columns'] ?? 80;
1035
        $arguments['convertErrorsToExceptions']                       = $arguments['convertErrorsToExceptions'] ?? true;
1036
        $arguments['convertNoticesToExceptions']                      = $arguments['convertNoticesToExceptions'] ?? true;
1037
        $arguments['convertWarningsToExceptions']                     = $arguments['convertWarningsToExceptions'] ?? true;
1038
        $arguments['crap4jThreshold']                                 = $arguments['crap4jThreshold'] ?? 30;
1039
        $arguments['disallowTestOutput']                              = $arguments['disallowTestOutput'] ?? false;
1040
        $arguments['disallowTodoAnnotatedTests']                      = $arguments['disallowTodoAnnotatedTests'] ?? false;
1041
        $arguments['enforceTimeLimit']                                = $arguments['enforceTimeLimit'] ?? false;
1042
        $arguments['excludeGroups']                                   = $arguments['excludeGroups'] ?? [];
1043
        $arguments['failOnRisky']                                     = $arguments['failOnRisky'] ?? false;
1044
        $arguments['failOnWarning']                                   = $arguments['failOnWarning'] ?? false;
1045
        $arguments['groups']                                          = $arguments['groups'] ?? [];
1046
        $arguments['processIsolation']                                = $arguments['processIsolation'] ?? false;
1047
        $arguments['processUncoveredFilesFromWhitelist']              = $arguments['processUncoveredFilesFromWhitelist'] ?? false;
1048
        $arguments['registerMockObjectsFromTestArgumentsRecursively'] = $arguments['registerMockObjectsFromTestArgumentsRecursively'] ?? false;
1049
        $arguments['repeat']                                          = $arguments['repeat'] ?? false;
1050
        $arguments['reportHighLowerBound']                            = $arguments['reportHighLowerBound'] ?? 90;
1051
        $arguments['reportLowUpperBound']                             = $arguments['reportLowUpperBound'] ?? 50;
1052
        $arguments['reportUselessTests']                              = $arguments['reportUselessTests'] ?? true;
1053
        $arguments['reverseList']                                     = $arguments['reverseList'] ?? false;
1054
        $arguments['stopOnError']                                     = $arguments['stopOnError'] ?? false;
1055
        $arguments['stopOnFailure']                                   = $arguments['stopOnFailure'] ?? false;
1056
        $arguments['stopOnIncomplete']                                = $arguments['stopOnIncomplete'] ?? false;
1057
        $arguments['stopOnRisky']                                     = $arguments['stopOnRisky'] ?? false;
1058
        $arguments['stopOnSkipped']                                   = $arguments['stopOnSkipped'] ?? false;
1059
        $arguments['stopOnWarning']                                   = $arguments['stopOnWarning'] ?? false;
1060
        $arguments['strictCoverage']                                  = $arguments['strictCoverage'] ?? false;
1061
        $arguments['testdoxExcludeGroups']                            = $arguments['testdoxExcludeGroups'] ?? [];
1062
        $arguments['testdoxGroups']                                   = $arguments['testdoxGroups'] ?? [];
1063
        $arguments['timeoutForLargeTests']                            = $arguments['timeoutForLargeTests'] ?? 60;
1064
        $arguments['timeoutForMediumTests']                           = $arguments['timeoutForMediumTests'] ?? 10;
1065
        $arguments['timeoutForSmallTests']                            = $arguments['timeoutForSmallTests'] ?? 1;
1066
        $arguments['verbose']                                         = $arguments['verbose'] ?? false;
1067
    }
1068
1069
    /**
1070
     * @param string $type
1071
     * @param string $message
1072
     */
1073
    private function writeMessage($type, $message)
1074
    {
1075
        if (!$this->messagePrinted) {
1076
            $this->write("\n");
1077
        }
1078
1079
        $this->write(
1080
            \sprintf(
1081
                "%-15s%s\n",
1082
                $type . ':',
1083
                $message
1084
            )
1085
        );
1086
1087
        $this->messagePrinted = true;
1088
    }
1089
}
1090