Meaningful error codes instead of plain -1

This commit is contained in:
Pavel Kirienko
2014-03-28 19:21:08 +04:00
parent 4886e2194f
commit ae63ad5db5
34 changed files with 112 additions and 73 deletions
+29
View File
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
*/
#pragma once
namespace uavcan
{
/**
* Common error codes.
* Functions that return signed integers may also return inverted error codes,
* i.e. returned value should be inverted back to get the actual error code.
*/
enum
{
ErrOk,
ErrFailure,
ErrInvalidParam,
ErrMemory,
ErrDriver,
ErrUnknownDataType,
ErrInvalidMarshalData,
ErrInvalidTransferListener,
ErrNotInited,
ErrRecursiveCall,
ErrLogic
};
}
+4 -3
View File
@@ -10,6 +10,7 @@
#include <algorithm>
#include <stdexcept>
#include <cstring>
#include <uavcan/error.hpp>
#include <uavcan/fatal_error.hpp>
#include <uavcan/util/compile_time.hpp>
#include <uavcan/impl_constants.hpp>
@@ -308,7 +309,7 @@ class Array : public ArrayImpl<T, ArrayMode, MaxSize_>
}
if (size() == MaxSize_) // Error: Max array length reached, but the end of stream is not
{
return -1;
return -ErrInvalidMarshalData;
}
push_back(value);
}
@@ -323,7 +324,7 @@ class Array : public ArrayImpl<T, ArrayMode, MaxSize_>
}
if ((sz > 0) && ((sz - 1u) > (MaxSize_ - 1u))) // -Werror=type-limits
{
return -1;
return -ErrInvalidMarshalData;
}
resize(sz);
if (sz == 0)
@@ -333,7 +334,7 @@ class Array : public ArrayImpl<T, ArrayMode, MaxSize_>
return decodeImpl(codec, tao_mode, FalseType());
}
assert(0); // Unreachable
return -1;
return -ErrLogic;
}
public:
@@ -5,13 +5,13 @@
#pragma once
#include <limits>
#include <cmath>
#include <uavcan/stdint.hpp>
#include <uavcan/data_type.hpp>
#include <uavcan/util/compile_time.hpp>
#include <uavcan/impl_constants.hpp>
#include <uavcan/marshal/type_util.hpp>
#include <uavcan/marshal/integer_spec.hpp>
#include <cmath>
#ifndef UAVCAN_CPP_VERSION
# error UAVCAN_CPP_VERSION
@@ -4,6 +4,7 @@
#pragma once
#include <uavcan/error.hpp>
#include <uavcan/node/abstract_node.hpp>
#include <uavcan/data_type.hpp>
#include <uavcan/node/global_data_type_registry.hpp>
@@ -35,11 +36,11 @@ class GenericPublisher
INode& node_;
LazyConstructor<TransferSender> sender_;
bool checkInit()
int checkInit()
{
if (sender_)
{
return true;
return 0;
}
GlobalDataTypeRegistry::instance().freeze();
@@ -50,11 +51,11 @@ class GenericPublisher
if (!descr)
{
UAVCAN_TRACE("GenericPublisher", "Type [%s] is not registered", DataSpec::getDataTypeFullName());
return false;
return -ErrUnknownDataType;
}
sender_.template construct<Dispatcher&, const DataTypeDescriptor&, CanTxQueue::Qos, MonotonicDuration>
(node_.getDispatcher(), *descr, CanTxQueue::Qos(Qos), max_transfer_interval_);
return true;
return 0;
}
MonotonicTime getTxDeadline() const { return node_.getMonotonicTime() + tx_timeout_; }
@@ -67,15 +68,16 @@ class GenericPublisher
int genericPublish(const DataStruct& message, TransferType transfer_type, NodeID dst_node_id,
TransferID* tid, MonotonicTime blocking_deadline)
{
if (!checkInit())
const int res = checkInit();
if (res < 0)
{
return -1;
return res;
}
IMarshalBuffer* const buf = getBuffer();
if (!buf)
{
return -1;
return -ErrMemory;
}
{
@@ -85,7 +87,7 @@ class GenericPublisher
if (encode_res <= 0)
{
assert(0); // Impossible, internal error
return -1;
return -ErrInvalidMarshalData;
}
}
if (tid)
@@ -117,7 +119,7 @@ public:
int init()
{
return checkInit() ? 0 : -1;
return checkInit();
}
int publish(const DataStruct& message, TransferType transfer_type, NodeID dst_node_id,
@@ -134,7 +136,7 @@ public:
TransferSender* getTransferSender()
{
checkInit();
(void)checkInit();
return sender_.isConstructed() ? static_cast<TransferSender*>(sender_) : NULL;
}
@@ -4,6 +4,7 @@
#pragma once
#include <uavcan/error.hpp>
#include <uavcan/node/abstract_node.hpp>
#include <uavcan/data_type.hpp>
#include <uavcan/node/global_data_type_registry.hpp>
@@ -113,11 +114,11 @@ class GenericSubscriber : Noncopyable
ReceivedDataStructureSpec message_;
uint32_t failure_count_;
bool checkInit()
int checkInit()
{
if (forwarder_)
{
return true;
return 0;
}
GlobalDataTypeRegistry::instance().freeze();
@@ -128,11 +129,11 @@ class GenericSubscriber : Noncopyable
if (!descr)
{
UAVCAN_TRACE("GenericSubscriber", "Type [%s] is not registered", DataSpec::getDataTypeFullName());
return false;
return -ErrUnknownDataType;
}
forwarder_.template construct<SelfType&, const DataTypeDescriptor&, IAllocator&>
(*this, *descr, node_.getAllocator());
return true;
return 0;
}
bool decodeTransfer(IncomingTransfer& transfer)
@@ -167,19 +168,20 @@ class GenericSubscriber : Noncopyable
{
stop();
if (!checkInit())
const int res = checkInit();
if (res < 0)
{
UAVCAN_TRACE("GenericSubscriber", "Initialization failure [%s]", DataSpec::getDataTypeFullName());
return -1;
return res;
}
if (!(node_.getDispatcher().*registration_method)(forwarder_))
{
UAVCAN_TRACE("GenericSubscriber", "Failed to register transfer listener [%s]",
DataSpec::getDataTypeFullName());
return -1;
return -ErrInvalidTransferListener;
}
return 1;
return 0;
}
protected:
+3 -2
View File
@@ -5,6 +5,7 @@
#pragma once
#include <cassert>
#include <uavcan/error.hpp>
#include <uavcan/impl_constants.hpp>
#include <uavcan/dynamic_memory.hpp>
#include <uavcan/node/abstract_node.hpp>
@@ -94,7 +95,7 @@ public:
{
return INode::spin(deadline);
}
return -1;
return -ErrNotInited;
}
int spin(MonotonicDuration duration)
@@ -103,7 +104,7 @@ public:
{
return INode::spin(duration);
}
return -1;
return -ErrNotInited;
}
bool isStarted() const { return started_; }
+1 -1
View File
@@ -37,7 +37,7 @@ public:
if (!dst_node_id.isUnicast())
{
assert(0);
return -1;
return -ErrInvalidParam;
}
return publish(message, TransferTypeMessageUnicast, dst_node_id);
}
@@ -4,6 +4,7 @@
#pragma once
#include <uavcan/error.hpp>
#include <uavcan/linked_list.hpp>
#include <uavcan/transport/dispatcher.hpp>
@@ -182,7 +182,7 @@ public:
if (!isCallbackValid())
{
UAVCAN_TRACE("ServiceClient", "Invalid callback");
return -1;
return -ErrInvalidParam;
}
pending_ = true;
@@ -196,7 +196,7 @@ public:
{
UAVCAN_TRACE("ServiceClient", "Type [%s] is not registered", DataType::getDataTypeFullName());
cancel();
return -1;
return -ErrUnknownDataType;
}
/*
@@ -211,7 +211,7 @@ public:
{
UAVCAN_TRACE("ServiceClient", "OTR access failure, dtd=%s", descr->toString().c_str());
cancel();
return -1;
return -ErrMemory;
}
const TransferID transfer_id = *otr_tid;
otr_tid->increment();
@@ -235,7 +235,7 @@ public:
{
assert(0); // Must have been created
cancel();
return -1;
return -ErrLogic;
}
const typename TransferListenerType::ExpectedResponseParams erp(server_node_id, transfer_id);
tl->setExpectedResponseParams(erp);
@@ -91,7 +91,7 @@ public:
if (!try_implicit_cast<bool>(callback, true))
{
UAVCAN_TRACE("ServiceServer", "Invalid callback");
return -1;
return -ErrInvalidParam;
}
callback_ = callback;
+1 -1
View File
@@ -67,7 +67,7 @@ public:
if (!try_implicit_cast<bool>(callback, true))
{
UAVCAN_TRACE("Subscriber", "Invalid callback");
return -1;
return -ErrInvalidParam;
}
callback_ = callback;
@@ -101,7 +101,7 @@ public:
if (!try_implicit_cast<bool>(callback, true))
{
UAVCAN_TRACE("PanicListener", "Invalid callback");
return -1;
return -ErrInvalidParam;
}
callback_ = callback;
return sub_.start(PanicMsgCallback(this, &PanicListener::handleMsg));
@@ -6,6 +6,7 @@
#pragma once
#include <cassert>
#include <uavcan/error.hpp>
#include <uavcan/stdint.hpp>
#include <uavcan/linked_list.hpp>
#include <uavcan/dynamic_memory.hpp>
@@ -5,6 +5,7 @@
#pragma once
#include <cassert>
#include <uavcan/error.hpp>
#include <uavcan/stdint.hpp>
#include <uavcan/transport/perf_counter.hpp>
#include <uavcan/transport/transfer_listener.hpp>
@@ -7,6 +7,7 @@
#include <algorithm>
#include <limits>
#include <uavcan/stdint.hpp>
#include <uavcan/error.hpp>
#include <uavcan/transport/frame.hpp>
#include <uavcan/linked_list.hpp>
#include <uavcan/dynamic_memory.hpp>
@@ -166,7 +167,7 @@ public:
if (!data)
{
assert(0);
return -1;
return -ErrInvalidParam;
}
if (offset >= max_write_pos_)
{
@@ -186,7 +187,7 @@ public:
if (!data)
{
assert(0);
return -1;
return -ErrInvalidParam;
}
if (offset >= Size)
{
@@ -6,6 +6,7 @@
#include <cassert>
#include <algorithm>
#include <uavcan/error.hpp>
#include <uavcan/stdint.hpp>
#include <uavcan/transport/transfer_receiver.hpp>
#include <uavcan/transport/perf_counter.hpp>
@@ -6,6 +6,7 @@
#include <cstdlib>
#include <cassert>
#include <uavcan/error.hpp>
#include <uavcan/data_type.hpp>
#include <uavcan/transport/crc.hpp>
#include <uavcan/transport/transfer.hpp>
+1 -1
View File
@@ -157,7 +157,7 @@ int Scheduler::spin(MonotonicTime deadline)
if (inside_spin_) // Preventing recursive calls
{
assert(0);
return -1;
return -ErrRecursiveCall;
}
inside_spin_ = true;
@@ -84,7 +84,7 @@ void DataTypeInfoProvider::handleGetDataTypeInfoRequest(const protocol::GetDataT
int DataTypeInfoProvider::start()
{
int res = -1;
int res = 0;
res = cats_srv_.start(
ComputeAggregateTypeSignatureCallback(this, &DataTypeInfoProvider::handleComputeAggregateTypeSignatureRequest));
@@ -108,12 +108,12 @@ int GlobalTimeSyncMaster::init()
GlobalDataTypeRegistry::instance().find(DataTypeKindMessage, protocol::GlobalTimeSync::getDataTypeFullName());
if (desc == NULL)
{
return -1;
return -ErrUnknownDataType;
}
dtid_ = desc->getID();
// Iface master array
int res = -1;
int res = -ErrLogic;
for (uint8_t i = 0; i < MaxCanIfaces; i++)
{
if (!iface_masters_[i].isConstructed())
+1 -1
View File
@@ -105,7 +105,7 @@ int NodeInitializer::checkOneNodeOneDataTypeKind(NodeID nid, DataTypeKind kind)
}
if (!last_cats_request_ok_)
{
return -1;
return -ErrFailure;
}
return 0;
}
@@ -59,15 +59,13 @@ void NodeStatusProvider::handleGetNodeInfoRequest(const protocol::GetNodeInfo::R
int NodeStatusProvider::startAndPublish()
{
int res = -1;
if (!isNodeInfoInitialized())
{
UAVCAN_TRACE("NodeStatusProvider", "Node info was not initialized");
return -1;
return -ErrNotInited;
}
res = publish(); // Initial broadcast
int res = publish(); // Initial broadcast
if (res < 0)
{
goto fail;
+1 -1
View File
@@ -73,7 +73,7 @@ int ParamServer::start(IParamManager* manager)
{
if (manager == NULL)
{
return -1;
return -ErrInvalidParam;
}
manager_ = manager;
+4 -4
View File
@@ -219,7 +219,7 @@ int CanIOManager::sendToIface(int iface_index, const CanFrame& frame, MonotonicT
if (iface == NULL)
{
assert(0); // Nonexistent interface
return -1;
return -ErrLogic;
}
const int res = iface->send(frame, tx_deadline, flags);
if (res != 1)
@@ -311,7 +311,7 @@ int CanIOManager::send(const CanFrame& frame, MonotonicTime tx_deadline, Monoton
const int select_res = driver_.select(masks, blocking_deadline);
if (select_res < 0)
{
return select_res;
return -ErrDriver;
}
assert(masks.read == 0);
}
@@ -383,7 +383,7 @@ int CanIOManager::receive(CanRxFrame& out_frame, MonotonicTime blocking_deadline
const int select_res = driver_.select(masks, blocking_deadline);
if (select_res < 0)
{
return select_res;
return -ErrDriver;
}
}
@@ -418,7 +418,7 @@ int CanIOManager::receive(CanRxFrame& out_frame, MonotonicTime blocking_deadline
{
counters_[i].frames_rx += 1;
}
return res;
return (res < 0) ? -ErrDriver : res;
}
}
+2 -2
View File
@@ -226,7 +226,7 @@ int Dispatcher::send(const Frame& frame, MonotonicTime tx_deadline, MonotonicTim
if (frame.getSrcNodeID() != getNodeID())
{
assert(0);
return -1;
return -ErrLogic;
}
CanFrame can_frame;
@@ -234,7 +234,7 @@ int Dispatcher::send(const Frame& frame, MonotonicTime tx_deadline, MonotonicTim
{
UAVCAN_TRACE("Dispatcher", "Unable to send: frame is malformed: %s", frame.toString().c_str());
assert(0);
return -1;
return -ErrLogic;
}
return canio_.send(can_frame, tx_deadline, blocking_deadline, iface_mask, qos, flags);
}
+1 -1
View File
@@ -29,7 +29,7 @@ int Frame::getMaxPayloadLen() const
}
default:
assert(0);
return -1;
return -ErrLogic;
}
}
+2 -3
View File
@@ -113,7 +113,7 @@ int DynamicTransferBufferManagerEntry::read(unsigned int offset, uint8_t* data,
if (!data)
{
assert(0);
return -1;
return -ErrInvalidParam;
}
if (offset >= max_write_pos_)
{
@@ -148,7 +148,7 @@ int DynamicTransferBufferManagerEntry::write(unsigned int offset, const uint8_t*
if (!data)
{
assert(0);
return -1;
return -ErrInvalidParam;
}
if (offset >= max_size_)
@@ -190,7 +190,6 @@ int DynamicTransferBufferManagerEntry::write(unsigned int offset, const uint8_t*
if (new_block == NULL)
{
break; // We're in deep shit.
}
// Appending the chain with the new block
if (last_written_block != NULL)
@@ -15,7 +15,7 @@ namespace uavcan
int IncomingTransfer::write(unsigned int, const uint8_t*, unsigned int)
{
assert(0); // Incoming transfer container is read-only
return -1;
return -ErrLogic;
}
/*
@@ -35,7 +35,7 @@ int SingleFrameIncomingTransfer::read(unsigned int offset, uint8_t* data, unsign
if (data == NULL)
{
assert(0);
return -1;
return -ErrInvalidParam;
}
if (offset >= payload_len_)
{
@@ -69,7 +69,7 @@ int MultiFrameIncomingTransfer::read(unsigned int offset, uint8_t* data, unsigne
if (tbb == NULL)
{
UAVCAN_TRACE("MultiFrameIncomingTransfer", "Read failed: no such buffer");
return -1;
return -ErrLogic;
}
return tbb->read(offset, data, len);
}
+3 -3
View File
@@ -31,7 +31,7 @@ int TransferSender::send(const uint8_t* payload, int payload_len, MonotonicTime
assert(0);
UAVCAN_TRACE("TransferSender", "Frame payload write failure, %i", res);
registerError();
return (res < 0) ? res : -1;
return (res < 0) ? res : -ErrLogic;
}
frame.makeLast();
assert(frame.isLast() && frame.isFirst());
@@ -97,7 +97,7 @@ int TransferSender::send(const uint8_t* payload, int payload_len, MonotonicTime
}
assert(0);
return -1; // Return path analysis is apparently broken. There should be no warning, this 'return' is unreachable.
return -ErrLogic; // Return path analysis is apparently broken. There should be no warning, this 'return' is unreachable.
}
int TransferSender::send(const uint8_t* payload, int payload_len, MonotonicTime tx_deadline,
@@ -113,7 +113,7 @@ int TransferSender::send(const uint8_t* payload, int payload_len, MonotonicTime
{
UAVCAN_TRACE("TransferSender", "OTR access failure, dtd=%s tt=%i",
data_type_.toString().c_str(), int(transfer_type));
return -1;
return -ErrMemory;
}
const TransferID this_tid = tid->get();
+2 -2
View File
@@ -552,7 +552,7 @@ TEST(Array, TailArrayOptimizationErrors)
a2.push_back(56); // Garbage
ASSERT_EQ(1, a2.size());
// Will fail - declared length is more than 5 items
ASSERT_EQ(-1, A::decode(a2, sc_rd, uavcan::TailArrayOptDisabled));
ASSERT_GT(0, A::decode(a2, sc_rd, uavcan::TailArrayOptDisabled));
// Must be cleared
ASSERT_TRUE(a2.empty());
}
@@ -563,7 +563,7 @@ TEST(Array, TailArrayOptimizationErrors)
a2.push_back(56); // Garbage
ASSERT_EQ(1, a2.size());
// Will fail - no length field, but the stream is too long
ASSERT_EQ(-1, A::decode(a2, sc_rd, uavcan::TailArrayOptEnabled));
ASSERT_GT(0, A::decode(a2, sc_rd, uavcan::TailArrayOptEnabled));
// Will contain some garbage
ASSERT_EQ(5, a2.size());
// Interpreted stream - see the values above
+1 -1
View File
@@ -67,7 +67,7 @@ TEST(Node, Basic)
* Init the first node
*/
ASSERT_FALSE(node1.isStarted());
ASSERT_EQ(-1, node1.spin(uavcan::MonotonicDuration::fromMSec(20))); // Not initialized - will fail
ASSERT_EQ(-uavcan::ErrNotInited, node1.spin(uavcan::MonotonicDuration::fromMSec(20)));
ASSERT_LE(0, node1.start(result));
ASSERT_TRUE(node1.isStarted());
+1 -1
View File
@@ -63,7 +63,7 @@ TEST(ServiceClient, Basic)
// Server
uavcan::ServiceServer<root_ns_a::StringService> server(nodes.a);
ASSERT_EQ(1, server.start(stringServiceServerCallback));
ASSERT_EQ(0, server.start(stringServiceServerCallback));
{
// Caller
+5 -5
View File
@@ -82,7 +82,7 @@ TEST(Subscriber, Basic)
sizeof(uavcan::Subscriber<uavcan::mavlink::Message, Listener::ExtendedBinder>) << std::endl;
// Null binder - will fail
ASSERT_EQ(-1, sub_extended.start(Listener::ExtendedBinder(NULL, NULL)));
ASSERT_EQ(-uavcan::ErrInvalidParam, sub_extended.start(Listener::ExtendedBinder(NULL, NULL)));
Listener listener;
@@ -125,10 +125,10 @@ TEST(Subscriber, Basic)
*/
ASSERT_EQ(0, node.getDispatcher().getNumMessageListeners());
ASSERT_EQ(1, sub_extended.start(listener.bindExtended()));
ASSERT_EQ(1, sub_extended2.start(listener.bindExtended()));
ASSERT_EQ(1, sub_simple.start(listener.bindSimple()));
ASSERT_EQ(1, sub_simple2.start(listener.bindSimple()));
ASSERT_EQ(0, sub_extended.start(listener.bindExtended()));
ASSERT_EQ(0, sub_extended2.start(listener.bindExtended()));
ASSERT_EQ(0, sub_simple.start(listener.bindSimple()));
ASSERT_EQ(0, sub_simple2.start(listener.bindSimple()));
ASSERT_EQ(4, node.getDispatcher().getNumMessageListeners());
+5 -4
View File
@@ -94,12 +94,12 @@ TEST(CanIOManager, Reception)
* Perf counters
*/
driver.select_failure = true;
EXPECT_EQ(-1, iomgr.receive(frame, uavcan::MonotonicTime(), flags));
EXPECT_EQ(-uavcan::ErrDriver, iomgr.receive(frame, uavcan::MonotonicTime(), flags));
driver.select_failure = false;
driver.ifaces.at(1).pushRx(frames[0][0]);
driver.ifaces.at(1).rx_failure = true;
EXPECT_EQ(-1, iomgr.receive(frame, uavcan::MonotonicTime(), flags));
EXPECT_EQ(-uavcan::ErrDriver, iomgr.receive(frame, uavcan::MonotonicTime(), flags));
driver.ifaces.at(0).num_errors = 9000;
driver.ifaces.at(1).num_errors = 100500;
@@ -268,8 +268,9 @@ TEST(CanIOManager, Transmission)
*/
// Select failure
driver.select_failure = true;
EXPECT_EQ(-1, iomgr.receive(rx_frame, tsMono(2000), flags));
EXPECT_EQ(-1, iomgr.send(frames[0], tsMono(2100), tsMono(2000), ALL_IFACES_MASK, CanTxQueue::Volatile, flags));
EXPECT_EQ(-uavcan::ErrDriver, iomgr.receive(rx_frame, tsMono(2000), flags));
EXPECT_EQ(-uavcan::ErrDriver,
iomgr.send(frames[0], tsMono(2100), tsMono(2000), ALL_IFACES_MASK, CanTxQueue::Volatile, flags));
EXPECT_EQ(1200, clockmock.monotonic);
EXPECT_EQ(1200, clockmock.utc);
ASSERT_EQ(0, flags);