Skip to content

Commit

Permalink
Merge branch 'fix-infinite-shrinking' into develop
Browse files Browse the repository at this point in the history
* fix-infinite-shrinking:
  bounce between first and second values when shrinking a composite
  • Loading branch information
Baptouuuu committed Jan 23, 2021
2 parents 873bd5a + b699be3 commit c4839f7
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 16 deletions.
55 changes: 43 additions & 12 deletions src/Set/Composite/Combination.php
Expand Up @@ -55,27 +55,58 @@ public function shrinkable(): bool
*/
public function shrink(): array
{
/** @var list<Value> */
$strategyA = [];
/** @var list<Value> */
$strategyB = [];
return ['a' => $this->shrinkFirst(), 'b' => $this->shrinkSecond()];
}

/**
* @param 'a'|'b' $strategy
*/
private function shrinkFirst(string $strategy = 'a'): self
{
$values = [];
$foundOne = false;

foreach ($this->values as $value) {
if (!$foundOne && $value->shrinkable()) {
$strategyA[] = $value->shrink()->a();
$strategyB[] = $value->shrink()->b();
/** @var Value */
$values[] = $value->shrink()->{$strategy}();
$foundOne = true;
} else {
$strategyA[] = $value;
$strategyB[] = $value;
$values[] = $value;
}
}

return self::of(...\array_reverse($values));
}

/**
* Will try to shrink the second value that can be shrunk
*
* It will fallback to shrinking the first one with the "b" strategy if
* there is only one shrinkable value
*/
private function shrinkSecond(): self
{
$values = [];
$found = 0;

foreach ($this->values as $value) {
if ($value->shrinkable()) {
$found++;
}

if ($found === 2 && $value->shrinkable()) {
$values[] = $value->shrink()->a();
} else {
$values[] = $value;
}
}

return [
'a' => self::of(...\array_reverse($strategyA)),
'b' => self::of(...\array_reverse($strategyB)),
];
if ($found >= 2) {
return self::of(...\array_reverse($values));
}

return $this->shrinkFirst('b');
}

private static function of(Value $value, Value ...$values): self
Expand Down
8 changes: 4 additions & 4 deletions tests/Set/Composite/CombinationTest.php
Expand Up @@ -62,7 +62,7 @@ public function testCombinationIsShrinkableAsLongAsAtLeastOneValueIsShrinkable()
$this->assertTrue($shrinkable->shrinkable());
}

public function testShrinkUsesTheFirstValueThatIsShrinkableToBuildItsOwnDichotomy()
public function testShrinkUsesFirstTwoValuesThatAreShrinkableToBuildItsOwnDichotomy()
{
$combination = new Combination(Value::immutable(
66,
Expand Down Expand Up @@ -91,7 +91,7 @@ public function testShrinkUsesTheFirstValueThatIsShrinkableToBuildItsOwnDichotom
$shrinked['a']->unwrap(),
);
$this->assertSame(
[42, 23, 66],
[42, 24, 33],
$shrinked['b']->unwrap(),
);
$this->assertSame(
Expand All @@ -103,11 +103,11 @@ public function testShrinkUsesTheFirstValueThatIsShrinkableToBuildItsOwnDichotom
$shrinked['a']->shrink()['b']->unwrap(),
);
$this->assertSame(
[42, 23, 65],
[42, 23, 33],
$shrinked['b']->shrink()['b']->unwrap(),
);
$this->assertSame(
[42, 23, 33],
[42, 12, 33],
$shrinked['b']->shrink()['a']->unwrap(),
);
}
Expand Down
31 changes: 31 additions & 0 deletions tests/Set/CompositeTest.php
Expand Up @@ -10,11 +10,15 @@
Set,
Set\Value,
Random\MtRand,
PHPUnit\BlackBox,
Exception\EmptySet,
};
use PHPUnit\Framework\ExpectationFailedException;

class CompositeTest extends TestCase
{
use BlackBox;

private $set;

public function setUp(): void
Expand Down Expand Up @@ -352,4 +356,31 @@ public function testThrowWhenUnableToGenerateValues()
->values(new MtRand)
->current();
}

/**
* This test is here to help fix the problem described in the issue linked below
*
* @see https://github.com/Innmind/BlackBox/issues/6
*/
public function testShrinksAsFastAsPossible()
{
try {
$this
->forAll(Set\Integers::below(0), Set\Integers::above(0))
->filter(fn($a, $b) => $a !== 0)
->then(function($a, $b) {
$this->assertGreaterThanOrEqual(
0,
$a + $b,
"[$a,$b]",
);
});
$this->fail('The assertion should fail');
} catch (ExpectationFailedException $e) {
$this->assertStringContainsString(
'[-1,0]',
$e->getMessage(),
);
}
}
}

0 comments on commit c4839f7

Please sign in to comment.