Browse Source

Add SolverProblemsException and test basic solver failures

Nils Adermann 13 years ago
parent
commit
52d876e11e

+ 4 - 0
src/Composer/DependencyResolver/Solver.php

@@ -1035,6 +1035,10 @@ class Solver
         //findrecommendedsuggested(solv);
         //solver_prepare_solutions(solv);
 
+        if ($this->problems) {
+            throw new SolverProblemsException($this->problems, $this->learnedPool);
+        }
+
         return $this->createTransaction();
     }
 

+ 65 - 0
src/Composer/DependencyResolver/SolverProblemsException.php

@@ -0,0 +1,65 @@
+<?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\DependencyResolver;
+
+/**
+ * @author Nils Adermann <naderman@naderman.de>
+ */
+class SolverProblemsException extends \RuntimeException
+{
+    protected $problems;
+
+    public function __construct(array $problems, array $learnedPool)
+    {
+        $message = '';
+        foreach ($problems as $i => $problem) {
+            $message .= '[';
+            foreach ($problem as $why) {
+
+                if (is_int($why) && isset($learnedPool[$why])) {
+                    $rules = $learnedPool[$why];
+                } else {
+                    $rules = $why;
+                }
+
+                if (isset($rules['packages'])) {
+                    $message .= $this->jobToText($rules);
+                } else {
+                    $message .= '(';
+                    foreach ($rules as $rule) {
+                        if ($rule instanceof Rule) {
+                            if ($rule->getType() == RuleSet::TYPE_LEARNED) {
+                                $message .= 'learned: ';
+                            }
+                            $message .= $rule . ', ';
+                        } else {
+                            $message .= 'String(' . $rule . '), ';
+                        }
+                    }
+                    $message .= ')';
+                }
+                $message .= ', ';
+            }
+            $message .= "]\n";
+        }
+
+        parent::__construct($message);
+    }
+
+    public function jobToText($job)
+    {
+        //$output = serialize($job);
+        $output = 'Job(cmd='.$job['cmd'].', target='.$job['packageName'].', packages=['.implode(', ', $job['packages']).'])';
+        return $output;
+    }
+}

+ 42 - 1
tests/Composer/Test/DependencyResolver/SolverTest.php

@@ -19,6 +19,7 @@ use Composer\DependencyResolver\DefaultPolicy;
 use Composer\DependencyResolver\Pool;
 use Composer\DependencyResolver\Request;
 use Composer\DependencyResolver\Solver;
+use Composer\DependencyResolver\SolverProblemsException;
 use Composer\Package\Link;
 use Composer\Package\LinkConstraint\VersionConstraint;
 use Composer\Test\TestCase;
@@ -484,6 +485,47 @@ class SolverTest extends TestCase
         ));
     }
 
+    public function testConflictResultEmpty()
+    {
+        $this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));
+        $this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));;
+
+        $packageA->setConflicts(array(
+            new Link('A', 'B', new VersionConstraint('>=', '1.0'), 'conflicts'),
+        ));
+
+        $this->reposComplete();
+
+        $this->request->install('A');
+        $this->request->install('B');
+
+        try {
+            $transaction = $this->solver->solve($this->request);
+            $this->fail('Unsolvable conflict did not resolve in exception.');
+        } catch (SolverProblemsException $e) {
+        }
+    }
+
+    public function testUnsatisfiableRequires()
+    {
+        $this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));
+        $this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));
+
+        $packageA->setRequires(array(
+            new Link('A', 'B', new VersionConstraint('>=', '2.0'), 'requires'),
+        ));
+
+        $this->reposComplete();
+
+        $this->request->install('A');
+
+        try {
+            $transaction = $this->solver->solve($this->request);
+            $this->fail('Unsolvable conflict did not resolve in exception.');
+        } catch (SolverProblemsException $e) {
+        }
+    }
+
     protected function reposComplete()
     {
         $this->pool->addRepository($this->repoInstalled);
@@ -513,5 +555,4 @@ class SolverTest extends TestCase
 
         $this->assertEquals($expected, $result);
     }
-
 }