class DNFManagerReposTestCase(unittest.TestCase):
    """Test the repo abstraction of the DNF base."""
    def setUp(self):
        self.maxDiff = None
        self.dnf_manager = DNFManager()

    def _add_repo(self, repo_id):
        """Add a mocked repo with the specified id."""
        repo = Repo(repo_id, self.dnf_manager._base.conf)
        self.dnf_manager._base.repos.add(repo)
        return repo

    def _check_repo(self, repo_id, attributes):
        """Check the DNF repo configuration."""
        repo = self.dnf_manager._base.repos[repo_id]
        repo_conf = repo.dump()
        repo_conf = repo_conf.splitlines(keepends=False)

        print(repo.dump())

        for attribute in attributes:
            assert attribute in repo_conf

    def _check_content(self, repo_data, expected_content):
        """Check the generated content of the .repo file."""
        expected_content = dedent(expected_content).strip()
        content = self.dnf_manager.generate_repo_file(repo_data)
        assert content == expected_content

        expected_attrs = expected_content.splitlines(keepends=False)
        self.dnf_manager.add_repository(repo_data)
        self._check_repo(repo_data.name, expected_attrs)

    def test_repositories(self):
        """Test the repositories property."""
        assert self.dnf_manager.repositories == []

        self._add_repo("r1")
        self._add_repo("r2")
        self._add_repo("r3")

        assert self.dnf_manager.repositories == ["r1", "r2", "r3"]

    def test_enabled_repositories(self):
        """Test the enabled_repositories property."""
        assert self.dnf_manager.enabled_repositories == []

        self._add_repo("r1").disable()
        self._add_repo("r2").enable()
        self._add_repo("r3").disable()
        self._add_repo("r4").enable()

        assert self.dnf_manager.enabled_repositories == ["r2", "r4"]

    def test_set_repository_enabled(self):
        """Test the set_repository_enabled function."""
        self._add_repo("r1")

        self.dnf_manager.set_repository_enabled("r1", True)
        assert "r1" in self.dnf_manager.enabled_repositories

        self.dnf_manager.set_repository_enabled("r1", False)
        assert "r1" not in self.dnf_manager.enabled_repositories

        with pytest.raises(UnknownRepositoryError):
            self.dnf_manager.set_repository_enabled("r2", True)

    def test_add_repository_default(self):
        """Test the add_repository method with defaults."""
        data = RepoConfigurationData()
        data.name = "r1"

        self.dnf_manager.add_repository(data)

        self._check_repo("r1", [
            "baseurl = ",
            "proxy = ",
            "sslverify = 1",
            "sslcacert = ",
            "sslclientcert = ",
            "sslclientkey = ",
            "cost = 1000",
            "includepkgs = ",
            "excludepkgs = ",
        ])

    def test_add_repository_enabled(self):
        """Test the add_repository method with enabled repo."""
        data = RepoConfigurationData()
        data.name = "r1"
        data.enabled = True

        self.dnf_manager.add_repository(data)

        self._check_repo("r1", [
            "enabled = 1",
        ])

    def test_add_repository_disabled(self):
        """Test the add_repository method with disabled repo."""
        data = RepoConfigurationData()
        data.name = "r1"
        data.enabled = False

        self.dnf_manager.add_repository(data)

        self._check_repo("r1", [
            "enabled = 0",
        ])

    def test_add_repository_baseurl(self):
        """Test the add_repository method with baseurl."""
        data = RepoConfigurationData()
        data.name = "r1"
        data.type = URL_TYPE_BASEURL
        data.url = "http://repo"

        self.dnf_manager.add_repository(data)

        self._check_repo("r1", [
            "baseurl = http://repo",
        ])

    def test_add_repository_mirrorlist(self):
        """Test the add_repository method with mirrorlist."""
        data = RepoConfigurationData()
        data.name = "r1"
        data.type = URL_TYPE_MIRRORLIST
        data.url = "http://mirror"

        self.dnf_manager.add_repository(data)
        self._check_repo("r1", [
            "mirrorlist = http://mirror",
        ])

    def test_add_repository_metalink(self):
        """Test the add_repository method with metalink."""
        data = RepoConfigurationData()
        data.name = "r1"
        data.type = URL_TYPE_METALINK
        data.url = "http://metalink"

        self.dnf_manager.add_repository(data)
        self._check_repo("r1", [
            "metalink = http://metalink",
        ])

    def test_add_repository_no_ssl_configuration(self):
        """Test the add_repository method without the ssl configuration."""
        data = RepoConfigurationData()
        data.name = "r1"
        data.ssl_verification_enabled = False

        self.dnf_manager.add_repository(data)
        self._check_repo("r1", [
            "sslverify = 0",
        ])

    def test_add_repository_ssl_configuration(self):
        """Test the add_repository method with the ssl configuration."""
        data = RepoConfigurationData()
        data.name = "r1"
        data.ssl_verification_enabled = True
        data.ssl_configuration.ca_cert_path = "file:///ca-cert"
        data.ssl_configuration.client_cert_path = "file:///client-cert"
        data.ssl_configuration.client_key_path = "file:///client-key"

        self.dnf_manager.add_repository(data)
        self._check_repo("r1", [
            "sslverify = 1",
            "sslcacert = file:///ca-cert",
            "sslclientcert = file:///client-cert",
            "sslclientkey = file:///client-key",
        ])

    def test_add_repository_invalid_proxy(self):
        """Test the add_repository method the invalid proxy configuration."""
        data = RepoConfigurationData()
        data.name = "r1"
        data.proxy = "@:/invalid"

        self.dnf_manager.add_repository(data)
        self._check_repo("r1", [
            "proxy = ",
        ])

    def test_add_repository_no_auth_proxy(self):
        """Test the add_repository method the no auth proxy configuration."""
        data = RepoConfigurationData()
        data.name = "r1"
        data.proxy = "http://example.com:1234"

        self.dnf_manager.add_repository(data)
        self._check_repo("r1", [
            "proxy = http://example.com:1234",
        ])

    def test_add_repository_proxy(self):
        """Test the add_repository method with the proxy configuration."""
        data = RepoConfigurationData()
        data.name = "r1"
        data.proxy = "http://*****:*****@example.com:1234"

        self.dnf_manager.add_repository(data)
        self._check_repo("r1", [
            "proxy = http://example.com:1234",
            "proxy_username = user",
            "proxy_password = pass",
        ])

    def test_add_repository_cost(self):
        """Test the add_repository method with a cost."""
        data = RepoConfigurationData()
        data.name = "r1"
        data.cost = 256

        self.dnf_manager.add_repository(data)
        self._check_repo("r1", ["cost = 256"])

    def test_add_repository_packages(self):
        """Test the add_repository method with packages."""
        data = RepoConfigurationData()
        data.name = "r1"
        data.included_packages = ["p1", "p2"]
        data.excluded_packages = ["p3", "p4"]

        self.dnf_manager.add_repository(data)
        self._check_repo("r1", [
            "includepkgs = p1, p2",
            "excludepkgs = p3, p4",
        ])

    def test_add_repository_replace(self):
        """Test the add_repository method with a replacement."""
        data = RepoConfigurationData()
        data.name = "r1"
        data.url = "http://u1"

        self.dnf_manager.add_repository(data)
        self._check_repo("r1", [
            "baseurl = http://u1",
        ])

        data.url = "http://u2"

        self.dnf_manager.add_repository(data)
        self._check_repo("r1", [
            "baseurl = http://u2",
        ])

    def test_generate_repo_file_baseurl(self):
        """Test the generate_repo_file method with baseurl."""
        data = RepoConfigurationData()
        data.name = "r1"
        data.type = URL_TYPE_BASEURL
        data.url = "http://repo"
        data.proxy = "http://example.com:1234"
        data.cost = 256

        self._check_content(
            data, """
            [r1]
            name = r1
            enabled = 1
            baseurl = http://repo
            proxy = http://example.com:1234
            cost = 256
            """)

    def test_generate_repo_file_mirrorlist(self):
        """Test the generate_repo_file method with mirrorlist."""
        data = RepoConfigurationData()
        data.name = "r1"
        data.type = URL_TYPE_MIRRORLIST
        data.url = "http://mirror"
        data.ssl_verification_enabled = False
        data.proxy = "http://*****:*****@example.com:1234"

        self._check_content(
            data, """
            [r1]
            name = r1
            enabled = 1
            mirrorlist = http://mirror
            sslverify = 0
            proxy = http://example.com:1234
            proxy_username = user
            proxy_password = pass
            """)

    def test_generate_repo_file_metalink(self):
        """Test the generate_repo_file method with metalink."""
        data = RepoConfigurationData()
        data.name = "r1"
        data.enabled = False
        data.type = URL_TYPE_METALINK
        data.url = "http://metalink"
        data.included_packages = ["p1", "p2"]
        data.excluded_packages = ["p3", "p4"]

        self._check_content(
            data, """
            [r1]
            name = r1
            enabled = 0
            metalink = http://metalink
            includepkgs = p1, p2
            excludepkgs = p3, p4
            """)

    def test_load_repository_unknown(self):
        """Test the load_repository method with an unknown repo."""
        with pytest.raises(UnknownRepositoryError):
            self.dnf_manager.load_repository("r1")

    def test_load_repository_failed(self):
        """Test the load_repository method with a failure."""
        repo = self._add_repo("r1")
        repo.load = Mock(side_effect=RepoError("Fake error!"))

        with pytest.raises(MetadataError) as cm:
            self.dnf_manager.load_repository("r1")

        repo.load.assert_called_once()
        assert repo.enabled is False
        assert str(cm.value) == "Fake error!"

    def test_load_repository(self):
        """Test the load_repository method."""
        repo = self._add_repo("r1")
        repo.load = Mock()

        self.dnf_manager.load_repository("r1")

        repo.load.assert_called_once()
        assert repo.enabled is True

    def _create_repo(self, repo, repo_dir):
        """Generate fake metadata for the repo."""
        # Create the repodata directory.
        os.makedirs(os.path.join(repo_dir, "repodata"))

        # Create the repomd.xml file.
        md_path = os.path.join(repo_dir, "repodata", "repomd.xml")
        md_content = "Metadata for {}.".format(repo.id)

        with open(md_path, 'w') as f:
            f.write(md_content)

        # Set up the baseurl.
        repo.baseurl.append("file://" + repo_dir)

    def test_load_no_repomd_hashes(self):
        """Test the load_repomd_hashes method with no repositories."""
        self.dnf_manager.load_repomd_hashes()
        assert self.dnf_manager._md_hashes == {}

    def test_load_one_repomd_hash(self):
        """Test the load_repomd_hashes method with one repository."""
        with TemporaryDirectory() as d:
            r1 = self._add_repo("r1")
            self._create_repo(r1, d)

            self.dnf_manager.load_repomd_hashes()
            assert self.dnf_manager._md_hashes == {
                'r1':
                b"\x90\xa0\xb7\xce\xc2H\x85#\xa3\xfci"
                b"\x9e+\xf4\xe2\x19D\xbc\x9b'\xeb\xb7"
                b"\x90\x1d\xcey\xb3\xd4p\xc3\x1d\xfb",
            }

    def test_load_repomd_hashes(self):
        """Test the load_repomd_hashes method."""
        with TemporaryDirectory() as d:
            r1 = self._add_repo("r1")
            r1.baseurl = [
                "file://nonexistent/1",
                "file://nonexistent/2",
                "file://nonexistent/3",
            ]
            self._create_repo(r1, d + "/r1")

            r2 = self._add_repo("r2")
            r2.baseurl = [
                "file://nonexistent/1",
                "file://nonexistent/2",
                "file://nonexistent/3",
            ]

            r3 = self._add_repo("r3")
            r3.metalink = "file://metalink"

            r4 = self._add_repo("r4")
            r4.mirrorlist = "file://mirrorlist"

            self.dnf_manager.load_repomd_hashes()

            assert self.dnf_manager._md_hashes == {
                'r1':
                b"\x90\xa0\xb7\xce\xc2H\x85#\xa3\xfci"
                b"\x9e+\xf4\xe2\x19D\xbc\x9b'\xeb\xb7"
                b"\x90\x1d\xcey\xb3\xd4p\xc3\x1d\xfb",
                'r2':
                None,
                'r3':
                None,
                'r4':
                None,
            }

    def test_verify_repomd_hashes(self):
        """Test the verify_repomd_hashes method."""
        with TemporaryDirectory() as d:
            # Test no repository.
            assert self.dnf_manager.verify_repomd_hashes() is False

            # Create a repository.
            r = self._add_repo("r1")
            self._create_repo(r, d)

            # Test no loaded repository.
            assert self.dnf_manager.verify_repomd_hashes() is False

            # Test a loaded repository.
            self.dnf_manager.load_repomd_hashes()
            assert self.dnf_manager.verify_repomd_hashes() is True

            # Test a different content of metadata.
            with open(os.path.join(d, "repodata", "repomd.xml"), 'w') as f:
                f.write("Different metadata for r1.")

            assert self.dnf_manager.verify_repomd_hashes() is False

            # Test a reloaded repository.
            self.dnf_manager.load_repomd_hashes()
            assert self.dnf_manager.verify_repomd_hashes() is True

            # Test the base reset.
            self.dnf_manager.reset_base()
            assert self.dnf_manager.verify_repomd_hashes() is False
