Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 621 | Zur aktuellen Revision | Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php declare(strict_types=1);
2
/*
3
 * This file is part of PHPUnit.
4
 *
5
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace PHPUnit\Framework;
11
 
12
use const DEBUG_BACKTRACE_IGNORE_ARGS;
13
use const PHP_EOL;
14
use function array_shift;
15
use function array_unshift;
16
use function assert;
17
use function class_exists;
18
use function count;
19
use function debug_backtrace;
20
use function explode;
21
use function file_get_contents;
22
use function func_get_args;
23
use function implode;
24
use function interface_exists;
25
use function is_array;
26
use function is_bool;
27
use function is_int;
28
use function is_iterable;
29
use function is_object;
30
use function is_string;
31
use function preg_match;
32
use function preg_split;
33
use function sprintf;
34
use function strpos;
35
use ArrayAccess;
36
use Countable;
37
use DOMAttr;
38
use DOMDocument;
39
use DOMElement;
40
use PHPUnit\Framework\Constraint\ArrayHasKey;
41
use PHPUnit\Framework\Constraint\Callback;
42
use PHPUnit\Framework\Constraint\ClassHasAttribute;
43
use PHPUnit\Framework\Constraint\ClassHasStaticAttribute;
44
use PHPUnit\Framework\Constraint\Constraint;
45
use PHPUnit\Framework\Constraint\Count;
46
use PHPUnit\Framework\Constraint\DirectoryExists;
47
use PHPUnit\Framework\Constraint\FileExists;
48
use PHPUnit\Framework\Constraint\GreaterThan;
49
use PHPUnit\Framework\Constraint\IsAnything;
50
use PHPUnit\Framework\Constraint\IsEmpty;
51
use PHPUnit\Framework\Constraint\IsEqual;
52
use PHPUnit\Framework\Constraint\IsEqualCanonicalizing;
53
use PHPUnit\Framework\Constraint\IsEqualIgnoringCase;
54
use PHPUnit\Framework\Constraint\IsEqualWithDelta;
55
use PHPUnit\Framework\Constraint\IsFalse;
56
use PHPUnit\Framework\Constraint\IsFinite;
57
use PHPUnit\Framework\Constraint\IsIdentical;
58
use PHPUnit\Framework\Constraint\IsInfinite;
59
use PHPUnit\Framework\Constraint\IsInstanceOf;
60
use PHPUnit\Framework\Constraint\IsJson;
61
use PHPUnit\Framework\Constraint\IsNan;
62
use PHPUnit\Framework\Constraint\IsNull;
63
use PHPUnit\Framework\Constraint\IsReadable;
64
use PHPUnit\Framework\Constraint\IsTrue;
65
use PHPUnit\Framework\Constraint\IsType;
66
use PHPUnit\Framework\Constraint\IsWritable;
67
use PHPUnit\Framework\Constraint\JsonMatches;
68
use PHPUnit\Framework\Constraint\LessThan;
69
use PHPUnit\Framework\Constraint\LogicalAnd;
70
use PHPUnit\Framework\Constraint\LogicalNot;
71
use PHPUnit\Framework\Constraint\LogicalOr;
72
use PHPUnit\Framework\Constraint\LogicalXor;
73
use PHPUnit\Framework\Constraint\ObjectEquals;
74
use PHPUnit\Framework\Constraint\ObjectHasAttribute;
75
use PHPUnit\Framework\Constraint\RegularExpression;
76
use PHPUnit\Framework\Constraint\SameSize;
77
use PHPUnit\Framework\Constraint\StringContains;
78
use PHPUnit\Framework\Constraint\StringEndsWith;
79
use PHPUnit\Framework\Constraint\StringMatchesFormatDescription;
80
use PHPUnit\Framework\Constraint\StringStartsWith;
81
use PHPUnit\Framework\Constraint\TraversableContainsEqual;
82
use PHPUnit\Framework\Constraint\TraversableContainsIdentical;
83
use PHPUnit\Framework\Constraint\TraversableContainsOnly;
84
use PHPUnit\Util\Type;
85
use PHPUnit\Util\Xml;
86
use PHPUnit\Util\Xml\Loader as XmlLoader;
87
 
88
/**
89
 * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
90
 */
