blob: 1626db0493aa0f3aa1c799a91d803507fb479012 [file]
// Copyright 2024 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "iree/io/vec_stream.h"
#include <array>
#include <string>
#include <string_view>
#include "iree/base/api.h"
#include "iree/testing/gtest.h"
#include "iree/testing/status_matchers.h"
namespace {
using iree::Status;
using iree::StatusCode;
using iree::testing::status::StatusIs;
using testing::ElementsAre;
using testing::ElementsAreArray;
using testing::Eq;
using StreamPtr =
std::unique_ptr<iree_io_stream_t, void (*)(iree_io_stream_t*)>;
static StreamPtr CreateStream(iree_io_stream_mode_t mode,
size_t block_size = 1 * 1024) {
iree_io_stream_t* stream = NULL;
IREE_CHECK_OK(iree_io_vec_stream_create(mode, block_size,
iree_allocator_system(), &stream));
return StreamPtr(stream, iree_io_stream_release);
}
template <typename T, size_t N>
static StreamPtr CreateStreamWithContents(iree_io_stream_mode_t mode,
T (&elements)[N],
size_t block_size = 1 * 1024) {
iree_io_stream_t* stream = NULL;
IREE_CHECK_OK(iree_io_vec_stream_create(mode | IREE_IO_STREAM_MODE_WRITABLE,
block_size, iree_allocator_system(),
&stream));
IREE_CHECK_OK(iree_io_stream_write(stream, sizeof(T) * N, elements));
IREE_CHECK_OK(iree_io_stream_seek(stream, IREE_IO_STREAM_SEEK_SET, 0));
return StreamPtr(stream, iree_io_stream_release);
}
TEST(VecStreamTest, Empty) {
auto stream = CreateStream(IREE_IO_STREAM_MODE_READABLE);
EXPECT_EQ(iree_io_stream_mode(stream.get()), IREE_IO_STREAM_MODE_READABLE);
EXPECT_EQ(iree_io_stream_offset(stream.get()), 0);
EXPECT_EQ(iree_io_stream_length(stream.get()), 0);
EXPECT_TRUE(iree_io_stream_is_eos(stream.get()));
}
TEST(VecStreamTest, SeekSet) {
uint8_t data[5] = {0, 1, 2, 3, 4};
auto stream = CreateStreamWithContents(IREE_IO_STREAM_MODE_READABLE, data);
// Streams start at origin 0.
EXPECT_EQ(iree_io_stream_offset(stream.get()), 0);
EXPECT_EQ(iree_io_stream_length(stream.get()), sizeof(data));
EXPECT_FALSE(iree_io_stream_is_eos(stream.get()));
// No-op seek to origin.
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 0));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 0);
EXPECT_FALSE(iree_io_stream_is_eos(stream.get()));
// Seek to end-of-stream.
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET,
iree_io_stream_length(stream.get())));
EXPECT_EQ(iree_io_stream_offset(stream.get()),
iree_io_stream_length(stream.get()));
EXPECT_TRUE(iree_io_stream_is_eos(stream.get()));
// Seek to absolute offset 1.
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 1));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 1);
EXPECT_FALSE(iree_io_stream_is_eos(stream.get()));
// Seek to absolute offset length-1 (last valid byte).
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 4));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 4);
EXPECT_FALSE(iree_io_stream_is_eos(stream.get()));
// Try seeking out of bounds (off the front of the list).
EXPECT_THAT(
Status(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, -1)),
StatusIs(StatusCode::kOutOfRange));
// Seek off the end of the stream to extend it.
EXPECT_EQ(iree_io_stream_length(stream.get()), 5);
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 6));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 6);
EXPECT_EQ(iree_io_stream_length(stream.get()), 6);
EXPECT_TRUE(iree_io_stream_is_eos(stream.get()));
}
TEST(VecStreamTest, SeekFromCurrent) {
uint8_t data[5] = {0, 1, 2, 3, 4};
auto stream = CreateStreamWithContents(IREE_IO_STREAM_MODE_READABLE, data);
// Streams start at origin 0.
EXPECT_EQ(iree_io_stream_offset(stream.get()), 0);
EXPECT_EQ(iree_io_stream_length(stream.get()), sizeof(data));
EXPECT_FALSE(iree_io_stream_is_eos(stream.get()));
// Seek to end-of-stream by jumping the full length.
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(),
IREE_IO_STREAM_SEEK_FROM_CURRENT,
iree_io_stream_length(stream.get())));
EXPECT_EQ(iree_io_stream_offset(stream.get()),
iree_io_stream_length(stream.get()));
EXPECT_TRUE(iree_io_stream_is_eos(stream.get()));
// Reset back to origin by seeking back the full length.
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(),
IREE_IO_STREAM_SEEK_FROM_CURRENT,
-iree_io_stream_length(stream.get())));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 0);
EXPECT_FALSE(iree_io_stream_is_eos(stream.get()));
// Seek forward to absolute position 1.
IREE_EXPECT_OK(
iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_FROM_CURRENT, 1));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 1);
EXPECT_FALSE(iree_io_stream_is_eos(stream.get()));
// No-op seek to current location (absolute 1).
IREE_EXPECT_OK(
iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_FROM_CURRENT, 0));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 1);
EXPECT_FALSE(iree_io_stream_is_eos(stream.get()));
// Seek to absolute offset length-1 (last valid byte) - here (5-1) - 1 = 3.
IREE_EXPECT_OK(
iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_FROM_CURRENT, 3));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 4);
EXPECT_FALSE(iree_io_stream_is_eos(stream.get()));
// Seek forward 1 to absolute end-of-stream.
IREE_EXPECT_OK(
iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_FROM_CURRENT, 1));
EXPECT_EQ(iree_io_stream_offset(stream.get()),
iree_io_stream_length(stream.get()));
EXPECT_TRUE(iree_io_stream_is_eos(stream.get()));
// Reset back to origin.
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 0));
// Try seeking out of bounds.
EXPECT_THAT(Status(iree_io_stream_seek(
stream.get(), IREE_IO_STREAM_SEEK_FROM_CURRENT, -100)),
StatusIs(StatusCode::kOutOfRange));
// Seek off the end of the stream to extend it.
EXPECT_EQ(iree_io_stream_length(stream.get()), 5);
IREE_EXPECT_OK(
iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_FROM_CURRENT, 600));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 600);
EXPECT_EQ(iree_io_stream_length(stream.get()), 600);
EXPECT_TRUE(iree_io_stream_is_eos(stream.get()));
}
TEST(VecStreamTest, SeekFromEnd) {
uint8_t data[5] = {0, 1, 2, 3, 4};
auto stream = CreateStreamWithContents(IREE_IO_STREAM_MODE_READABLE, data);
// Streams start at origin 0.
EXPECT_EQ(iree_io_stream_offset(stream.get()), 0);
EXPECT_EQ(iree_io_stream_length(stream.get()), sizeof(data));
EXPECT_FALSE(iree_io_stream_is_eos(stream.get()));
// Jump to end-of-stream.
IREE_EXPECT_OK(
iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_FROM_END, 0));
EXPECT_EQ(iree_io_stream_offset(stream.get()),
iree_io_stream_length(stream.get()));
EXPECT_TRUE(iree_io_stream_is_eos(stream.get()));
// Reset back to origin by seeking back the full length.
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_FROM_END,
-iree_io_stream_length(stream.get())));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 0);
EXPECT_FALSE(iree_io_stream_is_eos(stream.get()));
// Seek to absolute offset length-1 (last valid byte) - here 5 - 1 = 4.
IREE_EXPECT_OK(
iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_FROM_END, -1));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 4);
EXPECT_FALSE(iree_io_stream_is_eos(stream.get()));
// Reset back to origin.
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 0));
// Try seeking out of bounds.
EXPECT_THAT(Status(iree_io_stream_seek(stream.get(),
IREE_IO_STREAM_SEEK_FROM_END, -100)),
StatusIs(StatusCode::kOutOfRange));
// Seek off the end of the stream to extend it.
EXPECT_EQ(iree_io_stream_length(stream.get()), 5);
IREE_EXPECT_OK(
iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_FROM_END, 100));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 105);
EXPECT_EQ(iree_io_stream_length(stream.get()), 105);
EXPECT_TRUE(iree_io_stream_is_eos(stream.get()));
}
TEST(VecStreamTest, SeekToAlignment) {
uint8_t data[5] = {0, 1, 2, 3, 4};
auto stream = CreateStreamWithContents(IREE_IO_STREAM_MODE_READABLE, data);
// Streams start at origin 0.
EXPECT_EQ(iree_io_stream_offset(stream.get()), 0);
EXPECT_EQ(iree_io_stream_length(stream.get()), sizeof(data));
EXPECT_FALSE(iree_io_stream_is_eos(stream.get()));
// Alignment must be a power of two.
EXPECT_THAT(Status(iree_io_stream_seek_to_alignment(stream.get(), 3)),
StatusIs(StatusCode::kInvalidArgument));
EXPECT_THAT(Status(iree_io_stream_seek_to_alignment(stream.get(), 63)),
StatusIs(StatusCode::kInvalidArgument));
EXPECT_THAT(Status(iree_io_stream_seek_to_alignment(stream.get(), -2)),
StatusIs(StatusCode::kInvalidArgument));
// Alignment at 0 should always be ok.
IREE_EXPECT_OK(iree_io_stream_seek_to_alignment(stream.get(), 0));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 0);
IREE_EXPECT_OK(iree_io_stream_seek_to_alignment(stream.get(), 1));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 0);
IREE_EXPECT_OK(iree_io_stream_seek_to_alignment(stream.get(), 2));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 0);
// Seek forward to an unaligned absolute offset 1.
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 1));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 1);
// Seek forward to alignment 2, which should be absolute offset 2.
IREE_EXPECT_OK(iree_io_stream_seek_to_alignment(stream.get(), 2));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 2);
// Alignment that matches the current offset (2) should be a no-op.
IREE_EXPECT_OK(iree_io_stream_seek_to_alignment(stream.get(), 2));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 2);
// Align up from an aligned value.
IREE_EXPECT_OK(iree_io_stream_seek_to_alignment(stream.get(), 4));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 4);
// Align off the end of the stream to extend.
EXPECT_EQ(iree_io_stream_length(stream.get()), 5);
IREE_EXPECT_OK(iree_io_stream_seek_to_alignment(stream.get(), 16));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 16);
EXPECT_EQ(iree_io_stream_length(stream.get()), 16);
EXPECT_TRUE(iree_io_stream_is_eos(stream.get()));
}
TEST(VecStreamTest, ReadUpTo) {
uint8_t data[5] = {0, 1, 2, 3, 4};
auto stream = CreateStreamWithContents(IREE_IO_STREAM_MODE_READABLE, data);
// Streams start at origin 0.
EXPECT_EQ(iree_io_stream_offset(stream.get()), 0);
EXPECT_EQ(iree_io_stream_length(stream.get()), sizeof(data));
EXPECT_FALSE(iree_io_stream_is_eos(stream.get()));
uint8_t read_buffer[64] = {0xDD};
iree_host_size_t read_length = 0;
// Reads of zero length should no-op.
IREE_EXPECT_OK(
iree_io_stream_read(stream.get(), 0, read_buffer, &read_length));
EXPECT_EQ(read_length, 0);
EXPECT_EQ(iree_io_stream_offset(stream.get()), 0);
// Reads should advance the stream offset.
memset(read_buffer, 0xDD, sizeof(read_buffer));
IREE_EXPECT_OK(
iree_io_stream_read(stream.get(), 1, read_buffer, &read_length));
EXPECT_EQ(read_length, 1);
EXPECT_EQ(iree_io_stream_offset(stream.get()), 1);
EXPECT_EQ(read_buffer[0], 0);
EXPECT_EQ(read_buffer[1], 0xDD);
// Read another chunk of 2 bytes.
memset(read_buffer, 0xDD, sizeof(read_buffer));
IREE_EXPECT_OK(
iree_io_stream_read(stream.get(), 2, read_buffer, &read_length));
EXPECT_EQ(read_length, 2);
EXPECT_EQ(iree_io_stream_offset(stream.get()), 3);
EXPECT_EQ(read_buffer[0], 1);
EXPECT_EQ(read_buffer[1], 2);
EXPECT_EQ(read_buffer[2], 0xDD);
// Read up to the end of the stream (2 bytes remaining) by reading over.
memset(read_buffer, 0xDD, sizeof(read_buffer));
IREE_EXPECT_OK(iree_io_stream_read(stream.get(), sizeof(read_buffer),
read_buffer, &read_length));
EXPECT_EQ(read_length, 2);
EXPECT_EQ(iree_io_stream_offset(stream.get()),
iree_io_stream_length(stream.get()));
EXPECT_TRUE(iree_io_stream_is_eos(stream.get()));
EXPECT_EQ(read_buffer[0], 3);
EXPECT_EQ(read_buffer[1], 4);
EXPECT_EQ(read_buffer[2], 0xDD);
// Reading from the end of the stream should be a no-op.
memset(read_buffer, 0xDD, sizeof(read_buffer));
IREE_EXPECT_OK(iree_io_stream_read(stream.get(), sizeof(read_buffer),
read_buffer, &read_length));
EXPECT_EQ(read_length, 0);
EXPECT_EQ(iree_io_stream_offset(stream.get()),
iree_io_stream_length(stream.get()));
EXPECT_TRUE(iree_io_stream_is_eos(stream.get()));
EXPECT_EQ(read_buffer[0], 0xDD);
}
TEST(VecStreamTest, ReadExact) {
uint8_t data[5] = {0, 1, 2, 3, 4};
auto stream = CreateStreamWithContents(IREE_IO_STREAM_MODE_READABLE, data);
// Streams start at origin 0.
EXPECT_EQ(iree_io_stream_offset(stream.get()), 0);
EXPECT_EQ(iree_io_stream_length(stream.get()), sizeof(data));
EXPECT_FALSE(iree_io_stream_is_eos(stream.get()));
uint8_t read_buffer[64] = {0xDD};
// Reads of zero length should no-op.
IREE_EXPECT_OK(iree_io_stream_read(stream.get(), 0, read_buffer, NULL));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 0);
// Reads should advance the stream offset.
memset(read_buffer, 0xDD, sizeof(read_buffer));
IREE_EXPECT_OK(iree_io_stream_read(stream.get(), 1, read_buffer, NULL));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 1);
EXPECT_EQ(read_buffer[0], 0);
EXPECT_EQ(read_buffer[1], 0xDD);
// Read another chunk of 2 bytes.
memset(read_buffer, 0xDD, sizeof(read_buffer));
IREE_EXPECT_OK(iree_io_stream_read(stream.get(), 2, read_buffer, NULL));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 3);
EXPECT_EQ(read_buffer[0], 1);
EXPECT_EQ(read_buffer[1], 2);
EXPECT_EQ(read_buffer[2], 0xDD);
// Read up to the end of the stream (2 bytes remaining) by reading over.
memset(read_buffer, 0xDD, sizeof(read_buffer));
IREE_EXPECT_OK(iree_io_stream_read(stream.get(), 2, read_buffer, NULL));
EXPECT_EQ(iree_io_stream_offset(stream.get()),
iree_io_stream_length(stream.get()));
EXPECT_TRUE(iree_io_stream_is_eos(stream.get()));
EXPECT_EQ(read_buffer[0], 3);
EXPECT_EQ(read_buffer[1], 4);
EXPECT_EQ(read_buffer[2], 0xDD);
// Reading from the end of the stream fails with no read length arg.
memset(read_buffer, 0xDD, sizeof(read_buffer));
EXPECT_THAT(Status(iree_io_stream_read(stream.get(), sizeof(read_buffer),
read_buffer, NULL)),
StatusIs(StatusCode::kOutOfRange));
// Reset back to the origin and try reading off the end.
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 0));
EXPECT_THAT(Status(iree_io_stream_read(stream.get(), sizeof(read_buffer),
read_buffer, NULL)),
StatusIs(StatusCode::kOutOfRange));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 0);
}
TEST(VecStreamTest, Write) {
auto stream =
CreateStream(IREE_IO_STREAM_MODE_READABLE | IREE_IO_STREAM_MODE_WRITABLE);
uint8_t data[5] = {0xDD};
const uint8_t write_buffer[8] = {0, 1, 2, 3, 4, 5, 6, 7};
// Writes of zero length should be a no-op.
memset(data, 0xDD, sizeof(data));
IREE_EXPECT_OK(iree_io_stream_write(stream.get(), 0, write_buffer));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 0);
EXPECT_EQ(iree_io_stream_length(stream.get()), 0);
EXPECT_EQ(data[0], 0xDD);
// Writes should advance the stream.
memset(data, 0xDD, sizeof(data));
IREE_EXPECT_OK(iree_io_stream_write(stream.get(), 1, write_buffer));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 1);
EXPECT_EQ(iree_io_stream_length(stream.get()), 1);
IREE_ASSERT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 0));
IREE_ASSERT_OK(iree_io_stream_read(stream.get(), 1, data, NULL));
EXPECT_EQ(data[0], 0);
EXPECT_EQ(data[1], 0xDD);
// Write 2 more bytes and ensure only those are mutated.
memset(data, 0xDD, sizeof(data));
IREE_EXPECT_OK(iree_io_stream_write(stream.get(), 2, &write_buffer[1]));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 1 + 2);
EXPECT_EQ(iree_io_stream_length(stream.get()), 1 + 2);
IREE_ASSERT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 0));
IREE_ASSERT_OK(iree_io_stream_read(stream.get(), 3, data, NULL));
EXPECT_EQ(data[0], 0);
EXPECT_EQ(data[1], 1);
EXPECT_EQ(data[2], 2);
EXPECT_EQ(data[3], 0xDD);
// Seek to the end of the stream and try to write 0 bytes (should be a no-op).
IREE_EXPECT_OK(
iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_FROM_END, 0));
EXPECT_TRUE(iree_io_stream_is_eos(stream.get()));
IREE_EXPECT_OK(iree_io_stream_write(stream.get(), 0, write_buffer));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 3);
EXPECT_EQ(iree_io_stream_length(stream.get()), 3);
EXPECT_TRUE(iree_io_stream_is_eos(stream.get()));
// Overwrite the entire contents of the storage.
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 0));
IREE_EXPECT_OK(
iree_io_stream_write(stream.get(), sizeof(data), write_buffer));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 5);
EXPECT_EQ(iree_io_stream_length(stream.get()), 5);
IREE_ASSERT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 0));
IREE_ASSERT_OK(iree_io_stream_read(stream.get(), sizeof(data), data, NULL));
EXPECT_THAT(data,
ElementsAre(write_buffer[0], write_buffer[1], write_buffer[2],
write_buffer[3], write_buffer[4]));
}
TEST(VecStreamTest, FillSizes) {
auto stream =
CreateStream(IREE_IO_STREAM_MODE_READABLE | IREE_IO_STREAM_MODE_WRITABLE);
uint8_t pattern[] = {0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0};
// Fill patterns must be 1,2,4,8 bytes.
EXPECT_THAT(Status(iree_io_stream_fill(stream.get(), 1, pattern, 3)),
StatusIs(StatusCode::kInvalidArgument));
EXPECT_THAT(Status(iree_io_stream_fill(stream.get(), 1, pattern, 9)),
StatusIs(StatusCode::kInvalidArgument));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 0);
}
TEST(VecStreamTest, Fill1) {
auto stream =
CreateStream(IREE_IO_STREAM_MODE_READABLE | IREE_IO_STREAM_MODE_WRITABLE);
uint8_t pattern[] = {0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0};
// Extend to 16 bytes for easy fill testing.
IREE_EXPECT_OK(
iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 16));
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 0));
// Fill with pattern size 1.
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 1));
IREE_EXPECT_OK(iree_io_stream_fill(stream.get(), 3, pattern, 1));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 1 + 3);
IREE_EXPECT_OK(
iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_FROM_END, -2));
IREE_EXPECT_OK(iree_io_stream_fill(stream.get(), 2, pattern, 1));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 16 - 2 + 2);
uint8_t data[16] = {0xDD};
IREE_ASSERT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 0));
IREE_ASSERT_OK(iree_io_stream_read(stream.get(), sizeof(data), data, NULL));
EXPECT_THAT(data,
ElementsAre(0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80));
}
TEST(VecStreamTest, Fill2) {
auto stream =
CreateStream(IREE_IO_STREAM_MODE_READABLE | IREE_IO_STREAM_MODE_WRITABLE);
uint8_t pattern[] = {0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0};
// Extend to 16 bytes for easy fill testing.
IREE_EXPECT_OK(
iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 16));
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 0));
// Fill with pattern size 2.
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 1));
IREE_EXPECT_OK(iree_io_stream_fill(stream.get(), 3, pattern, 2));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 1 + 3 * 2);
IREE_EXPECT_OK(
iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_FROM_END, -4));
IREE_EXPECT_OK(iree_io_stream_fill(stream.get(), 2, pattern, 2));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 16 - 4 + 2 * 2);
uint8_t data[16] = {0xDD};
IREE_ASSERT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 0));
IREE_ASSERT_OK(iree_io_stream_read(stream.get(), sizeof(data), data, NULL));
EXPECT_THAT(data,
ElementsAre(0x00, 0x80, 0x90, 0x80, 0x90, 0x80, 0x90, 0x00, 0x00,
0x00, 0x00, 0x00, 0x80, 0x90, 0x80, 0x90));
}
TEST(VecStreamTest, Fill4) {
auto stream =
CreateStream(IREE_IO_STREAM_MODE_READABLE | IREE_IO_STREAM_MODE_WRITABLE);
uint8_t pattern[] = {0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0};
// Extend to 16 bytes for easy fill testing.
IREE_EXPECT_OK(
iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 16));
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 0));
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 1));
IREE_EXPECT_OK(iree_io_stream_fill(stream.get(), 2, pattern, 4));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 1 + 2 * 4);
IREE_EXPECT_OK(
iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_FROM_END, -4));
IREE_EXPECT_OK(iree_io_stream_fill(stream.get(), 1, pattern, 4));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 16 - 4 + 1 * 4);
uint8_t data[16] = {0xDD};
IREE_ASSERT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 0));
IREE_ASSERT_OK(iree_io_stream_read(stream.get(), sizeof(data), data, NULL));
EXPECT_THAT(data,
ElementsAre(0x00, 0x80, 0x90, 0xA0, 0xB0, 0x80, 0x90, 0xA0, 0xB0,
0x00, 0x00, 0x00, 0x80, 0x90, 0xA0, 0xB0));
}
TEST(VecStreamTest, Fill8Unaligned) {
auto stream =
CreateStream(IREE_IO_STREAM_MODE_READABLE | IREE_IO_STREAM_MODE_WRITABLE);
uint8_t pattern[] = {0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0};
// Extend to 16 bytes for easy fill testing.
IREE_EXPECT_OK(
iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 16));
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 0));
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 1));
IREE_EXPECT_OK(iree_io_stream_fill(stream.get(), 1, pattern, 8));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 1 + 1 * 8);
uint8_t data[16] = {0xDD};
IREE_ASSERT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 0));
IREE_ASSERT_OK(iree_io_stream_read(stream.get(), sizeof(data), data, NULL));
EXPECT_THAT(data,
ElementsAre(0x00, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
}
TEST(VecStreamTest, Fill8End) {
auto stream =
CreateStream(IREE_IO_STREAM_MODE_READABLE | IREE_IO_STREAM_MODE_WRITABLE);
uint8_t pattern[] = {0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0};
// Extend to 16 bytes for easy fill testing.
IREE_EXPECT_OK(
iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 16));
IREE_EXPECT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 0));
IREE_EXPECT_OK(
iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_FROM_END, -8));
IREE_EXPECT_OK(iree_io_stream_fill(stream.get(), 1, pattern, 8));
EXPECT_EQ(iree_io_stream_offset(stream.get()), 16);
uint8_t data[16] = {0xDD};
IREE_ASSERT_OK(iree_io_stream_seek(stream.get(), IREE_IO_STREAM_SEEK_SET, 0));
IREE_ASSERT_OK(iree_io_stream_read(stream.get(), sizeof(data), data, NULL));
EXPECT_THAT(data,
ElementsAre(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0));
}
} // namespace