Completed
Pull Request — master (#438)
by
unknown
09:55
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
 *
34
 * Note: this test generates temporary files that are not deleted
35
 */
36
class FileWriterGeneratorStrategyTest extends TestCase
37
{
38
    /** @var string */
39
    private $tempDir;
40
41
    protected function setUp() : void
42
    {
43
        $this->tempDir = sys_get_temp_dir() . '/' . self::class;
44
45
        if (! is_dir($this->tempDir)) {
46
            mkdir($this->tempDir);
47
        }
48
49
        ini_set('open_basedir', __DIR__ . '/../../..' . PATH_SEPARATOR . $this->tempDir);
50
    }
51
52
    public function testGenerate() : void
53
    {
54
        /** @var FileLocatorInterface|\PHPUnit_Framework_MockObject_MockObject $locator */
55
        $locator   = $this->createMock(FileLocatorInterface::class);
56
        $generator = new FileWriterGeneratorStrategy($locator);
57
        $tmpFile   = $this->tempDir . '/' . uniqid('FileWriterGeneratorStrategyTest', true) . '.php';
58
        $namespace = 'Foo';
59
        $className = UniqueIdentifierGenerator::getIdentifier('Bar');
60
        $fqcn      = $namespace . '\\' . $className;
61
62
        $locator
63
            ->expects(self::any())
64
            ->method('getProxyFileName')
65
            ->with($fqcn)
66
            ->will(self::returnValue($tmpFile));
67
68
        $body = $generator->generate(new ClassGenerator($fqcn));
69
70
        self::assertGreaterThan(0, strpos($body, $className));
71
        self::assertFalse(class_exists($fqcn, false));
72
        self::assertFileExists($tmpFile);
73
        self::assertFileIsReadable($tmpFile);
74
75
        // a user note on php.net recommended calling this as we have just called chmod on a file.
76
        clearstatcache();
77
78
        // Calculate the permission that should have been set.
79
        // The operators below are bit-wise "AND" (&) and "NOT" (~), read more at: http://php.net/manual/en/language.operators.bitwise.php
80
        $perm = 0666 & ~umask();
81
82
        self::assertSame($perm, fileperms($tmpFile) & 0777, 'File permission was not correct: ' . decoct($perm));
83
84
        /* @noinspection PhpIncludeInspection */
85
        require $tmpFile;
86
87
        self::assertTrue(class_exists($fqcn, false));
88
    }
89
90
    public function testGenerateWillFailIfTmpFileCannotBeWrittenToDisk() : void
91
    {
92
        $tmpDirPath = $this->tempDir . '/' . uniqid('nonWritable', true);
93
        mkdir($tmpDirPath, 0555, true);
94
95
        /** @var FileLocatorInterface|\PHPUnit_Framework_MockObject_MockObject $locator */
96
        $locator   = $this->createMock(FileLocatorInterface::class);
97
        $generator = new FileWriterGeneratorStrategy($locator);
98
        $tmpFile   = $tmpDirPath . '/' . uniqid('FileWriterGeneratorStrategyFailedFileWriteTest', true) . '.php';
99
        $namespace = 'Foo';
100
        $className = UniqueIdentifierGenerator::getIdentifier('Bar');
101
        $fqcn      = $namespace . '\\' . $className;
102
103
        $locator
104
            ->expects(self::any())
105
            ->method('getProxyFileName')
106
            ->with($fqcn)
107
            ->will(self::returnValue($tmpFile));
108
109
        $this->expectException(FileNotWritableException::class);
110
        $generator->generate(new ClassGenerator($fqcn));
111
    }
112
113
    public function testGenerateWillFailIfTmpFileCannotBeMovedToFinalDestination() : void
114
    {
115
        /** @var FileLocatorInterface|\PHPUnit_Framework_MockObject_MockObject $locator */
116
        $locator   = $this->createMock(FileLocatorInterface::class);
117
        $generator = new FileWriterGeneratorStrategy($locator);
118
        $tmpFile   = $this->tempDir . '/' . uniqid('FileWriterGeneratorStrategyFailedFileMoveTest', true) . '.php';
119
        $namespace = 'Foo';
120
        $className = UniqueIdentifierGenerator::getIdentifier('Bar');
121
        $fqcn      = $namespace . '\\' . $className;
122
123
        $locator
124
            ->expects(self::any())
125
            ->method('getProxyFileName')
126
            ->with($fqcn)
127
            ->will(self::returnValue($tmpFile));
128
129
        mkdir($tmpFile);
130
131
        $this->expectException(FileNotWritableException::class);
132
        $generator->generate(new ClassGenerator($fqcn));
133
    }
134
135
    public function testWhenFailingAllTemporaryFilesAreRemoved() : void
136
    {
137
        $tmpDirPath = $this->tempDir . '/' . uniqid('noTempFilesLeftBehind', true);
138
139
        mkdir($tmpDirPath);
140
141
        /** @var FileLocatorInterface|\PHPUnit_Framework_MockObject_MockObject $locator */
142
        $locator   = $this->createMock(FileLocatorInterface::class);
143
        $generator = new FileWriterGeneratorStrategy($locator);
144
        $tmpFile   = $tmpDirPath . '/' . uniqid('FileWriterGeneratorStrategyFailedFileMoveTest', true) . '.php';
145
        $namespace = 'Foo';
146
        $className = UniqueIdentifierGenerator::getIdentifier('Bar');
147
        $fqcn      = $namespace . '\\' . $className;
148
149
        $locator
150
            ->expects(self::any())
151
            ->method('getProxyFileName')
152
            ->with($fqcn)
153
            ->will(self::returnValue($tmpFile));
154
155
        mkdir($tmpFile);
156
157
        try {
158
            $generator->generate(new ClassGenerator($fqcn));
159
160
            self::fail('An exception was supposed to be thrown');
161
        } catch (FileNotWritableException $exception) {
162
            rmdir($tmpFile);
163
164
            self::assertEquals(['.', '..'], scandir($tmpDirPath));
165
        }
166
    }
167
}
168