SimpleKernel 1.17.0
Loading...
Searching...
No Matches
system_test.h File Reference
#include <etl/vector.h>
#include <cstdint>
#include <type_traits>
#include "kernel_log.hpp"
Include dependency graph for system_test.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  TestResult
 单个测试线程的结果记录 More...
 

Macros

#define EXPECT_EQ(val1, val2, msg)
 
#define EXPECT_NE(val1, val2, msg)
 
#define EXPECT_GT(val1, val2, msg)
 
#define EXPECT_LT(val1, val2, msg)
 
#define EXPECT_GE(val1, val2, msg)
 
#define EXPECT_LE(val1, val2, msg)
 
#define EXPECT_TRUE(cond, msg)
 
#define EXPECT_FALSE(cond, msg)
 

Enumerations

enum class  TestThreadStatus : uint8_t {
  kPending , kRunning , kPassed , kFailed ,
  kTimeout
}
 测试线程运行状态 More...
 

Functions

template<typename T1 , typename T2 >
bool expect_eq_helper (const T1 &val1, const T2 &val2, const char *msg)
 
template<typename T1 , typename T2 >
bool expect_ne_helper (const T1 &val1, const T2 &val2, const char *msg)
 
template<typename T1 , typename T2 >
bool expect_gt_helper (const T1 &val1, const T2 &val2, const char *msg)
 
template<typename T1 , typename T2 >
bool expect_lt_helper (const T1 &val1, const T2 &val2, const char *msg)
 
template<typename T1 , typename T2 >
bool expect_ge_helper (const T1 &val1, const T2 &val2, const char *msg)
 
template<typename T1 , typename T2 >
bool expect_le_helper (const T1 &val1, const T2 &val2, const char *msg)
 
auto ctor_dtor_test () -> bool
 
auto spinlock_test () -> bool
 
auto virtual_memory_test () -> bool
 
auto interrupt_test () -> bool
 
auto fifo_scheduler_test () -> bool
 
auto rr_scheduler_test () -> bool
 
auto cfs_scheduler_test () -> bool
 
auto idle_scheduler_test () -> bool
 
auto thread_group_system_test () -> bool
 线程组系统测试入口
 
auto wait_system_test () -> bool
 Wait 系统测试入口
 
auto clone_system_test () -> bool
 
auto exit_system_test () -> bool
 Exit 系统测试入口
 
auto ramfs_system_test () -> bool
 
auto fatfs_system_test () -> bool
 
auto memory_test () -> bool
 
auto kernel_task_test () -> bool
 
auto user_task_test () -> bool
 
auto mutex_test () -> bool
 
void QemuExit (bool success)
 测试结束后退出 QEMU,success=true 表示全部通过
 

Macro Definition Documentation

◆ EXPECT_EQ

#define EXPECT_EQ (   val1,
  val2,
  msg 
)
Value:
if (!expect_eq_helper(val1, val2, msg)) { \
return false; \
}
bool expect_eq_helper(const T1 &val1, const T2 &val2, const char *msg)
Definition system_test.h:19

Definition at line 126 of file system_test.h.

127 { \
128 return false; \
129 }

◆ EXPECT_FALSE

#define EXPECT_FALSE (   cond,
  msg 
)
Value:
if (cond) { \
klog::Err("FAIL: {}", msg); \
return false; \
}

Definition at line 162 of file system_test.h.

163 { \
164 klog::Err("FAIL: {}", msg); \
165 return false; \
166 }

◆ EXPECT_GE

#define EXPECT_GE (   val1,
  val2,
  msg 
)
Value:
if (!expect_ge_helper(val1, val2, msg)) { \
return false; \
}
bool expect_ge_helper(const T1 &val1, const T2 &val2, const char *msg)
Definition system_test.h:91

Definition at line 146 of file system_test.h.

147 { \
148 return false; \
149 }

◆ EXPECT_GT

#define EXPECT_GT (   val1,
  val2,
  msg 
)
Value:
if (!expect_gt_helper(val1, val2, msg)) { \
return false; \
}
bool expect_gt_helper(const T1 &val1, const T2 &val2, const char *msg)
Definition system_test.h:55

Definition at line 136 of file system_test.h.

137 { \
138 return false; \
139 }

◆ EXPECT_LE

#define EXPECT_LE (   val1,
  val2,
  msg 
)
Value:
if (!expect_le_helper(val1, val2, msg)) { \
return false; \
}
bool expect_le_helper(const T1 &val1, const T2 &val2, const char *msg)

Definition at line 151 of file system_test.h.

152 { \
153 return false; \
154 }

◆ EXPECT_LT

#define EXPECT_LT (   val1,
  val2,
  msg 
)
Value:
if (!expect_lt_helper(val1, val2, msg)) { \
return false; \
}
bool expect_lt_helper(const T1 &val1, const T2 &val2, const char *msg)
Definition system_test.h:73

Definition at line 141 of file system_test.h.

142 { \
143 return false; \
144 }

◆ EXPECT_NE

#define EXPECT_NE (   val1,
  val2,
  msg 
)
Value:
if (!expect_ne_helper(val1, val2, msg)) { \
return false; \
}
bool expect_ne_helper(const T1 &val1, const T2 &val2, const char *msg)
Definition system_test.h:37

Definition at line 131 of file system_test.h.

132 { \
133 return false; \
134 }

◆ EXPECT_TRUE

#define EXPECT_TRUE (   cond,
  msg 
)
Value:
if (!(cond)) { \
klog::Err("FAIL: {}", msg); \
return false; \
}

Definition at line 156 of file system_test.h.

157 { \
158 klog::Err("FAIL: {}", msg); \
159 return false; \
160 }

Enumeration Type Documentation

◆ TestThreadStatus

enum class TestThreadStatus : uint8_t
strong

测试线程运行状态

Enumerator
kPending 

等待启动

kRunning 

运行中

kPassed 

测试通过

kFailed 

测试失败

kTimeout 

超时未完成

Definition at line 222 of file system_test.h.

222 : uint8_t {
223 kPending,
224 kRunning,
225 kPassed,
226 kFailed,
227 kTimeout,
228};
@ kPassed
测试通过
@ kRunning
运行中
@ kTimeout
超时未完成
@ kPending
等待启动
@ kFailed
测试失败

Function Documentation

◆ cfs_scheduler_test()

auto cfs_scheduler_test ( ) -> bool

Definition at line 554 of file cfs_scheduler_test.cpp.

554 {
555 klog::Info("\n=== CFS Scheduler System Tests ===\n");
556
557 if (!test_cfs_basic_functionality()) {
558 return false;
559 }
560
561 if (!test_cfs_vruntime_ordering()) {
562 return false;
563 }
564
565 if (!test_cfs_new_task_vruntime()) {
566 return false;
567 }
568
569 if (!test_cfs_weight_impact()) {
570 return false;
571 }
572
573 if (!test_cfs_preemption()) {
574 return false;
575 }
576
577 if (!test_cfs_no_preemption()) {
578 return false;
579 }
580
581 if (!test_cfs_dequeue()) {
582 return false;
583 }
584
585 if (!test_cfs_statistics()) {
586 return false;
587 }
588
589 if (!test_cfs_min_vruntime_update()) {
590 return false;
591 }
592
593 if (!test_cfs_multiple_ticks()) {
594 return false;
595 }
596
597 if (!test_cfs_fairness()) {
598 return false;
599 }
600
601 if (!test_cfs_mixed_operations()) {
602 return false;
603 }
604
605 if (!test_cfs_robustness()) {
606 return false;
607 }
608
609 klog::Info("=== All CFS Scheduler Tests Passed ===\n");
610 return true;
611}
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志
Here is the call graph for this function:

◆ clone_system_test()

auto clone_system_test ( ) -> bool

Definition at line 425 of file clone_system_test.cpp.

