rust-dnsbox/lib/dnsbox-base/src/records/tests.rs

131 lines
3.9 KiB
Rust

use bytes::{Bytes, Buf};
use common_types::classes;
use failure::ResultExt;
use records::structs;
use ser::{packet, text, StaticRRData};
use std::fmt;
use std::io::Cursor;
fn rrdata_de<T>(data: &'static [u8]) -> ::errors::Result<T>
where
T: StaticRRData
{
let mut data = Cursor::new(Bytes::from_static(data));
let result = T::deserialize_rr_data(3600, classes::IN, T::TYPE, &mut data)?;
ensure!(!data.has_remaining(), "rrdata not read completely");
Ok(result)
}
fn rrdata_parse<T>(data: &str) -> ::errors::Result<T>
where
T: StaticRRData
{
let mut data = data;
let result = T::dns_parse_rr_data(3600, classes::IN, T::TYPE, &mut data)?;
let data = data.trim();
ensure!(data.is_empty(), "didn't parse complete rrdata text, remaining: {:?}", data);
Ok(result)
}
fn check<T>(txt: &str, data: &'static [u8]) -> ::errors::Result<()>
where
T: StaticRRData + fmt::Debug + PartialEq
{
let d1: T = rrdata_de(data).context("couldn't parse binary record")?;
let d2: T = rrdata_parse(txt).context("couldn't parse text record")?;
ensure!(d1 == d2, "decoded data not equal: {:?} != {:?}", d1, d2);
Ok(())
}
fn check2<T>(txt: &str, data: &'static [u8], canon: &str) -> ::errors::Result<()>
where
T: StaticRRData + fmt::Debug + PartialEq
{
let d1: T = rrdata_de(data).context("couldn't parse binary record")?;
let d2: T = rrdata_parse(txt).context("couldn't parse text record")?;
ensure!(d1 == d2, "decoded data not equal: {:?} != {:?}", d1, d2);
Ok(())
}
#[test]
fn test_a() {
check::<structs::A>("127.0.0.1", b"\x7f\x00\x00\x01").unwrap();
}
fn test_txt_for<T>()
where
T: StaticRRData + fmt::Debug + PartialEq
{
// at least one "segment" (which could be empty)
check2::<T>(r#" "" "#, b"", r#" "" "#).unwrap_err();
check2::<T>(r#""#, b"\x00", r#" "" "#).unwrap_err();
// one empty segment
check2::<T>(r#" "" "#, b"\x00", r#" "" "#).unwrap();
// one segment
check::<T>(r#" "foo" "#, b"\x03foo").unwrap();
// two segments
check::<T>(r#" "foo" "bar!" "#, b"\x03foo\x04bar!").unwrap();
// segment with too many bytes in text form
{
let mut s = String::new();
s.push('"');
for _ in 0..256 { s.push('a'); }
s.push('"');
rrdata_parse::<T>(&s).unwrap_err();
}
}
#[test]
fn test_txt() {
test_txt_for::<structs::TXT>();
}
#[test]
fn test_ds() {
check::<structs::DS>(" 1 2 3 ", b"\x00\x01\x02\x03").unwrap();
check::<structs::DS>(" 1 2 3 abcd", b"\x00\x01\x02\x03\xab\xcd").unwrap();
check::<structs::DS>(" 1 2 3 a b c d", b"\x00\x01\x02\x03\xab\xcd").unwrap();
}
#[test]
fn test_nsec() {
check::<structs::NSEC>("foo.bar. ", b"\x03foo\x03bar\x00").unwrap();
check::<structs::NSEC>("foo.bar. A NS ", b"\x03foo\x03bar\x00\x00\x01\x60").unwrap();
check::<structs::NSEC>("foo.bar. A NS TYPE256 TYPE65280 ", b"\x03foo\x03bar\x00\x00\x01\x60\x01\x01\x80\xff\x01\x80").unwrap();
}
#[test]
fn test_dnskey() {
check::<structs::DNSKEY>("256 2 3", b"\x01\x00\x02\x03").unwrap();
check::<structs::DNSKEY>("256 2 3 /w==", b"\x01\x00\x02\x03\xff").unwrap();
check::<structs::DNSKEY>("256 2 3 /w ==", b"\x01\x00\x02\x03\xff").unwrap();
}
#[test]
fn test_nsec3() {
check::<structs::NSEC3>("1 2 300 - vs", b"\x01\x02\x01\x2c\x00\x01\xff").unwrap();
check::<structs::NSEC3>("1 2 300 - vs A NS", b"\x01\x02\x01\x2c\x00\x01\xff\x00\x01\x60").unwrap();
check::<structs::NSEC3>("1 2 300 ab vs A NS", b"\x01\x02\x01\x2c\x01\xab\x01\xff\x00\x01\x60").unwrap();
// invalid base32 texts
text::parse::<structs::NSEC3>("1 2 300 - v").unwrap_err();
text::parse::<structs::NSEC3>("1 2 300 - vv").unwrap_err();
// invalid (empty) next-hashed values
packet::deserialize::<structs::NSEC3>(Bytes::from_static(b"\x01\x02\x01\x2c\x00\x00")).unwrap_err();
}
#[test]
fn test_nsec3param() {
check::<structs::NSEC3PARAM>("1 2 300 -", b"\x01\x02\x01\x2c\x00").unwrap();
check::<structs::NSEC3PARAM>("1 2 300 ab", b"\x01\x02\x01\x2c\x01\xab").unwrap();
// `salt` hex string must not contain spaces
text::parse::<structs::NSEC3PARAM>("1 2 300 a b").unwrap_err();
}
#[test]
fn test_spf() {
test_txt_for::<structs::SPF>();
}