libuav original

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers service_server.cpp Source File

service_server.cpp

00001 /*
00002  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
00003  */
00004 
00005 #include <gtest/gtest.h>
00006 #include <uavcan/node/service_server.hpp>
00007 #include <uavcan/util/method_binder.hpp>
00008 #include <root_ns_a/StringService.hpp>
00009 #include <root_ns_a/EmptyService.hpp>
00010 #include "../clock.hpp"
00011 #include "../transport/can/can.hpp"
00012 #include "test_node.hpp"
00013 
00014 
00015 struct StringServerImpl
00016 {
00017     const char* string_response;
00018 
00019     StringServerImpl(const char* string_response) : string_response(string_response) { }
00020 
00021     void handleRequest(const uavcan::ReceivedDataStructure<root_ns_a::StringService::Request>& request,
00022                        root_ns_a::StringService::Response& response)
00023     {
00024         std::cout << request << std::endl;
00025         response.string_response = request.string_request;
00026         response.string_response += " --> ";
00027         response.string_response += string_response;
00028         std::cout << response << std::endl;
00029     }
00030 
00031     typedef uavcan::MethodBinder<StringServerImpl*,
00032         void (StringServerImpl::*)(const uavcan::ReceivedDataStructure<root_ns_a::StringService::Request>&,
00033                                    root_ns_a::StringService::Response&)> Binder;
00034 
00035     Binder bind() { return Binder(this, &StringServerImpl::handleRequest); }
00036 };
00037 
00038 
00039 struct EmptyServerImpl
00040 {
00041     void handleRequest(const uavcan::ReceivedDataStructure<root_ns_a::EmptyService::Request>& request,
00042                        root_ns_a::EmptyService::Response&)
00043     {
00044         std::cout << request << std::endl;
00045     }
00046 
00047     typedef uavcan::MethodBinder<EmptyServerImpl*,
00048         void (EmptyServerImpl::*)(const uavcan::ReceivedDataStructure<root_ns_a::EmptyService::Request>&,
00049                                    root_ns_a::EmptyService::Response&)> Binder;
00050 
00051     Binder bind() { return Binder(this, &EmptyServerImpl::handleRequest); }
00052 };
00053 
00054 
00055 TEST(ServiceServer, Basic)
00056 {
00057     // Manual type registration - we can't rely on the GDTR state
00058     uavcan::GlobalDataTypeRegistry::instance().reset();
00059     uavcan::DefaultDataTypeRegistrator<root_ns_a::StringService> _registrator;
00060 
00061     SystemClockDriver clock_driver;
00062     CanDriverMock can_driver(1, clock_driver);
00063     TestNode node(can_driver, clock_driver, 1);
00064 
00065     StringServerImpl impl("456");
00066 
00067     {
00068         uavcan::ServiceServer<root_ns_a::StringService, StringServerImpl::Binder> server(node);
00069 
00070         ASSERT_EQ(0, node.getDispatcher().getNumServiceRequestListeners());
00071         server.start(impl.bind());
00072         ASSERT_EQ(1, node.getDispatcher().getNumServiceRequestListeners());
00073 
00074         /*
00075          * Request frames
00076          */
00077         for (uint8_t i = 0; i < 2; i++)
00078         {
00079             uavcan::Frame frame(root_ns_a::StringService::DefaultDataTypeID, uavcan::TransferTypeServiceRequest,
00080                                 uavcan::NodeID(uint8_t(i + 0x10)), 1, i);
00081 
00082             const uint8_t req[] = {'r', 'e', 'q', uint8_t(i + '0')};
00083             frame.setPayload(req, sizeof(req));
00084 
00085             frame.setStartOfTransfer(true);
00086             frame.setEndOfTransfer(true);
00087             frame.setPriority(i);
00088 
00089             uavcan::RxFrame rx_frame(frame, clock_driver.getMonotonic(), clock_driver.getUtc(), 0);
00090             can_driver.ifaces[0].pushRx(rx_frame);
00091         }
00092 
00093         node.spin(clock_driver.getMonotonic() + uavcan::MonotonicDuration::fromUSec(10000));
00094 
00095         /*
00096          * Responses (MFT)
00097          */
00098         ASSERT_EQ(4, can_driver.ifaces[0].tx.size());
00099         for (int i = 0; i < 2; i++)
00100         {
00101             char payloads[2][8];
00102             std::snprintf(payloads[0], 8, "req%i ", i);
00103             std::snprintf(payloads[1], 8, "--> 456");
00104 
00105             // First frame
00106             uavcan::Frame fr;
00107             ASSERT_TRUE(fr.parse(can_driver.ifaces[0].popTxFrame()));
00108             std::cout << fr.toString() << std::endl;
00109             ASSERT_FALSE(std::strncmp(payloads[0], reinterpret_cast<const char*>(fr.getPayloadPtr() + 2), 5)); // No CRC
00110 
00111             ASSERT_EQ(i, fr.getTransferID().get());
00112             ASSERT_EQ(uavcan::TransferTypeServiceResponse, fr.getTransferType());
00113             ASSERT_EQ(i + 0x10, fr.getDstNodeID().get());
00114             ASSERT_EQ(i, fr.getPriority().get());
00115 
00116             // Second frame
00117             ASSERT_TRUE(fr.parse(can_driver.ifaces[0].popTxFrame()));
00118             std::cout << fr.toString() << std::endl;
00119             // cppcheck-suppress arrayIndexOutOfBounds
00120             ASSERT_FALSE(std::strncmp(payloads[1], reinterpret_cast<const char*>(fr.getPayloadPtr()), 7));
00121 
00122             ASSERT_EQ(i, fr.getTransferID().get());
00123             ASSERT_EQ(uavcan::TransferTypeServiceResponse, fr.getTransferType());
00124             ASSERT_EQ(i + 0x10, fr.getDstNodeID().get());
00125         }
00126 
00127         ASSERT_EQ(0, server.getRequestFailureCount());
00128         ASSERT_EQ(0, server.getResponseFailureCount());
00129 
00130         ASSERT_EQ(1, node.getDispatcher().getNumServiceRequestListeners());
00131     }
00132     ASSERT_EQ(0, node.getDispatcher().getNumServiceRequestListeners());
00133 }
00134 
00135 
00136 TEST(ServiceServer, Empty)
00137 {
00138     // Manual type registration - we can't rely on the GDTR state
00139     uavcan::GlobalDataTypeRegistry::instance().reset();
00140     uavcan::DefaultDataTypeRegistrator<root_ns_a::EmptyService> _registrator;
00141 
00142     SystemClockDriver clock_driver;
00143     CanDriverMock can_driver(1, clock_driver);
00144     TestNode node(can_driver, clock_driver, 1);
00145 
00146     EmptyServerImpl impl;
00147 
00148     uavcan::ServiceServer<root_ns_a::EmptyService, EmptyServerImpl::Binder> server(node);
00149 
00150     std::cout << "sizeof(ServiceServer<root_ns_a::EmptyService, EmptyServerImpl::Binder>): "
00151               << sizeof(uavcan::ServiceServer<root_ns_a::EmptyService, EmptyServerImpl::Binder>) << std::endl;
00152 
00153     ASSERT_EQ(0, node.getDispatcher().getNumServiceRequestListeners());
00154     ASSERT_GE(0, server.start(impl.bind()));
00155     ASSERT_EQ(1, node.getDispatcher().getNumServiceRequestListeners());
00156 }