def setup(self):
        self.context_manager_mock = mock.Mock()
        self.file_mock = mock.Mock()
        self.enter_mock = mock.Mock()
        self.exit_mock = mock.Mock()
        self.enter_mock.return_value = self.file_mock
        setattr(self.context_manager_mock, '__enter__', self.enter_mock)
        setattr(self.context_manager_mock, '__exit__', self.exit_mock)

        self.uri = mock.Mock()

        self.solver = SolverRepositoryBase(self.uri)
    def setup(self):
        self.context_manager_mock = mock.Mock()
        self.file_mock = mock.Mock()
        self.enter_mock = mock.Mock()
        self.exit_mock = mock.Mock()
        self.enter_mock.return_value = self.file_mock
        setattr(self.context_manager_mock, '__enter__', self.enter_mock)
        setattr(self.context_manager_mock, '__exit__', self.exit_mock)

        self.uri = mock.Mock()

        self.solver = SolverRepositoryBase(self.uri)
示例#3
0
 def _setup_solver(self):
     solver = Sat()
     for xml_repo in self.xml_state.get_repository_sections_used_for_build(
     ):
         repo_source = xml_repo.get_source().get_path()
         repo_sourcetype = xml_repo.get_sourcetype() or ''
         repo_user = xml_repo.get_username()
         repo_secret = xml_repo.get_password()
         repo_type = xml_repo.get_type()
         repo_dist = xml_repo.get_distribution()
         repo_components = xml_repo.get_components()
         if not repo_type:
             repo_type = SolverRepositoryBase(
                 Uri(uri=repo_source, source_type=repo_sourcetype),
                 repo_user, repo_secret).get_repo_type()
         if repo_type == 'apt-deb':
             # Debian based repos can be setup for a specific
             # distribution including a list of individual components.
             # For each component of the selected distribution extra
             # repository metadata exists. In such a case we iterate
             # over the configured dist components and add them as
             # repository each.
             dist_type = solver.set_dist_type('deb')
             if repo_components and repo_dist:
                 for component in repo_components.split():
                     repo_source_for_component = os.sep.join([
                         repo_source.rstrip(os.sep), 'dists', repo_dist,
                         component, f'binary-{dist_type.get("arch")}'
                     ])
                     solver.add_repository(
                         SolverRepository.new(
                             Uri(repo_source_for_component, repo_type,
                                 repo_sourcetype), repo_user, repo_secret))
                 continue
         solver.add_repository(
             SolverRepository.new(
                 Uri(repo_source, repo_type, repo_sourcetype), repo_user,
                 repo_secret))
     return solver
示例#4
0
    def add_obs_repositories(
            self,
            xml_state: XMLState,
            profile: Optional[str] = None,
            arch: str = 'x86_64',
            repo: str = 'images') -> Dict[str, obs_repo_status_type]:
        """
        Add repositories from the obs project to the provided XMLState

        :param XMLState xml_state: XMLState object reference
        :param str arch: OBS architecture, defaults to: 'x86_64'
        :param str repo:
            OBS image package build repository name, defaults to: 'images'
        """
        repository_status_report: Dict[str, obs_repo_status_type] = {}
        if not OBS._delete_obsrepositories_placeholder_repo(xml_state):
            # The repo list does not contain the obsrepositories flag
            # Therefore it's not needed to look for repos in the OBS
            # project configuration
            return repository_status_report

        package_name = self.package if not profile \
            else f'{self.package}:{profile}'
        log.info(f'Using OBS repositories from {self.project}/{package_name}')
        buildinfo_link = os.sep.join([
            self.api_server, 'build', self.project, repo, arch, package_name,
            '_buildinfo'
        ])
        request = self._create_request(buildinfo_link)
        buildinfo_xml_tree = OBS._import_xml_request(request)
        repo_paths = buildinfo_xml_tree.getroot().xpath('/buildinfo/path')
        if not repo_paths:
            raise KiwiOBSPluginBuildInfoError(
                f'OBS buildinfo for {package_name} has no repo paths')
        repo_prio_ascending = 0
        repo_prio_descending = 501
        repo_alias = None
        for repo_path in repo_paths:
            repo_url = repo_path.get('url')
            if not repo_url:
                repo_url = 'obs://{0}/{1}'.format(repo_path.get('project'),
                                                  repo_path.get('repository'))
            if repo_url:
                try:
                    repo_uri = Uri(repo_url)
                    repo_url = repo_uri.translate(
                        check_build_environment=False)
                    request = requests.get(repo_url)
                    request.raise_for_status()
                except Exception as issue:
                    repository_status_report[repo_url] = obs_repo_status_type(
                        flag='unreachable', message=f'ignored:{issue}')
                    continue

                repo_check = SolverRepositoryBase(repo_uri)
                repo_type = repo_check.get_repo_type()
                if not repo_type:
                    repository_status_report[repo_url] = obs_repo_status_type(
                        flag='repo_type_unknown',
                        message='ignored:Unknown repository type')
                    continue

                if repo_type == 'rpm-md':
                    repo_prio_ascending += 1
                    repo_prio = repo_prio_ascending
                else:
                    repo_prio_descending -= 1
                    repo_prio = repo_prio_descending

                repository_status_report[repo_url] = obs_repo_status_type(
                    flag='ok', message='imported')
                xml_state.add_repository(repo_url, repo_type, repo_alias,
                                         f'{repo_prio}')
        return repository_status_report
