SimpleKernel 1.17.0
Loading...
Searching...
No Matches
kernel_fdt_test.cpp
Go to the documentation of this file.
1
5#include "kernel_fdt.hpp"
6
7#include <gtest/gtest.h>
8
9#include "riscv64_virt.dtb.h"
11
12class KernelFdtTest : public ::testing::Test {
13 protected:
14 void SetUp() override {
17 env_state_.BindThreadToCore(std::this_thread::get_id(), 0);
18 }
19
21
23};
24
25TEST_F(KernelFdtTest, ConstructorTest) {
26 KernelFdt kerlen_fdt((uint64_t)riscv64_virt_dtb_data);
27}
28
29TEST_F(KernelFdtTest, GetMemoryTest) {
30 KernelFdt kerlen_fdt((uint64_t)riscv64_virt_dtb_data);
31
32 auto result = kerlen_fdt.GetMemory();
33 ASSERT_TRUE(result.has_value()) << result.error().message();
34
35 auto [memory_base, memory_size] = *result;
36 EXPECT_EQ(memory_base, 0x80000000);
37 EXPECT_EQ(memory_size, 0x8000000);
38}
39
40TEST_F(KernelFdtTest, GetSerialTest) {
41 KernelFdt kerlen_fdt((uint64_t)riscv64_virt_dtb_data);
42
43 auto result = kerlen_fdt.GetSerial();
44 ASSERT_TRUE(result.has_value()) << result.error().message();
45
46 auto [serial_base, serial_size, serial_irq] = *result;
47 EXPECT_EQ(serial_base, 0x10000000);
48 EXPECT_EQ(serial_size, 0x100);
49 EXPECT_EQ(serial_irq, 0xA);
50}
51
52TEST_F(KernelFdtTest, GetTimebaseFrequencyTest) {
53 KernelFdt kerlen_fdt((uint64_t)riscv64_virt_dtb_data);
54
55 auto result = kerlen_fdt.GetTimebaseFrequency();
56 ASSERT_TRUE(result.has_value()) << result.error().message();
57
58 EXPECT_EQ(*result, 0x989680);
59}
60
61TEST_F(KernelFdtTest, GetCoreCountTest) {
62 KernelFdt kerlen_fdt((uint64_t)riscv64_virt_dtb_data);
63
64 auto result = kerlen_fdt.GetCoreCount();
65 ASSERT_TRUE(result.has_value()) << result.error().message();
66
67 EXPECT_GT(*result, 0); // 至少有一个 CPU 核心
68}
69
70TEST_F(KernelFdtTest, CopyConstructorTest) {
71 KernelFdt kerlen_fdt((uint64_t)riscv64_virt_dtb_data);
72 KernelFdt kerlen_fdt2(kerlen_fdt);
73
74 auto result1 = kerlen_fdt.GetMemory();
75 auto result2 = kerlen_fdt2.GetMemory();
76
77 ASSERT_TRUE(result1.has_value());
78 ASSERT_TRUE(result2.has_value());
79
80 auto [memory_base1, memory_size1] = *result1;
81 auto [memory_base2, memory_size2] = *result2;
82
83 EXPECT_EQ(memory_base1, memory_base2);
84 EXPECT_EQ(memory_size1, memory_size2);
85}
86
87TEST_F(KernelFdtTest, AssignmentTest) {
88 KernelFdt kerlen_fdt((uint64_t)riscv64_virt_dtb_data);
89 KernelFdt kerlen_fdt2;
90
91 kerlen_fdt2 = kerlen_fdt;
92
93 auto result1 = kerlen_fdt.GetMemory();
94 auto result2 = kerlen_fdt2.GetMemory();
95
96 ASSERT_TRUE(result1.has_value());
97 ASSERT_TRUE(result2.has_value());
98
99 auto [memory_base1, memory_size1] = *result1;
100 auto [memory_base2, memory_size2] = *result2;
101
102 EXPECT_EQ(memory_base1, memory_base2);
103 EXPECT_EQ(memory_size1, memory_size2);
104}
105
106TEST_F(KernelFdtTest, MoveConstructorTest) {
107 KernelFdt kerlen_fdt((uint64_t)riscv64_virt_dtb_data);
108 auto result = kerlen_fdt.GetMemory();
109 ASSERT_TRUE(result.has_value());
110 auto [expected_base, expected_size] = *result;
111
112 KernelFdt kerlen_fdt2(std::move(kerlen_fdt));
113
114 auto result2 = kerlen_fdt2.GetMemory();
115 ASSERT_TRUE(result2.has_value());
116 auto [memory_base, memory_size] = *result2;
117
118 EXPECT_EQ(memory_base, expected_base);
119 EXPECT_EQ(memory_size, expected_size);
120}
121
122TEST_F(KernelFdtTest, MoveAssignmentTest) {
123 KernelFdt kerlen_fdt((uint64_t)riscv64_virt_dtb_data);
124 auto result = kerlen_fdt.GetMemory();
125 ASSERT_TRUE(result.has_value());
126 auto [expected_base, expected_size] = *result;
127
128 KernelFdt kerlen_fdt2;
129 kerlen_fdt2 = std::move(kerlen_fdt);
130
131 auto result2 = kerlen_fdt2.GetMemory();
132 ASSERT_TRUE(result2.has_value());
133 auto [memory_base, memory_size] = *result2;
134
135 EXPECT_EQ(memory_base, expected_base);
136 EXPECT_EQ(memory_size, expected_size);
137}
138
139TEST_F(KernelFdtTest, ForEachCompatibleNodeTest) {
140 KernelFdt kerlen_fdt((uint64_t)riscv64_virt_dtb_data);
141
142 size_t count = 0;
143 auto result = kerlen_fdt.ForEachCompatibleNode(
144 "virtio,mmio",
145 [&count](int offset, const char* node_name, uint64_t mmio_base,
146 size_t mmio_size, uint32_t irq) -> bool {
147 (void)offset;
148 (void)node_name;
149 (void)mmio_base;
150 (void)mmio_size;
151 (void)irq;
152 ++count;
153 return true;
154 });
155 ASSERT_TRUE(result.has_value()) << result.error().message();
156 EXPECT_EQ(count, 8); // riscv64 virt has 8 virtio,mmio nodes
157}
158
159TEST_F(KernelFdtTest, ForEachNodeCompatibleDataTest) {
160 KernelFdt kerlen_fdt((uint64_t)riscv64_virt_dtb_data);
161
162 bool found_plic = false;
163 auto result = kerlen_fdt.ForEachNode(
164 [&found_plic](const char* node_name, const char* compatible_data,
165 size_t compatible_len, uint64_t mmio_base, size_t mmio_size,
166 uint32_t irq) -> bool {
167 (void)mmio_base;
168 (void)mmio_size;
169 (void)irq;
170 if (compatible_data == nullptr || compatible_len == 0) {
171 return true;
172 }
173 // Look for PLIC node which has multi-string compatible:
174 // "sifive,plic-1.0.0\0riscv,plic0"
175 if (strcmp(node_name, "plic@c000000") == 0) {
176 found_plic = true;
177 // Should have both strings in the stringlist
178 EXPECT_GT(compatible_len, strlen("sifive,plic-1.0.0") + 1);
179 // First string should be "sifive,plic-1.0.0"
180 EXPECT_STREQ(compatible_data, "sifive,plic-1.0.0");
181 // Second string starts after first null terminator
182 const char* second =
183 compatible_data + strlen("sifive,plic-1.0.0") + 1;
184 EXPECT_STREQ(second, "riscv,plic0");
185 }
186 return true;
187 });
188 ASSERT_TRUE(result.has_value()) << result.error().message();
189 EXPECT_TRUE(found_plic) << "PLIC node not found in ForEachNode traversal";
190}
191
192TEST_F(KernelFdtTest, ForEachCompatibleNodeNoMatchTest) {
193 KernelFdt kerlen_fdt((uint64_t)riscv64_virt_dtb_data);
194
195 size_t count = 0;
196 auto result = kerlen_fdt.ForEachCompatibleNode(
197 "nonexistent,device",
198 [&count](int offset, const char* node_name, uint64_t mmio_base,
199 size_t mmio_size, uint32_t irq) -> bool {
200 (void)offset;
201 (void)node_name;
202 (void)mmio_base;
203 (void)mmio_size;
204 (void)irq;
205 ++count;
206 return true;
207 });
208 ASSERT_TRUE(result.has_value()) << result.error().message();
209 EXPECT_EQ(count, 0); // No matching nodes
210}
211
212TEST_F(KernelFdtTest, ForEachCompatibleNodeEarlyStopTest) {
213 KernelFdt kerlen_fdt((uint64_t)riscv64_virt_dtb_data);
214
215 size_t count = 0;
216 auto result = kerlen_fdt.ForEachCompatibleNode(
217 "virtio,mmio",
218 [&count](int offset, const char* node_name, uint64_t mmio_base,
219 size_t mmio_size, uint32_t irq) -> bool {
220 (void)offset;
221 (void)node_name;
222 (void)mmio_base;
223 (void)mmio_size;
224 (void)irq;
225 ++count;
226 return count < 3; // Stop after 3 nodes
227 });
228 ASSERT_TRUE(result.has_value()) << result.error().message();
229 EXPECT_EQ(count, 3);
230}
231
232TEST_F(KernelFdtTest, MultiCompatibleMatchTest) {
233 KernelFdt kerlen_fdt((uint64_t)riscv64_virt_dtb_data);
234
235 // The PLIC node has compatible = "sifive,plic-1.0.0\0riscv,plic0"
236 // ForEachCompatibleNode uses fdt_node_offset_by_compatible which
237 // matches against any string in the compatible stringlist
238 size_t count = 0;
239 auto result = kerlen_fdt.ForEachCompatibleNode(
240 "riscv,plic0",
241 [&count](int offset, const char* node_name, uint64_t mmio_base,
242 size_t mmio_size, uint32_t irq) -> bool {
243 (void)offset;
244 (void)node_name;
245 (void)mmio_base;
246 (void)mmio_size;
247 (void)irq;
248 ++count;
249 return true;
250 });
251 ASSERT_TRUE(result.has_value()) << result.error().message();
252 EXPECT_EQ(count,
253 1); // Should find the PLIC node via second compatible string
254}
void SetUp() override
test_env::TestEnvironmentState env_state_
void TearDown() override
FDT(Flattened Device Tree)解析器
auto GetTimebaseFrequency() const -> Expected< uint32_t >
获取 CPU 时钟频率
auto GetCoreCount() const -> Expected< size_t >
获取 CPU 核心数量
auto GetSerial() const -> Expected< std::tuple< uint64_t, size_t, uint32_t > >
获取串口信息
auto ForEachCompatibleNode(const char *compatible, Callback &&callback) const -> Expected< void >
遍历所有匹配指定 compatible 的 FDT 节点
auto ForEachNode(Callback &&callback) const -> Expected< void >
遍历 FDT 中所有设备节点
auto GetMemory() const -> Expected< std::pair< uint64_t, size_t > >
获取内存信息
void ClearCurrentThreadEnvironment()
清除当前线程的环境实例指针
void BindThreadToCore(std::thread::id tid, size_t core_id)
将指定线程绑定到核心
void InitializeCores(size_t num_cores)
初始化指定数量的核心
void SetCurrentThreadEnvironment()
设置当前线程的环境实例指针
TEST_F(KernelFdtTest, ConstructorTest)
static constexpr uint8_t riscv64_virt_dtb_data[]
#define strlen
#define strcmp
#define EXPECT_TRUE(cond, msg)
#define EXPECT_GT(val1, val2, msg)
#define EXPECT_EQ(val1, val2, msg)