Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ public function open(): void
* @type int $size Size in bytes.
* @type string $type `file`, `dir`, or `link`.
* }
* @throws RuntimeException When a non-blank line is not a decodable index
* entry.
* @throws RuntimeException When the index cannot be read or a non-blank
* line is not a decodable entry.
* @throws InvalidArgumentException When the decoded path is not a valid
* remote absolute path.
*/
Expand All @@ -164,6 +164,11 @@ public function next_entry(): ?array
}
return self::decode_index_line($remote_index_json_line);
}
if (!feof($this->remote_index_file_handle)) {
throw new RuntimeException(
"Failed to read the remote index file: {$this->remote_index_path}"
);
}
return null;
}

Expand Down
47 changes: 47 additions & 0 deletions tests/Import/RemoteIndexReadFailureStream.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

// phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedNamespaceFound -- Existing importer test namespace.
// phpcs:disable Generic.Classes.OpeningBraceSameLine.BraceOnNewLine -- Match the existing importer test classes.

namespace ImportTests;

/** Stream wrapper whose reads fail before EOF. */
final class RemoteIndexReadFailureStream
{
/** @var resource|null Stream context supplied by PHP. */
public $context;

public function stream_open(
string $path,
string $mode,
int $options,
?string &$opened_path
): bool {
unset($path, $mode, $options, $opened_path);
return true;
}

public function stream_read(int $count): string
{
unset($count);
return '';
}

public function stream_eof(): bool
{
return false;
}

/** @return array{mode:int,size:int} */
public function stream_stat(): array
{
return ['mode' => 0100644, 'size' => 1];
}

/** @return array{mode:int,size:int} */
public function url_stat(string $path, int $flags): array
{
unset($path, $flags);
return ['mode' => 0100644, 'size' => 1];
}
}
26 changes: 26 additions & 0 deletions tests/Import/RemoteIndexReaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use PHPUnit\Framework\TestCase;

require_once __DIR__ . '/../../packages/reprint-client/bin/reprint-client';
require_once __DIR__ . '/RemoteIndexReadFailureStream.php';

final class RemoteIndexReaderTest extends TestCase
{
Expand Down Expand Up @@ -147,6 +148,31 @@ public function testLineDecoderRejectsABlankRecord(): void
\RemoteIndexReader::decode_index_line("\n");
}

public function testReadFailureDoesNotLookLikeEndOfFile(): void
{
$scheme = 'failingremoteindex';
$this->assertTrue(
stream_wrapper_register(
$scheme,
RemoteIndexReadFailureStream::class
)
);
$reader = new \RemoteIndexReader($scheme . '://index');
try {
$reader->open();
$reader->next_entry();
$this->fail('Expected the remote index read failure to throw.');
} catch (\RuntimeException $exception) {
$this->assertStringContainsString(
'Failed to read the remote index file',
$exception->getMessage()
);
} finally {
$reader->close();
stream_wrapper_unregister($scheme);
}
}

private function indexLine(
string $path,
int $ctime,
Expand Down
Loading