Skip to content

Commit a4b115a

Browse files
authored
Fixed bug where including relative paths would fail to find the correct file (#358)
* Added unit tests to verify current behavior * Fixed bug where including relative paths would fail to find the correct file * Added gtest environment to access executable path This path lets tests access files relative to the executable for better transportability * Changed file commandto add_custom_target The file command only copies during the cmake configure step. If source files change, file is not ran again
1 parent 284b1b7 commit a4b115a

15 files changed

+188
-0
lines changed

src/xml_parsing.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,16 @@ void XMLParser::Pimpl::loadDocImpl(BT_TinyXML2::XMLDocument* doc, bool add_inclu
187187

188188
opened_documents.emplace_back(new BT_TinyXML2::XMLDocument());
189189
BT_TinyXML2::XMLDocument* next_doc = opened_documents.back().get();
190+
191+
// change current path to the included file for handling additional relative paths
192+
const filesystem::path previous_path = current_path;
193+
current_path = file_path.parent_path().make_absolute();
194+
190195
next_doc->LoadFile(file_path.str().c_str());
191196
loadDocImpl(next_doc, add_includes);
197+
198+
// reset current path to the previous value
199+
current_path = previous_path;
192200
}
193201

194202
for (auto bt_node = xml_root->FirstChildElement("BehaviorTree");

tests/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ elseif(BUILD_UNIT_TESTS)
5858
bt_sample_nodes gtest gtest_main)
5959
target_include_directories(${BEHAVIOR_TREE_LIBRARY}_test PRIVATE gtest/include ${GTEST_INCLUDE_DIRS})
6060

61+
add_custom_command(TARGET ${BEHAVIOR_TREE_LIBRARY}_test POST_BUILD
62+
COMMAND ${CMAKE_COMMAND} -E copy_directory
63+
${CMAKE_SOURCE_DIR}/tests/trees
64+
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/trees)
65+
6166
add_test(BehaviorTreeCoreTest ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${BEHAVIOR_TREE_LIBRARY}_test)
6267

6368
endif()

tests/gtest_factory.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "action_test_node.h"
33
#include "condition_test_node.h"
44
#include "behaviortree_cpp_v3/xml_parsing.h"
5+
#include "environment.h"
56
#include "../sample_nodes/crossdoor_nodes.h"
67
#include "../sample_nodes/dummy_nodes.h"
78

@@ -303,4 +304,58 @@ TEST(BehaviorTreeFactory, SubTreeWithRemapping)
303304
ASSERT_FALSE( talk_bb->getAny("talk_out") );
304305
}
305306

307+
#if !defined(USING_ROS) && !defined(USING_ROS2)
308+
TEST(BehaviorTreeFactory, CreateTreeFromFile)
309+
{
310+
BehaviorTreeFactory factory;
311+
312+
// should not throw
313+
Tree tree = factory.createTreeFromFile((environment->executable_path.parent_path() / "trees/parent_no_include.xml").str());
314+
ASSERT_EQ(NodeStatus::SUCCESS, tree.tickRoot());
315+
}
316+
317+
TEST(BehaviorTreeFactory, CreateTreeFromFileWhichIncludesFileFromSameDirectory)
318+
{
319+
BehaviorTreeFactory factory;
320+
321+
// should not throw
322+
Tree tree = factory.createTreeFromFile((environment->executable_path.parent_path() / "trees/child/child_include_sibling.xml").str());
323+
ASSERT_EQ(NodeStatus::SUCCESS, tree.tickRoot());
324+
}
325+
326+
TEST(BehaviorTreeFactory, CreateTreeFromFileWhichIncludesFileFromChildDirectory)
327+
{
328+
BehaviorTreeFactory factory;
329+
330+
// should not throw
331+
Tree tree = factory.createTreeFromFile((environment->executable_path.parent_path() / "trees/parent_include_child.xml").str());
332+
ASSERT_EQ(NodeStatus::SUCCESS, tree.tickRoot());
333+
}
306334