91
abstract class Assert
92
{
93
    /**
94
     * @var int
95
     */
96
    private static $count = 0;
97
 
98
    /**
99
     * Asserts that an array has a specified key.
100
     *
101
     * @param int|string        $key
102
     * @param array|ArrayAccess $array
103
     *
104
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
105
     * @throws Exception
106
     * @throws ExpectationFailedException
107
     */
108
    public static function assertArrayHasKey($key, $array, string $message = ''): void
109
    {
110
        if (!(is_int($key) || is_string($key))) {
111
            throw InvalidArgumentException::create(
112
                1,
113
                'integer or string'
114
            );
115
        }
116
 
117
        if (!(is_array($array) || $array instanceof ArrayAccess)) {
118
            throw InvalidArgumentException::create(
119
                2,
120
                'array or ArrayAccess'
121
            );
122
        }
123
 
124
        $constraint = new ArrayHasKey($key);
125
 
126
        static::assertThat($array, $constraint, $message);
127
    }
128
 
129
    /**
130
     * Asserts that an array does not have a specified key.
131
     *
132
     * @param int|string        $key
133
     * @param array|ArrayAccess $array
134
     *
135
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
136
     * @throws Exception
137
     * @throws ExpectationFailedException
138
     */
139
    public static function assertArrayNotHasKey($key, $array, string $message = ''): void
140
    {
141
        if (!(is_int($key) || is_string($key))) {
142
            throw InvalidArgumentException::create(
143
                1,
144
                'integer or string'
145
            );
146
        }
147
 
148
        if (!(is_array($array) || $array instanceof ArrayAccess)) {
149
            throw InvalidArgumentException::create(
150
                2,
151
                'array or ArrayAccess'
152
            );
153
        }
154
 
155
        $constraint = new LogicalNot(
156
            new ArrayHasKey($key)
157
        );
158
 
159
        static::assertThat($array, $constraint, $message);
160
    }
161
 
162
    /**
163
     * Asserts that a haystack contains a needle.
164
     *
165
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
166
     * @throws Exception
167
     * @throws ExpectationFailedException
168
     */
169
    public static function assertContains($needle, iterable $haystack, string $message = ''): void
170
    {
171
        $constraint = new TraversableContainsIdentical($needle);
172
 
173
        static::assertThat($haystack, $constraint, $message);
174
    }
175
 
176
    public static function assertContainsEquals($needle, iterable $haystack, string $message = ''): void
177
    {
178
        $constraint = new TraversableContainsEqual($needle);
179
 
180
        static::assertThat($haystack, $constraint, $message);
181
    }
182
 
183
    /**
184
     * Asserts that a haystack does not contain a needle.
185
     *
186
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
187
     * @throws Exception
188
     * @throws ExpectationFailedException
189
     */
190
    public static function assertNotContains($needle, iterable $haystack, string $message = ''): void
191
    {
192
        $constraint = new LogicalNot(
193
            new TraversableContainsIdentical($needle)
194
        );
195
 
196
        static::assertThat($haystack, $constraint, $message);
197
    }
198
 
199
    public static function assertNotContainsEquals($needle, iterable $haystack, string $message = ''): void
200
    {
201
        $constraint = new LogicalNot(new TraversableContainsEqual($needle));
202
 
203
        static::assertThat($haystack, $constraint, $message);
204
    }
205
 
206
    /**
207
     * Asserts that a haystack contains only values of a given type.
208
     *
209
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
210
     * @throws ExpectationFailedException
211
     */
212
    public static function assertContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void
213
    {
214
        if ($isNativeType === null) {
215
            $isNativeType = Type::isType($type);
216
        }
217
 
218
        static::assertThat(
219
            $haystack,
220
            new TraversableContainsOnly(
221
                $type,
222
                $isNativeType
223
            ),
224
            $message
225
        );
226
    }
227
 
228
    /**
229
     * Asserts that a haystack contains only instances of a given class name.
230
     *
231
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
232
     * @throws ExpectationFailedException
233
     */
234
    public static function assertContainsOnlyInstancesOf(string $className, iterable $haystack, string $message = ''): void
235
    {
236
        static::assertThat(
237
            $haystack,
238
            new TraversableContainsOnly(
239
                $className,
240
                false
241
            ),
242
            $message
243
        );
244
    }
245
 
246
    /**
247
     * Asserts that a haystack does not contain only values of a given type.
248
     *
249
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
250
     * @throws ExpectationFailedException
251
     */
252
    public static function assertNotContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void
253
    {
254
        if ($isNativeType === null) {
255
            $isNativeType = Type::isType($type);
256
        }
257
 
258
        static::assertThat(
259
            $haystack,
260
            new LogicalNot(
261
                new TraversableContainsOnly(
262
                    $type,
263
                    $isNativeType
264
                )
265
            ),
266
            $message
267
        );
268
    }
269
 
270
    /**
271
     * Asserts the number of elements of an array, Countable or Traversable.
272
     *
273
     * @param Countable|iterable $haystack
274
     *
275
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
276
     * @throws Exception
277
     * @throws ExpectationFailedException
278
     */
279
    public static function assertCount(int $expectedCount, $haystack, string $message = ''): void
280
    {
281
        if (!$haystack instanceof Countable && !is_iterable($haystack)) {
282
            throw InvalidArgumentException::create(2, 'countable or iterable');
283
        }
284
 
285
        static::assertThat(
286
            $haystack,
287
            new Count($expectedCount),
288
            $message
289
        );
290
    }
291
 
292
    /**
293
     * Asserts the number of elements of an array, Countable or Traversable.
294
     *
295
     * @param Countable|iterable $haystack
296
     *
297
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
298
     * @throws Exception
299
     * @throws ExpectationFailedException
300
     */
301
    public static function assertNotCount(int $expectedCount, $haystack, string $message = ''): void
302
    {
303
        if (!$haystack instanceof Countable && !is_iterable($haystack)) {
304
            throw InvalidArgumentException::create(2, 'countable or iterable');
305
        }
306
 
307
        $constraint = new LogicalNot(
308
            new Count($expectedCount)
309
        );
310
 
311
        static::assertThat($haystack, $constraint, $message);
312
    }
313
 
314
    /**
315
     * Asserts that two variables are equal.
316
     *
317
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
318
     * @throws ExpectationFailedException
319
     */
320
    public static function assertEquals($expected, $actual, string $message = ''): void
321
    {
322
        $constraint = new IsEqual($expected);
323
 
324
        static::assertThat($actual, $constraint, $message);
325
    }
326
 
327
    /**
328
     * Asserts that two variables are equal (canonicalizing).
329
     *
330
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
331
     * @throws ExpectationFailedException
332
     */
333
    public static function assertEqualsCanonicalizing($expected, $actual, string $message = ''): void
334
    {
335
        $constraint = new IsEqualCanonicalizing($expected);
336
 
337
        static::assertThat($actual, $constraint, $message);
338
    }
339
 
340
    /**
341
     * Asserts that two variables are equal (ignoring case).
342
     *
343
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
344
     * @throws ExpectationFailedException
345
     */
346
    public static function assertEqualsIgnoringCase($expected, $actual, string $message = ''): void
347
    {
348
        $constraint = new IsEqualIgnoringCase($expected);
349
 
350
        static::assertThat($actual, $constraint, $message);
351
    }
352
 
353
    /**
354
     * Asserts that two variables are equal (with delta).
355
     *
356
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
357
     * @throws ExpectationFailedException
358
     */
359
    public static function assertEqualsWithDelta($expected, $actual, float $delta, string $message = ''): void
360
    {
361
        $constraint = new IsEqualWithDelta(
362
            $expected,
363
            $delta
364
        );
365
 
366
        static::assertThat($actual, $constraint, $message);
367
    }
368
 
369
    /**
370
     * Asserts that two variables are not equal.
371
     *
372
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
373
     * @throws ExpectationFailedException
374
     */
375
    public static function assertNotEquals($expected, $actual, string $message = ''): void
376
    {
377
        $constraint = new LogicalNot(
378
            new IsEqual($expected)
379
        );
380
 
381
        static::assertThat($actual, $constraint, $message);
382
    }
383
 
384
    /**
385
     * Asserts that two variables are not equal (canonicalizing).
386
     *
387
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
388
     * @throws ExpectationFailedException
389
     */
390
    public static function assertNotEqualsCanonicalizing($expected, $actual, string $message = ''): void
391
    {
392
        $constraint = new LogicalNot(
393
            new IsEqualCanonicalizing($expected)
394
        );
395
 
396
        static::assertThat($actual, $constraint, $message);
397
    }
398
 
399
    /**
400
     * Asserts that two variables are not equal (ignoring case).
401
     *
402
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
403
     * @throws ExpectationFailedException
404
     */
405
    public static function assertNotEqualsIgnoringCase($expected, $actual, string $message = ''): void
406
    {
407
        $constraint = new LogicalNot(
408
            new IsEqualIgnoringCase($expected)
409
        );
410
 
411
        static::assertThat($actual, $constraint, $message);
412
    }
413
 
414
    /**
415
     * Asserts that two variables are not equal (with delta).
416
     *
417
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
418
     * @throws ExpectationFailedException
419
     */
420
    public static function assertNotEqualsWithDelta($expected, $actual, float $delta, string $message = ''): void
421
    {
422
        $constraint = new LogicalNot(
423
            new IsEqualWithDelta(
424
                $expected,
425
                $delta
426
            )
427
        );
428
 
429
        static::assertThat($actual, $constraint, $message);
430
    }
431
 
432
    /**
433
     * @throws ExpectationFailedException
434
     */
435
    public static function assertObjectEquals(object $expected, object $actual, string $method = 'equals', string $message = ''): void
436
    {
437
        static::assertThat(
438
            $actual,
439
            static::objectEquals($expected, $method),
440
            $message
441
        );
442
    }
443
 
444
    /**
445
     * Asserts that a variable is empty.
446
     *
447
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
448
     * @throws ExpectationFailedException
449
     *
450
     * @psalm-assert empty $actual
451
     */
452
    public static function assertEmpty($actual, string $message = ''): void
453
    {
454
        static::assertThat($actual, static::isEmpty(), $message);
455
    }
456
 
457
    /**
458
     * Asserts that a variable is not empty.
459
     *
460
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
461
     * @throws ExpectationFailedException
462
     *
463
     * @psalm-assert !empty $actual
464
     */
465
    public static function assertNotEmpty($actual, string $message = ''): void
466
    {
467
        static::assertThat($actual, static::logicalNot(static::isEmpty()), $message);
468
    }
469
 
470
    /**
471
     * Asserts that a value is greater than another value.
472
     *
473
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
474
     * @throws ExpectationFailedException
475
     */
476
    public static function assertGreaterThan($expected, $actual, string $message = ''): void
477
    {
478
        static::assertThat($actual, static::greaterThan($expected), $message);
479
    }
480
 
481
    /**
482
     * Asserts that a value is greater than or equal to another value.
483
     *
484
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
485
     * @throws ExpectationFailedException
486
     */
487
    public static function assertGreaterThanOrEqual($expected, $actual, string $message = ''): void
488
    {
489
        static::assertThat(
490
            $actual,
491
            static::greaterThanOrEqual($expected),
492
            $message
493
        );
494
    }
495
 
496
    /**
497
     * Asserts that a value is smaller than another value.
498
     *
499
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
500
     * @throws ExpectationFailedException
501
     */
502
    public static function assertLessThan($expected, $actual, string $message = ''): void
503
    {
504
        static::assertThat($actual, static::lessThan($expected), $message);
505
    }
506
 
507
    /**
508
     * Asserts that a value is smaller than or equal to another value.
509
     *
510
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
511
     * @throws ExpectationFailedException
512
     */
513
    public static function assertLessThanOrEqual($expected, $actual, string $message = ''): void
514
    {
515
        static::assertThat($actual, static::lessThanOrEqual($expected), $message);
516
    }
517
 
518
    /**
519
     * Asserts that the contents of one file is equal to the contents of another
520
     * file.
521
     *
522
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
523
     * @throws ExpectationFailedException
524
     */
525
    public static function assertFileEquals(string $expected, string $actual, string $message = ''): void
526
    {
527
        static::assertFileExists($expected, $message);
528
        static::assertFileExists($actual, $message);
529
 
530
        $constraint = new IsEqual(file_get_contents($expected));
531
 
532
        static::assertThat(file_get_contents($actual), $constraint, $message);
533
    }
534
 
535
    /**
536
     * Asserts that the contents of one file is equal to the contents of another
537
     * file (canonicalizing).
538
     *
539
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
540
     * @throws ExpectationFailedException
541
     */
542
    public static function assertFileEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void
543
    {
544
        static::assertFileExists($expected, $message);
545
        static::assertFileExists($actual, $message);
546
 
547
        $constraint = new IsEqualCanonicalizing(
548
            file_get_contents($expected)
549
        );
550
 
551
        static::assertThat(file_get_contents($actual), $constraint, $message);
552
    }
553
 
554
    /**
555
     * Asserts that the contents of one file is equal to the contents of another
556
     * file (ignoring case).
557
     *
558
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
559
     * @throws ExpectationFailedException
560
     */
561
    public static function assertFileEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void
562
    {
563
        static::assertFileExists($expected, $message);
564
        static::assertFileExists($actual, $message);
565
 
566
        $constraint = new IsEqualIgnoringCase(file_get_contents($expected));
567
 
568
        static::assertThat(file_get_contents($actual), $constraint, $message);
569
    }
570
 
571
    /**
572
     * Asserts that the contents of one file is not equal to the contents of
573
     * another file.
574
     *
575
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
576
     * @throws ExpectationFailedException
577
     */
578
    public static function assertFileNotEquals(string $expected, string $actual, string $message = ''): void
579
    {
580
        static::assertFileExists($expected, $message);
581
        static::assertFileExists($actual, $message);
582
 
583
        $constraint = new LogicalNot(
584
            new IsEqual(file_get_contents($expected))
585
        );
586
 
587
        static::assertThat(file_get_contents($actual), $constraint, $message);
588
    }
589
 
590
    /**
591
     * Asserts that the contents of one file is not equal to the contents of another
592
     * file (canonicalizing).
593
     *
594
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
595
     * @throws ExpectationFailedException
596
     */
597
    public static function assertFileNotEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void
598
    {
599
        static::assertFileExists($expected, $message);
600
        static::assertFileExists($actual, $message);
601
 
602
        $constraint = new LogicalNot(
603
            new IsEqualCanonicalizing(file_get_contents($expected))
604
        );
605
 
606
        static::assertThat(file_get_contents($actual), $constraint, $message);
607
    }
608
 
609
    /**
610
     * Asserts that the contents of one file is not equal to the contents of another
611
     * file (ignoring case).
612
     *
613
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
614
     * @throws ExpectationFailedException
615
     */
616
    public static function assertFileNotEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void
617
    {
618
        static::assertFileExists($expected, $message);
619
        static::assertFileExists($actual, $message);
620
 
621
        $constraint = new LogicalNot(
622
            new IsEqualIgnoringCase(file_get_contents($expected))
623
        );
624
 
625
        static::assertThat(file_get_contents($actual), $constraint, $message);
626
    }
627
 
628
    /**
629
     * Asserts that the contents of a string is equal
630
     * to the contents of a file.
631
     *
632
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
633
     * @throws ExpectationFailedException
634
     */
635
    public static function assertStringEqualsFile(string $expectedFile, string $actualString, string $message = ''): void
636
    {
637
        static::assertFileExists($expectedFile, $message);
638
 
639
        $constraint = new IsEqual(file_get_contents($expectedFile));
640
 
641
        static::assertThat($actualString, $constraint, $message);
642
    }
643
 
644
    /**
645
     * Asserts that the contents of a string is equal
646
     * to the contents of a file (canonicalizing).
647
     *
648
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
649
     * @throws ExpectationFailedException
650
     */
651
    public static function assertStringEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void
652
    {
653
        static::assertFileExists($expectedFile, $message);
654
 
655
        $constraint = new IsEqualCanonicalizing(file_get_contents($expectedFile));
656
 
657
        static::assertThat($actualString, $constraint, $message);
658
    }
659
 
660
    /**
661
     * Asserts that the contents of a string is equal
662
     * to the contents of a file (ignoring case).
663
     *
664
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
665
     * @throws ExpectationFailedException
666
     */
667
    public static function assertStringEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void
668
    {
669
        static::assertFileExists($expectedFile, $message);
670
 
671
        $constraint = new IsEqualIgnoringCase(file_get_contents($expectedFile));
672
 
673
        static::assertThat($actualString, $constraint, $message);
674
    }
675
 
676
    /**
677
     * Asserts that the contents of a string is not equal
678
     * to the contents of a file.
679
     *
680
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
681
     * @throws ExpectationFailedException
682
     */
683
    public static function assertStringNotEqualsFile(string $expectedFile, string $actualString, string $message = ''): void
684
    {
685
        static::assertFileExists($expectedFile, $message);
686
 
687
        $constraint = new LogicalNot(
688
            new IsEqual(file_get_contents($expectedFile))
689
        );
690
 
691
        static::assertThat($actualString, $constraint, $message);
692
    }
693
 
694
    /**
695
     * Asserts that the contents of a string is not equal
696
     * to the contents of a file (canonicalizing).
697
     *
698
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
699
     * @throws ExpectationFailedException
700
     */
701
    public static function assertStringNotEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void
702
    {
703
        static::assertFileExists($expectedFile, $message);
704
 
705
        $constraint = new LogicalNot(
706
            new IsEqualCanonicalizing(file_get_contents($expectedFile))
707
        );
708
 
709
        static::assertThat($actualString, $constraint, $message);
710
    }
711
 
712
    /**
713
     * Asserts that the contents of a string is not equal
714
     * to the contents of a file (ignoring case).
715
     *
716
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
717
     * @throws ExpectationFailedException
718
     */
719
    public static function assertStringNotEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void
720
    {
721
        static::assertFileExists($expectedFile, $message);
722
 
723
        $constraint = new LogicalNot(
724
            new IsEqualIgnoringCase(file_get_contents($expectedFile))
725
        );
726
 
727
        static::assertThat($actualString, $constraint, $message);
728
    }
729
 
730
    /**
731
     * Asserts that a file/dir is readable.
732
     *
733
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
734
     * @throws ExpectationFailedException
735
     */
736
    public static function assertIsReadable(string $filename, string $message = ''): void
737
    {
738
        static::assertThat($filename, new IsReadable, $message);
739
    }
740
 
741
    /**
742
     * Asserts that a file/dir exists and is not readable.
743
     *
744
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
745
     * @throws ExpectationFailedException
746
     */
747
    public static function assertIsNotReadable(string $filename, string $message = ''): void
748
    {
749
        static::assertThat($filename, new LogicalNot(new IsReadable), $message);
750
    }
751
 
752
    /**
753
     * Asserts that a file/dir exists and is not readable.
754
     *
755
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
756
     * @throws ExpectationFailedException
757
     *
758
     * @codeCoverageIgnore
759
     *
760
     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4062
761
     */
762
    public static function assertNotIsReadable(string $filename, string $message = ''): void
763
    {
764
        self::createWarning('assertNotIsReadable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertIsNotReadable() instead.');
765
 
766
        static::assertThat($filename, new LogicalNot(new IsReadable), $message);
767
    }
768
 
769
    /**
770
     * Asserts that a file/dir exists and is writable.
771
     *
772
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
773
     * @throws ExpectationFailedException
774
     */
775
    public static function assertIsWritable(string $filename, string $message = ''): void
776
    {
777
        static::assertThat($filename, new IsWritable, $message);
778
    }
779
 
780
    /**
781
     * Asserts that a file/dir exists and is not writable.
782
     *
783
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
784
     * @throws ExpectationFailedException
785
     */
786
    public static function assertIsNotWritable(string $filename, string $message = ''): void
787
    {
788
        static::assertThat($filename, new LogicalNot(new IsWritable), $message);
789
    }
790
 
791
    /**
792
     * Asserts that a file/dir exists and is not writable.
793
     *
794
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
795
     * @throws ExpectationFailedException
796
     *
797
     * @codeCoverageIgnore
798
     *
799
     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4065
800
     */
801
    public static function assertNotIsWritable(string $filename, string $message = ''): void
802
    {
803
        self::createWarning('assertNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertIsNotWritable() instead.');
804
 
805
        static::assertThat($filename, new LogicalNot(new IsWritable), $message);
806
    }
807
 
808
    /**
809
     * Asserts that a directory exists.
810
     *
811
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
812
     * @throws ExpectationFailedException
813
     */
814
    public static function assertDirectoryExists(string $directory, string $message = ''): void
815
    {
816
        static::assertThat($directory, new DirectoryExists, $message);
817
    }
818
 
819
    /**
820
     * Asserts that a directory does not exist.
821
     *
822
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
823
     * @throws ExpectationFailedException
824
     */
825
    public static function assertDirectoryDoesNotExist(string $directory, string $message = ''): void
826
    {
827
        static::assertThat($directory, new LogicalNot(new DirectoryExists), $message);
828
    }
829
 
830
    /**
831
     * Asserts that a directory does not exist.
832
     *
833
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
834
     * @throws ExpectationFailedException
835
     *
836
     * @codeCoverageIgnore
837
     *
838
     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4068
839
     */
840
    public static function assertDirectoryNotExists(string $directory, string $message = ''): void
841
    {
842
        self::createWarning('assertDirectoryNotExists() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryDoesNotExist() instead.');
843
 
844
        static::assertThat($directory, new LogicalNot(new DirectoryExists), $message);
845
    }
846
 
847
    /**
848
     * Asserts that a directory exists and is readable.
849
     *
850
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
851
     * @throws ExpectationFailedException
852
     */
853
    public static function assertDirectoryIsReadable(string $directory, string $message = ''): void
854
    {
855
        self::assertDirectoryExists($directory, $message);
856
        self::assertIsReadable($directory, $message);
857
    }
858
 
859
    /**
860
     * Asserts that a directory exists and is not readable.
861
     *
862
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
863
     * @throws ExpectationFailedException
864
     */
865
    public static function assertDirectoryIsNotReadable(string $directory, string $message = ''): void
866
    {
867
        self::assertDirectoryExists($directory, $message);
868
        self::assertIsNotReadable($directory, $message);
869
    }
870
 
871
    /**
872
     * Asserts that a directory exists and is not readable.
873
     *
874
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
875
     * @throws ExpectationFailedException
876
     *
877
     * @codeCoverageIgnore
878
     *
879
     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4071
880
     */
881
    public static function assertDirectoryNotIsReadable(string $directory, string $message = ''): void
882
    {
883
        self::createWarning('assertDirectoryNotIsReadable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryIsNotReadable() instead.');
884
 
885
        self::assertDirectoryExists($directory, $message);
886
        self::assertIsNotReadable($directory, $message);
887
    }
888
 
889
    /**
890
     * Asserts that a directory exists and is writable.
891
     *
892
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
893
     * @throws ExpectationFailedException
894
     */
895
    public static function assertDirectoryIsWritable(string $directory, string $message = ''): void
896
    {
897
        self::assertDirectoryExists($directory, $message);
898
        self::assertIsWritable($directory, $message);
899
    }
900
 
901
    /**
902
     * Asserts that a directory exists and is not writable.
903
     *
904
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
905
     * @throws ExpectationFailedException
906
     */
907
    public static function assertDirectoryIsNotWritable(string $directory, string $message = ''): void
908
    {
909
        self::assertDirectoryExists($directory, $message);
910
        self::assertIsNotWritable($directory, $message);
911
    }
912
 
913
    /**
914
     * Asserts that a directory exists and is not writable.
915
     *
916
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
917
     * @throws ExpectationFailedException
918
     *
919
     * @codeCoverageIgnore
920
     *
921
     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4074
922
     */
923
    public static function assertDirectoryNotIsWritable(string $directory, string $message = ''): void
924
    {
925
        self::createWarning('assertDirectoryNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryIsNotWritable() instead.');
926
 
927
        self::assertDirectoryExists($directory, $message);
928
        self::assertIsNotWritable($directory, $message);
929
    }
930
 
931
    /**
932
     * Asserts that a file exists.
933
     *
934
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
935
     * @throws ExpectationFailedException
936
     */
937
    public static function assertFileExists(string $filename, string $message = ''): void
938
    {
939
        static::assertThat($filename, new FileExists, $message);
940
    }
941
 
942
    /**
943
     * Asserts that a file does not exist.
944
     *
945
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
946
     * @throws ExpectationFailedException
947
     */
948
    public static function assertFileDoesNotExist(string $filename, string $message = ''): void
949
    {
950
        static::assertThat($filename, new LogicalNot(new FileExists), $message);
951
    }
952
 
953
    /**
954
     * Asserts that a file does not exist.
955
     *
956
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
957
     * @throws ExpectationFailedException
958
     *
959
     * @codeCoverageIgnore
960
     *
961
     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4077
962
     */
963
    public static function assertFileNotExists(string $filename, string $message = ''): void
964
    {
965
        self::createWarning('assertFileNotExists() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileDoesNotExist() instead.');
966
 
967
        static::assertThat($filename, new LogicalNot(new FileExists), $message);
968
    }
969
 
970
    /**
971
     * Asserts that a file exists and is readable.
972
     *
973
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
974
     * @throws ExpectationFailedException
975
     */
976
    public static function assertFileIsReadable(string $file, string $message = ''): void
977
    {
978
        self::assertFileExists($file, $message);
979
        self::assertIsReadable($file, $message);
980
    }
981
 
982
    /**
983
     * Asserts that a file exists and is not readable.
984
     *
985
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
986
     * @throws ExpectationFailedException
987
     */
988
    public static function assertFileIsNotReadable(string $file, string $message = ''): void
989
    {
990
        self::assertFileExists($file, $message);
991
        self::assertIsNotReadable($file, $message);
992
    }
993
 
994
    /**
995
     * Asserts that a file exists and is not readable.
996
     *
997
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
998
     * @throws ExpectationFailedException
999
     *
1000
     * @codeCoverageIgnore
1001
     *
1002
     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4080
1003
     */
1004
    public static function assertFileNotIsReadable(string $file, string $message = ''): void
1005
    {
1006
        self::createWarning('assertFileNotIsReadable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileIsNotReadable() instead.');
1007
 
1008
        self::assertFileExists($file, $message);
1009
        self::assertIsNotReadable($file, $message);
1010
    }
1011
 
1012
    /**
1013
     * Asserts that a file exists and is writable.
1014
     *
1015
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1016
     * @throws ExpectationFailedException
1017
     */
1018
    public static function assertFileIsWritable(string $file, string $message = ''): void
1019
    {
1020
        self::assertFileExists($file, $message);
1021
        self::assertIsWritable($file, $message);
1022
    }
1023
 
1024
    /**
1025
     * Asserts that a file exists and is not writable.
1026
     *
1027
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1028
     * @throws ExpectationFailedException
1029
     */
1030
    public static function assertFileIsNotWritable(string $file, string $message = ''): void
1031
    {
1032
        self::assertFileExists($file, $message);
1033
        self::assertIsNotWritable($file, $message);
1034
    }
1035
 
1036
    /**
1037
     * Asserts that a file exists and is not writable.
1038
     *
1039
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1040
     * @throws ExpectationFailedException
1041
     *
1042
     * @codeCoverageIgnore
1043
     *
1044
     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4083
1045
     */
1046
    public static function assertFileNotIsWritable(string $file, string $message = ''): void
1047
    {
1048
        self::createWarning('assertFileNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileIsNotWritable() instead.');
1049
 
1050
        self::assertFileExists($file, $message);
1051
        self::assertIsNotWritable($file, $message);
1052
    }
1053
 
1054
    /**
1055
     * Asserts that a condition is true.
1056
     *
1057
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1058
     * @throws ExpectationFailedException
1059
     *
1060
     * @psalm-assert true $condition
1061
     */
1062
    public static function assertTrue($condition, string $message = ''): void
1063
    {
1064
        static::assertThat($condition, static::isTrue(), $message);
1065
    }
1066
 
1067
    /**
1068
     * Asserts that a condition is not true.
1069
     *
1070
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1071
     * @throws ExpectationFailedException
1072
     *
1073
     * @psalm-assert !true $condition
1074
     */
1075
    public static function assertNotTrue($condition, string $message = ''): void
1076
    {
1077
        static::assertThat($condition, static::logicalNot(static::isTrue()), $message);
1078
    }
1079
 
1080
    /**
1081
     * Asserts that a condition is false.
1082
     *
1083
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1084
     * @throws ExpectationFailedException
1085
     *
1086
     * @psalm-assert false $condition
1087
     */
1088
    public static function assertFalse($condition, string $message = ''): void
1089
    {
1090
        static::assertThat($condition, static::isFalse(), $message);
1091
    }
1092
 
1093
    /**
1094
     * Asserts that a condition is not false.
1095
     *
1096
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1097
     * @throws ExpectationFailedException
1098
     *
1099
     * @psalm-assert !false $condition
1100
     */
1101
    public static function assertNotFalse($condition, string $message = ''): void
1102
    {
1103
        static::assertThat($condition, static::logicalNot(static::isFalse()), $message);
1104
    }
1105
 
1106
    /**
1107
     * Asserts that a variable is null.
1108
     *
1109
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1110
     * @throws ExpectationFailedException
1111
     *
1112
     * @psalm-assert null $actual
1113
     */
1114
    public static function assertNull($actual, string $message = ''): void
1115
    {
1116
        static::assertThat($actual, static::isNull(), $message);
1117
    }
1118
 
1119
    /**
1120
     * Asserts that a variable is not null.
1121
     *
1122
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1123
     * @throws ExpectationFailedException
1124
     *
1125
     * @psalm-assert !null $actual
1126
     */
1127
    public static function assertNotNull($actual, string $message = ''): void
1128
    {
1129
        static::assertThat($actual, static::logicalNot(static::isNull()), $message);
1130
    }
1131
 
1132
    /**
1133
     * Asserts that a variable is finite.
1134
     *
1135
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1136
     * @throws ExpectationFailedException
1137
     */
1138
    public static function assertFinite($actual, string $message = ''): void
1139
    {
1140
        static::assertThat($actual, static::isFinite(), $message);
1141
    }
1142
 
1143
    /**
1144
     * Asserts that a variable is infinite.
1145
     *
1146
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1147
     * @throws ExpectationFailedException
1148
     */
1149
    public static function assertInfinite($actual, string $message = ''): void
1150
    {
1151
        static::assertThat($actual, static::isInfinite(), $message);
1152
    }
1153
 
1154
    /**
1155
     * Asserts that a variable is nan.
1156
     *
1157
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1158
     * @throws ExpectationFailedException
1159
     */
1160
    public static function assertNan($actual, string $message = ''): void
1161
    {
1162
        static::assertThat($actual, static::isNan(), $message);
1163
    }
1164
 
1165
    /**
1166
     * Asserts that a class has a specified attribute.
1167
     *
1168
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1169
     * @throws Exception
1170
     * @throws ExpectationFailedException
1171
     */
1172
    public static function assertClassHasAttribute(string $attributeName, string $className, string $message = ''): void
1173
    {
1174
        if (!self::isValidClassAttributeName($attributeName)) {
1175
            throw InvalidArgumentException::create(1, 'valid attribute name');
1176
        }
1177
 
1178
        if (!class_exists($className)) {
1179
            throw InvalidArgumentException::create(2, 'class name');
1180
        }
1181
 
1182
        static::assertThat($className, new ClassHasAttribute($attributeName), $message);
1183
    }
1184
 
1185
    /**
1186
     * Asserts that a class does not have a specified attribute.
1187
     *
1188
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1189
     * @throws Exception
1190
     * @throws ExpectationFailedException
1191
     */
1192
    public static function assertClassNotHasAttribute(string $attributeName, string $className, string $message = ''): void
1193
    {
1194
        if (!self::isValidClassAttributeName($attributeName)) {
1195
            throw InvalidArgumentException::create(1, 'valid attribute name');
1196
        }
1197
 
1198
        if (!class_exists($className)) {
1199
            throw InvalidArgumentException::create(2, 'class name');
1200
        }
1201
 
1202
        static::assertThat(
1203
            $className,
1204
            new LogicalNot(
1205
                new ClassHasAttribute($attributeName)
1206
            ),
1207
            $message
1208
        );
1209
    }
1210
 
1211
    /**
1212
     * Asserts that a class has a specified static attribute.
1213
     *
1214
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1215
     * @throws Exception
1216
     * @throws ExpectationFailedException
1217
     */
1218
    public static function assertClassHasStaticAttribute(string $attributeName, string $className, string $message = ''): void
1219
    {
1220
        if (!self::isValidClassAttributeName($attributeName)) {
1221
            throw InvalidArgumentException::create(1, 'valid attribute name');
1222
        }
1223
 
1224
        if (!class_exists($className)) {
1225
            throw InvalidArgumentException::create(2, 'class name');
1226
        }
1227
 
1228
        static::assertThat(
1229
            $className,
1230
            new ClassHasStaticAttribute($attributeName),
1231
            $message
1232
        );
1233
    }
1234
 
1235
    /**
1236
     * Asserts that a class does not have a specified static attribute.
1237
     *
1238
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1239
     * @throws Exception
1240
     * @throws ExpectationFailedException
1241
     */
1242
    public static function assertClassNotHasStaticAttribute(string $attributeName, string $className, string $message = ''): void
1243
    {
1244
        if (!self::isValidClassAttributeName($attributeName)) {
1245
            throw InvalidArgumentException::create(1, 'valid attribute name');
1246
        }
1247
 
1248
        if (!class_exists($className)) {
1249
            throw InvalidArgumentException::create(2, 'class name');
1250
        }
1251
 
1252
        static::assertThat(
1253
            $className,
1254
            new LogicalNot(
1255
                new ClassHasStaticAttribute($attributeName)
1256
            ),
1257
            $message
1258
        );
1259
    }
1260
 
1261
    /**
1262
     * Asserts that an object has a specified attribute.
1263
     *
1264
     * @param object $object
1265
     *
1266
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1267
     * @throws Exception
1268
     * @throws ExpectationFailedException
1269
     */
1270
    public static function assertObjectHasAttribute(string $attributeName, $object, string $message = ''): void
1271
    {
1272
        if (!self::isValidObjectAttributeName($attributeName)) {
1273
            throw InvalidArgumentException::create(1, 'valid attribute name');
1274
        }
1275
 
1276
        if (!is_object($object)) {
1277
            throw InvalidArgumentException::create(2, 'object');
1278
        }
1279
 
1280
        static::assertThat(
1281
            $object,
1282
            new ObjectHasAttribute($attributeName),
1283
            $message
1284
        );
1285
    }
1286
 
1287
    /**
1288
     * Asserts that an object does not have a specified attribute.
1289
     *
1290
     * @param object $object
1291
     *
1292
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1293
     * @throws Exception
1294
     * @throws ExpectationFailedException
1295
     */
1296
    public static function assertObjectNotHasAttribute(string $attributeName, $object, string $message = ''): void
1297
    {
1298
        if (!self::isValidObjectAttributeName($attributeName)) {
1299
            throw InvalidArgumentException::create(1, 'valid attribute name');
1300
        }
1301
 
1302
        if (!is_object($object)) {
1303
            throw InvalidArgumentException::create(2, 'object');
1304
        }
1305
 
1306
        static::assertThat(
1307
            $object,
1308
            new LogicalNot(
1309
                new ObjectHasAttribute($attributeName)
1310
            ),
1311
            $message
1312
        );
1313
    }
1314
 
1315
    /**
1316
     * Asserts that two variables have the same type and value.
1317
     * Used on objects, it asserts that two variables reference
1318
     * the same object.
1319
     *
1320
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1321
     * @throws ExpectationFailedException
1322
     *
1323
     * @psalm-template ExpectedType
1324
     *
1325
     * @psalm-param ExpectedType $expected
1326
     *
1327
     * @psalm-assert =ExpectedType $actual
1328
     */
1329
    public static function assertSame($expected, $actual, string $message = ''): void
1330
    {
1331
        static::assertThat(
1332
            $actual,
1333
            new IsIdentical($expected),
1334
            $message
1335
        );
1336
    }
1337
 
1338
    /**
1339
     * Asserts that two variables do not have the same type and value.
1340
     * Used on objects, it asserts that two variables do not reference
1341
     * the same object.
1342
     *
1343
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1344
     * @throws ExpectationFailedException
1345
     */
1346
    public static function assertNotSame($expected, $actual, string $message = ''): void
1347
    {
1348
        if (is_bool($expected) && is_bool($actual)) {
1349
            static::assertNotEquals($expected, $actual, $message);
1350
        }
1351
 
1352
        static::assertThat(
1353
            $actual,
1354
            new LogicalNot(
1355
                new IsIdentical($expected)
1356
            ),
1357
            $message
1358
        );
1359
    }
1360
 
1361
    /**
1362
     * Asserts that a variable is of a given type.
1363
     *
1364
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1365
     * @throws Exception
1366
     * @throws ExpectationFailedException
1367
     *
1368
     * @psalm-template ExpectedType of object
1369
     *
1370
     * @psalm-param class-string<ExpectedType> $expected
1371
     *
1372
     * @psalm-assert =ExpectedType $actual
1373
     */
1374
    public static function assertInstanceOf(string $expected, $actual, string $message = ''): void
1375
    {
1376
        if (!class_exists($expected) && !interface_exists($expected)) {
1377
            throw InvalidArgumentException::create(1, 'class or interface name');
1378
        }
1379
 
1380
        static::assertThat(
1381
            $actual,
1382
            new IsInstanceOf($expected),
1383
            $message
1384
        );
1385
    }
1386
 
1387
    /**
1388
     * Asserts that a variable is not of a given type.
1389
     *
1390
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1391
     * @throws Exception
1392
     * @throws ExpectationFailedException
1393
     *
1394
     * @psalm-template ExpectedType of object
1395
     *
1396
     * @psalm-param class-string<ExpectedType> $expected
1397
     *
1398
     * @psalm-assert !ExpectedType $actual
1399
     */
1400
    public static function assertNotInstanceOf(string $expected, $actual, string $message = ''): void
1401
    {
1402
        if (!class_exists($expected) && !interface_exists($expected)) {
1403
            throw InvalidArgumentException::create(1, 'class or interface name');
1404
        }
1405
 
1406
        static::assertThat(
1407
            $actual,
1408
            new LogicalNot(
1409
                new IsInstanceOf($expected)
1410
            ),
1411
            $message
1412
        );
1413
    }
1414
 
1415
    /**
1416
     * Asserts that a variable is of type array.
1417
     *
1418
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1419
     * @throws ExpectationFailedException
1420
     *
1421
     * @psalm-assert array $actual
1422
     */
1423
    public static function assertIsArray($actual, string $message = ''): void
1424
    {
1425
        static::assertThat(
1426
            $actual,
1427
            new IsType(IsType::TYPE_ARRAY),
1428
            $message
1429
        );
1430
    }
1431
 
1432
    /**
1433
     * Asserts that a variable is of type bool.
1434
     *
1435
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1436
     * @throws ExpectationFailedException
1437
     *
1438
     * @psalm-assert bool $actual
1439
     */
1440
    public static function assertIsBool($actual, string $message = ''): void
1441
    {
1442
        static::assertThat(
1443
            $actual,
1444
            new IsType(IsType::TYPE_BOOL),
1445
            $message
1446
        );
1447
    }
1448
 
1449
    /**
1450
     * Asserts that a variable is of type float.
1451
     *
1452
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1453
     * @throws ExpectationFailedException
1454
     *
1455
     * @psalm-assert float $actual
1456
     */
1457
    public static function assertIsFloat($actual, string $message = ''): void
1458
    {
1459
        static::assertThat(
1460
            $actual,
1461
            new IsType(IsType::TYPE_FLOAT),
1462
            $message
1463
        );
1464
    }
1465
 
1466
    /**
1467
     * Asserts that a variable is of type int.
1468
     *
1469
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1470
     * @throws ExpectationFailedException
1471
     *
1472
     * @psalm-assert int $actual
1473
     */
1474
    public static function assertIsInt($actual, string $message = ''): void
1475
    {
1476
        static::assertThat(
1477
            $actual,
1478
            new IsType(IsType::TYPE_INT),
1479
            $message
1480
        );
1481
    }
1482
 
1483
    /**
1484
     * Asserts that a variable is of type numeric.
1485
     *
1486
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1487
     * @throws ExpectationFailedException
1488
     *
1489
     * @psalm-assert numeric $actual
1490
     */
1491
    public static function assertIsNumeric($actual, string $message = ''): void
1492
    {
1493
        static::assertThat(
1494
            $actual,
1495
            new IsType(IsType::TYPE_NUMERIC),
1496
            $message
1497
        );
1498
    }
1499
 
1500
    /**
1501
     * Asserts that a variable is of type object.
1502
     *
1503
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1504
     * @throws ExpectationFailedException
1505
     *
1506
     * @psalm-assert object $actual
1507
     */
1508
    public static function assertIsObject($actual, string $message = ''): void
1509
    {
1510
        static::assertThat(
1511
            $actual,
1512
            new IsType(IsType::TYPE_OBJECT),
1513
            $message
1514
        );
1515
    }
1516
 
1517
    /**
1518
     * Asserts that a variable is of type resource.
1519
     *
1520
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1521
     * @throws ExpectationFailedException
1522
     *
1523
     * @psalm-assert resource $actual
1524
     */
1525
    public static function assertIsResource($actual, string $message = ''): void
1526
    {
1527
        static::assertThat(
1528
            $actual,
1529
            new IsType(IsType::TYPE_RESOURCE),
1530
            $message
1531
        );
1532
    }
1533
 
1534
    /**
1535
     * Asserts that a variable is of type resource and is closed.
1536
     *
1537
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1538
     * @throws ExpectationFailedException
1539
     *
1540
     * @psalm-assert resource $actual
1541
     */
1542
    public static function assertIsClosedResource($actual, string $message = ''): void
1543
    {
1544
        static::assertThat(
1545
            $actual,
1546
            new IsType(IsType::TYPE_CLOSED_RESOURCE),
1547
            $message
1548
        );
1549
    }
1550
 
1551
    /**
1552
     * Asserts that a variable is of type string.
1553
     *
1554
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1555
     * @throws ExpectationFailedException
1556
     *
1557
     * @psalm-assert string $actual
1558
     */
1559
    public static function assertIsString($actual, string $message = ''): void
1560
    {
1561
        static::assertThat(
1562
            $actual,
1563
            new IsType(IsType::TYPE_STRING),
1564
            $message
1565
        );
1566
    }
1567
 
1568
    /**
1569
     * Asserts that a variable is of type scalar.
1570
     *
1571
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1572
     * @throws ExpectationFailedException
1573
     *
1574
     * @psalm-assert scalar $actual
1575
     */
1576
    public static function assertIsScalar($actual, string $message = ''): void
1577
    {
1578
        static::assertThat(
1579
            $actual,
1580
            new IsType(IsType::TYPE_SCALAR),
1581
            $message
1582
        );
1583
    }
1584
 
1585
    /**
1586
     * Asserts that a variable is of type callable.
1587
     *
1588
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1589
     * @throws ExpectationFailedException
1590
     *
1591
     * @psalm-assert callable $actual
1592
     */
1593
    public static function assertIsCallable($actual, string $message = ''): void
1594
    {
1595
        static::assertThat(
1596
            $actual,
1597
            new IsType(IsType::TYPE_CALLABLE),
1598
            $message
1599
        );
1600
    }
1601
 
1602
    /**
1603
     * Asserts that a variable is of type iterable.
1604
     *
1605
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1606
     * @throws ExpectationFailedException
1607
     *
1608
     * @psalm-assert iterable $actual
1609
     */
1610
    public static function assertIsIterable($actual, string $message = ''): void
1611
    {
1612
        static::assertThat(
1613
            $actual,
1614
            new IsType(IsType::TYPE_ITERABLE),
1615
            $message
1616
        );
1617
    }
1618
 
1619
    /**
1620
     * Asserts that a variable is not of type array.
1621
     *
1622
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1623
     * @throws ExpectationFailedException
1624
     *
1625
     * @psalm-assert !array $actual
1626
     */
1627
    public static function assertIsNotArray($actual, string $message = ''): void
1628
    {
1629
        static::assertThat(
1630
            $actual,
1631
            new LogicalNot(new IsType(IsType::TYPE_ARRAY)),
1632
            $message
1633
        );
1634
    }
1635
 
1636
    /**
1637
     * Asserts that a variable is not of type bool.
1638
     *
1639
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1640
     * @throws ExpectationFailedException
1641
     *
1642
     * @psalm-assert !bool $actual
1643
     */
1644
    public static function assertIsNotBool($actual, string $message = ''): void
1645
    {
1646
        static::assertThat(
1647
            $actual,
1648
            new LogicalNot(new IsType(IsType::TYPE_BOOL)),
1649
            $message
1650
        );
1651
    }
1652
 
1653
    /**
1654
     * Asserts that a variable is not of type float.
1655
     *
1656
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1657
     * @throws ExpectationFailedException
1658
     *
1659
     * @psalm-assert !float $actual
1660
     */
1661
    public static function assertIsNotFloat($actual, string $message = ''): void
1662
    {
1663
        static::assertThat(
1664
            $actual,
1665
            new LogicalNot(new IsType(IsType::TYPE_FLOAT)),
1666
            $message
1667
        );
1668
    }
1669
 
1670
    /**
1671
     * Asserts that a variable is not of type int.
1672
     *
1673
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1674
     * @throws ExpectationFailedException
1675
     *
1676
     * @psalm-assert !int $actual
1677
     */
1678
    public static function assertIsNotInt($actual, string $message = ''): void
1679
    {
1680
        static::assertThat(
1681
            $actual,
1682
            new LogicalNot(new IsType(IsType::TYPE_INT)),
1683
            $message
1684
        );
1685
    }
1686
 
1687
    /**
1688
     * Asserts that a variable is not of type numeric.
1689
     *
1690
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1691
     * @throws ExpectationFailedException
1692
     *
1693
     * @psalm-assert !numeric $actual
1694
     */
1695
    public static function assertIsNotNumeric($actual, string $message = ''): void
1696
    {
1697
        static::assertThat(
1698
            $actual,
1699
            new LogicalNot(new IsType(IsType::TYPE_NUMERIC)),
1700
            $message
1701
        );
1702
    }
1703
 
1704
    /**
1705
     * Asserts that a variable is not of type object.
1706
     *
1707
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1708
     * @throws ExpectationFailedException
1709
     *
1710
     * @psalm-assert !object $actual
1711
     */
1712
    public static function assertIsNotObject($actual, string $message = ''): void
1713
    {
1714
        static::assertThat(
1715
            $actual,
1716
            new LogicalNot(new IsType(IsType::TYPE_OBJECT)),
1717
            $message
1718
        );
1719
    }
1720
 
1721
    /**
1722
     * Asserts that a variable is not of type resource.
1723
     *
1724
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1725
     * @throws ExpectationFailedException
1726
     *
1727
     * @psalm-assert !resource $actual
1728
     */
1729
    public static function assertIsNotResource($actual, string $message = ''): void
1730
    {
1731
        static::assertThat(
1732
            $actual,
1733
            new LogicalNot(new IsType(IsType::TYPE_RESOURCE)),
1734
            $message
1735
        );
1736
    }
1737
 
1738
    /**
1739
     * Asserts that a variable is not of type resource.
1740
     *
1741
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1742
     * @throws ExpectationFailedException
1743
     *
1744
     * @psalm-assert !resource $actual
1745
     */
1746
    public static function assertIsNotClosedResource($actual, string $message = ''): void
1747
    {
1748
        static::assertThat(
1749
            $actual,
1750
            new LogicalNot(new IsType(IsType::TYPE_CLOSED_RESOURCE)),
1751
            $message
1752
        );
1753
    }
1754
 
1755
    /**
1756
     * Asserts that a variable is not of type string.
1757
     *
1758
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1759
     * @throws ExpectationFailedException
1760
     *
1761
     * @psalm-assert !string $actual
1762
     */
1763
    public static function assertIsNotString($actual, string $message = ''): void
1764
    {
1765
        static::assertThat(
1766
            $actual,
1767
            new LogicalNot(new IsType(IsType::TYPE_STRING)),
1768
            $message
1769
        );
1770
    }
1771
 
1772
    /**
1773
     * Asserts that a variable is not of type scalar.
1774
     *
1775
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1776
     * @throws ExpectationFailedException
1777
     *
1778
     * @psalm-assert !scalar $actual
1779
     */
1780
    public static function assertIsNotScalar($actual, string $message = ''): void
1781
    {
1782
        static::assertThat(
1783
            $actual,
1784
            new LogicalNot(new IsType(IsType::TYPE_SCALAR)),
1785
            $message
1786
        );
1787
    }
1788
 
1789
    /**
1790
     * Asserts that a variable is not of type callable.
1791
     *
1792
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1793
     * @throws ExpectationFailedException
1794
     *
1795
     * @psalm-assert !callable $actual
1796
     */
1797
    public static function assertIsNotCallable($actual, string $message = ''): void
1798
    {
1799
        static::assertThat(
1800
            $actual,
1801
            new LogicalNot(new IsType(IsType::TYPE_CALLABLE)),
1802
            $message
1803
        );
1804
    }
1805
 
1806
    /**
1807
     * Asserts that a variable is not of type iterable.
1808
     *
1809
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1810
     * @throws ExpectationFailedException
1811
     *
1812
     * @psalm-assert !iterable $actual
1813
     */
1814
    public static function assertIsNotIterable($actual, string $message = ''): void
1815
    {
1816
        static::assertThat(
1817
            $actual,
1818
            new LogicalNot(new IsType(IsType::TYPE_ITERABLE)),
1819
            $message
1820
        );
1821
    }
1822
 
1823
    /**
1824
     * Asserts that a string matches a given regular expression.
1825
     *
1826
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1827
     * @throws ExpectationFailedException
1828
     */
1829
    public static function assertMatchesRegularExpression(string $pattern, string $string, string $message = ''): void
1830
    {
1831
        static::assertThat($string, new RegularExpression($pattern), $message);
1832
    }
1833
 
1834
    /**
1835
     * Asserts that a string matches a given regular expression.
1836
     *
1837
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1838
     * @throws ExpectationFailedException
1839
     *
1840
     * @codeCoverageIgnore
1841
     *
1842
     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4086
1843
     */
1844
    public static function assertRegExp(string $pattern, string $string, string $message = ''): void
1845
    {
1846
        self::createWarning('assertRegExp() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertMatchesRegularExpression() instead.');
1847
 
1848
        static::assertThat($string, new RegularExpression($pattern), $message);
1849
    }
1850
 
1851
    /**
1852
     * Asserts that a string does not match a given regular expression.
1853
     *
1854
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1855
     * @throws ExpectationFailedException
1856
     */
1857
    public static function assertDoesNotMatchRegularExpression(string $pattern, string $string, string $message = ''): void
1858
    {
1859
        static::assertThat(
1860
            $string,
1861
            new LogicalNot(
1862
                new RegularExpression($pattern)
1863
            ),
1864
            $message
1865
        );
1866
    }
1867
 
1868
    /**
1869
     * Asserts that a string does not match a given regular expression.
1870
     *
1871
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1872
     * @throws ExpectationFailedException
1873
     *
1874
     * @codeCoverageIgnore
1875
     *
1876
     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4089
1877
     */
1878
    public static function assertNotRegExp(string $pattern, string $string, string $message = ''): void
1879
    {
1880
        self::createWarning('assertNotRegExp() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDoesNotMatchRegularExpression() instead.');
1881
 
1882
        static::assertThat(
1883
            $string,
1884
            new LogicalNot(
1885
                new RegularExpression($pattern)
1886
            ),
1887
            $message
1888
        );
1889
    }
1890
 
1891
    /**
1892
     * Assert that the size of two arrays (or `Countable` or `Traversable` objects)
1893
     * is the same.
1894
     *
1895
     * @param Countable|iterable $expected
1896
     * @param Countable|iterable $actual
1897
     *
1898
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1899
     * @throws Exception
1900
     * @throws ExpectationFailedException
1901
     */
1902
    public static function assertSameSize($expected, $actual, string $message = ''): void
1903
    {
1904
        if (!$expected instanceof Countable && !is_iterable($expected)) {
1905
            throw InvalidArgumentException::create(1, 'countable or iterable');
1906
        }
1907
 
1908
        if (!$actual instanceof Countable && !is_iterable($actual)) {
1909
            throw InvalidArgumentException::create(2, 'countable or iterable');
1910
        }
1911
 
1912
        static::assertThat(
1913
            $actual,
1914
            new SameSize($expected),
1915
            $message
1916
        );
1917
    }
1918
 
1919
    /**
1920
     * Assert that the size of two arrays (or `Countable` or `Traversable` objects)
1921
     * is not the same.
1922
     *
1923
     * @param Countable|iterable $expected
1924
     * @param Countable|iterable $actual
1925
     *
1926
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1927
     * @throws Exception
1928
     * @throws ExpectationFailedException
1929
     */
1930
    public static function assertNotSameSize($expected, $actual, string $message = ''): void
1931
    {
1932
        if (!$expected instanceof Countable && !is_iterable($expected)) {
1933
            throw InvalidArgumentException::create(1, 'countable or iterable');
1934
        }
1935
 
1936
        if (!$actual instanceof Countable && !is_iterable($actual)) {
1937
            throw InvalidArgumentException::create(2, 'countable or iterable');
1938
        }
1939
 
1940
        static::assertThat(
1941
            $actual,
1942
            new LogicalNot(
1943
                new SameSize($expected)
1944
            ),
1945
            $message
1946
        );
1947
    }
1948
 
1949
    /**
1950
     * Asserts that a string matches a given format string.
1951
     *
1952
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1953
     * @throws ExpectationFailedException
1954
     */
1955
    public static function assertStringMatchesFormat(string $format, string $string, string $message = ''): void
1956
    {
1957
        static::assertThat($string, new StringMatchesFormatDescription($format), $message);
1958
    }
1959
 
1960
    /**
1961
     * Asserts that a string does not match a given format string.
1962
     *
1963
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1964
     * @throws ExpectationFailedException
1965
     */
1966
    public static function assertStringNotMatchesFormat(string $format, string $string, string $message = ''): void
1967
    {
1968
        static::assertThat(
1969
            $string,
1970
            new LogicalNot(
1971
                new StringMatchesFormatDescription($format)
1972
            ),
1973
            $message
1974
        );
1975
    }
1976
 
1977
    /**
1978
     * Asserts that a string matches a given format file.
1979
     *
1980
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
1981
     * @throws ExpectationFailedException
1982
     */
1983
    public static function assertStringMatchesFormatFile(string $formatFile, string $string, string $message = ''): void
1984
    {
1985
        static::assertFileExists($formatFile, $message);
1986
 
1987
        static::assertThat(
1988
            $string,
1989
            new StringMatchesFormatDescription(
1990
                file_get_contents($formatFile)
1991
            ),
1992
            $message
1993
        );
1994
    }
1995
 
1996
    /**
1997
     * Asserts that a string does not match a given format string.
1998
     *
1999
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2000
     * @throws ExpectationFailedException
2001
     */
2002
    public static function assertStringNotMatchesFormatFile(string $formatFile, string $string, string $message = ''): void
2003
    {
2004
        static::assertFileExists($formatFile, $message);
2005
 
2006
        static::assertThat(
2007
            $string,
2008
            new LogicalNot(
2009
                new StringMatchesFormatDescription(
2010
                    file_get_contents($formatFile)
2011
                )
2012
            ),
2013
            $message
2014
        );
2015
    }
2016
 
2017
    /**
2018
     * Asserts that a string starts with a given prefix.
2019
     *
2020
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2021
     * @throws ExpectationFailedException
2022
     */
2023
    public static function assertStringStartsWith(string $prefix, string $string, string $message = ''): void
2024
    {
2025
        static::assertThat($string, new StringStartsWith($prefix), $message);
2026
    }
2027
 
2028
    /**
2029
     * Asserts that a string starts not with a given prefix.
2030
     *
2031
     * @param string $prefix
2032
     * @param string $string
2033
     *
2034
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2035
     * @throws ExpectationFailedException
2036
     */
2037
    public static function assertStringStartsNotWith($prefix, $string, string $message = ''): void
2038
    {
2039
        static::assertThat(
2040
            $string,
2041
            new LogicalNot(
2042
                new StringStartsWith($prefix)
2043
            ),
2044
            $message
2045
        );
2046
    }
2047
 
2048
    /**
2049
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2050
     * @throws ExpectationFailedException
2051
     */
2052
    public static function assertStringContainsString(string $needle, string $haystack, string $message = ''): void
2053
    {
2054
        $constraint = new StringContains($needle, false);
2055
 
2056
        static::assertThat($haystack, $constraint, $message);
2057
    }
2058
 
2059
    /**
2060
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2061
     * @throws ExpectationFailedException
2062
     */
2063
    public static function assertStringContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void
2064
    {
2065
        $constraint = new StringContains($needle, true);
2066
 
2067
        static::assertThat($haystack, $constraint, $message);
2068
    }
2069
 
2070
    /**
2071
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2072
     * @throws ExpectationFailedException
2073
     */
2074
    public static function assertStringNotContainsString(string $needle, string $haystack, string $message = ''): void
2075
    {
2076
        $constraint = new LogicalNot(new StringContains($needle));
2077
 
2078
        static::assertThat($haystack, $constraint, $message);
2079
    }
2080
 
2081
    /**
2082
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2083
     * @throws ExpectationFailedException
2084
     */
2085
    public static function assertStringNotContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void
2086
    {
2087
        $constraint = new LogicalNot(new StringContains($needle, true));
2088
 
2089
        static::assertThat($haystack, $constraint, $message);
2090
    }
2091
 
2092
    /**
2093
     * Asserts that a string ends with a given suffix.
2094
     *
2095
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2096
     * @throws ExpectationFailedException
2097
     */
2098
    public static function assertStringEndsWith(string $suffix, string $string, string $message = ''): void
2099
    {
2100
        static::assertThat($string, new StringEndsWith($suffix), $message);
2101
    }
2102
 
2103
    /**
2104
     * Asserts that a string ends not with a given suffix.
2105
     *
2106
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2107
     * @throws ExpectationFailedException
2108
     */
2109
    public static function assertStringEndsNotWith(string $suffix, string $string, string $message = ''): void
2110
    {
2111
        static::assertThat(
2112
            $string,
2113
            new LogicalNot(
2114
                new StringEndsWith($suffix)
2115
            ),
2116
            $message
2117
        );
2118
    }
2119
 
2120
    /**
2121
     * Asserts that two XML files are equal.
2122
     *
2123
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2124
     * @throws Exception
2125
     * @throws ExpectationFailedException
2126
     */
2127
    public static function assertXmlFileEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void
2128
    {
2129
        $expected = (new XmlLoader)->loadFile($expectedFile);
2130
        $actual   = (new XmlLoader)->loadFile($actualFile);
2131
 
2132
        static::assertEquals($expected, $actual, $message);
2133
    }
2134
 
2135
    /**
2136
     * Asserts that two XML files are not equal.
2137
     *
2138
     * @throws \PHPUnit\Util\Exception
2139
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2140
     * @throws ExpectationFailedException
2141
     */
2142
    public static function assertXmlFileNotEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void
2143
    {
2144
        $expected = (new XmlLoader)->loadFile($expectedFile);
2145
        $actual   = (new XmlLoader)->loadFile($actualFile);
2146
 
2147
        static::assertNotEquals($expected, $actual, $message);
2148
    }
2149
 
2150
    /**
2151
     * Asserts that two XML documents are equal.
2152
     *
2153
     * @param DOMDocument|string $actualXml
2154
     *
2155
     * @throws \PHPUnit\Util\Xml\Exception
2156
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2157
     * @throws ExpectationFailedException
2158
     */
2159
    public static function assertXmlStringEqualsXmlFile(string $expectedFile, $actualXml, string $message = ''): void
2160
    {
2161
        if (!is_string($actualXml)) {
2162
            self::createWarning('Passing an argument of type DOMDocument for the $actualXml parameter is deprecated. Support for this will be removed in PHPUnit 10.');
2163
 
2164
            $actual = $actualXml;
2165
        } else {
2166
            $actual = (new XmlLoader)->load($actualXml);
2167
        }
2168
 
2169
        $expected = (new XmlLoader)->loadFile($expectedFile);
2170
 
2171
        static::assertEquals($expected, $actual, $message);
2172
    }
2173
 
2174
    /**
2175
     * Asserts that two XML documents are not equal.
2176
     *
2177
     * @param DOMDocument|string $actualXml
2178
     *
2179
     * @throws \PHPUnit\Util\Xml\Exception
2180
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2181
     * @throws ExpectationFailedException
2182
     */
2183
    public static function assertXmlStringNotEqualsXmlFile(string $expectedFile, $actualXml, string $message = ''): void
2184
    {
2185
        if (!is_string($actualXml)) {
2186
            self::createWarning('Passing an argument of type DOMDocument for the $actualXml parameter is deprecated. Support for this will be removed in PHPUnit 10.');
2187
 
2188
            $actual = $actualXml;
2189
        } else {
2190
            $actual = (new XmlLoader)->load($actualXml);
2191
        }
2192
 
2193
        $expected = (new XmlLoader)->loadFile($expectedFile);
2194
 
2195
        static::assertNotEquals($expected, $actual, $message);
2196
    }
2197
 
2198
    /**
2199
     * Asserts that two XML documents are equal.
2200
     *
2201
     * @param DOMDocument|string $expectedXml
2202
     * @param DOMDocument|string $actualXml
2203
     *
2204
     * @throws \PHPUnit\Util\Xml\Exception
2205
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2206
     * @throws ExpectationFailedException
2207
     */
2208
    public static function assertXmlStringEqualsXmlString($expectedXml, $actualXml, string $message = ''): void
2209
    {
2210
        if (!is_string($expectedXml)) {
2211
            self::createWarning('Passing an argument of type DOMDocument for the $expectedXml parameter is deprecated. Support for this will be removed in PHPUnit 10.');
2212
 
2213
            $expected = $expectedXml;
2214
        } else {
2215
            $expected = (new XmlLoader)->load($expectedXml);
2216
        }
2217
 
2218
        if (!is_string($actualXml)) {
2219
            self::createWarning('Passing an argument of type DOMDocument for the $actualXml parameter is deprecated. Support for this will be removed in PHPUnit 10.');
2220
 
2221
            $actual = $actualXml;
2222
        } else {
2223
            $actual = (new XmlLoader)->load($actualXml);
2224
        }
2225
 
2226
        static::assertEquals($expected, $actual, $message);
2227
    }
2228
 
2229
    /**
2230
     * Asserts that two XML documents are not equal.
2231
     *
2232
     * @param DOMDocument|string $expectedXml
2233
     * @param DOMDocument|string $actualXml
2234
     *
2235
     * @throws \PHPUnit\Util\Xml\Exception
2236
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2237
     * @throws ExpectationFailedException
2238
     */
2239
    public static function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, string $message = ''): void
