1#! /usr/bin/env vpython3 2# Copyright 2016 The Chromium Authors 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6import unittest 7from xml.etree import ElementTree 8 9from pylib.utils import dexdump 10 11# pylint: disable=protected-access 12 13emptyAnnotations = dexdump.Annotations(classAnnotations={}, 14 methodsAnnotations={}) 15 16 17class DexdumpXMLParseTest(unittest.TestCase): 18 19 def testParseAnnotations(self): 20 example_xml_string = ( 21 '<package name="com.foo.bar">\n' 22 'Class #1 annotations:\n' 23 'Annotations on class\n' 24 ' VISIBILITY_RUNTIME Ldalvik/annotation/AppModeFull; value=Alpha\n' 25 'Annotations on method #512 \'example\'\n' 26 ' VISIBILITY_SYSTEM Ldalvik/annotation/Signature; value=Bravo\n' 27 ' VISIBILITY_RUNTIME Ldalvik/annotation/Test;\n' 28 ' VISIBILITY_RUNTIME Ldalvik/annotation/Test2; value=Charlie\n' 29 ' VISIBILITY_RUNTIME Ldalvik/annotation/Test3; A=B x B={ C D }\n' 30 ' VISIBILITY_RUNTIME Ldalvik/annotation/Test4; A=B x B={ C D } C=D\n' 31 '<class name="Class1" extends="java.lang.Object">\n' 32 '</class>\n' 33 '<class name="Class2" extends="java.lang.Object">\n' 34 '</class>\n' 35 '</package>\n') 36 37 actual = dexdump._ParseAnnotations(example_xml_string) 38 39 expected = { 40 1: 41 dexdump.Annotations( 42 classAnnotations={'AppModeFull': { 43 'value': 'Alpha' 44 }}, 45 methodsAnnotations={ 46 'example': { 47 'Test': None, 48 'Test2': { 49 'value': 'Charlie' 50 }, 51 'Test3': { 52 'A': 'B x', 53 'B': ['C', 'D'] 54 }, 55 'Test4': { 56 'A': 'B x', 57 'B': ['C', 'D'], 58 'C': 'D' 59 }, 60 } 61 }, 62 ) 63 } 64 65 self.assertEqual(expected, actual) 66 67 def testParseRootXmlNode(self): 68 example_xml_string = ('<api>' 69 '<package name="com.foo.bar1">' 70 '<class' 71 ' name="Class1"' 72 ' extends="java.lang.Object"' 73 ' abstract="false"' 74 ' static="false"' 75 ' final="true"' 76 ' visibility="public">' 77 '<method' 78 ' name="class1Method1"' 79 ' return="java.lang.String"' 80 ' abstract="false"' 81 ' native="false"' 82 ' synchronized="false"' 83 ' static="false"' 84 ' final="false"' 85 ' visibility="public">' 86 '</method>' 87 '<method' 88 ' name="class1Method2"' 89 ' return="viod"' 90 ' abstract="false"' 91 ' native="false"' 92 ' synchronized="false"' 93 ' static="false"' 94 ' final="false"' 95 ' visibility="public">' 96 '</method>' 97 '</class>' 98 '<class' 99 ' name="Class2"' 100 ' extends="java.lang.Object"' 101 ' abstract="true"' 102 ' static="false"' 103 ' final="true"' 104 ' visibility="public">' 105 '<method' 106 ' name="class2Method1"' 107 ' return="java.lang.String"' 108 ' abstract="false"' 109 ' native="false"' 110 ' synchronized="false"' 111 ' static="false"' 112 ' final="false"' 113 ' visibility="public">' 114 '</method>' 115 '</class>' 116 '</package>' 117 '<package name="com.foo.bar2">' 118 '</package>' 119 '<package name="com.foo.bar3">' 120 '</package>' 121 '</api>') 122 123 actual = dexdump._ParseRootNode(ElementTree.fromstring(example_xml_string), 124 {}) 125 126 expected = { 127 'com.foo.bar1': { 128 'classes': { 129 'Class1': { 130 'methods': ['class1Method1', 'class1Method2'], 131 'superclass': 'java.lang.Object', 132 'is_abstract': False, 133 'annotations': emptyAnnotations, 134 }, 135 'Class2': { 136 'methods': ['class2Method1'], 137 'superclass': 'java.lang.Object', 138 'is_abstract': True, 139 'annotations': emptyAnnotations, 140 } 141 }, 142 }, 143 'com.foo.bar2': { 144 'classes': {} 145 }, 146 'com.foo.bar3': { 147 'classes': {} 148 }, 149 } 150 self.assertEqual(expected, actual) 151 152 def testParsePackageNode(self): 153 example_xml_string = ( 154 '<package name="com.foo.bar">' 155 '<class name="Class1" extends="java.lang.Object">' 156 '</class>' 157 '<class name="Class2" extends="java.lang.Object" abstract="true">' 158 '</class>' 159 '</package>') 160 161 162 (actual, classCount) = dexdump._ParsePackageNode( 163 ElementTree.fromstring(example_xml_string), 0, {}) 164 165 expected = { 166 'classes': { 167 'Class1': { 168 'methods': [], 169 'superclass': 'java.lang.Object', 170 'is_abstract': False, 171 'annotations': emptyAnnotations, 172 }, 173 'Class2': { 174 'methods': [], 175 'superclass': 'java.lang.Object', 176 'is_abstract': True, 177 'annotations': emptyAnnotations, 178 }, 179 }, 180 } 181 self.assertEqual(expected, actual) 182 self.assertEqual(classCount, 2) 183 184 def testParseClassNode(self): 185 example_xml_string = ('<class name="Class1" extends="java.lang.Object">' 186 '<method name="method1" visibility="public">' 187 '</method>' 188 '<method name="method2" visibility="public">' 189 '</method>' 190 '<method name="method3" visibility="private">' 191 '</method>' 192 '</class>') 193 194 actual = dexdump._ParseClassNode(ElementTree.fromstring(example_xml_string), 195 0, {}) 196 197 expected = { 198 'methods': ['method1', 'method2'], 199 'superclass': 'java.lang.Object', 200 'is_abstract': False, 201 'annotations': emptyAnnotations, 202 } 203 self.assertEqual(expected, actual) 204 205 206if __name__ == '__main__': 207 unittest.main() 208