AK: Fix MemoryStream seek from end
The seek offset is still applied positively when seeking from the end; see the Kernel's seek implementation.
This commit is contained in:
parent
784ac6b9f2
commit
8bcf25561b
Notes:
sideshowbarker
2024-07-16 23:57:20 +09:00
Author: https://github.com/kleinesfilmroellchen Commit: https://github.com/SerenityOS/serenity/commit/8bcf25561b Pull-request: https://github.com/SerenityOS/serenity/pull/21070 Reviewed-by: https://github.com/ADKaster ✅
2 changed files with 98 additions and 2 deletions
|
@ -81,10 +81,10 @@ ErrorOr<size_t> FixedMemoryStream::seek(i64 offset, SeekMode seek_mode)
|
|||
m_offset += offset;
|
||||
break;
|
||||
case SeekMode::FromEndPosition:
|
||||
if (offset > static_cast<i64>(m_bytes.size()))
|
||||
if (-offset > static_cast<i64>(m_bytes.size()))
|
||||
return Error::from_string_view_or_print_error_and_return_errno("Offset past the start of the stream memory"sv, EINVAL);
|
||||
|
||||
m_offset = m_bytes.size() - offset;
|
||||
m_offset = m_bytes.size() + offset;
|
||||
break;
|
||||
}
|
||||
return m_offset;
|
||||
|
|
|
@ -151,3 +151,99 @@ TEST_CASE(allocating_memory_stream_offset_of_with_write_offset_multiple_of_chunk
|
|||
EXPECT_EQ(offset.value(), AllocatingMemoryStream::CHUNK_SIZE - 32 - 1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(fixed_memory_read_write)
|
||||
{
|
||||
constexpr auto some_words = "These are some words"sv;
|
||||
|
||||
auto empty = TRY_OR_FAIL(ByteBuffer::create_uninitialized(some_words.length()));
|
||||
FixedMemoryStream stream { empty.bytes() };
|
||||
|
||||
ReadonlyBytes buffer { some_words.characters_without_null_termination(), some_words.length() };
|
||||
TRY_OR_FAIL(stream.write_some(buffer));
|
||||
|
||||
EXPECT_EQ(TRY_OR_FAIL(stream.tell()), some_words.length());
|
||||
EXPECT(stream.is_eof());
|
||||
|
||||
TRY_OR_FAIL(stream.seek(0));
|
||||
auto contents = TRY_OR_FAIL(stream.read_until_eof());
|
||||
EXPECT_EQ(contents.bytes(), some_words.bytes());
|
||||
}
|
||||
|
||||
TEST_CASE(fixed_memory_close)
|
||||
{
|
||||
auto empty = TRY_OR_FAIL(ByteBuffer::create_uninitialized(64));
|
||||
FixedMemoryStream stream { empty.bytes() };
|
||||
EXPECT(stream.is_open());
|
||||
stream.close();
|
||||
EXPECT(stream.is_open());
|
||||
}
|
||||
|
||||
TEST_CASE(fixed_memory_read_only)
|
||||
{
|
||||
constexpr auto some_words = "These are some words"sv;
|
||||
|
||||
FixedMemoryStream stream { ReadonlyBytes { some_words.bytes() } };
|
||||
|
||||
auto contents = TRY_OR_FAIL(stream.read_until_eof());
|
||||
EXPECT_EQ(contents.bytes(), some_words.bytes());
|
||||
|
||||
TRY_OR_FAIL(stream.seek(0));
|
||||
ReadonlyBytes buffer { some_words.characters_without_null_termination(), some_words.length() };
|
||||
EXPECT_CRASH("Write protection assert", [&] {
|
||||
(void)stream.write_some(buffer);
|
||||
return Test::Crash::Failure::DidNotCrash;
|
||||
});
|
||||
|
||||
EXPECT_EQ(TRY_OR_FAIL(stream.tell()), 0ull);
|
||||
EXPECT(!stream.is_eof());
|
||||
}
|
||||
|
||||
TEST_CASE(fixed_memory_seeking_around)
|
||||
{
|
||||
auto stream_buffer = TRY_OR_FAIL(ByteBuffer::create_uninitialized(8702ul));
|
||||
FixedMemoryStream stream { ReadonlyBytes { stream_buffer.bytes() } };
|
||||
|
||||
auto buffer = TRY_OR_FAIL(ByteBuffer::create_uninitialized(16));
|
||||
|
||||
TRY_OR_FAIL(stream.seek(500, SeekMode::SetPosition));
|
||||
EXPECT_EQ(stream.tell().release_value(), 500ul);
|
||||
TRY_OR_FAIL(stream.read_until_filled(buffer));
|
||||
|
||||
TRY_OR_FAIL(stream.seek(234, SeekMode::FromCurrentPosition));
|
||||
EXPECT_EQ(stream.tell().release_value(), 750ul);
|
||||
TRY_OR_FAIL(stream.read_until_filled(buffer));
|
||||
|
||||
TRY_OR_FAIL(stream.seek(-105, SeekMode::FromEndPosition));
|
||||
EXPECT_EQ(stream.tell().release_value(), 8597ul);
|
||||
TRY_OR_FAIL(stream.read_until_filled(buffer));
|
||||
}
|
||||
|
||||
BENCHMARK_CASE(fixed_memory_tell)
|
||||
{
|
||||
auto stream_buffer = TRY_OR_FAIL(ByteBuffer::create_uninitialized(10 * KiB));
|
||||
FixedMemoryStream stream { ReadonlyBytes { stream_buffer.bytes() } };
|
||||
|
||||
auto expected_fixed_memory_offset = 0u;
|
||||
auto ten_byte_buffer = TRY_OR_FAIL(ByteBuffer::create_uninitialized(1));
|
||||
for (auto i = 0u; i < 4000; ++i) {
|
||||
TRY_OR_FAIL(stream.read_until_filled(ten_byte_buffer));
|
||||
expected_fixed_memory_offset += 1u;
|
||||
EXPECT_EQ(expected_fixed_memory_offset, TRY_OR_FAIL(stream.tell()));
|
||||
}
|
||||
|
||||
for (auto i = 0u; i < 4000; ++i) {
|
||||
auto seek_fixed_memory_offset = TRY_OR_FAIL(stream.seek(-1, SeekMode::FromCurrentPosition));
|
||||
expected_fixed_memory_offset -= 1;
|
||||
EXPECT_EQ(seek_fixed_memory_offset, TRY_OR_FAIL(stream.tell()));
|
||||
EXPECT_EQ(expected_fixed_memory_offset, TRY_OR_FAIL(stream.tell()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(fixed_memory_truncate)
|
||||
{
|
||||
auto stream_buffer = TRY_OR_FAIL(ByteBuffer::create_uninitialized(10 * KiB));
|
||||
FixedMemoryStream stream { ReadonlyBytes { stream_buffer.bytes() } };
|
||||
|
||||
EXPECT(stream.truncate(999).is_error());
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue