use crate::behavior_tests::TestActions::{Dec, Inc, LessThan, LessThanRunningSuccess};
use bonsai_bt::{
Action, ActionArgs, After, AlwaysSucceed, Event, Failure, Float, If, Invert, Race, Select, Sequence,
Status::Running, Success, UpdateArgs, Wait, WaitForever, WhenAll, WhenAny, While, WhileAll, BT,
};
#[derive(Clone, Debug)]
enum TestActions {
Inc,
Dec,
LessThan(i32),
LessThanRunningSuccess(i32),
}
fn tick(mut acc: i32, dt: Float, state: &mut BT<TestActions, ()>) -> (i32, bonsai_bt::Status, Float) {
let e: Event = UpdateArgs { dt }.into();
println!("acc {}", acc);
let (s, t) = state
.tick(&e, &mut |args: ActionArgs<Event, TestActions>, _| match *args.action {
Inc => {
acc += 1;
(Success, args.dt)
}
Dec => {
acc -= 1;
(Success, args.dt)
}
LessThan(v) => {
println!("inside less than with acc: {}", acc);
if acc < v {
println!("success {}<{}", acc, v);
(Success, args.dt)
} else {
println!("failure {}>={}", acc, v);
(Failure, args.dt)
}
}
TestActions::LessThanRunningSuccess(v) => {
println!("inside LessThanRunningSuccess with acc: {}", acc);
if acc < v {
println!("success {}<{}", acc, v);
(Running, args.dt)
} else {
println!("failure {}>={}", acc, v);
(Success, args.dt)
}
}
})
.unwrap();
println!("status: {:?} dt: {}", s, t);
(acc, s, t)
}
fn tick_with_ref(acc: &mut i32, dt: Float, state: &mut BT<TestActions, ()>) {
let e: Event = UpdateArgs { dt }.into();
state
.tick(&e, &mut |args: ActionArgs<Event, TestActions>, _| match *args.action {
Inc => {
*acc += 1;
(Success, args.dt)
}
Dec => {
*acc -= 1;
(Success, args.dt)
}
TestActions::LessThanRunningSuccess(_) | LessThan(_) => todo!(),
})
.unwrap();
}
#[test]
fn test_immediate_termination() {
let mut a: i32 = 0;
let seq = Sequence(vec![Action(Inc), Action(Inc)]);
let mut state = BT::new(seq, ());
tick_with_ref(&mut a, 0.0, &mut state);
assert_eq!(a, 2);
assert!(state.is_finished());
state.reset_bt();
tick_with_ref(&mut a, 1.0, &mut state);
assert_eq!(a, 4);
assert!(state.is_finished());
state.reset_bt();
}
#[test]
fn while_wait_sequence_twice() {
let mut a: i32 = 0;
let w = While(
Box::new(Wait(2.001)),
vec![Sequence(vec![Wait(0.5), Action(Inc), Wait(0.5), Action(Inc)])],
);
let mut state = BT::new(w, ());
tick_with_ref(&mut a, 1.0, &mut state);
assert_eq!(a, 2);
tick_with_ref(&mut a, 1.0, &mut state);
assert_eq!(a, 4);
tick_with_ref(&mut a, 1.0, &mut state);
assert_eq!(a, 4);
}
#[test]
fn wait_sec() {
let a: i32 = 0;
let seq = Sequence(vec![Wait(1.0), Action(Inc)]);
let mut state = BT::new(seq, ());
let (a, _, _) = tick(a, 1.0, &mut state);
assert_eq!(a, 1);
}
#[test]
fn wait_half_sec() {
let a: i32 = 0;
let seq = Sequence(vec![Wait(1.0), Action(Inc)]);
let mut state = BT::new(seq, ());
let (a, _, _) = tick(a, 0.5, &mut state);
assert_eq!(a, 0);
let (a, _, _) = tick(a, 0.5, &mut state);
assert_eq!(a, 1);
}
#[test]
fn sequence_of_one_event() {
let a: i32 = 0;
let seq = Sequence(vec![Action(Inc)]);
let mut state = BT::new(seq, ());
let (a, _, _) = tick(a, 1.0, &mut state);
assert_eq!(a, 1);
}
#[test]
fn wait_two_waits() {
let a: i32 = 0;
let seq = Sequence(vec![Wait(0.5), Wait(0.5), Action(Inc)]);
let mut state = BT::new(seq, ());
let (a, _, _) = tick(a, 1.0, &mut state);
assert_eq!(a, 1);
}
#[test]
fn loop_ten_times() {
let a: i32 = 0;
let rep = While(Box::new(Wait(50.0)), vec![Wait(0.5), Action(Inc), Wait(0.5)]);
let mut state = BT::new(rep, ());
let (a, _, _) = tick(a, 10.0, &mut state);
assert_eq!(a, 10);
}
#[test]
fn when_all_wait() {
let a: i32 = 0;
let all = Sequence(vec![
WhenAll(vec![Wait(0.5), Wait(1.0)]),
Action(Inc),
]);
let mut state = BT::new(all, ());
let (a, _, _) = tick(a, 0.5, &mut state);
assert_eq!(a, 0);
let (a, _, _) = tick(a, 0.5, &mut state);
assert_eq!(a, 1);
}
#[test]
fn while_wait_sequence() {
let mut a: i32 = 0;
let w = While(
Box::new(Wait(9.999999)),
vec![Sequence(vec![Wait(0.5), Action(Inc), Wait(0.5), Action(Inc)])],
);
let mut state = BT::new(w, ());
for _ in 0..100 {
(a, _, _) = tick(a, 0.1, &mut state);
}
assert_eq!(a, 19);
}
#[test]
fn while_wait_forever_sequence() {
let mut a: i32 = 0;
let w = While(Box::new(WaitForever), vec![Sequence(vec![Action(Inc), Wait(1.0)])]);
let mut state = BT::new(w, ());
(a, _, _) = tick(a, 1.001, &mut state);
assert_eq!(a, 2);
}
#[test]
fn test_if_less_than() {
let a: i32 = 3;
let _if = If(
Box::new(Action(LessThan(1))),
Box::new(Action(Inc)), Box::new(Action(Dec)), );
let mut state = BT::new(_if, ());
let (a, s, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 2);
assert_eq!(s, Success);
state.reset_bt();
let (a, s, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 1);
assert_eq!(s, Success);
state.reset_bt();
let (a, s, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 0);
assert_eq!(s, Success);
state.reset_bt();
let (a, s, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 1);
assert_eq!(s, Success);
}
#[test]
fn when_all_if() {
let a: i32 = 0;
let inc = Sequence(vec![Action(Inc), Action(Inc)]);
let dec = Sequence(vec![Action(Dec), Action(Dec)]);
let _if = If(Box::new(Action(LessThan(1))), Box::new(inc), Box::new(dec));
let _while = While(Box::new(Wait(50.0)), vec![Wait(0.5), Action(Inc), Wait(0.5)]);
let w = WhenAll(vec![_if, _while]);
let mut state = BT::new(w, ());
let (a, _, _) = tick(a, 8.0, &mut state);
assert_eq!(a, 10);
let (a, _, _) = tick(a, 2.0, &mut state);
assert_eq!(a, 12);
}
#[test]
fn test_alter_wait_time() {
let a: i32 = 0;
let rep = While(Box::new(Wait(50.0)), vec![Wait(0.5), Action(Inc), Wait(0.5)]);
let mut state = BT::new(rep, ());
let (a, _, _) = tick(a, 10.0, &mut state);
assert_eq!(a, 10);
}
#[test]
fn test_select_succeed_on_first() {
let a: i32 = 0;
let sel = Select(vec![Action(Inc), Action(Inc), Action(Inc)]);
let mut state = BT::new(sel, ());
let (a, _, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 1);
state.reset_bt();
let (a, _, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 2);
}
#[test]
fn test_select_needs_reset() {
let a: i32 = 3;
let sel = Select(vec![Action(LessThan(1)), Action(Dec), Action(Inc)]);
let mut state = BT::new(sel, ());
let (a, s, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 2);
assert_eq!(s, Success);
state.reset_bt();
let (a, s, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 1);
assert_eq!(s, Success);
state.reset_bt();
let (a, s, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 0);
assert_eq!(s, Success);
state.reset_bt();
let (a, s, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 0);
assert_eq!(s, Success);
}
#[test]
fn test_select_and_when_all() {
let a: i32 = 3;
let sel = Select(vec![Action(LessThan(1)), Action(Dec), Action(Inc)]);
let whenall = WhenAll(vec![Wait(0.35), sel]);
let mut state = BT::new(whenall, ());
let (a, s, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 2);
assert_eq!(s, Running);
let (a, s, _) = tick(a, 0.3, &mut state);
assert_eq!(a, 2);
assert_eq!(s, Success);
}
#[test]
fn test_select_and_invert() {
let a: i32 = 3;
let sel = Invert(Box::new(Select(vec![Action(LessThan(1)), Action(Dec), Action(Inc)])));
let mut state = BT::new(sel, ());
let (a, s, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 2);
assert_eq!(s, Failure);
state.reset_bt();
let (a, s, _) = tick(a, 0.3, &mut state);
assert_eq!(a, 1);
assert_eq!(s, Failure);
state.reset_bt();
let (a, s, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 0);
assert_eq!(s, Failure);
state.reset_bt();
let (a, s, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 0);
assert_eq!(s, Failure);
}
#[test]
fn test_always_succeed() {
let a: i32 = 3;
let sel = Sequence(vec![
Wait(0.5),
Action(LessThan(2)),
Wait(0.5),
Action(LessThan(1)),
Wait(0.5),
]);
let behavior = AlwaysSucceed(Box::new(sel));
let mut state = BT::new(behavior, ());
let (a, s, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 3);
assert_eq!(s, Running);
let (a, s, _) = tick(a, 0.7, &mut state);
assert_eq!(a, 3);
assert_eq!(s, Success);
state.reset_bt();
let (a, s, _) = tick(a, 0.5, &mut state);
assert_eq!(a, 3);
assert_eq!(s, Success);
state.reset_bt();
let (a, s, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 3);
assert_eq!(s, Running);
}
#[test]
fn test_after_all_succeed_in_order() {
let a: i32 = 0;
let after = After(vec![Action(Inc), Wait(0.1), Wait(0.2)]);
let mut state = BT::new(after, ());
let (a, s, dt) = tick(a, 0.1, &mut state);
assert_eq!(a, 1);
assert_eq!(s, Running);
assert_eq!(dt, 0.0);
let (a, s, dt) = tick(a, 0.1, &mut state);
assert_eq!(a, 1);
assert_eq!(s, Success);
assert_eq!(dt, 0.0);
}
#[test]
fn test_after_all_succeed_out_of_order() {
let a: i32 = 0;
let after = After(vec![Action(Inc), Wait(0.2), Wait(0.1)]);
let mut state = BT::new(after, ());
let (a, s, dt) = tick(a, 0.05, &mut state);
assert_eq!(a, 1);
assert_eq!(s, Running);
assert_eq!(dt, 0.0);
let (a, s, dt) = tick(a, 0.1, &mut state);
assert_eq!(a, 1);
assert_eq!(s, Failure);
assert_eq!(dt, 0.0);
}
#[test]
fn test_repeat_sequence() {
{
let a: i32 = 0;
let after = WhileAll(Box::new(Action(LessThanRunningSuccess(5))), vec![Action(Inc)]);
let mut state = BT::new(after, ());
let (a, s, dt) = tick(a, 0.0, &mut state);
assert_eq!(a, 5);
assert_eq!(s, Success);
assert_eq!(dt, 0.0);
}
}
#[test]
fn test_repeat_sequence_double_running() {
let after = WhileAll(
Box::new(Action(LessThanRunningSuccess(5))), vec![
Action(LessThanRunningSuccess(5)), Action(Dec), Action(Dec), Action(LessThan(0)), ],
);
let mut state = BT::new(after, ());
let mut current_value = 0;
loop {
let (a, s, _) = tick(current_value, 0.0, &mut state);
current_value = a;
match s {
Running => {
current_value += 1; }
_ => {
break;
}
}
}
assert_eq!(current_value, 3);
}
#[test]
fn test_repeat_sequence2() {
let after = WhileAll(
Box::new(Action(LessThanRunningSuccess(5))), vec![
Action(LessThanRunningSuccess(10)), Action(Dec), Action(Dec), Action(Dec), ],
);
let mut state = BT::new(after, ());
let mut current_value = 0;
let mut current_status;
loop {
let (a, s, _) = tick(current_value, 0.0, &mut state);
current_value = a;
current_status = s;
match s {
Running => {
current_value += 1; }
_ => {
break;
}
}
}
assert_eq!(current_status, bonsai_bt::Status::Success);
assert_eq!(current_value, 7);
}
#[test]
fn test_repeat_sequence3() {
let after = WhileAll(
Box::new(Action(LessThanRunningSuccess(2))),
vec![
Action(LessThanRunningSuccess(10)),
Action(Dec),
Action(Dec),
Action(Dec),
Action(LessThanRunningSuccess(10)),
Action(Dec),
],
);
let mut state = BT::new(after, ());
let mut current_value = 0;
let mut current_status;
loop {
let (a, s, _) = tick(current_value, 0.0, &mut state);
current_value = a;
current_status = s;
match s {
Running => {
current_value += 1;
}
_ => {
break;
}
}
}
assert_eq!(current_status, Success);
assert_eq!(current_value, 9);
}
#[test]
fn test_repeat_sequence_nested() {
let dec2 = Sequence(vec![Action(Dec), Action(Dec)]);
let inc1 = Sequence(vec![Action(Inc)]);
let nested = WhileAll(Box::new(Action(LessThanRunningSuccess(5))), vec![Action(Inc), inc1]);
let after = WhileAll(
Box::new(Action(LessThanRunningSuccess(1))),
vec![
nested, Action(Dec), dec2, ], );
let mut state = BT::new(after, ());
let mut current_value = 0;
let mut current_status;
loop {
let (a, s, _) = tick(current_value, 0.0, &mut state);
current_value = a;
current_status = s;
match s {
Running => {}
_ => {
break;
}
}
}
assert_eq!(current_status, bonsai_bt::Status::Success);
assert_eq!(current_value, 3);
}
#[test]
fn test_repeat_sequence_fail() {
{
let a: i32 = 4;
let after = WhileAll(
Box::new(Action(LessThanRunningSuccess(5))),
vec![Action(Dec), Action(LessThan(0))],
);
let mut state = BT::new(after, ());
let (a, s, dt) = tick(a, 0.0, &mut state);
assert_eq!(a, 3);
assert_eq!(s, Failure);
assert_eq!(dt, 0.0);
}
}
#[test]
fn test_repeat_sequence_timed() {
let a: i32 = 0;
let time_step = 0.1;
let steps = 5;
let after = WhileAll(
Box::new(Action(LessThanRunningSuccess(steps))),
vec![Wait(time_step), Action(Inc)],
);
let mut state = BT::new(after, ());
let (a, s, dt) = tick(a, time_step * 3.0, &mut state);
assert_eq!(dt, 0.0);
assert_eq!(a, 3);
assert_eq!(s, Running);
let (a, s, dt) = tick(a, 100.0, &mut state);
assert_eq!(dt, 100.0);
assert_eq!(a, 5);
assert_eq!(s, Success);
}
#[test]
#[should_panic]
fn test_repeat_sequence_empty() {
let after = WhileAll(Box::new(Action(LessThanRunningSuccess(0))), vec![]);
let _state = BT::new(after, ());
}
#[test]
fn race_returns_first_success() {
let a: i32 = 0;
let behavior = Race(vec![Action(Inc), Wait(10.0)]);
let mut state = BT::new(behavior, ());
let (a, s, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 1);
assert_eq!(s, Success);
}
#[test]
fn race_returns_first_failure() {
let a: i32 = 5;
let behavior = Race(vec![Action(LessThan(1)), Wait(10.0)]);
let mut state = BT::new(behavior, ());
let (a, s, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 5);
assert_eq!(s, Failure);
}
#[test]
fn race_running_until_first_completes() {
let a: i32 = 0;
let behavior = Race(vec![Wait(1.0), Wait(2.0)]);
let mut state = BT::new(behavior, ());
let (_a, s, _) = tick(a, 0.5, &mut state);
assert_eq!(s, Running);
let (_a, s, _) = tick(_a, 0.5, &mut state);
assert_eq!(s, Success);
}
#[test]
fn race_second_child_wins_if_first_is_running() {
let a: i32 = 0;
let behavior = Race(vec![WaitForever, Action(Inc)]);
let mut state = BT::new(behavior, ());
let (a, s, _) = tick(a, 0.1, &mut state);
assert_eq!(a, 1);
assert_eq!(s, Success);
}
#[test]
fn race_failure_short_circuits_unlike_when_any() {
let a: i32 = 5;
let behavior = Race(vec![Action(LessThan(1)), Wait(10.0)]);
let mut state = BT::new(behavior, ());
let (a, s, _) = tick(a, 0.1, &mut state);
assert_eq!(s, Failure);
let behavior_any = WhenAny(vec![Action(LessThan(1)), Wait(10.0)]);
let mut state_any = BT::new(behavior_any, ());
let (_, s_any, _) = tick(a, 0.1, &mut state_any);
assert_eq!(s_any, Running);
}
#[test]
fn race_timeout_pattern() {
let a: i32 = 0;
let behavior = Race(vec![WaitForever, Wait(1.0)]);
let mut state = BT::new(behavior, ());
let (_, s, _) = tick(a, 0.5, &mut state);
assert_eq!(s, Running);
let (_, s, _) = tick(a, 0.5, &mut state);
assert_eq!(s, Success);
}
#[test]
fn race_empty() {
let a: i32 = 0;
let behavior = Race(vec![]);
let mut state = BT::new(behavior, ());
let (_, s, _) = tick(a, 0.1, &mut state);
assert_eq!(s, Running);
}
#[test]
fn memoryless_sequence_all_success() {
let a: i32 = 0;
let rs = Sequence(vec![Action(Inc), Action(Inc)]).memory(false);
let mut bt = BT::new(rs, ());
let (a, status, _) = tick(a, 0.0, &mut bt);
assert_eq!(a, 2);
assert_eq!(status, Success);
assert!(bt.is_finished());
}
#[test]
fn memoryless_sequence_failure_short_circuits() {
let a: i32 = 5;
let rs = Sequence(vec![Action(LessThan(3)), Action(Inc)]).memory(false);
let mut bt = BT::new(rs, ());
let (a, status, _) = tick(a, 0.0, &mut bt);
assert_eq!(status, Failure);
assert_eq!(a, 5, "later children must not be ticked on failure");
}
#[test]
fn memoryless_sequence_running_short_circuits_then_re_evaluates() {
let mut a: i32 = 0;
let rs = Sequence(vec![Action(LessThan(3)), Action(LessThanRunningSuccess(3))]).memory(false);
let mut bt = BT::new(rs, ());
let (acc, status, _) = tick(a, 0.0, &mut bt);
a = acc;
assert_eq!(status, Running);
assert_eq!(a, 0);
a = 5;
let (acc, status, _) = tick(a, 0.0, &mut bt);
assert_eq!(
status, Failure,
"memoryless composite must abort once earlier cond fails"
);
assert_eq!(acc, 5, "the previously-running child must NOT be re-ticked");
}
#[test]
fn memoryless_sequence_resets_wait_state() {
let a: i32 = 0;
let rs = Sequence(vec![Wait(1.0), Action(Inc)]).memory(false);
let mut bt = BT::new(rs, ());
for _ in 0..5 {
let (_, status, _) = tick(a, 0.5, &mut bt);
assert_eq!(status, Running, "wait elapsed time is discarded on re-tick");
}
}
#[test]
fn memoryless_sequence_empty_is_success() {
let rs: bonsai_bt::Behavior<TestActions> = Sequence(vec![]).memory(false);
let mut bt = BT::new(rs, ());
let (_, status, _) = tick(0, 0.0, &mut bt);
assert_eq!(status, Success);
}
#[test]
fn memoryless_select_short_circuits_on_success() {
let a: i32 = 5;
let rs = Select(vec![Action(LessThan(3)), Action(LessThan(10)), Action(Inc)]).memory(false);
let mut bt = BT::new(rs, ());
let (acc, status, _) = tick(a, 0.0, &mut bt);
assert_eq!(status, Success);
assert_eq!(acc, 5, "short-circuited siblings must not be ticked");
}
#[test]
fn memoryless_select_all_fail_returns_failure() {
let a: i32 = 5;
let rs = Select(vec![Action(LessThan(0)), Action(LessThan(1))]).memory(false);
let mut bt = BT::new(rs, ());
let (_, status, _) = tick(a, 0.0, &mut bt);
assert_eq!(status, Failure);
}
#[test]
fn memoryless_select_empty_is_failure() {
let rs: bonsai_bt::Behavior<TestActions> = Select(vec![]).memory(false);
let mut bt = BT::new(rs, ());
let (_, status, _) = tick(0, 0.0, &mut bt);
assert_eq!(status, Failure);
}
#[test]
fn nested_memoryless_sequence() {
let inner = Sequence(vec![Action(Inc)]).memory(false);
let outer = Sequence(vec![Action(LessThan(2)), inner]).memory(false);
let mut bt = BT::new(outer, ());
let (a, status, _) = tick(0, 0.0, &mut bt);
assert_eq!(status, Success);
assert_eq!(a, 1);
}
#[test]
fn memoryless_inside_sequence_does_not_disturb_outer_progress() {
let outer = Sequence(vec![Action(Inc), Sequence(vec![Action(Inc)]).memory(false)]);
let mut bt = BT::new(outer, ());
let (a, status, _) = tick(0, 0.0, &mut bt);
assert_eq!(status, Success);
assert_eq!(a, 2);
}
#[test]
fn memoryless_sequence_bt_finishes_and_can_reset() {
let rs = Sequence(vec![Action(Inc), Action(Inc)]).memory(false);
let mut bt = BT::new(rs, ());
let (_, status, _) = tick(0, 0.0, &mut bt);
assert_eq!(status, Success);
assert!(bt.is_finished());
bt.reset_bt();
let (a, status, _) = tick(0, 0.0, &mut bt);
assert_eq!(status, Success);
assert_eq!(a, 2);
}
#[test]
fn memoryless_sequence_many_ticks_no_drift() {
let rs = Sequence(vec![Action(Inc), Action(Inc)]).memory(false);
let mut bt = BT::new(rs, ());
let mut a: i32 = 0;
for _ in 0..1000 {
let (acc, status, _) = tick(a, 0.0, &mut bt);
a = acc;
assert_eq!(status, Success);
bt.reset_bt();
}
assert_eq!(a, 2 * 1000);
}