Completed
Push — output_parsers_refactor ( cf2136...710907 )
by Alessandro
02:32
created

Runner   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 165
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 96.1%

Importance

Changes 19
Bugs 4 Features 1
Metric Value
wmc 19
c 19
b 4
f 1
lcom 1
cbo 8
dl 0
loc 165
ccs 74
cts 77
cp 0.961
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 1
B run() 0 48 6
A getReturnCode() 0 10 3
A createProcessStackFromFiles() 0 7 2
A runProcess() 0 15 4
A markProcessCompleted() 0 18 3
1
<?php
2
3
namespace Paraunit\Runner;
4
5
use Paraunit\Configuration\PHPUnitConfigFile;
6
use Paraunit\Printer\DebugPrinter;
7
use Paraunit\Process\ParaunitProcessAbstract;
8
use Paraunit\Process\ParaunitProcessInterface;
9
use Paraunit\Process\ProcessFactory;
10
use Paraunit\Lifecycle\EngineEvent;
11
use Paraunit\Lifecycle\ProcessEvent;
12
use Symfony\Component\Console\Output\OutputInterface;
13
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
14
15
/**
16
 * Class Runner.
17
 */
18
class Runner
19
{
20
    /** @var int */
21
    protected $maxProcessNumber;
22
23
    /** @var ParaunitProcessAbstract[] */
24
    protected $processStack;
25
26
    /** @var ParaunitProcessAbstract[] */
27
    protected $processCompleted;
28
29
    /** @var ParaunitProcessAbstract[] */
30
    protected $processRunning;
31
32
    /** @var  ProcessFactory */
33
    protected $processFactory;
34
35
    /** @var EventDispatcherInterface */
36
    protected $eventDispatcher;
37
38
    /**
39
     * @param int $maxProcessNumber
40
     * @param EventDispatcherInterface $eventDispatcher
41
     * @param ProcessFactory $processFactory
42
     */
43 7
    public function __construct(
44
        $maxProcessNumber = 10,
45
        EventDispatcherInterface $eventDispatcher,
46
        ProcessFactory $processFactory
47
    )
48
    {
49 7
        $this->eventDispatcher = $eventDispatcher;
50 7
        $this->maxProcessNumber = $maxProcessNumber;
51 7
        $this->processFactory = $processFactory;
52
53 7
        $this->processStack = array();
54 7
        $this->processCompleted = array();
55 7
        $this->processRunning = array();
56 7
    }
57
58
    /**
59
     * @param                 $files
60
     * @param OutputInterface $outputInterface
61
     * @param PHPUnitConfigFile $phpunitConfigFile
62
     * @param bool $debug
63
     * @return int
64
     */
65 7
    public function run($files, OutputInterface $outputInterface, PHPUnitConfigFile $phpunitConfigFile, $debug = false)
66
    {
67 7
        $this->eventDispatcher->dispatch(EngineEvent::BEFORE_START, new EngineEvent($files, $outputInterface));
68
69 7
        $this->processFactory->setConfigFile($phpunitConfigFile);
70 7
        $start = new \Datetime('now');
71 7
        $this->createProcessStackFromFiles($files);
72
73 7
        $this->eventDispatcher->dispatch(
74 7
            EngineEvent::START,
75 7
            new EngineEvent($files, $outputInterface, array('start' => $start,))
76 7
        );
77
78 7
        while ( ! empty($this->processStack) || ! empty($this->processRunning)) {
79
80 7
            if ($process = $this->runProcess($debug)) {
81 7
                $this->eventDispatcher->dispatch(ProcessEvent::PROCESS_STARTED, new ProcessEvent($process));
82 7
            }
83
84 7
            foreach ($this->processRunning as $process) {
85
86 7
                if ($process->isTerminated()) {
87
88 7
                    $this->eventDispatcher->dispatch(
89 7
                        ProcessEvent::PROCESS_TERMINATED,
90 7
                        new ProcessEvent($process, array('output_interface' => $outputInterface,))
91 7
                    );
92
                    // Completed or back to the stack
93 7
                    $this->markProcessCompleted($process);
94 7
                }
95
96 7
                usleep(500);
97 7
            }
98 7
        }
99
100 7
        $end = new \Datetime('now');
101
102 7
        $this->eventDispatcher->dispatch(
103 7
            EngineEvent::END,
104 7
            new EngineEvent(
105 7
                $files,
106 7
                $outputInterface,
107 7
                array('end' => $end, 'start' => $start, 'process_completed' => $this->processCompleted)
108 7
            )
109 7
        );
110
111 7
        return $this->getReturnCode();
112
    }
113
114
    /**
115
     * @return int
116
     */
117 7
    protected function getReturnCode()
118
    {
119 7
        foreach ($this->processCompleted as $process) {
120 7
            if ($process->getExitCode() != 0) {
121 5
                return 10;
122
            }
123 2
        }
124
125 2
        return 0;
126
    }
127
128
    /**
129
     * @param string[] $files
130
     */
131 7
    protected function createProcessStackFromFiles($files)
132
    {
133 7
        foreach ($files as $file) {
134 7
            $process = $this->processFactory->createProcess($file);
135 7
            $this->processStack[$process->getUniqueId()] = $process;
136 7
        }
137 7
    }
138
139
    /**
140
     * @param $debug
141
     *
142
     * @return ParaunitProcessAbstract
143
     */
144 7
    protected function runProcess($debug)
145
    {
146 7
        if ($this->maxProcessNumber > count($this->processRunning) && ! empty($this->processStack)) {
147
            /** @var ParaunitProcessInterface $process */
148 7
            $process = array_pop($this->processStack);
149 7
            $process->start();
150 7
            $this->processRunning[$process->getUniqueId()] = $process;
151
152 7
            if ($debug) {
153
                DebugPrinter::printDebugOutput($process, $this->processRunning);
154
            }
155
156 7
            return $process;
157
        }
158 7
    }
159
160
    /**
161
     * @param ParaunitProcessAbstract $process
162
     * @throws \Exception
163
     */
164 7
    protected function markProcessCompleted(ParaunitProcessAbstract $process)
165
    {
166 7
        $pHash = $process->getUniqueId();
167
168 7
        if (array_key_exists($pHash, $this->processRunning)) {
169 7
            unset($this->processRunning[$pHash]);
170 7
        } else {
171
            throw new \Exception('Trying to remove a non-existing process from running stack\! ID: ' . $pHash);
172
        }
173
174 7
        if ($process->isToBeRetried()) {
175 3
            $process->reset();
176 3
            $process->increaseRetryCount();
177 3
            $this->processStack[$pHash] = $process;
178 3
        } else {
179 7
            $this->processCompleted[$pHash] = $process;
180
        }
181 7
    }
182
}
183