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

TestCase::run()   F

Complexity

Conditions 22
Paths > 20000

Size

Total Lines 129
Code Lines 92

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 22
eloc 92
nc 24600
nop 1
dl 0
loc 129
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\Framework;
12
13
use PHPUnit\Framework\Constraint\Exception as ExceptionConstraint;
14
use PHPUnit\Framework\Constraint\ExceptionCode;
15
use PHPUnit\Framework\Constraint\ExceptionMessage;
16
use PHPUnit\Framework\Constraint\ExceptionMessageRegularExpression;
17
use PHPUnit_Framework_MockObject_Generator;
18
use PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount;
19
use PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex;
20
use PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastCount;
21
use PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce;
22
use PHPUnit_Framework_MockObject_Matcher_InvokedAtMostCount;
23
use PHPUnit_Framework_MockObject_Matcher_InvokedCount;
24
use PHPUnit_Framework_MockObject_MockBuilder;
25
use PHPUnit_Framework_MockObject_MockObject;
26
use PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls;
27
use PHPUnit_Framework_MockObject_Stub_Exception;
28
use PHPUnit_Framework_MockObject_Stub_Return;
29
use PHPUnit_Framework_MockObject_Stub_ReturnArgument;
30
use PHPUnit_Framework_MockObject_Stub_ReturnCallback;
31
use PHPUnit_Framework_MockObject_Stub_ReturnSelf;
32
use PHPUnit_Framework_MockObject_Stub_ReturnValueMap;
33
use PHPUnit\Runner\BaseTestRunner;
34
use PHPUnit\Runner\PhptTestCase;
35
use PHPUnit\Util\GlobalState;
36
use PHPUnit\Util\InvalidArgumentHelper;
37
use PHPUnit\Util\PHP\AbstractPhpProcess;
38
use Prophecy;
39
use ReflectionClass;
40
use ReflectionException;
41
use ReflectionObject;
42
use SebastianBergmann;
43
use SebastianBergmann\GlobalState\Snapshot;
44
use SebastianBergmann\GlobalState\Restorer;
45
use SebastianBergmann\GlobalState\Blacklist;
46
use SebastianBergmann\Diff\Differ;
47
use SebastianBergmann\Exporter\Exporter;
48
use SebastianBergmann\ObjectEnumerator\Enumerator;
49
use Prophecy\Exception\Prediction\PredictionException;
50
use Prophecy\Prophet;
51
use DeepCopy\DeepCopy;
52
use Text_Template;
53
use Throwable;
54
55
/**
56
 * A TestCase defines the fixture to run multiple tests.
57
 *
58
 * To define a TestCase
59
 *
60
 *   1) Implement a subclass of PHPUnit\Framework\TestCase.
61
 *   2) Define instance variables that store the state of the fixture.
62
 *   3) Initialize the fixture state by overriding setUp().
63
 *   4) Clean-up after a test by overriding tearDown().
64
 *
65
 * Each test runs in its own fixture so there can be no side effects
66
 * among test runs.
67
 *
68
 * Here is an example:
69
 *
70
 * <code>
71
 * <?php
72
 * class MathTest extends PHPUnit\Framework\TestCase
73
 * {
74
 *     public $value1;
75
 *     public $value2;
76
 *
77
 *     protected function setUp()
78
 *     {
79
 *         $this->value1 = 2;
80
 *         $this->value2 = 3;
81
 *     }
82
 * }
83
 * ?>
84
 * </code>
85
 *
86
 * For each test implement a method which interacts with the fixture.
87
 * Verify the expected results with assertions specified by calling
88
 * assert with a boolean.
89
 *
90
 * <code>
91
 * <?php
92
 * public function testPass()
93
 * {
94
 *     $this->assertTrue($this->value1 + $this->value2 == 5);
95
 * }
96
 * ?>
97
 * </code>
98
 */
