Skip to content

Commit c4f4cfd

Browse files
committed
Added parallel tests (partial)
1 parent a548f70 commit c4f4cfd

File tree

9 files changed

+281
-6
lines changed

9 files changed

+281
-6
lines changed
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
using Adnc.FluidBT.TaskParents;
2+
using Adnc.FluidBT.Tasks;
3+
using NSubstitute;
4+
using NUnit.Framework;
5+
6+
namespace Adnc.FluidBT.Testing {
7+
public class ParallelTest {
8+
public class UpdateMethod {
9+
private Parallel parallel;
10+
11+
[SetUp]
12+
public void SetParallel () {
13+
parallel = new Parallel();
14+
}
15+
16+
public class OnSuccess : UpdateMethod {
17+
[SetUp]
18+
public void CreateTree () {
19+
parallel
20+
.AddChild(A.TaskStub().Build())
21+
.AddChild(A.TaskStub().Build());
22+
}
23+
24+
[Test]
25+
public void Returns_success_when_all_children_return_success () {
26+
Assert.AreEqual(TaskStatus.Success, parallel.Update());
27+
}
28+
29+
[Test]
30+
public void Ticks_all_children_at_once () {
31+
parallel.Update();
32+
33+
parallel.children.ForEach(child => { child.Received(1).Update(); });
34+
}
35+
36+
[Test]
37+
public void Runs_end_on_all_children_when_complete () {
38+
parallel.Update();
39+
40+
parallel.children.ForEach(child => { child.Received(1).End(); });
41+
}
42+
}
43+
44+
public class OnContinue : UpdateMethod {
45+
[SetUp]
46+
public void CreateTree () {
47+
parallel
48+
.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Continue).Build())
49+
.AddChild(A.TaskStub().Build());
50+
}
51+
52+
[Test]
53+
public void Returns_continue_if_any_child_returns_continue () {
54+
Assert.AreEqual(TaskStatus.Continue, parallel.Update());
55+
}
56+
57+
[Test]
58+
public void Reruns_continue_tasks () {
59+
parallel.Update();
60+
parallel.Update();
61+
62+
parallel.children[0].Received(2).Update();
63+
}
64+
65+
[Test]
66+
public void Does_not_rerun_a_task_after_it_returns_success () {
67+
parallel.Update();
68+
parallel.Update();
69+
70+
parallel.children[1].Received(1).Update();
71+
}
72+
73+
[Test]
74+
public void Returns_success_when_continue_changes_to_success () {
75+
parallel.Update();
76+
parallel.children[0].Update().Returns(TaskStatus.Success);
77+
parallel.Update();
78+
79+
Assert.AreEqual(TaskStatus.Success, parallel.Update());
80+
}
81+
82+
[Test]
83+
public void Runs_end_on_all_children_after_changing_to_success () {
84+
parallel.Update();
85+
parallel.children[0].Update().Returns(TaskStatus.Success);
86+
parallel.Update();
87+
88+
parallel.children.ForEach(child => { child.Received(1).End(); });
89+
}
90+
}
91+
92+
public class OnFailure : UpdateMethod {
93+
[SetUp]
94+
public void CreateTree () {
95+
parallel
96+
.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Failure).Build())
97+
.AddChild(A.TaskStub().Build());
98+
}
99+
100+
[Test]
101+
public void Returns_failure_if_any_child_returns_failure () {
102+
Assert.AreEqual(TaskStatus.Failure, parallel.Update());
103+
}
104+
105+
[Test]
106+
public void Runs_failed_tasks_after_the_failed_node () {
107+
parallel.Update();
108+
109+
parallel.children[1].Received(1).Update();
110+
}
111+
112+
[Test]
113+
public void Runs_end_on_all_children_when_complete () {
114+
parallel.Update();
115+
parallel.children.ForEach((child) => child.Received(1).End());
116+
}
117+
}
118+
}
119+
120+
public class EndMethod {
121+
public void Ends_all_ongoing_tasks () {
122+
123+
}
124+
125+
public void Does_not_end_any_tasks_if_called_before_update () {
126+
127+
}
128+
}
129+
130+
public class ResetMethod {
131+
public void Does_not_recall_previous_node_status_after_usage () {
132+
}
133+
134+
public void Does_not_trigger_end_on_children () {
135+
}
136+
}
137+
}
138+
}

