d5992301df853f88c52a9fc249edeebd7003b426
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Package / DependencyResolverTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Package;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Package\DependencyResolver;
18
19 /**
20 * Testcase for the dependency resolver class
21 *
22 * @author Markus Klein <klein.t3@mfc-linz.at>
23 */
24 class DependencyResolverTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
25
26 /**
27 * @test
28 * @param array $unsortedPackageStatesConfiguration
29 * @param array $frameworkPackageKeys
30 * @param array $expectedGraph
31 * @dataProvider buildDependencyGraphBuildsCorrectGraphDataProvider
32 */
33 public function buildDependencyGraphBuildsCorrectGraph(array $unsortedPackageStatesConfiguration, array $frameworkPackageKeys, array $expectedGraph) {
34 $packageKeys = array_keys($unsortedPackageStatesConfiguration);
35
36 $basePathAssignment = array(
37 array($unsortedPackageStatesConfiguration, '', array(DependencyResolver::SYSEXT_FOLDER), array_diff($packageKeys, $frameworkPackageKeys)),
38 array($unsortedPackageStatesConfiguration, DependencyResolver::SYSEXT_FOLDER, array(), $frameworkPackageKeys),
39 );
40
41 $dependencyResolver = $this->getAccessibleMock(DependencyResolver::class, array('getPackageKeysInBasePath'));
42 $dependencyResolver->expects($this->any())->method('getPackageKeysInBasePath')->will($this->returnValueMap($basePathAssignment));
43 $dependencyGraph = $dependencyResolver->_call('buildDependencyGraph', $unsortedPackageStatesConfiguration);
44
45 $this->assertEquals($expectedGraph, $dependencyGraph);
46 }
47
48 /**
49 * @test
50 * @dataProvider packageSortingDataProvider
51 */
52 public function sortPackageStatesConfigurationByDependencyMakesSureThatDependantPackagesAreStandingBeforeAPackageInTheInternalPackagesAndPackagesConfigurationArrays($unsortedPackageStatesConfiguration, $frameworkPackageKeys, $expectedSortedPackageStatesConfiguration) {
53 $packageKeys = array_keys($unsortedPackageStatesConfiguration);
54
55 $basePathAssignment = array(
56 array($unsortedPackageStatesConfiguration, '', array(DependencyResolver::SYSEXT_FOLDER), array_diff($packageKeys, $frameworkPackageKeys)),
57 array($unsortedPackageStatesConfiguration, DependencyResolver::SYSEXT_FOLDER, array(), $frameworkPackageKeys),
58 );
59
60 $dependencyResolver = $this->getAccessibleMock(DependencyResolver::class, array('getPackageKeysInBasePath'));
61 $dependencyResolver->expects($this->any())->method('getPackageKeysInBasePath')->will($this->returnValueMap($basePathAssignment));
62 $sortedPackageStatesConfiguration = $dependencyResolver->_call('sortPackageStatesConfigurationByDependency', $unsortedPackageStatesConfiguration);
63
64 $this->assertEquals($expectedSortedPackageStatesConfiguration, $sortedPackageStatesConfiguration, 'The package states configurations have not been ordered according to their dependencies!');
65 }
66
67 /**
68 * @test
69 * @dataProvider buildDependencyGraphForPackagesBuildsCorrectGraphDataProvider
70 */
71 public function buildDependencyGraphForPackagesBuildsCorrectGraph($packages, $expectedGraph) {
72 $dependencyResolver = $this->getAccessibleMock(DependencyResolver::class, array('dummy'));
73 $dependencyGraph = $dependencyResolver->_call('buildDependencyGraphForPackages', $packages, array_keys($packages));
74
75 $this->assertEquals($expectedGraph, $dependencyGraph);
76 }
77
78 /**
79 * @test
80 * @expectedException \UnexpectedValueException
81 */
82 public function sortPackageStatesConfigurationByDependencyThrowsExceptionWhenCycleDetected() {
83 $unsortedPackageStatesConfiguration = array(
84 'A' => array(
85 'state' => 'active',
86 'dependencies' => array('B'),
87 ),
88 'B' => array(
89 'state' => 'active',
90 'dependencies' => array('A')
91 ),
92 );
93
94 $packageKeys = array_keys($unsortedPackageStatesConfiguration);
95
96 $basePathAssignment = array(
97 array($unsortedPackageStatesConfiguration, '', array(DependencyResolver::SYSEXT_FOLDER), $packageKeys),
98 array($unsortedPackageStatesConfiguration, DependencyResolver::SYSEXT_FOLDER, array(), array()),
99 );
100
101 $dependencyResolver = $this->getAccessibleMock(DependencyResolver::class, array('getActivePackageKeysOfType'));
102 $dependencyResolver->expects($this->any())->method('getActivePackageKeysOfType')->will($this->returnValueMap($basePathAssignment));
103 $dependencyResolver->_call('sortPackageStatesConfigurationByDependency', $unsortedPackageStatesConfiguration);
104 }
105
106 /**
107 * @test
108 * @expectedException \UnexpectedValueException
109 */
110 public function buildDependencyGraphForPackagesThrowsExceptionWhenDependencyOnUnavailablePackageDetected() {
111 $packages = array(
112 'A' => array(
113 'dependencies' => array('B'),
114 )
115 );
116 $dependencyResolver = $this->getAccessibleMock(DependencyResolver::class, array('dummy'));
117 $dependencyResolver->_call('buildDependencyGraphForPackages', $packages, array_keys($packages));
118 }
119
120 /**
121 * @return array
122 */
123 public function buildDependencyGraphBuildsCorrectGraphDataProvider() {
124 return array(
125 'TYPO3 Flow Packages' => array(
126 array(
127 'TYPO3.Flow' => array(
128 'state' => 'active',
129 'dependencies' => array('Symfony.Component.Yaml', 'Doctrine.Common', 'Doctrine.DBAL', 'Doctrine.ORM')
130 ),
131 'Doctrine.ORM' => array(
132 'state' => 'active',
133 'dependencies' => array('Doctrine.Common', 'Doctrine.DBAL')
134 ),
135 'Doctrine.Common' => array(
136 'state' => 'active',
137 'dependencies' => array()
138 ),
139 'Doctrine.DBAL' => array(
140 'state' => 'active',
141 'dependencies' => array('Doctrine.Common')
142 ),
143 'Symfony.Component.Yaml' => array(
144 'state' => 'active',
145 'dependencies' => array()
146 ),
147 ),
148 array(
149 'Doctrine.Common'
150 ),
151 array(
152 'TYPO3.Flow' => array(
153 'TYPO3.Flow' => FALSE,
154 'Doctrine.ORM' => TRUE,
155 'Doctrine.Common' => TRUE,
156 'Doctrine.DBAL' => TRUE,
157 'Symfony.Component.Yaml' => TRUE,
158 ),
159 'Doctrine.ORM' => array(
160 'TYPO3.Flow' => FALSE,
161 'Doctrine.ORM' => FALSE,
162 'Doctrine.Common' => TRUE,
163 'Doctrine.DBAL' => TRUE,
164 'Symfony.Component.Yaml' => FALSE,
165 ),
166 'Doctrine.Common' => array(
167 'TYPO3.Flow' => FALSE,
168 'Doctrine.ORM' => FALSE,
169 'Doctrine.Common' => FALSE,
170 'Doctrine.DBAL' => FALSE,
171 'Symfony.Component.Yaml' => FALSE,
172 ),
173 'Doctrine.DBAL' => array(
174 'TYPO3.Flow' => FALSE,
175 'Doctrine.ORM' => FALSE,
176 'Doctrine.Common' => TRUE,
177 'Doctrine.DBAL' => FALSE,
178 'Symfony.Component.Yaml' => FALSE,
179 ),
180 'Symfony.Component.Yaml' => array(
181 'TYPO3.Flow' => FALSE,
182 'Doctrine.ORM' => FALSE,
183 'Doctrine.Common' => TRUE,
184 'Doctrine.DBAL' => FALSE,
185 'Symfony.Component.Yaml' => FALSE,
186 ),
187 ),
188 ),
189 'TYPO3 CMS Extensions' => array(
190 array(
191 'core' => array(
192 'state' => 'active',
193 'dependencies' => array(),
194 ),
195 'setup' => array (
196 'state' => 'active',
197 'dependencies' => array('core'),
198 ),
199 'openid' => array(
200 'state' => 'active',
201 'dependencies' => array('core', 'setup')
202 ),
203 'news' => array (
204 'state' => 'active',
205 'dependencies' => array('extbase'),
206 ),
207 'extbase' => array (
208 'state' => 'active',
209 'dependencies' => array('core'),
210 ),
211 'pt_extbase' => array (
212 'state' => 'active',
213 'dependencies' => array('extbase'),
214 ),
215 'foo' => array (
216 'state' => 'active',
217 'dependencies' => array(),
218 ),
219 ),
220 array(
221 'core', 'setup', 'openid', 'extbase'
222 ),
223 array(
224 'core' => array(
225 'core' => FALSE,
226 'setup' => FALSE,
227 'openid' => FALSE,
228 'news' => FALSE,
229 'extbase' => FALSE,
230 'pt_extbase' => FALSE,
231 'foo' => FALSE
232 ),
233 'setup' => array(
234 'core' => TRUE,
235 'setup' => FALSE,
236 'openid' => FALSE,
237 'news' => FALSE,
238 'extbase' => FALSE,
239 'pt_extbase' => FALSE,
240 'foo' => FALSE
241 ),
242 'openid' => array (
243 'core' => TRUE,
244 'setup' => TRUE,
245 'openid' => FALSE,
246 'news' => FALSE,
247 'extbase' => FALSE,
248 'pt_extbase' => FALSE,
249 'foo' => FALSE
250 ),
251 'news' => array (
252 'core' => FALSE,
253 'setup' => FALSE,
254 'openid' => TRUE,
255 'news' => FALSE,
256 'extbase' => TRUE,
257 'pt_extbase' => FALSE,
258 'foo' => FALSE
259 ),
260 'extbase' => array (
261 'core' => TRUE,
262 'setup' => FALSE,
263 'openid' => FALSE,
264 'news' => FALSE,
265 'extbase' => FALSE,
266 'pt_extbase' => FALSE,
267 'foo' => FALSE
268 ),
269 'pt_extbase' => array(
270 'core' => FALSE,
271 'setup' => FALSE,
272 'openid' => TRUE,
273 'news' => FALSE,
274 'extbase' => TRUE,
275 'pt_extbase' => FALSE,
276 'foo' => FALSE
277 ),
278 'foo' => array(
279 'core' => FALSE,
280 'setup' => FALSE,
281 'openid' => TRUE,
282 'news' => FALSE,
283 'extbase' => TRUE,
284 'pt_extbase' => FALSE,
285 'foo' => FALSE
286 ),
287 ),
288 ),
289 'Dummy Packages' => array(
290 array(
291 'A' => array(
292 'state' => 'active',
293 'dependencies' => array('B', 'D', 'C'),
294 ),
295 'B' => array(
296 'state' => 'active',
297 'dependencies' => array()
298 ),
299 'C' => array(
300 'state' => 'active',
301 'dependencies' => array('E')
302 ),
303 'D' => array (
304 'state' => 'active',
305 'dependencies' => array('E'),
306 ),
307 'E' => array (
308 'state' => 'active',
309 'dependencies' => array(),
310 ),
311 'F' => array (
312 'state' => 'active',
313 'dependencies' => array(),
314 ),
315 ),
316 array(
317 'B', 'C', 'E'
318 ),
319 array(
320 'A' => array(
321 'A' => FALSE,
322 'B' => TRUE,
323 'C' => TRUE,
324 'D' => TRUE,
325 'E' => FALSE,
326 'F' => FALSE,
327 ),
328 'B' => array(
329 'A' => FALSE,
330 'B' => FALSE,
331 'C' => FALSE,
332 'D' => FALSE,
333 'E' => FALSE,
334 'F' => FALSE,
335 ),
336 'C' => array(
337 'A' => FALSE,
338 'B' => FALSE,
339 'C' => FALSE,
340 'D' => FALSE,
341 'E' => TRUE,
342 'F' => FALSE,
343 ),
344 'D' => array (
345 'A' => FALSE,
346 'B' => TRUE,
347 'C' => TRUE,
348 'D' => FALSE,
349 'E' => FALSE,
350 'F' => FALSE,
351 ),
352 'E' => array (
353 'A' => FALSE,
354 'B' => FALSE,
355 'C' => FALSE,
356 'D' => FALSE,
357 'E' => FALSE,
358 'F' => FALSE,
359 ),
360 'F' => array (
361 'A' => FALSE,
362 'B' => TRUE,
363 'C' => TRUE,
364 'D' => FALSE,
365 'E' => FALSE,
366 'F' => FALSE,
367 ),
368 ),
369 ),
370 );
371 }
372
373 /**
374 * @return array
375 */
376 public function packageSortingDataProvider() {
377 return array(
378 'TYPO3 Flow Packages' => array(
379 array(
380 'TYPO3.Flow' => array(
381 'state' => 'active',
382 'dependencies' => array('Symfony.Component.Yaml', 'Doctrine.Common', 'Doctrine.DBAL', 'Doctrine.ORM')
383 ),
384 'Doctrine.ORM' => array(
385 'state' => 'active',
386 'dependencies' => array('Doctrine.Common', 'Doctrine.DBAL')
387 ),
388 'Doctrine.Common' => array(
389 'state' => 'active',
390 'dependencies' => array()
391 ),
392 'Doctrine.DBAL' => array(
393 'state' => 'active',
394 'dependencies' => array('Doctrine.Common')
395 ),
396 'Symfony.Component.Yaml' => array(
397 'state' => 'active',
398 'dependencies' => array()
399 ),
400 ),
401 array(
402 'Doctrine.Common'
403 ),
404 array(
405 'Doctrine.Common' => array(
406 'state' => 'active',
407 'dependencies' => array()
408 ),
409 'Doctrine.DBAL' => array(
410 'state' => 'active',
411 'dependencies' => array('Doctrine.Common')
412 ),
413 'Doctrine.ORM' => array(
414 'state' => 'active',
415 'dependencies' => array('Doctrine.Common', 'Doctrine.DBAL')
416 ),
417 'Symfony.Component.Yaml' => array(
418 'state' => 'active',
419 'dependencies' => array()
420 ),
421 'TYPO3.Flow' => array(
422 'state' => 'active',
423 'dependencies' => array('Symfony.Component.Yaml', 'Doctrine.Common', 'Doctrine.DBAL', 'Doctrine.ORM')
424 ),
425 ),
426 ),
427 'TYPO3 CMS Extensions' => array(
428 array(
429 'core' => array(
430 'state' => 'active',
431 'dependencies' => array(),
432 ),
433 'setup' => array (
434 'state' => 'active',
435 'dependencies' => array('core'),
436 ),
437 'openid' => array(
438 'state' => 'active',
439 'dependencies' => array('core', 'setup')
440 ),
441 'news' => array (
442 'state' => 'active',
443 'dependencies' => array('extbase'),
444 ),
445 'extbase' => array (
446 'state' => 'active',
447 'dependencies' => array('core'),
448 ),
449 'pt_extbase' => array (
450 'state' => 'active',
451 'dependencies' => array('extbase'),
452 ),
453 'foo' => array (
454 'state' => 'active',
455 'dependencies' => array(),
456 ),
457 ),
458 array(
459 'core', 'setup', 'openid', 'extbase'
460 ),
461 array(
462 'core' => array(
463 'state' => 'active',
464 'dependencies' => array(),
465 ),
466 'setup' => array (
467 'state' => 'active',
468 'dependencies' => array('core'),
469 ),
470 'openid' => array(
471 'state' => 'active',
472 'dependencies' => array('core', 'setup')
473 ),
474 'extbase' => array (
475 'state' => 'active',
476 'dependencies' => array('core'),
477 ),
478 'foo' => array (
479 'state' => 'active',
480 'dependencies' => array(),
481 ),
482 'pt_extbase' => array (
483 'state' => 'active',
484 'dependencies' => array('extbase'),
485 ),
486 'news' => array (
487 'state' => 'active',
488 'dependencies' => array('extbase'),
489 ),
490 ),
491 ),
492 'Dummy Packages' => array(
493 array(
494 'A' => array(
495 'state' => 'active',
496 'dependencies' => array('B', 'D', 'C'),
497 ),
498 'B' => array(
499 'state' => 'active',
500 'dependencies' => array()
501 ),
502 'C' => array(
503 'state' => 'active',
504 'dependencies' => array('E')
505 ),
506 'D' => array (
507 'state' => 'active',
508 'dependencies' => array('E'),
509 ),
510 'E' => array (
511 'state' => 'active',
512 'dependencies' => array(),
513 ),
514 'F' => array (
515 'state' => 'active',
516 'dependencies' => array(),
517 ),
518 ),
519 array(
520 'B', 'C', 'E'
521 ),
522 array(
523 'B' => array(
524 'state' => 'active',
525 'dependencies' => array(),
526 ),
527 'E' => array (
528 'state' => 'active',
529 'dependencies' => array(),
530 ),
531 'C' => array (
532 'state' => 'active',
533 'dependencies' => array('E'),
534 ),
535 'F' => array (
536 'state' => 'active',
537 'dependencies' => array(),
538 ),
539 'D' => array(
540 'state' => 'active',
541 'dependencies' => array('E'),
542 ),
543 'A' => array(
544 'state' => 'active',
545 'dependencies' => array('B', 'D', 'C'),
546 ),
547 ),
548 ),
549 );
550 }
551
552 /**
553 * @return array
554 */
555 public function buildDependencyGraphForPackagesBuildsCorrectGraphDataProvider() {
556 return array(
557 'TYPO3 Flow Packages' => array(
558 array(
559 'TYPO3.Flow' => array(
560 'state' => 'active',
561 'dependencies' => array('Symfony.Component.Yaml', 'Doctrine.Common', 'Doctrine.DBAL', 'Doctrine.ORM')
562 ),
563 'Doctrine.ORM' => array(
564 'state' => 'active',
565 'dependencies' => array('Doctrine.Common', 'Doctrine.DBAL')
566 ),
567 'Doctrine.Common' => array(
568 'state' => 'active',
569 'dependencies' => array()
570 ),
571 'Doctrine.DBAL' => array(
572 'state' => 'active',
573 'dependencies' => array('Doctrine.Common')
574 ),
575 'Symfony.Component.Yaml' => array(
576 'state' => 'active',
577 'dependencies' => array()
578 ),
579 ),
580 array(
581 'TYPO3.Flow' => array(
582 'TYPO3.Flow' => FALSE,
583 'Doctrine.ORM' => TRUE,
584 'Doctrine.Common' => TRUE,
585 'Doctrine.DBAL' => TRUE,
586 'Symfony.Component.Yaml' => TRUE,
587 ),
588 'Doctrine.ORM' => array(
589 'TYPO3.Flow' => FALSE,
590 'Doctrine.ORM' => FALSE,
591 'Doctrine.Common' => TRUE,
592 'Doctrine.DBAL' => TRUE,
593 'Symfony.Component.Yaml' => FALSE,
594 ),
595 'Doctrine.Common' => array(
596 'TYPO3.Flow' => FALSE,
597 'Doctrine.ORM' => FALSE,
598 'Doctrine.Common' => FALSE,
599 'Doctrine.DBAL' => FALSE,
600 'Symfony.Component.Yaml' => FALSE,
601 ),
602 'Doctrine.DBAL' => array(
603 'TYPO3.Flow' => FALSE,
604 'Doctrine.ORM' => FALSE,
605 'Doctrine.Common' => TRUE,
606 'Doctrine.DBAL' => FALSE,
607 'Symfony.Component.Yaml' => FALSE,
608 ),
609 'Symfony.Component.Yaml' => array(
610 'TYPO3.Flow' => FALSE,
611 'Doctrine.ORM' => FALSE,
612 'Doctrine.Common' => FALSE,
613 'Doctrine.DBAL' => FALSE,
614 'Symfony.Component.Yaml' => FALSE,
615 ),
616 ),
617 ),
618 'TYPO3 CMS Extensions' => array(
619 array(
620 'core' => array(
621 'state' => 'active',
622 'dependencies' => array(),
623 ),
624 'openid' => array(
625 'state' => 'active',
626 'dependencies' => array('core', 'setup')
627 ),
628 'scheduler' => array (
629 'state' => 'active',
630 'dependencies' => array('core'),
631 ),
632 'setup' => array (
633 'state' => 'active',
634 'dependencies' => array('core'),
635 ),
636 'sv' => array (
637 'state' => 'active',
638 'dependencies' => array('core'),
639 ),
640 ),
641 array(
642 'core' => array(
643 'core' => FALSE,
644 'setup' => FALSE,
645 'sv' => FALSE,
646 'scheduler' => FALSE,
647 'openid' => FALSE,
648 ),
649 'openid' => array(
650 'core' => TRUE,
651 'setup' => TRUE,
652 'sv' => FALSE,
653 'scheduler' => FALSE,
654 'openid' => FALSE,
655 ),
656 'scheduler' => array (
657 'core' => TRUE,
658 'setup' => FALSE,
659 'sv' => FALSE,
660 'scheduler' => FALSE,
661 'openid' => FALSE,
662 ),
663 'setup' => array (
664 'core' => TRUE,
665 'setup' => FALSE,
666 'sv' => FALSE,
667 'scheduler' => FALSE,
668 'openid' => FALSE,
669 ),
670 'sv' => array (
671 'core' => TRUE,
672 'setup' => FALSE,
673 'sv' => FALSE,
674 'scheduler' => FALSE,
675 'openid' => FALSE,
676 ),
677 ),
678 ),
679 'Dummy Packages' => array(
680 array(
681 'A' => array(
682 'state' => 'active',
683 'dependencies' => array('B', 'D', 'C'),
684 ),
685 'B' => array(
686 'state' => 'active',
687 'dependencies' => array()
688 ),
689 'C' => array(
690 'state' => 'active',
691 'dependencies' => array('E')
692 ),
693 'D' => array (
694 'state' => 'active',
695 'dependencies' => array('E'),
696 ),
697 'E' => array (
698 'state' => 'active',
699 'dependencies' => array(),
700 ),
701 'F' => array (
702 'state' => 'active',
703 'dependencies' => array(),
704 ),
705 ),
706 array(
707 'A' => array(
708 'A' => FALSE,
709 'B' => TRUE,
710 'C' => TRUE,
711 'D' => TRUE,
712 'E' => FALSE,
713 'F' => FALSE,
714 ),
715 'B' => array(
716 'A' => FALSE,
717 'B' => FALSE,
718 'C' => FALSE,
719 'D' => FALSE,
720 'E' => FALSE,
721 'F' => FALSE,
722 ),
723 'C' => array(
724 'A' => FALSE,
725 'B' => FALSE,
726 'C' => FALSE,
727 'D' => FALSE,
728 'E' => TRUE,
729 'F' => FALSE,
730 ),
731 'D' => array (
732 'A' => FALSE,
733 'B' => FALSE,
734 'C' => FALSE,
735 'D' => FALSE,
736 'E' => TRUE,
737 'F' => FALSE,
738 ),
739 'E' => array (
740 'A' => FALSE,
741 'B' => FALSE,
742 'C' => FALSE,
743 'D' => FALSE,
744 'E' => FALSE,
745 'F' => FALSE,
746 ),
747 'F' => array (
748 'A' => FALSE,
749 'B' => FALSE,
750 'C' => FALSE,
751 'D' => FALSE,
752 'E' => FALSE,
753 'F' => FALSE,
754 ),
755 ),
756 ),
757 'Suggestions without reverse dependency' => array(
758 array(
759 'A' => array(
760 'state' => 'active',
761 'suggestions' => array('B'),
762 ),
763 'B' => array(
764 'state' => 'active',
765 ),
766 'C' => array(
767 'state' => 'active',
768 'dependencies' => array('A')
769 ),
770 ),
771 array(
772 'A' => array(
773 'A' => FALSE,
774 'B' => TRUE,
775 'C' => FALSE,
776 ),
777 'B' => array(
778 'A' => FALSE,
779 'B' => FALSE,
780 'C' => FALSE,
781 ),
782 'C' => array(
783 'A' => TRUE,
784 'B' => FALSE,
785 'C' => FALSE,
786 ),
787 ),
788 ),
789 'Suggestions with reverse dependency' => array(
790 array(
791 'A' => array(
792 'state' => 'active',
793 'suggestions' => array('B'),
794 ),
795 'B' => array(
796 'state' => 'active',
797 'dependencies' => array('A')
798 ),
799 'C' => array(
800 'state' => 'active',
801 'dependencies' => array('A')
802 ),
803 ),
804 array(
805 'A' => array(
806 'A' => FALSE,
807 'B' => FALSE,
808 'C' => FALSE,
809 ),
810 'B' => array(
811 'A' => TRUE,
812 'B' => FALSE,
813 'C' => FALSE,
814 ),
815 'C' => array(
816 'A' => TRUE,
817 'B' => FALSE,
818 'C' => FALSE,
819 ),
820 ),
821 ),
822 );
823 }
824
825 /**
826 * @return array
827 */
828 public function findPathInGraphReturnsCorrectPathDataProvider() {
829 return array(
830 'Simple path' => array(
831 array(
832 'A' => array('A' => FALSE, 'B' => FALSE, 'C' => FALSE, 'Z' => TRUE),
833 'B' => array('A' => FALSE, 'B' => FALSE, 'C' => FALSE, 'Z' => FALSE),
834 'C' => array('A' => FALSE, 'B' => FALSE, 'C' => FALSE, 'Z' => FALSE),
835 'Z' => array('A' => FALSE, 'B' => FALSE, 'C' => FALSE, 'Z' => FALSE)
836 ),
837 'A', 'Z',
838 array('A', 'Z')
839 ),
840 'No path' => array(
841 array(
842 'A' => array('A' => FALSE, 'B' => TRUE, 'C' => FALSE, 'Z' => FALSE),
843 'B' => array('A' => FALSE, 'B' => FALSE, 'C' => FALSE, 'Z' => FALSE),
844 'C' => array('A' => FALSE, 'B' => TRUE, 'C' => FALSE, 'Z' => FALSE),
845 'Z' => array('A' => FALSE, 'B' => TRUE, 'C' => FALSE, 'Z' => FALSE)
846 ),
847 'A', 'C',
848 array()
849 ),
850 'Longer path' => array(
851 array(
852 'A' => array('A' => FALSE, 'B' => TRUE, 'C' => TRUE, 'Z' => TRUE),
853 'B' => array('A' => FALSE, 'B' => FALSE, 'C' => FALSE, 'Z' => FALSE),
854 'C' => array('A' => FALSE, 'B' => FALSE, 'C' => FALSE, 'Z' => TRUE),
855 'Z' => array('A' => FALSE, 'B' => FALSE, 'C' => FALSE, 'Z' => FALSE)
856 ),
857 'A', 'Z',
858 array('A', 'C', 'Z')
859 ),
860 );
861 }
862
863 /**
864 * @param array $graph
865 * @param string $from
866 * @param string $to
867 * @param array $expected
868 * @test
869 * @dataProvider findPathInGraphReturnsCorrectPathDataProvider
870 */
871 public function findPathInGraphReturnsCorrectPath(array $graph, $from, $to, array $expected) {
872 $dependencyResolver = $this->getAccessibleMock(DependencyResolver::class, array('dummy'));
873 $path = $dependencyResolver->_call('findPathInGraph', $graph, $from, $to);
874
875 $this->assertSame($expected, $path);
876 }
877
878 }