scratch – Blame information for rev 87

Subversion Repositories:
Rev:
Rev Author Line No. Line
87 office 1 <?php
2  
3 namespace GuzzleHttp\Tests\Event;
4  
5 use GuzzleHttp\Event\Emitter;
6 use GuzzleHttp\Event\EventInterface;
7 use GuzzleHttp\Event\SubscriberInterface;
8  
9 /**
10 * @link https://github.com/symfony/symfony/blob/master/src/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php Based on this test.
11 */
12 class EmitterTest extends \PHPUnit_Framework_TestCase
13 {
14 /* Some pseudo events */
15 const preFoo = 'pre.foo';
16 const postFoo = 'post.foo';
17 const preBar = 'pre.bar';
18 const postBar = 'post.bar';
19  
20 /** @var Emitter */
21 private $emitter;
22 private $listener;
23  
24 protected function setUp()
25 {
26 $this->emitter = new Emitter();
27 $this->listener = new TestEventListener();
28 }
29  
30 protected function tearDown()
31 {
32 $this->emitter = null;
33 $this->listener = null;
34 }
35  
36 public function testInitialState()
37 {
38 $this->assertEquals(array(), $this->emitter->listeners());
39 }
40  
41 public function testAddListener()
42 {
43 $this->emitter->on('pre.foo', array($this->listener, 'preFoo'));
44 $this->emitter->on('post.foo', array($this->listener, 'postFoo'));
45 $this->assertCount(1, $this->emitter->listeners(self::preFoo));
46 $this->assertCount(1, $this->emitter->listeners(self::postFoo));
47 $this->assertCount(2, $this->emitter->listeners());
48 }
49  
50 public function testGetListenersSortsByPriority()
51 {
52 $listener1 = new TestEventListener();
53 $listener2 = new TestEventListener();
54 $listener3 = new TestEventListener();
55 $listener1->name = '1';
56 $listener2->name = '2';
57 $listener3->name = '3';
58  
59 $this->emitter->on('pre.foo', array($listener1, 'preFoo'), -10);
60 $this->emitter->on('pre.foo', array($listener2, 'preFoo'), 10);
61 $this->emitter->on('pre.foo', array($listener3, 'preFoo'));
62  
63 $expected = array(
64 array($listener2, 'preFoo'),
65 array($listener3, 'preFoo'),
66 array($listener1, 'preFoo'),
67 );
68  
69 $this->assertSame($expected, $this->emitter->listeners('pre.foo'));
70 }
71  
72 public function testGetAllListenersSortsByPriority()
73 {
74 $listener1 = new TestEventListener();
75 $listener2 = new TestEventListener();
76 $listener3 = new TestEventListener();
77 $listener4 = new TestEventListener();
78 $listener5 = new TestEventListener();
79 $listener6 = new TestEventListener();
80  
81 $this->emitter->on('pre.foo', [$listener1, 'preFoo'], -10);
82 $this->emitter->on('pre.foo', [$listener2, 'preFoo']);
83 $this->emitter->on('pre.foo', [$listener3, 'preFoo'], 10);
84 $this->emitter->on('post.foo', [$listener4, 'preFoo'], -10);
85 $this->emitter->on('post.foo', [$listener5, 'preFoo']);
86 $this->emitter->on('post.foo', [$listener6, 'preFoo'], 10);
87  
88 $expected = [
89 'pre.foo' => [[$listener3, 'preFoo'], [$listener2, 'preFoo'], [$listener1, 'preFoo']],
90 'post.foo' => [[$listener6, 'preFoo'], [$listener5, 'preFoo'], [$listener4, 'preFoo']],
91 ];
92  
93 $this->assertSame($expected, $this->emitter->listeners());
94 }
95  
96 public function testDispatch()
97 {
98 $this->emitter->on('pre.foo', array($this->listener, 'preFoo'));
99 $this->emitter->on('post.foo', array($this->listener, 'postFoo'));
100 $this->emitter->emit(self::preFoo, $this->getEvent());
101 $this->assertTrue($this->listener->preFooInvoked);
102 $this->assertFalse($this->listener->postFooInvoked);
103 $this->assertInstanceOf('GuzzleHttp\Event\EventInterface', $this->emitter->emit(self::preFoo, $this->getEvent()));
104 $event = $this->getEvent();
105 $return = $this->emitter->emit(self::preFoo, $event);
106 $this->assertSame($event, $return);
107 }
108  
109 public function testDispatchForClosure()
110 {
111 $invoked = 0;
112 $listener = function () use (&$invoked) {
113 $invoked++;
114 };
115 $this->emitter->on('pre.foo', $listener);
116 $this->emitter->on('post.foo', $listener);
117 $this->emitter->emit(self::preFoo, $this->getEvent());
118 $this->assertEquals(1, $invoked);
119 }
120  
121 public function testStopEventPropagation()
122 {
123 $otherListener = new TestEventListener();
124  
125 // postFoo() stops the propagation, so only one listener should
126 // be executed
127 // Manually set priority to enforce $this->listener to be called first
128 $this->emitter->on('post.foo', array($this->listener, 'postFoo'), 10);
129 $this->emitter->on('post.foo', array($otherListener, 'preFoo'));
130 $this->emitter->emit(self::postFoo, $this->getEvent());
131 $this->assertTrue($this->listener->postFooInvoked);
132 $this->assertFalse($otherListener->postFooInvoked);
133 }
134  
135 public function testDispatchByPriority()
136 {
137 $invoked = array();
138 $listener1 = function () use (&$invoked) {
139 $invoked[] = '1';
140 };
141 $listener2 = function () use (&$invoked) {
142 $invoked[] = '2';
143 };
144 $listener3 = function () use (&$invoked) {
145 $invoked[] = '3';
146 };
147 $this->emitter->on('pre.foo', $listener1, -10);
148 $this->emitter->on('pre.foo', $listener2);
149 $this->emitter->on('pre.foo', $listener3, 10);
150 $this->emitter->emit(self::preFoo, $this->getEvent());
151 $this->assertEquals(array('3', '2', '1'), $invoked);
152 }
153  
154 public function testRemoveListener()
155 {
156 $this->emitter->on('pre.bar', [$this->listener, 'preFoo']);
157 $this->assertNotEmpty($this->emitter->listeners(self::preBar));
158 $this->emitter->removeListener('pre.bar', [$this->listener, 'preFoo']);
159 $this->assertEmpty($this->emitter->listeners(self::preBar));
160 $this->emitter->removeListener('notExists', [$this->listener, 'preFoo']);
161 }
162  
163 public function testAddSubscriber()
164 {
165 $eventSubscriber = new TestEventSubscriber();
166 $this->emitter->attach($eventSubscriber);
167 $this->assertNotEmpty($this->emitter->listeners(self::preFoo));
168 $this->assertNotEmpty($this->emitter->listeners(self::postFoo));
169 }
170  
171 public function testAddSubscriberWithMultiple()
172 {
173 $eventSubscriber = new TestEventSubscriberWithMultiple();
174 $this->emitter->attach($eventSubscriber);
175 $listeners = $this->emitter->listeners('pre.foo');
176 $this->assertNotEmpty($this->emitter->listeners(self::preFoo));
177 $this->assertCount(2, $listeners);
178 }
179  
180 public function testAddSubscriberWithPriorities()
181 {
182 $eventSubscriber = new TestEventSubscriber();
183 $this->emitter->attach($eventSubscriber);
184  
185 $eventSubscriber = new TestEventSubscriberWithPriorities();
186 $this->emitter->attach($eventSubscriber);
187  
188 $listeners = $this->emitter->listeners('pre.foo');
189 $this->assertNotEmpty($this->emitter->listeners(self::preFoo));
190 $this->assertCount(2, $listeners);
191 $this->assertInstanceOf('GuzzleHttp\Tests\Event\TestEventSubscriberWithPriorities', $listeners[0][0]);
192 }
193  
194 public function testdetach()
195 {
196 $eventSubscriber = new TestEventSubscriber();
197 $this->emitter->attach($eventSubscriber);
198 $this->assertNotEmpty($this->emitter->listeners(self::preFoo));
199 $this->assertNotEmpty($this->emitter->listeners(self::postFoo));
200 $this->emitter->detach($eventSubscriber);
201 $this->assertEmpty($this->emitter->listeners(self::preFoo));
202 $this->assertEmpty($this->emitter->listeners(self::postFoo));
203 }
204  
205 public function testdetachWithPriorities()
206 {
207 $eventSubscriber = new TestEventSubscriberWithPriorities();
208 $this->emitter->attach($eventSubscriber);
209 $this->assertNotEmpty($this->emitter->listeners(self::preFoo));
210 $this->assertNotEmpty($this->emitter->listeners(self::postFoo));
211 $this->emitter->detach($eventSubscriber);
212 $this->assertEmpty($this->emitter->listeners(self::preFoo));
213 $this->assertEmpty($this->emitter->listeners(self::postFoo));
214 }
215  
216 public function testEventReceivesEventNameAsArgument()
217 {
218 $listener = new TestWithDispatcher();
219 $this->emitter->on('test', array($listener, 'foo'));
220 $this->assertNull($listener->name);
221 $this->emitter->emit('test', $this->getEvent());
222 $this->assertEquals('test', $listener->name);
223 }
224  
225 /**
226 * @see https://bugs.php.net/bug.php?id=62976
227 *
228 * This bug affects:
229 * - The PHP 5.3 branch for versions < 5.3.18
230 * - The PHP 5.4 branch for versions < 5.4.8
231 * - The PHP 5.5 branch is not affected
232 */
233 public function testWorkaroundForPhpBug62976()
234 {
235 $dispatcher = new Emitter();
236 $dispatcher->on('bug.62976', new CallableClass());
237 $dispatcher->removeListener('bug.62976', function () {});
238 $this->assertNotEmpty($dispatcher->listeners('bug.62976'));
239 }
240  
241 public function testRegistersEventsOnce()
242 {
243 $this->emitter->once('pre.foo', array($this->listener, 'preFoo'));
244 $this->emitter->on('pre.foo', array($this->listener, 'preFoo'));
245 $this->assertCount(2, $this->emitter->listeners(self::preFoo));
246 $this->emitter->emit(self::preFoo, $this->getEvent());
247 $this->assertTrue($this->listener->preFooInvoked);
248 $this->assertCount(1, $this->emitter->listeners(self::preFoo));
249 }
250  
251 public function testReturnsEmptyArrayForNonExistentEvent()
252 {
253 $this->assertEquals([], $this->emitter->listeners('doesnotexist'));
254 }
255  
256 public function testCanAddFirstAndLastListeners()
257 {
258 $b = '';
259 $this->emitter->on('foo', function () use (&$b) { $b .= 'a'; }, 'first'); // 1
260 $this->emitter->on('foo', function () use (&$b) { $b .= 'b'; }, 'last'); // 0
261 $this->emitter->on('foo', function () use (&$b) { $b .= 'c'; }, 'first'); // 2
262 $this->emitter->on('foo', function () use (&$b) { $b .= 'd'; }, 'first'); // 3
263 $this->emitter->on('foo', function () use (&$b) { $b .= 'e'; }, 'first'); // 4
264 $this->emitter->on('foo', function () use (&$b) { $b .= 'f'; }); // 0
265 $this->emitter->emit('foo', $this->getEvent());
266 $this->assertEquals('edcabf', $b);
267 }
268  
269 /**
270 * @return \GuzzleHttp\Event\EventInterface
271 */
272 private function getEvent()
273 {
274 return $this->getMockBuilder('GuzzleHttp\Event\AbstractEvent')
275 ->getMockForAbstractClass();
276 }
277 }
278  
279 class CallableClass
280 {
281 public function __invoke()
282 {
283 }
284 }
285  
286 class TestEventListener
287 {
288 public $preFooInvoked = false;
289 public $postFooInvoked = false;
290  
291 /* Listener methods */
292  
293 public function preFoo(EventInterface $e)
294 {
295 $this->preFooInvoked = true;
296 }
297  
298 public function postFoo(EventInterface $e)
299 {
300 $this->postFooInvoked = true;
301  
302 $e->stopPropagation();
303 }
304  
305 /**
306 * @expectedException \PHPUnit_Framework_Error_Deprecated
307 */
308 public function testHasDeprecatedAddListener()
309 {
310 $emitter = new Emitter();
311 $emitter->addListener('foo', function () {});
312 }
313  
314 /**
315 * @expectedException \PHPUnit_Framework_Error_Deprecated
316 */
317 public function testHasDeprecatedAddSubscriber()
318 {
319 $emitter = new Emitter();
320 $emitter->addSubscriber('foo', new TestEventSubscriber());
321 }
322 }
323  
324 class TestWithDispatcher
325 {
326 public $name;
327  
328 public function foo(EventInterface $e, $name)
329 {
330 $this->name = $name;
331 }
332 }
333  
334 class TestEventSubscriber extends TestEventListener implements SubscriberInterface
335 {
336 public function getEvents()
337 {
338 return [
339 'pre.foo' => ['preFoo'],
340 'post.foo' => ['postFoo']
341 ];
342 }
343 }
344  
345 class TestEventSubscriberWithPriorities extends TestEventListener implements SubscriberInterface
346 {
347 public function getEvents()
348 {
349 return [
350 'pre.foo' => ['preFoo', 10],
351 'post.foo' => ['postFoo']
352 ];
353 }
354 }
355  
356 class TestEventSubscriberWithMultiple extends TestEventListener implements SubscriberInterface
357 {
358 public function getEvents()
359 {
360 return ['pre.foo' => [['preFoo', 10],['preFoo', 20]]];
361 }
362 }