diff options
Diffstat (limited to 'host/tests/offload_io_srv_test.cpp')
-rw-r--r-- | host/tests/offload_io_srv_test.cpp | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/host/tests/offload_io_srv_test.cpp b/host/tests/offload_io_srv_test.cpp new file mode 100644 index 000000000..99bd6dd53 --- /dev/null +++ b/host/tests/offload_io_srv_test.cpp @@ -0,0 +1,278 @@ +// +// Copyright 2019 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#include "common/mock_link.hpp" +#include <uhdlib/transport/offload_io_service.hpp> +#include <boost/test/unit_test.hpp> +#include <iostream> +#include <atomic> + +using namespace uhd::transport; + +class mock_recv_io; +constexpr size_t FRAME_SIZE = 1000; + +static mock_send_link::sptr make_send_link(size_t num_frames) +{ + const mock_send_link::link_params params = {FRAME_SIZE, num_frames}; + return std::make_shared<mock_send_link>(params); +} + +static mock_recv_link::sptr make_recv_link(size_t num_frames) +{ + const mock_recv_link::link_params params = {FRAME_SIZE, num_frames}; + return std::make_shared<mock_recv_link>(params); +} + +class mock_recv_io : public recv_io_if +{ +public: + mock_recv_io(recv_link_if::sptr link) : _link(link) {} + + frame_buff::uptr get_recv_buff(int32_t timeout_ms) + { + if (_frames_allocated > 0) { + _frames_allocated--; + return _link->get_recv_buff(timeout_ms); + } + return nullptr; + } + + void release_recv_buff(frame_buff::uptr buff) + { + _link->release_recv_buff(std::move(buff)); + } + + size_t get_num_send_frames() const + { + return 0; + } + + size_t get_num_recv_frames() const + { + return _link->get_num_recv_frames(); + } + + void allocate_frames(const size_t num_frames) + { + _frames_allocated += num_frames; + } + +private: + std::atomic<size_t> _frames_allocated{0}; + recv_link_if::sptr _link; +}; + +class mock_send_io : public send_io_if +{ +public: + mock_send_io(send_link_if::sptr link) : _link(link) {} + + frame_buff::uptr get_send_buff(int32_t timeout_ms) + { + return _link->get_send_buff(timeout_ms); + } + + void release_send_buff(frame_buff::uptr buff) + { + _link->release_send_buff(std::move(buff)); + } + + size_t get_num_send_frames() const + { + return _link->get_num_send_frames(); + } + + size_t get_num_recv_frames() const + { + return 0; + } + +private: + send_link_if::sptr _link; +}; + +class mock_io_service : public io_service +{ +public: + void attach_recv_link(recv_link_if::sptr /*link*/) {} + + void attach_send_link(send_link_if::sptr /*link*/) {} + + send_io_if::sptr make_send_client(send_link_if::sptr send_link, + size_t /*num_send_frames*/, + send_io_if::send_callback_t /*cb*/, + recv_link_if::sptr /*recv_link*/, + size_t /*num_recv_frames*/, + recv_callback_t /*recv_cb*/) + { + return std::make_shared<mock_send_io>(send_link); + } + + recv_io_if::sptr make_recv_client(recv_link_if::sptr recv_link, + size_t /*num_recv_frames*/, + recv_callback_t /*cb*/, + send_link_if::sptr /*fc_link*/, + size_t /*num_send_frames*/, + recv_io_if::fc_callback_t /*fc_cb*/) + { + auto io = std::make_shared<mock_recv_io>(recv_link); + _recv_io.push_back(io); + return io; + } + + void allocate_recv_frames(const size_t client_idx, const size_t num_frames) + { + assert(client_idx < _recv_io.size()); + _recv_io[client_idx]->allocate_frames(num_frames); + } + +private: + std::vector<std::shared_ptr<mock_recv_io>> _recv_io; +}; + +constexpr auto RECV_ONLY = offload_io_service::RECV_ONLY; +constexpr auto SEND_ONLY = offload_io_service::SEND_ONLY; +constexpr auto BOTH_SEND_AND_RECV = offload_io_service::BOTH_SEND_AND_RECV; + +constexpr auto POLL = offload_io_service::POLL; +constexpr auto BLOCK = offload_io_service::BLOCK; +using params_t = offload_io_service::params_t; + +std::vector<offload_io_service::wait_mode_t> wait_modes({POLL, BLOCK}); + +BOOST_AUTO_TEST_CASE(test_construction) +{ + for (const auto wait_mode : wait_modes) { + params_t params {{}, SEND_ONLY, wait_mode}; + auto mock_io_srv = std::make_shared<mock_io_service>(); + auto io_srv = offload_io_service::make(mock_io_srv, params_t()); + auto send_link = make_send_link(5); + io_srv->attach_send_link(send_link); + auto send_client = + io_srv->make_send_client(send_link, 5, nullptr, nullptr, 0, nullptr); + } + for (const auto wait_mode : wait_modes) { + params_t params {{}, RECV_ONLY, wait_mode}; + auto mock_io_srv = std::make_shared<mock_io_service>(); + auto io_srv = offload_io_service::make(mock_io_srv, params_t()); + auto recv_link = make_recv_link(5); + io_srv->attach_recv_link(recv_link); + auto recv_client = + io_srv->make_recv_client(recv_link, 5, nullptr, nullptr, 0, nullptr); + } +} + +BOOST_AUTO_TEST_CASE(test_construction_with_options) +{ + offload_io_service::params_t params; + params.cpu_affinity_list = {0}; + + auto mock_io_srv = std::make_shared<mock_io_service>(); + auto io_srv = offload_io_service::make(mock_io_srv, params); + auto send_link = make_send_link(5); + io_srv->attach_send_link(send_link); + auto recv_link = make_recv_link(5); + io_srv->attach_recv_link(recv_link); + auto send_client = + io_srv->make_send_client(send_link, 5, nullptr, nullptr, 0, nullptr); + auto recv_client = + io_srv->make_recv_client(recv_link, 5, nullptr, nullptr, 0, nullptr); +} + +BOOST_AUTO_TEST_CASE(test_send) +{ + for (const auto wait_mode : wait_modes) { + params_t params = {{}, SEND_ONLY, wait_mode}; + auto mock_io_srv = std::make_shared<mock_io_service>(); + auto io_srv = offload_io_service::make(mock_io_srv, params); + auto send_link = make_send_link(5); + io_srv->attach_send_link(send_link); + auto send_client = + io_srv->make_send_client(send_link, 1, nullptr, nullptr, 0, nullptr); + + for (size_t i = 0; i < 10; i++) { + auto buff = send_client->get_send_buff(100); + BOOST_CHECK(buff != nullptr); + send_client->release_send_buff(std::move(buff)); + } + send_client.reset(); + } +} + +BOOST_AUTO_TEST_CASE(test_recv) +{ + for (const auto wait_mode : wait_modes) { + params_t params = {{}, RECV_ONLY, wait_mode}; + auto mock_io_srv = std::make_shared<mock_io_service>(); + auto io_srv = offload_io_service::make(mock_io_srv, params); + auto recv_link = make_recv_link(5); + io_srv->attach_recv_link(recv_link); + + auto recv_client = + io_srv->make_recv_client(recv_link, 1, nullptr, nullptr, 0, nullptr); + + for (size_t i = 0; i < 10; i++) { + recv_link->push_back_recv_packet( + boost::shared_array<uint8_t>(new uint8_t[FRAME_SIZE]), FRAME_SIZE); + } + BOOST_CHECK(recv_client); + mock_io_srv->allocate_recv_frames(0, 10); + + for (size_t i = 0; i < 10; i++) { + auto buff = recv_client->get_recv_buff(100); + BOOST_CHECK(buff != nullptr); + recv_client->release_recv_buff(std::move(buff)); + } + recv_client.reset(); + } +} + +BOOST_AUTO_TEST_CASE(test_send_recv) +{ + auto mock_io_srv = std::make_shared<mock_io_service>(); + auto io_srv = offload_io_service::make(mock_io_srv, params_t()); + auto send_link = make_send_link(5); + io_srv->attach_send_link(send_link); + auto recv_link = make_recv_link(5); + io_srv->attach_recv_link(recv_link); + + auto send_client = + io_srv->make_send_client(send_link, 1, nullptr, nullptr, 0, nullptr); + auto recv_client = + io_srv->make_recv_client(recv_link, 1, nullptr, nullptr, 0, nullptr); + + for (size_t i = 0; i < 20; i++) { + recv_link->push_back_recv_packet( + boost::shared_array<uint8_t>(new uint8_t[FRAME_SIZE]), FRAME_SIZE); + } + + for (size_t i = 0; i < 10; i++) { + send_client->release_send_buff(send_client->get_send_buff(100)); + mock_io_srv->allocate_recv_frames(0, 1); + recv_client->release_recv_buff(recv_client->get_recv_buff(100)); + } + + auto recv_client2 = + io_srv->make_recv_client(recv_link, 1, nullptr, nullptr, 0, nullptr); + auto send_client2 = + io_srv->make_send_client(send_link, 1, nullptr, nullptr, 0, nullptr); + for (size_t i = 0; i < 5; i++) { + mock_io_srv->allocate_recv_frames(1, 1); + recv_client2->release_recv_buff(recv_client2->get_recv_buff(100)); + send_client2->release_send_buff(send_client2->get_send_buff(100)); + } + send_client2.reset(); + recv_client2.reset(); + + for (size_t i = 0; i < 5; i++) { + mock_io_srv->allocate_recv_frames(0, 1); + recv_client->release_recv_buff(recv_client->get_recv_buff(100)); + } + + send_client.reset(); + recv_client.reset(); +} |