realtime_server_goal_handle_tests.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019, Open Source Robotics Foundation, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Willow Garage, Inc. nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <gmock/gmock.h>
33 #include <actionlib/TwoIntsAction.h>
34 #include <chrono>
35 #include <functional>
36 #include <memory>
37 #include <mutex>
38 #include <thread>
39 
43 
44 const size_t ATTEMPTS = 10;
45 const std::chrono::milliseconds DELAY(250);
46 
48 {
50  bool have_handle_ = false;
52  std::mutex mtx_;
53 
55  {
56  std::unique_lock<std::mutex> lock(mtx_);
57  handle_ = handle;
58  handle_.setAccepted();
59  have_handle_ = true;
60  }
61 
63  {
64  }
65 
67  {
68  for (size_t i = 0; i < ATTEMPTS; ++i)
69  {
70  ros::spinOnce();
71  std::this_thread::sleep_for(DELAY);
72  std::unique_lock<std::mutex> lock(mtx_);
73  if (have_handle_)
74  {
75  break;
76  }
77  }
78  std::unique_lock<std::mutex> lock(mtx_);
79  return have_handle_;
80  }
81 };
82 
84 {
85  bool have_feedback_ = false;
86  std::mutex mtx_;
87 
88  using FeedbackConstPtr = TwoIntsActionServer::FeedbackConstPtr;
90  {
91  std::unique_lock<std::mutex> lock(mtx_);
92  have_feedback_ = true;
93  }
94 
96  {
97  for (size_t i = 0; i < ATTEMPTS; ++i)
98  {
99  ros::spinOnce();
100  std::this_thread::sleep_for(DELAY);
101  std::unique_lock<std::mutex> lock(mtx_);
102  if (have_feedback_)
103  {
104  break;
105  }
106  }
107  std::unique_lock<std::mutex> lock(mtx_);
108  return have_feedback_;
109  }
110 };
111 
112 std::shared_ptr<TwoIntsActionClient>
114  const std::string & server_name,
115  FeedbackCallback * cb = nullptr)
116 {
117  auto ac = std::make_shared<TwoIntsActionClient>(server_name, true);
118 
119  for (size_t i = 0; i < ATTEMPTS && !ac->isServerConnected(); ++i)
120  {
121  ros::spinOnce();
122  std::this_thread::sleep_for(DELAY);
123  }
124  if (!ac->isServerConnected())
125  {
126  ac.reset();
127  } else {
128  actionlib::TwoIntsGoal goal;
129  goal.a = 2;
130  goal.b = 3;
131  ac->sendGoal(
132  goal,
135  std::bind(&FeedbackCallback::feedback_callback, cb, std::placeholders::_1));
136  }
137  return ac;
138 }
139 
140 bool wait_for_result(std::shared_ptr<TwoIntsActionClient> ac)
141 {
142  for (int i = 0; i < ATTEMPTS; ++i)
143  {
144  ros::spinOnce();
145  if (ac->getState().isDone())
146  {
147  return true;
148  }
149  std::this_thread::sleep_for(DELAY);
150  }
151  return false;
152 }
153 
154 std::shared_ptr<TwoIntsActionServer>
155 make_server(const std::string & server_name, ActionCallback & callbacks)
156 {
157  ros::NodeHandle nh;
158  auto as = std::make_shared<TwoIntsActionServer>(
159  nh, server_name,
160  std::bind(&ActionCallback::goal_callback, &callbacks, std::placeholders::_1),
161  std::bind(&ActionCallback::cancel_callback, &callbacks, std::placeholders::_1), false);
162  as->start();
163  return as;
164 }
165 
167 {
168  ActionCallback callbacks;
169  const std::string server_name("set_aborted");
170  auto as = make_server(server_name, callbacks);
171 
172  auto client = send_goal(server_name);
173  ASSERT_NE(nullptr, client.get());
174 
175  ASSERT_TRUE(callbacks.wait_for_handle());
177  ASSERT_TRUE(rt_handle.valid());
178 
179  {
180  actionlib::TwoIntsResult::Ptr result(new actionlib::TwoIntsResult);
181  result->sum = 42;
182  rt_handle.setAborted(result);
183  rt_handle.runNonRealtime(ros::TimerEvent());
184  }
185 
186  ASSERT_TRUE(wait_for_result(client));
187  auto state = client->getState();
188  EXPECT_EQ(state, actionlib::SimpleClientGoalState::ABORTED) << state.toString();
189  auto result = client->getResult();
190  ASSERT_NE(nullptr, result.get());
191  EXPECT_EQ(42, result->sum);
192 }
193 
195 {
196  ActionCallback callbacks;
197  const std::string server_name("set_canceled");
198  auto as = make_server(server_name, callbacks);
199 
200  auto client = send_goal(server_name);
201  ASSERT_NE(nullptr, client.get());
202 
203  ASSERT_TRUE(callbacks.wait_for_handle());
205  ASSERT_TRUE(rt_handle.valid());
206 
207  // Cancel and wait for server to learn about that
208  client->cancelGoal();
209  for (size_t i = 0; i < ATTEMPTS; ++i)
210  {
211  actionlib_msgs::GoalStatus gs = callbacks.handle_.getGoalStatus();
212  if (gs.status == actionlib_msgs::GoalStatus::PREEMPTING) {
213  break;
214  }
215  ros::spinOnce();
216  std::this_thread::sleep_for(DELAY);
217  }
218  ASSERT_EQ(callbacks.handle_.getGoalStatus().status, actionlib_msgs::GoalStatus::PREEMPTING);
219 
220  {
221  actionlib::TwoIntsResult::Ptr result(new actionlib::TwoIntsResult);
222  result->sum = 1234;
223  rt_handle.setCanceled(result);
224  rt_handle.runNonRealtime(ros::TimerEvent());
225  }
226 
227  ASSERT_TRUE(wait_for_result(client));
228  auto state = client->getState();
229  EXPECT_EQ(state, actionlib::SimpleClientGoalState::PREEMPTED) << state.toString();
230  auto result = client->getResult();
231  ASSERT_NE(nullptr, result.get());
232  EXPECT_EQ(1234, result->sum);
233 }
234 
236 {
237  ActionCallback callbacks;
238  const std::string server_name("set_succeeded");
239  auto as = make_server(server_name, callbacks);
240 
241  auto client = send_goal(server_name);
242  ASSERT_NE(nullptr, client.get());
243 
244  ASSERT_TRUE(callbacks.wait_for_handle());
246  ASSERT_TRUE(rt_handle.valid());
247 
248  {
249  actionlib::TwoIntsResult::Ptr result(new actionlib::TwoIntsResult);
250  result->sum = 321;
251  rt_handle.setSucceeded(result);
252  rt_handle.runNonRealtime(ros::TimerEvent());
253  }
254 
255  ASSERT_TRUE(wait_for_result(client));
256  auto state = client->getState();
257  EXPECT_EQ(state, actionlib::SimpleClientGoalState::SUCCEEDED) << state.toString();
258  auto result = client->getResult();
259  ASSERT_NE(nullptr, result.get());
260  EXPECT_EQ(321, result->sum);
261 }
262 
264 {
265  ActionCallback callbacks;
266  FeedbackCallback client_callbacks;
267  const std::string server_name("send_feedback");
268  auto as = make_server(server_name, callbacks);
269 
270  auto client = send_goal(server_name, &client_callbacks);
271  ASSERT_NE(nullptr, client.get());
272 
273  ASSERT_TRUE(callbacks.wait_for_handle());
275  ASSERT_TRUE(rt_handle.valid());
276 
277  {
278  actionlib::TwoIntsFeedback::Ptr fb(new actionlib::TwoIntsFeedback());
279  rt_handle.setFeedback(fb);
280  rt_handle.runNonRealtime(ros::TimerEvent());
281  }
282 
283  EXPECT_TRUE(client_callbacks.wait_for_feedback());
284 }
285 
286 int main(int argc, char ** argv) {
287  ::testing::InitGoogleTest(&argc, argv);
288  ros::init(argc, argv, "realtime_server_goal_handle_tests");
289  return RUN_ALL_TESTS();
290 }
const size_t ATTEMPTS
std::shared_ptr< TwoIntsActionClient > send_goal(const std::string &server_name, FeedbackCallback *cb=nullptr)
ServerGoalHandle< ActionSpec > GoalHandle
bool wait_for_result(std::shared_ptr< TwoIntsActionClient > ac)
void feedback_callback(const FeedbackConstPtr &)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
const std::chrono::milliseconds DELAY(250)
actionlib_msgs::GoalStatus getGoalStatus() const
void cancel_callback(GoalHandle handle)
void setAccepted(const std::string &text=std::string(""))
boost::function< void()> SimpleActiveCallback
std::shared_ptr< TwoIntsActionServer > make_server(const std::string &server_name, ActionCallback &callbacks)
void goal_callback(GoalHandle handle)
TwoIntsActionServer::FeedbackConstPtr FeedbackConstPtr
boost::function< void(const SimpleClientGoalState &state, const ResultConstPtr &result)> SimpleDoneCallback
TEST(RealtimeServerGoalHandle, set_aborted)
int main(int argc, char **argv)
ROSCPP_DECL void spinOnce()


realtime_tools
Author(s): Stuart Glaser
autogenerated on Mon Feb 28 2022 23:22:45