The input usually comes from another Generator.
public static fromValueAndInput ( T $value, |
||
$value | T | |
$input | ||
$generatorName | string | 'tuple' |
return |
public function shrink(GeneratedValue $element) { if (!$this->contains($element)) { throw new DomainException(var_export($element, true) . ' is not in one of the given domains'); } $input = $element->input(); $originalGeneratorIndex = $input['generator']; $shrinkedValue = $this->generators[$originalGeneratorIndex]['generator']->shrink($input['value']); return GeneratedValue::fromValueAndInput($shrinkedValue->unbox(), ['value' => $shrinkedValue, 'generator' => $originalGeneratorIndex], 'frequency'); }
private function shrinkInSize($sequence) { if (count($sequence->unbox()) === 0) { return $sequence; } $input = $sequence->input(); $indexOfElementToRemove = array_rand($input); unset($input[$indexOfElementToRemove]); $input = array_values($input); return GeneratedValue::fromValueAndInput(array_map(function ($element) { return $element->unbox(); }, $input), $input, 'sequence'); }
public function shrink(GeneratedValue $set) { // TODO: extract duplication with Generator\SequenceGenerator // to do so, implement __toString for every Generator (put it // in the interface) and then Extract Class // ContainmentCheck::of($this)->on($set); // which will use $generator->__toString() in the error message if (!$this->contains($set)) { throw new DomainException('Cannot shrink {' . var_export($set, true) . '} because ' . 'it does not belong to the domain of this set'); } if (count($set->input()) === 0) { return $set; } $input = $set->input(); // TODO: make deterministic $indexOfElementToRemove = array_rand($input); unset($input[$indexOfElementToRemove]); $input = array_values($input); return GeneratedValue::fromValueAndInput(array_map(function ($element) { return $element->unbox(); }, $input), array_values($input), 'set'); }
public function shrink(GeneratedValue $tuple) { $this->checkValueToShrink($tuple); $input = $tuple->input(); // TODO: make deterministic if (count($input) > 0) { $attemptsToShrink = 10; $numberOfElementsToShrink = rand(1, max(floor($this->numberOfGenerators / 2), 1)); while ($numberOfElementsToShrink > 0 && $attemptsToShrink > 0) { $indexOfElementToShrink = rand(0, $this->numberOfGenerators - 1); $shrinkedValue = $this->generators[$indexOfElementToShrink]->shrink($input[$indexOfElementToShrink]); if ($shrinkedValue === $input[$indexOfElementToShrink]) { $attemptsToShrink--; continue; } $numberOfElementsToShrink--; $input[$indexOfElementToShrink] = $shrinkedValue; } } return GeneratedValue::fromValueAndInput(array_map(function ($element) { return $element->unbox(); }, $input), $input, 'tuple'); }
private function packageGeneratedValue($outerGeneratorValue, $innerGeneratorValue) { return GeneratedValue::fromValueAndInput($outerGeneratorValue->unbox(), [$outerGeneratorValue, $innerGeneratorValue], 'bind'); }
public function __invoke(callable $assertion) { $sizes = Size::withTriangleGrowth($this->maxSize)->limit($this->iterations); try { $redTestException = null; $this->notifyListeners('startPropertyVerification'); for ($iteration = 0; $iteration < $this->iterations && !$this->terminationConditionsAreSatisfied(); $iteration++) { $generatedValues = []; $values = []; foreach ($this->generators as $name => $generator) { $value = $generator($sizes->at($iteration), $this->rand); if (!$value instanceof GeneratedValue) { throw new RuntimeException("The value returned by a generator should be an instance of GeneratedValue, but it is " . var_export($value, true)); } $generatedValues[] = $value; $values[] = $value->unbox(); } $generation = GeneratedValue::fromValueAndInput($values, $generatedValues, 'tuple'); $this->notifyListeners('newGeneration', $generation->unbox(), $iteration); if (!$this->antecedentsAreSatisfied($values)) { continue; } $this->ordinaryEvaluations++; Evaluation::of($assertion)->with($generation)->onFailure(function ($generatedValues, $exception) use($assertion) { $this->notifyListeners('failure', $generatedValues->unbox(), $exception); if (!$this->shrinkingEnabled) { throw $exception; } $shrinking = $this->shrinkerFactory->random($this->generators, $assertion); // MAYBE: put into ShrinkerFactory? $shrinking->addGoodShrinkCondition(function (GeneratedValue $generatedValues) { return $this->antecedentsAreSatisfied($generatedValues->unbox()); })->onAttempt(function (GeneratedValue $generatedValues) { $this->notifyListeners('shrinking', $generatedValues->unbox()); })->from($generatedValues, $exception); })->execute(); } } catch (Exception $e) { $redTestException = $e; $wrap = (bool) getenv('ERIS_ORIGINAL_INPUT'); if ($wrap) { $message = "Original input: " . var_export($values, true) . PHP_EOL . "Possibly shrinked input follows." . PHP_EOL; throw new RuntimeException($message, -1, $e); } else { throw $e; } } finally { $this->notifyListeners('endPropertyVerification', $this->ordinaryEvaluations, $this->iterations, $redTestException); } }