debian-forge/test/mod/test_util_path.py
Tomáš Hozza 8463394d2c util/path: add join_abs() to join potentially absolute paths
It turned out that in many cases, stages need to join two absolute
paths, the pipeline tree path and the path on a booted system. However,
the standard `os.path.join()` function can't handle such situation as
just prepending the root to the subsequent paths.

Add a new helper function, which is able to join any paths together,
regardless if any of them is absolute or not. If the root is not
absolute, the result will be made absolute to the filesystem root `/`.

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
2025-01-06 11:53:46 -08:00

108 lines
2.8 KiB
Python

#
# Tests for the 'osbuild.util.path' module
#
import os
import time
from datetime import datetime
from pathlib import Path
from tempfile import TemporaryDirectory
import pytest
from osbuild.util import path
@pytest.fixture(name="tempdir")
def tempdir_fixture():
with TemporaryDirectory(prefix="path-") as tmp:
yield tmp
def test_clamp_mtime(tempdir):
# This does not need to be precise, anything created within the last 1½h
# should be "clamped". By adding a bit of slack chrony, random
# RTC jumps and DST/timezone changes will not affect the test
clamp_start = int(time.time() - 90 * 60)
tree = Path(tempdir, "tree")
tree.mkdir()
os.makedirs(os.path.join(tree, "a", "bunch", "of", "directories"))
file = Path(tree, "file")
file.touch()
folder = Path(tree, "folder")
folder.mkdir()
link = Path(tree, "link")
link.symlink_to(folder, target_is_directory=True)
# Some time way in the past
clamp_to = int(datetime(2022, 2, 13, 14, 17, 8).timestamp())
path.clamp_mtime(tree, clamp_start, clamp_to)
def ensure_mtime(target, dfd):
stat = os.stat(target, dir_fd=dfd, follow_symlinks=False)
assert stat.st_mtime <= clamp_to, f"failed for {target} ({dfd})"
for _, dirs, files, dfd in os.fwalk(tree):
ensure_mtime(".", dfd)
for d in dirs:
ensure_mtime(d, dfd)
for f in files:
ensure_mtime(f, dfd)
def test_in_tree():
cases = {
("/tmp/file", "/tmp", False): True, # Simple, non-existent
("/etc", "/", True): True, # Simple, should exist
("/tmp/../../file", "/tmp", False): False, # Relative path escape
("/very/fake/directory/and/file", "/very", False): True, # non-existent, OK
("/very/fake/directory/and/file", "/very", True): False, # non-existent, not-OK
("../..", os.path.abspath("."), False): False, # Relative path escape from cwd
(".", os.path.abspath("../.."), False): True, # cwd inside parent of parent
}
for args, expected in cases.items():
assert path.in_tree(*args) == expected, args
@pytest.mark.parametrize("test_case", (
{
"args": ("",),
"expected": "/"
},
{
"args": ("", "file"),
"expected": "/file"
},
{
"args": ("", "/file"),
"expected": "/file"
},
{
"args": ("/tmp", "/file"),
"expected": "/tmp/file"
},
{
"args": ("/tmp", "/foo", "/bar"),
"expected": "/tmp/foo/bar"
},
{
"args": ("/", "/foo"),
"expected": "/foo"
},
{
"args": ("/", "/foo", "/bar"),
"expected": "/foo/bar"
},
{
"args": (Path("/tmp"), "/foo", "/bar"),
"expected": "/tmp/foo/bar"
},
))
def test_join_abs(test_case):
assert path.join_abs(*test_case["args"]) == test_case["expected"]