diff --git a/composer.json b/composer.json index 4706870..725fedc 100644 --- a/composer.json +++ b/composer.json @@ -24,13 +24,13 @@ "bin/roave-no-leaks" ], "require-dev": { - "doctrine/coding-standard": "^5.0", + "doctrine/coding-standard": "^6.0.0", "infection/infection": "^0.12.2", "phpstan/phpstan": "^0.11.4", "phpstan/phpstan-phpunit": "^0.11.0", "phpstan/phpstan-strict-rules": "^0.11.0", "psalm/plugin-phpunit": "^0.5.3", - "squizlabs/php_codesniffer": "^3.4", - "vimeo/psalm": "^3.2" + "squizlabs/php_codesniffer": "^3.4.1", + "vimeo/psalm": "^3.2.2" } } diff --git a/src/CollectTestExecutionMemoryFootprints.php b/src/CollectTestExecutionMemoryFootprints.php index 6be3e33..4217900 100644 --- a/src/CollectTestExecutionMemoryFootprints.php +++ b/src/CollectTestExecutionMemoryFootprints.php @@ -5,15 +5,12 @@ namespace Roave\NoLeaks\PHPUnit; use Exception; -use PHPUnit\Framework\AssertionFailedError; -use PHPUnit\Framework\Test; use PHPUnit\Framework\TestListener; +use PHPUnit\Framework\TestListenerDefaultImplementation; use PHPUnit\Framework\TestSuite; -use PHPUnit\Framework\Warning; use PHPUnit\Runner\AfterLastTestHook; use PHPUnit\Runner\AfterSuccessfulTestHook; use PHPUnit\Runner\BeforeTestHook; -use Throwable; use function array_combine; use function array_filter; use function array_intersect_key; @@ -38,6 +35,8 @@ final class CollectTestExecutionMemoryFootprints implements AfterLastTestHook, TestListener { + use TestListenerDefaultImplementation; + /** @var array> */ private $preTestMemoryUsages = []; @@ -106,40 +105,4 @@ public function executeAfterLastTest() : void )); } } - - public function addError(Test $test, Throwable $t, float $time) : void - { - } - - public function addWarning(Test $test, Warning $e, float $time) : void - { - } - - public function addFailure(Test $test, AssertionFailedError $e, float $time) : void - { - } - - public function addIncompleteTest(Test $test, Throwable $t, float $time) : void - { - } - - public function addRiskyTest(Test $test, Throwable $t, float $time) : void - { - } - - public function addSkippedTest(Test $test, Throwable $t, float $time) : void - { - } - - public function endTestSuite(TestSuite $suite) : void - { - } - - public function startTest(Test $test) : void - { - } - - public function endTest(Test $test, float $time) : void - { - } } diff --git a/src/MeasuredBaselineTestMemoryLeak.php b/src/MeasuredBaselineTestMemoryLeak.php index cb3bfed..a5c2ad9 100644 --- a/src/MeasuredBaselineTestMemoryLeak.php +++ b/src/MeasuredBaselineTestMemoryLeak.php @@ -51,30 +51,28 @@ public static function fromBaselineTestMemoryUsages( throw new Exception('Pre- and post- baseline test run collected memory usages don\'t match in number'); } - if (count($preBaselineTestMemoryUsages) < 3) { - throw new Exception(sprintf( - 'At least 3 baseline test run memory profiles are required, %d given', - count($preBaselineTestMemoryUsages) - )); - } + $memoryUsages = array_map(static function (int $beforeRun, int $afterRun) : int { + return $afterRun - $beforeRun; + }, $preBaselineTestMemoryUsages, $postBaselineTestMemoryUsages); - $memoryUsages = array_values(array_map(static function (int $beforeRun, int $afterRun) : int { - $memoryUsage = $afterRun - $beforeRun; + // Note: profile 0 is discarded, as it may contain autoloading and other static test suite initialisation state + $relevantMemoryUsages = array_slice($memoryUsages, 1); - if ($memoryUsage < 0) { - throw new Exception(sprintf( - 'Baseline memory usage of %d detected: invalid negative memory usage', - $memoryUsage - )); + $nonNegativeMemoryUsages = array_values(array_filter( + $relevantMemoryUsages, + static function (int $memoryUsage) : bool { + return $memoryUsage >= 0; } + )); - return $memoryUsage; - }, $preBaselineTestMemoryUsages, $postBaselineTestMemoryUsages)); - - // Note: profile 0 is discarded, as it may contain autoloading and other static test suite initialisation state - $relevantMemoryUsages = array_slice($memoryUsages, 1); + if (count($nonNegativeMemoryUsages) < 2) { + throw new Exception(sprintf( + 'At least 3 baseline test run memory profiles are required, %d given', + count($nonNegativeMemoryUsages) + 1 + )); + } - if (array_filter(array_count_values($relevantMemoryUsages), static function (int $count) : bool { + if (array_filter(array_count_values($nonNegativeMemoryUsages), static function (int $count) : bool { return $count > 1; }) === []) { // @TODO good enough for detecting standard deviation for now, I guess? :| @@ -84,7 +82,7 @@ public static function fromBaselineTestMemoryUsages( )); } - return new self(...$relevantMemoryUsages); + return new self(...$nonNegativeMemoryUsages); } public function lessThan(int $testRunMemoryLeak) : bool diff --git a/test/unit/MeasuredBaselineTestMemoryLeakTest.php b/test/unit/MeasuredBaselineTestMemoryLeakTest.php index 1feb0ad..cbb682b 100644 --- a/test/unit/MeasuredBaselineTestMemoryLeakTest.php +++ b/test/unit/MeasuredBaselineTestMemoryLeakTest.php @@ -35,23 +35,45 @@ public function testRejectsHighlyInconsistentProfiles() : void ); } - public function testRejectsNegativeMemoryLeaks() : void + public function testFiltersNegativeMemoryLeaks() : void { - $this->expectExceptionMessage('Baseline memory usage of -1 detected: invalid negative memory usage'); - - MeasuredBaselineTestMemoryLeak::fromBaselineTestMemoryUsages( - [100, 50, 51], - [200, 49, 51] + self::assertEquals( + MeasuredBaselineTestMemoryLeak::fromBaselineTestMemoryUsages( + [100, 51, 52, 53], + [200, 51, 53, 54] + ), + MeasuredBaselineTestMemoryLeak::fromBaselineTestMemoryUsages( + [100, 50, 51, 51, 53], + [200, 49, 51, 52, 54] + ) ); } public function testRejectsDataSetWithTooFewMemoryLeakProfiles() : void { + $validMeasurement = MeasuredBaselineTestMemoryLeak::fromBaselineTestMemoryUsages( + [100, 50, 60], + [200, 50, 60] + ); + + self::assertTrue($validMeasurement->lessThan(1)); + self::assertFalse($validMeasurement->lessThan(0)); + $this->expectExceptionMessage('At least 3 baseline test run memory profiles are required, 2 given'); MeasuredBaselineTestMemoryLeak::fromBaselineTestMemoryUsages( [100, 50], - [200, 49] + [200, 50] + ); + } + + public function testRejectsDataSetWithTooFewValidMemoryLeakProfiles() : void + { + $this->expectExceptionMessage('At least 3 baseline test run memory profiles are required, 2 given'); + + MeasuredBaselineTestMemoryLeak::fromBaselineTestMemoryUsages( + [100, 50, 50], + [200, 50, 49] ); }