2240
    {
2241
        if (!is_string($expectedXml)) {
2242
            self::createWarning('Passing an argument of type DOMDocument for the $expectedXml parameter is deprecated. Support for this will be removed in PHPUnit 10.');
2243
 
2244
            $expected = $expectedXml;
2245
        } else {
2246
            $expected = (new XmlLoader)->load($expectedXml);
2247
        }
2248
 
2249
        if (!is_string($actualXml)) {
2250
            self::createWarning('Passing an argument of type DOMDocument for the $actualXml parameter is deprecated. Support for this will be removed in PHPUnit 10.');
2251
 
2252
            $actual = $actualXml;
2253
        } else {
2254
            $actual = (new XmlLoader)->load($actualXml);
2255
        }
2256
 
2257
        static::assertNotEquals($expected, $actual, $message);
2258
    }
2259
 
2260
    /**
2261
     * Asserts that a hierarchy of DOMElements matches.
2262
     *
2263
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2264
     * @throws AssertionFailedError
2265
     * @throws ExpectationFailedException
2266
     *
2267
     * @codeCoverageIgnore
2268
     *
2269
     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4091
2270
     */
2271
    public static function assertEqualXMLStructure(DOMElement $expectedElement, DOMElement $actualElement, bool $checkAttributes = false, string $message = ''): void
