# Copyright 2007-2019 Red Hat, Inc. and others.
#
# This file is part of Bodhi.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

from datetime import datetime, timezone
from hashlib import sha256
from os.path import basename, exists, join
from unittest import mock
import glob
import os
import shutil
import tempfile

import createrepo_c
import pytest

from bodhi.server.buildsys import DevBuildsys, setup_buildsystem, teardown_buildsystem
from bodhi.server.config import config
from bodhi.server.metadata import UpdateInfoMetadata
from bodhi.server.models import Release, Update, UpdateRequest, UpdateStatus
import bodhi.server.metadata as bodhi_metadata

from . import base


class UpdateInfoMetadataTestCase(base.BasePyTestCase):
    def setup_method(self, method):
        """
        Initialize our temporary repo.
        """
        super().setup_method(method)
        setup_buildsystem({'buildsystem': 'dev'})
        self.tempdir = tempfile.mkdtemp('bodhi')
        self.tempcompdir = join(self.tempdir, 'f17-updates-testing')
        self.temprepo = join(self.tempcompdir, 'compose', 'Everything', 'i386', 'os')
        base.mkmetadatadir(join(self.temprepo, 'f17-updates-testing', 'i386'), updateinfo=False)
        config['cache_dir'] = os.path.join(self.tempdir, 'cache')
        os.makedirs(config['cache_dir'])

    def teardown_method(self, method):
        """
        Clean up the tempdir.
        """
        super().teardown_method(method)
        teardown_buildsystem()
        shutil.rmtree(self.tempdir)
        config['cache_dir'] = None


