sark-h2 0.28.2

Fiber-free HTTP/2 protocol primitives and manifold server for sark
use sark_h2::{
    frame,
    frame::{
        Ack,
        controls::{Priority, RstStream, Settings},
        layout::Header,
        numbers::{Flags, Increment, Length, ParseError, Type},
        payload::{Continuation, Payload, Ping, WindowUpdate},
    },
    stream::Id,
};

#[test]
fn ping_size_beats_protocol() {
    let h = Header {
        length: Length::new(7).expect("fixture domain"),
        kind: Type::Ping,
        flags: Flags(0),
        stream_id: Id::new(1).expect("fixture domain"),
    };
    assert!(
        Ping::parse(h, &[0u8; 7])
            == Err(ParseError::FrameSize {
                kind: frame::numbers::Type::Ping,
                actual: 7,
                expected: 8,
            })
    );
}

#[test]
fn priority_checks_size() {
    let h = Header {
        length: Length::new(4).expect("fixture domain"),
        kind: Type::Priority,
        flags: Flags(0),
        stream_id: Id::new(0).expect("fixture domain"),
    };
    assert!(
        Priority::parse(h, &[0, 0, 0, 0])
            == Err(ParseError::FrameSize {
                kind: frame::numbers::Type::Priority,
                actual: 4,
                expected: 5,
            })
    );
}

#[test]
fn rst_size_beats_protocol() {
    let h = Header {
        length: Length::new(3).expect("fixture domain"),
        kind: Type::RstStream,
        flags: Flags(0),
        stream_id: Id::new(0).expect("fixture domain"),
    };
    assert!(
        RstStream::parse(h, &[0, 0, 0])
            == Err(ParseError::FrameSize {
                kind: frame::numbers::Type::RstStream,
                actual: 3,
                expected: 4,
            })
    );
}

#[test]
fn settings_checks_size() {
    let h = Header {
        length: Length::new(5).expect("fixture domain"),
        kind: Type::Settings,
        flags: Flags(0),
        stream_id: Id::new(3).expect("fixture domain"),
    };
    assert!(
        Settings::parse(h, &[0u8; 5])
            == Err(ParseError::SettingsSize {
                actual: 5,
                ack: Ack::Required,
            })
    );
}

#[test]
fn window_r_bit() {
    let h = Header {
        length: Length::new(4).expect("fixture domain"),
        kind: Type::WindowUpdate,
        flags: Flags(0),
        stream_id: Id::new(1).expect("fixture domain"),
    };
    let result = WindowUpdate::parse(h, &[0xff, 0xff, 0xff, 0xff]);
    let w = result.expect("valid frame fixture must parse");
    assert_eq!(w.increment.get(), 0x7fff_ffff);
}

#[test]
fn cont_zero_stream() {
    let h = Header {
        length: Length::new(0).expect("fixture domain"),
        kind: Type::Continuation,
        flags: Flags(0),
        stream_id: Id::new(0).expect("fixture domain"),
    };
    assert!(
        Continuation::parse(h, &[])
            == Err(ParseError::Stream {
                kind: h.kind,
                actual: h.stream_id,
            })
    );
}

#[test]
fn parse_need_more() {
    let f = Ping {
        ack: Ack::Required,
        opaque: [9u8; 8],
    };
    let mut out = Vec::new();
    Payload::Ping(f).encode(&mut out).expect("frame allocation");
    assert!(
        Payload::parse(&out[..out.len() - 1])
            == Err(ParseError::Need {
                actual: 16,
                required: 17,
            })
    );
}

#[test]
fn parse_two() {
    let mut out = Vec::new();
    Payload::Ping(Ping {
        ack: Ack::Required,
        opaque: [1u8; 8],
    })
    .encode(&mut out)
    .expect("frame allocation");
    let first = out.len();
    Payload::WindowUpdate(WindowUpdate {
        stream_id: Id::new(0).expect("fixture domain"),
        increment: Increment::new(1024).expect("fixture domain"),
    })
    .encode(&mut out)
    .expect("frame allocation");
    let result = Payload::parse(&out);
    let (f1, n1) = result.expect("valid frame fixture must parse");
    assert_eq!(n1, first);
    assert!(matches!(f1, Payload::Ping(p) if p.opaque == [1u8; 8]));
    let result = Payload::parse(&out[n1..]);
    let (f2, n2) = result.expect("valid frame fixture must parse");
    assert_eq!(n1 + n2, out.len());
    assert!(matches!(f2, Payload::WindowUpdate(w) if w.increment.get() == 1024));
}