Skip to content
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
74 changes: 60 additions & 14 deletions src/Internal/CacheManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static function reset(): void
}

/**
* Returns the absolute path to the cache directory, isolating by system user if using temp dir.
* Returns the absolute path to the cache directory, isolating by system user and parallel test worker if using temp dir.
*/
public static function getCacheDir(): string
{
Expand Down Expand Up @@ -55,7 +55,20 @@ public static function getCacheDir(): string
$user = (string) getmyuid();
}

$userHash = hash('xxh128', 'typephp_' . $user);
$testToken = getenv('TEST_TOKEN');
$uniqueToken = getenv('UNIQUE_TEST_TOKEN');
$pestWorkerId = getenv('PEST_PARALLEL_WORKER_ID');

$workerToken = '0';
if (\is_string($testToken) && $testToken !== '') {
$workerToken = $testToken;
} elseif (\is_string($uniqueToken) && $uniqueToken !== '') {
$workerToken = $uniqueToken;
} elseif (\is_string($pestWorkerId) && $pestWorkerId !== '') {
$workerToken = $pestWorkerId;
}

$userHash = hash('xxh128', 'typephp_' . $user . '_w' . $workerToken);

return self::$resolvedCacheDir = sys_get_temp_dir() . '/typephp-cache-' . $userHash;
}
Expand Down Expand Up @@ -135,26 +148,59 @@ public static function writeCachedFileSafely(string $cachedFile, string $transfo
}

/**
* Clears all cached transformed files from the cache directory.
* Clears all cached transformed files from the cache directory,
* including all parallel worker directories (_w1, _w2, etc.).
*/
public static function clear(): int
{
$cacheDir = self::getCacheDir();
$config = Config::get();
$customDir = $config['cache_dir'] ?? null;

if (! is_dir($cacheDir) || is_link($cacheDir)) {
return 0;
}
$dirsToClear = [];

$files = glob($cacheDir . '/*.php');
if ($files === false || \count($files) === 0) {
return 0;
if (\is_string($customDir) && $customDir !== '') {
if (is_dir($customDir) && ! is_link($customDir)) {
$dirsToClear[] = $customDir;
}
} else {
$tempBase = sys_get_temp_dir();
$matchedDirs = glob($tempBase . '/typephp-cache-*');

if ($matchedDirs !== false) {
foreach ($matchedDirs as $d) {
if (is_dir($d) && ! is_link($d)) {
if (\function_exists('posix_geteuid')) {
$owner = @fileowner($d);
if ($owner !== false && $owner !== posix_geteuid()) {
continue;
}
}
$dirsToClear[] = $d;
}
}
}
}

$count = 0;
foreach ($files as $file) {
if (is_file($file) && ! is_link($file)) {
@unlink($file);
$count++;
foreach ($dirsToClear as $dir) {
$files = glob($dir . '/*.php');
if ($files !== false) {
foreach ($files as $file) {
if (is_file($file) && ! is_link($file)) {
@unlink($file);
$count++;
}
}
}

// Also clean up any lingering temporary swap files
$tmpFiles = glob($dir . '/.tmp_*');
if ($tmpFiles !== false) {
foreach ($tmpFiles as $tFile) {
if (is_file($tFile) && ! is_link($tFile)) {
@unlink($tFile);
}
}
}
}

Expand Down
22 changes: 21 additions & 1 deletion src/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
$isDisabledConst = \defined('TYPEPHP_DISABLE') && TYPEPHP_DISABLE;

$isTooling = false;
$binary = '';

if (isset($_SERVER['argv']) && \is_array($_SERVER['argv']) && \count($_SERVER['argv']) > 0) {
$candidate = $_SERVER['argv'][0];
Expand All @@ -36,13 +37,32 @@
'composer' => true,
'deptrac' => true,
'phan' => true,
'paratest' => true,
];

$isTooling = isset($toolingBinaries[$binary]);
}
}

if (! $isDisabledEnv && ! $isDisabledConst && ! $isTooling) {
$isParallelParent = false;
if (isset($_SERVER['argv']) && \is_array($_SERVER['argv'])) {
$hasParallelArg = false;
foreach ($_SERVER['argv'] as $arg) {
if (\is_string($arg) && (str_starts_with($arg, '--parallel') || $arg === '-p' || str_starts_with($arg, '--processes'))) {
$hasParallelArg = true;

break;
}
}

$isParallelParent = ($binary === 'paratest') || ($binary === 'pest' && $hasParallelArg);

if (getenv('TEST_TOKEN') !== false || getenv('PARATEST') !== false || getenv('PEST_PARALLEL_WORKER_ID') !== false) {
$isParallelParent = false;
}
}

if (! $isDisabledEnv && ! $isDisabledConst && ! $isTooling && ! $isParallelParent) {
TypePHP::boot();
}
}
3 changes: 2 additions & 1 deletion tests/TypeChecking/ArraysAndShapes/KeyOfValueOfTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ function testKeylessTupleKeyOf(int $index): int
expect($conn->localAction(['action' => 'start']))->toBeTrue();

expect(fn () => $conn->localAction(['action' => 'pause']))
->toThrow(TypeError::class, "['action'] must be a key of TypePHP\Tests\Fixtures\Types\DoctrineLikeConnection::LOCAL_ACTIONS");
->toThrow(TypeError::class, "['action'] must be a key of TypePHP\Tests\Fixtures\Types\DoctrineLikeConnection::LOCAL_ACTIONS")
;
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ public function formatValue(bool $asInt, mixed $value): mixed
expect($service->formatByNegation(true, 100))->toBe(100);

expect(fn () => $service->formatByNegation(true, -50))
->toThrow(TypeError::class, 'Return value must be of type positive-int');
->toThrow(TypeError::class, 'Return value must be of type positive-int')
;
});
});
});
3 changes: 2 additions & 1 deletion tests/TypeChecking/Scalars/ClassStringInterfaceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ public function count(): int
expect(testTemplateWithIntersectionBoundClassString(ArrayObject::class))->toBe(ArrayObject::class);

expect(fn () => testTemplateWithIntersectionBoundClassString(stdClass::class))
->toThrow(TypeError::class, 'must be a class-string of');
->toThrow(TypeError::class, 'must be a class-string of')
;
});
});
Loading