blob: 0ae45aaad55deb1312e04d26a64afd677fede3f9 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/storage/lib/paver/stream-reader.h"
#include <fidl/fuchsia.paver/cpp/wire.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <zxtest/zxtest.h>
#include "zircon/errors.h"
namespace {
constexpr char kFileData[] = "lalalala";
TEST(StreamReaderTest, InvalidChannel) { ASSERT_NOT_OK(paver::StreamReader::Create({})); }
class FakePayloadStream : public fidl::WireServer<fuchsia_paver::PayloadStream> {
public:
FakePayloadStream() : loop_(&kAsyncLoopConfigAttachToCurrentThread) {
zx::result server = fidl::CreateEndpoints(&client_);
ASSERT_OK(server.status_value());
fidl::BindServer(loop_.dispatcher(), std::move(server.value()), this);
loop_.StartThread("payload-stream-test-loop");
}
void ReadSuccess(ReadDataCompleter::Sync& completer) {
vmo_.write(kFileData, 0, sizeof(kFileData));
fuchsia_paver::wire::ReadInfo info{.offset = 0, .size = sizeof(kFileData)};
completer.Reply(fuchsia_paver::wire::ReadResult::WithInfo(
fidl::ObjectView<fuchsia_paver::wire::ReadInfo>::FromExternal(&info)));
}
static void ReadError(ReadDataCompleter::Sync& completer) {
completer.Reply(fuchsia_paver::wire::ReadResult::WithErr(ZX_ERR_INTERNAL));
}
static void ReadEof(ReadDataCompleter::Sync& completer) {
completer.Reply(fuchsia_paver::wire::ReadResult::WithEof(true));
}
void ReadData(ReadDataCompleter::Sync& completer) override {
if (!vmo_) {
completer.Reply(fuchsia_paver::wire::ReadResult::WithErr(ZX_ERR_BAD_STATE));
return;
}
if (return_err_) {
ReadError(completer);
} else if (return_eof_) {
ReadEof(completer);
} else {
ReadSuccess(completer);
}
}
void RegisterVmo(RegisterVmoRequestView request, RegisterVmoCompleter::Sync& completer) override {
vmo_ = std::move(request->vmo);
completer.Reply(ZX_OK);
}
fidl::ClientEnd<fuchsia_paver::PayloadStream> client() { return std::move(client_); }
void ReturnErr() { return_err_ = true; }
void ReturnEof() { return_eof_ = true; }
private:
fidl::ClientEnd<fuchsia_paver::PayloadStream> client_;
async::Loop loop_;
zx::vmo vmo_;
bool return_err_ = false;
bool return_eof_ = false;
};
class StreamReaderTest : public zxtest::Test {
protected:
FakePayloadStream stream_;
};
TEST_F(StreamReaderTest, Create) { ASSERT_OK(paver::StreamReader::Create(stream_.client())); }
TEST_F(StreamReaderTest, ReadError) {
auto status = paver::StreamReader::Create(stream_.client());
ASSERT_OK(status);
std::unique_ptr<paver::StreamReader> reader = std::move(status.value());
stream_.ReturnErr();
char buffer[sizeof(kFileData)] = {};
size_t actual;
ASSERT_NE(reader->Read(buffer, sizeof(buffer), &actual), ZX_OK);
}
TEST_F(StreamReaderTest, ReadEof) {
auto status = paver::StreamReader::Create(stream_.client());
ASSERT_OK(status);
std::unique_ptr<paver::StreamReader> reader = std::move(status.value());
stream_.ReturnEof();
char buffer[sizeof(kFileData)] = {};
size_t actual;
ASSERT_OK(reader->Read(buffer, sizeof(buffer), &actual));
ASSERT_EQ(actual, 0);
}
TEST_F(StreamReaderTest, ReadSingle) {
auto status = paver::StreamReader::Create(stream_.client());
ASSERT_OK(status);
std::unique_ptr<paver::StreamReader> reader = std::move(status.value());
char buffer[sizeof(kFileData)] = {};
size_t actual;
ASSERT_OK(reader->Read(buffer, sizeof(buffer), &actual));
ASSERT_EQ(actual, sizeof(buffer));
ASSERT_EQ(memcmp(buffer, kFileData, sizeof(buffer)), 0);
stream_.ReturnEof();
ASSERT_OK(reader->Read(buffer, sizeof(buffer), &actual));
ASSERT_EQ(actual, 0);
}
TEST_F(StreamReaderTest, ReadMultiple) {
auto status = paver::StreamReader::Create(stream_.client());
ASSERT_OK(status);
std::unique_ptr<paver::StreamReader> reader = std::move(status.value());
char buffer[sizeof(kFileData)] = {};
size_t actual;
ASSERT_OK(reader->Read(buffer, sizeof(buffer), &actual));
ASSERT_EQ(actual, sizeof(buffer));
ASSERT_EQ(memcmp(buffer, kFileData, sizeof(buffer)), 0);
ASSERT_OK(reader->Read(buffer, sizeof(buffer), &actual));
ASSERT_EQ(actual, sizeof(buffer));
ASSERT_EQ(memcmp(buffer, kFileData, sizeof(buffer)), 0);
stream_.ReturnEof();
ASSERT_OK(reader->Read(buffer, sizeof(buffer), &actual));
ASSERT_EQ(actual, 0);
}
TEST_F(StreamReaderTest, ReadPartial) {
auto status = paver::StreamReader::Create(stream_.client());
ASSERT_OK(status);
std::unique_ptr<paver::StreamReader> reader = std::move(status.value());
constexpr size_t kBufferSize = sizeof(kFileData) - 3;
char buffer[kBufferSize] = {};
size_t actual;
ASSERT_OK(reader->Read(buffer, sizeof(buffer), &actual));
ASSERT_EQ(actual, sizeof(buffer));
ASSERT_EQ(memcmp(buffer, kFileData, sizeof(buffer)), 0);
stream_.ReturnEof();
ASSERT_OK(reader->Read(buffer, sizeof(buffer), &actual));
ASSERT_EQ(actual, 3);
ASSERT_EQ(memcmp(buffer, kFileData + kBufferSize, 3), 0);
ASSERT_OK(reader->Read(buffer, sizeof(buffer), &actual));
ASSERT_EQ(actual, 0);
}
} // namespace