aboutsummaryrefslogtreecommitdiffstats
path: root/host/tests
diff options
context:
space:
mode:
Diffstat (limited to 'host/tests')
-rw-r--r--host/tests/CMakeLists.txt56
-rw-r--r--host/tests/addr_test.cpp80
-rw-r--r--host/tests/buffer_test.cpp64
-rw-r--r--host/tests/byteswap_test.cpp39
-rw-r--r--host/tests/convert_test.cpp262
-rw-r--r--host/tests/dict_test.cpp72
-rw-r--r--host/tests/error_test.cpp59
-rw-r--r--host/tests/gain_group_test.cpp122
-rw-r--r--host/tests/module_test.cpp26
-rw-r--r--host/tests/ranges_test.cpp57
-rw-r--r--host/tests/subdev_spec_test.cpp45
-rw-r--r--host/tests/time_spec_test.cpp80
-rw-r--r--host/tests/tune_helper_test.cpp251
-rw-r--r--host/tests/vrt_test.cpp141
-rw-r--r--host/tests/warning_test.cpp29
-rw-r--r--host/tests/wax_test.cpp104
16 files changed, 1487 insertions, 0 deletions
diff --git a/host/tests/CMakeLists.txt b/host/tests/CMakeLists.txt
new file mode 100644
index 000000000..f08fe669b
--- /dev/null
+++ b/host/tests/CMakeLists.txt
@@ -0,0 +1,56 @@
+#
+# Copyright 2010-2011 Ettus Research LLC
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+########################################################################
+# unit test suite
+########################################################################
+SET(test_sources
+ addr_test.cpp
+ buffer_test.cpp
+ byteswap_test.cpp
+ convert_test.cpp
+ dict_test.cpp
+ error_test.cpp
+ gain_group_test.cpp
+ ranges_test.cpp
+ subdev_spec_test.cpp
+ time_spec_test.cpp
+ tune_helper_test.cpp
+ vrt_test.cpp
+ warning_test.cpp
+ wax_test.cpp
+)
+
+#turn each test cpp file into an executable with an int main() function
+ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK -DBOOST_TEST_MAIN)
+
+#for each source: build an executable, register it as a test, and install
+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)
+ ADD_TEST(${test_name} ${test_name})
+ INSTALL(TARGETS ${test_name} RUNTIME DESTINATION ${PKG_DATA_DIR}/tests COMPONENT tests)
+ENDFOREACH(test_source)
+
+########################################################################
+# demo of a loadable module
+########################################################################
+IF(MSVC OR APPLE OR LINUX)
+ ADD_LIBRARY(module_test MODULE module_test.cpp)
+ TARGET_LINK_LIBRARIES(module_test uhd)
+ENDIF()
diff --git a/host/tests/addr_test.cpp b/host/tests/addr_test.cpp
new file mode 100644
index 000000000..01a7ab607
--- /dev/null
+++ b/host/tests/addr_test.cpp
@@ -0,0 +1,80 @@
+//
+// Copyright 2010-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <boost/test/unit_test.hpp>
+#include <uhd/types/mac_addr.hpp>
+#include <uhd/types/device_addr.hpp>
+#include <uhd/usrp/dboard_id.hpp>
+#include <boost/assign/list_of.hpp>
+#include <boost/foreach.hpp>
+#include <algorithm>
+#include <iostream>
+
+BOOST_AUTO_TEST_CASE(test_mac_addr){
+ std::cout << "Testing mac addr..." << std::endl;
+ const std::string mac_addr_str("00:01:23:45:67:89");
+ uhd::mac_addr_t mac_addr = uhd::mac_addr_t::from_string(mac_addr_str);
+ std::cout << "Input: " << mac_addr_str << std::endl;
+ std::cout << "Output: " << mac_addr.to_string() << std::endl;
+ BOOST_CHECK_EQUAL(mac_addr_str, mac_addr.to_string());
+}
+
+BOOST_AUTO_TEST_CASE(test_device_addr){
+ std::cout << "Testing device addr..." << std::endl;
+
+ //load the device address with something
+ uhd::device_addr_t dev_addr;
+ dev_addr["key1"] = "val1";
+ dev_addr["key2"] = "val2";
+
+ //convert to and from args string
+ std::cout << "Pretty Print: " << std::endl << dev_addr.to_pp_string();
+ std::string args_str = dev_addr.to_string();
+ std::cout << "Args String: " << args_str << std::endl;
+ uhd::device_addr_t new_dev_addr(args_str);
+
+ //they should be the same size
+ BOOST_REQUIRE_EQUAL(dev_addr.size(), new_dev_addr.size());
+
+ //the keys should match
+ std::vector<std::string> old_dev_addr_keys = dev_addr.keys();
+ std::vector<std::string> new_dev_addr_keys = new_dev_addr.keys();
+ BOOST_CHECK_EQUAL_COLLECTIONS(
+ old_dev_addr_keys.begin(), old_dev_addr_keys.end(),
+ new_dev_addr_keys.begin(), new_dev_addr_keys.end()
+ );
+
+ //the vals should match
+ std::vector<std::string> old_dev_addr_vals = dev_addr.vals();
+ std::vector<std::string> new_dev_addr_vals = new_dev_addr.vals();
+ BOOST_CHECK_EQUAL_COLLECTIONS(
+ old_dev_addr_vals.begin(), old_dev_addr_vals.end(),
+ new_dev_addr_vals.begin(), new_dev_addr_vals.end()
+ );
+}
+
+BOOST_AUTO_TEST_CASE(test_dboard_id){
+ std::cout << "Testing dboard id..." << std::endl;
+
+ using namespace uhd::usrp;
+
+ BOOST_CHECK(dboard_id_t() == dboard_id_t::none());
+ BOOST_CHECK_EQUAL(dboard_id_t().to_uint16(), dboard_id_t::none().to_uint16());
+ BOOST_CHECK_EQUAL(dboard_id_t::from_string("0x1234").to_uint16(), 0x1234);
+ BOOST_CHECK_EQUAL(dboard_id_t::from_string("1234").to_uint16(), 1234);
+ std::cout << "Pretty Print: " << std::endl << dboard_id_t::none().to_pp_string();
+}
diff --git a/host/tests/buffer_test.cpp b/host/tests/buffer_test.cpp
new file mode 100644
index 000000000..23b52a9bf
--- /dev/null
+++ b/host/tests/buffer_test.cpp
@@ -0,0 +1,64 @@
+//
+// Copyright 2010-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <boost/test/unit_test.hpp>
+#include <uhd/transport/bounded_buffer.hpp>
+#include <boost/assign/list_of.hpp>
+
+using namespace boost::assign;
+using namespace uhd::transport;
+
+static const double timeout = 0.01/*secs*/;
+
+BOOST_AUTO_TEST_CASE(test_bounded_buffer_with_timed_wait){
+ bounded_buffer<int> bb(3);
+
+ //push elements, check for timeout
+ BOOST_CHECK(bb.push_with_timed_wait(0, timeout));
+ BOOST_CHECK(bb.push_with_timed_wait(1, timeout));
+ BOOST_CHECK(bb.push_with_timed_wait(2, timeout));
+ BOOST_CHECK(not bb.push_with_timed_wait(3, timeout));
+
+ int val;
+ //pop elements, check for timeout and check values
+ BOOST_CHECK(bb.pop_with_timed_wait(val, timeout));
+ BOOST_CHECK_EQUAL(val, 0);
+ BOOST_CHECK(bb.pop_with_timed_wait(val, timeout));
+ BOOST_CHECK_EQUAL(val, 1);
+ BOOST_CHECK(bb.pop_with_timed_wait(val, timeout));
+ BOOST_CHECK_EQUAL(val, 2);
+ BOOST_CHECK(not bb.pop_with_timed_wait(val, timeout));
+}
+
+BOOST_AUTO_TEST_CASE(test_bounded_buffer_with_pop_on_full){
+ bounded_buffer<int> bb(3);
+
+ //push elements, check for timeout
+ BOOST_CHECK(bb.push_with_pop_on_full(0));
+ BOOST_CHECK(bb.push_with_pop_on_full(1));
+ BOOST_CHECK(bb.push_with_pop_on_full(2));
+ BOOST_CHECK(not bb.push_with_pop_on_full(3));
+
+ int val;
+ //pop elements, check for timeout and check values
+ BOOST_CHECK(bb.pop_with_timed_wait(val, timeout));
+ BOOST_CHECK_EQUAL(val, 1);
+ BOOST_CHECK(bb.pop_with_timed_wait(val, timeout));
+ BOOST_CHECK_EQUAL(val, 2);
+ BOOST_CHECK(bb.pop_with_timed_wait(val, timeout));
+ BOOST_CHECK_EQUAL(val, 3);
+}
diff --git a/host/tests/byteswap_test.cpp b/host/tests/byteswap_test.cpp
new file mode 100644
index 000000000..7d94bbfba
--- /dev/null
+++ b/host/tests/byteswap_test.cpp
@@ -0,0 +1,39 @@
+//
+// Copyright 2010-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <boost/test/unit_test.hpp>
+#include <uhd/utils/byteswap.hpp>
+
+BOOST_AUTO_TEST_CASE(test_byteswap16){
+ boost::uint16_t x = 0x0123;
+ boost::uint16_t y = 0x2301;
+ BOOST_CHECK_EQUAL(uhd::byteswap(x), y);
+}
+
+BOOST_AUTO_TEST_CASE(test_byteswap32){
+ boost::uint32_t x = 0x01234567;
+ boost::uint32_t y = 0x67452301;
+ BOOST_CHECK_EQUAL(uhd::byteswap(x), y);
+}
+
+BOOST_AUTO_TEST_CASE(test_byteswap64){
+ //split up 64 bit constants to avoid long-long compiler warnings
+ boost::uint64_t x = 0x01234567 | (boost::uint64_t(0x89abcdef) << 32);
+ boost::uint64_t y = 0xefcdab89 | (boost::uint64_t(0x67452301) << 32);
+ BOOST_CHECK_EQUAL(uhd::byteswap(x), y);
+}
+
diff --git a/host/tests/convert_test.cpp b/host/tests/convert_test.cpp
new file mode 100644
index 000000000..d1c2b7625
--- /dev/null
+++ b/host/tests/convert_test.cpp
@@ -0,0 +1,262 @@
+//
+// Copyright 2011-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/convert.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/foreach.hpp>
+#include <boost/cstdint.hpp>
+#include <complex>
+#include <vector>
+#include <cstdlib>
+#include <iostream>
+
+using namespace uhd;
+
+//typedefs for complex types
+typedef std::complex<boost::int16_t> sc16_t;
+typedef std::complex<float> fc32_t;
+typedef std::complex<double> fc64_t;
+
+#define MY_CHECK_CLOSE(a, b, f) if ((std::abs(a) > (f) and std::abs(b) > (f))) \
+ BOOST_CHECK_CLOSE_FRACTION(a, b, f)
+
+/***********************************************************************
+ * Loopback runner:
+ * convert input buffer into intermediate buffer
+ * convert intermediate buffer into output buffer
+ **********************************************************************/
+template <typename Range> static void loopback(
+ size_t nsamps,
+ const io_type_t &io_type,
+ const otw_type_t &otw_type,
+ const Range &input,
+ Range &output
+){
+ //item32 is largest device type
+ std::vector<boost::uint32_t> interm(nsamps);
+
+ std::vector<const void *> input0(1, &input[0]), input1(1, &interm[0]);
+ std::vector<void *> output0(1, &interm[0]), output1(1, &output[0]);
+
+ //convert to intermediate type
+ convert::get_converter_cpu_to_otw(
+ io_type, otw_type, input0.size(), output0.size()
+ )(input0, output0, nsamps);
+
+ //convert back to host type
+ convert::get_converter_otw_to_cpu(
+ io_type, otw_type, input1.size(), output1.size()
+ )(input1, output1, nsamps);
+}
+
+/***********************************************************************
+ * Test short conversion
+ **********************************************************************/
+static void test_convert_types_sc16(
+ size_t nsamps,
+ const io_type_t &io_type,
+ const otw_type_t &otw_type
+){
+ //fill the input samples
+ std::vector<sc16_t> input(nsamps), output(nsamps);
+ BOOST_FOREACH(sc16_t &in, input) in = sc16_t(
+ std::rand()-(RAND_MAX/2),
+ std::rand()-(RAND_MAX/2)
+ );
+
+ //run the loopback and test
+ loopback(nsamps, io_type, otw_type, input, output);
+ BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end());
+}
+
+BOOST_AUTO_TEST_CASE(test_convert_types_be_sc16){
+ io_type_t io_type(io_type_t::COMPLEX_INT16);
+ otw_type_t otw_type;
+ otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN;
+ otw_type.width = 16;
+
+ //try various lengths to test edge cases
+ for (size_t nsamps = 1; nsamps < 16; nsamps++){
+ test_convert_types_sc16(nsamps, io_type, otw_type);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_convert_types_le_sc16){
+ io_type_t io_type(io_type_t::COMPLEX_INT16);
+ otw_type_t otw_type;
+ otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN;
+ otw_type.width = 16;
+
+ //try various lengths to test edge cases
+ for (size_t nsamps = 1; nsamps < 16; nsamps++){
+ test_convert_types_sc16(nsamps, io_type, otw_type);
+ }
+}
+
+/***********************************************************************
+ * Test float conversion
+ **********************************************************************/
+template <typename data_type>
+static void test_convert_types_for_floats(
+ size_t nsamps,
+ const io_type_t &io_type,
+ const otw_type_t &otw_type
+){
+ typedef typename data_type::value_type value_type;
+
+ //fill the input samples
+ std::vector<data_type> input(nsamps), output(nsamps);
+ BOOST_FOREACH(data_type &in, input) in = data_type(
+ (std::rand()/value_type(RAND_MAX/2)) - 1,
+ (std::rand()/value_type(RAND_MAX/2)) - 1
+ );
+
+ //run the loopback and test
+ loopback(nsamps, io_type, otw_type, input, output);
+ for (size_t i = 0; i < nsamps; i++){
+ MY_CHECK_CLOSE(input[i].real(), output[i].real(), value_type(0.01));
+ MY_CHECK_CLOSE(input[i].imag(), output[i].imag(), value_type(0.01));
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_convert_types_be_fc32){
+ io_type_t io_type(io_type_t::COMPLEX_FLOAT32);
+ otw_type_t otw_type;
+ otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN;
+ otw_type.width = 16;
+
+ //try various lengths to test edge cases
+ for (size_t nsamps = 1; nsamps < 16; nsamps++){
+ test_convert_types_for_floats<fc32_t>(nsamps, io_type, otw_type);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_convert_types_le_fc32){
+ io_type_t io_type(io_type_t::COMPLEX_FLOAT32);
+ otw_type_t otw_type;
+ otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN;
+ otw_type.width = 16;
+
+ //try various lengths to test edge cases
+ for (size_t nsamps = 1; nsamps < 16; nsamps++){
+ test_convert_types_for_floats<fc32_t>(nsamps, io_type, otw_type);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_convert_types_be_fc64){
+ io_type_t io_type(io_type_t::COMPLEX_FLOAT64);
+ otw_type_t otw_type;
+ otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN;
+ otw_type.width = 16;
+
+ //try various lengths to test edge cases
+ for (size_t nsamps = 1; nsamps < 16; nsamps++){
+ test_convert_types_for_floats<fc64_t>(nsamps, io_type, otw_type);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_convert_types_le_fc64){
+ io_type_t io_type(io_type_t::COMPLEX_FLOAT64);
+ otw_type_t otw_type;
+ otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN;
+ otw_type.width = 16;
+
+ //try various lengths to test edge cases
+ for (size_t nsamps = 1; nsamps < 16; nsamps++){
+ test_convert_types_for_floats<fc64_t>(nsamps, io_type, otw_type);
+ }
+}
+
+/***********************************************************************
+ * Test float to short conversion loopback
+ **********************************************************************/
+BOOST_AUTO_TEST_CASE(test_convert_types_fc32_to_sc16){
+ io_type_t io_type_in(io_type_t::COMPLEX_FLOAT32);
+ io_type_t io_type_out(io_type_t::COMPLEX_INT16);
+
+ otw_type_t otw_type;
+ otw_type.byteorder = otw_type_t::BO_NATIVE;
+ otw_type.width = 16;
+
+ const size_t nsamps = 13;
+ std::vector<fc32_t> input(nsamps);
+ BOOST_FOREACH(fc32_t &in, input) in = fc32_t(
+ (std::rand()/float(RAND_MAX/2)) - 1,
+ (std::rand()/float(RAND_MAX/2)) - 1
+ );
+ std::vector<boost::uint32_t> interm(nsamps);
+ std::vector<sc16_t> output(nsamps);
+
+ std::vector<const void *> input0(1, &input[0]), input1(1, &interm[0]);
+ std::vector<void *> output0(1, &interm[0]), output1(1, &output[0]);
+
+ //convert float to intermediate
+ convert::get_converter_cpu_to_otw(
+ io_type_in, otw_type, input0.size(), output0.size()
+ )(input0, output0, nsamps);
+
+ //convert intermediate to short
+ convert::get_converter_otw_to_cpu(
+ io_type_out, otw_type, input1.size(), output1.size()
+ )(input1, output1, nsamps);
+
+ //test that the inputs and outputs match
+ for (size_t i = 0; i < nsamps; i++){
+ MY_CHECK_CLOSE(input[i].real(), output[i].real()/float(32767), float(0.01));
+ MY_CHECK_CLOSE(input[i].imag(), output[i].imag()/float(32767), float(0.01));
+ }
+}
+
+/***********************************************************************
+ * Test short to float conversion loopback
+ **********************************************************************/
+BOOST_AUTO_TEST_CASE(test_convert_types_sc16_to_fc32){
+ io_type_t io_type_in(io_type_t::COMPLEX_INT16);
+ io_type_t io_type_out(io_type_t::COMPLEX_FLOAT32);
+
+ otw_type_t otw_type;
+ otw_type.byteorder = otw_type_t::BO_NATIVE;
+ otw_type.width = 16;
+
+ const size_t nsamps = 13;
+ std::vector<sc16_t> input(nsamps);
+ BOOST_FOREACH(sc16_t &in, input) in = sc16_t(
+ std::rand()-(RAND_MAX/2),
+ std::rand()-(RAND_MAX/2)
+ );
+ std::vector<boost::uint32_t> interm(nsamps);
+ std::vector<fc32_t> output(nsamps);
+
+ std::vector<const void *> input0(1, &input[0]), input1(1, &interm[0]);
+ std::vector<void *> output0(1, &interm[0]), output1(1, &output[0]);
+
+ //convert short to intermediate
+ convert::get_converter_cpu_to_otw(
+ io_type_in, otw_type, input0.size(), output0.size()
+ )(input0, output0, nsamps);
+
+ //convert intermediate to float
+ convert::get_converter_otw_to_cpu(
+ io_type_out, otw_type, input1.size(), output1.size()
+ )(input1, output1, nsamps);
+
+ //test that the inputs and outputs match
+ for (size_t i = 0; i < nsamps; i++){
+ MY_CHECK_CLOSE(input[i].real()/float(32767), output[i].real(), float(0.01));
+ MY_CHECK_CLOSE(input[i].imag()/float(32767), output[i].imag(), float(0.01));
+ }
+}
diff --git a/host/tests/dict_test.cpp b/host/tests/dict_test.cpp
new file mode 100644
index 000000000..7b388d090
--- /dev/null
+++ b/host/tests/dict_test.cpp
@@ -0,0 +1,72 @@
+//
+// Copyright 2010-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <boost/test/unit_test.hpp>
+#include <uhd/types/dict.hpp>
+#include <boost/assign/list_of.hpp>
+
+BOOST_AUTO_TEST_CASE(test_dict_init){
+ uhd::dict<int, int> d;
+ d[-1] = 3;
+ d[0] = 4;
+ d[1] = 5;
+ BOOST_CHECK(d.has_key(0));
+ BOOST_CHECK(not d.has_key(2));
+ BOOST_CHECK(d.keys()[1] == 0);
+ BOOST_CHECK(d.vals()[1] == 4);
+ BOOST_CHECK_EQUAL(d[-1], 3);
+}
+
+BOOST_AUTO_TEST_CASE(test_dict_assign){
+ uhd::dict<int, int> d = boost::assign::map_list_of
+ (-1, 3)
+ (0, 4)
+ (1, 5)
+ ;
+ BOOST_CHECK(d.has_key(0));
+ BOOST_CHECK(not d.has_key(2));
+ BOOST_CHECK(d.keys()[1] == 0);
+ BOOST_CHECK(d.vals()[1] == 4);
+ BOOST_CHECK_EQUAL(d[-1], 3);
+}
+
+BOOST_AUTO_TEST_CASE(test_const_dict){
+ const uhd::dict<int, int> d = boost::assign::map_list_of
+ (-1, 3)
+ (0, 4)
+ (1, 5)
+ ;
+ BOOST_CHECK(d.has_key(0));
+ BOOST_CHECK(not d.has_key(2));
+ BOOST_CHECK(d.keys()[1] == 0);
+ BOOST_CHECK(d.vals()[1] == 4);
+ BOOST_CHECK_EQUAL(d[-1], 3);
+ BOOST_CHECK_THROW(d[2], std::exception);
+}
+
+BOOST_AUTO_TEST_CASE(test_dict_pop){
+ uhd::dict<int, int> d = boost::assign::map_list_of
+ (-1, 3)
+ (0, 4)
+ (1, 5)
+ ;
+ BOOST_CHECK(d.has_key(0));
+ BOOST_CHECK_EQUAL(d.pop(0), 4);
+ BOOST_CHECK(not d.has_key(0));
+ BOOST_CHECK(d.keys()[0] == -1);
+ BOOST_CHECK(d.keys()[1] == 1);
+}
diff --git a/host/tests/error_test.cpp b/host/tests/error_test.cpp
new file mode 100644
index 000000000..983f0150c
--- /dev/null
+++ b/host/tests/error_test.cpp
@@ -0,0 +1,59 @@
+//
+// Copyright 2010-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <boost/test/unit_test.hpp>
+#include <uhd/exception.hpp>
+#include <uhd/utils/assert_has.hpp>
+#include <vector>
+#include <iostream>
+
+BOOST_AUTO_TEST_CASE(test_exception_methods){
+ try{
+ throw uhd::assertion_error("your assertion failed: 1 != 2");
+ }
+ catch(const uhd::exception &e){
+ std::cout << "what: " << e.what() << std::endl;
+ std::cout << "code: " << e.code() << std::endl;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_assert_has){
+ std::vector<int> vec;
+ vec.push_back(2);
+ vec.push_back(3);
+ vec.push_back(5);
+
+ //verify the uhd::has utility
+ BOOST_CHECK(uhd::has(vec, 2));
+ BOOST_CHECK(not uhd::has(vec, 1));
+
+ std::cout << "The output of the assert_has error:" << std::endl;
+ try{
+ uhd::assert_has(vec, 1, "prime");
+ }catch(const std::exception &e){
+ std::cout << e.what() << std::endl;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_assert_throw){
+ std::cout << "The output of the assert throw error:" << std::endl;
+ try{
+ UHD_ASSERT_THROW(2 + 2 == 5);
+ }catch(const std::exception &e){
+ std::cout << e.what() << std::endl;
+ }
+}
diff --git a/host/tests/gain_group_test.cpp b/host/tests/gain_group_test.cpp
new file mode 100644
index 000000000..07eaf146e
--- /dev/null
+++ b/host/tests/gain_group_test.cpp
@@ -0,0 +1,122 @@
+//
+// Copyright 2010-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <boost/test/unit_test.hpp>
+#include <uhd/utils/gain_group.hpp>
+#include <boost/bind.hpp>
+#include <boost/math/special_functions/round.hpp>
+#include <iostream>
+
+#define rint(x) boost::math::iround(x)
+
+using namespace uhd;
+
+/***********************************************************************
+ * Define gain element classes with needed functions
+ **********************************************************************/
+class gain_element1{
+public:
+
+ gain_range_t get_range(void){
+ return gain_range_t(0, 90, 1);
+ }
+
+ double get_value(void){
+ return _gain;
+ }
+
+ void set_value(double gain){
+ double step = get_range().step();
+ _gain = step*rint(gain/step);
+ }
+
+private:
+ double _gain;
+};
+
+class gain_element2{
+public:
+
+ gain_range_t get_range(void){
+ return gain_range_t(-20, 10, 0.1);
+ }
+
+ double get_value(void){
+ return _gain;
+ }
+
+ void set_value(double gain){
+ double step = get_range().step();
+ _gain = step*rint(gain/step);
+ }
+
+private:
+ double _gain;
+};
+
+//create static instances of gain elements to be shared by the tests
+static gain_element1 g1;
+static gain_element2 g2;
+
+static gain_group::sptr get_gain_group(size_t pri1 = 0, size_t pri2 = 0){
+ //create instance of gain group
+ gain_fcns_t gain_fcns;
+ gain_group::sptr gg(gain_group::make());
+
+ //load gain group with function sets
+ gain_fcns.get_range = boost::bind(&gain_element1::get_range, &g1);
+ gain_fcns.get_value = boost::bind(&gain_element1::get_value, &g1);
+ gain_fcns.set_value = boost::bind(&gain_element1::set_value, &g1, _1);
+ gg->register_fcns("g1", gain_fcns, pri1);
+
+ gain_fcns.get_range = boost::bind(&gain_element2::get_range, &g2);
+ gain_fcns.get_value = boost::bind(&gain_element2::get_value, &g2);
+ gain_fcns.set_value = boost::bind(&gain_element2::set_value, &g2, _1);
+ gg->register_fcns("g2", gain_fcns, pri2);
+
+ return gg;
+}
+
+/***********************************************************************
+ * Test cases
+ **********************************************************************/
+static const double tolerance = 0.001;
+
+BOOST_AUTO_TEST_CASE(test_gain_group_overall){
+ gain_group::sptr gg = get_gain_group();
+
+ //test the overall stuff
+ gg->set_value(80);
+ BOOST_CHECK_CLOSE(gg->get_value(), 80.0, tolerance);
+ BOOST_CHECK_CLOSE(gg->get_range().start(), -20.0, tolerance);
+ BOOST_CHECK_CLOSE(gg->get_range().stop(), 100.0, tolerance);
+ BOOST_CHECK_CLOSE(gg->get_range().step(), 0.1, tolerance);
+}
+
+BOOST_AUTO_TEST_CASE(test_gain_group_priority){
+ gain_group::sptr gg = get_gain_group(0, 1);
+
+ //test the overall stuff
+ gg->set_value(80);
+ BOOST_CHECK_CLOSE(gg->get_value(), 80.0, tolerance);
+ BOOST_CHECK_CLOSE(gg->get_range().start(), -20.0, tolerance);
+ BOOST_CHECK_CLOSE(gg->get_range().stop(), 100.0, tolerance);
+ BOOST_CHECK_CLOSE(gg->get_range().step(), 0.1, tolerance);
+
+ //test the the higher priority gain got filled first (gain 2)
+ BOOST_CHECK_CLOSE(g2.get_value(), g2.get_range().stop(), tolerance);
+}
diff --git a/host/tests/module_test.cpp b/host/tests/module_test.cpp
new file mode 100644
index 000000000..af2f749a7
--- /dev/null
+++ b/host/tests/module_test.cpp
@@ -0,0 +1,26 @@
+//
+// Copyright 2010-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/static.hpp>
+#include <iostream>
+
+UHD_STATIC_BLOCK(module_test){
+ std::cout << "---------------------------------------" << std::endl;
+ std::cout << "-- Good news, everyone!" << std::endl;
+ std::cout << "-- The test module has been loaded." << std::endl;
+ std::cout << "---------------------------------------" << std::endl;
+}
diff --git a/host/tests/ranges_test.cpp b/host/tests/ranges_test.cpp
new file mode 100644
index 000000000..5f6de4645
--- /dev/null
+++ b/host/tests/ranges_test.cpp
@@ -0,0 +1,57 @@
+//
+// Copyright 2010-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <boost/test/unit_test.hpp>
+#include <uhd/types/ranges.hpp>
+#include <iostream>
+
+using namespace uhd;
+
+static const double tolerance = 0.001;
+
+BOOST_AUTO_TEST_CASE(test_ranges_bounds){
+ meta_range_t mr;
+ mr.push_back(range_t(-1.0, +1.0, 0.1));
+ BOOST_CHECK_CLOSE(mr.start(), -1.0, tolerance);
+ BOOST_CHECK_CLOSE(mr.stop(), +1.0, tolerance);
+ BOOST_CHECK_CLOSE(mr.step(), 0.1, tolerance);
+
+ mr.push_back(range_t(40.0, 60.0, 1.0));
+ BOOST_CHECK_CLOSE(mr.start(), -1.0, tolerance);
+ BOOST_CHECK_CLOSE(mr.stop(), 60.0, tolerance);
+ BOOST_CHECK_CLOSE(mr.step(), 0.1, tolerance);
+
+ BOOST_CHECK_EQUAL(mr.size(), unsigned(2));
+
+ BOOST_CHECK_CLOSE(mr[0].start(), -1.0, tolerance);
+ BOOST_CHECK_CLOSE(mr[0].stop(), +1.0, tolerance);
+ BOOST_CHECK_CLOSE(mr[0].step(), 0.1, tolerance);
+}
+
+BOOST_AUTO_TEST_CASE(test_ranges_clip){
+ meta_range_t mr;
+ mr.push_back(range_t(-1.0, +1.0, 0.1));
+ mr.push_back(range_t(40.0, 60.0, 1.0));
+
+ BOOST_CHECK_CLOSE(mr.clip(-30.0), -1.0, tolerance);
+ BOOST_CHECK_CLOSE(mr.clip(70.0), 60.0, tolerance);
+ BOOST_CHECK_CLOSE(mr.clip(20.0), 1.0, tolerance);
+ BOOST_CHECK_CLOSE(mr.clip(50.0), 50.0, tolerance);
+
+ BOOST_CHECK_CLOSE(mr.clip(50.9, false), 50.9, tolerance);
+ BOOST_CHECK_CLOSE(mr.clip(50.9, true), 51.0, tolerance);
+}
diff --git a/host/tests/subdev_spec_test.cpp b/host/tests/subdev_spec_test.cpp
new file mode 100644
index 000000000..aa0b9a119
--- /dev/null
+++ b/host/tests/subdev_spec_test.cpp
@@ -0,0 +1,45 @@
+//
+// Copyright 2010-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <boost/test/unit_test.hpp>
+#include <uhd/usrp/subdev_spec.hpp>
+#include <boost/foreach.hpp>
+#include <iostream>
+
+BOOST_AUTO_TEST_CASE(test_subdevice_spec){
+ std::cout << "Testing subdevice specification..." << std::endl;
+
+ //load the subdev spec with something
+ uhd::usrp::subdev_spec_t sd_spec;
+ sd_spec.push_back(uhd::usrp::subdev_spec_pair_t("A", "AB"));
+ sd_spec.push_back(uhd::usrp::subdev_spec_pair_t("B", "AB"));
+
+ //convert to and from args string
+ std::cout << "Pretty Print: " << std::endl << sd_spec.to_pp_string();
+ std::string markup_str = sd_spec.to_string();
+ std::cout << "Markup String: " << markup_str << std::endl;
+ uhd::usrp::subdev_spec_t new_sd_spec(markup_str);
+
+ //they should be the same size
+ BOOST_REQUIRE_EQUAL(sd_spec.size(), new_sd_spec.size());
+
+ //the contents should match
+ for (size_t i = 0; i < sd_spec.size(); i++){
+ BOOST_CHECK_EQUAL(sd_spec.at(i).db_name, new_sd_spec.at(i).db_name);
+ BOOST_CHECK_EQUAL(sd_spec.at(i).sd_name, new_sd_spec.at(i).sd_name);
+ }
+}
diff --git a/host/tests/time_spec_test.cpp b/host/tests/time_spec_test.cpp
new file mode 100644
index 000000000..e57bbced1
--- /dev/null
+++ b/host/tests/time_spec_test.cpp
@@ -0,0 +1,80 @@
+//
+// Copyright 2010-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <boost/test/unit_test.hpp>
+#include <uhd/types/time_spec.hpp>
+#include <boost/foreach.hpp>
+#include <boost/thread.hpp> //sleep
+#include <iostream>
+
+BOOST_AUTO_TEST_CASE(test_time_spec_compare){
+ std::cout << "Testing time specification compare..." << std::endl;
+
+ BOOST_CHECK(uhd::time_spec_t(2.0) == uhd::time_spec_t(2.0));
+ BOOST_CHECK(uhd::time_spec_t(2.0) > uhd::time_spec_t(1.0));
+ BOOST_CHECK(uhd::time_spec_t(1.0) < uhd::time_spec_t(2.0));
+
+ BOOST_CHECK(uhd::time_spec_t(1.1) == uhd::time_spec_t(1.1));
+ BOOST_CHECK(uhd::time_spec_t(1.1) > uhd::time_spec_t(1.0));
+ BOOST_CHECK(uhd::time_spec_t(1.0) < uhd::time_spec_t(1.1));
+
+ BOOST_CHECK(uhd::time_spec_t(0.1) == uhd::time_spec_t(0.1));
+ BOOST_CHECK(uhd::time_spec_t(0.2) > uhd::time_spec_t(0.1));
+ BOOST_CHECK(uhd::time_spec_t(0.1) < uhd::time_spec_t(0.2));
+}
+
+#define CHECK_TS_EQUAL(lhs, rhs) \
+ BOOST_CHECK_CLOSE((lhs).get_real_secs(), (rhs).get_real_secs(), 0.001)
+
+BOOST_AUTO_TEST_CASE(test_time_spec_arithmetic){
+ std::cout << "Testing time specification arithmetic..." << std::endl;
+
+ CHECK_TS_EQUAL(uhd::time_spec_t(2.3) + uhd::time_spec_t(1.0), uhd::time_spec_t(3.3));
+ CHECK_TS_EQUAL(uhd::time_spec_t(2.3) - uhd::time_spec_t(1.0), uhd::time_spec_t(1.3));
+ CHECK_TS_EQUAL(uhd::time_spec_t(1.0) + uhd::time_spec_t(2.3), uhd::time_spec_t(3.3));
+ CHECK_TS_EQUAL(uhd::time_spec_t(1.0) - uhd::time_spec_t(2.3), uhd::time_spec_t(-1.3));
+}
+
+BOOST_AUTO_TEST_CASE(test_time_spec_parts){
+ std::cout << "Testing time specification parts..." << std::endl;
+
+ BOOST_CHECK_EQUAL(uhd::time_spec_t(1.1).get_full_secs(), 1);
+ BOOST_CHECK_CLOSE(uhd::time_spec_t(1.1).get_frac_secs(), 0.1, 0.001);
+ BOOST_CHECK_EQUAL(uhd::time_spec_t(1.1).get_tick_count(100), 10);
+
+ BOOST_CHECK_EQUAL(uhd::time_spec_t(-1.1).get_full_secs(), -1);
+ BOOST_CHECK_CLOSE(uhd::time_spec_t(-1.1).get_frac_secs(), -0.1, 0.001);
+ BOOST_CHECK_EQUAL(uhd::time_spec_t(-1.1).get_tick_count(100), -10);
+}
+
+BOOST_AUTO_TEST_CASE(test_time_spec_get_system_time){
+ std::cout << "Testing time specification get system time..." << std::endl;
+
+ //Not really checking for high resolution timing here,
+ //just need to check that system time is minimally working.
+
+ uhd::time_spec_t start = uhd::time_spec_t::get_system_time();
+ boost::this_thread::sleep(boost::posix_time::milliseconds(500));
+ uhd::time_spec_t stop = uhd::time_spec_t::get_system_time();
+
+ uhd::time_spec_t diff = stop - start;
+ std::cout << "start: " << start.get_real_secs() << std::endl;
+ std::cout << "stop: " << stop.get_real_secs() << std::endl;
+ std::cout << "diff: " << diff.get_real_secs() << std::endl;
+ BOOST_CHECK(diff.get_real_secs() > 0); //assert positive
+ BOOST_CHECK(diff.get_real_secs() < 1.0); //assert under 1s
+}
diff --git a/host/tests/tune_helper_test.cpp b/host/tests/tune_helper_test.cpp
new file mode 100644
index 000000000..9147cd310
--- /dev/null
+++ b/host/tests/tune_helper_test.cpp
@@ -0,0 +1,251 @@
+//
+// Copyright 2010-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <boost/test/unit_test.hpp>
+#include <uhd/usrp/tune_helper.hpp>
+#include <uhd/usrp/subdev_props.hpp>
+#include <uhd/usrp/dsp_props.hpp>
+#include <uhd/usrp/dsp_utils.hpp>
+#include <iostream>
+
+using namespace uhd;
+using namespace uhd::usrp;
+
+/***********************************************************************
+ * Dummy properties objects
+ **********************************************************************/
+class dummy_subdev : public wax::obj{
+public:
+ dummy_subdev(double resolution):
+ _resolution(resolution)
+ {
+ /* NOP */
+ }
+private:
+ void get(const wax::obj &key, wax::obj &val){
+ switch(key.as<subdev_prop_t>()){
+
+ case SUBDEV_PROP_FREQ:
+ val = _freq;
+ return;
+
+ case SUBDEV_PROP_USE_LO_OFFSET:
+ val = false;
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+ }
+
+ void set(const wax::obj &key, const wax::obj &val){
+ switch(key.as<subdev_prop_t>()){
+ case SUBDEV_PROP_FREQ:
+ _freq = _resolution*int(val.as<double>()/_resolution);
+ return;
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+ }
+
+ double _freq, _resolution;
+};
+
+class dummy_subdev_basic : public wax::obj{
+private:
+ void get(const wax::obj &key, wax::obj &val){
+ switch(key.as<subdev_prop_t>()){
+
+ case SUBDEV_PROP_FREQ:
+ val = double(0.0); //always zero
+ return;
+
+ case SUBDEV_PROP_USE_LO_OFFSET:
+ val = false;
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+ }
+
+ void set(const wax::obj &key, const wax::obj &){
+ switch(key.as<subdev_prop_t>()){
+ case SUBDEV_PROP_FREQ:
+ // do nothing
+ return;
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+ }
+};
+
+class dummy_subdev_bw : public wax::obj{
+private:
+ void get(const wax::obj &key, wax::obj &val){
+ switch(key.as<subdev_prop_t>()){
+
+ case SUBDEV_PROP_FREQ:
+ val = _freq;
+ return;
+
+ case SUBDEV_PROP_USE_LO_OFFSET:
+ val = true;
+ return;
+
+ case SUBDEV_PROP_BANDWIDTH:
+ val = _bandwidth;
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+ }
+
+ void set(const wax::obj &key, const wax::obj &val){
+ switch(key.as<subdev_prop_t>()){
+ case SUBDEV_PROP_FREQ:
+ _freq = val.as<double>();
+ return;
+
+ case SUBDEV_PROP_BANDWIDTH:
+ _bandwidth = val.as<double>();
+ return;
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+ }
+
+ double _freq, _bandwidth;
+};
+
+class dummy_dsp : public wax::obj{
+public:
+ dummy_dsp(double codec_rate):
+ _codec_rate(codec_rate)
+ {
+ /* NOP */
+ }
+private:
+ void get(const wax::obj &key_, wax::obj &val){
+ named_prop_t key = named_prop_t::extract(key_);
+ switch(key.as<dsp_prop_t>()){
+ case DSP_PROP_CODEC_RATE:
+ val = _codec_rate;
+ return;
+
+ case DSP_PROP_HOST_RATE:
+ val = _host_rate;
+ return;
+
+ case DSP_PROP_FREQ_SHIFT:
+ val = _freq_shift;
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+ }
+
+ void set(const wax::obj &key_, const wax::obj &val){
+ named_prop_t key = named_prop_t::extract(key_);
+ switch(key.as<dsp_prop_t>()){
+ case DSP_PROP_FREQ_SHIFT:
+ _freq_shift = val.as<double>();
+ dsp_type1::calc_cordic_word_and_update(_freq_shift, _codec_rate);
+ return;
+
+ case DSP_PROP_HOST_RATE:
+ _host_rate = val.as<double>();
+ return;
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+ }
+
+ double _codec_rate, _freq_shift, _host_rate;
+};
+
+/***********************************************************************
+ * Test cases
+ **********************************************************************/
+static const double tolerance = 0.001;
+
+BOOST_AUTO_TEST_CASE(test_tune_helper_rx){
+ dummy_subdev subdev(1e6);
+ dummy_dsp dsp(100e6);
+
+ std::cout << "Testing tune helper RX automatic IF offset" << std::endl;
+ tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.3451e9);
+ std::cout << tr.to_pp_string() << std::endl;
+ BOOST_CHECK_CLOSE(tr.actual_rf_freq, 2.345e9, tolerance);
+ BOOST_CHECK_CLOSE(tr.actual_dsp_freq, -100e3, tolerance);
+
+ double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link());
+ BOOST_CHECK_CLOSE(freq_derived, 2.3451e9, tolerance);
+}
+
+BOOST_AUTO_TEST_CASE(test_tune_helper_tx){
+ dummy_subdev subdev(1e6);
+ dummy_dsp dsp(100e6);
+
+ std::cout << "Testing tune helper TX automatic IF offset" << std::endl;
+ tune_result_t tr = tune_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.3451e9);
+ std::cout << tr.to_pp_string() << std::endl;
+ BOOST_CHECK_CLOSE(tr.actual_rf_freq, 2.345e9, tolerance);
+ BOOST_CHECK_CLOSE(tr.actual_dsp_freq, 100e3, tolerance);
+
+ double freq_derived = derive_freq_from_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link());
+ BOOST_CHECK_CLOSE(freq_derived, 2.3451e9, tolerance);
+}
+
+BOOST_AUTO_TEST_CASE(test_tune_helper_rx_nyquist){
+ dummy_subdev_basic subdev;
+ dummy_dsp dsp(100e6);
+
+ std::cout << "Testing tune helper RX dummy basic board" << std::endl;
+ tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 55e6);
+ std::cout << tr.to_pp_string() << std::endl;
+ BOOST_CHECK_CLOSE(tr.actual_rf_freq, 0.0, tolerance);
+ BOOST_CHECK_CLOSE(tr.actual_dsp_freq, 45e6, tolerance);
+
+ double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link());
+ BOOST_CHECK_CLOSE(freq_derived, -45e6, tolerance);
+}
+
+BOOST_AUTO_TEST_CASE(test_tune_helper_rx_lo_off){
+ dummy_subdev_bw subdev;
+ dummy_dsp dsp(100e6);
+ tune_result_t tr;
+
+ std::cout << "Testing tune helper RX automatic LO offset B >> fs" << std::endl;
+ subdev[SUBDEV_PROP_BANDWIDTH] = double(40e6);
+ dsp[DSP_PROP_HOST_RATE] = double(4e6);
+ tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.45e9);
+ std::cout << tr.to_pp_string() << std::endl;
+ BOOST_CHECK_CLOSE(tr.actual_rf_freq, 2.45e9+4e6/2, tolerance);
+
+ std::cout << "Testing tune helper RX automatic LO offset B > fs" << std::endl;
+ subdev[SUBDEV_PROP_BANDWIDTH] = double(40e6);
+ dsp[DSP_PROP_HOST_RATE] = double(25e6);
+ tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.45e9);
+ std::cout << tr.to_pp_string() << std::endl;
+ BOOST_CHECK_CLOSE(tr.actual_rf_freq, 2.45e9+(40e6-25e6)/2, tolerance);
+
+ std::cout << "Testing tune helper RX automatic LO offset B < fs" << std::endl;
+ subdev[SUBDEV_PROP_BANDWIDTH] = double(20e6);
+ dsp[DSP_PROP_HOST_RATE] = double(25e6);
+ tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.45e9);
+ std::cout << tr.to_pp_string() << std::endl;
+ BOOST_CHECK_CLOSE(tr.actual_rf_freq, 2.45e9, tolerance);
+}
diff --git a/host/tests/vrt_test.cpp b/host/tests/vrt_test.cpp
new file mode 100644
index 000000000..066f1493b
--- /dev/null
+++ b/host/tests/vrt_test.cpp
@@ -0,0 +1,141 @@
+//
+// Copyright 2010-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <boost/test/unit_test.hpp>
+#include <uhd/transport/vrt_if_packet.hpp>
+#include <cstdlib>
+
+using namespace uhd::transport;
+
+static void pack_and_unpack(
+ vrt::if_packet_info_t &if_packet_info_in
+){
+ boost::uint32_t header_buff[vrt::max_if_hdr_words32];
+
+ //pack metadata into a vrt header
+ vrt::if_hdr_pack_be(
+ header_buff, if_packet_info_in
+ );
+
+ vrt::if_packet_info_t if_packet_info_out;
+ if_packet_info_out.num_packet_words32 = if_packet_info_in.num_packet_words32;
+
+ //unpack the vrt header back into metadata
+ vrt::if_hdr_unpack_be(
+ header_buff, if_packet_info_out
+ );
+
+ //check the the unpacked metadata is the same
+ BOOST_CHECK_EQUAL(if_packet_info_in.packet_count, if_packet_info_out.packet_count);
+ BOOST_CHECK_EQUAL(if_packet_info_in.num_header_words32, if_packet_info_out.num_header_words32);
+ BOOST_CHECK_EQUAL(if_packet_info_in.num_payload_words32, if_packet_info_out.num_payload_words32);
+ BOOST_CHECK_EQUAL(if_packet_info_in.has_sid, if_packet_info_out.has_sid);
+ if (if_packet_info_in.has_sid and if_packet_info_out.has_sid){
+ BOOST_CHECK_EQUAL(if_packet_info_in.sid, if_packet_info_out.sid);
+ }
+ BOOST_CHECK_EQUAL(if_packet_info_in.has_cid, if_packet_info_out.has_cid);
+ if (if_packet_info_in.has_cid and if_packet_info_out.has_cid){
+ BOOST_CHECK_EQUAL(if_packet_info_in.cid, if_packet_info_out.cid);
+ }
+ BOOST_CHECK_EQUAL(if_packet_info_in.has_tsi, if_packet_info_out.has_tsi);
+ if (if_packet_info_in.has_tsi and if_packet_info_out.has_tsi){
+ BOOST_CHECK_EQUAL(if_packet_info_in.tsi, if_packet_info_out.tsi);
+ }
+ BOOST_CHECK_EQUAL(if_packet_info_in.has_tsf, if_packet_info_out.has_tsf);
+ if (if_packet_info_in.has_tsf and if_packet_info_out.has_tsf){
+ BOOST_CHECK_EQUAL(if_packet_info_in.tsf, if_packet_info_out.tsf);
+ }
+ BOOST_CHECK_EQUAL(if_packet_info_in.has_tlr, if_packet_info_out.has_tlr);
+ if (if_packet_info_in.has_tlr and if_packet_info_out.has_tlr){
+ BOOST_CHECK_EQUAL(if_packet_info_in.tlr, if_packet_info_out.tlr);
+ }
+}
+
+/***********************************************************************
+ * Loopback test the vrt packer/unpacker with various packet info combos
+ * The trailer is not tested as it is not convenient to do so.
+ **********************************************************************/
+
+BOOST_AUTO_TEST_CASE(test_with_none){
+ vrt::if_packet_info_t if_packet_info;
+ if_packet_info.packet_count = 0;
+ if_packet_info.has_sid = false;
+ if_packet_info.has_cid = false;
+ if_packet_info.has_tsi = false;
+ if_packet_info.has_tsf = false;
+ if_packet_info.has_tlr = false;
+ if_packet_info.num_payload_words32 = 0;
+ pack_and_unpack(if_packet_info);
+}
+
+BOOST_AUTO_TEST_CASE(test_with_sid){
+ vrt::if_packet_info_t if_packet_info;
+ if_packet_info.packet_count = 1;
+ if_packet_info.has_sid = true;
+ if_packet_info.has_cid = false;
+ if_packet_info.has_tsi = false;
+ if_packet_info.has_tsf = false;
+ if_packet_info.has_tlr = false;
+ if_packet_info.sid = std::rand();
+ if_packet_info.num_payload_words32 = 1111;
+ pack_and_unpack(if_packet_info);
+}
+
+static const bool cid_enb = false;
+
+BOOST_AUTO_TEST_CASE(test_with_cid){
+ vrt::if_packet_info_t if_packet_info;
+ if_packet_info.packet_count = 2;
+ if_packet_info.has_sid = false;
+ if_packet_info.has_cid = cid_enb;
+ if_packet_info.has_tsi = false;
+ if_packet_info.has_tsf = false;
+ if_packet_info.has_tlr = false;
+ if_packet_info.cid = std::rand();
+ if_packet_info.num_payload_words32 = 2222;
+ pack_and_unpack(if_packet_info);
+}
+
+BOOST_AUTO_TEST_CASE(test_with_time){
+ vrt::if_packet_info_t if_packet_info;
+ if_packet_info.packet_count = 3;
+ if_packet_info.has_sid = false;
+ if_packet_info.has_cid = false;
+ if_packet_info.has_tsi = true;
+ if_packet_info.has_tsf = true;
+ if_packet_info.has_tlr = false;
+ if_packet_info.tsi = std::rand();
+ if_packet_info.tsf = std::rand();
+ if_packet_info.num_payload_words32 = 33333;
+ pack_and_unpack(if_packet_info);
+}
+
+BOOST_AUTO_TEST_CASE(test_with_all){
+ vrt::if_packet_info_t if_packet_info;
+ if_packet_info.packet_count = 4;
+ if_packet_info.has_sid = true;
+ if_packet_info.has_cid = cid_enb;
+ if_packet_info.has_tsi = true;
+ if_packet_info.has_tsf = true;
+ if_packet_info.has_tlr = false;
+ if_packet_info.sid = std::rand();
+ if_packet_info.cid = std::rand();
+ if_packet_info.tsi = std::rand();
+ if_packet_info.tsf = std::rand();
+ if_packet_info.num_payload_words32 = 44444;
+ pack_and_unpack(if_packet_info);
+}
diff --git a/host/tests/warning_test.cpp b/host/tests/warning_test.cpp
new file mode 100644
index 000000000..3394f84d4
--- /dev/null
+++ b/host/tests/warning_test.cpp
@@ -0,0 +1,29 @@
+//
+// Copyright 2010-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <boost/test/unit_test.hpp>
+#include <uhd/utils/warning.hpp>
+#include <iostream>
+
+BOOST_AUTO_TEST_CASE(test_warning_post){
+ std::cerr << "---begin print test ---" << std::endl;
+ uhd::warning::post(
+ "This is a test print for a warning message.\n"
+ "And this is the second line of the test print.\n"
+ );
+ std::cerr << "---end print test ---" << std::endl;
+}
diff --git a/host/tests/wax_test.cpp b/host/tests/wax_test.cpp
new file mode 100644
index 000000000..18730e0c2
--- /dev/null
+++ b/host/tests/wax_test.cpp
@@ -0,0 +1,104 @@
+//
+// Copyright 2010-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <boost/test/unit_test.hpp>
+#include <boost/shared_ptr.hpp>
+#include <uhd/wax.hpp>
+#include <iostream>
+
+enum opt_a_t{OPTION_A_0, OPTION_A_1};
+enum opt_b_t{OPTION_B_0, OPTION_B_1};
+
+BOOST_AUTO_TEST_CASE(test_enums){
+ wax::obj opta = OPTION_A_0;
+ BOOST_CHECK_THROW(opta.as<opt_b_t>(), std::exception);
+ BOOST_CHECK_EQUAL(opta.as<opt_a_t>(), OPTION_A_0);
+}
+
+/***********************************************************************
+ * demo class for wax framework
+ **********************************************************************/
+class wax_demo : public wax::obj{
+public:
+ typedef boost::shared_ptr<wax_demo> sptr;
+
+ wax_demo(size_t sub_demos, size_t len){
+ d_nums = std::vector<float>(len);
+ if (sub_demos != 0){
+ for (size_t i = 0; i < len; i++){
+ d_subs.push_back(sptr(new wax_demo(sub_demos-1, len)));
+ }
+ }
+ }
+ ~wax_demo(void){
+ /* NOP */
+ }
+private:
+ std::vector<float> d_nums;
+ std::vector<sptr> d_subs;
+
+ void get(const wax::obj &key, wax::obj &value){
+ if (d_subs.size() == 0){
+ value = d_nums[key.as<size_t>()];
+ }else{
+ value = d_subs[key.as<size_t>()]->get_link();
+ }
+ }
+ void set(const wax::obj &key, const wax::obj &value){
+ if (d_subs.size() == 0){
+ d_nums[key.as<size_t>()] = value.as<float>();
+ }else{
+ throw std::runtime_error("cant set to a wax demo with sub demos");
+ }
+ }
+};
+
+BOOST_AUTO_TEST_CASE(test_chaining){
+ wax_demo wd(2, 1);
+ std::cout << "chain 1" << std::endl;
+ wd[size_t(0)];
+ std::cout << "chain 2" << std::endl;
+ wd[size_t(0)][size_t(0)];
+ std::cout << "chain 3" << std::endl;
+ wd[size_t(0)][size_t(0)][size_t(0)];
+}
+
+BOOST_AUTO_TEST_CASE(test_set_get){
+ wax_demo wd(2, 10);
+ std::cout << "set and get all" << std::endl;
+ for (size_t i = 0; i < 10; i++){
+ for (size_t j = 0; j < 10; j++){
+ for (size_t k = 0; k < 10; k++){
+ float val = float(i * j * k + i + j + k);
+ //std::cout << i << " " << j << " " << k << std::endl;
+ wd[i][j][k] = val;
+ BOOST_CHECK_EQUAL(val, wd[i][j][k].as<float>());
+ }
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_proxy){
+ wax_demo wd(2, 1);
+ std::cout << "store proxy" << std::endl;
+ wax::obj p = wd[size_t(0)][size_t(0)];
+ p[size_t(0)] = float(5);
+
+ std::cout << "assign proxy" << std::endl;
+ wax::obj a = p[size_t(0)];
+ BOOST_CHECK_EQUAL(a.as<float>(), float(5));
+}