kaish_kernel/backend/
mod.rs1mod local;
24mod overlay;
25
26pub use local::LocalBackend;
27pub use overlay::VirtualOverlayBackend;
28
29#[cfg(test)]
30pub mod testing;
31
32#[cfg(test)]
33pub use testing::MockBackend;
34
35pub use kaish_types::backend::{
37 BackendError, BackendResult, ConflictError, MountInfo, PatchOp, ReadRange, ToolInfo,
38 ToolResult, WriteMode,
39};
40
41pub use kaish_tool_api::KernelBackend;
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50 use super::testing::MockBackend;
51 use crate::tools::{ExecContext, ToolArgs};
52 use crate::vfs::DirEntry;
53 use std::sync::atomic::Ordering;
54 use std::sync::Arc;
55
56 #[test]
57 fn test_backend_error_from_io_error() {
58 let not_found = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
59 let backend_err: BackendError = not_found.into();
60 assert!(matches!(backend_err, BackendError::NotFound(_)));
61
62 let permission = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "no access");
63 let backend_err: BackendError = permission.into();
64 assert!(matches!(backend_err, BackendError::PermissionDenied(_)));
65 }
66
67 #[test]
68 fn test_dir_entry_constructors() {
69 let dir = DirEntry::directory("mydir");
70 assert!(dir.is_dir());
71 assert_eq!(dir.name, "mydir");
72
73 let file = DirEntry::file("myfile.txt", 1024);
74 assert!(file.is_file());
75 assert_eq!(file.size, 1024);
76 }
77
78 #[test]
79 fn test_tool_result() {
80 let success = ToolResult::success("hello");
81 assert!(success.ok());
82 assert_eq!(success.stdout, "hello");
83
84 let failure = ToolResult::failure(1, "error");
85 assert!(!failure.ok());
86 assert_eq!(failure.code, 1);
87 }
88
89 #[test]
90 fn test_read_range() {
91 let lines = ReadRange::lines(10, 20);
92 assert_eq!(lines.start_line, Some(10));
93 assert_eq!(lines.end_line, Some(20));
94
95 let bytes = ReadRange::bytes(100, 50);
96 assert_eq!(bytes.offset, Some(100));
97 assert_eq!(bytes.limit, Some(50));
98 }
99
100 #[tokio::test]
101 async fn test_mock_backend_call_tool_routing() {
102 let (backend, call_count) = MockBackend::new();
103 let backend: Arc<dyn KernelBackend> = Arc::new(backend);
104 let mut ctx = ExecContext::with_backend(backend.clone());
105
106 assert_eq!(call_count.load(Ordering::SeqCst), 0);
108
109 let args = ToolArgs::new();
111 let result = backend.call_tool("test-tool", args, &mut ctx).await.unwrap();
112
113 assert_eq!(call_count.load(Ordering::SeqCst), 1);
115 assert!(result.ok());
116 assert!(result.stdout.contains("mock executed: test-tool"));
117
118 let args = ToolArgs::new();
120 backend.call_tool("another-tool", args, &mut ctx).await.unwrap();
121 assert_eq!(call_count.load(Ordering::SeqCst), 2);
122 }
123}