Completed
Pull Request — master (#423)
by Marco
24:53
created

PropertiesTest::testGetPublicProperties()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ProxyManagerTest\ProxyGenerator\Util;
6
7
use PHPUnit\Framework\TestCase;
8
use ProxyManager\ProxyGenerator\Util\Properties;
9
use ProxyManagerTestAsset\ClassWithAbstractProtectedMethod;
10
use ProxyManagerTestAsset\ClassWithAbstractPublicMethod;
11
use ProxyManagerTestAsset\ClassWithCollidingPrivateInheritedProperties;
12
use ProxyManagerTestAsset\ClassWithMixedProperties;
13
use ProxyManagerTestAsset\ClassWithMixedReferenceableTypedProperties;
14
use ProxyManagerTestAsset\ClassWithMixedTypedProperties;
15
use ProxyManagerTestAsset\ClassWithPrivateProperties;
16
use ReflectionClass;
17
use ReflectionProperty;
18
19
/**
20
 * Tests for {@see \ProxyManager\ProxyGenerator\Util\Properties}
21
 *
22
 * @covers \ProxyManager\ProxyGenerator\Util\Properties
23
 * @group Coverage
24
 */
25
class PropertiesTest extends TestCase
26
{
27
    public function testGetPublicProperties() : void
28
    {
29
        $properties       = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedProperties::class));
30
        $publicProperties = $properties->getPublicProperties();
31
32
        self::assertCount(3, $publicProperties);
33
        self::assertInstanceOf(ReflectionProperty::class, $publicProperties['publicProperty0']);
34
        self::assertInstanceOf(ReflectionProperty::class, $publicProperties['publicProperty1']);
35
        self::assertInstanceOf(ReflectionProperty::class, $publicProperties['publicProperty2']);
36
    }
37
38
    public function testGetPublicPropertiesSkipsAbstractMethods() : void
39
    {
40
        $properties = Properties::fromReflectionClass(new ReflectionClass(ClassWithAbstractPublicMethod::class));
41
42
        self::assertEmpty($properties->getPublicProperties());
43
    }
44
45
    public function testGetProtectedProperties() : void
46
    {
47
        $properties = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedProperties::class));
48
49
        $protectedProperties = $properties->getProtectedProperties();
50
51
        self::assertCount(3, $protectedProperties);
52
53
        self::assertInstanceOf(ReflectionProperty::class, $protectedProperties["\0*\0protectedProperty0"]);
54
        self::assertInstanceOf(ReflectionProperty::class, $protectedProperties["\0*\0protectedProperty1"]);
55
        self::assertInstanceOf(ReflectionProperty::class, $protectedProperties["\0*\0protectedProperty2"]);
56
    }
57
58
    public function testOnlyNullableProperties() : void
