55 lines
2.0 KiB
Python
55 lines
2.0 KiB
Python
"""Unit tests for jobs.py template rendering and safety."""
|
|
|
|
from media_library_viewer_api.jobs import JOB_TEMPLATES, JobTemplate
|
|
|
|
|
|
class TestJobTemplate:
|
|
def test_render_basic(self):
|
|
template = JobTemplate(
|
|
name="Test",
|
|
description="A test job",
|
|
command_template="echo {path}",
|
|
)
|
|
result = template.render({"path": "/media/file.mkv"})
|
|
assert result == "echo /media/file.mkv"
|
|
|
|
def test_render_quotes_spaces(self):
|
|
template = JobTemplate(
|
|
name="Test",
|
|
description="A test job",
|
|
command_template="du -sh {path}",
|
|
)
|
|
result = template.render({"path": "/media/My Movie (2024)/file.mkv"})
|
|
# shlex.quote wraps in single quotes
|
|
assert "'" in result or "\\" in result
|
|
assert "My Movie (2024)" in result
|
|
|
|
def test_render_quotes_special_chars(self):
|
|
template = JobTemplate(
|
|
name="Test",
|
|
description="A test job",
|
|
command_template="stat {path}",
|
|
)
|
|
result = template.render({"path": "/media/file;rm -rf /"})
|
|
# Injection attempt should be safely quoted
|
|
assert "rm -rf" in result # it's there but quoted
|
|
assert result.startswith("stat ")
|
|
# Should not be executable as separate command
|
|
assert ";" not in result or "'" in result
|
|
|
|
|
|
class TestBuiltinTemplates:
|
|
def test_all_templates_exist(self):
|
|
assert "disk_usage" in JOB_TEMPLATES
|
|
assert "ffprobe" in JOB_TEMPLATES
|
|
assert "dry_run_find_empty_dirs" in JOB_TEMPLATES
|
|
|
|
def test_all_templates_renderable(self):
|
|
for key, template in JOB_TEMPLATES.items():
|
|
result = template.render({"path": "/test/path"})
|
|
assert "/test/path" in result or "'/test/path'" in result
|
|
|
|
def test_no_destructive_in_phase1(self):
|
|
for key, template in JOB_TEMPLATES.items():
|
|
assert template.destructive is False, f"Template {key} is marked destructive"
|