use fluxion_stream::{CombineLatestExt, MapOrderedExt, OrderedStreamExt, ScanOrderedExt};
use fluxion_test_utils::{
helpers::unwrap_stream,
test_channel,
test_data::{animal_dog, person_alice, person_bob, person_charlie, TestData},
unwrap_value, Sequenced,
};
#[tokio::test]
async fn test_scan_ordered_chained() -> anyhow::Result<()> {
let (tx, stream) = test_channel::<Sequenced<TestData>>();
let mut result = stream
.scan_ordered::<Sequenced<i32>, _, _>(0, |sum: &mut i32, value: &TestData| {
if let TestData::Person(p) = value {
*sum += p.age as i32;
}
*sum
})
.scan_ordered(0, |count: &mut i32, _sum: &i32| {
*count += 1;
*count
});
tx.unbounded_send(Sequenced::new(person_alice()))?; assert_eq!(
unwrap_value(Some(
unwrap_stream::<Sequenced<i32>, _>(&mut result, 500).await,
))
.value,
1
);
tx.unbounded_send(Sequenced::new(person_bob()))?; assert_eq!(
unwrap_value(Some(unwrap_stream(&mut result, 500).await)).value,
2
);
tx.unbounded_send(Sequenced::new(person_charlie()))?; assert_eq!(
unwrap_value(Some(unwrap_stream(&mut result, 500).await)).value,
3
);
drop(tx);
Ok(())
}
#[tokio::test]
async fn test_scan_ordered_composed_with_map_ordered() -> anyhow::Result<()> {
let (tx, stream) = test_channel::<Sequenced<TestData>>();
let mut result = stream.map_ordered(|_item| Sequenced::new(10)).scan_ordered(
0,
|sum: &mut i32, value: &i32| {
*sum += value;
*sum
},
);
tx.unbounded_send(Sequenced::new(person_alice()))?;
assert_eq!(
unwrap_value(Some(
unwrap_stream::<Sequenced<i32>, _>(&mut result, 500).await
))
.value,
10
);
tx.unbounded_send(Sequenced::new(person_bob()))?;
assert_eq!(
unwrap_value(Some(unwrap_stream(&mut result, 500).await)).value,
20
);
tx.unbounded_send(Sequenced::new(person_charlie()))?;
assert_eq!(
unwrap_value(Some(unwrap_stream(&mut result, 500).await)).value,
30
);
drop(tx);
Ok(())
}
#[tokio::test]
async fn test_ordered_merge_scan_ordered_name_change() -> anyhow::Result<()> {
let (s1_tx, s1_rx) = test_channel::<Sequenced<TestData>>();
let (s2_tx, s2_rx) = test_channel::<Sequenced<TestData>>();
let mut stream = s1_rx.ordered_merge(vec![s2_rx]).scan_ordered(
None::<String>,
|last_name: &mut Option<String>, item: &TestData| {
let current_name = match item {
TestData::Person(p) => p.name.clone(),
_ => "Unknown".to_string(),
};
let result = match last_name {
Some(prev) if prev != ¤t_name => {
format!("Name changed from {} to {}", prev, current_name)
}
Some(_) => format!("Same name: {}", current_name),
None => format!("First entry: {}", current_name),
};
*last_name = Some(current_name);
result
},
);
s1_tx.unbounded_send(Sequenced::new(person_alice()))?;
assert_eq!(
unwrap_value::<Sequenced<String>>(Some(unwrap_stream(&mut stream, 500).await)).value,
"First entry: Alice"
);
s2_tx.unbounded_send(Sequenced::new(person_alice()))?;
assert_eq!(
unwrap_value::<Sequenced<String>>(Some(unwrap_stream(&mut stream, 500).await)).value,
"Same name: Alice"
);
s1_tx.unbounded_send(Sequenced::new(person_bob()))?;
assert_eq!(
unwrap_value::<Sequenced<String>>(Some(unwrap_stream(&mut stream, 500).await)).value,
"Name changed from Alice to Bob"
);
Ok(())
}
#[tokio::test]
async fn test_combine_latest_scan_ordered_total_age() -> anyhow::Result<()> {
let (person_tx, person_rx) = test_channel::<Sequenced<TestData>>();
let (animal_tx, animal_rx) = test_channel::<Sequenced<TestData>>();
let person_stream = person_rx;
let animal_stream = animal_rx;
let combine_filter = |_: &fluxion_stream::CombinedState<TestData, u64>| true;
let mut stream = person_stream
.combine_latest(vec![animal_stream], combine_filter)
.scan_ordered(
0u32,
|total_age: &mut u32, state: &fluxion_stream::CombinedState<TestData, u64>| {
let values = state.values();
let current_sum: u32 = values
.iter()
.map(|v| match v {
TestData::Person(p) => p.age,
_ => 0,
})
.sum();
*total_age += current_sum;
*total_age
},
);
person_tx.unbounded_send(Sequenced::new(person_alice()))?; animal_tx.unbounded_send(Sequenced::new(animal_dog()))?; assert_eq!(
unwrap_value::<Sequenced<u32>>(Some(unwrap_stream(&mut stream, 500).await)).value,
25
);
person_tx.unbounded_send(Sequenced::new(person_bob()))?; assert_eq!(
unwrap_value::<Sequenced<u32>>(Some(unwrap_stream(&mut stream, 500).await)).value,
55
);
person_tx.unbounded_send(Sequenced::new(person_charlie()))?; assert_eq!(
unwrap_value::<Sequenced<u32>>(Some(unwrap_stream(&mut stream, 500).await)).value,
90
);
Ok(())
}