59
    {
60
        $nullablePublicProperties = Properties
61
            ::fromReflectionClass(new ReflectionClass(ClassWithMixedTypedProperties::class))
62
            ->onlyNullableProperties()
63
            ->getInstanceProperties();
64
65
        self::assertCount(48, $nullablePublicProperties);
66
        self::assertSame(
67
            [
68
                'publicUnTypedProperty',
69
                'publicUnTypedPropertyWithoutDefaultValue',
70
                'publicNullableBoolProperty',
71
                'publicNullableBoolPropertyWithoutDefaultValue',
72
                'publicNullableIntProperty',
73
                'publicNullableIntPropertyWithoutDefaultValue',
74
                'publicNullableFloatProperty',
75
                'publicNullableFloatPropertyWithoutDefaultValue',
76
                'publicNullableStringProperty',
77
                'publicNullableStringPropertyWithoutDefaultValue',
78
                'publicNullableArrayProperty',
79
                'publicNullableArrayPropertyWithoutDefaultValue',
80
                'publicNullableIterableProperty',
81
                'publicNullableIterablePropertyWithoutDefaultValue',
82
                'publicNullableObjectProperty',
83
                'publicNullableClassProperty',
84
                'protectedUnTypedProperty',
85
                'protectedUnTypedPropertyWithoutDefaultValue',
86
                'protectedNullableBoolProperty',
87
                'protectedNullableBoolPropertyWithoutDefaultValue',
88
                'protectedNullableIntProperty',
89
                'protectedNullableIntPropertyWithoutDefaultValue',
90
                'protectedNullableFloatProperty',
91
                'protectedNullableFloatPropertyWithoutDefaultValue',
92
                'protectedNullableStringProperty',
93
                'protectedNullableStringPropertyWithoutDefaultValue',
94
                'protectedNullableArrayProperty',
95
                'protectedNullableArrayPropertyWithoutDefaultValue',
96
                'protectedNullableIterableProperty',
97
                'protectedNullableIterablePropertyWithoutDefaultValue',
98
                'protectedNullableObjectProperty',
99
                'protectedNullableClassProperty',
100
                'privateUnTypedProperty',
101
                'privateUnTypedPropertyWithoutDefaultValue',
102
                'privateNullableBoolProperty',
103
                'privateNullableBoolPropertyWithoutDefaultValue',
104
                'privateNullableIntProperty',
105
                'privateNullableIntPropertyWithoutDefaultValue',
106
                'privateNullableFloatProperty',
107
                'privateNullableFloatPropertyWithoutDefaultValue',
108
                'privateNullableStringProperty',
109
                'privateNullableStringPropertyWithoutDefaultValue',
110
                'privateNullableArrayProperty',
111
                'privateNullableArrayPropertyWithoutDefaultValue',
112
                'privateNullableIterableProperty',
113
                'privateNullableIterablePropertyWithoutDefaultValue',
114
                'privateNullableObjectProperty',
115
                'privateNullableClassProperty',
116
            ],
117
            array_values(array_map(static function (ReflectionProperty $property) : string {
118
                return $property->getName();
119
            }, $nullablePublicProperties))
120
        );
121
    }
122
123
    public function testOnlyPropertiesThatCanBeUnset() : void
124
    {
125
        $nonReferenceableProperties = Properties
126
            ::fromReflectionClass(new ReflectionClass(ClassWithMixedTypedProperties::class))
127
            ->onlyPropertiesThatCanBeUnset()
128
            ->getInstanceProperties();
129
130
        self::assertCount(42, $nonReferenceableProperties);
131
        self::assertSame(
132
            [
133
                'publicUnTypedProperty',
134
                'publicUnTypedPropertyWithoutDefaultValue',
135
                'publicBoolProperty',
136
                'publicNullableBoolProperty',
137
                'publicIntProperty',
138
                'publicNullableIntProperty',
139
                'publicFloatProperty',
140
                'publicNullableFloatProperty',
141
                'publicStringProperty',
142
                'publicNullableStringProperty',
143
                'publicArrayProperty',
144
                'publicNullableArrayProperty',
145
                'publicIterableProperty',
146
                'publicNullableIterableProperty',
147
                'protectedUnTypedProperty',
148
                'protectedUnTypedPropertyWithoutDefaultValue',
149
                'protectedBoolProperty',
150
                'protectedNullableBoolProperty',
151
                'protectedIntProperty',
152
                'protectedNullableIntProperty',
153
                'protectedFloatProperty',
154
                'protectedNullableFloatProperty',
155
                'protectedStringProperty',
156
                'protectedNullableStringProperty',
157
                'protectedArrayProperty',
158
                'protectedNullableArrayProperty',
159
                'protectedIterableProperty',
160
                'protectedNullableIterableProperty',
161
                'privateUnTypedProperty',
162
                'privateUnTypedPropertyWithoutDefaultValue',
163
                'privateBoolProperty',
164
                'privateNullableBoolProperty',
165
                'privateIntProperty',
166
                'privateNullableIntProperty',
167
                'privateFloatProperty',
168
                'privateNullableFloatProperty',
169
                'privateStringProperty',
170
                'privateNullableStringProperty',
171
                'privateArrayProperty',
172
                'privateNullableArrayProperty',
173
                'privateIterableProperty',
174
                'privateNullableIterableProperty',
175
            ],
176
            array_values(array_map(static function (ReflectionProperty $property) : string {
177
                return $property->getName();
178
            }, $nonReferenceableProperties))
179
        );
180
    }
