use std::fs;
use std::path::PathBuf;
use tempfile::TempDir;
use vtcode_core::tools::cache::FileCache;
use vtcode_core::tools::registry::ToolRegistry;
use serde_json::{Value, json};
#[cfg(test)]
mod e2e_tests {
use super::*;
#[tokio::test]
async fn test_file_operations_with_cache() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let workspace_root = temp_dir.path().to_path_buf();
let test_file = workspace_root.join("test_file.txt");
let test_content = "This is test content for caching verification.";
fs::write(&test_file, test_content).expect("Failed to write test file");
let mut registry = ToolRegistry::new(workspace_root.clone());
let read_args = json!({
"path": test_file.to_string_lossy(),
"max_bytes": 1000
});
let result1 = registry.execute_tool("read_file", read_args.clone()).await;
assert!(result1.is_ok(), "First read should succeed");
let content1 = result1.unwrap();
assert_eq!(content1["content"], test_content);
let result2 = registry.execute_tool("read_file", read_args).await;
assert!(result2.is_ok(), "Second read should succeed");
let content2 = result2.unwrap();
assert_eq!(content2["content"], test_content);
let new_content = "Updated content after caching.";
let write_args = json!({
"path": test_file.to_string_lossy(),
"content": new_content
});
let write_result = registry.execute_tool("write_file", write_args).await;
assert!(write_result.is_ok(), "Write operation should succeed");
let read_args2 = json!({
"path": test_file.to_string_lossy(),
"max_bytes": 1000
});
let result3 = registry.execute_tool("read_file", read_args2).await;
assert!(result3.is_ok(), "Read after write should succeed");
let content3 = result3.unwrap();
assert_eq!(content3["content"], new_content);
let disk_content = fs::read_to_string(&test_file).expect("Failed to read from disk");
assert_eq!(disk_content, new_content);
}
#[tokio::test]
async fn test_cache_statistics_tracking() {
let cache = FileCache::new(100);
let initial_stats = cache.stats().await;
assert_eq!(initial_stats.hits, 0);
assert_eq!(initial_stats.misses, 0);
let miss_result = cache.get_file("nonexistent").await;
assert!(miss_result.is_none());
let after_miss_stats = cache.stats().await;
assert_eq!(after_miss_stats.hits, 0);
assert_eq!(after_miss_stats.misses, 1);
let test_data = Value::String("cached content".to_string());
cache.put_file("test_key".to_string(), test_data.clone()).await;
let hit_result = cache.get_file("test_key").await;
assert!(hit_result.is_some());
assert_eq!(hit_result.unwrap(), test_data);
let after_hit_stats = cache.stats().await;
assert_eq!(after_hit_stats.hits, 1);
assert_eq!(after_hit_stats.misses, 1);
}
#[tokio::test]
async fn test_cache_capacity_limits() {
let cache = FileCache::new(2);
cache.put_file("key1".to_string(), Value::String("data1".to_string())).await;
cache.put_file("key2".to_string(), Value::String("data2".to_string())).await;
cache.put_file("key3".to_string(), Value::String("data3".to_string())).await;
let (file_capacity, dir_capacity) = cache.capacity();
assert_eq!(file_capacity, 2);
let (file_len, dir_len) = cache.len();
assert!(file_len <= 2); }
#[tokio::test]
async fn test_directory_caching() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let workspace_root = temp_dir.path().to_path_buf();
let subdir = workspace_root.join("subdir");
fs::create_dir(&subdir).expect("Failed to create subdir");
fs::write(subdir.join("file1.txt"), "content1").expect("Failed to write file1");
fs::write(subdir.join("file2.txt"), "content2").expect("Failed to write file2");
let mut registry = ToolRegistry::new(workspace_root.clone());
let list_args = json!({
"path": subdir.to_string_lossy()
});
let result1 = registry.execute_tool("list_files", list_args.clone()).await;
assert!(result1.is_ok(), "First list should succeed");
let result2 = registry.execute_tool("list_files", list_args).await;
assert!(result2.is_ok(), "Second list should succeed");
assert_eq!(result1.unwrap(), result2.unwrap());
}
#[tokio::test]
async fn test_cache_invalidation() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let workspace_root = temp_dir.path().to_path_buf();
let test_file = workspace_root.join("test.txt");
let mut registry = ToolRegistry::new(workspace_root.clone());
fs::write(&test_file, "original").expect("Failed to write original content");
let read_args = json!({
"path": test_file.to_string_lossy()
});
let result1 = registry.execute_tool("read_file", read_args.clone()).await;
assert!(result1.is_ok());
assert_eq!(result1.unwrap()["content"], "original");
let edit_args = json!({
"path": test_file.to_string_lossy(),
"old_str": "original",
"new_str": "modified"
});
let edit_result = registry.execute_tool("edit_file", edit_args).await;
assert!(edit_result.is_ok(), "Edit should succeed");
let result2 = registry.execute_tool("read_file", read_args).await;
assert!(result2.is_ok());
assert_eq!(result2.unwrap()["content"], "modified");
}
#[tokio::test]
async fn test_write_file_overwrite_mode() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let workspace_root = temp_dir.path().to_path_buf();
let mut registry = ToolRegistry::new(workspace_root.clone());
let test_file = workspace_root.join("test.txt");
let args = json!({
"path": "test.txt",
"content": "Hello World",
"mode": "overwrite"
});
let result = registry.execute_tool("write_file", args).await.expect("write_file should succeed");
assert_eq!(result["success"], true);
let content = fs::read_to_string(&test_file).expect("File should exist");
assert_eq!(content, "Hello World");
}
#[tokio::test]
async fn test_write_file_append_mode() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let workspace_root = temp_dir.path().to_path_buf();
let mut registry = ToolRegistry::new(workspace_root.clone());
let test_file = workspace_root.join("test.txt");
registry.execute_tool("write_file", json!({
"path": "test.txt",
"content": "Hello",
"mode": "overwrite"
})).await.expect("Initial write should succeed");
let args = json!({
"path": "test.txt",
"content": " World",
"mode": "append"
});
let result = registry.execute_tool("write_file", args).await.expect("append write_file should succeed");
assert_eq!(result["success"], true);
let content = fs::read_to_string(&test_file).expect("File should exist");
assert_eq!(content, "Hello World");
}
#[tokio::test]
async fn test_write_file_skip_if_exists_mode() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let workspace_root = temp_dir.path().to_path_buf();
let mut registry = ToolRegistry::new(workspace_root.clone());
let test_file = workspace_root.join("test.txt");
registry.execute_tool("write_file", json!({
"path": "test.txt",
"content": "Original",
"mode": "overwrite"
})).await.expect("Initial write should succeed");
let args = json!({
"path": "test.txt",
"content": "New Content",
"mode": "skip_if_exists"
});
let result = registry.execute_tool("write_file", args).await.expect("skip_if_exists write_file should succeed");
assert_eq!(result["success"], true);
assert_eq!(result["skipped"], true);
let content = fs::read_to_string(&test_file).expect("File should exist");
assert_eq!(content, "Original");
}
#[tokio::test]
async fn test_edit_file_exact_match() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let workspace_root = temp_dir.path().to_path_buf();
let mut registry = ToolRegistry::new(workspace_root.clone());
let test_file = workspace_root.join("test.txt");
registry.execute_tool("write_file", json!({
"path": "test.txt",
"content": "Hello World\nThis is a test file.",
"mode": "overwrite"
})).await.expect("Initial write should succeed");
let edit_args = json!({
"path": "test.txt",
"old_str": "Hello World",
"new_str": "Hello Universe"
});
let result = registry.execute_tool("edit_file", edit_args).await.expect("edit_file should succeed");
assert_eq!(result["success"], true);
let content = fs::read_to_string(&test_file).expect("File should exist");
assert_eq!(content, "Hello Universe\nThis is a test file.");
}
#[tokio::test]
async fn test_edit_file_multiple_occurrences() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let workspace_root = temp_dir.path().to_path_buf();
let mut registry = ToolRegistry::new(workspace_root.clone());
let test_file = workspace_root.join("test.txt");
registry.execute_tool("write_file", json!({
"path": "test.txt",
"content": "test\ntest\nmore test content",
"mode": "overwrite"
})).await.expect("Initial write should succeed");
let edit_args = json!({
"path": "test.txt",
"old_str": "test",
"new_str": "example"
});
let result = registry.execute_tool("edit_file", edit_args).await.expect("edit_file should succeed");
assert_eq!(result["success"], true);
let content = fs::read_to_string(&test_file).expect("File should exist");
assert_eq!(content, "example\nexample\nmore example content");
}
#[tokio::test]
async fn test_edit_file_with_newlines() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let workspace_root = temp_dir.path().to_path_buf();
let mut registry = ToolRegistry::new(workspace_root.clone());
let test_file = workspace_root.join("test.txt");
registry.execute_tool("write_file", json!({
"path": "test.txt",
"content": "Line 1\nLine 2\nLine 3",
"mode": "overwrite"
})).await.expect("Initial write should succeed");
let edit_args = json!({
"path": "test.txt",
"old_str": "Line 1\nLine 2",
"new_str": "New Line 1\nNew Line 2"
});
let result = registry.execute_tool("edit_file", edit_args).await.expect("edit_file should succeed");
assert_eq!(result["success"], true);
let content = fs::read_to_string(&test_file).expect("File should exist");
assert_eq!(content, "New Line 1\nNew Line 2\nLine 3");
}
#[tokio::test]
async fn test_write_file_creates_directories() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let workspace_root = temp_dir.path().to_path_buf();
let mut registry = ToolRegistry::new(workspace_root.clone());
let nested_file = temp_dir.path().join("dir").join("subdir").join("test.txt");
let args = json!({
"path": "dir/subdir/test.txt",
"content": "Nested content",
"mode": "overwrite"
});
let result = registry.execute_tool("write_file", args).await.expect("write_file should succeed");
assert_eq!(result["success"], true);
let content = fs::read_to_string(&nested_file).expect("File should exist");
assert_eq!(content, "Nested content");
}
}