diff --git a/src/viam/sdk/CMakeLists.txt b/src/viam/sdk/CMakeLists.txt index 8b5990d55..4805e1c07 100644 --- a/src/viam/sdk/CMakeLists.txt +++ b/src/viam/sdk/CMakeLists.txt @@ -37,6 +37,7 @@ endif() target_sources(viamsdk PRIVATE common/client_helper.cpp + common/exception.cpp common/linear_algebra.cpp common/pose.cpp common/proto_type.cpp @@ -109,6 +110,7 @@ target_sources(viamsdk ../.. FILES ../../viam/sdk/common/client_helper.hpp + ../../viam/sdk/common/exception.hpp ../../viam/sdk/common/linear_algebra.hpp ../../viam/sdk/common/pose.hpp ../../viam/sdk/common/proto_type.hpp diff --git a/src/viam/sdk/common/client_helper.hpp b/src/viam/sdk/common/client_helper.hpp index 42a52a7ff..703d072ec 100644 --- a/src/viam/sdk/common/client_helper.hpp +++ b/src/viam/sdk/common/client_helper.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -16,7 +17,7 @@ class ClientHelper { static void default_rsc_(RequestType&) {} static void default_rhc_(const ResponseType&) {} static void default_ehc_(const ::grpc::Status& status) { - throw std::runtime_error(status.error_message()); + throw GRPCException(status); } public: diff --git a/src/viam/sdk/common/exception.cpp b/src/viam/sdk/common/exception.cpp new file mode 100644 index 000000000..f9832e122 --- /dev/null +++ b/src/viam/sdk/common/exception.cpp @@ -0,0 +1,56 @@ +#include + +namespace viam { +namespace sdk { + +Exception::Exception(ErrorCondition condition, const std::string& what) + : std::runtime_error("viam::sdk::Exception: " + what), condition_(condition){}; + +Exception::Exception(const std::string& what) : Exception(ErrorCondition::k_general, what){}; + +Exception::~Exception() = default; + +const std::error_condition& Exception::condition() const noexcept { + return condition_; +}; + +std::error_condition make_error_condition(ErrorCondition e) { + struct ErrorCategory : std::error_category { + const char* name() const noexcept override { + return "viam::sdk"; + }; + std::string message(int ev) const override { + switch (static_cast(ev)) { + case ErrorCondition::k_general: + return "general"; + case ErrorCondition::k_connection: + return "connection establishment failure"; + case ErrorCondition::k_duplicate_registration: + return "duplicate registration"; + case ErrorCondition::k_duplicate_resource: + return "duplicate resource"; + case ErrorCondition::k_grpc: + return "gRPC"; + case ErrorCondition::k_not_supported: + return "not supported"; + case ErrorCondition::k_resource_not_found: + return "resource not found"; + default: + return "unknown"; + } + }; + }; + + static const ErrorCategory errorCategory{}; + return {static_cast(e), errorCategory}; +} + +GRPCException::GRPCException(grpc::Status status) + : Exception(ErrorCondition::k_grpc, status.error_message()), status_(std::move(status)){}; + +const grpc::Status& GRPCException::status() const noexcept { + return status_; +} + +} // namespace sdk +} // namespace viam diff --git a/src/viam/sdk/common/exception.hpp b/src/viam/sdk/common/exception.hpp new file mode 100644 index 000000000..c9ab11e3b --- /dev/null +++ b/src/viam/sdk/common/exception.hpp @@ -0,0 +1,66 @@ +/// @file common/exception.hpp +/// +/// @brief Defines custom exceptions for the SDK. +#pragma once +#include +#include +#include + +#include + +namespace viam { +namespace sdk { + +/// @defgroup Exception Classes related to SDK exceptions. + +/// @class ErrorCondition +/// @brief Defines a set of a error conditions to be used in conjunction with +/// Exception. +/// @ingroup Exception +enum class ErrorCondition : uint8_t { + k_general = 0, // Default condition + k_connection = 1, // Issue during connection establishment + k_duplicate_registration = 2, // API or API/Model pair has already been registered + k_duplicate_resource = 3, // Resource has already been added + k_grpc = 4, // gRPC error from remote machine + k_not_supported = 5, // Behavior not supported by the SDK + k_resource_not_found = 6 // Resource does not exist +}; + +std::error_condition make_error_condition(ErrorCondition e); + +/// @class Exception +/// @brief Defines an exception type for the SDK. +/// @ingroup Exception +class Exception : public std::runtime_error { + public: + explicit Exception(ErrorCondition condition, const std::string& what); + explicit Exception(const std::string& what); + virtual ~Exception(); + + const std::error_condition& condition() const noexcept; + + private: + std::error_condition condition_; +}; + +/// @class GRPCException +/// @brief Defines an exception from a gRPC interaction. +/// @ingroup Exception +class GRPCException : public Exception { + public: + explicit GRPCException(grpc::Status status); + + const grpc::Status& status() const noexcept; + + private: + grpc::Status status_; +}; + +} // namespace sdk +} // namespace viam + +namespace std { +template <> +struct is_error_condition_enum : true_type {}; +} // namespace std diff --git a/src/viam/sdk/common/proto_type.cpp b/src/viam/sdk/common/proto_type.cpp index 01a6fc879..c0d10d252 100644 --- a/src/viam/sdk/common/proto_type.cpp +++ b/src/viam/sdk/common/proto_type.cpp @@ -10,6 +10,7 @@ #include #include +#include #include namespace viam { @@ -131,7 +132,7 @@ Value ProtoType::proto_value() { break; } default: { - throw std::runtime_error( + throw Exception( "Invalid proto_value conversion type. This should never happen;\ please file a bug report."); } @@ -194,8 +195,9 @@ bool operator==(const ProtoType& lhs, const ProtoType& rhs) { return std::equal(lhs_vec.begin(), lhs_vec.end(), rhs_vec.begin(), rhs_vec.end(), pred); } default: { - throw "Invalid proto_value conversion type. This should never happen;\ - please file a bug report."; + throw Exception( + "Invalid proto_value conversion type. This should never happen;\ + please file a bug report."); } } } diff --git a/src/viam/sdk/components/board/board.cpp b/src/viam/sdk/components/board/board.cpp index e15d72c2e..3abbf46fd 100644 --- a/src/viam/sdk/components/board/board.cpp +++ b/src/viam/sdk/components/board/board.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -48,7 +49,8 @@ Board::power_mode Board::from_proto(viam::component::board::v1::PowerMode proto) } case viam::component::board::v1::POWER_MODE_UNSPECIFIED: default: { - throw std::runtime_error("Invalid proto board power_mode to decode"); + throw Exception(ErrorCondition::k_not_supported, + "Invalid proto board power_mode to decode"); } } } @@ -86,7 +88,7 @@ viam::component::board::v1::PowerMode Board::to_proto(Board::power_mode power_mo return viam::component::board::v1::POWER_MODE_OFFLINE_DEEP; } default: { - throw std::runtime_error("Invalid board power_mode to encode"); + throw Exception(ErrorCondition::k_not_supported, "Invalid board power_mode to encode"); } } } diff --git a/src/viam/sdk/components/board/client.cpp b/src/viam/sdk/components/board/client.cpp index e28383f3d..f96f2807d 100644 --- a/src/viam/sdk/components/board/client.cpp +++ b/src/viam/sdk/components/board/client.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -101,7 +102,7 @@ Board::analog_value BoardClient::read_analog(const std::string& analog_reader_na const grpc::Status status = stub_->ReadAnalogReader(ctx, request, &response); if (!status.ok()) { - throw std::runtime_error(status.error_message()); + throw GRPCException(status); } return response.value(); } @@ -130,7 +131,7 @@ Board::digital_value BoardClient::read_digital_interrupt(const std::string& digi const grpc::Status status = stub_->GetDigitalInterruptValue(ctx, request, &response); if (!status.ok()) { - throw std::runtime_error(status.error_message()); + throw GRPCException(status); } return response.value(); } diff --git a/src/viam/sdk/components/encoder/encoder.cpp b/src/viam/sdk/components/encoder/encoder.cpp index 52a2505c7..a155976d0 100644 --- a/src/viam/sdk/components/encoder/encoder.cpp +++ b/src/viam/sdk/components/encoder/encoder.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -31,7 +32,8 @@ Encoder::position_type Encoder::from_proto(viam::component::encoder::v1::Positio return Encoder::position_type::ticks_count; } default: { - throw std::runtime_error("Invalid proto encoder type to decode"); + throw Exception(ErrorCondition::k_not_supported, + "Invalid proto encoder type to decode"); } } } @@ -64,7 +66,8 @@ viam::component::encoder::v1::PositionType Encoder::to_proto(position_type posit return viam::component::encoder::v1::POSITION_TYPE_TICKS_COUNT; } default: { - throw std::runtime_error("Invalid proto encoder type to encode"); + throw Exception(ErrorCondition::k_not_supported, + "Invalid proto encoder type to encode"); } } } diff --git a/src/viam/sdk/components/motor/motor.hpp b/src/viam/sdk/components/motor/motor.hpp index 173cd69e3..fcc27d8c4 100644 --- a/src/viam/sdk/components/motor/motor.hpp +++ b/src/viam/sdk/components/motor/motor.hpp @@ -83,7 +83,7 @@ class Motor : public Component, public Stoppable { /// `revolutions` == 0, this will run the motor at `rpm` indefinetely. If `revolutions` != 0, /// this will block until the number of revolutions has been completed or another operation /// comes in. - /// @throws runtime_error if position reporting is not supported + /// @throws `Exception` if position reporting is not supported inline void go_for(double rpm, double revolutions) { return go_for(rpm, revolutions, {}); } @@ -96,14 +96,14 @@ class Motor : public Component, public Stoppable { /// this will block until the number of revolutions has been completed or another operation /// comes in. /// @param extra Any additional arguments to the method. - /// @throws runtime_error if position reporting is not supported + /// @throws `Exception` if position reporting is not supported virtual void go_for(double rpm, double revolutions, const AttributeMap& extra) = 0; /// @brief Move the motor to a specific position that is relative to its /// home position at a specified speed which is expressed in RPM. /// @param rpm Speed of motor travel in rotations per minute /// @param position_revolutions Number of revolutions relative to motor's home home/zero - /// @throws runtime_error if position reporting is not supported + /// @throws `Exception` if position reporting is not supported inline void go_to(double rpm, double position_revolutions) { return go_to(rpm, position_revolutions, {}); } @@ -113,12 +113,12 @@ class Motor : public Component, public Stoppable { /// @param rpm Speed of motor travel in rotations per minute /// @param position_revolutions Number of revolutions relative to motor's home home/zero /// @param extra Any additional arguments to the method. - /// @throws runtime_error if position reporting is not supported + /// @throws `Exception` if position reporting is not supported virtual void go_to(double rpm, double position_revolutions, const AttributeMap& extra) = 0; /// @brief Sets the current position of the motor as the new zero position. /// @param offset Motor position - /// @throws runtime_error if position reporting is not supported + /// @throws `Exception` if position reporting is not supported inline void reset_zero_position(double offset) { return reset_zero_position(offset, {}); } @@ -126,18 +126,18 @@ class Motor : public Component, public Stoppable { /// @brief Sets the current position of the motor as the new zero position. /// @param offset Motor position /// @param extra Any additional arguments to the method - /// @throws runtime_error if position reporting is not supported + /// @throws `Exception` if position reporting is not supported virtual void reset_zero_position(double offset, const AttributeMap& extra) = 0; /// @brief Reports the position of the robot's motor relative to its zero position. - /// @throws runtime_error if position reporting is not supported + /// @throws `Exception` if position reporting is not supported inline position get_position() { return get_position({}); } /// @brief Reports the position of the robot's motor relative to its zero position. /// @param extra Any additional arguments to the method - /// @throws runtime_error if position reporting is not supported + /// @throws `Exception` if position reporting is not supported virtual position get_position(const AttributeMap& extra) = 0; /// @brief Returns the properties of the motor which comprises the booleans indicating diff --git a/src/viam/sdk/components/servo/servo.hpp b/src/viam/sdk/components/servo/servo.hpp index d9012b66f..2a8652f8a 100644 --- a/src/viam/sdk/components/servo/servo.hpp +++ b/src/viam/sdk/components/servo/servo.hpp @@ -43,14 +43,14 @@ class Servo : public Component, public Stoppable { virtual void move(uint32_t angle_deg, const AttributeMap& extra) = 0; /// @brief Get the current angle (degrees) of the servo. - /// @throws runtime_error if position reporting is not supported + /// @throws `Exception` if position reporting is not supported inline position get_position() { return get_position({}); } /// @brief Reports the position of the robot's servo relative to its zero position. /// @param extra Any additional arguments to the method - /// @throws runtime_error if position reporting is not supported + /// @throws `Exception` if position reporting is not supported virtual position get_position(const AttributeMap& extra) = 0; /// @brief Stops a resource from running. diff --git a/src/viam/sdk/config/resource.cpp b/src/viam/sdk/config/resource.cpp index 4a002dfcf..15dd21493 100644 --- a/src/viam/sdk/config/resource.cpp +++ b/src/viam/sdk/config/resource.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -84,8 +85,7 @@ void ResourceConfig::fix_api() { // config structs if (this->api_.type_namespace() != this->namespace__ || this->api_.resource_subtype() != this->type_) { - throw std::runtime_error( - "component namespace and/or type do not match component api field"); + throw Exception("component namespace and/or type do not match component api field"); } } diff --git a/src/viam/sdk/module/service.cpp b/src/viam/sdk/module/service.cpp index 90217bbb9..87e6931d7 100644 --- a/src/viam/sdk/module/service.cpp +++ b/src/viam/sdk/module/service.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -54,7 +55,7 @@ Dependencies ModuleService::get_dependencies_( std::ostringstream buffer; buffer << resource_name << ": Dependency " << "`" << dep_name << "` was not found during (re)configuration"; - throw std::invalid_argument(buffer.str()); + throw Exception(ErrorCondition::k_resource_not_found, buffer.str()); } deps.emplace(dep_name, dep_resource); } @@ -217,7 +218,7 @@ ModuleService::ModuleService(int argc, char** argv, std::vector> registrations) { if (argc < 2) { - throw std::runtime_error("Need socket path as command line argument"); + throw Exception("Need socket path as command line argument"); } module_ = std::make_unique(argv[1]); server_ = std::make_unique(); diff --git a/src/viam/sdk/module/signal_manager.hpp b/src/viam/sdk/module/signal_manager.hpp index 1000136b4..90e62d12d 100644 --- a/src/viam/sdk/module/signal_manager.hpp +++ b/src/viam/sdk/module/signal_manager.hpp @@ -16,7 +16,7 @@ class SignalManager { /// @brief Wait for SignalManager to receive SIGINT or SIGTERM. /// @return The signal number if successful. - /// @throws runtime_error if the underlying sigwait call was unsuccessful. + /// @throws `std::runtime_error` if the underlying sigwait call was unsuccessful. int wait(); private: diff --git a/src/viam/sdk/registry/registry.cpp b/src/viam/sdk/registry/registry.cpp index 67aa67fde..6f427e12c 100644 --- a/src/viam/sdk/registry/registry.cpp +++ b/src/viam/sdk/registry/registry.cpp @@ -10,7 +10,7 @@ #include #include #include - +#include #include #include #include @@ -59,8 +59,9 @@ const Model& ModelRegistration::model() const { void Registry::register_model(std::shared_ptr resource) { std::string reg_key = resource->api().to_string() + "/" + resource->model().to_string(); if (resources_.find(reg_key) != resources_.end()) { - const std::string err = "Cannot add resource with name " + reg_key + "as it already exists"; - throw std::runtime_error(err); + const std::string err = "Cannot register API/model pair" + reg_key + + " as that pair has already been registered"; + throw Exception(ErrorCondition::k_duplicate_registration, err); } resources_.emplace(std::move(reg_key), std::move(resource)); @@ -69,7 +70,9 @@ void Registry::register_model(std::shared_ptr resource) void Registry::register_resource_server_( API api, std::shared_ptr resource_registration) { if (server_apis_.find(api) != server_apis_.end()) { - throw std::runtime_error("Cannot add api " + api.to_string() + " as it already exists"); + const std::string err = + "Cannot register server API" + api.to_string() + " as it has already been registered"; + throw Exception(ErrorCondition::k_duplicate_registration, err); } server_apis_.emplace(std::move(api), std::move(resource_registration)); @@ -78,7 +81,9 @@ void Registry::register_resource_server_( void Registry::register_resource_client_( API api, std::shared_ptr resource_registration) { if (client_apis_.find(api) != client_apis_.end()) { - throw std::runtime_error("Cannot add api " + api.to_string() + " as it already exists"); + const std::string err = + "Cannot register client API" + api.to_string() + " as it has already been registered"; + throw Exception(ErrorCondition::k_duplicate_registration, err); } client_apis_.emplace(std::move(api), std::move(resource_registration)); @@ -128,7 +133,7 @@ const google::protobuf::ServiceDescriptor* Registry::get_service_descriptor_( const google::protobuf::DescriptorPool* p = google::protobuf::DescriptorPool::generated_pool(); const google::protobuf::ServiceDescriptor* sd = p->FindServiceByName(service_full_name); if (!sd) { - throw std::runtime_error("Unable to get service descriptor"); + throw Exception("Unable to get service descriptor"); } return sd; } diff --git a/src/viam/sdk/registry/registry.hpp b/src/viam/sdk/registry/registry.hpp index 89b4ff931..436600e8a 100644 --- a/src/viam/sdk/registry/registry.hpp +++ b/src/viam/sdk/registry/registry.hpp @@ -114,7 +114,7 @@ class Registry { public: /// @brief Registers a resource with the Registry. /// @param resource An object containing resource registration information. - /// @throws `std::runtime_error` if the resource has already been registered. + /// @throws `Exception` if the resource has already been registered. static void register_model(std::shared_ptr resource); /// @brief Lookup a given registered resource. diff --git a/src/viam/sdk/resource/resource_api.cpp b/src/viam/sdk/resource/resource_api.cpp index 0f98c1d11..24f8f55f1 100644 --- a/src/viam/sdk/resource/resource_api.cpp +++ b/src/viam/sdk/resource/resource_api.cpp @@ -11,6 +11,7 @@ #include +#include #include #include @@ -67,7 +68,7 @@ API API::from_string(std::string api) { boost::split(api_parts, api, boost::is_any_of(":")); return {api_parts.at(0), api_parts.at(1), api_parts.at(2)}; } - throw "string " + api + " is not a valid api name"; + throw Exception("string " + api + " is not a valid api name"); } API::API(APIType type, std::string resource_subtype) @@ -143,7 +144,7 @@ Name Name::from_proto(const viam::common::v1::ResourceName& proto) { Name Name::from_string(std::string name) { if (!std::regex_match(name, NAME_REGEX)) { - throw "Received invalid Name string: " + name; + throw Exception("Received invalid Name string: " + name); } std::vector slash_splits; boost::split(slash_splits, name, boost::is_any_of("/")); @@ -233,7 +234,7 @@ Model Model::from_str(std::string model) { if (std::regex_match(model, SINGLE_FIELD_REGEX)) { return {"rdk", "builtin", model}; } - throw std::runtime_error("string " + model + " is not a valid model name"); + throw Exception("string " + model + " is not a valid model name"); } std::string ModelFamily::to_string() const { diff --git a/src/viam/sdk/resource/resource_api.hpp b/src/viam/sdk/resource/resource_api.hpp index 7a01a874f..5677a8fd4 100644 --- a/src/viam/sdk/resource/resource_api.hpp +++ b/src/viam/sdk/resource/resource_api.hpp @@ -125,7 +125,7 @@ class Model { /// @brief Parses a single model string into a Model, using default values for namespace and /// family if not provided. /// - /// @throws `std::runtime_error` if given an invalid model (i.e., one with non-word characters). + /// @throws `Exception` if given an invalid model (i.e., one with non-word characters). static Model from_str(std::string model); friend bool operator==(const Model& lhs, const Model& rhs); diff --git a/src/viam/sdk/resource/resource_manager.cpp b/src/viam/sdk/resource/resource_manager.cpp index 795fa8c15..8f2940c5f 100644 --- a/src/viam/sdk/resource/resource_manager.cpp +++ b/src/viam/sdk/resource/resource_manager.cpp @@ -14,6 +14,7 @@ #include +#include #include #include #include @@ -67,7 +68,7 @@ std::string get_shortcut_name(const std::string& name) { void ResourceManager::do_add(const Name& name, std::shared_ptr resource) { if (name.name().empty()) { - throw "Empty name used for resource: " + name.to_string(); + throw Exception("Empty name used for resource: " + name.to_string()); } std::string short_name = name.short_name(); @@ -76,7 +77,8 @@ void ResourceManager::do_add(const Name& name, std::shared_ptr resourc void ResourceManager::do_add(std::string name, std::shared_ptr resource) { if (resources_.find(name) != resources_.end()) { - throw "Attempted to add resource that already existed: " + name; + throw Exception(ErrorCondition::k_duplicate_resource, + "Attempted to add resource that already existed: " + name); } std::string shortcut = get_shortcut_name(name); @@ -102,7 +104,9 @@ void ResourceManager::add(const Name& name, std::shared_ptr resource) void ResourceManager::do_remove(const Name& name) { const std::string short_name = name.short_name(); if (resources_.find(short_name) == resources_.end()) { - throw "attempted to remove resource " + name.to_string() + " but it didn't exist!"; + throw Exception( + ErrorCondition::k_resource_not_found, + "Attempted to remove resource " + name.to_string() + " but it didn't exist!"); } resources_.erase(short_name); diff --git a/src/viam/sdk/resource/resource_manager.hpp b/src/viam/sdk/resource/resource_manager.hpp index 0457162be..3bc894f49 100644 --- a/src/viam/sdk/resource/resource_manager.hpp +++ b/src/viam/sdk/resource/resource_manager.hpp @@ -25,12 +25,12 @@ class ResourceManager { public: /// @brief Returns a resource. /// @param name the name of the desired resource. - /// @throws `std::runtime_error` if the desired resource does not exist. + /// @throws `Exception` if the desired resource does not exist. std::shared_ptr resource(const std::string& name); /// @brief Returns a resource after dynamically downcasting to `T`. /// @param name of the desired resource. - /// @throws `std::runtime_error` if the desired resource does not exist. + /// @throws `Exception` if the desired resource does not exist. template std::shared_ptr resource(const std::string& name) { static_assert(std::is_base_of::value, "T is not derived from Resource"); diff --git a/src/viam/sdk/robot/client.hpp b/src/viam/sdk/robot/client.hpp index 2597f4b01..c043dabcb 100644 --- a/src/viam/sdk/robot/client.hpp +++ b/src/viam/sdk/robot/client.hpp @@ -72,7 +72,7 @@ class RobotClient { /// @brief Lookup and return a `shared_ptr` to a resource. /// @param name The `ResourceName` of the resource. - /// @throws `std::runtime_error` if the requested resource doesn't exist or is the wrong type. + /// @throws `Exception` if the requested resource doesn't exist or is the wrong type. /// @return a `shared_ptr` to the requested resource as an uncasted `Resource`. /// /// This method should not be called directly except in specific cases. The @@ -86,7 +86,7 @@ class RobotClient { template /// @brief Lookup and return a `shared_ptr` to a resource of the requested type. /// @param name The ordinary name of the resource. - /// @throws `std::runtime_error` if the requested resource doesn't exist or is the wrong type. + /// @throws `Exception` if the requested resource doesn't exist or is the wrong type. /// @return a `shared_ptr` to the requested resource. std::shared_ptr resource_by_name(std::string name) { ResourceName r; diff --git a/src/viam/sdk/rpc/dial.cpp b/src/viam/sdk/rpc/dial.cpp index 4ac15590e..34ac1c24f 100644 --- a/src/viam/sdk/rpc/dial.cpp +++ b/src/viam/sdk/rpc/dial.cpp @@ -11,6 +11,7 @@ #include #include +#include extern "C" void* init_rust_runtime(); extern "C" int free_rust_runtime(void* ptr); @@ -103,9 +104,7 @@ std::shared_ptr ViamChannel::dial(const char* uri, uri, entity, type, payload, opts.allows_insecure_downgrade(), float_timeout.count(), ptr); if (socket_path == NULL) { free_rust_runtime(ptr); - // TODO(RSDK-1742) Replace throwing of strings with throwing of - // runtime_error - throw "Unable to establish connecting path!"; + throw Exception(ErrorCondition::k_connection, "Unable to establish connecting path"); } std::string address("unix://"); diff --git a/src/viam/sdk/rpc/server.cpp b/src/viam/sdk/rpc/server.cpp index 1b55ddef1..ff755fe50 100644 --- a/src/viam/sdk/rpc/server.cpp +++ b/src/viam/sdk/rpc/server.cpp @@ -5,6 +5,7 @@ #include #include +#include #include namespace viam { @@ -33,7 +34,7 @@ std::shared_ptr Server::lookup_resource_server(const API& api) { void Server::register_service(grpc::Service* service) { if (!builder_) { - throw std::runtime_error("Cannot register a new service after the server has started"); + throw Exception("Cannot register a new service after the server has started"); } builder_->RegisterService(service); @@ -45,7 +46,7 @@ void Server::add_resource(std::shared_ptr resource) { std::ostringstream buffer; buffer << "Attempted to add resource with API: " << api << " but no matching resource server as found"; - throw std::runtime_error(buffer.str()); + throw Exception(ErrorCondition::k_resource_not_found, buffer.str()); } auto resource_server = managed_servers_.at(api); auto name = resource->name(); @@ -54,7 +55,7 @@ void Server::add_resource(std::shared_ptr resource) { void Server::start() { if (server_) { - throw std::runtime_error("Attempted to start server that was already running"); + throw Exception("Attempted to start server that was already running"); } server_ = builder_->BuildAndStart(); @@ -64,7 +65,7 @@ void Server::start() { void Server::add_listening_port(std::string address, std::shared_ptr creds) { if (!builder_) { - throw std::runtime_error("Cannot add a listening port after server has started"); + throw Exception("Cannot add a listening port after server has started"); } if (!creds) { diff --git a/src/viam/sdk/rpc/server.hpp b/src/viam/sdk/rpc/server.hpp index 5e1a12f03..2f453bb4a 100644 --- a/src/viam/sdk/rpc/server.hpp +++ b/src/viam/sdk/rpc/server.hpp @@ -28,13 +28,13 @@ class Server { ~Server(); /// @brief Starts the grpc server. Can only be called once. - /// @throws `std::runtime_error` if the server was already `start`ed. + /// @throws `Exception` if the server was already `start`ed. /// repeated calls. void start(); /// @brief Registers a gRPC service. /// @param service The gRPC service to be registered. - /// @throws `std::runtime_error` if called after the server has been `start`ed. + /// @throws `Exception` if called after the server has been `start`ed. void register_service(grpc::Service* service); /// @brief Returns reference to managed resource server. @@ -44,13 +44,13 @@ class Server { /// @brief Adds a specific managed resource to the associated resource server /// @param resource The resource to add - /// @throws `std::runtime_error` if a matching `ResourceServer` doesn't exist in the server. + /// @throws `Exception` if a matching `ResourceServer` doesn't exist in the server. void add_resource(std::shared_ptr resource); /// @brief Adds a listening port to the server. /// @param address The address to listen at. /// @param creds The server credentials; defaults to a insecure server credentials. - /// @throws `std::runtime_error` if called after the server has been `start`ed. + /// @throws `Exception` if called after the server has been `start`ed. void add_listening_port(std::string address, std::shared_ptr creds = nullptr); diff --git a/src/viam/sdk/services/mlmodel/client.cpp b/src/viam/sdk/services/mlmodel/client.cpp index 923461e1a..6e978dbb8 100644 --- a/src/viam/sdk/services/mlmodel/client.cpp +++ b/src/viam/sdk/services/mlmodel/client.cpp @@ -19,6 +19,8 @@ #include #include +#include + namespace viam { namespace sdk { @@ -58,7 +60,7 @@ std::shared_ptr MLModelServiceClient::infer( const auto result = stub_->Infer(ctx, *req, resp); if (!result.ok()) { - throw std::runtime_error(result.error_message()); + throw GRPCException(result); } for (const auto& kv : resp->output_tensors().tensors()) { @@ -107,8 +109,7 @@ struct MLModelService::metadata MLModelServiceClient::metadata(const AttributeMa message << "Failed to deserialize returned Metadata.TensorInfo.data_type field " "with value `" << s.data_type() << "` to one of the known tensor data types"; - // TODO: Throw viam exception once PR #100 merges. - throw std::runtime_error(message.str()); + throw Exception(message.str()); } ti.data_type = *data_type; ti.shape.reserve(s.shape_size()); @@ -133,8 +134,7 @@ struct MLModelService::metadata MLModelServiceClient::metadata(const AttributeMa message << "Failed to deserialize returned " "Metadata.TensorInfo.File.label_type field with value `" << af.label_type() << "` to one of the known label types"; - // TODO: Throw viam exception once PR #100 merges. - throw std::runtime_error(message.str()); + throw Exception(message.str()); } } } diff --git a/src/viam/sdk/services/mlmodel/private/proto.cpp b/src/viam/sdk/services/mlmodel/private/proto.cpp index 7a063069c..c03a7b223 100644 --- a/src/viam/sdk/services/mlmodel/private/proto.cpp +++ b/src/viam/sdk/services/mlmodel/private/proto.cpp @@ -23,6 +23,8 @@ #include #include +#include + namespace viam { namespace sdk { namespace mlmodel_details { @@ -123,7 +125,7 @@ MLModelService::tensor_views make_sdk_tensor_from_api_tensor_t(const T* data, if (!data || (size == 0) || shape.empty()) { std::ostringstream message; message << "Empty or zero length data or shape"; - throw std::invalid_argument(message.str()); + throw Exception(message.str()); } if (ts) { @@ -143,7 +145,7 @@ MLModelService::tensor_views make_sdk_tensor_from_api_tensor_t(const T* data, std::ostringstream message; // TODO: Provide the shape message << "Provided shape information exceeds bounds of size_t when linearized"; - throw std::length_error(message.str()); + throw Exception(message.str()); } shape_accum = next_shape_accum; } @@ -162,7 +164,7 @@ MLModelService::tensor_views make_sdk_tensor_from_api_tensor_t(const T* data, std::ostringstream message; // TODO: Provide the shape and details message << "Number of provided data elements does not match provided shape"; - throw std::invalid_argument(message.str()); + throw Exception(message.str()); } return MLModelService::make_tensor_view(data, size, std::move(shape)); @@ -240,7 +242,7 @@ MLModelService::tensor_views make_sdk_tensor_from_api_tensor( std::move(shape), storage); } - throw std::invalid_argument("Unsupported tensor data type"); + throw Exception(ErrorCondition::k_not_supported, "Unsupported tensor data type"); } } // namespace mlmodel_details diff --git a/src/viam/sdk/services/motion/motion.cpp b/src/viam/sdk/services/motion/motion.cpp index e31a1ab4a..8b16705d6 100644 --- a/src/viam/sdk/services/motion/motion.cpp +++ b/src/viam/sdk/services/motion/motion.cpp @@ -6,6 +6,7 @@ #include #include +#include #include namespace viam { @@ -253,7 +254,7 @@ Motion::plan_state Motion::from_proto(const service::motion::v1::PlanState& prot return Motion::plan_state::k_stopped; } default: { - throw std::runtime_error("Invalid proto PlanState to encode"); + throw Exception(ErrorCondition::k_not_supported, "Invalid proto PlanState to encode"); } } } @@ -273,7 +274,8 @@ service::motion::v1::PlanState Motion::to_proto(const Motion::plan_state& state) return service::motion::v1::PLAN_STATE_STOPPED; } default: { - throw std::runtime_error("Invalid plan_state to encode to proto"); + throw Exception(ErrorCondition::k_not_supported, + "Invalid plan_state to encode to proto"); } } } diff --git a/src/viam/sdk/spatialmath/geometry.cpp b/src/viam/sdk/spatialmath/geometry.cpp index 3325b6abd..2eb829083 100644 --- a/src/viam/sdk/spatialmath/geometry.cpp +++ b/src/viam/sdk/spatialmath/geometry.cpp @@ -7,6 +7,7 @@ #include +#include #include namespace viam { @@ -19,7 +20,7 @@ viam::common::v1::Sphere GeometryConfig::sphere_proto() const { sphere.set_radius_mm(sphere_specifics.radius); return sphere; } catch (...) { - throw std::runtime_error( + throw Exception( "Couldn't convert geometry config to sphere proto; sphere specifics not found"); } } @@ -35,8 +36,7 @@ viam::common::v1::RectangularPrism GeometryConfig::box_proto() const { *box.mutable_dims_mm() = vec3; return box; } catch (...) { - throw std::runtime_error( - "Couldn't convert geometry config to box proto; box specifics not found"); + throw Exception("Couldn't convert geometry config to box proto; box specifics not found"); } } @@ -48,7 +48,7 @@ viam::common::v1::Capsule GeometryConfig::capsule_proto() const { capsule.set_length_mm(capsule_specifics.length); return capsule; } catch (...) { - throw std::runtime_error( + throw Exception( "Couldn't convert geometry config to capsule proto; capsule specifics not found"); } } @@ -122,7 +122,7 @@ GeometryConfig GeometryConfig::from_proto(const viam::common::v1::Geometry& prot } case viam::common::v1::Geometry::GeometryTypeCase::GEOMETRY_TYPE_NOT_SET: default: { - throw "Geometry type is not supported"; + throw Exception(ErrorCondition::k_not_supported, "Geometry type is not supported"); } } } diff --git a/src/viam/sdk/spatialmath/orientation.cpp b/src/viam/sdk/spatialmath/orientation.cpp index ca5229d18..7351c6029 100644 --- a/src/viam/sdk/spatialmath/orientation.cpp +++ b/src/viam/sdk/spatialmath/orientation.cpp @@ -8,6 +8,7 @@ #include +#include #include namespace viam { @@ -91,7 +92,7 @@ OrientationConfig OrientationConfig::from_proto(proto::Orientation proto) { } case proto::Orientation::TypeCase::TYPE_NOT_SET: default: { - throw std::runtime_error("orientation type not known"); + throw Exception(ErrorCondition::k_not_supported, "orientation type not known"); } } return cfg; @@ -151,7 +152,7 @@ proto::Orientation OrientationConfig::to_proto() const { return orientation; }; default: { - throw std::runtime_error("orientation type not known"); + throw Exception(ErrorCondition::k_not_supported, "orientation type not known"); } } } diff --git a/src/viam/sdk/tests/mocks/mock_motor.cpp b/src/viam/sdk/tests/mocks/mock_motor.cpp index 834570795..670639635 100644 --- a/src/viam/sdk/tests/mocks/mock_motor.cpp +++ b/src/viam/sdk/tests/mocks/mock_motor.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -26,7 +27,7 @@ void MockMotor::set_power(double power_pct, const AttributeMap& extra) { void MockMotor::go_for(double rpm, double revolutions, const AttributeMap& extra) { // This is the actual behavior from rdk:builtin:fake_motor if (rpm == 0.0) { - throw std::runtime_error("Cannot move motor at 0 RPM"); + throw Exception("Cannot move motor at 0 RPM"); } position_ += revolutions; } diff --git a/src/viam/sdk/tests/test_motor.cpp b/src/viam/sdk/tests/test_motor.cpp index 83e230faa..f5257bbe8 100644 --- a/src/viam/sdk/tests/test_motor.cpp +++ b/src/viam/sdk/tests/test_motor.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -104,7 +105,7 @@ BOOST_AUTO_TEST_CASE(mock_do_command) { BOOST_AUTO_TEST_CASE(mock_exception_creation) { std::shared_ptr motor = MockMotor::get_mock_motor(); - BOOST_CHECK_THROW(motor->go_for(0.0, 1.0), std::runtime_error); + BOOST_CHECK_THROW(motor->go_for(0.0, 1.0), Exception); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/viam/sdk/tests/test_resource.cpp b/src/viam/sdk/tests/test_resource.cpp index 65e895e9a..c3af1fe78 100644 --- a/src/viam/sdk/tests/test_resource.cpp +++ b/src/viam/sdk/tests/test_resource.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -37,9 +38,9 @@ BOOST_AUTO_TEST_CASE(test_api) { BOOST_CHECK(api2.is_service_type()); BOOST_CHECK(!api2.is_component_type()); - BOOST_CHECK_THROW(API::from_string("nsservicest"), std::string); - BOOST_CHECK_THROW(API::from_string("ns:service:#st"), std::string); - BOOST_CHECK_THROW(API::from_string("ns:service"), std::string); + BOOST_CHECK_THROW(API::from_string("nsservicest"), Exception); + BOOST_CHECK_THROW(API::from_string("ns:service:#st"), Exception); + BOOST_CHECK_THROW(API::from_string("ns:service"), Exception); } BOOST_AUTO_TEST_CASE(test_name) { @@ -67,7 +68,7 @@ BOOST_AUTO_TEST_CASE(test_name) { BOOST_CHECK_EQUAL(name3.to_string(), "ns:component:st/name"); BOOST_CHECK_EQUAL(Name::from_proto(name3.to_proto()), name3); - BOOST_CHECK_THROW(Name::from_string("ns:service:#st/remote:name"), std::string); + BOOST_CHECK_THROW(Name::from_string("ns:service:#st/remote:name"), Exception); } BOOST_AUTO_TEST_CASE(test_model) { @@ -88,7 +89,7 @@ BOOST_AUTO_TEST_CASE(test_model) { Model model5(empty, "model5"); BOOST_CHECK_EQUAL(model5.to_string(), "model5"); - BOOST_CHECK_THROW(Model::from_str("@"), std::runtime_error); + BOOST_CHECK_THROW(Model::from_str("@"), Exception); } BOOST_AUTO_TEST_CASE(test_linkconfig) { @@ -246,7 +247,7 @@ BOOST_AUTO_TEST_CASE(test_resource) { BOOST_CHECK_EQUAL(value.number_value(), 1); *proto_cfg.mutable_api() = "ns:component:test"; - BOOST_CHECK_THROW(ResourceConfig::from_proto(proto_cfg), std::runtime_error); + BOOST_CHECK_THROW(ResourceConfig::from_proto(proto_cfg), Exception); } } // namespace sdktests