From e14f963a22bebde41e8ee31371d295c6bbf86a82 Mon Sep 17 00:00:00 2001 From: Nisha Agarwal Date: Tue, 13 Jun 2017 15:42:16 +0000 Subject: [PATCH] Fixes hashing issues for py3.5 This fix uses encoding 'utf-8' before doing hashing. Closes-Bug: 1697719 Co-Authored-By: Vladyslav Drok Change-Id: Ia61bed31ebd98032847504d6c96080330088d9ec --- ironic/common/utils.py | 13 ++++++++++--- ironic/tests/unit/common/test_utils.py | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/ironic/common/utils.py b/ironic/common/utils.py index 1d1b5a6b17..c6085d74ed 100644 --- a/ironic/common/utils.py +++ b/ironic/common/utils.py @@ -281,8 +281,13 @@ def hash_file(file_like_object, hash_algo='md5'): :returns: a condensed digest of the bytes of contents. """ checksum = _get_hash_object(hash_algo) - for chunk in iter(lambda: file_like_object.read(32768), b''): - checksum.update(chunk) + while True: + chunk = file_like_object.read(32768) + if not chunk: + break + encoded_chunk = (chunk.encode(encoding='utf-8') + if isinstance(chunk, six.string_types) else chunk) + checksum.update(encoded_chunk) return checksum.hexdigest() @@ -298,7 +303,9 @@ def file_has_content(path, content, hash_algo='md5'): with open(path, 'rb') as existing: file_hash_hex = hash_file(existing, hash_algo=hash_algo) ref_hash = _get_hash_object(hash_algo) - ref_hash.update(content) + encoded_content = (content.encode(encoding='utf-8') + if isinstance(content, six.string_types) else content) + ref_hash.update(encoded_content) return file_hash_hex == ref_hash.hexdigest() diff --git a/ironic/tests/unit/common/test_utils.py b/ironic/tests/unit/common/test_utils.py index ef040b9143..6c0096eaf2 100644 --- a/ironic/tests/unit/common/test_utils.py +++ b/ironic/tests/unit/common/test_utils.py @@ -127,6 +127,16 @@ class GenericUtilsTestCase(base.TestCase): # | THEN | self.assertEqual(expected, actual) + def test_hash_file_for_md5_not_binary(self): + # | GIVEN | + data = u'Mary had a little lamb, its fleece as white as sno\u0449' + file_like_object = six.StringIO(data) + expected = hashlib.md5(data.encode('utf-8')).hexdigest() + # | WHEN | + actual = utils.hash_file(file_like_object) # using default, 'md5' + # | THEN | + self.assertEqual(expected, actual) + def test_hash_file_for_sha1(self): # | GIVEN | data = b'Mary had a little lamb, its fleece as white as snow' @@ -163,6 +173,14 @@ class GenericUtilsTestCase(base.TestCase): self.assertTrue(utils.file_has_content('foo', ref)) mopen.assert_called_once_with('foo', 'rb') + def test_file_has_content_equal_not_binary(self): + data = u'Mary had a little lamb, its fleece as white as sno\u0449' + ref = data + with mock.patch('ironic.common.utils.open', + mock.mock_open(read_data=data)) as mopen: + self.assertTrue(utils.file_has_content('foo', ref)) + mopen.assert_called_once_with('foo', 'rb') + def test_file_has_content_differ(self): data = b'Mary had a little lamb, its fleece as white as snow' ref = data + b'!'