1 #include <gtest/gtest.h>
15 std::cout <<
"ctor" << std::endl;
22 if(!getInput(
"in_port_A", val_A))
26 if(!getInput(
"in_port_B", val_B))
31 if(val_A == 42 && val_B == 66)
40 return { BT::InputPort<int>(
"in_port_A", 42,
"magic_number"),
41 BT::InputPort<int>(
"in_port_B") };
45 TEST(PortTest, WrongNodeConfig)
52 ASSERT_ANY_THROW(node.
tick());
55 TEST(PortTest, DefaultPorts)
57 std::string xml_txt = R
"(
58 <root BTCPP_format="4" >
59 <BehaviorTree ID="MainTree">
60 <NodeWithPorts in_port_B="66" />
71 TEST(PortTest, MissingPort)
73 std::string xml_txt = R
"(
74 <root BTCPP_format="4" >
75 <BehaviorTree ID="MainTree">
83 ASSERT_ANY_THROW(tree.tickWhileRunning());
88 std::string xml_txt = R
"(
89 <root BTCPP_format="4" >
90 <BehaviorTree ID="MainTree">
91 <NodeWithPorts da_port="66" />
103 std::string xml_txt = R
"(
104 <root BTCPP_format="4" >
105 <BehaviorTree ID="MainTree" _description="this is my tree" >
107 <NodeWithPorts name="first" in_port_B="66" _description="this is my action" />
108 <SubTree ID="mySubTree" name="second" _description="this is a subtree"/>
112 <BehaviorTree ID="mySubTree" _description="this is a subtree" >
113 <NodeWithPorts name="third" in_port_B="99" />
127 status = tree.tickWhileRunning();
135 std::string xml_txt =
137 <root BTCPP_format="4" >
138 <BehaviorTree ID="MainTree">
139 <Action ID="NodeWithPorts" name="NodeWithPortsName" in_port_B="66" _not_da_port="whateva" _skipIf="true" />
148 const TreeNode* root = tree.rootNode();
149 ASSERT_NE(root,
nullptr);
173 if(getInput(
"int_port", val_A) && getInput(
"any_port", val_B))
182 return { BT::InputPort<int>(
"int_port"), BT::InputPort<MyType>(
"any_port") };
200 return { BT::OutputPort<int>(
"int_port"), BT::OutputPort<MyType>(
"any_port") };
204 TEST(PortTest, EmptyPort)
206 std::string xml_txt = R
"(
207 <root BTCPP_format="4" >
208 <BehaviorTree ID="MainTree">
210 <NodeInPorts int_port="{ip}" any_port="{ap}" />
211 <NodeOutPorts int_port="{ip}" any_port="{ap}" />
241 return { BT::InputPort<std::string>(
"name") };
255 std::vector<double>* states)
261 getInput(
"states", *states_);
267 return { BT::InputPort<std::vector<double>>(
"states") };
271 std::vector<double>* states_;
274 TEST(PortTest, SubtreeStringInput_Issue489)
276 std::string xml_txt = R
"(
277 <root BTCPP_format="4" >
278 <BehaviorTree ID="Main">
279 <SubTree ID="Subtree_A" states="3;7"/>
282 <BehaviorTree ID="Subtree_A">
283 <ActionVectorDoubleIn states="{states}"/>
287 std::vector<double> states;
298 ASSERT_EQ(2, states.size());
299 ASSERT_EQ(3, states[0]);
300 ASSERT_EQ(7, states[1]);
307 std::vector<std::string>* states)
313 getInput(
"states", *states_);
319 return { BT::InputPort<std::vector<std::string>>(
"states") };
323 std::vector<std::string>* states_;
326 TEST(PortTest, SubtreeStringInput_StringVector)
328 std::string xml_txt = R
"(
329 <root BTCPP_format="4" >
330 <BehaviorTree ID="Main">
331 <ActionVectorStringIn states="hello;world;with spaces"/>
335 std::vector<std::string> states;
346 ASSERT_EQ(3, states.size());
347 ASSERT_EQ(
"hello", states[0]);
348 ASSERT_EQ(
"world", states[1]);
349 ASSERT_EQ(
"with spaces", states[2]);
358 return x == other.
x && y == other.
y;
362 return !(*
this == other);
371 str.remove_prefix(5);
372 return convertFromJSON<Point2D>(str);
375 if(parts.size() != 2)
379 int x = convertFromString<int>(parts[0]);
380 int y = convertFromString<int>(parts[1]);
385 [[nodiscard]] std::string BT::toStr<Point2D>(
const Point2D& point)
392 add_field(
"x", &point.x);
393 add_field(
"y", &point.y);
405 const int answer = getInput<int>(
"answer").value();
411 const std::string greet = getInput<std::string>(
"greeting").value();
417 const Point2D point = getInput<Point2D>(
"pos").value();
418 if(point.
x != 1 || point.
y != 2)
428 return { BT::InputPort<int>(
"answer", 42,
"the answer"),
429 BT::InputPort<std::string>(
"greeting",
"hello",
"be polite"),
430 BT::InputPort<Point2D>(
"pos",
Point2D{ 1, 2 },
"where") };
434 TEST(PortTest, DefaultInput)
436 std::string xml_txt = R
"(
437 <root BTCPP_format="4" >
446 auto status = tree.tickOnce();
459 auto res_str = getInput<std::string>(
"val_str");
461 auto res_int = getInput<BT::Any>(
"val_int");
464 auto res_real_A = getInput<double>(
"val_real");
466 auto res_real_B = getInput<BT::Any>(
"val_real");
468 bool expected = res_str.value() ==
"hello" && res_int->cast<
int>() == 42 &&
469 res_real_A.value() == 3.14 && res_real_B->cast<
double>() == 3.14;
476 return { BT::InputPort<BT::Any>(
"val_str"), BT::InputPort<BT::Any>(
"val_int"),
477 BT::InputPort<double>(
"val_real") };
490 setOutput(
"val_str",
BT::Any(1.0));
491 setOutput(
"val_str",
BT::Any(1));
492 setOutput(
"val_str",
BT::Any(
"hello"));
494 setOutput(
"val_int", 42);
495 setOutput(
"val_real", 3.14);
501 return { BT::OutputPort<BT::Any>(
"val_str"), BT::OutputPort<int>(
"val_int"),
502 BT::OutputPort<BT::Any>(
"val_real") };
506 TEST(PortTest, AnyPort)
508 std::string xml_txt = R
"(
509 <root BTCPP_format="4" >
512 <SetAny val_str="{val_str}" val_int="{val_int}" val_real="{val_real}"/>
513 <GetAny val_str="{val_str}" val_int="{val_int}" val_real="{val_real}"/>
522 auto status = tree.tickOnce();
535 Point2D pointA, pointB, pointC, pointD, pointE, input;
537 if(!getInput(
"pointA", pointA) || pointA !=
Point2D{ 1, 2 })
539 throw std::runtime_error(
"failed pointA");
541 if(!getInput(
"pointB", pointB) || pointB !=
Point2D{ 3, 4 })
543 throw std::runtime_error(
"failed pointB");
545 if(!getInput(
"pointC", pointC) || pointC !=
Point2D{ 5, 6 })
547 throw std::runtime_error(
"failed pointC");
549 if(!getInput(
"pointD", pointD) || pointD !=
Point2D{ 7, 8 })
551 throw std::runtime_error(
"failed pointD");
553 if(!getInput(
"pointE", pointE) || pointE !=
Point2D{ 9, 10 })
555 throw std::runtime_error(
"failed pointE");
557 if(!getInput(
"input", input) || input !=
Point2D{ -1, -2 })
559 throw std::runtime_error(
"failed input");
566 return { BT::InputPort<Point2D>(
"input",
"no default value"),
567 BT::InputPort<Point2D>(
"pointA",
Point2D{ 1, 2 },
"default value is [1,2]"),
568 BT::InputPort<Point2D>(
"pointB",
"{point}",
569 "default value inside blackboard {point}"),
570 BT::InputPort<Point2D>(
"pointC",
"5,6",
"default value is [5,6]"),
571 BT::InputPort<Point2D>(
"pointD",
"{=}",
572 "default value inside blackboard {pointD}"),
573 BT::InputPort<Point2D>(
"pointE", R
"(json:{"x":9,"y":10})",
574 "default value is [9,10]") };
578 TEST(PortTest, DefaultInputPoint2D)
580 std::string xml_txt = R
"(
581 <root BTCPP_format="4" >
583 <NodeWithDefaultPoints input="-1,-2"/>
591 auto tree = factory.createTreeFromText(xml_txt);
593 tree.subtrees.front()->blackboard->set<
Point2D>(
"point",
Point2D{ 3, 4 });
594 tree.subtrees.front()->blackboard->set<
Point2D>(
"pointD",
Point2D{ 7, 8 });
597 ASSERT_NO_THROW(status = tree.tickOnce());
612 std::string input, msgA, msgB, msgC;
613 if(!getInput(
"input", input) || input !=
"from XML")
615 throw std::runtime_error(
"failed input");
617 if(!getInput(
"msgA", msgA) || msgA !=
"hello")
619 throw std::runtime_error(
"failed msgA");
621 if(!getInput(
"msgB", msgB) || msgB !=
"ciao")
623 throw std::runtime_error(
"failed msgB");
625 if(!getInput(
"msgC", msgC) || msgC !=
"hola")
627 throw std::runtime_error(
"failed msgC");
634 return { BT::InputPort<std::string>(
"input",
"no default"),
635 BT::InputPort<std::string>(
"msgA",
"hello",
"default value is 'hello'"),
636 BT::InputPort<std::string>(
"msgB",
"{msg}",
637 "default value inside blackboard {msg}"),
638 BT::InputPort<std::string>(
"msgC",
"{=}",
639 "default value inside blackboard {msgC}") };
643 TEST(PortTest, DefaultInputStrings)
645 std::string xml_txt = R
"(
646 <root BTCPP_format="4" >
648 <NodeWithDefaultStrings input="from XML"/>
656 tree.subtrees.front()->blackboard->set<std::string>(
"msg",
"ciao");
657 tree.subtrees.front()->blackboard->set<std::string>(
"msgC",
"hola");
660 ASSERT_NO_THROW(status = tree.tickOnce());
687 return { BT::InputPort<std::shared_ptr<TestStruct>>(
"input",
nullptr,
688 "default value is nullptr") };
692 TEST(PortTest, Default_Issues_767)
702 auto p =
InputPort<std::shared_ptr<Point2D>>(
"ptr_A",
nullptr,
"default nullptr"));
703 ASSERT_NO_THROW(
auto p =
InputPort<std::shared_ptr<std::string>>(
"ptr_B",
nullptr,
707 TEST(PortTest, DefaultWronglyOverriden)
712 std::string xml_txt_wrong = R
"(
713 <root BTCPP_format="4" >
715 <NodeWithDefaultNullptr input=""/>
719 std::string xml_txt_correct = R"(
720 <root BTCPP_format="4" >
722 <NodeWithDefaultNullptr/>