use chaotic_semantic_memory::prelude::*;
use tempfile::NamedTempFile;
#[tokio::test]
async fn export_json_path_too_long_rejected() {
let framework = ChaoticSemanticFramework::builder()
.without_persistence()
.build()
.await
.unwrap();
framework
.inject_concept("long-path", HVec10240::random())
.await
.unwrap();
let long_path = "/tmp/".to_string() + &"x".repeat(5000);
let result = framework.export_json(&long_path).await;
assert!(result.is_err());
}
#[tokio::test]
async fn export_json_path_traversal_rejected() {
let framework = ChaoticSemanticFramework::builder()
.without_persistence()
.build()
.await
.unwrap();
framework
.inject_concept("traversal", HVec10240::random())
.await
.unwrap();
let traversal_path = "/tmp/../etc/passwd";
let result = framework.export_json(traversal_path).await;
assert!(result.is_err());
}
#[tokio::test]
async fn import_json_skips_invalid_association() {
let framework = ChaoticSemanticFramework::builder()
.without_persistence()
.build()
.await
.unwrap();
let vector1 = HVec10240::random();
let vector2 = HVec10240::random();
let vector3 = HVec10240::random();
let v1_b64 = serde_json::to_string(&vector1).unwrap();
let v2_b64 = serde_json::to_string(&vector2).unwrap();
let v3_b64 = serde_json::to_string(&vector3).unwrap();
let v1_b64 = v1_b64.trim_matches('"');
let v2_b64 = v2_b64.trim_matches('"');
let v3_b64 = v3_b64.trim_matches('"');
let payload_json = serde_json::json!({
"version": "0.3.5",
"exported_at": 12345,
"concepts": [
{
"id": "import-invalid-0",
"vector": v1_b64,
"metadata": {},
"created_at": 1,
"modified_at": 1
},
{
"id": "import-invalid-1",
"vector": v2_b64,
"metadata": {},
"created_at": 1,
"modified_at": 1
},
{
"id": "import-invalid-2",
"vector": v3_b64,
"metadata": {},
"created_at": 1,
"modified_at": 1
}
],
"associations": [
["import-invalid-0", "import-invalid-1", 0.5],
["import-invalid-0", "import-invalid-2", -0.5] ]
});
let temp = NamedTempFile::new().unwrap();
let path = temp.path().to_str().unwrap();
std::fs::write(path, serde_json::to_string(&payload_json).unwrap()).unwrap();
let imported = framework.import_json(path, false).await.unwrap();
assert_eq!(imported, 3);
}
#[tokio::test]
async fn backup_and_restore_with_persistence() {
let temp = NamedTempFile::new().unwrap();
let db_path = temp.path().to_str().unwrap().to_string();
let framework = ChaoticSemanticFramework::builder()
.with_local_db(db_path.clone())
.build()
.await
.unwrap();
framework
.inject_concept("backup-1", HVec10240::random())
.await
.unwrap();
framework
.inject_concept("backup-2", HVec10240::random())
.await
.unwrap();
framework.persist().await.unwrap();
let backup_temp = NamedTempFile::new().unwrap();
let backup_path = backup_temp.path().to_str().unwrap();
framework.backup(backup_path).await.unwrap();
let restore_temp = NamedTempFile::new().unwrap();
let restore_path = restore_temp.path().to_str().unwrap().to_string();
let framework2 = ChaoticSemanticFramework::builder()
.with_local_db(restore_path)
.build()
.await
.unwrap();
framework2.restore(backup_path).await.unwrap();
let stats = framework2.stats().await.unwrap();
assert_eq!(stats.concept_count, 2);
}
#[tokio::test]
async fn concept_history_with_limit_clamping() {
let temp = NamedTempFile::new().unwrap();
let db_path = temp.path().to_str().unwrap().to_string();
let framework = ChaoticSemanticFramework::builder()
.with_local_db(db_path)
.build()
.await
.unwrap();
framework
.inject_concept("history-limit", HVec10240::random())
.await
.unwrap();
let history = framework
.concept_history("history-limit", 5000)
.await
.unwrap();
assert!(history.len() <= 1000);
}