Completed
Pull Request — master (#217)
by
unknown
03:02
created

Runner::complete()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 11
ccs 0
cts 10
cp 0
rs 9.4285
cc 2
eloc 8
nc 2
nop 0
crap 6
1
<?php
2
namespace ParaTest\Runners\PHPUnit;
3
4
use Habitat\Habitat;
5
6
class Runner extends BaseRunner
7
{
8
    /**
9
     * A collection of available tokens based on the number
10
     * of processes specified in $options
11
     *
12
     * @var array
13
     */
14
    protected $tokens = array();
15
16
17 8
    public function __construct($opts = array())
18
    {
19 8
        parent::__construct($opts);
20 8
        $this->initTokens();
21 8
    }
22
23
    /**
24
     * The money maker. Runs all ExecutableTest objects in separate processes.
25
     */
26 2
    public function run()
27
    {
28 2
        parent::run();
29
30 2
        while (count($this->running) || count($this->pending)) {
31 2
            foreach ($this->running as $key => $test) {
32 2
                if (!$this->testIsStillRunning($test)) {
33 2
                    unset($this->running[$key]);
34 2
                    $this->releaseToken($key);
35 2
                }
36 2
            }
37 2
            $this->fillRunQueue();
38 2
            usleep(10000);
39 2
        }
40 2
    }
41
42
    /**
43
     * Finalizes the run process. This method
44
     * prints all results, rewinds the log interpreter,
45
     * logs any results to JUnit, and cleans up temporary
46
     * files
47
     */
48
    public function complete()
49
    {
50
        $this->printer->printResults();
51
        $this->interpreter->rewind();
52
        $this->log();
53
        $this->logCoverage();
54
        $readers = $this->interpreter->getReaders();
55
        foreach ($readers as $reader) {
56
            $reader->removeLog();
57
        }
58
    }
59
60
    /**
61
     * This method removes ExecutableTest objects from the pending collection
62
     * and adds them to the running collection. It is also in charge of recycling and
63
     * acquiring available test tokens for use
64
     */
65 2
    private function fillRunQueue()
66
    {
67 2
        $opts = $this->options;
68 2
        while (sizeof($this->pending) && sizeof($this->running) < $opts->processes) {
0 ignored issues
show
Documentation introduced by
The property $processes is declared protected in ParaTest\Runners\PHPUnit\Options. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
69 2
            $tokenData = $this->getNextAvailableToken();
70 2
            if ($tokenData !== false) {
71 2
                $this->acquireToken($tokenData['token']);
72 2
                $env = array('TEST_TOKEN' => $tokenData['token'], 'UNIQUE_TEST_TOKEN' => $tokenData['unique']) + Habitat::getAll();
73 2
                $this->running[$tokenData['token']] = array_shift($this->pending)->run($opts->phpunit, $opts->filtered, $env);
0 ignored issues
show
Documentation introduced by
The property $phpunit is declared protected in ParaTest\Runners\PHPUnit\Options. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property $filtered is declared protected in ParaTest\Runners\PHPUnit\Options. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
74 2
            }
75 2
        }
76 2
    }
77
78
    /**
79
     * Returns whether or not a test has finished being
80
     * executed. If it has, this method also halts a test process - optionally
81
     * throwing an exception if a fatal error has occurred -
82
     * prints feedback, and updates the overall exit code
83
     *
84
     * @param ExecutableTest $test
85
     * @return bool
86
     * @throws \Exception
87
     */
88 2
    private function testIsStillRunning($test)
89
    {
90 2
        if (!$test->isDoneRunning()) {
91 2
            return true;
92
        }
93 2
        $this->setExitCode($test);
94 2
        $test->stop();
95 2
        if ($this->options->stopOnFailure && $test->getExitCode() > 0) {
0 ignored issues
show
Documentation introduced by
The property $stopOnFailure is declared protected in ParaTest\Runners\PHPUnit\Options. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
96
            $this->pending = array();
97
        }
98 2
        if (static::PHPUNIT_FATAL_ERROR === $test->getExitCode()) {
99
            $errorOutput = $test->getStderr();
100
            if (!$errorOutput) {
101
                $errorOutput = $test->getStdout();
102
            }
103
            throw new \Exception($errorOutput);
104
        }
105 2
        $this->printer->printFeedback($test);
106 2
        if ($this->hasCoverage()) {
107 2
            $this->addCoverage($test);
108 2
        }
109
110 2
        return false;
111
    }
112
113
    /**
114
     * If the provided test object has an exit code
115
     * higher than the currently set exit code, that exit
116
     * code will be set as the overall exit code
117
     *
118
     * @param ExecutableTest $test
119
     */
120 2
    private function setExitCode(ExecutableTest $test)
121
    {
122 2
        $exit = $test->getExitCode();
123 2
        if ($exit > $this->exitcode) {
124 2
            $this->exitcode = $exit;
125 2
        }
126 2
    }
127
128
    /**
129
     * Initialize the available test tokens based
130
     * on how many processes ParaTest will be run in
131
     */
132 8
    protected function initTokens()
133
    {
134 8
        $this->tokens = array();
135 8
        for ($i = 0; $i < $this->options->processes; $i++) {
0 ignored issues
show
Documentation introduced by
The property $processes is declared protected in ParaTest\Runners\PHPUnit\Options. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
136 8
            $this->tokens[$i] = array('token' => $i, 'unique' => uniqid($i), 'available' => true);
137 8
        }
138 8
    }
139
140
    /**
141
     * Gets the next token that is available to be acquired
142
     * from a finished process
143
     *
144
     * @return bool|array
145
     */
146 4
    protected function getNextAvailableToken()
147
    {
148 4
        foreach ($this->tokens as $data) {
149 4
            if ($data['available']) {
150 3
                return $data;
151
            }
152 4
        }
153 1
        return false;
154
    }
155
156
    /**
157
     * Flag a token as available for use
158
     *
159
     * @param string $tokenIdentifier
160
     */
161 3
    protected function releaseToken($tokenIdentifier)
162
    {
163
        $filtered = array_filter($this->tokens, function ($val) use ($tokenIdentifier) {
164 3
            return ($val['token'] === $tokenIdentifier);
165 3
        });
166 3
        $keys = array_keys($filtered);
167 3
        $this->tokens[$keys[0]]['available'] = true;
168 3
    }
169
170
    /**
171
     * Flag a token as acquired and not available for use
172
     *
173
     * @param string $tokenIdentifier
174
     */
175 2
    protected function acquireToken($tokenIdentifier)
176
    {
177
        $filtered = array_filter($this->tokens, function ($val) use ($tokenIdentifier) {
178 2
            return ($val['token'] === $tokenIdentifier);
179 2
        });
180 2
        $keys = array_keys($filtered);
181 2
        $this->tokens[$keys[0]]['available'] = false;
182 2
    }
183
184
    /**
185
     * @param ExecutableTest $test
186
     */
187 2
    private function addCoverage(ExecutableTest $test)
188
    {
189 2
        $coverageFile = $test->getCoverageFileName();
190 2
        $this->getCoverage()->addCoverageFromFile($coverageFile);
191 2
    }
192
}
193