aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/tests/CMakeLists.txt12
-rw-r--r--host/tests/common/CMakeLists.txt15
-rw-r--r--host/tests/common/mock_ctrl_iface_impl.cpp35
-rw-r--r--host/tests/common/mock_ctrl_iface_impl.hpp30
-rw-r--r--host/tests/common/mock_zero_copy.cpp29
-rw-r--r--host/tests/common/mock_zero_copy.hpp88
-rw-r--r--host/tests/device3_test.cpp145
7 files changed, 295 insertions, 59 deletions
diff --git a/host/tests/CMakeLists.txt b/host/tests/CMakeLists.txt
index 44c042f65..0424b1b53 100644
--- a/host/tests/CMakeLists.txt
+++ b/host/tests/CMakeLists.txt
@@ -11,6 +11,14 @@
include(UHDUnitTest)
########################################################################
+# build test common
+########################################################################
+SET(test_common_SOURCEDIR ${CMAKE_CURRENT_SOURCE_DIR}/common)
+ADD_SUBDIRECTORY(common)
+LINK_DIRECTORIES(test_common_SOURCEDIR)
+
+
+########################################################################
# unit test suite
########################################################################
SET(test_sources
@@ -74,12 +82,12 @@ IF(ENABLE_C_API)
ENDIF(ENABLE_C_API)
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/lib/include")
-
+INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/common")
#for each source: build an executable, register it as a test
FOREACH(test_source ${test_sources})
GET_FILENAME_COMPONENT(test_name ${test_source} NAME_WE)
ADD_EXECUTABLE(${test_name} ${test_source})
- TARGET_LINK_LIBRARIES(${test_name} uhd ${Boost_LIBRARIES})
+ TARGET_LINK_LIBRARIES(${test_name} uhd uhd_test ${Boost_LIBRARIES})
UHD_ADD_TEST(${test_name} ${test_name})
UHD_INSTALL(TARGETS ${test_name} RUNTIME DESTINATION ${PKG_LIB_DIR}/tests COMPONENT tests)
ENDFOREACH(test_source)
diff --git a/host/tests/common/CMakeLists.txt b/host/tests/common/CMakeLists.txt
new file mode 100644
index 000000000..91a70dfae
--- /dev/null
+++ b/host/tests/common/CMakeLists.txt
@@ -0,0 +1,15 @@
+#
+# Copyright 2018 Ettus Research, a National Instruments Company
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+
+########################################################################
+# Build uhd_test static lib
+########################################################################
+INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/lib/include")
+ADD_LIBRARY(uhd_test ${CMAKE_CURRENT_SOURCE_DIR}/mock_ctrl_iface_impl.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/mock_zero_copy.cpp
+ ${CMAKE_SOURCE_DIR}/lib/rfnoc/graph_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/rfnoc/async_msg_handler.cpp
+) \ No newline at end of file
diff --git a/host/tests/common/mock_ctrl_iface_impl.cpp b/host/tests/common/mock_ctrl_iface_impl.cpp
new file mode 100644
index 000000000..24a938e4f
--- /dev/null
+++ b/host/tests/common/mock_ctrl_iface_impl.cpp
@@ -0,0 +1,35 @@
+//
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#include "mock_ctrl_iface_impl.hpp"
+static const uint64_t TEST_NOC_ID = 0xAAAABBBBCCCCDDDD;
+
+uint64_t mock_ctrl_iface_impl::send_cmd_pkt(
+ const size_t addr,
+ const size_t data,
+ const bool readback,
+ const uint64_t timestamp
+) {
+ if (not readback) {
+ std::cout << str(boost::format("[MOCK] poke to addr: %016X, data == %016X") % addr % data) << std::endl;
+ } else {
+ std::cout << str(boost::format("[MOCK] peek64 to addr: %016X") % data) << std::endl;
+ switch (data) {
+ case uhd::rfnoc::SR_READBACK_REG_ID:
+ return TEST_NOC_ID;
+ case uhd::rfnoc::SR_READBACK_REG_FIFOSIZE:
+ return 0x0000000000010000;
+ case uhd::rfnoc::SR_READBACK_REG_USER:
+ return 0x0123456789ABCDEF;
+ case uhd::rfnoc::SR_READBACK_COMPAT:
+ return uhd::rfnoc::NOC_SHELL_COMPAT_MAJOR << 32 |
+ uhd::rfnoc::NOC_SHELL_COMPAT_MINOR;
+ default:
+ return 0;
+ }
+ }
+ return 0;
+} \ No newline at end of file
diff --git a/host/tests/common/mock_ctrl_iface_impl.hpp b/host/tests/common/mock_ctrl_iface_impl.hpp
new file mode 100644
index 000000000..8d2aafed6
--- /dev/null
+++ b/host/tests/common/mock_ctrl_iface_impl.hpp
@@ -0,0 +1,30 @@
+//
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+
+#ifndef INCLUDED_MOCK_CTRL_IFACE_IMPL_HPP
+#define INCLUDED_MOCK_CTRL_IFACE_IMPL_HPP
+
+#include <uhd/rfnoc/constants.hpp>
+#include <uhdlib/rfnoc/ctrl_iface.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/format.hpp>
+#include <boost/bind.hpp>
+#include <boost/make_shared.hpp>
+#include <queue>
+
+class mock_ctrl_iface_impl : public uhd::rfnoc::ctrl_iface
+{
+
+ uint64_t send_cmd_pkt(
+ const size_t addr,
+ const size_t data,
+ const bool readback=false,
+ const uint64_t timestamp=0
+ );
+};
+#endif /* INCLUDED_MOCK_CTRL_IFACE_IMPL_HPP */ \ No newline at end of file
diff --git a/host/tests/common/mock_zero_copy.cpp b/host/tests/common/mock_zero_copy.cpp
new file mode 100644
index 000000000..b1d384ec7
--- /dev/null
+++ b/host/tests/common/mock_zero_copy.cpp
@@ -0,0 +1,29 @@
+//
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+
+#include "mock_zero_copy.hpp"
+#include <boost/shared_ptr.hpp>
+
+uhd::transport::managed_recv_buffer::sptr mock_zero_copy::get_recv_buff(double) {
+ if (_rx_mems.empty()) {
+ return uhd::transport::managed_recv_buffer::sptr(); // timeout
+ }
+ _mrbs.push_back(boost::make_shared<mock_mrb>());
+ uhd::transport::managed_recv_buffer::sptr mrb =
+ _mrbs.back()->get_new(_rx_mems.front(), _rx_lens.front());
+ _rx_mems.pop_front();
+ _rx_lens.pop_front();
+ return mrb;
+}
+
+uhd::transport::managed_send_buffer::sptr mock_zero_copy::get_send_buff(double) {
+ _msbs.push_back(boost::make_shared<mock_msb>());
+ _tx_mems.push_back(
+ boost::shared_array<uint8_t>(new uint8_t[SEND_BUFF_SIZE]));
+ _tx_lens.push_back(SEND_BUFF_SIZE);
+ return _msbs.back()->get_new(_tx_mems.back(), &_tx_lens.back());
+}
diff --git a/host/tests/common/mock_zero_copy.hpp b/host/tests/common/mock_zero_copy.hpp
new file mode 100644
index 000000000..838975129
--- /dev/null
+++ b/host/tests/common/mock_zero_copy.hpp
@@ -0,0 +1,88 @@
+//
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#ifndef INCLUDED_MOCK_XPORT_HPP
+#define INCLUDED_MOCK_XPORT_HPP
+
+#include <uhdlib/rfnoc/xports.hpp>
+#include <uhd/transport/chdr.hpp>
+#include <uhd/transport/vrt_if_packet.hpp>
+#include <uhd/transport/zero_copy.hpp>
+#include <uhd/types/endianness.hpp>
+#include <uhd/types/sid.hpp>
+#include <uhd/utils/byteswap.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/shared_array.hpp>
+#include <list>
+#include <vector>
+/***********************************************************************
+ * Transport mockups
+ **********************************************************************/
+/*! A single transport class that implements send() and recv()
+ *
+ * Tx and Rx are separate. We can access the other end of the FIFOs from
+ * this class.
+ */
+static constexpr size_t SEND_BUFF_SIZE = 1024;
+static constexpr size_t RECV_BUFF_SIZE = 1024;
+
+/***********************************************************************
+ * Dummy managed buffers for testing
+ **********************************************************************/
+class mock_msb : public uhd::transport::managed_send_buffer {
+ public:
+ void release(void) { /* nop */
+ }
+
+ sptr get_new(boost::shared_array<uint8_t> mem, size_t* len) {
+ _mem = mem;
+ return make(this, mem.get(), *len);
+ }
+
+ private:
+ boost::shared_array<uint8_t> _mem;
+};
+
+
+class mock_mrb : public uhd::transport::managed_recv_buffer {
+ public:
+ void release(void) { /* nop */
+ }
+
+ sptr get_new(boost::shared_array<uint8_t> mem, size_t len) {
+ _mem = mem;
+ return make(this, _mem.get(), len);
+ }
+
+ private:
+ boost::shared_array<uint8_t> _mem;
+};
+
+class mock_zero_copy : public uhd::transport::zero_copy_if {
+ public:
+ typedef boost::shared_ptr<mock_zero_copy> sptr;
+ uhd::transport::managed_recv_buffer::sptr get_recv_buff(double);
+
+ uhd::transport::managed_send_buffer::sptr get_send_buff(double);
+
+ size_t get_num_recv_frames(void) const { return 1; }
+ size_t get_num_send_frames(void) const { return 1; }
+ size_t get_recv_frame_size(void) const { return RECV_BUFF_SIZE; }
+ size_t get_send_frame_size(void) const { return SEND_BUFF_SIZE; }
+
+ private:
+ std::list<boost::shared_array<uint8_t>> _tx_mems;
+ std::list<size_t> _tx_lens;
+
+ std::list<boost::shared_array<uint8_t>> _rx_mems;
+ std::list<size_t> _rx_lens;
+
+ std::vector<boost::shared_ptr<mock_msb>> _msbs;
+ std::vector<boost::shared_ptr<mock_mrb>> _mrbs;
+};
+
+#endif /*INCLUDED_MOCK_XPORT_HPP*/ \ No newline at end of file
diff --git a/host/tests/device3_test.cpp b/host/tests/device3_test.cpp
index eb29d560f..658855f15 100644
--- a/host/tests/device3_test.cpp
+++ b/host/tests/device3_test.cpp
@@ -5,71 +5,53 @@
// SPDX-License-Identifier: GPL-3.0-or-later
//
-#include <uhd/property_tree.hpp>
-#include <uhd/types/wb_iface.hpp>
+
+#include "mock_zero_copy.hpp"
+#include "mock_ctrl_iface_impl.hpp"
#include <uhd/device3.hpp>
+#include <uhd/property_tree.hpp>
#include <uhd/rfnoc/block_ctrl.hpp>
#include <uhd/rfnoc/graph.hpp>
-#include <uhd/rfnoc/constants.hpp>
-#include <uhdlib/rfnoc/ctrl_iface.hpp>
+#include <uhdlib/rfnoc/graph_impl.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/shared_ptr.hpp>
#include <boost/test/unit_test.hpp>
#include <exception>
#include <iostream>
+
+
using namespace uhd;
using namespace uhd::rfnoc;
+using namespace uhd::transport::vrt;
+using uhd::transport::managed_send_buffer;
+using uhd::transport::managed_recv_buffer;
-static const uint64_t TEST_NOC_ID = 0xAAAABBBBCCCCDDDD;
static const sid_t TEST_SID0 = 0x00000200; // 0.0.2.0
static const sid_t TEST_SID1 = 0x00000210; // 0.0.2.F
-// Pseudo-wb-iface
-class pseudo_ctrl_iface_impl : public ctrl_iface
-{
- public:
- pseudo_ctrl_iface_impl() {}
- virtual ~pseudo_ctrl_iface_impl() {}
-
- uint64_t send_cmd_pkt(
- const size_t addr,
- const size_t data,
- const bool readback=false,
- const uint64_t timestamp=0
- ) {
- if (not readback) {
- std::cout << str(boost::format("[PSEUDO] poke to addr: %016X, data == %016X") % addr % data) << std::endl;
- } else {
- std::cout << str(boost::format("[PSEUDO] peek64 to addr: %016X") % data) << std::endl;
- switch (data) {
- case SR_READBACK_REG_ID:
- return TEST_NOC_ID;
- case SR_READBACK_REG_FIFOSIZE:
- return 0x000000000000000B;
- case SR_READBACK_REG_USER:
- return 0x0123456789ABCDEF;
- case SR_READBACK_COMPAT:
- return uhd::rfnoc::NOC_SHELL_COMPAT_MAJOR << 32 |
- uhd::rfnoc::NOC_SHELL_COMPAT_MINOR;
- default:
- return 0;
- }
- }
- return 0;
- }
-};
+uhd::both_xports_t make_mock_transport(const uhd::sid_t& tx_sid) {
+ uhd::both_xports_t xports;
+ xports.send_sid = tx_sid;
+ xports.recv_sid = tx_sid.reversed();
+ xports.send_buff_size = SEND_BUFF_SIZE;
+ xports.recv_buff_size = RECV_BUFF_SIZE;
+ xports.send = boost::make_shared<mock_zero_copy>();
+ xports.recv = xports.send;
+ return xports;
+}
-// Pseudo-device
-class pseudo_device3_impl : public uhd::device3
+// Mock-device
+class mock_device3_impl : public uhd::device3, public boost::enable_shared_from_this<mock_device3_impl>
{
public:
- pseudo_device3_impl()
+ mock_device3_impl()
{
_tree = uhd::property_tree::make();
- _tree->create<std::string>("/name").set("Test Pseudo-Device3");
-
+ _tree->create<std::string>("/name").set("Test Mock-Device3");
// We can re-use this:
std::map<size_t, ctrl_iface::sptr> ctrl_ifaces{
- {0, ctrl_iface::sptr(new pseudo_ctrl_iface_impl())}
+ {0, ctrl_iface::sptr(new mock_ctrl_iface_impl())}
};
// Add two block controls:
@@ -78,10 +60,9 @@ class pseudo_device3_impl : public uhd::device3
make_args.base_address = TEST_SID0.get_dst();
make_args.device_index = 0;
make_args.tree = _tree;
- std::cout << "[PSEUDO] Generating block controls 1/2:" << std::endl;
+ std::cout << "[MOCK] Generating block controls 1/2:" << std::endl;
_rfnoc_block_ctrl.push_back( block_ctrl_base::make(make_args) );
-
- std::cout << "[PSEUDO] Generating block controls 2/2:" << std::endl;
+ std::cout << "[MOCK] Generating block controls 2/2:" << std::endl;
make_args.base_address = TEST_SID1.get_dst();
_rfnoc_block_ctrl.push_back( block_ctrl::make(make_args) );
}
@@ -98,20 +79,38 @@ class pseudo_device3_impl : public uhd::device3
throw uhd::not_implemented_error(str(boost::format("%d %f") % async_metadata.channel % timeout));
}
- rfnoc::graph::sptr create_graph(const std::string &) { return rfnoc::graph::sptr(); }
+ rfnoc::graph::sptr create_graph(const std::string &name)
+ {
+ sid_t async_sid(0);
+ async_sid.set_dst_addr(2);
+ auto async_xports = make_mock_transport(async_sid);
+
+ auto async_msg_handler = uhd::rfnoc::async_msg_handler::make(
+ async_xports.recv,
+ async_xports.send,
+ async_xports.send_sid,
+ async_xports.endianness
+ );
+ auto graph = boost::make_shared<uhd::rfnoc::graph_impl>(
+ name,
+ shared_from_this(),
+ async_msg_handler
+ );
+ return graph;
+ }
};
-device3::sptr make_pseudo_device()
+device3::sptr make_mock_device()
{
- return device3::sptr(new pseudo_device3_impl());
+ return device3::sptr(new mock_device3_impl());
}
-class dummy_block_ctrl : public block_ctrl {
+class mock_block_ctrl : public block_ctrl {
int foo;
};
BOOST_AUTO_TEST_CASE(test_device3) {
- device3::sptr my_device = make_pseudo_device();
+ device3::sptr my_device = make_mock_device();
std::cout << "Checking block 0..." << std::endl;
BOOST_REQUIRE(my_device->find_blocks("Block").size());
@@ -130,8 +129,40 @@ BOOST_AUTO_TEST_CASE(test_device3) {
BOOST_CHECK_EQUAL(block1->get_block_id(), "0/Block_1");
}
+
+BOOST_AUTO_TEST_CASE(test_device3_graph) {
+ auto my_device = make_mock_device();
+ std::cout << "Start device3 test graph.." << std::endl;
+ std::cout << "Checking block 0..." << std::endl;
+ BOOST_REQUIRE(my_device->find_blocks("Block").size());
+ std::cout << "Getting block 0..." << std::endl;
+ auto block0 = my_device->get_block_ctrl(my_device->find_blocks("Block")[0]);
+ BOOST_REQUIRE(block0);
+ BOOST_CHECK_EQUAL(block0->get_block_id(), "0/Block_0");
+
+ std::cout << "Checking block 1..." << std::endl;
+ BOOST_REQUIRE(my_device->has_block(block_id_t("0/Block_1")));
+
+ std::cout << "Getting block 1..." << std::endl;
+ auto block1 = my_device->get_block_ctrl(block_id_t("0/Block_1"));
+ BOOST_REQUIRE(block1);
+ BOOST_CHECK_EQUAL(block1->get_block_id(), "0/Block_1");
+ std::cout << "Creating graph..." << std::endl;
+ auto graph = my_device->create_graph("test_graph");
+ BOOST_CHECK(graph);
+ std::cout << "Connecting block_0 to block_1 ..." << std::endl;
+ graph->connect(block_id_t("0/Block_0"), 0, block_id_t("0/Block_1"), 0);
+
+ BOOST_CHECK_EQUAL(block0->list_upstream_nodes().size(),0);
+ BOOST_CHECK_EQUAL(block0->list_downstream_nodes().size(),1);
+ BOOST_CHECK_EQUAL(block0->list_downstream_nodes()[0].lock()->unique_id(),"0/Block_1");
+ BOOST_CHECK_EQUAL(block1->list_upstream_nodes().size(),1);
+ BOOST_CHECK_EQUAL(block1->list_downstream_nodes().size(),0);
+ BOOST_CHECK_EQUAL(block1->list_upstream_nodes()[0].lock()->unique_id(),"0/Block_0");
+}
+
BOOST_AUTO_TEST_CASE(test_device3_cast) {
- device3::sptr my_device = make_pseudo_device();
+ device3::sptr my_device = make_mock_device();
std::cout << "Getting block 0..." << std::endl;
block_ctrl::sptr block0 = my_device->get_block_ctrl<block_ctrl>(block_id_t("0/Block_0"));
@@ -144,10 +175,10 @@ BOOST_AUTO_TEST_CASE(test_device3_cast) {
}
BOOST_AUTO_TEST_CASE(test_device3_fail) {
- device3::sptr my_device = make_pseudo_device();
+ device3::sptr my_device = make_mock_device();
BOOST_CHECK(not my_device->has_block(block_id_t("0/FooBarBlock_0")));
- BOOST_CHECK(not my_device->has_block<dummy_block_ctrl>(block_id_t("0/Block_1")));
+ BOOST_CHECK(not my_device->has_block<mock_block_ctrl>(block_id_t("0/Block_1")));
BOOST_CHECK(my_device->find_blocks("FooBarBlock").size() == 0);
BOOST_CHECK(my_device->find_blocks<block_ctrl>("FooBarBlock").size() == 0);
@@ -157,7 +188,7 @@ BOOST_AUTO_TEST_CASE(test_device3_fail) {
uhd::lookup_error
);
BOOST_REQUIRE_THROW(
- my_device->get_block_ctrl<dummy_block_ctrl>(block_id_t("0/Block_1")),
+ my_device->get_block_ctrl<mock_block_ctrl>(block_id_t("0/Block_1")),
uhd::lookup_error
);
}