service_server.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
  3. */
  4. #include <gtest/gtest.h>
  5. #include <uavcan/node/service_server.hpp>
  6. #include <uavcan/util/method_binder.hpp>
  7. #include <root_ns_a/StringService.hpp>
  8. #include <root_ns_a/EmptyService.hpp>
  9. #include "../clock.hpp"
  10. #include "../transport/can/can.hpp"
  11. #include "test_node.hpp"
  12. struct StringServerImpl
  13. {
  14. const char* string_response;
  15. StringServerImpl(const char* string_response) : string_response(string_response) { }
  16. void handleRequest(const uavcan::ReceivedDataStructure<root_ns_a::StringService::Request>& request,
  17. root_ns_a::StringService::Response& response)
  18. {
  19. std::cout << request << std::endl;
  20. response.string_response = request.string_request;
  21. response.string_response += " --> ";
  22. response.string_response += string_response;
  23. std::cout << response << std::endl;
  24. }
  25. typedef uavcan::MethodBinder<StringServerImpl*,
  26. void (StringServerImpl::*)(const uavcan::ReceivedDataStructure<root_ns_a::StringService::Request>&,
  27. root_ns_a::StringService::Response&)> Binder;
  28. Binder bind() { return Binder(this, &StringServerImpl::handleRequest); }
  29. };
  30. struct EmptyServerImpl
  31. {
  32. void handleRequest(const uavcan::ReceivedDataStructure<root_ns_a::EmptyService::Request>& request,
  33. root_ns_a::EmptyService::Response&)
  34. {
  35. std::cout << request << std::endl;
  36. }
  37. typedef uavcan::MethodBinder<EmptyServerImpl*,
  38. void (EmptyServerImpl::*)(const uavcan::ReceivedDataStructure<root_ns_a::EmptyService::Request>&,
  39. root_ns_a::EmptyService::Response&)> Binder;
  40. Binder bind() { return Binder(this, &EmptyServerImpl::handleRequest); }
  41. };
  42. TEST(ServiceServer, Basic)
  43. {
  44. // Manual type registration - we can't rely on the GDTR state
  45. uavcan::GlobalDataTypeRegistry::instance().reset();
  46. uavcan::DefaultDataTypeRegistrator<root_ns_a::StringService> _registrator;
  47. SystemClockDriver clock_driver;
  48. CanDriverMock can_driver(1, clock_driver);
  49. TestNode node(can_driver, clock_driver, 1);
  50. StringServerImpl impl("456");
  51. {
  52. uavcan::ServiceServer<root_ns_a::StringService, StringServerImpl::Binder> server(node);
  53. ASSERT_EQ(0, node.getDispatcher().getNumServiceRequestListeners());
  54. server.start(impl.bind());
  55. ASSERT_EQ(1, node.getDispatcher().getNumServiceRequestListeners());
  56. /*
  57. * Request frames
  58. */
  59. for (uint8_t i = 0; i < 2; i++)
  60. {
  61. uavcan::Frame frame(root_ns_a::StringService::DefaultDataTypeID, uavcan::TransferTypeServiceRequest,
  62. uavcan::NodeID(uint8_t(i + 0x10)), 1, i);
  63. const uint8_t req[] = {'r', 'e', 'q', uint8_t(i + '0')};
  64. frame.setPayload(req, sizeof(req));
  65. frame.setStartOfTransfer(true);
  66. frame.setEndOfTransfer(true);
  67. frame.setPriority(i);
  68. uavcan::RxFrame rx_frame(frame, clock_driver.getMonotonic(), clock_driver.getUtc(), 0);
  69. can_driver.ifaces[0].pushRx(rx_frame);
  70. }
  71. node.spin(clock_driver.getMonotonic() + uavcan::MonotonicDuration::fromUSec(10000));
  72. /*
  73. * Responses (MFT)
  74. */
  75. ASSERT_EQ(4, can_driver.ifaces[0].tx.size());
  76. for (int i = 0; i < 2; i++)
  77. {
  78. char payloads[2][8];
  79. std::snprintf(payloads[0], 8, "req%i ", i);
  80. std::snprintf(payloads[1], 8, "--> 456");
  81. // First frame
  82. uavcan::Frame fr;
  83. ASSERT_TRUE(fr.parse(can_driver.ifaces[0].popTxFrame()));
  84. std::cout << fr.toString() << std::endl;
  85. ASSERT_FALSE(std::strncmp(payloads[0], reinterpret_cast<const char*>(fr.getPayloadPtr() + 2), 5)); // No CRC
  86. ASSERT_EQ(i, fr.getTransferID().get());
  87. ASSERT_EQ(uavcan::TransferTypeServiceResponse, fr.getTransferType());
  88. ASSERT_EQ(i + 0x10, fr.getDstNodeID().get());
  89. ASSERT_EQ(i, fr.getPriority().get());
  90. // Second frame
  91. ASSERT_TRUE(fr.parse(can_driver.ifaces[0].popTxFrame()));
  92. std::cout << fr.toString() << std::endl;
  93. // cppcheck-suppress arrayIndexOutOfBounds
  94. ASSERT_FALSE(std::strncmp(payloads[1], reinterpret_cast<const char*>(fr.getPayloadPtr()), 7));
  95. ASSERT_EQ(i, fr.getTransferID().get());
  96. ASSERT_EQ(uavcan::TransferTypeServiceResponse, fr.getTransferType());
  97. ASSERT_EQ(i + 0x10, fr.getDstNodeID().get());
  98. }
  99. ASSERT_EQ(0, server.getRequestFailureCount());
  100. ASSERT_EQ(0, server.getResponseFailureCount());
  101. ASSERT_EQ(1, node.getDispatcher().getNumServiceRequestListeners());
  102. }
  103. ASSERT_EQ(0, node.getDispatcher().getNumServiceRequestListeners());
  104. }
  105. TEST(ServiceServer, Empty)
  106. {
  107. // Manual type registration - we can't rely on the GDTR state
  108. uavcan::GlobalDataTypeRegistry::instance().reset();
  109. uavcan::DefaultDataTypeRegistrator<root_ns_a::EmptyService> _registrator;
  110. SystemClockDriver clock_driver;
  111. CanDriverMock can_driver(1, clock_driver);
  112. TestNode node(can_driver, clock_driver, 1);
  113. EmptyServerImpl impl;
  114. uavcan::ServiceServer<root_ns_a::EmptyService, EmptyServerImpl::Binder> server(node);
  115. std::cout << "sizeof(ServiceServer<root_ns_a::EmptyService, EmptyServerImpl::Binder>): "
  116. << sizeof(uavcan::ServiceServer<root_ns_a::EmptyService, EmptyServerImpl::Binder>) << std::endl;
  117. ASSERT_EQ(0, node.getDispatcher().getNumServiceRequestListeners());
  118. ASSERT_GE(0, server.start(impl.bind()));
  119. ASSERT_EQ(1, node.getDispatcher().getNumServiceRequestListeners());
  120. }