summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gemato/verify.py44
-rw-r--r--tests/test_verify.py99
2 files changed, 143 insertions, 0 deletions
diff --git a/gemato/verify.py b/gemato/verify.py
index 14052eb..a34264e 100644
--- a/gemato/verify.py
+++ b/gemato/verify.py
@@ -125,6 +125,50 @@ def verify_path(path, e):
return (True, [])
+def verify_entry_compatibility(e1, e2):
+ """
+ Verify that the two entries @e1 and @e2 are compatible.
+
+ If the entries are compatible, returns (True, diff). Otherwise,
+ returns (False, diff). Here diff is a list of differences between
+ @e1 and @e2. Each list element is a tuple of (name, e1, e2).
+
+ In case of successful comparison, the diff may contain additional
+ hashes that are present only in one of the entries.
+ """
+
+ assert e1.path == e2.path
+ assert isinstance(e1, gemato.manifest.ManifestPathEntry)
+ assert isinstance(e2, gemato.manifest.ManifestPathEntry)
+
+ # 1. compare types
+ t1 = e1.tag
+ t2 = e2.tag
+ if t1 != t2:
+ # all those tags have compatible semantics
+ COMPATIBLE_TAGS = ('MANIFEST', 'DATA', 'EBUILD', 'AUX')
+ if t1 not in COMPATIBLE_TAGS or t2 not in COMPATIBLE_TAGS:
+ return (False, [('__type__', t1, t2)])
+
+ # 2. compare sizes
+ if e1.size != e2.size:
+ return (False, [('__size__', e1.size, e2.size)])
+
+ # 3. compare checksums
+ hashes = frozenset(e1.checksums) | frozenset(e2.checksums)
+ ret = True
+ diff = []
+ for h in sorted(hashes):
+ h1 = e1.checksums.get(h)
+ h2 = e2.checksums.get(h)
+ if h1 != h2:
+ diff.append((h, h1, h2))
+ if h1 is not None and h2 is not None:
+ ret = False
+
+ return (ret, diff)
+
+
class ManifestMismatch(Exception):
"""
An exception raised for verification failure.
diff --git a/tests/test_verify.py b/tests/test_verify.py
index 5f3e492..837fa16 100644
--- a/tests/test_verify.py
+++ b/tests/test_verify.py
@@ -435,3 +435,102 @@ class ExceptionVerificationTest(object):
def testNone(self):
self.assertRaises(gemato.verify.ManifestMismatch,
gemato.verify.gemato.verify.assert_path_verifies, self.path, None)
+
+
+class EntryCompatibilityVerificationTest(unittest.TestCase):
+ def test_matching_entry(self):
+ e1 = gemato.manifest.ManifestEntryDATA.from_list(
+ ('DATA', 'test', '0', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ e2 = gemato.manifest.ManifestEntryDATA.from_list(
+ ('DATA', 'test', '0', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ self.assertEqual(gemato.verify.verify_entry_compatibility(e1, e2),
+ (True, []))
+
+ def test_compatible_types(self):
+ e1 = gemato.manifest.ManifestEntryDATA.from_list(
+ ('DATA', 'test', '0', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ e2 = gemato.manifest.ManifestEntryEBUILD.from_list(
+ ('EBUILD', 'test', '0', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ self.assertEqual(gemato.verify.verify_entry_compatibility(e1, e2),
+ (True, []))
+
+ def test_compatible_types_AUX(self):
+ e1 = gemato.manifest.ManifestEntryDATA.from_list(
+ ('DATA', 'files/test.patch', '0', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ e2 = gemato.manifest.ManifestEntryAUX.from_list(
+ ('AUX', 'test.patch', '0', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ self.assertEqual(gemato.verify.verify_entry_compatibility(e1, e2),
+ (True, []))
+
+ def test_compatible_types_MANIFEST(self):
+ e1 = gemato.manifest.ManifestEntryDATA.from_list(
+ ('DATA', 'test', '0', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ e2 = gemato.manifest.ManifestEntryMANIFEST.from_list(
+ ('MANIFEST', 'test', '0', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ self.assertEqual(gemato.verify.verify_entry_compatibility(e1, e2),
+ (True, []))
+
+ def test_incompatible_types_DATA_MISC(self):
+ e1 = gemato.manifest.ManifestEntryDATA.from_list(
+ ('DATA', 'test', '0', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ e2 = gemato.manifest.ManifestEntryMISC.from_list(
+ ('MISC', 'test', '0', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ self.assertEqual(gemato.verify.verify_entry_compatibility(e1, e2),
+ (False, [('__type__', 'DATA', 'MISC')]))
+
+ def test_incompatible_types_DATA_OPTIONAL(self):
+ e1 = gemato.manifest.ManifestEntryDATA.from_list(
+ ('DATA', 'test', '0', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ e2 = gemato.manifest.ManifestEntryOPTIONAL.from_list(
+ ('OPTIONAL', 'test'))
+ self.assertEqual(gemato.verify.verify_entry_compatibility(e1, e2),
+ (False, [('__type__', 'DATA', 'OPTIONAL')]))
+
+ def test_incompatible_types_MISC_OPTIONAL(self):
+ e1 = gemato.manifest.ManifestEntryMISC.from_list(
+ ('MISC', 'test', '0', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ e2 = gemato.manifest.ManifestEntryOPTIONAL.from_list(
+ ('OPTIONAL', 'test'))
+ self.assertEqual(gemato.verify.verify_entry_compatibility(e1, e2),
+ (False, [('__type__', 'MISC', 'OPTIONAL')]))
+
+ def test_incompatible_types_DATA_IGNORE(self):
+ e1 = gemato.manifest.ManifestEntryDATA.from_list(
+ ('DATA', 'test', '0', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ e2 = gemato.manifest.ManifestEntryIGNORE.from_list(
+ ('IGNORE', 'test'))
+ self.assertEqual(gemato.verify.verify_entry_compatibility(e1, e2),
+ (False, [('__type__', 'DATA', 'IGNORE')]))
+
+ def test_incompatible_types_DATA_DIST(self):
+ e1 = gemato.manifest.ManifestEntryDATA.from_list(
+ ('DATA', 'test', '0', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ e2 = gemato.manifest.ManifestEntryDIST.from_list(
+ ('DIST', 'test', '0', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ self.assertEqual(gemato.verify.verify_entry_compatibility(e1, e2),
+ (False, [('__type__', 'DATA', 'DIST')]))
+
+ def test_mismatched_size(self):
+ e1 = gemato.manifest.ManifestEntryDATA.from_list(
+ ('DATA', 'test', '0', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ e2 = gemato.manifest.ManifestEntryDATA.from_list(
+ ('DATA', 'test', '32', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ self.assertEqual(gemato.verify.verify_entry_compatibility(e1, e2),
+ (False, [('__size__', 0, 32)]))
+
+ def test_mismatched_md5(self):
+ e1 = gemato.manifest.ManifestEntryDATA.from_list(
+ ('DATA', 'test', '0', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ e2 = gemato.manifest.ManifestEntryDATA.from_list(
+ ('DATA', 'test', '0', 'MD5', '9e107d9d372bb6826bd81d3542a419d6'))
+ self.assertEqual(gemato.verify.verify_entry_compatibility(e1, e2),
+ (False, [('MD5', 'd41d8cd98f00b204e9800998ecf8427e', '9e107d9d372bb6826bd81d3542a419d6')]))
+
+ def test_different_hashsets(self):
+ e1 = gemato.manifest.ManifestEntryDATA.from_list(
+ ('DATA', 'test', '0', 'MD5', 'd41d8cd98f00b204e9800998ecf8427e'))
+ e2 = gemato.manifest.ManifestEntryDATA.from_list(
+ ('DATA', 'test', '0', 'SHA1', 'da39a3ee5e6b4b0d3255bfef95601890afd80709'))
+ self.assertEqual(gemato.verify.verify_entry_compatibility(e1, e2),
+ (True, [('MD5', 'd41d8cd98f00b204e9800998ecf8427e', None),
+ ('SHA1', None, 'da39a3ee5e6b4b0d3255bfef95601890afd80709')]))