set up tests and examples
This commit is contained in:
		
							
								
								
									
										144
									
								
								radixtree/tests/basic_test.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								radixtree/tests/basic_test.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,144 @@
 | 
			
		||||
use radixtree::RadixTree;
 | 
			
		||||
use std::path::PathBuf;
 | 
			
		||||
use tempfile::tempdir;
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_basic_operations() -> Result<(), radixtree::Error> {
 | 
			
		||||
    // Create a temporary directory for the test
 | 
			
		||||
    let temp_dir = tempdir().expect("Failed to create temp directory");
 | 
			
		||||
    let db_path = temp_dir.path().to_str().unwrap();
 | 
			
		||||
    
 | 
			
		||||
    // Create a new radix tree
 | 
			
		||||
    let mut tree = RadixTree::new(db_path, true)?;
 | 
			
		||||
    
 | 
			
		||||
    // Test setting and getting values
 | 
			
		||||
    let key = "test_key";
 | 
			
		||||
    let value = b"test_value".to_vec();
 | 
			
		||||
    tree.set(key, value.clone())?;
 | 
			
		||||
    
 | 
			
		||||
    let retrieved_value = tree.get(key)?;
 | 
			
		||||
    assert_eq!(retrieved_value, value);
 | 
			
		||||
    
 | 
			
		||||
    // Test updating a value
 | 
			
		||||
    let new_value = b"updated_value".to_vec();
 | 
			
		||||
    tree.update(key, new_value.clone())?;
 | 
			
		||||
    
 | 
			
		||||
    let updated_value = tree.get(key)?;
 | 
			
		||||
    assert_eq!(updated_value, new_value);
 | 
			
		||||
    
 | 
			
		||||
    // Test deleting a value
 | 
			
		||||
    tree.delete(key)?;
 | 
			
		||||
    
 | 
			
		||||
    // Trying to get a deleted key should return an error
 | 
			
		||||
    let result = tree.get(key);
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_empty_key() -> Result<(), radixtree::Error> {
 | 
			
		||||
    // Create a temporary directory for the test
 | 
			
		||||
    let temp_dir = tempdir().expect("Failed to create temp directory");
 | 
			
		||||
    let db_path = temp_dir.path().to_str().unwrap();
 | 
			
		||||
    
 | 
			
		||||
    // Create a new radix tree
 | 
			
		||||
    let mut tree = RadixTree::new(db_path, true)?;
 | 
			
		||||
    
 | 
			
		||||
    // Test setting and getting empty key
 | 
			
		||||
    let key = "";
 | 
			
		||||
    let value = b"value_for_empty_key".to_vec();
 | 
			
		||||
    tree.set(key, value.clone())?;
 | 
			
		||||
    
 | 
			
		||||
    let retrieved_value = tree.get(key)?;
 | 
			
		||||
    assert_eq!(retrieved_value, value);
 | 
			
		||||
    
 | 
			
		||||
    // Test deleting empty key
 | 
			
		||||
    tree.delete(key)?;
 | 
			
		||||
    
 | 
			
		||||
    // Trying to get a deleted key should return an error
 | 
			
		||||
    let result = tree.get(key);
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_multiple_keys() -> Result<(), radixtree::Error> {
 | 
			
		||||
    // Create a temporary directory for the test
 | 
			
		||||
    let temp_dir = tempdir().expect("Failed to create temp directory");
 | 
			
		||||
    let db_path = temp_dir.path().to_str().unwrap();
 | 
			
		||||
    
 | 
			
		||||
    // Create a new radix tree
 | 
			
		||||
    let mut tree = RadixTree::new(db_path, true)?;
 | 
			
		||||
    
 | 
			
		||||
    // Insert multiple keys
 | 
			
		||||
    let test_data = [
 | 
			
		||||
        ("key1", b"value1".to_vec()),
 | 
			
		||||
        ("key2", b"value2".to_vec()),
 | 
			
		||||
        ("key3", b"value3".to_vec()),
 | 
			
		||||
    ];
 | 
			
		||||
    
 | 
			
		||||
    for (key, value) in &test_data {
 | 
			
		||||
        tree.set(key, value.clone())?;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Verify all keys can be retrieved
 | 
			
		||||
    for (key, expected_value) in &test_data {
 | 
			
		||||
        let retrieved_value = tree.get(key)?;
 | 
			
		||||
        assert_eq!(&retrieved_value, expected_value);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_shared_prefixes() -> Result<(), radixtree::Error> {
 | 
			
		||||
    // Create a temporary directory for the test
 | 
			
		||||
    let temp_dir = tempdir().expect("Failed to create temp directory");
 | 
			
		||||
    let db_path = temp_dir.path().to_str().unwrap();
 | 
			
		||||
    
 | 
			
		||||
    // Create a new radix tree
 | 
			
		||||
    let mut tree = RadixTree::new(db_path, true)?;
 | 
			
		||||
    
 | 
			
		||||
    // Insert keys with shared prefixes
 | 
			
		||||
    let test_data = [
 | 
			
		||||
        ("test", b"value_test".to_vec()),
 | 
			
		||||
        ("testing", b"value_testing".to_vec()),
 | 
			
		||||
        ("tested", b"value_tested".to_vec()),
 | 
			
		||||
    ];
 | 
			
		||||
    
 | 
			
		||||
    for (key, value) in &test_data {
 | 
			
		||||
        tree.set(key, value.clone())?;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Verify all keys can be retrieved
 | 
			
		||||
    for (key, expected_value) in &test_data {
 | 
			
		||||
        let retrieved_value = tree.get(key)?;
 | 
			
		||||
        assert_eq!(&retrieved_value, expected_value);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_persistence() -> Result<(), radixtree::Error> {
 | 
			
		||||
    // Create a temporary directory for the test
 | 
			
		||||
    let temp_dir = tempdir().expect("Failed to create temp directory");
 | 
			
		||||
    let db_path = temp_dir.path().to_str().unwrap();
 | 
			
		||||
    
 | 
			
		||||
    // Create a new radix tree and add some data
 | 
			
		||||
    {
 | 
			
		||||
        let mut tree = RadixTree::new(db_path, true)?;
 | 
			
		||||
        tree.set("persistent_key", b"persistent_value".to_vec())?;
 | 
			
		||||
    } // Tree is dropped here
 | 
			
		||||
    
 | 
			
		||||
    // Create a new tree instance with the same path
 | 
			
		||||
    {
 | 
			
		||||
        let mut tree = RadixTree::new(db_path, false)?;
 | 
			
		||||
        let value = tree.get("persistent_key")?;
 | 
			
		||||
        assert_eq!(value, b"persistent_value".to_vec());
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										153
									
								
								radixtree/tests/getall_test.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								radixtree/tests/getall_test.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,153 @@
 | 
			
		||||
use radixtree::RadixTree;
 | 
			
		||||
use std::collections::HashMap;
 | 
			
		||||
use tempfile::tempdir;
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_getall() -> Result<(), radixtree::Error> {
 | 
			
		||||
    // Create a temporary directory for the test
 | 
			
		||||
    let temp_dir = tempdir().expect("Failed to create temp directory");
 | 
			
		||||
    let db_path = temp_dir.path().to_str().unwrap();
 | 
			
		||||
    
 | 
			
		||||
    // Create a new radix tree
 | 
			
		||||
    let mut tree = RadixTree::new(db_path, true)?;
 | 
			
		||||
 | 
			
		||||
    // Set up test data with common prefixes
 | 
			
		||||
    let test_data: HashMap<&str, &str> = [
 | 
			
		||||
        ("user_1", "data1"),
 | 
			
		||||
        ("user_2", "data2"),
 | 
			
		||||
        ("user_3", "data3"),
 | 
			
		||||
        ("admin_1", "admin_data1"),
 | 
			
		||||
        ("admin_2", "admin_data2"),
 | 
			
		||||
        ("guest", "guest_data"),
 | 
			
		||||
    ].iter().cloned().collect();
 | 
			
		||||
 | 
			
		||||
    // Set all test data
 | 
			
		||||
    for (key, value) in &test_data {
 | 
			
		||||
        tree.set(key, value.as_bytes().to_vec())?;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Test getall with 'user_' prefix
 | 
			
		||||
    let user_values = tree.getall("user_")?;
 | 
			
		||||
    
 | 
			
		||||
    // Should return 3 values
 | 
			
		||||
    assert_eq!(user_values.len(), 3);
 | 
			
		||||
 | 
			
		||||
    // Convert byte arrays to strings for easier comparison
 | 
			
		||||
    let user_value_strings: Vec<String> = user_values
 | 
			
		||||
        .iter()
 | 
			
		||||
        .map(|v| String::from_utf8_lossy(v).to_string())
 | 
			
		||||
        .collect();
 | 
			
		||||
 | 
			
		||||
    // Check all expected values are present
 | 
			
		||||
    assert!(user_value_strings.contains(&"data1".to_string()));
 | 
			
		||||
    assert!(user_value_strings.contains(&"data2".to_string()));
 | 
			
		||||
    assert!(user_value_strings.contains(&"data3".to_string()));
 | 
			
		||||
 | 
			
		||||
    // Test getall with 'admin_' prefix
 | 
			
		||||
    let admin_values = tree.getall("admin_")?;
 | 
			
		||||
    
 | 
			
		||||
    // Should return 2 values
 | 
			
		||||
    assert_eq!(admin_values.len(), 2);
 | 
			
		||||
 | 
			
		||||
    // Convert byte arrays to strings for easier comparison
 | 
			
		||||
    let admin_value_strings: Vec<String> = admin_values
 | 
			
		||||
        .iter()
 | 
			
		||||
        .map(|v| String::from_utf8_lossy(v).to_string())
 | 
			
		||||
        .collect();
 | 
			
		||||
 | 
			
		||||
    // Check all expected values are present
 | 
			
		||||
    assert!(admin_value_strings.contains(&"admin_data1".to_string()));
 | 
			
		||||
    assert!(admin_value_strings.contains(&"admin_data2".to_string()));
 | 
			
		||||
 | 
			
		||||
    // Test getall with empty prefix (should return all values)
 | 
			
		||||
    let all_values = tree.getall("")?;
 | 
			
		||||
    
 | 
			
		||||
    // Should return all 6 values
 | 
			
		||||
    assert_eq!(all_values.len(), test_data.len());
 | 
			
		||||
 | 
			
		||||
    // Test getall with non-existent prefix
 | 
			
		||||
    let non_existent_values = tree.getall("xyz")?;
 | 
			
		||||
    
 | 
			
		||||
    // Should return empty array
 | 
			
		||||
    assert_eq!(non_existent_values.len(), 0);
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_getall_with_updates() -> Result<(), radixtree::Error> {
 | 
			
		||||
    // Create a temporary directory for the test
 | 
			
		||||
    let temp_dir = tempdir().expect("Failed to create temp directory");
 | 
			
		||||
    let db_path = temp_dir.path().to_str().unwrap();
 | 
			
		||||
    
 | 
			
		||||
    // Create a new radix tree
 | 
			
		||||
    let mut tree = RadixTree::new(db_path, true)?;
 | 
			
		||||
 | 
			
		||||
    // Set initial values
 | 
			
		||||
    tree.set("key1", b"value1".to_vec())?;
 | 
			
		||||
    tree.set("key2", b"value2".to_vec())?;
 | 
			
		||||
    tree.set("key3", b"value3".to_vec())?;
 | 
			
		||||
 | 
			
		||||
    // Get initial values
 | 
			
		||||
    let initial_values = tree.getall("key")?;
 | 
			
		||||
    assert_eq!(initial_values.len(), 3);
 | 
			
		||||
 | 
			
		||||
    // Update a value
 | 
			
		||||
    tree.update("key2", b"updated_value2".to_vec())?;
 | 
			
		||||
 | 
			
		||||
    // Get values after update
 | 
			
		||||
    let updated_values = tree.getall("key")?;
 | 
			
		||||
    assert_eq!(updated_values.len(), 3);
 | 
			
		||||
 | 
			
		||||
    // Convert to strings for easier comparison
 | 
			
		||||
    let updated_value_strings: Vec<String> = updated_values
 | 
			
		||||
        .iter()
 | 
			
		||||
        .map(|v| String::from_utf8_lossy(v).to_string())
 | 
			
		||||
        .collect();
 | 
			
		||||
 | 
			
		||||
    // Check the updated value is present
 | 
			
		||||
    assert!(updated_value_strings.contains(&"value1".to_string()));
 | 
			
		||||
    assert!(updated_value_strings.contains(&"updated_value2".to_string()));
 | 
			
		||||
    assert!(updated_value_strings.contains(&"value3".to_string()));
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_getall_with_deletions() -> Result<(), radixtree::Error> {
 | 
			
		||||
    // Create a temporary directory for the test
 | 
			
		||||
    let temp_dir = tempdir().expect("Failed to create temp directory");
 | 
			
		||||
    let db_path = temp_dir.path().to_str().unwrap();
 | 
			
		||||
    
 | 
			
		||||
    // Create a new radix tree
 | 
			
		||||
    let mut tree = RadixTree::new(db_path, true)?;
 | 
			
		||||
 | 
			
		||||
    // Set initial values
 | 
			
		||||
    tree.set("prefix_1", b"value1".to_vec())?;
 | 
			
		||||
    tree.set("prefix_2", b"value2".to_vec())?;
 | 
			
		||||
    tree.set("prefix_3", b"value3".to_vec())?;
 | 
			
		||||
    tree.set("other", b"other_value".to_vec())?;
 | 
			
		||||
 | 
			
		||||
    // Get initial values
 | 
			
		||||
    let initial_values = tree.getall("prefix_")?;
 | 
			
		||||
    assert_eq!(initial_values.len(), 3);
 | 
			
		||||
 | 
			
		||||
    // Delete a key
 | 
			
		||||
    tree.delete("prefix_2")?;
 | 
			
		||||
 | 
			
		||||
    // Get values after deletion
 | 
			
		||||
    let after_delete_values = tree.getall("prefix_")?;
 | 
			
		||||
    assert_eq!(after_delete_values.len(), 2);
 | 
			
		||||
 | 
			
		||||
    // Convert to strings for easier comparison
 | 
			
		||||
    let after_delete_strings: Vec<String> = after_delete_values
 | 
			
		||||
        .iter()
 | 
			
		||||
        .map(|v| String::from_utf8_lossy(v).to_string())
 | 
			
		||||
        .collect();
 | 
			
		||||
 | 
			
		||||
    // Check the remaining values
 | 
			
		||||
    assert!(after_delete_strings.contains(&"value1".to_string()));
 | 
			
		||||
    assert!(after_delete_strings.contains(&"value3".to_string()));
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										185
									
								
								radixtree/tests/prefix_test.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								radixtree/tests/prefix_test.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,185 @@
 | 
			
		||||
use radixtree::RadixTree;
 | 
			
		||||
use std::collections::HashMap;
 | 
			
		||||
use tempfile::tempdir;
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_list() -> Result<(), radixtree::Error> {
 | 
			
		||||
    // Create a temporary directory for the test
 | 
			
		||||
    let temp_dir = tempdir().expect("Failed to create temp directory");
 | 
			
		||||
    let db_path = temp_dir.path().to_str().unwrap();
 | 
			
		||||
    
 | 
			
		||||
    // Create a new radix tree
 | 
			
		||||
    let mut tree = RadixTree::new(db_path, true)?;
 | 
			
		||||
 | 
			
		||||
    // Insert keys with various prefixes
 | 
			
		||||
    let test_data: HashMap<&str, &str> = [
 | 
			
		||||
        ("apple", "fruit1"),
 | 
			
		||||
        ("application", "software1"),
 | 
			
		||||
        ("apply", "verb1"),
 | 
			
		||||
        ("banana", "fruit2"),
 | 
			
		||||
        ("ball", "toy1"),
 | 
			
		||||
        ("cat", "animal1"),
 | 
			
		||||
        ("car", "vehicle1"),
 | 
			
		||||
        ("cargo", "shipping1"),
 | 
			
		||||
    ].iter().cloned().collect();
 | 
			
		||||
 | 
			
		||||
    // Set all test data
 | 
			
		||||
    for (key, value) in &test_data {
 | 
			
		||||
        tree.set(key, value.as_bytes().to_vec())?;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Test prefix 'app' - should return apple, application, apply
 | 
			
		||||
    let app_keys = tree.list("app")?;
 | 
			
		||||
    assert_eq!(app_keys.len(), 3);
 | 
			
		||||
    assert!(app_keys.contains(&"apple".to_string()));
 | 
			
		||||
    assert!(app_keys.contains(&"application".to_string()));
 | 
			
		||||
    assert!(app_keys.contains(&"apply".to_string()));
 | 
			
		||||
 | 
			
		||||
    // Test prefix 'ba' - should return banana, ball
 | 
			
		||||
    let ba_keys = tree.list("ba")?;
 | 
			
		||||
    assert_eq!(ba_keys.len(), 2);
 | 
			
		||||
    assert!(ba_keys.contains(&"banana".to_string()));
 | 
			
		||||
    assert!(ba_keys.contains(&"ball".to_string()));
 | 
			
		||||
 | 
			
		||||
    // Test prefix 'car' - should return car, cargo
 | 
			
		||||
    let car_keys = tree.list("car")?;
 | 
			
		||||
    assert_eq!(car_keys.len(), 2);
 | 
			
		||||
    assert!(car_keys.contains(&"car".to_string()));
 | 
			
		||||
    assert!(car_keys.contains(&"cargo".to_string()));
 | 
			
		||||
 | 
			
		||||
    // Test prefix 'z' - should return empty list
 | 
			
		||||
    let z_keys = tree.list("z")?;
 | 
			
		||||
    assert_eq!(z_keys.len(), 0);
 | 
			
		||||
 | 
			
		||||
    // Test empty prefix - should return all keys
 | 
			
		||||
    let all_keys = tree.list("")?;
 | 
			
		||||
    assert_eq!(all_keys.len(), test_data.len());
 | 
			
		||||
    for key in test_data.keys() {
 | 
			
		||||
        assert!(all_keys.contains(&key.to_string()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Test exact key as prefix - should return just that key
 | 
			
		||||
    let exact_key = tree.list("apple")?;
 | 
			
		||||
    assert_eq!(exact_key.len(), 1);
 | 
			
		||||
    assert_eq!(exact_key[0], "apple");
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_list_with_deletion() -> Result<(), radixtree::Error> {
 | 
			
		||||
    // Create a temporary directory for the test
 | 
			
		||||
    let temp_dir = tempdir().expect("Failed to create temp directory");
 | 
			
		||||
    let db_path = temp_dir.path().to_str().unwrap();
 | 
			
		||||
    
 | 
			
		||||
    // Create a new radix tree
 | 
			
		||||
    let mut tree = RadixTree::new(db_path, true)?;
 | 
			
		||||
 | 
			
		||||
    // Set keys with common prefixes
 | 
			
		||||
    tree.set("test1", b"value1".to_vec())?;
 | 
			
		||||
    tree.set("test2", b"value2".to_vec())?;
 | 
			
		||||
    tree.set("test3", b"value3".to_vec())?;
 | 
			
		||||
    tree.set("other", b"value4".to_vec())?;
 | 
			
		||||
 | 
			
		||||
    // Initial check
 | 
			
		||||
    let test_keys = tree.list("test")?;
 | 
			
		||||
    assert_eq!(test_keys.len(), 3);
 | 
			
		||||
    assert!(test_keys.contains(&"test1".to_string()));
 | 
			
		||||
    assert!(test_keys.contains(&"test2".to_string()));
 | 
			
		||||
    assert!(test_keys.contains(&"test3".to_string()));
 | 
			
		||||
 | 
			
		||||
    // Delete one key
 | 
			
		||||
    tree.delete("test2")?;
 | 
			
		||||
 | 
			
		||||
    // Check after deletion
 | 
			
		||||
    let test_keys_after = tree.list("test")?;
 | 
			
		||||
    assert_eq!(test_keys_after.len(), 2);
 | 
			
		||||
    assert!(test_keys_after.contains(&"test1".to_string()));
 | 
			
		||||
    assert!(!test_keys_after.contains(&"test2".to_string()));
 | 
			
		||||
    assert!(test_keys_after.contains(&"test3".to_string()));
 | 
			
		||||
 | 
			
		||||
    // Check all keys
 | 
			
		||||
    let all_keys = tree.list("")?;
 | 
			
		||||
    assert_eq!(all_keys.len(), 3);
 | 
			
		||||
    assert!(all_keys.contains(&"other".to_string()));
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_list_edge_cases() -> Result<(), radixtree::Error> {
 | 
			
		||||
    // Create a temporary directory for the test
 | 
			
		||||
    let temp_dir = tempdir().expect("Failed to create temp directory");
 | 
			
		||||
    let db_path = temp_dir.path().to_str().unwrap();
 | 
			
		||||
    
 | 
			
		||||
    // Create a new radix tree
 | 
			
		||||
    let mut tree = RadixTree::new(db_path, true)?;
 | 
			
		||||
 | 
			
		||||
    // Test with empty tree
 | 
			
		||||
    let empty_result = tree.list("any")?;
 | 
			
		||||
    assert_eq!(empty_result.len(), 0);
 | 
			
		||||
 | 
			
		||||
    // Set a single key
 | 
			
		||||
    tree.set("single", b"value".to_vec())?;
 | 
			
		||||
 | 
			
		||||
    // Test with prefix that's longer than any key
 | 
			
		||||
    let long_prefix = tree.list("singlelonger")?;
 | 
			
		||||
    assert_eq!(long_prefix.len(), 0);
 | 
			
		||||
 | 
			
		||||
    // Test with partial prefix match
 | 
			
		||||
    let partial = tree.list("sing")?;
 | 
			
		||||
    assert_eq!(partial.len(), 1);
 | 
			
		||||
    assert_eq!(partial[0], "single");
 | 
			
		||||
 | 
			
		||||
    // Test with very long keys
 | 
			
		||||
    let long_key1 = "a".repeat(100) + "key1";
 | 
			
		||||
    let long_key2 = "a".repeat(100) + "key2";
 | 
			
		||||
 | 
			
		||||
    tree.set(&long_key1, b"value1".to_vec())?;
 | 
			
		||||
    tree.set(&long_key2, b"value2".to_vec())?;
 | 
			
		||||
 | 
			
		||||
    let long_prefix_result = tree.list(&"a".repeat(100))?;
 | 
			
		||||
    assert_eq!(long_prefix_result.len(), 2);
 | 
			
		||||
    assert!(long_prefix_result.contains(&long_key1));
 | 
			
		||||
    assert!(long_prefix_result.contains(&long_key2));
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_list_performance() -> Result<(), radixtree::Error> {
 | 
			
		||||
    // Create a temporary directory for the test
 | 
			
		||||
    let temp_dir = tempdir().expect("Failed to create temp directory");
 | 
			
		||||
    let db_path = temp_dir.path().to_str().unwrap();
 | 
			
		||||
    
 | 
			
		||||
    // Create a new radix tree
 | 
			
		||||
    let mut tree = RadixTree::new(db_path, true)?;
 | 
			
		||||
 | 
			
		||||
    // Insert a large number of keys with different prefixes
 | 
			
		||||
    let prefixes = ["user", "post", "comment", "like", "share"];
 | 
			
		||||
 | 
			
		||||
    // Set 100 keys for each prefix (500 total)
 | 
			
		||||
    for prefix in &prefixes {
 | 
			
		||||
        for i in 0..100 {
 | 
			
		||||
            let key = format!("{}_{}", prefix, i);
 | 
			
		||||
            tree.set(&key, format!("value_{}", key).as_bytes().to_vec())?;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Test retrieving by each prefix
 | 
			
		||||
    for prefix in &prefixes {
 | 
			
		||||
        let keys = tree.list(prefix)?;
 | 
			
		||||
        assert_eq!(keys.len(), 100);
 | 
			
		||||
 | 
			
		||||
        // Verify all keys have the correct prefix
 | 
			
		||||
        for key in &keys {
 | 
			
		||||
            assert!(key.starts_with(prefix));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Test retrieving all keys
 | 
			
		||||
    let all_keys = tree.list("")?;
 | 
			
		||||
    assert_eq!(all_keys.len(), 500);
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										180
									
								
								radixtree/tests/serialize_test.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								radixtree/tests/serialize_test.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,180 @@
 | 
			
		||||
use radixtree::{Node, NodeRef};
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_node_serialization() {
 | 
			
		||||
    // Create a node with some data
 | 
			
		||||
    let node = Node {
 | 
			
		||||
        key_segment: "test".to_string(),
 | 
			
		||||
        value: b"test_value".to_vec(),
 | 
			
		||||
        children: vec![
 | 
			
		||||
            NodeRef {
 | 
			
		||||
                key_part: "child1".to_string(),
 | 
			
		||||
                node_id: 1,
 | 
			
		||||
            },
 | 
			
		||||
            NodeRef {
 | 
			
		||||
                key_part: "child2".to_string(),
 | 
			
		||||
                node_id: 2,
 | 
			
		||||
            },
 | 
			
		||||
        ],
 | 
			
		||||
        is_leaf: true,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Serialize the node
 | 
			
		||||
    let serialized = node.serialize();
 | 
			
		||||
    
 | 
			
		||||
    // Deserialize the node
 | 
			
		||||
    let deserialized = Node::deserialize(&serialized).expect("Failed to deserialize node");
 | 
			
		||||
    
 | 
			
		||||
    // Verify the deserialized node matches the original
 | 
			
		||||
    assert_eq!(deserialized.key_segment, node.key_segment);
 | 
			
		||||
    assert_eq!(deserialized.value, node.value);
 | 
			
		||||
    assert_eq!(deserialized.is_leaf, node.is_leaf);
 | 
			
		||||
    assert_eq!(deserialized.children.len(), node.children.len());
 | 
			
		||||
    
 | 
			
		||||
    for (i, child) in node.children.iter().enumerate() {
 | 
			
		||||
        assert_eq!(deserialized.children[i].key_part, child.key_part);
 | 
			
		||||
        assert_eq!(deserialized.children[i].node_id, child.node_id);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_empty_node_serialization() {
 | 
			
		||||
    // Create an empty node
 | 
			
		||||
    let node = Node {
 | 
			
		||||
        key_segment: "".to_string(),
 | 
			
		||||
        value: vec![],
 | 
			
		||||
        children: vec![],
 | 
			
		||||
        is_leaf: false,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Serialize the node
 | 
			
		||||
    let serialized = node.serialize();
 | 
			
		||||
    
 | 
			
		||||
    // Deserialize the node
 | 
			
		||||
    let deserialized = Node::deserialize(&serialized).expect("Failed to deserialize node");
 | 
			
		||||
    
 | 
			
		||||
    // Verify the deserialized node matches the original
 | 
			
		||||
    assert_eq!(deserialized.key_segment, node.key_segment);
 | 
			
		||||
    assert_eq!(deserialized.value, node.value);
 | 
			
		||||
    assert_eq!(deserialized.is_leaf, node.is_leaf);
 | 
			
		||||
    assert_eq!(deserialized.children.len(), node.children.len());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_node_with_many_children() {
 | 
			
		||||
    // Create a node with many children
 | 
			
		||||
    let mut children = Vec::new();
 | 
			
		||||
    for i in 0..100 {
 | 
			
		||||
        children.push(NodeRef {
 | 
			
		||||
            key_part: format!("child{}", i),
 | 
			
		||||
            node_id: i as u32,
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    let node = Node {
 | 
			
		||||
        key_segment: "parent".to_string(),
 | 
			
		||||
        value: b"parent_value".to_vec(),
 | 
			
		||||
        children,
 | 
			
		||||
        is_leaf: true,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Serialize the node
 | 
			
		||||
    let serialized = node.serialize();
 | 
			
		||||
    
 | 
			
		||||
    // Deserialize the node
 | 
			
		||||
    let deserialized = Node::deserialize(&serialized).expect("Failed to deserialize node");
 | 
			
		||||
    
 | 
			
		||||
    // Verify the deserialized node matches the original
 | 
			
		||||
    assert_eq!(deserialized.key_segment, node.key_segment);
 | 
			
		||||
    assert_eq!(deserialized.value, node.value);
 | 
			
		||||
    assert_eq!(deserialized.is_leaf, node.is_leaf);
 | 
			
		||||
    assert_eq!(deserialized.children.len(), node.children.len());
 | 
			
		||||
    
 | 
			
		||||
    for (i, child) in node.children.iter().enumerate() {
 | 
			
		||||
        assert_eq!(deserialized.children[i].key_part, child.key_part);
 | 
			
		||||
        assert_eq!(deserialized.children[i].node_id, child.node_id);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_node_with_large_value() {
 | 
			
		||||
    // Create a node with a large value
 | 
			
		||||
    let large_value = vec![0u8; 4096]; // 4KB value
 | 
			
		||||
    
 | 
			
		||||
    let node = Node {
 | 
			
		||||
        key_segment: "large_value".to_string(),
 | 
			
		||||
        value: large_value.clone(),
 | 
			
		||||
        children: vec![],
 | 
			
		||||
        is_leaf: true,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Serialize the node
 | 
			
		||||
    let serialized = node.serialize();
 | 
			
		||||
    
 | 
			
		||||
    // Deserialize the node
 | 
			
		||||
    let deserialized = Node::deserialize(&serialized).expect("Failed to deserialize node");
 | 
			
		||||
    
 | 
			
		||||
    // Verify the deserialized node matches the original
 | 
			
		||||
    assert_eq!(deserialized.key_segment, node.key_segment);
 | 
			
		||||
    assert_eq!(deserialized.value, node.value);
 | 
			
		||||
    assert_eq!(deserialized.is_leaf, node.is_leaf);
 | 
			
		||||
    assert_eq!(deserialized.children.len(), node.children.len());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_version_compatibility() {
 | 
			
		||||
    // This test ensures that the serialization format is compatible with version 1
 | 
			
		||||
    
 | 
			
		||||
    // Create a node
 | 
			
		||||
    let node = Node {
 | 
			
		||||
        key_segment: "test".to_string(),
 | 
			
		||||
        value: b"test_value".to_vec(),
 | 
			
		||||
        children: vec![
 | 
			
		||||
            NodeRef {
 | 
			
		||||
                key_part: "child".to_string(),
 | 
			
		||||
                node_id: 1,
 | 
			
		||||
            },
 | 
			
		||||
        ],
 | 
			
		||||
        is_leaf: true,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Serialize the node
 | 
			
		||||
    let serialized = node.serialize();
 | 
			
		||||
    
 | 
			
		||||
    // Verify the first byte is the version byte (1)
 | 
			
		||||
    assert_eq!(serialized[0], 1);
 | 
			
		||||
    
 | 
			
		||||
    // Deserialize the node
 | 
			
		||||
    let deserialized = Node::deserialize(&serialized).expect("Failed to deserialize node");
 | 
			
		||||
    
 | 
			
		||||
    // Verify the deserialized node matches the original
 | 
			
		||||
    assert_eq!(deserialized.key_segment, node.key_segment);
 | 
			
		||||
    assert_eq!(deserialized.value, node.value);
 | 
			
		||||
    assert_eq!(deserialized.is_leaf, node.is_leaf);
 | 
			
		||||
    assert_eq!(deserialized.children.len(), node.children.len());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_invalid_serialization() {
 | 
			
		||||
    // Test with empty data
 | 
			
		||||
    let result = Node::deserialize(&[]);
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    
 | 
			
		||||
    // Test with invalid version
 | 
			
		||||
    let result = Node::deserialize(&[2, 0, 0, 0, 0]);
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
    
 | 
			
		||||
    // Test with truncated data
 | 
			
		||||
    let node = Node {
 | 
			
		||||
        key_segment: "test".to_string(),
 | 
			
		||||
        value: b"test_value".to_vec(),
 | 
			
		||||
        children: vec![],
 | 
			
		||||
        is_leaf: true,
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    let serialized = node.serialize();
 | 
			
		||||
    let truncated = &serialized[0..serialized.len() / 2];
 | 
			
		||||
    
 | 
			
		||||
    let result = Node::deserialize(truncated);
 | 
			
		||||
    assert!(result.is_err());
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user