brianium /
paratest
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | declare(strict_types=1); |
||
| 4 | |||
| 5 | namespace ParaTest\Console\Testers; |
||
| 6 | |||
| 7 | use ParaTest\Runners\PHPUnit\Configuration; |
||
| 8 | use ParaTest\Runners\PHPUnit\Runner; |
||
| 9 | use ParaTest\Runners\PHPUnit\WrapperRunner; |
||
| 10 | use Symfony\Component\Console\Command\Command; |
||
| 11 | use Symfony\Component\Console\Input\InputArgument; |
||
| 12 | use Symfony\Component\Console\Input\InputInterface; |
||
| 13 | use Symfony\Component\Console\Input\InputOption; |
||
| 14 | use Symfony\Component\Console\Output\OutputInterface; |
||
| 15 | |||
| 16 | /** |
||
| 17 | * Class PHPUnit. |
||
| 18 | * |
||
| 19 | * Creates the interface for PHPUnit testing |
||
| 20 | */ |
||
| 21 | class PHPUnit extends Tester |
||
| 22 | { |
||
| 23 | /** |
||
| 24 | * @var \ParaTest\Console\Commands\ParaTestCommand |
||
| 25 | */ |
||
| 26 | protected $command; |
||
| 27 | |||
| 28 | /** |
||
| 29 | * Configures the ParaTestCommand with PHPUnit specific |
||
| 30 | * definitions. |
||
| 31 | * |
||
| 32 | * @param Command $command |
||
| 33 | */ |
||
| 34 | 8 | public function configure(Command $command) |
|
| 35 | { |
||
| 36 | $command |
||
| 37 | 8 | ->addOption('phpunit', null, InputOption::VALUE_REQUIRED, 'The PHPUnit binary to execute. <comment>(default: vendor/bin/phpunit)</comment>') |
|
| 38 | 8 | ->addOption('runner', null, InputOption::VALUE_REQUIRED, 'Runner or WrapperRunner. <comment>(default: Runner)</comment>') |
|
| 39 | 8 | ->addOption('bootstrap', null, InputOption::VALUE_REQUIRED, 'The bootstrap file to be used by PHPUnit.') |
|
| 40 | 8 | ->addOption('configuration', 'c', InputOption::VALUE_REQUIRED, 'The PHPUnit configuration file to use.') |
|
| 41 | 8 | ->addOption('group', 'g', InputOption::VALUE_REQUIRED, 'Only runs tests from the specified group(s).') |
|
| 42 | 8 | ->addOption('exclude-group', null, InputOption::VALUE_REQUIRED, 'Don\'t run tests from the specified group(s).') |
|
| 43 | 8 | ->addOption('stop-on-failure', null, InputOption::VALUE_NONE, 'Don\'t start any more processes after a failure.') |
|
| 44 | 8 | ->addOption('log-junit', null, InputOption::VALUE_REQUIRED, 'Log test execution in JUnit XML format to file.') |
|
| 45 | 8 | ->addOption('colors', null, InputOption::VALUE_NONE, 'Displays a colored bar as a test result.') |
|
| 46 | 8 | ->addOption('testsuite', null, InputOption::VALUE_OPTIONAL, 'Filter which testsuite to run') |
|
| 47 | 8 | ->addArgument('path', InputArgument::OPTIONAL, 'The path to a directory or file containing tests. <comment>(default: current directory)</comment>') |
|
| 48 | 8 | ->addOption('path', null, InputOption::VALUE_REQUIRED, 'An alias for the path argument.'); |
|
| 49 | 8 | $this->command = $command; |
|
|
0 ignored issues
–
show
|
|||
| 50 | 8 | } |
|
| 51 | |||
| 52 | /** |
||
| 53 | * Executes the PHPUnit Runner. Will Display help if no config and no path |
||
| 54 | * supplied. |
||
| 55 | * |
||
| 56 | * @param InputInterface $input |
||
| 57 | * @param OutputInterface $output |
||
| 58 | * |
||
| 59 | * @return int|mixed |
||
| 60 | */ |
||
| 61 | public function execute(InputInterface $input, OutputInterface $output) |
||
| 62 | { |
||
| 63 | if (!$this->hasConfig($input) && !$this->hasPath($input)) { |
||
| 64 | $this->displayHelp($input, $output); |
||
| 65 | } |
||
| 66 | |||
| 67 | if ($input->getOption('runner') === 'WrapperRunner') { |
||
| 68 | $runner = new WrapperRunner($this->getRunnerOptions($input)); |
||
| 69 | } else { |
||
| 70 | if ($input->getOption('runner') !== '') { |
||
| 71 | // because we want to have to bootstrap script inherited before check/initialization |
||
| 72 | $runnerOption = $this->getRunnerOptions($input); |
||
| 73 | $runnerClass = $input->getOption('runner'); |
||
| 74 | if (null !== $runnerClass && class_exists($runnerClass)) { |
||
| 75 | $runner = new $runnerClass($runnerOption); |
||
| 76 | } |
||
| 77 | } |
||
| 78 | } |
||
| 79 | |||
| 80 | if (!isset($runner)) { |
||
| 81 | $runner = new Runner($this->getRunnerOptions($input)); |
||
| 82 | } |
||
| 83 | |||
| 84 | $runner->run(); |
||
| 85 | |||
| 86 | return $runner->getExitCode(); |
||
| 87 | } |
||
| 88 | |||
| 89 | /** |
||
| 90 | * Returns whether or not a test path has been supplied |
||
| 91 | * via option or regular input. |
||
| 92 | * |
||
| 93 | * @param InputInterface $input |
||
| 94 | * |
||
| 95 | * @return bool |
||
| 96 | */ |
||
| 97 | protected function hasPath(InputInterface $input) |
||
| 98 | { |
||
| 99 | $argument = $input->getArgument('path'); |
||
| 100 | $option = $input->getOption('path'); |
||
| 101 | |||
| 102 | return $argument || $option; |
||
| 103 | } |
||
| 104 | |||
| 105 | /** |
||
| 106 | * Is there a PHPUnit xml configuration present. |
||
| 107 | * |
||
| 108 | * @param InputInterface $input |
||
| 109 | * |
||
| 110 | * @return bool |
||
| 111 | */ |
||
| 112 | 4 | protected function hasConfig(InputInterface $input): bool |
|
| 113 | { |
||
| 114 | 4 | return false !== $this->getConfig($input); |
|
| 115 | } |
||
| 116 | |||
| 117 | /** |
||
| 118 | * @param \Symfony\Component\Console\Input\InputInterface $input |
||
| 119 | * |
||
| 120 | * @return \ParaTest\Runners\PHPUnit\Configuration|bool |
||
| 121 | */ |
||
| 122 | 4 | protected function getConfig(InputInterface $input) |
|
| 123 | { |
||
| 124 | 4 | $cwd = getcwd() . DIRECTORY_SEPARATOR; |
|
| 125 | |||
| 126 | 4 | if ($input->getOption('configuration')) { |
|
| 127 | $configFilename = $input->getOption('configuration'); |
||
| 128 | 4 | } elseif (file_exists($cwd . 'phpunit.xml.dist')) { |
|
| 129 | 4 | $configFilename = $cwd . 'phpunit.xml.dist'; |
|
| 130 | } elseif (file_exists($cwd . 'phpunit.xml')) { |
||
| 131 | $configFilename = $cwd . 'phpunit.xml'; |
||
| 132 | } else { |
||
| 133 | return false; |
||
| 134 | } |
||
| 135 | |||
| 136 | 4 | return new Configuration($configFilename); |
|
| 137 | } |
||
| 138 | |||
| 139 | /** |
||
| 140 | * @param \Symfony\Component\Console\Input\InputInterface $input |
||
| 141 | * |
||
| 142 | * @throws \RuntimeException |
||
| 143 | * |
||
| 144 | * @return array |
||
| 145 | */ |
||
| 146 | 4 | public function getRunnerOptions(InputInterface $input): array |
|
| 147 | { |
||
| 148 | 4 | $path = $input->getArgument('path'); |
|
| 149 | 4 | $options = $this->getOptions($input); |
|
| 150 | 4 | $bootstrap = $this->getBootstrapFile($input, $options); |
|
| 151 | 4 | $this->requireBootstrap($bootstrap); |
|
| 152 | |||
| 153 | 4 | if ($this->hasCoverage($options)) { |
|
| 154 | 2 | $options['coverage-php'] = tempnam(sys_get_temp_dir(), 'paratest_'); |
|
| 155 | } |
||
| 156 | |||
| 157 | 4 | if ($path) { |
|
| 158 | 4 | $options = array_merge(['path' => $path], $options); |
|
| 159 | } |
||
| 160 | |||
| 161 | 4 | return $options; |
|
| 162 | } |
||
| 163 | |||
| 164 | /** |
||
| 165 | * Require the bootstrap. If the file is specified, but does not exist |
||
| 166 | * then an exception will be raised. |
||
| 167 | * |
||
| 168 | * @param $file |
||
| 169 | * |
||
| 170 | * @throws \RuntimeException |
||
| 171 | */ |
||
| 172 | 5 | public function requireBootstrap(string $file) |
|
| 173 | { |
||
| 174 | 5 | if (!$file) { |
|
| 175 | return; |
||
| 176 | } |
||
| 177 | |||
| 178 | 5 | if (!file_exists($file)) { |
|
| 179 | $message = sprintf('Bootstrap specified but could not be found (%s)', $file); |
||
| 180 | throw new \RuntimeException($message); |
||
| 181 | } |
||
| 182 | |||
| 183 | 5 | $this->scopedRequire($file); |
|
| 184 | 5 | } |
|
| 185 | |||
| 186 | /** |
||
| 187 | * This function limits the scope of a required file |
||
| 188 | * so that variables defined in it do not break |
||
| 189 | * this object's configuration. |
||
| 190 | * |
||
| 191 | * @param mixed $file |
||
| 192 | */ |
||
| 193 | 5 | protected function scopedRequire(string $file) |
|
| 194 | { |
||
| 195 | 5 | $cwd = getcwd(); |
|
| 196 | 5 | require_once $file; |
|
| 197 | 5 | chdir($cwd); |
|
| 198 | 5 | } |
|
| 199 | |||
| 200 | /** |
||
| 201 | * Return whether or not code coverage information should be collected. |
||
| 202 | * |
||
| 203 | * @param $options |
||
| 204 | * |
||
| 205 | * @return bool |
||
| 206 | */ |
||
| 207 | 4 | protected function hasCoverage(array $options): bool |
|
| 208 | { |
||
| 209 | 4 | $isFileFormat = isset($options['coverage-html']) || isset($options['coverage-clover']); |
|
| 210 | 4 | $isPHP = isset($options['coverage-php']); |
|
| 211 | |||
| 212 | 4 | return $isFileFormat && !$isPHP; |
|
| 213 | } |
||
| 214 | |||
| 215 | /** |
||
| 216 | * Fetch the path to the bootstrap file. |
||
| 217 | * |
||
| 218 | * @param InputInterface $input |
||
| 219 | * @param array $options |
||
| 220 | * |
||
| 221 | * @return string |
||
| 222 | */ |
||
| 223 | 4 | protected function getBootstrapFile(InputInterface $input, array $options): string |
|
| 224 | { |
||
| 225 | 4 | if (isset($options['bootstrap'])) { |
|
| 226 | return $options['bootstrap']; |
||
| 227 | } |
||
| 228 | |||
| 229 | 4 | if (!$this->hasConfig($input)) { |
|
| 230 | return ''; |
||
| 231 | } |
||
| 232 | |||
| 233 | 4 | $config = $this->getConfig($input); |
|
| 234 | 4 | $bootstrap = $config->getBootstrap(); |
|
| 235 | |||
| 236 | 4 | return ($bootstrap) ? $config->getConfigDir() . $bootstrap : ''; |
|
| 237 | } |
||
| 238 | } |
||
| 239 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.
Either this assignment is in error or an instanceof check should be added for that assignment.