Руслан Урядинский / libuavcan

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers server.cpp Source File

server.cpp

00001 /*
00002  * Copyright (C) 2015 Pavel Kirienko <pavel.kirienko@gmail.com>
00003  */
00004 
00005 #if __GNUC__
00006 // We need auto_ptr for compatibility reasons
00007 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
00008 # pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
00009 #endif
00010 
00011 #include <gtest/gtest.h>
00012 #include <memory>
00013 #include <uavcan/protocol/dynamic_node_id_server/distributed.hpp>
00014 #include <uavcan/protocol/dynamic_node_id_client.hpp>
00015 #include "../event_tracer.hpp"
00016 #include "../../helpers.hpp"
00017 #include "../memory_storage_backend.hpp"
00018 
00019 using uavcan::dynamic_node_id_server::UniqueID;
00020 
00021 
00022 class CommitHandler : public uavcan::dynamic_node_id_server::distributed::IRaftLeaderMonitor
00023 {
00024     const std::string id_;
00025 
00026     virtual void handleLogCommitOnLeader(const uavcan::protocol::dynamic_node_id::server::Entry& entry)
00027     {
00028         std::cout << "ENTRY COMMITTED [" << id_ << "]\n" << entry << std::endl;
00029     }
00030 
00031     virtual void handleLocalLeadershipChange(bool local_node_is_leader)
00032     {
00033         std::cout << "I AM LEADER [" << id_ << "]: " << (local_node_is_leader ? "YES" : "NOT ANYMORE") << std::endl;
00034     }
00035 
00036 public:
00037     CommitHandler(const std::string& id) : id_(id) { }
00038 };
00039 
00040 
00041 TEST(dynamic_node_id_server_RaftCore, Basic)
00042 {
00043     using namespace uavcan::dynamic_node_id_server::distributed;
00044     using namespace uavcan::protocol::dynamic_node_id::server;
00045 
00046     uavcan::GlobalDataTypeRegistry::instance().reset();
00047     uavcan::DefaultDataTypeRegistrator<Discovery> _reg1;
00048     uavcan::DefaultDataTypeRegistrator<AppendEntries> _reg2;
00049     uavcan::DefaultDataTypeRegistrator<RequestVote> _reg3;
00050 
00051     EventTracer tracer_a("a");
00052     EventTracer tracer_b("b");
00053     MemoryStorageBackend storage_a;
00054     MemoryStorageBackend storage_b;
00055     CommitHandler commit_handler_a("a");
00056     CommitHandler commit_handler_b("b");
00057 
00058     InterlinkedTestNodesWithSysClock nodes;
00059 
00060     std::auto_ptr<RaftCore> raft_a(new RaftCore(nodes.a, storage_a, tracer_a, commit_handler_a));
00061     std::auto_ptr<RaftCore> raft_b(new RaftCore(nodes.b, storage_b, tracer_b, commit_handler_b));
00062 
00063     /*
00064      * Initialization
00065      */
00066     ASSERT_LE(0, raft_a->init(2, uavcan::TransferPriority::OneHigherThanLowest));
00067     ASSERT_LE(0, raft_b->init(2, uavcan::TransferPriority::OneHigherThanLowest));
00068 
00069     /*
00070      * Running and trying not to fall
00071      */
00072     nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(9000));
00073 
00074     // Either must become a leader
00075     ASSERT_TRUE(raft_a->isLeader() || raft_b->isLeader());
00076 
00077     ASSERT_EQ(0, raft_a->getCommitIndex());
00078     ASSERT_EQ(0, raft_b->getCommitIndex());
00079 
00080     /*
00081      * Adding some stuff
00082      */
00083     Entry::FieldTypes::unique_id unique_id;
00084     uavcan::fill_n(unique_id.begin(), 16, uint8_t(0xAA));
00085 
00086     (raft_a->isLeader() ? raft_a : raft_b)->appendLog(unique_id, uavcan::NodeID(1));
00087 
00088     nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(6000));
00089 
00090     ASSERT_EQ(1, raft_a->getCommitIndex());
00091     ASSERT_EQ(1, raft_b->getCommitIndex());
00092 
00093     /*
00094      * Terminating the leader
00095      */
00096     raft_a.reset();
00097 
00098     nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(6000));
00099 
00100     /*
00101      * Reinitializing the leader - current Follower will become the new Leader
00102      */
00103     storage_a.reset();
00104 
00105     raft_a.reset(new RaftCore(nodes.a, storage_a, tracer_a, commit_handler_a));
00106     ASSERT_LE(0, raft_a->init(2, uavcan::TransferPriority::OneHigherThanLowest));
00107     ASSERT_EQ(0, raft_a->getCommitIndex());
00108 
00109     nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(9000));
00110 
00111     ASSERT_FALSE(raft_a->isLeader());
00112     ASSERT_TRUE(raft_b->isLeader());
00113 
00114     ASSERT_EQ(1, raft_a->getCommitIndex());
00115     ASSERT_EQ(1, raft_b->getCommitIndex());
00116 }
00117 
00118 
00119 TEST(dynamic_node_id_server_Server, Basic)
00120 {
00121     using namespace uavcan::dynamic_node_id_server;
00122     using namespace uavcan::protocol::dynamic_node_id;
00123     using namespace uavcan::protocol::dynamic_node_id::server;
00124 
00125     uavcan::GlobalDataTypeRegistry::instance().reset();
00126     uavcan::DefaultDataTypeRegistrator<Discovery> _reg1;
00127     uavcan::DefaultDataTypeRegistrator<AppendEntries> _reg2;
00128     uavcan::DefaultDataTypeRegistrator<RequestVote> _reg3;
00129     uavcan::DefaultDataTypeRegistrator<Allocation> _reg4;
00130     uavcan::DefaultDataTypeRegistrator<uavcan::protocol::GetNodeInfo> _reg5;
00131     uavcan::DefaultDataTypeRegistrator<uavcan::protocol::NodeStatus> _reg6;
00132 
00133     EventTracer tracer;
00134     MemoryStorageBackend storage;
00135 
00136     // Node A is Allocator, Node B is Allocatee
00137     InterlinkedTestNodesWithSysClock nodes(uavcan::NodeID(10), uavcan::NodeID::Broadcast);
00138 
00139     UniqueID own_unique_id;
00140     own_unique_id[0] = 0xAA;
00141     own_unique_id[3] = 0xCC;
00142     own_unique_id[7] = 0xEE;
00143     own_unique_id[9] = 0xBB;
00144 
00145     /*
00146      * Server
00147      */
00148     DistributedServer server(nodes.a, storage, tracer);
00149 
00150     ASSERT_LE(0, server.init(own_unique_id, 1));
00151 
00152     ASSERT_EQ(0, server.getNumAllocations());
00153 
00154     /*
00155      * Client
00156      */
00157     uavcan::DynamicNodeIDClient client(nodes.b);
00158     uavcan::protocol::HardwareVersion::FieldTypes::unique_id unique_id;
00159     for (uavcan::uint8_t i = 0; i < unique_id.size(); i++)
00160     {
00161         unique_id[i] = i;
00162     }
00163     const uavcan::NodeID PreferredNodeID = 42;
00164     ASSERT_LE(0, client.start(unique_id, PreferredNodeID));
00165 
00166     /*
00167      * Fire
00168      */
00169     nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(15000));
00170 
00171     ASSERT_TRUE(client.isAllocationComplete());
00172     ASSERT_EQ(PreferredNodeID, client.getAllocatedNodeID());
00173 
00174     ASSERT_EQ(2, server.getNumAllocations());   // Server's own node ID + client
00175 }
00176 
00177 
00178 TEST(dynamic_node_id_server, ObjectSizes)
00179 {
00180     using namespace uavcan;
00181     using namespace uavcan::protocol::dynamic_node_id::server;
00182     using namespace uavcan::dynamic_node_id_server;
00183 
00184     std::cout << "distributed::Log:             " << sizeof(distributed::Log) << std::endl;
00185     std::cout << "distributed::PersistentState: " << sizeof(distributed::PersistentState) << std::endl;
00186     std::cout << "distributed::ClusterManager:  " << sizeof(distributed::ClusterManager) << std::endl;
00187     std::cout << "distributed::RaftCore:        " << sizeof(distributed::RaftCore) << std::endl;
00188     std::cout << "distributed::Server:          " << sizeof(distributed::Server) << std::endl;
00189     std::cout << "AllocationRequestManager:     " << sizeof(AllocationRequestManager) << std::endl;
00190 
00191     std::cout << "ServiceServer<AppendEntries>:  " << sizeof(ServiceServer<AppendEntries>) << std::endl;
00192     std::cout << "ServiceClient<AppendEntries>:  " << sizeof(ServiceClient<AppendEntries>) << std::endl;
00193     std::cout << "ServiceServer<RequestVote>:    " << sizeof(ServiceServer<RequestVote>) << std::endl;
00194     std::cout << "ServiceClient<RequestVote>:    " << sizeof(ServiceClient<RequestVote>) << std::endl;
00195 }