Completed
Push — master ( 483be6...2f25cf )
by Marco
04:50
created

FileWriterGeneratorStrategyTest::setUp()   A

Complexity

Conditions 2
Paths 2

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 2
nc 2
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ProxyManagerTest\GeneratorStrategy;
6
7
use PHPUnit\Framework\TestCase;
8
use ProxyManager\Exception\FileNotWritableException;
9
use ProxyManager\FileLocator\FileLocatorInterface;
10
use ProxyManager\Generator\ClassGenerator;
11
use ProxyManager\Generator\Util\UniqueIdentifierGenerator;
12
use ProxyManager\GeneratorStrategy\FileWriterGeneratorStrategy;
13
use const PATH_SEPARATOR;
14
use function class_exists;
15
use function clearstatcache;
16
use function decoct;
17
use function fileperms;
18
use function ini_set;
19
use function is_dir;
20
use function mkdir;
21
use function rmdir;
22
use function scandir;
23
use function strpos;
24
use function sys_get_temp_dir;
25
use function umask;
26
use function uniqid;
27
28
/**
29
 * Tests for {@see \ProxyManager\GeneratorStrategy\FileWriterGeneratorStrategy}
30
 *
31
 * @group Coverage
32
 * @covers \ProxyManager\GeneratorStrategy\FileWriterGeneratorStrategy
33
 * @runTestsInSeparateProcesses
34
 *
35
 * Note: this test generates temporary files that are not deleted
36
 */
37
class FileWriterGeneratorStrategyTest extends TestCase
38
{
39
    /** @var string */
40
    private $tempDir;
41
42
    protected function setUp() : void
43
    {
44
        $this->tempDir = sys_get_temp_dir() . '/' . uniqid('FileWriterGeneratorStrategyTest', true);
45
46
        if (! is_dir($this->tempDir)) {
47
            mkdir($this->tempDir);
48
        }
49
50
        ini_set('open_basedir', __DIR__ . '/../../..' . PATH_SEPARATOR . $this->tempDir);
51
    }
52
53
    public function testGenerate() : void
54
    {
55
        /** @var FileLocatorInterface|\PHPUnit_Framework_MockObject_MockObject $locator */
56
        $locator   = $this->createMock(FileLocatorInterface::class);
57
        $generator = new FileWriterGeneratorStrategy($locator);
58
        $tmpFile   = $this->tempDir . '/' . uniqid('FileWriterGeneratorStrategyTest', true) . '.php';
59
        $namespace = 'Foo';
60
        $className = UniqueIdentifierGenerator::getIdentifier('Bar');
61
        $fqcn      = $namespace . '\\' . $className;
62
63
        $locator
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<ProxyManager\File...r\FileLocatorInterface>.

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...
64
            ->expects(self::any())
65
            ->method('getProxyFileName')
66
            ->with($fqcn)
67
            ->will(self::returnValue($tmpFile));
68
69
        $body = $generator->generate(new ClassGenerator($fqcn));
70
71
        self::assertGreaterThan(0, strpos($body, $className));
72
        self::assertFalse(class_exists($fqcn, false));
73
        self::assertFileExists($tmpFile);
74
        self::assertFileIsReadable($tmpFile);
75
76
        // a user note on php.net recommended calling this as we have just called chmod on a file.
77
        clearstatcache();
78
79
        // Calculate the permission that should have been set.
80
        // The operators below are bit-wise "AND" (&) and "NOT" (~), read more at: http://php.net/manual/en/language.operators.bitwise.php
81
        $perm = 0666 & ~umask();
82
83
        self::assertSame($perm, fileperms($tmpFile) & 0777, 'File permission was not correct: ' . decoct($perm));
84
85
        /* @noinspection PhpIncludeInspection */
86
        require $tmpFile;
87
88
        self::assertTrue(class_exists($fqcn, false));
89
    }
90
91
    public function testGenerateWillFailIfTmpFileCannotBeWrittenToDisk() : void
92
    {
93
        $tmpDirPath = $this->tempDir . '/' . uniqid('nonWritable', true);
94
        mkdir($tmpDirPath, 0555, true);
95
96
        /** @var FileLocatorInterface|\PHPUnit_Framework_MockObject_MockObject $locator */
97
        $locator   = $this->createMock(FileLocatorInterface::class);
98
        $generator = new FileWriterGeneratorStrategy($locator);
99
        $tmpFile   = $tmpDirPath . '/' . uniqid('FileWriterGeneratorStrategyFailedFileWriteTest', true) . '.php';
100
        $namespace = 'Foo';
101
        $className = UniqueIdentifierGenerator::getIdentifier('Bar');
102
        $fqcn      = $namespace . '\\' . $className;
103
104
        $locator
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<ProxyManager\File...r\FileLocatorInterface>.

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...
105
            ->expects(self::any())
106
            ->method('getProxyFileName')
107
            ->with($fqcn)
108
            ->will(self::returnValue($tmpFile));
109
110
        $this->expectException(FileNotWritableException::class);
111
        $generator->generate(new ClassGenerator($fqcn));
112
    }
113
114
    public function testGenerateWillFailIfTmpFileCannotBeMovedToFinalDestination() : void
115
    {
116
        /** @var FileLocatorInterface|\PHPUnit_Framework_MockObject_MockObject $locator */
117
        $locator   = $this->createMock(FileLocatorInterface::class);
118
        $generator = new FileWriterGeneratorStrategy($locator);
119
        $tmpFile   = $this->tempDir . '/' . uniqid('FileWriterGeneratorStrategyFailedFileMoveTest', true) . '.php';
120
        $namespace = 'Foo';
121
        $className = UniqueIdentifierGenerator::getIdentifier('Bar');
122
        $fqcn      = $namespace . '\\' . $className;
123
124
        $locator
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<ProxyManager\File...r\FileLocatorInterface>.

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...
125
            ->expects(self::any())
126
            ->method('getProxyFileName')
127
            ->with($fqcn)
128
            ->will(self::returnValue($tmpFile));
129
130
        mkdir($tmpFile);
131
132
        $this->expectException(FileNotWritableException::class);
133
        $generator->generate(new ClassGenerator($fqcn));
134
    }
135
136
    public function testWhenFailingAllTemporaryFilesAreRemoved() : void
137
    {
138
        $tmpDirPath = $this->tempDir . '/' . uniqid('noTempFilesLeftBehind', true);
139
140
        mkdir($tmpDirPath);
141
142
        /** @var FileLocatorInterface|\PHPUnit_Framework_MockObject_MockObject $locator */
143
        $locator   = $this->createMock(FileLocatorInterface::class);
144
        $generator = new FileWriterGeneratorStrategy($locator);
145
        $tmpFile   = $tmpDirPath . '/' . uniqid('FileWriterGeneratorStrategyFailedFileMoveTest', true) . '.php';
146
        $namespace = 'Foo';
147
        $className = UniqueIdentifierGenerator::getIdentifier('Bar');
148
        $fqcn      = $namespace . '\\' . $className;
149
150
        $locator
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<ProxyManager\File...r\FileLocatorInterface>.

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...
151
            ->expects(self::any())
152
            ->method('getProxyFileName')
153
            ->with($fqcn)
154
            ->will(self::returnValue($tmpFile));
155
156
        mkdir($tmpFile);
157
158
        try {
159
            $generator->generate(new ClassGenerator($fqcn));
160
161
            self::fail('An exception was supposed to be thrown');
162
        } catch (FileNotWritableException $exception) {
163
            rmdir($tmpFile);
164
165
            self::assertEquals(['.', '..'], scandir($tmpDirPath));
166
        }
167
    }
168
}
169