Przeglądaj źródła

Add PoolBuilder test harness for writing .test files

Jordi Boggiano 5 lat temu
rodzic
commit
921a97457d

+ 23 - 0
tests/Composer/Test/DependencyResolver/Fixtures/poolbuilder/fixed-packages-do-not-load-from-repos.test

@@ -0,0 +1,23 @@
+--TEST--
+Fixed packages do not get loaded from the repos
+
+--REQUEST--
+{
+    "some/pkg": "*"
+}
+
+--FIXED--
+[
+    {"name": "some/pkg", "version": "1.0.3", "id": 1}
+]
+
+--PACKAGES--
+[
+    {"name": "some/pkg", "version": "1.0.0"},
+    {"name": "some/pkg", "version": "1.1.0"}
+]
+
+--EXPECT--
+[
+    1
+]

+ 44 - 0
tests/Composer/Test/DependencyResolver/Fixtures/poolbuilder/stability-flags-take-over-minimum-stability-and-filter-packages.test

@@ -0,0 +1,44 @@
+--TEST--
+Stability flags apply
+
+--ROOT--
+{
+    "stability-flags": {
+        "flagged/pkg": "alpha"
+    },
+    "minimum-stability": "RC",
+    "aliases": [
+        {
+            "package": "default/pkg",
+            "version": "1.0.0-RC",
+            "alias": "1.2.0"
+        }
+    ]
+}
+
+--REQUEST--
+{
+    "flagged/pkg": "*",
+    "default/pkg": "*"
+}
+
+--PACKAGES--
+[
+    {"name": "flagged/pkg", "version": "1.0.0", "id": 1},
+    {"name": "flagged/pkg", "version": "1.0.0-beta", "id": 2},
+    {"name": "flagged/pkg", "version": "1.0.0-dev", "id": 3},
+    {"name": "flagged/pkg", "version": "1.0.0-RC", "id": 4},
+    {"name": "default/pkg", "version": "1.0.0", "id": 5},
+    {"name": "default/pkg", "version": "1.0.0-RC", "id": 6},
+    {"name": "default/pkg", "version": "1.0.0-alpha", "id": 7}
+]
+
+--EXPECT--
+[
+    1,
+    2,
+    4,
+    5,
+    6,
+    "default/pkg-1.2.0.0 alias of 6"
+]

+ 194 - 0
tests/Composer/Test/DependencyResolver/PoolBuilderTest.php

