Completed
Pull Request — master (#94)
by Alessandro
04:59
created

Runner::run()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 8
cts 8
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 2
nop 0
crap 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
13
/**
14
 * Class Runner
15
 * @package Paraunit\Runner
16
 */
17
class Runner
18
{
19
    /** @var  ProcessBuilderFactory */
20
    private $processBuilderFactory;
21
22
    /** @var EventDispatcherInterface */
23
    private $eventDispatcher;
24
25
    /** @var Filter */
26
    private $filter;
27
28
    /** @var PipelineCollection */
29
    private $pipelineCollection;
30
31
    /** @var \SplQueue */
32
    private $queuedProcesses;
33
34
    /** @var int */
35
    private $exitCode;
36
37
    /**
38
     * @param EventDispatcherInterface $eventDispatcher
39
     * @param ProcessBuilderFactory $processFactory
40
     * @param Filter $filter
41
     * @param PipelineCollection $pipelineCollection
42
     */
43 32
    public function __construct(
44
        EventDispatcherInterface $eventDispatcher,
45
        ProcessBuilderFactory $processFactory,
46
        Filter $filter,
47
        PipelineCollection $pipelineCollection
48
    ) {
49 32
        $this->eventDispatcher = $eventDispatcher;
50 32
        $this->processBuilderFactory = $processFactory;
51 32
        $this->filter = $filter;
52 32
        $this->pipelineCollection = $pipelineCollection;
53 32
        $this->queuedProcesses = new \SplQueue();
54 32
        $this->exitCode = 0;
55
    }
56
57
    /**
58
     * @return int The final exit code: 0 if no failures, 10 otherwise
59
     */
60 16
    public function run(): int
61
    {
62 16
        $this->eventDispatcher->dispatch(EngineEvent::BEFORE_START);
63
64 16
        $this->createProcessQueue();
65
66 16
        $this->eventDispatcher->dispatch(EngineEvent::START);
67
68 16
        while ($this->pipelineCollection->checkRunningState() || $this->pushToPipeline()) {
69 15
            usleep(100);
70
        }
71
72 16
        $this->eventDispatcher->dispatch(EngineEvent::END);
73
74 16
        return $this->exitCode;
75
    }
76
77
    /**
78
     * @param ProcessEvent $processEvent
79
     */
80 28
    public function onProcessParsingCompleted(ProcessEvent $processEvent)
81
    {
82 28
        $process = $processEvent->getProcess();
83
84 28
        if ($process->isToBeRetried()) {
85 5
            $process->reset();
86 5
            $process->increaseRetryCount();
87
88 5
            $this->queuedProcesses->enqueue($process);
89
90 5
            $this->eventDispatcher->dispatch(ProcessEvent::PROCESS_TO_BE_RETRIED, new ProcessEvent($process));
91 27
        } elseif ($process->getExitCode() !== 0) {
92 11
            $this->exitCode = 10;
93
        }
94
    }
95
96 16
    private function createProcessQueue()
97
    {
98 16
        foreach ($this->filter->filterTestFiles() as $file) {
99 15
            $processBuilder = $this->processBuilderFactory->create($file);
100 15
            $this->queuedProcesses->enqueue(new SymfonyProcessWrapper($processBuilder, $file));
101
        }
102
    }
103
104 16
    private function pushToPipeline(): bool
105
    {
106 16
        $somethingHasBeenPushed = false;
107 16
        while (! $this->queuedProcesses->isEmpty() && $this->pipelineCollection->hasEmptySlots()) {
108 15
            $this->pipelineCollection->push($this->queuedProcesses->dequeue());
109 15
            $somethingHasBeenPushed = true;
110
        }
111
112 16
        return $somethingHasBeenPushed;
113
    }
114
}
115