summaryrefslogtreecommitdiff
path: root/tests/unittests/test_apport.py
blob: c731a30abd415e01b3f8b516b31680c666ddee97 (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
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
import os

import pytest

from tests.unittests.helpers import mock

M_PATH = "cloudinit.apport."


@pytest.fixture()
def apport(request, mocker, paths):
    """Mock apport.hookutils before importing cloudinit.apport.

    This avoids our optional import dependency on apport, providing tests with
    mocked apport.hookutils function call counts.
    """
    m_hookutils = mock.Mock()
    mocker.patch.dict("sys.modules", {"apport.hookutils": m_hookutils})
    mocker.patch(M_PATH + "read_cfg_paths", return_value=paths)
    from cloudinit import apport

    yield apport


class TestApport:
    @pytest.mark.parametrize(
        "instance_data,choice_idx,expected_report",
        (
            pytest.param(
                '{"v1": {"cloud_name": "mycloud"}}',
                None,
                {},
                id="v1_cloud_name_exists",
            ),
            pytest.param(
                '{"v1": {"cloud_id": "invalid"}}',
                1,
                {"CloudName": "Azure"},
                id="v1_no_cloud_name_present",
            ),
            pytest.param("{}", 0, {"CloudName": "AliYun"}, id="no_v1_key"),
            pytest.param(
                "{", 22, {"CloudName": "Oracle"}, id="not_valid_json"
            ),
        ),
    )
    def test_attach_cloud_info(
        self, instance_data, choice_idx, expected_report, apport, paths
    ):
        """Prompt for cloud name when instance-data.json is not-json/absent."""

        instance_data_file = paths.get_runpath("instance_data")
        if instance_data is None:
            assert not os.path.exists(instance_data_file)
        else:
            with open(instance_data_file, "w") as stream:
                stream.write(instance_data)
        ui = mock.Mock()
        ui.yesno.return_value = True
        ui.choice.return_value = (choice_idx, "")
        report = {}
        apport.attach_cloud_info(report, ui)
        if choice_idx is not None:
            assert ui.choice.call_count == 1
            assert report["CloudName"] == apport.KNOWN_CLOUD_NAMES[choice_idx]
        else:
            assert ui.choice.call_count == 0

    def test_attach_user_data(self, apport, paths):
        user_data_file = paths.get_ipath_cur("userdata_raw")
        ui = mock.Mock()
        ui.yesno.return_value = True
        report = object()
        apport.attach_user_data(report, ui)
        assert [
            mock.call(report, user_data_file, "user_data.txt"),
        ] == apport.attach_file.call_args_list
        assert [
            mock.call(
                report,
                "/var/log/installer/autoinstall-user-data",
                "AutoInstallUserData",
            ),
            mock.call(report, "/autoinstall.yaml", "AutoInstallYAML"),
            mock.call(
                report,
                "/etc/cloud/cloud.cfg.d/99-installer.cfg",
                "InstallerCloudCfg",
            ),
        ] == apport.attach_file_if_exists.call_args_list

    @pytest.mark.parametrize(
        "report,tags",
        (
            ({"Irrelevant": "."}, ""),
            ({"UdiLog": "."}, "ubuntu-desktop-installer"),
            ({"CurtinError": ".", "SubiquityLog": "."}, "curtin subiquity"),
            (
                {
                    "UdiLog": ".",
                    "JournalErrors": "...Breaking ordering cycle...",
                },
                "systemd-ordering ubuntu-desktop-installer",
            ),
        ),
    )
    def test_add_bug_tags_assigns_proper_tags(self, report, tags, apport):
        """Tags are assigned based on non-empty project report key values."""

        apport.add_bug_tags(report)
        assert report.get("Tags", "") == tags