2272
    {
2273
        self::createWarning('assertEqualXMLStructure() is deprecated and will be removed in PHPUnit 10.');
2274
 
2275
        $expectedElement = Xml::import($expectedElement);
2276
        $actualElement   = Xml::import($actualElement);
2277
 
2278
        static::assertSame(
2279
            $expectedElement->tagName,
2280
            $actualElement->tagName,
2281
            $message
2282
        );
2283
 
2284
        if ($checkAttributes) {
2285
            static::assertSame(
2286
                $expectedElement->attributes->length,
2287
                $actualElement->attributes->length,
2288
                sprintf(
2289
                    '%s%sNumber of attributes on node "%s" does not match',
2290
                    $message,
2291
                    !empty($message) ? "\n" : '',
2292
                    $expectedElement->tagName
2293
                )
2294
            );
2295
 
2296
            for ($i = 0; $i < $expectedElement->attributes->length; $i++) {
2297
                $expectedAttribute = $expectedElement->attributes->item($i);
2298
                $actualAttribute   = $actualElement->attributes->getNamedItem($expectedAttribute->name);
2299
 
2300
                assert($expectedAttribute instanceof DOMAttr);
2301
 
2302
                if (!$actualAttribute) {
2303
                    static::fail(
2304
                        sprintf(
2305
                            '%s%sCould not find attribute "%s" on node "%s"',
2306
                            $message,
2307
                            !empty($message) ? "\n" : '',
2308
                            $expectedAttribute->name,
2309
                            $expectedElement->tagName
2310
                        )
2311
                    );
2312
                }
2313
            }
2314
        }
2315
 
2316
        Xml::removeCharacterDataNodes($expectedElement);
2317
        Xml::removeCharacterDataNodes($actualElement);
2318
 
2319
        static::assertSame(
2320
            $expectedElement->childNodes->length,
2321
            $actualElement->childNodes->length,
2322
            sprintf(
2323
                '%s%sNumber of child nodes of "%s" differs',
2324
                $message,
2325
                !empty($message) ? "\n" : '',
2326
                $expectedElement->tagName
2327
            )
2328
        );
2329
 
2330
        for ($i = 0; $i < $expectedElement->childNodes->length; $i++) {
2331
            static::assertEqualXMLStructure(
2332
                $expectedElement->childNodes->item($i),
2333
                $actualElement->childNodes->item($i),
2334
                $checkAttributes,
2335
                $message
2336
            );
2337
        }
2338
    }
