smux_rust 0.2.1

A simple multiplexing library for Rust, inspired by xtaci/smux
use smux_rust::Config;
use std::time::Duration;

#[test]
fn test_config_default() {
    let config = Config::default();
    assert_eq!(config.version, 1);
    assert!(!config.keep_alive_disabled);
    assert_eq!(config.max_frame_size, 32768);
}

#[test]
fn test_config_verify() {
    let mut config = Config::default();
    
    // 测试无效版本
    config.version = 3;
    assert!(config.verify().is_err());
    
    // 测试有效版本
    config.version = 2;
    assert!(config.verify().is_ok());
    
    // 测试无效的保活间隔
    config.version = 1;
    config.keep_alive_interval = Duration::from_secs(0);
    assert!(config.verify().is_err());
    
    // 测试无效的超时
    config.keep_alive_interval = Duration::from_secs(10);
    config.keep_alive_timeout = Duration::from_secs(5);
    assert!(config.verify().is_err());
    
    // 测试无效的帧大小
    config.keep_alive_timeout = Duration::from_secs(30);
    config.max_frame_size = 0;
    assert!(config.verify().is_err());
    
    config.max_frame_size = 70000; // 超过 65535
    assert!(config.verify().is_err());
    
    // 测试无效的缓冲区大小
    config.max_frame_size = 32768;
    config.max_stream_buffer = 0;
    assert!(config.verify().is_err());
    
    config.max_stream_buffer = 65536;
    config.max_receive_buffer = 1000; // 小于 max_stream_buffer
    assert!(config.verify().is_err());
}

#[test]
fn test_frame_encode_decode() {
    use smux_rust::frame::{Frame, Cmd, RawHeader};
    
    // 测试帧编码
    let frame = Frame {
        ver: 1,
        cmd: Cmd::Psh,
        sid: 12345,
        data: bytes::Bytes::from("Hello, World!"),
    };
    
    let encoded = frame.encode();
    assert!(encoded.len() >= 8); // 至少包含 8 字节头部
    
    // 测试头部解码
    let header = RawHeader::from_bytes(&encoded[..8]);
    assert!(header.is_some());
    let header = header.unwrap();
    assert_eq!(header.ver, 1);
    assert_eq!(header.cmd, Cmd::Psh);
    assert_eq!(header.sid, 12345);
    assert_eq!(header.length, 13);
}

#[tokio::test]
async fn test_allocator() {
    use smux_rust::alloc::Allocator;
    
    let alloc = Allocator::new();
    
    // 测试分配
    let buf1 = alloc.get(100).await.unwrap();
    assert_eq!(buf1.len(), 100);
    assert!(buf1.capacity() >= 100);
    let cap1 = buf1.capacity();
    
    // 测试回收和重用
    alloc.put(buf1).await.unwrap();
    let buf2 = alloc.get(100).await.unwrap();
    assert_eq!(buf2.capacity(), cap1);
    assert_eq!(buf2.len(), 100);
    
    // 测试不同大小的分配
    let buf3 = alloc.get(1000).await.unwrap();
    assert_eq!(buf3.len(), 1000);
    assert!(buf3.capacity() >= 1000);
    alloc.put(buf3).await.unwrap();
    
    // 测试无效大小
    assert!(alloc.get(0).await.is_none());
    assert!(alloc.get(70000).await.is_none());
}

#[tokio::test]
async fn test_shaper_queue() {
    use smux_rust::shaper::{ShaperQueue, WriteRequest, ClassId};
    use smux_rust::frame::{Frame, Cmd};
    
    let mut queue = ShaperQueue::new();
    
    // 创建一些请求
    let req1 = WriteRequest {
        class: ClassId::Data,
        frame: Frame::new(1, Cmd::Psh, 1),
        seq: 1,
    };
    
    let req2 = WriteRequest {
        class: ClassId::Ctrl,
        frame: Frame::new(1, Cmd::Syn, 2),
        seq: 2,
    };
    
    let req3 = WriteRequest {
        class: ClassId::Data,
        frame: Frame::new(1, Cmd::Psh, 3),
        seq: 3,
    };
    
    // 测试推送和弹出
    queue.push(req1.clone()).await;
    queue.push(req2.clone()).await;
    queue.push(req3.clone()).await;
    
    assert_eq!(queue.len().await, 3);
    
    // 控制帧应该优先
    let popped = queue.pop().await;
    assert!(popped.is_some());
    let popped_req = popped.unwrap();
    assert_eq!(popped_req.class, ClassId::Ctrl);
    
    // 继续弹出
    let popped2 = queue.pop().await;
    assert!(popped2.is_some());
    
    let popped3 = queue.pop().await;
    assert!(popped3.is_some());
    
    // 队列应该为空
    assert!(queue.is_empty().await);
}

// 注意:以下测试需要真实的网络连接,在实际环境中运行
// 这里提供测试框架,但需要真实的 TCP 连接才能完全测试