[Windows] Add platform agnostic asserts (#461)

* introduce PlatformAgnosticAssertions which handle cross platform issues

* Update packages-tests/FileFormatter/ValueObject/NewLineTest.php

* apply PlatformAgnosticAssertions on MoveValueObjectsToValueObjectDirectoryRectorTest

* use PlatformAgnosticAssertions in AbstractTestCase

* Github Actions: run tests on windows-latest and ubuntu-latest

* added PlatformAgnosticAssertions::assertStringEqualsFile()

* Ensure tests manually tear down props (#1)

* check for windows or linux line ending. \n is contained in both.

* support assertFileEquals() normalizing

* add OS to name, to separate

* fixed windows compat in VendorLocationDetector

* ParentClassMethodTypeOverrideGuard: fixed windows-compat

* ClassMethodParamVendorLockResolver: windows compat

* Docs

* Update PlatformAgnosticAssertions.php

* Delete tests.yaml

* Create tests.yaml

Co-authored-by: Markus Staab <m.staab@complex-it.de>
Co-authored-by: Markus Staab <maggus.staab@googlemail.com>
Co-authored-by: Markus Staab <markus.staab@redaxo.de>
Co-authored-by: Dan <dpock32509@gmail.com>
This commit is contained in:
Tomas Votruba 2021-08-16 09:08:51 +02:00 committed by GitHub
parent cdf9dc5c68
commit 6cdfebe40c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 126 additions and 10 deletions

View File

@ -5,12 +5,12 @@ declare(strict_types=1);
namespace Rector\Tests\FileFormatter\ValueObject;
use Iterator;
use PHPUnit\Framework\TestCase;
use Rector\FileFormatter\Exception\InvalidNewLineStringException;
use Rector\FileFormatter\ValueObject\NewLine;
use Rector\Testing\PHPUnit\AbstractTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;
final class NewLineTest extends TestCase
final class NewLineTest extends AbstractTestCase
{
/**
* @dataProvider extractFromFiles

View File

@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Rector\Testing\PHPUnit;
use Iterator;
use Nette\Utils\Strings;
use PHPStan\Analyser\NodeScopeResolver;
use PHPUnit\Framework\ExpectationFailedException;
use Psr\Container\ContainerInterface;
@ -74,6 +73,19 @@ abstract class AbstractRectorTestCase extends AbstractTestCase implements Rector
$bootstrapFilesIncluder->includeBootstrapFiles();
}
protected function tearDown(): void
{
// free memory and trigger gc to reduce memory peak consumption on windows
unset(
$this->applicationFileProcessor,
$this->parameterProvider,
$this->dynamicSourceLocatorProvider,
$this->removedAndAddedFilesCollector,
$this->originalTempFileInfo,
);
gc_collect_cycles();
}
/**
* @return Iterator<SmartFileInfo>
*/
@ -142,7 +154,7 @@ abstract class AbstractRectorTestCase extends AbstractTestCase implements Rector
private function normalizeNewlines(string $string): string
{
return Strings::replace($string, '#\r\n|\r|\n#', "\n");
return str_replace("\r\n", "\n", $string);
}
private function processFileInfo(SmartFileInfo $fileInfo): string

View File

@ -12,6 +12,8 @@ use Symplify\SmartFileSystem\SmartFileInfo;
abstract class AbstractTestCase extends TestCase
{
use PlatformAgnosticAssertions;
/**
* @var array<string, RectorKernel>
*/

View File

@ -0,0 +1,83 @@
<?php
declare(strict_types=1);
namespace Rector\Testing\PHPUnit;
use Nette\Utils\FileSystem;
use PHPUnit\Framework\Constraint\IsEqual;
/**
* Relaxes phpunit assertions to be forgiving about platform issues, like directory-separators or newlines.
* Mostly required to make assertion work on Windows.
*/
trait PlatformAgnosticAssertions
{
/**
* Asserts that two variables have the same type and value.
* Used on objects, it asserts that two variables reference
* the same object.
*
* @psalm-template ExpectedType
* @psalm-param ExpectedType $expected
* @psalm-assert =ExpectedType $actual
*/
public static function assertSame($expected, $actual, string $message = ''): void
{
if (is_string($expected)) {
$expected = self::normalize($expected);
}
if (is_string($actual)) {
$actual = self::normalize($actual);
}
parent::assertSame($expected, $actual, $message);
}
/**
* Asserts that the contents of a string is equal
* to the contents of a file.
*/
public static function assertStringEqualsFile(
string $expectedFile,
string $actualString,
string $message = ''
): void {
parent::assertFileExists($expectedFile, $message);
$expectedString = self::getNormalizedFileContents($expectedFile);
$isEqual = new IsEqual($expectedString);
$actualString = self::normalize($actualString);
parent::assertThat($actualString, $isEqual, $message);
}
/**
* Asserts that the contents of one file is equal to the contents of another
* file.
*/
public static function assertFileEquals(string $expected, string $actual, string $message = ''): void
{
static::assertFileExists($expected, $message);
static::assertFileExists($actual, $message);
$isEqual = new IsEqual(self::getNormalizedFileContents($expected));
static::assertThat(self::getNormalizedFileContents($actual), $isEqual, $message);
}
private static function normalize(string $string): array | string
{
$string = str_replace("\r\n", "\n", $string);
return str_replace(DIRECTORY_SEPARATOR, '/', $string);
}
private static function getNormalizedFileContents(string $filePath): string
{
$expectedString = FileSystem::read($filePath);
return self::normalize($expectedString);
}
}

View File

@ -63,7 +63,7 @@ final class ClassMethodParamVendorLockResolver
continue;
}
$normalizedFileName = $this->pathNormalizer->normalizePath($fileName);
$normalizedFileName = $this->pathNormalizer->normalizePath($fileName, '/');
return str_contains($normalizedFileName, '/vendor/');
}

View File

@ -8,6 +8,9 @@ use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;
/**
* Minor differences on windows, see https://github.com/rectorphp/rector/issues/6571
*/
final class SensitiveHereNowDocRectorTest extends AbstractRectorTestCase
{
/**

View File

@ -23,6 +23,11 @@ final class TypeNormalizerTest extends AbstractTestCase
$this->typeNormalizer = $this->getService(TypeNormalizer::class);
}
protected function tearDown(): void
{
unset($this->typeNormalizer);
}
/**
* @dataProvider provideDataNormalizeArrayOfUnionToUnionArray()
*/

View File

@ -152,7 +152,8 @@ CODE_SAMPLE
return new Concat($argumentVariables[0], $argumentVariables[1]);
}
if (\str_contains($string, PHP_EOL)) {
// checks for windows or linux line ending. \n is contained in both.
if (\str_contains($string, "\n")) {
return null;
}

View File

@ -27,7 +27,7 @@ final class VendorLocationDetector
return false;
}
$normalizedFileName = $this->pathNormalizer->normalizePath($fileName);
$normalizedFileName = $this->pathNormalizer->normalizePath($fileName, '/');
return str_contains($normalizedFileName, '/vendor/');
}

View File

@ -11,12 +11,14 @@ use PHPStan\Reflection\MethodReflection;
use Rector\CodingStyle\Reflection\VendorLocationDetector;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Symplify\SmartFileSystem\Normalizer\PathNormalizer;
final class ParentClassMethodTypeOverrideGuard
{
public function __construct(
private NodeNameResolver $nodeNameResolver,
private VendorLocationDetector $vendorLocationDetector
private VendorLocationDetector $vendorLocationDetector,
private PathNormalizer $pathNormalizer
) {
}
@ -69,7 +71,8 @@ final class ParentClassMethodTypeOverrideGuard
return false;
}
return ! str_contains($fileName, '/vendor/');
$normalizedFileName = $this->pathNormalizer->normalizePath($fileName, '/');
return ! str_contains($normalizedFileName, '/vendor/');
}
public function hasParentClassMethod(ClassMethod $classMethod): bool

View File

@ -161,7 +161,7 @@ final class FileRelocationResolver
): string {
// A. first "dir has changed" dummy detection
$relativeFilePathParts = Strings::split(
$oldSmartFileInfo->getRelativeFilePath(),
$this->normalizeDirectorySeparator($oldSmartFileInfo->getRelativeFilePath()),
// the windows dir separator would be interpreted as a regex-escape char, therefore quote it.
'#' . preg_quote(DIRECTORY_SEPARATOR, '#') . '#'
);
@ -179,4 +179,9 @@ final class FileRelocationResolver
return implode(DIRECTORY_SEPARATOR, $relativeFilePathParts);
}
private function normalizeDirectorySeparator(string $path): string
{
return str_replace('/', DIRECTORY_SEPARATOR, $path);
}
}

View File

@ -34,6 +34,8 @@ final class ClassWithPublicPropertiesFactoryTest extends AbstractTestCase
public function test(SmartFileInfo $fixtureFileInfo): void
{
$contents = $fixtureFileInfo->getContents();
// normalize for windows compat
$contents = str_replace("\r\n", "\n", $contents);
[$content, $expected] = explode("-----\n", $contents, 2);
$classSettings = Json::decode($content, Json::FORCE_ARRAY);