mirror of
https://github.com/kevinveenbirkenbach/create-linux-swapfile.git
synced 2026-08-16 20:02:47 +00:00
Turns the loose main.py into the 'swap-forge' distribution with a src layout, shipping both the swap-forge and the older swafo command. A failing swap command no longer produces a traceback: CalledProcessError is caught and reported as "'mkswap' failed with exit code 1" at exit 1, a missing binary as exit 127. Required binaries are declared per filesystem path so an ext4 host is never asked for btrfs tooling. The fstab entry is still written last, after swapon, so a failed activation leaves /etc/fstab untouched. The e2e suite proves that byte for byte across a create, a same-size rerun and a resize cycle, with real fallocate, chmod and file sizes. Adds unit, integration and container-based e2e tests, ruff and markdown/mermaid linting, CodeQL and Dependabot, and pins the core metadata to 2.4 so twine accepts the artifacts. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
63 lines
1.7 KiB
Python
63 lines
1.7 KiB
Python
import os
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[2]
|
|
SRC_DIR = REPO_ROOT / "src"
|
|
|
|
|
|
def run_cli(*args, path=None):
|
|
"""Run 'python -m swap_forge' with the working tree on PYTHONPATH.
|
|
|
|
Args:
|
|
args: Command line arguments for the CLI.
|
|
path: Replacement PATH, used to hide the findmnt binary.
|
|
"""
|
|
env = dict(os.environ)
|
|
env["PYTHONPATH"] = str(SRC_DIR)
|
|
if path is not None:
|
|
env["PATH"] = str(path)
|
|
return subprocess.run(
|
|
[sys.executable, "-m", "swap_forge", *args],
|
|
capture_output=True,
|
|
text=True,
|
|
env=env,
|
|
check=False,
|
|
)
|
|
|
|
|
|
class TestCli(unittest.TestCase):
|
|
def test_help_exits_zero(self):
|
|
result = run_cli("--help")
|
|
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
self.assertIn("Swapfile size", result.stdout)
|
|
|
|
def test_missing_size_is_rejected(self):
|
|
result = run_cli()
|
|
|
|
self.assertEqual(result.returncode, 2)
|
|
self.assertIn("size", result.stderr)
|
|
|
|
def test_missing_findmnt_fails_cleanly(self):
|
|
with tempfile.TemporaryDirectory() as empty:
|
|
result = run_cli("2048M", path=empty)
|
|
|
|
self.assertEqual(result.returncode, 127)
|
|
self.assertIn("required command 'findmnt' is not installed", result.stderr)
|
|
self.assertNotIn("Traceback", result.stderr)
|
|
|
|
def test_invalid_size_fails_without_a_traceback(self):
|
|
result = run_cli("64T")
|
|
|
|
self.assertEqual(result.returncode, 1)
|
|
self.assertIn("Invalid size format", result.stderr)
|
|
self.assertNotIn("Traceback", result.stderr)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|