13 #include <gtest/gtest.h>
17 #include "../sample_nodes/dummy_nodes.h"
31 auto res = getInput<int>(
"in_port");
34 throw RuntimeError(
"BB_TestNode needs input: ", res.error());
36 value = res.value() * 2;
37 if(!setOutput(
"out_port", value))
46 return { BT::InputPort<int>(
"in_port"), BT::OutputPort<int>(
"out_port") };
65 BT::InputPort<int>(
"input_int"),
66 BT::InputPort<std::string>(
"input_string"),
69 BT::OutputPort<int>(
"output_int"),
70 BT::OutputPort<std::string>(
"output_string") };
74 TEST(BlackboardTest, GetInputsFromBlackboard)
79 assignDefaultRemapping<BB_TestNode>(config);
82 bb->set(
"in_port", 11);
89 ASSERT_EQ(bb->get<
int>(
"out_port"), 22);
92 TEST(BlackboardTest, BasicRemapping)
101 bb->set(
"my_input_port", 11);
106 ASSERT_EQ(bb->get<
int>(
"my_output_port"), 22);
109 TEST(BlackboardTest, GetInputsFromText)
125 ASSERT_EQ(bb->get<
int>(
"out_port"), 22);
128 TEST(BlackboardTest, SetOutputFromText)
132 <root BTCPP_format="4" >
133 <BehaviorTree ID="MainTree">
135 <BB_TestNode in_port="11" out_port="{my_port}"/>
136 <Script code="my_port=-43" />
151 TEST(BlackboardTest, WithFactory)
159 <root BTCPP_format="4" >
160 <BehaviorTree ID="MainTree">
162 <BB_TestNode in_port="11"
163 out_port="{my_input_port}"/>
165 <BB_TestNode in_port="{my_input_port}"
166 out_port="{my_input_port}" />
168 <BB_TestNode in_port="{my_input_port}"
169 out_port="{my_output_port}" />
180 ASSERT_EQ(bb->get<
int>(
"my_input_port"), 44);
181 ASSERT_EQ(bb->get<
int>(
"my_output_port"), 88);
184 TEST(BlackboardTest, TypoInPortName)
191 <root BTCPP_format="4" >
192 <BehaviorTree ID="MainTree">
193 <BB_TestNode inpuuuut_port="{value}" />
200 TEST(BlackboardTest, CheckPortType)
206 std::string good_one = R
"(
207 <root BTCPP_format="4" >
208 <BehaviorTree ID="MainTree">
210 <TypedNode name = "first" output_int="{matching}" output_string="{whatever}" output="{no_problem}" />
211 <TypedNode name = "second" input_int="{matching}" input="{whatever}" input_string="{no_problem}" />
217 ASSERT_NE(tree.rootNode(),
nullptr);
219 std::string bad_one = R
"(
220 <root BTCPP_format="4" >
221 <BehaviorTree ID="MainTree">
223 <TypedNode name = "first" output_int="{value}" />
224 <TypedNode name = "second" input_string="{value}" />
237 std::cout <<
"Constructor: ref_count " << sptr_.use_count() << std::endl;
242 std::cout <<
"ctor copy: ref_count " << sptr_.use_count() << std::endl;
247 sptr_ = (from.
sptr_);
248 std::cout <<
"equal copied: ref_count " << sptr_.use_count() << std::endl;
254 std::cout << (
"Destructor") << std::endl;
259 return sptr_.use_count();
266 TEST(BlackboardTest, MoveVsCopy)
274 std::cout << (
"----- before set -----") << std::endl;
275 blackboard->set(
"testmove", test);
276 std::cout << (
" ----- after set -----") << std::endl;
285 TEST(BlackboardTest, CheckTypeSafety)
301 long* test_obj = &value;
303 blackboard->set(
"testmove", test_obj);
305 auto const timeout = std::chrono::milliseconds(250);
309 std::atomic_llong cycles = 0;
311 auto start = std::chrono::system_clock::now();
312 while((std::chrono::system_clock::now() - start) < timeout)
314 auto r1 = blackboard->getAnyLocked(
"testmove");
315 auto value_ptr = (r1.get()->cast<
long*>());
321 auto t1 = std::thread(func);
326 ASSERT_EQ(cycles, value);
331 std::atomic_llong cycles = 0;
333 auto start = std::chrono::system_clock::now();
334 while((std::chrono::system_clock::now() - start) < timeout)
336 auto value_ptr = blackboard->get<
long*>(
"testmove");
342 auto t1 = std::thread(func);
346 ASSERT_NE(cycles, value);
350 TEST(BlackboardTest, SetStringView)
355 bb->set(
"string_view", string_view_const);
357 ASSERT_NO_THROW(bb->set(
"string_view", string_view_const));
360 TEST(ParserTest, Issue605_whitespaces)
365 <root BTCPP_format="4" >
366 <BehaviorTree ID="MySubtree">
367 <Script code=" sub_value:=false " />
370 <BehaviorTree ID="MainTree">
372 <Script code=" my_value:=true " />
373 <SubTree ID="MySubtree" sub_value="{my_value} "/>
382 for(
auto const& subtree : tree.subtrees)
384 subtree->blackboard->debugMessage();
388 ASSERT_EQ(
false, tree.rootBlackboard()->get<
bool>(
"my_value"));
400 return { BT::InputPort<int32_t>(
"first"), BT::InputPort<int32_t>(
"second"),
401 BT::InputPort<std::string>(
"operator") };
406 int32_t firstValue = 0;
407 int32_t secondValue = 0;
408 std::string inputOperator;
409 if(!getInput(
"first", firstValue) || !getInput(
"second", secondValue) ||
410 !getInput(
"operator", inputOperator))
414 if((inputOperator ==
"==" && firstValue == secondValue) ||
415 (inputOperator ==
"!=" && firstValue != secondValue) ||
416 (inputOperator ==
"<=" && firstValue <= secondValue) ||
417 (inputOperator ==
">=" && firstValue >= secondValue) ||
418 (inputOperator ==
"<" && firstValue < secondValue) ||
419 (inputOperator ==
">" && firstValue > secondValue))
428 TEST(BlackboardTest, IssueSetBlackboard)
433 <root BTCPP_format="4" >
434 <BehaviorTree ID="MySubtree">
435 <ComparisonNode first="{value}" second="42" operator="==" />
438 <BehaviorTree ID="MainTree">
440 <SetBlackboard value="42" output_key="value" />
441 <SubTree ID="MySubtree" value="{value} "/>
452 ASSERT_EQ(42, tree.rootBlackboard()->get<
int>(
"value"));
461 TEST(BlackboardTest, SetBlackboard_Issue725)
466 <root BTCPP_format="4">
467 <BehaviorTree ID="MainTree">
468 <SetBlackboard value="{first_point}" output_key="other_point" />
475 auto& blackboard = tree.
subtrees.front()->blackboard;
477 const Point point = { 2, 7 };
478 blackboard->set(
"first_point", point);
480 const auto status = tree.tickOnce();
482 Point other_point = blackboard->get<
Point>(
"other_point");
485 ASSERT_EQ(other_point.
x, point.
x);
486 ASSERT_EQ(other_point.
y, point.
y);
489 TEST(BlackboardTest, NullOutputRemapping)
498 bb->set(
"my_input_port", 11);
511 <root BTCPP_format="4" >
512 <BehaviorTree ID="MySubtree">
514 <Script code=" important_value:= sub_value " />
515 <Script code=" my_value=false " />
516 <SaySomething message="{message}" />
519 <BehaviorTree ID="MainTree">
521 <Script code=" my_value:=true; another_value:='hi' " />
522 <SubTree ID="MySubtree" sub_value="true" message="{another_value}" _autoremap="true" />
534 std::vector<std::vector<std::string>> expected_keys;
535 for(
const auto& sub : tree.subtrees)
537 std::vector<std::string> keys;
538 for(
const auto& str_view : sub->blackboard->getKeys())
540 keys.push_back(std::string(str_view));
542 expected_keys.push_back(keys);
545 auto status = tree.tickWhileRunning();
550 ASSERT_EQ(bb_backup.size(), tree.subtrees.size());
553 for(
size_t i = 0; i < tree.subtrees.size(); i++)
555 const auto keys = tree.subtrees[i]->blackboard->getKeys();
556 ASSERT_EQ(expected_keys[i].
size(), keys.size());
557 for(
size_t a = 0; a < keys.size(); a++)
559 ASSERT_EQ(expected_keys[i][a], keys[a]);
562 status = tree.tickWhileRunning();
566 TEST(BlackboardTest, RootBlackboard)
571 <root BTCPP_format="4" >
572 <BehaviorTree ID="SubA">
574 <SubTree ID="SubB" />
575 <Script code=" @var3:=3 " />
579 <BehaviorTree ID="SubB">
581 <SaySomething message="{@msg}" />
582 <Script code=" @var4:=4 " />
586 <BehaviorTree ID="Sub_Issue823">
587 <BB_TestNode in_port="2" out_port="{@var5}" />
590 <BehaviorTree ID="MainTree">
592 <Script code=" msg:='hello' " />
593 <SubTree ID="SubA" />
595 <Script code="@var5:=0" />
596 <SubTree ID="Sub_Issue823" />
598 <Script code=" var1:=1 " />
599 <Script code=" @var2:=2 " />
612 ASSERT_EQ(1, tree.rootBlackboard()->get<
int>(
"var1"));
613 ASSERT_EQ(2, tree.rootBlackboard()->get<
int>(
"var2"));
614 ASSERT_EQ(3, tree.rootBlackboard()->get<
int>(
"var3"));
615 ASSERT_EQ(4, tree.rootBlackboard()->get<
int>(
"var4"));
616 ASSERT_EQ(4, tree.rootBlackboard()->get<
int>(
"var5"));
619 TEST(BlackboardTest, TimestampedInterface)
625 ASSERT_FALSE(bb->getStamped<
int>(
"value"));
626 ASSERT_FALSE(bb->getStamped(
"value", value));
628 auto nsec_before = std::chrono::steady_clock::now().time_since_epoch().count();
629 bb->set(
"value", 42);
630 auto result = bb->getStamped<
int>(
"value");
631 auto stamp_opt = bb->getStamped<
int>(
"value", value);
633 ASSERT_EQ(result->value, 42);
634 ASSERT_EQ(result->stamp.seq, 1);
635 ASSERT_GE(result->stamp.time.count(), nsec_before);
637 ASSERT_EQ(value, 42);
638 ASSERT_TRUE(stamp_opt);
639 ASSERT_EQ(stamp_opt->seq, 1);
640 ASSERT_GE(stamp_opt->time.count(), nsec_before);
643 nsec_before = std::chrono::steady_clock::now().time_since_epoch().count();
644 bb->set(
"value", 69);
645 result = bb->getStamped<
int>(
"value");
646 stamp_opt = bb->getStamped<
int>(
"value", value);
648 ASSERT_EQ(result->value, 69);
649 ASSERT_EQ(result->stamp.seq, 2);
650 ASSERT_GE(result->stamp.time.count(), nsec_before);
652 ASSERT_EQ(value, 69);
653 ASSERT_TRUE(stamp_opt);
654 ASSERT_EQ(stamp_opt->seq, 2);
655 ASSERT_GE(stamp_opt->time.count(), nsec_before);