Completed
Push — master ( b300ac...74322c )
by Marco
9s
created

InstallerTest::testActivate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
dl 0
loc 6
rs 9.4285
c 3
b 0
f 0
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
3
namespace PackageVersionsTest;
4
5
use Composer\Composer;
6
use Composer\Config;
7
use Composer\EventDispatcher\EventDispatcher;
8
use Composer\Installer\InstallationManager;
9
use Composer\IO\IOInterface;
10
use Composer\Package\Locker;
11
use Composer\Package\RootAliasPackage;
12
use Composer\Package\RootPackage;
13
use Composer\Package\RootPackageInterface;
14
use Composer\Repository\InstalledRepositoryInterface;
15
use Composer\Repository\RepositoryManager;
16
use Composer\Script\Event;
17
use PackageVersions\Installer;
18
use PHPUnit_Framework_TestCase;
19
20
/**
21
 * @covers \PackageVersions\Installer
22
 */
23
final class InstallerTest extends PHPUnit_Framework_TestCase
24
{
25
    /**
26
     * @var Composer|\PHPUnit_Framework_MockObject_MockObject
27
     */
28
    private $composer;
29
30
    /**
31
     * @var EventDispatcher|\PHPUnit_Framework_MockObject_MockObject
32
     */
33
    private $eventDispatcher;
34
35
    /**
36
     * @var IOInterface|\PHPUnit_Framework_MockObject_MockObject
37
     */
38
    private $io;
39
40
    /**
41
     * @var Installer
42
     */
43
    private $installer;
44
45
    /**
46
     * {@inheritDoc}
47
     *
48
     * @throws \PHPUnit_Framework_Exception
49
     */
50
    protected function setUp()
51
    {
52
        parent::setUp();
53
54
        $this->installer       = new Installer();
55
        $this->io              = $this->getMock(IOInterface::class);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::getMock() has been deprecated with message: Method deprecated since Release 5.4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
56
        $this->composer        = $this->getMock(Composer::class);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::getMock() has been deprecated with message: Method deprecated since Release 5.4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
57
        $this->eventDispatcher = $this->getMockBuilder(EventDispatcher::class)->disableOriginalConstructor()->getMock();
58
59
        $this->composer->expects(self::any())->method('getEventDispatcher')->willReturn($this->eventDispatcher);
60
    }
61
62
    public function testGetSubscribedEvents()
63
    {
64
        $events = Installer::getSubscribedEvents();
65
66
        self::assertSame(
67
            [
68
                'post-install-cmd' => 'dumpVersionsClass',
69
                'post-update-cmd'  => 'dumpVersionsClass',
70
            ],
71
            $events
72
        );
73
74
        foreach ($events as $callback) {
75
            self::assertInternalType('callable', [$this->installer, $callback]);
76
        }
77
    }
78
79
    public function testDumpVersionsClass()
80
    {
81
        $config            = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock();
82
        $locker            = $this->getMockBuilder(Locker::class)->disableOriginalConstructor()->getMock();
83
        $repositoryManager = $this->getMockBuilder(RepositoryManager::class)->disableOriginalConstructor()->getMock();
84
        $installManager    = $this->getMockBuilder(InstallationManager::class)->disableOriginalConstructor()->getMock();
85
        $repository        = $this->getMock(InstalledRepositoryInterface::class);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::getMock() has been deprecated with message: Method deprecated since Release 5.4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
86
        $package           = $this->getMock(RootPackageInterface::class);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::getMock() has been deprecated with message: Method deprecated since Release 5.4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
87
88
        $vendorDir = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true);
89
90
        $expectedPath = $vendorDir . '/ocramius/package-versions/src/PackageVersions';
91
92
        mkdir($expectedPath, 0777, true);
93
94
        $locker
95
            ->expects(self::any())
96
            ->method('getLockData')
97
            ->willReturn([
98
                'packages' => [
99
                    [
100
                        'name'    => 'foo/bar',
101
                        'version' => '1.2.3',
102
                        'source'  => [
103
                            'reference' => 'abc123',
104
                        ],
105
                    ],
106
                    [
107
                        'name'    => 'baz/tab',
108
                        'version' => '4.5.6',
109
                        'source'  => [
110
                            'reference' => 'def456',
111
                        ],
112
                    ],
113
                ],
114
                'packages-dev' => [
115
                    [
116
                        'name'    => 'tar/taz',
117
                        'version' => '7.8.9',
118
                        'source'  => [
119
                            'reference' => 'ghi789',
120
                        ],
121
                    ]
122
                ],
123
            ]);
124
125
        $repositoryManager->expects(self::any())->method('getLocalRepository')->willReturn($repository);
126
127
        $this->composer->expects(self::any())->method('getConfig')->willReturn($config);
128
        $this->composer->expects(self::any())->method('getLocker')->willReturn($locker);
129
        $this->composer->expects(self::any())->method('getRepositoryManager')->willReturn($repositoryManager);
130
        $this->composer->expects(self::any())->method('getPackage')->willReturn($package);
131
        $this->composer->expects(self::any())->method('getInstallationManager')->willReturn($installManager);
132
133
        $package->expects(self::any())->method('getName')->willReturn('root/package');
134
        $package->expects(self::any())->method('getVersion')->willReturn('1.3.5');
135
        $package->expects(self::any())->method('getSourceReference')->willReturn('aaabbbcccddd');
136
137
        $config->expects(self::any())->method('get')->with('vendor-dir')->willReturn($vendorDir);
138
139
        Installer::dumpVersionsClass(new Event(
140
            'post-install-cmd',
141
            $this->composer,
142
            $this->io
143
        ));
144
145
        $expectedSource = <<<'PHP'
146
<?php
147
148
namespace PackageVersions;
149
150
/**
151
 * This class is generated by ocramius/package-versions, specifically by
152
 * @see \PackageVersions\Installer
153
 *
154
 * This file is overwritten at every run of `composer install` or `composer update`.
155
 */
156
final class Versions
157
{
158
    const VERSIONS = array (
159
  'foo/bar' => '1.2.3@abc123',
160
  'baz/tab' => '4.5.6@def456',
161
  'tar/taz' => '7.8.9@ghi789',
162
  'root/package' => '1.3.5@aaabbbcccddd',
163
);
164
165
    private function __construct()
166
    {
167
    }
168
169
    /**
170
     * @throws \OutOfBoundsException if a version cannot be located
171
     */
172
    public static function getVersion(string $packageName) : string
173
    {
174
        if (! isset(self::VERSIONS[$packageName])) {
175
            throw new \OutOfBoundsException(
176
                'Required package "' . $packageName . '" is not installed: cannot detect its version'
177
            );
178
        }
179
180
        return self::VERSIONS[$packageName];
181
    }
182
}
183
184
PHP;
185
186
        self::assertSame($expectedSource, file_get_contents($expectedPath . '/Versions.php'));
187
188
        $this->rmDir($vendorDir);
189
    }