181
182
    public function testOnlyNonReferenceableProperties() : void
183
    {
184
        self::assertTrue(
185
            Properties
186
                ::fromReflectionClass(new ReflectionClass(ClassWithMixedReferenceableTypedProperties::class))
187
                ->onlyNonReferenceableProperties()
188
                ->empty()
189
        );
190
191
        $nonReferenceableProperties = Properties
192
            ::fromReflectionClass(new ReflectionClass(ClassWithMixedTypedProperties::class))
193
            ->onlyNonReferenceableProperties()
194
            ->getInstanceProperties();
195
196
        self::assertCount(48, $nonReferenceableProperties);
197
        self::assertSame(
198
            [
199
                'publicBoolPropertyWithoutDefaultValue',
200
                'publicNullableBoolPropertyWithoutDefaultValue',
201
                'publicIntPropertyWithoutDefaultValue',
202
                'publicNullableIntPropertyWithoutDefaultValue',
203
                'publicFloatPropertyWithoutDefaultValue',
204
                'publicNullableFloatPropertyWithoutDefaultValue',
205
                'publicStringPropertyWithoutDefaultValue',
206
                'publicNullableStringPropertyWithoutDefaultValue',
207
                'publicArrayPropertyWithoutDefaultValue',
208
                'publicNullableArrayPropertyWithoutDefaultValue',
209
                'publicIterablePropertyWithoutDefaultValue',
210
                'publicNullableIterablePropertyWithoutDefaultValue',
211
                'publicObjectProperty',
212
                'publicNullableObjectProperty',
213
                'publicClassProperty',
214
                'publicNullableClassProperty',
215
                'protectedBoolPropertyWithoutDefaultValue',
216
                'protectedNullableBoolPropertyWithoutDefaultValue',
217
                'protectedIntPropertyWithoutDefaultValue',
218
                'protectedNullableIntPropertyWithoutDefaultValue',
219
                'protectedFloatPropertyWithoutDefaultValue',
220
                'protectedNullableFloatPropertyWithoutDefaultValue',
221
                'protectedStringPropertyWithoutDefaultValue',
222
                'protectedNullableStringPropertyWithoutDefaultValue',
223
                'protectedArrayPropertyWithoutDefaultValue',
224
                'protectedNullableArrayPropertyWithoutDefaultValue',
225
                'protectedIterablePropertyWithoutDefaultValue',
226
                'protectedNullableIterablePropertyWithoutDefaultValue',
227
                'protectedObjectProperty',
228
                'protectedNullableObjectProperty',
229
                'protectedClassProperty',
230
                'protectedNullableClassProperty',
231
                'privateBoolPropertyWithoutDefaultValue',
232
                'privateNullableBoolPropertyWithoutDefaultValue',
233
                'privateIntPropertyWithoutDefaultValue',
234
                'privateNullableIntPropertyWithoutDefaultValue',
235
                'privateFloatPropertyWithoutDefaultValue',
236
                'privateNullableFloatPropertyWithoutDefaultValue',
237
                'privateStringPropertyWithoutDefaultValue',
238
                'privateNullableStringPropertyWithoutDefaultValue',
239
                'privateArrayPropertyWithoutDefaultValue',
240
                'privateNullableArrayPropertyWithoutDefaultValue',
241
                'privateIterablePropertyWithoutDefaultValue',
242
                'privateNullableIterablePropertyWithoutDefaultValue',
243
                'privateObjectProperty',
244
                'privateNullableObjectProperty',
245
                'privateClassProperty',
246
                'privateNullableClassProperty',
247
            ],
248
            array_values(array_map(static function (ReflectionProperty $property) : string {
249
                return $property->getName();
250
            }, $nonReferenceableProperties))
251
        );
252
    }
