@@ -107,6 +107,111 @@ TEST(PreconditionsDecorator, StringEquals)
107107 ASSERT_EQ (counters[1 ], 1 );
108108}
109109
110+ class KeepRunning : public BT ::StatefulActionNode
111+ {
112+ public:
113+ KeepRunning (const std::string& name, const BT::NodeConfig& config)
114+ : BT::StatefulActionNode(name, config)
115+ {}
116+
117+ static BT::PortsList providedPorts ()
118+ {
119+ return {};
120+ }
121+
122+ BT::NodeStatus onStart () override
123+ {
124+ return BT::NodeStatus::RUNNING;
125+ }
126+
127+ BT::NodeStatus onRunning () override
128+ {
129+ return BT::NodeStatus::RUNNING;
130+ }
131+
132+ void onHalted () override
133+ {
134+ std::cout << " Node halted\n " ;
135+ }
136+ };
137+
138+ TEST (PreconditionsDecorator, ChecksConditionOnce)
139+ {
140+ BehaviorTreeFactory factory;
141+ factory.registerNodeType <KeepRunning>(" KeepRunning" );
142+
143+ const std::string xml_text = R"(
144+
145+ <root BTCPP_format="4" >
146+ <BehaviorTree ID="MainTree">
147+ <Sequence>
148+ <Script code = "A:=0" />
149+ <Script code = "B:=0" />
150+ <Precondition if=" A==0 " else="FAILURE">
151+ <KeepRunning _while="B==0" />
152+ </Precondition>
153+ </Sequence>
154+ </BehaviorTree>
155+ </root>)" ;
156+
157+ auto tree = factory.createTreeFromText (xml_text);
158+
159+ EXPECT_EQ (tree.tickOnce (), NodeStatus::RUNNING);
160+ // While the child is still running, attempt to fail the precondition.
161+ tree.rootBlackboard ()->set (" A" , 1 );
162+ EXPECT_EQ (tree.tickOnce (), NodeStatus::RUNNING);
163+ // Finish running the tree, the else condition should not be hit.
164+ tree.rootBlackboard ()->set (" B" , 1 );
165+ EXPECT_EQ (tree.tickOnce (), NodeStatus::SUCCESS);
166+ }
167+
168+ TEST (PreconditionsDecorator, CanRunChildrenMultipleTimes)
169+ {
170+ BehaviorTreeFactory factory;
171+ factory.registerNodeType <KeepRunning>(" KeepRunning" );
172+ std::array<int , 1 > counters;
173+ RegisterTestTick (factory, " Test" , counters);
174+
175+ const std::string xml_text = R"(
176+
177+ <root BTCPP_format="4" >
178+ <BehaviorTree ID="MainTree">
179+ <Sequence>
180+ <Script code = "A:=0" />
181+ <Script code = "B:=0" />
182+ <Script code = "C:=1" />
183+ <Repeat num_cycles="3">
184+ <Sequence>
185+ <Precondition if=" A==0 " else="SUCCESS">
186+ <TestA/>
187+ </Precondition>
188+ <KeepRunning _while="C==0" />
189+ <KeepRunning _while="B==0" />
190+ </Sequence>
191+ </Repeat>
192+ </Sequence>
193+ </BehaviorTree>
194+ </root>)" ;
195+
196+ auto tree = factory.createTreeFromText (xml_text);
197+
198+ EXPECT_EQ (tree.tickOnce (), NodeStatus::RUNNING);
199+ EXPECT_EQ (counters[0 ], 1 ); // Precondition hit once;
200+
201+ // In the second repeat, fail the precondition
202+ tree.rootBlackboard ()->set (" A" , 1 );
203+ tree.rootBlackboard ()->set (" B" , 1 );
204+ tree.rootBlackboard ()->set (" C" , 0 );
205+ EXPECT_EQ (tree.tickOnce (), NodeStatus::RUNNING);
206+ EXPECT_EQ (counters[0 ], 1 ); // Precondition still only hit once.
207+
208+ // Finally in the last repeat, hit the condition again.
209+ tree.rootBlackboard ()->set (" A" , 0 );
210+ tree.rootBlackboard ()->set (" C" , 1 );
211+ EXPECT_EQ (tree.tickOnce (), NodeStatus::SUCCESS);
212+ EXPECT_EQ (counters[0 ], 2 ); // Precondition hit twice now.
213+ }
214+
110215TEST (Preconditions, Basic)
111216{
112217 BehaviorTreeFactory factory;
@@ -246,34 +351,6 @@ TEST(Preconditions, Issue615_NoSkipWhenRunning_A)
246351 ASSERT_EQ (tree.tickOnce (), NodeStatus::RUNNING);
247352}
248353
249- class KeepRunning : public BT ::StatefulActionNode
250- {
251- public:
252- KeepRunning (const std::string& name, const BT::NodeConfig& config)
253- : BT::StatefulActionNode(name, config)
254- {}
255-
256- static BT::PortsList providedPorts ()
257- {
258- return {};
259- }
260-
261- BT::NodeStatus onStart () override
262- {
263- return BT::NodeStatus::RUNNING;
264- }
265-
266- BT::NodeStatus onRunning () override
267- {
268- return BT::NodeStatus::RUNNING;
269- }
270-
271- void onHalted () override
272- {
273- std::cout << " Node halted\n " ;
274- }
275- };
276-
277354TEST (Preconditions, Issue615_NoSkipWhenRunning_B)
278355{
279356 static constexpr auto xml_text = R"(
0 commit comments