use super::*;
use amari_holographic::optical::{CodebookConfig, LeeEncoderConfig};
use std::time::Duration;
use tempfile::tempdir;
fn test_encoder_config() -> LeeEncoderConfig {
LeeEncoderConfig {
carrier_frequency: 0.25,
carrier_angle: 0.0,
dimensions: (256, 256),
}
}
fn test_codebook_config() -> CodebookConfig {
CodebookConfig {
dimensions: (256, 256),
base_seed: 12345,
}
}
#[test]
fn test_symbolic_expression_roundtrip() {
let expr = SymbolicExpression::bind(
SymbolicExpression::symbol("AGENT"),
SymbolicExpression::symbol("John"),
);
let json = serde_json::to_string(&expr).unwrap();
let restored: SymbolicExpression = serde_json::from_str(&json).unwrap();
assert_eq!(expr, restored);
}
#[test]
fn test_journal_replay_consistency() {
let mut journal = MemoryJournal::new(test_encoder_config(), test_codebook_config());
journal.ops.push(MemoryOp::RegisterSymbol {
symbol: amari_holographic::optical::SymbolId::new("AGENT"),
seed: Some(12345),
timestamp: 1000,
});
journal.ops.push(MemoryOp::Store {
key: SymbolicExpression::symbol("test_key"),
value: SymbolicExpression::symbol("test_value"),
strength: 1.0,
timestamp: 2000,
});
let state = journal.replay_to_state();
assert_eq!(state.associations.len(), 1);
assert!(state
.symbol_seeds
.contains_key(&amari_holographic::optical::SymbolId::new("AGENT")));
}
#[test]
fn test_checkpoint_restore_same_hardware() {
let dir = tempdir().unwrap();
let journal_path = dir.path().join("test_journal.bin");
let hardware = MockOpticalHardware::new(42);
let config = CheckpointConfig {
journal_path: journal_path.clone(),
interval: Duration::from_secs(3600), ..Default::default()
};
let mut memory = CheckpointedOpticalMemory::new(
hardware,
test_encoder_config(),
test_codebook_config(),
config.clone(),
)
.unwrap();
memory
.store(
SymbolicExpression::role_filler("AGENT", "John"),
SymbolicExpression::role_filler("ACTION", "run"),
)
.unwrap();
memory.checkpoint().unwrap();
drop(memory);
let same_hardware = MockOpticalHardware::new(42);
let mut restored = CheckpointedOpticalMemory::restore(same_hardware, config).unwrap();
let result = restored
.retrieve(&SymbolicExpression::role_filler("AGENT", "John"))
.unwrap();
assert!(result.is_some());
}
#[test]
fn test_checkpoint_restore_different_hardware() {
let dir = tempdir().unwrap();
let journal_path = dir.path().join("test_journal.bin");
let hardware = MockOpticalHardware::new(42);
let config = CheckpointConfig {
journal_path: journal_path.clone(),
interval: Duration::from_secs(3600),
..Default::default()
};
let mut memory = CheckpointedOpticalMemory::new(
hardware,
test_encoder_config(),
test_codebook_config(),
config.clone(),
)
.unwrap();
memory
.store(
SymbolicExpression::role_filler("AGENT", "John"),
SymbolicExpression::role_filler("ACTION", "run"),
)
.unwrap();
memory.checkpoint().unwrap();
drop(memory);
let different_hardware = MockOpticalHardware::new(999); let mut restored = CheckpointedOpticalMemory::restore(different_hardware, config).unwrap();
let result = restored
.retrieve(&SymbolicExpression::role_filler("AGENT", "John"))
.unwrap();
assert!(result.is_some());
}
#[test]
fn test_fingerprint_detects_drift() {
let mut hardware = MockOpticalHardware::new(42);
let fingerprint = TMatrixFingerprint::capture(&mut hardware, 5).unwrap();
let validation = fingerprint.validate(&mut hardware).unwrap();
assert!(matches!(validation, FingerprintValidation::Valid));
hardware.drift_t_matrix(0.5);
let validation = fingerprint.validate(&mut hardware).unwrap();
assert!(!matches!(validation, FingerprintValidation::Valid));
}
#[test]
fn test_fingerprint_detects_different_hardware() {
let mut hardware1 = MockOpticalHardware::new(42);
let fingerprint = TMatrixFingerprint::capture(&mut hardware1, 5).unwrap();
let mut hardware2 = MockOpticalHardware::new(999);
let validation = fingerprint.validate(&mut hardware2).unwrap();
assert!(matches!(
validation,
FingerprintValidation::DifferentHardware { .. }
));
}
#[test]
fn test_store_retrieve_basic() {
let dir = tempdir().unwrap();
let journal_path = dir.path().join("test_journal.bin");
let hardware = MockOpticalHardware::new(42);
let config = CheckpointConfig {
journal_path,
interval: Duration::from_secs(3600),
..Default::default()
};
let mut memory = CheckpointedOpticalMemory::new(
hardware,
test_encoder_config(),
test_codebook_config(),
config,
)
.unwrap();
memory
.store(
SymbolicExpression::symbol("cat"),
SymbolicExpression::symbol("meow"),
)
.unwrap();
memory
.store(
SymbolicExpression::symbol("dog"),
SymbolicExpression::symbol("bark"),
)
.unwrap();
let cat_result = memory.retrieve(&SymbolicExpression::symbol("cat")).unwrap();
assert!(cat_result.is_some());
assert_eq!(
cat_result.unwrap().value,
SymbolicExpression::symbol("meow")
);
let dog_result = memory.retrieve(&SymbolicExpression::symbol("dog")).unwrap();
assert!(dog_result.is_some());
assert_eq!(
dog_result.unwrap().value,
SymbolicExpression::symbol("bark")
);
}
#[test]
fn test_memory_decay() {
let dir = tempdir().unwrap();
let journal_path = dir.path().join("test_journal.bin");
let hardware = MockOpticalHardware::new(42);
let config = CheckpointConfig {
journal_path,
interval: Duration::from_secs(3600),
..Default::default()
};
let mut memory = CheckpointedOpticalMemory::new(
hardware,
test_encoder_config(),
test_codebook_config(),
config,
)
.unwrap();
memory
.store(
SymbolicExpression::symbol("key"),
SymbolicExpression::symbol("value"),
)
.unwrap();
memory.decay(0.5).unwrap();
let stats = memory.stats();
assert_eq!(stats.n_associations, 1);
memory.decay(0.01).unwrap();
let stats = memory.stats();
assert_eq!(stats.n_associations, 0);
}
#[test]
fn test_memory_forget() {
let dir = tempdir().unwrap();
let journal_path = dir.path().join("test_journal.bin");
let hardware = MockOpticalHardware::new(42);
let config = CheckpointConfig {
journal_path,
interval: Duration::from_secs(3600),
..Default::default()
};
let mut memory = CheckpointedOpticalMemory::new(
hardware,
test_encoder_config(),
test_codebook_config(),
config,
)
.unwrap();
memory
.store(
SymbolicExpression::symbol("key1"),
SymbolicExpression::symbol("value1"),
)
.unwrap();
memory
.store(
SymbolicExpression::symbol("key2"),
SymbolicExpression::symbol("value2"),
)
.unwrap();
assert_eq!(memory.stats().n_associations, 2);
memory.forget(&SymbolicExpression::symbol("key1")).unwrap();
assert_eq!(memory.stats().n_associations, 1);
let result = memory
.retrieve(&SymbolicExpression::symbol("key1"))
.unwrap();
assert!(result.is_none());
}
#[test]
fn test_hardware_info() {
let dir = tempdir().unwrap();
let journal_path = dir.path().join("test_journal.bin");
let hardware = MockOpticalHardware::new(42);
let config = CheckpointConfig {
journal_path,
..Default::default()
};
let memory = CheckpointedOpticalMemory::new(
hardware,
test_encoder_config(),
test_codebook_config(),
config,
)
.unwrap();
let info = memory.hardware_info();
assert!(info.is_ready);
assert!(info.is_calibrated);
assert_eq!(info.dimensions, (256, 256));
assert_eq!(info.n_modes, 100);
}
#[test]
fn test_journal_compaction() {
let mut journal = MemoryJournal::new(test_encoder_config(), test_codebook_config());
for i in 0..100 {
journal.append(MemoryOp::store(
SymbolicExpression::symbol(format!("key{}", i)),
SymbolicExpression::symbol(format!("value{}", i)),
1.0,
));
}
assert_eq!(journal.ops.len(), 100);
assert!(journal.base_state.is_none());
journal.compact();
assert!(journal.ops.is_empty());
assert!(journal.base_state.is_some());
assert_eq!(journal.base_state.as_ref().unwrap().associations.len(), 100);
}
#[test]
fn test_journal_save_load() {
let dir = tempdir().unwrap();
let path = dir.path().join("test_journal.bin");
let mut journal = MemoryJournal::new(test_encoder_config(), test_codebook_config());
journal.append(MemoryOp::store(
SymbolicExpression::symbol("key"),
SymbolicExpression::symbol("value"),
1.0,
));
journal.save(&path).unwrap();
let loaded = MemoryJournal::load(&path).unwrap();
assert_eq!(loaded.ops.len(), 1);
}