425 {
426 klog::Info("===== Clone System Test Start =====");
427
428 g_tests_completed = 0;
429 g_tests_failed = 0;
430
431 auto& task_mgr = TaskManagerSingleton::instance();
432
433 auto test1 = kstd::make_unique<TaskControlBlock>("TestCloneProcess", 10,
434 test_clone_process, nullptr);
435 task_mgr.AddTask(std::move(test1));
436
437 auto test2 = kstd::make_unique<TaskControlBlock>("TestCloneThread", 10,
438 test_clone_thread, nullptr);
439 task_mgr.AddTask(std::move(test2));
440
441 auto test3 = kstd::make_unique<TaskControlBlock>(
442 "TestCloneParentFlag", 10, test_clone_parent_flag, nullptr);
443 task_mgr.AddTask(std::move(test3));
444
445 auto test4 = kstd::make_unique<TaskControlBlock>(
446 "TestCloneFlagsAutoCompletion", 10, test_clone_flags_auto_completion,
447 nullptr);
448 task_mgr.AddTask(std::move(test4));
449
450 int timeout = 200;
451 while (timeout > 0) {
452 (void)sys_sleep(50);
453 if (g_tests_completed >= 4) {
454 break;
455 }
456 timeout--;
457 }
458
459 EXPECT_EQ(g_tests_completed, 4, "tests completed");
460 EXPECT_EQ(g_tests_failed, 0, "tests failed");
461
462 klog::Info("Clone System Test Suite: COMPLETED");
463 return true;
464}
auto sys_sleep(uint64_t ms) -> int
休眠指定毫秒数
Definition syscall.cpp:90
#define EXPECT_EQ(val1, val2, msg)
Here is the call graph for this function:

◆ ctor_dtor_test()

auto ctor_dtor_test ( ) -> bool

Definition at line 63 of file ctor_dtor_test.cpp.

63 {
64#ifdef __aarch64__
65 cpu_io::SetupFpu();
66#endif
67
68 klog::Info("Running C++ Runtime Tests...");
69
70 // 1. Verify Global Initialization
71 EXPECT_EQ(global_value_with_init, 42, "Global int init");
72 EXPECT_EQ(global_u32_value_with_init, 0xa1a2a3a4UL, "Global uint32 init");
73 EXPECT_EQ(global_u64_value_with_init, 0xb1b2b3b4b5b6b7b8ULL,
74 "Global uint64 init");
75 EXPECT_EQ(global_u16_value_with_init, 0x1234, "Global uint16 init");
76 EXPECT_EQ(global_u8a_value_with_init, 0x42, "Global uint8 a init");
77 EXPECT_EQ(global_u8b_value_with_init, 0x43, "Global uint8 b init");
78 EXPECT_EQ(global_u8c_value_with_init, 0x44, "Global uint8 c init");
79 EXPECT_EQ(global_u8d_value_with_init, 0x45, "Global uint8 d init");
80
81 // 2. Verify Global Constructors
82 // global_value1_with_constructor was initialized to 1
83 // constructor_destructor_1 adds 0x200
84 // constructor_destructor_4 adds 0x100000
85 // Expected: 1 | 0x200 | 0x100000 = 0x100201 (1049089)
86 unsigned int expected_v1 = 1 | 0x200 | 0x100000;
88 "Global constructor execution 1");
89
90 unsigned int expected_v2 = 2 | 0x200 | 0x100000;
92 "Global constructor execution 2");
93
94 // 3. Verify Class Member, Virtual Function, and Stack Object Destructor
95 int start_dtor = g_dtor_count;
96 {
97 auto inst_class = InsClass();
98 EXPECT_EQ(inst_class.val, 'B', "Class constructor body");
99 inst_class.Func();
100 EXPECT_EQ(inst_class.val, 'C', "Virtual function dispatch");
101 }
102 EXPECT_EQ(g_dtor_count, start_dtor + 1,
103 "Stack object destructor verification");
104
105 // 4. Verify Static Local Variable
106 static InsClass inst_class_static;
107 EXPECT_TRUE(inst_class_static.val == 'B' || inst_class_static.val == 'C',
108 "Static local object constructor/persistence");
109 inst_class_static.Func();
110 EXPECT_EQ(inst_class_static.val, 'C', "Static local object virtual func");
111
112 klog::Info("PASS: All C++ Runtime Tests passed.");
113
114 return true;
115}
void Func() override
static uint8_t global_u8d_value_with_init
static uint16_t global_u16_value_with_init
static unsigned int global_value2_with_constructor
static unsigned int global_value1_with_constructor
static uint64_t global_u64_value_with_init
static int global_value_with_init
static uint8_t global_u8b_value_with_init
static uint32_t global_u32_value_with_init
static uint8_t global_u8c_value_with_init
static uint8_t global_u8a_value_with_init
static int g_dtor_count
#define EXPECT_TRUE(cond, msg)
Here is the call graph for this function:

◆ exit_system_test()

auto exit_system_test ( ) -> bool

Exit 系统测试入口

Definition at line 452 of file exit_system_test.cpp.

452 {
453 klog::Info("===== Exit System Test Start =====");
454
455 // 重置全局计数器
456 g_tests_completed = 0;
457 g_tests_failed = 0;
458 g_exit_test_counter = 0;
459
460 auto& task_mgr = TaskManagerSingleton::instance();
461
462 // 测试 1: Normal exit
463 auto test1 = kstd::make_unique<TaskControlBlock>("TestExitNormal", 10,
464 test_exit_normal, nullptr);
465 task_mgr.AddTask(std::move(test1));
466
467 // 测试 2: Exit with error
468 auto test2 = kstd::make_unique<TaskControlBlock>(
469 "TestExitWithError", 10, test_exit_with_error, nullptr);
470 task_mgr.AddTask(std::move(test2));
471
472 // 测试 3: Thread exit
473 auto test3 = kstd::make_unique<TaskControlBlock>("TestThreadExit", 10,
474 test_thread_exit, nullptr);
475 task_mgr.AddTask(std::move(test3));
476
477 // 测试 4: Orphan exit
478 auto test4 = kstd::make_unique<TaskControlBlock>("TestOrphanExit", 10,
479 test_orphan_exit, nullptr);
480 task_mgr.AddTask(std::move(test4));
481
482 // 测试 5: Zombie process
483 auto test5 = kstd::make_unique<TaskControlBlock>(
484 "TestZombieProcess", 10, test_zombie_process, nullptr);
485 task_mgr.AddTask(std::move(test5));
486
487 klog::Info("Waiting for all 5 sub-tests to complete...");
488
489 // 等待所有子测试完成(每个子测试在退出前会增加 g_tests_completed)
490 // 超时: 200 * 50ms = 10s
491 int timeout = 200;
492 while (timeout > 0) {
493 (void)sys_sleep(50);
494 if (g_tests_completed.load() >= 5) {
495 break;
496 }
497 timeout--;
498 }
499
500 klog::Info("Exit System Test: completed={}, failed={}",
501 g_tests_completed.load(), g_tests_failed.load());
502
503 EXPECT_EQ(g_tests_completed, 5, "All 5 sub-tests completed");
504 EXPECT_EQ(g_tests_failed, 0, "No sub-tests failed");
505
506 klog::Info("===== Exit System Test End =====");
507 return true;
508}
Here is the call graph for this function:

◆ expect_eq_helper()

template<typename T1 , typename T2 >
bool expect_eq_helper ( const T1 &  val1,
const T2 &  val2,
const char *  msg 
)

Definition at line 19 of file system_test.h.

19 {
20#pragma GCC diagnostic push
21#pragma GCC diagnostic ignored "-Wsign-compare"
22 if (val1 != val2) {
23#pragma GCC diagnostic pop
24 if constexpr (std::is_convertible_v<T1, uint64_t> &&
25 std::is_convertible_v<T2, uint64_t>) {
26 klog::Err("FAIL: {}. Expected {}, got {}", msg,
27 static_cast<uint64_t>(val2), static_cast<uint64_t>(val1));
28 } else {
29 klog::Err("FAIL: {}", msg);
30 }
31 return false;
32 }
33 return true;
34}
auto Err(etl::format_string< Args... > fmt, Args &&... args) -> void
以 ERROR 级别记录日志
Here is the call graph for this function:

