use eidetica::{auth::types::SigKey, crdt::Doc, instance::LegacyInstanceOps, store::DocStore};
use super::helpers::*;
use crate::helpers::*;
#[test]
fn test_get_entry_basic() {
let (_instance, tree) = setup_tree_with_key("test_key");
let entry_id = add_data_to_subtree(&tree, "data", &[("test_key", "test_value")]);
let entry = tree.get_entry(&entry_id).expect("Failed to get entry");
assert_eq!(entry.id(), entry_id);
assert_eq!(entry.sig.key, SigKey::Direct("test_key".to_string()));
assert!(entry.sig.sig.is_some());
}
#[test]
fn test_get_entries_multiple() {
let (_instance, tree) = setup_db_and_tree_with_key("test_key");
let entry_ids = create_linear_chain(&tree, "data", 3);
let entries = tree.get_entries(&entry_ids).expect("Failed to get entries");
assert_eq!(entries.len(), 3);
for (i, entry) in entries.iter().enumerate() {
assert_eq!(entry.id(), entry_ids[i]);
}
}
#[test]
fn test_entry_retrieval_error_handling() {
let (_instance, tree) = setup_db_and_tree_with_key("test_key");
let entry_id = add_data_to_subtree(&tree, "data", &[("key", "value")]);
assert!(tree.get_entry(&entry_id).is_ok());
let result = tree.get_entry("non_existent_entry");
assert!(result.is_err());
assert!(result.unwrap_err().is_not_found());
let entry_ids = vec![entry_id.as_str(), "non_existent_entry"];
let result = tree.get_entries(entry_ids);
assert!(result.is_err());
assert!(result.unwrap_err().is_not_found());
let result = tree.verify_entry_signature("non_existent_entry");
assert!(result.is_err());
assert!(result.unwrap_err().is_not_found());
}
#[test]
fn test_tree_validation_rejects_foreign_entries() {
let db = setup_db_with_key("test_key");
let mut settings1 = Doc::new();
settings1.set_string("name", "tree1".to_string());
let tree1 = db
.new_database(settings1, "test_key")
.expect("Failed to create tree1");
let mut settings2 = Doc::new();
settings2.set_string("name", "tree2".to_string());
let tree2 = db
.new_database(settings2, "test_key")
.expect("Failed to create tree2");
let op1 = tree1
.new_transaction()
.expect("Failed to create operation in tree1");
let store1 = op1
.get_store::<DocStore>("data")
.expect("Failed to get subtree in tree1");
store1
.set("key", "value1")
.expect("Failed to set value in tree1");
let entry1_id = op1.commit().expect("Failed to commit operation in tree1");
let op2 = tree2
.new_transaction()
.expect("Failed to create operation in tree2");
let store2 = op2
.get_store::<DocStore>("data")
.expect("Failed to get subtree in tree2");
store2
.set("key", "value2")
.expect("Failed to set value in tree2");
let entry2_id = op2.commit().expect("Failed to commit operation in tree2");
assert!(tree1.get_entry(&entry1_id).is_ok());
assert!(tree2.get_entry(&entry2_id).is_ok());
let result = tree1.get_entry(&entry2_id);
assert!(result.is_err());
let error_msg = result.unwrap_err().to_string();
assert!(error_msg.contains("does not belong to database"));
let result = tree2.get_entry(&entry1_id);
assert!(result.is_err());
let error_msg = result.unwrap_err().to_string();
assert!(error_msg.contains("does not belong to database"));
}
#[test]
fn test_tree_validation_get_entries() {
let db = setup_db_with_key("test_key");
let mut settings1 = Doc::new();
settings1.set_string("name", "tree1".to_string());
let tree1 = db
.new_database(settings1, "test_key")
.expect("Failed to create tree1");
let mut settings2 = Doc::new();
settings2.set_string("name", "tree2".to_string());
let tree2 = db
.new_database(settings2, "test_key")
.expect("Failed to create tree2");
let mut tree1_entries = Vec::new();
for i in 0..2 {
let op = tree1
.new_transaction()
.expect("Failed to create operation in tree1");
let store = op
.get_store::<DocStore>("data")
.expect("Failed to get subtree in tree1");
store
.set("key", format!("value1_{i}"))
.expect("Failed to set value in tree1");
let entry_id = op.commit().expect("Failed to commit operation in tree1");
tree1_entries.push(entry_id);
}
let op2 = tree2
.new_transaction()
.expect("Failed to create operation in tree2");
let store2 = op2
.get_store::<DocStore>("data")
.expect("Failed to get subtree in tree2");
store2
.set("key", "value2")
.expect("Failed to set value in tree2");
let entry2_id = op2.commit().expect("Failed to commit operation in tree2");
let entries = tree1
.get_entries(&tree1_entries)
.expect("Failed to get tree1 entries");
assert_eq!(entries.len(), 2);
let mixed_entries = vec![tree1_entries[0].clone(), entry2_id];
let result = tree1.get_entries(&mixed_entries);
assert!(result.is_err());
let error_msg = result.unwrap_err().to_string();
assert!(error_msg.contains("does not belong to database"));
}
#[test]
fn test_auth_helpers_signed_entries() {
let (_instance, tree) = setup_tree_with_auth_config("TEST_KEY");
let entry_id = add_authenticated_data(&tree, "data", &[("key", "value")]);
assert_entry_authentication(&tree, &entry_id, "TEST_KEY");
assert_entry_belongs_to_tree(&tree, &entry_id);
let entry = tree.get_entry(&entry_id).expect("Failed to get entry");
let sig_info = &entry.sig;
assert!(sig_info.is_signed_by("TEST_KEY"));
assert!(!sig_info.is_signed_by("OTHER_KEY"));
}
#[test]
fn test_auth_helpers_default_authenticated_entries() {
let (_instance, tree) = setup_db_and_tree_with_key("test_key");
let entry_id = add_data_to_subtree(&tree, "data", &[("key", "value")]);
assert_entry_authentication(&tree, &entry_id, "test_key");
let entry = tree.get_entry(&entry_id).expect("Failed to get entry");
let sig_info = &entry.sig;
assert!(sig_info.is_signed_by("test_key"));
assert!(!sig_info.is_signed_by("OTHER_KEY"));
}
#[test]
fn test_verify_entry_signature_auth_scenarios() {
let (_instance, tree) = setup_tree_with_auth_config("TEST_KEY");
let signed_entry_id = add_authenticated_data(&tree, "data", &[("key", "value1")]);
assert_entry_authentication(&tree, &signed_entry_id, "TEST_KEY");
let unsigned_entry_id = add_data_to_subtree(&tree, "data", &[("key", "value2")]);
let is_valid_unsigned = tree
.verify_entry_signature(&unsigned_entry_id)
.expect("Failed to verify unsigned entry");
assert!(is_valid_unsigned);
}
#[test]
fn test_verify_entry_signature_unauthorized_key() {
let (instance, tree) = setup_tree_with_auth_config("AUTHORIZED_KEY");
let _unauthorized_public_key = instance
.add_private_key("UNAUTHORIZED_KEY")
.expect("Failed to add unauthorized key");
let authorized_entry_id = add_authenticated_data(&tree, "data", &[("key", "value1")]);
assert_entry_authentication(&tree, &authorized_entry_id, "AUTHORIZED_KEY");
let unauthorized_signing_key = instance
.backend()
.get_private_key("UNAUTHORIZED_KEY")
.expect("Failed to get unauthorized signing key")
.expect("Unauthorized key should exist in backend");
let tree_with_unauthorized_key = eidetica::Database::open(
instance.clone(),
tree.root_id(),
unauthorized_signing_key,
"UNAUTHORIZED_KEY".to_string(),
)
.expect("Failed to load tree with unauthorized key");
let op2 = tree_with_unauthorized_key
.new_transaction()
.expect("Failed to create operation");
let store2 = op2
.get_store::<DocStore>("data")
.expect("Failed to get subtree");
store2.set("key", "value2").expect("Failed to set value");
let commit_result = op2.commit();
assert!(commit_result.is_err());
let error_msg = commit_result.unwrap_err().to_string();
assert!(
error_msg.contains("authentication validation failed")
|| error_msg.contains("not found")
|| error_msg.contains("No active key found")
);
}
#[test]
fn test_verify_entry_signature_validates_tree_auth() {
let (_instance, tree) = setup_tree_with_auth_config("VALID_KEY");
let entry_id = add_authenticated_data(&tree, "data", &[("key", "value")]);
assert_entry_authentication(&tree, &entry_id, "VALID_KEY");
}
#[test]
fn test_tree_queries() {
let (_instance, tree) = setup_db_and_tree_with_key("test_key");
let initial_entries = tree
.get_all_entries()
.expect("Failed to get initial entries");
let initial_count = initial_entries.len();
assert!(initial_count >= 1);
let mut entry_ids = Vec::new();
for i in 0..3 {
let op = tree.new_transaction().expect("Failed to create operation");
let store = op
.get_store::<DocStore>("data")
.expect("Failed to get subtree");
store
.set("key", format!("value_{i}"))
.expect("Failed to set value");
let entry_id = op.commit().expect("Failed to commit operation");
entry_ids.push(entry_id);
}
let all_entries = tree.get_all_entries().expect("Failed to get all entries");
assert_eq!(all_entries.len(), initial_count + 3);
for entry_id in &entry_ids {
let found = all_entries.iter().any(|entry| entry.id() == *entry_id);
assert!(found, "Entry {entry_id} not found in all_entries");
}
}
#[test]
fn test_batch_vs_individual_retrieval() {
let (_instance, tree) = setup_db_and_tree_with_key("test_key");
let mut entry_ids = Vec::new();
for i in 0..5 {
let op = tree.new_transaction().expect("Failed to create operation");
let store = op
.get_store::<DocStore>("data")
.expect("Failed to get subtree");
store
.set("key", format!("value_{i}"))
.expect("Failed to set value");
let entry_id = op.commit().expect("Failed to commit operation");
entry_ids.push(entry_id);
}
let mut individual_entries = Vec::new();
for entry_id in &entry_ids {
let entry = tree.get_entry(entry_id).expect("Failed to get entry");
individual_entries.push(entry);
}
let batch_entries = tree.get_entries(&entry_ids).expect("Failed to get entries");
assert_eq!(individual_entries.len(), batch_entries.len());
for (individual, batch) in individual_entries.iter().zip(batch_entries.iter()) {
assert_eq!(individual.id(), batch.id());
assert_eq!(individual.sig, batch.sig);
}
}