示例#2
0
class DNFManagerReposTestCase(unittest.TestCase):
    """Test the repo abstraction of the DNF base."""

    def setUp(self):
        self.maxDiff = None
        self.dnf_manager = DNFManager()

    def _add_repo(self, repo_id):
        """Add a mocked repo with the specified id."""
        repo = Repo(repo_id, self.dnf_manager._base.conf)
        self.dnf_manager._base.repos.add(repo)
        return repo

    def test_repositories(self):
        """Test the repositories property."""
        assert self.dnf_manager.repositories == []

        self._add_repo("r1")
        self._add_repo("r2")
        self._add_repo("r3")

        assert self.dnf_manager.repositories == ["r1", "r2", "r3"]

    def test_load_repository_unknown(self):
        """Test the load_repository method with an unknown repo."""
        with pytest.raises(UnknownRepositoryError):
            self.dnf_manager.load_repository("r1")

    def test_load_repository_failed(self):
        """Test the load_repository method with a failure."""
        repo = self._add_repo("r1")
        repo.load = Mock(side_effect=RepoError("Fake error!"))

        with pytest.raises(MetadataError) as cm:
            self.dnf_manager.load_repository("r1")

        repo.load.assert_called_once()
        assert repo.enabled is False
        assert str(cm.value) == "Fake error!"

    def test_load_repository(self):
        """Test the load_repository method."""
        repo = self._add_repo("r1")
        repo.load = Mock()

        self.dnf_manager.load_repository("r1")

        repo.load.assert_called_once()
        assert repo.enabled is True

    def _create_repo(self, repo, repo_dir):
        """Generate fake metadata for the repo."""
        # Create the repodata directory.
        os.makedirs(os.path.join(repo_dir, "repodata"))

        # Create the repomd.xml file.
        md_path = os.path.join(repo_dir, "repodata", "repomd.xml")
        md_content = "Metadata for {}.".format(repo.id)

        with open(md_path, 'w') as f:
            f.write(md_content)

        # Set up the baseurl.
        repo.baseurl.append("file://" + repo_dir)

    def test_load_no_repomd_hashes(self):
        """Test the load_repomd_hashes method with no repositories."""
        self.dnf_manager.load_repomd_hashes()
        assert self.dnf_manager._md_hashes == {}

    def test_load_one_repomd_hash(self):
        """Test the load_repomd_hashes method with one repository."""
        with TemporaryDirectory() as d:
            r1 = self._add_repo("r1")
            self._create_repo(r1, d)

            self.dnf_manager.load_repomd_hashes()
            assert self.dnf_manager._md_hashes == {
                'r1': b"\x90\xa0\xb7\xce\xc2H\x85#\xa3\xfci"
                      b"\x9e+\xf4\xe2\x19D\xbc\x9b'\xeb\xb7"
                      b"\x90\x1d\xcey\xb3\xd4p\xc3\x1d\xfb",
            }

    def test_load_repomd_hashes(self):
        """Test the load_repomd_hashes method."""
        with TemporaryDirectory() as d:
            r1 = self._add_repo("r1")
            r1.baseurl = [
                "file://nonexistent/1",
                "file://nonexistent/2",
                "file://nonexistent/3",
            ]
            self._create_repo(r1, d + "/r1")

            r2 = self._add_repo("r2")
            r2.baseurl = [
                "file://nonexistent/1",
                "file://nonexistent/2",
                "file://nonexistent/3",
            ]

            r3 = self._add_repo("r3")
            r3.metalink = "file://metalink"

            r4 = self._add_repo("r4")
            r4.mirrorlist = "file://mirrorlist"

            self.dnf_manager.load_repomd_hashes()

            assert self.dnf_manager._md_hashes == {
                'r1': b"\x90\xa0\xb7\xce\xc2H\x85#\xa3\xfci"
                      b"\x9e+\xf4\xe2\x19D\xbc\x9b'\xeb\xb7"
                      b"\x90\x1d\xcey\xb3\xd4p\xc3\x1d\xfb",
                'r2': None,
                'r3': None,
                'r4': None,
            }

    def test_verify_repomd_hashes(self):
        """Test the verify_repomd_hashes method."""
        with TemporaryDirectory() as d:
            # Test no repository.
            assert self.dnf_manager.verify_repomd_hashes() is False

            # Create a repository.
            r = self._add_repo("r1")
            self._create_repo(r, d)

            # Test no loaded repository.
            assert self.dnf_manager.verify_repomd_hashes() is False

            # Test a loaded repository.
            self.dnf_manager.load_repomd_hashes()
            assert self.dnf_manager.verify_repomd_hashes() is True

            # Test a different content of metadata.
            with open(os.path.join(d, "repodata", "repomd.xml"), 'w') as f:
                f.write("Different metadata for r1.")

            assert self.dnf_manager.verify_repomd_hashes() is False

            # Test a reloaded repository.
            self.dnf_manager.load_repomd_hashes()
            assert self.dnf_manager.verify_repomd_hashes() is True

            # Test the base reset.
            self.dnf_manager.reset_base()
            assert self.dnf_manager.verify_repomd_hashes() is False