use crate::{
rr::{ServiceBinding, ServiceParameter},
DomainName,
};
use std::{
collections::BTreeSet,
net::{Ipv4Addr, Ipv6Addr},
str::FromStr,
};
#[test]
fn test_https_alias_form() {
let domain_name = "example.com".parse().unwrap();
let target_name = "foo.example.com".parse().unwrap();
let service_binding = ServiceBinding {
name: domain_name,
ttl: 7200,
priority: 0, target_name,
parameters: BTreeSet::default(),
https: true,
};
let result = service_binding.to_string();
assert_eq!(
result,
"example.com. 7200 IN HTTPS 0 foo.example.com.".to_string()
);
}
#[test]
fn test_svcb_use_the_ownername() {
let domain_name = "example.com".parse().unwrap();
let target_name = DomainName::default();
let service_binding = ServiceBinding {
name: domain_name,
ttl: 300,
priority: 1,
target_name,
parameters: BTreeSet::default(),
https: false,
};
let result = service_binding.to_string();
assert_eq!(result, "example.com. 300 IN SVCB 1 .");
}
#[test]
fn test_https_map_port() {
let domain_name = "example.com".parse().unwrap();
let target_name = "foo.example.com".parse().unwrap();
let service_binding = ServiceBinding {
name: domain_name,
ttl: 7200,
priority: 16,
target_name,
parameters: vec![ServiceParameter::PORT { port: 53 }]
.into_iter()
.collect::<BTreeSet<ServiceParameter>>(),
https: true,
};
let result = service_binding.to_string();
assert_eq!(
result,
"example.com. 7200 IN HTTPS 16 foo.example.com. port=53"
);
}
#[test]
fn test_svcb_unregistered_key_value() {
let domain_name = "example.com".parse().unwrap();
let target_name = "foo.example.com".parse().unwrap();
let service_binding = ServiceBinding {
name: domain_name,
ttl: 300,
priority: 1,
target_name,
parameters: vec![ServiceParameter::PRIVATE {
number: 667,
wire_data: b"hello".to_vec(),
}]
.into_iter()
.collect::<BTreeSet<ServiceParameter>>(),
https: false,
};
let result = service_binding.to_string();
assert_eq!(
result,
"example.com. 300 IN SVCB 1 foo.example.com. key667=hello"
);
}
#[test]
fn test_https_unregistered_key_escaped_value() {
let domain_name = "example.com".parse().unwrap();
let target_name = "foo.example.com".parse().unwrap();
let service_binding = ServiceBinding {
name: domain_name,
ttl: 300,
priority: 1,
target_name,
parameters: vec![ServiceParameter::PRIVATE {
number: 667,
wire_data: b"hello\xd2qoo".to_vec(),
}]
.into_iter()
.collect::<BTreeSet<ServiceParameter>>(),
https: true,
};
let result = service_binding.to_string();
assert_eq!(
result,
"example.com. 300 IN HTTPS 1 foo.example.com. key667=\"hello\\210qoo\""
);
}
#[test]
fn test_svcb_ipv6_hints() {
let domain_name = "example.com".parse().unwrap();
let target_name = "foo.example.com".parse().unwrap();
let service_binding = ServiceBinding {
name: domain_name,
ttl: 7200,
priority: 1,
target_name,
parameters: vec![ServiceParameter::IPV6_HINT {
hints: vec![
Ipv6Addr::from_str("2001:db8::1").unwrap(),
Ipv6Addr::from_str("2001:db8::53:1").unwrap(),
],
}]
.into_iter()
.collect::<BTreeSet<ServiceParameter>>(),
https: false,
};
let result = service_binding.to_string();
assert_eq!(
result,
"example.com. 7200 IN SVCB 1 foo.example.com. ipv6hint=\"2001:db8::1,2001:db8::53:1\""
);
}
#[test]
fn test_https_ipv6_hint_in_ipv4_mapped_ipv6_format() {
let domain_name = "example.com".parse().unwrap();
let target_name = "foo.example.com".parse().unwrap();
let service_binding = ServiceBinding {
name: domain_name,
ttl: 300,
priority: 1,
target_name,
parameters: vec![ServiceParameter::IPV6_HINT {
hints: vec![Ipv6Addr::from_str("2001:db8:ffff:ffff:ffff:ffff:198.51.100.100").unwrap()],
}]
.into_iter()
.collect::<BTreeSet<ServiceParameter>>(),
https: true,
};
let result = service_binding.to_string();
assert_eq!(result,
"example.com. 300 IN HTTPS 1 foo.example.com. ipv6hint=\"2001:db8:ffff:ffff:ffff:ffff:c633:6464\"");
}
#[test]
fn test_svcb_multiple_parameters_in_wrong_order() {
let domain_name = "example.org".parse().unwrap();
let target_name = "foo.example.org".parse().unwrap();
let service_binding = ServiceBinding {
name: domain_name,
ttl: 7200,
priority: 16,
target_name,
parameters: vec![
ServiceParameter::ALPN {
alpn_ids: vec!["h2".to_string(), "h3-19".to_string()],
},
ServiceParameter::MANDATORY {
key_ids: vec![4, 1], },
ServiceParameter::IPV4_HINT {
hints: vec![Ipv4Addr::from_str("192.0.2.1").unwrap()],
},
]
.into_iter()
.collect::<BTreeSet<ServiceParameter>>(),
https: false,
};
let result = service_binding.to_string();
assert_eq!(result,
"example.org. 7200 IN SVCB 16 foo.example.org. mandatory=alpn,ipv4hint alpn=h2,h3-19 ipv4hint=192.0.2.1");
}
#[test]
fn test_https_alpn_with_escaped_values() {
let domain_name = "example.org".parse().unwrap();
let target_name = "foo.example.org".parse().unwrap();
let service_binding = ServiceBinding {
name: domain_name,
ttl: 300,
priority: 16,
target_name,
parameters: vec![ServiceParameter::ALPN {
alpn_ids: vec!["f\\oo,bar".to_string(), "h2".to_string()],
}]
.into_iter()
.collect::<BTreeSet<ServiceParameter>>(),
https: true,
};
let result = service_binding.to_string();
assert_eq!(
result,
"example.org. 300 IN HTTPS 16 foo.example.org. alpn=\"f\\\\\\\\oo\\,bar,h2\""
);
}