1#!/usr/bin/env python 2# 3# Copyright (C) 2018 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17"""Unit tests for manifest_fixer.py.""" 18 19import sys 20import unittest 21from xml.dom import minidom 22 23import manifest_check 24 25sys.dont_write_bytecode = True 26 27 28def uses_library_xml(name, attr=''): 29 return '<uses-library android:name="%s"%s />' % (name, attr) 30 31 32def required_xml(value): 33 return ' android:required="%s"' % ('true' if value else 'false') 34 35 36def uses_library_apk(name, sfx=''): 37 return "uses-library%s:'%s'" % (sfx, name) 38 39 40def required_apk(value): 41 return '' if value else '-not-required' 42 43 44class EnforceUsesLibrariesTest(unittest.TestCase): 45 """Unit tests for add_extract_native_libs function.""" 46 47 def run_test(self, xml, apk, uses_libraries=[], optional_uses_libraries=[]): #pylint: disable=dangerous-default-value 48 doc = minidom.parseString(xml) 49 try: 50 relax = False 51 manifest_check.enforce_uses_libraries( 52 doc, uses_libraries, optional_uses_libraries, relax, False, 53 'path/to/X/AndroidManifest.xml') 54 manifest_check.enforce_uses_libraries(apk, uses_libraries, 55 optional_uses_libraries, 56 relax, True, 57 'path/to/X/X.apk') 58 return True 59 except manifest_check.ManifestMismatchError: 60 return False 61 62 xml_tmpl = ( 63 '<?xml version="1.0" encoding="utf-8"?>\n<manifest ' 64 'xmlns:android="http://schemas.android.com/apk/res/android">\n ' 65 '<application>\n %s\n </application>\n</manifest>\n') 66 67 apk_tmpl = ( 68 "package: name='com.google.android.something' versionCode='100'\n" 69 "sdkVersion:'29'\n" 70 "targetSdkVersion:'29'\n" 71 "uses-permission: name='android.permission.ACCESS_NETWORK_STATE'\n" 72 '%s\n' 73 "densities: '160' '240' '320' '480' '640' '65534") 74 75 def test_uses_library(self): 76 xml = self.xml_tmpl % (uses_library_xml('foo')) 77 apk = self.apk_tmpl % (uses_library_apk('foo')) 78 matches = self.run_test(xml, apk, uses_libraries=['foo']) 79 self.assertTrue(matches) 80 81 def test_uses_library_required(self): 82 xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(True))) 83 apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(True))) 84 matches = self.run_test(xml, apk, uses_libraries=['foo']) 85 self.assertTrue(matches) 86 87 def test_optional_uses_library(self): 88 xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(False))) 89 apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(False))) 90 matches = self.run_test(xml, apk, optional_uses_libraries=['foo']) 91 self.assertTrue(matches) 92 93 def test_expected_uses_library(self): 94 xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(False))) 95 apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(False))) 96 matches = self.run_test(xml, apk, uses_libraries=['foo']) 97 self.assertFalse(matches) 98 99 def test_expected_optional_uses_library(self): 100 xml = self.xml_tmpl % (uses_library_xml('foo')) 101 apk = self.apk_tmpl % (uses_library_apk('foo')) 102 matches = self.run_test(xml, apk, optional_uses_libraries=['foo']) 103 self.assertFalse(matches) 104 105 def test_missing_uses_library(self): 106 xml = self.xml_tmpl % ('') 107 apk = self.apk_tmpl % ('') 108 matches = self.run_test(xml, apk, uses_libraries=['foo']) 109 self.assertFalse(matches) 110 111 def test_missing_optional_uses_library(self): 112 xml = self.xml_tmpl % ('') 113 apk = self.apk_tmpl % ('') 114 matches = self.run_test(xml, apk, optional_uses_libraries=['foo']) 115 self.assertFalse(matches) 116 117 def test_extra_uses_library(self): 118 xml = self.xml_tmpl % (uses_library_xml('foo')) 119 apk = self.apk_tmpl % (uses_library_xml('foo')) 120 matches = self.run_test(xml, apk) 121 self.assertFalse(matches) 122 123 def test_extra_optional_uses_library(self): 124 xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(False))) 125 apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(False))) 126 matches = self.run_test(xml, apk) 127 self.assertFalse(matches) 128 129 def test_multiple_uses_library(self): 130 xml = self.xml_tmpl % ('\n'.join( 131 [uses_library_xml('foo'), 132 uses_library_xml('bar')])) 133 apk = self.apk_tmpl % ('\n'.join( 134 [uses_library_apk('foo'), 135 uses_library_apk('bar')])) 136 matches = self.run_test(xml, apk, uses_libraries=['foo', 'bar']) 137 self.assertTrue(matches) 138 139 def test_multiple_optional_uses_library(self): 140 xml = self.xml_tmpl % ('\n'.join([ 141 uses_library_xml('foo', required_xml(False)), 142 uses_library_xml('bar', required_xml(False)) 143 ])) 144 apk = self.apk_tmpl % ('\n'.join([ 145 uses_library_apk('foo', required_apk(False)), 146 uses_library_apk('bar', required_apk(False)) 147 ])) 148 matches = self.run_test( 149 xml, apk, optional_uses_libraries=['foo', 'bar']) 150 self.assertTrue(matches) 151 152 def test_order_uses_library(self): 153 xml = self.xml_tmpl % ('\n'.join( 154 [uses_library_xml('foo'), 155 uses_library_xml('bar')])) 156 apk = self.apk_tmpl % ('\n'.join( 157 [uses_library_apk('foo'), 158 uses_library_apk('bar')])) 159 matches = self.run_test(xml, apk, uses_libraries=['bar', 'foo']) 160 self.assertFalse(matches) 161 162 def test_order_optional_uses_library(self): 163 xml = self.xml_tmpl % ('\n'.join([ 164 uses_library_xml('foo', required_xml(False)), 165 uses_library_xml('bar', required_xml(False)) 166 ])) 167 apk = self.apk_tmpl % ('\n'.join([ 168 uses_library_apk('foo', required_apk(False)), 169 uses_library_apk('bar', required_apk(False)) 170 ])) 171 matches = self.run_test( 172 xml, apk, optional_uses_libraries=['bar', 'foo']) 173 self.assertFalse(matches) 174 175 def test_duplicate_uses_library(self): 176 xml = self.xml_tmpl % ('\n'.join( 177 [uses_library_xml('foo'), 178 uses_library_xml('foo')])) 179 apk = self.apk_tmpl % ('\n'.join( 180 [uses_library_apk('foo'), 181 uses_library_apk('foo')])) 182 matches = self.run_test(xml, apk, uses_libraries=['foo']) 183 self.assertTrue(matches) 184 185 def test_duplicate_optional_uses_library(self): 186 xml = self.xml_tmpl % ('\n'.join([ 187 uses_library_xml('foo', required_xml(False)), 188 uses_library_xml('foo', required_xml(False)) 189 ])) 190 apk = self.apk_tmpl % ('\n'.join([ 191 uses_library_apk('foo', required_apk(False)), 192 uses_library_apk('foo', required_apk(False)) 193 ])) 194 matches = self.run_test(xml, apk, optional_uses_libraries=['foo']) 195 self.assertTrue(matches) 196 197 def test_mixed(self): 198 xml = self.xml_tmpl % ('\n'.join([ 199 uses_library_xml('foo'), 200 uses_library_xml('bar', required_xml(False)) 201 ])) 202 apk = self.apk_tmpl % ('\n'.join([ 203 uses_library_apk('foo'), 204 uses_library_apk('bar', required_apk(False)) 205 ])) 206 matches = self.run_test( 207 xml, apk, uses_libraries=['foo'], optional_uses_libraries=['bar']) 208 self.assertTrue(matches) 209 210 def test_mixed_with_namespace(self): 211 xml = self.xml_tmpl % ('\n'.join([ 212 uses_library_xml('foo'), 213 uses_library_xml('bar', required_xml(False)) 214 ])) 215 apk = self.apk_tmpl % ('\n'.join([ 216 uses_library_apk('foo'), 217 uses_library_apk('bar', required_apk(False)) 218 ])) 219 matches = self.run_test( 220 xml, 221 apk, 222 uses_libraries=['//x/y/z:foo'], 223 optional_uses_libraries=['//x/y/z:bar']) 224 self.assertTrue(matches) 225 226 227class ExtractTargetSdkVersionTest(unittest.TestCase): 228 229 def run_test(self, xml, apk, version): 230 doc = minidom.parseString(xml) 231 v = manifest_check.extract_target_sdk_version(doc, is_apk=False) 232 self.assertEqual(v, version) 233 v = manifest_check.extract_target_sdk_version(apk, is_apk=True) 234 self.assertEqual(v, version) 235 236 xml_tmpl = ( 237 '<?xml version="1.0" encoding="utf-8"?>\n<manifest ' 238 'xmlns:android="http://schemas.android.com/apk/res/android">\n ' 239 '<uses-sdk android:minSdkVersion="28" android:targetSdkVersion="%s" ' 240 '/>\n</manifest>\n') 241 242 apk_tmpl = ( 243 "package: name='com.google.android.something' versionCode='100'\n" 244 "sdkVersion:'28'\n" 245 "targetSdkVersion:'%s'\n" 246 "uses-permission: name='android.permission.ACCESS_NETWORK_STATE'\n") 247 248 def test_targert_sdk_version_28(self): 249 xml = self.xml_tmpl % '28' 250 apk = self.apk_tmpl % '28' 251 self.run_test(xml, apk, '28') 252 253 def test_targert_sdk_version_29(self): 254 xml = self.xml_tmpl % '29' 255 apk = self.apk_tmpl % '29' 256 self.run_test(xml, apk, '29') 257 258 259if __name__ == '__main__': 260 unittest.main(verbosity=2) 261