Completed
Pull Request — master (#51)
by Alessandro
12:50
created

testGetVersionsIsNotNormalizedForRootPackage()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 91
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 91
rs 8.518
cc 1
eloc 36
nc 1
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 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->createMock(IOInterface::class);
56
        $this->composer        = $this->createMock(Composer::class);
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->createMock(InstalledRepositoryInterface::class);
86
        $package           = $this->createMock(RootPackageInterface::class);
87
88
        $vendorDir = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true);
89
90
        $expectedPath = $vendorDir . '/ocramius/package-versions/src/PackageVersions';
91
92
        /** @noinspection MkdirRaceConditionInspection */
93
        mkdir($expectedPath, 0777, true);
94
95
        $locker
96
            ->expects(self::any())
97
            ->method('getLockData')
98
            ->willReturn([
99
                'packages' => [
100
                    [
101
                        'name'    => 'ocramius/package-versions',
102
                        'version' => '1.0.0',
103
                    ],
104
                    [
105
                        'name'    => 'foo/bar',
106
                        'version' => '1.2.3',
107
                        'source'  => [
108
                            'reference' => 'abc123',
109
                        ],
110
                    ],
111
                    [
112
                        'name'    => 'baz/tab',
113
                        'version' => '4.5.6',
114
                        'source'  => [
115
                            'reference' => 'def456',
116
                        ],
117
                    ],
118
                ],
119
                'packages-dev' => [
120
                    [
121
                        'name'    => 'tar/taz',
122
                        'version' => '7.8.9',
123
                        'source'  => [
124
                            'reference' => 'ghi789',
125
                        ],
126
                    ]
127
                ],
128
            ]);
129
130
        $repositoryManager->expects(self::any())->method('getLocalRepository')->willReturn($repository);
131
132
        $this->composer->expects(self::any())->method('getConfig')->willReturn($config);
133
        $this->composer->expects(self::any())->method('getLocker')->willReturn($locker);
134
        $this->composer->expects(self::any())->method('getRepositoryManager')->willReturn($repositoryManager);
135
        $this->composer->expects(self::any())->method('getPackage')->willReturn($package);
136
        $this->composer->expects(self::any())->method('getInstallationManager')->willReturn($installManager);
137
138
        $package->expects(self::any())->method('getName')->willReturn('root/package');
139
        $package->expects(self::any())->method('getVersion')->willReturn('1.3.5');
140
        $package->expects(self::any())->method('getSourceReference')->willReturn('aaabbbcccddd');
141
142
        $config->expects(self::any())->method('get')->with('vendor-dir')->willReturn($vendorDir);
143
144
        Installer::dumpVersionsClass(new Event(
145
            'post-install-cmd',
146
            $this->composer,
147
            $this->io
148
        ));
149
150
        $expectedSource = <<<'PHP'
151
<?php
152
153
namespace PackageVersions;
154
155
/**
156
 * This class is generated by ocramius/package-versions, specifically by
157
 * @see \PackageVersions\Installer
158
 *
159
 * This file is overwritten at every run of `composer install` or `composer update`.
160
 */
161
final class Versions
162
{
163
    const VERSIONS = array (
164
  'ocramius/package-versions' => '1.0.0@',
165
  'foo/bar' => '1.2.3@abc123',
166
  'baz/tab' => '4.5.6@def456',
167
  'tar/taz' => '7.8.9@ghi789',
168
  'root/package' => '1.3.5@aaabbbcccddd',
169
);
170
171
    private function __construct()
172
    {
173
    }
174
175
    /**
176
     * @throws \OutOfBoundsException if a version cannot be located
177
     */
178
    public static function getVersion(string $packageName) : string
179
    {
180
        if (! isset(self::VERSIONS[$packageName])) {
181
            throw new \OutOfBoundsException(
182
                'Required package "' . $packageName . '" is not installed: cannot detect its version'
183
            );
184
        }
185
186
        return self::VERSIONS[$packageName];
187
    }
188
}
189
190
PHP;
191
192
        self::assertSame($expectedSource, file_get_contents($expectedPath . '/Versions.php'));
