‪TYPO3CMS  10.4
DependencyOrderingServiceTest.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
19 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
20 
24 class ‪DependencyOrderingServiceTest extends UnitTestCase
25 {
34  public function ‪orderByDependenciesBuildsCorrectOrder(array $items, $beforeKey, $afterKey, array $expectedOrderedItems)
35  {
36  $orderedItems = (new ‪DependencyOrderingService())->orderByDependencies($items, $beforeKey, $afterKey);
37  self::assertSame($expectedOrderedItems, $orderedItems);
38  }
39 
44  {
45  return [
46  'unordered' => [
47  [ // $items
48  1 => [],
49  2 => [],
50  ],
51  'before',
52  'after',
53  [ // $expectedOrderedItems
54  1 => [],
55  2 => [],
56  ]
57  ],
58  'ordered' => [
59  [ // $items
60  1 => [],
61  2 => [
62  'precedes' => [ 1 ]
63  ],
64  ],
65  'precedes',
66  'after',
67  [ // $expectedOrderedItems
68  2 => [
69  'precedes' => [ 1 ]
70  ],
71  1 => [],
72  ]
73  ],
74  'mixed' => [
75  [ // $items
76  1 => [],
77  2 => [
78  'before' => [ 1 ]
79  ],
80  3 => [
81  'otherProperty' => true
82  ]
83  ],
84  'before',
85  'after',
86  [ // $expectedOrderedItems
87  2 => [
88  'before' => [ 1 ]
89  ],
90  1 => [],
91  3 => [
92  'otherProperty' => true
93  ],
94  ]
95  ],
96  'reference to non-existing' => [
97  [ // $items
98  2 => [
99  'before' => [ 1 ],
100  'depends' => [ 3 ]
101  ],
102  3 => [
103  'otherProperty' => true
104  ]
105  ],
106  'before',
107  'depends',
108  [ // $expectedOrderedItems
109  3 => [
110  'otherProperty' => true
111  ],
112  2 => [
113  'before' => [ 1 ],
114  'depends' => [ 3 ]
115  ],
116  ]
117  ],
118  'multiple dependencies' => [
119  [ // $items
120  1 => [
121  'depends' => [ 3, 2, 4 ],
122  ],
123  2 => [],
124  3 => [
125  'depends' => [ 2 ],
126  ],
127  ],
128  'before',
129  'depends',
130  [ // $expectedOrderedItems
131  2 => [],
132  3 => [
133  'depends' => [ 2 ],
134  ],
135  1 => [
136  'depends' => [ 3, 2, 4 ],
137  ],
138  ],
139  ],
140  'direct dependency is moved up' => [
141  [ // $items
142  1 => [],
143  2 => [],
144  3 => [
145  'depends' => [ 1 ],
146  ],
147  ],
148  'before',
149  'depends',
150  [ // $expectedOrderedItems
151  1 => [],
152  3 => [
153  'depends' => [ 1 ],
154  ],
155  2 => [],
156  ],
157  ],
158  ];
159  }
160 
168  public function ‪prepareDependenciesBuildsFullIdentifierList(array $dependencies, array $expectedDependencies)
169  {
171  $dependencyOrderingService = $this->getAccessibleMock(DependencyOrderingService::class, ['dummy']);
172  $preparedDependencies = $dependencyOrderingService->_call('prepareDependencies', $dependencies);
173  self::assertEquals($expectedDependencies, $preparedDependencies);
174  }
175 
180  {
181  return [
182  'simple' => [
183  [ // $dependencies
184  1 => [
185  'before' => [],
186  'after' => [ 2 ]
187  ],
188  ],
189  [ // $expectedDependencies
190  1 => [
191  'before' => [],
192  'after' => [ 2 ]
193  ],
194  2 => [
195  'before' => [],
196  'after' => [],
197  ]
198  ]
199  ],
200  'missing before' => [
201  [ // $dependencies
202  1 => [
203  'after' => [ 2 ]
204  ],
205  ],
206  [ // $expectedDependencies
207  1 => [
208  'before' => [],
209  'after' => [ 2 ]
210  ],
211  2 => [
212  'before' => [],
213  'after' => [],
214  ]
215  ]
216  ],
217  ];
218  }
219 
226  public function ‪buildDependencyGraphBuildsValidGraph(array $dependencies, array $expectedGraph)
227  {
228  $graph = (new ‪DependencyOrderingService())->buildDependencyGraph($dependencies);
229  self::assertEquals($expectedGraph, $graph);
230  }
231 
236  {
237  return [
238  'graph1' => [
239  [ // dependencies
240  1 => [
241  'before' => [],
242  'after' => [ 2 ]
243  ],
244  ],
245  [ // graph
246  1 => [
247  1 => false,
248  2 => true
249  ],
250  2 => [
251  1 => false,
252  2 => false
253  ],
254  ]
255  ],
256  'graph2' => [
257  [ // dependencies
258  1 => [
259  'before' => [ 3 ],
260  'after' => [ 2 ]
261  ],
262  ],
263  [ // graph
264  1 => [
265  1 => false,
266  2 => true,
267  3 => false,
268  ],
269  2 => [
270  1 => false,
271  2 => false,
272  3 => false,
273  ],
274  3 => [
275  1 => true,
276  2 => false,
277  3 => false,
278  ],
279  ]
280  ],
281  'graph3' => [
282  [ // dependencies
283  3 => [
284  'before' => [],
285  'after' => []
286  ],
287  1 => [
288  'before' => [ 3 ],
289  'after' => [ 2 ]
290  ],
291  2 => [
292  'before' => [ 3 ],
293  'after' => []
294  ]
295  ],
296  [ // graph
297  1 => [
298  1 => false,
299  2 => true,
300  3 => false,
301  ],
302  2 => [
303  1 => false,
304  2 => false,
305  3 => false,
306  ],
307  3 => [
308  1 => true,
309  2 => true,
310  3 => false,
311  ],
312  ]
313  ],
314  'cyclic graph' => [
315  [ // dependencies
316  1 => [
317  'before' => [ 2 ],
318  'after' => []
319  ],
320  2 => [
321  'before' => [ 1 ],
322  'after' => []
323  ]
324  ],
325  [ // graph
326  1 => [
327  1 => false,
328  2 => true,
329  ],
330  2 => [
331  1 => true,
332  2 => false,
333  ],
334  ]
335  ],
336  'TYPO3 Flow Packages' => [
337  [ // dependencies
338  'TYPO3.Flow' => [
339  'before' => [],
340  'after' => ['Symfony.Component.Yaml', 'Doctrine.Common', 'Doctrine.DBAL', 'Doctrine.ORM']
341  ],
342  'Doctrine.ORM' => [
343  'before' => [],
344  'after' => ['Doctrine.Common', 'Doctrine.DBAL']
345  ],
346  'Doctrine.Common' => [
347  'before' => [],
348  'after' => []
349  ],
350  'Doctrine.DBAL' => [
351  'before' => [],
352  'after' => ['Doctrine.Common']
353  ],
354  'Symfony.Component.Yaml' => [
355  'before' => [],
356  'after' => []
357  ],
358  ],
359  [ // graph
360  'TYPO3.Flow' => [
361  'TYPO3.Flow' => false,
362  'Doctrine.ORM' => true,
363  'Doctrine.Common' => true,
364  'Doctrine.DBAL' => true,
365  'Symfony.Component.Yaml' => true,
366  ],
367  'Doctrine.ORM' => [
368  'TYPO3.Flow' => false,
369  'Doctrine.ORM' => false,
370  'Doctrine.Common' => true,
371  'Doctrine.DBAL' => true,
372  'Symfony.Component.Yaml' => false,
373  ],
374  'Doctrine.Common' => [
375  'TYPO3.Flow' => false,
376  'Doctrine.ORM' => false,
377  'Doctrine.Common' => false,
378  'Doctrine.DBAL' => false,
379  'Symfony.Component.Yaml' => false,
380  ],
381  'Doctrine.DBAL' => [
382  'TYPO3.Flow' => false,
383  'Doctrine.ORM' => false,
384  'Doctrine.Common' => true,
385  'Doctrine.DBAL' => false,
386  'Symfony.Component.Yaml' => false,
387  ],
388  'Symfony.Component.Yaml' => [
389  'TYPO3.Flow' => false,
390  'Doctrine.ORM' => false,
391  'Doctrine.Common' => false,
392  'Doctrine.DBAL' => false,
393  'Symfony.Component.Yaml' => false,
394  ],
395  ],
396  ],
397  'TYPO3 CMS Extensions' => [
398  [ // dependencies
399  'core' => [
400  'before' => [],
401  'after' => [],
402  ],
403  'openid' => [
404  'before' => [],
405  'after' => ['core', 'setup']
406  ],
407  'scheduler' => [
408  'before' => [],
409  'after' => ['core'],
410  ],
411  'setup' => [
412  'before' => [],
413  'after' => ['core'],
414  ],
415  ],
416  [ // graph
417  'core' => [
418  'core' => false,
419  'setup' => false,
420  'scheduler' => false,
421  'openid' => false,
422  ],
423  'openid' => [
424  'core' => true,
425  'setup' => true,
426  'scheduler' => false,
427  'openid' => false,
428  ],
429  'scheduler' => [
430  'core' => true,
431  'setup' => false,
432  'scheduler' => false,
433  'openid' => false,
434  ],
435  'setup' => [
436  'core' => true,
437  'setup' => false,
438  'scheduler' => false,
439  'openid' => false,
440  ],
441  ],
442  ],
443  'Dummy Packages' => [
444  [ // dependencies
445  'A' => [
446  'before' => [],
447  'after' => ['B', 'D', 'C'],
448  ],
449  'B' => [
450  'before' => [],
451  'after' => []
452  ],
453  'C' => [
454  'before' => [],
455  'after' => ['E']
456  ],
457  'D' => [
458  'before' => [],
459  'after' => ['E'],
460  ],
461  'E' => [
462  'before' => [],
463  'after' => [],
464  ],
465  'F' => [
466  'before' => [],
467  'after' => [],
468  ],
469  ],
470  [ // graph
471  'A' => [
472  'A' => false,
473  'B' => true,
474  'C' => true,
475  'D' => true,
476  'E' => false,
477  'F' => false,
478  ],
479  'B' => [
480  'A' => false,
481  'B' => false,
482  'C' => false,
483  'D' => false,
484  'E' => false,
485  'F' => false,
486  ],
487  'C' => [
488  'A' => false,
489  'B' => false,
490  'C' => false,
491  'D' => false,
492  'E' => true,
493  'F' => false,
494  ],
495  'D' => [
496  'A' => false,
497  'B' => false,
498  'C' => false,
499  'D' => false,
500  'E' => true,
501  'F' => false,
502  ],
503  'E' => [
504  'A' => false,
505  'B' => false,
506  'C' => false,
507  'D' => false,
508  'E' => false,
509  'F' => false,
510  ],
511  'F' => [
512  'A' => false,
513  'B' => false,
514  'C' => false,
515  'D' => false,
516  'E' => false,
517  'F' => false,
518  ],
519  ],
520  ],
521  'Suggestions without reverse dependency' => [
522  [ // dependencies
523  'A' => [
524  'before' => [],
525  'after' => [],
526  'after-resilient' => ['B'] // package suggestion
527  ],
528  'B' => [
529  'before' => [],
530  'after' => [],
531  ],
532  'C' => [
533  'before' => [],
534  'after' => ['A']
535  ],
536  ],
537  [ // graph
538  'A' => [
539  'A' => false,
540  'B' => true,
541  'C' => false,
542  ],
543  'B' => [
544  'A' => false,
545  'B' => false,
546  'C' => false,
547  ],
548  'C' => [
549  'A' => true,
550  'B' => false,
551  'C' => false,
552  ],
553  ],
554  ],
555  'Suggestions with reverse dependency' => [
556  [ // dependencies
557  'A' => [
558  'before' => [],
559  'after' => [],
560  'after-resilient' => ['B'], // package suggestion
561  ],
562  'B' => [
563  'before' => [],
564  'after' => ['A']
565  ],
566  'C' => [
567  'before' => [],
568  'after' => ['A']
569  ],
570  ],
571  [ // graph
572  'A' => [
573  'A' => false,
574  'B' => false,
575  'C' => false,
576  ],
577  'B' => [
578  'A' => true,
579  'B' => false,
580  'C' => false,
581  ],
582  'C' => [
583  'A' => true,
584  'B' => false,
585  'C' => false,
586  ],
587  ],
588  ],
589  ];
590  }
591 
598  public function ‪calculateOrderResolvesCorrectOrder(array $graph, array $expectedList)
599  {
600  $list = (new ‪DependencyOrderingService())->calculateOrder($graph);
601  self::assertSame($expectedList, $list);
602  }
603 
608  {
609  return [
610  'list1' => [
611  [ // $graph
612  1 => [
613  1 => false,
614  2 => true
615  ],
616  2 => [
617  1 => false,
618  2 => false
619  ],
620  ],
621  [ // $expectedList
622  2, 1
623  ]
624  ],
625  'list2' => [
626  [ // $graph
627  1 => [
628  1 => false,
629  2 => true,
630  3 => false,
631  ],
632  2 => [
633  1 => false,
634  2 => false,
635  3 => false,
636  ],
637  3 => [
638  1 => true,
639  2 => true,
640  3 => false,
641  ],
642  ],
643  [ // $expectedList
644  2, 1, 3
645  ]
646  ],
647  ];
648  }
649 
654  {
655  $this->expectException(\UnexpectedValueException::class);
656  $this->expectExceptionCode(1381960494);
657 
658  (new ‪DependencyOrderingService())->calculateOrder([
659  1 => [
660  1 => false,
661  2 => true,
662  ],
663  2 => [
664  1 => true,
665  2 => false,
666  ],
667  ]);
668  }
669 
674  {
675  return [
676  'Simple path' => [
677  [
678  'A' => ['A' => false, 'B' => false, 'C' => false, 'Z' => true],
679  'B' => ['A' => false, 'B' => false, 'C' => false, 'Z' => false],
680  'C' => ['A' => false, 'B' => false, 'C' => false, 'Z' => false],
681  'Z' => ['A' => false, 'B' => false, 'C' => false, 'Z' => false]
682  ],
683  'A', 'Z',
684  ['A', 'Z']
685  ],
686  'No path' => [
687  [
688  'A' => ['A' => false, 'B' => true, 'C' => false, 'Z' => false],
689  'B' => ['A' => false, 'B' => false, 'C' => false, 'Z' => false],
690  'C' => ['A' => false, 'B' => true, 'C' => false, 'Z' => false],
691  'Z' => ['A' => false, 'B' => true, 'C' => false, 'Z' => false]
692  ],
693  'A', 'C',
694  []
695  ],
696  'Longer path' => [
697  [
698  'A' => ['A' => false, 'B' => true, 'C' => true, 'Z' => true],
699  'B' => ['A' => false, 'B' => false, 'C' => false, 'Z' => false],
700  'C' => ['A' => false, 'B' => false, 'C' => false, 'Z' => true],
701  'Z' => ['A' => false, 'B' => false, 'C' => false, 'Z' => false]
702  ],
703  'A', 'Z',
704  ['A', 'C', 'Z']
705  ],
706  ];
707  }
708 
717  public function ‪findPathInGraphReturnsCorrectPath(array $graph, $from, $to, array $expected)
718  {
720  $dependencyOrderingService = $this->getAccessibleMock(DependencyOrderingService::class, ['dummy']);
721  $path = $dependencyOrderingService->_call('findPathInGraph', $graph, $from, $to);
722 
723  self::assertSame($expected, $path);
724  }
725 }
‪TYPO3\CMS\Core\Tests\Unit\Service\DependencyOrderingServiceTest\prepareDependenciesBuildsFullIdentifierList
‪prepareDependenciesBuildsFullIdentifierList(array $dependencies, array $expectedDependencies)
Definition: DependencyOrderingServiceTest.php:168
‪TYPO3\CMS\Core\Tests\Unit\Service\DependencyOrderingServiceTest\findPathInGraphReturnsCorrectPathDataProvider
‪array findPathInGraphReturnsCorrectPathDataProvider()
Definition: DependencyOrderingServiceTest.php:673
‪TYPO3\CMS\Core\Tests\Unit\Service\DependencyOrderingServiceTest
Definition: DependencyOrderingServiceTest.php:25
‪TYPO3\CMS\Core\Tests\Unit\Service\DependencyOrderingServiceTest\buildDependencyGraphBuildsValidGraph
‪buildDependencyGraphBuildsValidGraph(array $dependencies, array $expectedGraph)
Definition: DependencyOrderingServiceTest.php:226
‪TYPO3\CMS\Core\Service\DependencyOrderingService
Definition: DependencyOrderingService.php:32
‪TYPO3\CMS\Core\Tests\Unit\Service\DependencyOrderingServiceTest\orderByDependenciesBuildsCorrectOrderDataProvider
‪array orderByDependenciesBuildsCorrectOrderDataProvider()
Definition: DependencyOrderingServiceTest.php:43
‪TYPO3\CMS\Core\Tests\Unit\Service\DependencyOrderingServiceTest\buildDependencyGraphBuildsValidGraphDataProvider
‪array buildDependencyGraphBuildsValidGraphDataProvider()
Definition: DependencyOrderingServiceTest.php:235
‪TYPO3\CMS\Core\Tests\Unit\Service\DependencyOrderingServiceTest\orderByDependenciesBuildsCorrectOrder
‪orderByDependenciesBuildsCorrectOrder(array $items, $beforeKey, $afterKey, array $expectedOrderedItems)
Definition: DependencyOrderingServiceTest.php:34
‪TYPO3\CMS\Core\Tests\Unit\Service\DependencyOrderingServiceTest\findPathInGraphReturnsCorrectPath
‪findPathInGraphReturnsCorrectPath(array $graph, $from, $to, array $expected)
Definition: DependencyOrderingServiceTest.php:717
‪TYPO3\CMS\Core\Tests\Unit\Service\DependencyOrderingServiceTest\calculateOrderResolvesCorrectOrder
‪calculateOrderResolvesCorrectOrder(array $graph, array $expectedList)
Definition: DependencyOrderingServiceTest.php:598
‪TYPO3\CMS\Core\Tests\Unit\Service\DependencyOrderingServiceTest\calculateOrderResolvesCorrectOrderDataProvider
‪array calculateOrderResolvesCorrectOrderDataProvider()
Definition: DependencyOrderingServiceTest.php:607
‪TYPO3\CMS\Core\Tests\Unit\Service
Definition: DependencyOrderingServiceTest.php:16
‪TYPO3\CMS\Core\Tests\Unit\Service\DependencyOrderingServiceTest\prepareDependenciesBuildsFullIdentifierListDataProvider
‪array prepareDependenciesBuildsFullIdentifierListDataProvider()
Definition: DependencyOrderingServiceTest.php:179
‪TYPO3\CMS\Core\Tests\Unit\Service\DependencyOrderingServiceTest\calculateOrderDetectsCyclicGraph
‪calculateOrderDetectsCyclicGraph()
Definition: DependencyOrderingServiceTest.php:653