use super::*;
#[test]
fn test_license_tier_display() {
assert_eq!(LicenseTier::Professional.to_string(), "Professional");
assert_eq!(LicenseTier::Team.to_string(), "Team");
assert_eq!(LicenseTier::Enterprise.to_string(), "Enterprise");
}
#[test]
fn test_premium_feature_enum_only_contains_true_premium_variants() {
let all_premium = [
PremiumFeature::EncryptionAtRest,
PremiumFeature::Snapshots,
PremiumFeature::MultiTenancy,
PremiumFeature::RBAC,
PremiumFeature::SSO,
PremiumFeature::AuditLogging,
];
assert_eq!(
all_premium.len(),
6,
"PremiumFeature must have exactly 6 variants"
);
for feature in &all_premium {
match feature {
PremiumFeature::EncryptionAtRest
| PremiumFeature::Snapshots
| PremiumFeature::MultiTenancy
| PremiumFeature::RBAC
| PremiumFeature::SSO
| PremiumFeature::AuditLogging => {}
}
}
}
#[test]
fn test_premium_feature_display_values() {
assert_eq!(
PremiumFeature::EncryptionAtRest.to_string(),
"Encryption at Rest"
);
assert_eq!(PremiumFeature::Snapshots.to_string(), "Snapshots & Backups");
assert_eq!(PremiumFeature::MultiTenancy.to_string(), "Multi-Tenancy");
assert_eq!(PremiumFeature::RBAC.to_string(), "RBAC");
assert_eq!(PremiumFeature::SSO.to_string(), "SSO");
assert_eq!(PremiumFeature::AuditLogging.to_string(), "Audit Logging");
}
#[test]
fn test_premium_feature_serde_roundtrip() {
let features = vec![
PremiumFeature::EncryptionAtRest,
PremiumFeature::Snapshots,
PremiumFeature::RBAC,
];
let json = serde_json::to_string(&features).unwrap();
let deserialized: Vec<PremiumFeature> = serde_json::from_str(&json).unwrap();
assert_eq!(features, deserialized);
}
#[test]
fn test_legacy_license_with_removed_features_deserializes() {
let legacy_json = r#"{
"key": "LEGACY-KEY",
"tier": "Professional",
"organization": "Legacy Corp",
"expires_at": 9999999999,
"max_instances": 5,
"features": ["HybridSearch", "Snapshots", "AdvancedFiltering", "GpuAcceleration", "RBAC"]
}"#;
let info: LicenseInfo = serde_json::from_str(legacy_json).unwrap();
assert_eq!(
info.features.len(),
2,
"Only Snapshots and RBAC are true premium"
);
assert!(info.features.contains(&PremiumFeature::Snapshots));
assert!(info.features.contains(&PremiumFeature::RBAC));
}
#[test]
fn test_license_info_is_expired() {
let expired = LicenseInfo {
key: "TEST-KEY".to_string(),
tier: LicenseTier::Professional,
organization: "Test Corp".to_string(),
expires_at: 1_000_000, max_instances: 1,
features: vec![],
};
assert!(expired.is_expired());
let valid = LicenseInfo {
key: "TEST-KEY".to_string(),
tier: LicenseTier::Professional,
organization: "Test Corp".to_string(),
expires_at: u64::MAX,
max_instances: 1,
features: vec![],
};
assert!(!valid.is_expired());
}
#[test]
fn test_signed_license_parse_invalid_format() {
let result = SignedLicense::parse("invalid-format");
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("Invalid license format"));
}
#[test]
fn test_signed_license_parse_invalid_base64() {
let result = SignedLicense::parse("not-base64.also-not-base64");
assert!(result.is_err());
}
const ISSUER_PUBKEY: &str = include_str!("../tests/fixtures/license/issuer_public.b64");
const WRONG_ISSUER_PUBKEY: &str = include_str!("../tests/fixtures/license/wrong_issuer_public.b64");
const GOLDEN_PROFESSIONAL: &str = include_str!("../tests/fixtures/license/golden_professional.lic");
const GOLDEN_TEAM: &str = include_str!("../tests/fixtures/license/golden_team.lic");
const GOLDEN_ENTERPRISE: &str = include_str!("../tests/fixtures/license/golden_enterprise.lic");
const GOLDEN_PERPETUAL: &str = include_str!("../tests/fixtures/license/golden_perpetual.lic");
const EXPIRED: &str = include_str!("../tests/fixtures/license/expired.lic");
fn verify_golden(license: &str) -> LicenseInfo {
let signed = SignedLicense::parse(license.trim()).unwrap();
signed.verify_with_key(ISSUER_PUBKEY.trim()).unwrap();
signed.extract_info().unwrap()
}
#[test]
fn test_golden_professional_verifies_with_all_features_lenient_dropped() {
let info = verify_golden(GOLDEN_PROFESSIONAL);
assert_eq!(info.tier, LicenseTier::Professional);
assert_eq!(info.organization, "VelesDB Golden Fixtures");
assert_eq!(info.expires_at, 4_102_444_799);
assert_eq!(info.max_instances, 1);
assert!(!info.is_expired());
assert!(info.features.is_empty());
}
#[test]
fn test_golden_team_verifies_and_filters_to_known_features() {
let info = verify_golden(GOLDEN_TEAM);
assert_eq!(info.tier, LicenseTier::Team);
assert_eq!(info.max_instances, 5);
assert_eq!(
info.features,
[PremiumFeature::Snapshots, PremiumFeature::EncryptionAtRest]
);
}
#[test]
fn test_golden_enterprise_u32_max_instances_decodes() {
let info = verify_golden(GOLDEN_ENTERPRISE);
assert_eq!(info.tier, LicenseTier::Enterprise);
assert_eq!(info.max_instances, i64::from(u32::MAX));
assert_eq!(info.expires_at_formatted(), "2099-12-31");
assert_eq!(
info.features,
[
PremiumFeature::Snapshots,
PremiumFeature::EncryptionAtRest,
PremiumFeature::MultiTenancy,
]
);
}
#[test]
fn test_golden_perpetual_never_expires_or_wraps_to_1969() {
let info = verify_golden(GOLDEN_PERPETUAL);
assert!(!info.is_expired());
assert_eq!(info.expires_at_formatted(), "Never");
assert_eq!(info.max_instances, i64::from(u32::MAX));
}
#[test]
fn test_signed_expired_fixture_rejected_by_validate_license() {
let err = validate_license(EXPIRED.trim(), ISSUER_PUBKEY.trim()).unwrap_err();
assert!(
err.to_string().contains("expired"),
"unexpected error: {err}"
);
}
#[test]
fn test_golden_fixture_tampered_payload_fails_verification() {
let mut parts = GOLDEN_TEAM.trim().split('.');
let payload_b64 = parts.next().unwrap();
let sig_b64 = parts.next().unwrap();
let mut payload = BASE64.decode(payload_b64).unwrap();
let mid = payload.len() / 2;
payload[mid] ^= 0x01;
let tampered = format!("{}.{}", BASE64.encode(&payload), sig_b64);
let signed = SignedLicense::parse(&tampered).unwrap();
assert!(signed.verify_with_key(ISSUER_PUBKEY.trim()).is_err());
}
#[test]
fn test_golden_fixture_wrong_issuer_key_fails_verification() {
let signed = SignedLicense::parse(GOLDEN_TEAM.trim()).unwrap();
assert!(signed.verify_with_key(WRONG_ISSUER_PUBKEY.trim()).is_err());
}
#[test]
fn test_golden_fixture_truncated_signature_rejected() {
let trimmed = GOLDEN_TEAM.trim();
let truncated = &trimmed[..trimmed.len() - 4];
assert!(SignedLicense::parse(truncated).is_err());
}