193
194
        $this->rmDir($vendorDir);
195
    }
196
197
    public function testDumpVersionsClassNoDev()
198
    {
199
        $config            = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock();
200
        $locker            = $this->getMockBuilder(Locker::class)->disableOriginalConstructor()->getMock();
201
        $repositoryManager = $this->getMockBuilder(RepositoryManager::class)->disableOriginalConstructor()->getMock();
202
        $installManager    = $this->getMockBuilder(InstallationManager::class)->disableOriginalConstructor()->getMock();
203
        $repository        = $this->createMock(InstalledRepositoryInterface::class);
204
        $package           = $this->createMock(RootPackageInterface::class);
205
206
        $vendorDir = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true);
207
208
        $expectedPath = $vendorDir . '/ocramius/package-versions/src/PackageVersions';
209
210
        /** @noinspection MkdirRaceConditionInspection */
211
        mkdir($expectedPath, 0777, true);
212
213
        $locker
214
            ->expects(self::any())
215
            ->method('getLockData')
216
            ->willReturn([
217
                'packages' => [
218
                    [
219
                        'name'    => 'ocramius/package-versions',
220
                        'version' => '1.0.0',
221
                    ],
222
                    [
223
                        'name'    => 'foo/bar',
224
                        'version' => '1.2.3',
225
                        'source'  => [
226
                            'reference' => 'abc123',
227
                        ],
228
                    ],
229
                    [
230
                        'name'    => 'baz/tab',
231
                        'version' => '4.5.6',
232
                        'source'  => [
233
                            'reference' => 'def456',
234
                        ],
235
                    ],
236
                ],
237
            ]);
238
239
        $repositoryManager->expects(self::any())->method('getLocalRepository')->willReturn($repository);
240
241
        $this->composer->expects(self::any())->method('getConfig')->willReturn($config);
242
        $this->composer->expects(self::any())->method('getLocker')->willReturn($locker);
243
        $this->composer->expects(self::any())->method('getRepositoryManager')->willReturn($repositoryManager);
244
        $this->composer->expects(self::any())->method('getPackage')->willReturn($package);
245
        $this->composer->expects(self::any())->method('getInstallationManager')->willReturn($installManager);
246
247
        $package->expects(self::any())->method('getName')->willReturn('root/package');
248
        $package->expects(self::any())->method('getVersion')->willReturn('1.3.5');
249
        $package->expects(self::any())->method('getSourceReference')->willReturn('aaabbbcccddd');
250
251
        $config->expects(self::any())->method('get')->with('vendor-dir')->willReturn($vendorDir);
252
253
        Installer::dumpVersionsClass(new Event(
254
            'post-install-cmd',
255
            $this->composer,
256
            $this->io
257
        ));
258
259
        $expectedSource = <<<'PHP'
260
<?php
261
262
namespace PackageVersions;
263
264
/**
265
 * This class is generated by ocramius/package-versions, specifically by
266
 * @see \PackageVersions\Installer
267
 *
268
 * This file is overwritten at every run of `composer install` or `composer update`.
269
 */
270
final class Versions
271
{
272
    const VERSIONS = array (
273
  'ocramius/package-versions' => '1.0.0@',
274
  'foo/bar' => '1.2.3@abc123',
275
  'baz/tab' => '4.5.6@def456',
276
  'root/package' => '1.3.5@aaabbbcccddd',
277
);
278
279
    private function __construct()
280
    {
281
    }
282
283
    /**
284
     * @throws \OutOfBoundsException if a version cannot be located
285
     */
286
    public static function getVersion(string $packageName) : string
287
    {
288
        if (! isset(self::VERSIONS[$packageName])) {
289
            throw new \OutOfBoundsException(
290
                'Required package "' . $packageName . '" is not installed: cannot detect its version'
291
            );
292
        }
293
294
        return self::VERSIONS[$packageName];
295
    }
296
}
297
298
PHP;
299
300
        self::assertSame($expectedSource, file_get_contents($expectedPath . '/Versions.php'));
301
302
        $this->rmDir($vendorDir);
