summaryrefslogtreecommitdiffstatshomepage
path: root/tests/test_recipes.py
blob: 772833dd14a90b3963142425bf09dcf21083325e (plain) (blame)
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import json
import os
import subprocess
import tempfile
import unittest
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]


class RecipeTests(unittest.TestCase):
    def invoke(self, role, *recipes):
        with tempfile.TemporaryDirectory() as directory:
            path = Path(directory)
            commands = {
                "chezmoi": 'if [ "$1" = data ]; then printf \'%s\\n\' "$ROLE_DATA"; else echo "chezmoi $*"; fi',
                "sudo": 'echo "UNEXPECTED sudo"; exit 99',
                "flatpak": 'echo "UNEXPECTED flatpak"; exit 99',
                "pacman": 'echo "UNEXPECTED pacman"; exit 99',
            }
            for name, body in commands.items():
                executable = path / name
                executable.write_text("#!/bin/sh\n" + body + "\n")
                executable.chmod(0o755)
            return subprocess.run(
                ["just", *recipes],
                cwd=ROOT,
                env={
                    **os.environ,
                    "PATH": f"{path}:{os.environ['PATH']}",
                    "ROLE_DATA": json.dumps({"machineRole": role}),
                },
                capture_output=True,
                text=True,
                check=False,
            )

    def test_invalid_role_stops_package_commands(self):
        for recipe in ["pkg-apply", "pkg-fix", "flatpak-update"]:
            with self.subTest(recipe=recipe):
                result = self.invoke("invalid", recipe)
                self.assertNotEqual(result.returncode, 0)
                self.assertNotIn("UNEXPECTED", result.stdout)

    def test_non_host_maintenance_only_uses_chezmoi(self):
        for role in ["vm", "canonical"]:
            for recipe in ["diff", "merge", "re-add"]:
                with self.subTest(role=role, recipe=recipe):
                    result = self.invoke(role, recipe)
                    self.assertEqual(result.returncode, 0, result.stderr)
                    self.assertIn("chezmoi", result.stdout)
                    self.assertNotIn("UNEXPECTED", result.stdout)

    def test_non_host_etc_paths_fail_before_home_changes(self):
        for recipe in ["diff", "merge", "re-add"]:
            result = self.invoke("canonical", recipe, ".config/zsh", "etc/hosts")
            self.assertNotEqual(result.returncode, 0)
            self.assertNotIn("chezmoi", result.stdout)

    def test_vm_migration_initializes_role_before_switch(self):
        result = subprocess.check_output(
            ["just", "--justfile", "nix/justfile", "--dry-run", "migrate-chezmoi"],
            cwd=ROOT,
            stderr=subprocess.STDOUT,
            text=True,
        )
        self.assertLess(result.index("chezmoi init"), result.index("switch.sh"))

    def test_host_home_paths_do_not_select_etc(self):
        for recipe in ["diff", "merge", "re-add"]:
            result = self.invoke("host", recipe, ".config/zsh")
            self.assertEqual(result.returncode, 0, result.stderr)
            self.assertEqual(len(result.stdout.splitlines()), 1)
            self.assertIn(".config/zsh", result.stdout)

    def test_host_mixed_paths_are_split_by_domain(self):
        for domain, expected in [("home", ".config/zsh"), ("etc", "etc/hosts")]:
            result = subprocess.check_output(
                [
                    "bash",
                    "-c",
                    (
                        "source scripts/maintenance-lib.sh; "
                        "_machine_role() { echo host; }; "
                        '_maintenance_select auto "$1" .config/zsh etc/hosts; '
                        'printf "%s\\n" "$maintenance_run" "${args[@]}"'
                    ),
                    "test",
                    domain,
                ],
                cwd=ROOT,
                text=True,
            )
            self.assertEqual(result.splitlines(), ["true", expected])