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