303
    }
304
305
    /**
306
     * @group #12
307
     *
308
     * @throws \RuntimeException
309
     */
310
    public function testDumpVersionsWithoutPackageSourceDetails()
311
    {
312
        $config            = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock();
313
        $locker            = $this->getMockBuilder(Locker::class)->disableOriginalConstructor()->getMock();
314
        $repositoryManager = $this->getMockBuilder(RepositoryManager::class)->disableOriginalConstructor()->getMock();
315
        $installManager    = $this->getMockBuilder(InstallationManager::class)->disableOriginalConstructor()->getMock();
316
        $repository        = $this->createMock(InstalledRepositoryInterface::class);
317
        $package           = $this->createMock(RootPackageInterface::class);
318
319
        $vendorDir = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true);
320
321
        $expectedPath = $vendorDir . '/ocramius/package-versions/src/PackageVersions';
322
323
        /** @noinspection MkdirRaceConditionInspection */
324
        mkdir($expectedPath, 0777, true);
325
326
        $locker
327
            ->expects(self::any())
328
            ->method('getLockData')
329
            ->willReturn([
330
                'packages' => [
331
                    [
332
                        'name'    => 'ocramius/package-versions',
333
                        'version' => '1.0.0',
334
                    ],
335
                    [
336
                        'name'    => 'foo/bar',
337
                        'version' => '1.2.3',
338
                        'dist'  => [
339
                            'reference' => 'abc123', // version defined in the dist, this time
340
                        ],
341
                    ],
342
                    [
343
                        'name'    => 'baz/tab',
344
                        'version' => '4.5.6', // source missing
345
                    ],
346
                ],
347
            ]);
348
349
        $repositoryManager->expects(self::any())->method('getLocalRepository')->willReturn($repository);
350
351
        $this->composer->expects(self::any())->method('getConfig')->willReturn($config);
352
        $this->composer->expects(self::any())->method('getLocker')->willReturn($locker);
353
        $this->composer->expects(self::any())->method('getRepositoryManager')->willReturn($repositoryManager);
354
        $this->composer->expects(self::any())->method('getPackage')->willReturn($package);
355
        $this->composer->expects(self::any())->method('getInstallationManager')->willReturn($installManager);
356
357
        $package->expects(self::any())->method('getName')->willReturn('root/package');
358
        $package->expects(self::any())->method('getVersion')->willReturn('1.3.5');
359
        $package->expects(self::any())->method('getSourceReference')->willReturn('aaabbbcccddd');
360
361
        $config->expects(self::any())->method('get')->with('vendor-dir')->willReturn($vendorDir);
362
363
        Installer::dumpVersionsClass(new Event(
364
            'post-install-cmd',
365
            $this->composer,
366
            $this->io
367
        ));
368
369
        $expectedSource = <<<'PHP'
370
<?php
371
372
namespace PackageVersions;
373
374
/**
375
 * This class is generated by ocramius/package-versions, specifically by
376
 * @see \PackageVersions\Installer
377
 *
378
 * This file is overwritten at every run of `composer install` or `composer update`.
379
 */
380
final class Versions
381
{
382
    const VERSIONS = array (
383
  'ocramius/package-versions' => '1.0.0@',
384
  'foo/bar' => '1.2.3@abc123',
385
  'baz/tab' => '4.5.6@',
386
  'root/package' => '1.3.5@aaabbbcccddd',
387
);
388
389
    private function __construct()
390
    {
391
    }
392
393
    /**
394
     * @throws \OutOfBoundsException if a version cannot be located
395
     */
396
    public static function getVersion(string $packageName) : string
397
    {
398
        if (! isset(self::VERSIONS[$packageName])) {
399
            throw new \OutOfBoundsException(
400
                'Required package "' . $packageName . '" is not installed: cannot detect its version'
401
            );
402
        }
403
404
        return self::VERSIONS[$packageName];
405
    }
406
}
407
408
PHP;
409
410
        self::assertSame($expectedSource, file_get_contents($expectedPath . '/Versions.php'));