335+
TEST(BehaviorTreeFactory, CreateTreeFromFileWhichIncludesFileFromChildDirectoryWhichIncludesFileFromSameDirectory)
336+
{
337+
BehaviorTreeFactory factory;
338+
339+
// should not throw
340+
Tree tree = factory.createTreeFromFile((environment->executable_path.parent_path() / "trees/parent_include_child_include_sibling.xml").str());
341+
ASSERT_EQ(NodeStatus::SUCCESS, tree.tickRoot());
342+
}
343+
344+
TEST(BehaviorTreeFactory, CreateTreeFromFileWhichIncludesFileFromChildDirectoryWhichIncludesFileFromChildDirectory)
345+
{
346+
BehaviorTreeFactory factory;
347+
348+
// should not throw
349+
Tree tree = factory.createTreeFromFile((environment->executable_path.parent_path() / "trees/parent_include_child_include_child.xml").str());
350+
ASSERT_EQ(NodeStatus::SUCCESS, tree.tickRoot());
351+
}
352+
353+
TEST(BehaviorTreeFactory, CreateTreeFromFileWhichIncludesFileFromChildDirectoryWhichIncludesFileFromParentDirectory)
354+
{
355+
BehaviorTreeFactory factory;
356+
357+
// should not throw
358+
Tree tree = factory.createTreeFromFile((environment->executable_path.parent_path() / "trees/parent_include_child_include_parent.xml").str());
359+
ASSERT_EQ(NodeStatus::SUCCESS, tree.tickRoot());
360+
}
361+
#endif

tests/gtest_tree.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "action_test_node.h"
1515
#include "condition_test_node.h"
1616
#include "behaviortree_cpp_v3/behavior_tree.h"
17+
#include "environment.h"
1718

1819
#include <sstream>
1920
#include <string>
@@ -118,8 +119,16 @@ TEST_F(BehaviorTreeTest, PrintWithStream)
118119
ASSERT_TRUE(std::getline(stream, line, '\n').fail());
119120
}
120121

122+
// define extern variable from environment.h
123+
Environment* environment;
124+
121125
int main(int argc, char** argv)
122126
{
123127
testing::InitGoogleTest(&argc, argv);
128+
129+
// gtest will take ownership of this pointer and free it for us
130+
environment = new Environment(argc, argv);
131+
testing::AddGlobalTestEnvironment(environment);
132+
124133
return RUN_ALL_TESTS();
125134
}

tests/include/environment.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#ifndef ENVIRONMENT_H
2+
#define ENVIRONMENT_H
3+
4+
#include <gtest/gtest.h>
5+
6+
#include "filesystem/path.h"
7+
8+
class Environment : public testing::Environment
9+
{
10+
public:
11+
Environment(int argc, char** argv)
12+
{
13+
if (argc >= 1)
14+
{
15+
executable_path = filesystem::path(argv[0]).make_absolute();
16+
}
17+
}
18+
19+
// the absolute path to the test executable
20+
filesystem::path executable_path;
21+
};
22+
23+
// for accessing the environment within a test
24+
extern Environment* environment;
25+
26+
#endif
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<root main_tree_to_execute = "ChildChildNoInclude">
2+
<BehaviorTree ID="ChildChildNoInclude">
3+
<AlwaysSuccess />
4+
</BehaviorTree>
5+
</root>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<root main_tree_to_execute = "ChildIncludeChild">
2+
<include path="child/child_child_no_include.xml" />
3+
4+
<BehaviorTree ID="ChildIncludeChild">
5+
<Sequence>
6+
<SubTree ID="ChildChildNoInclude" />
7+
<AlwaysSuccess />
8+
</Sequence>
9+
</BehaviorTree>
10+
</root>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<root main_tree_to_execute = "ChildIncludeParent">
2+
<include path="../parent_no_include.xml" />
3+
4+
<BehaviorTree ID="ChildIncludeParent">
5+
<Sequence>
6+
<SubTree ID="ParentNoInclude" />
7+
<AlwaysSuccess />
8+
</Sequence>
9+
</BehaviorTree>
10+
</root>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<root main_tree_to_execute = "ChildIncludeSibling">
2+
<include path="child_no_include.xml" />
3+
4+
<BehaviorTree ID="ChildIncludeSibling">
5+
<Sequence>
6+
<SubTree ID="ChildNoInclude" />
7+
<AlwaysSuccess />
8+
</Sequence>
9+
</BehaviorTree>
10+
</root>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<root main_tree_to_execute = "ChildNoInclude">
2+
<BehaviorTree ID="ChildNoInclude">
3+
<AlwaysSuccess />
4+
</BehaviorTree>
5+
</root>

0 commit comments

Comments
 (0)