TypeFunctionsTest   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 297
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 103
dl 0
loc 297
rs 10
c 0
b 0
f 0
wmc 17

34 Methods

Rating   Name   Duplication   Size   Complexity  
A hp$0 ➔ stringableProvider() 0 12 1
A hp$0 ➔ testIsStringable() 0 3 1
A hp$0 ➔ testExpectType() 0 10 2
A hp$0 ➔ objectifyProvider() 0 34 1
A hp$0 ➔ testArrayifyCircularReference() 0 3 1
A hp$0 ➔ arrayifyProvider() 0 26 1
A hp$0 ➔ typeDescriptionProvider() 0 14 1
A hp$0 ➔ testObjectify() 0 3 1
testExpectTypeExplicitMessage() 0 3 ?
testGetTypeDescription() 0 5 ?
testExpectType() 0 10 ?
A testIsAssociativeArray() 0 3 1
testObjectifyCircularReference() 0 3 ?
circularReferenceProvider() 0 10 ?
A testIsNumericArray() 0 3 1
A hp$0 ➔ testExpectTypeExplicitMessageType() 0 3 1
A varProvider() 0 11 1
testArrayify() 0 3 ?
A hp$0 ➔ testArrayify() 0 3 1
A hp$0 ➔ circularReferenceProvider() 0 10 1
stringableProvider() 0 12 ?
A hp$0 ➔ testObjectifyCircularReference() 0 3 1
arrayifyProvider() 0 26 ?
testIsStringable() 0 3 ?
A hp$0 ➔ testExpectTypeExplicitMessage() 0 3 1
A hp$0 ➔ __toString() 0 1 1
objectifyProvider() 0 34 ?
testExpectTypeExplicitMessageType() 0 3 ?
testObjectify() 0 3 ?
testArrayifyCircularReference() 0 3 ?
expectTypeProvider() 0 26 ?
A hp$0 ➔ expectTypeProvider() 0 26 1
A hp$0 ➔ testGetTypeDescription() 0 5 1
typeDescriptionProvider() 0 14 ?
1
<?php
2
3
namespace Jasny\Tests;
4
5
use function Jasny\get_type_description;
6
use function Jasny\is_stringable;
7
use PHPStan\Testing\TestCase;
8
9
use function Jasny\expect_type;
10
use function Jasny\is_associative_array;
11
use function Jasny\is_numeric_array;
12
use function Jasny\objectify;
13
use function Jasny\arrayify;
14
15
/**
16
 * Test type functions
17
 * @coversNothing
18
 */
