Skip to content

Commit 6c9929c

Browse files
committed
fixes and checks in default values, based on PR #773
1 parent 21ab495 commit 6c9929c

File tree

4 files changed

+96
-8
lines changed

4 files changed

+96
-8
lines changed

include/behaviortree_cpp/actions/script_node.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class ScriptNode : public SyncActionNode
3131

3232
static PortsList providedPorts()
3333
{
34-
return {InputPort("code", "Piece of code that can be parsed")};
34+
return {InputPort<std::string>("code", "Piece of code that can be parsed")};
3535
}
3636

3737
private:

include/behaviortree_cpp/basic_types.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ using StringView = std::string_view;
6161
// vector of key/value pairs
6262
using KeyValueVector = std::vector<std::pair<std::string, std::string>>;
6363

64+
65+
struct AnyTypeAllowed
66+
{};
67+
68+
6469
/**
6570
* convertFromString is used to convert a string into a custom type.
6671
*
@@ -142,6 +147,11 @@ inline StringConverter GetAnyFromStringFunctor()
142147
{
143148
return [](StringView str) { return Any(str); };
144149
}
150+
else if constexpr(std::is_same_v<BT::AnyTypeAllowed, T> ||
151+
std::is_enum_v<T>)
152+
{
153+
return {};
154+
}
145155
else {
146156
return [](StringView str) { return Any(convertFromString<T>(str)); };
147157
}
@@ -265,9 +275,6 @@ using Result = Expected<std::monostate>;
265275
[[nodiscard]]
266276
bool IsAllowedPortName(StringView str);
267277

268-
struct AnyTypeAllowed
269-
{};
270-
271278
class TypeInfo
272279
{
273280
public:

src/xml_parsing.cpp

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,7 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element,
636636

637637
const TreeNodeManifest* manifest = nullptr;
638638

639-
auto manifest_it = factory.manifests().find(type_ID);
639+
auto manifest_it = factory.manifests().find(type_ID);
640640
if(manifest_it != factory.manifests().end())
641641
{
642642
manifest = &manifest_it->second;
@@ -647,8 +647,40 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element,
647647
{
648648
if (IsAllowedPortName(att->Name()))
649649
{
650-
const std::string attribute_name = att->Name();
651-
port_remap[attribute_name] = att->Value();
650+
const std::string port_name = att->Name();
651+
const std::string port_value = att->Value();
652+
653+
if(manifest)
654+
{
655+
auto port_model_it = manifest->ports.find(port_name);
656+
if(port_model_it == manifest->ports.end())
657+
{
658+
throw RuntimeError(StrCat("a port with name [", port_name,
659+
"] is found in the XML, but not in the providedPorts()"));
660+
}
661+
else {
662+
const auto& port_model = port_model_it->second;
663+
bool is_blacbkboard = port_value.size() >= 3 &&
664+
port_value.front() == '{' &&
665+
port_value.back() == '}';
666+
// let's test already if conversion is possible
667+
if(!is_blacbkboard && port_model.converter() && port_model.isStronglyTyped())
668+
{
669+
// This may throw
670+
try {
671+
port_model.converter()(port_value);
672+
}
673+
catch(std::exception& ex)
674+
{
675+
auto msg = StrCat("The port with name \"", port_name, "\" and value \"", port_value,
676+
"\" can not be converted to ", port_model.typeName());
677+
throw LogicError(msg);
678+
}
679+
}
680+
}
681+
}
682+
683+
port_remap[port_name] = port_value;
652684
}
653685
}
654686

tests/gtest_ports.cpp

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,8 +533,32 @@ TEST(PortTest, DefaultInputStrings)
533533
ASSERT_EQ(status, NodeStatus::SUCCESS);
534534
}
535535

536+
struct TestStruct
537+
{
538+
int a;
539+
double b;
540+
std::string c;
541+
};
536542

537-
TEST(PortTest, Default_Issues_767_768)
543+
class NodeWithDefaultNullptr : public SyncActionNode
544+
{
545+
public:
546+
NodeWithDefaultNullptr(const std::string& name, const NodeConfig& config) :
547+
SyncActionNode(name, config) {}
548+
549+
NodeStatus tick() override
550+
{
551+
return NodeStatus::SUCCESS;
552+
}
553+
554+
static PortsList providedPorts()
555+
{
556+
return {BT::InputPort< std::shared_ptr<TestStruct> >("input", nullptr, "default value is nullptr")};
557+
}
558+
};
559+
560+
561+
TEST(PortTest, Default_Issues_767)
538562
{
539563
using namespace BT;
540564

@@ -545,4 +569,29 @@ TEST(PortTest, Default_Issues_767_768)
545569
ASSERT_NO_THROW(auto p = InputPort<std::shared_ptr<std::string>>("ptr_B", nullptr, "default nullptr"));
546570
}
547571

572+
TEST(PortTest, DefaultWronglyOverriden)
573+
{
574+
BT::BehaviorTreeFactory factory;
575+
factory.registerNodeType<NodeWithDefaultNullptr>("NodeWithDefaultNullptr");
576+
577+
std::string xml_txt_wrong = R"(
578+
<root BTCPP_format="4" >
579+
<BehaviorTree>
580+
<NodeWithDefaultNullptr input=""/>
581+
</BehaviorTree>
582+
</root>)";
583+
584+
std::string xml_txt_correct = R"(
585+
<root BTCPP_format="4" >
586+
<BehaviorTree>
587+
<NodeWithDefaultNullptr/>
588+
</BehaviorTree>
589+
</root>)";
548590

591+
// this should throw, because we are NOT using the default,
592+
// but overriding it with an empty string instead.
593+
// See issue 768 for reference
594+
ASSERT_ANY_THROW( auto tree = factory.createTreeFromText(xml_txt_wrong));
595+
// This is correct
596+
ASSERT_NO_THROW( auto tree = factory.createTreeFromText(xml_txt_correct));
597+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy