TraceableEventDispatcherTest.php 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\EventDispatcher\Tests\Debug;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher;
  13. use Symfony\Component\EventDispatcher\Debug\WrappedListener;
  14. use Symfony\Component\EventDispatcher\Event;
  15. use Symfony\Component\EventDispatcher\EventDispatcher;
  16. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  17. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  18. use Symfony\Component\Stopwatch\Stopwatch;
  19. class TraceableEventDispatcherTest extends TestCase
  20. {
  21. public function testAddRemoveListener()
  22. {
  23. $dispatcher = new EventDispatcher();
  24. $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
  25. $tdispatcher->addListener('foo', $listener = function () {});
  26. $listeners = $dispatcher->getListeners('foo');
  27. $this->assertCount(1, $listeners);
  28. $this->assertSame($listener, $listeners[0]);
  29. $tdispatcher->removeListener('foo', $listener);
  30. $this->assertCount(0, $dispatcher->getListeners('foo'));
  31. }
  32. public function testGetListeners()
  33. {
  34. $dispatcher = new EventDispatcher();
  35. $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
  36. $tdispatcher->addListener('foo', $listener = function () {});
  37. $this->assertSame($dispatcher->getListeners('foo'), $tdispatcher->getListeners('foo'));
  38. }
  39. public function testHasListeners()
  40. {
  41. $dispatcher = new EventDispatcher();
  42. $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
  43. $this->assertFalse($dispatcher->hasListeners('foo'));
  44. $this->assertFalse($tdispatcher->hasListeners('foo'));
  45. $tdispatcher->addListener('foo', $listener = function () {});
  46. $this->assertTrue($dispatcher->hasListeners('foo'));
  47. $this->assertTrue($tdispatcher->hasListeners('foo'));
  48. }
  49. public function testGetListenerPriority()
  50. {
  51. $dispatcher = new EventDispatcher();
  52. $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
  53. $tdispatcher->addListener('foo', function () {}, 123);
  54. $listeners = $dispatcher->getListeners('foo');
  55. $this->assertSame(123, $tdispatcher->getListenerPriority('foo', $listeners[0]));
  56. // Verify that priority is preserved when listener is removed and re-added
  57. // in preProcess() and postProcess().
  58. $tdispatcher->dispatch('foo', new Event());
  59. $listeners = $dispatcher->getListeners('foo');
  60. $this->assertSame(123, $tdispatcher->getListenerPriority('foo', $listeners[0]));
  61. }
  62. public function testGetListenerPriorityReturnsZeroWhenWrappedMethodDoesNotExist()
  63. {
  64. $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
  65. $traceableEventDispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
  66. $traceableEventDispatcher->addListener('foo', function () {}, 123);
  67. $listeners = $traceableEventDispatcher->getListeners('foo');
  68. $this->assertSame(0, $traceableEventDispatcher->getListenerPriority('foo', $listeners[0]));
  69. }
  70. public function testAddRemoveSubscriber()
  71. {
  72. $dispatcher = new EventDispatcher();
  73. $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
  74. $subscriber = new EventSubscriber();
  75. $tdispatcher->addSubscriber($subscriber);
  76. $listeners = $dispatcher->getListeners('foo');
  77. $this->assertCount(1, $listeners);
  78. $this->assertSame(array($subscriber, 'call'), $listeners[0]);
  79. $tdispatcher->removeSubscriber($subscriber);
  80. $this->assertCount(0, $dispatcher->getListeners('foo'));
  81. }
  82. /**
  83. * @dataProvider isWrappedDataProvider
  84. *
  85. * @param bool $isWrapped
  86. */
  87. public function testGetCalledListeners($isWrapped)
  88. {
  89. $dispatcher = new EventDispatcher();
  90. $stopWatch = new Stopwatch();
  91. $tdispatcher = new TraceableEventDispatcher($dispatcher, $stopWatch);
  92. $listener = function () {};
  93. if ($isWrapped) {
  94. $listener = new WrappedListener($listener, 'foo', $stopWatch, $dispatcher);
  95. }
  96. $tdispatcher->addListener('foo', $listener, 5);
  97. $this->assertEquals(array(), $tdispatcher->getCalledListeners());
  98. $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'type' => 'Closure', 'pretty' => 'closure', 'priority' => 5)), $tdispatcher->getNotCalledListeners());
  99. $tdispatcher->dispatch('foo');
  100. $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'type' => 'Closure', 'pretty' => 'closure', 'priority' => 5)), $tdispatcher->getCalledListeners());
  101. $this->assertEquals(array(), $tdispatcher->getNotCalledListeners());
  102. }
  103. public function isWrappedDataProvider()
  104. {
  105. return array(
  106. array(false),
  107. array(true),
  108. );
  109. }
  110. public function testGetCalledListenersNested()
  111. {
  112. $tdispatcher = null;
  113. $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
  114. $dispatcher->addListener('foo', function (Event $event, $eventName, $dispatcher) use (&$tdispatcher) {
  115. $tdispatcher = $dispatcher;
  116. $dispatcher->dispatch('bar');
  117. });
  118. $dispatcher->addListener('bar', function (Event $event) {});
  119. $dispatcher->dispatch('foo');
  120. $this->assertSame($dispatcher, $tdispatcher);
  121. $this->assertCount(2, $dispatcher->getCalledListeners());
  122. }
  123. public function testLogger()
  124. {
  125. $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
  126. $dispatcher = new EventDispatcher();
  127. $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch(), $logger);
  128. $tdispatcher->addListener('foo', $listener1 = function () {});
  129. $tdispatcher->addListener('foo', $listener2 = function () {});
  130. $logger->expects($this->at(0))->method('debug')->with('Notified event "foo" to listener "closure".');
  131. $logger->expects($this->at(1))->method('debug')->with('Notified event "foo" to listener "closure".');
  132. $tdispatcher->dispatch('foo');
  133. }
  134. public function testLoggerWithStoppedEvent()
  135. {
  136. $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
  137. $dispatcher = new EventDispatcher();
  138. $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch(), $logger);
  139. $tdispatcher->addListener('foo', $listener1 = function (Event $event) { $event->stopPropagation(); });
  140. $tdispatcher->addListener('foo', $listener2 = function () {});
  141. $logger->expects($this->at(0))->method('debug')->with('Notified event "foo" to listener "closure".');
  142. $logger->expects($this->at(1))->method('debug')->with('Listener "closure" stopped propagation of the event "foo".');
  143. $logger->expects($this->at(2))->method('debug')->with('Listener "closure" was not called for event "foo".');
  144. $tdispatcher->dispatch('foo');
  145. }
  146. public function testDispatchCallListeners()
  147. {
  148. $called = array();
  149. $dispatcher = new EventDispatcher();
  150. $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
  151. $tdispatcher->addListener('foo', function () use (&$called) { $called[] = 'foo1'; }, 10);
  152. $tdispatcher->addListener('foo', function () use (&$called) { $called[] = 'foo2'; }, 20);
  153. $tdispatcher->dispatch('foo');
  154. $this->assertSame(array('foo2', 'foo1'), $called);
  155. }
  156. public function testDispatchNested()
  157. {
  158. $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
  159. $loop = 1;
  160. $dispatchedEvents = 0;
  161. $dispatcher->addListener('foo', $listener1 = function () use ($dispatcher, &$loop) {
  162. ++$loop;
  163. if (2 == $loop) {
  164. $dispatcher->dispatch('foo');
  165. }
  166. });
  167. $dispatcher->addListener('foo', function () use (&$dispatchedEvents) {
  168. ++$dispatchedEvents;
  169. });
  170. $dispatcher->dispatch('foo');
  171. $this->assertSame(2, $dispatchedEvents);
  172. }
  173. public function testDispatchReusedEventNested()
  174. {
  175. $nestedCall = false;
  176. $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
  177. $dispatcher->addListener('foo', function (Event $e) use ($dispatcher) {
  178. $dispatcher->dispatch('bar', $e);
  179. });
  180. $dispatcher->addListener('bar', function (Event $e) use (&$nestedCall) {
  181. $nestedCall = true;
  182. });
  183. $this->assertFalse($nestedCall);
  184. $dispatcher->dispatch('foo');
  185. $this->assertTrue($nestedCall);
  186. }
  187. public function testListenerCanRemoveItselfWhenExecuted()
  188. {
  189. $eventDispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
  190. $listener1 = function ($event, $eventName, EventDispatcherInterface $dispatcher) use (&$listener1) {
  191. $dispatcher->removeListener('foo', $listener1);
  192. };
  193. $eventDispatcher->addListener('foo', $listener1);
  194. $eventDispatcher->addListener('foo', function () {});
  195. $eventDispatcher->dispatch('foo');
  196. $this->assertCount(1, $eventDispatcher->getListeners('foo'), 'expected listener1 to be removed');
  197. }
  198. }
  199. class EventSubscriber implements EventSubscriberInterface
  200. {
  201. public static function getSubscribedEvents()
  202. {
  203. return array('foo' => 'call');
  204. }
  205. }