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