getProxyTestedClasses()   B
last analyzed

Complexity

Conditions 5
Paths 1

Size

Total Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 40
rs 8.9688
c 0
b 0
f 0
cc 5
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ProxyManagerTest\Functional;
6
7
use PHPUnit\Framework\TestCase;
8
use ProxyManager\Exception\ExceptionInterface;
9
use ProxyManager\Generator\ClassGenerator;
10
use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
11
use ProxyManager\Proxy\ProxyInterface;
12
use ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizerGenerator;
13
use ProxyManager\ProxyGenerator\AccessInterceptorValueHolderGenerator;
14
use ProxyManager\ProxyGenerator\LazyLoadingGhostGenerator;
15
use ProxyManager\ProxyGenerator\LazyLoadingValueHolderGenerator;
16
use ProxyManager\ProxyGenerator\NullObjectGenerator;
17
use ProxyManager\ProxyGenerator\ProxyGeneratorInterface;
18
use ProxyManager\ProxyGenerator\RemoteObjectGenerator;
19
use ProxyManager\Signature\ClassSignatureGenerator;
20
use ProxyManager\Signature\SignatureGenerator;
21
use ReflectionClass;
22
use ReflectionException;
23
use function array_filter;
24
use function array_map;
25
use function array_merge;
26
use function get_declared_classes;
27
use function realpath;
28
use function strpos;
29
use function uniqid;
30
31
/**
32
 * Verifies that proxy-manager will not attempt to `eval()` code that will cause fatal errors
33
 *
34
 * @group Functional
35
 * @coversNothing
36
 */
37
final class FatalPreventionFunctionalTest extends TestCase
38
{
39
    /**
40
     * Verifies that code generation and evaluation will not cause fatals with any given class
41
     *
42
     * @param string $generatorClass an instantiable class (no arguments) implementing
43
     *                               the {@see \ProxyManager\ProxyGenerator\ProxyGeneratorInterface}
44
     * @param string $className      a valid (existing/autoloadable) class name
45
     *
46
     * @dataProvider getTestedClasses
47
     *
48
     * @psalm-param class-string<ProxyGeneratorInterface> $generatorClass
49
     * @psalm-param class-string                          $className
50
     */
51
    public function testCodeGeneration(string $generatorClass, string $className) : void
52
    {
53
        $generatedClass          = new ClassGenerator(uniqid('generated', true));
54
        $generatorStrategy       = new EvaluatingGeneratorStrategy();
55
        $classGenerator          = new $generatorClass();
56
        $classSignatureGenerator = new ClassSignatureGenerator(new SignatureGenerator());
57
58
        try {
59
            $classGenerator->generate(new ReflectionClass($className), $generatedClass);
60
            $classSignatureGenerator->addSignature($generatedClass, ['key' => 'eval tests']);
61
            $generatorStrategy->generate($generatedClass);
62
        } catch (ExceptionInterface $e) {
63
            // empty catch: this is actually a supported failure
64
        } catch (ReflectionException $e) {
65
            // empty catch: this is actually a supported failure
66
        }
67
68
        self::assertTrue(true, 'Code generation succeeded: proxy is valid or couldn\'t be generated at all');
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...eventionFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
69
    }
70
71
    /**
72
     * @return string[][]
73
     *
74
     * @psalm-return array<int, array<int, class-string<ProxyGeneratorInterface>|class-string>>
75
     */
76
    public function getTestedClasses() : array
77
    {
78
        return array_merge(
79
            [],
80
            ...array_map(
81
                function ($generator) : array {
82
                    return array_map(
83
                        static function ($class) use ($generator) : array {
84
                            return [$generator, $class];
85
                        },
86
                        $this->getProxyTestedClasses()
87
                    );
88
                },
89
                [
90
                    AccessInterceptorScopeLocalizerGenerator::class,
91
                    AccessInterceptorValueHolderGenerator::class,
92
                    LazyLoadingGhostGenerator::class,
93
                    LazyLoadingValueHolderGenerator::class,
94
                    NullObjectGenerator::class,
95
                    RemoteObjectGenerator::class,
96
                ]
97
            )
98
        );
99
    }
100
101
    /**
102
     * @return string[]
103
     *
104
     * @psalm-return array<int, class-string>
105
     *
106
     * @private (public only for PHP 5.3 compatibility)
107
     */
108
    private function getProxyTestedClasses() : array
109
    {
110
        $skippedPaths = [
111
            realpath(__DIR__ . '/../../../src'),
112
            realpath(__DIR__ . '/../../../vendor'),
113
            realpath(__DIR__ . '/../../ProxyManagerTest'),
114
        ];
115
116
        return array_filter(
117
            get_declared_classes(),
118
            static function ($className) use ($skippedPaths) : bool {
119
                $reflectionClass = new ReflectionClass($className);
120
121
                $fileName = $reflectionClass->getFileName();
122
123
                if (! $fileName) {
124
                    return false;
125
                }
126
127
                if ($reflectionClass->implementsInterface(ProxyInterface::class)) {
128
                    return false;
129
                }
130
131
                $realPath = realpath($fileName);
132
133
                self::assertIsString($realPath);
0 ignored issues
show
Bug introduced by
The method assertIsString() does not seem to exist on object<ProxyManagerTest\...eventionFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
134
135
                foreach ($skippedPaths as $skippedPath) {
136
                    self::assertIsString($skippedPath);
0 ignored issues
show
Bug introduced by
The method assertIsString() does not seem to exist on object<ProxyManagerTest\...eventionFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
137
138
                    if (strpos($realPath, $skippedPath) === 0) {
139
                        // skip classes defined within ProxyManager, vendor or the test suite
140
                        return false;
141
                    }
142
                }
143
144
                return true;
145
            }
146
        );
147
    }
148
}
149