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