1 #!/usr/bin/env python3 2 3 from __future__ import print_function 4 5 import os 6 import subprocess 7 import sys 8 import unittest 9 import zipfile 10 11 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 12 13 from compat import TemporaryDirectory 14 from vndk_definition_tool import DexFileReader 15 16 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) 17 INPUT_DIR = os.path.join(SCRIPT_DIR, 'testdata', 'test_dex_file') 18 19 20 class ModifiedUTF8Test(unittest.TestCase): 21 def test_encode(self): 22 self.assertEqual(b'\xc0\x80', u'\u0000'.encode('mutf-8')) 23 self.assertEqual(b'\x09', u'\u0009'.encode('mutf-8')) 24 self.assertEqual(b'\x7f', u'\u007f'.encode('mutf-8')) 25 self.assertEqual(b'\xc2\x80', u'\u0080'.encode('mutf-8')) 26 self.assertEqual(b'\xdf\xbf', u'\u07ff'.encode('mutf-8')) 27 self.assertEqual(b'\xe0\xa0\x80', u'\u0800'.encode('mutf-8')) 28 self.assertEqual(b'\xe7\xbf\xbf', u'\u7fff'.encode('mutf-8')) 29 self.assertEqual(b'\xed\xa0\x81\xed\xb0\x80', 30 u'\U00010400'.encode('mutf-8')) 31 32 33 def test_decode(self): 34 self.assertEqual(u'\u0000', b'\xc0\x80'.decode('mutf-8')) 35 self.assertEqual(u'\u0009', b'\x09'.decode('mutf-8')) 36 self.assertEqual(u'\u007f', b'\x7f'.decode('mutf-8')) 37 self.assertEqual(u'\u0080', b'\xc2\x80'.decode('mutf-8')) 38 self.assertEqual(u'\u07ff', b'\xdf\xbf'.decode('mutf-8')) 39 self.assertEqual(u'\u0800', b'\xe0\xa0\x80'.decode('mutf-8')) 40 self.assertEqual(u'\u7fff', b'\xe7\xbf\xbf'.decode('mutf-8')) 41 self.assertEqual(u'\U00010400', 42 b'\xed\xa0\x81\xed\xb0\x80'.decode('mutf-8')) 43 44 45 class DexFileTest(unittest.TestCase): 46 def _assemble_smali(self, dest, source): 47 """Assemble a smali source file. Skip the test if the smali command is 48 unavailable.""" 49 try: 50 subprocess.check_call(['smali', 'a', source, '-o', dest]) 51 except IOError: 52 self.skipTest('smali not available') 53 54 55 def _create_zip_file(self, dest, paths): 56 """Create a zip file from several input files.""" 57 with zipfile.ZipFile(dest, 'w') as zip_file: 58 for path in paths: 59 zip_file.write(path, os.path.basename(path)) 60 61 62 def test_generate_classes_dex_names(self): 63 seq = DexFileReader.generate_classes_dex_names() 64 self.assertEqual('classes.dex', next(seq)) 65 self.assertEqual('classes2.dex', next(seq)) 66 self.assertEqual('classes3.dex', next(seq)) 67 68 69 def test_enumerate_dex_strings_buf(self): 70 with TemporaryDirectory() as tmp_dir: 71 smali_file = os.path.join(INPUT_DIR, 'Hello.smali') 72 classes_dex = os.path.join(tmp_dir, 'classes.dex') 73 self._assemble_smali(classes_dex, smali_file) 74 75 with open(classes_dex, 'rb') as classes_dex: 76 buf = classes_dex.read() 77 78 strs = set(DexFileReader.enumerate_dex_strings_buf(buf)) 79 80 self.assertIn('hello', strs) 81 self.assertIn('world', strs) 82 83 84 def test_enumerate_dex_strings_apk(self): 85 with TemporaryDirectory() as tmp_dir: 86 smali_file = os.path.join(INPUT_DIR, 'Hello.smali') 87 classes_dex = os.path.join(tmp_dir, 'classes.dex') 88 self._assemble_smali(classes_dex, smali_file) 89 90 smali_file = os.path.join(INPUT_DIR, 'Example.smali') 91 classes2_dex = os.path.join(tmp_dir, 'classes2.dex') 92 self._assemble_smali(classes2_dex, smali_file) 93 94 zip_file = os.path.join(tmp_dir, 'example.apk') 95 self._create_zip_file(zip_file, [classes_dex, classes2_dex]) 96 97 strs = set(DexFileReader.enumerate_dex_strings_apk(zip_file)) 98 99 self.assertIn('hello', strs) 100 self.assertIn('world', strs) 101 self.assertIn('foo', strs) 102 self.assertIn('bar', strs) 103 104 105 if __name__ == '__main__': 106 unittest.main() 107