190
191
    public function testDumpVersionsClassNoDev()
192
    {
193
        $config            = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock();
194
        $locker            = $this->getMockBuilder(Locker::class)->disableOriginalConstructor()->getMock();
195
        $repositoryManager = $this->getMockBuilder(RepositoryManager::class)->disableOriginalConstructor()->getMock();
196
        $installManager    = $this->getMockBuilder(InstallationManager::class)->disableOriginalConstructor()->getMock();
197
        $repository        = $this->getMock(InstalledRepositoryInterface::class);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::getMock() has been deprecated with message: Method deprecated since Release 5.4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
198
        $package           = $this->getMock(RootPackageInterface::class);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::getMock() has been deprecated with message: Method deprecated since Release 5.4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
199
200
        $vendorDir = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true);
201
202
        $expectedPath = $vendorDir . '/ocramius/package-versions/src/PackageVersions';
203
204
        mkdir($expectedPath, 0777, true);
205
206
        $locker
207
            ->expects(self::any())
208
            ->method('getLockData')
209
            ->willReturn([
210
                'packages' => [
211
                    [
212
                        'name'    => 'foo/bar',
213
                        'version' => '1.2.3',
214
                        'source'  => [
215
                            'reference' => 'abc123',
216
                        ],
217
                    ],
218
                    [
219
                        'name'    => 'baz/tab',
220
                        'version' => '4.5.6',
221
                        'source'  => [
222
                            'reference' => 'def456',
223
                        ],
224
                    ],
225
                ],
226
            ]);
