wsb-daemon 0.275.7622

wsb's daemon: the workbench, the GitHub mirror's schedule and peer continuity, for every workspace on the machine
use super::*;
use tokio::io::{AsyncWriteExt, BufReader};

/// TEST20079: messages are read whole, however the bytes arrive, and a malformed stream is
/// an error, never a guessed message.
#[tokio::test]
async fn test20079_messages_are_read_whole_or_refused() {
    let (mut tx, rx) = tokio::io::duplex(64);
    let mut reader = BufReader::new(rx);
    let one = serde_json::json!({ "jsonrpc": "2.0", "id": 1, "result": { "text": "é😀" } });
    let body = serde_json::to_vec(&one).unwrap();
    tokio::spawn(async move {
        // Split mid-header and mid-body, with a header the reader does not use.
        let framed = [format!("Content-Type: application/vscode-jsonrpc\r\nContent-Length: {}\r\n\r\n", body.len()).into_bytes(), body].concat();
        for chunk in framed.chunks(7) {
            tx.write_all(chunk).await.unwrap();
            tx.flush().await.unwrap();
        }
        write(&mut tx, &serde_json::json!({ "jsonrpc": "2.0", "method": "x" })).await.unwrap();
    });
    assert_eq!(read(&mut reader).await.unwrap(), Some(one));
    assert_eq!(read(&mut reader).await.unwrap(), Some(serde_json::json!({ "jsonrpc": "2.0", "method": "x" })));
    assert!(read(&mut reader).await.unwrap().is_none(), "the end between messages is the end");

    let refused = |bytes: &'static [u8]| async move { read(&mut BufReader::new(bytes)).await };
    assert!(matches!(refused(b"Content-Type: x\r\n\r\n{}").await, Err(FramingError::NoLength)));
    assert!(matches!(refused(b"Content-Length: 10\r\n\r\n{}").await, Err(FramingError::Truncated)));
    assert!(matches!(refused(b"Content-Length: 2\r\n").await, Err(FramingError::Truncated)));
    assert!(matches!(refused(b"Content-Length: x\r\n\r\n").await, Err(FramingError::Header(_))));
    assert!(matches!(refused(b"Content-Length: 99999999999\r\n\r\n").await, Err(FramingError::TooLarge(_))));
    assert!(matches!(refused(b"Content-Length: 2\r\n\r\n{]").await, Err(FramingError::Json(_))));
}