class TestSolverRepositoryBase:
    def setup(self):
        self.context_manager_mock = mock.Mock()
        self.file_mock = mock.Mock()
        self.enter_mock = mock.Mock()
        self.exit_mock = mock.Mock()
        self.enter_mock.return_value = self.file_mock
        setattr(self.context_manager_mock, '__enter__', self.enter_mock)
        setattr(self.context_manager_mock, '__exit__', self.exit_mock)

        self.uri = mock.Mock()

        self.solver = SolverRepositoryBase(self.uri)

    @raises(NotImplementedError)
    def test__setup_repository_metadata(self):
        self.solver._setup_repository_metadata()

    def test__get_repomd_xpath(self):
        xml_data = etree.parse('../data/repomd.xml')
        assert self.solver._get_repomd_xpath(
            xml_data, 'repo:data[@type="primary"]/repo:location')[0].get(
                'href') == 'repodata/55f95a93-primary.xml.gz'

    @patch('kiwi.solver.repository.base.NamedTemporaryFile')
    @patch.object(SolverRepositoryBase, 'download_from_repository')
    @patch('lxml.etree.parse')
    def test__get_repomd_xml(self, mock_parse, mock_download, mock_tmpfile):
        tmpfile = mock.Mock()
        tmpfile.name = 'tmpfile'
        xml_data = mock.Mock()
        mock_parse.return_value = xml_data
        mock_tmpfile.return_value = tmpfile
        assert self.solver._get_repomd_xml() == xml_data
        mock_download.assert_called_once_with('repodata/repomd.xml', 'tmpfile')
        mock_parse.assert_called_once_with('tmpfile')

    @patch('kiwi.solver.repository.base.mkdtemp')
    def test__create_temporary_metadata_dir(self, mock_mkdtemp):
        mock_mkdtemp.return_value = 'tmpdir'
        self.solver._create_temporary_metadata_dir()
        assert self.solver.repository_metadata_dirs == ['tmpdir']
        mock_mkdtemp.assert_called_once_with(prefix='metadata_dir.')

    @patch_open
    @patch('os.path.exists')
    def test_is_uptodate_static_time(self, mock_exists, mock_open):
        mock_exists.return_value = True
        mock_open.return_value = self.context_manager_mock
        self.file_mock.read.return_value = 'static'
        self.uri.alias.return_value = 'repo-alias'
        assert self.solver.is_uptodate() is False
        mock_open.assert_called_once_with(
            '/var/tmp/kiwi/satsolver/repo-alias.timestamp')

    @patch_open
    @patch('os.path.exists')
    @patch('kiwi.solver.repository.base.SolverRepositoryBase.timestamp')
    def test_is_uptodate_some_time(self, mock_timestamp, mock_exists,
                                   mock_open):
        mock_exists.return_value = True
        mock_open.return_value = self.context_manager_mock
        self.file_mock.read.return_value = 'some-time'
        mock_timestamp.return_value = 'some-time'
        self.uri.alias.return_value = 'repo-alias'
        assert self.solver.is_uptodate() is True
        mock_open.assert_called_once_with(
            '/var/tmp/kiwi/satsolver/repo-alias.timestamp')

    def test_timestamp(self):
        assert self.solver.timestamp() == 'static'

    @patch('kiwi.solver.repository.base.urlopen')
    @patch('kiwi.solver.repository.base.Request')
    @patch_open
    def test_download_from_repository_with_credentials(self, mock_open,
                                                       mock_request,
                                                       mock_urlopen):
        request = mock.Mock()
        mock_request.return_value = request
        location = mock.Mock()
        location.read.return_value = 'data-from-network'
        mock_urlopen.return_value = location
        mock_open.return_value = self.context_manager_mock
        self.uri.is_remote.return_value = True
        self.uri.translate.return_value = 'http://myrepo/file'
        self.solver.user = '******'
        self.solver.secret = 'secret'
        self.solver.download_from_repository('repodata/file', 'target-file')
        mock_urlopen.assert_called_once_with(request)
        mock_request.assert_called_once_with(
            'http://myrepo/file/repodata/file')
        request.add_header.assert_called_once_with('Authorization',
                                                   b'Basic dXNlcjpzZWNyZXQ=')
        mock_open.assert_called_once_with('target-file', 'wb')
        self.file_mock.write.assert_called_once_with('data-from-network')

    @patch('kiwi.solver.repository.base.urlopen')
    @patch('kiwi.solver.repository.base.Request')
    @patch_open
    def test_download_from_repository_remote(self, mock_open, mock_request,
                                             mock_urlopen):
        request = mock.Mock()
        mock_request.return_value = request
        location = mock.Mock()
        location.read.return_value = 'data-from-network'
        mock_urlopen.return_value = location
        mock_open.return_value = self.context_manager_mock
        self.uri.is_remote.return_value = True
        self.uri.translate.return_value = 'http://myrepo/file'
        self.solver.download_from_repository('repodata/file', 'target-file')
        mock_urlopen.assert_called_once_with(request)
        mock_request.assert_called_once_with(
            'http://myrepo/file/repodata/file')
        mock_open.assert_called_once_with('target-file', 'wb')
        self.file_mock.write.assert_called_once_with('data-from-network')

    @patch('kiwi.solver.repository.base.urlopen')
    @patch('kiwi.solver.repository.base.Request')
    @patch_open
    def test_download_from_repository_local(self, mock_open, mock_request,
                                            mock_urlopen):
        request = mock.Mock()
        mock_request.return_value = request
        location = mock.Mock()
        location.read.return_value = 'data'
        mock_urlopen.return_value = location
        mock_open.return_value = self.context_manager_mock
        self.uri.is_remote.return_value = False
        self.uri.translate.return_value = '/my_local_repo/file'
        self.solver.download_from_repository('repodata/file', 'target-file')
        mock_urlopen.assert_called_once_with(request)
        mock_request.assert_called_once_with(
            'file:///my_local_repo/file/repodata/file')
        mock_open.assert_called_once_with('target-file', 'wb')
        self.file_mock.write.assert_called_once_with('data')

    @patch('kiwi.solver.repository.base.urlopen')
    @raises(KiwiUriOpenError)
    def test_download_from_repository_raises(self, mock_urlopen):
        self.uri.is_remote.return_value = False
        self.uri.translate.return_value = '/my_local_repo/file'
        mock_urlopen.side_effect = Exception
        self.solver.download_from_repository('repodata/file', 'target-file')

    @patch('kiwi.solver.repository.base.mkdtemp')
    @patch('kiwi.solver.repository.base.random.randrange')
    @patch('kiwi.solver.repository.base.Command.run')
    def test__create_solvables_rpms2_solv(self, mock_command, mock_rand,
                                          mock_mkdtemp):
        mock_rand.return_value = 0xfe
        self.solver.repository_metadata_dirs = ['metadata_dir.XXXX']
        mock_mkdtemp.return_value = 'solv_dir.XX'
        self.solver._create_solvables('meta_dir.XX', 'rpms2solv')
        mock_command.assert_called_once_with([
            'bash', '-c',
            'rpms2solv meta_dir.XX/*.rpm > solv_dir.XX/solvable-fefefefe'
        ])

    @patch('kiwi.solver.repository.base.mkdtemp')
    @patch('kiwi.solver.repository.base.random.randrange')
    @patch('kiwi.solver.repository.base.Command.run')
    @patch('kiwi.solver.repository.base.glob.iglob')
    def test__create_solvables_rpmmd2_solv(self, mock_glob, mock_command,
                                           mock_rand, mock_mkdtemp):
        mock_glob.return_value = ['some-solv-data-file']
        mock_rand.return_value = 0xfe
        self.solver.repository_metadata_dirs = ['metadata_dir.XXXX']
        mock_mkdtemp.return_value = 'solv_dir.XX'
        self.solver._create_solvables('meta_dir.XX', 'rpmmd2solv')
        mock_glob.assert_called_once_with('meta_dir.XX/*')
        mock_command.assert_called_once_with([
            'bash', '-c', ' '.join([
                'gzip -cd --force some-solv-data-file', '|',
                'rpmmd2solv > solv_dir.XX/solvable-fefefefe'
            ])
        ])

    @patch('kiwi.solver.repository.base.Command.run')
    @patch('kiwi.solver.repository.base.Path.wipe')
    @patch('kiwi.solver.repository.base.Path.create')
    @patch('kiwi.solver.repository.base.SolverRepositoryBase.is_uptodate')
    @patch.object(SolverRepositoryBase, '_setup_repository_metadata')
    @patch_open
    def test_create_repository_solvable(self, mock_open,
                                        mock_setup_repository_metadata,
                                        mock_is_uptodate, mock_path_create,
                                        mock_path_wipe, mock_command):
        mock_is_uptodate.return_value = False
        mock_open.return_value = self.context_manager_mock
        self.solver.repository_solvable_dir = 'solvable_dir.XX'
        self.uri.alias.return_value = 'repo-alias'
        self.uri.uri = 'repo-uri'
        assert self.solver.create_repository_solvable('target_dir') == \
            'target_dir/repo-alias'
        mock_is_uptodate.assert_called_once_with('target_dir')
        mock_setup_repository_metadata.assert_called_once_with()
        mock_command.assert_called_once_with([
            'bash', '-c', 'mergesolv solvable_dir.XX/* > target_dir/repo-alias'
        ])
        assert mock_open.call_args_list == [
            call('target_dir/repo-alias.info', 'w'),
            call('target_dir/repo-alias.timestamp', 'w')
        ]
        assert self.file_mock.write.call_args_list == [
            call(''.join(['repo-uri', os.linesep])),
            call('static')
        ]

    @patch('kiwi.solver.repository.base.Path.wipe')
    def test_destructor(self, mock_wipe):
        self.solver.repository_metadata_dirs = ['meta_dir.XX']
        self.solver.repository_solvable_dir = 'solv_dir.XX'
        self.solver.__del__()
        assert mock_wipe.call_args_list == [
            call('meta_dir.XX'), call('solv_dir.XX')
        ]