99
abstract class TestCase extends Assert implements Test, SelfDescribing
100
{
101
    /**
102
     * Enable or disable the backup and restoration of the $GLOBALS array.
103
     * Overwrite this attribute in a child class of TestCase.
104
     * Setting this attribute in setUp() has no effect!
105
     *
106
     * @var bool
107
     */
108
    protected $backupGlobals;
109
110
    /**
111
     * @var array
112
     */
113
    protected $backupGlobalsBlacklist = [];
114
115
    /**
116
     * Enable or disable the backup and restoration of static attributes.
117
     * Overwrite this attribute in a child class of TestCase.
118
     * Setting this attribute in setUp() has no effect!
119
     *
120
     * @var bool
121
     */
122
    protected $backupStaticAttributes;
123
124
    /**
125
     * @var array
126
     */
127
    protected $backupStaticAttributesBlacklist = [];
128
129
    /**
130
     * Whether or not this test is to be run in a separate PHP process.
131
     *
132
     * @var bool
133
     */
134
    protected $runTestInSeparateProcess;
135
136
    /**
137
     * Whether or not this test should preserve the global state when
138
     * running in a separate PHP process.
139
     *
140
     * @var bool
141
     */
142
    protected $preserveGlobalState = true;
143
144
    /**
145
     * Whether or not this test is running in a separate PHP process.
146
     *
147
     * @var bool
148
     */
149
    private $inIsolation = false;
150
151
    /**
152
     * @var array
153
     */
154
    private $data;
155
156
    /**
157
     * @var string
158
     */
159
    private $dataName;
160
161
    /**
162
     * @var bool
163
     */
164
    private $useErrorHandler;
165
166
    /**
167
     * The name of the expected Exception.
168
     *
169
     * @var string
170
     */
171
    private $expectedException;
172
173
    /**
174
     * The message of the expected Exception.
175
     *
176
     * @var string
177
     */
178
    private $expectedExceptionMessage = '';
179
180
    /**
181
     * The regex pattern to validate the expected Exception message.
182
     *
183
     * @var string
184
     */
185
    private $expectedExceptionMessageRegExp = '';
186
187
    /**
188
     * The code of the expected Exception.
189
     *
190
     * @var int|string
191
     */
192
    private $expectedExceptionCode;
193
194
    /**
195
     * The name of the test case.
196
     *
197
     * @var string
198
     */
199
    private $name;
200
201
    /**
202
     * @var array
203
     */
204
    private $dependencies = [];
205
206
    /**
207
     * @var array
208
     */
209
    private $dependencyInput = [];
210
211
    /**
212
     * @var array
213
     */
214
    private $iniSettings = [];
215
216
    /**
217
     * @var array
218
     */
219
    private $locale = [];
220
221
    /**
222
     * @var array
223
     */
224
    private $mockObjects = [];
225
226
    /**
227
     * @var array
228
     */
229
    private $mockObjectGenerator;
230
231
    /**
232
     * @var int
233
     */
234
    private $status;
235
236
    /**
237
     * @var string
238
     */
239
    private $statusMessage = '';
240
241
    /**
242
     * @var int
243
     */
244
    private $numAssertions = 0;
245
246
    /**
247
     * @var TestResult
248
     */
249
    private $result;
250
251
    /**
252
     * @var mixed
253
     */
254
    private $testResult;
255
256
    /**
257
     * @var string
258
     */
259
    private $output = '';
260
261
    /**
262
     * @var string
263
     */
264
    private $outputExpectedRegex;
265
266
    /**
267
     * @var string
268
     */
269
    private $outputExpectedString;
270
271
    /**
272
     * @var mixed
273
     */
274
    private $outputCallback = false;
275
276
    /**
277
     * @var bool
278
     */
279
    private $outputBufferingActive = false;
280
281
    /**
282
     * @var int
283
     */
284
    private $outputBufferingLevel;
285
286
    /**
287
     * @var SebastianBergmann\GlobalState\Snapshot
288
     */
289
    private $snapshot;
290
291
    /**
292
     * @var Prophecy\Prophet
293
     */
294
    private $prophet;
295
296
    /**
297
     * @var bool
298
     */
299
    private $beStrictAboutChangesToGlobalState = false;
300
301
    /**
302
     * @var bool
303
     */
304
    private $registerMockObjectsFromTestArgumentsRecursively = false;
305
306
    /**
307
     * @var string[]
308
     */
309
    private $warnings = [];
310
311
    /**
312
     * @var array
313
     */
314
    private $groups = [];
315
316
    /**
317
     * @var bool
318
     */
319
    private $doesNotPerformAssertions = false;
320
321
    /**
322
     * Constructs a test case with the given name.
323
     *
324
     * @param string $name
325
     * @param array  $data
326
     * @param string $dataName
327
     */
328
    public function __construct($name = null, array $data = [], $dataName = '')
329
    {
330
        if ($name !== null) {
331
            $this->setName($name);
332
        }
333
334
        $this->data     = $data;
335
        $this->dataName = $dataName;
336
    }
337
338
    /**
339
     * Returns a string representation of the test case.
340
     *
341
     * @return string
342
     */
343
    public function toString()
344
    {
345
        $class = new ReflectionClass($this);
346
347
        $buffer = \sprintf(
348
            '%s::%s',
349
            $class->name,
350
            $this->getName(false)
351
        );
352
353
        return $buffer . $this->getDataSetAsString();
354
    }
355
356
    /**
357
     * Counts the number of test cases executed by run(TestResult result).
358
     *
359
     * @return int
360
     */
361
    public function count()
362
    {
363
        return 1;
364
    }
365
366
    public function getGroups()
367
    {
368
        return $this->groups;
369
    }
370
371
    /**
372
     * @param array $groups
373
     */
374
    public function setGroups(array $groups)
375
    {
376
        $this->groups = $groups;
377
    }
378
379
    /**
380
     * Returns the annotations for this test.
381
     *
382
     * @return array
383
     */
384
    public function getAnnotations()
385
    {
386
        return \PHPUnit\Util\Test::parseTestMethodAnnotations(
387
            \get_class($this),
388
            $this->name
389
        );
390
    }
391
392
    /**
393
     * Gets the name of a TestCase.
394
     *
395
     * @param bool $withDataSet
396
     *
397
     * @return string
398
     */
399
    public function getName($withDataSet = true)
400
    {
401
        if ($withDataSet) {
402
            return $this->name . $this->getDataSetAsString(false);
403
        }
404
405
        return $this->name;
406
    }
407
408
    /**
409
     * Returns the size of the test.
410
     *
411
     * @return int
412
     */
413
    public function getSize()
414
    {
415
        return \PHPUnit\Util\Test::getSize(
416
            \get_class($this),
417
            $this->getName(false)
418
        );
419
    }
420
421
    /**
422
     * @return bool
423
     */
424
    public function hasSize()
425
    {
426
        return $this->getSize() !== \PHPUnit\Util\Test::UNKNOWN;
427
    }
428
429
    /**
430
     * @return bool
431
     */
432
    public function isSmall()
433
    {
434
        return $this->getSize() === \PHPUnit\Util\Test::SMALL;
435
    }
436
437
    /**
438
     * @return bool
439
     */
440
    public function isMedium()
441
    {
442
        return $this->getSize() === \PHPUnit\Util\Test::MEDIUM;
443
    }
444
445
    /**
446
     * @return bool
447
     */
448
    public function isLarge()
449
    {
450
        return $this->getSize() === \PHPUnit\Util\Test::LARGE;
451
    }
452
453
    /**
454
     * @return string
455
     */
456
    public function getActualOutput()
457
    {
458
        if (!$this->outputBufferingActive) {
459
            return $this->output;
460
        }
461
462
        return \ob_get_contents();
463
    }
464
465
    /**
466
     * @return bool
467
     */
468
    public function hasOutput()
469
    {
470
        if (\strlen($this->output) === 0) {
471
            return false;
472
        }
473
474
        if ($this->hasExpectationOnOutput()) {
475
            return false;
476
        }
477
478
        return true;
479
    }
480
481
    /**
482
     * @return bool
483
     */
484
    public function doesNotPerformAssertions()
485
    {
486
        return $this->doesNotPerformAssertions;
487
    }
488
489
    /**
490
     * @param string $expectedRegex
491
     *
492
     * @throws Exception
493
     */
494
    public function expectOutputRegex($expectedRegex)
495
    {
496
        if ($this->outputExpectedString !== null) {
497
            throw new Exception;
498
        }
499
500
        if (\is_string($expectedRegex) || \is_null($expectedRegex)) {
501
            $this->outputExpectedRegex = $expectedRegex;
502
        }
503
    }
504
505
    /**
506
     * @param string $expectedString
507
     */
508
    public function expectOutputString($expectedString)
509
    {
510
        if ($this->outputExpectedRegex !== null) {
511
            throw new Exception;
512
        }
513
514
        if (\is_string($expectedString) || \is_null($expectedString)) {
515
            $this->outputExpectedString = $expectedString;
516
        }
517
    }
518
519
    /**
520
     * @return bool
521
     */
522
    public function hasExpectationOnOutput()
523
    {
524
        return \is_string($this->outputExpectedString) || \is_string($this->outputExpectedRegex);
525
    }
526
527
    /**
528
     * @return string
529
     */
530
    public function getExpectedException()
531
    {
532
        return $this->expectedException;
533
    }
534
535
    /**
536
     * @return int|string
537
     */
538
    public function getExpectedExceptionCode()
539
    {
540
        return $this->expectedExceptionCode;
541
    }
542
543
    /**
544
     * @return string
545
     */
546
    public function getExpectedExceptionMessage()
547
    {
548
        return $this->expectedExceptionMessage;
549
    }
550
551
    /**
552
     * @param string $exception
553
     */
554
    public function expectException($exception)
555
    {
556
        if (!\is_string($exception)) {
557
            throw InvalidArgumentHelper::factory(1, 'string');
558
        }
559
560
        $this->expectedException = $exception;
561
    }
562
563
    /**
564
     * @param int|string $code
565
     *
566
     * @throws Exception
567
     */
568
    public function expectExceptionCode($code)
569
    {
570
        if (!$this->expectedException) {
571
            $this->expectedException = \Exception::class;
572
        }
573
574
        if (!\is_int($code) && !\is_string($code)) {
575
            throw InvalidArgumentHelper::factory(1, 'integer or string');
576
        }
577
578
        $this->expectedExceptionCode = $code;
579
    }
580
581
    /**
582
     * @param string $message
583
     *
584
     * @throws Exception
585
     */
586
    public function expectExceptionMessage($message)
587
    {
588
        if (!$this->expectedException) {
589
            $this->expectedException = \Exception::class;
590
        }
591
592
        if (!\is_string($message)) {
593
            throw InvalidArgumentHelper::factory(1, 'string');
594
        }
595
596
        $this->expectedExceptionMessage = $message;
597
    }
598
599
    /**
600
     * @param string $messageRegExp
601
     *
602
     * @throws Exception
603
     */
604
    public function expectExceptionMessageRegExp($messageRegExp)
605
    {
606
        if (!\is_string($messageRegExp)) {
607
            throw InvalidArgumentHelper::factory(1, 'string');
608
        }
609
610
        $this->expectedExceptionMessageRegExp = $messageRegExp;
611
    }
612
613
    /**
614
     * @param bool $flag
615
     */
616
    public function setRegisterMockObjectsFromTestArgumentsRecursively($flag)
617
    {
618
        if (!\is_bool($flag)) {
619
            throw InvalidArgumentHelper::factory(1, 'boolean');
620
        }
621
622
        $this->registerMockObjectsFromTestArgumentsRecursively = $flag;
623
    }
624
625
    protected function setExpectedExceptionFromAnnotation()
626
    {
627
        try {
628
            $expectedException = \PHPUnit\Util\Test::getExpectedException(
629
                \get_class($this),
630
                $this->name
631
            );
632
633
            if ($expectedException !== false) {
634
                $this->expectException($expectedException['class']);
635
636
                if ($expectedException['code'] !== null) {
637
                    $this->expectExceptionCode($expectedException['code']);
638
                }
639
640
                if ($expectedException['message'] !== '') {
641
                    $this->expectExceptionMessage($expectedException['message']);
642
                } elseif ($expectedException['message_regex'] !== '') {
643
                    $this->expectExceptionMessageRegExp($expectedException['message_regex']);
644
                }
645
            }
646
        } catch (ReflectionException $e) {
647
        }
648
    }
649
650
    /**
651
     * @param bool $useErrorHandler
652
     */
653
    public function setUseErrorHandler($useErrorHandler)
654
    {
655
        $this->useErrorHandler = $useErrorHandler;
656
    }
657
658
    protected function setUseErrorHandlerFromAnnotation()
659
    {
660
        try {
661
            $useErrorHandler = \PHPUnit\Util\Test::getErrorHandlerSettings(
662
                \get_class($this),
663
                $this->name
664
            );
665
666
            if ($useErrorHandler !== null) {
667
                $this->setUseErrorHandler($useErrorHandler);
668
            }
669
        } catch (ReflectionException $e) {
670
        }
671
    }
672
673
    protected function checkRequirements()
674
    {
675
        if (!$this->name || !\method_exists($this, $this->name)) {
676
            return;
677
        }
678
679
        $missingRequirements = \PHPUnit\Util\Test::getMissingRequirements(
680
            \get_class($this),
681
            $this->name
682
        );
683
684
        if (!empty($missingRequirements)) {
685
            $this->markTestSkipped(\implode(PHP_EOL, $missingRequirements));
686
        }
687
    }
688
689
    /**
690
     * Returns the status of this test.
691
     *
692
     * @return int
693
     */
694
    public function getStatus()
695
    {
696
        return $this->status;
697
    }
698
699
    public function markAsRisky()
700
    {
701
        $this->status = BaseTestRunner::STATUS_RISKY;
702
    }
703
704
    /**
705
     * Returns the status message of this test.
706
     *
707
     * @return string
708
     */
709
    public function getStatusMessage()
710
    {
711
        return $this->statusMessage;
712
    }
713
714
    /**
715
     * Returns whether or not this test has failed.
716
     *
717
     * @return bool
718
     */
719
    public function hasFailed()
720
    {
721
        $status = $this->getStatus();
722
723
        return $status == BaseTestRunner::STATUS_FAILURE ||
724
            $status == BaseTestRunner::STATUS_ERROR;
725
    }
726
727
    /**
728
     * Runs the test case and collects the results in a TestResult object.
729
     * If no TestResult object is passed a new one will be created.
730
     *
731
     * @param TestResult $result
732
     *
733
     * @return TestResult
734
     *
735
     * @throws Exception
736
     */
737
    public function run(TestResult $result = null)
738
    {
739
        if ($result === null) {
740
            $result = $this->createResult();
741
        }
742
743
        if (!$this instanceof WarningTestCase) {
744
            $this->setTestResultObject($result);
745
            $this->setUseErrorHandlerFromAnnotation();
746
        }
747
748
        if ($this->useErrorHandler !== null) {
749
            $oldErrorHandlerSetting = $result->getConvertErrorsToExceptions();
750
            $result->convertErrorsToExceptions($this->useErrorHandler);
751
        }
752
753
        if (!$this instanceof WarningTestCase &&
754
            !$this instanceof SkippedTestCase &&
755
            !$this->handleDependencies()) {
756
            return;
757
        }
758
759
        if ($this->runTestInSeparateProcess === true &&
760
            $this->inIsolation !== true &&
761
            !$this instanceof PhptTestCase) {
762
            $class = new ReflectionClass($this);
763
764
            $template = new Text_Template(
765
                __DIR__ . '/../Util/PHP/Template/TestCaseMethod.tpl'
766
            );
767
768
            if ($this->preserveGlobalState) {
769
                $constants     = GlobalState::getConstantsAsString();
770
                $globals       = GlobalState::getGlobalsAsString();
771
                $includedFiles = GlobalState::getIncludedFilesAsString();
772
                $iniSettings   = GlobalState::getIniSettingsAsString();
773
            } else {
774
                $constants = '';
775
                if (!empty($GLOBALS['__PHPUNIT_BOOTSTRAP'])) {
776
                    $globals = '$GLOBALS[\'__PHPUNIT_BOOTSTRAP\'] = ' . \var_export($GLOBALS['__PHPUNIT_BOOTSTRAP'], true) . ";\n";
777
                } else {
778
                    $globals = '';
779
                }
780
                $includedFiles = '';
781
                $iniSettings   = '';
782
            }
783
784
            $coverage                                   = $result->getCollectCodeCoverageInformation() ? 'true' : 'false';
785
            $isStrictAboutTestsThatDoNotTestAnything    = $result->isStrictAboutTestsThatDoNotTestAnything() ? 'true' : 'false';
786
            $isStrictAboutOutputDuringTests             = $result->isStrictAboutOutputDuringTests() ? 'true' : 'false';
787
            $enforcesTimeLimit                          = $result->enforcesTimeLimit() ? 'true' : 'false';
788
            $isStrictAboutTodoAnnotatedTests            = $result->isStrictAboutTodoAnnotatedTests() ? 'true' : 'false';
789
            $isStrictAboutResourceUsageDuringSmallTests = $result->isStrictAboutResourceUsageDuringSmallTests() ? 'true' : 'false';
790
791
            if (\defined('PHPUNIT_COMPOSER_INSTALL')) {
792
                $composerAutoload = \var_export(PHPUNIT_COMPOSER_INSTALL, true);
793
            } else {
794
                $composerAutoload = '\'\'';
795
            }
796
797
            if (\defined('__PHPUNIT_PHAR__')) {
798
                $phar = \var_export(__PHPUNIT_PHAR__, true);
799
            } else {
800
                $phar = '\'\'';
801
            }
802
803
            if ($result->getCodeCoverage()) {
804
                $codeCoverageFilter = $result->getCodeCoverage()->filter();
805
            } else {
806
                $codeCoverageFilter = null;
807
            }
808
809
            $data               = \var_export(\serialize($this->data), true);
810
            $dataName           = \var_export($this->dataName, true);
811
            $dependencyInput    = \var_export(\serialize($this->dependencyInput), true);
812
            $includePath        = \var_export(\get_include_path(), true);
813
            $codeCoverageFilter = \var_export(\serialize($codeCoverageFilter), true);
814
            // must do these fixes because TestCaseMethod.tpl has unserialize('{data}') in it, and we can't break BC
815
            // the lines above used to use addcslashes() rather than var_export(), which breaks null byte escape sequences
816
            $data               = "'." . $data . ".'";
817
            $dataName           = "'.(" . $dataName . ").'";
818
            $dependencyInput    = "'." . $dependencyInput . ".'";
819
            $includePath        = "'." . $includePath . ".'";
820
            $codeCoverageFilter = "'." . $codeCoverageFilter . ".'";
821
822
            $configurationFilePath = $GLOBALS['__PHPUNIT_CONFIGURATION_FILE'] ?? '';
823
824
            $template->setVar(
825
                [
826
                    'composerAutoload'                           => $composerAutoload,
827
                    'phar'                                       => $phar,
828
                    'filename'                                   => $class->getFileName(),
829
                    'className'                                  => $class->getName(),
830
                    'methodName'                                 => $this->name,
831
                    'collectCodeCoverageInformation'             => $coverage,
832
                    'data'                                       => $data,
833
                    'dataName'                                   => $dataName,
834
                    'dependencyInput'                            => $dependencyInput,
835
                    'constants'                                  => $constants,
836
                    'globals'                                    => $globals,
837
                    'include_path'                               => $includePath,
838
                    'included_files'                             => $includedFiles,
839
                    'iniSettings'                                => $iniSettings,
840
                    'isStrictAboutTestsThatDoNotTestAnything'    => $isStrictAboutTestsThatDoNotTestAnything,
841
                    'isStrictAboutOutputDuringTests'             => $isStrictAboutOutputDuringTests,
842
                    'enforcesTimeLimit'                          => $enforcesTimeLimit,
843
                    'isStrictAboutTodoAnnotatedTests'            => $isStrictAboutTodoAnnotatedTests,
844
                    'isStrictAboutResourceUsageDuringSmallTests' => $isStrictAboutResourceUsageDuringSmallTests,
845
                    'codeCoverageFilter'                         => $codeCoverageFilter,
846
                    'configurationFilePath'                      => $configurationFilePath
847
                ]
848
            );
849
850
            $this->prepareTemplate($template);
851
852
            $php = AbstractPhpProcess::factory();
853
            $php->runTestJob($template->render(), $this, $result);
854
        } else {
855
            $result->run($this);
856
        }
857
858
        if ($this->useErrorHandler !== null) {
859
            $result->convertErrorsToExceptions($oldErrorHandlerSetting);
860
        }
861
862
        $this->result = null;
863
864
        return $result;
865
    }
866
867
    /**
868
     * Runs the bare test sequence.
869
     */
870
    public function runBare()
871
    {
872
        $this->numAssertions = 0;
873
874
        $this->snapshotGlobalState();
875
        $this->startOutputBuffering();
876
        \clearstatcache();
877
        $currentWorkingDirectory = \getcwd();
878
879
        $hookMethods = \PHPUnit\Util\Test::getHookMethods(\get_class($this));
880
881
        try {
882
            $hasMetRequirements = false;
883
            $this->checkRequirements();
884
            $hasMetRequirements = true;
885
886
            if ($this->inIsolation) {
887
                foreach ($hookMethods['beforeClass'] as $method) {
888
                    $this->$method();
889
                }
890
            }
891
892
            $this->setExpectedExceptionFromAnnotation();
893
            $this->setDoesNotPerformAssertionsFromAnnotation();
894
895
            foreach ($hookMethods['before'] as $method) {
896
                $this->$method();
897
            }
898
899
            $this->assertPreConditions();
900
            $this->testResult = $this->runTest();
901
            $this->verifyMockObjects();
902
            $this->assertPostConditions();
903
904
            if (!empty($this->warnings)) {
905
                throw new Warning(
906
                    \implode(
907
                        "\n",
908
                        \array_unique($this->warnings)
909
                    )
910
                );
911
            }
912
913
            $this->status = BaseTestRunner::STATUS_PASSED;
914
        } catch (IncompleteTest $e) {
915
            $this->status        = BaseTestRunner::STATUS_INCOMPLETE;
916
            $this->statusMessage = $e->getMessage();
917
        } catch (SkippedTest $e) {
918
            $this->status        = BaseTestRunner::STATUS_SKIPPED;
919
            $this->statusMessage = $e->getMessage();
920
        } catch (Warning $e) {
921
            $this->status        = BaseTestRunner::STATUS_WARNING;
922
            $this->statusMessage = $e->getMessage();
923
        } catch (AssertionFailedError $e) {
924
            $this->status        = BaseTestRunner::STATUS_FAILURE;
925
            $this->statusMessage = $e->getMessage();
926
        } catch (PredictionException $e) {
927
            $this->status        = BaseTestRunner::STATUS_FAILURE;
928
            $this->statusMessage = $e->getMessage();
929
        } catch (Throwable $_e) {
930
            $e = $_e;
931
        }
932
933
        if (isset($_e)) {
934
            $this->status        = BaseTestRunner::STATUS_ERROR;
935
            $this->statusMessage = $_e->getMessage();
936
        }
937
938
        // Clean up the mock objects.
939
        $this->mockObjects = [];
940
        $this->prophet     = null;
941
942
        // Tear down the fixture. An exception raised in tearDown() will be
943
        // caught and passed on when no exception was raised before.
944
        try {
945
            if ($hasMetRequirements) {
946
                foreach ($hookMethods['after'] as $method) {
947
                    $this->$method();
948
                }
949
950
                if ($this->inIsolation) {
951
                    foreach ($hookMethods['afterClass'] as $method) {
952
                        $this->$method();
953
                    }
954
                }
955
            }
956
        } catch (Throwable $_e) {
957
            if (!isset($e)) {
958
                $e = $_e;
959
            }
960
        }
961
962
        try {
963
            $this->stopOutputBuffering();
964
        } catch (RiskyTestError $_e) {
965
            if (!isset($e)) {
966
                $e = $_e;
967
            }
968
        }
969
970
        \clearstatcache();
971
972
        if ($currentWorkingDirectory != \getcwd()) {
973
            \chdir($currentWorkingDirectory);
974
        }
975
976
        $this->restoreGlobalState();
977
978
        // Clean up INI settings.
979
        foreach ($this->iniSettings as $varName => $oldValue) {
980
            \ini_set($varName, $oldValue);
981
        }
982
983
        $this->iniSettings = [];
984
985
        // Clean up locale settings.
986
        foreach ($this->locale as $category => $locale) {
987
            \setlocale($category, $locale);
988
        }
989
990
        // Perform assertion on output.
991
        if (!isset($e)) {
992
            try {
993
                if ($this->outputExpectedRegex !== null) {
994
                    $this->assertRegExp($this->outputExpectedRegex, $this->output);
995
                } elseif ($this->outputExpectedString !== null) {
996
                    $this->assertEquals($this->outputExpectedString, $this->output);
997
                }
998
            } catch (Throwable $_e) {
999
                $e = $_e;
1000
            }
1001
        }
1002
1003
        // Workaround for missing "finally".
1004
        if (isset($e)) {
1005
            if ($e instanceof PredictionException) {
1006
                $e = new AssertionFailedError($e->getMessage());
1007
            }
1008
1009
            $this->onNotSuccessfulTest($e);
1010
        }
1011
    }
1012
1013
    /**
1014
     * Override to run the test and assert its state.
1015
     *
1016
     * @return mixed
1017
     *
1018
     * @throws Exception|Exception
1019
     * @throws Exception
1020
     */
1021
    protected function runTest()
1022
    {
1023
        if ($this->name === null) {
1024
            throw new Exception(
1025
                'PHPUnit\Framework\TestCase::$name must not be null.'
1026
            );
1027
        }
1028
1029
        try {
1030
            $class  = new ReflectionClass($this);
1031
            $method = $class->getMethod($this->name);
1032
        } catch (ReflectionException $e) {
1033
            $this->fail($e->getMessage());
1034
        }
1035
1036
        $testArguments = \array_merge($this->data, $this->dependencyInput);
1037
1038
        $this->registerMockObjectsFromTestArguments($testArguments);
1039
1040
        try {
1041
            $testResult = $method->invokeArgs($this, $testArguments);
1042
        } catch (Throwable $_e) {
1043
            $e = $_e;
1044
        }
1045
1046
        if (isset($e)) {
1047
            $checkException = false;
1048
1049
            if (!($e instanceof SkippedTestError) && \is_string($this->expectedException)) {
1050
                $checkException = true;
1051
1052
                if ($e instanceof Exception) {
1053
                    $checkException = false;
1054
                }
1055
1056
                $reflector = new ReflectionClass($this->expectedException);
1057
1058
                if ($this->expectedException === 'PHPUnit\Framework\Exception' ||
1059
                    $this->expectedException === '\PHPUnit\Framework\Exception' ||
1060
                    $reflector->isSubclassOf('PHPUnit\Framework\Exception')) {
1061
                    $checkException = true;
1062
                }
1063
            }
1064
1065
            if ($checkException) {
1066
                $this->assertThat(
1067
                    $e,
1068
                    new ExceptionConstraint(
1069
                        $this->expectedException
1070
                    )
1071
                );
1072
1073
                if (\is_string($this->expectedExceptionMessage) &&
1074
                    !empty($this->expectedExceptionMessage)) {
1075
                    $this->assertThat(
1076
                        $e,
1077
                        new ExceptionMessage(
1078
                            $this->expectedExceptionMessage
1079
                        )
1080
                    );
1081
                }
1082
1083
                if (\is_string($this->expectedExceptionMessageRegExp) &&
1084
                    !empty($this->expectedExceptionMessageRegExp)) {
1085
                    $this->assertThat(
1086
                        $e,
1087
                        new ExceptionMessageRegularExpression(
1088
                            $this->expectedExceptionMessageRegExp
1089
                        )
1090
                    );
1091
                }
1092
1093
                if ($this->expectedExceptionCode !== null) {
1094
                    $this->assertThat(
1095
                        $e,
1096
                        new ExceptionCode(
1097
                            $this->expectedExceptionCode
1098
                        )
1099
                    );
1100
                }
1101
1102
                return;
1103
            }
1104
1105
            throw $e;
1106
        }
1107
1108
        if ($this->expectedException !== null) {
1109
            $this->assertThat(
1110
                null,
1111
                new ExceptionConstraint(
1112
                    $this->expectedException
1113
                )
1114
            );
1115
        }
1116
1117
        return $testResult;
1118
    }
1119
1120
    /**
1121
     * Verifies the mock object expectations.
1122
     */
1123
    protected function verifyMockObjects()
1124
    {
1125
        foreach ($this->mockObjects as $mockObject) {
1126
            if ($mockObject->__phpunit_hasMatchers()) {
1127
                $this->numAssertions++;
1128
            }
1129
1130
            $mockObject->__phpunit_verify(
1131
                $this->shouldInvocationMockerBeReset($mockObject)
1132
            );
1133
        }
1134
1135
        if ($this->prophet !== null) {
1136
            try {
1137
                $this->prophet->checkPredictions();
1138
            } catch (Throwable $t) {
1139
                /* Intentionally left empty */
1140
            }
1141
1142
            foreach ($this->prophet->getProphecies() as $objectProphecy) {
1143
                foreach ($objectProphecy->getMethodProphecies() as $methodProphecies) {
1144
                    foreach ($methodProphecies as $methodProphecy) {
1145
                        $this->numAssertions += \count($methodProphecy->getCheckedPredictions());
1146
                    }
1147
                }
1148
            }
1149
1150
            if (isset($t)) {
1151
                throw $t;
1152
            }
1153
        }
1154
    }
1155
1156
    /**
1157
     * Sets the name of a TestCase.
1158
     *
1159
     * @param  string
1160
     */
1161
    public function setName($name)
1162
    {
1163
        $this->name = $name;
1164
    }
1165
1166
    /**
1167
     * Sets the dependencies of a TestCase.
1168
     *
1169
     * @param array $dependencies
1170
     */
1171
    public function setDependencies(array $dependencies)
1172
    {
1173
        $this->dependencies = $dependencies;
1174
    }
1175
1176
    /**
1177
     * Returns true if the tests has dependencies
1178
     *
1179
     * @return bool
1180
     */
1181
    public function hasDependencies()
1182
    {
1183
        return \count($this->dependencies) > 0;
1184
    }
1185
1186
    /**
1187
     * Sets
1188
     *
1189
     * @param array $dependencyInput
1190
     */
1191
    public function setDependencyInput(array $dependencyInput)
1192
    {
1193
        $this->dependencyInput = $dependencyInput;
1194
    }
1195
1196
    /**
1197
     * @param bool $beStrictAboutChangesToGlobalState
1198
     */
1199
    public function setBeStrictAboutChangesToGlobalState($beStrictAboutChangesToGlobalState)
1200
    {
1201
        $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState;
1202
    }
1203
1204
    /**
1205
     * Calling this method in setUp() has no effect!
1206
     *
1207
     * @param bool $backupGlobals
1208
     */
1209
    public function setBackupGlobals($backupGlobals)
1210
    {
1211
        if (\is_null($this->backupGlobals) && \is_bool($backupGlobals)) {
1212
            $this->backupGlobals = $backupGlobals;
1213
        }
1214
    }
1215
1216
    /**
1217
     * Calling this method in setUp() has no effect!
1218
     *
1219
     * @param bool $backupStaticAttributes
1220
     */
1221
    public function setBackupStaticAttributes($backupStaticAttributes)
1222
    {
1223
        if (\is_null($this->backupStaticAttributes) &&
1224
            \is_bool($backupStaticAttributes)) {
1225
            $this->backupStaticAttributes = $backupStaticAttributes;
1226
        }
1227
    }
1228
1229
    /**
1230
     * @param bool $runTestInSeparateProcess
1231
     *
1232
     * @throws Exception
1233
     */
1234
    public function setRunTestInSeparateProcess($runTestInSeparateProcess)
1235
    {
1236
        if (\is_bool($runTestInSeparateProcess)) {
1237
            if ($this->runTestInSeparateProcess === null) {
1238
                $this->runTestInSeparateProcess = $runTestInSeparateProcess;
1239
            }
1240
        } else {
1241
            throw InvalidArgumentHelper::factory(1, 'boolean');
1242
        }
1243
    }
1244
1245
    /**
1246
     * @param bool $preserveGlobalState
1247
     *
1248
     * @throws Exception
1249
     */
1250
    public function setPreserveGlobalState($preserveGlobalState)
1251
    {
1252
        if (\is_bool($preserveGlobalState)) {
1253
            $this->preserveGlobalState = $preserveGlobalState;
1254
        } else {
1255
            throw InvalidArgumentHelper::factory(1, 'boolean');
1256
        }
1257
    }
1258
1259
    /**
1260
     * @param bool $inIsolation
1261
     *
1262
     * @throws Exception
1263
     */
1264
    public function setInIsolation($inIsolation)
1265
    {
1266
        if (\is_bool($inIsolation)) {
1267
            $this->inIsolation = $inIsolation;
1268
        } else {
1269
            throw InvalidArgumentHelper::factory(1, 'boolean');
1270
        }
1271
    }
1272
1273
    /**
1274
     * @return bool
1275
     */
1276
    public function isInIsolation()
1277
    {
1278
        return $this->inIsolation;
1279
    }
1280
1281
    /**
1282
     * @return mixed
1283
     */
1284
    public function getResult()
1285
    {
1286
        return $this->testResult;
1287
    }
1288
1289
    /**
1290
     * @param mixed $result
1291
     */
1292
    public function setResult($result)
1293
    {
1294
        $this->testResult = $result;
1295
    }
1296
1297
    /**
1298
     * @param callable $callback
1299
     *
1300
     * @throws Exception
1301
     */
1302
    public function setOutputCallback($callback)
1303
    {
1304
        if (!\is_callable($callback)) {
1305
            throw InvalidArgumentHelper::factory(1, 'callback');
1306
        }
1307
1308
        $this->outputCallback = $callback;
1309
    }
1310
1311
    /**
1312
     * @return TestResult
1313
     */
1314
    public function getTestResultObject()
1315
    {
1316
        return $this->result;
1317
    }
1318
1319
    /**
1320
     * @param TestResult $result
1321
     */
1322
    public function setTestResultObject(TestResult $result)
1323
    {
1324
        $this->result = $result;
1325
    }
1326
1327
    /**
1328
     * @param PHPUnit_Framework_MockObject_MockObject $mockObject
1329
     */
1330
    public function registerMockObject(PHPUnit_Framework_MockObject_MockObject $mockObject)
1331
    {
1332
        $this->mockObjects[] = $mockObject;
1333
    }
1334
1335
    /**
1336
     * This method is a wrapper for the ini_set() function that automatically
1337
     * resets the modified php.ini setting to its original value after the
1338
     * test is run.
1339
     *
1340
     * @param string $varName
1341
     * @param string $newValue
1342
     *
1343
     * @throws Exception
1344
     */
1345
    protected function iniSet($varName, $newValue)
1346
    {
1347
        if (!\is_string($varName)) {
1348
            throw InvalidArgumentHelper::factory(1, 'string');
1349
        }
1350
1351
        $currentValue = \ini_set($varName, $newValue);
1352
1353
        if ($currentValue !== false) {
1354
            $this->iniSettings[$varName] = $currentValue;
1355
        } else {
1356
            throw new Exception(
1357
                \sprintf(
1358
                    'INI setting "%s" could not be set to "%s".',
1359
                    $varName,
1360
                    $newValue
1361
                )
1362
            );
1363
        }
1364
    }
1365
1366
    /**
1367
     * This method is a wrapper for the setlocale() function that automatically
1368
     * resets the locale to its original value after the test is run.
1369
     *
1370
     * @param int    $category
1371
     * @param string $locale
1372
     *
1373
     * @throws Exception
1374
     */
1375
    protected function setLocale()
1376
    {
1377
        $args = \func_get_args();
1378
1379
        if (\count($args) < 2) {
1380
            throw new Exception;
1381
        }
1382
1383
        $category = $args[0];
1384
        $locale   = $args[1];
1385
1386
        $categories = [
1387
            LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME
1388
        ];
1389
1390
        if (\defined('LC_MESSAGES')) {
1391
            $categories[] = LC_MESSAGES;
1392
        }
1393
1394
        if (!\in_array($category, $categories)) {
1395
            throw new Exception;
1396
        }
1397
1398
        if (!\is_array($locale) && !\is_string($locale)) {
1399
            throw new Exception;
1400
        }
1401
1402
        $this->locale[$category] = \setlocale($category, 0);
1403
1404
        $result = \call_user_func_array('setlocale', $args);
1405
1406
        if ($result === false) {
1407
            throw new Exception(
1408
                'The locale functionality is not implemented on your platform, ' .
1409
                'the specified locale does not exist or the category name is ' .
1410
                'invalid.'
1411
            );
1412
        }
1413
    }
1414
1415
    /**
1416
     * Returns a builder object to create mock objects using a fluent interface.
1417
     *
1418
     * @param string $className
1419
     *
1420
     * @return PHPUnit_Framework_MockObject_MockBuilder
1421
     */
1422
    public function getMockBuilder($className)
1423
    {
1424
        return new PHPUnit_Framework_MockObject_MockBuilder($this, $className);
1425
    }
1426
1427
    /**
1428
     * Returns a test double for the specified class.
1429
     *
1430
     * @param string $originalClassName
1431
     *
1432
     * @return PHPUnit_Framework_MockObject_MockObject
1433
     *
1434
     * @throws Exception
1435
     */
1436
    protected function createMock($originalClassName)
1437
    {
1438
        return $this->getMockBuilder($originalClassName)
1439
            ->disableOriginalConstructor()
1440
            ->disableOriginalClone()
1441
            ->disableArgumentCloning()
1442
            ->disallowMockingUnknownTypes()
1443
            ->getMock();
1444
    }
1445
1446
    /**
1447
     * Returns a configured test double for the specified class.
1448
     *
1449
     * @param string $originalClassName
1450
     * @param array  $configuration
1451
     *
1452
     * @return PHPUnit_Framework_MockObject_MockObject
1453
     *
1454
     * @throws Exception
1455
     */
1456
    protected function createConfiguredMock($originalClassName, array $configuration)
1457
    {
1458
        $o = $this->createMock($originalClassName);
1459
1460
        foreach ($configuration as $method => $return) {
1461
            $o->method($method)->willReturn($return);
1462
        }
1463
1464
        return $o;
1465
    }
1466
1467
    /**
1468
     * Returns a partial test double for the specified class.
1469
     *
1470
     * @param string $originalClassName
1471
     * @param array  $methods
1472
     *
1473
     * @return PHPUnit_Framework_MockObject_MockObject
1474
     *
1475
     * @throws Exception
1476
     */
1477
    protected function createPartialMock($originalClassName, array $methods)
1478
    {
1479
        return $this->getMockBuilder($originalClassName)
1480
            ->disableOriginalConstructor()
1481
            ->disableOriginalClone()
1482
            ->disableArgumentCloning()
1483
            ->disallowMockingUnknownTypes()
1484
            ->setMethods(empty($methods) ? null : $methods)
1485
            ->getMock();
1486
    }
1487
1488
    /**
1489
     * Returns a test proxy for the specified class.
1490
     *
1491
     * @param string $originalClassName
1492
     * @param array  $constructorArguments
1493
     *
1494
     * @return PHPUnit_Framework_MockObject_MockObject
1495
     *
1496
     * @throws Exception
1497
     */
1498
    protected function createTestProxy($originalClassName, array $constructorArguments = [])
1499
    {
1500
        return $this->getMockBuilder($originalClassName)
1501
            ->setConstructorArgs($constructorArguments)
1502
            ->enableProxyingToOriginalMethods()
1503
            ->getMock();
1504
    }
1505
1506
    /**
1507
     * Mocks the specified class and returns the name of the mocked class.
1508
     *
1509
     * @param string $originalClassName
1510
     * @param array  $methods
1511
     * @param array  $arguments
1512
     * @param string $mockClassName
1513
     * @param bool   $callOriginalConstructor
1514
     * @param bool   $callOriginalClone
1515
     * @param bool   $callAutoload
1516
     * @param bool   $cloneArguments
1517
     *
1518
     * @return string
1519
     *
1520
     * @throws Exception
1521
     */
1522
    protected function getMockClass($originalClassName, $methods = [], array $arguments = [], $mockClassName = '', $callOriginalConstructor = false, $callOriginalClone = true, $callAutoload = true, $cloneArguments = false)
1523
    {
1524
        $mock = $this->getMockObjectGenerator()->getMock(
1525
            $originalClassName,
1526
            $methods,
1527
            $arguments,
1528
            $mockClassName,
1529
            $callOriginalConstructor,
1530
            $callOriginalClone,
1531
            $callAutoload,
1532
            $cloneArguments
1533
        );
1534
1535
        return \get_class($mock);
1536
    }
1537
1538
    /**
1539
     * Returns a mock object for the specified abstract class with all abstract
1540
     * methods of the class mocked. Concrete methods are not mocked by default.
1541
     * To mock concrete methods, use the 7th parameter ($mockedMethods).
1542
     *
1543
     * @param string $originalClassName
1544
     * @param array  $arguments
1545
     * @param string $mockClassName
1546
     * @param bool   $callOriginalConstructor
1547
     * @param bool   $callOriginalClone
1548
     * @param bool   $callAutoload
1549
     * @param array  $mockedMethods
1550
     * @param bool   $cloneArguments
1551
     *
1552
     * @return PHPUnit_Framework_MockObject_MockObject
1553
     *
1554
     * @throws Exception
1555
     */
1556
    protected function getMockForAbstractClass($originalClassName, array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = [], $cloneArguments = false)
1557
    {
1558
        $mockObject = $this->getMockObjectGenerator()->getMockForAbstractClass(
1559
            $originalClassName,
1560
            $arguments,
1561
            $mockClassName,
1562
            $callOriginalConstructor,
1563
            $callOriginalClone,
1564
            $callAutoload,
1565
            $mockedMethods,
1566
            $cloneArguments
1567
        );
1568
1569
        $this->registerMockObject($mockObject);
1570
1571
        return $mockObject;
1572
    }
1573
1574
    /**
1575
     * Returns a mock object based on the given WSDL file.
1576
     *
1577
     * @param string $wsdlFile
1578
     * @param string $originalClassName
1579
     * @param string $mockClassName
1580
     * @param array  $methods
1581
     * @param bool   $callOriginalConstructor
1582
     * @param array  $options                 An array of options passed to SOAPClient::_construct
1583
     *
1584
     * @return PHPUnit_Framework_MockObject_MockObject
1585
     */
1586
    protected function getMockFromWsdl($wsdlFile, $originalClassName = '', $mockClassName = '', array $methods = [], $callOriginalConstructor = true, array $options = [])
1587
    {
1588
        if ($originalClassName === '') {
1589
            $originalClassName = \pathinfo(\basename(\parse_url($wsdlFile)['path']), PATHINFO_FILENAME);
1590
        }
1591
1592
        if (!\class_exists($originalClassName)) {
1593
            eval(
1594
                $this->getMockObjectGenerator()->generateClassFromWsdl(
1595
                    $wsdlFile,
1596
                    $originalClassName,
1597
                    $methods,
1598
                    $options
1599
                )
1600
            );
1601
        }
1602
1603
        $mockObject = $this->getMockObjectGenerator()->getMock(
1604
            $originalClassName,
1605
            $methods,
1606
            ['', $options],
1607
            $mockClassName,
1608
            $callOriginalConstructor,
1609
            false,
1610
            false
1611
        );
1612
1613
        $this->registerMockObject($mockObject);
1614
1615
        return $mockObject;
1616
    }
1617
1618
    /**
1619
     * Returns a mock object for the specified trait with all abstract methods
1620
     * of the trait mocked. Concrete methods to mock can be specified with the
1621
     * `$mockedMethods` parameter.
1622
     *
1623
     * @param string $traitName
1624
     * @param array  $arguments
1625
     * @param string $mockClassName
1626
     * @param bool   $callOriginalConstructor
1627
     * @param bool   $callOriginalClone
1628
     * @param bool   $callAutoload
1629
     * @param array  $mockedMethods
1630
     * @param bool   $cloneArguments
1631
     *
1632
     * @return PHPUnit_Framework_MockObject_MockObject
1633
     *
1634
     * @throws Exception
1635
     */
1636
    protected function getMockForTrait($traitName, array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = [], $cloneArguments = false)
1637
    {
1638
        $mockObject = $this->getMockObjectGenerator()->getMockForTrait(
1639
            $traitName,
1640
            $arguments,
1641
            $mockClassName,
1642
            $callOriginalConstructor,
1643
            $callOriginalClone,
1644
            $callAutoload,
1645
            $mockedMethods,
1646
            $cloneArguments
1647
        );
1648
1649
        $this->registerMockObject($mockObject);
1650
1651
        return $mockObject;
1652
    }
1653
1654
    /**
1655
     * Returns an object for the specified trait.
1656
     *
1657
     * @param string $traitName
1658
     * @param array  $arguments
1659
     * @param string $traitClassName
1660
     * @param bool   $callOriginalConstructor
1661
     * @param bool   $callOriginalClone
1662
     * @param bool   $callAutoload
1663
     *
1664
     * @return object
1665
     *
1666
     * @throws Exception
1667
     */
1668
    protected function getObjectForTrait($traitName, array $arguments = [], $traitClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true)
1669
    {
1670
        return $this->getMockObjectGenerator()->getObjectForTrait(
1671
            $traitName,
1672
            $arguments,
1673
            $traitClassName,
1674
            $callOriginalConstructor,
1675
            $callOriginalClone,
1676
            $callAutoload
1677
        );
1678
    }
1679
1680
    /**
1681
     * @param string|null $classOrInterface
1682
     *
1683
     * @return \Prophecy\Prophecy\ObjectProphecy
1684
     *
1685
     * @throws \LogicException
1686
     */
1687
    protected function prophesize($classOrInterface = null)
1688
    {
1689
        return $this->getProphet()->prophesize($classOrInterface);
1690
    }
1691
1692
    /**
1693
     * Adds a value to the assertion counter.
1694
     *
1695
     * @param int $count
1696
     */
1697
    public function addToAssertionCount($count)
1698
    {
1699
        $this->numAssertions += $count;
1700
    }
1701
1702
    /**
1703
     * Returns the number of assertions performed by this test.
1704
     *
1705
     * @return int
1706
     */
1707
    public function getNumAssertions()
1708
    {
1709
        return $this->numAssertions;
1710
    }
1711
1712
    /**
1713
     * Returns a matcher that matches when the method is executed
1714
     * zero or more times.
1715
     *
1716
     * @return PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount
1717
     */
1718
    public static function any()
1719
    {
1720
        return new PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount;
1721
    }
1722
1723
    /**
1724
     * Returns a matcher that matches when the method is never executed.
1725
     *
1726
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount
1727
     */
1728
    public static function never()
1729
    {
1730
        return new PHPUnit_Framework_MockObject_Matcher_InvokedCount(0);
1731
    }
1732
1733
    /**
1734
     * Returns a matcher that matches when the method is executed
1735
     * at least N times.
1736
     *
1737
     * @param int $requiredInvocations
1738
     *
1739
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastCount
1740
     */
1741
    public static function atLeast($requiredInvocations)
1742
    {
1743
        return new PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastCount(
1744
            $requiredInvocations
1745
        );
1746
    }
1747
1748
    /**
1749
     * Returns a matcher that matches when the method is executed at least once.
1750
     *
1751
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce
1752
     */
1753
    public static function atLeastOnce()
1754
    {
1755
        return new PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce;
1756
    }
1757
1758
    /**
1759
     * Returns a matcher that matches when the method is executed exactly once.
1760
     *
1761
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount
1762
     */
1763
    public static function once()
1764
    {
1765
        return new PHPUnit_Framework_MockObject_Matcher_InvokedCount(1);
1766
    }
1767
1768
    /**
1769
     * Returns a matcher that matches when the method is executed
1770
     * exactly $count times.
1771
     *
1772
     * @param int $count
1773
     *
1774
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount
1775
     */
1776
    public static function exactly($count)
1777
    {
1778
        return new PHPUnit_Framework_MockObject_Matcher_InvokedCount($count);
1779
    }
1780
1781
    /**
1782
     * Returns a matcher that matches when the method is executed
1783
     * at most N times.
1784
     *
1785
     * @param int $allowedInvocations
1786
     *
1787
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtMostCount
1788
     */
1789
    public static function atMost($allowedInvocations)
1790
    {
1791
        return new PHPUnit_Framework_MockObject_Matcher_InvokedAtMostCount(
1792
            $allowedInvocations
1793
        );
1794
    }
1795
1796
    /**
1797
     * Returns a matcher that matches when the method is executed
1798
     * at the given index.
1799
     *
1800
     * @param int $index
1801
     *
1802
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex
1803
     */
1804
    public static function at($index)
1805
    {
1806
        return new PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex($index);
1807
    }
1808
1809
    /**
1810
     * @param mixed $value
1811
     *
1812
     * @return PHPUnit_Framework_MockObject_Stub_Return
1813
     */
1814
    public static function returnValue($value)
1815
    {
1816
        return new PHPUnit_Framework_MockObject_Stub_Return($value);
1817
    }
1818
1819
    /**
1820
     * @param array $valueMap
1821
     *
1822
     * @return PHPUnit_Framework_MockObject_Stub_ReturnValueMap
1823
     */
1824
    public static function returnValueMap(array $valueMap)
1825
    {
1826
        return new PHPUnit_Framework_MockObject_Stub_ReturnValueMap($valueMap);
1827
    }
1828
1829
    /**
1830
     * @param int $argumentIndex
1831
     *
1832
     * @return PHPUnit_Framework_MockObject_Stub_ReturnArgument
1833
     */
1834
    public static function returnArgument($argumentIndex)
1835
    {
1836
        return new PHPUnit_Framework_MockObject_Stub_ReturnArgument(
1837
            $argumentIndex
1838
        );
1839
    }
1840
1841
    /**
1842
     * @param mixed $callback
1843
     *
1844
     * @return PHPUnit_Framework_MockObject_Stub_ReturnCallback
1845
     */
1846
    public static function returnCallback($callback)
1847
    {
1848
        return new PHPUnit_Framework_MockObject_Stub_ReturnCallback($callback);
1849
    }
1850
1851
    /**
1852
     * Returns the current object.
1853
     *
1854
     * This method is useful when mocking a fluent interface.
1855
     *
1856
     * @return PHPUnit_Framework_MockObject_Stub_ReturnSelf
1857
     */
1858
    public static function returnSelf()
1859
    {
1860
        return new PHPUnit_Framework_MockObject_Stub_ReturnSelf();
1861
    }
1862
1863
    /**
1864
     * @param Throwable $exception
1865
     *
1866
     * @return PHPUnit_Framework_MockObject_Stub_Exception
1867
     */
1868
    public static function throwException(Throwable $exception)
1869
    {
1870
        return new PHPUnit_Framework_MockObject_Stub_Exception($exception);
1871
    }
1872
1873
    /**
1874
     * @param mixed $value , ...
1875
     *
1876
     * @return PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls
1877
     */
1878
    public static function onConsecutiveCalls()
1879
    {
1880
        $args = \func_get_args();
1881
1882
        return new PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls($args);
1883
    }
1884
1885
    /**
1886
     * @return bool
1887
     */
1888
    public function usesDataProvider()
1889
    {
1890
        return !empty($this->data);
1891
    }
1892
1893
    /**
1894
     * @return string
1895
     */
1896
    public function dataDescription()
1897
    {
1898
        return \is_string($this->dataName) ? $this->dataName : '';
1899
    }
1900
1901
    /**
1902
     * Gets the data set description of a TestCase.
1903
     *
1904
     * @param bool $includeData
1905
     *
1906
     * @return string
1907
     */
1908
    protected function getDataSetAsString($includeData = true)
1909
    {
1910
        $buffer = '';
1911
1912
        if (!empty($this->data)) {
1913
            if (\is_int($this->dataName)) {
1914
                $buffer .= \sprintf(' with data set #%d', $this->dataName);
1915
            } else {
1916
                $buffer .= \sprintf(' with data set "%s"', $this->dataName);
1917
            }
1918
1919
            $exporter = new Exporter;
1920
1921
            if ($includeData) {
1922
                $buffer .= \sprintf(' (%s)', $exporter->shortenedRecursiveExport($this->data));
1923
            }
1924
        }
1925
1926
        return $buffer;
1927
    }
1928
1929
    /**
1930
     * Gets the data set of a TestCase.
1931
     *
1932
     * @return array
1933
     */
1934
    protected function getProvidedData()
1935
    {
1936
        return $this->data;
1937
    }
1938
1939
    /**
1940
     * Creates a default TestResult object.
1941
     *
1942
     * @return TestResult
1943
     */
1944
    protected function createResult()
1945
    {
1946
        return new TestResult;
1947
    }
1948
1949
    protected function handleDependencies()
1950
    {
1951
        if (!empty($this->dependencies) && !$this->inIsolation) {
1952
            $className  = \get_class($this);
1953
            $passed     = $this->result->passed();
1954
            $passedKeys = \array_keys($passed);
1955
            $numKeys    = \count($passedKeys);
1956
1957
            for ($i = 0; $i < $numKeys; $i++) {
1958
                $pos = \strpos($passedKeys[$i], ' with data set');
1959
1960
                if ($pos !== false) {
1961
                    $passedKeys[$i] = \substr($passedKeys[$i], 0, $pos);
1962
                }
1963
            }
1964
1965
            $passedKeys = \array_flip(\array_unique($passedKeys));
1966
1967
            foreach ($this->dependencies as $dependency) {
1968
                $clone = false;
1969
1970
                if (\strpos($dependency, 'clone ') === 0) {
1971
                    $clone      = true;
1972
                    $dependency = \substr($dependency, \strlen('clone '));
1973
                } elseif (\strpos($dependency, '!clone ') === 0) {
1974
                    $clone      = false;
1975
                    $dependency = \substr($dependency, \strlen('!clone '));
1976
                }
1977
1978
                if (\strpos($dependency, '::') === false) {
1979
                    $dependency = $className . '::' . $dependency;
1980
                }
1981
1982
                if (!isset($passedKeys[$dependency])) {
1983
                    $this->result->startTest($this);
1984
                    $this->result->addError(
1985
                        $this,
1986
                        new SkippedTestError(
1987
                            \sprintf(
1988
                                'This test depends on "%s" to pass.',
1989
                                $dependency
1990
                            )
1991
                        ),
1992
                        0
1993
                    );
1994
                    $this->result->endTest($this, 0);
1995
1996
                    return false;
1997
                }
1998
1999
                if (isset($passed[$dependency])) {
2000
                    if ($passed[$dependency]['size'] != \PHPUnit\Util\Test::UNKNOWN &&
2001
                        $this->getSize() != \PHPUnit\Util\Test::UNKNOWN &&
2002
                        $passed[$dependency]['size'] > $this->getSize()) {
2003
                        $this->result->addError(
2004
                            $this,
2005
                            new SkippedTestError(
2006
                                'This test depends on a test that is larger than itself.'
2007
                            ),
2008
                            0
2009
                        );
2010
2011
                        return false;
2012
                    }
2013
2014
                    if ($clone) {
2015
                        $deepCopy = new DeepCopy;
2016
                        $deepCopy->skipUncloneable(false);
2017
2018
                        $this->dependencyInput[$dependency] = $deepCopy->copy($passed[$dependency]['result']);
2019
                    } else {
2020
                        $this->dependencyInput[$dependency] = $passed[$dependency]['result'];
2021
                    }
2022
                } else {
2023
                    $this->dependencyInput[$dependency] = null;
2024
                }
2025
            }
2026
        }
2027
2028
        return true;
2029
    }
2030
2031
    /**
2032
     * This method is called before the first test of this test class is run.
2033
     */
2034
    public static function setUpBeforeClass()
2035
    {
2036
    }
2037
2038
    /**
2039
     * Sets up the fixture, for example, open a network connection.
2040
     * This method is called before a test is executed.
2041
     */
2042
    protected function setUp()
2043
    {
2044
    }
2045
2046
    /**
2047
     * Performs assertions shared by all tests of a test case.
2048
     *
2049
     * This method is called before the execution of a test starts
2050
     * and after setUp() is called.
2051
     */
2052
    protected function assertPreConditions()
2053
    {
2054
    }
2055
2056
    /**
2057
     * Performs assertions shared by all tests of a test case.
2058
     *
2059
     * This method is called before the execution of a test ends
2060
     * and before tearDown() is called.
2061
     */
2062
    protected function assertPostConditions()
2063
    {
2064
    }
2065
2066
    /**
2067
     * Tears down the fixture, for example, close a network connection.
2068
     * This method is called after a test is executed.
2069
     */
2070
    protected function tearDown()
2071
    {
2072
    }
2073
2074
    /**
2075
     * This method is called after the last test of this test class is run.
2076
     */
2077
    public static function tearDownAfterClass()
2078
    {
2079
    }
2080
2081
    /**
2082
     * This method is called when a test method did not execute successfully.
2083
     *
2084
     * @param Throwable $t
2085
     *
2086
     * @throws Throwable
2087
     */
2088
    protected function onNotSuccessfulTest(Throwable $t)
2089
    {
2090
        throw $t;
2091
    }
2092
2093
    /**
2094
     * Performs custom preparations on the process isolation template.
2095
     *
2096
     * @param Text_Template $template
2097
     */
2098
    protected function prepareTemplate(Text_Template $template)
2099
    {
2100
    }
2101
2102
    /**
2103
     * Get the mock object generator, creating it if it doesn't exist.
2104
     *
2105
     * @return PHPUnit_Framework_MockObject_Generator
2106
     */
2107
    private function getMockObjectGenerator()
2108
    {
2109
        if (null === $this->mockObjectGenerator) {
2110
            $this->mockObjectGenerator = new PHPUnit_Framework_MockObject_Generator;
2111
        }
2112
2113
        return $this->mockObjectGenerator;
2114
    }
2115
2116
    private function startOutputBuffering()
2117
    {
2118
        \ob_start();
2119
2120
        $this->outputBufferingActive = true;
2121
        $this->outputBufferingLevel  = \ob_get_level();
2122
    }
2123
2124
    private function stopOutputBuffering()
2125
    {
2126
        if (\ob_get_level() != $this->outputBufferingLevel) {
2127
            while (\ob_get_level() >= $this->outputBufferingLevel) {
2128
                \ob_end_clean();
2129
            }
2130
2131
            throw new RiskyTestError(
2132
                'Test code or tested code did not (only) close its own output buffers'
2133
            );
2134
        }
2135
2136
        $output = \ob_get_contents();
2137
2138
        if ($this->outputCallback === false) {
2139
            $this->output = $output;
2140
        } else {
2141
            $this->output = \call_user_func_array(
2142
                $this->outputCallback,
2143
                [$output]
2144
            );
2145
        }
2146
2147
        \ob_end_clean();
2148
2149
        $this->outputBufferingActive = false;
2150
        $this->outputBufferingLevel  = \ob_get_level();
2151
    }
2152
2153
    private function snapshotGlobalState()
2154
    {
2155
        if ($this->runTestInSeparateProcess ||
2156
            $this->inIsolation ||
2157
            (!$this->backupGlobals === true && !$this->backupStaticAttributes)) {
2158
            return;
2159
        }
2160
2161
        $this->snapshot = $this->createGlobalStateSnapshot($this->backupGlobals === true);
2162
    }
2163
2164
    private function restoreGlobalState()
2165
    {
2166
        if (!$this->snapshot instanceof Snapshot) {
2167
            return;
2168
        }
2169
2170
        if ($this->beStrictAboutChangesToGlobalState) {
2171
            try {
2172
                $this->compareGlobalStateSnapshots(
2173
                    $this->snapshot,
2174
                    $this->createGlobalStateSnapshot($this->backupGlobals === true)
2175
                );
2176
            } catch (RiskyTestError $rte) {
2177
                // Intentionally left empty
2178
            }
2179
        }
2180
2181
        $restorer = new Restorer;
2182
2183
        if ($this->backupGlobals === true) {
2184
            $restorer->restoreGlobalVariables($this->snapshot);
2185
        }
2186
2187
        if ($this->backupStaticAttributes) {
2188
            $restorer->restoreStaticAttributes($this->snapshot);
2189
        }
2190
2191
        $this->snapshot = null;
2192
2193
        if (isset($rte)) {
2194
            throw $rte;
2195
        }
2196
    }
2197
2198
    /**
2199
     * @param bool $backupGlobals
2200
     *
2201
     * @return Snapshot
2202
     */
2203
    private function createGlobalStateSnapshot($backupGlobals)
2204
    {
2205
        $blacklist = new Blacklist;
2206
2207
        foreach ($this->backupGlobalsBlacklist as $globalVariable) {
2208
            $blacklist->addGlobalVariable($globalVariable);
2209
        }
2210
2211
        if (!\defined('PHPUNIT_TESTSUITE')) {
2212
            $blacklist->addClassNamePrefix('PHPUnit');
2213
            $blacklist->addClassNamePrefix('File_Iterator');
2214
            $blacklist->addClassNamePrefix('SebastianBergmann\CodeCoverage');
2215
            $blacklist->addClassNamePrefix('PHP_Invoker');
2216
            $blacklist->addClassNamePrefix('PHP_Timer');
2217
            $blacklist->addClassNamePrefix('PHP_Token');
2218
            $blacklist->addClassNamePrefix('Symfony');
2219
            $blacklist->addClassNamePrefix('Text_Template');
2220
            $blacklist->addClassNamePrefix('Doctrine\Instantiator');
2221
            $blacklist->addClassNamePrefix('Prophecy');
2222
2223
            foreach ($this->backupStaticAttributesBlacklist as $class => $attributes) {
2224
                foreach ($attributes as $attribute) {
2225
                    $blacklist->addStaticAttribute($class, $attribute);
2226
                }
2227
            }
2228
        }
2229
2230
        return new Snapshot(
2231
            $blacklist,
2232
            $backupGlobals,
2233
            (bool) $this->backupStaticAttributes,
2234
            false,
2235
            false,
2236
            false,
2237
            false,
2238
            false,
2239
            false,
2240
            false
2241
        );
2242
    }
2243
2244
    /**
2245
     * @param Snapshot $before
2246
     * @param Snapshot $after
2247
     *
2248
     * @throws RiskyTestError
2249
     */
2250
    private function compareGlobalStateSnapshots(Snapshot $before, Snapshot $after)
2251
    {
2252
        $backupGlobals = $this->backupGlobals === null || $this->backupGlobals === true;
2253
2254
        if ($backupGlobals) {
2255
            $this->compareGlobalStateSnapshotPart(
2256
                $before->globalVariables(),
2257
                $after->globalVariables(),
2258
                "--- Global variables before the test\n+++ Global variables after the test\n"
2259
            );
2260
2261
            $this->compareGlobalStateSnapshotPart(
2262
                $before->superGlobalVariables(),
2263
                $after->superGlobalVariables(),
2264
                "--- Super-global variables before the test\n+++ Super-global variables after the test\n"
2265
            );
2266
        }
2267
2268
        if ($this->backupStaticAttributes) {
2269
            $this->compareGlobalStateSnapshotPart(
2270
                $before->staticAttributes(),
2271
                $after->staticAttributes(),
2272
                "--- Static attributes before the test\n+++ Static attributes after the test\n"
2273
            );
2274
        }
2275
    }
2276
2277
    /**
2278
     * @param array  $before
2279
     * @param array  $after
2280
     * @param string $header
2281
     *
2282
     * @throws RiskyTestError
2283
     */
2284
    private function compareGlobalStateSnapshotPart(array $before, array $after, $header)
2285
    {
2286
        if ($before != $after) {
2287
            $differ   = new Differ($header);
2288
            $exporter = new Exporter;
2289
2290
            $diff = $differ->diff(
2291
                $exporter->export($before),
2292
                $exporter->export($after)
2293
            );
2294
2295
            throw new RiskyTestError(
2296
                $diff
2297
            );
2298
        }
2299
    }
2300
2301
    /**
2302
     * @return Prophecy\Prophet
2303
     */
2304
    private function getProphet()
2305
    {
2306
        if ($this->prophet === null) {
2307
            $this->prophet = new Prophet;
2308
        }
2309
2310
        return $this->prophet;
2311
    }
2312
2313
    /**
2314
     * @param PHPUnit_Framework_MockObject_MockObject $mock
2315
     *
2316
     * @return bool
2317
     */
2318
    private function shouldInvocationMockerBeReset(PHPUnit_Framework_MockObject_MockObject $mock)
2319
    {
2320
        $enumerator = new Enumerator;
2321
2322
        foreach ($enumerator->enumerate($this->dependencyInput) as $object) {
2323
            if ($mock === $object) {
2324
                return false;
2325
            }
2326
        }
2327
2328
        if (!\is_array($this->testResult) && !\is_object($this->testResult)) {
2329
            return true;
2330
        }
2331
2332
        foreach ($enumerator->enumerate($this->testResult) as $object) {
2333
            if ($mock === $object) {
2334
                return false;
2335
            }
2336
        }
2337
2338
        return true;
2339
    }
2340
2341
    /**
2342
     * @param array $testArguments
2343
     * @param array $originalTestArguments
2344
     */
2345
    private function registerMockObjectsFromTestArguments(array $testArguments, array &$visited = [])
2346
    {
2347
        if ($this->registerMockObjectsFromTestArgumentsRecursively) {
2348
            $enumerator = new Enumerator;
2349
2350
            foreach ($enumerator->enumerate($testArguments) as $object) {
2351
                if ($object instanceof PHPUnit_Framework_MockObject_MockObject) {
2352
                    $this->registerMockObject($object);
2353
                }
2354
            }
2355
        } else {
2356
            foreach ($testArguments as $testArgument) {
2357
                if ($testArgument instanceof PHPUnit_Framework_MockObject_MockObject) {
2358
                    if ($this->isCloneable($testArgument)) {
2359
                        $testArgument = clone $testArgument;
2360
                    }
2361
2362
                    $this->registerMockObject($testArgument);
2363
                } elseif (\is_array($testArgument) && !\in_array($testArgument, $visited, true)) {
2364
                    $visited[] = $testArgument;
2365
2366
                    $this->registerMockObjectsFromTestArguments(
2367
                        $testArgument,
2368
                        $visited
2369
                    );
2370
                }
2371
            }
2372
        }
2373
    }
2374
2375
    private function setDoesNotPerformAssertionsFromAnnotation()
2376
    {
2377
        $annotations = $this->getAnnotations();
2378
2379
        if (isset($annotations['method']['doesNotPerformAssertions'])) {
2380
            $this->doesNotPerformAssertions = true;
2381
        }
2382
    }
2383
2384
    /**
2385
     * @param PHPUnit_Framework_MockObject_MockObject $testArgument
2386
     *
2387
     * @return bool
2388
     */
2389
    private function isCloneable(PHPUnit_Framework_MockObject_MockObject $testArgument)
2390
    {
2391
        $reflector = new ReflectionObject($testArgument);
2392
2393
        if (!$reflector->isCloneable()) {
2394
            return false;
2395
        }
2396
2397
        if ($reflector->hasMethod('__clone') &&
2398
            $reflector->getMethod('__clone')->isPublic()) {
2399
            return true;
2400
        }
2401
2402
        return false;
2403
    }
2404
}
2405