227
228
        $repositoryManager->expects(self::any())->method('getLocalRepository')->willReturn($repository);
229
230
        $this->composer->expects(self::any())->method('getConfig')->willReturn($config);
231
        $this->composer->expects(self::any())->method('getLocker')->willReturn($locker);
232
        $this->composer->expects(self::any())->method('getRepositoryManager')->willReturn($repositoryManager);
233
        $this->composer->expects(self::any())->method('getPackage')->willReturn($package);
234
        $this->composer->expects(self::any())->method('getInstallationManager')->willReturn($installManager);
235
236
        $package->expects(self::any())->method('getName')->willReturn('root/package');
237
        $package->expects(self::any())->method('getVersion')->willReturn('1.3.5');
238
        $package->expects(self::any())->method('getSourceReference')->willReturn('aaabbbcccddd');
239
240
        $config->expects(self::any())->method('get')->with('vendor-dir')->willReturn($vendorDir);
241
242
        Installer::dumpVersionsClass(new Event(
243
            'post-install-cmd',
244
            $this->composer,
245
            $this->io
246
        ));
247
248
        $expectedSource = <<<'PHP'
249
<?php
250
251
namespace PackageVersions;
252
253
/**
254
 * This class is generated by ocramius/package-versions, specifically by
255
 * @see \PackageVersions\Installer
256
 *
257
 * This file is overwritten at every run of `composer install` or `composer update`.
258
 */
259
final class Versions
260
{
261
    const VERSIONS = array (
262
  'foo/bar' => '1.2.3@abc123',
263
  'baz/tab' => '4.5.6@def456',
264
  'root/package' => '1.3.5@aaabbbcccddd',
265
);
266
267
    private function __construct()
268
    {
269
    }
270
271
    /**
272
     * @throws \OutOfBoundsException if a version cannot be located
273
     */
274
    public static function getVersion(string $packageName) : string
275
    {
276
        if (! isset(self::VERSIONS[$packageName])) {
277
            throw new \OutOfBoundsException(
278
                'Required package "' . $packageName . '" is not installed: cannot detect its version'
279
            );
280
        }
281
282
        return self::VERSIONS[$packageName];
283
    }
284
}
285
286
PHP;
287
288
        self::assertSame($expectedSource, file_get_contents($expectedPath . '/Versions.php'));
289
290
        $this->rmDir($vendorDir);
291
    }
292
293
    /**
294
     * @group #12
295
     *
296
     * @throws \RuntimeException
297
     */
298
    public function testDumpVersionsWithoutPackageSourceDetails()
299
    {
300
        $config            = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock();
301
        $locker            = $this->getMockBuilder(Locker::class)->disableOriginalConstructor()->getMock();
302
        $repositoryManager = $this->getMockBuilder(RepositoryManager::class)->disableOriginalConstructor()->getMock();
303
        $installManager    = $this->getMockBuilder(InstallationManager::class)->disableOriginalConstructor()->getMock();
304
        $repository        = $this->getMock(InstalledRepositoryInterface::class);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::getMock() has been deprecated with message: Method deprecated since Release 5.4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
305
        $package           = $this->getMock(RootPackageInterface::class);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::getMock() has been deprecated with message: Method deprecated since Release 5.4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
306
307
        $vendorDir = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true);
308
309
        $expectedPath = $vendorDir . '/ocramius/package-versions/src/PackageVersions';
310
311
        mkdir($expectedPath, 0777, true);
312
313
        $locker
314
            ->expects(self::any())
315
            ->method('getLockData')
