Completed
Push — master ( 4e22dd...ea07d4 )
by Marco
8s
created

E2EInstaller::execComposerInDir()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 1
eloc 7
nc 1
nop 2
1
<?php
2
3
namespace PackageVersionsTest;
4
5
use PHPUnit_Framework_TestCase;
6
use RecursiveCallbackFilterIterator;
7
use RecursiveDirectoryIterator;
8
use RecursiveIteratorIterator;
9
use SplFileInfo;
10
use ZipArchive;
11
12
/**
13
 * @coversNothing
14
 */
15
class E2EInstaller extends PHPUnit_Framework_TestCase
16
{
17
    /**
18
     * @var string
19
     */
20
    private $tempGlobalComposerHome;
21
22
    /**
23
     * @var string
24
     */
25
    private $tempLocalComposerHome;
26
27
    /**
28
     * @var string
29
     */
30
    private $tempArtifact;
31
32
    public function setUp()
33
    {
34
        $this->tempGlobalComposerHome = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true) . '/global';
35
        $this->tempLocalComposerHome = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true) . '/local';
36
        $this->tempArtifact = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true) . '/artifacts';
37
        mkdir($this->tempGlobalComposerHome, 0700, true);
38
        mkdir($this->tempLocalComposerHome, 0700, true);
39
        mkdir($this->tempArtifact, 0700, true);
40
41
        putenv('COMPOSER_HOME=' . $this->tempGlobalComposerHome);
42
    }
43
44
    public function tearDown()
45
    {
46
        $this->rmDir($this->tempGlobalComposerHome);
47
        $this->rmDir($this->tempLocalComposerHome);
48
        $this->rmDir($this->tempArtifact);
49
50
        putenv('COMPOSER_HOME');
51
    }
52
53
    public function testGloballyInstalledPluginDoesNotGenerateVersionsForLocalProject()
54
    {
55
        $this->createPackageVersionsArtifact();
56
57
        $this->writeComposerJsonFile(
58
            [
59
                'name'         => 'package-versions/e2e-global',
60
                'require'      => [
61
                    'ocramius/package-versions' => '1.0.0'
62
                ],
63
                'repositories' => [
64
                    [
65
                        'packagist' => false,
66
                    ],
67
                    [
68
                        'type' => 'artifact',
69
                        'url' => $this->tempArtifact,
70
                    ]
71
                ]
72
            ],
73
            $this->tempGlobalComposerHome
74
        );
75
76
        $this->execComposerInDir('global update', $this->tempGlobalComposerHome);
77
78
        $this->createArtifact();
79
        $this->writeComposerJsonFile(
80
            [
81
                'name'         => 'package-versions/e2e-local',
82
                'require'      => [
83
                    'test/package' => '2.0.0'
84
                ],
85
                'repositories' => [
86
                    [
87
                        'packagist' => false,
88
                    ],
89
                    [
90
                        'type' => 'artifact',
91
                        'url' => $this->tempArtifact,
92
                    ]
93
                ]
94
            ],
95
            $this->tempLocalComposerHome
96
        );
97
98
        $this->execComposerInDir('update', $this->tempLocalComposerHome);
99
        $this->assertFileNotExists(
100
            $this->tempLocalComposerHome . '/vendor/ocramius/package-versions/src/PackageVersions/Versions.php'
101
        );
102
    }
103
104
    public function testRemovingPluginDoesNotAttemptToGenerateVersions()
