manifest_check_test.py 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  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. import sys
  19. import unittest
  20. from xml.dom import minidom
  21. import manifest_check
  22. sys.dont_write_bytecode = True
  23. def uses_library_xml(name, attr=''):
  24. return '<uses-library android:name="%s"%s />' % (name, attr)
  25. def required_xml(value):
  26. return ' android:required="%s"' % ('true' if value else 'false')
  27. def uses_library_apk(name, sfx=''):
  28. return "uses-library%s:'%s'" % (sfx, name)
  29. def required_apk(value):
  30. return '' if value else '-not-required'
  31. class EnforceUsesLibrariesTest(unittest.TestCase):
  32. """Unit tests for add_extract_native_libs function."""
  33. def run_test(self, xml, apk, uses_libraries=[], optional_uses_libraries=[]): #pylint: disable=dangerous-default-value
  34. doc = minidom.parseString(xml)
  35. try:
  36. relax = False
  37. manifest_check.enforce_uses_libraries(
  38. doc, uses_libraries, optional_uses_libraries, relax, False,
  39. 'path/to/X/AndroidManifest.xml')
  40. manifest_check.enforce_uses_libraries(apk, uses_libraries,
  41. optional_uses_libraries,
  42. relax, True,
  43. 'path/to/X/X.apk')
  44. return True
  45. except manifest_check.ManifestMismatchError:
  46. return False
  47. xml_tmpl = (
  48. '<?xml version="1.0" encoding="utf-8"?>\n<manifest '
  49. 'xmlns:android="http://schemas.android.com/apk/res/android">\n '
  50. '<application>\n %s\n </application>\n</manifest>\n')
  51. apk_tmpl = (
  52. "package: name='com.google.android.something' versionCode='100'\n"
  53. "sdkVersion:'29'\n"
  54. "targetSdkVersion:'29'\n"
  55. "uses-permission: name='android.permission.ACCESS_NETWORK_STATE'\n"
  56. '%s\n'
  57. "densities: '160' '240' '320' '480' '640' '65534")
  58. def test_uses_library(self):
  59. xml = self.xml_tmpl % (uses_library_xml('foo'))
  60. apk = self.apk_tmpl % (uses_library_apk('foo'))
  61. matches = self.run_test(xml, apk, uses_libraries=['foo'])
  62. self.assertTrue(matches)
  63. def test_uses_library_required(self):
  64. xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(True)))
  65. apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(True)))
  66. matches = self.run_test(xml, apk, uses_libraries=['foo'])
  67. self.assertTrue(matches)
  68. def test_optional_uses_library(self):
  69. xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(False)))
  70. apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(False)))
  71. matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
  72. self.assertTrue(matches)
  73. def test_expected_uses_library(self):
  74. xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(False)))
  75. apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(False)))
  76. matches = self.run_test(xml, apk, uses_libraries=['foo'])
  77. self.assertFalse(matches)
  78. def test_expected_optional_uses_library(self):
  79. xml = self.xml_tmpl % (uses_library_xml('foo'))
  80. apk = self.apk_tmpl % (uses_library_apk('foo'))
  81. matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
  82. self.assertFalse(matches)
  83. def test_missing_uses_library(self):
  84. xml = self.xml_tmpl % ('')
  85. apk = self.apk_tmpl % ('')
  86. matches = self.run_test(xml, apk, uses_libraries=['foo'])
  87. self.assertFalse(matches)
  88. def test_missing_optional_uses_library(self):
  89. xml = self.xml_tmpl % ('')
  90. apk = self.apk_tmpl % ('')
  91. matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
  92. self.assertFalse(matches)
  93. def test_extra_uses_library(self):
  94. xml = self.xml_tmpl % (uses_library_xml('foo'))
  95. apk = self.apk_tmpl % (uses_library_xml('foo'))
  96. matches = self.run_test(xml, apk)
  97. self.assertFalse(matches)
  98. def test_extra_optional_uses_library(self):
  99. xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(False)))
  100. apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(False)))
  101. matches = self.run_test(xml, apk)
  102. self.assertFalse(matches)
  103. def test_multiple_uses_library(self):
  104. xml = self.xml_tmpl % ('\n'.join(
  105. [uses_library_xml('foo'),
  106. uses_library_xml('bar')]))
  107. apk = self.apk_tmpl % ('\n'.join(
  108. [uses_library_apk('foo'),
  109. uses_library_apk('bar')]))
  110. matches = self.run_test(xml, apk, uses_libraries=['foo', 'bar'])
  111. self.assertTrue(matches)
  112. def test_multiple_optional_uses_library(self):
  113. xml = self.xml_tmpl % ('\n'.join([
  114. uses_library_xml('foo', required_xml(False)),
  115. uses_library_xml('bar', required_xml(False))
  116. ]))
  117. apk = self.apk_tmpl % ('\n'.join([
  118. uses_library_apk('foo', required_apk(False)),
  119. uses_library_apk('bar', required_apk(False))
  120. ]))
  121. matches = self.run_test(
  122. xml, apk, optional_uses_libraries=['foo', 'bar'])
  123. self.assertTrue(matches)
  124. def test_order_uses_library(self):
  125. xml = self.xml_tmpl % ('\n'.join(
  126. [uses_library_xml('foo'),
  127. uses_library_xml('bar')]))
  128. apk = self.apk_tmpl % ('\n'.join(
  129. [uses_library_apk('foo'),
  130. uses_library_apk('bar')]))
  131. matches = self.run_test(xml, apk, uses_libraries=['bar', 'foo'])
  132. self.assertFalse(matches)
  133. def test_order_optional_uses_library(self):
  134. xml = self.xml_tmpl % ('\n'.join([
  135. uses_library_xml('foo', required_xml(False)),
  136. uses_library_xml('bar', required_xml(False))
  137. ]))
  138. apk = self.apk_tmpl % ('\n'.join([
  139. uses_library_apk('foo', required_apk(False)),
  140. uses_library_apk('bar', required_apk(False))
  141. ]))
  142. matches = self.run_test(
  143. xml, apk, optional_uses_libraries=['bar', 'foo'])
  144. self.assertFalse(matches)
  145. def test_duplicate_uses_library(self):
  146. xml = self.xml_tmpl % ('\n'.join(
  147. [uses_library_xml('foo'),
  148. uses_library_xml('foo')]))
  149. apk = self.apk_tmpl % ('\n'.join(
  150. [uses_library_apk('foo'),
  151. uses_library_apk('foo')]))
  152. matches = self.run_test(xml, apk, uses_libraries=['foo'])
  153. self.assertTrue(matches)
  154. def test_duplicate_optional_uses_library(self):
  155. xml = self.xml_tmpl % ('\n'.join([
  156. uses_library_xml('foo', required_xml(False)),
  157. uses_library_xml('foo', required_xml(False))
  158. ]))
  159. apk = self.apk_tmpl % ('\n'.join([
  160. uses_library_apk('foo', required_apk(False)),
  161. uses_library_apk('foo', required_apk(False))
  162. ]))
  163. matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
  164. self.assertTrue(matches)
  165. def test_mixed(self):
  166. xml = self.xml_tmpl % ('\n'.join([
  167. uses_library_xml('foo'),
  168. uses_library_xml('bar', required_xml(False))
  169. ]))
  170. apk = self.apk_tmpl % ('\n'.join([
  171. uses_library_apk('foo'),
  172. uses_library_apk('bar', required_apk(False))
  173. ]))
  174. matches = self.run_test(
  175. xml, apk, uses_libraries=['foo'], optional_uses_libraries=['bar'])
  176. self.assertTrue(matches)
  177. def test_mixed_with_namespace(self):
  178. xml = self.xml_tmpl % ('\n'.join([
  179. uses_library_xml('foo'),
  180. uses_library_xml('bar', required_xml(False))
  181. ]))
  182. apk = self.apk_tmpl % ('\n'.join([
  183. uses_library_apk('foo'),
  184. uses_library_apk('bar', required_apk(False))
  185. ]))
  186. matches = self.run_test(
  187. xml,
  188. apk,
  189. uses_libraries=['//x/y/z:foo'],
  190. optional_uses_libraries=['//x/y/z:bar'])
  191. self.assertTrue(matches)
  192. class ExtractTargetSdkVersionTest(unittest.TestCase):
  193. def run_test(self, xml, apk, version):
  194. doc = minidom.parseString(xml)
  195. v = manifest_check.extract_target_sdk_version(doc, is_apk=False)
  196. self.assertEqual(v, version)
  197. v = manifest_check.extract_target_sdk_version(apk, is_apk=True)
  198. self.assertEqual(v, version)
  199. xml_tmpl = (
  200. '<?xml version="1.0" encoding="utf-8"?>\n<manifest '
  201. 'xmlns:android="http://schemas.android.com/apk/res/android">\n '
  202. '<uses-sdk android:minSdkVersion="28" android:targetSdkVersion="%s" '
  203. '/>\n</manifest>\n')
  204. apk_tmpl = (
  205. "package: name='com.google.android.something' versionCode='100'\n"
  206. "sdkVersion:'28'\n"
  207. "targetSdkVersion:'%s'\n"
  208. "uses-permission: name='android.permission.ACCESS_NETWORK_STATE'\n")
  209. def test_targert_sdk_version_28(self):
  210. xml = self.xml_tmpl % '28'
  211. apk = self.apk_tmpl % '28'
  212. self.run_test(xml, apk, '28')
  213. def test_targert_sdk_version_29(self):
  214. xml = self.xml_tmpl % '29'
  215. apk = self.apk_tmpl % '29'
  216. self.run_test(xml, apk, '29')
  217. if __name__ == '__main__':
  218. unittest.main(verbosity=2)