316
            ->willReturn([
317
                'packages' => [
318
                    [
319
                        'name'    => 'foo/bar',
320
                        'version' => '1.2.3',
321
                        'dist'  => [
322
                            'reference' => 'abc123', // version defined in the dist, this time
323
                        ],
324
                    ],
325
                    [
326
                        'name'    => 'baz/tab',
327
                        'version' => '4.5.6', // source missing
328
                    ],
329
                ],
330
            ]);
331
332
        $repositoryManager->expects(self::any())->method('getLocalRepository')->willReturn($repository);
333
334
        $this->composer->expects(self::any())->method('getConfig')->willReturn($config);
335
        $this->composer->expects(self::any())->method('getLocker')->willReturn($locker);
336
        $this->composer->expects(self::any())->method('getRepositoryManager')->willReturn($repositoryManager);
337
        $this->composer->expects(self::any())->method('getPackage')->willReturn($package);
338
        $this->composer->expects(self::any())->method('getInstallationManager')->willReturn($installManager);
339
340
        $package->expects(self::any())->method('getName')->willReturn('root/package');
341
        $package->expects(self::any())->method('getVersion')->willReturn('1.3.5');
342
        $package->expects(self::any())->method('getSourceReference')->willReturn('aaabbbcccddd');
343
344
        $config->expects(self::any())->method('get')->with('vendor-dir')->willReturn($vendorDir);
345
346
        Installer::dumpVersionsClass(new Event(
347
            'post-install-cmd',
348
            $this->composer,
349
            $this->io
350
        ));
351
352
        $expectedSource = <<<'PHP'
353
<?php
354
355
namespace PackageVersions;
356
357
/**
358
 * This class is generated by ocramius/package-versions, specifically by
359
 * @see \PackageVersions\Installer
360
 *
361
 * This file is overwritten at every run of `composer install` or `composer update`.
362
 */
363
final class Versions
364
{
365
    const VERSIONS = array (
366
  'foo/bar' => '1.2.3@abc123',
367
  'baz/tab' => '4.5.6@',
368
  'root/package' => '1.3.5@aaabbbcccddd',
369
);
370
371
    private function __construct()
372
    {
373
    }
374
375
    /**
376
     * @throws \OutOfBoundsException if a version cannot be located
377
     */
378
    public static function getVersion(string $packageName) : string
379
    {
380
        if (! isset(self::VERSIONS[$packageName])) {
381
            throw new \OutOfBoundsException(
382
                'Required package "' . $packageName . '" is not installed: cannot detect its version'
383
            );
384
        }
385
386
        return self::VERSIONS[$packageName];
387
    }
388
}
389
390
PHP;
391
392
        self::assertSame($expectedSource, file_get_contents($expectedPath . '/Versions.php'));
393
394
        $this->rmDir($vendorDir);
395
    }
396
397
    /**
398
     * @dataProvider rootPackageProvider
399
     *
400
     * @param RootPackageInterface $rootPackage
401
     * @param bool                 $inVendor
402
     *
403
     * @throws \RuntimeException
404
     */
405
    public function testDumpsVersionsClassToSpecificLocation(RootPackageInterface $rootPackage, bool $inVendor)
406
    {
407
        $config            = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock();
408
        $locker            = $this->getMockBuilder(Locker::class)->disableOriginalConstructor()->getMock();
409
        $repositoryManager = $this->getMockBuilder(RepositoryManager::class)->disableOriginalConstructor()->getMock();
410
        $installManager    = $this->getMockBuilder(InstallationManager::class)->disableOriginalConstructor()->getMock();
411
        $repository        = $this->getMock(InstalledRepositoryInterface::class);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::getMock() has been deprecated with message: Method deprecated since Release 5.4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
412
413
        $vendorDir = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true) . '/vendor';
414
415
        mkdir($vendorDir, 0777, true);
416
417
        $expectedPath = $inVendor
418
            ? $vendorDir . '/ocramius/package-versions/src/PackageVersions'
419
            : realpath($vendorDir . '/..') . '/src/PackageVersions';
420
421
        mkdir($expectedPath, 0777, true);
422
423
        $locker
424
            ->expects(self::any())
425
            ->method('getLockData')
