[diffoscope] 01/02: Improve AndroidManifest.xml comparison for APK files.

Maria Glukhova siamezzze-guest at moszumanska.debian.org
Wed Mar 8 00:03:16 CET 2017


This is an automated email from the git hooks/post-receive script.

siamezzze-guest pushed a commit to branch experimental
in repository diffoscope.

commit e8963b4fb6720a29a4e5104eda81c83d525842de
Author: Maria Glukhova <siamezzze at gmail.com>
Date:   Mon Mar 6 05:54:08 2017 +0200

    Improve AndroidManifest.xml comparison for APK files.
    
    Instead of comparing both decoded and undecoded AndroidManifest.xml file,
    try to first compare decoded one and resort to comparing undecoded ones
    only if no difference found in the former.
---
 diffoscope/comparators/apk.py |  53 ++++++++++++++++++++++++++++++++++++++++++
 tests/comparators/test_apk.py |  29 +++++++++++++++++++----
 tests/data/test3.apk          | Bin 0 -> 571 bytes
 3 files changed, 77 insertions(+), 5 deletions(-)

diff --git a/diffoscope/comparators/apk.py b/diffoscope/comparators/apk.py
index 65e9773..fc0b5f1 100644
--- a/diffoscope/comparators/apk.py
+++ b/diffoscope/comparators/apk.py
@@ -28,7 +28,9 @@ from diffoscope.difference import Difference
 
 from .utils.file import File
 from .utils.archive import Archive
+from .utils.compare import compare_files
 from .zip import Zipinfo, ZipinfoVerbose
+from .missing_file import MissingFile
 
 logger = logging.getLogger(__name__)
 
@@ -45,6 +47,8 @@ class ApkContainer(Archive):
             get_temporary_directory().name,
             os.path.basename(self.source.name),
         )
+        self._andmanifest = None
+        self._andmanifest_orig = None
 
         logger.debug("Extracting %s to %s", self.source.name, self._unpacked)
 
@@ -72,12 +76,30 @@ class ApkContainer(Archive):
                     continue
 
                 relpath = abspath[len(self._unpacked)+1:]
+
+                if filename == 'AndroidManifest.xml':
+                    containing_dir = root[len(self._unpacked)+1:]
+                    if containing_dir == 'original':
+                        self._andmanifest_orig = relpath
+                    if containing_dir == '':
+                        self._andmanifest = relpath
+                    continue
+
                 current_dir.append(relpath)
 
             self._members.extend(current_dir)
 
         return self
 
+    def get_android_manifest(self):
+        return self.get_member(self._andmanifest) \
+            if self._andmanifest else None
+
+    def get_original_android_manifest(self):
+        if self._andmanifest_orig:
+            return self.get_member(self._andmanifest_orig)
+        return MissingFile('/dev/null', self._andmanifest_orig)
+
     def close_archive(self):
         pass
 
@@ -88,6 +110,37 @@ class ApkContainer(Archive):
         src_path = os.path.join(self._unpacked, member_name)
         return src_path
 
+    def compare_manifests(self, other):
+        my_android_manifest = self.get_android_manifest()
+        other_android_manifest = other.get_android_manifest()
+        comment = None
+        diff_manifests = None
+        if my_android_manifest and other_android_manifest:
+            diff_manifests = compare_files(my_android_manifest,
+                                           other_android_manifest)
+            if diff_manifests is None:
+                comment = 'No difference found for decoded AndroidManifest.xml'
+        else:
+            comment = 'No decoded AndroidManifest.xml found ' + \
+                      'for one of the APK files.'
+        if diff_manifests:
+            return diff_manifests
+
+        diff_manifests = compare_files(self.get_original_android_manifest(),
+                                       other.get_original_android_manifest())
+        if diff_manifests is not None:
+            diff_manifests.add_comment(comment)
+        return diff_manifests
+
+    def compare(self, other, source=None):
+        differences = []
+        try:
+            differences.append(self.compare_manifests(other))
+        except AttributeError:  # no apk-specific methods, e.g. MissingArchive
+            pass
+        differences.extend(super().compare(other, source=source))
+        return differences
+
 class ApkFile(File):
     RE_FILE_TYPE = re.compile(r'^(Java|Zip) archive data.*\b')
     RE_FILE_EXTENSION = re.compile(r'\.apk$')
diff --git a/tests/comparators/test_apk.py b/tests/comparators/test_apk.py
index 77b3648..262cf47 100644
--- a/tests/comparators/test_apk.py
+++ b/tests/comparators/test_apk.py
@@ -27,6 +27,7 @@ from utils.nonexisting import assert_non_existing
 
 apk1 = load_fixture('test1.apk')
 apk2 = load_fixture('test2.apk')
+apk3 = load_fixture('test3.apk')
 
 def test_identification(apk1):
     assert isinstance(apk1, ApkFile)
@@ -39,6 +40,10 @@ def test_no_differences(apk1):
 def differences(apk1, apk2):
     return apk1.compare(apk2).details
 
+ at pytest.fixture
+def differences2(apk1, apk3):
+    return apk1.compare(apk3).details
+
 @skip_unless_tools_exist('apktool', 'zipinfo')
 def test_compare_non_existing(monkeypatch, apk1):
     assert_non_existing(monkeypatch, apk1)
@@ -52,12 +57,26 @@ def test_zipinfo(differences):
 
 @skip_unless_tools_exist('apktool', 'zipinfo')
 def test_android_manifest(differences):
-    assert differences[2].source1 == 'AndroidManifest.xml'
-    assert differences[2].source2 == 'AndroidManifest.xml'
+    assert differences[1].source1 == 'AndroidManifest.xml'
+    assert differences[1].source2 == 'AndroidManifest.xml'
     expected_diff = get_data('apk_manifest_expected_diff')
-    assert differences[2].unified_diff == expected_diff
+    assert differences[1].unified_diff == expected_diff
 
 @skip_unless_tools_exist('apktool', 'zipinfo')
 def test_apk_metadata_source(differences):
-    assert differences[1].source1 == 'APK metadata'
-    assert differences[1].source2 == 'APK metadata'
+    assert differences[2].source1 == 'APK metadata'
+    assert differences[2].source2 == 'APK metadata'
+
+ at skip_unless_tools_exist('apktool', 'zipinfo')
+def test_skip_undecoded_android_manifest(differences):
+    assert not any(difference.source1 == 'original/AndroidManifest.xml'
+                   for difference in differences)
+    assert not any(difference.source2 == 'original/AndroidManifest.xml'
+                   for difference in differences)
+
+ at skip_unless_tools_exist('apktool', 'zipinfo')
+def test_no_android_manifest(differences2):
+    assert differences2[1].source1 == 'original/AndroidManifest.xml'
+    assert differences2[1].source2 == '/dev/null'
+    assert differences2[1].comment == 'No decoded AndroidManifest.xml ' \
+                                      'found for one of the APK files.'
diff --git a/tests/data/test3.apk b/tests/data/test3.apk
new file mode 100644
index 0000000..ff852cf
Binary files /dev/null and b/tests/data/test3.apk differ

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/diffoscope.git


More information about the diffoscope mailing list