annotate vendor/symfony/event-dispatcher/Tests/AbstractEventDispatcherTest.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 129ea1e6d783
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /*
Chris@0 4 * This file is part of the Symfony package.
Chris@0 5 *
Chris@0 6 * (c) Fabien Potencier <fabien@symfony.com>
Chris@0 7 *
Chris@0 8 * For the full copyright and license information, please view the LICENSE
Chris@0 9 * file that was distributed with this source code.
Chris@0 10 */
Chris@0 11
Chris@0 12 namespace Symfony\Component\EventDispatcher\Tests;
Chris@0 13
Chris@0 14 use PHPUnit\Framework\TestCase;
Chris@0 15 use Symfony\Component\EventDispatcher\Event;
Chris@0 16 use Symfony\Component\EventDispatcher\EventDispatcher;
Chris@0 17 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
Chris@0 18
Chris@0 19 abstract class AbstractEventDispatcherTest extends TestCase
Chris@0 20 {
Chris@0 21 /* Some pseudo events */
Chris@0 22 const preFoo = 'pre.foo';
Chris@0 23 const postFoo = 'post.foo';
Chris@0 24 const preBar = 'pre.bar';
Chris@0 25 const postBar = 'post.bar';
Chris@0 26
Chris@0 27 /**
Chris@0 28 * @var EventDispatcher
Chris@0 29 */
Chris@0 30 private $dispatcher;
Chris@0 31
Chris@0 32 private $listener;
Chris@0 33
Chris@0 34 protected function setUp()
Chris@0 35 {
Chris@0 36 $this->dispatcher = $this->createEventDispatcher();
Chris@0 37 $this->listener = new TestEventListener();
Chris@0 38 }
Chris@0 39
Chris@0 40 protected function tearDown()
Chris@0 41 {
Chris@0 42 $this->dispatcher = null;
Chris@0 43 $this->listener = null;
Chris@0 44 }
Chris@0 45
Chris@0 46 abstract protected function createEventDispatcher();
Chris@0 47
Chris@0 48 public function testInitialState()
Chris@0 49 {
Chris@17 50 $this->assertEquals([], $this->dispatcher->getListeners());
Chris@0 51 $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
Chris@0 52 $this->assertFalse($this->dispatcher->hasListeners(self::postFoo));
Chris@0 53 }
Chris@0 54
Chris@0 55 public function testAddListener()
Chris@0 56 {
Chris@17 57 $this->dispatcher->addListener('pre.foo', [$this->listener, 'preFoo']);
Chris@17 58 $this->dispatcher->addListener('post.foo', [$this->listener, 'postFoo']);
Chris@12 59 $this->assertTrue($this->dispatcher->hasListeners());
Chris@0 60 $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
Chris@0 61 $this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
Chris@0 62 $this->assertCount(1, $this->dispatcher->getListeners(self::preFoo));
Chris@0 63 $this->assertCount(1, $this->dispatcher->getListeners(self::postFoo));
Chris@0 64 $this->assertCount(2, $this->dispatcher->getListeners());
Chris@0 65 }
Chris@0 66
Chris@0 67 public function testGetListenersSortsByPriority()
Chris@0 68 {
Chris@0 69 $listener1 = new TestEventListener();
Chris@0 70 $listener2 = new TestEventListener();
Chris@0 71 $listener3 = new TestEventListener();
Chris@0 72 $listener1->name = '1';
Chris@0 73 $listener2->name = '2';
Chris@0 74 $listener3->name = '3';
Chris@0 75
Chris@17 76 $this->dispatcher->addListener('pre.foo', [$listener1, 'preFoo'], -10);
Chris@17 77 $this->dispatcher->addListener('pre.foo', [$listener2, 'preFoo'], 10);
Chris@17 78 $this->dispatcher->addListener('pre.foo', [$listener3, 'preFoo']);
Chris@0 79
Chris@17 80 $expected = [
Chris@17 81 [$listener2, 'preFoo'],
Chris@17 82 [$listener3, 'preFoo'],
Chris@17 83 [$listener1, 'preFoo'],
Chris@17 84 ];
Chris@0 85
Chris@0 86 $this->assertSame($expected, $this->dispatcher->getListeners('pre.foo'));
Chris@0 87 }
Chris@0 88
Chris@0 89 public function testGetAllListenersSortsByPriority()
Chris@0 90 {
Chris@0 91 $listener1 = new TestEventListener();
Chris@0 92 $listener2 = new TestEventListener();
Chris@0 93 $listener3 = new TestEventListener();
Chris@0 94 $listener4 = new TestEventListener();
Chris@0 95 $listener5 = new TestEventListener();
Chris@0 96 $listener6 = new TestEventListener();
Chris@0 97
Chris@0 98 $this->dispatcher->addListener('pre.foo', $listener1, -10);
Chris@0 99 $this->dispatcher->addListener('pre.foo', $listener2);
Chris@0 100 $this->dispatcher->addListener('pre.foo', $listener3, 10);
Chris@0 101 $this->dispatcher->addListener('post.foo', $listener4, -10);
Chris@0 102 $this->dispatcher->addListener('post.foo', $listener5);
Chris@0 103 $this->dispatcher->addListener('post.foo', $listener6, 10);
Chris@0 104
Chris@17 105 $expected = [
Chris@17 106 'pre.foo' => [$listener3, $listener2, $listener1],
Chris@17 107 'post.foo' => [$listener6, $listener5, $listener4],
Chris@17 108 ];
Chris@0 109
Chris@0 110 $this->assertSame($expected, $this->dispatcher->getListeners());
Chris@0 111 }
Chris@0 112
Chris@0 113 public function testGetListenerPriority()
Chris@0 114 {
Chris@0 115 $listener1 = new TestEventListener();
Chris@0 116 $listener2 = new TestEventListener();
Chris@0 117
Chris@0 118 $this->dispatcher->addListener('pre.foo', $listener1, -10);
Chris@0 119 $this->dispatcher->addListener('pre.foo', $listener2);
Chris@0 120
Chris@0 121 $this->assertSame(-10, $this->dispatcher->getListenerPriority('pre.foo', $listener1));
Chris@0 122 $this->assertSame(0, $this->dispatcher->getListenerPriority('pre.foo', $listener2));
Chris@0 123 $this->assertNull($this->dispatcher->getListenerPriority('pre.bar', $listener2));
Chris@0 124 $this->assertNull($this->dispatcher->getListenerPriority('pre.foo', function () {}));
Chris@0 125 }
Chris@0 126
Chris@0 127 public function testDispatch()
Chris@0 128 {
Chris@17 129 $this->dispatcher->addListener('pre.foo', [$this->listener, 'preFoo']);
Chris@17 130 $this->dispatcher->addListener('post.foo', [$this->listener, 'postFoo']);
Chris@0 131 $this->dispatcher->dispatch(self::preFoo);
Chris@0 132 $this->assertTrue($this->listener->preFooInvoked);
Chris@0 133 $this->assertFalse($this->listener->postFooInvoked);
Chris@0 134 $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch('noevent'));
Chris@0 135 $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(self::preFoo));
Chris@0 136 $event = new Event();
Chris@0 137 $return = $this->dispatcher->dispatch(self::preFoo, $event);
Chris@0 138 $this->assertSame($event, $return);
Chris@0 139 }
Chris@0 140
Chris@0 141 public function testDispatchForClosure()
Chris@0 142 {
Chris@0 143 $invoked = 0;
Chris@0 144 $listener = function () use (&$invoked) {
Chris@0 145 ++$invoked;
Chris@0 146 };
Chris@0 147 $this->dispatcher->addListener('pre.foo', $listener);
Chris@0 148 $this->dispatcher->addListener('post.foo', $listener);
Chris@0 149 $this->dispatcher->dispatch(self::preFoo);
Chris@0 150 $this->assertEquals(1, $invoked);
Chris@0 151 }
Chris@0 152
Chris@0 153 public function testStopEventPropagation()
Chris@0 154 {
Chris@0 155 $otherListener = new TestEventListener();
Chris@0 156
Chris@0 157 // postFoo() stops the propagation, so only one listener should
Chris@0 158 // be executed
Chris@0 159 // Manually set priority to enforce $this->listener to be called first
Chris@17 160 $this->dispatcher->addListener('post.foo', [$this->listener, 'postFoo'], 10);
Chris@17 161 $this->dispatcher->addListener('post.foo', [$otherListener, 'postFoo']);
Chris@0 162 $this->dispatcher->dispatch(self::postFoo);
Chris@0 163 $this->assertTrue($this->listener->postFooInvoked);
Chris@0 164 $this->assertFalse($otherListener->postFooInvoked);
Chris@0 165 }
Chris@0 166
Chris@0 167 public function testDispatchByPriority()
Chris@0 168 {
Chris@17 169 $invoked = [];
Chris@0 170 $listener1 = function () use (&$invoked) {
Chris@0 171 $invoked[] = '1';
Chris@0 172 };
Chris@0 173 $listener2 = function () use (&$invoked) {
Chris@0 174 $invoked[] = '2';
Chris@0 175 };
Chris@0 176 $listener3 = function () use (&$invoked) {
Chris@0 177 $invoked[] = '3';
Chris@0 178 };
Chris@0 179 $this->dispatcher->addListener('pre.foo', $listener1, -10);
Chris@0 180 $this->dispatcher->addListener('pre.foo', $listener2);
Chris@0 181 $this->dispatcher->addListener('pre.foo', $listener3, 10);
Chris@0 182 $this->dispatcher->dispatch(self::preFoo);
Chris@17 183 $this->assertEquals(['3', '2', '1'], $invoked);
Chris@0 184 }
Chris@0 185
Chris@0 186 public function testRemoveListener()
Chris@0 187 {
Chris@0 188 $this->dispatcher->addListener('pre.bar', $this->listener);
Chris@0 189 $this->assertTrue($this->dispatcher->hasListeners(self::preBar));
Chris@0 190 $this->dispatcher->removeListener('pre.bar', $this->listener);
Chris@0 191 $this->assertFalse($this->dispatcher->hasListeners(self::preBar));
Chris@0 192 $this->dispatcher->removeListener('notExists', $this->listener);
Chris@0 193 }
Chris@0 194
Chris@0 195 public function testAddSubscriber()
Chris@0 196 {
Chris@0 197 $eventSubscriber = new TestEventSubscriber();
Chris@0 198 $this->dispatcher->addSubscriber($eventSubscriber);
Chris@0 199 $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
Chris@0 200 $this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
Chris@0 201 }
Chris@0 202
Chris@0 203 public function testAddSubscriberWithPriorities()
Chris@0 204 {
Chris@0 205 $eventSubscriber = new TestEventSubscriber();
Chris@0 206 $this->dispatcher->addSubscriber($eventSubscriber);
Chris@0 207
Chris@0 208 $eventSubscriber = new TestEventSubscriberWithPriorities();
Chris@0 209 $this->dispatcher->addSubscriber($eventSubscriber);
Chris@0 210
Chris@0 211 $listeners = $this->dispatcher->getListeners('pre.foo');
Chris@0 212 $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
Chris@0 213 $this->assertCount(2, $listeners);
Chris@0 214 $this->assertInstanceOf('Symfony\Component\EventDispatcher\Tests\TestEventSubscriberWithPriorities', $listeners[0][0]);
Chris@0 215 }
Chris@0 216
Chris@0 217 public function testAddSubscriberWithMultipleListeners()
Chris@0 218 {
Chris@0 219 $eventSubscriber = new TestEventSubscriberWithMultipleListeners();
Chris@0 220 $this->dispatcher->addSubscriber($eventSubscriber);
Chris@0 221
Chris@0 222 $listeners = $this->dispatcher->getListeners('pre.foo');
Chris@0 223 $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
Chris@0 224 $this->assertCount(2, $listeners);
Chris@0 225 $this->assertEquals('preFoo2', $listeners[0][1]);
Chris@0 226 }
Chris@0 227
Chris@0 228 public function testRemoveSubscriber()
Chris@0 229 {
Chris@0 230 $eventSubscriber = new TestEventSubscriber();
Chris@0 231 $this->dispatcher->addSubscriber($eventSubscriber);
Chris@0 232 $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
Chris@0 233 $this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
Chris@0 234 $this->dispatcher->removeSubscriber($eventSubscriber);
Chris@0 235 $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
Chris@0 236 $this->assertFalse($this->dispatcher->hasListeners(self::postFoo));
Chris@0 237 }
Chris@0 238
Chris@0 239 public function testRemoveSubscriberWithPriorities()
Chris@0 240 {
Chris@0 241 $eventSubscriber = new TestEventSubscriberWithPriorities();
Chris@0 242 $this->dispatcher->addSubscriber($eventSubscriber);
Chris@0 243 $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
Chris@0 244 $this->dispatcher->removeSubscriber($eventSubscriber);
Chris@0 245 $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
Chris@0 246 }
Chris@0 247
Chris@0 248 public function testRemoveSubscriberWithMultipleListeners()
Chris@0 249 {
Chris@0 250 $eventSubscriber = new TestEventSubscriberWithMultipleListeners();
Chris@0 251 $this->dispatcher->addSubscriber($eventSubscriber);
Chris@0 252 $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
Chris@0 253 $this->assertCount(2, $this->dispatcher->getListeners(self::preFoo));
Chris@0 254 $this->dispatcher->removeSubscriber($eventSubscriber);
Chris@0 255 $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
Chris@0 256 }
Chris@0 257
Chris@0 258 public function testEventReceivesTheDispatcherInstanceAsArgument()
Chris@0 259 {
Chris@0 260 $listener = new TestWithDispatcher();
Chris@17 261 $this->dispatcher->addListener('test', [$listener, 'foo']);
Chris@0 262 $this->assertNull($listener->name);
Chris@0 263 $this->assertNull($listener->dispatcher);
Chris@0 264 $this->dispatcher->dispatch('test');
Chris@0 265 $this->assertEquals('test', $listener->name);
Chris@0 266 $this->assertSame($this->dispatcher, $listener->dispatcher);
Chris@0 267 }
Chris@0 268
Chris@0 269 /**
Chris@0 270 * @see https://bugs.php.net/bug.php?id=62976
Chris@0 271 *
Chris@0 272 * This bug affects:
Chris@0 273 * - The PHP 5.3 branch for versions < 5.3.18
Chris@0 274 * - The PHP 5.4 branch for versions < 5.4.8
Chris@0 275 * - The PHP 5.5 branch is not affected
Chris@0 276 */
Chris@0 277 public function testWorkaroundForPhpBug62976()
Chris@0 278 {
Chris@0 279 $dispatcher = $this->createEventDispatcher();
Chris@0 280 $dispatcher->addListener('bug.62976', new CallableClass());
Chris@0 281 $dispatcher->removeListener('bug.62976', function () {});
Chris@0 282 $this->assertTrue($dispatcher->hasListeners('bug.62976'));
Chris@0 283 }
Chris@0 284
Chris@0 285 public function testHasListenersWhenAddedCallbackListenerIsRemoved()
Chris@0 286 {
Chris@0 287 $listener = function () {};
Chris@0 288 $this->dispatcher->addListener('foo', $listener);
Chris@0 289 $this->dispatcher->removeListener('foo', $listener);
Chris@0 290 $this->assertFalse($this->dispatcher->hasListeners());
Chris@0 291 }
Chris@0 292
Chris@0 293 public function testGetListenersWhenAddedCallbackListenerIsRemoved()
Chris@0 294 {
Chris@0 295 $listener = function () {};
Chris@0 296 $this->dispatcher->addListener('foo', $listener);
Chris@0 297 $this->dispatcher->removeListener('foo', $listener);
Chris@17 298 $this->assertSame([], $this->dispatcher->getListeners());
Chris@0 299 }
Chris@0 300
Chris@0 301 public function testHasListenersWithoutEventsReturnsFalseAfterHasListenersWithEventHasBeenCalled()
Chris@0 302 {
Chris@0 303 $this->assertFalse($this->dispatcher->hasListeners('foo'));
Chris@0 304 $this->assertFalse($this->dispatcher->hasListeners());
Chris@0 305 }
Chris@14 306
Chris@14 307 public function testHasListenersIsLazy()
Chris@14 308 {
Chris@14 309 $called = 0;
Chris@17 310 $listener = [function () use (&$called) { ++$called; }, 'onFoo'];
Chris@14 311 $this->dispatcher->addListener('foo', $listener);
Chris@14 312 $this->assertTrue($this->dispatcher->hasListeners());
Chris@14 313 $this->assertTrue($this->dispatcher->hasListeners('foo'));
Chris@14 314 $this->assertSame(0, $called);
Chris@14 315 }
Chris@14 316
Chris@14 317 public function testDispatchLazyListener()
Chris@14 318 {
Chris@14 319 $called = 0;
Chris@14 320 $factory = function () use (&$called) {
Chris@14 321 ++$called;
Chris@14 322
Chris@14 323 return new TestWithDispatcher();
Chris@14 324 };
Chris@17 325 $this->dispatcher->addListener('foo', [$factory, 'foo']);
Chris@14 326 $this->assertSame(0, $called);
Chris@14 327 $this->dispatcher->dispatch('foo', new Event());
Chris@14 328 $this->dispatcher->dispatch('foo', new Event());
Chris@14 329 $this->assertSame(1, $called);
Chris@14 330 }
Chris@14 331
Chris@14 332 public function testRemoveFindsLazyListeners()
Chris@14 333 {
Chris@14 334 $test = new TestWithDispatcher();
Chris@14 335 $factory = function () use ($test) { return $test; };
Chris@14 336
Chris@17 337 $this->dispatcher->addListener('foo', [$factory, 'foo']);
Chris@14 338 $this->assertTrue($this->dispatcher->hasListeners('foo'));
Chris@17 339 $this->dispatcher->removeListener('foo', [$test, 'foo']);
Chris@14 340 $this->assertFalse($this->dispatcher->hasListeners('foo'));
Chris@14 341
Chris@17 342 $this->dispatcher->addListener('foo', [$test, 'foo']);
Chris@14 343 $this->assertTrue($this->dispatcher->hasListeners('foo'));
Chris@17 344 $this->dispatcher->removeListener('foo', [$factory, 'foo']);
Chris@14 345 $this->assertFalse($this->dispatcher->hasListeners('foo'));
Chris@14 346 }
Chris@14 347
Chris@14 348 public function testPriorityFindsLazyListeners()
Chris@14 349 {
Chris@14 350 $test = new TestWithDispatcher();
Chris@14 351 $factory = function () use ($test) { return $test; };
Chris@14 352
Chris@17 353 $this->dispatcher->addListener('foo', [$factory, 'foo'], 3);
Chris@17 354 $this->assertSame(3, $this->dispatcher->getListenerPriority('foo', [$test, 'foo']));
Chris@17 355 $this->dispatcher->removeListener('foo', [$factory, 'foo']);
Chris@14 356
Chris@17 357 $this->dispatcher->addListener('foo', [$test, 'foo'], 5);
Chris@17 358 $this->assertSame(5, $this->dispatcher->getListenerPriority('foo', [$factory, 'foo']));
Chris@14 359 }
Chris@14 360
Chris@14 361 public function testGetLazyListeners()
Chris@14 362 {
Chris@14 363 $test = new TestWithDispatcher();
Chris@14 364 $factory = function () use ($test) { return $test; };
Chris@14 365
Chris@17 366 $this->dispatcher->addListener('foo', [$factory, 'foo'], 3);
Chris@17 367 $this->assertSame([[$test, 'foo']], $this->dispatcher->getListeners('foo'));
Chris@14 368
Chris@17 369 $this->dispatcher->removeListener('foo', [$test, 'foo']);
Chris@17 370 $this->dispatcher->addListener('bar', [$factory, 'foo'], 3);
Chris@17 371 $this->assertSame(['bar' => [[$test, 'foo']]], $this->dispatcher->getListeners());
Chris@14 372 }
Chris@0 373 }
Chris@0 374
Chris@0 375 class CallableClass
Chris@0 376 {
Chris@0 377 public function __invoke()
Chris@0 378 {
Chris@0 379 }
Chris@0 380 }
Chris@0 381
Chris@0 382 class TestEventListener
Chris@0 383 {
Chris@0 384 public $preFooInvoked = false;
Chris@0 385 public $postFooInvoked = false;
Chris@0 386
Chris@0 387 /* Listener methods */
Chris@0 388
Chris@0 389 public function preFoo(Event $e)
Chris@0 390 {
Chris@0 391 $this->preFooInvoked = true;
Chris@0 392 }
Chris@0 393
Chris@0 394 public function postFoo(Event $e)
Chris@0 395 {
Chris@0 396 $this->postFooInvoked = true;
Chris@0 397
Chris@0 398 $e->stopPropagation();
Chris@0 399 }
Chris@0 400 }
Chris@0 401
Chris@0 402 class TestWithDispatcher
Chris@0 403 {
Chris@0 404 public $name;
Chris@0 405 public $dispatcher;
Chris@0 406
Chris@0 407 public function foo(Event $e, $name, $dispatcher)
Chris@0 408 {
Chris@0 409 $this->name = $name;
Chris@0 410 $this->dispatcher = $dispatcher;
Chris@0 411 }
Chris@0 412 }
Chris@0 413
Chris@0 414 class TestEventSubscriber implements EventSubscriberInterface
Chris@0 415 {
Chris@0 416 public static function getSubscribedEvents()
Chris@0 417 {
Chris@17 418 return ['pre.foo' => 'preFoo', 'post.foo' => 'postFoo'];
Chris@0 419 }
Chris@0 420 }
Chris@0 421
Chris@0 422 class TestEventSubscriberWithPriorities implements EventSubscriberInterface
Chris@0 423 {
Chris@0 424 public static function getSubscribedEvents()
Chris@0 425 {
Chris@17 426 return [
Chris@17 427 'pre.foo' => ['preFoo', 10],
Chris@17 428 'post.foo' => ['postFoo'],
Chris@17 429 ];
Chris@0 430 }
Chris@0 431 }
Chris@0 432
Chris@0 433 class TestEventSubscriberWithMultipleListeners implements EventSubscriberInterface
Chris@0 434 {
Chris@0 435 public static function getSubscribedEvents()
Chris@0 436 {
Chris@17 437 return ['pre.foo' => [
Chris@17 438 ['preFoo1'],
Chris@17 439 ['preFoo2', 10],
Chris@17 440 ]];
Chris@0 441 }
Chris@0 442 }