3 # http://www.drdobbs.com/testing/unit-testing-with-python/240165163
16 from binascii import unhexlify
17 from distutils.version import LooseVersion
19 localmodule = os.path.realpath(
20 os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..'))
21 print('localmodule: ' + localmodule)
22 if localmodule not in sys.path:
23 sys.path.insert(0, localmodule)
25 import fdroidserver.common
26 import fdroidserver.exception
27 import fdroidserver.metadata
28 import fdroidserver.update
29 from fdroidserver.common import FDroidPopen
32 class UpdateTest(unittest.TestCase):
36 logging.basicConfig(level=logging.INFO)
37 self.basedir = os.path.join(localmodule, 'tests')
38 self.tmpdir = os.path.abspath(os.path.join(self.basedir, '..', '.testfiles'))
39 if not os.path.exists(self.tmpdir):
40 os.makedirs(self.tmpdir)
41 os.chdir(self.basedir)
43 def testInsertStoreMetadata(self):
45 fdroidserver.common.fill_config_defaults(config)
46 config['accepted_formats'] = ('txt', 'yml')
47 fdroidserver.update.config = config
48 fdroidserver.update.options = fdroidserver.common.options
49 os.chdir(os.path.join(localmodule, 'tests'))
51 shutil.rmtree(os.path.join('repo', 'info.guardianproject.urzip'), ignore_errors=True)
53 shutil.rmtree(os.path.join('build', 'com.nextcloud.client'), ignore_errors=True)
54 shutil.copytree(os.path.join('source-files', 'com.nextcloud.client'),
55 os.path.join('build', 'com.nextcloud.client'))
57 shutil.rmtree(os.path.join('build', 'com.nextcloud.client.dev'), ignore_errors=True)
58 shutil.copytree(os.path.join('source-files', 'com.nextcloud.client.dev'),
59 os.path.join('build', 'com.nextcloud.client.dev'))
61 shutil.rmtree(os.path.join('build', 'eu.siacs.conversations'), ignore_errors=True)
62 shutil.copytree(os.path.join('source-files', 'eu.siacs.conversations'),
63 os.path.join('build', 'eu.siacs.conversations'))
66 for packageName in ('info.guardianproject.urzip', 'org.videolan.vlc', 'obb.mainpatch.current',
67 'com.nextcloud.client', 'com.nextcloud.client.dev',
68 'eu.siacs.conversations'):
69 apps[packageName] = fdroidserver.metadata.App()
70 apps[packageName]['id'] = packageName
71 apps[packageName]['CurrentVersionCode'] = 0xcafebeef
73 apps['info.guardianproject.urzip']['CurrentVersionCode'] = 100
75 buildnextcloudclient = fdroidserver.metadata.Build()
76 buildnextcloudclient.gradle = ['generic']
77 apps['com.nextcloud.client']['builds'] = [buildnextcloudclient]
79 buildnextclouddevclient = fdroidserver.metadata.Build()
80 buildnextclouddevclient.gradle = ['versionDev']
81 apps['com.nextcloud.client.dev']['builds'] = [buildnextclouddevclient]
83 build_conversations = fdroidserver.metadata.Build()
84 build_conversations.gradle = ['free']
85 apps['eu.siacs.conversations']['builds'] = [build_conversations]
87 fdroidserver.update.insert_localized_app_metadata(apps)
89 appdir = os.path.join('repo', 'info.guardianproject.urzip', 'en-US')
90 self.assertTrue(os.path.isfile(os.path.join(appdir, 'icon.png')))
91 self.assertTrue(os.path.isfile(os.path.join(appdir, 'featureGraphic.png')))
93 self.assertEqual(6, len(apps))
94 for packageName, app in apps.items():
95 self.assertTrue('localized' in app)
96 self.assertTrue('en-US' in app['localized'])
97 self.assertEqual(1, len(app['localized']))
98 if packageName == 'info.guardianproject.urzip':
99 self.assertEqual(7, len(app['localized']['en-US']))
100 self.assertEqual('full description\n', app['localized']['en-US']['description'])
101 self.assertEqual('title\n', app['localized']['en-US']['name'])
102 self.assertEqual('short description\n', app['localized']['en-US']['summary'])
103 self.assertEqual('video\n', app['localized']['en-US']['video'])
104 self.assertEqual('icon.png', app['localized']['en-US']['icon'])
105 self.assertEqual('featureGraphic.png', app['localized']['en-US']['featureGraphic'])
106 self.assertEqual('100\n', app['localized']['en-US']['whatsNew'])
107 elif packageName == 'org.videolan.vlc':
108 self.assertEqual('icon.png', app['localized']['en-US']['icon'])
109 self.assertEqual(9, len(app['localized']['en-US']['phoneScreenshots']))
110 self.assertEqual(15, len(app['localized']['en-US']['sevenInchScreenshots']))
111 elif packageName == 'obb.mainpatch.current':
112 self.assertEqual('icon.png', app['localized']['en-US']['icon'])
113 self.assertEqual('featureGraphic.png', app['localized']['en-US']['featureGraphic'])
114 self.assertEqual(1, len(app['localized']['en-US']['phoneScreenshots']))
115 self.assertEqual(1, len(app['localized']['en-US']['sevenInchScreenshots']))
116 elif packageName == 'com.nextcloud.client':
117 self.assertEqual('Nextcloud', app['localized']['en-US']['name'])
118 self.assertEqual(1073, len(app['localized']['en-US']['description']))
119 self.assertEqual(78, len(app['localized']['en-US']['summary']))
120 elif packageName == 'com.nextcloud.client.dev':
121 self.assertEqual('Nextcloud Dev', app['localized']['en-US']['name'])
122 self.assertEqual(586, len(app['localized']['en-US']['description']))
123 self.assertEqual(79, len(app['localized']['en-US']['summary']))
124 elif packageName == 'eu.siacs.conversations':
125 self.assertEqual('Conversations', app['localized']['en-US']['name'])
127 def test_insert_triple_t_metadata(self):
128 importer = os.path.join(self.basedir, 'tmp', 'importer')
129 packageName = 'org.fdroid.ci.test.app'
130 if not os.path.isdir(importer):
131 logging.warning('skipping test_insert_triple_t_metadata, import.TestCase must run first!')
133 tmptestsdir = tempfile.mkdtemp(prefix=inspect.currentframe().f_code.co_name,
135 packageDir = os.path.join(tmptestsdir, 'build', packageName)
136 shutil.copytree(importer, packageDir)
138 # always use the same commit so these tests work when ci-test-app.git is updated
139 repo = git.Repo(packageDir)
140 for remote in repo.remotes:
142 repo.git.reset('--hard', 'b9e5d1a0d8d6fc31d4674b2f0514fef10762ed4f')
143 repo.git.clean('-fdx')
145 os.mkdir(os.path.join(tmptestsdir, 'metadata'))
147 metadata['Description'] = 'This is just a test app'
148 with open(os.path.join(tmptestsdir, 'metadata', packageName + '.yml'), 'w') as fp:
149 yaml.dump(metadata, fp)
152 fdroidserver.common.fill_config_defaults(config)
153 config['accepted_formats'] = ('yml')
154 fdroidserver.common.config = config
155 fdroidserver.update.config = config
156 fdroidserver.update.options = fdroidserver.common.options
157 os.chdir(tmptestsdir)
159 apps = fdroidserver.metadata.read_metadata(xref=True)
160 fdroidserver.update.copy_triple_t_store_metadata(apps)
162 # TODO ideally, this would compare the whole dict like in metadata.TestCase's test_read_metadata()
164 'ar', 'ast_ES', 'az', 'ca', 'ca_ES', 'cs-CZ', 'cs_CZ', 'da',
165 'da-DK', 'de', 'de-DE', 'el', 'en-US', 'es', 'es-ES', 'es_ES', 'et',
166 'fi', 'fr', 'fr-FR', 'he_IL', 'hi-IN', 'hi_IN', 'hu', 'id', 'it',
167 'it-IT', 'it_IT', 'iw-IL', 'ja', 'ja-JP', 'kn_IN', 'ko', 'ko-KR',
168 'ko_KR', 'lt', 'nb', 'nb_NO', 'nl', 'nl-NL', 'no', 'pl', 'pl-PL',
169 'pl_PL', 'pt', 'pt-BR', 'pt-PT', 'pt_BR', 'ro', 'ro_RO', 'ru-RU',
170 'ru_RU', 'sv-SE', 'sv_SE', 'te', 'tr', 'tr-TR', 'uk', 'uk_UA', 'vi',
171 'vi_VN', 'zh-CN', 'zh_CN', 'zh_TW',
173 locales = sorted(list(apps['org.fdroid.ci.test.app']['localized'].keys()))
174 self.assertEqual(correctlocales, locales)
176 def javagetsig(self, apkfile):
177 getsig_dir = os.path.join(os.path.dirname(__file__), 'getsig')
178 if not os.path.exists(getsig_dir + "/getsig.class"):
179 logging.critical("getsig.class not found. To fix: cd '%s' && ./make.sh" % getsig_dir)
181 # FDroidPopen needs some config to work
183 fdroidserver.common.fill_config_defaults(config)
184 fdroidserver.common.config = config
185 p = FDroidPopen(['java', '-cp', os.path.join(os.path.dirname(__file__), 'getsig'),
186 'getsig', os.path.join(os.getcwd(), apkfile)])
188 for line in p.output.splitlines():
189 if line.startswith('Result:'):
190 sig = line[7:].strip()
192 if p.returncode == 0:
197 def testGoodGetsig(self):
198 # config needed to use jarsigner and keytool
200 fdroidserver.common.fill_config_defaults(config)
201 fdroidserver.update.config = config
202 apkfile = os.path.join(os.path.dirname(__file__), 'urzip.apk')
203 sig = self.javagetsig(apkfile)
204 self.assertIsNotNone(sig, "sig is None")
205 pysig = fdroidserver.update.getsig(apkfile)
206 self.assertIsNotNone(pysig, "pysig is None")
207 self.assertEqual(sig, fdroidserver.update.getsig(apkfile),
208 "python sig not equal to java sig!")
209 self.assertEqual(len(sig), len(pysig),
210 "the length of the two sigs are different!")
212 self.assertEqual(unhexlify(sig), unhexlify(pysig),
213 "the length of the two sigs are different!")
214 except TypeError as e:
216 self.assertTrue(False, 'TypeError!')
218 def testBadGetsig(self):
219 """getsig() should still be able to fetch the fingerprint of bad signatures"""
220 # config needed to use jarsigner and keytool
222 fdroidserver.common.fill_config_defaults(config)
223 fdroidserver.update.config = config
225 apkfile = os.path.join(os.path.dirname(__file__), 'urzip-badsig.apk')
226 sig = fdroidserver.update.getsig(apkfile)
227 self.assertEqual(sig, 'e0ecb5fc2d63088e4a07ae410a127722',
228 "python sig should be: " + str(sig))
230 apkfile = os.path.join(os.path.dirname(__file__), 'urzip-badcert.apk')
231 sig = fdroidserver.update.getsig(apkfile)
232 self.assertEqual(sig, 'e0ecb5fc2d63088e4a07ae410a127722',
233 "python sig should be: " + str(sig))
235 def testScanApksAndObbs(self):
236 os.chdir(os.path.join(localmodule, 'tests'))
237 if os.path.basename(os.getcwd()) != 'tests':
238 raise Exception('This test must be run in the "tests/" subdir')
241 fdroidserver.common.fill_config_defaults(config)
242 config['ndk_paths'] = dict()
243 config['accepted_formats'] = ['json', 'txt', 'yml']
244 fdroidserver.common.config = config
245 fdroidserver.update.config = config
247 fdroidserver.update.options = type('', (), {})()
248 fdroidserver.update.options.clean = True
249 fdroidserver.update.options.delete_unknown = True
250 fdroidserver.update.options.rename_apks = False
251 fdroidserver.update.options.allow_disabled_algorithms = False
253 apps = fdroidserver.metadata.read_metadata(xref=True)
254 knownapks = fdroidserver.common.KnownApks()
255 apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
256 self.assertEqual(len(apks), 12)
258 self.assertEqual(apk['packageName'], 'com.politedroid')
259 self.assertEqual(apk['versionCode'], 3)
260 self.assertEqual(apk['minSdkVersion'], '3')
261 self.assertEqual(apk['targetSdkVersion'], '3')
262 self.assertFalse('maxSdkVersion' in apk)
264 self.assertEqual(apk['packageName'], 'obb.main.oldversion')
265 self.assertEqual(apk['versionCode'], 1444412523)
266 self.assertEqual(apk['minSdkVersion'], '4')
267 self.assertEqual(apk['targetSdkVersion'], '18')
268 self.assertFalse('maxSdkVersion' in apk)
270 fdroidserver.update.insert_obbs('repo', apps, apks)
272 if apk['packageName'] == 'obb.mainpatch.current':
273 self.assertEqual(apk.get('obbMainFile'), 'main.1619.obb.mainpatch.current.obb')
274 self.assertEqual(apk.get('obbPatchFile'), 'patch.1619.obb.mainpatch.current.obb')
275 elif apk['packageName'] == 'obb.main.oldversion':
276 self.assertEqual(apk.get('obbMainFile'), 'main.1434483388.obb.main.oldversion.obb')
277 self.assertIsNone(apk.get('obbPatchFile'))
278 elif apk['packageName'] == 'obb.main.twoversions':
279 self.assertIsNone(apk.get('obbPatchFile'))
280 if apk['versionCode'] == 1101613:
281 self.assertEqual(apk.get('obbMainFile'), 'main.1101613.obb.main.twoversions.obb')
282 elif apk['versionCode'] == 1101615:
283 self.assertEqual(apk.get('obbMainFile'), 'main.1101615.obb.main.twoversions.obb')
284 elif apk['versionCode'] == 1101617:
285 self.assertEqual(apk.get('obbMainFile'), 'main.1101615.obb.main.twoversions.obb')
287 self.assertTrue(False)
288 elif apk['packageName'] == 'info.guardianproject.urzip':
289 self.assertIsNone(apk.get('obbMainFile'))
290 self.assertIsNone(apk.get('obbPatchFile'))
292 def test_scan_apk(self):
294 fdroidserver.common.fill_config_defaults(config)
295 fdroidserver.update.config = config
296 os.chdir(os.path.join(localmodule, 'tests'))
297 if os.path.basename(os.getcwd()) != 'tests':
298 raise Exception('This test must be run in the "tests/" subdir')
300 apk_info = fdroidserver.update.scan_apk('org.dyndns.fules.ck_20.apk')
302 self.assertEqual(apk_info['icons_src'], {'240': 'res/drawable-hdpi-v4/icon_launcher.png',
303 '120': 'res/drawable-ldpi-v4/icon_launcher.png',
304 '160': 'res/drawable-mdpi-v4/icon_launcher.png',
305 '-1': 'res/drawable-mdpi-v4/icon_launcher.png'})
306 self.assertEqual(apk_info['icons'], {})
307 self.assertEqual(apk_info['features'], [])
308 self.assertEqual(apk_info['antiFeatures'], set())
309 self.assertEqual(apk_info['versionName'], 'v1.6pre2')
310 self.assertEqual(apk_info['hash'],
311 '897486e1f857c6c0ee32ccbad0e1b8cd82f6d0e65a44a23f13f852d2b63a18c8')
312 self.assertEqual(apk_info['packageName'], 'org.dyndns.fules.ck')
313 self.assertEqual(apk_info['versionCode'], 20)
314 self.assertEqual(apk_info['size'], 132453)
315 self.assertEqual(apk_info['nativecode'],
316 ['arm64-v8a', 'armeabi', 'armeabi-v7a', 'mips', 'mips64', 'x86', 'x86_64'])
317 self.assertEqual(apk_info['minSdkVersion'], '7')
318 self.assertEqual(apk_info['sig'], '9bf7a6a67f95688daec75eab4b1436ac')
319 self.assertEqual(apk_info['hashType'], 'sha256')
320 self.assertEqual(apk_info['targetSdkVersion'], '8')
322 def test_scan_apk_no_sig(self):
324 fdroidserver.common.fill_config_defaults(config)
325 fdroidserver.update.config = config
326 os.chdir(os.path.join(localmodule, 'tests'))
327 if os.path.basename(os.getcwd()) != 'tests':
328 raise Exception('This test must be run in the "tests/" subdir')
330 with self.assertRaises(fdroidserver.exception.BuildException):
331 fdroidserver.update.scan_apk('urzip-release-unsigned.apk')
333 def test_process_apk(self):
335 def _build_yaml_representer(dumper, data):
336 '''Creates a YAML representation of a Build instance'''
337 return dumper.represent_dict(data)
340 fdroidserver.common.fill_config_defaults(config)
341 fdroidserver.update.config = config
342 os.chdir(os.path.join(localmodule, 'tests'))
343 if os.path.basename(os.getcwd()) != 'tests':
344 raise Exception('This test must be run in the "tests/" subdir')
346 config['ndk_paths'] = dict()
347 config['accepted_formats'] = ['json', 'txt', 'yml']
348 fdroidserver.common.config = config
349 fdroidserver.update.config = config
351 fdroidserver.update.options = type('', (), {})()
352 fdroidserver.update.options.clean = True
353 fdroidserver.update.options.rename_apks = False
354 fdroidserver.update.options.delete_unknown = True
355 fdroidserver.update.options.allow_disabled_algorithms = False
357 for icon_dir in fdroidserver.update.get_all_icon_dirs('repo'):
358 if not os.path.exists(icon_dir):
359 os.makedirs(icon_dir)
361 knownapks = fdroidserver.common.KnownApks()
362 apkList = ['../urzip.apk', '../org.dyndns.fules.ck_20.apk']
364 for apkName in apkList:
365 _, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo', knownapks,
367 # Don't care about the date added to the repo and relative apkName
370 # avoid AAPT application name bug
373 # ensure that icons have been extracted properly
374 if apkName == '../urzip.apk':
375 self.assertEqual(apk['icon'], 'info.guardianproject.urzip.100.png')
376 if apkName == '../org.dyndns.fules.ck_20.apk':
377 self.assertEqual(apk['icon'], 'org.dyndns.fules.ck.20.png')
378 for density in fdroidserver.update.screen_densities:
379 icon_path = os.path.join(fdroidserver.update.get_icon_dir('repo', density),
381 self.assertTrue(os.path.isfile(icon_path))
382 self.assertTrue(os.path.getsize(icon_path) > 1)
384 savepath = os.path.join('metadata', 'apk', apk['packageName'] + '.yaml')
385 # Uncomment to save APK metadata
386 # with open(savepath, 'w') as f:
387 # yaml.add_representer(fdroidserver.metadata.Build, _build_yaml_representer)
388 # yaml.dump(apk, f, default_flow_style=False)
390 with open(savepath, 'r') as f:
391 frompickle = yaml.load(f)
393 self.assertEqual(apk, frompickle)
395 def test_process_apk_signed_by_disabled_algorithms(self):
397 fdroidserver.common.fill_config_defaults(config)
398 fdroidserver.update.config = config
400 config['ndk_paths'] = dict()
401 config['accepted_formats'] = ['json', 'txt', 'yml']
402 fdroidserver.common.config = config
403 fdroidserver.update.config = config
405 fdroidserver.update.options = type('', (), {})()
406 fdroidserver.update.options.clean = True
407 fdroidserver.update.options.verbose = True
408 fdroidserver.update.options.rename_apks = False
409 fdroidserver.update.options.delete_unknown = True
410 fdroidserver.update.options.allow_disabled_algorithms = False
412 knownapks = fdroidserver.common.KnownApks()
414 tmptestsdir = tempfile.mkdtemp(prefix=inspect.currentframe().f_code.co_name,
416 print('tmptestsdir', tmptestsdir)
417 os.chdir(tmptestsdir)
420 # setup the repo, create icons dirs, etc.
421 fdroidserver.update.process_apks({}, 'repo', knownapks)
422 fdroidserver.update.process_apks({}, 'archive', knownapks)
424 disabledsigs = ['org.bitbucket.tickytacky.mirrormirror_2.apk', ]
425 for apkName in disabledsigs:
426 shutil.copy(os.path.join(self.basedir, apkName),
427 os.path.join(tmptestsdir, 'repo'))
429 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
431 allow_disabled_algorithms=True,
432 archive_bad_sig=False)
433 self.assertFalse(skip)
434 self.assertIsNotNone(apk)
435 self.assertTrue(cachechanged)
436 self.assertFalse(os.path.exists(os.path.join('archive', apkName)))
437 self.assertTrue(os.path.exists(os.path.join('repo', apkName)))
439 javac = config['jarsigner'].replace('jarsigner', 'javac')
440 v = subprocess.check_output([javac, '-version'], stderr=subprocess.STDOUT)[6:-1].decode('utf-8')
441 if LooseVersion(v) < LooseVersion('1.8.0_132'):
442 print('SKIPPING: running tests with old Java (' + v + ')')
445 # this test only works on systems with fully updated Java/jarsigner
446 # that has MD5 listed in jdk.jar.disabledAlgorithms in java.security
447 # https://blogs.oracle.com/java-platform-group/oracle-jre-will-no-longer-trust-md5-signed-code-by-default
448 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
450 allow_disabled_algorithms=False,
451 archive_bad_sig=True)
452 self.assertTrue(skip)
453 self.assertIsNone(apk)
454 self.assertFalse(cachechanged)
455 self.assertTrue(os.path.exists(os.path.join('archive', apkName)))
456 self.assertFalse(os.path.exists(os.path.join('repo', apkName)))
458 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'archive',
460 allow_disabled_algorithms=False,
461 archive_bad_sig=False)
462 self.assertFalse(skip)
463 self.assertIsNotNone(apk)
464 self.assertTrue(cachechanged)
465 self.assertTrue(os.path.exists(os.path.join('archive', apkName)))
466 self.assertFalse(os.path.exists(os.path.join('repo', apkName)))
468 # ensure that icons have been moved to the archive as well
469 for density in fdroidserver.update.screen_densities:
470 icon_path = os.path.join(fdroidserver.update.get_icon_dir('archive', density),
472 self.assertTrue(os.path.isfile(icon_path))
473 self.assertTrue(os.path.getsize(icon_path) > 1)
475 badsigs = ['urzip-badcert.apk', 'urzip-badsig.apk', 'urzip-release-unsigned.apk', ]
476 for apkName in badsigs:
477 shutil.copy(os.path.join(self.basedir, apkName),
478 os.path.join(tmptestsdir, 'repo'))
480 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
482 allow_disabled_algorithms=False,
483 archive_bad_sig=False)
484 self.assertTrue(skip)
485 self.assertIsNone(apk)
486 self.assertFalse(cachechanged)
488 def test_process_invalid_apk(self):
489 os.chdir(os.path.join(localmodule, 'tests'))
490 if os.path.basename(os.getcwd()) != 'tests':
491 raise Exception('This test must be run in the "tests/" subdir')
494 fdroidserver.common.fill_config_defaults(config)
495 fdroidserver.common.config = config
496 fdroidserver.update.config = config
497 fdroidserver.update.options.delete_unknown = False
499 knownapks = fdroidserver.common.KnownApks()
500 apk = 'fake.ota.update_1234.zip' # this is not an APK, scanning should fail
501 (skip, apk, cachechanged) = fdroidserver.update.process_apk({}, apk, 'repo', knownapks,
504 self.assertTrue(skip)
505 self.assertIsNone(apk)
506 self.assertFalse(cachechanged)
508 def test_translate_per_build_anti_features(self):
509 os.chdir(os.path.join(localmodule, 'tests'))
510 if os.path.basename(os.getcwd()) != 'tests':
511 raise Exception('This test must be run in the "tests/" subdir')
514 fdroidserver.common.fill_config_defaults(config)
515 config['ndk_paths'] = dict()
516 config['accepted_formats'] = ['json', 'txt', 'yml']
517 fdroidserver.common.config = config
518 fdroidserver.update.config = config
520 fdroidserver.update.options = type('', (), {})()
521 fdroidserver.update.options.clean = True
522 fdroidserver.update.options.delete_unknown = True
523 fdroidserver.update.options.rename_apks = False
524 fdroidserver.update.options.allow_disabled_algorithms = False
526 apps = fdroidserver.metadata.read_metadata(xref=True)
527 knownapks = fdroidserver.common.KnownApks()
528 apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
529 fdroidserver.update.translate_per_build_anti_features(apps, apks)
530 self.assertEqual(len(apks), 12)
533 if apk['packageName'] == 'com.politedroid' and apk['versionCode'] == 3:
534 antiFeatures = apk.get('antiFeatures')
535 self.assertTrue('KnownVuln' in antiFeatures)
536 self.assertEqual(3, len(antiFeatures))
538 self.assertTrue(foundtest)
540 def test_create_metadata_from_template(self):
541 tmptestsdir = tempfile.mkdtemp(prefix=inspect.currentframe().f_code.co_name,
543 print('tmptestsdir', tmptestsdir)
544 os.chdir(tmptestsdir)
547 shutil.copy(os.path.join(localmodule, 'tests', 'urzip.apk'), 'repo')
550 fdroidserver.common.fill_config_defaults(config)
551 config['ndk_paths'] = dict()
552 config['accepted_formats'] = ['json', 'txt', 'yml']
553 fdroidserver.common.config = config
554 fdroidserver.update.config = config
556 fdroidserver.update.options = type('', (), {})()
557 fdroidserver.update.options.clean = True
558 fdroidserver.update.options.delete_unknown = False
559 fdroidserver.update.options.rename_apks = False
560 fdroidserver.update.options.allow_disabled_algorithms = False
562 knownapks = fdroidserver.common.KnownApks()
563 apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
564 self.assertEqual(1, len(apks))
567 testfile = 'metadata/info.guardianproject.urzip.yml'
568 # create empty 0 byte .yml file, run read_metadata, it should work
569 open(testfile, 'a').close()
570 apps = fdroidserver.metadata.read_metadata(xref=True)
571 self.assertEqual(1, len(apps))
574 # test using internal template
575 apps = fdroidserver.metadata.read_metadata(xref=True)
576 self.assertEqual(0, len(apps))
577 fdroidserver.update.create_metadata_from_template(apk)
578 self.assertTrue(os.path.exists(testfile))
579 apps = fdroidserver.metadata.read_metadata(xref=True)
580 self.assertEqual(1, len(apps))
581 for app in apps.values():
582 self.assertEqual('urzip', app['Name'])
583 self.assertEqual(1, len(app['Categories']))
586 # test using external template.yml
588 self.assertFalse(os.path.exists(testfile))
589 shutil.copy(os.path.join(localmodule, 'examples', 'template.yml'), tmptestsdir)
590 fdroidserver.update.create_metadata_from_template(apk)
591 self.assertTrue(os.path.exists(testfile))
592 apps = fdroidserver.metadata.read_metadata(xref=True)
593 self.assertEqual(1, len(apps))
594 for app in apps.values():
595 self.assertEqual('urzip', app['Name'])
596 self.assertEqual(1, len(app['Categories']))
597 self.assertEqual('Internet', app['Categories'][0])
599 with open(testfile) as fp:
601 self.assertEqual('urzip', data['Name'])
602 self.assertEqual('urzip', data['Summary'])
604 def test_has_known_vulnerability(self):
606 'org.bitbucket.tickytacky.mirrormirror_1.apk',
607 'org.bitbucket.tickytacky.mirrormirror_2.apk',
608 'org.bitbucket.tickytacky.mirrormirror_3.apk',
609 'org.bitbucket.tickytacky.mirrormirror_4.apk',
610 'org.dyndns.fules.ck_20.apk',
615 'urzip-release-unsigned.apk',
616 'repo/com.politedroid_3.apk',
617 'repo/com.politedroid_4.apk',
618 'repo/com.politedroid_5.apk',
619 'repo/com.politedroid_6.apk',
620 'repo/obb.main.oldversion_1444412523.apk',
621 'repo/obb.mainpatch.current_1619_another-release-key.apk',
622 'repo/obb.mainpatch.current_1619.apk',
623 'repo/obb.main.twoversions_1101613.apk',
624 'repo/obb.main.twoversions_1101615.apk',
625 'repo/obb.main.twoversions_1101617.apk',
626 'repo/urzip-; Рахма́нинов, [rɐxˈmanʲɪnəf] سيرجي_رخمانينوف 谢尔盖·.apk',
629 self.assertFalse(fdroidserver.update.has_known_vulnerability(f))
630 with self.assertRaises(fdroidserver.exception.FDroidException):
631 fdroidserver.update.has_known_vulnerability('janus.apk')
634 if __name__ == "__main__":
635 parser = optparse.OptionParser()
636 parser.add_option("-v", "--verbose", action="store_true", default=False,
637 help="Spew out even more information than normal")
638 (fdroidserver.common.options, args) = parser.parse_args(['--verbose'])
640 newSuite = unittest.TestSuite()
641 newSuite.addTest(unittest.makeSuite(UpdateTest))
642 unittest.main(failfast=False)