Browse Source

Merge remote-tracking branch 'curry684/issue-4767'

Jordi Boggiano 9 years ago
parent
commit
8771eca527

+ 5 - 0
src/Composer/Package/Loader/RootPackageLoader.php

@@ -113,6 +113,11 @@ class RootPackageLoader extends ArrayLoader
             }
         }
 
+        if (isset($links[$config['name']])) {
+            throw new \InvalidArgumentException(sprintf('Root package \'%s\' cannot require itself in its composer.json' . PHP_EOL .
+                        'Did you accidentally name your root package after an external package?', $config['name']));
+        }
+
         $realPackage->setAliases($aliases);
         $realPackage->setStabilityFlags($stabilityFlags);
         $realPackage->setReferences($references);

+ 16 - 0
tests/Composer/Test/Fixtures/installer/install-self-from-root.test

@@ -0,0 +1,16 @@
+--TEST--
+Tries to require a package with the same name as the root package
+--COMPOSER--
+{
+    "name": "foo/bar",
+    "require": {
+        "foo/bar": "@dev"
+    }
+}
+--RUN--
+install
+--EXPECT-EXCEPTION--
+InvalidArgumentException
+--EXPECT--
+Root package 'foo/bar' cannot require itself in its composer.json
+Did you accidentally name your root package after an external package?

+ 29 - 6
tests/Composer/Test/InstallerTest.php

@@ -140,7 +140,7 @@ class InstallerTest extends TestCase
     /**
      * @dataProvider getIntegrationTests
      */
-    public function testIntegration($file, $message, $condition, $composerConfig, $lock, $installed, $run, $expectLock, $expectOutput, $expect, $expectExitCode)
+    public function testIntegration($file, $message, $condition, $composerConfig, $lock, $installed, $run, $expectLock, $expectOutput, $expect, $expectResult)
     {
         if ($condition) {
             eval('$res = '.$condition.';');
@@ -150,6 +150,14 @@ class InstallerTest extends TestCase
         }
 
         $io = new BufferIO('', OutputInterface::VERBOSITY_NORMAL, new OutputFormatter(false));
+
+        // Prepare for exceptions
+        if (!is_int($expectResult)) {
+            $normalizedOutput = rtrim(str_replace("\n", PHP_EOL, $expect));
+            $this->setExpectedException($expectResult, $normalizedOutput);
+        }
+
+        // Create Composer mock object according to configuration
         $composer = FactoryMock::create($io, $composerConfig);
 
         $jsonMock = $this->getMockBuilder('Composer\Json\JsonFile')->disableOriginalConstructor()->getMock();
@@ -225,9 +233,14 @@ class InstallerTest extends TestCase
         $appOutput = fopen('php://memory', 'w+');
         $result = $application->run(new StringInput($run), new StreamOutput($appOutput));
         fseek($appOutput, 0);
-        $output = str_replace("\r", '', $io->getOutput());
-        $this->assertEquals($expectExitCode, $result, $output . stream_get_contents($appOutput));
 
+        // Shouldn't check output and results if an exception was expected by this point
+        if (!is_int($expectResult)) {
+            return;
+        }
+
+        $output = str_replace("\r", '', $io->getOutput());
+        $this->assertEquals($expectResult, $result, $output . stream_get_contents($appOutput));
         if ($expectLock) {
             unset($actualLock['hash']);
             unset($actualLock['content-hash']);
@@ -259,7 +272,7 @@ class InstallerTest extends TestCase
             $installedDev = array();
             $lock = array();
             $expectLock = array();
-            $expectExitCode = 0;
+            $expectResult = 0;
 
             try {
                 $message = $testData['TEST'];
@@ -296,12 +309,21 @@ class InstallerTest extends TestCase
                 }
                 $expectOutput = isset($testData['EXPECT-OUTPUT']) ? $testData['EXPECT-OUTPUT'] : null;
                 $expect = $testData['EXPECT'];
-                $expectExitCode = isset($testData['EXPECT-EXIT-CODE']) ? (int) $testData['EXPECT-EXIT-CODE'] : 0;
+                if (!empty($testData['EXPECT-EXCEPTION'])) {
+                    $expectResult = $testData['EXPECT-EXCEPTION'];
+                    if (!empty($testData['EXPECT-EXIT-CODE'])) {
+                        throw new \LogicException('EXPECT-EXCEPTION and EXPECT-EXIT-CODE are mutually exclusive');
+                    }
+                } elseif (!empty($testData['EXPECT-EXIT-CODE'])) {
+                    $expectResult = (int) $testData['EXPECT-EXIT-CODE'];
+                } else {
+                    $expectResult = 0;
+                }
             } catch (\Exception $e) {
                 die(sprintf('Test "%s" is not valid: '.$e->getMessage(), str_replace($fixturesDir.'/', '', $file)));
             }
 
-            $tests[basename($file)] = array(str_replace($fixturesDir.'/', '', $file), $message, $condition, $composer, $lock, $installed, $run, $expectLock, $expectOutput, $expect, $expectExitCode);
+            $tests[basename($file)] = array(str_replace($fixturesDir.'/', '', $file), $message, $condition, $composer, $lock, $installed, $run, $expectLock, $expectOutput, $expect, $expectResult);
         }
 
         return $tests;
@@ -321,6 +343,7 @@ class InstallerTest extends TestCase
             'EXPECT-LOCK' => false,
             'EXPECT-OUTPUT' => false,
             'EXPECT-EXIT-CODE' => false,
+            'EXPECT-EXCEPTION' => false,
             'EXPECT' => true,
         );