Passed
Pull Request — master (#1312)
by Michael
05:26
created

AssertTest::getResource()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 7
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Xmf\Test;
6
7
use PHPUnit\Framework\TestCase;
0 ignored issues
show
Bug introduced by
The type PHPUnit\Framework\TestCase was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
9
/*
10
 * This file is part of the webmozart/assert package.
11
 *
12
 * (c) Bernhard Schussek <[email protected]>
13
 *
14
 * The MIT License (MIT)
15
 *
16
 * Copyright (c) 2014 Bernhard Schussek
17
 *
18
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
19
 * this software and associated documentation files (the "Software"), to deal in
20
 * the Software without restriction, including without limitation the rights to
21
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
22
 * the Software, and to permit persons to whom the Software is furnished to do so,
23
 * subject to the following conditions:
24
 *
25
 * The above copyright notice and this permission notice shall be included in all
26
 * copies or substantial portions of the Software.
27
 *
28
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
30
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
31
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
32
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
33
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34
 */
35
36
use ArrayIterator;
37
use Exception;
38
use Error;
39
use LogicException;
40
use RuntimeException;
41
use stdClass;
42
use Xmf\Assert;
43
44
/**
45
 * @since  1.0
46
 *
47
 * @author Bernhard Schussek <[email protected]>
48
 */
49
class AssertTest extends TestCase
50
{
51
    private static $resource;
52
53
    public static function getResource()
54
    {
55
        if (!static::$resource) {
0 ignored issues
show
Bug introduced by
Since $resource is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $resource to at least protected.
Loading history...
56
            static::$resource = fopen(__FILE__, 'r');
57
        }
58
59
        return static::$resource;
60
    }
61
62
    public static function tearDownAfterClass(): void
63
    {
64
        @fclose(self::$resource);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for fclose(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

64
        /** @scrutinizer ignore-unhandled */ @fclose(self::$resource);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
65
    }
66
67
    public function getTests(): array
68
    {
69
        $resource = self::getResource();
70
71
        return [
72
            ['string', ['value'], true],
73
            ['string', [''], true],
74
            ['string', [1234], false],
75
            ['stringNotEmpty', ['value'], true],
76
            ['stringNotEmpty', [''], false],
77
            ['stringNotEmpty', [1234], false],
78
            ['integer', [123], true],
79
            ['integer', ['123'], false],
80
            ['integer', [1.0], false],
81
            ['integer', [1.23], false],
82
            ['integerish', [1.0], true],
83
            ['integerish', [1.23], false],
84
            ['integerish', [123], true],
85
            ['integerish', ['123'], true],
86
            ['float', [1.0], true],
87
            ['float', [1.23], true],
88
            ['float', [123], false],
89
            ['float', ['123'], false],
90
            ['numeric', [1.0], true],
91
            ['numeric', [1.23], true],
92
            ['numeric', [123], true],
93
            ['numeric', ['123'], true],
94
            ['numeric', ['foo'], false],
95
            ['boolean', [true], true],
96
            ['boolean', [false], true],
97
            ['boolean', [1], false],
98
            ['boolean', ['1'], false],
99
            ['scalar', ['1'], true],
100
            ['scalar', [123], true],
101
            ['scalar', [true], true],
102
            ['scalar', [null], false],
103
            ['scalar', [[]], false],
104
            ['scalar', [new stdClass()], false],
105
            ['object', [new stdClass()], true],
106
            ['object', [new RuntimeException()], true],
107
            ['object', [null], false],
108
            ['object', [true], false],
109
            ['object', [1], false],
110
            ['object', [[]], false],
111
            ['resource', [$resource], true],
112
            ['resource', [$resource, 'stream'], true],
113
            ['resource', [$resource, 'other'], false],
114
            ['resource', [1], false],
115
            ['isCallable', ['strlen'], true],
116
            ['isCallable', [[$this, 'getTests']], true],
117
            ['isCallable', [static function () { }], true],
118
            ['isCallable', [1234], false],
119
            ['isCallable', ['foobar'], false],
120
            ['isArray', [[]], true],
121
            ['isArray', [[1, 2, 3]], true],
122
            ['isArray', [new ArrayIterator([])], false],
123
            ['isArray', [123], false],
124
            ['isArray', [new stdClass()], false],
125
            ['isTraversable', [[]], true],
126
            ['isTraversable', [[1, 2, 3]], true],
127
            ['isTraversable', [new ArrayIterator([])], true],
128
            ['isTraversable', [123], false],
129
            ['isTraversable', [new stdClass()], false],
130
            ['isInstanceOf', [new stdClass(), 'stdClass'], true],
131
            ['isInstanceOf', [new Exception(), 'stdClass'], false],
132
            ['isInstanceOf', [123, 'stdClass'], false],
133
            ['isInstanceOf', [[], 'stdClass'], false],
134
            ['notInstanceOf', [new stdClass(), 'stdClass'], false],
135
            ['notInstanceOf', [new Exception(), 'stdClass'], true],
136
            ['notInstanceOf', [123, 'stdClass'], true],
137
            ['notInstanceOf', [[], 'stdClass'], true],
138
            ['true', [true], true],
139
            ['true', [false], false],
140
            ['true', [1], false],
141
            ['true', [null], false],
142
            ['false', [false], true],
143
            ['false', [true], false],
144
            ['false', [1], false],
145
            ['false', [0], false],
146
            ['false', [null], false],
147
            ['null', [null], true],
148
            ['null', [false], false],
149
            ['null', [0], false],
150
            ['notNull', [false], true],
151
            ['notNull', [0], true],
152
            ['notNull', [null], false],
153
            ['isEmpty', [null], true],
154
            ['isEmpty', [false], true],
155
            ['isEmpty', [0], true],
156
            ['isEmpty', [''], true],
157
            ['isEmpty', [1], false],
158
            ['isEmpty', ['a'], false],
159
            ['notEmpty', [1], true],
160
            ['notEmpty', ['a'], true],
161
            ['notEmpty', [null], false],
162
            ['notEmpty', [false], false],
163
            ['notEmpty', [0], false],
164
            ['notEmpty', [''], false],
165
            ['eq', [1, 1], true],
166
            ['eq', [1, '1'], true],
167
            ['eq', [1, true], true],
168
            ['eq', [1, 0], false],
169
            ['notEq', [1, 0], true],
170
            ['notEq', [1, 1], false],
171
            ['notEq', [1, '1'], false],
172
            ['notEq', [1, true], false],
173
            ['same', [1, 1], true],
174
            ['same', [1, '1'], false],
175
            ['same', [1, true], false],
176
            ['same', [1, 0], false],
177
            ['notSame', [1, 0], true],
178
            ['notSame', [1, 1], false],
179
            ['notSame', [1, '1'], true],
180
            ['notSame', [1, true], true],
181
            ['greaterThan', [1, 0], true],
182
            ['greaterThan', [0, 0], false],
183
            ['greaterThanEq', [2, 1], true],
184
            ['greaterThanEq', [1, 1], true],
185
            ['greaterThanEq', [0, 1], false],
186
            ['lessThan', [0, 1], true],
187
            ['lessThan', [1, 1], false],
188
            ['lessThanEq', [0, 1], true],
189
            ['lessThanEq', [1, 1], true],
190
            ['lessThanEq', [2, 1], false],
191
            ['range', [1, 1, 2], true],
192
            ['range', [2, 1, 2], true],
193
            ['range', [0, 1, 2], false],
194
            ['range', [3, 1, 2], false],
195
            ['oneOf', [1, [1, 2, 3]], true],
196
            ['oneOf', [1, ['1', '2', '3']], false],
197
            ['contains', ['abcd', 'ab'], true],
198
            ['contains', ['abcd', 'bc'], true],
199
            ['contains', ['abcd', 'cd'], true],
200
            ['contains', ['abcd', 'de'], false],
201
            ['contains', ['', 'de'], false],
202
            ['startsWith', ['abcd', 'ab'], true],
203
            ['startsWith', ['abcd', 'bc'], false],
204
            ['startsWith', ['', 'bc'], false],
205
            ['startsWithLetter', ['abcd'], true],
206
            ['startsWithLetter', ['1abcd'], false],
207
            ['startsWithLetter', [''], false],
208
            ['endsWith', ['abcd', 'cd'], true],
209
            ['endsWith', ['abcd', 'bc'], false],
210
            ['endsWith', ['', 'bc'], false],
211
            ['regex', ['abcd', '~^ab~'], true],
212
            ['regex', ['abcd', '~^bc~'], false],
213
            ['regex', ['', '~^bc~'], false],
214
            ['alpha', ['abcd'], true],
215
            ['alpha', ['ab1cd'], false],
216
            ['alpha', [''], false],
217
            ['digits', ['1234'], true],
218
            ['digits', ['12a34'], false],
219
            ['digits', [''], false],
220
            ['alnum', ['ab12'], true],
221
            ['alnum', ['ab12$'], false],
222
            ['alnum', [''], false],
223
            ['lower', ['abcd'], true],
224
            ['lower', ['abCd'], false],
225
            ['lower', ['ab_d'], false],
226
            ['lower', [''], false],
227
            ['upper', ['ABCD'], true],
228
            ['upper', ['ABcD'], false],
229
            ['upper', ['AB_D'], false],
230
            ['upper', [''], false],
231
            ['length', ['abcd', 4], true],
232
            ['length', ['abc', 4], false],
233
            ['length', ['abcde', 4], false],
234
            ['length', ['äbcd', 4], true, true],
235
            ['length', ['äbc', 4], false, true],
236
            ['length', ['äbcde', 4], false, true],
237
            ['minLength', ['abcd', 4], true],
238
            ['minLength', ['abcde', 4], true],
239
            ['minLength', ['abc', 4], false],
240
            ['minLength', ['äbcd', 4], true, true],
241
            ['minLength', ['äbcde', 4], true, true],
242
            ['minLength', ['äbc', 4], false, true],
243
            ['maxLength', ['abcd', 4], true],
244
            ['maxLength', ['abc', 4], true],
245
            ['maxLength', ['abcde', 4], false],
246
            ['maxLength', ['äbcd', 4], true, true],
247
            ['maxLength', ['äbc', 4], true, true],
248
            ['maxLength', ['äbcde', 4], false, true],
249
            ['lengthBetween', ['abcd', 3, 5], true],
250
            ['lengthBetween', ['abc', 3, 5], true],
251
            ['lengthBetween', ['abcde', 3, 5], true],
252
            ['lengthBetween', ['ab', 3, 5], false],
253
            ['lengthBetween', ['abcdef', 3, 5], false],
254
            ['lengthBetween', ['äbcd', 3, 5], true, true],
255
            ['lengthBetween', ['äbc', 3, 5], true, true],
256
            ['lengthBetween', ['äbcde', 3, 5], true, true],
257
            ['lengthBetween', ['äb', 3, 5], false, true],
258
            ['lengthBetween', ['äbcdef', 3, 5], false, true],
259
            ['fileExists', [__FILE__], true],
260
            ['fileExists', [__DIR__], true],
261
            ['fileExists', [__DIR__ . '/foobar'], false],
262
            ['file', [__FILE__], true],
263
            ['file', [__DIR__], false],
264
            ['file', [__DIR__ . '/foobar'], false],
265
            ['directory', [__DIR__], true],
266
            ['directory', [__FILE__], false],
267
            ['directory', [__DIR__ . '/foobar'], false],
268
            // no tests for readable()/writable() for now
269
            ['classExists', [__CLASS__], true],
270
            ['classExists', [__NAMESPACE__ . '\Foobar'], false],
271
            ['subclassOf', [__CLASS__, TestCase::class], true],
272
            ['subclassOf', [__CLASS__, 'stdClass'], false],
273
            ['implementsInterface', ['ArrayIterator', 'Traversable'], true],
274
            ['implementsInterface', [__CLASS__, 'Traversable'], false],
275
            ['propertyExists', [(object)['property' => 0], 'property'], true],
276
            ['propertyExists', [(object)['property' => null], 'property'], true],
277
            ['propertyExists', [(object)['property' => null], 'foo'], false],
278
            ['propertyNotExists', [(object)['property' => 0], 'property'], false],
279
            ['propertyNotExists', [(object)['property' => null], 'property'], false],
280
            ['propertyNotExists', [(object)['property' => null], 'foo'], true],
281
            ['methodExists', ['RuntimeException', 'getMessage'], true],
282
            ['methodExists', [new RuntimeException(), 'getMessage'], true],
283
            ['methodExists', ['stdClass', 'getMessage'], false],
284
            ['methodExists', [new stdClass(), 'getMessage'], false],
285
            ['methodExists', [null, 'getMessage'], false],
286
            ['methodExists', [true, 'getMessage'], false],
287
            ['methodExists', [1, 'getMessage'], false],
288
            ['methodNotExists', ['RuntimeException', 'getMessage'], false],
289
            ['methodNotExists', [new RuntimeException(), 'getMessage'], false],
290
            ['methodNotExists', ['stdClass', 'getMessage'], true],
291
            ['methodNotExists', [new stdClass(), 'getMessage'], true],
292
            ['methodNotExists', [null, 'getMessage'], true],
293
            ['methodNotExists', [true, 'getMessage'], true],
294
            ['methodNotExists', [1, 'getMessage'], true],
295
            ['keyExists', [['key' => 0], 'key'], true],
296
            ['keyExists', [['key' => null], 'key'], true],
297
            ['keyExists', [['key' => null], 'foo'], false],
298
            ['keyNotExists', [['key' => 0], 'key'], false],
299
            ['keyNotExists', [['key' => null], 'key'], false],
300
            ['keyNotExists', [['key' => null], 'foo'], true],
301
            ['count', [[0, 1, 2], 3], true],
302
            ['count', [[0, 1, 2], 2], false],
303
            ['uuid', ['00000000-0000-0000-0000-000000000000'], true],
304
            ['uuid', ['ff6f8cb0-c57d-21e1-9b21-0800200c9a66'], true],
305
            ['uuid', ['ff6f8cb0-c57d-11e1-9b21-0800200c9a66'], true],
306
            ['uuid', ['ff6f8cb0-c57d-31e1-9b21-0800200c9a66'], true],
307
            ['uuid', ['ff6f8cb0-c57d-41e1-9b21-0800200c9a66'], true],
308
            ['uuid', ['ff6f8cb0-c57d-51e1-9b21-0800200c9a66'], true],
309
            ['uuid', ['FF6F8CB0-C57D-11E1-9B21-0800200C9A66'], true],
310
            ['uuid', ['zf6f8cb0-c57d-11e1-9b21-0800200c9a66'], false],
311
            ['uuid', ['af6f8cb0c57d11e19b210800200c9a66'], false],
312
            ['uuid', ['ff6f8cb0-c57da-51e1-9b21-0800200c9a66'], false],
313
            ['uuid', ['af6f8cb-c57d-11e1-9b21-0800200c9a66'], false],
314
            ['uuid', ['3f6f8cb0-c57d-11e1-9b21-0800200c9a6'], false],
315
            ['throws', [function () { throw new LogicException('test'); }, 'LogicException'], true],
316
            ['throws', [function () { throw new LogicException('test'); }, 'IllogicException'], false],
317
            ['throws', [function () { throw new Exception('test'); }], true],
318
            //array('throws', array(function() { trigger_error('test'); }, 'Throwable'), true, false, 70000),
319
            ['throws', [function () { trigger_error('test'); }, 'Unthrowable'], false, false, 70000],
320
            ['throws', [function () { throw new Error(); }, 'Throwable'], true, true, 70000],
321
        ];
322
    }
323
324
    public function getMethods(): array
325
    {
326
        $methods = [];
327
328
        foreach ($this->getTests() as $params) {
329
            $methods[$params[0]] = [$params[0]];
330
        }
331
332
        return array_values($methods);
333
    }
334
335
    /**
336
     * @dataProvider getTests
337
     */
338
    public function testAssert($method, $args, $success, $multibyte = false, $minVersion = null)
339
    {
340
        if ($minVersion && PHP_VERSION_ID < $minVersion) {
341
            $this->markTestSkipped(sprintf('This test requires php %s or upper.', $minVersion));
342
343
            return;
344
        }
345
        if ($multibyte && !function_exists('mb_strlen')) {
346
            $this->markTestSkipped('The function mb_strlen() is not available');
347
348
            return;
349
        }
350
351
        if (!$success) {
352
            $this->expectException(\InvalidArgumentException::class);
353
        }
354
355
        call_user_func_array([Assert::class, $method], $args);
356
        self::assertTrue(true, 'Return type ensures this assertion is never reached on failure');
357
    }
358
359
    /**
360
     * @dataProvider getTests
361
     */
362
    public function testNullOr($method, $args, $success, $multibyte = false, $minVersion = null)
363
    {
364
        if ($minVersion && PHP_VERSION_ID < $minVersion) {
365
            $this->markTestSkipped(sprintf('This test requires php %s or upper.', $minVersion));
366
367
            return;
368
        }
369
        if ($multibyte && !function_exists('mb_strlen')) {
370
            $this->markTestSkipped('The function mb_strlen() is not available');
371
372
            return;
373
        }
374
375
        if (!$success && null !== reset($args)) {
376
            $this->expectException(\InvalidArgumentException::class);
377
        }
378
379
        call_user_func_array([Assert::class, 'nullOr' . ucfirst($method)], $args);
380
        self::assertTrue(true, 'Return type ensures this assertion is never reached on failure');
381
    }
382
383
    /**
384
     * @dataProvider getMethods
385
     */
386
    public function testNullOrAcceptsNull($method)
387
    {
388
        call_user_func([Assert::class, 'nullOr' . ucfirst($method)], null);
389
        self::assertTrue(true, 'Return type ensures this assertion is never reached on failure');
390
    }
391
392
    /**
393
     * @dataProvider getTests
394
     */
395
    public function testAllArray($method, $args, $success, $multibyte = false, $minVersion = null)
396
    {
397
        if ($minVersion && PHP_VERSION_ID < $minVersion) {
398
            $this->markTestSkipped(sprintf('This test requires php %s or upper.', $minVersion));
399
400
            return;
401
        }
402
        if ($multibyte && !function_exists('mb_strlen')) {
403
            $this->markTestSkipped('The function mb_strlen() is not available');
404
405
            return;
406
        }
407
408
        if (!$success) {
409
            $this->expectException(\InvalidArgumentException::class);
410
        }
411
412
        $arg = array_shift($args);
413
        array_unshift($args, [$arg]);
414
415
        call_user_func_array([Assert::class, 'all' . ucfirst($method)], $args);
416
        self::assertTrue(true, 'Return type ensures this assertion is never reached on failure');
417
    }
418
419
    /**
420
     * @dataProvider getTests
421
     */
422
    public function testAllTraversable($method, $args, $success, $multibyte = false, $minVersion = null)
423
    {
424
        if ($minVersion && PHP_VERSION_ID < $minVersion) {
425
            $this->markTestSkipped(sprintf('This test requires php %s or upper.', $minVersion));
426
427
            return;
428
        }
429
        if ($multibyte && !function_exists('mb_strlen')) {
430
            $this->markTestSkipped('The function mb_strlen() is not available');
431
432
            return;
433
        }
434
435
        if (!$success) {
436
            $this->expectException(\InvalidArgumentException::class);
437
        }
438
439
        $arg = array_shift($args);
440
        array_unshift($args, new ArrayIterator([$arg]));
441
442
        call_user_func_array([Assert::class, 'all' . ucfirst($method)], $args);
443
        self::assertTrue(true, 'Return type ensures this assertion is never reached on failure');
444
    }
445
446
    public function getStringConversions(): array
447
    {
448
        return [
449
            ['integer', ['foobar'], 'Expected an integer. Got: string'],
450
            ['string', [1], 'Expected a string. Got: integer'],
451
            ['string', [true], 'Expected a string. Got: boolean'],
452
            ['string', [null], 'Expected a string. Got: NULL'],
453
            ['string', [[]], 'Expected a string. Got: array'],
454
            ['string', [new stdClass()], 'Expected a string. Got: stdClass'],
455
            ['string', [self::getResource()], 'Expected a string. Got: resource'],
456
457
            ['eq', ['1', '2'], 'Expected a value equal to "2". Got: "1"'],
458
            ['eq', [1, 2], 'Expected a value equal to 2. Got: 1'],
459
            ['eq', [true, false], 'Expected a value equal to false. Got: true'],
460
            ['eq', [true, null], 'Expected a value equal to null. Got: true'],
461
            ['eq', [null, true], 'Expected a value equal to true. Got: null'],
462
            ['eq', [[1], [2]], 'Expected a value equal to array. Got: array'],
463
            ['eq', [new ArrayIterator([]), new stdClass()], 'Expected a value equal to stdClass. Got: ArrayIterator'],
464
            ['eq', [1, self::getResource()], 'Expected a value equal to resource. Got: 1'],
465
        ];
466
    }
467
468
    /**
469
     * @dataProvider getStringConversions
470
     */
471
    public function testConvertValuesToStrings($method, $args, $exceptionMessage)
472
    {
473
        $this->expectException(\InvalidArgumentException::class, $exceptionMessage);
474
475
        call_user_func_array([Assert::class, $method], $args);
476
    }
477
}
478