411
412
        $this->rmDir($vendorDir);
413
    }
414
415
    /**
416
     * @dataProvider rootPackageProvider
417
     *
418
     * @param RootPackageInterface $rootPackage
419
     * @param bool                 $inVendor
420
     *
421
     * @throws \RuntimeException
422
     */
423
    public function testDumpsVersionsClassToSpecificLocation(RootPackageInterface $rootPackage, bool $inVendor)
424
    {
425
        $config            = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock();
426
        $locker            = $this->getMockBuilder(Locker::class)->disableOriginalConstructor()->getMock();
427
        $repositoryManager = $this->getMockBuilder(RepositoryManager::class)->disableOriginalConstructor()->getMock();
428
        $installManager    = $this->getMockBuilder(InstallationManager::class)->disableOriginalConstructor()->getMock();
429
        $repository        = $this->createMock(InstalledRepositoryInterface::class);
430
431
        $vendorDir = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true) . '/vendor';
432
433
        /** @noinspection MkdirRaceConditionInspection */
434
        mkdir($vendorDir, 0777, true);
435
436
        /** @noinspection RealpathInSteamContextInspection */
437
        $expectedPath      = $inVendor
438
            ? $vendorDir . '/ocramius/package-versions/src/PackageVersions'
439
            : realpath($vendorDir . '/..') . '/src/PackageVersions';
440
441
        /** @noinspection MkdirRaceConditionInspection */
442
        mkdir($expectedPath, 0777, true);
443
444
        $locker
445
            ->expects(self::any())
446
            ->method('getLockData')
447
            ->willReturn([
448
                'packages' => [
449
                    [
450
                        'name'    => 'ocramius/package-versions',
451
                        'version' => '1.0.0',
452
                    ]
453
                ],
454
                'packages-dev' => [],
455
            ]);
456
457
        $repositoryManager->expects(self::any())->method('getLocalRepository')->willReturn($repository);
458
459
        $this->composer->expects(self::any())->method('getConfig')->willReturn($config);
460
        $this->composer->expects(self::any())->method('getLocker')->willReturn($locker);
461
        $this->composer->expects(self::any())->method('getRepositoryManager')->willReturn($repositoryManager);
462
        $this->composer->expects(self::any())->method('getPackage')->willReturn($rootPackage);
463
        $this->composer->expects(self::any())->method('getInstallationManager')->willReturn($installManager);
464
465
        $config->expects(self::any())->method('get')->with('vendor-dir')->willReturn($vendorDir);
466
467
        Installer::dumpVersionsClass(new Event(
468
            'post-install-cmd',
469
            $this->composer,
470
            $this->io
471
        ));
472
473
        self::assertStringMatchesFormat(
474
            '%Aclass Versions%A1.2.3@%A',
475
            file_get_contents($expectedPath . '/Versions.php')
476
        );
477
478
        $this->rmDir($vendorDir);
479
    }
480
481
    /**
482
     * @return bool[][]|RootPackageInterface[][] the root package and whether the versions class is to be generated in
483
     *                                           the vendor dir or not
484
     */
485
    public function rootPackageProvider() : array
486
    {
487
        $baseRootPackage                         = new RootPackage('root/package', '1.2.3', '1.2.3');
488
        $aliasRootPackage                        = new RootAliasPackage($baseRootPackage, '1.2.3', '1.2.3');
489
        $indirectAliasRootPackage                = new RootAliasPackage($aliasRootPackage, '1.2.3', '1.2.3');
490
        $packageVersionsRootPackage              = new RootPackage('ocramius/package-versions', '1.2.3', '1.2.3');
491
        $aliasPackageVersionsRootPackage         = new RootAliasPackage($packageVersionsRootPackage, '1.2.3', '1.2.3');
492
        $indirectAliasPackageVersionsRootPackage = new RootAliasPackage(
493
            $aliasPackageVersionsRootPackage,
494
            '1.2.3',
495
            '1.2.3'
496
        );
497
498
        return [
499
            'root package is not ocramius/package-versions' => [
500
                $baseRootPackage,
501
                true
502
            ],
503
            'alias root package is not ocramius/package-versions' => [
504
                $aliasRootPackage,
505
                true
506
            ],
507
            'indirect alias root package is not ocramius/package-versions' => [
508
                $indirectAliasRootPackage,
509
                true
510
            ],
511
            'root package is ocramius/package-versions' => [
512
                $packageVersionsRootPackage,
513
                false
514
            ],
515
            'alias root package is ocramius/package-versions' => [
516
                $aliasPackageVersionsRootPackage,
517
                false
518
            ],
519
            'indirect alias root package is ocramius/package-versions' => [
520
                $indirectAliasPackageVersionsRootPackage,
521
                false
522
            ],
523
        ];
524
    }