示例#6
0
    def setup(self):
        self.uri = mock.Mock()

        self.solver = SolverRepositoryBase(self.uri)
示例#7
0
class TestSolverRepositoryBase:
    def setup(self):
        self.uri = mock.Mock()

        self.solver = SolverRepositoryBase(self.uri)

    @patch.object(SolverRepositoryBase, '_get_repomd_xml')
    @patch.object(SolverRepositoryBase, '_get_deb_packages')
    @patch.object(SolverRepositoryBase, '_get_pacman_packages')
    def test_get_repo_type_not_detected(self, mock_get_pacman_packages,
                                        mock_get_deb_packages,
                                        mock_get_repomd_xml):
        mock_get_repomd_xml.side_effect = KiwiUriOpenError('error')
        mock_get_pacman_packages.side_effect = KiwiUriOpenError('error')
        mock_get_deb_packages.side_effect = KiwiUriOpenError('error')
        assert self.solver.get_repo_type() is None

    @patch.object(SolverRepositoryBase, '_get_repomd_xml')
    def test_get_repo_type_rpm_md(self, mock_get_repomd_xml):
        assert self.solver.get_repo_type() == 'rpm-md'

    @patch.object(SolverRepositoryBase, '_get_repomd_xml')
    @patch.object(SolverRepositoryBase, '_get_deb_packages')
    def test_get_repo_type_deb(self, mock_get_deb_packages,
                               mock_get_repomd_xml):
        mock_get_repomd_xml.side_effect = KiwiUriOpenError('error')
        assert self.solver.get_repo_type() == 'apt-deb'

    @patch.object(SolverRepositoryBase, '_get_repomd_xml')
    @patch.object(SolverRepositoryBase, '_get_deb_packages')
    @patch.object(SolverRepositoryBase, '_get_pacman_packages')
    def test_get_repo_type_pacman(self, mock_get_pacman_packages,
                                  mock_get_deb_packages, mock_get_repomd_xml):
        mock_get_repomd_xml.side_effect = KiwiUriOpenError('error')
        mock_get_deb_packages.side_effect = KiwiUriOpenError('error')
        mock_get_pacman_packages.return_value = '"some_repo.db.sig"'
        assert self.solver.get_repo_type() == 'pacman'

    def test__setup_repository_metadata(self):
        with raises(NotImplementedError):
            self.solver._setup_repository_metadata()

    def test__get_repomd_xpath(self):
        xml_data = etree.parse('../data/repomd.xml')
        assert self.solver._get_repomd_xpath(
            xml_data, 'repo:data[@type="primary"]/repo:location')[0].get(
                'href') == 'repodata/55f95a93-primary.xml.gz'

    @patch('kiwi.solver.repository.base.Temporary.new_file')
    @patch.object(SolverRepositoryBase, 'download_from_repository')
    @patch('os.path.isfile')
    def test__get_pacman_packages(self, mock_os_isfile, mock_download,
                                  mock_tmpfile):
        Defaults.set_platform_name('x86_64')
        mock_os_isfile.return_value = True
        tmpfile = mock.Mock()
        tmpfile.name = 'tmpfile'
        mock_tmpfile.return_value = tmpfile
        with patch('builtins.open', create=True) as mock_open:
            mock_open.return_value = MagicMock(spec=io.IOBase)
            file_handle = mock_open.return_value.__enter__.return_value
            file_handle.read.return_value = 'data'
            assert self.solver._get_pacman_packages() == 'data'
            mock_download.assert_called_once_with('x86_64', 'tmpfile')

    @patch('kiwi.solver.repository.base.Temporary.new_file')
    @patch.object(SolverRepositoryBase, 'download_from_repository')
    @patch('os.path.isfile')
    def test__get_deb_packages(self, mock_os_isfile, mock_download,
                               mock_tmpfile):
        mock_os_isfile.return_value = True
        tmpfile = mock.Mock()
        tmpfile.name = 'tmpfile'
        mock_tmpfile.return_value = tmpfile
        with patch('builtins.open', create=True) as mock_open:
            mock_open.return_value = MagicMock(spec=io.IOBase)
            file_handle = mock_open.return_value.__enter__.return_value
            file_handle.read.return_value = 'data'
            assert self.solver._get_deb_packages() == 'data'
            mock_download.assert_called_once_with('Packages.gz', 'tmpfile')
        mock_download.reset_mock()
        assert self.solver._get_deb_packages('download_dir') == \
            'download_dir/Packages.gz'
        mock_download.assert_called_once_with('Packages.gz',
                                              'download_dir/Packages.gz')

    @patch('kiwi.solver.repository.base.Temporary.new_file')
    @patch.object(SolverRepositoryBase, 'download_from_repository')
    @patch('lxml.etree.parse')
    def test__get_repomd_xml(self, mock_parse, mock_download, mock_tmpfile):
        tmpfile = mock.Mock()
        tmpfile.name = 'tmpfile'
        xml_data = mock.Mock()
        mock_parse.return_value = xml_data
        mock_tmpfile.return_value = tmpfile
        assert self.solver._get_repomd_xml() == xml_data
        mock_download.assert_called_once_with('repodata/repomd.xml', 'tmpfile')
        mock_parse.assert_called_once_with('tmpfile')

    @patch('kiwi.solver.repository.base.Temporary')
    def test__create_temporary_metadata_dir(self, mock_Temporary):
        self.solver._create_temporary_metadata_dir()
        assert self.solver.repository_metadata_dirs == [
            mock_Temporary.return_value.new_dir.return_value
        ]
        mock_Temporary.assert_called_once_with(prefix='kiwi_metadata_dir.')

    @patch('os.path.exists')
    def test_is_uptodate_static_time(self, mock_exists):
        mock_exists.return_value = True
        self.uri.alias.return_value = 'repo-alias'

        m_open = mock_open(read_data='static')
        with patch('builtins.open', m_open, create=True):
            assert self.solver.is_uptodate() is False

        m_open.assert_called_once_with(
            '/var/tmp/kiwi/satsolver/repo-alias.timestamp')

    @patch('os.path.exists')
    @patch('kiwi.solver.repository.base.SolverRepositoryBase.timestamp')
    def test_is_uptodate_some_time(self, mock_timestamp, mock_exists):
        mock_exists.return_value = True
        mock_timestamp.return_value = 'some-time'
        self.uri.alias.return_value = 'repo-alias'

        m_open = mock_open(read_data='some-time')
        with patch('builtins.open', m_open, create=True):
            assert self.solver.is_uptodate() is True

        m_open.assert_called_once_with(
            '/var/tmp/kiwi/satsolver/repo-alias.timestamp')

    def test_timestamp(self):
        assert self.solver.timestamp() == 'static'

    @patch('kiwi.solver.repository.base.urlopen')
    @patch('kiwi.solver.repository.base.Request')
    def test_download_from_repository_with_credentials(self, mock_request,
                                                       mock_urlopen):
        request = mock.Mock()
        mock_request.return_value = request
        location = mock.Mock()
        location.read.return_value = 'data-from-network'
        mock_urlopen.return_value = location
        self.uri.is_remote.return_value = True
        self.uri.translate.return_value = 'http://myrepo/file'
        self.solver.user = '******'
        self.solver.secret = 'secret'

        m_open = mock_open()
        with patch('builtins.open', m_open, create=True):
            self.solver.download_from_repository('repodata/file',
                                                 'target-file')

        mock_urlopen.assert_called_once_with(request)
        mock_request.assert_called_once_with(
            'http://myrepo/file/repodata/file')
        request.add_header.assert_called_once_with('Authorization',
                                                   b'Basic dXNlcjpzZWNyZXQ=')
        m_open.assert_called_once_with('target-file', 'wb')
        m_open.return_value.write.assert_called_once_with('data-from-network')

    @patch('kiwi.solver.repository.base.urlopen')
    @patch('kiwi.solver.repository.base.Request')
    def test_download_from_repository_remote(self, mock_request, mock_urlopen):
        request = mock.Mock()
        mock_request.return_value = request
        location = mock.Mock()
        location.read.return_value = 'data-from-network'
        mock_urlopen.return_value = location
        self.uri.is_remote.return_value = True
        self.uri.translate.return_value = 'http://myrepo/file'

        m_open = mock_open()
        with patch('builtins.open', m_open, create=True):
            self.solver.download_from_repository('repodata/file',
                                                 'target-file')

        mock_urlopen.assert_called_once_with(request)
        mock_request.assert_called_once_with(
            'http://myrepo/file/repodata/file')
        m_open.assert_called_once_with('target-file', 'wb')
        m_open.return_value.write.assert_called_once_with('data-from-network')

    @patch('kiwi.solver.repository.base.urlopen')
    @patch('kiwi.solver.repository.base.Request')
    def test_download_from_repository_local(self, mock_request, mock_urlopen):
        request = mock.Mock()
        mock_request.return_value = request
        location = mock.Mock()
        location.read.return_value = 'data'
        mock_urlopen.return_value = location
        self.uri.is_remote.return_value = False
        self.uri.translate.return_value = '/my_local_repo/file'

        m_open = mock_open()
        with patch('builtins.open', m_open, create=True):
            self.solver.download_from_repository('repodata/file',
                                                 'target-file')

        mock_urlopen.assert_called_once_with(request)
        mock_request.assert_called_once_with(
            'file:///my_local_repo/file/repodata/file')
        m_open.assert_called_once_with('target-file', 'wb')
        m_open.return_value.write.assert_called_once_with('data')

    @patch('kiwi.solver.repository.base.urlopen')
    def test_download_from_repository_raises(self, mock_urlopen):
        self.uri.is_remote.return_value = False
        self.uri.translate.return_value = '/my_local_repo/file'
        mock_urlopen.side_effect = Exception
        with raises(KiwiUriOpenError):
            self.solver.download_from_repository('repodata/file',
                                                 'target-file')

    @patch('kiwi.solver.repository.base.Temporary')
    @patch('kiwi.solver.repository.base.random.randrange')
    @patch('kiwi.solver.repository.base.Command.run')
    def test__create_solvables_rpms2_solv(self, mock_command, mock_rand,
                                          mock_Temporary):
        mock_rand.return_value = 0xfe
        self.solver.repository_metadata_dirs = ['metadata_dir.XXXX']
        mock_Temporary.return_value.new_dir.return_value.name = 'solv_dir.XX'
        self.solver._create_solvables('meta_dir.XX', 'rpms2solv')
        mock_command.assert_called_once_with([
            'bash', '-c',
            'rpms2solv meta_dir.XX/*.rpm > solv_dir.XX/solvable-fefefefe'
        ])

    @patch('kiwi.solver.repository.base.Temporary')
    @patch('kiwi.solver.repository.base.random.randrange')
    @patch('kiwi.solver.repository.base.Command.run')
    @patch('kiwi.solver.repository.base.glob.iglob')
    def test__create_solvables_rpmmd2_solv(self, mock_glob, mock_command,
                                           mock_rand, mock_Temporary):
        mock_glob.return_value = ['some-solv-data-file']
        mock_rand.return_value = 0xfe
        self.solver.repository_metadata_dirs = ['metadata_dir.XXXX']
        mock_Temporary.return_value.new_dir.return_value.name = 'solv_dir.XX'
        self.solver._create_solvables('meta_dir.XX', 'rpmmd2solv')
        mock_glob.assert_called_once_with('meta_dir.XX/*')
        mock_command.assert_called_once_with([
            'bash', '-c', ' '.join([
                'gzip -cd --force some-solv-data-file', '|',
                'rpmmd2solv > solv_dir.XX/solvable-fefefefe'
            ])
        ])

    @patch('kiwi.solver.repository.base.Temporary')
    @patch('kiwi.solver.repository.base.random.randrange')
    @patch('kiwi.solver.repository.base.Command.run')
    @patch('kiwi.solver.repository.base.glob.iglob')
    def test__create_solvables_deb2_solv(self, mock_glob, mock_command,
                                         mock_rand, mock_Temporary):
        mock_glob.return_value = ['some-solv-data-file']
        mock_rand.return_value = 0xfe
        self.solver.repository_metadata_dirs = ['metadata_dir.XXXX']
        mock_Temporary.return_value.new_dir.return_value.name = 'solv_dir.XX'
        self.solver._create_solvables('meta_dir.XX', 'deb2solv')
        mock_glob.assert_called_once_with('meta_dir.XX/*')
        mock_command.assert_called_once_with([
            'bash', '-c', ' '.join([
                'gzip -cd --force some-solv-data-file', '|',
                'deb2solv -r > solv_dir.XX/solvable-fefefefe'
            ])
        ])

    @patch('kiwi.solver.repository.base.Command.run')
    @patch('kiwi.solver.repository.base.Path.wipe')
    @patch('kiwi.solver.repository.base.Path.create')
    @patch('kiwi.solver.repository.base.SolverRepositoryBase.is_uptodate')
    @patch.object(SolverRepositoryBase, '_setup_repository_metadata')
    def test_create_repository_solvable(self, mock_setup_repository_metadata,
                                        mock_is_uptodate, mock_path_create,
                                        mock_path_wipe, mock_command):
        mock_is_uptodate.return_value = False
        tempdir = Mock()
        tempdir.name = 'solvable_dir.XX'
        self.solver.repository_solvable_dir = tempdir
        self.uri.alias.return_value = 'repo-alias'
        self.uri.uri = 'repo-uri'

        m_open = mock_open()
        with patch('builtins.open', m_open, create=True):
            assert self.solver.create_repository_solvable('target_dir') == \
                'target_dir/repo-alias'

        mock_is_uptodate.assert_called_once_with('target_dir')
        mock_setup_repository_metadata.assert_called_once_with()
        mock_command.assert_called_once_with([
            'bash', '-c', 'mergesolv solvable_dir.XX/* > target_dir/repo-alias'
        ])
        assert m_open.call_args_list == [
            call('target_dir/repo-alias.info', 'w'),
            call('target_dir/repo-alias.timestamp', 'w')
        ]
        assert m_open.return_value.write.call_args_list == [
            call(''.join(['repo-uri', os.linesep])),
            call('static')
        ]
