TYPO3 CMS  TYPO3_7-6
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 
19 
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  'sv' => [
415  'before' => [],
416  'after' => ['core'],
417  ],
418  ],
419  [ // graph
420  'core' => [
421  'core' => false,
422  'setup' => false,
423  'sv' => false,
424  'scheduler' => false,
425  'openid' => false,
426  ],
427  'openid' => [
428  'core' => true,
429  'setup' => true,
430  'sv' => false,
431  'scheduler' => false,
432  'openid' => false,
433  ],
434  'scheduler' => [
435  'core' => true,
436  'setup' => false,
437  'sv' => false,
438  'scheduler' => false,
439  'openid' => false,
440  ],
441  'setup' => [
442  'core' => true,
443  'setup' => false,
444  'sv' => false,
445  'scheduler' => false,
446  'openid' => false,
447  ],
448  'sv' => [
449  'core' => true,
450  'setup' => false,
451  'sv' => false,
452  'scheduler' => false,
453  'openid' => false,
454  ],
455  ],
456  ],
457  'Dummy Packages' => [
458  [ // dependencies
459  'A' => [
460  'before' => [],
461  'after' => ['B', 'D', 'C'],
462  ],
463  'B' => [
464  'before' => [],
465  'after' => []
466  ],
467  'C' => [
468  'before' => [],
469  'after' => ['E']
470  ],
471  'D' => [
472  'before' => [],
473  'after' => ['E'],
474  ],
475  'E' => [
476  'before' => [],
477  'after' => [],
478  ],
479  'F' => [
480  'before' => [],
481  'after' => [],
482  ],
483  ],
484  [ // graph
485  'A' => [
486  'A' => false,
487  'B' => true,
488  'C' => true,
489  'D' => true,
490  'E' => false,
491  'F' => false,
492  ],
493  'B' => [
494  'A' => false,
495  'B' => false,
496  'C' => false,
497  'D' => false,
498  'E' => false,
499  'F' => false,
500  ],
501  'C' => [
502  'A' => false,
503  'B' => false,
504  'C' => false,
505  'D' => false,
506  'E' => true,
507  'F' => false,
508  ],
509  'D' => [
510  'A' => false,
511  'B' => false,
512  'C' => false,
513  'D' => false,
514  'E' => true,
515  'F' => false,
516  ],
517  'E' => [
518  'A' => false,
519  'B' => false,
520  'C' => false,
521  'D' => false,
522  'E' => false,
523  'F' => false,
524  ],
525  'F' => [
526  'A' => false,
527  'B' => false,
528  'C' => false,
529  'D' => false,
530  'E' => false,
531  'F' => false,
532  ],
533  ],
534  ],
535  'Suggestions without reverse dependency' => [
536  [ // dependencies
537  'A' => [
538  'before' => [],
539  'after' => [],
540  'after-resilient' => ['B'] // package suggestion
541  ],
542  'B' => [
543  'before' => [],
544  'after' => [],
545  ],
546  'C' => [
547  'before' => [],
548  'after' => ['A']
549  ],
550  ],
551  [ // graph
552  'A' => [
553  'A' => false,
554  'B' => true,
555  'C' => false,
556  ],
557  'B' => [
558  'A' => false,
559  'B' => false,
560  'C' => false,
561  ],
562  'C' => [
563  'A' => true,
564  'B' => false,
565  'C' => false,
566  ],
567  ],
568  ],
569  'Suggestions with reverse dependency' => [
570  [ // dependencies
571  'A' => [
572  'before' => [],
573  'after' => [],
574  'after-resilient' => ['B'], // package suggestion
575  ],
576  'B' => [
577  'before' => [],
578  'after' => ['A']
579  ],
580  'C' => [
581  'before' => [],
582  'after' => ['A']
583  ],
584  ],
585  [ // graph
586  'A' => [
587  'A' => false,
588  'B' => false,
589  'C' => false,
590  ],
591  'B' => [
592  'A' => true,
593  'B' => false,
594  'C' => false,
595  ],
596  'C' => [
597  'A' => true,
598  'B' => false,
599  'C' => false,
600  ],
601  ],
602  ],
603  ];
604  }
605 
612  public function calculateOrderResolvesCorrectOrder(array $graph, array $expectedList)
613  {
614  $list = (new DependencyOrderingService())->calculateOrder($graph);
615  $this->assertSame($expectedList, $list);
616  }
617 
622  {
623  return [
624  'list1' => [
625  [ // $graph
626  1 => [
627  1 => false,
628  2 => true
629  ],
630  2 => [
631  1 => false,
632  2 => false
633  ],
634  ],
635  [ // $expectedList
636  2, 1
637  ]
638  ],
639  'list2' => [
640  [ // $graph
641  1 => [
642  1 => false,
643  2 => true,
644  3 => false,
645  ],
646  2 => [
647  1 => false,
648  2 => false,
649  3 => false,
650  ],
651  3 => [
652  1 => true,
653  2 => true,
654  3 => false,
655  ],
656  ],
657  [ // $expectedList
658  2, 1, 3
659  ]
660  ],
661  ];
662  }
663 
670  {
671  (new DependencyOrderingService())->calculateOrder([
672  1 => [
673  1 => false,
674  2 => true,
675  ],
676  2 => [
677  1 => true,
678  2 => false,
679  ],
680  ]);
681  }
682 
687  {
688  return [
689  'Simple path' => [
690  [
691  'A' => ['A' => false, 'B' => false, 'C' => false, 'Z' => true],
692  'B' => ['A' => false, 'B' => false, 'C' => false, 'Z' => false],
693  'C' => ['A' => false, 'B' => false, 'C' => false, 'Z' => false],
694  'Z' => ['A' => false, 'B' => false, 'C' => false, 'Z' => false]
695  ],
696  'A', 'Z',
697  ['A', 'Z']
698  ],
699  'No path' => [
700  [
701  'A' => ['A' => false, 'B' => true, 'C' => false, 'Z' => false],
702  'B' => ['A' => false, 'B' => false, 'C' => false, 'Z' => false],
703  'C' => ['A' => false, 'B' => true, 'C' => false, 'Z' => false],
704  'Z' => ['A' => false, 'B' => true, 'C' => false, 'Z' => false]
705  ],
706  'A', 'C',
707  []
708  ],
709  'Longer path' => [
710  [
711  'A' => ['A' => false, 'B' => true, 'C' => true, 'Z' => true],
712  'B' => ['A' => false, 'B' => false, 'C' => false, 'Z' => false],
713  'C' => ['A' => false, 'B' => false, 'C' => false, 'Z' => true],
714  'Z' => ['A' => false, 'B' => false, 'C' => false, 'Z' => false]
715  ],
716  'A', 'Z',
717  ['A', 'C', 'Z']
718  ],
719  ];
720  }
721 
730  public function findPathInGraphReturnsCorrectPath(array $graph, $from, $to, array $expected)
731  {
733  $dependencyOrderingService = $this->getAccessibleMock(DependencyOrderingService::class, ['dummy']);
734  $path = $dependencyOrderingService->_call('findPathInGraph', $graph, $from, $to);
735 
736  $this->assertSame($expected, $path);
737  }
738 }
orderByDependenciesBuildsCorrectOrder(array $items, $beforeKey, $afterKey, array $expectedOrderedItems)
getAccessibleMock( $originalClassName, $methods=[], array $arguments=[], $mockClassName='', $callOriginalConstructor=true, $callOriginalClone=true, $callAutoload=true)