summaryrefslogtreecommitdiff
path: root/test/io_test_helper.cc
diff options
context:
space:
mode:
Diffstat (limited to 'test/io_test_helper.cc')
-rw-r--r--test/io_test_helper.cc165
1 files changed, 165 insertions, 0 deletions
diff --git a/test/io_test_helper.cc b/test/io_test_helper.cc
new file mode 100644
index 0000000..880a114
--- /dev/null
+++ b/test/io_test_helper.cc
@@ -0,0 +1,165 @@
+#include "io_test_helper.hh"
+
+#include "io.hh"
+
+#include <algorithm>
+#include <cstddef>
+#include <expected>
+#include <memory>
+#include <utility>
+
+namespace {
+
+class BreakingReader : public io::Reader {
+ public:
+ BreakingReader(std::unique_ptr<io::Reader> reader, size_t offset,
+ io::ReadError error)
+ : reader_(std::move(reader)), offset_(offset), error_(error) {}
+
+ [[nodiscard]]
+ std::expected<size_t, io::ReadError> read(void* dst, size_t max) override {
+ if (offset_ == 0)
+ return std::unexpected(error_);
+ size_t avail = std::min(offset_, max);
+ auto ret = reader_->read(dst, avail);
+ if (ret.has_value()) {
+ offset_ -= ret.value();
+ }
+ return ret;
+ }
+
+ [[nodiscard]]
+ std::expected<size_t, io::ReadError> skip(size_t max) override {
+ if (offset_ == 0)
+ return std::unexpected(error_);
+ size_t avail = std::min(offset_, max);
+ auto ret = reader_->skip(avail);
+ if (ret.has_value()) {
+ offset_ -= ret.value();
+ }
+ return ret;
+ }
+
+ [[nodiscard]]
+ int raw_fd() const override {
+ return reader_->raw_fd();
+ }
+
+ private:
+ std::unique_ptr<io::Reader> reader_;
+ size_t offset_;
+ io::ReadError const error_;
+};
+
+class BreakingWriter : public io::Writer {
+ public:
+ BreakingWriter(std::unique_ptr<io::Writer> writer, size_t offset,
+ io::WriteError error)
+ : writer_(std::move(writer)), offset_(offset), error_(error) {}
+
+ [[nodiscard]]
+ std::expected<size_t, io::WriteError> write(void const* dst,
+ size_t size) override {
+ if (offset_ == 0)
+ return std::unexpected(error_);
+ size_t avail = std::min(offset_, size);
+ auto ret = writer_->write(dst, avail);
+ if (ret.has_value()) {
+ offset_ -= ret.value();
+ }
+ return ret;
+ }
+
+ [[nodiscard]]
+ std::expected<void, io::WriteError> close() override {
+ return writer_->close();
+ }
+
+ [[nodiscard]]
+ int raw_fd() const override {
+ return writer_->raw_fd();
+ }
+
+ private:
+ std::unique_ptr<io::Writer> writer_;
+ size_t offset_;
+ io::WriteError const error_;
+};
+
+class MaxBlockReader : public io::Reader {
+ public:
+ MaxBlockReader(std::unique_ptr<io::Reader> reader, size_t max_block_size)
+ : reader_(std::move(reader)), max_block_size_(max_block_size) {}
+
+ [[nodiscard]]
+ std::expected<size_t, io::ReadError> read(void* dst, size_t max) override {
+ size_t avail = std::min(max_block_size_, max);
+ return reader_->read(dst, avail);
+ }
+
+ [[nodiscard]]
+ std::expected<size_t, io::ReadError> skip(size_t max) override {
+ size_t avail = std::min(max_block_size_, max);
+ return reader_->skip(avail);
+ }
+
+ [[nodiscard]]
+ int raw_fd() const override {
+ return reader_->raw_fd();
+ }
+
+ private:
+ std::unique_ptr<io::Reader> reader_;
+ size_t const max_block_size_;
+};
+
+class MaxBlockWriter : public io::Writer {
+ public:
+ MaxBlockWriter(std::unique_ptr<io::Writer> writer, size_t max_block_size)
+ : writer_(std::move(writer)), max_block_size_(max_block_size) {}
+
+ [[nodiscard]]
+ std::expected<size_t, io::WriteError> write(void const* dst,
+ size_t size) override {
+ size_t avail = std::min(max_block_size_, size);
+ return writer_->write(dst, avail);
+ }
+
+ [[nodiscard]]
+ std::expected<void, io::WriteError> close() override {
+ return writer_->close();
+ }
+
+ [[nodiscard]]
+ int raw_fd() const override {
+ return writer_->raw_fd();
+ }
+
+ private:
+ std::unique_ptr<io::Writer> writer_;
+ size_t const max_block_size_;
+};
+
+} // namespace
+
+std::unique_ptr<io::Reader> io_make_breaking(std::unique_ptr<io::Reader> reader,
+ size_t offset,
+ io::ReadError error) {
+ return std::make_unique<BreakingReader>(std::move(reader), offset, error);
+}
+
+std::unique_ptr<io::Writer> io_make_breaking(std::unique_ptr<io::Writer> writer,
+ size_t offset,
+ io::WriteError error) {
+ return std::make_unique<BreakingWriter>(std::move(writer), offset, error);
+}
+
+std::unique_ptr<io::Reader> io_make_max_block(
+ std::unique_ptr<io::Reader> reader, size_t max_block_size) {
+ return std::make_unique<MaxBlockReader>(std::move(reader), max_block_size);
+}
+
+std::unique_ptr<io::Writer> io_make_max_block(
+ std::unique_ptr<io::Writer> writer, size_t max_block_size) {
+ return std::make_unique<MaxBlockWriter>(std::move(writer), max_block_size);
+}