Completed
Push — master ( 1fe131...339793 )
by Arnold
03:33
created

TypeFunctionsTest::typeDescriptionProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 11
nc 1
nop 0
dl 0
loc 14
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
namespace Jasny\Tests;
4
5
use function Jasny\get_type_description;
6
use PHPStan\Testing\TestCase;
7
8
use function Jasny\expect_type;
9
use function Jasny\is_associative_array;
10
use function Jasny\is_numeric_array;
11
use function Jasny\objectify;
12
use function Jasny\arrayify;
13
14
/**
15
 * Test type functions
16
 * @coversNothing
17
 */
18
class TypeFunctionsTest extends TestCase
19
{
20
    const NONE = 0;
21
    const NUMERIC = 1;
22
    const ASSOC = 2;
23
    
24
    public function varProvider()
25
    {
26
        return [
27
            [['foo', 'bar'], self::NUMERIC],
28
            [['a' => 'foo', 'b' => 'bar'], self::ASSOC],
29
            [[1 => 'foo', 'bar'], self::ASSOC],
30
            [['foo', 'b' => 'bar'], self::ASSOC],
31
            [['foo', 2 => 'bar'], self::ASSOC],
32
            [[], self::NUMERIC],
33
            ['foo', self::NONE],
34
            [(object)['a' => 'b'], self::NONE]
35
        ];
36
    }
37
    
38
    /**
39
     * @covers Jasny\is_associative_array
40
     * @dataProvider varProvider
41
     * 
42
     * @param mixed $var
43
     * @param int   $type
44
     */
45
    public function testIsAssociativeArray($var, $type)
46
    {
47
        $this->assertEquals($type === self::ASSOC, is_associative_array($var));
48
    }
49
    
50
    /**
51
     * @covers Jasny\is_numeric_array
52
     * @dataProvider varProvider
53
     * 
54
     * @param mixed $var
55
     * @param int   $type
56
     */
57
    public function testIsNumericArray($var, $type)
58
    {
59
        $this->assertEquals($type === self::NUMERIC, is_numeric_array($var));
60
    }
61
    
62
    
63
    public function objectifyProvider()
64
    {
65
        return [
66
            [
67
                'foo',
68
                'foo'
69
            ],
70
            [
71
                ['a' => 'foo'],
72
                (object)['a' => 'foo']
73
            ],
74
            [
75
                ['foo', 'bar', 'zoo'],
76
                ['foo', 'bar', 'zoo']
77
            ],
78
            [
79
                ['a' => ['b' => ['c' => 'foo']]],
80
                (object)['a' => (object)['b' => (object)['c' => 'foo']]]
81
            ],
82
            [
83
                (object)['a' => ['b' => ['c' => 'foo']]],
84
                (object)['a' => (object)['b' => (object)['c' => 'foo']]]
85
            ],
86
            [
87
                ['a' => 'foo', 'b' => ['bar', 'zoo'], 'c' => true],
88
                (object)['a' => 'foo', 'b' => ['bar', 'zoo'], 'c' => true]
89
            ],
90
            [
91
                [1 => 'a', 'b'],
92
                (object)['1' => 'a', '2' => 'b']
93
            ],
94
            [
95
                [],
96
                []
97
            ]
98
        ];
99
    }
100
    
101
    /**
102
     * @covers Jasny\objectify
103
     * @dataProvider objectifyProvider
104
     * 
105
     * @param mixed $var
106
     * @param mixed $expect
107
     */
108
    public function testObjectify($var, $expect)
109
    {
110
        $this->assertEquals($expect, objectify($var));
111
    }
112
    
113
    
114
    public function arrayifyProvider()
115
    {
116
        return [
117
            [
118
                'foo',
119
                'foo'
120
            ],
121
            [
122
                (object)['a' => 'foo'],
123
                ['a' => 'foo']
124
            ],
125
            [
126
                (object)['a' => (object)['b' => (object)['c' => 'foo']]],
127
                ['a' => ['b' => ['c' => 'foo']]],
128
            ],
129
            [
130
                ['a' => (object)['b' => (object)['c' => 'foo']]],
131
                ['a' => ['b' => ['c' => 'foo']]]
132
            ],
133
            [
134
                (object)['date' => new \DateTime('2000-01-01')],
135
                ['date' => new \DateTime('2000-01-01')]
136
            ],
137
            [
138
                new \stdClass(),
139
                []
140
            ]
141
        ];
142
    }
143
    
144
    /**
145
     * @covers Jasny\arrayify
146
     * @dataProvider arrayifyProvider
147
     * 
148
     * @param mixed $var
149
     * @param mixed $expect
150
     */
151
    public function testArrayify($var, $expect)
152
    {
153
        $this->assertEquals($expect, arrayify($var));
154
    }
155
156
    
157
    public function circularReferenceProvider()
158
    {
159
        $object = new \stdClass();
160
        $object->items = [
161
            'foo',
162
            $object
163
        ];
164
        
165
        return [
166
            [$object]
167
        ];
168
    }
169
    
170
    /**
171
     * @covers Jasny\objectify
172
     * @dataProvider circularReferenceProvider
173
     * 
174
     * @expectedException \OverflowException
175
     * @expectedExceptionMessage Maximum recursion depth reached. Possible circular reference.
176
     */
177
    public function testObjectifyCircularReference(\stdClass $object)
178
    {
179
        objectify($object);
180
    }
181
    
182
    /**
183
     * @covers Jasny\arrayify
184
     * @dataProvider circularReferenceProvider
185
     * 
186
     * @expectedException \OverflowException
187
     * @expectedExceptionMessage Maximum recursion depth reached. Possible circular reference.
188
     */
189
    public function testArrayifyCircularReference(\stdClass $object)
190
    {
191
        arrayify($object);
192
    }
193
194
    public function typeDescriptionProvider()
195
    {
196
        $closedResource = fopen('php://memory', 'r+');
197
        fclose($closedResource);
1 ignored issue
show
Bug introduced by
It seems like $closedResource can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

197
        fclose(/** @scrutinizer ignore-type */ $closedResource);
Loading history...
198
199
        return [
200
            [10, 'integer'],
201
            [10.2, 'float'],
202
            [true, 'boolean'],
203
            [[], 'array'],
204
            [(object)[], 'stdClass object'],
205
            [new \DateTime(), 'DateTime object'],
206
            [fopen('data://text/plain,hello', 'r'), 'stream resource'],
207
            [$closedResource, 'resource (closed)']
208
        ];
209
    }
210
211
    /**
212
     * @covers Jasny\get_type_description
213
     * @dataProvider typeDescriptionProvider
214
     */
215
    public function testGetTypeDescription($var, $expected)
216
    {
217
        $type = get_type_description($var);
218
219
        $this->assertSame($expected, $type);
220
    }
221
222
    
223
    public function expectTypeProvider()
224
    {
225
        $closedResource = fopen('php://memory', 'r+');
226
        fclose($closedResource);
1 ignored issue
show
Bug introduced by
It seems like $closedResource can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

226
        fclose(/** @scrutinizer ignore-type */ $closedResource);
Loading history...
227
228
        return [
229
            [10, 'int'],
230
            [true, 'bool'],
231
            [[], 'array'],
232
            [(object)[], 'stdClass'],
233
            [10, ['int', 'boolean']],
234
            ['foo', 'int', "Expected int, string given"],
235
            ['foo', ['int', 'boolean'], "Expected int or boolean, string given"],
236
            [(object)[], 'Foo', "Expected Foo object, stdClass object given"],
237
            [fopen('data://text/plain,hello', 'r'), 'string', "Expected string, stream resource given"],
238
            [$closedResource, 'string', "Expected string, resource (closed) given"]
239
        ];
240
    }
241
    
242
    /**
243
     * @covers Jasny\expect_type
244
     * @dataProvider expectTypeProvider
245
     * 
246
     * @param mixed           $var
247
     * @param string|string[] $type
248
     * @param string|false    $error
249
     */
250
    public function testExpectType($var, $type, $error = false)
251
    {
252
        if ($error) {
253
            $this->expectException(\InvalidArgumentException::class);
254
            $this->expectExceptionMessage($error);
255
        }
256
        
257
        expect_type($var, $type, \InvalidArgumentException::class);
258
259
        $this->assertTrue(true); // No warnings
260
    }
261
    
262
    /**
263
     * @covers Jasny\expect_type
264
     * 
265
     * @expectedException Exception
266
     * @expectedExceptionMessage Lorem ipsum string black
267
     */
268
    public function testExpectTypeExplicitMessage()
269
    {
270
        expect_type('foo', 'int', \Exception::class, "Lorem ipsum %s black");
271
    }
272
}
273