use nextjson::formats;
use nextjson::formats::Format;
use nextjson::{Decoder, Encoder, Error, NsonDeserialize, Number, Token, Value, Write};
#[test]
fn lexer_error_branches() {
for bad in [r#""\q""#, r#""\x""#, r#""\u12""#, r#""\u""#] {
assert!(
nextjson::from_str::<Value>(bad).is_err(),
"accepted escape {bad:?}"
);
}
assert!(nextjson::from_str::<Value>(r#""\ud800""#).is_err());
assert!(nextjson::from_str::<Value>(r#""\udfff""#).is_err());
assert!(nextjson::from_str::<Value>("\"a\u{01}b\"").is_err());
assert!(nextjson::from_slice::<Value>(&[b'"', 0xC3, 0x28, b'"']).is_err());
for bad in [
"01", "1.", ".5", "1e", "+1", "--1", "1..2", "1e+", "0x10", "1_0", "-",
] {
assert!(
nextjson::from_str::<Value>(bad).is_err(),
"accepted number {bad:?}"
);
}
let huge = "9".repeat(60);
assert!(nextjson::from_str::<Number>(&huge).is_err());
for bad in ["tru", "nul", "truE", "]", "}", ",", ":", ""] {
assert!(
nextjson::from_str::<Value>(bad).is_err(),
"accepted {bad:?}"
);
}
}
#[test]
fn decoder_container_error_branches() {
for bad in [r#"{1:2}"#, r#"{true:2}"#, r#"{null:2}"#, r#"{[1]:2}"#] {
assert!(
nextjson::from_str::<Value>(bad).is_err(),
"accepted key form {bad:?}"
);
}
assert!(nextjson::from_str::<Value>(r#"{"a" 1}"#).is_err());
assert!(nextjson::from_str::<Value>(r#"{"a":}"#).is_err());
assert!(nextjson::from_str::<Value>(r#"[1 2]"#).is_err());
assert!(nextjson::from_str::<Value>(r#"{"a":1"#).is_err());
assert!(nextjson::from_str::<Value>(r#"[1,2"#).is_err());
assert!(nextjson::from_str::<Value>(r#"{"a":1,}"#).is_err());
assert!(nextjson::from_str::<Value>(r#"[,]"#).is_err());
assert!(nextjson::from_str::<Value>(r#"{"a":1,,}"#).is_err());
let deep = "[".repeat(200) + &"]".repeat(200);
assert!(nextjson::from_str::<Value>(&deep).is_err());
assert!(nextjson::from_str::<char>(r#""ab""#).is_err());
assert!(nextjson::from_str::<char>(r#"1"#).is_err());
assert!(nextjson::from_str::<bool>(r#"1"#).is_err());
assert!(nextjson::from_str::<()>(r#"1"#).is_err());
assert!(nextjson::from_str::<u32>(r#""x""#).is_err());
assert!(nextjson::from_str::<i32>(r#"1.5"#).is_err());
}
#[test]
fn tree_decoder_paths() {
let toks = vec![
Token::BeginObject,
Token::Str("a".into()),
Token::Number(Number::from(1_i64)),
Token::EndObject,
];
let mut d = Decoder::from_tokens(toks);
let v = Value::nextdecode(&mut d).unwrap();
assert_eq!(v["a"], Value::from(1_i64));
d.end().unwrap();
let mut d = Decoder::from_tokens(vec![Token::BeginObject]);
assert!(Value::nextdecode(&mut d).is_err());
let toks = vec![
Token::BeginObject,
Token::Str("a".into()),
Token::Number(Number::from(1_i64)),
Token::EndObject,
];
let mut d = Decoder::from_tokens(toks);
let mark = d.save();
let v = Value::nextdecode(&mut d).unwrap();
assert_eq!(v["a"], Value::from(1_i64));
d.restore(mark);
let v2 = Value::nextdecode(&mut d).unwrap();
assert_eq!(v2, v);
}
struct Sink(Vec<u8>);
impl Write for Sink {
fn write_all(&mut self, buf: &[u8]) -> Result<(), Error> {
self.0.extend_from_slice(buf);
Ok(())
}
fn flush(&mut self) -> Result<(), Error> {
Ok(())
}
}
fn validating() -> Encoder<Sink, true> {
Encoder::<_, true>::new(Sink(Vec::new()))
}
#[test]
fn checked_encoder_protocol_errors() {
let mut e = validating();
e.write_u64(1).unwrap();
assert!(e.write_u64(2).is_err());
e.finish().unwrap();
let mut e = validating();
e.begin_array().unwrap();
e.separator().unwrap();
assert!(e.end_array().is_err());
let mut e = validating();
e.begin_array().unwrap();
assert!(e.key("k").is_err());
let mut e = validating();
e.begin_object().unwrap();
e.key("a").unwrap();
assert!(e.key("b").is_err());
let mut e = validating();
e.begin_object().unwrap();
assert!(e.write_u64(1).is_err());
let mut e = validating();
e.begin_object().unwrap();
e.key("a").unwrap();
assert!(e.end_object().is_err());
let mut e = validating();
e.begin_array().unwrap();
e.separator().unwrap();
e.begin_object().unwrap();
assert!(e.end_array().is_err());
let mut e = validating();
assert!(e.end_object().is_err());
let e = validating();
assert!(e.finish().is_err());
}
struct OneByte<R>(R);
impl<R: std::io::Read> std::io::Read for OneByte<R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
if buf.is_empty() {
return Ok(0);
}
let mut one = [0u8; 1];
let n = self.0.read(&mut one)?;
if n > 0 {
buf[0] = one[0];
}
Ok(n)
}
}
#[test]
fn stream_decoder_single_byte_chunks() {
let input = br#"{"a":[1,2,"x"],"b":true,"c":1.5}"#;
let v: Value = nextjson::from_reader(OneByte(&input[..])).unwrap();
assert_eq!(v["a"][2], Value::from("x"));
assert_eq!(v["b"], Value::from(true));
assert_eq!(v["c"], Value::from(1.5_f64));
}
#[test]
fn stream_decoder_truncated_input_errors() {
let input = br#"{"a":[1,2"#;
assert!(nextjson::from_reader::<_, Value>(OneByte(&input[..])).is_err());
}
#[test]
fn yaml_feature_error_branches() {
assert!(formats::Yaml.decode::<Value>(b"a: !!int xyz\n").is_err());
assert!(formats::Yaml.decode::<Value>(b"a: !!float zz\n").is_err());
assert!(formats::Yaml.decode::<Value>(b"a: !!bool maybe\n").is_err());
assert!(formats::Yaml.decode::<Value>(b"a: !!float .inf\n").is_err());
assert!(formats::Yaml.decode::<Value>(b"a: !!nope x\n").is_err());
assert!(formats::Yaml.decode::<Value>(b"a: &\n").is_err());
assert!(formats::Yaml.decode::<Value>(b"a: *x y\n").is_err());
assert!(formats::Yaml.decode::<Value>(b"a: *missing\n").is_err());
assert!(formats::Yaml.decode::<Value>(b"a:\n <<: 42\n").is_err());
assert!(formats::Yaml.decode::<Value>(b"a: |x\n v\n").is_err());
assert!(formats::Yaml.decode::<Value>(b"a: .inf\n").is_err());
assert!(formats::Yaml.decode::<Value>(b"a: -.inf\n").is_err());
assert!(formats::Yaml.decode::<Value>(b"a: .nan\n").is_err());
assert!(formats::Yaml.decode::<Value>(b"a: [*x]\n").is_err());
assert!(formats::Yaml.decode::<Value>(b"a: {x: &a 1}\n").is_err());
assert!(formats::Yaml.decode::<Value>(b"a: 1\nb: 2\n").is_ok());
assert!(formats::Yaml
.decode::<Value>(b"a:\n b: 1\n c: 2\n")
.is_err());
}
#[test]
fn yaml_block_scalar_edge_cases() {
let v: Value = formats::Yaml.decode(b"a: |+\n x\n").unwrap();
assert_eq!(v["a"], Value::from("x\n"));
let v: Value = formats::Yaml.decode(b"a: >\n one\n\n two\n").unwrap();
assert_eq!(v["a"], Value::from("one\ntwo\n"));
let v: Value = formats::Yaml.decode(b"a: |1\n x\n").unwrap();
assert_eq!(v["a"], Value::from(" x\n"));
let v: Value = formats::Yaml.decode(b"a: &t |\n x\nb: *t\n").unwrap();
assert_eq!(v["a"], v["b"]);
}
#[test]
fn toml_radix_and_string_error_branches() {
assert!(formats::Toml.decode::<Value>(b"x = 0xZZ\n").is_err());
assert!(formats::Toml.decode::<Value>(b"x = 0o9\n").is_err());
assert!(formats::Toml.decode::<Value>(b"x = 0b2\n").is_err());
assert!(formats::Toml.decode::<Value>(b"x = \"\"\"abc\n").is_err());
assert!(formats::Toml.decode::<Value>(b"x = '''abc\n").is_err());
assert!(formats::Toml
.decode::<Value>(b"x = \"\"\"a\\qb\"\"\"\n")
.is_err());
assert!(formats::Toml
.decode::<Value>(b"x = \"\"\"a\\u12\"\"\"\n")
.is_err());
for bad in [
"2020-13-99",
"1979-05-27T25:00:00",
"07:99:00",
"1979-05-27T07:00:00+99:00",
] {
let input = format!("x = {bad}\n");
assert!(
formats::Toml.decode::<Value>(input.as_bytes()).is_err(),
"accepted bad datetime {bad:?}"
);
}
}