roplat 0.2.0

roplat: just a robot operation system
Documentation
//! `WithPeriod` / `IterWithPeriod` 节律测试。

use roplat::rhythm::{Rhythm, WithPeriod};
use std::ops::AddAssign;
use std::sync::{Arc, Mutex};
use std::time::Duration;

#[tokio::test]
async fn test_iter_rhythm_basic() {
    // 测试基础迭代器功能
    let data = vec![1, 2, 3, 4, 5];

    let result = Arc::new(Mutex::new(Vec::new()));
    let result_clone = result.clone();

    data.into_iter()
        .drive(result_clone, |results, value| async move {
            results.lock().unwrap().push(value);
            ((), results)
        })
        .await;

    let collected = result.lock().unwrap();
    assert_eq!(*collected, vec![1, 2, 3, 4, 5]);
}

#[tokio::test]
async fn test_iter_rhythm_empty() {
    // 测试空迭代器
    let data: Vec<i32> = vec![];

    let counter = Arc::new(Mutex::new(0));
    let counter_clone = counter.clone();

    data.into_iter()
        .drive(counter_clone, |count, _value| async move {
            count.lock().unwrap().add_assign(1);
            ((), count)
        })
        .await;

    assert_eq!(*counter.lock().unwrap(), 0);
}

#[tokio::test]
async fn test_iter_rhythm_algorithmic_generator() {
    // 测试算法生成器:斐波那契数列
    let mut fib = (0..10).scan((0u64, 1), |state, _| {
        let (a, b) = *state;
        *state = (b, a + b);
        Some(a)
    });

    let result = Arc::new(Mutex::new(Vec::new()));
    let result_clone = result.clone();

    fib.drive(result_clone, |results, value| async move {
        results.lock().unwrap().push(value);
        ((), results)
    })
    .await;

    let collected = result.lock().unwrap();
    // 斐波那契数列前 10 项: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
    assert_eq!(*collected, vec![0, 1, 1, 2, 3, 5, 8, 13, 21, 34]);
}

#[tokio::test]
async fn test_iter_rhythm_range() {
    // 测试范围迭代器
    let sum = Arc::new(Mutex::new(0i32));
    let sum_clone = sum.clone();

    (0..10)
        .drive(sum_clone, |total, value| async move {
            total.lock().unwrap().add_assign(value);
            ((), total)
        })
        .await;

    // 0 + 1 + 2 + ... + 9 = 45
    assert_eq!(*sum.lock().unwrap(), 45);
}

#[tokio::test]
async fn test_paced_iter_rhythm_timing() {
    // 测试定速回放的时间控制
    let data = vec![1, 2, 3, 4, 5];

    let result = Arc::new(Mutex::new(Vec::new()));
    let result_clone = result.clone();

    let start = std::time::Instant::now();
    data.into_iter()
        .with_period(Duration::from_millis(10))
        .drive(result_clone, |results, value| async move {
            results.lock().unwrap().push(value);
            ((), results)
        })
        .await;
    let elapsed = start.elapsed();

    let collected = result.lock().unwrap();
    assert_eq!(*collected, vec![1, 2, 3, 4, 5]);

    // 5 个数据,间隔 10ms,应该至少需要 40ms (4 个间隔)
    // 我们允许一定的误差,但至少应该 > 35ms
    assert!(elapsed >= Duration::from_millis(35));
}

#[tokio::test]
async fn test_paced_iter_rhythm_empty() {
    // 测试定速迭代器的空情况
    let data: Vec<i32> = vec![];

    let counter = Arc::new(Mutex::new(0));
    let counter_clone = counter.clone();

    data.into_iter()
        .with_period(Duration::from_millis(10))
        .drive(counter_clone, |count, _value| async move {
            count.lock().unwrap().add_assign(1);
            ((), count)
        })
        .await;

    assert_eq!(*counter.lock().unwrap(), 0);
}

#[tokio::test]
async fn test_iter_rhythm_complex_data() {
    // 测试复杂数据类型
    #[derive(Debug, PartialEq, Clone)]
    struct Point {
        x: f64,
        y: f64,
    }

    let data = vec![
        Point { x: 0.0, y: 0.0 },
        Point { x: 1.0, y: 1.0 },
        Point { x: 2.0, y: 2.0 },
    ];

    let result = Arc::new(Mutex::new(Vec::new()));
    let result_clone = result.clone();

    data.into_iter()
        .drive(result_clone, |results, point| async move {
            results.lock().unwrap().push(point);
            ((), results)
        })
        .await;

    let collected = result.lock().unwrap();
    assert_eq!(collected.len(), 3);
    assert_eq!(collected[0].x, 0.0);
    assert_eq!(collected[1].x, 1.0);
    assert_eq!(collected[2].x, 2.0);
}

#[tokio::test]
async fn test_iter_rhythm_with_state() {
    // 测试带状态的迭代器处理
    let data: Vec<i32> = (1..=10).collect();

    let product = Arc::new(Mutex::new(1i64));
    let product_clone = product.clone();

    data.into_iter()
        .drive(product_clone, |prod, value| async move {
            *prod.lock().unwrap() *= value as i64;
            ((), prod)
        })
        .await;

    // 10! = 3628800
    assert_eq!(*product.lock().unwrap(), 3628800);
}

#[tokio::test]
async fn test_with_period_basic() {
    // 测试 WithPeriod trait 的基本功能
    let data = vec![1, 2, 3];

    let sum = Arc::new(Mutex::new(0i32));
    let sum_clone = sum.clone();

    data.into_iter()
        .with_period(Duration::from_millis(5))
        .drive(sum_clone, |total, value| async move {
            total.lock().unwrap().add_assign(value);
            ((), total)
        })
        .await;

    assert_eq!(*sum.lock().unwrap(), 6);
}

#[tokio::test]
async fn test_paced_iter_rhythm_high_frequency() {
    // 测试高频回放 (1kHz)
    let data: Vec<i32> = (0..100).collect();

    let counter = Arc::new(Mutex::new(0));
    let counter_clone = counter.clone();

    let start = std::time::Instant::now();
    data.into_iter()
        .with_period(Duration::from_millis(1))
        .drive(counter_clone, |count, _value| async move {
            count.lock().unwrap().add_assign(1);
            ((), count)
        })
        .await;
    let elapsed = start.elapsed();

    assert_eq!(*counter.lock().unwrap(), 100);
    // 100 个数据,间隔 1ms,应该至少需要 99ms
    assert!(elapsed >= Duration::from_millis(90));
}