aboutsummaryrefslogtreecommitdiff
path: root/tests/installer-steps/test_set_user_password.py
blob: 9f21b3ad22611f108377c6ce4d08f2ae01a073bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
"""Test that the primary user's password is set under a guard.

archsetup runs with `set -e` OFF (line 21), so an unguarded `chpasswd` that
fails silently leaves the primary user with no password and no log entry -- an
unloggable account on a fresh install. set_user_password guards the chpasswd
with error_fatal so a failure aborts loudly instead of passing unnoticed.

Method: sed-extract set_user_password from the real `archsetup`, run it with a
fake chpasswd (controlled exit) and a fake error_fatal recorder. Assert the
guard fires on failure and stays quiet on success.

Run from repo root:
    python3 -m unittest tests.installer-steps.test_set_user_password
"""

import os
import subprocess
import textwrap
import unittest

REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
ARCHSETUP = os.path.join(REPO_ROOT, "archsetup")


def run_set_password(chpasswd_rc):
    """Run set_user_password with a fake chpasswd exiting chpasswd_rc."""
    script = textwrap.dedent(f"""\
        password="hunter2"
        logfile=/dev/null
        display() {{ :; }}
        chpasswd() {{ cat >/dev/null; return {chpasswd_rc}; }}
        error_fatal() {{ echo "FATAL: $1"; exit 9; }}
        source <(sed -n '/^set_user_password() {{/,/^}}/p' "{ARCHSETUP}")
        set_user_password "alice"
        echo "REACHED-END"
    """)
    return subprocess.run(
        ["bash", "-c", script], capture_output=True, text=True, timeout=10,
    )


class SetUserPassword(unittest.TestCase):
    def test_success_does_not_abort(self):
        r = run_set_password(0)
        self.assertIn("REACHED-END", r.stdout)
        self.assertNotIn("FATAL", r.stdout)

    def test_failure_aborts_with_error_fatal(self):
        r = run_set_password(1)
        self.assertIn("FATAL: setting password for alice", r.stdout,
                      "a chpasswd failure must abort via error_fatal")
        self.assertNotIn("REACHED-END", r.stdout)


if __name__ == "__main__":
    unittest.main()