class TestAddUpdate(UpdateInfoMetadataTestCase):
    """
    This class contains tests for the UpdateInfoMetadata.add_update() method.
    """

    def test_build_not_in_builds(self):
        """
        Test correct behavior when a build in update.builds isn't found in self.builds() and
        koji.getBuild() is called instead.
        """
        update = self.db.query(Update).one()
        now = datetime(year=2018, month=2, day=8, hour=12, minute=41, second=4)
        update.date_modified = now
        md = UpdateInfoMetadata(update.release, update.request, self.db, self.temprepo,
                                close_shelf=False)

        md.add_update(update)

        md.shelf.close()

        assert len(md.uinfo.updates) == 1
        assert md.uinfo.updates[0].title == update.title
        assert md.uinfo.updates[0].release == update.release.long_name
        assert md.uinfo.updates[0].status == UpdateStatus.testing.value
        assert md.uinfo.updates[0].updated_date == update.date_modified
        assert md.uinfo.updates[0].fromstr == config.get('bodhi_email')
        assert md.uinfo.updates[0].rights == config.get('updateinfo_rights')
        assert md.uinfo.updates[0].description == update.notes
        assert md.uinfo.updates[0].id == update.alias
        assert md.uinfo.updates[0].severity == 'Moderate'
        assert len(md.uinfo.updates[0].references) == 1
        bug = md.uinfo.updates[0].references[0]
        assert bug.href == update.bugs[0].url
        assert bug.id == '12345'
        assert bug.type == 'bugzilla'
        assert len(md.uinfo.updates[0].collections) == 1
        col = md.uinfo.updates[0].collections[0]
        assert col.name == update.release.long_name
        assert col.shortname == update.release.name
        assert len(col.packages) == 2
        pkg = col.packages[0]
        assert pkg.epoch == '0'
        # It's a little goofy, but the DevBuildsys is going to return TurboGears rpms when its
        # listBuildRPMs() method is called, so let's just roll with it.
        assert pkg.name == 'TurboGears'
        assert pkg.src == \
            ('https://download.fedoraproject.org/pub/fedora/linux/updates/17/SRPMS/T/'
             'TurboGears-1.0.2.2-2.fc17.src.rpm')
        assert pkg.version == '1.0.2.2'
        assert not pkg.reboot_suggested
        assert not pkg.relogin_suggested
        assert pkg.arch == 'src'
        assert pkg.filename == 'TurboGears-1.0.2.2-2.fc17.src.rpm'
        pkg = col.packages[1]
        assert pkg.epoch == '0'
        assert pkg.name == 'TurboGears'
        assert pkg.src == \
            ('https://download.fedoraproject.org/pub/fedora/linux/updates/17/i386/T/'
             'TurboGears-1.0.2.2-2.fc17.noarch.rpm')
        assert pkg.version == '1.0.2.2'
        assert not pkg.reboot_suggested
        assert not pkg.relogin_suggested
        assert pkg.arch == 'noarch'
        assert pkg.filename == 'TurboGears-1.0.2.2-2.fc17.noarch.rpm'

    def test_status_for_update_being_pushed_to_stable(self):
        """
        The metadata should report the status based on request if the update is being pushed
        into a repository for the first time.
        """
        update = self.db.query(Update).one()
        update.status = UpdateStatus.testing
        update.request = UpdateRequest.stable
        md = UpdateInfoMetadata(update.release, update.request, self.db, self.temprepo,
                                close_shelf=False)
        md.add_update(update)
        md.shelf.close()

        assert len(md.uinfo.updates) == 1
        assert md.uinfo.updates[0].status == UpdateStatus.stable.value

    def test_status_for_update_being_pushed_to_testing(self):
        """
        The metadata should report the status based on request if the update is being pushed
        into a repository for the first time.
        """
        update = self.db.query(Update).one()
        update.status = UpdateStatus.pending
        update.request = UpdateRequest.testing
        md = UpdateInfoMetadata(update.release, update.request, self.db, self.temprepo,
                                close_shelf=False)
        md.add_update(update)
        md.shelf.close()

        assert len(md.uinfo.updates) == 1
        assert md.uinfo.updates[0].status == UpdateStatus.testing.value

    def test_status_for_update_already_in_repo(self):
        """
        The metadata should report the status based on update status if the update was
        already into the repo.
        """
        update = self.db.query(Update).one()
        update.status = UpdateStatus.stable
        update.request = None
        md = UpdateInfoMetadata(update.release, update.request, self.db, self.temprepo,
                                close_shelf=False)
        md.add_update(update)
        md.shelf.close()

        assert len(md.uinfo.updates) == 1
        assert md.uinfo.updates[0].status == update.status.value

    @pytest.mark.parametrize(
        'date_modified,date_pushed',
        [pytest.param(
            datetime(year=2022, month=11, day=23, hour=12, minute=41, second=4),
            datetime(year=2022, month=11, day=23, hour=11, minute=41, second=4),
            id='modified_after_push'),
         pytest.param(
            datetime(year=2022, month=11, day=23, hour=11, minute=41, second=4),
            datetime(year=2022, month=11, day=23, hour=12, minute=41, second=4),
            id='modified_before_push'),
         pytest.param(
            None,
            datetime(year=2022, month=11, day=23, hour=12, minute=41, second=4),
            id='never_modified'),
         pytest.param(
            datetime(year=2022, month=11, day=23, hour=12, minute=41, second=4),
            None,
            id='never_pushed'),
         pytest.param(
            None,
            None,
            id='first_compose')])
    def test_date_modified_and_date_pushed(self, date_modified, date_pushed):
        """The metadata should use the most recent between date_modified and date_pushed."""
        expected = datetime(year=2022, month=11, day=23, hour=12, minute=41, second=4)
        update = self.db.query(Update).one()
        update.date_modified = date_modified
        update.date_stable = date_pushed
        if not date_modified and not date_pushed:
            update.date_submitted = expected
        md = UpdateInfoMetadata(update.release, update.request, self.db, self.temprepo,
                                close_shelf=False)
        md.add_update(update)
        md.shelf.close()

        assert len(md.uinfo.updates) == 1
        assert md.uinfo.updates[0].updated_date == expected

    def test_date_pushed_none(self):
        """updated_date should use date_submitted if an update's date_pushed is None."""
        update = self.db.query(Update).one()
        update.date_stable = update.date_testing = None
        md = UpdateInfoMetadata(update.release, update.request, self.db, self.temprepo,
                                close_shelf=False)
        md.add_update(update)
        md.shelf.close()

        assert len(md.uinfo.updates) == 1
        assert md.uinfo.updates[0].issued_date == update.date_submitted.replace(tzinfo=None)

    def test_rpm_with_arch(self):
        """Ensure that an RPM with a non 386 arch gets handled correctly."""
        update = self.db.query(Update).one()
        md = UpdateInfoMetadata(update.release, update.request, self.db, self.temprepo,
                                close_shelf=False)
        # Set the arch to aarch64
        fake_rpms = [{
            'nvr': 'TurboGears-1.0.2.2-2.fc17', 'buildtime': 1178868422, 'arch': 'aarch64',
            'id': 62330, 'size': 761742, 'build_id': 6475, 'name': 'TurboGears', 'epoch': None,
            'version': '1.0.2.2', 'release': '2.fc17', 'buildroot_id': 1883,
            'payloadhash': '6787febe92434a9be2a8f309d0e2014e'}]

        with mock.patch.object(md, 'get_rpms', mock.MagicMock(return_value=fake_rpms)):
            md.add_update(update)

        md.shelf.close()
        col = md.uinfo.updates[0].collections[0]
        assert len(col.packages) == 1
        pkg = col.packages[0]
        assert pkg.src == \
            ('https://download.fedoraproject.org/pub/fedora/linux/updates/17/aarch64/T/'
             'TurboGears-1.0.2.2-2.fc17.aarch64.rpm')

    def test_rpm_with_epoch(self):
        """Ensure that an RPM with an Epoch gets handled correctly."""
        update = self.db.query(Update).one()
        md = UpdateInfoMetadata(update.release, update.request, self.db, self.temprepo,
                                close_shelf=False)
        # We'll fake the return of get_rpms so we can inject an epoch of 42.
        fake_rpms = [{
            'nvr': 'TurboGears-1.0.2.2-2.fc17', 'buildtime': 1178868422, 'arch': 'src', 'id': 62330,
            'size': 761742, 'build_id': 6475, 'name': 'TurboGears', 'epoch': 42,
            'version': '1.0.2.2', 'release': '2.fc17', 'buildroot_id': 1883,
            'payloadhash': '6787febe92434a9be2a8f309d0e2014e'}]

        with mock.patch.object(md, 'get_rpms', mock.MagicMock(return_value=fake_rpms)):
            md.add_update(update)

        md.shelf.close()
        col = md.uinfo.updates[0].collections[0]
        assert len(col.packages) == 1
        pkg = col.packages[0]
        assert pkg.epoch == '42'