19
class TypeFunctionsTest extends TestCase
20
{
21
    const NONE = 0;
22
    const NUMERIC = 1;
23
    const ASSOC = 2;
24
25
    public function varProvider()
26
    {
27
        return [
28
            [['foo', 'bar'], self::NUMERIC],
29
            [['a' => 'foo', 'b' => 'bar'], self::ASSOC],
30
            [[1 => 'foo', 'bar'], self::ASSOC],
31
            [['foo', 'b' => 'bar'], self::ASSOC],
32
            [['foo', 2 => 'bar'], self::ASSOC],
33
            [[], self::NUMERIC],
34
            ['foo', self::NONE],
35
            [(object)['a' => 'b'], self::NONE]
36
        ];
37
    }
38
39
    /**
40
     * @covers \Jasny\is_associative_array
41
     * @dataProvider varProvider
42
     *
43
     * @param mixed $var
44
     * @param int $type
45
     */
46
    public function testIsAssociativeArray($var, $type)
47
    {
48
        $this->assertEquals($type === self::ASSOC, is_associative_array($var));
49
    }
50
51
    /**
52
     * @covers \Jasny\is_numeric_array
53
     * @dataProvider varProvider
54
     *
55
     * @param mixed $var
56
     * @param int $type
57
     */
58
    public function testIsNumericArray($var, $type)
59
    {
60
        $this->assertEquals($type === self::NUMERIC, is_numeric_array($var));
61
    }
62
63
    public function stringableProvider()
64
    {
65
        return [
66
            [null, false],
67
            [true, false],
68
            ['', true],
69
            ['foo', true],
70
            [0, true],
71
            [42, true],
72
            [1.23, true],
73
            [(object)['a' => 'b'], false],
74
            [new class() { function __toString() { return 'f'; } }, true]
75
        ];
76
    }
77
78
    /**
79
     * @covers \Jasny\is_stringable
80
     * @dataProvider stringableProvider
81
     */
82
    public function testIsStringable($var, $expected)
83
    {
84
        $this->assertSame($expected, is_stringable($var));
85
    }
86
    
87
    public function objectifyProvider()
88
    {
89
        return [
90
            [
91
                'foo',
92
                'foo'
93
            ],
94
            [
95
                ['a' => 'foo'],
96
                (object)['a' => 'foo']
97
            ],
98
            [
99
                ['foo', 'bar', 'zoo'],
100
                ['foo', 'bar', 'zoo']
101
            ],
102
            [
103
                ['a' => ['b' => ['c' => 'foo']]],
104
                (object)['a' => (object)['b' => (object)['c' => 'foo']]]
105
            ],
106
            [
107
                (object)['a' => ['b' => ['c' => 'foo']]],
108
                (object)['a' => (object)['b' => (object)['c' => 'foo']]]
109
            ],
110
            [
111
                ['a' => 'foo', 'b' => ['bar', 'zoo'], 'c' => true],
112
                (object)['a' => 'foo', 'b' => ['bar', 'zoo'], 'c' => true]
113
            ],
114
            [
115
                [1 => 'a', 'b'],
116
                (object)['1' => 'a', '2' => 'b']
117
            ],
118
            [
119
                [],
120
                []
121
            ]
122
        ];
123
    }
124
    
125
    /**
126
     * @covers \Jasny\objectify
127
     * @dataProvider objectifyProvider
128
     * 
129
     * @param mixed $var
130
     * @param mixed $expect
131
     */
132
    public function testObjectify($var, $expect)
133
    {
134
        $this->assertEquals($expect, objectify($var));
135
    }
136
    
137
    
138
    public function arrayifyProvider()
139
    {
140
        return [
141
            [
142
                'foo',
143
                'foo'
144
            ],
145
            [
146
                (object)['a' => 'foo'],
147
                ['a' => 'foo']
148
            ],
149
            [
150
                (object)['a' => (object)['b' => (object)['c' => 'foo']]],
151
                ['a' => ['b' => ['c' => 'foo']]],
152
            ],
153
            [
154
                ['a' => (object)['b' => (object)['c' => 'foo']]],
155
                ['a' => ['b' => ['c' => 'foo']]]
156
            ],
157
            [
158
                (object)['date' => new \DateTime('2000-01-01')],
159
                ['date' => new \DateTime('2000-01-01')]
160
            ],
161
            [
162
                new \stdClass(),
163
                []
164
            ]
165
        ];
166
    }
167
    
168
    /**
169
     * @covers \Jasny\arrayify
170
     * @dataProvider arrayifyProvider
171
     * 
172
     * @param mixed $var
173
     * @param mixed $expect
174
     */
175
    public function testArrayify($var, $expect)
176
    {
177
        $this->assertEquals($expect, arrayify($var));
178
    }
179
180
    
181
    public function circularReferenceProvider()
182
    {
183
        $object = new \stdClass();
184
        $object->items = [
185
            'foo',
186
            $object
187
        ];
188
        
189
        return [
190
            [$object]
191
        ];
192
    }
193
    
194
    /**
195
     * @covers \Jasny\objectify
196
     * @dataProvider circularReferenceProvider
197
     * 
198
     * @expectedException \OverflowException
199
     * @expectedExceptionMessage Maximum recursion depth reached. Possible circular reference.
200
     */
201
    public function testObjectifyCircularReference(\stdClass $object)
202
    {
203
        objectify($object);
204
    }
205
    
206
    /**
207
     * @covers \Jasny\arrayify
208
     * @dataProvider circularReferenceProvider
209
     * 
210
     * @expectedException \OverflowException
211
     * @expectedExceptionMessage Maximum recursion depth reached. Possible circular reference.
212
     */
213
    public function testArrayifyCircularReference(\stdClass $object)
214
    {
215
        arrayify($object);
216
    }
217
218
    public function typeDescriptionProvider()
219
    {
220
        $closedResource = fopen('php://memory', 'r+');
221
        fclose($closedResource);
222
223
        return [
224
            [10, 'integer'],
225
            [10.2, 'float'],
226
            [true, 'boolean'],
227
            [[], 'array'],
228
            [(object)[], 'stdClass object'],
229
            [new \DateTime(), 'DateTime object'],
230
            [fopen('data://text/plain,hello', 'r'), 'stream resource'],
231
            [$closedResource, 'resource (closed)']
232
        ];
233
    }
234
235
    /**
236
     * @covers \Jasny\get_type_description
237
     * @dataProvider typeDescriptionProvider
238
     */
239
    public function testGetTypeDescription($var, $expected)
240
    {
241
        $type = get_type_description($var);
242
243
        $this->assertSame($expected, $type);
244
    }
245
246
    
247
    public function expectTypeProvider()
248
    {
249
        $streamResource = fopen('data://text/plain,a', 'r');
250
251
        $closedResource = fopen('php://memory', 'r+');
252
        fclose($closedResource);
253
254
        return [
255
            [10, 'int'],
256
            [10, 'integer'],
257
            [true, 'bool'],
258
            [true, 'boolean'],
259
            [[], 'array'],
260
            [(object)[], 'stdClass'],
261
            [10, ['int', 'boolean']],
262
            ['foo', 'int', "Expected int, string given"],
263
            ['foo', ['int', 'boolean'], "Expected int or boolean, string given"],
264
            [(object)[], 'Foo', "Expected Foo object, stdClass object given"],
265
            [$streamResource, 'resource'],
266
            [$streamResource, 'stream resource'],
267
            [$streamResource, ['stream resource', 'gd resource']],
268
            [$streamResource, 'string', "Expected string, stream resource given"],
269
            [$streamResource, 'gd resource', "Expected gd resource, stream resource given"],
270
            [$streamResource, ['int', 'gd resource'], "Expected int or gd resource, stream resource given"],
271
            [$streamResource, 'stream', "Expected stream object, stream resource given"],
272
            [$closedResource, 'string', "Expected string, resource (closed) given"]
273
        ];
274
    }
275
    
276
    /**
277
     * @covers \Jasny\expect_type
278
     * @dataProvider expectTypeProvider
279
     * 
280
     * @param mixed           $var
281
     * @param string|string[] $type
282
     * @param string|false    $error
283
     */
284
    public function testExpectType($var, $type, $error = false)
285
    {
286
        if ($error) {
287
            $this->expectException(\InvalidArgumentException::class);
288
            $this->expectExceptionMessage($error);
289
        }
290
        
291
        expect_type($var, $type, \InvalidArgumentException::class);
292
293
        $this->assertTrue(true); // No warnings
294
    }
295
    
296
    /**
297
     * @covers \Jasny\expect_type
298
     * 
299
     * @expectedException Exception
300
     * @expectedExceptionMessage Lorem ipsum string black
301
     */
302
    public function testExpectTypeExplicitMessage()
303
    {
304
        expect_type('foo', 'int', \Exception::class, "Lorem ipsum %s black");
305
    }
306
307
    /**
308
     * @covers \Jasny\expect_type
309
     *
310
     * @expectedException Exception
311
     * @expectedExceptionMessage Lorem int ipsum string black
312
     */
313
    public function testExpectTypeExplicitMessageType()
314
    {
315
        expect_type('foo', 'int', \Exception::class, 'Lorem %2$s ipsum %1$s black');
316
    }
317
}
318