class TestSolverRepositoryBase(object):
    def setup(self):
        self.context_manager_mock = mock.Mock()
        self.file_mock = mock.Mock()
        self.enter_mock = mock.Mock()
        self.exit_mock = mock.Mock()
        self.enter_mock.return_value = self.file_mock
        setattr(self.context_manager_mock, '__enter__', self.enter_mock)
        setattr(self.context_manager_mock, '__exit__', self.exit_mock)

        self.uri = mock.Mock()

        self.solver = SolverRepositoryBase(self.uri)

    @raises(NotImplementedError)
    def test__setup_repository_metadata(self):
        self.solver._setup_repository_metadata()

    def test__get_repomd_xpath(self):
        xml_data = etree.parse('../data/repomd.xml')
        assert self.solver._get_repomd_xpath(
            xml_data, 'repo:data[@type="primary"]/repo:location'
        )[0].get('href') == 'repodata/55f95a93-primary.xml.gz'

    @patch('kiwi.solver.repository.base.NamedTemporaryFile')
    @patch.object(SolverRepositoryBase, 'download_from_repository')
    @patch('lxml.etree.parse')
    def test__get_repomd_xml(self, mock_parse, mock_download, mock_tmpfile):
        tmpfile = mock.Mock()
        tmpfile.name = 'tmpfile'
        xml_data = mock.Mock()
        mock_parse.return_value = xml_data
        mock_tmpfile.return_value = tmpfile
        assert self.solver._get_repomd_xml() == xml_data
        mock_download.assert_called_once_with(
            'repodata/repomd.xml', 'tmpfile'
        )
        mock_parse.assert_called_once_with('tmpfile')

    @patch('kiwi.solver.repository.base.mkdtemp')
    def test__create_temporary_metadata_dir(self, mock_mkdtemp):
        mock_mkdtemp.return_value = 'tmpdir'
        self.solver._create_temporary_metadata_dir()
        assert self.solver.repository_metadata_dirs == ['tmpdir']
        mock_mkdtemp.assert_called_once_with(prefix='metadata_dir.')

    @patch_open
    @patch('os.path.exists')
    def test_is_uptodate_static_time(self, mock_exists, mock_open):
        mock_exists.return_value = True
        mock_open.return_value = self.context_manager_mock
        self.file_mock.read.return_value = 'static'
        self.uri.alias.return_value = 'repo-alias'
        assert self.solver.is_uptodate() is False
        mock_open.assert_called_once_with(
            '/var/tmp/kiwi/satsolver/repo-alias.timestamp'
        )

    @patch_open
    @patch('os.path.exists')
    @patch('kiwi.solver.repository.base.SolverRepositoryBase.timestamp')
    def test_is_uptodate_some_time(
        self, mock_timestamp, mock_exists, mock_open
    ):
        mock_exists.return_value = True
        mock_open.return_value = self.context_manager_mock
        self.file_mock.read.return_value = 'some-time'
        mock_timestamp.return_value = 'some-time'
        self.uri.alias.return_value = 'repo-alias'
        assert self.solver.is_uptodate() is True
        mock_open.assert_called_once_with(
            '/var/tmp/kiwi/satsolver/repo-alias.timestamp'
        )

    def test_timestamp(self):
        assert self.solver.timestamp() == 'static'

    @patch('kiwi.solver.repository.base.urlopen')
    @patch('kiwi.solver.repository.base.Request')
    @patch_open
    def test_download_from_repository_with_credentials(
        self, mock_open, mock_request, mock_urlopen
    ):
        request = mock.Mock()
        mock_request.return_value = request
        location = mock.Mock()
        location.read.return_value = 'data-from-network'
        mock_urlopen.return_value = location
        mock_open.return_value = self.context_manager_mock
        self.uri.is_remote.return_value = True
        self.uri.translate.return_value = 'http://myrepo/file'
        self.solver.user = '******'
        self.solver.secret = 'secret'
        self.solver.download_from_repository(
            'repodata/file', 'target-file'
        )
        mock_urlopen.assert_called_once_with(request)
        mock_request.assert_called_once_with(
            'http://myrepo/file/repodata/file'
        )
        request.add_header.assert_called_once_with(
            'Authorization', b'Basic dXNlcjpzZWNyZXQ='
        )
        mock_open.assert_called_once_with(
            'target-file', 'wb'
        )
        self.file_mock.write.assert_called_once_with(
            'data-from-network'
        )

    @patch('kiwi.solver.repository.base.urlopen')
    @patch('kiwi.solver.repository.base.Request')
    @patch_open
    def test_download_from_repository_remote(
        self, mock_open, mock_request, mock_urlopen
    ):
        request = mock.Mock()
        mock_request.return_value = request
        location = mock.Mock()
        location.read.return_value = 'data-from-network'
        mock_urlopen.return_value = location
        mock_open.return_value = self.context_manager_mock
        self.uri.is_remote.return_value = True
        self.uri.translate.return_value = 'http://myrepo/file'
        self.solver.download_from_repository('repodata/file', 'target-file')
        mock_urlopen.assert_called_once_with(request)
        mock_request.assert_called_once_with(
            'http://myrepo/file/repodata/file'
        )
        mock_open.assert_called_once_with(
            'target-file', 'wb'
        )
        self.file_mock.write.assert_called_once_with(
            'data-from-network'
        )

    @patch('kiwi.solver.repository.base.urlopen')
    @patch('kiwi.solver.repository.base.Request')
    @patch_open
    def test_download_from_repository_local(
        self, mock_open, mock_request, mock_urlopen
    ):
        request = mock.Mock()
        mock_request.return_value = request
        location = mock.Mock()
        location.read.return_value = 'data'
        mock_urlopen.return_value = location
        mock_open.return_value = self.context_manager_mock
        self.uri.is_remote.return_value = False
        self.uri.translate.return_value = '/my_local_repo/file'
        self.solver.download_from_repository('repodata/file', 'target-file')
        mock_urlopen.assert_called_once_with(request)
        mock_request.assert_called_once_with(
            'file:///my_local_repo/file/repodata/file'
        )
        mock_open.assert_called_once_with(
            'target-file', 'wb'
        )
        self.file_mock.write.assert_called_once_with(
            'data'
        )

    @patch('kiwi.solver.repository.base.urlopen')
    @raises(KiwiUriOpenError)
    def test_download_from_repository_raises(self, mock_urlopen):
        self.uri.is_remote.return_value = False
        self.uri.translate.return_value = '/my_local_repo/file'
        mock_urlopen.side_effect = Exception
        self.solver.download_from_repository('repodata/file', 'target-file')

    @patch('kiwi.solver.repository.base.mkdtemp')
    @patch('kiwi.solver.repository.base.random.randrange')
    @patch('kiwi.solver.repository.base.Command.run')
    def test__create_solvables_rpms2_solv(
        self, mock_command, mock_rand, mock_mkdtemp
    ):
        mock_rand.return_value = 0xfe
        self.solver.repository_metadata_dirs = ['metadata_dir.XXXX']
        mock_mkdtemp.return_value = 'solv_dir.XX'
        self.solver._create_solvables('meta_dir.XX', 'rpms2solv')
        mock_command.assert_called_once_with(
            [
                'bash', '-c',
                'rpms2solv meta_dir.XX/*.rpm > solv_dir.XX/solvable-fefefefe'
            ]
        )

    @patch('kiwi.solver.repository.base.mkdtemp')
    @patch('kiwi.solver.repository.base.random.randrange')
    @patch('kiwi.solver.repository.base.Command.run')
    @patch('kiwi.solver.repository.base.glob.iglob')
    def test__create_solvables_rpmmd2_solv(
        self, mock_glob, mock_command, mock_rand, mock_mkdtemp
    ):
        mock_glob.return_value = ['some-solv-data-file']
        mock_rand.return_value = 0xfe
        self.solver.repository_metadata_dirs = ['metadata_dir.XXXX']
        mock_mkdtemp.return_value = 'solv_dir.XX'
        self.solver._create_solvables('meta_dir.XX', 'rpmmd2solv')
        mock_glob.assert_called_once_with('meta_dir.XX/*')
        mock_command.assert_called_once_with(
            [
                'bash', '-c',
                ' '.join([
                    'gzip -cd --force some-solv-data-file',
                    '|',
                    'rpmmd2solv > solv_dir.XX/solvable-fefefefe'
                ])
            ]
        )

    @patch('kiwi.solver.repository.base.Command.run')
    @patch('kiwi.solver.repository.base.Path.wipe')
    @patch('kiwi.solver.repository.base.Path.create')
    @patch('kiwi.solver.repository.base.SolverRepositoryBase.is_uptodate')
    @patch.object(SolverRepositoryBase, '_setup_repository_metadata')
    @patch_open
    def test_create_repository_solvable(
        self, mock_open, mock_setup_repository_metadata, mock_is_uptodate,
        mock_path_create, mock_path_wipe, mock_command
    ):
        mock_is_uptodate.return_value = False
        mock_open.return_value = self.context_manager_mock
        self.solver.repository_solvable_dir = 'solvable_dir.XX'
        self.uri.alias.return_value = 'repo-alias'
        self.uri.uri = 'repo-uri'
        assert self.solver.create_repository_solvable('target_dir') == \
            'target_dir/repo-alias'
        mock_is_uptodate.assert_called_once_with('target_dir')
        mock_setup_repository_metadata.assert_called_once_with()
        mock_command.assert_called_once_with(
            [
                'bash', '-c',
                'mergesolv solvable_dir.XX/* > target_dir/repo-alias'
            ]
        )
        assert mock_open.call_args_list == [
            call('target_dir/repo-alias.info', 'w'),
            call('target_dir/repo-alias.timestamp', 'w')
        ]
        assert self.file_mock.write.call_args_list == [
            call(''.join(['repo-uri', os.linesep])),
            call('static')
        ]

    @patch('kiwi.solver.repository.base.Path.wipe')
    def test_destructor(self, mock_wipe):
        self.solver.repository_metadata_dirs = ['meta_dir.XX']
        self.solver.repository_solvable_dir = 'solv_dir.XX'
        self.solver.__del__()
        assert mock_wipe.call_args_list == [
            call('meta_dir.XX'), call('solv_dir.XX')
        ]