@@ -109,6 +109,7 @@ TEST(BehaviorTreeFactory, XMLParsingOrder)
109
109
XMLParser parser (factory);
110
110
parser.loadFromText (xml_text_subtree);
111
111
auto trees = parser.registeredBehaviorTrees ();
112
+ ASSERT_EQ (trees.size (), 2 );
112
113
ASSERT_EQ (trees[0 ], " CrossDoorSubtree" );
113
114
ASSERT_EQ (trees[1 ], " MainTree" );
114
115
}
@@ -117,6 +118,7 @@ TEST(BehaviorTreeFactory, XMLParsingOrder)
117
118
parser.loadFromText (xml_text_subtree_part1);
118
119
parser.loadFromText (xml_text_subtree_part2);
119
120
auto trees = parser.registeredBehaviorTrees ();
121
+ ASSERT_EQ (trees.size (), 2 );
120
122
ASSERT_EQ (trees[0 ], " CrossDoorSubtree" );
121
123
ASSERT_EQ (trees[1 ], " MainTree" );
122
124
}
@@ -125,6 +127,7 @@ TEST(BehaviorTreeFactory, XMLParsingOrder)
125
127
parser.loadFromText (xml_text_subtree_part2);
126
128
parser.loadFromText (xml_text_subtree_part1);
127
129
auto trees = parser.registeredBehaviorTrees ();
130
+ ASSERT_EQ (trees.size (), 2 );
128
131
ASSERT_EQ (trees[0 ], " CrossDoorSubtree" );
129
132
ASSERT_EQ (trees[1 ], " MainTree" );
130
133
}
@@ -217,7 +220,12 @@ TEST(BehaviorTreeFactory, Issue7)
217
220
BehaviorTreeFactory factory;
218
221
XMLParser parser (factory);
219
222
223
+ // We expect that an incorrectly-constructed behavior tree will fail to load
220
224
EXPECT_THROW (parser.loadFromText (xml_text_issue), RuntimeError);
225
+
226
+ // We expect that no behavior trees will be registered after we unsuccessfully attempt to load a single tree
227
+ auto trees = parser.registeredBehaviorTrees ();
228
+ EXPECT_TRUE ( trees.empty () );
221
229
}
222
230
223
231
// clang-format off
@@ -408,6 +416,87 @@ TEST(BehaviorTreeFactory, DecoratorWithTwoChildrenThrows)
408
416
ASSERT_THROW (factory.createTreeFromText (xml_text), BehaviorTreeException);
409
417
}
410
418
419
+
420
+ TEST (BehaviorTreeFactory, RegisterValidAndInvalidTrees)
421
+ {
422
+ const std::string xml_text_ok = R"(
423
+ <root>
424
+ <BehaviorTree ID="ValidTree">
425
+ <Sequence name="door_open_sequence">
426
+ <Action ID="AlwaysSuccess" />
427
+ </Sequence>
428
+ </BehaviorTree>
429
+ </root> )" ;
430
+
431
+ const std::string xml_text_invalid = R"(
432
+ <root>
433
+ <BehaviorTree ID="InvalidTreeWithNoChildren">
434
+ </BehaviorTree>
435
+ </root> )" ;
436
+
437
+ BehaviorTreeFactory factory;
438
+ XMLParser parser (factory);
439
+
440
+ // GIVEN that a valid tree has been loaded
441
+ ASSERT_NO_THROW (parser.loadFromText (xml_text_ok));
442
+
443
+ // WHEN we attempt to load an invalid tree
444
+ ASSERT_THROW (parser.loadFromText (xml_text_invalid), RuntimeError);
445
+
446
+ // THEN the valid tree is still registered
447
+ auto trees = parser.registeredBehaviorTrees ();
448
+ ASSERT_EQ (trees.size (), 1 );
449
+ EXPECT_EQ (trees[0 ], " ValidTree" );
450
+ }
451
+
452
+ TEST (BehaviorTreeFactory, RegisterInvalidXMLBadActionNodeThrows)
453
+ {
454
+ // GIVEN an invalid tree
455
+ // This tree contains invalid XML because the action node is missing a trailing `/`.
456
+ // A valid line would read: <Action ID="AlwaysSuccess" />
457
+ const std::string xml_text_invalid = R"(
458
+ <root>
459
+ <BehaviorTree ID="InvalidTreeWithBadChild">
460
+ <Sequence name="seq">
461
+ <Action ID="AlwaysSuccess" >
462
+ </Sequence>
463
+ </BehaviorTree>
464
+ </root> )" ;
465
+
466
+ BehaviorTreeFactory factory;
467
+ XMLParser parser (factory);
468
+
469
+ // WHEN we attempt to load an invalid tree
470
+ // THEN a RuntimeError exception is thrown
471
+ EXPECT_THROW (parser.loadFromText (xml_text_invalid), RuntimeError);
472
+
473
+ // THEN no tree is registered
474
+ auto trees = parser.registeredBehaviorTrees ();
475
+ EXPECT_TRUE (trees.empty ());
476
+ }
477
+
478
+ TEST (BehaviorTreeFactory, RegisterInvalidXMLNoRootThrows)
479
+ {
480
+ // GIVEN an invalid tree
481
+ // This tree contains invalid XML because it does not have a root node
482
+ const std::string xml_text_invalid = R"(
483
+ <BehaviorTree ID="InvalidTreeNoRoot">
484
+ <Sequence name="seq">
485
+ <Action ID="AlwaysSuccess" />
486
+ </Sequence>
487
+ </BehaviorTree> )" ;
488
+
489
+ BehaviorTreeFactory factory;
490
+ XMLParser parser (factory);
491
+
492
+ // WHEN we attempt to load an invalid tree
493
+ // THEN a RuntimeError exception is thrown
494
+ EXPECT_THROW (parser.loadFromText (xml_text_invalid), RuntimeError);
495
+
496
+ // THEN no tree is registered
497
+ auto trees = parser.registeredBehaviorTrees ();
498
+ EXPECT_TRUE (trees.empty ());
499
+
411
500
TEST (BehaviorTreeFactory, ParserClearRegisteredBehaviorTrees)
412
501
{
413
502
const std::string tree_xml = R"(
0 commit comments