gtest_blackboard.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2018-2019 Davide Faconti, Eurecat - All Rights Reserved
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
4 * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
5 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
10 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #include <gtest/gtest.h>
14 #include "action_test_node.h"
15 #include "condition_test_node.h"
20 
21 using namespace BT;
22 
24 {
25  public:
26  BB_TestNode(const std::string& name, const NodeConfiguration& config):
27  SyncActionNode(name, config)
28  { }
29 
31  {
32  int value = 0;
33  auto res = getInput<int>("in_port");
34  if(!res)
35  {
36  throw RuntimeError("BB_TestNode needs input", res.error());
37  }
38  value = res.value()*2;
39  if( !setOutput("out_port", value) )
40  {
41  throw RuntimeError("BB_TestNode failed output");
42  }
43  return NodeStatus::SUCCESS;
44  }
45 
47  {
48  return { BT::InputPort<int>("in_port"),
49  BT::OutputPort<int>("out_port") };
50  }
51 };
52 
53 
55 {
56  public:
57  BB_TypedTestNode(const std::string& name, const NodeConfiguration& config):
58  SyncActionNode(name, config)
59  { }
60 
62  {
63  return NodeStatus::SUCCESS;
64  }
65 
67  {
68  return { BT::InputPort("input"),
69  BT::InputPort<int>("input_int"),
70  BT::InputPort<std::string>("input_string"),
71 
72  BT::OutputPort("output"),
73  BT::OutputPort<int>("output_int"),
74  BT::OutputPort<std::string>("output_string") };
75  }
76 };
77 
78 
79 TEST(BlackboardTest, GetInputsFromBlackboard)
80 {
81  auto bb = Blackboard::create();
82 
83  NodeConfiguration config;
84  assignDefaultRemapping<BB_TestNode>( config );
85 
86  config.blackboard = bb;
87  bb->set("in_port", 11 );
88 
89  BB_TestNode node("good_one", config);
90 
91  // this should read and write "my_entry" in tick()
92  node.executeTick();
93 
94  ASSERT_EQ( bb->get<int>("out_port"), 22 );
95 }
96 
97 TEST(BlackboardTest, BasicRemapping)
98 {
99  auto bb = Blackboard::create();
100 
101  NodeConfiguration config;
102 
103  config.blackboard = bb;
104  config.input_ports["in_port"] = "{my_input_port}";
105  config.output_ports["out_port"] = "{my_output_port}";
106  bb->set("my_input_port", 11 );
107 
108  BB_TestNode node("good_one", config);
109  node.executeTick();
110 
111  ASSERT_EQ( bb->get<int>("my_output_port"), 22 );
112 }
113 
114 TEST(BlackboardTest, GetInputsFromText)
115 {
116  auto bb = Blackboard::create();
117 
118  NodeConfiguration config;
119  config.input_ports["in_port"] = "11";
120 
121  BB_TestNode missing_out("missing_output", config);
122  EXPECT_THROW( missing_out.executeTick(), RuntimeError );
123 
124  config.blackboard = bb;
125  config.output_ports["out_port"] = "=";
126 
127  BB_TestNode node("good_one", config);
128  node.executeTick();
129 
130  ASSERT_EQ( bb->get<int>("out_port"), 22 );
131 }
132 
133 TEST(BlackboardTest, SetOutputFromText)
134 {
135  const char* xml_text = R"(
136 
137  <root main_tree_to_execute = "MainTree" >
138  <BehaviorTree ID="MainTree">
139  <Sequence>
140  <BB_TestNode in_port="11" out_port="{my_port}"/>
141  <SetBlackboard output_key="my_port" value="-43" />
142  </Sequence>
143  </BehaviorTree>
144  </root>
145  )";
146 
147  BehaviorTreeFactory factory;
148  factory.registerNodeType<BB_TestNode>("BB_TestNode");
149 
150  auto bb = Blackboard::create();
151 
152  auto tree = factory.createTreeFromText(xml_text, bb);
153  tree.root_node->executeTick();
154 }
155 
156 TEST(BlackboardTest, WithFactory)
157 {
158  BehaviorTreeFactory factory;
159 
160  factory.registerNodeType<BB_TestNode>("BB_TestNode");
161 
162  const std::string xml_text = R"(
163 
164  <root main_tree_to_execute = "MainTree" >
165  <BehaviorTree ID="MainTree">
166  <Sequence>
167  <BB_TestNode name = "first" in_port="11"
168  out_port="{my_input_port}"/>
169 
170  <BB_TestNode name = "second" in_port="{my_input_port}"
171  out_port="{my_input_port}" />
172 
173  <BB_TestNode name = "third" in_port="{my_input_port}"
174  out_port="{my_output_port}" />
175  </Sequence>
176  </BehaviorTree>
177  </root>)";
178 
179  auto bb = Blackboard::create();
180 
181  auto tree = factory.createTreeFromText(xml_text, bb);
182  NodeStatus status = tree.root_node->executeTick();
183 
184  ASSERT_EQ( status, NodeStatus::SUCCESS );
185  ASSERT_EQ( bb->get<int>("my_input_port"), 44 );
186  ASSERT_EQ( bb->get<int>("my_output_port"), 88 );
187 }
188 
189 
190 TEST(BlackboardTest, TypoInPortName)
191 {
192  BehaviorTreeFactory factory;
193  factory.registerNodeType<BB_TestNode>("BB_TestNode");
194 
195  const std::string xml_text = R"(
196 
197  <root main_tree_to_execute = "MainTree" >
198  <BehaviorTree ID="MainTree">
199  <BB_TestNode inpuuuut_port="{value}" />
200  </BehaviorTree>
201  </root>)";
202 
203  ASSERT_THROW( factory.createTreeFromText(xml_text), RuntimeError );
204 }
205 
206 
207 TEST(BlackboardTest, CheckPortType)
208 {
209  BehaviorTreeFactory factory;
210  factory.registerNodeType<BB_TypedTestNode>("TypedNode");
211 
212  //-----------------------------
213  std::string good_one = R"(
214  <root main_tree_to_execute = "MainTree" >
215  <BehaviorTree ID="MainTree">
216  <Sequence>
217  <TypedNode name = "first" output_int="{matching}" output_string="{whatever}" output="{no_problem}" />
218  <TypedNode name = "second" input_int="{matching}" input="{whatever}" input_string="{no_problem}" />
219  </Sequence>
220  </BehaviorTree>
221  </root>)";
222 
223  auto tree = factory.createTreeFromText(good_one);
224  ASSERT_NE( tree.root_node, nullptr );
225  //-----------------------------
226  std::string bad_one = R"(
227  <root main_tree_to_execute = "MainTree" >
228  <BehaviorTree ID="MainTree">
229  <Sequence>
230  <TypedNode name = "first" output_int="{value}" />
231  <TypedNode name = "second" input_string="{value}" />
232  </Sequence>
233  </BehaviorTree>
234  </root>)";
235 
236  ASSERT_THROW( factory.createTreeFromText(bad_one), RuntimeError);
237 }
238 
240  public:
241  RefCountClass(std::shared_ptr<int> value): sptr_(std::move(value))
242  {
243  std::cout<< "Constructor: ref_count " << sptr_.use_count() << std::endl;
244  }
245 
246  RefCountClass(const RefCountClass &from) : sptr_(from.sptr_)
247  {
248  std::cout<< "ctor copy: ref_count " << sptr_.use_count() << std::endl;
249  }
250 
252  {
253  sptr_ = (from.sptr_);
254  std::cout<< "equal copied: ref_count " << sptr_.use_count() << std::endl;
255  return *this;
256  }
257 
258  virtual ~RefCountClass() {
259  std::cout<<("Destructor")<< std::endl;
260  }
261 
262  int refCount() const { return sptr_.use_count(); }
263 
264  private:
265  std::shared_ptr<int> sptr_;
266 };
267 
268 TEST(BlackboardTest, MoveVsCopy)
269 {
270  auto blackboard = Blackboard::create();
271 
272  RefCountClass test( std::make_shared<int>() );
273 
274  ASSERT_EQ( test.refCount(), 1);
275 
276  std::cout<<("----- before set -----")<< std::endl;
277  blackboard->set("testmove", test );
278  std::cout<<(" ----- after set -----")<< std::endl;
279 
280  ASSERT_EQ( test.refCount(), 2);
281 
282  RefCountClass other( blackboard->get<RefCountClass>("testmove") );
283 
284  ASSERT_EQ( test.refCount(), 3);
285 }
286 
287 
288 TEST(BlackboardTest, CheckTypeSafety)
289 {
290  //TODO check type safety when ports are created.
291  // remember that std::string is considered a type erased type.
292 
293  bool is = std::is_constructible<BT::StringView, char*>::value;
294  ASSERT_TRUE( is );
295 
296  is = std::is_constructible<BT::StringView, std::string>::value;
297  ASSERT_TRUE( is );
298 }
299 
NodeStatus tick()
Method to be implemented by the user.
static Blackboard::Ptr create(Blackboard::Ptr parent={})
Definition: blackboard.h:38
void registerNodeType(const std::string &ID)
Definition: bt_factory.h:174
TEST(BlackboardTest, GetInputsFromBlackboard)
std::shared_ptr< int > sptr_
Definition: any.hpp:455
TreeNode * root_node
Definition: bt_factory.h:80
virtual ~RefCountClass()
Blackboard::Ptr blackboard
Definition: tree_node.h:47
std::pair< std::string, PortInfo > OutputPort(StringView name, StringView description={})
Definition: basic_types.h:280
static PortsList providedPorts()
The SyncActionNode is an ActionNode that explicitly prevents the status RUNNING and doesn&#39;t require a...
Definition: action_node.h:52
The BehaviorTreeFactory is used to create instances of a TreeNode at run-time.
Definition: bt_factory.h:98
RefCountClass(const RefCountClass &from)
Tree createTreeFromText(const std::string &text, Blackboard::Ptr blackboard=Blackboard::create())
Definition: bt_factory.cpp:170
int refCount() const
BB_TypedTestNode(const std::string &name, const NodeConfiguration &config)
NodeStatus tick()
Method to be implemented by the user.
PortsRemapping output_ports
Definition: tree_node.h:49
std::unordered_map< std::string, PortInfo > PortsList
Definition: basic_types.h:316
virtual NodeStatus executeTick() override
throws if the derived class return RUNNING.
static const char * xml_text
NodeStatus
Definition: basic_types.h:35
static PortsList providedPorts()
virtual BT::NodeStatus executeTick()
The method that should be used to invoke tick() and setStatus();.
Definition: tree_node.cpp:33
RefCountClass(std::shared_ptr< int > value)
std::pair< std::string, PortInfo > InputPort(StringView name, StringView description={})
Definition: basic_types.h:274
PortsRemapping input_ports
Definition: tree_node.h:48
RefCountClass & operator=(const RefCountClass &from)
BB_TestNode(const std::string &name, const NodeConfiguration &config)


behaviortree_cpp
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Sat Jun 8 2019 18:04:05