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();
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;
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]);
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;
assert_eq!(*product.lock().unwrap(), 3628800);
}
#[tokio::test]
async fn test_with_period_basic() {
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() {
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);
assert!(elapsed >= Duration::from_millis(90));
}