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 io 20import sys 21import unittest 22from xml.dom import minidom 23import xml.etree.ElementTree as ElementTree 24 25import manifest_fixer 26 27sys.dont_write_bytecode = True 28 29 30class CompareVersionGtTest(unittest.TestCase): 31 """Unit tests for compare_version_gt function.""" 32 33 def test_sdk(self): 34 """Test comparing sdk versions.""" 35 self.assertTrue(manifest_fixer.compare_version_gt('28', '27')) 36 self.assertFalse(manifest_fixer.compare_version_gt('27', '28')) 37 self.assertFalse(manifest_fixer.compare_version_gt('28', '28')) 38 39 def test_codename(self): 40 """Test comparing codenames.""" 41 self.assertTrue(manifest_fixer.compare_version_gt('Q', 'P')) 42 self.assertFalse(manifest_fixer.compare_version_gt('P', 'Q')) 43 self.assertFalse(manifest_fixer.compare_version_gt('Q', 'Q')) 44 45 def test_sdk_codename(self): 46 """Test comparing sdk versions with codenames.""" 47 self.assertTrue(manifest_fixer.compare_version_gt('Q', '28')) 48 self.assertFalse(manifest_fixer.compare_version_gt('28', 'Q')) 49 50 def test_compare_numeric(self): 51 """Test that numbers are compared in numeric and not lexicographic order.""" 52 self.assertTrue(manifest_fixer.compare_version_gt('18', '8')) 53 54 55class RaiseMinSdkVersionTest(unittest.TestCase): 56 """Unit tests for raise_min_sdk_version function.""" 57 58 def raise_min_sdk_version_test(self, input_manifest, min_sdk_version, 59 target_sdk_version, library): 60 doc = minidom.parseString(input_manifest) 61 manifest_fixer.raise_min_sdk_version(doc, min_sdk_version, 62 target_sdk_version, library) 63 output = io.StringIO() 64 manifest_fixer.write_xml(output, doc) 65 return output.getvalue() 66 67 manifest_tmpl = ( 68 '<?xml version="1.0" encoding="utf-8"?>\n' 69 '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n' 70 '%s' 71 '</manifest>\n') 72 73 def uses_sdk(self, min_sdk=None, target_sdk=None, extra=''): 74 attrs = '' 75 if min_sdk: 76 attrs += ' android:minSdkVersion="%s"' % min_sdk 77 if target_sdk: 78 attrs += ' android:targetSdkVersion="%s"' % target_sdk 79 if extra: 80 attrs += ' ' + extra 81 return ' <uses-sdk%s/>\n' % attrs 82 83 def assert_xml_equal(self, output, expected): 84 self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected)) 85 86 def test_no_uses_sdk(self): 87 """Tests inserting a uses-sdk element into a manifest.""" 88 89 manifest_input = self.manifest_tmpl % '' 90 expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='28') 91 output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False) 92 self.assert_xml_equal(output, expected) 93 94 def test_no_min(self): 95 """Tests inserting a minSdkVersion attribute into a uses-sdk element.""" 96 97 manifest_input = self.manifest_tmpl % ' <uses-sdk extra="foo"/>\n' 98 expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='28', 99 extra='extra="foo"') 100 output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False) 101 self.assert_xml_equal(output, expected) 102 103 def test_raise_min(self): 104 """Tests inserting a minSdkVersion attribute into a uses-sdk element.""" 105 106 manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='27') 107 expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='28') 108 output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False) 109 self.assert_xml_equal(output, expected) 110 111 def test_raise(self): 112 """Tests raising a minSdkVersion attribute.""" 113 114 manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='27') 115 expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='28') 116 output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False) 117 self.assert_xml_equal(output, expected) 118 119 def test_no_raise_min(self): 120 """Tests a minSdkVersion that doesn't need raising.""" 121 122 manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='28') 123 expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='27') 124 output = self.raise_min_sdk_version_test(manifest_input, '27', '27', False) 125 self.assert_xml_equal(output, expected) 126 127 def test_raise_codename(self): 128 """Tests raising a minSdkVersion attribute to a codename.""" 129 130 manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='28') 131 expected = self.manifest_tmpl % self.uses_sdk(min_sdk='P', target_sdk='P') 132 output = self.raise_min_sdk_version_test(manifest_input, 'P', 'P', False) 133 self.assert_xml_equal(output, expected) 134 135 def test_no_raise_codename(self): 136 """Tests a minSdkVersion codename that doesn't need raising.""" 137 138 manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='P') 139 expected = self.manifest_tmpl % self.uses_sdk(min_sdk='P', target_sdk='28') 140 output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False) 141 self.assert_xml_equal(output, expected) 142 143 def test_target(self): 144 """Tests an existing targetSdkVersion is preserved.""" 145 146 manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='26', target_sdk='27') 147 expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='27') 148 output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False) 149 self.assert_xml_equal(output, expected) 150 151 def test_no_target(self): 152 """Tests inserting targetSdkVersion when minSdkVersion exists.""" 153 154 manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='27') 155 expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='29') 156 output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False) 157 self.assert_xml_equal(output, expected) 158 159 def test_target_no_min(self): 160 """"Tests inserting targetSdkVersion when minSdkVersion exists.""" 161 162 manifest_input = self.manifest_tmpl % self.uses_sdk(target_sdk='27') 163 expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='27') 164 output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False) 165 self.assert_xml_equal(output, expected) 166 167 def test_no_target_no_min(self): 168 """Tests inserting targetSdkVersion when minSdkVersion does not exist.""" 169 170 manifest_input = self.manifest_tmpl % '' 171 expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='29') 172 output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False) 173 self.assert_xml_equal(output, expected) 174 175 def test_library_no_target(self): 176 """Tests inserting targetSdkVersion when minSdkVersion exists.""" 177 178 manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='27') 179 expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='16') 180 output = self.raise_min_sdk_version_test(manifest_input, '28', '29', True) 181 self.assert_xml_equal(output, expected) 182 183 def test_library_target_no_min(self): 184 """Tests inserting targetSdkVersion when minSdkVersion exists.""" 185 186 manifest_input = self.manifest_tmpl % self.uses_sdk(target_sdk='27') 187 expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='27') 188 output = self.raise_min_sdk_version_test(manifest_input, '28', '29', True) 189 self.assert_xml_equal(output, expected) 190 191 def test_library_no_target_no_min(self): 192 """Tests inserting targetSdkVersion when minSdkVersion does not exist.""" 193 194 manifest_input = self.manifest_tmpl % '' 195 expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='16') 196 output = self.raise_min_sdk_version_test(manifest_input, '28', '29', True) 197 self.assert_xml_equal(output, expected) 198 199 def test_extra(self): 200 """Tests that extra attributes and elements are maintained.""" 201 202 manifest_input = self.manifest_tmpl % ( 203 ' <!-- comment -->\n' 204 ' <uses-sdk android:minSdkVersion="27" extra="foo"/>\n' 205 ' <application/>\n') 206 207 # pylint: disable=line-too-long 208 expected = self.manifest_tmpl % ( 209 ' <!-- comment -->\n' 210 ' <uses-sdk android:minSdkVersion="28" extra="foo" android:targetSdkVersion="29"/>\n' 211 ' <application/>\n') 212 213 output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False) 214 215 self.assert_xml_equal(output, expected) 216 217 def test_indent(self): 218 """Tests that an inserted element copies the existing indentation.""" 219 220 manifest_input = self.manifest_tmpl % ' <!-- comment -->\n' 221 222 # pylint: disable=line-too-long 223 expected = self.manifest_tmpl % ( 224 ' <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="29"/>\n' 225 ' <!-- comment -->\n') 226 227 output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False) 228 229 self.assert_xml_equal(output, expected) 230 231 def test_multiple_uses_sdks(self): 232 """Tests a manifest that contains multiple uses_sdks elements.""" 233 234 manifest_input = self.manifest_tmpl % ( 235 ' <uses-sdk android:featureFlag="foo" android:minSdkVersion="21" />\n' 236 ' <uses-sdk android:featureFlag="!foo" android:minSdkVersion="22" />\n') 237 expected = self.manifest_tmpl % ( 238 ' <uses-sdk android:featureFlag="foo" android:minSdkVersion="28" android:targetSdkVersion="28" />\n' 239 ' <uses-sdk android:featureFlag="!foo" android:minSdkVersion="28" android:targetSdkVersion="28" />\n') 240 241 output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False) 242 self.assert_xml_equal(output, expected) 243 244class AddLoggingParentTest(unittest.TestCase): 245 """Unit tests for add_logging_parent function.""" 246 247 def assert_xml_equal(self, output, expected): 248 self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected)) 249 250 def add_logging_parent_test(self, input_manifest, logging_parent=None): 251 doc = minidom.parseString(input_manifest) 252 if logging_parent: 253 manifest_fixer.add_logging_parent(doc, logging_parent) 254 output = io.StringIO() 255 manifest_fixer.write_xml(output, doc) 256 return output.getvalue() 257 258 manifest_tmpl = ( 259 '<?xml version="1.0" encoding="utf-8"?>\n' 260 '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n' 261 '%s' 262 '</manifest>\n') 263 264 def uses_logging_parent(self, logging_parent=None): 265 attrs = '' 266 if logging_parent: 267 meta_text = ('<meta-data android:name="android.content.pm.LOGGING_PARENT" ' 268 'android:value="%s"/>\n') % logging_parent 269 attrs += ' <application>\n %s </application>\n' % meta_text 270 271 return attrs 272 273 def test_no_logging_parent(self): 274 """Tests manifest_fixer with no logging_parent.""" 275 manifest_input = self.manifest_tmpl % '' 276 expected = self.manifest_tmpl % self.uses_logging_parent() 277 output = self.add_logging_parent_test(manifest_input) 278 self.assert_xml_equal(output, expected) 279 280 def test_logging_parent(self): 281 """Tests manifest_fixer with no logging_parent.""" 282 manifest_input = self.manifest_tmpl % '' 283 expected = self.manifest_tmpl % self.uses_logging_parent('FOO') 284 output = self.add_logging_parent_test(manifest_input, 'FOO') 285 self.assert_xml_equal(output, expected) 286 287 288class AddUsesLibrariesTest(unittest.TestCase): 289 """Unit tests for add_uses_libraries function.""" 290 291 def assert_xml_equal(self, output, expected): 292 self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected)) 293 294 def run_test(self, input_manifest, new_uses_libraries): 295 doc = minidom.parseString(input_manifest) 296 manifest_fixer.add_uses_libraries(doc, new_uses_libraries, True) 297 output = io.StringIO() 298 manifest_fixer.write_xml(output, doc) 299 return output.getvalue() 300 301 manifest_tmpl = ( 302 '<?xml version="1.0" encoding="utf-8"?>\n' 303 '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n' 304 '%s' 305 '</manifest>\n') 306 307 def uses_libraries(self, name_required_pairs): 308 ret = ' <application>\n' 309 for name, required in name_required_pairs: 310 ret += ( 311 ' <uses-library android:name="%s" android:required="%s"/>\n' 312 ) % (name, required) 313 ret += ' </application>\n' 314 return ret 315 316 def test_empty(self): 317 """Empty new_uses_libraries must not touch the manifest.""" 318 manifest_input = self.manifest_tmpl % self.uses_libraries([ 319 ('foo', 'true'), 320 ('bar', 'false')]) 321 expected = manifest_input 322 output = self.run_test(manifest_input, []) 323 self.assert_xml_equal(output, expected) 324 325 def test_not_overwrite(self): 326 """new_uses_libraries must not overwrite existing tags.""" 327 manifest_input = self.manifest_tmpl % self.uses_libraries([ 328 ('foo', 'true'), 329 ('bar', 'false')]) 330 expected = manifest_input 331 output = self.run_test(manifest_input, ['foo', 'bar']) 332 self.assert_xml_equal(output, expected) 333 334 def test_add(self): 335 """New names are added with 'required:true'.""" 336 manifest_input = self.manifest_tmpl % self.uses_libraries([ 337 ('foo', 'true'), 338 ('bar', 'false')]) 339 expected = self.manifest_tmpl % self.uses_libraries([ 340 ('foo', 'true'), 341 ('bar', 'false'), 342 ('baz', 'true'), 343 ('qux', 'true')]) 344 output = self.run_test(manifest_input, ['bar', 'baz', 'qux']) 345 self.assert_xml_equal(output, expected) 346 347 def test_no_application(self): 348 """When there is no <application> tag, the tag is added.""" 349 manifest_input = ( 350 '<?xml version="1.0" encoding="utf-8"?>\n' 351 '<manifest xmlns:android=' 352 '"http://schemas.android.com/apk/res/android">\n' 353 '</manifest>\n') 354 expected = self.manifest_tmpl % self.uses_libraries([ 355 ('foo', 'true'), 356 ('bar', 'true')]) 357 output = self.run_test(manifest_input, ['foo', 'bar']) 358 self.assert_xml_equal(output, expected) 359 360 def test_empty_application(self): 361 """Even when here is an empty <application/> tag, the libs are added.""" 362 manifest_input = ( 363 '<?xml version="1.0" encoding="utf-8"?>\n' 364 '<manifest xmlns:android=' 365 '"http://schemas.android.com/apk/res/android">\n' 366 ' <application/>\n' 367 '</manifest>\n') 368 expected = self.manifest_tmpl % self.uses_libraries([ 369 ('foo', 'true'), 370 ('bar', 'true')]) 371 output = self.run_test(manifest_input, ['foo', 'bar']) 372 self.assert_xml_equal(output, expected) 373 374 def test_multiple_application(self): 375 """When there are multiple applications, the libs are added to each.""" 376 manifest_input = self.manifest_tmpl % ( 377 self.uses_libraries([('foo', 'false')]) + 378 self.uses_libraries([('bar', 'false')])) 379 expected = self.manifest_tmpl % ( 380 self.uses_libraries([('foo', 'false'), ('bar', 'true')]) + 381 self.uses_libraries([('bar', 'false'), ('foo', 'true')])) 382 output = self.run_test(manifest_input, ['foo', 'bar']) 383 self.assert_xml_equal(output, expected) 384 385 386class AddUsesNonSdkApiTest(unittest.TestCase): 387 """Unit tests for add_uses_libraries function.""" 388 389 def assert_xml_equal(self, output, expected): 390 self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected)) 391 392 def run_test(self, input_manifest): 393 doc = minidom.parseString(input_manifest) 394 manifest_fixer.add_uses_non_sdk_api(doc) 395 output = io.StringIO() 396 manifest_fixer.write_xml(output, doc) 397 return output.getvalue() 398 399 manifest_tmpl = ( 400 '<?xml version="1.0" encoding="utf-8"?>\n' 401 '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n' 402 ' %s\n' 403 '</manifest>\n') 404 405 def uses_non_sdk_api(self, value): 406 return '<application %s/>' % ('android:usesNonSdkApi="true"' if value else '') 407 408 def test_set_true(self): 409 """Empty new_uses_libraries must not touch the manifest.""" 410 manifest_input = self.manifest_tmpl % self.uses_non_sdk_api(False) 411 expected = self.manifest_tmpl % self.uses_non_sdk_api(True) 412 output = self.run_test(manifest_input) 413 self.assert_xml_equal(output, expected) 414 415 def test_already_set(self): 416 """new_uses_libraries must not overwrite existing tags.""" 417 manifest_input = self.manifest_tmpl % self.uses_non_sdk_api(True) 418 expected = manifest_input 419 output = self.run_test(manifest_input) 420 self.assert_xml_equal(output, expected) 421 422 def test_multiple_applications(self): 423 """new_uses_libraries must be added to all applications.""" 424 manifest_input = self.manifest_tmpl % (self.uses_non_sdk_api(True) + self.uses_non_sdk_api(False)) 425 expected = self.manifest_tmpl % (self.uses_non_sdk_api(True) + self.uses_non_sdk_api(True)) 426 output = self.run_test(manifest_input) 427 self.assert_xml_equal(output, expected) 428 429 430class UseEmbeddedDexTest(unittest.TestCase): 431 """Unit tests for add_use_embedded_dex function.""" 432 433 def assert_xml_equal(self, output, expected): 434 self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected)) 435 436 def run_test(self, input_manifest): 437 doc = minidom.parseString(input_manifest) 438 manifest_fixer.add_use_embedded_dex(doc) 439 output = io.StringIO() 440 manifest_fixer.write_xml(output, doc) 441 return output.getvalue() 442 443 manifest_tmpl = ( 444 '<?xml version="1.0" encoding="utf-8"?>\n' 445 '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n' 446 ' %s\n' 447 '</manifest>\n') 448 449 def use_embedded_dex(self, value): 450 return '<application android:useEmbeddedDex="%s" />' % value 451 452 def test_manifest_with_undeclared_preference(self): 453 manifest_input = self.manifest_tmpl % '<application/>' 454 expected = self.manifest_tmpl % self.use_embedded_dex('true') 455 output = self.run_test(manifest_input) 456 self.assert_xml_equal(output, expected) 457 458 def test_manifest_with_use_embedded_dex(self): 459 manifest_input = self.manifest_tmpl % self.use_embedded_dex('true') 460 expected = manifest_input 461 output = self.run_test(manifest_input) 462 self.assert_xml_equal(output, expected) 463 464 def test_manifest_with_not_use_embedded_dex(self): 465 manifest_input = self.manifest_tmpl % self.use_embedded_dex('false') 466 self.assertRaises(RuntimeError, self.run_test, manifest_input) 467 468 def test_multiple_applications(self): 469 manifest_input = self.manifest_tmpl % ( 470 self.use_embedded_dex('true') + 471 '<application/>' 472 ) 473 expected = self.manifest_tmpl % ( 474 self.use_embedded_dex('true') + 475 self.use_embedded_dex('true') 476 ) 477 output = self.run_test(manifest_input) 478 self.assert_xml_equal(output, expected) 479 480 481class AddExtractNativeLibsTest(unittest.TestCase): 482 """Unit tests for add_extract_native_libs function.""" 483 484 def assert_xml_equal(self, output, expected): 485 self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected)) 486 487 def run_test(self, input_manifest, value): 488 doc = minidom.parseString(input_manifest) 489 manifest_fixer.add_extract_native_libs(doc, value) 490 output = io.StringIO() 491 manifest_fixer.write_xml(output, doc) 492 return output.getvalue() 493 494 manifest_tmpl = ( 495 '<?xml version="1.0" encoding="utf-8"?>\n' 496 '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n' 497 ' %s\n' 498 '</manifest>\n') 499 500 def extract_native_libs(self, value): 501 return '<application android:extractNativeLibs="%s" />' % value 502 503 def test_set_true(self): 504 manifest_input = self.manifest_tmpl % '<application/>' 505 expected = self.manifest_tmpl % self.extract_native_libs('true') 506 output = self.run_test(manifest_input, True) 507 self.assert_xml_equal(output, expected) 508 509 def test_set_false(self): 510 manifest_input = self.manifest_tmpl % '<application/>' 511 expected = self.manifest_tmpl % self.extract_native_libs('false') 512 output = self.run_test(manifest_input, False) 513 self.assert_xml_equal(output, expected) 514 515 def test_match(self): 516 manifest_input = self.manifest_tmpl % self.extract_native_libs('true') 517 expected = manifest_input 518 output = self.run_test(manifest_input, True) 519 self.assert_xml_equal(output, expected) 520 521 def test_conflict(self): 522 manifest_input = self.manifest_tmpl % self.extract_native_libs('true') 523 self.assertRaises(RuntimeError, self.run_test, manifest_input, False) 524 525 def test_multiple_applications(self): 526 manifest_input = self.manifest_tmpl % (self.extract_native_libs('true') + '<application/>') 527 expected = self.manifest_tmpl % (self.extract_native_libs('true') + self.extract_native_libs('true')) 528 output = self.run_test(manifest_input, True) 529 self.assert_xml_equal(output, expected) 530 531 532class AddNoCodeApplicationTest(unittest.TestCase): 533 """Unit tests for set_has_code_to_false function.""" 534 535 def assert_xml_equal(self, output, expected): 536 self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected)) 537 538 def run_test(self, input_manifest): 539 doc = minidom.parseString(input_manifest) 540 manifest_fixer.set_has_code_to_false(doc) 541 output = io.StringIO() 542 manifest_fixer.write_xml(output, doc) 543 return output.getvalue() 544 545 manifest_tmpl = ( 546 '<?xml version="1.0" encoding="utf-8"?>\n' 547 '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n' 548 '%s' 549 '</manifest>\n') 550 551 def test_no_application(self): 552 manifest_input = self.manifest_tmpl % '' 553 expected = self.manifest_tmpl % ' <application android:hasCode="false"/>\n' 554 output = self.run_test(manifest_input) 555 self.assert_xml_equal(output, expected) 556 557 def test_has_application_no_has_code(self): 558 manifest_input = self.manifest_tmpl % ' <application/>\n' 559 expected = self.manifest_tmpl % ' <application android:hasCode="false"/>\n' 560 output = self.run_test(manifest_input) 561 self.assert_xml_equal(output, expected) 562 563 def test_has_application_has_code_false(self): 564 """ Do nothing if there's already an application element. """ 565 manifest_input = self.manifest_tmpl % ' <application android:hasCode="false"/>\n' 566 output = self.run_test(manifest_input) 567 self.assert_xml_equal(output, manifest_input) 568 569 def test_has_application_has_code_true(self): 570 """ Do nothing if there's already an application element even if its 571 hasCode attribute is true. """ 572 manifest_input = self.manifest_tmpl % ' <application android:hasCode="true"/>\n' 573 output = self.run_test(manifest_input) 574 self.assert_xml_equal(output, manifest_input) 575 576 def test_multiple_applications(self): 577 """ Apply to all applications """ 578 manifest_input = self.manifest_tmpl % ( 579 ' <application android:hasCode="true" />\n' + 580 ' <application android:hasCode="false" />\n' + 581 ' <application/>\n') 582 expected = self.manifest_tmpl % ( 583 ' <application android:hasCode="true" />\n' + 584 ' <application android:hasCode="false" />\n' + 585 ' <application android:hasCode="false" />\n') 586 output = self.run_test(manifest_input) 587 self.assert_xml_equal(output, expected) 588 589 590class AddTestOnlyApplicationTest(unittest.TestCase): 591 """Unit tests for set_test_only_flag_to_true function.""" 592 593 def assert_xml_equal(self, output, expected): 594 self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected)) 595 596 def run_test(self, input_manifest): 597 doc = minidom.parseString(input_manifest) 598 manifest_fixer.set_test_only_flag_to_true(doc) 599 output = io.StringIO() 600 manifest_fixer.write_xml(output, doc) 601 return output.getvalue() 602 603 manifest_tmpl = ( 604 '<?xml version="1.0" encoding="utf-8"?>\n' 605 '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n' 606 '%s' 607 '</manifest>\n') 608 609 def test_no_application(self): 610 manifest_input = self.manifest_tmpl % '' 611 expected = self.manifest_tmpl % ' <application android:testOnly="true"/>\n' 612 output = self.run_test(manifest_input) 613 self.assert_xml_equal(output, expected) 614 615 def test_has_application_no_test_only(self): 616 manifest_input = self.manifest_tmpl % ' <application/>\n' 617 expected = self.manifest_tmpl % ' <application android:testOnly="true"/>\n' 618 output = self.run_test(manifest_input) 619 self.assert_xml_equal(output, expected) 620 621 def test_has_application_test_only_true(self): 622 """ If there's already an application element.""" 623 manifest_input = self.manifest_tmpl % ' <application android:testOnly="true"/>\n' 624 output = self.run_test(manifest_input) 625 self.assert_xml_equal(output, manifest_input) 626 627 def test_has_application_test_only_false(self): 628 """ If there's already an application element with the testOnly attribute as false.""" 629 manifest_input = self.manifest_tmpl % ' <application android:testOnly="false"/>\n' 630 output = self.run_test(manifest_input) 631 self.assert_xml_equal(output, manifest_input) 632 633 def test_multiple_applications(self): 634 manifest_input = self.manifest_tmpl % ( 635 ' <application android:testOnly="true" />\n' + 636 ' <application android:testOnly="false" />\n' + 637 ' <application/>\n' 638 ) 639 expected = self.manifest_tmpl % ( 640 ' <application android:testOnly="true" />\n' + 641 ' <application android:testOnly="false" />\n' + 642 ' <application android:testOnly="true" />\n' 643 ) 644 output = self.run_test(manifest_input) 645 self.assert_xml_equal(output, expected) 646 647 648class SetMaxSdkVersionTest(unittest.TestCase): 649 """Unit tests for set_max_sdk_version function.""" 650 651 def assert_xml_equal(self, output, expected): 652 self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected)) 653 654 def run_test(self, input_manifest, max_sdk_version): 655 doc = minidom.parseString(input_manifest) 656 manifest_fixer.set_max_sdk_version(doc, max_sdk_version) 657 output = io.StringIO() 658 manifest_fixer.write_xml(output, doc) 659 return output.getvalue() 660 661 manifest_tmpl = ( 662 '<?xml version="1.0" encoding="utf-8"?>\n' 663 '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n' 664 '%s' 665 '</manifest>\n') 666 667 def permission(self, max_sdk=None): 668 if max_sdk is None: 669 return ' <permission/>' 670 return ' <permission android:maxSdkVersion="%s"/>\n' % max_sdk 671 672 def uses_permission(self, max_sdk=None): 673 if max_sdk is None: 674 return ' <uses-permission/>' 675 return ' <uses-permission android:maxSdkVersion="%s"/>\n' % max_sdk 676 677 def test_permission_no_max_sdk_version(self): 678 """Tests if permission has no maxSdkVersion attribute""" 679 manifest_input = self.manifest_tmpl % self.permission() 680 expected = self.manifest_tmpl % self.permission() 681 output = self.run_test(manifest_input, '9000') 682 self.assert_xml_equal(output, expected) 683 684 def test_permission_max_sdk_version_changed(self): 685 """Tests if permission maxSdkVersion attribute is set to current""" 686 manifest_input = self.manifest_tmpl % self.permission('current') 687 expected = self.manifest_tmpl % self.permission(9000) 688 output = self.run_test(manifest_input, '9000') 689 self.assert_xml_equal(output, expected) 690 691 def test_permission_max_sdk_version_not_changed(self): 692 """Tests if permission maxSdkVersion attribute is not set to current""" 693 manifest_input = self.manifest_tmpl % self.permission(30) 694 expected = self.manifest_tmpl % self.permission(30) 695 output = self.run_test(manifest_input, '9000') 696 self.assert_xml_equal(output, expected) 697 698 def test_uses_permission_no_max_sdk_version(self): 699 """Tests if uses-permission has no maxSdkVersion attribute""" 700 manifest_input = self.manifest_tmpl % self.uses_permission() 701 expected = self.manifest_tmpl % self.uses_permission() 702 output = self.run_test(manifest_input, '9000') 703 self.assert_xml_equal(output, expected) 704 705 def test_uses_permission_max_sdk_version_changed(self): 706 """Tests if uses-permission maxSdkVersion attribute is set to current""" 707 manifest_input = self.manifest_tmpl % self.uses_permission('current') 708 expected = self.manifest_tmpl % self.uses_permission(9000) 709 output = self.run_test(manifest_input, '9000') 710 self.assert_xml_equal(output, expected) 711 712 def test_uses_permission_max_sdk_version_not_changed(self): 713 """Tests if uses-permission maxSdkVersion attribute is not set to current""" 714 manifest_input = self.manifest_tmpl % self.uses_permission(30) 715 expected = self.manifest_tmpl % self.uses_permission(30) 716 output = self.run_test(manifest_input, '9000') 717 self.assert_xml_equal(output, expected) 718 719 720class OverrideDefaultVersionTest(unittest.TestCase): 721 """Unit tests for override_default_version function.""" 722 723 def assert_xml_equal(self, output, expected): 724 self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected)) 725 726 def run_test(self, input_manifest, version): 727 doc = minidom.parseString(input_manifest) 728 manifest_fixer.override_placeholder_version(doc, version) 729 output = io.StringIO() 730 manifest_fixer.write_xml(output, doc) 731 return output.getvalue() 732 733 manifest_tmpl = ( 734 '<?xml version="1.0" encoding="utf-8"?>\n' 735 '<manifest xmlns:android="http://schemas.android.com/apk/res/android" ' 736 'android:versionCode="%s">\n' 737 '</manifest>\n') 738 739 def test_doesnt_override_existing_version(self): 740 """Tests that an existing version is not overridden""" 741 manifest_input = self.manifest_tmpl % '12345' 742 expected = manifest_input 743 output = self.run_test(manifest_input, '67890') 744 self.assert_xml_equal(output, expected) 745 746 def test_overrides_default_version(self): 747 """Tests that a default version is overridden""" 748 manifest_input = self.manifest_tmpl % '0' 749 expected = self.manifest_tmpl % '67890' 750 output = self.run_test(manifest_input, '67890') 751 self.assert_xml_equal(output, expected) 752 753 754if __name__ == '__main__': 755 unittest.main(verbosity=2) 756