blob: abe0d8b0e00dc9817b13faad6ccf147e8ce2ab90 [file] [log] [blame]
Colin Cross72119102019-05-20 13:14:18 -07001#!/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
Ulya Trafimovich0aba2522021-03-03 16:38:37 +000028def uses_library_xml(name, attr=''):
Spandan Dasf8807422021-08-25 20:01:17 +000029 return '<uses-library android:name="%s"%s />' % (name, attr)
Colin Cross72119102019-05-20 13:14:18 -070030
31
Ulya Trafimovich0aba2522021-03-03 16:38:37 +000032def required_xml(value):
Spandan Dasf8807422021-08-25 20:01:17 +000033 return ' android:required="%s"' % ('true' if value else 'false')
Colin Cross72119102019-05-20 13:14:18 -070034
35
Ulya Trafimovich0aba2522021-03-03 16:38:37 +000036def uses_library_apk(name, sfx=''):
Spandan Dasf8807422021-08-25 20:01:17 +000037 return "uses-library%s:'%s'" % (sfx, name)
Ulya Trafimovich0aba2522021-03-03 16:38:37 +000038
39
40def required_apk(value):
Spandan Dasf8807422021-08-25 20:01:17 +000041 return '' if value else '-not-required'
Ulya Trafimovich0aba2522021-03-03 16:38:37 +000042
43
Colin Cross72119102019-05-20 13:14:18 -070044class EnforceUsesLibrariesTest(unittest.TestCase):
Spandan Dasf8807422021-08-25 20:01:17 +000045 """Unit tests for add_extract_native_libs function."""
Colin Cross72119102019-05-20 13:14:18 -070046
Colin Cross6cb462b2024-09-11 11:34:35 -070047 def run_test(self, xml, apk, uses_libraries=(), optional_uses_libraries=(),
48 missing_optional_uses_libraries=()): #pylint: disable=dangerous-default-value
Spandan Dasf8807422021-08-25 20:01:17 +000049 doc = minidom.parseString(xml)
50 try:
51 relax = False
52 manifest_check.enforce_uses_libraries(
Jiakai Zhangf98da192024-04-15 11:15:41 +000053 doc, uses_libraries, optional_uses_libraries, missing_optional_uses_libraries,
54 relax, False, 'path/to/X/AndroidManifest.xml')
Spandan Dasf8807422021-08-25 20:01:17 +000055 manifest_check.enforce_uses_libraries(apk, uses_libraries,
56 optional_uses_libraries,
Jiakai Zhangf98da192024-04-15 11:15:41 +000057 missing_optional_uses_libraries,
Spandan Dasf8807422021-08-25 20:01:17 +000058 relax, True,
59 'path/to/X/X.apk')
60 return True
61 except manifest_check.ManifestMismatchError:
62 return False
Colin Cross72119102019-05-20 13:14:18 -070063
Spandan Dasf8807422021-08-25 20:01:17 +000064 xml_tmpl = (
65 '<?xml version="1.0" encoding="utf-8"?>\n<manifest '
66 'xmlns:android="http://schemas.android.com/apk/res/android">\n '
67 '<application>\n %s\n </application>\n</manifest>\n')
Colin Cross72119102019-05-20 13:14:18 -070068
Spandan Dasf8807422021-08-25 20:01:17 +000069 apk_tmpl = (
70 "package: name='com.google.android.something' versionCode='100'\n"
71 "sdkVersion:'29'\n"
72 "targetSdkVersion:'29'\n"
73 "uses-permission: name='android.permission.ACCESS_NETWORK_STATE'\n"
74 '%s\n'
75 "densities: '160' '240' '320' '480' '640' '65534")
Ulya Trafimovich0aba2522021-03-03 16:38:37 +000076
Spandan Dasf8807422021-08-25 20:01:17 +000077 def test_uses_library(self):
78 xml = self.xml_tmpl % (uses_library_xml('foo'))
79 apk = self.apk_tmpl % (uses_library_apk('foo'))
80 matches = self.run_test(xml, apk, uses_libraries=['foo'])
81 self.assertTrue(matches)
Colin Cross72119102019-05-20 13:14:18 -070082
Spandan Dasf8807422021-08-25 20:01:17 +000083 def test_uses_library_required(self):
84 xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(True)))
85 apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(True)))
86 matches = self.run_test(xml, apk, uses_libraries=['foo'])
87 self.assertTrue(matches)
Colin Cross72119102019-05-20 13:14:18 -070088
Spandan Dasf8807422021-08-25 20:01:17 +000089 def test_optional_uses_library(self):
90 xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(False)))
91 apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(False)))
92 matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
93 self.assertTrue(matches)
Colin Cross72119102019-05-20 13:14:18 -070094
Spandan Dasf8807422021-08-25 20:01:17 +000095 def test_expected_uses_library(self):
96 xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(False)))
97 apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(False)))
98 matches = self.run_test(xml, apk, uses_libraries=['foo'])
99 self.assertFalse(matches)
Colin Cross72119102019-05-20 13:14:18 -0700100
Spandan Dasf8807422021-08-25 20:01:17 +0000101 def test_expected_optional_uses_library(self):
102 xml = self.xml_tmpl % (uses_library_xml('foo'))
103 apk = self.apk_tmpl % (uses_library_apk('foo'))
104 matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
105 self.assertFalse(matches)
Colin Cross72119102019-05-20 13:14:18 -0700106
Jiakai Zhangf98da192024-04-15 11:15:41 +0000107 def test_expected_missing_optional_uses_library(self):
108 xml = self.xml_tmpl % (
109 uses_library_xml('foo') + uses_library_xml('missing') + uses_library_xml('bar'))
110 apk = self.apk_tmpl % (
111 uses_library_apk('foo') + uses_library_apk('missing') + uses_library_apk('bar'))
112 matches = self.run_test(xml, apk, optional_uses_libraries=['foo', 'bar'],
113 missing_optional_uses_libraries=['missing'])
114 self.assertFalse(matches)
115
Spandan Dasf8807422021-08-25 20:01:17 +0000116 def test_missing_uses_library(self):
Colin Cross6cb462b2024-09-11 11:34:35 -0700117 xml = self.xml_tmpl % ''
118 apk = self.apk_tmpl % ''
Spandan Dasf8807422021-08-25 20:01:17 +0000119 matches = self.run_test(xml, apk, uses_libraries=['foo'])
120 self.assertFalse(matches)
Colin Cross72119102019-05-20 13:14:18 -0700121
Spandan Dasf8807422021-08-25 20:01:17 +0000122 def test_missing_optional_uses_library(self):
Colin Cross6cb462b2024-09-11 11:34:35 -0700123 xml = self.xml_tmpl % ''
124 apk = self.apk_tmpl % ''
Spandan Dasf8807422021-08-25 20:01:17 +0000125 matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
126 self.assertFalse(matches)
Colin Cross72119102019-05-20 13:14:18 -0700127
Spandan Dasf8807422021-08-25 20:01:17 +0000128 def test_extra_uses_library(self):
129 xml = self.xml_tmpl % (uses_library_xml('foo'))
130 apk = self.apk_tmpl % (uses_library_xml('foo'))
131 matches = self.run_test(xml, apk)
132 self.assertFalse(matches)
Colin Cross72119102019-05-20 13:14:18 -0700133
Spandan Dasf8807422021-08-25 20:01:17 +0000134 def test_extra_optional_uses_library(self):
135 xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(False)))
136 apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(False)))
137 matches = self.run_test(xml, apk)
138 self.assertFalse(matches)
Colin Cross72119102019-05-20 13:14:18 -0700139
Spandan Dasf8807422021-08-25 20:01:17 +0000140 def test_multiple_uses_library(self):
141 xml = self.xml_tmpl % ('\n'.join(
142 [uses_library_xml('foo'),
143 uses_library_xml('bar')]))
144 apk = self.apk_tmpl % ('\n'.join(
145 [uses_library_apk('foo'),
146 uses_library_apk('bar')]))
147 matches = self.run_test(xml, apk, uses_libraries=['foo', 'bar'])
148 self.assertTrue(matches)
Colin Cross72119102019-05-20 13:14:18 -0700149
Spandan Dasf8807422021-08-25 20:01:17 +0000150 def test_multiple_optional_uses_library(self):
151 xml = self.xml_tmpl % ('\n'.join([
152 uses_library_xml('foo', required_xml(False)),
153 uses_library_xml('bar', required_xml(False))
154 ]))
155 apk = self.apk_tmpl % ('\n'.join([
156 uses_library_apk('foo', required_apk(False)),
157 uses_library_apk('bar', required_apk(False))
158 ]))
159 matches = self.run_test(
160 xml, apk, optional_uses_libraries=['foo', 'bar'])
161 self.assertTrue(matches)
Colin Cross72119102019-05-20 13:14:18 -0700162
Spandan Dasf8807422021-08-25 20:01:17 +0000163 def test_order_uses_library(self):
164 xml = self.xml_tmpl % ('\n'.join(
165 [uses_library_xml('foo'),
166 uses_library_xml('bar')]))
167 apk = self.apk_tmpl % ('\n'.join(
168 [uses_library_apk('foo'),
169 uses_library_apk('bar')]))
170 matches = self.run_test(xml, apk, uses_libraries=['bar', 'foo'])
171 self.assertFalse(matches)
Colin Cross72119102019-05-20 13:14:18 -0700172
Spandan Dasf8807422021-08-25 20:01:17 +0000173 def test_order_optional_uses_library(self):
174 xml = self.xml_tmpl % ('\n'.join([
175 uses_library_xml('foo', required_xml(False)),
176 uses_library_xml('bar', required_xml(False))
177 ]))
178 apk = self.apk_tmpl % ('\n'.join([
179 uses_library_apk('foo', required_apk(False)),
180 uses_library_apk('bar', required_apk(False))
181 ]))
182 matches = self.run_test(
183 xml, apk, optional_uses_libraries=['bar', 'foo'])
184 self.assertFalse(matches)
Colin Cross72119102019-05-20 13:14:18 -0700185
Spandan Dasf8807422021-08-25 20:01:17 +0000186 def test_duplicate_uses_library(self):
187 xml = self.xml_tmpl % ('\n'.join(
188 [uses_library_xml('foo'),
189 uses_library_xml('foo')]))
190 apk = self.apk_tmpl % ('\n'.join(
191 [uses_library_apk('foo'),
192 uses_library_apk('foo')]))
193 matches = self.run_test(xml, apk, uses_libraries=['foo'])
194 self.assertTrue(matches)
Colin Cross72119102019-05-20 13:14:18 -0700195
Spandan Dasf8807422021-08-25 20:01:17 +0000196 def test_duplicate_optional_uses_library(self):
197 xml = self.xml_tmpl % ('\n'.join([
198 uses_library_xml('foo', required_xml(False)),
199 uses_library_xml('foo', required_xml(False))
200 ]))
201 apk = self.apk_tmpl % ('\n'.join([
202 uses_library_apk('foo', required_apk(False)),
203 uses_library_apk('foo', required_apk(False))
204 ]))
205 matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
206 self.assertTrue(matches)
Colin Cross72119102019-05-20 13:14:18 -0700207
Spandan Dasf8807422021-08-25 20:01:17 +0000208 def test_mixed(self):
209 xml = self.xml_tmpl % ('\n'.join([
210 uses_library_xml('foo'),
211 uses_library_xml('bar', required_xml(False))
212 ]))
213 apk = self.apk_tmpl % ('\n'.join([
214 uses_library_apk('foo'),
215 uses_library_apk('bar', required_apk(False))
216 ]))
217 matches = self.run_test(
218 xml, apk, uses_libraries=['foo'], optional_uses_libraries=['bar'])
219 self.assertTrue(matches)
Colin Cross72119102019-05-20 13:14:18 -0700220
Spandan Dasf8807422021-08-25 20:01:17 +0000221 def test_mixed_with_namespace(self):
222 xml = self.xml_tmpl % ('\n'.join([
223 uses_library_xml('foo'),
224 uses_library_xml('bar', required_xml(False))
225 ]))
226 apk = self.apk_tmpl % ('\n'.join([
227 uses_library_apk('foo'),
228 uses_library_apk('bar', required_apk(False))
229 ]))
230 matches = self.run_test(
231 xml,
232 apk,
233 uses_libraries=['//x/y/z:foo'],
234 optional_uses_libraries=['//x/y/z:bar'])
235 self.assertTrue(matches)
Ulya Trafimovich1b513452021-07-20 14:27:32 +0100236
Colin Crosse1ab8492024-09-11 13:28:16 -0700237 def test_multiple_applications(self):
238 xml = """<?xml version="1.0" encoding="utf-8"?>
239 <manifest xmlns:android="http://schemas.android.com/apk/res/android">
240 <application android:featureFlag="foo">
241 <uses-library android:name="foo" />
242 <uses-library android:name="bar" android:required="false" />
243 </application>
244 <application android:featureFlag="!foo">
245 <uses-library android:name="foo" />
246 <uses-library android:name="qux" android:required="false" />
247 </application>
248 </manifest>
249 """
250 apk = self.apk_tmpl % ('\n'.join([
251 uses_library_apk('foo'),
252 uses_library_apk('bar', required_apk(False)),
253 uses_library_apk('foo'),
254 uses_library_apk('qux', required_apk(False))
255 ]))
256 matches = self.run_test(
257 xml,
258 apk,
259 uses_libraries=['//x/y/z:foo'],
260 optional_uses_libraries=['//x/y/z:bar', '//x/y/z:qux'])
261 self.assertTrue(matches)
262
Colin Cross72119102019-05-20 13:14:18 -0700263
264class ExtractTargetSdkVersionTest(unittest.TestCase):
Colin Cross72119102019-05-20 13:14:18 -0700265
Spandan Dasf8807422021-08-25 20:01:17 +0000266 def run_test(self, xml, apk, version):
267 doc = minidom.parseString(xml)
268 v = manifest_check.extract_target_sdk_version(doc, is_apk=False)
269 self.assertEqual(v, version)
270 v = manifest_check.extract_target_sdk_version(apk, is_apk=True)
271 self.assertEqual(v, version)
Ulya Trafimovich0aba2522021-03-03 16:38:37 +0000272
Spandan Dasf8807422021-08-25 20:01:17 +0000273 xml_tmpl = (
274 '<?xml version="1.0" encoding="utf-8"?>\n<manifest '
275 'xmlns:android="http://schemas.android.com/apk/res/android">\n '
276 '<uses-sdk android:minSdkVersion="28" android:targetSdkVersion="%s" '
277 '/>\n</manifest>\n')
Ulya Trafimovich0aba2522021-03-03 16:38:37 +0000278
Spandan Dasf8807422021-08-25 20:01:17 +0000279 apk_tmpl = (
280 "package: name='com.google.android.something' versionCode='100'\n"
281 "sdkVersion:'28'\n"
282 "targetSdkVersion:'%s'\n"
283 "uses-permission: name='android.permission.ACCESS_NETWORK_STATE'\n")
Ulya Trafimovich0aba2522021-03-03 16:38:37 +0000284
Colin Cross6cb462b2024-09-11 11:34:35 -0700285 def test_target_sdk_version_28(self):
Spandan Dasf8807422021-08-25 20:01:17 +0000286 xml = self.xml_tmpl % '28'
287 apk = self.apk_tmpl % '28'
288 self.run_test(xml, apk, '28')
289
Colin Cross6cb462b2024-09-11 11:34:35 -0700290 def test_target_sdk_version_29(self):
Spandan Dasf8807422021-08-25 20:01:17 +0000291 xml = self.xml_tmpl % '29'
292 apk = self.apk_tmpl % '29'
293 self.run_test(xml, apk, '29')
294
Colin Cross72119102019-05-20 13:14:18 -0700295
296if __name__ == '__main__':
Spandan Dasf8807422021-08-25 20:01:17 +0000297 unittest.main(verbosity=2)