test: cover testBehavior
This commit is contained in:
1 parent
a53c700c17
commit
8103be3f96
1 file changed
+157
@@ -156,3 +156,160 @@ VF_TEST(aRunningNodeResumesNextTickInsteadOfRestartingTheSequence) {
|
||||
int slowRuns = 0;
|
||||
int slowProgress = 0;
|
||||
|
||||
auto root = std::unique_ptr<SequenceNode>(new SequenceNode("sequence"));
|
||||
root->add(constantAction("first", BehaviorStatus::Success, &firstRuns));
|
||||
root->add(slowAction("slow", 2, &slowRuns, &slowProgress));
|
||||
|
||||
BehaviorTree tree(std::move(root));
|
||||
BehaviorContext ctx;
|
||||
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Running);
|
||||
CHECK_EQ(firstRuns, 1);
|
||||
CHECK_EQ(slowRuns, 1);
|
||||
|
||||
// The whole point: the first child must not run again while the second is
|
||||
// still Running.
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Running);
|
||||
CHECK_EQ(firstRuns, 1);
|
||||
CHECK_EQ(slowRuns, 2);
|
||||
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Success);
|
||||
CHECK_EQ(firstRuns, 1);
|
||||
CHECK_EQ(slowRuns, 3);
|
||||
|
||||
// Once settled the sequence starts over from the top.
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Running);
|
||||
CHECK_EQ(firstRuns, 2);
|
||||
CHECK_EQ(slowRuns, 4);
|
||||
}
|
||||
|
||||
VF_TEST(selectorResumesTheRunningBranchWithoutRecheckingEarlierOnes) {
|
||||
int guardChecks = 0;
|
||||
int slowRuns = 0;
|
||||
int slowProgress = 0;
|
||||
|
||||
auto root = std::unique_ptr<SelectorNode>(new SelectorNode("selector"));
|
||||
root->add(std::unique_ptr<BehaviorNode>(
|
||||
new ConditionNode("guard", [&guardChecks](BehaviorContext&) {
|
||||
++guardChecks;
|
||||
return false;
|
||||
})));
|
||||
root->add(slowAction("slow", 3, &slowRuns, &slowProgress));
|
||||
|
||||
BehaviorTree tree(std::move(root));
|
||||
BehaviorContext ctx;
|
||||
|
||||
tree.tick(ctx);
|
||||
CHECK_EQ(guardChecks, 1);
|
||||
tree.tick(ctx);
|
||||
tree.tick(ctx);
|
||||
CHECK_EQ(guardChecks, 1);
|
||||
CHECK_EQ(slowRuns, 3);
|
||||
CHECK_EQ(tree.root()->childAt(1)->name(), std::string("slow"));
|
||||
}
|
||||
|
||||
VF_TEST(cooldownBlocksForExactlyTheRequestedNumberOfTicks) {
|
||||
int runs = 0;
|
||||
auto gated = std::unique_ptr<BehaviorNode>(
|
||||
new CooldownNode("cooldown", constantAction("fire", BehaviorStatus::Success, &runs), 3));
|
||||
BehaviorTree tree(std::move(gated));
|
||||
BehaviorContext ctx;
|
||||
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Success);
|
||||
CHECK_EQ(runs, 1);
|
||||
|
||||
for (int blocked = 0; blocked < 3; ++blocked) {
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Failure);
|
||||
CHECK_EQ(runs, 1);
|
||||
}
|
||||
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Success);
|
||||
CHECK_EQ(runs, 2);
|
||||
|
||||
// And the block starts again immediately after the second firing.
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Failure);
|
||||
CHECK_EQ(runs, 2);
|
||||
}
|
||||
|
||||
VF_TEST(resettingTheTreeClearsALiveCooldown) {
|
||||
int runs = 0;
|
||||
auto gated = std::unique_ptr<BehaviorNode>(
|
||||
new CooldownNode("cooldown", constantAction("fire", BehaviorStatus::Success, &runs), 5));
|
||||
BehaviorTree tree(std::move(gated));
|
||||
BehaviorContext ctx;
|
||||
|
||||
tree.tick(ctx);
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Failure);
|
||||
tree.reset();
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Success);
|
||||
CHECK_EQ(runs, 2);
|
||||
}
|
||||
|
||||
VF_TEST(inverterFlipsSuccessAndFailureButLetsRunningThrough) {
|
||||
int progress = 0;
|
||||
int runs = 0;
|
||||
|
||||
BehaviorContext ctx;
|
||||
BehaviorTree yes(std::unique_ptr<BehaviorNode>(new InverterNode(
|
||||
"invert", constantAction("succeeds", BehaviorStatus::Success, nullptr))));
|
||||
CHECK(yes.tick(ctx) == BehaviorStatus::Failure);
|
||||
|
||||
BehaviorTree no(std::unique_ptr<BehaviorNode>(
|
||||
new InverterNode("invert", constantAction("fails", BehaviorStatus::Failure, nullptr))));
|
||||
CHECK(no.tick(ctx) == BehaviorStatus::Success);
|
||||
|
||||
BehaviorTree waiting(std::unique_ptr<BehaviorNode>(
|
||||
new InverterNode("invert", slowAction("slow", 2, &runs, &progress))));
|
||||
CHECK(waiting.tick(ctx) == BehaviorStatus::Running);
|
||||
}
|
||||
|
||||
VF_TEST(repeaterSucceedsOnlyAfterTheRequestedNumberOfCompletions) {
|
||||
int runs = 0;
|
||||
auto repeat = std::unique_ptr<BehaviorNode>(new RepeaterNode(
|
||||
"repeat", constantAction("beat", BehaviorStatus::Success, &runs), 3));
|
||||
BehaviorTree tree(std::move(repeat));
|
||||
BehaviorContext ctx;
|
||||
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Running);
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Running);
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Success);
|
||||
CHECK_EQ(runs, 3);
|
||||
|
||||
int failingRuns = 0;
|
||||
auto stopping = std::unique_ptr<BehaviorNode>(new RepeaterNode(
|
||||
"repeat", constantAction("beat", BehaviorStatus::Failure, &failingRuns), 3, true));
|
||||
BehaviorTree strict(std::move(stopping));
|
||||
CHECK(strict.tick(ctx) == BehaviorStatus::Failure);
|
||||
CHECK_EQ(failingRuns, 1);
|
||||
}
|
||||
|
||||
VF_TEST(retryUntilSuccessGivesUpAfterTheAttemptBudget) {
|
||||
int runs = 0;
|
||||
auto retry = std::unique_ptr<BehaviorNode>(new RetryUntilSuccessNode(
|
||||
"retry", constantAction("attempt", BehaviorStatus::Failure, &runs), 3));
|
||||
BehaviorTree tree(std::move(retry));
|
||||
BehaviorContext ctx;
|
||||
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Running);
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Running);
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Failure);
|
||||
CHECK_EQ(runs, 3);
|
||||
}
|
||||
|
||||
VF_TEST(timeLimitCutsOffAChildThatNeverSettles) {
|
||||
int runs = 0;
|
||||
auto limited = std::unique_ptr<BehaviorNode>(new TimeLimitNode(
|
||||
"window", constantAction("stall", BehaviorStatus::Running, &runs), 3));
|
||||
BehaviorTree tree(std::move(limited));
|
||||
BehaviorContext ctx;
|
||||
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Running);
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Running);
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Failure);
|
||||
CHECK_EQ(runs, 3);
|
||||
|
||||
// The budget is refilled once the decorator gave its verdict.
|
||||
CHECK(tree.tick(ctx) == BehaviorStatus::Running);
|
||||
CHECK_EQ(runs, 4);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user