codex-memory 3.0.15

A simple memory storage service with MCP interface for Claude Desktop
Documentation
use chrono::Utc;
use uuid::Uuid;

/// Generate test content with optional size
pub fn generate_test_content(size: Option<usize>) -> String {
    let base = "This is test content for codex-store. ";
    let size = size.unwrap_or(100);

    if size <= base.len() {
        base[..size].to_string()
    } else {
        let repeats = size / base.len() + 1;
        base.repeat(repeats)[..size].to_string()
    }
}

/// Generate test tags
pub fn generate_test_tags(count: usize) -> Vec<String> {
    (0..count).map(|i| format!("tag_{}", i)).collect()
}

/// Generate unique content to avoid deduplication
pub fn generate_unique_content() -> String {
    format!(
        "Unique content generated at {} with ID {}",
        Utc::now().to_rfc3339(),
        Uuid::new_v4()
    )
}

/// Test memory data structure for storage tests
#[allow(dead_code)]
pub struct TestMemory {
    pub content: String,
    pub context: String,
    pub summary: String,
    pub tags: Vec<String>,
}

#[allow(dead_code)]
impl TestMemory {
    /// Create full test memory (all fields populated)
    pub fn full() -> Self {
        Self {
            content: "This is a comprehensive test memory with all fields populated. It contains multiple sentences to simulate real content.".to_string(),
            context: "Test execution context for unit testing".to_string(),
            summary: "A test memory with all fields for validation".to_string(),
            tags: vec!["test".to_string(), "unit".to_string(), "validation".to_string()],
        }
    }

    /// Create test memory with specific context
    pub fn with_context_only() -> Self {
        Self {
            content: "Content with context but no summary".to_string(),
            context: "Important contextual information".to_string(),
            summary: "Default test summary".to_string(),
            tags: vec!["context-test".to_string()],
        }
    }

    /// Create test memory with specific summary
    pub fn with_summary_only() -> Self {
        Self {
            content: "Content with summary but no context. This is a longer piece of text that would benefit from summarization.".to_string(),
            context: "Default test context".to_string(),
            summary: "Content that has a summary".to_string(),
            tags: vec!["summary-test".to_string()],
        }
    }

    /// Create test memory with special characters in tags
    pub fn with_special_tags() -> Self {
        Self {
            content: "Testing special characters in tags".to_string(),
            context: "Test context for special tags".to_string(),
            summary: "Testing tag special characters".to_string(),
            tags: vec![
                "tag-with-dash".to_string(),
                "tag_with_underscore".to_string(),
                "tag.with.dots".to_string(),
                "CamelCaseTag".to_string(),
                "number123".to_string(),
            ],
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_generate_content() {
        let content = generate_test_content(Some(50));
        assert_eq!(content.len(), 50);

        let content = generate_test_content(Some(200));
        assert_eq!(content.len(), 200);
    }

    #[test]
    fn test_generate_tags() {
        let tags = generate_test_tags(5);
        assert_eq!(tags.len(), 5);
        assert_eq!(tags[0], "tag_0");
        assert_eq!(tags[4], "tag_4");
    }

    #[test]
    fn test_unique_content() {
        let content1 = generate_unique_content();
        let content2 = generate_unique_content();
        assert_ne!(content1, content2);
    }
}