1 #define ASIO_STANDALONE 7 #include <gtest/gtest.h> 10 #include <std_srvs/SetBool.h> 11 #include <websocketpp/config/asio_client.hpp> 16 constexpr
char URI[] =
"ws://localhost:9876";
20 111, 32, 119, 111, 114, 108, 100};
28 inline static const std::string
PARAM_1_NAME =
"/node_1/string_param";
32 inline static const std::string
PARAM_2_NAME =
"/node_2/int_array_param";
41 _wsClient = std::make_shared<foxglove::Client<websocketpp::config::asio_client>>();
46 std::shared_ptr<foxglove::Client<websocketpp::config::asio_client>>
_wsClient;
51 inline static const std::string SERVICE_NAME =
"/foo_service";
57 SERVICE_NAME, [&](
auto& req,
auto& res) {
58 res.message =
"hello";
59 res.success = req.data;
69 TEST(SmokeTest, testConnection) {
74 TEST(SmokeTest, testSubscription) {
76 const std::string topic_name =
"/pub_topic";
78 auto pub = nh.
advertise<std_msgs::String>(topic_name, 10,
true);
79 pub.
publish(std::string(
"hello world"));
82 const auto clientCount = 3;
83 for (
auto i = 0; i < clientCount; ++i) {
84 std::vector<uint8_t> msgData;
91 TEST(SmokeTest, testSubscriptionParallel) {
93 const std::string topic_name =
"/pub_topic";
95 auto pub = nh.
advertise<std_msgs::String>(topic_name, 10,
true);
96 pub.
publish(std::string(
"hello world"));
99 std::vector<std::future<std::vector<uint8_t>>> futures;
100 const auto clientCount = 3;
101 for (
auto i = 0; i < clientCount; ++i) {
106 for (
auto& future : futures) {
107 ASSERT_EQ(std::future_status::ready, future.wait_for(
DEFAULT_TIMEOUT));
108 auto msgData = future.get();
114 TEST(SmokeTest, testPublishing) {
119 advertisement.
topic =
"/foo";
125 std::promise<std::string> msgPromise;
126 auto msgFuture = msgPromise.get_future();
127 auto subscriber = nh.
subscribe<std_msgs::String>(
128 advertisement.
topic, 10, [&msgPromise](
const std_msgs::String::ConstPtr& msg) {
129 msgPromise.set_value(msg->data);
140 const auto msgResult = msgFuture.wait_for(
ONE_SECOND);
141 ASSERT_EQ(std::future_status::ready, msgResult);
142 EXPECT_EQ(
"hello world", msgFuture.get());
146 const std::string requestId =
"req-testGetAllParams";
149 ASSERT_EQ(std::future_status::ready, future.wait_for(
DEFAULT_TIMEOUT));
150 std::vector<foxglove::Parameter> params = future.get();
152 EXPECT_GE(params.size(), 2UL);
156 const std::string requestId =
"req-testGetNonExistingParameters";
159 {
"/foo_1/non_existing_parameter",
"/foo_2/non_existing/nested_parameter"}, requestId);
160 ASSERT_EQ(std::future_status::ready, future.wait_for(
DEFAULT_TIMEOUT));
161 std::vector<foxglove::Parameter> params = future.get();
163 EXPECT_TRUE(params.empty());
167 const std::string requestId =
"req-testGetParameters";
170 ASSERT_EQ(std::future_status::ready, future.wait_for(
DEFAULT_TIMEOUT));
171 std::vector<foxglove::Parameter> params = future.get();
173 EXPECT_EQ(2UL, params.size());
174 auto p1Iter = std::find_if(params.begin(), params.end(), [](
const auto&
param) {
177 auto p2Iter = std::find_if(params.begin(), params.end(), [](
const auto&
param) {
180 ASSERT_NE(p1Iter, params.end());
182 ASSERT_NE(p2Iter, params.end());
184 std::vector<double> double_array_val;
185 const auto array_params = p2Iter->getValue().getValue<std::vector<foxglove::ParameterValue>>();
186 for (
const auto& paramValue : array_params) {
187 double_array_val.push_back(paramValue.getValue<
double>());
194 const std::vector<foxglove::ParameterValue> newP2value = {4.1, 5.5, 6.6};
196 const std::vector<foxglove::Parameter> parameters = {
202 const std::string requestId =
"req-testSetParameters";
205 ASSERT_EQ(std::future_status::ready, future.wait_for(
DEFAULT_TIMEOUT));
206 std::vector<foxglove::Parameter> params = future.get();
208 EXPECT_EQ(2UL, params.size());
209 auto p1Iter = std::find_if(params.begin(), params.end(), [](
const auto&
param) {
212 auto p2Iter = std::find_if(params.begin(), params.end(), [](
const auto&
param) {
215 ASSERT_NE(p1Iter, params.end());
216 EXPECT_EQ(newP1value, p1Iter->getValue().getValue<
PARAM_1_TYPE>());
217 ASSERT_NE(p2Iter, params.end());
219 std::vector<double> double_array_val;
220 const auto array_params = p2Iter->getValue().getValue<std::vector<foxglove::ParameterValue>>();
221 for (
const auto& paramValue : array_params) {
222 double_array_val.push_back(paramValue.getValue<
double>());
224 const std::vector<double> expected_value = {4.1, 5.5, 6.6};
225 EXPECT_EQ(double_array_val, expected_value);
230 const std::vector<foxglove::Parameter> parameters = {
234 const std::string requestId =
"req-testSetParameters";
236 _wsClient->setParameters(parameters, requestId);
237 ASSERT_EQ(std::future_status::ready, future.wait_for(
DEFAULT_TIMEOUT));
238 std::vector<foxglove::Parameter> params = future.get();
240 EXPECT_EQ(1UL, params.size());
244 const std::vector<foxglove::Parameter> parameters = {
248 const std::string requestId =
"req-testUnsetParameter";
250 _wsClient->setParameters(parameters, requestId);
251 ASSERT_EQ(std::future_status::ready, future.wait_for(
DEFAULT_TIMEOUT));
252 std::vector<foxglove::Parameter> params = future.get();
254 EXPECT_EQ(0UL, params.size());
262 ASSERT_EQ(std::future_status::ready, future.wait_for(
DEFAULT_TIMEOUT));
263 std::vector<foxglove::Parameter> params = future.get();
265 ASSERT_EQ(1UL, params.size());
272 ASSERT_EQ(std::future_status::timeout, future.wait_for(
ONE_SECOND));
278 std::make_shared<foxglove::Client<websocketpp::config::asio_client>>(),
280 std::make_shared<foxglove::Client<websocketpp::config::asio_client>>(),
283 std::vector<std::future<std::vector<foxglove::Parameter>>> futures;
284 for (
auto client : clients) {
286 std::async(std::launch::async, [client]() -> std::vector<foxglove::Parameter> {
288 const std::string requestId =
"req-123";
290 client->getParameters({}, requestId);
292 if (future.valid()) {
300 for (
auto& future : futures) {
301 ASSERT_EQ(std::future_status::ready, future.wait_for(
DEFAULT_TIMEOUT));
302 std::vector<foxglove::Parameter> parameters;
303 EXPECT_NO_THROW(parameters = future.get());
304 EXPECT_GE(parameters.size(), 2UL);
311 std::make_shared<foxglove::Client<websocketpp::config::asio_client>>(),
313 std::make_shared<foxglove::Client<websocketpp::config::asio_client>>(),
317 for (
auto client : clients) {
318 ASSERT_EQ(std::future_status::ready, client->connect(
URI).wait_for(std::chrono::seconds(5)));
320 ASSERT_EQ(std::future_status::ready, serviceFuture.wait_for(std::chrono::seconds(5)));
329 const std::vector<uint8_t> expectedSerializedResponse = {1, 5, 0, 0, 0, 104, 101, 108, 108, 111};
331 std::vector<std::future<foxglove::ServiceResponse>> futures;
332 for (
auto client : clients) {
334 client->sendServiceRequest(request);
337 for (
auto& future : futures) {
338 ASSERT_EQ(std::future_status::ready, future.wait_for(std::chrono::seconds(5)));
340 EXPECT_NO_THROW(response = future.get());
341 EXPECT_EQ(response.serviceId, request.
serviceId);
342 EXPECT_EQ(response.callId, request.
callId);
343 EXPECT_EQ(response.encoding, request.
encoding);
344 EXPECT_EQ(response.data, expectedSerializedResponse);
349 int main(
int argc,
char** argv) {
350 testing::InitGoogleTest(&argc, argv);
355 std::this_thread::sleep_for(std::chrono::seconds(2));
359 const auto testResult = RUN_ALL_TESTS();
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
std::shared_ptr< foxglove::Client< websocketpp::config::asio_client > > _wsClient
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
static const PARAM_1_TYPE PARAM_1_DEFAULT_VALUE
constexpr uint8_t HELLO_WORLD_BINARY[]
std::future< Service > waitForService(std::shared_ptr< ClientInterface > client, const std::string &serviceName)
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
int main(int argc, char **argv)
void advertise(const std::vector< ClientAdvertisement > &channels) override
TEST(SmokeTest, testConnection)
std::vector< uint8_t > data
TEST_F(ParameterTest, testGetAllParams)
void publish(const boost::shared_ptr< M > &message) const
constexpr auto DEFAULT_TIMEOUT
void connect(const std::string &uri, std::function< void(websocketpp::connection_hdl)> onOpenHandler, std::function< void(websocketpp::connection_hdl)> onCloseHandler=nullptr) override
static const std::string PARAM_2_NAME
void publish(ClientChannelId channelId, const uint8_t *buffer, size_t size) override
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void unadvertise(const std::vector< ClientChannelId > &channelIds) override
std::vector< uint8_t > connectClientAndReceiveMsg(const std::string &uri, const std::string &topic_name)
void setParam(const std::string &key, const XmlRpc::XmlRpcValue &v) const
static const PARAM_2_TYPE PARAM_2_DEFAULT_VALUE
ros::ServiceServer _service
constexpr auto ONE_SECOND
static const std::string PARAM_1_NAME
std::vector< double > PARAM_2_TYPE
ClientChannelId channelId
std::future< ServiceResponse > waitForServiceResponse(std::shared_ptr< ClientInterface > client)
const std::string response
std::future< std::vector< Parameter > > waitForParameters(std::shared_ptr< ClientInterface > client, const std::string &requestId=std::string())