#![cfg(kani)]
use elicitation::verification::types::{
UuidBytes, UuidV4Bytes, UuidV7Bytes, has_valid_variant, has_version, is_valid_v4, is_valid_v7,
};
#[kani::proof]
fn verify_valid_variant_accepted() {
let mut bytes: [u8; 16] = kani::any();
bytes[8] = (bytes[8] & 0x3F) | 0x80;
assert!(has_valid_variant(&bytes));
let uuid_bytes = UuidBytes::new(bytes);
assert!(uuid_bytes.is_ok());
}
#[kani::proof]
fn verify_ncs_variant_rejected() {
let mut bytes: [u8; 16] = kani::any();
bytes[8] = bytes[8] & 0x7F;
assert!(!has_valid_variant(&bytes));
let uuid_bytes = UuidBytes::new(bytes);
assert!(uuid_bytes.is_err());
}
#[kani::proof]
fn verify_microsoft_variant_rejected() {
let mut bytes: [u8; 16] = kani::any();
bytes[8] = (bytes[8] & 0x1F) | 0xC0;
assert!(!has_valid_variant(&bytes));
let uuid_bytes = UuidBytes::new(bytes);
assert!(uuid_bytes.is_err());
}
#[kani::proof]
fn verify_reserved_variant_rejected() {
let mut bytes: [u8; 16] = kani::any();
bytes[8] = bytes[8] | 0xE0;
assert!(!has_valid_variant(&bytes));
let uuid_bytes = UuidBytes::new(bytes);
assert!(uuid_bytes.is_err());
}
#[kani::proof]
fn verify_version_extraction() {
let mut bytes: [u8; 16] = kani::any();
bytes[8] = (bytes[8] & 0x3F) | 0x80;
let version: u8 = kani::any();
kani::assume(version < 16);
bytes[6] = (bytes[6] & 0x0F) | (version << 4);
assert!(has_version(&bytes, version));
let uuid_bytes = UuidBytes::new(bytes).unwrap();
assert_eq!(uuid_bytes.version(), version);
}
#[kani::proof]
fn verify_v4_valid_construction() {
let mut bytes: [u8; 16] = kani::any();
bytes[6] = (bytes[6] & 0x0F) | 0x40; bytes[8] = (bytes[8] & 0x3F) | 0x80;
assert!(is_valid_v4(&bytes));
let v4 = UuidV4Bytes::new(bytes);
assert!(v4.is_ok());
let v4_unwrapped = v4.unwrap();
assert_eq!(v4_unwrapped.get().version(), 4);
}
#[kani::proof]
fn verify_v4_wrong_version_rejected() {
let mut bytes: [u8; 16] = kani::any();
let version: u8 = kani::any();
kani::assume(version != 4 && version < 16);
bytes[6] = (bytes[6] & 0x0F) | (version << 4);
bytes[8] = (bytes[8] & 0x3F) | 0x80;
assert!(!is_valid_v4(&bytes));
let v4 = UuidV4Bytes::new(bytes);
assert!(v4.is_err());
}
#[kani::proof]
fn verify_v4_invalid_variant_rejected() {
let mut bytes: [u8; 16] = kani::any();
bytes[6] = (bytes[6] & 0x0F) | 0x40;
let variant_bits: u8 = kani::any();
kani::assume((variant_bits & 0xC0) != 0x80);
bytes[8] = variant_bits;
assert!(!is_valid_v4(&bytes));
let v4 = UuidV4Bytes::new(bytes);
assert!(v4.is_err());
}
#[kani::proof]
fn verify_v7_valid_construction() {
let mut bytes: [u8; 16] = kani::any();
bytes[6] = (bytes[6] & 0x0F) | 0x70; bytes[8] = (bytes[8] & 0x3F) | 0x80;
assert!(is_valid_v7(&bytes));
let v7 = UuidV7Bytes::new(bytes);
assert!(v7.is_ok());
let v7_unwrapped = v7.unwrap();
assert_eq!(v7_unwrapped.get().version(), 7);
}
#[kani::proof]
fn verify_v7_wrong_version_rejected() {
let mut bytes: [u8; 16] = kani::any();
let version: u8 = kani::any();
kani::assume(version != 7 && version < 16);
bytes[6] = (bytes[6] & 0x0F) | (version << 4);
bytes[8] = (bytes[8] & 0x3F) | 0x80;
assert!(!is_valid_v7(&bytes));
let v7 = UuidV7Bytes::new(bytes);
assert!(v7.is_err());
}
#[kani::proof]
fn verify_v7_timestamp_extraction() {
let mut bytes: [u8; 16] = kani::any();
bytes[6] = (bytes[6] & 0x0F) | 0x70; bytes[8] = (bytes[8] & 0x3F) | 0x80;
let v7 = UuidV7Bytes::new(bytes).unwrap();
let timestamp = v7.timestamp_ms();
let expected = ((bytes[0] as u64) << 40)
| ((bytes[1] as u64) << 32)
| ((bytes[2] as u64) << 24)
| ((bytes[3] as u64) << 16)
| ((bytes[4] as u64) << 8)
| (bytes[5] as u64);
assert_eq!(timestamp, expected);
}
#[kani::proof]
fn verify_uuid_bytes_roundtrip() {
let mut bytes: [u8; 16] = kani::any();
bytes[8] = (bytes[8] & 0x3F) | 0x80;
let uuid_bytes = UuidBytes::new(bytes).unwrap();
let extracted = uuid_bytes.bytes();
assert_eq!(bytes, extracted);
}
#[kani::proof]
fn verify_v4_bytes_roundtrip() {
let mut bytes: [u8; 16] = kani::any();
bytes[6] = (bytes[6] & 0x0F) | 0x40; bytes[8] = (bytes[8] & 0x3F) | 0x80;
let v4 = UuidV4Bytes::new(bytes).unwrap();
let extracted = v4.bytes();
assert_eq!(bytes, extracted);
}
#[kani::proof]
fn verify_v7_bytes_roundtrip() {
let mut bytes: [u8; 16] = kani::any();
bytes[6] = (bytes[6] & 0x0F) | 0x70; bytes[8] = (bytes[8] & 0x3F) | 0x80;
let v7 = UuidV7Bytes::new(bytes).unwrap();
let extracted = v7.bytes();
assert_eq!(bytes, extracted);
}
use elicitation::{Generator, UuidGenerationMode, UuidGenerator};
use uuid::Uuid;
#[kani::proof]
fn verify_uuid_generator_nil() {
let mode = UuidGenerationMode::Nil;
let generator = UuidGenerator::new(mode);
let uuid = generator.generate();
assert_eq!(uuid, Uuid::nil(), "Nil mode produces nil UUID");
assert_eq!(uuid.as_bytes(), &[0u8; 16], "Nil UUID is all zeros");
}
#[kani::proof]
fn verify_uuid_generator_max() {
let mode = UuidGenerationMode::Max;
let generator = UuidGenerator::new(mode);
let uuid = generator.generate();
assert_eq!(uuid, Uuid::max(), "Max mode produces max UUID");
assert_eq!(uuid.as_bytes(), &[0xFFu8; 16], "Max UUID is all ones");
}
#[kani::proof]
fn verify_uuid_generator_v4_format() {
let mut bytes: [u8; 16] = kani::any();
bytes[6] = (bytes[6] & 0x0F) | 0x40;
bytes[8] = (bytes[8] & 0x3F) | 0x80;
let version = (bytes[6] & 0xF0) >> 4;
assert_eq!(version, 4, "Version bits identify V4");
let variant_bits = bytes[8] & 0xC0;
assert_eq!(variant_bits, 0x80, "Variant bits identify RFC 4122");
}
#[kani::proof]
fn verify_uuid_generator_mode_preserved() {
let mode = UuidGenerationMode::Nil;
let generator = UuidGenerator::new(mode);
assert_eq!(generator.mode(), mode, "Generator preserves mode");
}
#[kani::proof]
fn verify_uuid_generator_nil_consistent() {
let mode = UuidGenerationMode::Nil;
let generator = UuidGenerator::new(mode);
let uuid1 = generator.generate();
let uuid2 = generator.generate();
assert_eq!(uuid1, uuid2, "Nil mode is deterministic");
}
#[kani::proof]
fn verify_uuid_generator_max_consistent() {
let mode = UuidGenerationMode::Max;
let generator = UuidGenerator::new(mode);
let uuid1 = generator.generate();
let uuid2 = generator.generate();
assert_eq!(uuid1, uuid2, "Max mode is deterministic");
}