Subversion-Projekte lars-tiefland.laravel_shop

Revision

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