Files
music-mirror/tests/conftest.py
T
Emma Thorpe e9852e6c86
Build and publish container / build (pull_request) Successful in 15m16s
fix: keep the mirror readable under a umask that masks the owner's read bit
The umask handling added for group access cleared only the group bits and left
owner and other to the environment. A container whose umask carries 0400 then
produces mirror directories of mode 0300: writable and enterable, unreadable to
the very run that created them, and unreadable to anything serving the share.

Clear the owner read and execute bits from the umask as well. The `other` bits
stay where the environment puts them, because whether the mirror is
world-readable is a real policy question; being able to read a directory the
process itself just created is not.

Files were never exposed to this: mkstemp sets 0600 outright and copy2 takes
the source file's mode, both ignoring the umask.
2026-08-24 13:21:07 +01:00

104 lines
2.8 KiB
Python

import os
import shutil
import subprocess
import sys
import pytest
# Ensure the project root is on sys.path when running tests.
ROOT = os.path.dirname(os.path.dirname(__file__))
if ROOT not in sys.path:
sys.path.insert(0, ROOT)
@pytest.fixture(scope="session", autouse=True)
def require_ffmpeg():
"""The tests exercise real encodes; there is little point faking them."""
for tool in ("ffmpeg", "ffprobe"):
if shutil.which(tool) is None:
pytest.skip(f"{tool} is not on PATH", allow_module_level=True)
@pytest.fixture
def tight_umask():
"""Run a test under a umask that would otherwise make the mirror private."""
previous = os.umask(0o077)
yield
os.umask(previous)
@pytest.fixture
def owner_hostile_umask():
"""Return a callable applying a umask that masks off the owner's read bit.
Unusual, but it is what produces a mirror tree of mode 0300 -- writable and
enterable, unreadable to the very process that built it. Applied on demand
rather than for the whole test, because the source library is built by
something else entirely and the same umask would make the test's own
fixtures unreadable before the run under test even started.
"""
previous = os.umask(0o022)
yield lambda: os.umask(0o477)
os.umask(previous)
@pytest.fixture
def make_flac():
"""Return a factory writing a short tagged FLAC file."""
def factory(path, title="Test Title", artist="Test Artist", album="Test Album", seconds=1):
path.parent.mkdir(parents=True, exist_ok=True)
subprocess.run(
[
"ffmpeg",
"-nostdin",
"-hide_banner",
"-loglevel",
"error",
"-y",
"-f",
"lavfi",
"-i",
f"sine=frequency=440:duration={seconds}",
"-metadata",
f"title={title}",
"-metadata",
f"artist={artist}",
"-metadata",
f"album={album}",
"-metadata",
"track=3",
str(path),
],
check=True,
capture_output=True,
)
return path
return factory
@pytest.fixture
def probe_tag():
"""Return a helper reading a single metadata tag from a file."""
def reader(path, tag):
completed = subprocess.run(
[
"ffprobe",
"-v",
"error",
"-show_entries",
f"format_tags={tag}",
"-of",
"default=noprint_wrappers=1:nokey=1",
str(path),
],
check=True,
capture_output=True,
text=True,
)
return completed.stdout.strip()
return reader