Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix mutations + math float tests #427

Merged
merged 1 commit into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 44 additions & 2 deletions config/infection.json.dist
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,48 @@
}
},
"timeout": 10,
"minMsi": 98,
"minCoveredMsi": 100
"minMsi": 100,
"minCoveredMsi": 100,
"mutators": {
"@default": true,
"Break_": {
"ignore": [
"Psl\\Collection\\*Map::zip"
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the break gets transformed into a continue, it will produce the same output - yet slower.
So this is a false positive:

$u = $elements[0] ?? null;
if (null === $u) {
break;

]
},
"DecrementInteger": {
"ignore": [
"Psl\\DataStructure\\PriorityQueue::peek"
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fallback to ?? 0 will never occur since we first check the array size.
This is a false positive:

$priority = Math\max($keys) ?? 0;

I could solve it by doing an additional invariant check, but this seems slower for no real reason.

]
},
"FunctionCallRemoval": {
"ignore": [
"Psl\\Result\\Success::getThrowable"
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is actually covered - yet infection doesnt seem to be able to link the test to the mutation.

See

public function testGetException(): void
{
$wrapper = new Success('hello');
$this->expectException(InvariantViolationException::class);
$this->expectExceptionMessage('No exception thrown');
$wrapper->getThrowable();
}

]
},
"IncrementInteger": {
"ignore": [
"Psl\\DataStructure\\PriorityQueue::peek"
]
},
"LogicalNot": {
"ignore": [
"Psl\\Hash\\Context::update"
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard to cover this one:

// @codeCoverageIgnoreStart
/** @psalm-suppress ImpureFunctionCall - it creates a copy of the context, so we can consider it pure! */
if (!hash_update($internal_context, $data)) {
throw new Exception\RuntimeException('Unable to pump data into the active hashing context.');
}
// @codeCoverageIgnoreEnd

(the code coverage was already added as well.)

]
},
"MethodCallRemoval": {
"ignore": [
"Psl\\Iter\\Iterator::seek",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These functions were added to speed up the tests : it results in time-outs cause the iterator does not iterate anymore because it removes:

$this->next();

"Psl\\Iter\\Iterator::count"
]
},
"Throw_": {
"ignore": [
"Psl\\File\\ReadHandle::__construct",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added some tests as well - but didnt want to go into chmodding files and testing for readability / writability at this moment.

See

if (!Filesystem\exists($file)) {
throw Exception\NotFoundException::for($file);
}
if (!Filesystem\is_file($file)) {
throw Exception\NotFileException::for($file);
}
if (!Filesystem\is_readable($file)) {
throw Exception\NotReadableException::for($file);
}

"Psl\\File\\WriteHandle::__construct",
"Psl\\File\\ReadWriteHandle::__construct",
"Psl\\Hash\\Context::update"
]
}
}
}
1 change: 1 addition & 0 deletions config/phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
</coverage>
<php>
<ini name="error_reporting" value="-1" />
<ini name="precision" value="16" />
</php>
<testsuites>
<testsuite name="PHP Standard Library">
Expand Down
2 changes: 1 addition & 1 deletion src/Psl/Collection/MutableMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ public function get(string|int $k): mixed
*/
public function values(): MutableVector
{
return MutableVector::fromArray(array_values($this->elements));
return MutableVector::fromArray($this->elements);
}

/**
Expand Down
7 changes: 7 additions & 0 deletions tests/unit/Collection/AbstractMapTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,13 @@ public function testZip(): void
static::assertCount(2, $zipped);
static::assertSame(['hello', 'foo'], $zipped->at(1));
static::assertSame(['world', 'bar'], $zipped->at(2));

$map = $this->create([1 => 'hello', 2 => 'world']);
$zipped = $map->zip(['foo' => 'foo', 'bar' => 'bar']);
static::assertInstanceOf($this->mapClass, $zipped);
static::assertCount(2, $zipped);
static::assertSame(['hello', 'foo'], $zipped->at(1));
static::assertSame(['world', 'bar'], $zipped->at(2));
}

public function testTake(): void
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/Collection/MapTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ final class MapTest extends AbstractMapTest
*/
protected function create(iterable $items): Map
{
return new Map($items);
return Map::fromArray($items);
}
}
2 changes: 1 addition & 1 deletion tests/unit/Collection/MutableMapTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,6 @@ public function testRemove(): void
*/
protected function create(iterable $items): MutableMap
{
return new MutableMap($items);
return MutableMap::fromArray($items);
}
}
18 changes: 18 additions & 0 deletions tests/unit/DataStructure/PriorityQueueTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,24 @@ public function testEnqueueAndDequeue(): void
static::assertSame('hi', $queue->dequeue());
}

