artcraftx/crates/schema/sqlite_identifiers/tests/media_file_token_tests.rs

195 lines
5.4 KiB
Rust

/// Test MediaFileToken in isolation, just in case our macro-derived tests break.
use serde::Deserialize;
use serde::Serialize;
use sqlite_identifiers::ids::media_file_token::MediaFileToken;
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct CompositeType {
media_file_token: MediaFileToken,
string: String,
}
mod interface {
use sqlite_identifiers::ids::media_file_token::MediaFileToken;
#[test]
fn generate() {
let token = MediaFileToken::generate();
assert!(!token.to_string().is_empty());
assert!(token.to_string().starts_with("m_"));
}
#[test]
fn generated_tokens_have_stable_format() {
for _ in 0..25 {
let token = MediaFileToken::generate();
let value = token.as_str();
assert_eq!(value.len(), 32, "token {value} should be 32 chars");
assert!(value.starts_with("m_"));
assert!(value[2..].bytes().all(|b| b"0123456789abcdefghjkmnpqrstvwxyz".contains(&b)),
"token {value} should be lowercase crockford");
}
}
#[test]
fn new() {
let token = MediaFileToken::new("m_foo".to_string());
assert_eq!(token, MediaFileToken("m_foo".to_string()));
}
#[test]
fn new_from_str() {
let token = MediaFileToken::new_from_str("m_foo");
assert_eq!(token, MediaFileToken("m_foo".to_string()));
}
#[test]
fn as_str() {
let token = MediaFileToken("m_foo".to_string());
assert_eq!(token.as_str(), "m_foo");
}
#[test]
fn to_string() {
let token = MediaFileToken("m_foo".to_string());
assert_eq!(token.to_string(), "m_foo".to_string());
}
}
mod traits {
use sqlite_identifiers::ids::media_file_token::MediaFileToken;
#[test]
fn display() {
let token = MediaFileToken("m_foo".to_string());
assert_eq!(format!("{}", token), "m_foo".to_string());
}
#[test]
fn debug() {
let token = MediaFileToken("m_foo".to_string());
assert_eq!(format!("{:?}", token), "MediaFileToken(\"m_foo\")".to_string());
}
}
mod serialization {
use sqlite_identifiers::ids::media_file_token::MediaFileToken;
use crate::CompositeType;
// NB(bt,2024-09-25): These tests are broken with a recent upgrade
// #[test]
// fn serialize() {
// let expected = "\"m_foo\"".to_string(); // NB: Quoted
//
// let token = MediaFileToken("m_foo".to_string());
// assert_eq!(expected, toml::to_string(&token).unwrap());
//
// // Just to show this serializes the same as a string
// assert_eq!(expected, toml::to_string("m_foo").unwrap());
// }
#[test]
fn nested_serialize() {
let value = CompositeType { media_file_token: MediaFileToken("m_foo".to_string()), string: "bar".to_string() };
let expected = r#"{"media_file_token":"m_foo","string":"bar"}"#.to_string();
assert_eq!(expected, serde_json::to_string(&value).unwrap());
}
}
mod deserialization {
use sqlite_identifiers::ids::media_file_token::MediaFileToken;
use crate::CompositeType;
#[test]
fn deserialize() {
let payload = "\"m_foo\""; // NB: Quoted
let expected = "m_foo".to_string();
let value: MediaFileToken = serde_json::from_str(payload).unwrap();
assert_eq!(value, MediaFileToken(expected.clone()));
// Just to show this deserializes the same way as a string
let value: String = serde_json::from_str(payload).unwrap();
assert_eq!(value, expected.clone());
}
#[test]
fn nested_deserialize() {
let payload = r#"{"media_file_token":"m_foo","string":"bar"}"#.to_string();
let expected = CompositeType {
media_file_token: MediaFileToken("m_foo".to_string()),
string: "bar".to_string(),
};
assert_eq!(expected, serde_json::from_str::<CompositeType>(&payload).unwrap());
}
}
// These traits should be tested by the macro, but we duplicate them in case that breaks
mod crockford_traits {
use sqlite_identifiers::ids::media_file_token::MediaFileToken;
const ENTROPIC_CHARACTERS_MINIMUM : usize = 8;
#[test]
fn entropy_is_sufficient() {
assert!((32 - MediaFileToken::PREFIX.len()) > ENTROPIC_CHARACTERS_MINIMUM);
}
#[test]
fn token_length() {
assert_eq!(MediaFileToken::generate().as_str().len(), 32);
}
#[test]
fn tokens_are_random() {
let mut tokens = std::collections::HashSet::new();
for _ in 0..100 {
tokens.insert(MediaFileToken::generate().to_string());
}
assert_eq!(tokens.len(), 100);
}
#[test]
fn character_set() {
let token_string = MediaFileToken::generate().to_string();
let prefix = MediaFileToken::PREFIX;
let random_part = token_string.replace(prefix, "");
assert!(random_part.len() > ENTROPIC_CHARACTERS_MINIMUM);
assert!(random_part.chars().all(|c| c.is_numeric() || c.is_lowercase()));
}
#[test]
fn prefix_ends_with_separator() {
let prefix = MediaFileToken::PREFIX;
assert!(prefix.ends_with("_"));
let token_string = MediaFileToken::generate().to_string();
assert!(token_string.contains(":") || token_string.contains("_"));
}
#[test]
fn token_begins_with_prefix() {
let prefix = MediaFileToken::PREFIX;
let token_string = MediaFileToken::generate().to_string();
assert!(token_string.starts_with(prefix));
}
#[test]
fn entropy_suffix() {
let token = MediaFileToken::new_from_str("m_foo");
assert_eq!(token.entropy_suffix(), "foo");
let token = MediaFileToken::new_from_str("bar");
assert_eq!(token.entropy_suffix(), "bar");
let token = MediaFileToken::generate();
assert_eq!(token.entropy_suffix().len(), 30);
}
}