◆ expect_ge_helper()

template<typename T1 , typename T2 >
bool expect_ge_helper ( const T1 &  val1,
const T2 &  val2,
const char *  msg 
)

Definition at line 91 of file system_test.h.

91 {
92#pragma GCC diagnostic push
93#pragma GCC diagnostic ignored "-Wsign-compare"
94 if (!(val1 >= val2)) {
95#pragma GCC diagnostic pop
96 if constexpr (std::is_convertible_v<T1, uint64_t> &&
97 std::is_convertible_v<T2, uint64_t>) {
98 klog::Err("FAIL: {}. Expected {} >= {}", msg, static_cast<uint64_t>(val1),
99 static_cast<uint64_t>(val2));
100 } else {
101 klog::Err("FAIL: {}", msg);
102 }
103 return false;
104 }
105 return true;
106}
Here is the call graph for this function:

◆ expect_gt_helper()

template<typename T1 , typename T2 >
bool expect_gt_helper ( const T1 &  val1,
const T2 &  val2,
const char *  msg 
)

Definition at line 55 of file system_test.h.

55 {
56#pragma GCC diagnostic push
57#pragma GCC diagnostic ignored "-Wsign-compare"
58 if (!(val1 > val2)) {
59#pragma GCC diagnostic pop
60 if constexpr (std::is_convertible_v<T1, uint64_t> &&
61 std::is_convertible_v<T2, uint64_t>) {
62 klog::Err("FAIL: {}. Expected {} > {}", msg, static_cast<uint64_t>(val1),
63 static_cast<uint64_t>(val2));
64 } else {
65 klog::Err("FAIL: {}", msg);
66 }
67 return false;
68 }
69 return true;
70}
Here is the call graph for this function:

◆ expect_le_helper()

template<typename T1 , typename T2 >
bool expect_le_helper ( const T1 &  val1,
const T2 &  val2,
const char *  msg 
)

Definition at line 109 of file system_test.h.

109 {
110#pragma GCC diagnostic push
111#pragma GCC diagnostic ignored "-Wsign-compare"
112 if (!(val1 <= val2)) {
113#pragma GCC diagnostic pop
114 if constexpr (std::is_convertible_v<T1, uint64_t> &&
115 std::is_convertible_v<T2, uint64_t>) {
116 klog::Err("FAIL: {}. Expected {} <= {}", msg, static_cast<uint64_t>(val1),
117 static_cast<uint64_t>(val2));
118 } else {
119 klog::Err("FAIL: {}", msg);
120 }
121 return false;
122 }
123 return true;
124}
Here is the call graph for this function:

◆ expect_lt_helper()

template<typename T1 , typename T2 >
bool expect_lt_helper ( const T1 &  val1,
const T2 &  val2,
const char *  msg 
)

Definition at line 73 of file system_test.h.

73 {
74#pragma GCC diagnostic push
75#pragma GCC diagnostic ignored "-Wsign-compare"
76 if (!(val1 < val2)) {
77#pragma GCC diagnostic pop
78 if constexpr (std::is_convertible_v<T1, uint64_t> &&
79 std::is_convertible_v<T2, uint64_t>) {
80 klog::Err("FAIL: {}. Expected {} < {}", msg, static_cast<uint64_t>(val1),
81 static_cast<uint64_t>(val2));
82 } else {
83 klog::Err("FAIL: {}", msg);
84 }
85 return false;
86 }
87 return true;
88}
Here is the call graph for this function:

◆ expect_ne_helper()

template<typename T1 , typename T2 >
bool expect_ne_helper ( const T1 &  val1,
const T2 &  val2,
const char *  msg 
)

Definition at line 37 of file system_test.h.

37 {
38#pragma GCC diagnostic push
39#pragma GCC diagnostic ignored "-Wsign-compare"
40 if (val1 == val2) {
41#pragma GCC diagnostic pop
42 if constexpr (std::is_convertible_v<T1, uint64_t> &&
43 std::is_convertible_v<T2, uint64_t>) {
44 klog::Err("FAIL: {}. Expected not {}, got {}", msg,
45 static_cast<uint64_t>(val2), static_cast<uint64_t>(val1));
46 } else {
47 klog::Err("FAIL: {}", msg);
48 }
49 return false;
50 }
51 return true;
52}
Here is the call graph for this function:

◆ fatfs_system_test()

auto fatfs_system_test ( ) -> bool

Definition at line 16 of file fatfs_system_test.cpp.

