use std::any::TypeId;
use crate::response::autnum::Autnum;
use super::{
string::StringCheck, Check, CheckParams, Checks, GetChecks, GetGroupChecks, RdapStructure,
};
impl GetChecks for Autnum {
fn get_checks(&self, index: Option<usize>, params: CheckParams) -> super::Checks {
let sub_checks = {
let mut sub_checks: Vec<Checks> = vec![];
sub_checks.append(&mut GetGroupChecks::get_group_checks(
&self.common,
params.from_parent(TypeId::of::<Self>()),
));
sub_checks.append(
&mut self
.object_common
.get_group_checks(params.from_parent(TypeId::of::<Self>())),
);
sub_checks
};
let mut items = vec![];
if self.start_autnum.is_none() || self.end_autnum.is_none() {
items.push(Check::AutnumMissing.check_item())
}
if let Some(start_num) = &self.start_autnum.as_ref().and_then(|n| n.as_u32()) {
if let Some(end_num) = &self.end_autnum.as_ref().and_then(|n| n.as_u32()) {
if start_num > end_num {
items.push(Check::AutnumEndBeforeStart.check_item())
}
if is_autnum_reserved(*start_num) || is_autnum_reserved(*end_num) {
items.push(Check::AutnumReserved.check_item())
}
if is_autnum_documentation(*start_num) || is_autnum_documentation(*end_num) {
items.push(Check::AutnumDocumentation.check_item())
}
if is_autnum_private_use(*start_num) || is_autnum_private_use(*end_num) {
items.push(Check::AutnumPrivateUse.check_item())
}
}
}
if let Some(name) = &self.name {
if name.is_whitespace_or_empty() {
items.push(Check::NetworkOrAutnumNameIsEmpty.check_item())
}
if name.is_number() || name.is_bool() {
items.push(Check::NetworkOrAutnumNameIsNotString.check_item())
}
}
if let Some(autnum_type) = &self.autnum_type {
if autnum_type.is_whitespace_or_empty() {
items.push(Check::NetworkOrAutnumTypeIsEmpty.check_item())
}
if autnum_type.is_number() || autnum_type.is_bool() {
items.push(Check::NetworkOrAutnumTypeIsNotString.check_item())
}
}
if let Some(country) = &self.country {
if country.is_number() || country.is_bool() {
items.push(Check::NetworkOrAutnumCountryIsNotString.check_item())
}
}
Checks {
rdap_struct: RdapStructure::Autnum,
index,
items,
sub_checks,
}
}
}
pub fn is_autnum_reserved(autnum: u32) -> bool {
autnum == 0 || autnum == 65535 || autnum == 4294967295 || (65552..=131071).contains(&autnum)
}
pub fn is_autnum_documentation(autnum: u32) -> bool {
(64496..=64511).contains(&autnum) || (65536..=65551).contains(&autnum)
}
pub fn is_autnum_private_use(autnum: u32) -> bool {
(64512..=65534).contains(&autnum) || (4200000000..=4294967294).contains(&autnum)
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use crate::check::contains_check;
use crate::prelude::{Entity, ToResponse};
use crate::{
check::{Check, CheckParams, GetChecks},
response::{autnum::Autnum, RdapResponse},
};
use super::*;
#[test]
fn check_autnum_with_empty_name() {
let mut autnum = Autnum::builder().autnum_range(700..700).build();
autnum.name = Some("".to_string().into());
let rdap = autnum.to_response();
let checks = rdap.get_checks(None, CheckParams::for_rdap(&rdap));
dbg!(&checks);
assert!(checks
.items
.iter()
.any(|c| c.check == Check::NetworkOrAutnumNameIsEmpty));
}
#[test]
fn check_autnum_with_non_string_name() {
let json = r#"
{
"objectClassName" : "autnum",
"handle" : "XXXX-RIR",
"startAutnum" : 65536,
"endAutnum" : 65541,
"name": 1234,
"type" : "DIRECT ALLOCATION",
"status" : [ "active" ],
"country": "AU"
}
"#;
let rdap = serde_json::from_str::<RdapResponse>(json).expect("parsing JSON");
let checks = rdap.get_checks(None, CheckParams::for_rdap(&rdap));
assert!(checks
.items
.iter()
.any(|c| c.check == Check::NetworkOrAutnumNameIsNotString));
}
#[test]
fn check_autnum_with_empty_type() {
let mut autnum = Autnum::builder().autnum_range(700..700).build();
autnum.autnum_type = Some("".to_string().into());
let rdap = autnum.to_response();
let checks = rdap.get_checks(None, CheckParams::for_rdap(&rdap));
dbg!(&checks);
assert!(checks
.items
.iter()
.any(|c| c.check == Check::NetworkOrAutnumTypeIsEmpty));
}
#[test]
fn check_autnum_with_non_string_type() {
let json = r#"
{
"objectClassName" : "autnum",
"handle" : "XXXX-RIR",
"startAutnum" : 65536,
"endAutnum" : 65541,
"name": "AS-RTR-1",
"type" : 1234,
"status" : [ "active" ],
"country": "AU"
}
"#;
let rdap = serde_json::from_str::<RdapResponse>(json).expect("parsing JSON");
let checks = rdap.get_checks(None, CheckParams::for_rdap(&rdap));
assert!(checks
.items
.iter()
.any(|c| c.check == Check::NetworkOrAutnumTypeIsNotString));
}
#[test]
fn check_autnum_with_non_string_country() {
let json = r#"
{
"objectClassName" : "autnum",
"handle" : "XXXX-RIR",
"startAutnum" : 65536,
"endAutnum" : 65541,
"name": "AS-RTR-1",
"type" : "DIRECT ALLOCATION",
"status" : [ "active" ],
"country": 1234
}
"#;
let rdap = serde_json::from_str::<RdapResponse>(json).expect("parsing JSON");
let checks = rdap.get_checks(None, CheckParams::for_rdap(&rdap));
assert!(checks
.items
.iter()
.any(|c| c.check == Check::NetworkOrAutnumCountryIsNotString));
}
#[rstest]
#[case(0, true)]
#[case(65535, true)]
#[case(65552, true)]
#[case(131071, true)]
#[case(4294967295, true)]
#[case(1, false)]
#[case(65534, false)]
#[case(65551, false)]
#[case(131072, false)]
#[case(4294967294, false)]
fn check_autnum_is_reserved(#[case] autnum: u32, #[case] expected: bool) {
let actual = is_autnum_reserved(autnum);
assert_eq!(actual, expected);
}
#[rstest]
#[case(64496, true)]
#[case(64511, true)]
#[case(65536, true)]
#[case(65551, true)]
#[case(64495, false)]
#[case(64512, false)]
#[case(65535, false)]
#[case(65552, false)]
fn check_autnum_is_documentation(#[case] autnum: u32, #[case] expected: bool) {
let actual = is_autnum_documentation(autnum);
assert_eq!(actual, expected);
}
#[rstest]
#[case(64512, true)]
#[case(65534, true)]
#[case(4200000000, true)]
#[case(4294967294, true)]
#[case(65534, true)]
#[case(64511, false)]
#[case(65535, false)]
#[case(4199999999, false)]
#[case(4294967295, false)]
fn check_autnum_is_private_use(#[case] autnum: u32, #[case] expected: bool) {
let actual = is_autnum_private_use(autnum);
assert_eq!(actual, expected);
}
#[test]
fn test_autnum_with_entity_empty_handle() {
let autnum = Autnum::builder()
.autnum_range(701..703)
.entity(Entity::builder().handle("").build())
.build()
.to_response();
let checks = autnum.get_checks(None, CheckParams::for_rdap(&autnum));
assert!(contains_check(Check::HandleIsEmpty, &checks));
}
}