105
    {
106
        $this->createPackageVersionsArtifact();
107
        $this->createArtifact();
108
109
        $this->writeComposerJsonFile(
110
            [
111
                'name'         => 'package-versions/e2e-local',
112
                'require'      => [
113
                    'test/package' => '2.0.0',
114
                    'ocramius/package-versions' => '1.0.0'
115
                ],
116
                'repositories' => [
117
                    [
118
                        'packagist' => false,
119
                    ],
120
                    [
121
                        'type' => 'artifact',
122
                        'url' => $this->tempArtifact,
123
                    ]
124
                ]
125
            ],
126
            $this->tempLocalComposerHome
127
        );
128
129
        $this->execComposerInDir('update', $this->tempLocalComposerHome);
130
        $this->assertFileExists(
131
            $this->tempLocalComposerHome . '/vendor/ocramius/package-versions/src/PackageVersions/Versions.php'
132
        );
133
134
        $this->execComposerInDir('remove ocramius/package-versions', $this->tempLocalComposerHome);
135
136
        $this->assertFileNotExists(
137
            $this->tempLocalComposerHome . '/vendor/ocramius/package-versions/src/PackageVersions/Versions.php'
138
        );
139
    }
140
141
    private function createPackageVersionsArtifact()
142
    {
143
        $zip = new ZipArchive();
144
145
        $zip->open($this->tempArtifact . '/ocramius-package-versions-1.0.0.zip', ZipArchive::CREATE);
146
147
        $files = array_filter(
148
            iterator_to_array(new RecursiveIteratorIterator(
149
                new RecursiveCallbackFilterIterator(
150
                    new RecursiveDirectoryIterator(realpath(__DIR__ . '/../../'), RecursiveDirectoryIterator::SKIP_DOTS),
151
                    function (SplFileInfo $file, $key, RecursiveDirectoryIterator $iterator) {
152
                        return $iterator->getSubPathname()[0]  !== '.' && $iterator->getSubPathname() !== 'vendor';
153
                    }
154
                ),
155
                RecursiveIteratorIterator::LEAVES_ONLY
156
            )),
157
            function (SplFileInfo $file) {
158
                return !$file->isDir();
159
            }
160
        );
161
162
        array_walk(
163
            $files,
164
            function (SplFileInfo $file) use ($zip) {
165
                if ($file->getFilename() === 'composer.json') {
166
                    $contents = json_decode(file_get_contents($file->getRealPath()), true);
167
                    $contents['version'] = '1.0.0';
168
169
                    return $zip->addFromString('composer.json', json_encode($contents));
170
                }
171
172
                $zip->addFile(
173
                    $file->getRealPath(),
174
                    substr($file->getRealPath(), strlen(realpath(__DIR__ . '/../../')) + 1)
175
                );
176
            }
177
        );
178
179
        $zip->close();
180
    }
181
182
    private function createArtifact()
183
    {
184
        $zip = new ZipArchive();
185
186
        $zip->open($this->tempArtifact . '/test-package-2.0.0.zip', ZipArchive::CREATE);
187
        $zip->addFromString(
188
            'composer.json',
189
            json_encode(
190
                [
191
                    'name'    => 'test/package',
192
                    'version' => '2.0.0'
193
                ],
194
                JSON_PRETTY_PRINT
195
            )
196
        );
197
        $zip->close();
198
    }
199
200
    private function writeComposerJsonFile(array $config, string $directory)
201
    {
202
        file_put_contents(
203
            $directory . '/composer.json',
204
            json_encode($config, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)
205
        );
206
    }
207
208
    private function execComposerInDir(string $command, string $dir) : array
209
    {
210
        $currentDir = getcwd();
211
        chdir($dir);
212
        exec(__DIR__ . '/../../vendor/bin/composer ' . $command . ' 2> /dev/null', $output, $exitCode);
213
        $this->assertEquals(0, $exitCode);
214
        chdir($currentDir);
215
        return $output;
216
    }
217
218
    /**
219
     * @param string $directory
220
     *
221
     * @return void
222
     */
223
    private function rmDir(string $directory)
224
    {
225
        if (! is_dir($directory)) {
226
            unlink($directory);
227
228
            return;
229
        }
230
231
        array_map(
232
            function ($item) use ($directory) {
233
                $this->rmDir($directory . '/' . $item);
234
            },
235
            array_filter(
236
                scandir($directory),
237
                function (string $dirItem) {
238
                    return ! in_array($dirItem, ['.', '..'], true);
239
                }
240
            )
241
        );
242
243
        rmdir($directory);
244
    }
245
}
246