Beispiel #1
0
TEST(Frame, FrameParsing)
{
    using uavcan::Frame;
    using uavcan::CanFrame;
    using uavcan::NodeID;
    using uavcan::TransferID;

    CanFrame can;
    Frame frame;
    ASSERT_FALSE(frame.parse(can));

    for (unsigned i = 0; i < sizeof(CanFrame::data); i++)
    {
        can.data[i] = uint8_t(i | (i << 4));
    }

    /*
     * Message CAN ID fields and offsets:
     *   24 Priority
     *   8  Message Type ID
     *   7  Service Not Message (0)
     *   0  Source Node ID
     *
     * Service CAN ID fields and offsets:
     *   24 Priority
     *   16 Service Type ID
     *   15 Request Not Response
     *   8  Destination Node ID
     *   7  Service Not Message (1)
     *   0  Source Node ID
     */

    /*
     * SFT message broadcast
     */
    can.id = CanFrame::FlagEFF |
             (2 << 24) |
             (456 << 8) |
             (0 << 7) |
             (42 << 0);

    can.data[7] = 0xcf; // SET=110, TID=0

    ASSERT_FALSE(frame.parse(can));
    can.dlc = 8;

    ASSERT_TRUE(frame.parse(can));
    EXPECT_TRUE(frame.isStartOfTransfer());
    EXPECT_TRUE(frame.isEndOfTransfer());
    EXPECT_FALSE(frame.getToggle());
    ASSERT_EQ(2, frame.getPriority().get());
    ASSERT_EQ(NodeID(42), frame.getSrcNodeID());
    ASSERT_EQ(NodeID::Broadcast, frame.getDstNodeID());
    ASSERT_EQ(456, frame.getDataTypeID().get());
    ASSERT_EQ(TransferID(15), frame.getTransferID());
    ASSERT_EQ(uavcan::TransferTypeMessageBroadcast, frame.getTransferType());

    // TODO: test service frames
    // TODO: test malformed frames
}
Beispiel #2
0
TEST(NodeStatusMonitor, Basic)
{
    using uavcan::protocol::NodeStatus;
    using uavcan::NodeID;

    SystemClockMock clock_mock(100);
    clock_mock.monotonic_auto_advance = 1000;

    CanDriverMock can(2, clock_mock);

    TestNode node(can, clock_mock, 64);

    uavcan::GlobalDataTypeRegistry::instance().reset();
    uavcan::DefaultDataTypeRegistrator<uavcan::protocol::NodeStatus> _reg1;

    uavcan::NodeStatusMonitor nsm(node);
    ASSERT_LE(0, nsm.start());

    ASSERT_LE(0, node.spin(uavcan::MonotonicDuration::fromMSec(10)));

    /*
     * Empty NSM, no nodes were registered yet
     */
    ASSERT_FALSE(nsm.findNodeWithWorstStatus().isValid());

    uavcan::NodeStatusMonitor::NodeStatus st = nsm.getNodeStatus(uavcan::NodeID(123));
    ASSERT_FALSE(st.known);
    ASSERT_EQ(NodeStatus::STATUS_OFFLINE, st.status_code);

    /*
     * Some new status messages
     */
    publishNodeStatus(can, 10, NodeStatus::STATUS_OK, 12, 0);
    shortSpin(node);
    ASSERT_EQ(NodeID(10), nsm.findNodeWithWorstStatus());

    publishNodeStatus(can, 9,  NodeStatus::STATUS_INITIALIZING, 0, 0);
    shortSpin(node);
    ASSERT_EQ(NodeID(9), nsm.findNodeWithWorstStatus());

    publishNodeStatus(can, 11, NodeStatus::STATUS_CRITICAL, 999, 0);
    shortSpin(node);
    ASSERT_EQ(NodeID(11), nsm.findNodeWithWorstStatus());

    st = nsm.getNodeStatus(uavcan::NodeID(10));
    ASSERT_TRUE(st.known);
    ASSERT_EQ(NodeStatus::STATUS_OK, st.status_code);

    st = nsm.getNodeStatus(uavcan::NodeID(9));
    ASSERT_TRUE(st.known);
    ASSERT_EQ(NodeStatus::STATUS_INITIALIZING, st.status_code);

    st = nsm.getNodeStatus(uavcan::NodeID(11));
    ASSERT_TRUE(st.known);
    ASSERT_EQ(NodeStatus::STATUS_CRITICAL, st.status_code);

    /*
     * Timeout
     */
    std::cout << "Starting timeout test, current monotime is " << clock_mock.monotonic << std::endl;

    clock_mock.advance(500000);
    shortSpin(node);
    st = nsm.getNodeStatus(uavcan::NodeID(10));
    ASSERT_TRUE(st.known);
    ASSERT_EQ(NodeStatus::STATUS_OK, st.status_code);

    clock_mock.advance(500000);
    shortSpin(node);
    st = nsm.getNodeStatus(uavcan::NodeID(9));
    ASSERT_TRUE(st.known);
    ASSERT_EQ(NodeStatus::STATUS_INITIALIZING, st.status_code);

    clock_mock.advance(500000);
    shortSpin(node);
    st = nsm.getNodeStatus(uavcan::NodeID(11));
    ASSERT_TRUE(st.known);
    ASSERT_EQ(NodeStatus::STATUS_CRITICAL, st.status_code);

    /*
     * Will timeout now
     */
    clock_mock.advance(4000000);
    shortSpin(node);

    st = nsm.getNodeStatus(uavcan::NodeID(10));
    ASSERT_TRUE(st.known);
    ASSERT_EQ(NodeStatus::STATUS_OFFLINE, st.status_code);

    st = nsm.getNodeStatus(uavcan::NodeID(9));
    ASSERT_TRUE(st.known);
    ASSERT_EQ(NodeStatus::STATUS_OFFLINE, st.status_code);

    st = nsm.getNodeStatus(uavcan::NodeID(11));
    ASSERT_TRUE(st.known);
    ASSERT_EQ(NodeStatus::STATUS_OFFLINE, st.status_code);

    /*
     * Recovering one node, adding two extra
     */
    publishNodeStatus(can, 11, NodeStatus::STATUS_WARNING, 999, 0);
    shortSpin(node);

    publishNodeStatus(can, 127, NodeStatus::STATUS_WARNING, 9999, 0);
    shortSpin(node);

    publishNodeStatus(can, 1, NodeStatus::STATUS_OK, 1234, 0);
    shortSpin(node);

    /*
     * Making sure OFFLINE is still worst status
     */
    ASSERT_EQ(NodeID(9), nsm.findNodeWithWorstStatus());

    /*
     * Final validation
     */
    st = nsm.getNodeStatus(uavcan::NodeID(10));
    ASSERT_TRUE(st.known);
    ASSERT_EQ(NodeStatus::STATUS_OFFLINE, st.status_code);

    st = nsm.getNodeStatus(uavcan::NodeID(9));
    ASSERT_TRUE(st.known);
    ASSERT_EQ(NodeStatus::STATUS_OFFLINE, st.status_code);

    st = nsm.getNodeStatus(uavcan::NodeID(11));
    ASSERT_TRUE(st.known);
    ASSERT_EQ(NodeStatus::STATUS_WARNING, st.status_code);

    st = nsm.getNodeStatus(uavcan::NodeID(127));
    ASSERT_TRUE(st.known);
    ASSERT_EQ(NodeStatus::STATUS_WARNING, st.status_code);

    st = nsm.getNodeStatus(uavcan::NodeID(1));
    ASSERT_TRUE(st.known);
    ASSERT_EQ(NodeStatus::STATUS_OK, st.status_code);

    /*
     * Forgetting
     */
    nsm.forgetNode(127);
    st = nsm.getNodeStatus(uavcan::NodeID(127));
    ASSERT_FALSE(st.known);
    ASSERT_EQ(NodeStatus::STATUS_OFFLINE, st.status_code);

    nsm.forgetNode(9);
    st = nsm.getNodeStatus(uavcan::NodeID(9));
    ASSERT_FALSE(st.known);
    ASSERT_EQ(NodeStatus::STATUS_OFFLINE, st.status_code);
}