Pārlūkot izejas kodu

Wrapped the listener invocation a try/catch block that catches any
exception and throws a \RuntimeException.
Added a test case for the EventDispatcher.

Note:
In order to test the doDispatch method I had to use a stub EventDispatcher
with a getListeners that returned a preconfigured array. IMHO there should
be a way to inject the listeners into the EventDispatcher.

Andrea Turso 13 gadi atpakaļ
vecāks
revīzija
f626ccbcee

+ 5 - 1
src/Composer/Script/EventDispatcher.php

@@ -91,7 +91,11 @@ class EventDispatcher
                 throw new \UnexpectedValueException('Method '.$callable.' is not callable, can not call '.$event->getName().' script');
             }
 
-            $className::$methodName($event);
+            try {
+                $className::$methodName($event);
+            } catch (\Exception $e) {
+                throw new \RuntimeException("'{$callable}' terminated with an exception.");
+            }
         }
     }
 

+ 58 - 0
tests/Composer/Test/Script/EventDispatcherTest.php

@@ -0,0 +1,58 @@
+<?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\Script;
+
+use Exception;
+use Composer\Test\TestCase;
+use Composer\Script\Event;
+use Composer\Script\EventDispatcher;
+
+/**
+ *
+ * @group
+ * @ticket #693
+ * @author Andrea Turso <turso@officinesoftware.co.uk>
+ */
+class EventDispatcherTest extends TestCase
+{
+    /**
+     * @expectedException \RuntimeException
+     */
+    public function testListenerExceptionsAreSuppressed()
+    {
+        $dispatcher = $this->getDispatcherStubForListenersTest(array(
+                "Composer\Test\Script\EventDispatcherTest::call"
+            ));
+        $dispatcher->dispatchCommandEvent("post-install-cmd");
+    }
+
+    private function getDispatcherStubForListenersTest($listeners)
+    {
+        $dispatcher = $this->getMockBuilder('Composer\Script\EventDispatcher')
+                           ->setConstructorArgs(array(
+                               $this->getMock('Composer\Composer'),
+                               $this->getMock('Composer\IO\IOInterface')))
+                           ->setMethods(array('getListeners'))
+                           ->getMock();
+
+        $dispatcher->expects($this->atLeastOnce())
+                   ->method('getListeners')
+                   ->will($this->returnValue($listeners));
+
+        return $dispatcher;
+    }
+
+    public static function call()
+    {
+        throw new Exception();
+    }
+}