Skip to content

Commit ab8a8de

Browse files
dv-picknikclaude
andauthored
Say that duplicate SubTree names are checked across the whole tree (fixes #1219) (#1222)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 68afedf commit ab8a8de

2 files changed

Lines changed: 45 additions & 3 deletions

File tree

‎src/xml_parsing.cpp‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,8 +1226,8 @@ void BT::XMLParser::PImpl::recursivelyCreateSubtree(
12261226
if(sub->instance_name == subtree_path)
12271227
{
12281228
throw RuntimeError("Duplicate SubTree path detected: '", subtree_path,
1229-
"'. Multiple SubTree nodes with the same 'name' attribute "
1230-
"under the same parent are not allowed. "
1229+
"'. SubTree nodes in the same tree cannot share a 'name' "
1230+
"attribute, even under different parent nodes. "
12311231
"Please use unique names or omit the 'name' attribute "
12321232
"to auto-generate unique paths.");
12331233
}

‎tests/gtest_subtree.cpp‎

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,7 @@ TEST(SubTree, SubstringTreeIDsAreNotRecursive)
815815
// Test for Groot2 issue #56: duplicate _fullpath when multiple subtrees have the same name
816816
// https://github.com/BehaviorTree/Groot2/issues/56
817817
//
818-
// When two SubTree nodes under the same parent have the same "name" attribute,
818+
// When two SubTree nodes in the same tree have the same "name" attribute,
819819
// tree creation should fail with a clear error message.
820820
TEST(SubTree, DuplicateSubTreeName_Groot2Issue56)
821821
{
@@ -879,6 +879,48 @@ TEST(SubTree, DuplicateSubTreeName_ErrorMessage)
879879
}
880880
}
881881

882+
// The duplicate check covers the whole tree, so the message must not suggest
883+
// that moving one SubTree under another parent fixes it.
884+
TEST(SubTree, DuplicateSubTreeName_DifferentParents)
885+
{
886+
// clang-format off
887+
static const char* xml_text = R"(
888+
<root BTCPP_format="4" main_tree_to_execute="MainTree">
889+
<BehaviorTree ID="MainTree">
890+
<Fallback>
891+
<Sequence>
892+
<SubTree ID="Task" name="my_task"/>
893+
</Sequence>
894+
<Sequence>
895+
<SubTree ID="Task" name="my_task"/>
896+
</Sequence>
897+
</Fallback>
898+
</BehaviorTree>
899+
900+
<BehaviorTree ID="Task">
901+
<AlwaysSuccess/>
902+
</BehaviorTree>
903+
</root>
904+
)";
905+
// clang-format on
906+
907+
BehaviorTreeFactory factory;
908+
909+
try
910+
{
911+
(void)factory.createTreeFromText(xml_text);
912+
FAIL() << "Expected RuntimeError to be thrown";
913+
}
914+
catch(const RuntimeError& e)
915+
{
916+
std::string msg = e.what();
917+
EXPECT_TRUE(msg.find("Duplicate SubTree path") != std::string::npos)
918+
<< "Error message should mention 'Duplicate SubTree path'. Got: " << msg;
919+
EXPECT_TRUE(msg.find("same parent") == std::string::npos)
920+
<< "Error message should not limit the rule to one parent. Got: " << msg;
921+
}
922+
}
923+
882924
// Test that unique names under the same parent work correctly
883925
TEST(SubTree, UniqueSubTreeNames_WorksCorrectly)
884926
{

0 commit comments

Comments
 (0)