#![allow(
clippy::expect_used,
clippy::unwrap_used,
clippy::panic,
clippy::indexing_slicing,
clippy::too_many_lines,
clippy::similar_names,
clippy::uninlined_format_args,
clippy::cast_possible_wrap,
clippy::trivial_regex,
clippy::significant_drop_tightening,
clippy::items_after_statements
)]
mod redb_tests {
use redb::{Database, MultimapTableDefinition, ReadableTableMetadata, TableDefinition};
use tempfile::NamedTempFile;
const TABLE: TableDefinition<&str, &[u8]> = TableDefinition::new("test");
const MULTIMAP: MultimapTableDefinition<&str, &str> = MultimapTableDefinition::new("multi");
#[test]
fn test_01_redb_write_read_roundtrip() {
let tmp = NamedTempFile::new().unwrap();
let db = Database::create(tmp.path()).unwrap();
let txn = db.begin_write().unwrap();
{
let mut table = txn.open_table(TABLE).unwrap();
table.insert("key-1", b"value-1".as_slice()).unwrap();
}
txn.commit().unwrap();
let txn = db.begin_read().unwrap();
let table = txn.open_table(TABLE).unwrap();
let val = table.get("key-1").unwrap().unwrap();
assert_eq!(val.value(), b"value-1");
}
#[test]
fn test_02_redb_overwrite() {
let tmp = NamedTempFile::new().unwrap();
let db = Database::create(tmp.path()).unwrap();
let txn = db.begin_write().unwrap();
{
let mut table = txn.open_table(TABLE).unwrap();
table.insert("k", b"v1".as_slice()).unwrap();
}
txn.commit().unwrap();
let txn = db.begin_write().unwrap();
{
let mut table = txn.open_table(TABLE).unwrap();
table.insert("k", b"v2".as_slice()).unwrap();
}
txn.commit().unwrap();
let txn = db.begin_read().unwrap();
let table = txn.open_table(TABLE).unwrap();
assert_eq!(table.get("k").unwrap().unwrap().value(), b"v2");
}
#[test]
fn test_03_redb_delete() {
let tmp = NamedTempFile::new().unwrap();
let db = Database::create(tmp.path()).unwrap();
let txn = db.begin_write().unwrap();
{
let mut table = txn.open_table(TABLE).unwrap();
table.insert("del-me", b"gone".as_slice()).unwrap();
}
txn.commit().unwrap();
let txn = db.begin_write().unwrap();
{
let mut table = txn.open_table(TABLE).unwrap();
let removed = table.remove("del-me").unwrap();
assert!(removed.is_some());
}
txn.commit().unwrap();
let txn = db.begin_read().unwrap();
let table = txn.open_table(TABLE).unwrap();
assert!(table.get("del-me").unwrap().is_none());
}
#[test]
fn test_04_redb_multimap() {
let tmp = NamedTempFile::new().unwrap();
let db = Database::create(tmp.path()).unwrap();
let txn = db.begin_write().unwrap();
{
let mut table = txn.open_multimap_table(MULTIMAP).unwrap();
table.insert("category", "doc-001").unwrap();
table.insert("category", "doc-002").unwrap();
table.insert("category", "doc-003").unwrap();
}
txn.commit().unwrap();
let txn = db.begin_read().unwrap();
let table = txn.open_multimap_table(MULTIMAP).unwrap();
let values: Vec<String> = table
.get("category")
.unwrap()
.map(|v| v.unwrap().value().to_owned())
.collect();
assert_eq!(values.len(), 3);
}
#[test]
fn test_05_redb_table_len() {
let tmp = NamedTempFile::new().unwrap();
let db = Database::create(tmp.path()).unwrap();
let txn = db.begin_write().unwrap();
{
let mut table = txn.open_table(TABLE).unwrap();
for i in 0..10 {
table
.insert(format!("key-{i}").as_str(), format!("val-{i}").as_bytes())
.unwrap();
}
}
txn.commit().unwrap();
let txn = db.begin_read().unwrap();
let table = txn.open_table(TABLE).unwrap();
assert_eq!(table.len().unwrap(), 10);
}
#[test]
fn test_06_redb_persistence_across_reopen() {
let tmp = NamedTempFile::new().unwrap();
let path = tmp.path().to_owned();
{
let db = Database::create(&path).unwrap();
let txn = db.begin_write().unwrap();
{
let mut table = txn.open_table(TABLE).unwrap();
table
.insert("persist", b"across-reopen".as_slice())
.unwrap();
}
txn.commit().unwrap();
}
{
let db = Database::create(&path).unwrap();
let txn = db.begin_read().unwrap();
let table = txn.open_table(TABLE).unwrap();
let val = table.get("persist").unwrap().unwrap();
assert_eq!(val.value(), b"across-reopen");
}
}
#[test]
fn test_07_redb_concurrent_readers() {
let tmp = NamedTempFile::new().unwrap();
let db = std::sync::Arc::new(Database::create(tmp.path()).unwrap());
let txn = db.begin_write().unwrap();
{
let mut table = txn.open_table(TABLE).unwrap();
table.insert("shared", b"data".as_slice()).unwrap();
}
txn.commit().unwrap();
let handles: Vec<_> = (0..8)
.map(|_| {
let db = db.clone();
std::thread::spawn(move || {
let txn = db.begin_read().unwrap();
let table = txn.open_table(TABLE).unwrap();
assert!(table.get("shared").unwrap().is_some());
})
})
.collect();
for h in handles {
h.join().unwrap();
}
}
#[test]
fn test_08_redb_composite_key() {
let idx: TableDefinition<&[u8], &str> = TableDefinition::new("index");
let tmp = NamedTempFile::new().unwrap();
let db = Database::create(tmp.path()).unwrap();
let txn = db.begin_write().unwrap();
{
let mut table = txn.open_table(idx).unwrap();
let mut key = Vec::new();
key.extend_from_slice(&1000i64.to_be_bytes());
key.extend_from_slice(b"doc-001");
table.insert(key.as_slice(), "doc-001").unwrap();
}
txn.commit().unwrap();
let txn = db.begin_read().unwrap();
let table = txn.open_table(idx).unwrap();
assert_eq!(table.len().unwrap(), 1);
}
}
mod rusqlite_tests {
use rusqlite::{Connection, params};
#[test]
fn test_09_rusqlite_wal_mode() {
let conn = Connection::open_in_memory().unwrap();
conn.execute_batch("PRAGMA journal_mode=WAL;").unwrap();
let mode: String = conn
.query_row("PRAGMA journal_mode", [], |row| row.get(0))
.unwrap();
assert!(!mode.is_empty());
}
#[test]
fn test_10_rusqlite_foreign_keys() {
let conn = Connection::open_in_memory().unwrap();
conn.execute_batch("PRAGMA foreign_keys=ON;").unwrap();
let fk: i32 = conn
.query_row("PRAGMA foreign_keys", [], |row| row.get(0))
.unwrap();
assert_eq!(fk, 1);
}
#[test]
fn test_11_rusqlite_crud() {
let conn = Connection::open_in_memory().unwrap();
conn.execute_batch("CREATE TABLE docs (id TEXT PRIMARY KEY, title TEXT NOT NULL);")
.unwrap();
conn.execute(
"INSERT INTO docs (id, title) VALUES (?1, ?2)",
params!["doc-001", "Test Document"],
)
.unwrap();
let title: String = conn
.query_row(
"SELECT title FROM docs WHERE id = ?1",
params!["doc-001"],
|r| r.get(0),
)
.unwrap();
assert_eq!(title, "Test Document");
conn.execute(
"UPDATE docs SET title = ?1 WHERE id = ?2",
params!["Updated Title", "doc-001"],
)
.unwrap();
let updated: String = conn
.query_row(
"SELECT title FROM docs WHERE id = ?1",
params!["doc-001"],
|r| r.get(0),
)
.unwrap();
assert_eq!(updated, "Updated Title");
let deleted = conn
.execute("DELETE FROM docs WHERE id = ?1", params!["doc-001"])
.unwrap();
assert_eq!(deleted, 1);
}
#[test]
fn test_12_rusqlite_parameterized_prevents_injection() {
let conn = Connection::open_in_memory().unwrap();
conn.execute_batch("CREATE TABLE users (name TEXT);")
.unwrap();
conn.execute("INSERT INTO users (name) VALUES (?1)", params!["Alice"])
.unwrap();
let malicious = "'; DROP TABLE users; --";
conn.execute("INSERT INTO users (name) VALUES (?1)", params![malicious])
.unwrap();
let count: i32 = conn
.query_row("SELECT COUNT(*) FROM users", [], |r| r.get(0))
.unwrap();
assert_eq!(count, 2, "Table should still exist with 2 rows");
}
#[test]
fn test_13_rusqlite_transaction_rollback() {
let mut conn = Connection::open_in_memory().unwrap();
conn.execute_batch("CREATE TABLE t (v INTEGER);").unwrap();
conn.execute("INSERT INTO t (v) VALUES (1)", []).unwrap();
{
let tx = conn.transaction().unwrap();
tx.execute("INSERT INTO t (v) VALUES (2)", []).unwrap();
tx.rollback().unwrap();
}
let count: i32 = conn
.query_row("SELECT COUNT(*) FROM t", [], |r| r.get(0))
.unwrap();
assert_eq!(count, 1, "Rolled-back insert should not persist");
}
#[test]
fn test_14_rusqlite_check_constraint() {
let conn = Connection::open_in_memory().unwrap();
conn.execute_batch("CREATE TABLE log (action TEXT CHECK(action IN ('create','delete')));")
.unwrap();
assert!(
conn.execute("INSERT INTO log (action) VALUES ('create')", [])
.is_ok()
);
assert!(
conn.execute("INSERT INTO log (action) VALUES ('invalid')", [])
.is_err()
);
}
}
mod hash_tests {
use sha2::{Digest as _, Sha256};
use sha3::Sha3_512;
#[test]
fn test_15_sha256_empty() {
let hash = Sha256::digest(b"");
assert_eq!(
format!("{hash:x}"),
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
);
}
#[test]
fn test_16_sha256_abc() {
let hash = Sha256::digest(b"abc");
assert_eq!(
format!("{hash:x}"),
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
);
}
#[test]
fn test_17_sha256_448bit() {
let hash = Sha256::digest(b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
assert_eq!(
format!("{hash:x}"),
"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
);
}
#[test]
fn test_18_sha3_512_empty() {
let hash = Sha3_512::digest(b"");
let hex = format!("{hash:x}");
assert_eq!(hex.len(), 128);
assert!(hex.starts_with("a69f73cca23a9ac5c8b567dc185a756e"));
}
#[test]
fn test_19_sha3_512_abc() {
let hash = Sha3_512::digest(b"abc");
let hex = format!("{hash:x}");
assert_eq!(hex.len(), 128);
assert!(hex.starts_with("b751850b1a57168a5693cd924b6b096e"));
}
#[test]
fn test_20_sha256_deterministic() {
let data = b"CSAF document content for hashing";
let h1 = Sha256::digest(data);
let h2 = Sha256::digest(data);
assert_eq!(h1, h2);
}
#[test]
fn test_21_sha3_512_deterministic() {
let data = b"CSAF document content for hashing";
let h1 = Sha3_512::digest(data);
let h2 = Sha3_512::digest(data);
assert_eq!(h1, h2);
}
#[test]
fn test_22_sha256_incremental() {
let mut hasher = Sha256::new();
hasher.update(b"hello");
hasher.update(b" ");
hasher.update(b"world");
let incremental = hasher.finalize();
let oneshot = Sha256::digest(b"hello world");
assert_eq!(incremental, oneshot);
}
}
mod argon2_tests {
use argon2::password_hash::SaltString;
use argon2::password_hash::rand_core::OsRng;
use argon2::{Argon2, PasswordHash, PasswordHasher, PasswordVerifier};
#[test]
fn test_23_argon2_hash_and_verify() {
let password = b"correct_horse_battery_staple";
let salt = SaltString::generate(&mut OsRng);
let argon2 = Argon2::default();
let hash = argon2.hash_password(password, &salt).unwrap().to_string();
let parsed = PasswordHash::new(&hash).unwrap();
assert!(argon2.verify_password(password, &parsed).is_ok());
}
#[test]
fn test_24_argon2_reject_wrong_password() {
let salt = SaltString::generate(&mut OsRng);
let argon2 = Argon2::default();
let hash = argon2
.hash_password(b"real_password", &salt)
.unwrap()
.to_string();
let parsed = PasswordHash::new(&hash).unwrap();
assert!(argon2.verify_password(b"wrong_password", &parsed).is_err());
}
#[test]
fn test_25_argon2_different_salts_different_hashes() {
let password = b"same_password";
let argon2 = Argon2::default();
let salt1 = SaltString::generate(&mut OsRng);
let salt2 = SaltString::generate(&mut OsRng);
let hash1 = argon2.hash_password(password, &salt1).unwrap().to_string();
let hash2 = argon2.hash_password(password, &salt2).unwrap().to_string();
assert_ne!(
hash1, hash2,
"Different salts should produce different hashes"
);
}
#[test]
fn test_26_argon2_hash_format() {
let salt = SaltString::generate(&mut OsRng);
let argon2 = Argon2::default();
let hash = argon2.hash_password(b"test", &salt).unwrap().to_string();
assert!(
hash.starts_with("$argon2id$"),
"Hash should use argon2id: {hash}"
);
}
}
mod serde_json_tests {
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct TestDoc {
id: String,
title: String,
score: Option<f64>,
tags: Vec<String>,
}
#[test]
fn test_27_serde_roundtrip() {
let original = TestDoc {
id: "doc-001".to_owned(),
title: "Test".to_owned(),
score: Some(9.8),
tags: vec!["critical".to_owned()],
};
let json = serde_json::to_string(&original).unwrap();
let parsed: TestDoc = serde_json::from_str(&json).unwrap();
assert_eq!(original, parsed);
}
#[test]
fn test_28_serde_null_handling() {
let json = r#"{"id":"doc","title":"T","score":null,"tags":[]}"#;
let doc: TestDoc = serde_json::from_str(json).unwrap();
assert!(doc.score.is_none());
}
#[test]
fn test_29_serde_unicode() {
let json =
r#"{"id":"doc","title":"Sicherheitshinweis für ndaal GmbH 🔒","score":null,"tags":[]}"#;
let doc: TestDoc = serde_json::from_str(json).unwrap();
assert!(doc.title.contains("für"));
assert!(doc.title.contains('\u{1F512}')); }
#[test]
fn test_30_serde_invalid_json() {
let result: Result<TestDoc, _> = serde_json::from_str("not json");
assert!(result.is_err());
}
#[test]
fn test_31_serde_missing_required_field() {
let json = r#"{"id":"doc"}"#;
let result: Result<TestDoc, _> = serde_json::from_str(json);
assert!(result.is_err());
}
#[test]
fn test_32_serde_value_manipulation() {
let mut val = serde_json::json!({"data": {"id": "doc-001"}});
val["_links"] = serde_json::json!({
"self": {"href": "/api/v1/csaf/doc-001"}
});
assert_eq!(val["_links"]["self"]["href"], "/api/v1/csaf/doc-001");
}
#[test]
fn test_33_serde_csaf_document_from_file() {
let json = include_str!("../../../test/csaf/2026/003/ndaal-sa-2026-003.json");
let doc: csaf_models::csaf_document::CsafDocument = serde_json::from_str(json).unwrap();
let reserialized = serde_json::to_string_pretty(&doc).unwrap();
let reparsed: csaf_models::csaf_document::CsafDocument =
serde_json::from_str(&reserialized).unwrap();
assert_eq!(doc, reparsed);
}
}
mod chrono_tests {
use chrono::{DateTime, NaiveDate, Utc};
#[test]
fn test_34_chrono_parse_rfc3339() {
let ts = "2026-04-05T08:00:00.000Z";
let parsed = DateTime::parse_from_rfc3339(ts).unwrap();
assert_eq!(parsed.year(), 2026);
assert_eq!(parsed.month(), 4);
assert_eq!(parsed.day(), 5);
}
use chrono::Datelike;
#[test]
fn test_35_chrono_parse_rfc3339_no_millis() {
let ts = "2026-04-13T08:00:00Z";
let parsed = DateTime::parse_from_rfc3339(ts).unwrap();
assert_eq!(parsed.year(), 2026);
}
#[test]
fn test_36_chrono_utc_now_format() {
let now = Utc::now();
let formatted = now.format("%Y-%m-%dT%H:%M:%S%.3fZ").to_string();
assert!(formatted.contains('T'));
assert!(formatted.ends_with('Z'));
}
#[test]
fn test_37_chrono_duration_days() {
let d1 = NaiveDate::from_ymd_opt(2026, 4, 1).unwrap();
let d2 = NaiveDate::from_ymd_opt(2026, 4, 15).unwrap();
assert_eq!((d2 - d1).num_days(), 14);
}
#[test]
fn test_38_chrono_timestamp_millis() {
let now = Utc::now();
let millis = now.timestamp_millis();
assert!(millis > 0);
}
}
mod regex_tests {
use regex::Regex;
#[test]
fn test_39_regex_tracking_id_pattern() {
let re = Regex::new(r"^[a-z]+-[a-z]+-\d{4}-\d{3,}$").unwrap();
assert!(re.is_match("ndaal-sa-2026-001"));
assert!(re.is_match("ndaal-sa-2026-015"));
assert!(!re.is_match("NDAAL-SA-2026-001")); assert!(!re.is_match("invalid"));
}
#[test]
fn test_40_regex_cve_pattern() {
let re = Regex::new(r"(?i)^CVE-\d{4}-\d{4,}$").unwrap();
assert!(re.is_match("CVE-2024-1234"));
assert!(re.is_match("cve-2024-99999"));
assert!(!re.is_match("CVE-24-123"));
}
#[test]
fn test_41_regex_cvss_vector_v31() {
let re = Regex::new(r"^CVSS:3\.[01]/").unwrap();
assert!(re.is_match("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"));
assert!(!re.is_match("CVSS:4.0/AV:N"));
}
#[test]
fn test_42_regex_cvss_vector_v40() {
let re = Regex::new(r"^CVSS:4\.0/").unwrap();
assert!(re.is_match("CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N"));
assert!(!re.is_match("CVSS:3.1/AV:N"));
}
}
mod uuid_tests {
use uuid::Uuid;
#[test]
fn test_43_uuid_v4_format() {
let id = Uuid::new_v4();
assert_eq!(id.get_version(), Some(uuid::Version::Random));
assert_eq!(id.to_string().len(), 36);
}
#[test]
fn test_44_uuid_uniqueness() {
let ids: std::collections::HashSet<String> =
(0..1000).map(|_| Uuid::new_v4().to_string()).collect();
assert_eq!(ids.len(), 1000);
}
#[test]
fn test_45_uuid_parse_roundtrip() {
let id = Uuid::new_v4();
let s = id.to_string();
let parsed = Uuid::parse_str(&s).unwrap();
assert_eq!(id, parsed);
}
#[test]
fn test_46_uuid_serde_roundtrip() {
let id = Uuid::new_v4();
let json = serde_json::to_string(&id).unwrap();
let parsed: Uuid = serde_json::from_str(&json).unwrap();
assert_eq!(id, parsed);
}
}
mod matchit_tests {
#[test]
fn test_47_matchit_static_path() {
let mut router = matchit::Router::new();
router.insert("/api/v1/csaf", "list").unwrap();
let matched = router.at("/api/v1/csaf").unwrap();
assert_eq!(*matched.value, "list");
}
#[test]
fn test_48_matchit_named_param() {
let mut router = matchit::Router::new();
router.insert("/api/v1/csaf/{id}", "get").unwrap();
let matched = router.at("/api/v1/csaf/ndaal-sa-2026-003").unwrap();
assert_eq!(*matched.value, "get");
assert_eq!(matched.params.get("id"), Some("ndaal-sa-2026-003"));
}
#[test]
fn test_49_matchit_wildcard() {
let mut router = matchit::Router::new();
router.insert("/static/{*path}", "static").unwrap();
let matched = router.at("/static/css/custom.css").unwrap();
assert_eq!(*matched.value, "static");
assert_eq!(matched.params.get("path"), Some("css/custom.css"));
}
#[test]
fn test_50_matchit_no_match() {
let mut router = matchit::Router::new();
router.insert("/api/v1/csaf", "list").unwrap();
assert!(router.at("/nonexistent").is_err());
}
#[test]
fn test_51_matchit_multiple_params() {
let mut router = matchit::Router::new();
router.insert("/api/v1/{resource}/{id}", "item").unwrap();
let matched = router.at("/api/v1/csaf/doc-001").unwrap();
assert_eq!(matched.params.get("resource"), Some("csaf"));
assert_eq!(matched.params.get("id"), Some("doc-001"));
}
}
mod tls_tests {
use rcgen::{CertificateParams, KeyPair};
#[test]
fn test_52_rcgen_self_signed_cert() {
let params = CertificateParams::new(vec!["localhost".to_owned()]).unwrap();
let key_pair = KeyPair::generate().unwrap();
let cert = params.self_signed(&key_pair).unwrap();
let cert_der = rustls::pki_types::CertificateDer::from(cert);
assert!(!cert_der.is_empty());
}
#[test]
fn test_53_rcgen_cert_with_san() {
use rcgen::SanType;
use std::net::Ipv4Addr;
let mut params = CertificateParams::new(vec!["localhost".to_owned()]).unwrap();
params.subject_alt_names = vec![
SanType::DnsName("localhost".try_into().unwrap()),
SanType::IpAddress(Ipv4Addr::LOCALHOST.into()),
];
let key_pair = KeyPair::generate().unwrap();
let cert = params.self_signed(&key_pair).unwrap();
assert!(!cert.pem().is_empty());
}
#[test]
fn test_54_rustls_config_builder() {
let key_pair = KeyPair::generate().unwrap();
let params = CertificateParams::new(vec!["localhost".to_owned()]).unwrap();
let cert = params.self_signed(&key_pair).unwrap();
let cert_der = rustls::pki_types::CertificateDer::from(cert);
let key_der = rustls::pki_types::PrivateKeyDer::try_from(key_pair.serialize_der()).unwrap();
let _ = rustls::crypto::ring::default_provider().install_default();
let config = rustls::ServerConfig::builder()
.with_no_client_auth()
.with_single_cert(vec![cert_der], key_der);
assert!(config.is_ok(), "Rustls config should build successfully");
}
#[test]
fn test_55_rcgen_45_day_validity() {
let mut params = CertificateParams::new(vec!["localhost".to_owned()]).unwrap();
let now = time::OffsetDateTime::now_utc();
params.not_before = now;
params.not_after = now + time::Duration::days(45);
let key_pair = KeyPair::generate().unwrap();
let cert = params.self_signed(&key_pair).unwrap();
assert!(!cert.pem().is_empty());
}
}
mod sysinfo_tests {
use sysinfo::System;
#[test]
fn test_56_sysinfo_basic() {
let mut sys = System::new_all();
sys.refresh_all();
assert!(sys.total_memory() > 0);
assert!(!sys.cpus().is_empty());
}
#[test]
fn test_57_sysinfo_os_info() {
let name = System::name();
let version = System::os_version();
let hostname = System::host_name();
assert!(
name.is_some() || version.is_some() || hostname.is_some(),
"Should have at least one OS info field"
);
}
}
mod tokio_tests {
use tokio::sync::{Mutex, RwLock, broadcast};
#[tokio::test]
async fn test_58_tokio_async_mutex() {
let mutex = Mutex::new(0_i32);
{
let mut guard = mutex.lock().await;
*guard += 1;
}
assert_eq!(*mutex.lock().await, 1);
}
#[tokio::test]
async fn test_59_tokio_rwlock_many_readers() {
let lock = RwLock::new(42_i32);
{
let r1 = lock.read().await;
let r2 = lock.read().await;
assert_eq!(*r1, 42);
assert_eq!(*r2, 42);
}
}
#[tokio::test]
async fn test_60_tokio_broadcast_channel() {
let (tx, mut rx1) = broadcast::channel::<i32>(16);
let mut rx2 = tx.subscribe();
tx.send(100).unwrap();
assert_eq!(rx1.recv().await.unwrap(), 100);
assert_eq!(rx2.recv().await.unwrap(), 100);
}
#[tokio::test]
async fn test_61_tokio_spawn_and_join() {
let handle = tokio::spawn(async { 2 + 2 });
let result = handle.await.unwrap();
assert_eq!(result, 4);
}
#[tokio::test]
async fn test_62_tokio_fs_create_dir() {
let tmp = tempfile::tempdir().unwrap();
let target = tmp.path().join("nested/deep/path");
tokio::fs::create_dir_all(&target).await.unwrap();
assert!(target.exists());
}
}
mod http_tests {
use bytes::Bytes;
use http::{HeaderValue, Method, Response, StatusCode};
use http_body_util::Full;
#[test]
fn test_63_http_method_parsing() {
assert_eq!("GET".parse::<Method>().unwrap(), Method::GET);
assert_eq!("POST".parse::<Method>().unwrap(), Method::POST);
assert_eq!("PUT".parse::<Method>().unwrap(), Method::PUT);
assert_eq!("DELETE".parse::<Method>().unwrap(), Method::DELETE);
}
#[test]
fn test_64_http_status_code_ranges() {
assert!(StatusCode::OK.is_success());
assert!(StatusCode::NOT_FOUND.is_client_error());
assert!(StatusCode::INTERNAL_SERVER_ERROR.is_server_error());
assert_eq!(StatusCode::OK.as_u16(), 200);
assert_eq!(StatusCode::NOT_FOUND.as_u16(), 404);
}
#[test]
fn test_65_http_response_builder() {
let resp = Response::builder()
.status(StatusCode::CREATED)
.header("content-type", "application/json")
.header("location", "/api/v1/csaf/doc-001")
.body(Full::new(Bytes::from("{}")))
.unwrap();
assert_eq!(resp.status(), StatusCode::CREATED);
assert_eq!(
resp.headers().get("content-type").unwrap(),
&HeaderValue::from_static("application/json")
);
}
#[test]
fn test_66_http_uri_parsing() {
let uri: http::Uri = "https://example.com/api/v1/csaf?page=1".parse().unwrap();
assert_eq!(uri.scheme_str(), Some("https"));
assert_eq!(uri.host(), Some("example.com"));
assert_eq!(uri.path(), "/api/v1/csaf");
assert_eq!(uri.query(), Some("page=1"));
}
#[test]
fn test_67_http_header_case_insensitive() {
let resp = Response::builder()
.header("Content-Type", "text/plain")
.body(())
.unwrap();
assert!(resp.headers().get("content-type").is_some());
assert!(resp.headers().get("CONTENT-TYPE").is_some());
}
}
mod bytes_tests {
use bytes::{Bytes, BytesMut};
#[test]
fn test_68_bytes_from_slice() {
let b = Bytes::from_static(b"CSAF document body");
assert_eq!(b.len(), 18);
assert_eq!(&b[..4], b"CSAF");
}
#[test]
fn test_69_bytes_cheap_clone() {
let original = Bytes::from(vec![0u8; 1024]);
let clone1 = original.clone();
let clone2 = original.clone();
assert_eq!(original.len(), 1024);
assert_eq!(clone1.len(), 1024);
assert_eq!(clone2.len(), 1024);
}
#[test]
fn test_70_bytesmut_to_bytes() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"hello ");
buf.extend_from_slice(b"world");
let frozen: Bytes = buf.freeze();
assert_eq!(&frozen[..], b"hello world");
}
}
mod mime_guess_tests {
#[test]
fn test_71_mime_guess_json() {
let mime = mime_guess::from_path("data.json").first_raw();
assert_eq!(mime, Some("application/json"));
}
#[test]
fn test_72_mime_guess_css() {
let mime = mime_guess::from_path("static/css/custom.css").first_raw();
assert_eq!(mime, Some("text/css"));
}
#[test]
fn test_73_mime_guess_javascript() {
let mime = mime_guess::from_path("static/js/theme.js").first_raw();
assert!(
mime == Some("application/javascript") || mime == Some("text/javascript"),
"got: {mime:?}"
);
}
#[test]
fn test_74_mime_guess_unknown_extension() {
let mime = mime_guess::from_path("data.xyznotreal").first_raw();
assert!(mime.is_none());
}
}
mod time_tests {
use time::{Duration, OffsetDateTime};
#[test]
fn test_75_time_offset_datetime_now() {
let now = OffsetDateTime::now_utc();
assert!(now.year() >= 2024);
}
#[test]
fn test_76_time_45_day_duration() {
let now = OffsetDateTime::now_utc();
let expires = now + Duration::days(45);
let delta = expires - now;
assert_eq!(delta.whole_days(), 45);
}
#[test]
fn test_77_time_duration_arithmetic() {
let d = Duration::days(45);
assert_eq!(d.whole_seconds(), 45 * 24 * 60 * 60);
}
}
mod toml_tests {
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct TestConfig {
listen_addr: String,
listen_port: u16,
data_dir: String,
}
#[test]
fn test_78_toml_parse_config() {
let input = r#"
listen_addr = "127.0.0.1"
listen_port = 8443
data_dir = "./data"
"#;
let cfg: TestConfig = toml::from_str(input).unwrap();
assert_eq!(cfg.listen_addr, "127.0.0.1");
assert_eq!(cfg.listen_port, 8443);
assert_eq!(cfg.data_dir, "./data");
}
#[test]
fn test_79_toml_serialize_roundtrip() {
let cfg = TestConfig {
listen_addr: "0.0.0.0".to_owned(),
listen_port: 8180,
data_dir: "/var/lib/csaf".to_owned(),
};
let serialized = toml::to_string(&cfg).unwrap();
let parsed: TestConfig = toml::from_str(&serialized).unwrap();
assert_eq!(cfg, parsed);
}
#[test]
fn test_80_toml_invalid_syntax() {
let input = "listen_port = not_a_number";
let result: Result<TestConfig, _> = toml::from_str(input);
assert!(result.is_err());
}
}
mod clap_tests {
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(name = "test-cli")]
struct TestCli {
#[arg(short, long)]
config: Option<String>,
#[command(subcommand)]
command: TestCommand,
}
#[derive(Subcommand)]
enum TestCommand {
Import { path: String },
Stats,
}
#[test]
fn test_81_clap_parse_import() {
let cli =
TestCli::try_parse_from(["test-cli", "--config", "config.toml", "import", "/tmp/data"])
.unwrap();
assert_eq!(cli.config.as_deref(), Some("config.toml"));
match cli.command {
TestCommand::Import { path } => assert_eq!(path, "/tmp/data"),
TestCommand::Stats => panic!("wrong command"),
}
}
#[test]
fn test_82_clap_parse_stats_subcommand() {
let cli = TestCli::try_parse_from(["test-cli", "stats"]).unwrap();
assert!(matches!(cli.command, TestCommand::Stats));
}
#[test]
fn test_83_clap_missing_required_arg() {
let result = TestCli::try_parse_from(["test-cli", "import"]);
assert!(result.is_err());
}
}
mod tracing_tests {
use tracing::{Level, event, span};
#[test]
fn test_84_tracing_events_no_panic() {
event!(Level::INFO, "test info event");
event!(Level::WARN, tracking_id = "doc-001", "test warn");
event!(Level::ERROR, error = "something", "test error");
}
#[test]
fn test_85_tracing_span_creation() {
let span = span!(Level::INFO, "import_batch", count = 15);
let _enter = span.enter();
}
#[test]
fn test_86_tracing_subscriber_init_idempotent() {
let _ = tracing_subscriber::fmt().with_env_filter("info").try_init();
let _ = tracing_subscriber::fmt().with_env_filter("info").try_init();
}
}
mod anyhow_tests {
use anyhow::{Context, anyhow};
#[test]
fn test_87_anyhow_error_creation() {
let err = anyhow!("custom error: {}", 42);
assert!(err.to_string().contains("custom error: 42"));
}
#[test]
fn test_88_anyhow_context_chain() {
let result: Result<(), anyhow::Error> = Err(anyhow!("inner"))
.context("middle layer")
.context("outer context");
let err = result.unwrap_err();
let chain_str = format!("{err:#}");
assert!(chain_str.contains("outer context"));
}
#[test]
fn test_89_anyhow_from_std_error() {
let io_err = std::io::Error::other("disk full");
let err: anyhow::Error = anyhow::Error::new(io_err);
assert!(err.to_string().contains("disk full"));
}
}
mod thiserror_tests {
use thiserror::Error;
#[derive(Debug, Error)]
enum TestError {
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("not found: {0}")]
NotFound(String),
#[error("validation failed")]
Validation,
}
#[test]
fn test_90_thiserror_display() {
let err = TestError::NotFound("doc-001".to_owned());
assert_eq!(err.to_string(), "not found: doc-001");
let err2 = TestError::Validation;
assert_eq!(err2.to_string(), "validation failed");
}
#[test]
fn test_91_thiserror_from_conversion() {
let io_err = std::io::Error::other("disk full");
let err: TestError = io_err.into();
assert!(matches!(err, TestError::Io(_)));
assert!(err.to_string().contains("disk full"));
}
#[test]
fn test_92_thiserror_debug() {
let err = TestError::NotFound("doc-002".to_owned());
let debug = format!("{err:?}");
assert!(debug.contains("NotFound"));
}
}
mod tempfile_tests {
use std::io::Write;
use tempfile::{NamedTempFile, TempDir};
#[test]
fn test_93_tempfile_named() {
let mut tmp = NamedTempFile::new().unwrap();
tmp.write_all(b"test content").unwrap();
let path = tmp.path().to_owned();
assert!(path.exists());
drop(tmp);
assert!(!path.exists(), "Should be cleaned up on drop");
}
#[test]
fn test_94_tempdir_cleanup() {
let path;
{
let tmp = TempDir::new().unwrap();
path = tmp.path().to_owned();
assert!(path.exists());
std::fs::write(path.join("file.txt"), "hello").unwrap();
}
assert!(!path.exists());
}
#[test]
fn test_95_tempdir_persist() {
let tmp = TempDir::new().unwrap();
let sub = tmp.path().join("2026/003");
std::fs::create_dir_all(&sub).unwrap();
std::fs::write(sub.join("doc.json"), "{}").unwrap();
assert!(sub.join("doc.json").exists());
}
}
mod serde_direct_tests {
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Config {
#[serde(rename = "csaf_version")]
version: String,
#[serde(skip_serializing_if = "Option::is_none")]
tlp_label: Option<String>,
#[serde(default)]
sidecar_sha256: bool,
}
#[test]
fn test_96_serde_rename() {
let json = r#"{"csaf_version":"2.1","tlp_label":"CLEAR","sidecar_sha256":true}"#;
let cfg: Config = serde_json::from_str(json).unwrap();
assert_eq!(cfg.version, "2.1");
}
#[test]
fn test_97_serde_skip_serializing_none() {
let cfg = Config {
version: "2.1".to_owned(),
tlp_label: None,
sidecar_sha256: true,
};
let json = serde_json::to_string(&cfg).unwrap();
assert!(!json.contains("tlp_label"), "got: {json}");
}
#[test]
fn test_98_serde_default_on_missing() {
let json = r#"{"csaf_version":"2.0"}"#;
let cfg: Config = serde_json::from_str(json).unwrap();
assert_eq!(cfg.version, "2.0");
assert!(!cfg.sidecar_sha256);
}
#[test]
fn test_99_serde_tagged_enum() {
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(tag = "type")]
enum Event {
Create { tracking_id: String },
Delete { tracking_id: String },
}
let e = Event::Create {
tracking_id: "doc-001".to_owned(),
};
let json = serde_json::to_string(&e).unwrap();
assert!(json.contains("\"type\":\"Create\""));
let parsed: Event = serde_json::from_str(&json).unwrap();
assert_eq!(e, parsed);
}
}
mod tokio_rustls_tests {
use std::sync::Arc;
#[test]
fn test_100_tokio_rustls_acceptor_construction() {
use rcgen::{CertificateParams, KeyPair};
let _ = rustls::crypto::ring::default_provider().install_default();
let params = CertificateParams::new(vec!["localhost".to_owned()]).unwrap();
let key_pair = KeyPair::generate().unwrap();
let cert = params.self_signed(&key_pair).unwrap();
let cert_der = rustls::pki_types::CertificateDer::from(cert);
let key_der = rustls::pki_types::PrivateKeyDer::try_from(key_pair.serialize_der()).unwrap();
let config = rustls::ServerConfig::builder()
.with_no_client_auth()
.with_single_cert(vec![cert_der], key_der)
.unwrap();
let _acceptor = tokio_rustls::TlsAcceptor::from(Arc::new(config));
}
}
mod rustyload_patterns {
use std::collections::HashMap;
#[test]
fn test_101_http_method_parsing_case_insensitive() {
for (input, expected) in [
("GET", http::Method::GET),
("POST", http::Method::POST),
("PUT", http::Method::PUT),
("DELETE", http::Method::DELETE),
("PATCH", http::Method::PATCH),
("HEAD", http::Method::HEAD),
("OPTIONS", http::Method::OPTIONS),
] {
let parsed: http::Method = input.parse().unwrap();
assert_eq!(parsed, expected);
}
}
#[test]
fn test_102_http_method_invalid_rejected() {
assert!("".parse::<http::Method>().is_err());
assert!("GET ME".parse::<http::Method>().is_err()); assert!("INVALID".parse::<http::Method>().is_ok());
}
#[test]
fn test_103_http_request_builder_with_method_and_body() {
let body = r#"{"test": true}"#;
let req = http::Request::builder()
.method(http::Method::POST)
.uri("https://example.com/api/v1/csaf")
.header("content-type", "application/json")
.body(body.to_owned())
.unwrap();
assert_eq!(req.method(), http::Method::POST);
assert_eq!(req.uri().path(), "/api/v1/csaf");
assert_eq!(
req.headers().get("content-type").unwrap(),
"application/json"
);
assert_eq!(*req.body(), body);
}
#[test]
fn test_104_http_request_builder_with_custom_headers() {
let mut headers = HashMap::new();
headers.insert("Authorization", "Bearer test-token");
headers.insert("X-Custom", "value");
let mut builder = http::Request::builder()
.method(http::Method::GET)
.uri("https://api.example.com/csaf");
for (k, v) in &headers {
builder = builder.header(*k, *v);
}
let req = builder.body(()).unwrap();
assert!(req.headers().contains_key("authorization"));
assert!(req.headers().contains_key("x-custom"));
}
#[test]
fn test_105_protocol_selection_http() {
for scheme in ["http", "https"] {
let uri: http::Uri = format!("{scheme}://localhost:8180/api/v1").parse().unwrap();
assert!(uri.scheme_str() == Some("http") || uri.scheme_str() == Some("https"));
}
}
#[test]
fn test_106_protocol_selection_rejects_unknown() {
let uri: http::Uri = "ftp://localhost/file".parse().unwrap();
assert_eq!(uri.scheme_str(), Some("ftp"));
}
#[allow(dead_code)] struct RequestResult {
duration_ms: u64,
status: u16,
success: bool,
}
fn calculate_stats(results: &[RequestResult]) -> (usize, usize, usize, u64, u64) {
let total = results.len();
let successful = results.iter().filter(|r| r.success).count();
let failed = total - successful;
let min = results
.iter()
.filter(|r| r.success)
.map(|r| r.duration_ms)
.min()
.unwrap_or(0);
let max = results
.iter()
.filter(|r| r.success)
.map(|r| r.duration_ms)
.max()
.unwrap_or(0);
(total, successful, failed, min, max)
}
#[test]
fn test_107_stats_empty_results() {
let results: Vec<RequestResult> = vec![];
let (total, ok, fail, min, max) = calculate_stats(&results);
assert_eq!(total, 0);
assert_eq!(ok, 0);
assert_eq!(fail, 0);
assert_eq!(min, 0);
assert_eq!(max, 0);
}
#[test]
fn test_108_stats_mixed_success_failure() {
let results = vec![
RequestResult {
duration_ms: 100,
status: 200,
success: true,
},
RequestResult {
duration_ms: 200,
status: 200,
success: true,
},
RequestResult {
duration_ms: 50,
status: 0,
success: false,
},
];
let (total, ok, fail, min, max) = calculate_stats(&results);
assert_eq!(total, 3);
assert_eq!(ok, 2);
assert_eq!(fail, 1);
assert_eq!(min, 100);
assert_eq!(max, 200);
}
#[test]
fn test_109_stats_all_failures() {
let results = vec![
RequestResult {
duration_ms: 0,
status: 0,
success: false,
},
RequestResult {
duration_ms: 0,
status: 0,
success: false,
},
];
let (total, ok, fail, min, max) = calculate_stats(&results);
assert_eq!(total, 2);
assert_eq!(ok, 0);
assert_eq!(fail, 2);
assert_eq!(min, 0);
assert_eq!(max, 0);
}
#[test]
fn test_110_stats_all_success() {
let results = vec![
RequestResult {
duration_ms: 10,
status: 200,
success: true,
},
RequestResult {
duration_ms: 500,
status: 200,
success: true,
},
RequestResult {
duration_ms: 250,
status: 200,
success: true,
},
];
let (total, ok, fail, min, max) = calculate_stats(&results);
assert_eq!(total, 3);
assert_eq!(ok, 3);
assert_eq!(fail, 0);
assert_eq!(min, 10);
assert_eq!(max, 500);
}
}