|
1 | 1 | use crate::behavior_tests::TestActions::{Dec, Inc, LessThan, LessThanRunningSuccess}; |
2 | 2 | use bonsai_bt::{ |
3 | | - Action, ActionArgs, After, AlwaysSucceed, Event, Failure, Float, If, Invert, Select, Sequence, Status::Running, |
4 | | - Success, UpdateArgs, Wait, WaitForever, WhenAll, While, WhileAll, BT, |
| 3 | + Action, ActionArgs, After, AlwaysSucceed, Event, Failure, Float, If, Invert, Race, Select, Sequence, |
| 4 | + Status::Running, Success, UpdateArgs, Wait, WaitForever, WhenAll, WhenAny, While, WhileAll, BT, |
5 | 5 | }; |
6 | 6 |
|
7 | 7 | /// Some test actions. |
@@ -610,3 +610,95 @@ fn test_repeat_sequence_empty() { |
610 | 610 | // panics because no behaviors... |
611 | 611 | let _state = BT::new(after, ()); |
612 | 612 | } |
| 613 | + |
| 614 | +#[test] |
| 615 | +fn race_returns_first_success() { |
| 616 | + let a: i32 = 0; |
| 617 | + // Inc succeeds immediately, Wait is still running |
| 618 | + let behavior = Race(vec![Action(Inc), Wait(10.0)]); |
| 619 | + let mut state = BT::new(behavior, ()); |
| 620 | + let (a, s, _) = tick(a, 0.1, &mut state); |
| 621 | + assert_eq!(a, 1); |
| 622 | + assert_eq!(s, Success); |
| 623 | +} |
| 624 | + |
| 625 | +#[test] |
| 626 | +fn race_returns_first_failure() { |
| 627 | + let a: i32 = 5; |
| 628 | + // LessThan(1) fails immediately since 5 >= 1, Wait is still running |
| 629 | + let behavior = Race(vec![Action(LessThan(1)), Wait(10.0)]); |
| 630 | + let mut state = BT::new(behavior, ()); |
| 631 | + let (a, s, _) = tick(a, 0.1, &mut state); |
| 632 | + assert_eq!(a, 5); |
| 633 | + assert_eq!(s, Failure); |
| 634 | +} |
| 635 | + |
| 636 | +#[test] |
| 637 | +fn race_running_until_first_completes() { |
| 638 | + let a: i32 = 0; |
| 639 | + // Both children are time-based, neither completes on first tick |
| 640 | + let behavior = Race(vec![Wait(1.0), Wait(2.0)]); |
| 641 | + let mut state = BT::new(behavior, ()); |
| 642 | + |
| 643 | + // After 0.5s, both still running |
| 644 | + let (_a, s, _) = tick(a, 0.5, &mut state); |
| 645 | + assert_eq!(s, Running); |
| 646 | + |
| 647 | + // After another 0.5s (total 1.0s), first Wait completes with Success |
| 648 | + let (_a, s, _) = tick(_a, 0.5, &mut state); |
| 649 | + assert_eq!(s, Success); |
| 650 | +} |
| 651 | + |
| 652 | +#[test] |
| 653 | +fn race_second_child_wins_if_first_is_running() { |
| 654 | + let a: i32 = 0; |
| 655 | + let behavior = Race(vec![WaitForever, Action(Inc)]); |
| 656 | + let mut state = BT::new(behavior, ()); |
| 657 | + let (a, s, _) = tick(a, 0.1, &mut state); |
| 658 | + assert_eq!(a, 1); |
| 659 | + assert_eq!(s, Success); |
| 660 | +} |
| 661 | + |
| 662 | +#[test] |
| 663 | +fn race_failure_short_circuits_unlike_when_any() { |
| 664 | + // the main difference from WhenAny: |
| 665 | + // WhenAny would swallow the failure and keep running. |
| 666 | + // Race returns the failure immediately. |
| 667 | + let a: i32 = 5; |
| 668 | + // LessThan(1) fails immediately (5 >= 1), Wait(10.0) is still running |
| 669 | + let behavior = Race(vec![Action(LessThan(1)), Wait(10.0)]); |
| 670 | + let mut state = BT::new(behavior, ()); |
| 671 | + let (a, s, _) = tick(a, 0.1, &mut state); |
| 672 | + assert_eq!(s, Failure); |
| 673 | + |
| 674 | + // for WhenAny: same children, but failure is swallowed |
| 675 | + let behavior_any = WhenAny(vec![Action(LessThan(1)), Wait(10.0)]); |
| 676 | + let mut state_any = BT::new(behavior_any, ()); |
| 677 | + let (_, s_any, _) = tick(a, 0.1, &mut state_any); |
| 678 | + assert_eq!(s_any, Running); |
| 679 | +} |
| 680 | + |
| 681 | +#[test] |
| 682 | +fn race_timeout_pattern() { |
| 683 | + let a: i32 = 0; |
| 684 | + // Simulate a "slow action" using WaitForever with a 1-second timeout. |
| 685 | + // The timeout (Wait) fires first. |
| 686 | + let behavior = Race(vec![WaitForever, Wait(1.0)]); |
| 687 | + let mut state = BT::new(behavior, ()); |
| 688 | + |
| 689 | + let (_, s, _) = tick(a, 0.5, &mut state); |
| 690 | + assert_eq!(s, Running); |
| 691 | + |
| 692 | + let (_, s, _) = tick(a, 0.5, &mut state); |
| 693 | + assert_eq!(s, Success); |
| 694 | +} |
| 695 | + |
| 696 | +#[test] |
| 697 | +fn race_empty() { |
| 698 | + let a: i32 = 0; |
| 699 | + let behavior = Race(vec![]); |
| 700 | + let mut state = BT::new(behavior, ()); |
| 701 | + let (_, s, _) = tick(a, 0.1, &mut state); |
| 702 | + // No children means nothing can complete, stays Running |
| 703 | + assert_eq!(s, Running); |
| 704 | +} |
0 commit comments