3333use Symfony \Component \Security \Core \User \InMemoryUser ;
3434use Symfony \Component \Security \Http \FirewallMapInterface ;
3535use Symfony \Component \Security \Http \Logout \LogoutUrlGenerator ;
36+ use Symfony \Component \VarDumper \Caster \ClassStub ;
3637use Symfony \Contracts \EventDispatcher \EventDispatcherInterface ;
3738
3839class SecurityDataCollectorTest extends TestCase
@@ -223,46 +224,111 @@ public function testGetListeners()
223224 $ this ->assertSame (1 , $ listenerCalled );
224225 }
225226
226- public static function providerCollectDecisionLog (): \ Generator
227+ public function testCollectCollectsDecisionLogWhenStrategyIsAffirmative ()
227228 {
228229 $ voter1 = new DummyVoter ();
229230 $ voter2 = new DummyVoter ();
230231
231- $ eventDispatcher = new class () implements EventDispatcherInterface {
232+ $ decoratedVoter1 = new TraceableVoter ( $ voter1 , new class () implements EventDispatcherInterface {
232233 public function dispatch (object $ event , string $ eventName = null ): object
233234 {
234235 return new \stdClass ();
235236 }
236- };
237- $ decoratedVoter1 = new TraceableVoter ($ voter1 , $ eventDispatcher );
237+ });
238+
239+ $ strategy = MainConfiguration::STRATEGY_AFFIRMATIVE ;
240+
241+ $ accessDecisionManager = $ this ->createMock (TraceableAccessDecisionManager::class);
242+
243+ $ accessDecisionManager
244+ ->method ('getStrategy ' )
245+ ->willReturn ($ strategy );
238246
239- yield [
240- MainConfiguration::STRATEGY_AFFIRMATIVE ,
241- [[
247+ $ accessDecisionManager
248+ ->method ('getVoters ' )
249+ ->willReturn ([
250+ $ decoratedVoter1 ,
251+ $ decoratedVoter1 ,
252+ ]);
253+
254+ $ accessDecisionManager
255+ ->method ('getDecisionLog ' )
256+ ->willReturn ([[
242257 'attributes ' => ['view ' ],
243258 'object ' => new \stdClass (),
244259 'result ' => true ,
245260 'voterDetails ' => [
246261 ['voter ' => $ voter1 , 'attributes ' => ['view ' ], 'vote ' => VoterInterface::ACCESS_ABSTAIN ],
247262 ['voter ' => $ voter2 , 'attributes ' => ['view ' ], 'vote ' => VoterInterface::ACCESS_ABSTAIN ],
248263 ],
249- ]],
250- [$ decoratedVoter1 , $ decoratedVoter1 ],
251- [\get_class ($ voter1 ), \get_class ($ voter2 )],
252- [[
253- 'attributes ' => ['view ' ],
254- 'object ' => new \stdClass (),
255- 'result ' => true ,
256- 'voter_details ' => [
257- ['class ' => \get_class ($ voter1 ), 'attributes ' => ['view ' ], 'vote ' => VoterInterface::ACCESS_ABSTAIN ],
258- ['class ' => \get_class ($ voter2 ), 'attributes ' => ['view ' ], 'vote ' => VoterInterface::ACCESS_ABSTAIN ],
259- ],
260- ]],
264+ ]]);
265+
266+ $ dataCollector = new SecurityDataCollector (null , null , null , $ accessDecisionManager , null , null , true );
267+
268+ $ dataCollector ->collect (new Request (), new Response ());
269+
270+ $ actualDecisionLog = $ dataCollector ->getAccessDecisionLog ();
271+
272+ $ expectedDecisionLog = [[
273+ 'attributes ' => ['view ' ],
274+ 'object ' => new \stdClass (),
275+ 'result ' => true ,
276+ 'voter_details ' => [
277+ ['class ' => \get_class ($ voter1 ), 'attributes ' => ['view ' ], 'vote ' => VoterInterface::ACCESS_ABSTAIN ],
278+ ['class ' => \get_class ($ voter2 ), 'attributes ' => ['view ' ], 'vote ' => VoterInterface::ACCESS_ABSTAIN ],
279+ ],
280+ ]];
281+
282+ $ this ->assertEquals ($ actualDecisionLog , $ expectedDecisionLog , 'Wrong value returned by getAccessDecisionLog ' );
283+
284+ $ actualVoterClasses = array_map (static function (ClassStub $ classStub ): string {
285+ return (string ) $ classStub ;
286+ }, $ dataCollector ->getVoters ());
287+
288+ $ expectedVoterClasses = [
289+ \get_class ($ voter1 ),
290+ \get_class ($ voter2 ),
261291 ];
262292
263- yield [
264- MainConfiguration::STRATEGY_UNANIMOUS ,
265- [
293+ $ this ->assertSame (
294+ $ actualVoterClasses ,
295+ $ expectedVoterClasses ,
296+ 'Wrong value returned by getVoters '
297+ );
298+
299+ $ this ->assertSame ($ dataCollector ->getVoterStrategy (), $ strategy , 'Wrong value returned by getVoterStrategy ' );
300+ }
301+
302+ public function testCollectCollectsDecisionLogWhenStrategyIsUnanimous ()
303+ {
304+ $ voter1 = new DummyVoter ();
305+ $ voter2 = new DummyVoter ();
306+
307+ $ decoratedVoter1 = new TraceableVoter ($ voter1 , new class () implements EventDispatcherInterface {
308+ public function dispatch (object $ event , string $ eventName = null ): object
309+ {
310+ return new \stdClass ();
311+ }
312+ });
313+
314+ $ strategy = MainConfiguration::STRATEGY_UNANIMOUS ;
315+
316+ $ accessDecisionManager = $ this ->createMock (TraceableAccessDecisionManager::class);
317+
318+ $ accessDecisionManager
319+ ->method ('getStrategy ' )
320+ ->willReturn ($ strategy );
321+
322+ $ accessDecisionManager
323+ ->method ('getVoters ' )
324+ ->willReturn ([
325+ $ decoratedVoter1 ,
326+ $ decoratedVoter1 ,
327+ ]);
328+
329+ $ accessDecisionManager
330+ ->method ('getDecisionLog ' )
331+ ->willReturn ([
266332 [
267333 'attributes ' => ['view ' , 'edit ' ],
268334 'object ' => new \stdClass (),
@@ -283,78 +349,54 @@ public function dispatch(object $event, string $eventName = null): object
283349 ['voter ' => $ voter2 , 'attributes ' => ['update ' ], 'vote ' => VoterInterface::ACCESS_GRANTED ],
284350 ],
285351 ],
286- ],
287- [$ decoratedVoter1 , $ decoratedVoter1 ],
288- [\get_class ($ voter1 ), \get_class ($ voter2 )],
352+ ]);
353+
354+ $ dataCollector = new SecurityDataCollector (null , null , null , $ accessDecisionManager , null , null , true );
355+
356+ $ dataCollector ->collect (new Request (), new Response ());
357+
358+ $ actualDecisionLog = $ dataCollector ->getAccessDecisionLog ();
359+
360+ $ expectedDecisionLog = [
289361 [
290- [
291- 'attributes ' => ['view ' , 'edit ' ],
292- 'object ' => new \stdClass (),
293- 'result ' => false ,
294- 'voter_details ' => [
295- ['class ' => \get_class ($ voter1 ), 'attributes ' => ['view ' ], 'vote ' => VoterInterface::ACCESS_DENIED ],
296- ['class ' => \get_class ($ voter1 ), 'attributes ' => ['edit ' ], 'vote ' => VoterInterface::ACCESS_DENIED ],
297- ['class ' => \get_class ($ voter2 ), 'attributes ' => ['view ' ], 'vote ' => VoterInterface::ACCESS_GRANTED ],
298- ['class ' => \get_class ($ voter2 ), 'attributes ' => ['edit ' ], 'vote ' => VoterInterface::ACCESS_GRANTED ],
299- ],
362+ 'attributes ' => ['view ' , 'edit ' ],
363+ 'object ' => new \stdClass (),
364+ 'result ' => false ,
365+ 'voter_details ' => [
366+ ['class ' => \get_class ($ voter1 ), 'attributes ' => ['view ' ], 'vote ' => VoterInterface::ACCESS_DENIED ],
367+ ['class ' => \get_class ($ voter1 ), 'attributes ' => ['edit ' ], 'vote ' => VoterInterface::ACCESS_DENIED ],
368+ ['class ' => \get_class ($ voter2 ), 'attributes ' => ['view ' ], 'vote ' => VoterInterface::ACCESS_GRANTED ],
369+ ['class ' => \get_class ($ voter2 ), 'attributes ' => ['edit ' ], 'vote ' => VoterInterface::ACCESS_GRANTED ],
300370 ],
301- [
302- ' attributes ' => [ ' update ' ],
303- ' object ' => new \ stdClass () ,
304- ' result ' => true ,
305- ' voter_details ' => [
306- [ ' class ' => \get_class ( $ voter1 ), ' attributes ' => [ ' update ' ], ' vote ' => VoterInterface:: ACCESS_GRANTED ],
307- ['class ' => \get_class ($ voter2 ), 'attributes ' => ['update ' ], 'vote ' => VoterInterface::ACCESS_GRANTED ],
308- ],
371+ ],
372+ [
373+ ' attributes ' => [ ' update ' ] ,
374+ ' object ' => new \ stdClass () ,
375+ ' result ' => true ,
376+ ' voter_details ' => [
377+ ['class ' => \get_class ($ voter1 ), 'attributes ' => ['update ' ], 'vote ' => VoterInterface::ACCESS_GRANTED ],
378+ [ ' class ' => \get_class ( $ voter2 ), ' attributes ' => [ ' update ' ], ' vote ' => VoterInterface:: ACCESS_GRANTED ],
309379 ],
310380 ],
311381 ];
312- }
313382
314- /**
315- * Test the returned data when AccessDecisionManager is a TraceableAccessDecisionManager.
316- *
317- * @param string $strategy strategy returned by the AccessDecisionManager
318- * @param array $voters voters returned by AccessDecisionManager
319- * @param array $decisionLog log of the votes and final decisions from AccessDecisionManager
320- * @param array $expectedVoterClasses expected voter classes returned by the collector
321- * @param array $expectedDecisionLog expected decision log returned by the collector
322- *
323- * @dataProvider providerCollectDecisionLog
324- */
325- public function testCollectDecisionLog (string $ strategy , array $ decisionLog , array $ voters , array $ expectedVoterClasses , array $ expectedDecisionLog )
326- {
327- $ accessDecisionManager = $ this
328- ->getMockBuilder (TraceableAccessDecisionManager::class)
329- ->disableOriginalConstructor ()
330- ->setMethods (['getStrategy ' , 'getVoters ' , 'getDecisionLog ' ])
331- ->getMock ();
383+ $ this ->assertEquals ($ actualDecisionLog , $ expectedDecisionLog , 'Wrong value returned by getAccessDecisionLog ' );
332384
333- $ accessDecisionManager
334- ->expects ($ this ->any ())
335- ->method ('getStrategy ' )
336- ->willReturn ($ strategy );
385+ $ actualVoterClasses = array_map (static function (ClassStub $ classStub ): string {
386+ return (string ) $ classStub ;
387+ }, $ dataCollector ->getVoters ());
337388
338- $ accessDecisionManager
339- ->expects ($ this ->any ())
340- ->method ('getVoters ' )
341- ->willReturn ($ voters );
342-
343- $ accessDecisionManager
344- ->expects ($ this ->any ())
345- ->method ('getDecisionLog ' )
346- ->willReturn ($ decisionLog );
347-
348- $ dataCollector = new SecurityDataCollector (null , null , null , $ accessDecisionManager , null , null , true );
349- $ dataCollector ->collect (new Request (), new Response ());
350-
351- $ this ->assertEquals ($ dataCollector ->getAccessDecisionLog (), $ expectedDecisionLog , 'Wrong value returned by getAccessDecisionLog ' );
389+ $ expectedVoterClasses = [
390+ \get_class ($ voter1 ),
391+ \get_class ($ voter2 ),
392+ ];
352393
353394 $ this ->assertSame (
354- array_map ( function ( $ classStub ) { return ( string ) $ classStub ; }, $ dataCollector -> getVoters ()) ,
395+ $ actualVoterClasses ,
355396 $ expectedVoterClasses ,
356397 'Wrong value returned by getVoters '
357398 );
399+
358400 $ this ->assertSame ($ dataCollector ->getVoterStrategy (), $ strategy , 'Wrong value returned by getVoterStrategy ' );
359401 }
360402
@@ -390,7 +432,7 @@ private function getRoleHierarchy()
390432 }
391433}
392434
393- class DummyVoter implements VoterInterface
435+ final class DummyVoter implements VoterInterface
394436{
395437 public function vote (TokenInterface $ token , $ subject , array $ attributes )
396438 {
0 commit comments