2339
 
2340
    /**
2341
     * Evaluates a PHPUnit\Framework\Constraint matcher object.
2342
     *
2343
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2344
     * @throws ExpectationFailedException
2345
     */
2346
    public static function assertThat($value, Constraint $constraint, string $message = ''): void
2347
    {
2348
        self::$count += count($constraint);
2349
 
2350
        $constraint->evaluate($value, $message);
2351
    }
2352
 
2353
    /**
2354
     * Asserts that a string is a valid JSON string.
2355
     *
2356
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2357
     * @throws ExpectationFailedException
2358
     */
2359
    public static function assertJson(string $actualJson, string $message = ''): void
2360
    {
2361
        static::assertThat($actualJson, static::isJson(), $message);
2362
    }
2363
 
2364
    /**
2365
     * Asserts that two given JSON encoded objects or arrays are equal.
2366
     *
2367
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2368
     * @throws ExpectationFailedException
2369
     */
2370
    public static function assertJsonStringEqualsJsonString(string $expectedJson, string $actualJson, string $message = ''): void
2371
    {
2372
        static::assertJson($expectedJson, $message);
2373
        static::assertJson($actualJson, $message);
2374
 
2375
        static::assertThat($actualJson, new JsonMatches($expectedJson), $message);
2376
    }
