# -*- coding: utf-8 -*- try: import unittest2 as unittest except ImportError: import unittest from unittest import mock import os import tempfile import shutil from pungi.phases.image_checksum import ImageChecksumPhase, dump_checksums from tests.helpers import DummyCompose, PungiTestCase class TestImageChecksumPhase(PungiTestCase): def test_phase_is_never_skipped(self): compose = DummyCompose(self.topdir, {}) phase = ImageChecksumPhase(compose) self.assertFalse(phase.skip()) def test_config_skip_individual_with_multiple_algorithms(self): compose = DummyCompose( self.topdir, {"media_checksums": ["md5", "sha1"], "media_checksum_one_file": True}, ) phase = ImageChecksumPhase(compose) with self.assertRaises(ValueError) as ctx: phase.validate() self.assertIn("media_checksum_one_file", str(ctx.exception)) @mock.patch("os.path.exists") @mock.patch("kobo.shortcuts.compute_file_checksums") @mock.patch("pungi.phases.image_checksum.dump_checksums") def test_checksum_one_file(self, dump_checksums, cc, exists): compose = DummyCompose( self.topdir, {"media_checksums": ["sha256"], "media_checksum_one_file": True}, ) phase = ImageChecksumPhase(compose) exists.return_value = True cc.return_value = {"sha256": "cafebabe"} phase.run() dump_checksums.assert_called_once_with( self.topdir + "/compose/Client/i386/iso/CHECKSUM", set([("image.iso", 123, "sha256", "cafebabe")]), ) cc.assert_called_once_with( self.topdir + "/compose/Client/i386/iso/image.iso", ["sha256"] ) compose.image.add_checksum.assert_called_once_with(None, "sha256", "cafebabe") @mock.patch("os.path.exists") @mock.patch("kobo.shortcuts.compute_file_checksums") @mock.patch("pungi.phases.image_checksum.dump_checksums") def test_checksum_save_individuals(self, dump_checksums, cc, exists): compose = DummyCompose(self.topdir, {"media_checksums": ["md5", "sha256"]}) phase = ImageChecksumPhase(compose) exists.return_value = True cc.return_value = {"md5": "cafebabe", "sha256": "deadbeef"} phase.run() dump_checksums.assert_has_calls( [ mock.call( self.topdir + "/compose/Client/i386/iso/image.iso.MD5SUM", set([("image.iso", 123, "md5", "cafebabe")]), ), mock.call( self.topdir + "/compose/Client/i386/iso/image.iso.SHA256SUM", set([("image.iso", 123, "sha256", "deadbeef")]), ), mock.call( self.topdir + "/compose/Client/i386/iso/MD5SUM", set([("image.iso", 123, "md5", "cafebabe")]), ), mock.call( self.topdir + "/compose/Client/i386/iso/SHA256SUM", set([("image.iso", 123, "sha256", "deadbeef")]), ), ], any_order=True, ) cc.assert_called_once_with( self.topdir + "/compose/Client/i386/iso/image.iso", ["md5", "sha256"] ) compose.image.add_checksum.assert_has_calls( [mock.call(None, "sha256", "deadbeef"), mock.call(None, "md5", "cafebabe")], any_order=True, ) @mock.patch("os.path.exists") @mock.patch("kobo.shortcuts.compute_file_checksums") @mock.patch("pungi.phases.image_checksum.dump_checksums") def test_checksum_one_file_custom_name(self, dump_checksums, cc, exists): compose = DummyCompose( self.topdir, { "media_checksums": ["sha256"], "media_checksum_one_file": True, "media_checksum_base_filename": "%(release_short)s-%(variant)s-%(version)s-%(date)s%(type_suffix)s.%(respin)s_%(label)s-%(dirname)s", # noqa: E501 }, ) compose.compose_label = "Alpha-1.0" phase = ImageChecksumPhase(compose) exists.return_value = True cc.return_value = {"sha256": "cafebabe"} phase.run() dump_checksums.assert_called_once_with( self.topdir + "/compose/Client/i386/iso/test-Client-1.0-20151203.t.0_Alpha-1.0-iso-CHECKSUM", # noqa: E501 set([("image.iso", 123, "sha256", "cafebabe")]), ) cc.assert_called_once_with( self.topdir + "/compose/Client/i386/iso/image.iso", ["sha256"] ) compose.image.add_checksum.assert_called_once_with(None, "sha256", "cafebabe") @mock.patch("os.path.exists") @mock.patch("kobo.shortcuts.compute_file_checksums") @mock.patch("pungi.phases.image_checksum.dump_checksums") def test_checksum_save_individuals_custom_name(self, dump_checksums, cc, exists): compose = DummyCompose( self.topdir, { "media_checksums": ["md5", "sha256"], "media_checksum_base_filename": "%(release_short)s-%(variant)s-%(version)s-%(date)s%(type_suffix)s.%(respin)s", # noqa: E501 }, ) phase = ImageChecksumPhase(compose) exists.return_value = True cc.return_value = {"md5": "cafebabe", "sha256": "deadbeef"} phase.run() dump_checksums.assert_has_calls( [ mock.call( self.topdir + "/compose/Client/i386/iso/image.iso.MD5SUM", set([("image.iso", 123, "md5", "cafebabe")]), ), mock.call( self.topdir + "/compose/Client/i386/iso/image.iso.SHA256SUM", set([("image.iso", 123, "sha256", "deadbeef")]), ), mock.call( self.topdir + "/compose/Client/i386/iso/test-Client-1.0-20151203.t.0-MD5SUM", set([("image.iso", 123, "md5", "cafebabe")]), ), mock.call( self.topdir + "/compose/Client/i386/iso/test-Client-1.0-20151203.t.0-SHA256SUM", set([("image.iso", 123, "sha256", "deadbeef")]), ), ], any_order=True, ) cc.assert_called_once_with( self.topdir + "/compose/Client/i386/iso/image.iso", ["md5", "sha256"] ) compose.image.add_checksum.assert_has_calls( [mock.call(None, "sha256", "deadbeef"), mock.call(None, "md5", "cafebabe")], any_order=True, ) @mock.patch("os.path.exists") @mock.patch("kobo.shortcuts.compute_file_checksums") @mock.patch("pungi.phases.image_checksum.dump_checksums") def test_checksum_save_individuals_custom_name_str_format( self, dump_checksums, cc, exists ): compose = DummyCompose( self.topdir, { "media_checksums": ["md5", "sha256"], "media_checksum_base_filename": "{release_short}-{variant}-{version}-{date}{type_suffix}.{respin}", # noqa: E501 }, ) phase = ImageChecksumPhase(compose) exists.return_value = True cc.return_value = {"md5": "cafebabe", "sha256": "deadbeef"} phase.run() dump_checksums.assert_has_calls( [ mock.call( self.topdir + "/compose/Client/i386/iso/image.iso.MD5SUM", set([("image.iso", 123, "md5", "cafebabe")]), ), mock.call( self.topdir + "/compose/Client/i386/iso/image.iso.SHA256SUM", set([("image.iso", 123, "sha256", "deadbeef")]), ), mock.call( self.topdir + "/compose/Client/i386/iso/test-Client-1.0-20151203.t.0-MD5SUM", set([("image.iso", 123, "md5", "cafebabe")]), ), mock.call( self.topdir + "/compose/Client/i386/iso/test-Client-1.0-20151203.t.0-SHA256SUM", set([("image.iso", 123, "sha256", "deadbeef")]), ), ], any_order=True, ) cc.assert_called_once_with( self.topdir + "/compose/Client/i386/iso/image.iso", ["md5", "sha256"] ) compose.image.add_checksum.assert_has_calls( [mock.call(None, "sha256", "deadbeef"), mock.call(None, "md5", "cafebabe")], any_order=True, ) class TestDumpChecksums(unittest.TestCase): def setUp(self): self.tmp_dir = tempfile.mkdtemp() def tearDown(self): shutil.rmtree(self.tmp_dir) def test_dump_checksums(self): dump_checksums( os.path.join(self.tmp_dir, "CHECKSUM"), [ ("file2.iso", 456, "md5", "cafebabe"), ("file1.iso", 123, "md5", "abcdef"), ], ) with open(os.path.join(self.tmp_dir, "CHECKSUM"), "r") as f: data = f.read().rstrip().split("\n") expected = [ "# file1.iso: 123 bytes", "MD5 (file1.iso) = abcdef", "# file2.iso: 456 bytes", "MD5 (file2.iso) = cafebabe", ] self.assertEqual(expected, data)