gtest_coroutines.cpp
Go to the documentation of this file.
3 #include <chrono>
4 #include <future>
5 #include <gtest/gtest.h>
6 
7 using namespace std::chrono;
8 
9 using Millisecond = std::chrono::milliseconds;
10 using Timepoint = std::chrono::time_point<std::chrono::steady_clock>;
11 
13 {
14  public:
15  SimpleCoroAction(milliseconds timeout, bool will_fail,
16  const std::string &node_name,
17  const BT::NodeConfiguration &config)
18  : BT::CoroActionNode(node_name, config)
19  , will_fail_(will_fail)
20  , timeout_(timeout)
21  , start_time_(Timepoint::min())
22  {
23  }
24 
25  virtual void halt() override
26  {
27  std::cout << "Action was halted. doing cleanup here" << std::endl;
28  start_time_ = Timepoint::min();
29  halted_ = true;
31  }
32 
33  bool wasHalted()
34  {
35  return halted_;
36  }
37 
39  {
40  timeout_ = ms;
41  }
42 
43  protected:
44  virtual BT::NodeStatus tick() override
45  {
46  std::cout << "Starting action " << std::endl;
47  halted_ = false;
48 
49  if (start_time_ == Timepoint::min())
50  {
51  start_time_ = std::chrono::steady_clock::now();
52  }
53 
54  while (std::chrono::steady_clock::now() < (start_time_ + timeout_))
55  {
56  setStatusRunningAndYield();
57  }
58 
59  halted_ = false;
60 
61  std::cout << "Done" << std::endl;
62  start_time_ = Timepoint::min();
63  return (will_fail_ ? BT::NodeStatus::FAILURE : BT::NodeStatus::SUCCESS);
64  }
65 
66  public:
67  bool will_fail_;
68 
69  private:
70  std::chrono::milliseconds timeout_;
72  bool halted_;
73 };
74 
76 {
77  auto status = node.executeTick();
78  while (status == BT::NodeStatus::RUNNING)
79  {
80  status = node.executeTick();
81  std::this_thread::sleep_for(Millisecond(1));
82  }
83  return status;
84 }
85 
86 
87 TEST(CoroTest, do_action)
88 {
89  BT::NodeConfiguration node_config_;
90  node_config_.blackboard = BT::Blackboard::create();
91  BT::assignDefaultRemapping<SimpleCoroAction>(node_config_);
92  SimpleCoroAction node( milliseconds(200), false, "Action", node_config_);
93 
95  EXPECT_FALSE( node.wasHalted() );
96 
97  EXPECT_EQ(BT::NodeStatus::SUCCESS, executeWhileRunning(node)) << "Second call to coro action";
98  EXPECT_FALSE( node.wasHalted() );
99 
100  node.will_fail_ = true;
102  << "Should execute again and retun failure";
103  EXPECT_FALSE( node.wasHalted() );
104 
105 
107  << "Shoudln't fail because we set status to idle";
108  EXPECT_FALSE( node.wasHalted() );
109 }
110 
111 
112 TEST(CoroTest, do_action_timeout)
113 {
114  BT::NodeConfiguration node_config_;
115  node_config_.blackboard = BT::Blackboard::create();
116  BT::assignDefaultRemapping<SimpleCoroAction>(node_config_);
117 
118  SimpleCoroAction node( milliseconds(300), false, "Action", node_config_);
119  BT::TimeoutNode<> timeout("TimeoutAction", 200);
120 
121  timeout.setChild(&node);
122 
123  EXPECT_EQ(BT::NodeStatus::FAILURE, executeWhileRunning(timeout) ) << "should timeout";
124  EXPECT_TRUE( node.wasHalted() );
125 
126  node.setRequiredTime( Millisecond(100) );
127 
128  EXPECT_EQ(BT::NodeStatus::SUCCESS, executeWhileRunning(timeout) );
129  EXPECT_FALSE( node.wasHalted() );
130 }
131 
132 TEST(CoroTest, sequence_child)
133 {
134  BT::NodeConfiguration node_config_;
135  node_config_.blackboard = BT::Blackboard::create();
136  BT::assignDefaultRemapping<SimpleCoroAction>(node_config_);
137 
138  SimpleCoroAction actionA( milliseconds(200), false, "action_A", node_config_);
139  SimpleCoroAction actionB( milliseconds(200), false, "action_B", node_config_);
140  BT::TimeoutNode<> timeout("timeout", 300);
141  BT::SequenceNode sequence("sequence");
142 
143  timeout.setChild(&sequence);
144  sequence.addChild(&actionA);
145  sequence.addChild(&actionB);
146 
147  EXPECT_EQ(BT::NodeStatus::FAILURE, executeWhileRunning(timeout) ) << "should timeout";
148  EXPECT_FALSE( actionA.wasHalted() );
149  EXPECT_TRUE( actionB.wasHalted() );
150 }
151 
152 TEST(CoroTest, OtherThreadHalt)
153 {
154  BT::NodeConfiguration node_config_;
155  node_config_.blackboard = BT::Blackboard::create();
156  BT::assignDefaultRemapping<SimpleCoroAction>(node_config_);
157 
158  SimpleCoroAction actionA( milliseconds(200), false, "action_A", node_config_);
159  actionA.executeTick();
160 
161  std::cout << "----- 1 ------ " << std::endl;
162  auto handle = std::async(std::launch::async, [&](){
163  actionA.halt();
164  });
165  handle.wait();
166  std::cout << "----- 2 ------ " << std::endl;
167  EXPECT_TRUE( actionA.wasHalted() );
168 
169  std::cout << "----- 3------ " << std::endl;
170  handle = std::async(std::launch::async, [&](){
171  actionA.executeTick();
172  });
173  handle.wait();
174  std::cout << "----- 4 ------ " << std::endl;
175 }
176 
virtual void halt() override
TEST(CoroTest, do_action)
std::chrono::time_point< std::chrono::steady_clock > Timepoint
static Blackboard::Ptr create(Blackboard::Ptr parent={})
Definition: blackboard.h:38
BT::NodeStatus executeWhileRunning(BT::TreeNode &node)
The TimeoutNode will halt() a running child if the latter has been RUNNING for more than a give time...
Definition: timeout_node.h:24
std::chrono::milliseconds Millisecond
void halt() override
Blackboard::Ptr blackboard
Definition: tree_node.h:47
virtual BT::NodeStatus tick() override
Method to be implemented by the user.
The CoroActionNode class is an ideal candidate for asynchronous actions which need to communicate wit...
Definition: action_node.h:190
void setChild(TreeNode *child)
Abstract base class for Behavior Tree Nodes.
Definition: tree_node.h:53
SimpleCoroAction(milliseconds timeout, bool will_fail, const std::string &node_name, const BT::NodeConfiguration &config)
void addChild(TreeNode *child)
The method used to add nodes to the children vector.
NodeStatus
Definition: basic_types.h:35
virtual BT::NodeStatus executeTick()
The method that should be used to invoke tick() and setStatus();.
Definition: tree_node.cpp:33
void setRequiredTime(Millisecond ms)
The SequenceNode is used to tick children in an ordered sequence. If any child returns RUNNING...
Definition: sequence_node.h:34
std::chrono::milliseconds timeout_


behaviotree_cpp_v3
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Tue May 4 2021 02:56:24