asupersync-conformance 0.3.3

Conformance test suite for async runtime specifications
use crate::{
    BroadcastReceiver, BroadcastSender, ConformanceTest, MpscReceiver, MpscSender, OneshotSender,
    RuntimeInterface, TestCategory, TestResult, WatchReceiver, WatchSender, conformance_test,
};

pub fn collect_tests<RT: RuntimeInterface>() -> Vec<ConformanceTest<RT>> {
    vec![
        conformance_test! {
            id: "chan-001",
            name: "MPSC FIFO Ordering",
            description: "Verify that MPSC channel preserves FIFO order for a single producer",
            category: TestCategory::Channels,
            tags: ["mpsc", "ordering"],
            expected: "Messages received in the order sent",
            test: |rt| {
                rt.block_on(async {
                    let (tx, mut rx) = rt.mpsc_channel::<i32>(10);

                    for i in 0..10 {
                        tx.send(i).await.expect("send failed");
                    }
                    drop(tx);

                    for i in 0..10 {
                        match rx.recv().await {
                            Some(val) => {
                                if val != i {
                                    return TestResult::failed(format!("Expected {}, got {}", i, val));
                                }
                            }
                            None => return TestResult::failed("Channel closed prematurely"),
                        }
                    }

                    if rx.recv().await.is_some() {
                        return TestResult::failed("Channel should be empty and closed");
                    }

                    TestResult::passed()
                })
            }
        },
        conformance_test! {
            id: "chan-002",
            name: "MPSC Multi-Producer",
            description: "Verify multiple producers can send to the same channel",
            category: TestCategory::Channels,
            tags: ["mpsc", "concurrency"],
            expected: "All messages received",
            test: |rt| {
                rt.block_on(async {
                    let (tx, mut rx) = rt.mpsc_channel::<usize>(100);
                    let mut handles = Vec::new();

                    for i in 0..5 {
                        let tx = tx.clone();

                        handles.push(rt.spawn(async move {
                            for j in 0..10 {
                                tx.send(i * 10 + j).await.expect("send failed");
                            }
                        }));
                    }
                    drop(tx);

                    for h in handles {
                        h.await;
                    }

                    let mut received = Vec::new();
                    while let Some(val) = rx.recv().await {
                        received.push(val);
                    }

                    if received.len() != 50 {
                        return TestResult::failed(format!("Expected 50 messages, got {}", received.len()));
                    }

                    received.sort_unstable();
                    let expected: Vec<_> = (0..50).collect();

                    if received != expected {
                         return TestResult::failed("Received messages mismatch");
                    }

                    TestResult::passed()
                })
            }
        },
        conformance_test! {
            id: "chan-004",
            name: "Oneshot Success",
            description: "Verify oneshot channel sends and receives a value",
            category: TestCategory::Channels,
            tags: ["oneshot"],
            expected: "Value received",
            test: |rt| {
                rt.block_on(async {
                    let (tx, rx) = rt.oneshot_channel::<i32>();
                    tx.send(42).expect("send failed");
                    match rx.await {
                        Ok(42) => TestResult::passed(),
                        Ok(v) => TestResult::failed(format!("Expected 42, got {}", v)),
                        Err(_) => TestResult::failed("Receive failed"),
                    }
                })
            }
        },
        conformance_test! {
            id: "chan-005",
            name: "Oneshot Sender Dropped",
            description: "Verify error when oneshot sender is dropped",
            category: TestCategory::Channels,
            tags: ["oneshot", "error"],
            expected: "RecvError",
            test: |rt| {
                rt.block_on(async {
                    let (tx, rx) = rt.oneshot_channel::<i32>();
                    drop(tx);
                    match rx.await {
                        Ok(_) => TestResult::failed("Should not receive value"),
                        Err(_) => TestResult::passed(),
                    }
                })
            }
        },
        conformance_test! {
            id: "chan-006",
            name: "Broadcast Basic",
            description: "Verify broadcast sends to all subscribers",
            category: TestCategory::Channels,
            tags: ["broadcast"],
            expected: "All subscribers receive messages",
            test: |rt| {
                rt.block_on(async {
                    let (tx, mut rx1) = rt.broadcast_channel::<i32>(10);
                    let mut rx2 = tx.subscribe();

                    tx.send(10).expect("send failed");
                    tx.send(20).expect("send failed");

                    let v1_1 = rx1.recv().await.expect("rx1 recv 1");
                    let v1_2 = rx1.recv().await.expect("rx1 recv 2");

                    let v2_1 = rx2.recv().await.expect("rx2 recv 1");
                    let v2_2 = rx2.recv().await.expect("rx2 recv 2");

                    if v1_1 != 10 || v1_2 != 20 {
                        return TestResult::failed("rx1 received wrong values");
                    }
                    if v2_1 != 10 || v2_2 != 20 {
                        return TestResult::failed("rx2 received wrong values");
                    }

                    TestResult::passed()
                })
            }
        },
        conformance_test! {
            id: "chan-007",
            name: "Watch Latest Value",
            description: "Verify watch channel holds latest value",
            category: TestCategory::Channels,
            tags: ["watch"],
            expected: "Receiver sees initial and updates",
            test: |rt| {
                rt.block_on(async {
                    let (tx, mut rx) = rt.watch_channel::<i32>(0);

                    if rx.borrow_and_clone() != 0 {
                        return TestResult::failed("Initial value mismatch");
                    }

                    tx.send(1).expect("send failed");
                    rx.changed().await.expect("changed failed");
                    if rx.borrow_and_clone() != 1 {
                        return TestResult::failed("Update 1 mismatch");
                    }

                    tx.send(2).expect("send failed");
                    rx.changed().await.expect("changed failed");
                    if rx.borrow_and_clone() != 2 {
                        return TestResult::failed("Update 2 mismatch");
                    }

                    TestResult::passed()
                })
            }
        },
    ]
}