2377
 
2378
    /**
2379
     * Asserts that two given JSON encoded objects or arrays are not equal.
2380
     *
2381
     * @param string $expectedJson
2382
     * @param string $actualJson
2383
     *
2384
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2385
     * @throws ExpectationFailedException
2386
     */
2387
    public static function assertJsonStringNotEqualsJsonString($expectedJson, $actualJson, string $message = ''): void
2388
    {
2389
        static::assertJson($expectedJson, $message);
2390
        static::assertJson($actualJson, $message);
2391
 
2392
        static::assertThat(
2393
            $actualJson,
2394
            new LogicalNot(
2395
                new JsonMatches($expectedJson)
2396
            ),
2397
            $message
2398
        );
2399
    }
2400
 
2401
    /**
2402
     * Asserts that the generated JSON encoded object and the content of the given file are equal.
2403
     *
2404
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2405
     * @throws ExpectationFailedException
2406
     */
2407
    public static function assertJsonStringEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void
2408
    {
2409
        static::assertFileExists($expectedFile, $message);
2410
        $expectedJson = file_get_contents($expectedFile);
2411
 
2412
        static::assertJson($expectedJson, $message);
2413
        static::assertJson($actualJson, $message);
2414
 
2415
        static::assertThat($actualJson, new JsonMatches($expectedJson), $message);
2416
    }