525
526
    public function testVersionsAreNotDumpedIfPackageVersionsNotExplicitlyRequired()
527
    {
528
        $config            = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock();
529
        $locker            = $this->getMockBuilder(Locker::class)->disableOriginalConstructor()->getMock();
530
        $repositoryManager = $this->getMockBuilder(RepositoryManager::class)->disableOriginalConstructor()->getMock();
531
        $installManager    = $this->getMockBuilder(InstallationManager::class)->disableOriginalConstructor()->getMock();
532
        $repository        = $this->createMock(InstalledRepositoryInterface::class);
533
        $package           = $this->createMock(RootPackageInterface::class);
534
535
        $vendorDir = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true);
536
537
        $expectedPath = $vendorDir . '/ocramius/package-versions/src/PackageVersions';
538
539
        /** @noinspection MkdirRaceConditionInspection */
540
        mkdir($expectedPath, 0777, true);
541
542
        $locker
543
            ->expects(self::any())
544
            ->method('getLockData')
545
            ->willReturn([
546
                 'packages' => [
547
                     [
548
                         'name'    => 'foo/bar',
549
                         'version' => '1.2.3',
550
                         'dist'  => [
551
                             'reference' => 'abc123', // version defined in the dist, this time
552
                         ],
553
                     ],
554
                     [
555
                         'name'    => 'baz/tab',
556
                         'version' => '4.5.6', // source missing
557
                     ],
558
                 ],
559
             ]);
560
561
        $repositoryManager->expects(self::any())->method('getLocalRepository')->willReturn($repository);
562
563
        $this->composer->expects(self::any())->method('getConfig')->willReturn($config);
564
        $this->composer->expects(self::any())->method('getLocker')->willReturn($locker);
565
        $this->composer->expects(self::any())->method('getRepositoryManager')->willReturn($repositoryManager);
566
        $this->composer->expects(self::any())->method('getPackage')->willReturn($package);
567
        $this->composer->expects(self::any())->method('getInstallationManager')->willReturn($installManager);
568
569
        $package->expects(self::any())->method('getName')->willReturn('root/package');
570
        $package->expects(self::any())->method('getVersion')->willReturn('1.3.5');
571
        $package->expects(self::any())->method('getSourceReference')->willReturn('aaabbbcccddd');
572
573
        $config->expects(self::any())->method('get')->with('vendor-dir')->willReturn($vendorDir);
574
575
        Installer::dumpVersionsClass(new Event(
576
            'post-install-cmd',
577
            $this->composer,
578
            $this->io
579
        ));
580
581
        self::assertFileNotExists($expectedPath . '/Versions.php');
582
583
        $this->rmDir($vendorDir);
584
    }
585
586
    /**
587
     * @group #41
588
     * @group #46
589
     */
590
    public function testVersionsAreNotDumpedIfPackageIsScheduledForRemoval()
591
    {
592
        $config            = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock();
593
        $locker            = $this->getMockBuilder(Locker::class)->disableOriginalConstructor()->getMock();
594
        $package           = $this->createMock(RootPackageInterface::class);
595
        $vendorDir         = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true);
596
        $expectedPath      = $vendorDir . '/ocramius/package-versions/src/PackageVersions';
597
598
        $locker
599
            ->expects(self::any())
600
            ->method('getLockData')
