diff --git a/.gitignore b/.gitignore index 5a74142..51799f1 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ /.phpunit.result.cache /report/ /vendor/ +/vendor-bin/ /.vscode/ diff --git a/Makefile b/Makefile index 308f0ea..031e9a9 100644 --- a/Makefile +++ b/Makefile @@ -20,22 +20,12 @@ docs-functions: phpcheck: @phpcheck -phpcheck-coverage-html: +phpcheck-coverage: sudo phpenmod xdebug @phpcheck --coverage-html report/phpcheck-coverage sudo phpdismod xdebug @xdg-open report/phpcheck-coverage/index.html -phpcheck-coverage-console: - sudo phpenmod xdebug - @phpcheck --coverage-text - sudo phpdismod xdebug - -phpcheck-coverage-text: - sudo phpenmod xdebug - @phpcheck --coverage-text report/phpcheck-coverage.txt - sudo phpdismod xdebug - phpcheck-log-junit: @phpcheck --log-junit build/phpcheck.xml diff --git a/checks/GeneratorCheck.php b/checks/GeneratorCheck.php index 447c029..d177713 100644 --- a/checks/GeneratorCheck.php +++ b/checks/GeneratorCheck.php @@ -35,7 +35,7 @@ function ($interval) use ($ord) { public function checkStrings(string $string): bool { - return \mb_strlen($string) < 100; + return \mb_strlen($string) <= 30; } /** diff --git a/composer.json b/composer.json index c3a30aa..52d2dd7 100644 --- a/composer.json +++ b/composer.json @@ -38,6 +38,7 @@ "webmozart/assert": "^1.4" }, "require-dev": { + "bamarni/composer-bin-plugin": "^1.3", "cache/redis-adapter": "^1.0", "friendsofphp/php-cs-fixer": "^2.14", "knplabs/github-api": "^2.11", @@ -47,6 +48,9 @@ "phpunit/phpunit": "^8.1", "symfony/templating": "^4.2" }, + "suggest": { + "ext-simplexml": "Enables JUnit XML report" + }, "config": { "platform": { "php": "7.2.0" @@ -72,5 +76,10 @@ "Datashaman\\PHPCheck\\Checks\\": "checks/", "Datashaman\\PHPCheck\\Tests\\": "tests/" } + }, + "scripts": { + "bin": "echo 'bin not installed'", + "post-install-cmd": ["@composer bin all install --ansi"], + "post-update-cmd": ["@composer bin all update --ansi"] } } diff --git a/examples/check_encoder.php b/examples/check_encoder.php deleted file mode 100644 index 38e2500..0000000 --- a/examples/check_encoder.php +++ /dev/null @@ -1,24 +0,0 @@ -checks(100, 'encode', function ($input, $output) { - $result = $input[0] === decode($output); - - return $result; - }); - -foreach ($results as $result) { - if (!$result['passed']) { - echo "FAILURE!\n"; - dd($result); - exit(); - } -} - -echo "OK!\n"; diff --git a/playground/quickcheck.php b/playground/quickcheck.php deleted file mode 100644 index f012909..0000000 --- a/playground/quickcheck.php +++ /dev/null @@ -1,19 +0,0 @@ - + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ namespace Datashaman\PHPCheck; class Args { public $bootstrap; + public $coverageHtml = false; + public $coverageText = false; + public $filter; + public $logJunit = false; + public $logText = false; + public $maxSuccess = Runner::MAX_SUCCESS; + public $noAnsi; + public $noDefects; + public $path; + public $output; + public $subject; } diff --git a/src/CheckCommand.php b/src/CheckCommand.php index c7fda2d..81bc67e 100644 --- a/src/CheckCommand.php +++ b/src/CheckCommand.php @@ -94,17 +94,17 @@ protected function execute(InputInterface $input, OutputInterface $output): ?int { $args = new Args(); - $args->bootstrap = $input->getOption('bootstrap'); + $args->bootstrap = $input->getOption('bootstrap'); $args->coverageHtml = $input->getOption('coverage-html'); $args->coverageText = $input->getOption('coverage-text'); - $args->filter = $input->getOption('filter'); - $args->logJunit = $input->getOption('log-junit'); - $args->logText = $input->getOption('log-text'); - $args->maxSuccess = $input->getOption('max-success'); - $args->noAnsi = $input->getOption('no-ansi'); - $args->noDefects = $input->getOption('no-defects'); - $args->output = $output; - $args->path = $input->getArgument('path'); + $args->filter = $input->getOption('filter'); + $args->logJunit = $input->getOption('log-junit'); + $args->logText = $input->getOption('log-text'); + $args->maxSuccess = $input->getOption('max-success'); + $args->noAnsi = $input->getOption('no-ansi'); + $args->noDefects = $input->getOption('no-defects'); + $args->output = $output; + $args->path = $input->getArgument('path'); $result = app('runner')->execute($args); diff --git a/src/Coverage/TextCoverage.php b/src/Coverage/TextCoverage.php index c9a2b39..bce7624 100644 --- a/src/Coverage/TextCoverage.php +++ b/src/Coverage/TextCoverage.php @@ -9,7 +9,6 @@ */ namespace Datashaman\PHPCheck\Coverage; -use function Datashaman\PHPCheck\app; use SebastianBergmann\CodeCoverage\Report\Text; /** @@ -18,12 +17,9 @@ class TextCoverage extends Coverage { private $_output; + private $_noAnsi; - /** - * @param null|string $output - * @param null|bool $noAnsi - */ public function __construct( string $output = null, bool $noAnsi = null diff --git a/src/Events/EndEvent.php b/src/Events/EndEvent.php index 43af915..e588b48 100644 --- a/src/Events/EndEvent.php +++ b/src/Events/EndEvent.php @@ -37,7 +37,7 @@ public function __construct( ) { parent::__construct(); $this->function = $function; - $this->tags = $tags; - $this->status = $status; + $this->tags = $tags; + $this->status = $status; } } diff --git a/src/Events/ResultEvent.php b/src/Events/ResultEvent.php index a287513..598593c 100644 --- a/src/Events/ResultEvent.php +++ b/src/Events/ResultEvent.php @@ -49,8 +49,8 @@ public function __construct( ) { parent::__construct(); $this->function = $function; - $this->tags = $tags; - $this->args = $args; - $this->cause = $cause; + $this->tags = $tags; + $this->args = $args; + $this->cause = $cause; } } diff --git a/src/Events/StartEvent.php b/src/Events/StartEvent.php index b9948a6..83330db 100644 --- a/src/Events/StartEvent.php +++ b/src/Events/StartEvent.php @@ -31,6 +31,6 @@ public function __construct( ) { parent::__construct(); $this->function = $function; - $this->tags = $tags; + $this->tags = $tags; } } diff --git a/src/Random.php b/src/Random.php index 3052b0f..d6e4773 100644 --- a/src/Random.php +++ b/src/Random.php @@ -17,7 +17,7 @@ public function random($min = 0, $max = null) { do { $value = parent::random($min, $max); - } while (!is_int($value)); + } while (!\is_int($value)); return $value; } diff --git a/src/Runner.php b/src/Runner.php index 274e26b..4277fec 100644 --- a/src/Runner.php +++ b/src/Runner.php @@ -16,20 +16,16 @@ use phpDocumentor\Reflection\DocBlockFactory; use ReflectionFunction; use ReflectionFunctionAbstract; -use ReflectionMethod; use SimpleXMLElement; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Finder\Finder; use Throwable; use Webmozart\Assert\Assert; -class Runner implements EventSubscriberInterface +class Runner { public const MAX_DISCARD_RATIO = 10; - public const MAX_SIZE = 100; - public const MAX_SUCCESS = 100; protected const CONFIG_FILE = 'phpcheck.xml'; @@ -42,19 +38,6 @@ class Runner implements EventSubscriberInterface private $totalIterations = 0; - public static function getSubscribedEvents(): array - { - return [ - CheckEvents::END_ALL => 'onEndAll', - CheckEvents::FAILURE => 'onFailure', - CheckEvents::END => 'onEnd', - CheckEvents::ERROR => 'onError', - CheckEvents::START => 'onStart', - CheckEvents::START_ALL => 'onStartAll', - CheckEvents::SUCCESS => 'onSuccess', - ]; - } - public function getOutput() { return $this->output; @@ -84,57 +67,6 @@ public function iterate( return $result; } - protected function gatherMethods($args) - { - $methods = []; - $paths = $this->gatherPaths($args->output, $args->path); - - foreach ($paths as $path) { - $classes = \get_declared_classes(); - - include $path; - - $classes = \array_diff( - \get_declared_classes(), - $classes - ); - - $classes = \array_filter( - $classes, - function ($class) { - return \preg_match('/Check$/', $class) === 1; - } - ); - - $testClass = \array_pop($classes); - - [$classFilter, $methodFilter] = $this->getFilter($args); - - if ($classFilter && !\fnmatch($classFilter, $testClass)) { - continue; - } - - $class = app('reflection')->getClass($testClass); - $methods[$testClass] = []; - - foreach ($class->getMethods() as $method) { - $name = $method->getName(); - - if ($methodFilter && !\fnmatch($methodFilter, $name)) { - continue; - } - - if (\preg_match('/^check/', $method->getName()) !== 1) { - continue; - } - - $methods[$testClass][] = $method; - } - } - - return $methods; - } - public function execute(Args $args): void { $state = app('state'); @@ -215,7 +147,7 @@ public function execute(Args $args): void foreach ($functions as $function) { $tags = $this->getTags($function); - $event = new Events\StartEvent($function, $tags); + $event = new Events\StartEvent($function, $tags); $dispatcher->dispatch(CheckEvents::START, $event); $parameterCount = \count($function->getParameters()); @@ -279,6 +211,57 @@ public function execute(Args $args): void $dispatcher->dispatch(CheckEvents::END_ALL, $event); } + protected function gatherMethods($args) + { + $methods = []; + $paths = $this->gatherPaths($args->output, $args->path); + + foreach ($paths as $path) { + $classes = \get_declared_classes(); + + include $path; + + $classes = \array_diff( + \get_declared_classes(), + $classes + ); + + $classes = \array_filter( + $classes, + function ($class) { + return \preg_match('/Check$/', $class) === 1; + } + ); + + $testClass = \array_pop($classes); + + [$classFilter, $methodFilter] = $this->getFilter($args); + + if ($classFilter && !\fnmatch($classFilter, $testClass)) { + continue; + } + + $class = app('reflection')->getClass($testClass); + $methods[$testClass] = []; + + foreach ($class->getMethods() as $method) { + $name = $method->getName(); + + if ($methodFilter && !\fnmatch($methodFilter, $name)) { + continue; + } + + if (\preg_match('/^check/', $method->getName()) !== 1) { + continue; + } + + $methods[$testClass][] = $method; + } + } + + return $methods; + } + private function checks( int $size, callable $subject, @@ -297,7 +280,7 @@ private function checks( for ($iteration = 1; $iteration <= $size; $iteration++) { $input = generate(resize( - \min($iteration - 1, self::MAX_SIZE), + \min($iteration - 1, DEFAULT_SIZE), arguments($subject) )); [$passed, $output, $error] = $this->passed($reflection, $check, $input); diff --git a/src/generators.php b/src/generators.php index f6ee0bd..7ce3733 100644 --- a/src/generators.php +++ b/src/generators.php @@ -54,7 +54,7 @@ * * var_dump(generate(arguments('funcA'))); * - * /** + * \/** * * @param string $s {@gen faker("username")} * *\/ * function funcB(string $s) { @@ -63,9 +63,7 @@ * var_dump(generate(arguments('funcB'))); * * - * @param callable $f * - * @return Generator */ function arguments(callable $f): Generator { @@ -77,7 +75,7 @@ function arguments(callable $f): Generator if (!$cache->hasKey($f)) { $reflection = app('reflection'); - $function = $reflection->reflect($f); + $function = $reflection->reflect($f); $generators = []; @@ -129,7 +127,6 @@ function (Random $r, int $n = null) use ($generators) { * var_dump(generate(arrays())); * * - * @return Generator */ function arrays(): Generator { @@ -153,7 +150,6 @@ function arrays(): Generator * var_dump(sample(strings(ascii()))); * * - * @return Generator */ function ascii(): Generator { @@ -176,7 +172,6 @@ function ascii(): Generator * var_dump(generate(booleans(75))); * * - * @return Generator */ function booleans(int $chanceOfGettingTrue = 50): Generator { @@ -199,10 +194,9 @@ function (Random $r) use ($chanceOfGettingTrue) { * var_dump(sample(characters())); * * - * @param null|int|string $minChar The minimum character to be generated. - * @param null|int|string $maxChar The maximum character to be generated. + * @param null|int|string $minChar the minimum character to be generated + * @param null|int|string $maxChar the maximum character to be generated * - * @return Generator */ function characters( $minChar = null, @@ -265,8 +259,8 @@ function (Random $r) use ($codePoints) { * var_dump(sample(choose("a", "e"))); * * - * @param int|array|float|string $min The minimum element to generate. Can be an integer, float or a one character string. If it's an array, it must be a `[min, max]` pair. - * @param int|float|string $max The maximum element to generate. Can be an integer, float or a one character string. + * @param array|float|int|string $min The minimum element to generate. Can be an integer, float or a one character string. If it's an array, it must be a `[min, max]` pair. + * @param float|int|string $max The maximum element to generate. Can be an integer, float or a one character string. */ function choose($min = \PHP_INT_MIN, $max = \PHP_INT_MAX): Generator { @@ -313,9 +307,9 @@ function (Random $r) use ($min, $max, $strings) { * * var_dump(sample(chooseAny('float'))); * + * * @param string $type The type to be generated. Can be one of: `float`, `int`, `string`. * - * @return Generator */ function chooseAny(string $type): Generator { @@ -346,11 +340,10 @@ function chooseAny(string $type): Generator * var_dump(sample(datetimes('2000-01-01', '2100-01-01', timezones()))); * * - * @param null|array|string|DateTime $min The minimum datetime to be generated. If it's an array, it must a `[min, max]` pair. - * @param null|string|DateTime $max The maximum datetime to be generated. - * @param null|Generator $timezones Optional timezones generator. Default is naive datetimes. + * @param null|array|DateTime|string $min The minimum datetime to be generated. If it's an array, it must a `[min, max]` pair. + * @param null|DateTime|string $max the maximum datetime to be generated + * @param null|Generator $timezones Optional timezones generator. Default is naive datetimes. * - * @return Generator */ function datetimes( $min = null, @@ -410,10 +403,9 @@ function (Random $r) use ($min, $max, $timezones) { * var_dump(sample(dates('2000-01-01', '2300-01-01'))); * * - * @param int|array|string|DateTime $min The minimum date to be generated. If it's an array, it must be a `[min, max]` pair. - * @param int|string|DateTime $max The maximum date to be generated. + * @param array|DateTime|int|string $min The minimum date to be generated. If it's an array, it must be a `[min, max]` pair. + * @param DateTime|int|string $max the maximum date to be generated * - * @return Generator */ function dates($min = null, $max = null): Generator { @@ -455,9 +447,8 @@ function (Random $r) use ($min, $max) { * var_dump(generate(listOf1(elements(['abc', 123, 'u&me'])))); * * - * @param array $array The array to be generated from. + * @param array $array the array to be generated from * - * @return Generator */ function elements(array $array): Generator { @@ -488,7 +479,6 @@ function (Random $r) use ($array) { * * @param array $args,... First argument is the factory property or method name. If there is more than 1 argument, it's treated as a method call. If if there is 1 argument, it's treated as a property. * - * @return Generator */ function faker(...$args): Generator { @@ -519,10 +509,10 @@ function () use ($attr, $args, $faker) { * * var_dump(generate(floats(-1000, 1000))); * - * @param float $min The minimum float value to generate. - * @param float $max The maximum float value to generate. * - * @return Generator + * @param float $min the minimum float value to generate + * @param float $max the maximum float value to generate + * */ function floats(float $min = \PHP_FLOAT_MIN, float $max = \PHP_FLOAT_MAX): Generator { @@ -557,9 +547,8 @@ function () use ($min, $max) { * ]))); * * - * @param array $frequencies A weighted list consisting of pairs of `[weight, generator]`. + * @param array $frequencies a weighted list consisting of pairs of `[weight, generator]` * - * @return Generator */ function frequency(array $frequencies): Generator { @@ -616,9 +605,8 @@ function (Random $r) use ($map) { * var_dump(sample(listOf(growingElements([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])))); * * - * @param array $array The array containing the elements to be selected. + * @param array $array the array containing the elements to be selected * - * @return Generator */ function growingElements(array $array): Generator { @@ -645,13 +633,12 @@ function (Random $r, $n) use ($array) { * use function Datashaman\PHPCheck\intervals; * use function Datashaman\PHPCheck\sample; * - * var_dump(sample(intervals([[1, 10], [1, 5]]))); + * var_dump(sample(intervals([[1, 10]], [[1, 5]]))); * * - * @param array $include An array of intervals to include in selecting the value. - * @param array $exclude An array of intervals to exclude from the selection. + * @param array $include an array of intervals to include in selecting the value + * @param array $exclude an array of intervals to exclude from the selection * - * @return Generator */ function intervals( array $include = [[\PHP_INT_MIN, \PHP_INT_MAX]], @@ -729,9 +716,8 @@ function (Random $r) use ($exclude, $intervals, $max) { * var_dump(generate(resize(2, listOf(faker("ipv4"))))); * * - * @param Generator $gen The generator that creates the values. + * @param Generator $gen the generator that creates the values * - * @return Generator */ function listOf(Generator $gen): Generator { @@ -760,9 +746,8 @@ function (Random $r, $n) use ($gen) { * var_dump(generate(resize(2, listOf1(faker("emoji"))))); * * - * @param Generator $gen The generator that creates the values. + * @param Generator $gen the generator that creates the values * - * @return Generator */ function listOf1(Generator $gen): Generator { @@ -794,7 +779,6 @@ function (Random $r, $n) use ($gen) { * var_dump(sample(mixed())); * * - * @return Generator */ function mixed(): Generator { @@ -828,9 +812,9 @@ function mixed(): Generator * ] * ))); * - * @param array $gens The list of generators to be chosen from. * - * @return Generator + * @param array $gens the list of generators to be chosen from + * */ function oneof(array $gens): Generator { @@ -857,10 +841,9 @@ function (Random $r) use ($gens) { * var_dump(sample(resize(3, listOf(faker("firstname"))))); * * - * @param int $n The size to be used by the generator. - * @param Generator $gen The generator that creates the values. + * @param int $n the size to be used by the generator + * @param Generator $gen the generator that creates the values * - * @return Generator */ function resize(int $n, Generator $gen): Generator { @@ -888,10 +871,9 @@ function (Random $r) use ($n, $gen) { * }, listOf(strings(ascii()))))); * * - * @param callable $f The transform function that scales the size. - * @param Generator $gen The generator who's size will be scaled. + * @param callable $f the transform function that scales the size + * @param Generator $gen the generator who's size will be scaled * - * @return Generator */ function scale(callable $f, Generator $gen): Generator { @@ -920,9 +902,7 @@ function (Random $r, $n) use ($f, $gen) { * var_dump(generate(strings(characters('a', 'e')))); * * - * @param null|Generator $characters * - * @return Generator */ function strings(Generator $characters = null): Generator { @@ -959,10 +939,9 @@ function (Random $r, int $n) use ($characters) { * }))); * * - * @param Generator $gen The generator that creates the values. - * @param callable $f The predicate function that must be satisfied. + * @param Generator $gen the generator that creates the values + * @param callable $f the predicate function that must be satisfied * - * @return Generator */ function suchThat(Generator $gen, callable $f): Generator { @@ -1001,10 +980,9 @@ function (Random $r, $n) use ($gen, $f) { * }))); * * - * @param Generator $gen The generator that creates the values. - * @param callable $f The map function. + * @param Generator $gen the generator that creates the values + * @param callable $f the map function * - * @return Generator */ function suchThatMap(Generator $gen, callable $f): Generator { @@ -1042,10 +1020,9 @@ function (Random $r) use ($gen, $f) { * }))); * * - * @param Generator $gen The generator that creates the values. - * @param callable $f The predicate function that must be satisfied. + * @param Generator $gen the generator that creates the values + * @param callable $f the predicate function that must be satisfied * - * @return Generator */ function suchThatMaybe(Generator $gen, callable $f): Generator { @@ -1082,7 +1059,6 @@ function (Random $r, $n) use ($try) { * var_dump(generate(timezones())); * * - * @return Generator */ function timezones(): Generator { @@ -1111,10 +1087,10 @@ function (Random $r) use ($positions, $zones) { * * var_dump(sample(variant("123", strings(ascii())))); * - * @param string $seed The seed to be used by the generator. - * @param Generator $gen The generator to be seeded. * - * @return Generator + * @param string $seed the seed to be used by the generator + * @param Generator $gen the generator to be seeded + * */ function variant(string $seed, Generator $gen): Generator { @@ -1138,10 +1114,9 @@ function () use ($seed, $gen) { * var_dump(generate(vectorOf(5, choose(0, 10)))); * * - * @param int $n The length of the list to be generated. - * @param Generator $gen The generator that produces the values. + * @param int $n the length of the list to be generated + * @param Generator $gen the generator that produces the values * - * @return Generator */ function vectorOf(int $n, Generator $gen): Generator { diff --git a/src/helpers.php b/src/helpers.php index 96de7a8..6792191 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -33,7 +33,6 @@ * @param null|callable $f Callable to create the dependency. If this is null, the dependency is returned. * @nodocs * - * @return mixed */ function app($name, callable $f = null) { @@ -54,7 +53,7 @@ function app($name, callable $f = null) * Normalize the args coming back from a yield inside * the generator. * - * @param mixed $args Arguments received from a yield call. + * @param mixed $args arguments received from a yield call * @nodocs * * @return array @@ -90,10 +89,9 @@ function checkArgs($args) * * * @param string $expression PHP string expression to be evaluated. Must not include semi-colon. - * @param array $args Local arguments defined while the expression is evaluated. + * @param array $args local arguments defined while the expression is evaluated * @nodocs * - * @return mixed */ function evalWithArgs(string $expression, $args = []) { @@ -118,11 +116,7 @@ function evalWithArgs(string $expression, $args = []) * // Generate an ASCII string. * echo generate(strings(ascii())) . "\n"; * - * @param Generator $gen - * @param null|Random $r - * @param null|int $n * - * @return mixed */ function generate( Generator $gen, @@ -134,6 +128,8 @@ function generate( /** * @nodocs + * + * @param null|mixed $values */ function logExecution($subject, $method, $values = null): void { @@ -204,9 +200,8 @@ function logExecution($subject, $method, $values = null): void * var_dump(sample($genB)); * * - * @param callable $f A callable function that returns a value, should accept (Random $r = null, int $n = null), and should pass $r into any generate calls within its body. + * @param callable $f a callable function that returns a value, should accept (Random $r = null, int $n = null), and should pass $r into any generate calls within its body * - * @return Generator */ function makeGen(callable $f): Generator { @@ -261,19 +256,19 @@ function quickCheck(callable $f, $output = null): void if (null === $output) { $stdout = true; - $output = fopen('php://temp', 'w'); + $output = \fopen('php://temp', 'w'); } - $args = new Args(); + $args = new Args(); $args->subject = $f; - $args->output = new StreamOutput($output); + $args->output = new StreamOutput($output); app('runner')->execute($args); if ($stdout) { - rewind($output); - echo stream_get_contents($output); - fclose($output); + \rewind($output); + print \stream_get_contents($output); + \fclose($output); } } @@ -292,7 +287,7 @@ function quickCheck(callable $f, $output = null): void * var_dump(repr(new DateTime())); * * - * @param mixed $value The value to represent. + * @param mixed $value the value to represent * @nodocs * * @return string @@ -307,11 +302,11 @@ function repr($value) return '"' . $value . '"'; } - if ($value === PHP_INT_MIN) { + if ($value === \PHP_INT_MIN) { return 'PHP_INT_MIN'; } - if ($value === PHP_INT_MAX) { + if ($value === \PHP_INT_MAX) { return 'PHP_INT_MAX'; } @@ -357,9 +352,8 @@ function ($key) use ($value) { * var_dump(sample(strings(ascii()))); * * - * @param Generator $gen The generator that creates the values. + * @param Generator $gen the generator that creates the values * - * @return array */ function sample(Generator $gen): array {