|
1 | 1 | import os |
2 | 2 | import shutil |
| 3 | +import subprocess |
3 | 4 |
|
4 | 5 | import pytest |
5 | 6 |
|
@@ -124,15 +125,17 @@ def test_rmdir_empty(monitored_dir, server, fact_config, dirname): |
124 | 125 | f"Expected exactly 1 kernel rmdir event processed, got {kernel_delta}" |
125 | 126 |
|
126 | 127 |
|
127 | | -def test_rmdir_tree(monitored_dir, server, fact_config): |
| 128 | +def test_rmdir_recursive_with_rm(monitored_dir, server, fact_config): |
128 | 129 | """ |
129 | 130 | Tests that removing a directory tree recursively cleans up all inode tracking. |
130 | 131 |
|
131 | 132 | Scenario: Directory with nested subdirectories and files is removed recursively |
132 | | - using shutil.rmtree (similar to rm -rf). |
| 133 | + using the rm -rf command via subprocess. |
133 | 134 |
|
134 | 135 | This tests that all inodes (both files and directories) are properly removed |
135 | | - from tracking when a tree is deleted. |
| 136 | + from tracking when a tree is deleted by an external process. The rm command |
| 137 | + deletes directories eagerly (immediately after they become empty), creating |
| 138 | + an interleaved deletion pattern. |
136 | 139 |
|
137 | 140 | Args: |
138 | 141 | monitored_dir: Temporary directory path for creating test directories. |
@@ -175,25 +178,34 @@ def test_rmdir_tree(monitored_dir, server, fact_config): |
175 | 178 |
|
176 | 179 | server.wait_events(creation_events) |
177 | 180 |
|
178 | | - # Remove the entire tree recursively (like rm -rf) |
| 181 | + # Remove the entire tree recursively using subprocess (like running rm -rf) |
179 | 182 | # This will generate events for all files and directories |
180 | 183 | # Order: deepest files/dirs first, then work up to the root |
181 | | - shutil.rmtree(level1) |
| 184 | + proc = subprocess.Popen(["rm", "-rf", level1]) |
| 185 | + |
| 186 | + # Capture process info while subprocess is running |
| 187 | + rm_process = Process.from_proc(proc.pid) |
| 188 | + |
| 189 | + # Wait for completion |
| 190 | + proc.wait() |
| 191 | + if proc.returncode != 0: |
| 192 | + raise RuntimeError(f"rm command failed with exit code {proc.returncode}") |
182 | 193 |
|
183 | 194 | # All deletions should be tracked: 3 files + 3 directories |
184 | | - # shutil.rmtree deletes depth-first: file1, file2, file3, level3, level2, level1 |
| 195 | + # rm -rf deletes each directory immediately after it empties (interleaved): |
| 196 | + # file3, level3 (now empty), file2, level2 (now empty), file1, level1 (now empty) |
185 | 197 | unlink_events = [ |
186 | | - Event(process=process, event_type=EventType.UNLINK, |
187 | | - file=file1, host_path=file1), |
188 | | - Event(process=process, event_type=EventType.UNLINK, |
189 | | - file=file2, host_path=file2), |
190 | | - Event(process=process, event_type=EventType.UNLINK, |
| 198 | + Event(process=rm_process, event_type=EventType.UNLINK, |
191 | 199 | file=file3, host_path=file3), |
192 | | - Event(process=process, event_type=EventType.UNLINK, |
| 200 | + Event(process=rm_process, event_type=EventType.UNLINK, |
193 | 201 | file=level3, host_path=level3), |
194 | | - Event(process=process, event_type=EventType.UNLINK, |
| 202 | + Event(process=rm_process, event_type=EventType.UNLINK, |
| 203 | + file=file2, host_path=file2), |
| 204 | + Event(process=rm_process, event_type=EventType.UNLINK, |
195 | 205 | file=level2, host_path=level2), |
196 | | - Event(process=process, event_type=EventType.UNLINK, |
| 206 | + Event(process=rm_process, event_type=EventType.UNLINK, |
| 207 | + file=file1, host_path=file1), |
| 208 | + Event(process=rm_process, event_type=EventType.UNLINK, |
197 | 209 | file=level1, host_path=level1), |
198 | 210 | ] |
199 | 211 |
|
|
0 commit comments