public function testDefaultEnqueueSettings(): void
{
$queue = new DataStructure\PriorityQueue();
$queue->enqueue('hey');
$queue->enqueue('ho', 0);
$queue->enqueue('hi', -1);
$queue->enqueue('hello', 1);

static::assertCount(4, $queue);
static::assertSame('hello', $queue->dequeue());
static::assertCount(3, $queue);
static::assertSame('hey', $queue->dequeue());
static::assertCount(2, $queue);
static::assertSame('ho', $queue->dequeue());
static::assertCount(1, $queue);
static::assertSame('hi', $queue->dequeue());
}

public function testMultipleNodesWithSamePriority(): void
{
$queue = new DataStructure\PriorityQueue();
Expand Down
9 changes: 9 additions & 0 deletions tests/unit/File/ReadHandleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,13 @@ public function testNonExisting(): void
$this->expectException(File\Exception\NotFoundException::class);
File\open_read_only($temporary_file);
}

public function testNonFile(): void
{
$temporary_file = Filesystem\create_temporary_file();
Filesystem\delete_file($temporary_file);

$this->expectException(File\Exception\NotFileException::class);
File\open_read_only(dirname($temporary_file));
}
}
4 changes: 3 additions & 1 deletion tests/unit/Math/AcosTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@

final class AcosTest extends TestCase
{
use FloatAsserts;

/**
* @dataProvider provideData
*/
public function testAcos(float $expected, float $number): void
{
static::assertSame($expected, Math\acos($number));
static::assertFloatEquals($expected, Math\acos($number));
}

public function provideData(): array
Expand Down
4 changes: 3 additions & 1 deletion tests/unit/Math/AsinTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@

final class AsinTest extends TestCase
{
use FloatAsserts;

/**
* @dataProvider provideData
*/
public function testAsin(float $expected, float $number): void
{
static::assertSame($expected, Math\asin($number));
static::assertFloatEquals($expected, Math\asin($number));
}

public function provideData(): array
Expand Down
4 changes: 3 additions & 1 deletion tests/unit/Math/Atan2Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@

final class Atan2Test extends TestCase
{
use FloatAsserts;

/**
* @dataProvider provideData
*/
public function testAtan2(float $expected, float $y, float $x): void
{
static::assertSame($expected, Math\atan2($y, $x));
static::assertFloatEquals($expected, Math\atan2($y, $x));
}

public function provideData(): array
Expand Down
4 changes: 3 additions & 1 deletion tests/unit/Math/AtanTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@

final class AtanTest extends TestCase
{
use FloatAsserts;

/**
* @dataProvider provideData
*/
public function testAtan(float $expected, float $number): void
{
static::assertSame($expected, Math\atan($number));
static::assertFloatEquals($expected, Math\atan($number));
}

public function provideData(): array
Expand Down
4 changes: 3 additions & 1 deletion tests/unit/Math/CosTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@

final class CosTest extends TestCase
{
use FloatAsserts;

/**
* @dataProvider provideData
*/
public function testCos(float $expected, float $number): void
{
static::assertSame($expected, Math\cos($number));
static::assertFloatEquals($expected, Math\cos($number));
}

public function provideData(): array
Expand Down
25 changes: 25 additions & 0 deletions tests/unit/Math/FloatAsserts.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Psl\Tests\Unit\Math;

use PHPUnit\Framework\TestCase;
use Psl\Math;

trait FloatAsserts
{
/**
* Because not all systems have the same rounding rules and precisions,
* This method provides an assertion to compare floats based on epsilon:.
*
* @see https://www.php.net/manual/en/language.types.float.php#language.types.float.comparison
*/
public static function assertFloatEquals(float $a, float $b, float $epsilon = PHP_FLOAT_EPSILON): void
{
TestCase::assertTrue(
Math\abs($a - $b) <= $epsilon,
'Failed asserting that float ' . $a . ' is equal to ' . $b . '.'
);
}
}
4 changes: 3 additions & 1 deletion tests/unit/Math/SinTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@

final class SinTest extends TestCase
{
use FloatAsserts;

/**
* @dataProvider provideData
*/
public function testSin(float $expected, float $number): void
{
static::assertSame($expected, Math\sin($number));
static::assertFloatEquals($expected, Math\sin($number));
}

public function provideData(): array
Expand Down
9 changes: 6 additions & 3 deletions tests/unit/Math/TanTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,23 @@

final class TanTest extends TestCase
{
use FloatAsserts;

/**
* @dataProvider provideData
*/
public function testTan(float $expected, float $number): void
public function testTan(float $expected, float $number, float $epsilon = PHP_FLOAT_EPSILON): void
{
static::assertSame($expected, Math\tan($number));
static::assertFloatEquals($expected, Math\tan($number), $epsilon);
}

public function provideData(): array
{
return [
[
-3.380515006246586,
5.0
5.0,
0.00000000000001
Copy link
Collaborator Author

@veewee veewee Oct 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is off by one on my system for some odd reason. Therefor I decided to check only the first 14 digits

],

[
Expand Down