Skip to content

Commit 282a086

Browse files
committed
test(dunitest): fail-fast on mount and RAII-clean tracepoint state
Address one P2 and one P1 review item from fslongjin: - mount_debugfs returns AssertionResult now; callers use ASSERT_TRUE so a mount failure terminates the calling test instead of cascading against an ordinary directory. - Add a DebugfsMount RAII guard acquired right after mount (before enable) and armed after a successful enable write. Its destructor restores pre-test state on every exit path: disable (if armed) -> umount -> rmdir. Any mid-test ASSERT return can no longer leak a globally-enabled static key, pollute the shared ring buffer, or leak the mount point into later tests. Assertion semantics unchanged; 5/5 pass on QEMU x86_64. Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>
1 parent 07772c7 commit 282a086

1 file changed

Lines changed: 58 additions & 22 deletions

File tree

user/apps/tests/dunitest/suites/normal/sched_tracepoint.cc

Lines changed: 58 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,48 @@ bool write_file(const char* path, const char* data) {
5858
return n == static_cast<ssize_t>(len);
5959
}
6060

61-
// mount debugfs 到 root。
62-
void mount_debugfs(const char* root) {
63-
ASSERT_EQ(0, mount("none", root, "debugfs", 0, nullptr))
64-
<< "mount debugfs failed: errno=" << errno << " (" << strerror(errno) << ")";
61+
// mount debugfs 到 root。返回 AssertionResult,供调用处 ASSERT_TRUE 在 mount
62+
// 失败时终止当前 TEST(Thread7:避免 void helper 里的 fatal assertion 只 return helper
63+
// 而让测试继续对着普通目录跑、产生连锁失败)。
64+
::testing::AssertionResult mount_debugfs(const char* root) {
65+
if (mount("none", root, "debugfs", 0, nullptr) != 0) {
66+
return ::testing::AssertionFailure()
67+
<< "mount debugfs failed: errno=" << errno << " (" << strerror(errno)
68+
<< ")";
69+
}
70+
return ::testing::AssertionSuccess();
6571
}
6672

73+
// RAII guard:持有 debugfs mount 点,保证任意 ASSERT 提前 return 时都恢复测试前
74+
// 状态(Thread8:否则中途 ASSERT 失败会泄漏 enabled 的 static key + mount 点,污染
75+
// 共享 buffer 并给后续无关 exec 永久加开销)。
76+
//
77+
// 构造前提:mount_debugfs 已成功(mount 已生效)。此时析构必须 umount + rmdir。
78+
// arm_enable():在事件成功 enable 后调用,记录 enable 文件路径;析构时写回 "0"。
79+
// 析构顺序:disable(仅当 arm 过)→ umount → rmdir。不可拷贝/移动(持有路径所有权)。
80+
class DebugfsMount {
81+
public:
82+
explicit DebugfsMount(const char* root) : root_(root) {}
83+
84+
~DebugfsMount() {
85+
if (!enable_path_.empty()) {
86+
write_file(enable_path_.c_str(), "0");
87+
}
88+
umount(root_.c_str());
89+
rmdir(root_.c_str());
90+
}
91+
92+
DebugfsMount(const DebugfsMount&) = delete;
93+
DebugfsMount& operator=(const DebugfsMount&) = delete;
94+
95+
// 在事件成功 enable 后调用:析构时把该文件写回 "0"。
96+
void arm_enable(const char* enable_path) { enable_path_ = enable_path; }
97+
98+
private:
99+
std::string root_;
100+
std::string enable_path_;
101+
};
102+
67103
// 子模式:被 execve 进来后立即退出 0。
68104
[[noreturn]] void helper_exec_exit0() {
69105
char arg0[] = "/proc/self/exe";
@@ -100,7 +136,8 @@ TEST(SchedProcessExecTp, EventFilesExist) {
100136
snprintf(root, sizeof(root), "/tmp/sched_tp_events_%d", getpid());
101137
ASSERT_EQ(0, mkdir(root, 0755)) << strerror(errno);
102138

103-
mount_debugfs(root);
139+
ASSERT_TRUE(mount_debugfs(root)); // Thread7:mount 失败终止测试。
140+
DebugfsMount guard(root); // Thread8:RAII,任意提前 return 都 umount + rmdir。
104141

105142
const char* base_rel = "/tracing/events/sched/sched_process_exec";
106143
char base[256] = {};
@@ -145,8 +182,7 @@ TEST(SchedProcessExecTp, EventFilesExist) {
145182
EXPECT_EQ(end != nullptr && *end == '\0', true) << "id has trailing garbage: " << id;
146183
EXPECT_GE(idval, 0) << "invalid id: " << id;
147184

148-
EXPECT_EQ(0, umount(root)) << strerror(errno);
149-
EXPECT_EQ(0, rmdir(root)) << strerror(errno);
185+
// 清理由 RAII guard 析构完成(umount + rmdir;本测例未 enable,无需 disable)。
150186
}
151187

152188
// enable 后 execve 应触发事件,trace 文件留下记录。
@@ -155,7 +191,8 @@ TEST(SchedProcessExecTp, FiresOnExecve) {
155191
snprintf(root, sizeof(root), "/tmp/sched_tp_fire_%d", getpid());
156192
ASSERT_EQ(0, mkdir(root, 0755)) << strerror(errno);
157193

158-
mount_debugfs(root);
194+
ASSERT_TRUE(mount_debugfs(root)); // Thread7:mount 失败终止测试。
195+
DebugfsMount guard(root); // Thread8:RAII,析构 umount + rmdir。
159196

160197
const char* base_rel = "/tracing/events/sched/sched_process_exec";
161198
char base[256] = {};
@@ -165,6 +202,7 @@ TEST(SchedProcessExecTp, FiresOnExecve) {
165202
char enable_path[320] = {};
166203
snprintf(enable_path, sizeof(enable_path), "%s/enable", base);
167204
ASSERT_TRUE(write_file(enable_path, "1")) << "enable write failed";
205+
guard.arm_enable(enable_path); // Thread8:任意提前 return 析构都会写回 "0"。
168206

169207
// 清空 ring buffer:向 trace 写任意字节触发 clear。
170208
char trace_path[256] = {};
@@ -194,10 +232,7 @@ TEST(SchedProcessExecTp, FiresOnExecve) {
194232
<< "trace missing comm= field:\n"
195233
<< trace;
196234

197-
// 关闭事件并清理。
198-
write_file(enable_path, "0");
199-
EXPECT_EQ(0, umount(root)) << strerror(errno);
200-
EXPECT_EQ(0, rmdir(root)) << strerror(errno);
235+
// 清理由 RAII guard 析构完成(disable + umount + rmdir)。
201236
}
202237

203238
// 默认 disabled 时 execve 不应在 trace 留下 sched_process_exec 记录。
@@ -207,7 +242,8 @@ TEST(SchedProcessExecTp, DefaultDisabledNoRecords) {
207242
snprintf(root, sizeof(root), "/tmp/sched_tp_disabled_%d", getpid());
208243
ASSERT_EQ(0, mkdir(root, 0755)) << strerror(errno);
209244

210-
mount_debugfs(root);
245+
ASSERT_TRUE(mount_debugfs(root)); // Thread7:mount 失败终止测试。
246+
DebugfsMount guard(root); // Thread8:RAII,析构 umount + rmdir(本测例不 enable)。
211247

212248
char trace_path[256] = {};
213249
snprintf(trace_path, sizeof(trace_path), "%s/tracing/trace", root);
@@ -233,8 +269,7 @@ TEST(SchedProcessExecTp, DefaultDisabledNoRecords) {
233269
<< "tracepoint fired while disabled (static-key gate broken):\n"
234270
<< trace;
235271

236-
EXPECT_EQ(0, umount(root)) << strerror(errno);
237-
EXPECT_EQ(0, rmdir(root)) << strerror(errno);
272+
// 清理由 RAII guard 析构完成(umount + rmdir;本测例未 enable,无需 disable)。
238273
}
239274

240275
// enable 后能触发,disable 后不再触发。验证 enable/disable 状态机真正翻转 static-key。
@@ -243,7 +278,8 @@ TEST(SchedProcessExecTp, DisableStopsFiring) {
243278
snprintf(root, sizeof(root), "/tmp/sched_tp_disable_%d", getpid());
244279
ASSERT_EQ(0, mkdir(root, 0755)) << strerror(errno);
245280

246-
mount_debugfs(root);
281+
ASSERT_TRUE(mount_debugfs(root)); // Thread7:mount 失败终止测试。
282+
DebugfsMount guard(root); // Thread8:RAII,析构 umount + rmdir。
247283

248284
const char* base_rel = "/tracing/events/sched/sched_process_exec";
249285
char base[256] = {};
@@ -256,6 +292,7 @@ TEST(SchedProcessExecTp, DisableStopsFiring) {
256292

257293
// 基线:enable 后触发。
258294
ASSERT_TRUE(write_file(enable_path, "1")) << "enable write failed";
295+
guard.arm_enable(enable_path); // Thread8:任意提前 return 析构都会写回 "0"。
259296
ASSERT_TRUE(write_file(trace_path, "1")) << "trace clear write failed";
260297
{
261298
pid_t child = fork();
@@ -297,8 +334,7 @@ TEST(SchedProcessExecTp, DisableStopsFiring) {
297334
<< trace;
298335
}
299336

300-
EXPECT_EQ(0, umount(root)) << strerror(errno);
301-
EXPECT_EQ(0, rmdir(root)) << strerror(errno);
337+
// 清理由 RAII guard 析构完成(disable + umount + rmdir;析构再次写 "0" 对已 disable 状态幂等)。
302338
}
303339

304340
// non-leader 线程 execve:触发 de_thread 的 raw_pid 交换,old_pid ≠ pid。
@@ -308,7 +344,8 @@ TEST(SchedProcessExecTp, NonLeaderExecFiresWithDistinctOldPid) {
308344
snprintf(root, sizeof(root), "/tmp/sched_tp_nonleader_%d", getpid());
309345
ASSERT_EQ(0, mkdir(root, 0755)) << strerror(errno);
310346

311-
mount_debugfs(root);
347+
ASSERT_TRUE(mount_debugfs(root)); // Thread7:mount 失败终止测试。
348+
DebugfsMount guard(root); // Thread8:RAII,析构 umount + rmdir。
312349

313350
const char* base_rel = "/tracing/events/sched/sched_process_exec";
314351
char base[256] = {};
@@ -320,6 +357,7 @@ TEST(SchedProcessExecTp, NonLeaderExecFiresWithDistinctOldPid) {
320357
snprintf(trace_path, sizeof(trace_path), "%s/tracing/trace", root);
321358

322359
ASSERT_TRUE(write_file(enable_path, "1")) << "enable write failed";
360+
guard.arm_enable(enable_path); // Thread8:任意提前 return 析构都会写回 "0"。
323361
ASSERT_TRUE(write_file(trace_path, "1")) << "trace clear write failed";
324362

325363
// fork child:child 创建 sibling 线程(非 leader)执行 execve,leader 永久挂起。
@@ -363,9 +401,7 @@ TEST(SchedProcessExecTp, NonLeaderExecFiresWithDistinctOldPid) {
363401
<< "non-leader exec should produce distinct old_pid vs pid:\n"
364402
<< record;
365403

366-
write_file(enable_path, "0");
367-
EXPECT_EQ(0, umount(root)) << strerror(errno);
368-
EXPECT_EQ(0, rmdir(root)) << strerror(errno);
404+
// 清理由 RAII guard 析构完成(disable + umount + rmdir)。
369405
}
370406

371407
int main(int argc, char** argv) {

0 commit comments

Comments
 (0)