1515 *
1616 */
1717
18+ #include < future>
1819#include < string>
1920
2021#include < gtest/gtest.h>
@@ -62,6 +63,32 @@ class UserCommandsTest : public InternalFixture<::testing::Test>
6263{
6364};
6465
66+ struct AsyncRequestInfo {
67+ bool retval{false };
68+ msgs::Boolean response;
69+ bool result{false };
70+ };
71+
72+ // This calls a request from a new thread so that the calling function can
73+ // continue even if the request blocks.
74+ template <typename RequestT>
75+ auto asyncRequest (transport::Node &_node, const std::string &_topic,
76+ const RequestT &_req)
77+ {
78+ unsigned int timeout = 5000 ;
79+ auto asyncRetval = std::async (std::launch::async, [&]
80+ {
81+ AsyncRequestInfo info;
82+ info.retval =
83+ _node.Request (_topic, _req, timeout, info.response , info.result );
84+ return info;
85+ });
86+ // Sleep for a little bit for the async thread to spin up and make the service
87+ // request
88+ GZ_SLEEP_MS (10 );
89+ return asyncRetval;
90+ }
91+
6592// ///////////////////////////////////////////////
6693// See https://github.com/gazebosim/gz-sim/issues/1175
6794TEST_F (UserCommandsTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(Create))
@@ -137,22 +164,23 @@ TEST_F(UserCommandsTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(Create))
137164 auto pos = pose->mutable_position ();
138165 pos->set_z (10 );
139166
140- msgs::Boolean res;
141- bool result;
142- unsigned int timeout = 5000 ;
143- std::string service{" /world/empty/create" };
144-
167+ std::string service{" /world/empty/create/blocking" };
145168 transport::Node node;
146- EXPECT_TRUE (node.Request (service, req, timeout, res, result));
147- EXPECT_TRUE (result);
148- EXPECT_TRUE (res.data ());
169+ auto requestDataFuture = asyncRequest (node, service, req);
149170
150171 // Check entity has not been created yet
151172 EXPECT_EQ (kNullEntity , ecm->EntityByComponents (components::Model (),
152173 components::Name (" spawned_model" )));
153174
154175 // Run an iteration and check it was created
155176 server.Run (true , 1 , false );
177+ {
178+ auto requestData = requestDataFuture.get ();
179+ EXPECT_TRUE (requestData.retval );
180+ EXPECT_TRUE (requestData.result );
181+ EXPECT_TRUE (requestData.response .data ());
182+ }
183+
156184 EXPECT_EQ (entityCount + 4 , ecm->EntityCount ());
157185 entityCount = ecm->EntityCount ();
158186
@@ -169,12 +197,16 @@ TEST_F(UserCommandsTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(Create))
169197 req.Clear ();
170198 req.set_sdf (modelStr);
171199
172- EXPECT_TRUE (node.Request (service, req, timeout, res, result));
173- EXPECT_TRUE (result);
174- EXPECT_TRUE (res.data ());
200+ requestDataFuture = asyncRequest (node, service, req);
175201
176202 // Run an iteration and check it was not created
177203 server.Run (true , 1 , false );
204+ {
205+ auto requestData = requestDataFuture.get ();
206+ EXPECT_TRUE (requestData.retval );
207+ EXPECT_TRUE (requestData.result );
208+ EXPECT_FALSE (requestData.response .data ());
209+ }
178210
179211 EXPECT_EQ (entityCount, ecm->EntityCount ());
180212
@@ -183,12 +215,16 @@ TEST_F(UserCommandsTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(Create))
183215 req.set_sdf (modelStr);
184216 req.set_allow_renaming (true );
185217
186- EXPECT_TRUE (node.Request (service, req, timeout, res, result));
187- EXPECT_TRUE (result);
188- EXPECT_TRUE (res.data ());
218+ requestDataFuture = asyncRequest (node, service, req);
189219
190220 // Run an iteration and check it was created with a new name
191221 server.Run (true , 1 , false );
222+ {
223+ auto requestData = requestDataFuture.get ();
224+ EXPECT_TRUE (requestData.retval );
225+ EXPECT_TRUE (requestData.result );
226+ EXPECT_TRUE (requestData.response .data ());
227+ }
192228
193229 EXPECT_EQ (entityCount + 4 , ecm->EntityCount ());
194230 entityCount = ecm->EntityCount ();
@@ -202,12 +238,16 @@ TEST_F(UserCommandsTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(Create))
202238 req.set_sdf (modelStr);
203239 req.set_name (" banana" );
204240
205- EXPECT_TRUE (node.Request (service, req, timeout, res, result));
206- EXPECT_TRUE (result);
207- EXPECT_TRUE (res.data ());
241+ requestDataFuture = asyncRequest (node, service, req);
208242
209243 // Run an iteration and check it was created with given name
210244 server.Run (true , 1 , false );
245+ {
246+ auto requestData = requestDataFuture.get ();
247+ EXPECT_TRUE (requestData.retval );
248+ EXPECT_TRUE (requestData.result );
249+ EXPECT_TRUE (requestData.response .data ());
250+ }
211251
212252 EXPECT_EQ (entityCount + 4 , ecm->EntityCount ());
213253 entityCount = ecm->EntityCount ();
@@ -220,12 +260,16 @@ TEST_F(UserCommandsTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(Create))
220260 req.Clear ();
221261 req.set_sdf (lightStr);
222262
223- EXPECT_TRUE (node.Request (service, req, timeout, res, result));
224- EXPECT_TRUE (result);
225- EXPECT_TRUE (res.data ());
263+ requestDataFuture = asyncRequest (node, service, req);
226264
227265 // Run an iteration and check it was created
228266 server.Run (true , 1 , false );
267+ {
268+ auto requestData = requestDataFuture.get ();
269+ EXPECT_TRUE (requestData.retval );
270+ EXPECT_TRUE (requestData.result );
271+ EXPECT_TRUE (requestData.response .data ());
272+ }
229273
230274 EXPECT_EQ (entityCount + 2 , ecm->EntityCount ());
231275 entityCount = ecm->EntityCount ();
@@ -239,12 +283,16 @@ TEST_F(UserCommandsTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(Create))
239283 req.Clear ();
240284 req.mutable_light ()->set_name (" light_test" );
241285 req.mutable_light ()->set_parent_id (1 );
242- EXPECT_TRUE (node.Request (service, req, timeout, res, result));
243- EXPECT_TRUE (result);
244- EXPECT_TRUE (res.data ());
286+ requestDataFuture = asyncRequest (node, service, req);
245287
246288 // Run an iteration and check it was created
247289 server.Run (true , 1 , false );
290+ {
291+ auto requestData = requestDataFuture.get ();
292+ EXPECT_TRUE (requestData.retval );
293+ EXPECT_TRUE (requestData.result );
294+ EXPECT_TRUE (requestData.response .data ());
295+ }
248296
249297 EXPECT_EQ (entityCount + 2 , ecm->EntityCount ());
250298 entityCount = ecm->EntityCount ();
@@ -259,17 +307,13 @@ TEST_F(UserCommandsTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(Create))
259307 req.set_sdf (modelStr);
260308 req.set_name (" acerola" );
261309
262- EXPECT_TRUE (node.Request (service, req, timeout, res, result));
263- EXPECT_TRUE (result);
264- EXPECT_TRUE (res.data ());
310+ auto requestDataFuture1 = asyncRequest (node, service, req);
265311
266312 req.Clear ();
267313 req.set_sdf (modelStr);
268314 req.set_name (" coconut" );
269315
270- EXPECT_TRUE (node.Request (service, req, timeout, res, result));
271- EXPECT_TRUE (result);
272- EXPECT_TRUE (res.data ());
316+ auto requestDataFuture2 = asyncRequest (node, service, req);
273317
274318 // Check neither exists yet
275319 EXPECT_EQ (kNullEntity , ecm->EntityByComponents (components::Model (),
@@ -280,6 +324,18 @@ TEST_F(UserCommandsTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(Create))
280324
281325 // Run an iteration and check both models were created
282326 server.Run (true , 1 , false );
327+ {
328+ auto requestData = requestDataFuture1.get ();
329+ EXPECT_TRUE (requestData.retval );
330+ EXPECT_TRUE (requestData.result );
331+ EXPECT_TRUE (requestData.response .data ());
332+ }
333+ {
334+ auto requestData = requestDataFuture2.get ();
335+ EXPECT_TRUE (requestData.retval );
336+ EXPECT_TRUE (requestData.result );
337+ EXPECT_TRUE (requestData.response .data ());
338+ }
283339
284340 EXPECT_EQ (entityCount + 8 , ecm->EntityCount ());
285341 entityCount = ecm->EntityCount ();
@@ -293,12 +349,16 @@ TEST_F(UserCommandsTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(Create))
293349 req.Clear ();
294350 req.set_sdf (lightsStr);
295351
296- EXPECT_TRUE (node.Request (service, req, timeout, res, result));
297- EXPECT_TRUE (result);
298- EXPECT_TRUE (res.data ());
352+ requestDataFuture = asyncRequest (node, service, req);
299353
300354 // Run an iteration and check only the 1st was created
301355 server.Run (true , 1 , false );
356+ {
357+ auto requestData = requestDataFuture.get ();
358+ EXPECT_TRUE (requestData.retval );
359+ EXPECT_TRUE (requestData.result );
360+ EXPECT_TRUE (requestData.response .data ());
361+ }
302362
303363 EXPECT_EQ (entityCount + 2 , ecm->EntityCount ());
304364 entityCount = ecm->EntityCount ();
@@ -315,12 +375,16 @@ TEST_F(UserCommandsTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(Create))
315375 req.Clear ();
316376 req.set_sdf (badStr);
317377
318- EXPECT_TRUE (node.Request (service, req, timeout, res, result));
319- EXPECT_TRUE (result);
320- EXPECT_TRUE (res.data ());
378+ requestDataFuture = asyncRequest (node, service, req);
321379
322380 // Run an iteration and check nothing was created
323381 server.Run (true , 1 , false );
382+ {
383+ auto requestData = requestDataFuture.get ();
384+ EXPECT_TRUE (requestData.retval );
385+ EXPECT_TRUE (requestData.result );
386+ EXPECT_FALSE (requestData.response .data ());
387+ }
324388
325389 EXPECT_EQ (entityCount, ecm->EntityCount ());
326390
@@ -330,12 +394,16 @@ TEST_F(UserCommandsTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(Create))
330394 req.Clear ();
331395 req.set_sdf_filename (testModel);
332396
333- EXPECT_TRUE (node.Request (service, req, timeout, res, result));
334- EXPECT_TRUE (result);
335- EXPECT_TRUE (res.data ());
397+ requestDataFuture = asyncRequest (node, service, req);
336398
337399 // Run an iteration and check it was created
338400 server.Run (true , 1 , false );
401+ {
402+ auto requestData = requestDataFuture.get ();
403+ EXPECT_TRUE (requestData.retval );
404+ EXPECT_TRUE (requestData.result );
405+ EXPECT_TRUE (requestData.response .data ());
406+ }
339407 EXPECT_EQ (entityCount + 4 , ecm->EntityCount ());
340408
341409 EXPECT_NE (kNullEntity , ecm->EntityByComponents (components::Model (),
0 commit comments