class TestFetchUpdates(UpdateInfoMetadataTestCase):
    """Test the UpdateInfoMetadata._fetch_updates() method."""

    @mock.patch('bodhi.server.metadata.log.warning')
    def test_build_unassociated(self, warning):
        """A warning should be logged if the Bodhi Build object is not associated with an Update."""
        update = self.db.query(Update).one()
        update.date_stable = update.date_testing = None
        u = base.create_update(self.db, ['TurboGears-1.0.2.2-4.fc17'])
        u.builds[0].update = None
        self.db.flush()

        # _fetch_updates() is called as part of UpdateInfoMetadata.__init__() so we'll just
        # instantiate one.
        md = UpdateInfoMetadata(update.release, update.request, self.db, self.temprepo,
                                close_shelf=False)

        warning.assert_called_once_with(
            'TurboGears-1.0.2.2-4.fc17 does not have a corresponding update')
        # Since the Build didn't have an Update, no Update should have been added to md.updates.
        assert md.updates == set([])


class TestUpdateInfoMetadata(UpdateInfoMetadataTestCase):

    def setup_method(self, method):
        super().setup_method(method)

        self._new_compose_stage_dir = tempfile.mkdtemp()
        self._compose_stage_dir = config['compose_stage_dir']
        self._compose_dir = config['compose_dir']
        config['compose_stage_dir'] = self._new_compose_stage_dir
        config['compose_dir'] = os.path.join(config['compose_stage_dir'], 'compose')
        config['cache_dir'] = os.path.join(config['compose_stage_dir'], 'cache')
        os.makedirs(config['cache_dir'])
        os.makedirs(os.path.join(config['compose_dir'], 'f17-updates-testing'))

        # Initialize our temporary repo
        base.mkmetadatadir(self.temprepo, updateinfo=False)
        base.mkmetadatadir(join(self.tempcompdir, 'compose', 'Everything', 'source', 'tree'),
                           updateinfo=False)
        self.repodata = join(self.temprepo, 'repodata')
        assert exists(join(self.repodata, 'repomd.xml'))

        DevBuildsys.__rpms__ = [{
            'arch': 'src',
            'build_id': 6475,
            'buildroot_id': 1883,
            'buildtime': 1178868422,
            'epoch': None,
            'id': 62330,
            'name': 'bodhi',
            'nvr': 'bodhi-2.0-1.fc17',
            'release': '1.fc17',
            'size': 761742,
            'version': '2.0'
        }]

    def teardown_method(self, method):
        config['compose_stage_dir'] = self._compose_stage_dir
        config['compose_dir'] = self._compose_dir
        config['cache_dir'] = None
        shutil.rmtree(self._new_compose_stage_dir)
        super().teardown_method(method)

    def _verify_updateinfos(self, repodata):
        updateinfos = glob.glob(join(repodata, "*-updateinfo.xml*"))
        if hasattr(createrepo_c, 'ZCK_COMPRESSION'):
            assert len(updateinfos) == 2, f"We generated {len(updateinfos)} updateinfo metadata"
        else:
            assert len(updateinfos) == 1, f"We generated {len(updateinfos)} updateinfo metadata"
        for updateinfo in updateinfos:
            hash = basename(updateinfo).split("-", 1)[0]
            with open(updateinfo, 'rb') as fn:
                hashed = sha256(fn.read()).hexdigest()
            assert hash == hashed, f"File: {basename(updateinfo)}\nHash: {hashed}"

        return updateinfos

    def get_notice(self, uinfo, title):
        for record in uinfo.updates:
            if record.title == title:
                return record

    @mock.patch('bodhi.server.util.log.info')
    def test___init___uses_bz2_for_epel(self, info):
        """Assert that the __init__() method sets the comp_type attribute to cr.BZ2 for EPEL."""
        epel_7 = Release(id_prefix="FEDORA-EPEL", stable_tag='epel7')

        md = UpdateInfoMetadata(epel_7, UpdateRequest.stable, self.db, self.tempdir)

        assert md.comp_type == createrepo_c.BZ2
        assert not md.zchunk
        info.assert_any_call('Using custom createrepo_c config for FEDORA-EPEL.')

    @mock.patch('bodhi.server.util.log.info')
    def test___init___uses_xz_for_epel8(self, info):
        """Assert that the __init__() method sets the comp_type attribute to cr.XZ for EPEL-8."""
        epel_8 = Release(name="EPEL-8", id_prefix="FEDORA-EPEL", stable_tag='epel8')

        md = UpdateInfoMetadata(epel_8, UpdateRequest.stable, self.db, self.tempdir)

        assert md.comp_type == createrepo_c.XZ
        assert not md.zchunk
        info.assert_any_call('Using custom createrepo_c config for EPEL-8.')

    @mock.patch('bodhi.server.util.log.info')
    def test___init___uses_xz_for_fedora(self, info):
        """Assert that the __init__() method sets the comp_type attribute to cr.XZ for Fedora."""
        fedora = Release.query.one()

        md = UpdateInfoMetadata(fedora, UpdateRequest.stable, self.db, self.tempdir)

        assert md.comp_type == createrepo_c.XZ
        assert md.zchunk
        info.assert_any_call('Using createrepo_c defaults config.')

    def test_extended_metadata_once(self):
        """Assert that a single call to update the metadata works as expected."""
        self._test_extended_metadata()

    def test_extended_metadata_cache(self):
        """Asserts that when the same update is retrieved twice, the info is unshelved.

        After the first run, we clear the buildsystem.__rpms__ so that there would be no way to
        again retrieve the info from the buildsystem, and it'll have to be returned from the
        cache.
        """
        self._test_extended_metadata()
        shutil.rmtree(self.temprepo)
        base.mkmetadatadir(self.temprepo, updateinfo=False)
        base.mkmetadatadir(join(self.tempcompdir, 'compose', 'Everything', 'source', 'tree'),
                           updateinfo=False)
        DevBuildsys.__rpms__ = []
        self._test_extended_metadata()

    def _test_extended_metadata(self):
        update = self.db.query(Update).one()

        # Pretend it's pushed to testing
        update.status = UpdateStatus.testing
        update.request = None
        update.date_testing = datetime.now(timezone.utc)
        DevBuildsys.__tagged__[update.title] = ['f17-updates-testing']

        # Generate the XML
        md = UpdateInfoMetadata(update.release, update.request, self.db, self.tempcompdir)

        # Insert the updateinfo.xml into the repository
        md.insert_updateinfo(self.tempcompdir)
        updateinfos = self._verify_updateinfos(self.repodata)

        for updateinfo in updateinfos:
            # Read an verify the updateinfo.xml.gz
            uinfo = createrepo_c.UpdateInfo(updateinfo)
            notice = self.get_notice(uinfo, 'mutt-1.5.14-1.fc13')
            assert notice is None

            assert len(uinfo.updates) == 1
            notice = uinfo.updates[0]

            assert notice is not None
            assert notice.title == update.title
            assert notice.release == update.release.long_name
            assert notice.status == update.status.value
            if update.date_modified:
                assert notice.updated_date == update.date_modified
            assert notice.fromstr == config.get('bodhi_email')
            assert notice.rights == config.get('updateinfo_rights')
            assert notice.description == update.notes
            assert notice.id == update.alias
            assert notice.severity == 'Moderate'
            bug = notice.references[0]
            assert bug.href == update.bugs[0].url
            assert bug.id == '12345'
            assert bug.type == 'bugzilla'

            col = notice.collections[0]
            assert col.name == update.release.long_name
            assert col.shortname == update.release.name

            pkg = col.packages[0]
            assert pkg.epoch == '0'
            assert pkg.name == 'TurboGears'
            assert pkg.src == \
                ('https://download.fedoraproject.org/pub/fedora/linux/updates/testing/17/SRPMS/T/'
                 'TurboGears-1.0.2.2-2.fc17.src.rpm')
            assert pkg.version == '1.0.2.2'
            assert not pkg.reboot_suggested
            assert not pkg.relogin_suggested
            assert pkg.arch == 'src'
            assert pkg.filename == 'TurboGears-1.0.2.2-2.fc17.src.rpm'

    @mock.patch('bodhi.server.metadata.cr')
    def test_zchunk_metadata_coverage_xz_compression(self, mock_cr):
        """
        Let's test that we skip zchunk files, because we don't want to zchunk zchunk files.

        This test makes sure we reach 100% coverage by mocking createrepo.

        cr.ZCK_COMPRESSION is only defined when createrepo_c supports zchunk, but createrepo_c's
        zchunk support is only available in createrepo_c >= 0.12.0, and it is also a build flag,
        so we can't be sure that the createrepo_c we work with has that feature.

        This function is designed to *only* make sure we reach 100% coverage and isn't meant
        to test whether zchunk is working correctly.  _test_extended_metadata will take care
        of testing both the regular and zchunked updateinfo if zchunk is enabled
        """
        mock_cr.ZCK_COMPRESSION = 99
        mock_repomd = mock.MagicMock()
        mock_repomd.xml_dump = mock.MagicMock(return_value="test data")
        mock_cr.Repomd = mock.MagicMock(return_value=mock_repomd)

        bodhi_metadata.insert_in_repo(bodhi_metadata.cr.XZ_COMPRESSION, self.tempcompdir,
                                      'garbage', 'zck', '/dev/null', True)

        mock_cr.Repomd.assert_called_once_with(os.path.join(self.tempcompdir, 'repomd.xml'))
        assert mock_cr.RepomdRecord.mock_calls == \
            [mock.call('garbage', os.path.join(self.tempcompdir, 'garbage.zck')),
             mock.call().compress_and_fill(mock_cr.SHA256, mock_cr.XZ_COMPRESSION),
             mock.call().compress_and_fill().rename_file(),
             mock.call('garbage_zck', os.path.join(self.tempcompdir, 'garbage.zck')),
             mock.call().compress_and_fill(mock_cr.SHA256, mock_cr.ZCK_COMPRESSION),
             mock.call().compress_and_fill().rename_file()]
        rec = mock_cr.RepomdRecord.return_value
        rec_comp = rec.compress_and_fill.return_value
        # The last comp_type added is the _zck one
        assert rec_comp.type == 'garbage_zck'
        assert mock_cr.Repomd.return_value.set_record.mock_calls == \
            [mock.call(rec_comp), mock.call(rec_comp)]

        with open(os.path.join(self.tempcompdir, 'repomd.xml')) as repomd_file:
            repomd_contents = repomd_file.read()

        assert repomd_contents == 'test data'
        assert not os.path.exists(os.path.join(self.tempcompdir, 'garbage.zck'))

    @mock.patch('bodhi.server.metadata.cr')
    def test_zchunk_metadata_coverage_zchunk_skipped(self, mock_cr):
        """
        Let's test that we skip zchunk files, because we don't want to zchunk zchunk files.

        This test makes sure we reach 100% coverage by mocking createrepo.

        cr.ZCK_COMPRESSION is only defined when createrepo_c supports zchunk, but createrepo_c's
        zchunk support is only available in createrepo_c >= 0.12.0, and it is also a build flag,
        so we can't be sure that the createrepo_c we work with has that feature.

        This function is designed to *only* make sure we reach 100% coverage and isn't meant
        to test whether zchunk is working correctly.  _test_extended_metadata will take care
        of testing both the regular and zchunked updateinfo if zchunk is enabled
        """
        mock_cr.ZCK_COMPRESSION = 99
        mock_repomd = mock.MagicMock()
        mock_repomd.xml_dump = mock.MagicMock(return_value="test data")
        mock_cr.Repomd = mock.MagicMock(return_value=mock_repomd)

        bodhi_metadata.insert_in_repo(99, self.tempcompdir, 'garbage', 'zck', '/dev/null', True)

        mock_cr.Repomd.assert_called_once_with(os.path.join(self.tempcompdir, 'repomd.xml'))
        mock_cr.RepomdRecord.assert_called_once_with('garbage',
                                                     os.path.join(self.tempcompdir, 'garbage.zck'))
        rec = mock_cr.RepomdRecord.return_value
        rec.compress_and_fill.assert_called_once_with(mock_cr.SHA256, mock_cr.ZCK_COMPRESSION)
        rec_comp = rec.compress_and_fill.return_value
        rec_comp.rename_file.assert_called_once_with()
        assert rec_comp.type == 'garbage'
        mock_cr.Repomd.return_value.set_record.assert_called_once_with(rec_comp)

        with open(os.path.join(self.tempcompdir, 'repomd.xml')) as repomd_file:
            repomd_contents = repomd_file.read()

        assert repomd_contents == 'test data'
        assert not os.path.exists(os.path.join(self.tempcompdir, 'garbage.zck'))

    @mock.patch('bodhi.server.metadata.cr')
    def test_zchunk_metadata_coverage_zchunk_unsupported(self, mock_cr):
        """
        Let's test that we skip zchunk compression when it is unsupported by createrepo_c.

        This test makes sure we reach 100% coverage by mocking createrepo.

        cr.ZCK_COMPRESSION is only defined when createrepo_c supports zchunk, but createrepo_c's
        zchunk support is only available in createrepo_c >= 0.12.0, and it is also a build flag,
        so we can't be sure that the createrepo_c we work with has that feature.

        This function is designed to *only* make sure we reach 100% coverage and isn't meant
        to test whether zchunk is working correctly.  _test_extended_metadata will take care
        of testing both the regular and zchunked updateinfo if zchunk is enabled
        """
        del mock_cr.ZCK_COMPRESSION
        mock_repomd = mock.MagicMock()
        mock_repomd.xml_dump = mock.MagicMock(return_value="test data")
        mock_cr.Repomd = mock.MagicMock(return_value=mock_repomd)

        bodhi_metadata.insert_in_repo(bodhi_metadata.cr.XZ_COMPRESSION, self.tempcompdir,
                                      'garbage', 'xz', '/dev/null', True)

        mock_cr.Repomd.assert_called_once_with(os.path.join(self.tempcompdir, 'repomd.xml'))
        mock_cr.RepomdRecord.assert_called_once_with('garbage',
                                                     os.path.join(self.tempcompdir, 'garbage.xz'))
        rec = mock_cr.RepomdRecord.return_value
        rec.compress_and_fill.assert_called_once_with(mock_cr.SHA256, mock_cr.XZ_COMPRESSION)
        rec_comp = rec.compress_and_fill.return_value
        rec_comp.rename_file.assert_called_once_with()
        # The last inserted type is without _zck
        assert rec_comp.type == 'garbage'
        mock_cr.Repomd.return_value.set_record.assert_called_once_with(rec_comp)

        with open(os.path.join(self.tempcompdir, 'repomd.xml')) as repomd_file:
            repomd_contents = repomd_file.read()

        assert repomd_contents == 'test data'
        assert not os.path.exists(os.path.join(self.tempcompdir, 'garbage.zck'))