@@ -0,0 +1,194 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ *     Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Test\DependencyResolver;
+
+use Composer\IO\NullIO;
+use Composer\Repository\ArrayRepository;
+use Composer\Repository\LockArrayRepository;
+use Composer\DependencyResolver\DefaultPolicy;
+use Composer\DependencyResolver\Pool;
+use Composer\DependencyResolver\PoolBuilder;
+use Composer\DependencyResolver\Request;
+use Composer\DependencyResolver\Solver;
+use Composer\DependencyResolver\SolverProblemsException;
+use Composer\Package\BasePackage;
+use Composer\Package\AliasPackage;
+use Composer\Json\JsonFile;
+use Composer\Package\Loader\ArrayLoader;
+use Composer\Package\Version\VersionParser;
+use Composer\Repository\InstalledArrayRepository;
+use Composer\Repository\RepositorySet;
+use Composer\Test\TestCase;
+use Composer\Semver\Constraint\MultiConstraint;
+
+class PoolBuilderTest extends TestCase
+{
+    /**
+     * @dataProvider getIntegrationTests
+     */
+    public function testPoolBuilder($file, $message, $expect, $root, $requestData, $packages, $fixed)
+    {
+        $rootAliases = !empty($root['aliases']) ? $root['aliases'] : array();
+        $minimumStability = !empty($root['minimum-stability']) ? $root['minimum-stability'] : 'stable';
+        $stabilityFlags = !empty($root['stability-flags']) ? $root['stability-flags'] : array();
+        $stabilityFlags = array_map(function ($stability) {
+            return BasePackage::$stabilities[$stability];
+        }, $stabilityFlags);
+
+        $parser = new VersionParser();
+        $normalizedAliases = array();
+        foreach ($rootAliases as $alias) {
+            $normalizedAliases[$alias['package']][$parser->normalize($alias['version'])] = array(
+                'alias' => $alias['alias'],
+                'alias_normalized' => $parser->normalize($alias['alias']),
+            );
+        }
+
+        $loader = new ArrayLoader();
+        $packageIds = array();
+        $loadPackage = function ($data) use ($loader, &$packageIds) {
+            if (!empty($data['id'])) {
+                $id = $data['id'];
+                unset($data['id']);
+            }
+
+            $pkg = $loader->load($data);
+
+            if (!empty($id)) {
+                if (!empty($packageIds[$id])) {
+                    throw new \LogicException('Duplicate package id '.$id.' defined');
+                }
+                $packageIds[$id] = $pkg;
+            }
+
+            return $pkg;
+        };
+
+        $repositorySet = new RepositorySet($normalizedAliases, array(), $minimumStability, $stabilityFlags);
+        $repositorySet->addRepository($repo = new ArrayRepository());
+        foreach ($packages as $package) {
+            $repo->addPackage($loadPackage($package));
+        }
+
+        $request = new Request();
+        foreach ($requestData as $package => $constraint) {
+            $request->install($package, $parser->parseConstraints($constraint));
+        }
+
+        foreach ($fixed as $fixedPackage) {
+            $request->fixPackage($loadPackage($fixedPackage));
+        }
+
+        $pool = $repositorySet->createPool($request);
+        for ($i = 1, $count = count($pool); $i <= $count; $i++) {
+            $result[] = $pool->packageById($i);
+        }
+
+        $result = array_map(function ($package) use ($packageIds) {
+            if ($id = array_search($package, $packageIds, true)) {
+                return $id;
+            }
+
+            if ($package instanceof AliasPackage && $id = array_search($package->getAliasOf(), $packageIds, true)) {
+                return (string) $package->getName().'-'.$package->getVersion() .' alias of '.$id;
+            }
+
+            return (string) $package;
+        }, $result);
+
+        $this->assertSame($expect, $result);
+    }
+
+    public function getIntegrationTests()
+    {
+        $fixturesDir = realpath(__DIR__.'/Fixtures/poolbuilder/');
+        $tests = array();
+        foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($fixturesDir), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
+            if (!preg_match('/\.test$/', $file)) {
+                continue;
+            }
+
+            try {
+                $testData = $this->readTestFile($file, $fixturesDir);
+
+                $message = $testData['TEST'];
+
+                $request = JsonFile::parseJson($testData['REQUEST']);
+                $root = !empty($testData['ROOT']) ? JsonFile::parseJson($testData['ROOT']) : array();
+
+                $packages = JsonFile::parseJson($testData['PACKAGES']);
+                $fixed = array();
+                if (!empty($testData['FIXED'])) {
+                    $fixed = JsonFile::parseJson($testData['FIXED']);
+                }
+                $expect = JsonFile::parseJson($testData['EXPECT']);
+            } 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, $expect, $root, $request, $packages, $fixed);
+        }
+
+        return $tests;
+    }
+
+    protected function readTestFile(\SplFileInfo $file, $fixturesDir)
+    {
+        $tokens = preg_split('#(?:^|\n*)--([A-Z-]+)--\n#', file_get_contents($file->getRealPath()), null, PREG_SPLIT_DELIM_CAPTURE);
+
+        $sectionInfo = array(
+            'TEST' => true,
+            'ROOT' => false,
+            'REQUEST' => true,
+            'FIXED' => false,
+            'PACKAGES' => true,
+            'EXPECT' => true,
+        );
+
+        $section = null;
+        foreach ($tokens as $i => $token) {
+            if (null === $section && empty($token)) {
+                continue; // skip leading blank
+            }
+
+            if (null === $section) {
+                if (!isset($sectionInfo[$token])) {
+                    throw new \RuntimeException(sprintf(
+                        'The test file "%s" must not contain a section named "%s".',
+                        str_replace($fixturesDir.'/', '', $file),
+                        $token
+                    ));
+                }
+                $section = $token;
+                continue;
+            }
+
+            $sectionData = $token;
+
+            $data[$section] = $sectionData;
+            $section = $sectionData = null;
+        }
+
+        foreach ($sectionInfo as $section => $required) {
+            if ($required && !isset($data[$section])) {
+                throw new \RuntimeException(sprintf(
+                    'The test file "%s" must have a section named "%s".',
+                    str_replace($fixturesDir.'/', '', $file),
+                    $section
+                ));
+            }
+        }
+
+        return $data;
+    }
+}