diff --git a/src/xml_parsing.cpp b/src/xml_parsing.cpp
index 4c9a57b1c..02ee7fb3f 100644
--- a/src/xml_parsing.cpp
+++ b/src/xml_parsing.cpp
@@ -679,10 +679,11 @@ void VerifyXML(const std::string& xml_text,
std::string("Unknown node type: ") + child_name);
}
const auto child_type = child_search->second;
+ // Only the asynchronous CONTROL nodes can be detected here: the
+ // manifest does not record whether an ACTION is asynchronous, so
+ // async leaf actions are not caught.
if(child_type == NodeType::CONTROL &&
- ((child_name == "ThreadedAction") ||
- (child_name == "StatefulActionNode") ||
- (child_name == "CoroActionNode") || (child_name == "AsyncSequence")))
+ ((child_name == "AsyncSequence") || (child_name == "AsyncFallback")))
{
++async_count;
if(async_count > 1)
diff --git a/tests/gtest_reactive.cpp b/tests/gtest_reactive.cpp
index 55c9176de..c38ef11c7 100644
--- a/tests/gtest_reactive.cpp
+++ b/tests/gtest_reactive.cpp
@@ -187,6 +187,83 @@ TEST(Reactive, TwoAsyncNodesInReactiveSequence)
EXPECT_ANY_THROW(auto tree = factory.createTreeFromText(reactive_xml_text));
}
+TEST(Reactive, TwoAsyncFallbacksInReactiveSequence)
+{
+ static const char* reactive_xml_text = R"(
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+)";
+
+ BT::BehaviorTreeFactory factory;
+ std::array counters{};
+ RegisterTestTick(factory, "Test", counters);
+
+ EXPECT_ANY_THROW(auto tree = factory.createTreeFromText(reactive_xml_text));
+}
+
+TEST(Reactive, AsyncSequenceAndAsyncFallbackInReactiveSequence)
+{
+ static const char* reactive_xml_text = R"(
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+)";
+
+ BT::BehaviorTreeFactory factory;
+ std::array counters{};
+ RegisterTestTick(factory, "Test", counters);
+
+ EXPECT_ANY_THROW(auto tree = factory.createTreeFromText(reactive_xml_text));
+}
+
+TEST(Reactive, SingleAsyncChildInReactiveSequenceIsAllowed)
+{
+ static const char* reactive_xml_text = R"(
+
+
+
+
+
+
+
+
+
+
+
+)";
+
+ BT::BehaviorTreeFactory factory;
+ std::array counters{};
+ RegisterTestTick(factory, "Test", counters);
+
+ EXPECT_NO_THROW(auto tree = factory.createTreeFromText(reactive_xml_text));
+}
+
// ============ Phase 4: Additional Reactive Tests ============
TEST(Reactive, ReactiveSequence_FirstChildFails)