Skip to content

Commit fc5e66b

Browse files
committed
Add tests for scenarii around hardlinks
1 parent 89ee17e commit fc5e66b

5 files changed

Lines changed: 691 additions & 0 deletions

File tree

tests/test_file_open.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,3 +274,99 @@ def test_unmonitored_mounted_dir(
274274
)
275275

276276
server.wait_events([event])
277+
278+
279+
def test_open_via_hardlink(monitored_dir, server):
280+
"""
281+
Tests opening a file through a hardlink path when the original exists.
282+
The event should report the hardlink path as host_path.
283+
284+
Args:
285+
monitored_dir: Temporary directory path for creating test files.
286+
server: The server instance to communicate with.
287+
"""
288+
process = Process.from_proc()
289+
290+
# Create original file
291+
original = os.path.join(monitored_dir, 'original.txt')
292+
with open(original, 'w') as f:
293+
f.write('test content')
294+
295+
# Create hardlink
296+
hardlink = os.path.join(monitored_dir, 'hardlink.txt')
297+
os.link(original, hardlink)
298+
299+
# Open through hardlink
300+
with open(hardlink, 'r') as f:
301+
f.read()
302+
303+
events = [
304+
Event(
305+
process=process,
306+
event_type=EventType.CREATION,
307+
file=original,
308+
host_path=original,
309+
),
310+
Event(
311+
process=process,
312+
event_type=EventType.CREATION,
313+
file=hardlink,
314+
host_path=hardlink,
315+
),
316+
Event(
317+
process=process,
318+
event_type=EventType.OPEN,
319+
file=hardlink,
320+
host_path=hardlink,
321+
),
322+
]
323+
324+
server.wait_events(events)
325+
326+
327+
def test_open_via_original_with_hardlink(monitored_dir, server):
328+
"""
329+
Tests opening a file through its original path when a hardlink exists.
330+
Both paths should be tracked for the same inode.
331+
332+
Args:
333+
monitored_dir: Temporary directory path for creating test files.
334+
server: The server instance to communicate with.
335+
"""
336+
process = Process.from_proc()
337+
338+
# Create original file
339+
original = os.path.join(monitored_dir, 'original.txt')
340+
with open(original, 'w') as f:
341+
f.write('test content')
342+
343+
# Create hardlink
344+
hardlink = os.path.join(monitored_dir, 'hardlink.txt')
345+
os.link(original, hardlink)
346+
347+
# Open through original path
348+
with open(original, 'r') as f:
349+
f.read()
350+
351+
events = [
352+
Event(
353+
process=process,
354+
event_type=EventType.CREATION,
355+
file=original,
356+
host_path=original,
357+
),
358+
Event(
359+
process=process,
360+
event_type=EventType.CREATION,
361+
file=hardlink,
362+
host_path=hardlink,
363+
),
364+
Event(
365+
process=process,
366+
event_type=EventType.OPEN,
367+
file=original,
368+
host_path=original,
369+
),
370+
]
371+
372+
server.wait_events(events)

tests/test_path_chmod.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,3 +336,52 @@ def test_unmonitored_mounted_dir(
336336
)
337337

338338
server.wait_events([event])
339+
340+
341+
def test_chmod_hardlink(monitored_dir, server):
342+
"""
343+
Tests chmod on a file with hardlinks. The chmod affects the inode,
344+
but the event should report the specific path being used.
345+
346+
Args:
347+
monitored_dir: Temporary directory path for creating test files.
348+
server: The server instance to communicate with.
349+
"""
350+
process = Process.from_proc()
351+
mode = 0o600
352+
353+
# Create original file
354+
original = os.path.join(monitored_dir, 'original.txt')
355+
with open(original, 'w') as f:
356+
f.write('test content')
357+
358+
# Create hardlink
359+
hardlink = os.path.join(monitored_dir, 'hardlink.txt')
360+
os.link(original, hardlink)
361+
362+
# chmod through hardlink path
363+
os.chmod(hardlink, mode)
364+
365+
events = [
366+
Event(
367+
process=process,
368+
event_type=EventType.CREATION,
369+
file=original,
370+
host_path=original,
371+
),
372+
Event(
373+
process=process,
374+
event_type=EventType.CREATION,
375+
file=hardlink,
376+
host_path=hardlink,
377+
),
378+
Event(
379+
process=process,
380+
event_type=EventType.PERMISSION,
381+
file=hardlink,
382+
host_path=hardlink,
383+
mode=mode,
384+
),
385+
]
386+
387+
server.wait_events(events)

tests/test_path_chown.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,3 +263,72 @@ def test_no_change(
263263
]
264264

265265
server.wait_events(events)
266+
267+
268+
def test_chown_hardlink(test_container, server):
269+
"""
270+
Tests chown on a file with hardlinks. The chown affects the inode,
271+
but the event should report the specific path being used.
272+
273+
Args:
274+
test_container: A container for running commands in.
275+
server: The server instance to communicate with.
276+
"""
277+
# File Under Test
278+
original = '/container-dir/original.txt'
279+
hardlink = '/container-dir/hardlink.txt'
280+
281+
touch_cmd = f'touch {original}'
282+
link_cmd = f'ln {original} {hardlink}'
283+
chown_cmd = f'chown {TEST_UID}:{TEST_GID} {hardlink}'
284+
285+
# Create file and hardlink
286+
test_container.exec_run(touch_cmd)
287+
test_container.exec_run(link_cmd)
288+
289+
# chown through hardlink path
290+
test_container.exec_run(chown_cmd)
291+
292+
touch = Process.in_container(
293+
exe_path='/usr/bin/touch',
294+
args=touch_cmd,
295+
name='touch',
296+
container_id=test_container.id[:12],
297+
)
298+
ln = Process.in_container(
299+
exe_path='/usr/bin/ln',
300+
args=link_cmd,
301+
name='ln',
302+
container_id=test_container.id[:12],
303+
)
304+
chown = Process.in_container(
305+
exe_path='/usr/bin/chown',
306+
args=chown_cmd,
307+
name='chown',
308+
container_id=test_container.id[:12],
309+
)
310+
311+
events = [
312+
Event(
313+
process=touch,
314+
event_type=EventType.CREATION,
315+
file=original,
316+
host_path='',
317+
),
318+
Event(
319+
process=ln,
320+
event_type=EventType.CREATION,
321+
file=hardlink,
322+
host_path='',
323+
),
324+
Event(
325+
process=chown,
326+
event_type=EventType.OWNERSHIP,
327+
file=hardlink,
328+
host_path='',
329+
owner_uid=TEST_UID,
330+
owner_gid=TEST_GID,
331+
),
332+
]
333+
334+
server.wait_events(events)

0 commit comments

Comments
 (0)