use cloudllm::tools::FileSystemTool;
use tempfile::TempDir;
#[tokio::test]
async fn test_filesystem_creation() {
let fs = FileSystemTool::new();
assert!(fs.file_exists(".").await.is_ok());
}
#[tokio::test]
async fn test_with_root_path() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
fs.write_file("test.txt", "content").await.unwrap();
assert!(fs.file_exists("test.txt").await.unwrap());
}
#[tokio::test]
async fn test_with_allowed_extensions() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new()
.with_root_path(temp_dir.path().to_path_buf())
.with_allowed_extensions(vec!["txt".to_string(), "md".to_string()]);
fs.write_file("test.txt", "content").await.unwrap();
assert!(fs.file_exists("test.txt").await.unwrap());
let result = fs.write_file("test.pdf", "content").await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_write_and_read_file() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
let content = "Hello, World! This is a test file with multiple lines.\nLine 2\nLine 3";
fs.write_file("test.txt", content).await.unwrap();
let read_content = fs.read_file("test.txt").await.unwrap();
assert_eq!(read_content, content);
}
#[tokio::test]
async fn test_append_file() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
fs.write_file("test.txt", "Hello").await.unwrap();
fs.append_file("test.txt", " World").await.unwrap();
fs.append_file("test.txt", "!").await.unwrap();
let content = fs.read_file("test.txt").await.unwrap();
assert_eq!(content, "Hello World!");
}
#[tokio::test]
async fn test_file_exists() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
fs.write_file("exists.txt", "content").await.unwrap();
assert!(fs.file_exists("exists.txt").await.unwrap());
assert!(!fs.file_exists("nonexistent.txt").await.unwrap());
}
#[tokio::test]
async fn test_delete_file() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
fs.write_file("delete_me.txt", "content").await.unwrap();
assert!(fs.file_exists("delete_me.txt").await.unwrap());
fs.delete_file("delete_me.txt").await.unwrap();
assert!(!fs.file_exists("delete_me.txt").await.unwrap());
}
#[tokio::test]
async fn test_delete_nonexistent_file() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
let result = fs.delete_file("nonexistent.txt").await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_get_file_metadata() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
let test_content = "Hello";
fs.write_file("test.txt", test_content).await.unwrap();
let metadata = fs.get_file_metadata("test.txt").await.unwrap();
assert_eq!(metadata.name, "test.txt");
assert_eq!(metadata.size, test_content.len() as u64);
assert!(!metadata.is_directory);
assert!(!metadata.path.is_empty());
}
#[tokio::test]
async fn test_create_directory() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
fs.create_directory("newdir").await.unwrap();
assert!(fs.file_exists("newdir").await.unwrap());
let metadata = fs.get_file_metadata("newdir").await.unwrap();
assert!(metadata.is_directory);
}
#[tokio::test]
async fn test_create_nested_directories() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
fs.create_directory("a/b/c").await.unwrap();
assert!(fs.file_exists("a/b/c").await.unwrap());
}
#[tokio::test]
async fn test_read_directory() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
fs.write_file("file1.txt", "content1").await.unwrap();
fs.write_file("file2.txt", "content2").await.unwrap();
fs.create_directory("subdir").await.unwrap();
let entries = fs.read_directory(".", false).await.unwrap();
assert!(entries.len() >= 3);
assert!(entries
.iter()
.any(|e| e.name == "file1.txt" && !e.is_directory));
assert!(entries
.iter()
.any(|e| e.name == "file2.txt" && !e.is_directory));
assert!(entries.iter().any(|e| e.name == "subdir" && e.is_directory));
}
#[tokio::test]
async fn test_read_directory_recursive() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
fs.write_file("file1.txt", "content").await.unwrap();
fs.create_directory("subdir").await.unwrap();
fs.write_file("subdir/file2.txt", "content").await.unwrap();
fs.create_directory("subdir/nested").await.unwrap();
fs.write_file("subdir/nested/file3.txt", "content")
.await
.unwrap();
let entries = fs.read_directory(".", true).await.unwrap();
assert!(entries.len() >= 5); }
#[tokio::test]
async fn test_get_file_size() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
let content = "Hello";
fs.write_file("test.txt", content).await.unwrap();
let size = fs.get_file_size("test.txt").await.unwrap();
assert_eq!(size, content.len() as u64);
}
#[tokio::test]
async fn test_get_file_size_large() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
let content = "x".repeat(10000);
fs.write_file("large.txt", &content).await.unwrap();
let size = fs.get_file_size("large.txt").await.unwrap();
assert_eq!(size, 10000);
}
#[tokio::test]
async fn test_path_traversal_prevention() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
let result = fs.read_file("../../../etc/passwd").await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_path_traversal_prevention_write() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
let result = fs
.write_file("subdir/../../../etc/passwd", "malicious")
.await;
let _result = result; }
#[tokio::test]
async fn test_delete_directory_recursive() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
fs.create_directory("dir_to_delete").await.unwrap();
fs.write_file("dir_to_delete/file1.txt", "content")
.await
.unwrap();
fs.write_file("dir_to_delete/file2.txt", "content")
.await
.unwrap();
assert!(fs.file_exists("dir_to_delete").await.unwrap());
fs.delete_directory("dir_to_delete").await.unwrap();
assert!(!fs.file_exists("dir_to_delete").await.unwrap());
}
#[tokio::test]
async fn test_search_files() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
fs.write_file("test1.txt", "content").await.unwrap();
fs.write_file("test2.txt", "content").await.unwrap();
fs.write_file("other.md", "content").await.unwrap();
fs.create_directory("subdir").await.unwrap();
fs.write_file("subdir/test3.txt", "content").await.unwrap();
let results = fs.search_files(".", "test").await.unwrap();
assert!(results.len() >= 3); }
#[tokio::test]
async fn test_search_files_empty_results() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
fs.write_file("file.txt", "content").await.unwrap();
let results = fs.search_files(".", "nonexistent").await.unwrap();
assert!(results.is_empty());
}
#[tokio::test]
async fn test_read_nonexistent_file() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
let result = fs.read_file("nonexistent.txt").await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_read_directory_nonexistent() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
let result = fs.read_directory("nonexistent", false).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_write_creates_parent_directories() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
fs.write_file("a/b/c/deep.txt", "content").await.unwrap();
assert!(fs.file_exists("a/b/c/deep.txt").await.unwrap());
let content = fs.read_file("a/b/c/deep.txt").await.unwrap();
assert_eq!(content, "content");
}
#[tokio::test]
async fn test_append_creates_file_if_not_exists() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
fs.append_file("newfile.txt", "content").await.unwrap();
assert!(fs.file_exists("newfile.txt").await.unwrap());
let content = fs.read_file("newfile.txt").await.unwrap();
assert_eq!(content, "content");
}
#[tokio::test]
async fn test_extension_filtering_multiple_types() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new()
.with_root_path(temp_dir.path().to_path_buf())
.with_allowed_extensions(vec!["txt".to_string(), "md".to_string(), "rs".to_string()]);
fs.write_file("file.txt", "content").await.unwrap();
assert!(fs.file_exists("file.txt").await.unwrap());
fs.write_file("readme.md", "content").await.unwrap();
assert!(fs.file_exists("readme.md").await.unwrap());
fs.write_file("main.rs", "content").await.unwrap();
assert!(fs.file_exists("main.rs").await.unwrap());
let result = fs.write_file("document.pdf", "content").await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_metadata_for_directory() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
fs.create_directory("testdir").await.unwrap();
let metadata = fs.get_file_metadata("testdir").await.unwrap();
assert_eq!(metadata.name, "testdir");
assert!(metadata.is_directory);
}
#[tokio::test]
async fn test_read_directory_on_file_fails() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
fs.write_file("file.txt", "content").await.unwrap();
let result = fs.read_directory("file.txt", false).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_delete_directory_on_file_fails() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
fs.write_file("file.txt", "content").await.unwrap();
let result = fs.delete_directory("file.txt").await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_write_on_directory_fails() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
fs.create_directory("dir").await.unwrap();
let result = fs.write_file("dir", "content").await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_file_operations_with_special_characters() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
let filename = "test-file_2024.txt";
fs.write_file(filename, "content").await.unwrap();
assert!(fs.file_exists(filename).await.unwrap());
let content = fs.read_file(filename).await.unwrap();
assert_eq!(content, "content");
}
#[tokio::test]
async fn test_large_file_handling() {
let temp_dir = TempDir::new().unwrap();
let fs = FileSystemTool::new().with_root_path(temp_dir.path().to_path_buf());
let large_content = "x".repeat(1_000_000); fs.write_file("large.txt", &large_content).await.unwrap();
let content = fs.read_file("large.txt").await.unwrap();
assert_eq!(content.len(), 1_000_000);
assert_eq!(content, large_content);
}