253
254
    public function testGetProtectedPropertiesSkipsAbstractMethods() : void
255
    {
256
        $properties = Properties::fromReflectionClass(new ReflectionClass(ClassWithAbstractProtectedMethod::class));
257
258
        self::assertEmpty($properties->getProtectedProperties());
259
    }
260
261
    public function testGetPrivateProperties() : void
262
    {
263
        $properties = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedProperties::class));
264
265
        $privateProperties = $properties->getPrivateProperties();
266
267
        self::assertCount(3, $privateProperties);
268
269
        $prefix = "\0" . ClassWithMixedProperties::class . "\0";
270
271
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'privateProperty0']);
272
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'privateProperty1']);
273
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'privateProperty2']);
274
    }
275
276
    public function testGetPrivatePropertiesFromInheritance() : void
277
    {
278
        $properties = Properties::fromReflectionClass(
279
            new ReflectionClass(ClassWithCollidingPrivateInheritedProperties::class)
280
        );
281
282
        $privateProperties = $properties->getPrivateProperties();
283
284
        self::assertCount(11, $privateProperties);
285
286
        $prefix = "\0" . ClassWithCollidingPrivateInheritedProperties::class . "\0";
287
288
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property0']);
289
290
        $prefix = "\0" . ClassWithPrivateProperties::class . "\0";
291
292
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property0']);
293
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property1']);
294
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property2']);
295
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property3']);
296
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property4']);
297
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property5']);
298
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property6']);
299
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property7']);
300
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property8']);
301
        self::assertInstanceOf(ReflectionProperty::class, $privateProperties[$prefix . 'property9']);
302
    }
303
304
    public function testGetAccessibleMethods() : void
305
    {
306
        $properties           = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedProperties::class));
307
        $accessibleProperties = $properties->getAccessibleProperties();
308
309
        self::assertCount(6, $accessibleProperties);
310
        self::assertInstanceOf(ReflectionProperty::class, $accessibleProperties['publicProperty0']);
311
        self::assertInstanceOf(ReflectionProperty::class, $accessibleProperties['publicProperty1']);
312
        self::assertInstanceOf(ReflectionProperty::class, $accessibleProperties['publicProperty2']);
313
        self::assertInstanceOf(ReflectionProperty::class, $accessibleProperties["\0*\0protectedProperty0"]);
314
        self::assertInstanceOf(ReflectionProperty::class, $accessibleProperties["\0*\0protectedProperty1"]);
315
        self::assertInstanceOf(ReflectionProperty::class, $accessibleProperties["\0*\0protectedProperty2"]);
316
    }
317
318
    public function testGetGroupedPrivateProperties() : void
319
    {
320
        $properties     = Properties::fromReflectionClass(new ReflectionClass(ClassWithMixedProperties::class));
321
        $groupedPrivate = $properties->getGroupedPrivateProperties();
322
323
        self::assertCount(1, $groupedPrivate);
324
325
        $group = $groupedPrivate[ClassWithMixedProperties::class];
326
327
        self::assertCount(3, $group);
328
329
        self::assertInstanceOf(ReflectionProperty::class, $group['privateProperty0']);
330
        self::assertInstanceOf(ReflectionProperty::class, $group['privateProperty1']);
331
        self::assertInstanceOf(ReflectionProperty::class, $group['privateProperty2']);
332
    }
333
334
    public function testGetGroupedPrivatePropertiesWithInheritedProperties() : void
