summaryrefslogtreecommitdiff
path: root/deps/v8/build/android/convert_dex_profile_tests.py
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/build/android/convert_dex_profile_tests.py')
-rw-r--r--deps/v8/build/android/convert_dex_profile_tests.py276
1 files changed, 276 insertions, 0 deletions
diff --git a/deps/v8/build/android/convert_dex_profile_tests.py b/deps/v8/build/android/convert_dex_profile_tests.py
new file mode 100644
index 0000000000..0ddc5ce4a1
--- /dev/null
+++ b/deps/v8/build/android/convert_dex_profile_tests.py
@@ -0,0 +1,276 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Tests for convert_dex_profile.
+
+Can be run from build/android/:
+ $ cd build/android
+ $ python convert_dex_profile_tests.py
+"""
+
+import os
+import sys
+import tempfile
+import unittest
+
+import convert_dex_profile as cp
+
+sys.path.insert(1, os.path.join(os.path.dirname(__file__), 'gyp'))
+from util import build_utils
+
+cp.logging.disable(cp.logging.CRITICAL)
+
+# There are two obfuscations used in the tests below, each with the same
+# unobfuscated profile. The first, corresponding to DEX_DUMP, PROGUARD_MAPPING,
+# and OBFUSCATED_PROFILE, has an ambiguous method a() which is mapped to both
+# getInstance and initialize. The second, corresponding to DEX_DUMP_2,
+# PROGUARD_MAPPING_2 and OBFUSCATED_PROFILE_2, removes the ambiguity.
+
+DEX_DUMP = """
+
+Class descriptor : 'La;'
+ Direct methods -
+ #0 : (in La;)
+ name : '<clinit>'
+ type : '(Ljava/lang/String;)V'
+ code -
+ catches : 1
+ 0x000f - 0x001e
+ <any> -> 0x0093
+ positions :
+ 0x0001 line=310
+ 0x0057 line=313
+ locals :
+ #1 : (in La;)
+ name : '<init>'
+ type : '()V'
+ positions :
+ locals :
+ Virtual methods -
+ #0 : (in La;)
+ name : 'a'
+ type : '(Ljava/lang/String;)I'
+ positions :
+ 0x0000 line=2
+ 0x0003 line=3
+ 0x001b line=8
+ locals :
+ 0x0000 - 0x0021 reg=3 this La;
+ #1 : (in La;)
+ name : 'a'
+ type : '(Ljava/lang/Object;)I'
+ positions :
+ 0x0000 line=8
+ 0x0003 line=9
+ locals :
+ 0x0000 - 0x0021 reg=3 this La;
+ #2 : (in La;)
+ name : 'b'
+ type : '()La;'
+ positions :
+ 0x0000 line=1
+ locals :
+"""
+
+# pylint: disable=line-too-long
+PROGUARD_MAPPING = \
+"""org.chromium.Original -> a:
+ org.chromium.Original sDisplayAndroidManager -> e
+ org.chromium.Original another() -> b
+ 4:4:void inlined():237:237 -> a
+ 4:4:org.chromium.Original getInstance():203 -> a
+ 5:5:void org.chromium.Original$Subclass.<init>(org.chromium.Original,byte):130:130 -> a
+ 5:5:void initialize():237 -> a
+ 5:5:org.chromium.Original getInstance():203 -> a
+ 6:6:void initialize():237:237 -> a
+ 9:9:android.content.Context org.chromium.base.ContextUtils.getApplicationContext():49:49 -> a
+ 9:9:android.content.Context getContext():219 -> a
+ 9:9:void initialize():245 -> a
+ 9:9:org.chromium.Original getInstance():203 -> a"""
+
+OBFUSCATED_PROFILE = \
+"""La;
+PLa;->b()La;
+SLa;->a(Ljava/lang/Object;)I
+HPLa;->a(Ljava/lang/String;)I"""
+
+DEX_DUMP_2 = """
+
+Class descriptor : 'La;'
+ Direct methods -
+ #0 : (in La;)
+ name : '<clinit>'
+ type : '(Ljava/lang/String;)V'
+ code -
+ catches : 1
+ 0x000f - 0x001e
+ <any> -> 0x0093
+ positions :
+ 0x0001 line=310
+ 0x0057 line=313
+ locals :
+ #1 : (in La;)
+ name : '<init>'
+ type : '()V'
+ positions :
+ locals :
+ Virtual methods -
+ #0 : (in La;)
+ name : 'a'
+ type : '(Ljava/lang/String;)I'
+ positions :
+ 0x0000 line=2
+ 0x0003 line=3
+ 0x001b line=8
+ locals :
+ 0x0000 - 0x0021 reg=3 this La;
+ #1 : (in La;)
+ name : 'c'
+ type : '(Ljava/lang/Object;)I'
+ positions :
+ 0x0000 line=8
+ 0x0003 line=9
+ locals :
+ 0x0000 - 0x0021 reg=3 this La;
+ #2 : (in La;)
+ name : 'b'
+ type : '()La;'
+ positions :
+ 0x0000 line=1
+ locals :
+"""
+
+# pylint: disable=line-too-long
+PROGUARD_MAPPING_2 = \
+"""org.chromium.Original -> a:
+ org.chromium.Original sDisplayAndroidManager -> e
+ org.chromium.Original another() -> b
+ void initialize() -> c
+ org.chromium.Original getInstance():203 -> a
+ 4:4:void inlined():237:237 -> a"""
+
+OBFUSCATED_PROFILE_2 = \
+"""La;
+PLa;->b()La;
+HPSLa;->a()La;
+HPLa;->c()V"""
+
+UNOBFUSCATED_PROFILE = \
+"""Lorg/chromium/Original;
+PLorg/chromium/Original;->another()Lorg/chromium/Original;
+HPSLorg/chromium/Original;->getInstance()Lorg/chromium/Original;
+HPLorg/chromium/Original;->initialize()V"""
+
+class GenerateProfileTests(unittest.TestCase):
+ def testProcessDex(self):
+ dex = cp.ProcessDex(DEX_DUMP.splitlines())
+ self.assertIsNotNone(dex['a'])
+
+ self.assertEquals(len(dex['a'].FindMethodsAtLine('<clinit>', 311, 313)), 1)
+ self.assertEquals(len(dex['a'].FindMethodsAtLine('<clinit>', 309, 315)), 1)
+ clinit = dex['a'].FindMethodsAtLine('<clinit>', 311, 313)[0]
+ self.assertEquals(clinit.name, '<clinit>')
+ self.assertEquals(clinit.return_type, 'V')
+ self.assertEquals(clinit.param_types, 'Ljava/lang/String;')
+
+ self.assertEquals(len(dex['a'].FindMethodsAtLine('a', 8, None)), 2)
+ self.assertIsNone(dex['a'].FindMethodsAtLine('a', 100, None))
+
+# pylint: disable=protected-access
+ def testProcessProguardMapping(self):
+ dex = cp.ProcessDex(DEX_DUMP.splitlines())
+ mapping, reverse = cp.ProcessProguardMapping(
+ PROGUARD_MAPPING.splitlines(), dex)
+
+ self.assertEquals('La;', reverse.GetClassMapping('Lorg/chromium/Original;'))
+
+ getInstance = cp.Method(
+ 'getInstance', 'Lorg/chromium/Original;', '', 'Lorg/chromium/Original;')
+ initialize = cp.Method('initialize', 'Lorg/chromium/Original;', '', 'V')
+ another = cp.Method(
+ 'another', 'Lorg/chromium/Original;', '', 'Lorg/chromium/Original;')
+ subclassInit = cp.Method(
+ '<init>', 'Lorg/chromium/Original$Subclass;',
+ 'Lorg/chromium/Original;B', 'V')
+
+ mapped = mapping.GetMethodMapping(
+ cp.Method('a', 'La;', 'Ljava/lang/String;', 'I'))
+ self.assertEquals(len(mapped), 2)
+ self.assertIn(getInstance, mapped)
+ self.assertNotIn(subclassInit, mapped)
+ self.assertNotIn(
+ cp.Method('inlined', 'Lorg/chromium/Original;', '', 'V'), mapped)
+ self.assertIn(initialize, mapped)
+
+ mapped = mapping.GetMethodMapping(
+ cp.Method('a', 'La;', 'Ljava/lang/Object;', 'I'))
+ self.assertEquals(len(mapped), 1)
+ self.assertIn(getInstance, mapped)
+
+ mapped = mapping.GetMethodMapping(cp.Method('b', 'La;', '', 'La;'))
+ self.assertEquals(len(mapped), 1)
+ self.assertIn(another, mapped)
+
+ for from_method, to_methods in mapping._method_mapping.iteritems():
+ for to_method in to_methods:
+ self.assertIn(from_method, reverse.GetMethodMapping(to_method))
+ for from_class, to_class in mapping._class_mapping.iteritems():
+ self.assertEquals(from_class, reverse.GetClassMapping(to_class))
+
+ def testProcessProfile(self):
+ dex = cp.ProcessDex(DEX_DUMP.splitlines())
+ mapping, _ = cp.ProcessProguardMapping(PROGUARD_MAPPING.splitlines(), dex)
+ profile = cp.ProcessProfile(OBFUSCATED_PROFILE.splitlines(), mapping)
+
+ getInstance = cp.Method(
+ 'getInstance', 'Lorg/chromium/Original;', '', 'Lorg/chromium/Original;')
+ initialize = cp.Method('initialize', 'Lorg/chromium/Original;', '', 'V')
+ another = cp.Method(
+ 'another', 'Lorg/chromium/Original;', '', 'Lorg/chromium/Original;')
+
+ self.assertIn('Lorg/chromium/Original;', profile._classes)
+ self.assertIn(getInstance, profile._methods)
+ self.assertIn(initialize, profile._methods)
+ self.assertIn(another, profile._methods)
+
+ self.assertEquals(profile._methods[getInstance], set(['H', 'S', 'P']))
+ self.assertEquals(profile._methods[initialize], set(['H', 'P']))
+ self.assertEquals(profile._methods[another], set(['P']))
+
+ def testEndToEnd(self):
+ dex = cp.ProcessDex(DEX_DUMP.splitlines())
+ mapping, _ = cp.ProcessProguardMapping(PROGUARD_MAPPING.splitlines(), dex)
+
+ profile = cp.ProcessProfile(OBFUSCATED_PROFILE.splitlines(), mapping)
+ with tempfile.NamedTemporaryFile() as temp:
+ profile.WriteToFile(temp.name)
+ with open(temp.name, 'r') as f:
+ for a, b in zip(sorted(f), sorted(UNOBFUSCATED_PROFILE.splitlines())):
+ self.assertEquals(a.strip(), b.strip())
+
+ def testObfuscateProfile(self):
+ with build_utils.TempDir() as temp_dir:
+ # The dex dump is used as the dexfile, by passing /bin/cat as the dexdump
+ # program.
+ dex_path = os.path.join(temp_dir, 'dexdump')
+ with open(dex_path, 'w') as dex_file:
+ dex_file.write(DEX_DUMP_2)
+ mapping_path = os.path.join(temp_dir, 'mapping')
+ with open(mapping_path, 'w') as mapping_file:
+ mapping_file.write(PROGUARD_MAPPING_2)
+ unobfuscated_path = os.path.join(temp_dir, 'unobfuscated')
+ with open(unobfuscated_path, 'w') as unobfuscated_file:
+ unobfuscated_file.write(UNOBFUSCATED_PROFILE)
+ obfuscated_path = os.path.join(temp_dir, 'obfuscated')
+ cp.ObfuscateProfile(unobfuscated_path, dex_path, mapping_path, '/bin/cat',
+ obfuscated_path)
+ with open(obfuscated_path) as obfuscated_file:
+ obfuscated_profile = sorted(obfuscated_file.readlines())
+ for a, b in zip(
+ sorted(OBFUSCATED_PROFILE_2.splitlines()), obfuscated_profile):
+ self.assertEquals(a.strip(), b.strip())
+
+
+if __name__ == '__main__':
+ unittest.main()