blob: 8710e7629d3179827027ae1316b91ad8b8c29546 [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 "stream-reader.h"
#include <fcntl.h>
#include <fuchsia/paver/c/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/fidl-utils/bind.h>
#include <zxtest/zxtest.h>
namespace {
constexpr char kFileData[] = "lalalala";
TEST(StreamReaderTest, InvalidChannel) {
std::unique_ptr<paver::StreamReader> reader;
ASSERT_NE(paver::StreamReader::Create(zx::channel(), &reader), ZX_OK);
}
class StreamReaderTest : public zxtest::Test {
public:
StreamReaderTest()
: loop_(&kAsyncLoopConfigAttachToThread) {
zx::channel server;
ASSERT_OK(zx::channel::create(0, &client_, &server));
fidl_bind(loop_.dispatcher(), server.release(),
reinterpret_cast<fidl_dispatch_t*>(fuchsia_paver_PayloadStream_dispatch),
this, &ops_);
loop_.StartThread("payload-stream-test-loop");
}
zx_status_t ReadSuccess(fidl_txn_t* txn) {
fuchsia_paver_ReadResult result = {};
vmo_.write(kFileData, 0, sizeof(kFileData));
result.tag = fuchsia_paver_ReadResultTag_info;
result.info.offset = 0;
result.info.size = sizeof(kFileData);
return fuchsia_paver_PayloadStreamReadData_reply(txn, &result);
}
zx_status_t ReadError(fidl_txn_t* txn) {
fuchsia_paver_ReadResult result = {};
result.tag = fuchsia_paver_ReadResultTag_err;
result.err = ZX_ERR_INTERNAL;
return fuchsia_paver_PayloadStreamReadData_reply(txn, &result);
}
zx_status_t ReadEof(fidl_txn_t* txn) {
fuchsia_paver_ReadResult result = {};
result.tag = fuchsia_paver_ReadResultTag_eof;
result.eof = true;
return fuchsia_paver_PayloadStreamReadData_reply(txn, &result);
}
zx_status_t ReadData(fidl_txn_t* txn) {
if (!vmo_) {
return ZX_ERR_BAD_STATE;
}
if (return_err_) {
return ReadError(txn);
} else if (return_eof_) {
return ReadEof(txn);
} else {
return ReadSuccess(txn);
}
}
zx_status_t RegisterVmo(zx_handle_t vmo_handle, fidl_txn_t* txn) {
vmo_ = zx::vmo(vmo_handle);
return fuchsia_paver_PayloadStreamRegisterVmo_reply(txn, ZX_OK);
}
protected:
using Binder = fidl::Binder<StreamReaderTest>;
zx::channel client_;
async::Loop loop_;
static constexpr fuchsia_paver_PayloadStream_ops_t ops_ = {
.RegisterVmo = Binder::BindMember<&StreamReaderTest::RegisterVmo>,
.ReadData = Binder::BindMember<&StreamReaderTest::ReadData>,
};
zx::vmo vmo_;
bool return_err_ = false;
bool return_eof_ = false;
};
TEST_F(StreamReaderTest, Create) {
std::unique_ptr<paver::StreamReader> reader;
ASSERT_OK(paver::StreamReader::Create(std::move(client_), &reader));
}
TEST_F(StreamReaderTest, ReadError) {
std::unique_ptr<paver::StreamReader> reader;
ASSERT_OK(paver::StreamReader::Create(std::move(client_), &reader));
return_err_ = true;
char buffer[sizeof(kFileData)] = {};
size_t actual;
ASSERT_NE(reader->Read(buffer, sizeof(buffer), &actual), ZX_OK);
}
TEST_F(StreamReaderTest, ReadEof) {
std::unique_ptr<paver::StreamReader> reader;
ASSERT_OK(paver::StreamReader::Create(std::move(client_), &reader));
return_eof_ = true;
char buffer[sizeof(kFileData)] = {};
size_t actual;
ASSERT_OK(reader->Read(buffer, sizeof(buffer), &actual));
ASSERT_EQ(actual, 0);
}
TEST_F(StreamReaderTest, ReadSingle) {
std::unique_ptr<paver::StreamReader> reader;
ASSERT_OK(paver::StreamReader::Create(std::move(client_), &reader));
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);
return_eof_ = true;
ASSERT_OK(reader->Read(buffer, sizeof(buffer), &actual));
ASSERT_EQ(actual, 0);
}
TEST_F(StreamReaderTest, ReadMultiple) {
std::unique_ptr<paver::StreamReader> reader;
ASSERT_OK(paver::StreamReader::Create(std::move(client_), &reader));
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);
return_eof_ = true;
ASSERT_OK(reader->Read(buffer, sizeof(buffer), &actual));
ASSERT_EQ(actual, 0);
}
TEST_F(StreamReaderTest, ReadPartial) {
std::unique_ptr<paver::StreamReader> reader;
ASSERT_OK(paver::StreamReader::Create(std::move(client_), &reader));
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);
return_eof_ = true;
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