Assets/FluidBehaviorTree/Editor/Testing/ParentTasks/ParallelTest.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/FluidBehaviorTree/Editor/Testing/Tasks/TaskTest.cs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,5 +124,62 @@ public void Triggers_on_failure () {
124124
}
125125
}
126126
}
127+
128+
public class EndMethod {
129+
private TaskExample task;
130+
131+
[SetUp]
132+
public void CreateTask () {
133+
task = new TaskExample();
134+
}
135+
136+
[Test]
137+
public void Does_not_call_exit_if_not_run () {
138+
task.End();
139+
140+
Assert.AreEqual(0, task.ExitCount);
141+
}
142+
143+
[Test]
144+
public void Does_not_call_exit_if_last_status_was_success () {
145+
task.status = TaskStatus.Success;
146+
147+
task.Update();
148+
task.End();
149+
150+
Assert.AreEqual(1, task.ExitCount);
151+
}
152+
153+
[Test]
154+
public void Does_not_call_exit_if_last_status_was_failure () {
155+
task.status = TaskStatus.Failure;
156+
157+
task.Update();
158+
task.End();
159+
160+
Assert.AreEqual(1, task.ExitCount);
161+
}
162+
163+
[Test]
164+
public void Calls_exit_if_last_status_was_continue () {
165+
task.status = TaskStatus.Continue;
166+
167+
task.Update();
168+
task.End();
169+
170+
Assert.AreEqual(1, task.ExitCount);
171+
}
172+
173+
[Test]
174+
public void Reset_prevents_exit_from_being_called_when_it_should () {
175+
task.status = TaskStatus.Continue;
176+
177+
task.Update();
178+
task.Reset();
179+
task.End();
180+
181+
Assert.AreEqual(0, task.ExitCount);
182+
}
183+
}
127184
}
128185
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System.Collections.Generic;
2+
using Adnc.FluidBT.Tasks;
3+
4+
namespace Adnc.FluidBT.TaskParents {
5+
public class Parallel : CompositeBase {
6+
private readonly Dictionary<ITask, TaskStatus> _childStatus = new Dictionary<ITask, TaskStatus>();
7+
8+
protected override TaskStatus OnUpdate () {
9+
var successCount = 0;
10+
var failureCount = 0;
11+
12+
foreach (var child in children) {
13+
TaskStatus prevStatus;
14+
if (_childStatus.TryGetValue(child, out prevStatus) && prevStatus == TaskStatus.Success) {
15+
successCount++;
16+
continue;
17+
}
18+
19+
var status = child.Update();
20+
_childStatus[child] = status;
21+
22+
switch (status) {
23+
case TaskStatus.Failure:
24+
failureCount++;
25+
break;
26+
case TaskStatus.Success:
27+
successCount++;
28+
break;
29+
}
30+
}
31+
32+
if (successCount == children.Count) {
33+
foreach (var child in children) {
34+
child.End();
35+
}
36+
37+
return TaskStatus.Success;
38+
}
39+
40+
if (failureCount > 0) {
41+
foreach (var child in children) {
42+
child.End();
43+
}
44+
45+
return TaskStatus.Failure;
46+
}
47+
48+
return TaskStatus.Continue;
49+
}
50+
}
51+
}

Assets/FluidBehaviorTree/Scripts/TaskParents/Composites/Parallel.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/FluidBehaviorTree/Scripts/TaskParents/Composites/Sequence.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,13 @@ protected override TaskStatus OnUpdate () {
3434

3535
return TaskStatus.Success;
3636
}
37+
38+
public override ITask GetAbortCondition () {
39+
if (children.Count > 0) {
40+
return children[0].GetAbortCondition();
41+
}
42+
43+
return null;
44+
}
3745
}
3846
}

Assets/FluidBehaviorTree/Scripts/TaskParents/TaskParentBase.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ public abstract class TaskParentBase : ITaskParent {
66
private bool _enabled = true;
77

88
public AbortType AbortType { get; set; } = AbortType.None;
9+
public TaskStatus LastStatus { get; private set; }
910

1011
public bool Enabled {
1112
get { return children.Count != 0 && _enabled; }
@@ -20,14 +21,13 @@ public bool Enabled {
2021
public bool ValidAbortCondition { get; } = false;
2122

2223
public TaskStatus Update () {
23-
return OnUpdate();
24+
var status = OnUpdate();
25+
LastStatus = status;
26+
27+
return status;
2428
}
2529

2630
public virtual ITask GetAbortCondition () {
27-
if (children.Count > 0) {
28-
return children[0].GetAbortCondition();
29-
}
30-
3131
return null;
3232
}
3333

Assets/FluidBehaviorTree/Scripts/Tasks/ITask.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,7 @@ public interface ITask {
4141
/// </summary>
4242
/// <returns></returns>
4343
TaskStatus GetAbortStatus ();
44+
45+
TaskStatus LastStatus { get; }
4446
}
4547
}

Assets/FluidBehaviorTree/Scripts/Tasks/TaskBase.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22
public abstract class TaskBase : ITask {
33
private bool _init;
44
private bool _start;
5+
private bool _exit;
56

67
public bool Enabled { get; set; } = true;
78

9+
public TaskStatus LastStatus { get; private set; }
10+
811
public bool IsLowerPriority { get; } = false;
912

1013
public TaskStatus Update () {
@@ -16,9 +19,11 @@ public TaskStatus Update () {
1619
if (!_start) {
1720
Start();
1821
_start = true;
22+
_exit = true;
1923
}
2024

2125
var status = GetUpdate();
26+
LastStatus = status;
2227

2328
// Soft reset since the node has completed
2429
if (status != TaskStatus.Continue) {
@@ -38,6 +43,7 @@ public virtual ITask GetAbortCondition () {
3843
/// <param name="hardReset">Used to wipe the node back to its original state. Meant for pooling.</param>
3944
public void Reset (bool hardReset = false) {
4045
_start = false;
46+
_exit = false;
4147

4248
if (hardReset) {
4349
_init = false;
@@ -70,8 +76,15 @@ private void Init () {
7076
protected virtual void OnInit () {
7177
}
7278

79+
/// <summary>
80+
/// Exit can only be called if the exit bool has been activated (to safeguard against End() usage)
81+
/// </summary>
7382
private void Exit () {
74-
OnExit();
83+
if (_exit) {
84+
OnExit();
85+
}
86+
87+
_exit = false;
7588
}
7689

7790
protected virtual void OnExit () {

0 commit comments

Comments
 (0)