16 {
17 klog::Info("fatfs_system_test: start");
18
19 // T1: Get virtio-blk device via DeviceManager
20 DeviceNode* blk_nodes[4]{};
21 const size_t blk_count = DeviceManagerSingleton::instance().FindDevicesByType(
22 DeviceType::kBlock, blk_nodes, 4);
23 if (blk_count == 0 || blk_nodes[0]->block_device == nullptr) {
25 "fatfs_system_test: SKIP — no virtio-blk device "
26 "available");
27 return true; // Graceful skip, not a failure
28 }
29 vfs::BlockDevice* blk = blk_nodes[0]->block_device;
30 klog::Info("fatfs_system_test: virtio-blk device: {}", blk->GetName());
31 EXPECT_GT(blk->GetSectorCount(), static_cast<uint64_t>(0),
32 "fatfs_system_test: virtio-blk has zero sectors");
33
34 // T2: Mount FatFS at /mnt/fat
35 // vfs::Init() and ramfs mount at "/" should already have been done by
36 // ramfs_system_test, but call Init() again (it's idempotent).
37 auto init_result = vfs::Init();
38 EXPECT_TRUE(init_result.has_value(), "fatfs_system_test: vfs init failed");
39
40 // Create /mnt and /mnt/fat directories in the VFS tree (in ramfs at /)
41 // before mounting. MkDir is idempotent-ish — ignore errors if exists.
42 (void)vfs::MkDir("/mnt");
43 (void)vfs::MkDir("/mnt/fat");
44
45 static fatfs::FatFsFileSystem fat_fs(0);
46 auto fat_mount = fat_fs.Mount(blk);
47 EXPECT_TRUE(fat_mount.has_value(),
48 "fatfs_system_test: FatFsFileSystem::Mount failed");
49 klog::Info("fatfs_system_test: FatFsFileSystem::Mount ok");
50
51 auto vfs_mount = vfs::GetMountTable().Mount("/mnt/fat", &fat_fs, blk);
52 EXPECT_TRUE(vfs_mount.has_value(),
53 "fatfs_system_test: vfs mount at /mnt/fat failed");
54 klog::Info("fatfs_system_test: vfs mount at /mnt/fat ok");
55
56 // T3: Write a file on the FAT volume
57 {
58 auto file_result =
59 vfs::Open("/mnt/fat/test.txt",
61 EXPECT_TRUE(file_result.has_value(),
62 "fatfs_system_test: open /mnt/fat/test.txt failed");
63 vfs::File* file = file_result.value();
64
65 const char kMsg[] = "Hello, FatFS!";
66 auto write_result = vfs::Write(file, kMsg, sizeof(kMsg) - 1);
67 EXPECT_TRUE(write_result.has_value(),
68 "fatfs_system_test: write to /mnt/fat/test.txt failed");
69 EXPECT_EQ(write_result.value(), sizeof(kMsg) - 1,
70 "fatfs_system_test: write byte count mismatch");
71 klog::Info("fatfs_system_test: wrote {} bytes to /mnt/fat/test.txt",
72 write_result.value());
73
74 (void)vfs::Close(file);
75 }
76
77 // T4: Read back and verify
78 {
79 auto file_result =
80 vfs::Open("/mnt/fat/test.txt", vfs::OpenFlags::kOReadOnly);
81 EXPECT_TRUE(file_result.has_value(),
82 "fatfs_system_test: re-open /mnt/fat/test.txt failed");
83 vfs::File* file = file_result.value();
84
85 char buf[64] = {};
86 const char kMsg[] = "Hello, FatFS!";
87 auto read_result = vfs::Read(file, buf, sizeof(buf) - 1);
88 EXPECT_TRUE(read_result.has_value(),
89 "fatfs_system_test: read from /mnt/fat/test.txt failed");
90 EXPECT_EQ(read_result.value(), sizeof(kMsg) - 1,
91 "fatfs_system_test: read byte count mismatch");
92 EXPECT_EQ(memcmp(buf, kMsg, sizeof(kMsg) - 1), 0,
93 "fatfs_system_test: read content mismatch");
94 klog::Info("fatfs_system_test: verified read: {}", buf);
95
96 (void)vfs::Close(file);
97 }
98
99 // T5: MkDir on FAT volume
100 {
101 auto mkdir_result = vfs::MkDir("/mnt/fat/subdir");
102 EXPECT_TRUE(mkdir_result.has_value(),
103 "fatfs_system_test: mkdir /mnt/fat/subdir failed");
104 klog::Info("fatfs_system_test: mkdir /mnt/fat/subdir ok");
105
106 // Create a file inside subdir
107 auto inner =
108 vfs::Open("/mnt/fat/subdir/inner.txt",
110 EXPECT_TRUE(inner.has_value(),
111 "fatfs_system_test: create /mnt/fat/subdir/inner.txt failed");
112 if (inner.has_value()) {
113 (void)vfs::Close(inner.value());
114 }
115
116 // ReadDir on root of fat volume to find subdir
117 auto dir_file = vfs::Open(
119 EXPECT_TRUE(dir_file.has_value(),
120 "fatfs_system_test: open /mnt/fat as dir failed");
121 if (dir_file.has_value()) {
122 vfs::DirEntry entries[16] = {};
123 auto readdir_result = vfs::ReadDir(dir_file.value(), entries, 16);
124 EXPECT_TRUE(readdir_result.has_value(),
125 "fatfs_system_test: readdir /mnt/fat failed");
126 // Should see at least test.txt and subdir
127 EXPECT_GT(readdir_result.value(), static_cast<size_t>(1),
128 "fatfs_system_test: readdir /mnt/fat should return > 1 entry");
129 klog::Info("fatfs_system_test: readdir /mnt/fat returned {} entries",
130 readdir_result.value());
131 (void)vfs::Close(dir_file.value());
132 }
133 }
134
135 // T6: Unmount and remount — verify persistence
136 {
137 auto unmount_result = fat_fs.Unmount();
138 EXPECT_TRUE(unmount_result.has_value(),
139 "fatfs_system_test: FatFsFileSystem::Unmount failed");
140 klog::Info("fatfs_system_test: unmounted ok");
141
142 // Remount
143 auto remount_result = fat_fs.Mount(blk);
144 EXPECT_TRUE(remount_result.has_value(),
145 "fatfs_system_test: remount failed");
146 klog::Info("fatfs_system_test: remounted ok");
147
148 // Re-wire VFS mount
149 auto vfs_remount = vfs::GetMountTable().Mount("/mnt/fat", &fat_fs, blk);
150 EXPECT_TRUE(vfs_remount.has_value(),
151 "fatfs_system_test: vfs remount failed");
152
153 // Verify test.txt persisted
154 auto file_result =
155 vfs::Open("/mnt/fat/test.txt", vfs::OpenFlags::kOReadOnly);
156 EXPECT_TRUE(file_result.has_value(),
157 "fatfs_system_test: test.txt not found after remount");
158 if (file_result.has_value()) {
159 char buf[64] = {};
160 const char kMsg[] = "Hello, FatFS!";
161 auto read_result = vfs::Read(file_result.value(), buf, sizeof(buf) - 1);
162 EXPECT_TRUE(read_result.has_value(),
163 "fatfs_system_test: read after remount failed");
164 EXPECT_EQ(memcmp(buf, kMsg, sizeof(kMsg) - 1), 0,
165 "fatfs_system_test: data corrupted after remount");
166 klog::Info("fatfs_system_test: persistence verified: {}", buf);
167 (void)vfs::Close(file_result.value());
168 }
169 }
170
171 klog::Info("fatfs_system_test: all tests passed");
172 return true;
173}
FatFS VFS 适配器
Definition fatfs.hpp:25
块设备抽象基类
virtual auto GetName() const -> const char *=0
获取设备名称(如 "virtio-blk0")
virtual auto GetSectorCount() const -> uint64_t=0
获取设备总扇区数
@ kBlock
块设备(磁盘等)
@ kODirectory
必须是目录
auto Read(File *file, void *buf, size_t count) -> Expected< size_t >
从文件读取数据
Definition read.cpp:13
auto Write(File *file, const void *buf, size_t count) -> Expected< size_t >
向文件写入数据
Definition write.cpp:13
auto Open(const char *path, OpenFlags flags) -> Expected< File * >
打开文件
Definition open.cpp:14
auto ReadDir(File *file, DirEntry *dirent, size_t count) -> Expected< size_t >
读取目录内容
Definition readdir.cpp:13
auto MkDir(const char *path) -> Expected< void >
创建目录
Definition mkdir.cpp:14
auto Close(File *file) -> Expected< void >
关闭文件
Definition close.cpp:15
auto GetMountTable() -> MountTable &
获取全局挂载表实例
Definition mount.cpp:234
auto Init() -> Expected< void >
VFS 全局初始化
Definition vfs.cpp:80
#define memcmp
单个设备的硬件资源描述。
目录项结构(用于 readdir)
File — 打开的文件实例(每次 open 产生一个)
Definition vfs.hpp:65
#define EXPECT_GT(val1, val2, msg)
Here is the call graph for this function:

◆ fifo_scheduler_test()

auto fifo_scheduler_test ( ) -> bool

Definition at line 328 of file fifo_scheduler_test.cpp.

328 {
329 klog::Info("\n=== FIFO Scheduler System Tests ===\n");
330
331 if (!test_fifo_basic_functionality()) {
332 return false;
333 }
334
335 if (!test_fifo_ordering()) {
336 return false;
337 }
338
339 if (!test_fifo_dequeue()) {
340 return false;
341 }
342
343 if (!test_fifo_statistics()) {
344 return false;
345 }
346
347 if (!test_fifo_mixed_operations()) {
348 return false;
349 }
350
351 if (!test_fifo_repeated_enqueue()) {
352 return false;
353 }
354
355 if (!test_fifo_hooks()) {
356 return false;
357 }
358
359 if (!test_fifo_robustness()) {
360 return false;
361 }
362
363 klog::Info("=== All FIFO Scheduler Tests Passed ===\n");
364 return true;
365}
Here is the call graph for this function:

◆ idle_scheduler_test()

auto idle_scheduler_test ( ) -> bool

Definition at line 246 of file idle_scheduler_test.cpp.

246 {
247 klog::Info("\n=== Idle Scheduler System Tests ===\n");
248
249 if (!test_idle_basic_functionality()) {
250 return false;
251 }
252
253 if (!test_idle_pick_next_does_not_remove()) {
254 return false;
255 }
256
257 if (!test_idle_enqueue_dequeue()) {
258 return false;
259 }
260
261 if (!test_idle_on_tick_always_false()) {
262 return false;
263 }
264
265 if (!test_idle_on_time_slice_expired_always_false()) {
266 return false;
267 }
268
269 if (!test_idle_statistics()) {
270 return false;
271 }
272
273 if (!test_idle_dequeue_wrong_task()) {
274 return false;
275 }
276
277 if (!test_idle_robustness()) {
278 return false;
279 }
280
281 klog::Info("=== All Idle Scheduler Tests Passed ===\n");
282 return true;
283}
Here is the call graph for this function:

◆ interrupt_test()

auto interrupt_test ( ) -> bool
Todo:
等用户态调通后补上

Definition at line 22 of file interrupt_test.cpp.

22 {
23 klog::Info("interrupt_test: start");
24
25 (void)InterruptSingleton::instance().BroadcastIpi();
26
27 klog::Info("interrupt_test: broadcast ipi passed");
28
29 return true;
30}
Here is the call graph for this function:

◆ kernel_task_test()

auto kernel_task_test ( ) -> bool

Definition at line 51 of file kernel_task_test.cpp.

51 {
52 klog::Info("kernel_task_test: start");
53 g_task_a_counter = 0;
54 g_task_b_counter = 0;
55
56 // 创建线程 A
57 auto task_a = kstd::make_unique<TaskControlBlock>("Task A", 10, thread_func_a,
58 (void*)100);
59 TaskManagerSingleton::instance().AddTask(std::move(task_a));
60
61 // 创建线程 B
62 auto task_b = kstd::make_unique<TaskControlBlock>("Task B", 10, thread_func_b,
63 (void*)200);
64 TaskManagerSingleton::instance().AddTask(std::move(task_b));
65
66 klog::Info("Main: Waiting for tasks...");
67
68 // Wait for tasks to finish (or reach expected count)
69 int timeout = 200; // 200 * 50ms = 10s roughly
70 while (timeout > 0) {
71 (void)sys_sleep(50);
72 if (g_task_a_counter >= 5 && g_task_b_counter >= 5) {
73 break;
74 }
75 timeout--;
76 }
77
78 EXPECT_GT(timeout, 0, "Tasks should complete before timeout");
79 EXPECT_EQ(g_task_a_counter, 5, "Task A count");
80 EXPECT_EQ(g_task_b_counter, 5, "Task B count");
81
82 klog::Info("kernel_task_test: PASS");
83 return true;
84}
Here is the call graph for this function:

◆ memory_test()

auto memory_test ( ) -> bool

Definition at line 24 of file memory_test.cpp.

24 {
25 klog::Info("memory_test: start");
26
27 // Test 1: malloc & free
28 size_t size = 1024;
29 void* ptr = malloc(size);
30 EXPECT_TRUE(ptr != nullptr, "memory_test: malloc failed");
31
32 // Write and read verification
33 auto* byte_ptr = static_cast<uint8_t*>(ptr);
34 for (size_t i = 0; i < size; ++i) {
35 byte_ptr[i] = static_cast<uint8_t>(i & 0xFF);
36 }
37
38 for (size_t i = 0; i < size; ++i) {
39 EXPECT_EQ(byte_ptr[i], static_cast<uint8_t>(i & 0xFF),
40 "memory_test: verify failed");
41 }
42
43 free(ptr);
44 klog::Info("memory_test: malloc/free passed");
45
46 // Test 2: aligned_alloc
47 size_t alignment = 256;
48 size_t aligned_size = 512;
49 void* aligned_ptr = aligned_alloc(alignment, aligned_size);
50 EXPECT_TRUE(aligned_ptr != nullptr, "memory_test: aligned_alloc failed");
51
52 EXPECT_EQ(reinterpret_cast<uintptr_t>(aligned_ptr) & (alignment - 1), 0,
53 "memory_test: aligned_alloc alignment failed");
54
55 free(aligned_ptr);
56 klog::Info("memory_test: aligned_alloc passed");
57
58 // Test 3: Multiple small allocations
59 const int count = 10;
60 void* ptrs[count];
61
62 for (int i = 0; i < count; ++i) {
63 ptrs[i] = malloc(128);
64 EXPECT_TRUE(ptrs[i] != nullptr, "memory_test: multi alloc failed");
65 // Fill
66 kstd::memset(ptrs[i], i, 128);
67 }
68
69 for (int i = 0; i < count; ++i) {
70 auto* p = static_cast<uint8_t*>(ptrs[i]);
71 for (int j = 0; j < 128; ++j) {
72 EXPECT_EQ(p[j], i, "memory_test: multi alloc verify failed");
73 }
74 free(ptrs[i]);
75 }
76 klog::Info("memory_test: multi alloc passed");
77
78 return true;
79}
void * aligned_alloc(size_t alignment, size_t size)
Definition memory.cpp:58
void * malloc(size_t size)
Definition memory.cpp:31
void free(void *ptr)
Definition memory.cpp:38
Here is the call graph for this function:

◆ mutex_test()

auto mutex_test ( ) -> bool

Definition at line 297 of file mutex_test.cpp.

297 {
298 klog::Info("=== Mutex System Test Suite ===");
299
300 g_tests_completed = 0;
301 g_tests_failed = 0;
302
303 auto& task_mgr = TaskManagerSingleton::instance();
304
305 auto test1 = kstd::make_unique<TaskControlBlock>(
306 "TestMutexBasic", 10, test_mutex_basic_lock_unlock, nullptr);
307 task_mgr.AddTask(std::move(test1));
308
309 auto test2 = kstd::make_unique<TaskControlBlock>("TestMutexTryLock", 10,
310 test_mutex_trylock, nullptr);
311 task_mgr.AddTask(std::move(test2));
312
313 auto test3 = kstd::make_unique<TaskControlBlock>(
314 "TestMutexContention", 10, test_mutex_contention, nullptr);
315 task_mgr.AddTask(std::move(test3));
316
317 auto test4 = kstd::make_unique<TaskControlBlock>(
318 "TestMutexOrdering", 10, test_mutex_ordering, nullptr);
319 task_mgr.AddTask(std::move(test4));
320
321 constexpr int kExpectedTests = 4;
322 int timeout = 400;
323 while (timeout > 0) {
324 (void)sys_sleep(50);
325 if (g_tests_completed >= kExpectedTests) {
326 break;
327 }
328 timeout--;
329 }
330
331 EXPECT_EQ(g_tests_completed.load(), kExpectedTests,
332 "All mutex tests should complete");
333 EXPECT_EQ(g_tests_failed.load(), 0, "No mutex tests should fail");
334
335 klog::Info("Mutex System Test Suite: COMPLETED");
336 return true;
337}
Here is the call graph for this function:

◆ QemuExit()

void QemuExit ( bool  success)
inline

测试结束后退出 QEMU,success=true 表示全部通过

Definition at line 196 of file system_test.h.

196 {
197#if defined(__riscv)
198 // sifive_test device (virt machine 默认存在,地址 0x100000)
199 // 0x5555 = FINISHER_PASS, 0x3333 = FINISHER_FAIL
200 volatile auto* finisher = reinterpret_cast<volatile uint32_t*>(0x100000);
201 *finisher = success ? 0x5555 : 0x3333;
202#elif defined(__x86_64__)
203 // isa-debug-exit device (需要 QEMU 参数:
204 // -device isa-debug-exit,iobase=0xf4,iosize=0x04)
205 // QEMU 退出码 = (val << 1) | 1,所以 0 -> 1(pass), 1 -> 3(fail)
206 uint32_t code = success ? 0 : 1;
207 asm volatile("outl %0, %1" ::"a"(code), "Nd"(static_cast<uint16_t>(0xf4)));
208#elif defined(__aarch64__)
209 // PSCI SYSTEM_OFF (function id = 0x84000008)
210 // 需要 EL2/EL3 支持(ATF 已提供)
211 register uint64_t x0 asm("x0") = 0x84000008;
212 asm volatile("hvc #0" : "+r"(x0));
213#endif
214 __builtin_unreachable();
215}

◆ ramfs_system_test()

auto ramfs_system_test ( ) -> bool

Definition at line 12 of file ramfs_system_test.cpp.

12 {
13 klog::Info("ramfs_system_test: start");
14
15 // FileSystemInit() has already been called in main.cpp.
16 // ramfs is mounted at "/" — use VFS directly.
17
18 // T1: Create file, write, read back
19 {
20 auto file_result = vfs::Open(
22 EXPECT_TRUE(file_result.has_value(),
23 "ramfs_system_test: open /hello.txt failed");
24 vfs::File* file = file_result.value();
25
26 const char kMsg[] = "Hello, ramfs!";
27 auto write_result = vfs::Write(file, kMsg, sizeof(kMsg) - 1);
28 EXPECT_TRUE(write_result.has_value(), "ramfs_system_test: write failed");
29 EXPECT_EQ(write_result.value(), sizeof(kMsg) - 1,
30 "ramfs_system_test: write byte count mismatch");
31 klog::Info("ramfs_system_test: wrote {} bytes", write_result.value());
32
33 // Seek back to start
34 auto seek_result = vfs::Seek(file, 0, vfs::SeekWhence::kSet);
35 EXPECT_TRUE(seek_result.has_value(),
36 "ramfs_system_test: seek to start failed");
37 EXPECT_EQ(seek_result.value(), static_cast<uint64_t>(0),
38 "ramfs_system_test: seek position mismatch");
39
40 // Read back
41 char buf[64] = {};
42 auto read_result = vfs::Read(file, buf, sizeof(buf) - 1);
43 EXPECT_TRUE(read_result.has_value(), "ramfs_system_test: read failed");
44 EXPECT_EQ(read_result.value(), sizeof(kMsg) - 1,
45 "ramfs_system_test: read byte count mismatch");
46 EXPECT_EQ(memcmp(buf, kMsg, sizeof(kMsg) - 1), 0,
47 "ramfs_system_test: read content mismatch");
48 klog::Info("ramfs_system_test: read back: {}", buf);
49
50 (void)vfs::Close(file);
51 }
52
53 // T3: Seek to middle, partial read
54 {
55 auto file_result = vfs::Open("/hello.txt", vfs::OpenFlags::kOReadOnly);
56 EXPECT_TRUE(file_result.has_value(),
57 "ramfs_system_test: re-open for seek test failed");
58 vfs::File* file = file_result.value();
59
60 // Seek to offset 7
61 auto seek_result = vfs::Seek(file, 7, vfs::SeekWhence::kSet);
62 EXPECT_TRUE(seek_result.has_value(),
63 "ramfs_system_test: seek to offset 7 failed");
64 EXPECT_EQ(seek_result.value(), static_cast<uint64_t>(7),
65 "ramfs_system_test: seek offset 7 mismatch");
66
67 char buf[32] = {};
68 auto read_result = vfs::Read(file, buf, 5);
69 EXPECT_TRUE(read_result.has_value(),
70 "ramfs_system_test: partial read failed");
71 // "Hello, ramfs!" -> offset 7 = "ramfs"
72 EXPECT_EQ(read_result.value(), static_cast<size_t>(5),
73 "ramfs_system_test: partial read count mismatch");
74 EXPECT_EQ(memcmp(buf, "ramfs", 5), 0,
75 "ramfs_system_test: partial read content mismatch");
76 klog::Info("ramfs_system_test: partial read from offset 7: {}", buf);
77
78 (void)vfs::Close(file);
79 }
80
81 // T4: MkDir + ReadDir
82 {
83 auto mkdir_result = vfs::MkDir("/testdir");
84 EXPECT_TRUE(mkdir_result.has_value(),
85 "ramfs_system_test: mkdir /testdir failed");
86 klog::Info("ramfs_system_test: mkdir /testdir ok");
87
88 // Create a file inside
89 auto inner =
90 vfs::Open("/testdir/inner.txt",
92 EXPECT_TRUE(inner.has_value(),
93 "ramfs_system_test: open /testdir/inner.txt failed");
94 (void)vfs::Close(inner.value());
95
96 // ReadDir on /testdir
97 auto dir_file_result = vfs::Open(
99 EXPECT_TRUE(dir_file_result.has_value(),
100 "ramfs_system_test: open /testdir as dir failed");
101 vfs::File* dir_file = dir_file_result.value();
102
103 vfs::DirEntry entries[8] = {};
104 auto readdir_result = vfs::ReadDir(dir_file, entries, 8);
105 EXPECT_TRUE(readdir_result.has_value(),
106 "ramfs_system_test: readdir failed");
107 // Expect at least "." + ".." + "inner.txt" = 3 entries
108 EXPECT_GT(readdir_result.value(), static_cast<size_t>(2),
109 "ramfs_system_test: readdir should return > 2 entries");
110 klog::Info("ramfs_system_test: readdir returned {} entries",
111 readdir_result.value());
112
113 (void)vfs::Close(dir_file);
114 }
115
116 // T5: Unlink a file, confirm it can't be re-opened without kOCreate
117 {
118 auto unlink_result = vfs::Unlink("/hello.txt");
119 EXPECT_TRUE(unlink_result.has_value(),
120 "ramfs_system_test: unlink /hello.txt failed");
121 klog::Info("ramfs_system_test: unlink /hello.txt ok");
122
123 auto reopen = vfs::Open("/hello.txt", vfs::OpenFlags::kOReadOnly);
124 EXPECT_FALSE(reopen.has_value(),
125 "ramfs_system_test: /hello.txt should be gone after unlink");
126 klog::Info("ramfs_system_test: confirmed /hello.txt no longer exists");
127 }
128
129 // T6: RmDir
130 {
131 // Remove inner file first
132 auto unlink_result = vfs::Unlink("/testdir/inner.txt");
133 EXPECT_TRUE(unlink_result.has_value(),
134 "ramfs_system_test: unlink /testdir/inner.txt failed");
135
136 auto rmdir_result = vfs::RmDir("/testdir");
137 EXPECT_TRUE(rmdir_result.has_value(),
138 "ramfs_system_test: rmdir /testdir failed");
139 klog::Info("ramfs_system_test: rmdir /testdir ok");
140 }
141
142 // T7: Two independent files do not share data
143 {
144 auto f1 = vfs::Open("/fileA.txt",
146 auto f2 = vfs::Open("/fileB.txt",
148 EXPECT_TRUE(f1.has_value(), "ramfs_system_test: open fileA failed");
149 EXPECT_TRUE(f2.has_value(), "ramfs_system_test: open fileB failed");
150
151 const char kDataA[] = "AAAA";
152 const char kDataB[] = "BBBB";
153 (void)vfs::Write(f1.value(), kDataA, 4);
154 (void)vfs::Write(f2.value(), kDataB, 4);
155
156 (void)vfs::Seek(f1.value(), 0, vfs::SeekWhence::kSet);
157 (void)vfs::Seek(f2.value(), 0, vfs::SeekWhence::kSet);
158
159 char buf1[8] = {};
160 char buf2[8] = {};
161 (void)vfs::Read(f1.value(), buf1, 4);
162 (void)vfs::Read(f2.value(), buf2, 4);
163
164 EXPECT_EQ(memcmp(buf1, kDataA, 4), 0,
165 "ramfs_system_test: fileA data corrupted by fileB");
166 EXPECT_EQ(memcmp(buf2, kDataB, 4), 0,
167 "ramfs_system_test: fileB data corrupted by fileA");
168 klog::Info("ramfs_system_test: two files are independent");
169
170 (void)vfs::Close(f1.value());
171 (void)vfs::Close(f2.value());
172 (void)vfs::Unlink("/fileA.txt");
173 (void)vfs::Unlink("/fileB.txt");
174 }
175
176 klog::Info("ramfs_system_test: all tests passed");
177 return true;
178}
auto Unlink(const char *path) -> Expected< void >
删除文件
Definition unlink.cpp:15
auto RmDir(const char *path) -> Expected< void >
删除目录
Definition rmdir.cpp:15
auto Seek(File *file, int64_t offset, SeekWhence whence) -> Expected< uint64_t >
调整文件偏移量
Definition seek.cpp:13
@ kSet
从文件开头
#define EXPECT_FALSE(cond, msg)
Here is the call graph for this function:

◆ rr_scheduler_test()

auto rr_scheduler_test ( ) -> bool

Definition at line 431 of file rr_scheduler_test.cpp.

431 {
432 klog::Info("\n=== Round-Robin Scheduler System Tests ===\n");
433
434 if (!test_rr_basic_functionality()) {
435 return false;
436 }
437
438 if (!test_rr_round_robin_behavior()) {
439 return false;
440 }
441
442 if (!test_rr_time_slice_management()) {
443 return false;
444 }
445
446 if (!test_rr_dequeue()) {
447 return false;
448 }
449
450 if (!test_rr_statistics()) {
451 return false;
452 }
453
454 if (!test_rr_fairness()) {
455 return false;
456 }
457
458 if (!test_rr_mixed_operations()) {
459 return false;
460 }
461
462 if (!test_rr_multiple_rounds()) {
463 return false;
464 }
465
466 if (!test_rr_hooks()) {
467 return false;
468 }
469
470 if (!test_rr_robustness()) {
471 return false;
472 }
473
474 if (!test_rr_interleaved_operations()) {
475 return false;
476 }
477
478 klog::Info("=== All Round-Robin Scheduler Tests Passed ===\n");
479 return true;
480}
Here is the call graph for this function:

◆ spinlock_test()

auto spinlock_test ( ) -> bool

Definition at line 348 of file spinlock_test.cpp.

348 {
349 bool ret = true;
351
352 // 单元测试仅在核心 0 上运行,以避免日志混乱
353 if (core_id == 0) {
354 klog::Info("Starting spinlock_test");
355 ret = ret && test_basic_lock();
356 ret = ret && test_recursive_lock();
357 ret = ret && test_lock_guard();
358 ret = ret && test_interrupt_restore();
359 }
360
361 // SMP (多核) 测试在所有核心上运行
362 // 使用顺序执行以确保如果前一个测试失败,屏障不会死锁
363 if (!spinlock_smp_test()) ret = false;
364 if (!spinlock_smp_buffer_test()) ret = false;
365 if (!spinlock_smp_string_test()) ret = false;
366
367 if (core_id == 0) {
368 if (ret) {
369 klog::Info("spinlock_test passed");
370 } else {
371 klog::Err("spinlock_test failed");
372 }
373 }
374 return ret;
375}
auto GetCurrentCoreId() -> size_t
Definition cpu_io.h:26
size_t core_id
核心 ID
Definition per_cpu.hpp:1
Here is the call graph for this function:

◆ thread_group_system_test()

auto thread_group_system_test ( ) -> bool

线程组系统测试入口

Definition at line 243 of file thread_group_system_test.cpp.

243 {
244 klog::Info("=== Thread Group System Test Suite ===");
245
246 g_tests_completed = 0;
247 g_tests_failed = 0;
248
249 // 测试 1: 基本线程组功能
250 auto test1 = kstd::make_unique<TaskControlBlock>(
251 "TestThreadGroupBasic", 10, test_thread_group_basic, nullptr);
252 TaskManagerSingleton::instance().AddTask(std::move(test1));
253
254 // 测试 2: 动态加入和离开
255 auto test2 = kstd::make_unique<TaskControlBlock>(
256 "TestThreadGroupDynamic", 10, test_thread_group_dynamic, nullptr);
257 TaskManagerSingleton::instance().AddTask(std::move(test2));
258
259 // 测试 3: 并发退出
260 auto test3 = kstd::make_unique<TaskControlBlock>(
261 "TestThreadGroupConcurrentExit", 10, test_thread_group_concurrent_exit,
262 nullptr);
263 TaskManagerSingleton::instance().AddTask(std::move(test3));
264
265 // 同步等待所有测试完成
266 constexpr int kExpectedTests = 3;
267 int timeout = 400;
268 while (timeout > 0) {
269 (void)sys_sleep(50);
270 if (g_tests_completed >= kExpectedTests) {
271 break;
272 }
273 timeout--;
274 }
275
276 EXPECT_EQ(g_tests_completed.load(), kExpectedTests,
277 "All thread group tests should complete");
278 EXPECT_EQ(g_tests_failed.load(), 0, "No thread group tests should fail");
279
280 klog::Info("Thread Group System Test Suite: COMPLETED");
281 return true;
282}
Here is the call graph for this function:

◆ user_task_test()

auto user_task_test ( ) -> bool
Todo:
Implement user task tests when ELF loading path is testable

Definition at line 22 of file user_task_test.cpp.

22 {
23 klog::Info("user_task_test: SKIPPED (not yet implemented)");
24 return true;
25}
Here is the call graph for this function:

◆ virtual_memory_test()

auto virtual_memory_test ( ) -> bool

Definition at line 29 of file virtual_memory_test.cpp.

29 {
30 klog::Info("virtual_memory_test: start");
31
32 auto& vm = VirtualMemorySingleton::instance();
33
34 // Test 1: 创建用户页表
37 EXPECT_TRUE(user_page_dir != nullptr,
38 "virtual_memory_test: failed to create user page directory");
40 klog::Info("virtual_memory_test: user page directory created at {}",
41 user_page_dir);
42
43 // Test 2: 映射页面
44 void* virt_addr = reinterpret_cast<void*>(0x200000);
45 void* phys_addr = reinterpret_cast<void*>(0x90000000);
46
47 auto map_result =
48 vm.MapPage(user_page_dir, virt_addr, phys_addr,
50 EXPECT_TRUE(map_result.has_value(),
51 "virtual_memory_test: failed to map page");
52 klog::Info("virtual_memory_test: mapped va={} to pa={}", virt_addr,
53 phys_addr);
54
55 // Test 3: 获取映射
56 auto mapped = vm.GetMapping(user_page_dir, virt_addr);
57 EXPECT_TRUE(mapped.has_value(), "virtual_memory_test: failed to get mapping");
58 if (mapped) {
59 EXPECT_EQ(*mapped, phys_addr,
60 "virtual_memory_test: mapping address mismatch");
61 klog::Info("virtual_memory_test: verified mapping pa={}", *mapped);
62 }
63
64 // Test 4: 映射多个页面
65 constexpr size_t kNumPages = 5;
66 for (size_t i = 0; i < kNumPages; ++i) {
67 void* va = reinterpret_cast<void*>(0x300000 +
69 void* pa = reinterpret_cast<void*>(0x91000000 +
71
72 auto result = vm.MapPage(user_page_dir, va, pa,
74 EXPECT_TRUE(result.has_value(),
75 "virtual_memory_test: failed to map multiple pages");
76 }
77 klog::Info("virtual_memory_test: mapped {} pages", kNumPages);
78
79 // Test 5: 验证多页映射
80 for (size_t i = 0; i < kNumPages; ++i) {
81 void* va = reinterpret_cast<void*>(0x300000 +
83 void* pa = reinterpret_cast<void*>(0x91000000 +
85
86 auto m = vm.GetMapping(user_page_dir, va);
87 EXPECT_TRUE(m.has_value(),
88 "virtual_memory_test: multiple page mapping not found");
89 if (m) {
90 EXPECT_EQ(*m, pa, "virtual_memory_test: multiple page mapping mismatch");
91 }
92 }
93 klog::Info("virtual_memory_test: verified {} page mappings", kNumPages);
94
95 // Test 6: 取消映射
96 auto unmap_result = vm.UnmapPage(user_page_dir, virt_addr);
97 EXPECT_TRUE(unmap_result.has_value(),
98 "virtual_memory_test: failed to unmap page");
99
100 auto unmapped = vm.GetMapping(user_page_dir, virt_addr);
101 EXPECT_TRUE(!unmapped.has_value(),
102 "virtual_memory_test: page still mapped after unmap");
103 klog::Info("virtual_memory_test: unmapped va={}", virt_addr);
104
105 // Test 7: 克隆页表(复制映射)
106 auto clone_result = vm.ClonePageDirectory(user_page_dir, true);
107 EXPECT_TRUE(clone_result.has_value(),
108 "virtual_memory_test: failed to clone page directory");
109 void* cloned_page_dir = clone_result.value();
110 EXPECT_TRUE(cloned_page_dir != user_page_dir,
111 "virtual_memory_test: cloned page dir same as source");
112 klog::Info("virtual_memory_test: cloned page directory to {}",
113 cloned_page_dir);
114
115 // Test 8: 验证克隆的映射
116 for (size_t i = 0; i < kNumPages; ++i) {
117 void* va = reinterpret_cast<void*>(0x300000 +
119 void* pa = reinterpret_cast<void*>(0x91000000 +
121
122 auto src_m = vm.GetMapping(user_page_dir, va);
123 auto dst_m = vm.GetMapping(cloned_page_dir, va);
124
125 EXPECT_TRUE(src_m.has_value(),
126 "virtual_memory_test: source mapping lost after clone");
127 EXPECT_TRUE(dst_m.has_value(),
128 "virtual_memory_test: cloned mapping not found");
129
130 if (src_m && dst_m) {
131 EXPECT_EQ(*src_m, pa,
132 "virtual_memory_test: source mapping changed after clone");
133 EXPECT_EQ(*dst_m, pa, "virtual_memory_test: cloned mapping incorrect");
134 EXPECT_EQ(*src_m, *dst_m,
135 "virtual_memory_test: source and clone mappings differ");
136 }
137 }
138 klog::Info("virtual_memory_test: verified cloned mappings");
139
140 // Test 9: 克隆页表(不复制映射)
141 auto clone_no_map_result = vm.ClonePageDirectory(user_page_dir, false);
142 EXPECT_TRUE(clone_no_map_result.has_value(),
143 "virtual_memory_test: failed to clone page dir (no mappings)");
144 void* cloned_no_map = clone_no_map_result.value();
145 klog::Info("virtual_memory_test: cloned page directory (no mappings) to {}",
146 cloned_no_map);
147
148 // 验证新页表没有映射
149 for (size_t i = 0; i < kNumPages; ++i) {
150 void* va = reinterpret_cast<void*>(0x300000 +
152
153 auto m = vm.GetMapping(cloned_no_map, va);
154 EXPECT_TRUE(!m.has_value(),
155 "virtual_memory_test: cloned (no map) should have no mappings");
156 }
157 klog::Info("virtual_memory_test: verified no mappings in cloned page dir");
158
159 // Test 10: 在克隆的页表中添加新映射
160 void* new_va = reinterpret_cast<void*>(0x400000);
161 void* new_pa = reinterpret_cast<void*>(0x92000000);
162
163 auto clone_map_result =
164 vm.MapPage(cloned_no_map, new_va, new_pa,
166 EXPECT_TRUE(clone_map_result.has_value(),
167 "virtual_memory_test: failed to map in cloned page dir");
168
169 // 验证只在克隆的页表中有映射
170 auto user_m = vm.GetMapping(user_page_dir, new_va);
171 auto clone_m = vm.GetMapping(cloned_no_map, new_va);
172
173 EXPECT_TRUE(!user_m.has_value(),
174 "virtual_memory_test: mapping leaked to original page dir");
175 EXPECT_TRUE(clone_m.has_value(),
176 "virtual_memory_test: new mapping not in cloned page dir");
177 if (clone_m) {
178 EXPECT_EQ(*clone_m, new_pa,
179 "virtual_memory_test: new mapping address incorrect");
180 }
181 klog::Info("virtual_memory_test: verified independent mappings");
182
183 // Test 11: 销毁页表
184 vm.DestroyPageDirectory(user_page_dir, false);
185 klog::Info("virtual_memory_test: destroyed user page directory");
186
187 vm.DestroyPageDirectory(cloned_page_dir, false);
188 klog::Info("virtual_memory_test: destroyed cloned page directory");
189
190 vm.DestroyPageDirectory(cloned_no_map, false);
191 klog::Info("virtual_memory_test: destroyed cloned (no map) page directory");
192
193 // Test 12: 重新映射测试
196 EXPECT_TRUE(test_page_dir != nullptr,
197 "virtual_memory_test: failed to create test page dir");
198 memset(test_page_dir, 0, cpu_io::virtual_memory::kPageSize);
199
200 void* test_va = reinterpret_cast<void*>(0x500000);
201 void* test_pa1 = reinterpret_cast<void*>(0x93000000);
202 void* test_pa2 = reinterpret_cast<void*>(0x94000000);
203
204 // 第一次映射
205 (void)vm.MapPage(test_page_dir, test_va, test_pa1,
207
208 auto m1 = vm.GetMapping(test_page_dir, test_va);
209 EXPECT_TRUE(m1.has_value(), "virtual_memory_test: first mapping failed");
210 if (m1) {
211 EXPECT_EQ(*m1, test_pa1, "virtual_memory_test: first mapping incorrect");
212 }
213
214 // 重新映射到不同物理地址
215 (void)vm.MapPage(test_page_dir, test_va, test_pa2,
217
218 auto m2 = vm.GetMapping(test_page_dir, test_va);
219 EXPECT_TRUE(m2.has_value(), "virtual_memory_test: remap failed");
220 if (m2) {
221 EXPECT_EQ(*m2, test_pa2, "virtual_memory_test: remap address incorrect");
222 }
223 klog::Info("virtual_memory_test: verified remap from {} to {}", test_pa1,
224 test_pa2);
225
226 // 清理
227 vm.DestroyPageDirectory(test_page_dir, false);
228
229 klog::Info("virtual_memory_test: all tests passed");
230 return true;
231}
static constexpr size_t kPageSize
Definition cpu_io.h:63
auto GetUserPagePermissions(bool readable=true, bool writable=false, bool executable=false, bool global=false) -> uint64_t
Definition cpu_io.h:79
#define memset
void * aligned_alloc(size_t alignment, size_t size)
Definition memory.cpp:58
Here is the call graph for this function:

◆ wait_system_test()

auto wait_system_test ( ) -> bool

Wait 系统测试入口

Definition at line 326 of file wait_system_test.cpp.

326 {
327 klog::Info("=== Wait System Test Suite ===");
328
329 g_tests_completed = 0;
330 g_tests_failed = 0;
331
332 auto& task_mgr = TaskManagerSingleton::instance();
333
334 // 测试 1: 基本 wait 功能
335 auto test1 = kstd::make_unique<TaskControlBlock>("TestWaitBasic", 10,
336 test_wait_basic, nullptr);
337 task_mgr.AddTask(std::move(test1));
338
339 // 测试 2: 等待任意子进程
340 auto test2 = kstd::make_unique<TaskControlBlock>(
341 "TestWaitAnyChild", 10, test_wait_any_child, nullptr);
342 task_mgr.AddTask(std::move(test2));
343
344 // 测试 3: 非阻塞 wait
345 auto test3 = kstd::make_unique<TaskControlBlock>("TestWaitNoHang", 10,
346 test_wait_no_hang, nullptr);
347 task_mgr.AddTask(std::move(test3));
348
349 // 测试 4: 进程组 wait
350 auto test4 = kstd::make_unique<TaskControlBlock>(
351 "TestWaitProcessGroup", 10, test_wait_process_group, nullptr);
352 task_mgr.AddTask(std::move(test4));
353
354 // 测试 5: 僵尸进程回收
355 auto test5 = kstd::make_unique<TaskControlBlock>(
356 "TestWaitZombieReap", 10, test_wait_zombie_reap, nullptr);
357 task_mgr.AddTask(std::move(test5));
358
359 // 同步等待所有测试完成
360 constexpr int kExpectedTests = 5;
361 int timeout = 400;
362 while (timeout > 0) {
363 (void)sys_sleep(50);
364 if (g_tests_completed >= kExpectedTests) {
365 break;
366 }
367 timeout--;
368 }
369
370 EXPECT_EQ(g_tests_completed.load(), kExpectedTests,
371 "All wait tests should complete");
372 EXPECT_EQ(g_tests_failed.load(), 0, "No wait tests should fail");
373
374 klog::Info("Wait System Test Suite: COMPLETED");
375 return true;
376}
Here is the call graph for this function: