|
6 | 6 |
|
7 | 7 | use PHPUnit\Framework\TestCase; |
8 | 8 | use StaticPHP\Artifact\Artifact; |
| 9 | +use StaticPHP\Artifact\ArtifactCache; |
9 | 10 | use StaticPHP\Artifact\ArtifactDownloader; |
| 11 | +use StaticPHP\Artifact\Downloader\DownloadResult; |
10 | 12 | use StaticPHP\Config\ArtifactConfig; |
| 13 | +use StaticPHP\DI\ApplicationContext; |
| 14 | +use StaticPHP\Exception\DownloaderException; |
11 | 15 | use StaticPHP\Exception\WrongUsageException; |
12 | 16 | use StaticPHP\Registry\ArtifactLoader; |
13 | 17 |
|
@@ -337,6 +341,61 @@ public function testSetParallelAcceptsNormalValue(): void |
337 | 341 | $this->assertSame($downloader, $result); |
338 | 342 | } |
339 | 343 |
|
| 344 | + /** |
| 345 | + * @dataProvider failedFileListProvider |
| 346 | + */ |
| 347 | + public function testFailedFileListFallsBackToSourceMirror(?string $page, bool $no_alt): void |
| 348 | + { |
| 349 | + $listing = tempnam(sys_get_temp_dir(), 'spc-filelist-'); |
| 350 | + $this->assertNotFalse($listing); |
| 351 | + if ($page === null) { |
| 352 | + // A missing file URL makes curl fail without depending on the network. |
| 353 | + unlink($listing); |
| 354 | + } else { |
| 355 | + file_put_contents($listing, $page); |
| 356 | + } |
| 357 | + $artifact = new Artifact('fallback-test', [ |
| 358 | + 'source' => [ |
| 359 | + 'type' => 'filelist', |
| 360 | + 'url' => 'file://' . $listing, |
| 361 | + 'regex' => '/href="(?<file>libiconv-(?<version>[^"]+)\.tar\.gz)"/', |
| 362 | + ], |
| 363 | + 'source-mirror' => ['type' => 'local', 'dirname' => __DIR__], |
| 364 | + ]); |
| 365 | + $original_cache = ApplicationContext::get(ArtifactCache::class); |
| 366 | + $cache = $this->createMock(ArtifactCache::class); |
| 367 | + $cache->expects($no_alt ? $this->never() : $this->once()) |
| 368 | + ->method('lock') |
| 369 | + ->with($artifact, 'source', $this->callback(fn (DownloadResult $result) => $result->dirname === __DIR__)); |
| 370 | + ApplicationContext::set(ArtifactCache::class, $cache); |
| 371 | + try { |
| 372 | + if ($no_alt) { |
| 373 | + $this->expectException(DownloaderException::class); |
| 374 | + $this->expectExceptionMessage("Download artifact 'fallback-test' failed"); |
| 375 | + } |
| 376 | + (new ArtifactDownloader(['source-only' => true, 'no-alt' => $no_alt], false)) |
| 377 | + ->add($artifact) |
| 378 | + ->download(); |
| 379 | + } finally { |
| 380 | + ApplicationContext::set(ArtifactCache::class, $original_cache); |
| 381 | + if (file_exists($listing)) { |
| 382 | + unlink($listing); |
| 383 | + } |
| 384 | + } |
| 385 | + } |
| 386 | + |
| 387 | + public static function failedFileListProvider(): iterable |
| 388 | + { |
| 389 | + foreach ([false, true] as $no_alt) { |
| 390 | + $suffix = $no_alt ? ' without mirrors' : ' with mirrors'; |
| 391 | + yield 'request failure' . $suffix => [null, $no_alt]; |
| 392 | + yield 'empty listing' . $suffix => ['', $no_alt]; |
| 393 | + yield 'no matching releases' . $suffix => ['<html>Mirror unavailable</html>', $no_alt]; |
| 394 | + yield 'prereleases only' . $suffix => ['<a href="libiconv-1.20-rc1.tar.gz">release candidate</a>', $no_alt]; |
| 395 | + yield 'archive download failure' . $suffix => ['<a href="libiconv-1.19.tar.gz">release</a>', $no_alt]; |
| 396 | + } |
| 397 | + } |
| 398 | + |
340 | 399 | // ==================== Helpers ==================== |
341 | 400 |
|
342 | 401 | private function injectArtifactConfig(string $name, array $config): void |
|
0 commit comments