426
            ->willReturn([
427
                'packages' => [],
428
                'packages-dev' => [],
429
            ]);
430
431
        $repositoryManager->expects(self::any())->method('getLocalRepository')->willReturn($repository);
432
433
        $this->composer->expects(self::any())->method('getConfig')->willReturn($config);
434
        $this->composer->expects(self::any())->method('getLocker')->willReturn($locker);
435
        $this->composer->expects(self::any())->method('getRepositoryManager')->willReturn($repositoryManager);
436
        $this->composer->expects(self::any())->method('getPackage')->willReturn($rootPackage);
437
        $this->composer->expects(self::any())->method('getInstallationManager')->willReturn($installManager);
438
439
        $config->expects(self::any())->method('get')->with('vendor-dir')->willReturn($vendorDir);
440
441
        Installer::dumpVersionsClass(new Event(
442
            'post-install-cmd',
443
            $this->composer,
444
            $this->io
445
        ));
446
447
        self::assertStringMatchesFormat(
448
            '%Aclass Versions%A1.2.3@%A',
449
            file_get_contents($expectedPath . '/Versions.php')
450
        );
451
452
        $this->rmDir($vendorDir);
453
    }
454
455
    /**
456
     * @return bool[][]|RootPackageInterface[][] the root package and whether the versions class is to be generated in
457
     *                                           the vendor dir or not
458
     */
459
    public function rootPackageProvider() : array
460
    {
461
        $baseRootPackage                         = new RootPackage('root/package', '1.2.3', '1.2.3');
462
        $aliasRootPackage                        = new RootAliasPackage($baseRootPackage, '1.2.3', '1.2.3');
463
        $indirectAliasRootPackage                = new RootAliasPackage($aliasRootPackage, '1.2.3', '1.2.3');
464
        $packageVersionsRootPackage              = new RootPackage('ocramius/package-versions', '1.2.3', '1.2.3');
465
        $aliasPackageVersionsRootPackage         = new RootAliasPackage($packageVersionsRootPackage, '1.2.3', '1.2.3');
466
        $indirectAliasPackageVersionsRootPackage = new RootAliasPackage(
467
            $aliasPackageVersionsRootPackage,
468
            '1.2.3',
469
            '1.2.3'
470
        );
471
472
        return [
473
            'root package is not ocramius/package-versions' => [
474
                $baseRootPackage,
475
                true
476
            ],
477
            'alias root package is not ocramius/package-versions' => [
478
                $aliasRootPackage,
479
                true
480
            ],
481
            'indirect alias root package is not ocramius/package-versions' => [
482
                $indirectAliasRootPackage,
483
                true
484
            ],
485
            'root package is ocramius/package-versions' => [
486
                $packageVersionsRootPackage,
487
                false
488
            ],
489
            'alias root package is ocramius/package-versions' => [
490
                $aliasPackageVersionsRootPackage,
491
                false
492
            ],
493
            'indirect alias root package is ocramius/package-versions' => [
494
                $indirectAliasPackageVersionsRootPackage,
495
                false
496
            ],
497
        ];
498
    }
499
500
    /**
501
     * @param string $directory
502
     *
503
     * @return void
504
     */
505
    private function rmDir(string $directory)
506
    {
507
        if (! is_dir($directory)) {
508
            unlink($directory);
509
510
            return;
511
        }
512
513
        array_map(
514
            function ($item) use ($directory) {
515
                $this->rmDir($directory . '/' . $item);
516
            },
517
            array_filter(
518
                scandir($directory),
519
                function (string $dirItem) {
520
                    return ! in_array($dirItem, ['.', '..'], true);
521
                }
522
            )
523
        );
524
    }
525
526
    /**
527
     * @group composer/composer#5237
528
     */
529
    public function testWillEscapeRegexParsingOfClassDefinitions()
530
    {
531
        self::assertSame(
532
            1,
533
            preg_match_all(
534
                '{^((?:final\s+)?(?:\s*))class\s+(\S+)}mi',
535
                file_get_contents((new \ReflectionClass(Installer::class))->getFileName())
536
            )
537
        );
538
    }
539
}
540