Files
computer-playbook/tests/unit/utils/cleanup/test_databases_csv.py
T
kevinveenbirkenbachandClaude Opus 4.7 cf2a2594e5 chore(cleanup/databases_csv): drop verbose comments
Pruned per project convention "no unnecessary code comments":
- module docstring: 23 lines → 1 line (the file name + symbol already
  state intent; full incident write-up belongs in the commit log)
- wipe_database_entries docstring: 11 lines → 2 lines
- six inline rationale comments in tests/__main__ removed (test
  names already encode the intent)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 13:25:13 +02:00

187 lines
6.0 KiB
Python

"""Unit tests for `utils.cleanup.databases_csv` (databases.csv wipe helper)."""
from __future__ import annotations
import csv
import io
import unittest
from contextlib import redirect_stderr, redirect_stdout
from pathlib import Path
from tempfile import TemporaryDirectory
from utils.cleanup.databases_csv import main, wipe_database_entries
_HEADER = "instance;database;username;password\n"
class DatabasesCsvTestBase(unittest.TestCase):
def setUp(self) -> None:
self._tmp = TemporaryDirectory()
self.addCleanup(self._tmp.cleanup)
self.csv_file = Path(self._tmp.name) / "databases.csv"
def _write(self, content: str) -> None:
self.csv_file.write_text(content, encoding="utf-8")
def _read(self) -> list[list[str]]:
with self.csv_file.open(newline="", encoding="utf-8") as fh:
return list(csv.reader(fh, delimiter=";"))
class TestWipeDatabaseEntries(DatabasesCsvTestBase, unittest.TestCase):
def test_removes_matching_row_by_name(self):
self._write(
_HEADER
+ "mariadb;matomo;matomo;pw1\n"
+ "postgres;keycloak;keycloak;pw2\n"
+ "mariadb;nextcloud;nextcloud;pw3\n"
)
removed = wipe_database_entries(["web-app-matomo"], csv_file=self.csv_file)
self.assertEqual(removed, ["matomo:matomo"])
self.assertEqual(
self._read(),
[
["instance", "database", "username", "password"],
["postgres", "keycloak", "keycloak", "pw2"],
["mariadb", "nextcloud", "nextcloud", "pw3"],
],
)
def test_no_match_does_not_rewrite_file(self):
self._write(_HEADER + "postgres;keycloak;keycloak;pw2\n")
before_mtime = self.csv_file.stat().st_mtime_ns
removed = wipe_database_entries(["web-app-matomo"], csv_file=self.csv_file)
self.assertEqual(removed, [])
self.assertEqual(self.csv_file.stat().st_mtime_ns, before_mtime)
def test_missing_file_returns_empty(self):
removed = wipe_database_entries(["web-app-matomo"], csv_file=self.csv_file)
self.assertEqual(removed, [])
self.assertFalse(self.csv_file.exists())
def test_multiple_app_ids_in_one_call(self):
self._write(
_HEADER
+ "mariadb;matomo;matomo;pw1\n"
+ "postgres;keycloak;keycloak;pw2\n"
+ "mariadb;nextcloud;nextcloud;pw3\n"
)
removed = wipe_database_entries(
["web-app-matomo", "web-app-keycloak"],
csv_file=self.csv_file,
)
self.assertEqual(sorted(removed), ["keycloak:keycloak", "matomo:matomo"])
self.assertEqual(
self._read(),
[
["instance", "database", "username", "password"],
["mariadb", "nextcloud", "nextcloud", "pw3"],
],
)
def test_username_match_when_database_is_wildcard(self):
self._write(_HEADER + "mariadb;*;matomo;pw1\npostgres;*;keycloak;pw2\n")
removed = wipe_database_entries(["web-app-matomo"], csv_file=self.csv_file)
self.assertEqual(removed, ["*:matomo"])
self.assertEqual(
self._read(),
[
["instance", "database", "username", "password"],
["postgres", "*", "keycloak", "pw2"],
],
)
def test_unknown_app_id_no_op(self):
self._write(_HEADER + "mariadb;matomo;matomo;pw1\n")
removed = wipe_database_entries(
["web-app-does-not-exist"], csv_file=self.csv_file
)
self.assertEqual(removed, [])
def test_blank_lines_are_preserved(self):
self._write(
_HEADER
+ "mariadb;matomo;matomo;pw1\n"
+ "\n"
+ "postgres;keycloak;keycloak;pw2\n"
)
removed = wipe_database_entries(["web-app-matomo"], csv_file=self.csv_file)
self.assertEqual(removed, ["matomo:matomo"])
self.assertEqual(
self._read(),
[
["instance", "database", "username", "password"],
[],
["postgres", "keycloak", "keycloak", "pw2"],
],
)
def test_header_is_kept_even_when_all_data_rows_removed(self):
self._write(_HEADER + "mariadb;matomo;matomo;pw1\n")
removed = wipe_database_entries(["web-app-matomo"], csv_file=self.csv_file)
self.assertEqual(removed, ["matomo:matomo"])
self.assertEqual(
self._read(),
[["instance", "database", "username", "password"]],
)
def test_short_row_is_kept(self):
self._write(_HEADER + "garbage\nmariadb;matomo;matomo;pw1\n")
removed = wipe_database_entries(["web-app-matomo"], csv_file=self.csv_file)
self.assertEqual(removed, ["matomo:matomo"])
self.assertEqual(
self._read(),
[
["instance", "database", "username", "password"],
["garbage"],
],
)
def test_csv_without_header_is_still_processed(self):
self._write("mariadb;matomo;matomo;pw1\npostgres;keycloak;keycloak;pw2\n")
removed = wipe_database_entries(["web-app-matomo"], csv_file=self.csv_file)
self.assertEqual(removed, ["matomo:matomo"])
self.assertEqual(
self._read(),
[["postgres", "keycloak", "keycloak", "pw2"]],
)
class TestMainShim(DatabasesCsvTestBase, unittest.TestCase):
def test_no_argv_prints_usage_and_returns_2(self):
stderr = io.StringIO()
with redirect_stderr(stderr):
rc = main([])
self.assertEqual(rc, 2)
self.assertIn("usage:", stderr.getvalue())
def test_main_uses_default_path_when_no_override(self):
stdout = io.StringIO()
with redirect_stdout(stdout):
rc = main(["web-app-nonexistent"])
self.assertEqual(rc, 0)
self.assertIn("No databases.csv entries to wipe", stdout.getvalue())
if __name__ == "__main__": # pragma: no cover
unittest.main()