Completed
Push — master ( b61e2e...b32211 )
by Alessandro
11s
created

Runner   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 104
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 13
lcom 1
cbo 7
dl 0
loc 104
ccs 36
cts 36
cp 1
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 1
A getSubscribedEvents() 0 7 1
A run() 0 18 3
A onProcessParsingCompleted() 0 15 3
A createProcessQueue() 0 7 2
A pushToPipeline() 0 6 3
1
<?php
2
declare(strict_types=1);
3
4
namespace Paraunit\Runner;
5
6
use Paraunit\Filter\Filter;
7
use Paraunit\Lifecycle\EngineEvent;
8
use Paraunit\Lifecycle\ProcessEvent;
9
use Paraunit\Process\ProcessBuilderFactory;
10
use Paraunit\Process\SymfonyProcessWrapper;
11
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
12
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
13
14
/**
15
 * Class Runner
16
 * @package Paraunit\Runner
17
 */
18
class Runner implements EventSubscriberInterface
19
{
20
    /** @var  ProcessBuilderFactory */
21
    private $processBuilderFactory;
22
23
    /** @var EventDispatcherInterface */
24
    private $eventDispatcher;
25
26
    /** @var Filter */
27
    private $filter;
28
29
    /** @var PipelineCollection */
30
    private $pipelineCollection;
31
32
    /** @var \SplQueue */
33
    private $queuedProcesses;
34
35
    /** @var int */
36
    private $exitCode;
37
38
    /**
39
     * @param EventDispatcherInterface $eventDispatcher
40
     * @param ProcessBuilderFactory $processFactory
41
     * @param Filter $filter
42
     * @param PipelineCollection $pipelineCollection
43
     */
44 33
    public function __construct(
45
        EventDispatcherInterface $eventDispatcher,
46
        ProcessBuilderFactory $processFactory,
47
        Filter $filter,
48
        PipelineCollection $pipelineCollection
49
    ) {
50 33
        $this->eventDispatcher = $eventDispatcher;
51 33
        $this->processBuilderFactory = $processFactory;
52 33
        $this->filter = $filter;
53 33
        $this->pipelineCollection = $pipelineCollection;
54 33
        $this->queuedProcesses = new \SplQueue();
55 33
        $this->exitCode = 0;
56
    }
57
58 56
    public static function getSubscribedEvents(): array
59
    {
60
        return [
61 56
            ProcessEvent::PROCESS_TERMINATED => 'pushToPipeline',
62 56
            ProcessEvent::PROCESS_PARSING_COMPLETED => 'onProcessParsingCompleted',
63
        ];
64
    }
65
66
    /**
67
     * @return int The final exit code: 0 if no failures, 10 otherwise
68
     */
69 17
    public function run(): int
70
    {
71 17
        $this->eventDispatcher->dispatch(EngineEvent::BEFORE_START);
72
73 17
        $this->createProcessQueue();
74
75 17
        $this->eventDispatcher->dispatch(EngineEvent::START);
76
77
        do {
78 17
            $this->pushToPipeline();
79 17
            usleep(100);
80 17
            $this->pipelineCollection->triggerProcessTermination();
81 17
        } while (! $this->pipelineCollection->isEmpty() || ! $this->queuedProcesses->isEmpty());
82
83 17
        $this->eventDispatcher->dispatch(EngineEvent::END);
84
85 17
        return $this->exitCode;
86
    }
87
88
    /**
89
     * @param ProcessEvent $processEvent
90
     */
91 29
    public function onProcessParsingCompleted(ProcessEvent $processEvent)
92
    {
93 29
        $process = $processEvent->getProcess();
94
95 29
        if ($process->isToBeRetried()) {
96 5
            $process->reset();
97 5
            $process->increaseRetryCount();
98
99 5
            $this->queuedProcesses->enqueue($process);
100
101 5
            $this->eventDispatcher->dispatch(ProcessEvent::PROCESS_TO_BE_RETRIED, new ProcessEvent($process));
102 28
        } elseif ($process->getExitCode() !== 0) {
103 11
            $this->exitCode = 10;
104
        }
105
    }
106
107 17
    private function createProcessQueue()
108
    {
109 17
        foreach ($this->filter->filterTestFiles() as $file) {
110 16
            $processBuilder = $this->processBuilderFactory->create($file);
111 16
            $this->queuedProcesses->enqueue(new SymfonyProcessWrapper($processBuilder, $file));
112
        }
113
    }
114
115 17
    public function pushToPipeline()
116
    {
117 17
        while (! $this->queuedProcesses->isEmpty() && $this->pipelineCollection->hasEmptySlots()) {
118 16
            $this->pipelineCollection->push($this->queuedProcesses->dequeue());
119
        }
120
    }
121
}
122