libuav original
Dependents: UAVCAN UAVCAN_Subscriber
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 }
Generated on Tue Jul 12 2022 17:17:34 by 1.7.2