2417
 
2418
    /**
2419
     * Asserts that the generated JSON encoded object and the content of the given file are not equal.
2420
     *
2421
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2422
     * @throws ExpectationFailedException
2423
     */
2424
    public static function assertJsonStringNotEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void
2425
    {
2426
        static::assertFileExists($expectedFile, $message);
2427
        $expectedJson = file_get_contents($expectedFile);
2428
 
2429
        static::assertJson($expectedJson, $message);
2430
        static::assertJson($actualJson, $message);
2431
 
2432
        static::assertThat(
2433
            $actualJson,
2434
            new LogicalNot(
2435
                new JsonMatches($expectedJson)
2436
            ),
2437
            $message
2438
        );
2439
    }
2440
 
2441
    /**
2442
     * Asserts that two JSON files are equal.
2443
     *
2444
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2445
     * @throws ExpectationFailedException
2446
     */
2447
    public static function assertJsonFileEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void
2448
    {
2449
        static::assertFileExists($expectedFile, $message);
2450
        static::assertFileExists($actualFile, $message);
2451
 
2452
        $actualJson   = file_get_contents($actualFile);
2453
        $expectedJson = file_get_contents($expectedFile);
2454
 
2455
        static::assertJson($expectedJson, $message);
2456
        static::assertJson($actualJson, $message);
2457
 
2458
        $constraintExpected = new JsonMatches(
2459
            $expectedJson
2460
        );
2461
 
2462
        $constraintActual = new JsonMatches($actualJson);
2463
 
2464
        static::assertThat($expectedJson, $constraintActual, $message);
2465
        static::assertThat($actualJson, $constraintExpected, $message);
2466
    }
2467
 
2468
    /**
2469
     * Asserts that two JSON files are not equal.
2470
     *
2471
     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
2472
     * @throws ExpectationFailedException
2473
     */
2474
    public static function assertJsonFileNotEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void
2475
    {
2476
        static::assertFileExists($expectedFile, $message);
2477
        static::assertFileExists($actualFile, $message);
2478
 
2479
        $actualJson   = file_get_contents($actualFile);
2480
        $expectedJson = file_get_contents($expectedFile);
2481
 
2482
        static::assertJson($expectedJson, $message);
2483
        static::assertJson($actualJson, $message);
2484
 
2485
        $constraintExpected = new JsonMatches(
2486
            $expectedJson
2487
        );
2488
 
2489
        $constraintActual = new JsonMatches($actualJson);
2490
 
2491
        static::assertThat($expectedJson, new LogicalNot($constraintActual), $message);
2492
        static::assertThat($actualJson, new LogicalNot($constraintExpected), $message);
2493
    }
