blob: a36cb603146cba32d70a17242674830ac51c6ca1 [file] [log] [blame]
// Copyright 2020 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 "server.h"
#include <lib/sync/completion.h>
#include <unistd.h>
#include <thread>
#include <zxtest/zxtest.h>
#include "test/stub-block-device.h"
namespace {
class ServerTestFixture : public zxtest::Test {
public:
ServerTestFixture() : client_(blkdev_.proto()) {}
protected:
void SetUp() override {}
void TearDown() override;
void CreateThread();
void WaitForThreadStart();
void WaitForThreadExit();
void JoinThread();
StubBlockDevice blkdev_;
ddk::BlockProtocolClient client_;
std::unique_ptr<Server> server_;
fzl::fifo<block_fifo_request_t, block_fifo_response_t> fifo_;
private:
static int RunServer(void* arg);
sync_completion_t thread_started_;
sync_completion_t thread_exited_;
bool is_thread_running_ = false;
std::thread thread_;
};
void ServerTestFixture::TearDown() { ASSERT_FALSE(is_thread_running_); }
int ServerTestFixture::RunServer(void* arg) {
ServerTestFixture* fix = static_cast<ServerTestFixture*>(arg);
sync_completion_signal(&fix->thread_started_);
fix->server_->Serve();
sync_completion_signal(&fix->thread_exited_);
return 0;
}
void ServerTestFixture::CreateThread() {
std::thread th(RunServer, this);
thread_ = std::move(th);
is_thread_running_ = true;
}
void ServerTestFixture::WaitForThreadStart() {
ASSERT_OK(sync_completion_wait(&thread_started_, ZX_SEC(5)));
}
void ServerTestFixture::WaitForThreadExit() {
ASSERT_OK(sync_completion_wait(&thread_exited_, ZX_SEC(5)));
}
void ServerTestFixture::JoinThread() {
thread_.join();
is_thread_running_ = false;
}
TEST_F(ServerTestFixture, CreateServer) { ASSERT_OK(Server::Create(&client_, &fifo_, &server_)); }
TEST_F(ServerTestFixture, StartServer) {
ASSERT_OK(Server::Create(&client_, &fifo_, &server_));
CreateThread();
WaitForThreadStart();
// This code is racy with Serve() being called. This is expected.
// The server should handle shutdown commands at any time.
server_->Shutdown();
WaitForThreadExit();
JoinThread();
}
TEST_F(ServerTestFixture, CloseFifo) {
ASSERT_OK(Server::Create(&client_, &fifo_, &server_));
CreateThread();
WaitForThreadStart();
// Allow the server thread to do some work. The thread may not always get to make progress
// before the fifo is closed, but the server thread should handle it regardless.
usleep(20 * 1000);
fifo_.reset();
WaitForThreadExit();
JoinThread();
}
} // namespace