#![allow(clippy::float_cmp)]
use chaotic_semantic_memory::index::IndexBackend;
use chaotic_semantic_memory::prelude::*;
use chaotic_semantic_memory::reservoir::Reservoir;
use chaotic_semantic_memory::singularity::{Concept, Singularity, SingularityConfig};
use std::collections::HashMap;
const NS: &str = "_default";
#[tokio::test]
async fn empty_sequence_returns_zero_hypervector() {
let framework = ChaoticSemanticFramework::builder()
.without_persistence()
.with_reservoir_size(HVec10240::DIMENSION)
.build()
.await
.unwrap();
let output = framework.process_sequence(&[]).await.unwrap();
assert_eq!(output, HVec10240::zero());
}
#[test]
fn zero_length_inputs_are_rejected() {
let mut reservoir = Reservoir::new_seeded(8, 64, 7).unwrap();
assert!(reservoir.step(&[]).is_err());
assert!(Reservoir::new_seeded(0, 64, 7).is_err());
}
#[test]
fn concept_and_association_limits_enforced() {
let mut singularity = Singularity::with_config(SingularityConfig {
max_concepts: Some(2),
max_associations_per_concept: Some(1),
concept_cache_size: 64,
max_cached_top_k: 100,
index_backend: IndexBackend::BruteForce,
});
let mk = |id: &str, created_at: u64| Concept {
id: id.to_string(),
vector: HVec10240::random(),
metadata: HashMap::new(),
created_at,
modified_at: created_at,
expires_at: None,
canonical_concept_ids: Vec::new(),
};
singularity.inject(NS, mk("a", 1)).unwrap();
singularity.inject(NS, mk("b", 2)).unwrap();
singularity.inject(NS, mk("c", 3)).unwrap();
assert_eq!(singularity.len(NS), 2);
assert!(singularity.get(NS, "a").is_none());
assert!(singularity.get(NS, "b").is_some());
assert!(singularity.get(NS, "c").is_some());
singularity.associate(NS, "b", "c", 0.9).unwrap();
singularity.associate(NS, "b", "b", 0.1).unwrap();
let links = singularity.get_associations(NS, "b");
assert_eq!(links.len(), 1);
assert_eq!(links[0].0, "c");
}
#[test]
fn singularity_association_strength_is_validated() {
let mut singularity = Singularity::new(SingularityConfig::default());
let mk = |id: &str| Concept {
id: id.to_string(),
vector: HVec10240::random(),
metadata: HashMap::new(),
created_at: 1,
modified_at: 1,
expires_at: None,
canonical_concept_ids: Vec::new(),
};
singularity.inject(NS, mk("a")).unwrap();
singularity.inject(NS, mk("b")).unwrap();
assert!(singularity.associate(NS, "a", "b", f32::NAN).is_err());
assert!(singularity.associate(NS, "a", "b", f32::INFINITY).is_err());
assert!(singularity.associate(NS, "a", "b", -0.1).is_err());
assert!(singularity.associate(NS, "a", "b", 1.1).is_err());
}
#[test]
fn singularity_association_updates_instead_of_duplicating() {
let mut singularity = Singularity::new(SingularityConfig::default());
let mk = |id: &str| Concept {
id: id.to_string(),
vector: HVec10240::random(),
metadata: HashMap::new(),
created_at: 1,
modified_at: 1,
expires_at: None,
canonical_concept_ids: Vec::new(),
};
singularity.inject(NS, mk("a")).unwrap();
singularity.inject(NS, mk("b")).unwrap();
singularity.associate(NS, "a", "b", 0.2).unwrap();
singularity.associate(NS, "a", "b", 0.9).unwrap();
let links = singularity.get_associations(NS, "a");
assert_eq!(links.len(), 1);
assert_eq!(links[0].0, "b");
assert_eq!(links[0].1, 0.9);
}
#[test]
fn spectral_radius_inclusive_bounds() {
let mut reservoir = Reservoir::new_seeded(8, 64, 11).unwrap();
assert!(reservoir.set_spectral_radius(0.9).is_ok());
assert!(reservoir.set_spectral_radius(1.1).is_ok());
assert!(reservoir.set_spectral_radius(0.8999).is_err());
assert!(reservoir.set_spectral_radius(1.1001).is_err());
}
#[test]
fn reservoir_size_boundaries() {
let small = Reservoir::new_seeded(1, 1, 3).unwrap();
assert_eq!(small.size(), 1);
assert!(small.to_hypervector().is_err());
let mut exact = Reservoir::new_seeded(1, HVec10240::DIMENSION, 3).unwrap();
exact.step(&[0.25]).unwrap();
assert!(exact.to_hypervector().is_ok());
}