#[cfg(kani)]
mod verification {
use std::convert::TryFrom;
use typeid_prefix::{TypeIdPrefix, Sanitize};
use kani::Arbitrary;
#[derive(Debug)]
struct TypeIdPrefixInput {
input: String,
}
impl Arbitrary for TypeIdPrefixInput {
fn any() -> Self {
let len: usize = kani::any();
kani::assume(len <= 100);
let input: String = (0..len)
.map(|_| {
let c: u8 = kani::any();
kani::assume(c.is_ascii());
c as char
})
.collect();
TypeIdPrefixInput { input }
}
}
#[kani::proof]
fn verify_typeidprefix_try_from_and_sanitize() {
let input: TypeIdPrefixInput = kani::any();
let try_from_result = TypeIdPrefix::try_from(input.input.clone());
let sanitized = input.input.create_prefix_sanitized();
if input.input.len() > 63 {
kani::assert(try_from_result.is_err(), "Input length exceeds 63 characters, should be error.");
} else if input.input.is_empty() {
kani::assert(try_from_result.is_ok(), "Empty input should be ok.");
} else {
let is_ascii = input.input.is_ascii();
let starts_with_valid_char = input.input.chars().next().map_or(false, |c| c.is_ascii_lowercase());
let ends_with_valid_char = input.input.chars().last().map_or(false, |c| c.is_ascii_lowercase());
let contains_only_valid_chars = input.input.chars().all(|c| c.is_ascii_lowercase() || c == '_');
if !is_ascii || !starts_with_valid_char || !ends_with_valid_char || !contains_only_valid_chars {
kani::assert(try_from_result.is_err(), "Invalid input should be error.");
} else {
kani::assert(try_from_result.is_ok(), "Valid input should be ok.");
}
}
kani::assert(sanitized.len() <= 63, "Sanitized output should not exceed 63 characters.");
kani::assert(sanitized.chars().all(|c| c.is_ascii_lowercase() || c == '_'), "Sanitized output should only contain lowercase ASCII or underscore.");
kani::assert(!sanitized.starts_with('_'), "Sanitized output should not start with underscore.");
kani::assert(!sanitized.ends_with('_'), "Sanitized output should not end with underscore.");
kani::assert(TypeIdPrefix::try_from(sanitized.as_str()).is_ok(), "Sanitized output should always be valid.");
if try_from_result.is_ok() {
kani::assert(input.input == sanitized, "Valid input should match its sanitized version.");
}
}
#[kani::proof]
fn verify_typeidprefix_try_from_str_and_sanitize() {
let input: TypeIdPrefixInput = kani::any();
let try_from_result = TypeIdPrefix::try_from(input.input.as_str());
let sanitized = input.input.create_prefix_sanitized();
if input.input.len() > 63 {
kani::assert(try_from_result.is_err(), "Input length exceeds 63 characters, should be error.");
} else if input.input.is_empty() {
kani::assert(try_from_result.is_ok(), "Empty input should be ok.");
} else {
let is_ascii = input.input.is_ascii();
let starts_with_valid_char = input.input.chars().next().map_or(false, |c| c.is_ascii_lowercase());
let ends_with_valid_char = input.input.chars().last().map_or(false, |c| c.is_ascii_lowercase());
let contains_only_valid_chars = input.input.chars().all(|c| c.is_ascii_lowercase() || c == '_');
if !is_ascii || !starts_with_valid_char || !ends_with_valid_char || !contains_only_valid_chars {
kani::assert(try_from_result.is_err(), "Invalid input should be error.");
} else {
kani::assert(try_from_result.is_ok(), "Valid input should be ok.");
}
}
kani::assert(sanitized.len() <= 63, "Sanitized output should not exceed 63 characters.");
kani::assert(sanitized.chars().all(|c| c.is_ascii_lowercase() || c == '_'), "Sanitized output should only contain lowercase ASCII or underscore.");
kani::assert(!sanitized.starts_with('_'), "Sanitized output should not start with underscore.");
kani::assert(!sanitized.ends_with('_'), "Sanitized output should not end with underscore.");
kani::assert(TypeIdPrefix::try_from(sanitized.as_str()).is_ok(), "Sanitized output should always be valid.");
if try_from_result.is_ok() {
kani::assert(input.input == sanitized, "Valid input should match its sanitized version.");
}
}
}