aboutsummaryrefslogtreecommitdiffstats
path: root/host/tests/error_c_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/tests/error_c_test.cpp')
-rw-r--r--host/tests/error_c_test.cpp142
1 files changed, 142 insertions, 0 deletions
diff --git a/host/tests/error_c_test.cpp b/host/tests/error_c_test.cpp
new file mode 100644
index 000000000..bb9454678
--- /dev/null
+++ b/host/tests/error_c_test.cpp
@@ -0,0 +1,142 @@
+//
+// Copyright 2015 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/error.h>
+#include <uhd/types/dict.hpp>
+
+#include <boost/test/unit_test.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/assign.hpp>
+#include <boost/format.hpp>
+
+/*
+ * Test our conversions from exceptions to C-level UHD error codes.
+ * We use inline functions separate from the Boost test cases themselves
+ * to test our C++ macro, which returns the error code.
+ */
+
+typedef struct {
+ std::string last_error;
+} dummy_handle_t;
+
+template <typename error_type>
+UHD_INLINE uhd_error throw_uhd_exception(dummy_handle_t *handle, const uhd::exception* except){
+ UHD_SAFE_C_SAVE_ERROR(handle,
+ throw *dynamic_cast<const error_type*>(except);
+ )
+}
+
+UHD_INLINE uhd_error throw_boost_exception(dummy_handle_t *handle){
+ UHD_SAFE_C_SAVE_ERROR(handle,
+ std::runtime_error except("This is a std::runtime_error, thrown by Boost.");
+ BOOST_THROW_EXCEPTION(except);
+ )
+}
+
+UHD_INLINE uhd_error throw_std_exception(dummy_handle_t *handle){
+ UHD_SAFE_C_SAVE_ERROR(handle,
+ throw std::runtime_error("This is a std::runtime_error.");
+ )
+}
+
+UHD_INLINE uhd_error throw_unknown_exception(dummy_handle_t *handle){
+ UHD_SAFE_C_SAVE_ERROR(handle,
+ throw 1;
+ )
+}
+
+// There are enough non-standard names that we can't just use a conversion function
+static const uhd::dict<std::string, std::string> pretty_exception_names =
+ boost::assign::map_list_of
+ ("assertion_error", "AssertionError")
+ ("lookup_error", "LookupError")
+ ("index_error", "LookupError: IndexError")
+ ("key_error", "LookupError: KeyError")
+ ("type_error", "TypeError")
+ ("value_error", "ValueError")
+ ("runtime_error", "RuntimeError")
+ ("not_implemented_error", "RuntimeError: NotImplementedError")
+ ("usb_error", "RuntimeError: USBError 1")
+ ("environment_error", "EnvironmentError")
+ ("io_error", "EnvironmentError: IOError")
+ ("os_error", "EnvironmentError: OSError")
+ ("system_error", "SystemError")
+ ;
+
+#define UHD_TEST_CHECK_ERROR_CODE(cpp_exception_type, c_error_code) \
+ expected_msg = str(boost::format("This is a uhd::%s.") % BOOST_STRINGIZE(cpp_exception_type)); \
+ uhd::cpp_exception_type cpp_exception_type ## _foo(expected_msg); \
+ error_code = throw_uhd_exception<uhd::cpp_exception_type>(&handle, &cpp_exception_type ## _foo); \
+ BOOST_CHECK_EQUAL(error_code, c_error_code); \
+ BOOST_CHECK_EQUAL(handle.last_error, \
+ str(boost::format("%s: %s") \
+ % pretty_exception_names.get(BOOST_STRINGIZE(cpp_exception_type)) \
+ % expected_msg));
+
+// uhd::usb_error has a different constructor
+#define UHD_TEST_CHECK_USB_ERROR_CODE() \
+ expected_msg = "This is a uhd::usb_error."; \
+ uhd::usb_error usb_error_foo(1, expected_msg); \
+ error_code = throw_uhd_exception<uhd::usb_error>(&handle, &usb_error_foo); \
+ BOOST_CHECK_EQUAL(error_code, UHD_ERROR_USB); \
+ BOOST_CHECK_EQUAL(handle.last_error, \
+ str(boost::format("%s: %s") \
+ % pretty_exception_names.get("usb_error") \
+ % expected_msg));
+
+BOOST_AUTO_TEST_CASE(test_uhd_exception){
+ dummy_handle_t handle;
+ std::string expected_msg;
+ uhd_error error_code;
+
+ UHD_TEST_CHECK_ERROR_CODE(assertion_error, UHD_ERROR_ASSERTION);
+ UHD_TEST_CHECK_ERROR_CODE(lookup_error, UHD_ERROR_LOOKUP);
+ UHD_TEST_CHECK_ERROR_CODE(index_error, UHD_ERROR_INDEX);
+ UHD_TEST_CHECK_ERROR_CODE(key_error, UHD_ERROR_KEY);
+ UHD_TEST_CHECK_ERROR_CODE(type_error, UHD_ERROR_TYPE);
+ UHD_TEST_CHECK_ERROR_CODE(value_error, UHD_ERROR_VALUE);
+ UHD_TEST_CHECK_ERROR_CODE(runtime_error, UHD_ERROR_RUNTIME);
+ UHD_TEST_CHECK_ERROR_CODE(not_implemented_error, UHD_ERROR_NOT_IMPLEMENTED);
+ UHD_TEST_CHECK_ERROR_CODE(io_error, UHD_ERROR_IO);
+ UHD_TEST_CHECK_ERROR_CODE(os_error, UHD_ERROR_OS);
+ UHD_TEST_CHECK_ERROR_CODE(system_error, UHD_ERROR_SYSTEM);
+ UHD_TEST_CHECK_USB_ERROR_CODE();
+}
+
+BOOST_AUTO_TEST_CASE(test_boost_exception){
+ dummy_handle_t handle;
+ uhd_error error_code = throw_boost_exception(&handle);
+
+ // Boost error message cannot be determined here, so just check code
+ BOOST_CHECK_EQUAL(error_code, UHD_ERROR_BOOSTEXCEPT);
+}
+
+BOOST_AUTO_TEST_CASE(test_std_exception){
+ dummy_handle_t handle;
+ uhd_error error_code = throw_std_exception(&handle);
+
+ BOOST_CHECK_EQUAL(error_code, UHD_ERROR_STDEXCEPT);
+ BOOST_CHECK_EQUAL(handle.last_error, "This is a std::runtime_error.");
+}
+
+BOOST_AUTO_TEST_CASE(test_unknown_exception){
+ dummy_handle_t handle;
+ uhd_error error_code = throw_unknown_exception(&handle);
+
+ BOOST_CHECK_EQUAL(error_code, UHD_ERROR_UNKNOWN);
+ BOOST_CHECK_EQUAL(handle.last_error, "Unrecognized exception caught.");
+}