601
            ->willReturn([
602
                 'packages' => [
603
                     [
604
                         'name'    => 'ocramius/package-versions',
605
                         'version' => '1.0.0',
606
                     ]
607
                 ],
608
             ]);
609
610
        $this->composer->expects(self::any())->method('getConfig')->willReturn($config);
611
        $this->composer->expects(self::any())->method('getLocker')->willReturn($locker);
612
        $this->composer->expects(self::any())->method('getPackage')->willReturn($package);
613
614
        $config->expects(self::any())->method('get')->with('vendor-dir')->willReturn($vendorDir);
615
616
        Installer::dumpVersionsClass(new Event(
617
            'post-install-cmd',
618
            $this->composer,
619
            $this->io
620
        ));
621
622
        self::assertFileNotExists($expectedPath . '/Versions.php');
623
        self::assertFileNotExists($expectedPath . '/Versions.php');
624
    }
625
626
    public function testGeneratedVersionFileAccessRights()
627
    {
628
        if (0 === strpos(\PHP_OS, 'WIN')) {
629
            $this->markTestSkipped('Windows is kinda "meh" at file access levels');
630
        }
631
632
        $config            = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock();
633
        $locker            = $this->getMockBuilder(Locker::class)->disableOriginalConstructor()->getMock();
634
        $repositoryManager = $this->getMockBuilder(RepositoryManager::class)->disableOriginalConstructor()->getMock();
635
        $installManager    = $this->getMockBuilder(InstallationManager::class)->disableOriginalConstructor()->getMock();
636
        $repository        = $this->createMock(InstalledRepositoryInterface::class);
637
        $package           = $this->createMock(RootPackageInterface::class);
638
639
        $vendorDir = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true);
640
641
        $expectedPath = $vendorDir . '/ocramius/package-versions/src/PackageVersions';
642
643
        /** @noinspection MkdirRaceConditionInspection */
644
        mkdir($expectedPath, 0777, true);
645
646
        $locker
647
            ->expects(self::any())
648
            ->method('getLockData')
649
            ->willReturn([
650
                'packages' => [
651
                    [
652
                        'name'    => 'ocramius/package-versions',
653
                        'version' => '1.0.0',
654
                    ],
655
                ],
656
            ]);
657
658
        $repositoryManager->expects(self::any())->method('getLocalRepository')->willReturn($repository);
659
660
        $this->composer->expects(self::any())->method('getConfig')->willReturn($config);
661
        $this->composer->expects(self::any())->method('getLocker')->willReturn($locker);
662
        $this->composer->expects(self::any())->method('getRepositoryManager')->willReturn($repositoryManager);
663
        $this->composer->expects(self::any())->method('getPackage')->willReturn($package);
664
        $this->composer->expects(self::any())->method('getInstallationManager')->willReturn($installManager);
665
666
        $package->expects(self::any())->method('getName')->willReturn('root/package');
667
        $package->expects(self::any())->method('getVersion')->willReturn('1.3.5');
668
        $package->expects(self::any())->method('getSourceReference')->willReturn('aaabbbcccddd');
669
670
        $config->expects(self::any())->method('get')->with('vendor-dir')->willReturn($vendorDir);
671
672
        Installer::dumpVersionsClass(new Event(
673
            'post-install-cmd',
674
            $this->composer,
675
            $this->io
676
        ));
677
678
        $filePath = $expectedPath . '/Versions.php';
679
680
        self::assertFileExists($filePath);
681
        self::assertSame('0664', substr(sprintf('%o', fileperms($filePath)), -4));
682
683
        $this->rmDir($vendorDir);
684
    }
685
686
    /**
687
     * @param string $directory
688
     *
689
     * @return void
690
     */
691
    private function rmDir(string $directory)
692
    {
693
        if (! is_dir($directory)) {
694
            unlink($directory);
695
696
            return;
697
        }
698
699
        array_map(
700
            function ($item) use ($directory) {
701
                $this->rmDir($directory . '/' . $item);
702
            },
703
            array_filter(
704
                scandir($directory),
705
                function (string $dirItem) {
706
                    return ! in_array($dirItem, ['.', '..'], true);
707
                }
708
            )
709
        );
710
711
        rmdir($directory);
712
    }
