1#![allow(clippy::type_complexity)]
6
7#[cfg(feature = "alloc")]
8extern crate alloc;
9
10pub use crate::userspace::*;
12
13pub mod test_programs {
15 #[cfg(feature = "alloc")]
18 extern crate alloc;
19
20 pub mod hello_world {
22 use alloc::string::String;
23
24 pub fn run() -> Result<(), String> {
25 crate::println!("Hello, World from VeridianOS!");
26 Ok(())
27 }
28 }
29
30 pub mod process_test {
32 use alloc::string::String;
33
34 pub fn run() -> Result<(), String> {
35 crate::println!("Process test: checking process server...");
36 let ps = crate::services::process_server::get_process_server();
37 let processes = ps.list_processes();
38 if processes.is_empty() {
39 return Err(String::from("Process server has no processes"));
40 }
41 crate::println!(" Found {} processes", processes.len());
42 Ok(())
43 }
44 }
45
46 pub mod thread_test {
48 use alloc::string::String;
49
50 pub fn run() -> Result<(), String> {
51 crate::println!("Thread test: checking thread manager...");
52 let tm = crate::thread_api::get_thread_manager();
53 if tm.get_current_thread_id().is_some() {
54 crate::println!(" Thread manager responding");
55 Ok(())
56 } else {
57 Err(String::from("Thread manager not responding"))
58 }
59 }
60 }
61
62 pub mod filesystem_test {
64 use alloc::string::String;
65
66 pub fn run() -> Result<(), String> {
67 crate::println!("Filesystem test: exercising VFS...");
68
69 crate::fs::write_file("/tmp/fs_test.txt", b"VFS works")
71 .map_err(|e| alloc::format!("{}", e))?;
72
73 let data =
75 crate::fs::read_file("/tmp/fs_test.txt").map_err(|e| alloc::format!("{}", e))?;
76 if data != b"VFS works" {
77 return Err(String::from("Read data mismatch"));
78 }
79 crate::println!(" Write/read verified");
80
81 let vfs = crate::fs::get_vfs().read();
83 let node = vfs
84 .resolve_path("/tmp")
85 .map_err(|e| alloc::format!("{}", e))?;
86 let entries = node.readdir().map_err(|e| alloc::format!("{}", e))?;
87 let found = entries.iter().any(|e| e.name == "fs_test.txt");
88 if !found {
89 return Err(String::from("File not found in directory listing"));
90 }
91 crate::println!(" Directory listing verified");
92
93 Ok(())
94 }
95 }
96
97 pub mod network_test {
99 use alloc::string::String;
100
101 pub fn run() -> Result<(), String> {
102 crate::println!("Network test: checking network subsystem...");
103 let _initialized = crate::drivers::network::is_network_initialized();
104 crate::println!(" Network subsystem checked (non-critical)");
105 Ok(())
106 }
107 }
108
109 pub mod driver_test {
111 use alloc::string::String;
112
113 pub fn run() -> Result<(), String> {
114 crate::println!("Driver test: checking driver framework...");
115 let df = crate::services::driver_framework::get_driver_framework();
116 let stats = df.get_statistics();
117 crate::println!(
118 " Drivers: {}, Buses: {}",
119 stats.total_drivers,
120 stats.total_buses
121 );
122 if stats.total_drivers == 0 && stats.total_buses == 0 {
123 return Err(String::from("No drivers or buses registered"));
124 }
125 Ok(())
126 }
127 }
128
129 pub mod shell_test {
131 use alloc::string::String;
132
133 pub fn run() -> Result<(), String> {
134 crate::println!("Shell test: executing built-in commands...");
135 let shell = crate::services::shell::get_shell();
136
137 if !matches!(
139 shell.execute_command("pwd"),
140 crate::services::shell::CommandResult::Success(_)
141 ) {
142 return Err(String::from("pwd command failed"));
143 }
144 crate::println!(" pwd: ok");
145
146 if !matches!(
148 shell.execute_command("env"),
149 crate::services::shell::CommandResult::Success(_)
150 ) {
151 return Err(String::from("env command failed"));
152 }
153 crate::println!(" env: ok");
154
155 if !matches!(
157 shell.execute_command("nonexistent_cmd_xyz"),
158 crate::services::shell::CommandResult::NotFound
159 ) {
160 return Err(String::from("Expected NotFound for unknown command"));
161 }
162 crate::println!(" not-found detection: ok");
163
164 Ok(())
165 }
166 }
167
168 pub mod stdlib_test {
170 use alloc::string::String;
171
172 pub fn run() -> Result<(), String> {
173 crate::println!("Standard library test: basic validation...");
174 let s = String::from("hello");
176 let v: alloc::vec::Vec<u32> = alloc::vec![1, 2, 3];
177 if s.len() != 5 || v.len() != 3 {
178 return Err(String::from("Basic alloc types broken"));
179 }
180 crate::println!(" alloc types: ok");
181 Ok(())
182 }
183 }
184}
185
186pub mod test_runner {
187 #[cfg(feature = "alloc")]
190 extern crate alloc;
191
192 use alloc::{format, string::String, vec::Vec};
193
194 #[derive(Debug, Clone)]
196 pub struct TestSuiteSummary {
197 pub total_tests: usize,
198 pub passed: usize,
199 pub failed: usize,
200 pub errors: Vec<String>,
201 }
202
203 impl Default for TestSuiteSummary {
204 fn default() -> Self {
205 Self::new()
206 }
207 }
208
209 impl TestSuiteSummary {
210 pub fn new() -> Self {
211 Self {
212 total_tests: 0,
213 passed: 0,
214 failed: 0,
215 errors: Vec::new(),
216 }
217 }
218
219 pub fn success_rate(&self) -> f32 {
220 if self.total_tests == 0 {
221 100.0
222 } else {
223 (self.passed as f32 / self.total_tests as f32) * 100.0
224 }
225 }
226 }
227
228 pub fn run_phase2_validation() -> TestSuiteSummary {
230 let mut summary = TestSuiteSummary::new();
231
232 crate::println!("🚀 Running Phase 2 Validation Tests...");
233
234 let tests: [(&str, fn() -> Result<(), String>); 8] = [
236 ("Hello World", super::test_programs::hello_world::run),
237 ("Process Test", super::test_programs::process_test::run),
238 ("Thread Test", super::test_programs::thread_test::run),
239 (
240 "Filesystem Test",
241 super::test_programs::filesystem_test::run,
242 ),
243 ("Network Test", super::test_programs::network_test::run),
244 ("Driver Test", super::test_programs::driver_test::run),
245 ("Shell Test", super::test_programs::shell_test::run),
246 ("Stdlib Test", super::test_programs::stdlib_test::run),
247 ];
248
249 for (name, test_fn) in &tests {
250 summary.total_tests += 1;
251 match test_fn() {
252 Ok(()) => {
253 crate::println!("✅ {} - PASSED", name);
254 summary.passed += 1;
255 }
256 Err(e) => {
257 crate::println!("❌ {} - FAILED: {}", name, e);
258 summary.failed += 1;
259 summary.errors.push(format!("{}: {}", name, e));
260 }
261 }
262 }
263
264 crate::println!("");
265 crate::println!(
266 "📊 Test Results: {}/{} passed ({:.1}%)",
267 summary.passed,
268 summary.total_tests,
269 summary.success_rate()
270 );
271
272 summary
273 }
274
275 pub fn run_critical_tests() -> TestSuiteSummary {
277 let mut summary = TestSuiteSummary::new();
278
279 crate::println!("🔥 Running Critical Tests...");
280
281 let tests: [(&str, fn() -> Result<(), String>); 3] = [
283 ("Process Test", super::test_programs::process_test::run),
284 (
285 "Filesystem Test",
286 super::test_programs::filesystem_test::run,
287 ),
288 ("Driver Test", super::test_programs::driver_test::run),
289 ];
290
291 for (name, test_fn) in &tests {
292 summary.total_tests += 1;
293 match test_fn() {
294 Ok(()) => {
295 crate::println!("✅ {} - PASSED", name);
296 summary.passed += 1;
297 }
298 Err(e) => {
299 crate::println!("❌ {} - FAILED: {}", name, e);
300 summary.failed += 1;
301 summary.errors.push(format!("{}: {}", name, e));
302 }
303 }
304 }
305
306 summary
307 }
308
309 pub fn run_specific_tests(test_names: &[&str]) -> TestSuiteSummary {
311 let mut summary = TestSuiteSummary::new();
312
313 crate::println!("🎯 Running Specific Tests...");
314
315 for name in test_names {
316 summary.total_tests += 1;
317 let result = match *name {
318 "hello_world" => super::test_programs::hello_world::run(),
319 "process" => super::test_programs::process_test::run(),
320 "thread" => super::test_programs::thread_test::run(),
321 "filesystem" => super::test_programs::filesystem_test::run(),
322 "network" => super::test_programs::network_test::run(),
323 "driver" => super::test_programs::driver_test::run(),
324 "shell" => super::test_programs::shell_test::run(),
325 "stdlib" => super::test_programs::stdlib_test::run(),
326 _ => Err(format!("Unknown test: {}", name)),
327 };
328
329 match result {
330 Ok(()) => {
331 crate::println!("✅ {} - PASSED", name);
332 summary.passed += 1;
333 }
334 Err(e) => {
335 crate::println!("❌ {} - FAILED: {}", name, e);
336 summary.failed += 1;
337 summary.errors.push(format!("{}: {}", name, e));
338 }
339 }
340 }
341
342 summary
343 }
344
345 pub fn interactive_test_menu() -> TestSuiteSummary {
347 crate::println!("📋 Interactive test menu not available in kernel context");
348 crate::println!("Running full Phase 2 validation instead...");
349 run_phase2_validation()
350 }
351
352 #[cfg(test)]
353 mod tests {
354 use super::*;
355
356 #[test]
357 fn test_suite_summary_new() {
358 let s = TestSuiteSummary::new();
359 assert_eq!(s.total_tests, 0);
360 assert_eq!(s.passed, 0);
361 assert_eq!(s.failed, 0);
362 assert!(s.errors.is_empty());
363 }
364
365 #[test]
366 fn test_suite_summary_default() {
367 let s = TestSuiteSummary::default();
368 assert_eq!(s.total_tests, 0);
369 assert_eq!(s.passed, 0);
370 assert_eq!(s.failed, 0);
371 assert!(s.errors.is_empty());
372 }
373
374 #[test]
375 fn test_suite_summary_new_equals_default() {
376 let a = TestSuiteSummary::new();
377 let b = TestSuiteSummary::default();
378 assert_eq!(a.total_tests, b.total_tests);
379 assert_eq!(a.passed, b.passed);
380 assert_eq!(a.failed, b.failed);
381 assert_eq!(a.errors.len(), b.errors.len());
382 }
383
384 #[test]
385 fn test_success_rate_empty() {
386 let s = TestSuiteSummary::new();
387 assert_eq!(s.success_rate(), 100.0);
389 }
390
391 #[test]
392 fn test_success_rate_all_passed() {
393 let mut s = TestSuiteSummary::new();
394 s.total_tests = 10;
395 s.passed = 10;
396 s.failed = 0;
397 assert_eq!(s.success_rate(), 100.0);
398 }
399
400 #[test]
401 fn test_success_rate_none_passed() {
402 let mut s = TestSuiteSummary::new();
403 s.total_tests = 5;
404 s.passed = 0;
405 s.failed = 5;
406 assert_eq!(s.success_rate(), 0.0);
407 }
408
409 #[test]
410 fn test_success_rate_half_passed() {
411 let mut s = TestSuiteSummary::new();
412 s.total_tests = 4;
413 s.passed = 2;
414 s.failed = 2;
415 assert_eq!(s.success_rate(), 50.0);
416 }
417
418 #[test]
419 fn test_suite_summary_clone() {
420 let mut s = TestSuiteSummary::new();
421 s.total_tests = 3;
422 s.passed = 2;
423 s.failed = 1;
424 s.errors.push(String::from("test failure"));
425 let cloned = s.clone();
426 assert_eq!(cloned.total_tests, 3);
427 assert_eq!(cloned.passed, 2);
428 assert_eq!(cloned.failed, 1);
429 assert_eq!(cloned.errors.len(), 1);
430 assert_eq!(cloned.errors[0], "test failure");
431 }
432
433 #[test]
434 fn test_suite_summary_errors_accumulate() {
435 let mut s = TestSuiteSummary::new();
436 assert!(s.errors.is_empty());
437 s.errors.push(String::from("error 1"));
438 s.errors.push(String::from("error 2"));
439 assert_eq!(s.errors.len(), 2);
440 }
441
442 #[test]
443 fn test_suite_summary_debug_impl() {
444 let s = TestSuiteSummary::new();
445 let debug_str = alloc::format!("{:?}", s);
446 assert!(debug_str.contains("TestSuiteSummary"));
447 assert!(debug_str.contains("total_tests"));
448 }
449
450 #[test]
451 fn test_success_rate_single_test_passed() {
452 let mut s = TestSuiteSummary::new();
453 s.total_tests = 1;
454 s.passed = 1;
455 assert_eq!(s.success_rate(), 100.0);
456 }
457
458 #[test]
459 fn test_success_rate_single_test_failed() {
460 let mut s = TestSuiteSummary::new();
461 s.total_tests = 1;
462 s.passed = 0;
463 s.failed = 1;
464 assert_eq!(s.success_rate(), 0.0);
465 }
466 }
467}