2494
 
2495
    /**
2496
     * @throws Exception
2497
     */
2498
    public static function logicalAnd(): LogicalAnd
2499
    {
2500
        $constraints = func_get_args();
2501
 
2502
        $constraint = new LogicalAnd;
2503
        $constraint->setConstraints($constraints);
2504
 
2505
        return $constraint;
2506
    }
2507
 
2508
    public static function logicalOr(): LogicalOr
2509
    {
2510
        $constraints = func_get_args();
2511
 
2512
        $constraint = new LogicalOr;
2513
        $constraint->setConstraints($constraints);
2514
 
2515
        return $constraint;
2516
    }
2517
 
2518
    public static function logicalNot(Constraint $constraint): LogicalNot
2519
    {
2520
        return new LogicalNot($constraint);
2521
    }
2522
 
2523
    public static function logicalXor(): LogicalXor
2524
    {
2525
        $constraints = func_get_args();
2526
 
2527
        $constraint = new LogicalXor;
2528
        $constraint->setConstraints($constraints);
2529
 
2530
        return $constraint;
2531
    }
2532
 
2533
    public static function anything(): IsAnything
2534
    {
2535
        return new IsAnything;
2536
    }
2537
 
2538
    public static function isTrue(): IsTrue
2539
    {
2540
        return new IsTrue;
2541
    }
2542
 
2543
    /**
2544
     * @psalm-template CallbackInput of mixed
2545
     *
2546
     * @psalm-param callable(CallbackInput $callback): bool $callback
2547
     *
2548
     * @psalm-return Callback<CallbackInput>
2549
     */
2550
    public static function callback(callable $callback): Callback
2551
    {
2552
        return new Callback($callback);
2553
    }
2554
 
2555
    public static function isFalse(): IsFalse
2556
    {
2557
        return new IsFalse;
2558
    }
2559
 
2560
    public static function isJson(): IsJson
2561
    {
2562
        return new IsJson;
2563
    }
2564
 
2565
    public static function isNull(): IsNull
2566
    {
2567
        return new IsNull;
2568
    }
2569
 
2570
    public static function isFinite(): IsFinite
2571
    {
2572
        return new IsFinite;
2573
    }
2574
 
2575
    public static function isInfinite(): IsInfinite
2576
    {
2577
        return new IsInfinite;
2578
    }
2579
 
2580
    public static function isNan(): IsNan
2581
    {
2582
        return new IsNan;
2583
    }
2584
 
2585
    public static function containsEqual($value): TraversableContainsEqual
2586
    {
2587
        return new TraversableContainsEqual($value);
2588
    }
2589
 
2590
    public static function containsIdentical($value): TraversableContainsIdentical
2591
    {
2592
        return new TraversableContainsIdentical($value);
2593
    }
2594
 
2595
    public static function containsOnly(string $type): TraversableContainsOnly
2596
    {
2597
        return new TraversableContainsOnly($type);
2598
    }
2599
 
2600
    public static function containsOnlyInstancesOf(string $className): TraversableContainsOnly
2601
    {
2602
        return new TraversableContainsOnly($className, false);
2603
    }
2604
 
2605
    /**
2606
     * @param int|string $key
2607
     */
2608
    public static function arrayHasKey($key): ArrayHasKey
2609
    {
2610
        return new ArrayHasKey($key);
2611
    }
2612
 
2613
    public static function equalTo($value): IsEqual
2614
    {
2615
        return new IsEqual($value, 0.0, false, false);
2616
    }
2617
 
2618
    public static function equalToCanonicalizing($value): IsEqualCanonicalizing
2619
    {
2620
        return new IsEqualCanonicalizing($value);
2621
    }
2622
 
2623
    public static function equalToIgnoringCase($value): IsEqualIgnoringCase
2624
    {
2625
        return new IsEqualIgnoringCase($value);
2626
    }
2627
 
2628
    public static function equalToWithDelta($value, float $delta): IsEqualWithDelta
2629
    {
2630
        return new IsEqualWithDelta($value, $delta);
2631
    }
2632
 
2633
    public static function isEmpty(): IsEmpty
2634
    {
2635
        return new IsEmpty;
2636
    }
2637
 
2638
    public static function isWritable(): IsWritable
2639
    {
2640
        return new IsWritable;
2641
    }
2642
 
2643
    public static function isReadable(): IsReadable
2644
    {
2645
        return new IsReadable;
2646
    }
2647
 
2648
    public static function directoryExists(): DirectoryExists
2649
    {
2650
        return new DirectoryExists;
2651
    }
2652
 
2653
    public static function fileExists(): FileExists
2654
    {
2655
        return new FileExists;
2656
    }
2657
 
2658
    public static function greaterThan($value): GreaterThan
2659
    {
2660
        return new GreaterThan($value);
2661
    }
2662
 
2663
    public static function greaterThanOrEqual($value): LogicalOr
2664
    {
2665
        return static::logicalOr(
2666
            new IsEqual($value),
2667
            new GreaterThan($value)
2668
        );
2669
    }
2670
 
2671
    public static function classHasAttribute(string $attributeName): ClassHasAttribute
2672
    {
2673
        return new ClassHasAttribute($attributeName);
2674
    }
2675
 
2676
    public static function classHasStaticAttribute(string $attributeName): ClassHasStaticAttribute
2677
    {
2678
        return new ClassHasStaticAttribute($attributeName);
2679
    }
2680
 
2681
    public static function objectHasAttribute($attributeName): ObjectHasAttribute
2682
    {
2683
        return new ObjectHasAttribute($attributeName);
2684
    }
2685
 
2686
    public static function identicalTo($value): IsIdentical
2687
    {
2688
        return new IsIdentical($value);
2689
    }
2690
 
2691
    public static function isInstanceOf(string $className): IsInstanceOf
2692
    {
2693
        return new IsInstanceOf($className);
2694
    }
2695
 
2696
    public static function isType(string $type): IsType
2697
    {
2698
        return new IsType($type);
2699
    }
2700
 
2701
    public static function lessThan($value): LessThan
2702
    {
2703
        return new LessThan($value);
2704
    }
2705
 
2706
    public static function lessThanOrEqual($value): LogicalOr
2707
    {
2708
        return static::logicalOr(
2709
            new IsEqual($value),
2710
            new LessThan($value)
2711
        );
2712
    }
2713
 
2714
    public static function matchesRegularExpression(string $pattern): RegularExpression
2715
    {
2716
        return new RegularExpression($pattern);
2717
    }
2718
 
2719
    public static function matches(string $string): StringMatchesFormatDescription
2720
    {
2721
        return new StringMatchesFormatDescription($string);
2722
    }
2723
 
2724
    public static function stringStartsWith($prefix): StringStartsWith
2725
    {
2726
        return new StringStartsWith($prefix);
2727
    }
2728
 
2729
    public static function stringContains(string $string, bool $case = true): StringContains
2730
    {
2731
        return new StringContains($string, $case);
2732
    }
2733
 
2734
    public static function stringEndsWith(string $suffix): StringEndsWith
2735
    {
2736
        return new StringEndsWith($suffix);
2737
    }
2738
 
2739
    public static function countOf(int $count): Count
2740
    {
2741
        return new Count($count);
2742
    }
2743
 
2744
    public static function objectEquals(object $object, string $method = 'equals'): ObjectEquals
2745
    {
2746
        return new ObjectEquals($object, $method);
2747
    }
2748
 
2749
    /**
2750
     * Fails a test with the given message.
2751
     *
2752
     * @throws AssertionFailedError
2753
     *
2754
     * @psalm-return never-return
2755
     */
2756
    public static function fail(string $message = ''): void
2757
    {
2758
        self::$count++;
2759
 
2760
        throw new AssertionFailedError($message);
2761
    }
2762
 
2763
    /**
2764
     * Mark the test as incomplete.
2765
     *
2766
     * @throws IncompleteTestError
2767
     *
2768
     * @psalm-return never-return
2769
     */
2770
    public static function markTestIncomplete(string $message = ''): void
2771
    {
2772
        throw new IncompleteTestError($message);
2773
    }
2774
 
2775
    /**
2776
     * Mark the test as skipped.
2777
     *
2778
     * @throws SkippedTestError
2779
     * @throws SyntheticSkippedError
2780
     *
2781
     * @psalm-return never-return
2782
     */
2783
    public static function markTestSkipped(string $message = ''): void
2784
    {
2785
        if ($hint = self::detectLocationHint($message)) {
2786
            $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
2787
            array_unshift($trace, $hint);
2788
 
2789
            throw new SyntheticSkippedError($hint['message'], 0, $hint['file'], (int) $hint['line'], $trace);
2790
        }
2791
 
2792
        throw new SkippedTestError($message);
2793
    }
2794
 
2795
    /**
2796
     * Return the current assertion count.
2797
     */
2798
    public static function getCount(): int
2799
    {
2800
        return self::$count;
2801
    }
2802
 
2803
    /**
2804
     * Reset the assertion counter.
2805
     */
2806
    public static function resetCount(): void
2807
    {
2808
        self::$count = 0;
2809
    }
2810
 
2811
    private static function detectLocationHint(string $message): ?array
2812
    {
2813
        $hint  = null;
2814
        $lines = preg_split('/\r\n|\r|\n/', $message);
2815
 
2816
        while (strpos($lines[0], '__OFFSET') !== false) {
2817
            $offset = explode('=', array_shift($lines));
2818
 
2819
            if ($offset[0] === '__OFFSET_FILE') {
2820
                $hint['file'] = $offset[1];
2821
            }
2822
 
2823
            if ($offset[0] === '__OFFSET_LINE') {
2824
                $hint['line'] = $offset[1];
2825
            }
2826
        }
2827
 
2828
        if ($hint) {
2829
            $hint['message'] = implode(PHP_EOL, $lines);
2830
        }
2831
 
2832
        return $hint;
2833
    }
2834
 
2835
    private static function isValidObjectAttributeName(string $attributeName): bool
2836
    {
2837
        return (bool) preg_match('/[^\x00-\x1f\x7f-\x9f]+/', $attributeName);
2838
    }
2839
 
2840
    private static function isValidClassAttributeName(string $attributeName): bool
2841
    {
2842
        return (bool) preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName);
2843
    }
2844
 
2845
    /**
2846
     * @codeCoverageIgnore
2847
     */
2848
    private static function createWarning(string $warning): void
2849
    {
2850
        foreach (debug_backtrace() as $step) {
2851
            if (isset($step['object']) && $step['object'] instanceof TestCase) {
2852
                assert($step['object'] instanceof TestCase);
2853
 
2854
                $step['object']->addWarning($warning);
2855
 
2856
                break;
2857
            }
2858
        }
2859
    }
2860
}