Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more tests from RFC8949. #110

Merged
merged 1 commit into from
Feb 19, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 132 additions & 4 deletions ciborium/tests/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ use ciborium::{
value::Value,
};
use rstest::rstest;
use std::io::ErrorKind;

fn eof() -> Error<std::io::Error> {
Error::Io(ErrorKind::UnexpectedEof.into())
}

#[rstest(bytes, error,
// Invalid value
Expand All @@ -28,20 +33,143 @@ use rstest::rstest;

// Invalid UTF-8 in a string continuation
case("7F62C328FF", Error::Syntax(1)),

// End of input in a head
case("18", eof()),
case("19", eof()),
case("1a", eof()),
case("1b", eof()),
case("1901", eof()),
case("1a0102", eof()),
case("1b01020304050607", eof()),
case("38", eof()),
case("58", eof()),
case("78", eof()),
case("98", eof()),
case("9a01ff00", eof()),
case("b8", eof()),
case("d8", eof()),
case("f8", eof()),
case("f900", eof()),
case("fa0000", eof()),
case("fb000000", eof()),

// Definite-length strings with short data:
case("41", eof()),
case("61", eof()),
case("5affffffff00", eof()),
case("5bffffffffffffffff010203", eof()),
case("7affffffff00", eof()),
case("7b7fffffffffffffff010203", eof()),

// Definite-length maps and arrays not closed with enough items:
case("81", eof()),
case("818181818181818181", eof()),
case("8200", eof()),
case("a1", eof()),
case("a20102", eof()),
case("a100", eof()),
case("a2000000", eof()),

// Tag number not followed by tag content:
case("c0", eof()),

// Indefinite-length strings not closed by a "break" stop code:
case("5f4100", eof()),
case("7f6100", eof()),

// Indefinite-length maps and arrays not closed by a "break" stop code:
case("9f", eof()),
case("9f0102", eof()),
case("bf", eof()),
case("bf01020102", eof()),
case("819f", eof()),
case("9f8000", eof()),
case("9f9f9f9f9fffffffff", eof()),
case("9f819f819f9fffffff", eof()),

// Reserved additional information values:
case("1c", Error::Syntax(0)),
case("1d", Error::Syntax(0)),
case("1e", Error::Syntax(0)),
case("3c", Error::Syntax(0)),
case("3d", Error::Syntax(0)),
case("3e", Error::Syntax(0)),
case("5c", Error::Syntax(0)),
case("5d", Error::Syntax(0)),
case("5e", Error::Syntax(0)),
case("7c", Error::Syntax(0)),
case("7d", Error::Syntax(0)),
case("7e", Error::Syntax(0)),
case("9c", Error::Syntax(0)),
case("9d", Error::Syntax(0)),
case("9e", Error::Syntax(0)),
case("bc", Error::Syntax(0)),
case("bd", Error::Syntax(0)),
case("be", Error::Syntax(0)),
case("dc", Error::Syntax(0)),
case("dd", Error::Syntax(0)),
case("de", Error::Syntax(0)),
case("fc", Error::Syntax(0)),
case("fd", Error::Syntax(0)),
case("fe", Error::Syntax(0)),

// Reserved two-byte encodings of simple values:
case("f800", Error::Semantic(None, "invalid type: simple, expected known simple value".into())),
case("f801", Error::Semantic(None, "invalid type: simple, expected known simple value".into())),
case("f818", Error::Semantic(None, "invalid type: simple, expected known simple value".into())),
case("f81f", Error::Semantic(None, "invalid type: simple, expected known simple value".into())),

// Indefinite-length string chunks not of the correct type:
case("5f00ff", Error::Syntax(1)),
case("5f21ff", Error::Syntax(1)),
case("5f6100ff", Error::Syntax(1)),
case("5f80ff", Error::Syntax(1)),
case("5fa0ff", Error::Syntax(1)),
case("5fc000ff", Error::Syntax(1)),
case("5fe0ff", Error::Syntax(1)),
case("7f4100ff", Error::Syntax(1)),

// Indefinite-length string chunks not definite length:
//case("5f5f4100ffff", Error::Syntax(0)), These should fail, but do not currently.
//case("7f7f6100ffff", Error::Syntax(0)),

// Break occurring on its own outside of an indefinite-length item:
case("ff", Error::Semantic(None, "invalid type: break, expected non-break".into())),

// Break occurring in a definite-length array or map or a tag:
case("81ff", Error::Semantic(None, "invalid type: break, expected non-break".into())),
case("8200ff", Error::Semantic(None, "invalid type: break, expected non-break".into())),
case("a1ff", Error::Semantic(None, "invalid type: break, expected non-break".into())),
case("a1ff00", Error::Semantic(None, "invalid type: break, expected non-break".into())),
case("a100ff", Error::Semantic(None, "invalid type: break, expected non-break".into())),
case("a20000ff", Error::Semantic(None, "invalid type: break, expected non-break".into())),
case("9f81ff", Error::Semantic(None, "invalid type: break, expected non-break".into())),
case("9f829f819f9fffffffff", Error::Semantic(None, "invalid type: break, expected non-break".into())),

// Break in an indefinite-length map that would lead to an odd number of items (break in a value position):
case("bf00ff", Error::Semantic(None, "invalid type: break, expected non-break".into())),
case("bf000000ff", Error::Semantic(None, "invalid type: break, expected non-break".into())),

// Major type 0, 1, 6 with additional information 31:
case("1f", Error::Syntax(0)),
case("3f", Error::Syntax(0)),
case("df", Error::Syntax(0)),
)]
fn test(bytes: &str, error: Error<std::io::Error>) {
let bytes = hex::decode(bytes).unwrap();

// Due to no_std support, pretend that all io errors are EOF
let correct = match error {
Error::Io(..) => panic!(),
Error::Io(..) => ("io", None, None),
Error::Syntax(x) => ("syntax", Some(x), None),
Error::Semantic(x, y) => ("semantic", x, Some(y)),
Error::RecursionLimitExceeded => panic!(),
};

let result: Result<Value, _> = from_reader(&bytes[..]);
let actual = match result.unwrap_err() {
Error::Io(..) => panic!(),
let result: Result<Value, _> = from_reader(dbg!(&bytes[..]));
let actual = match dbg!(result.unwrap_err()) {
Error::Io(..) => ("io", None, None),
Error::Syntax(x) => ("syntax", Some(x), None),
Error::Semantic(x, y) => ("semantic", x, Some(y)),
Error::RecursionLimitExceeded => panic!(),
Expand Down
Loading