335
    {
336
        $properties = Properties::fromReflectionClass(
337
            new ReflectionClass(ClassWithCollidingPrivateInheritedProperties::class)
338
        );
339
340
        $groupedPrivate = $properties->getGroupedPrivateProperties();
341
342
        self::assertCount(2, $groupedPrivate);
343
344
        $group1 = $groupedPrivate[ClassWithCollidingPrivateInheritedProperties::class];
345
        $group2 = $groupedPrivate[ClassWithPrivateProperties::class];
346
347
        self::assertCount(1, $group1);
348
        self::assertCount(10, $group2);
349
350
        self::assertInstanceOf(ReflectionProperty::class, $group1['property0']);
351
        self::assertInstanceOf(ReflectionProperty::class, $group2['property0']);
352
        self::assertInstanceOf(ReflectionProperty::class, $group2['property1']);
353
        self::assertInstanceOf(ReflectionProperty::class, $group2['property2']);
354
        self::assertInstanceOf(ReflectionProperty::class, $group2['property3']);
355
        self::assertInstanceOf(ReflectionProperty::class, $group2['property4']);
356
        self::assertInstanceOf(ReflectionProperty::class, $group2['property5']);
357
        self::assertInstanceOf(ReflectionProperty::class, $group2['property6']);
358
        self::assertInstanceOf(ReflectionProperty::class, $group2['property7']);
359
        self::assertInstanceOf(ReflectionProperty::class, $group2['property8']);
360
        self::assertInstanceOf(ReflectionProperty::class, $group2['property9']);
361
    }
362
363
    public function testGetInstanceProperties() : void
364
    {
365
        $properties = Properties::fromReflectionClass(
366
            new ReflectionClass(ClassWithMixedProperties::class)
367
        );
368
369
        self::assertCount(9, $properties->getInstanceProperties());
370
    }
371
372
    /**
373
     * @dataProvider propertiesToSkipFixture
374
     *
375
     * @param string $propertyName with property name
376
     */
377
    public function testSkipPropertiesByFiltering(string $propertyName) : void
378
    {
379
        $properties = Properties::fromReflectionClass(
380
            new ReflectionClass(ClassWithMixedProperties::class)
381
        );
382
383
        self::assertArrayHasKey($propertyName, $properties->getInstanceProperties());
384
        $filteredProperties =  $properties->filter([$propertyName]);
385
386
        self::assertArrayNotHasKey($propertyName, $filteredProperties->getInstanceProperties());
387
    }
388
389
    public function testSkipOverwritedPropertyUsingInheritance() : void
390
    {
391
        $propertyName = "\0ProxyManagerTestAsset\\ClassWithCollidingPrivateInheritedProperties\0property0";
392
393
        $properties = Properties::fromReflectionClass(
394
            new ReflectionClass(ClassWithCollidingPrivateInheritedProperties::class)
395
        );
396
397
        self::assertArrayHasKey($propertyName, $properties->getInstanceProperties());
398
        $filteredProperties =  $properties->filter([$propertyName]);
399
400
        self::assertArrayNotHasKey($propertyName, $filteredProperties->getInstanceProperties());
401
    }
402
403
    public function testPropertiesIsSkippedFromRelatedMethods() : void
404
    {
405
        $properties = Properties::fromReflectionClass(
406
            new ReflectionClass(ClassWithMixedProperties::class)
407
        );
408
409
        self::assertArrayHasKey("\0*\0protectedProperty0", $properties->getProtectedProperties());
410
        self::assertArrayHasKey("\0*\0protectedProperty0", $properties->getInstanceProperties());
411
        $filteredProperties =  $properties->filter(["\0*\0protectedProperty0"]);
412
413
        self::assertArrayNotHasKey("\0*\0protectedProperty0", $filteredProperties->getProtectedProperties());
414
        self::assertArrayNotHasKey("\0*\0protectedProperty0", $filteredProperties->getInstanceProperties());
415
    }
416
417
    /** @return string[][] */
418
    public function propertiesToSkipFixture() : array
419
    {
420
        return [
421
            ['publicProperty0'],
422
            ["\0*\0protectedProperty0"],
423
            ["\0ProxyManagerTestAsset\\ClassWithMixedProperties\0privateProperty0"],
424
        ];
425
    }
426
}
427