File: test_main.py

package info (click to toggle)
bdebstrap 0.7.0-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 312 kB
  • sloc: python: 1,736; sh: 125; makefile: 4
file content (120 lines) | stat: -rw-r--r-- 5,419 bytes parent folder | download
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# Copyright (C) 2021-2022 Benjamin Drung <bdrung@posteo.de>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""Test main function of bdebstrap."""

import os
import subprocess
import unittest
import unittest.mock

from bdebstrap import OUTPUT_DIR, main

EXAMPLE_CONFIG_DIR = os.path.join(os.path.dirname(__file__), "..", "examples")


def default_hooks(output_dir: str) -> list[str]:
    """Return the list of default hooks."""
    return [
        f'--essential-hook=mkdir -p "$1{OUTPUT_DIR}"',
        "--customize-hook=chroot \"$1\" dpkg-query -f='${Package}\\t${Version}\\n' -W "
        f'> "$1{OUTPUT_DIR}/manifest"',
        f'--customize-hook=sync-out "{OUTPUT_DIR}" "{output_dir}"',
        f'--customize-hook=rm -rf "$1{OUTPUT_DIR}"',
    ]


class TestMain(unittest.TestCase):
    """
    This unittest class tests the main function.
    """

    @unittest.mock.patch("bdebstrap.Config.save")
    @unittest.mock.patch("bdebstrap.prepare_output_dir")
    @unittest.mock.patch("bdebstrap.Mmdebstrap.call")
    def test_debian_example(
        self,
        mmdebstrap_call_mock: unittest.mock.MagicMock,
        prepare_output_dir_mock: unittest.mock.MagicMock,
        config_save_mock: unittest.mock.MagicMock,
    ) -> None:
        """Test Debian unstable example."""
        args = [
            "-c",
            os.path.join(EXAMPLE_CONFIG_DIR, "Debian-unstable.yaml"),
            "--name",
            "Debian-unstable",
        ]
        with self.assertLogs("bdebstrap", level="INFO") as context_manager:
            self.assertEqual(main(args), 0)
            self.assertIn("Execution time", context_manager.output[-1])
        config_save_mock.assert_called_once_with("./Debian-unstable/config.yaml", False)
        mmdebstrap_call_mock.assert_called_once_with("./Debian-unstable", False)
        prepare_output_dir_mock.assert_called_once_with("./Debian-unstable", False, False)

    @unittest.mock.patch("bdebstrap.Config.save")
    @unittest.mock.patch("bdebstrap.prepare_output_dir")
    @unittest.mock.patch("bdebstrap.Mmdebstrap.call")
    def test_failed_mmdebstrap(
        self,
        mmdebstrap_call_mock: unittest.mock.MagicMock,
        prepare_output_dir_mock: unittest.mock.MagicMock,
        config_save_mock: unittest.mock.MagicMock,
    ) -> None:
        """Test failure of mmdebstrap call."""
        mmdebstrap_call_mock.side_effect = subprocess.CalledProcessError(42, "mmdebstrap")
        args = ["-c", os.path.join(EXAMPLE_CONFIG_DIR, "Debian-unstable.yaml"), "--name", "foobar"]
        with self.assertLogs("bdebstrap", level="ERROR") as context_manager:
            self.assertEqual(main(args), 1)
            self.assertEqual(
                ["ERROR:bdebstrap:mmdebstrap failed with exit code 42. See above for details."],
                context_manager.output,
            )
        config_save_mock.assert_called_once_with("./foobar/config.yaml", False)
        mmdebstrap_call_mock.assert_called_once_with("./foobar", False)
        prepare_output_dir_mock.assert_called_once_with("./foobar", False, False)

    @unittest.mock.patch("bdebstrap.Config.save")
    @unittest.mock.patch("bdebstrap.prepare_output_dir")
    @unittest.mock.patch("bdebstrap.Mmdebstrap.call")
    def test_empty_target(
        self,
        mmdebstrap_call_mock: unittest.mock.MagicMock,
        prepare_output_dir_mock: unittest.mock.MagicMock,
        config_save_mock: unittest.mock.MagicMock,
    ) -> None:
        """Test keeping target empty."""
        with self.assertLogs("bdebstrap", level="INFO"):
            self.assertEqual(main(["--name", "empty-target", "unstable"]), 0)
        config_save_mock.assert_called_once_with("./empty-target/config.yaml", False)
        mmdebstrap_call_mock.assert_called_once_with("./empty-target", False)
        prepare_output_dir_mock.assert_called_once_with("./empty-target", False, False)

    @unittest.mock.patch("bdebstrap.Config.save")
    @unittest.mock.patch("bdebstrap.prepare_output_dir")
    @unittest.mock.patch("subprocess.check_call")
    def test_minus_target(
        self,
        check_call_mock: unittest.mock.MagicMock,
        prepare_output_dir_mock: unittest.mock.MagicMock,
        config_save_mock: unittest.mock.MagicMock,
    ) -> None:
        """Test --target=-."""
        with self.assertLogs("bdebstrap", level="INFO"):
            self.assertEqual(main(["--target=-", "--name", "minus-target", "unstable"]), 0)
        check_call_mock.assert_called_once_with(
            ["mmdebstrap", "-v"] + default_hooks("./minus-target") + ["unstable", "-"]
        )
        config_save_mock.assert_called_once_with("./minus-target/config.yaml", False)
        prepare_output_dir_mock.assert_called_once_with("./minus-target", False, False)