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"), BT::OutputPort<int>("out_port")};
49  }
50 };
51 
53 {
54 public:
55  BB_TypedTestNode(const std::string& name, const NodeConfiguration& config) :
56  SyncActionNode(name, config)
57  {}
58 
60  {
61  return NodeStatus::SUCCESS;
62  }
63 
65  {
66  return {BT::InputPort("input"),
67  BT::InputPort<int>("input_int"),
68  BT::InputPort<std::string>("input_string"),
69 
70  BT::OutputPort("output"),
71  BT::OutputPort<int>("output_int"),
72  BT::OutputPort<std::string>("output_string")};
73  }
74 };
75 
76 TEST(BlackboardTest, GetInputsFromBlackboard)
77 {
78  auto bb = Blackboard::create();
79 
80  NodeConfiguration config;
81  assignDefaultRemapping<BB_TestNode>(config);
82 
83  config.blackboard = bb;
84  bb->set("in_port", 11);
85 
86  BB_TestNode node("good_one", config);
87 
88  // this should read and write "my_entry" in tick()
89  node.executeTick();
90 
91  ASSERT_EQ(bb->get<int>("out_port"), 22);
92 }
93 
94 TEST(BlackboardTest, BasicRemapping)
95 {
96  auto bb = Blackboard::create();
97 
98  NodeConfiguration config;
99 
100  config.blackboard = bb;
101  config.input_ports["in_port"] = "{my_input_port}";
102  config.output_ports["out_port"] = "{my_output_port}";
103  bb->set("my_input_port", 11);
104 
105  BB_TestNode node("good_one", config);
106  node.executeTick();
107 
108  ASSERT_EQ(bb->get<int>("my_output_port"), 22);
109 }
110 
111 TEST(BlackboardTest, GetInputsFromText)
112 {
113  auto bb = Blackboard::create();
114 
115  NodeConfiguration config;
116  config.input_ports["in_port"] = "11";
117 
118  BB_TestNode missing_out("missing_output", config);
119  EXPECT_THROW(missing_out.executeTick(), RuntimeError);
120 
121  config.blackboard = bb;
122  config.output_ports["out_port"] = "=";
123 
124  BB_TestNode node("good_one", config);
125  node.executeTick();
126 
127  ASSERT_EQ(bb->get<int>("out_port"), 22);
128 }
129 
130 TEST(BlackboardTest, SetOutputFromText)
131 {
132  const char* xml_text = R"(
133 
134  <root main_tree_to_execute = "MainTree" >
135  <BehaviorTree ID="MainTree">
136  <Sequence>
137  <BB_TestNode in_port="11" out_port="{my_port}"/>
138  <SetBlackboard output_key="my_port" value="-43" />
139  </Sequence>
140  </BehaviorTree>
141  </root>
142  )";
143 
144  BehaviorTreeFactory factory;
145  factory.registerNodeType<BB_TestNode>("BB_TestNode");
146 
147  auto bb = Blackboard::create();
148 
149  auto tree = factory.createTreeFromText(xml_text, bb);
150  tree.tickRoot();
151 }
152 
153 TEST(BlackboardTest, WithFactory)
154 {
155  BehaviorTreeFactory factory;
156 
157  factory.registerNodeType<BB_TestNode>("BB_TestNode");
158 
159  const std::string xml_text = R"(
160 
161  <root main_tree_to_execute = "MainTree" >
162  <BehaviorTree ID="MainTree">
163  <Sequence>
164  <BB_TestNode name = "first" in_port="11"
165  out_port="{my_input_port}"/>
166 
167  <BB_TestNode name = "second" in_port="{my_input_port}"
168  out_port="{my_input_port}" />
169 
170  <BB_TestNode name = "third" in_port="{my_input_port}"
171  out_port="{my_output_port}" />
172  </Sequence>
173  </BehaviorTree>
174  </root>)";
175 
176  auto bb = Blackboard::create();
177 
178  auto tree = factory.createTreeFromText(xml_text, bb);
179  NodeStatus status = tree.tickRoot();
180 
181  ASSERT_EQ(status, NodeStatus::SUCCESS);
182  ASSERT_EQ(bb->get<int>("my_input_port"), 44);
183  ASSERT_EQ(bb->get<int>("my_output_port"), 88);
184 }
185 
186 TEST(BlackboardTest, TypoInPortName)
187 {
188  BehaviorTreeFactory factory;
189  factory.registerNodeType<BB_TestNode>("BB_TestNode");
190 
191  const std::string xml_text = R"(
192 
193  <root main_tree_to_execute = "MainTree" >
194  <BehaviorTree ID="MainTree">
195  <BB_TestNode inpuuuut_port="{value}" />
196  </BehaviorTree>
197  </root>)";
198 
199  ASSERT_THROW(factory.createTreeFromText(xml_text), RuntimeError);
200 }
201 
202 TEST(BlackboardTest, CheckPortType)
203 {
204  BehaviorTreeFactory factory;
205  factory.registerNodeType<BB_TypedTestNode>("TypedNode");
206 
207  //-----------------------------
208  std::string good_one = R"(
209  <root main_tree_to_execute = "MainTree" >
210  <BehaviorTree ID="MainTree">
211  <Sequence>
212  <TypedNode name = "first" output_int="{matching}" output_string="{whatever}" output="{no_problem}" />
213  <TypedNode name = "second" input_int="{matching}" input="{whatever}" input_string="{no_problem}" />
214  </Sequence>
215  </BehaviorTree>
216  </root>)";
217 
218  auto tree = factory.createTreeFromText(good_one);
219  ASSERT_NE(tree.rootNode(), nullptr);
220  //-----------------------------
221  std::string bad_one = R"(
222  <root main_tree_to_execute = "MainTree" >
223  <BehaviorTree ID="MainTree">
224  <Sequence>
225  <TypedNode name = "first" output_int="{value}" />
226  <TypedNode name = "second" input_string="{value}" />
227  </Sequence>
228  </BehaviorTree>
229  </root>)";
230 
231  ASSERT_THROW(factory.createTreeFromText(bad_one), RuntimeError);
232 }
233 
235 {
236 public:
237  RefCountClass(std::shared_ptr<int> value) : sptr_(std::move(value))
238  {
239  std::cout << "Constructor: ref_count " << sptr_.use_count() << std::endl;
240  }
241 
242  RefCountClass(const RefCountClass& from) : sptr_(from.sptr_)
243  {
244  std::cout << "ctor copy: ref_count " << sptr_.use_count() << std::endl;
245  }
246 
248  {
249  sptr_ = (from.sptr_);
250  std::cout << "equal copied: ref_count " << sptr_.use_count() << std::endl;
251  return *this;
252  }
253 
254  virtual ~RefCountClass()
255  {
256  std::cout << ("Destructor") << std::endl;
257  }
258 
259  int refCount() const
260  {
261  return sptr_.use_count();
262  }
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 TEST(BlackboardTest, CheckTypeSafety)
288 {
289  //TODO check type safety when ports are created.
290  // remember that std::string is considered a type erased type.
291 
292  bool is = std::is_constructible<BT::StringView, char*>::value;
293  ASSERT_TRUE(is);
294 
295  is = std::is_constructible<BT::StringView, std::string>::value;
296  ASSERT_TRUE(is);
297 }
NodeStatus tick()
Method to be implemented by the user.
std::pair< std::string, PortInfo > InputPort(StringView name, StringView description={})
Definition: basic_types.h:293
static Blackboard::Ptr create(Blackboard::Ptr parent={})
Definition: blackboard.h:36
void registerNodeType(const std::string &ID)
Definition: bt_factory.h:364
TEST(BlackboardTest, GetInputsFromBlackboard)
std::shared_ptr< int > sptr_
Definition: any.hpp:455
virtual NodeStatus executeTick() override
throws if the derived class return RUNNING.
Definition: action_node.cpp:54
static const char * xml_text
virtual ~RefCountClass()
Blackboard::Ptr blackboard
Definition: tree_node.h:49
static PortsList providedPorts()
int refCount() const
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:251
RefCountClass(const RefCountClass &from)
NodeStatus tickRoot()
tickRoot send the tick signal to the root node. It will propagate through the entire tree...
Definition: bt_factory.h:210
Tree createTreeFromText(const std::string &text, Blackboard::Ptr blackboard=Blackboard::create())
Definition: bt_factory.cpp:278
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:51
std::unordered_map< std::string, PortInfo > PortsList
Definition: basic_types.h:333
std::pair< std::string, PortInfo > OutputPort(StringView name, StringView description={})
Definition: basic_types.h:300
NodeStatus
Definition: basic_types.h:35
static PortsList providedPorts()
RefCountClass(std::shared_ptr< int > value)
PortsRemapping input_ports
Definition: tree_node.h:50
RefCountClass & operator=(const RefCountClass &from)
BB_TestNode(const std::string &name, const NodeConfiguration &config)


behaviortree_cpp_v3
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Mon Jul 3 2023 02:50:14