Completed
Push — master ( 036050...37c720 )
by Marco
44:06 queued 19:08
created

testWithoutNonReferenceableProperties()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

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