713
714
    /**
715
     * @group composer/composer#5237
716
     */
717
    public function testWillEscapeRegexParsingOfClassDefinitions()
718
    {
719
        self::assertSame(
720
            1,
721
            preg_match_all(
722
                '{^((?:final\s+)?(?:\s*))class\s+(\S+)}mi',
723
                file_get_contents((new \ReflectionClass(Installer::class))->getFileName())
724
            )
725
        );
726
    }
727
728
    public function testGetVersionsIsNotNormalizedForRootPackage()
729
    {
730
        $config            = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock();
731
        $locker            = $this->getMockBuilder(Locker::class)->disableOriginalConstructor()->getMock();
732
        $repositoryManager = $this->getMockBuilder(RepositoryManager::class)->disableOriginalConstructor()->getMock();
733
        $installManager    = $this->getMockBuilder(InstallationManager::class)->disableOriginalConstructor()->getMock();
734
        $repository        = $this->createMock(InstalledRepositoryInterface::class);
735
        $package           = $this->createMock(RootPackageInterface::class);
736
737
        $vendorDir = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true);
738
739
        $expectedPath = $vendorDir . '/ocramius/package-versions/src/PackageVersions';
740
741
        /** @noinspection MkdirRaceConditionInspection */
742
        mkdir($expectedPath, 0777, true);
743
744
        $locker
745
            ->expects(self::any())
746
            ->method('getLockData')
747
            ->willReturn([
748
                'packages' => [
749
                    [
750
                        'name'    => 'ocramius/package-versions',
751
                        'version' => '1.0.0',
752
                    ],
753
                ],
754
            ]);
755
756
        $repositoryManager->expects(self::any())->method('getLocalRepository')->willReturn($repository);
757
758
        $this->composer->expects(self::any())->method('getConfig')->willReturn($config);
759
        $this->composer->expects(self::any())->method('getLocker')->willReturn($locker);
760
        $this->composer->expects(self::any())->method('getRepositoryManager')->willReturn($repositoryManager);
761
        $this->composer->expects(self::any())->method('getPackage')->willReturn($package);
762
        $this->composer->expects(self::any())->method('getInstallationManager')->willReturn($installManager);
763
764
        $package->expects(self::any())->method('getName')->willReturn('root/package');
765
        $package->expects(self::any())->method('getPrettyVersion')->willReturn('1.3.5');
766
        $package->expects(self::any())->method('getSourceReference')->willReturn('aaabbbcccddd');
767
768
        $config->expects(self::any())->method('get')->with('vendor-dir')->willReturn($vendorDir);
769
770
        Installer::dumpVersionsClass(new Event(
771
            'post-install-cmd',
772
            $this->composer,
773
            $this->io
774
        ));
775
776
        $expectedSource = <<<'PHP'
777
<?php
778
779
namespace PackageVersions;
780
781
/**
782
 * This class is generated by ocramius/package-versions, specifically by
783
 * @see \PackageVersions\Installer
784
 *
785
 * This file is overwritten at every run of `composer install` or `composer update`.
786
 */
787
final class Versions
788
{
789
    const VERSIONS = array (
790
  'ocramius/package-versions' => '1.0.0@',
791
  'root/package' => '1.3.5@aaabbbcccddd',
792
);
793
794
    private function __construct()
795
    {
796
    }
797
798
    /**
799
     * @throws \OutOfBoundsException if a version cannot be located
800
     */
801
    public static function getVersion(string $packageName) : string
802
    {
803
        if (! isset(self::VERSIONS[$packageName])) {
804
            throw new \OutOfBoundsException(
805
                'Required package "' . $packageName . '" is not installed: cannot detect its version'
806
            );
807
        }
808
809
        return self::VERSIONS[$packageName];
810
    }
811
}
812
813
PHP;
814
815
        self::assertSame($expectedSource, file_get_contents($expectedPath . '/Versions.php'));
816
817
        $this->rmDir($vendorDir);
818
    }
819
}
820