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), 13)
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')
301 self.assertEqual(apk_info['icons_src'], {'240': 'res/drawable-hdpi-v4/icon_launcher.png',
302 '120': 'res/drawable-ldpi-v4/icon_launcher.png',
303 '160': 'res/drawable-mdpi-v4/icon_launcher.png',
304 '-1': 'res/drawable-mdpi-v4/icon_launcher.png'})
305 self.assertEqual(apk_info['icons'], {})
306 self.assertEqual(apk_info['features'], [])
307 self.assertEqual(apk_info['antiFeatures'], set())
308 self.assertEqual(apk_info['versionName'], 'v1.6pre2')
309 self.assertEqual(apk_info['hash'],
310 '897486e1f857c6c0ee32ccbad0e1b8cd82f6d0e65a44a23f13f852d2b63a18c8')
311 self.assertEqual(apk_info['packageName'], 'org.dyndns.fules.ck')
312 self.assertEqual(apk_info['versionCode'], 20)
313 self.assertEqual(apk_info['size'], 132453)
314 self.assertEqual(apk_info['nativecode'],
315 ['arm64-v8a', 'armeabi', 'armeabi-v7a', 'mips', 'mips64', 'x86', 'x86_64'])
316 self.assertEqual(apk_info['minSdkVersion'], '7')
317 self.assertEqual(apk_info['sig'], '9bf7a6a67f95688daec75eab4b1436ac')
318 self.assertEqual(apk_info['hashType'], 'sha256')
319 self.assertEqual(apk_info['targetSdkVersion'], '8')
321 apk_info = fdroidserver.update.scan_apk('org.bitbucket.tickytacky.mirrormirror_4.apk')
322 self.assertEqual(apk_info['icons_src'], {'160': 'res/drawable-mdpi/mirror.png',
323 '-1': 'res/drawable-mdpi/mirror.png'})
325 apk_info = fdroidserver.update.scan_apk('repo/info.zwanenburg.caffeinetile_4.apk')
326 self.assertEqual(apk_info['icons_src'], {'160': 'res/drawable/ic_coffee_on.xml',
327 '-1': 'res/drawable/ic_coffee_on.xml'})
329 apk_info = fdroidserver.update.scan_apk('repo/com.politedroid_6.apk')
330 self.assertEqual(apk_info['icons_src'], {'120': 'res/drawable-ldpi-v4/icon.png',
331 '160': 'res/drawable-mdpi-v4/icon.png',
332 '240': 'res/drawable-hdpi-v4/icon.png',
333 '320': 'res/drawable-xhdpi-v4/icon.png',
334 '-1': 'res/drawable-mdpi-v4/icon.png'})
336 def test_scan_apk_no_sig(self):
338 fdroidserver.common.fill_config_defaults(config)
339 fdroidserver.update.config = config
340 os.chdir(os.path.join(localmodule, 'tests'))
341 if os.path.basename(os.getcwd()) != 'tests':
342 raise Exception('This test must be run in the "tests/" subdir')
344 with self.assertRaises(fdroidserver.exception.BuildException):
345 fdroidserver.update.scan_apk('urzip-release-unsigned.apk')
347 def test_process_apk(self):
349 def _build_yaml_representer(dumper, data):
350 '''Creates a YAML representation of a Build instance'''
351 return dumper.represent_dict(data)
354 fdroidserver.common.fill_config_defaults(config)
355 fdroidserver.update.config = config
356 os.chdir(os.path.join(localmodule, 'tests'))
357 if os.path.basename(os.getcwd()) != 'tests':
358 raise Exception('This test must be run in the "tests/" subdir')
360 config['ndk_paths'] = dict()
361 config['accepted_formats'] = ['json', 'txt', 'yml']
362 fdroidserver.common.config = config
363 fdroidserver.update.config = config
365 fdroidserver.update.options = type('', (), {})()
366 fdroidserver.update.options.clean = True
367 fdroidserver.update.options.rename_apks = False
368 fdroidserver.update.options.delete_unknown = True
369 fdroidserver.update.options.allow_disabled_algorithms = False
371 for icon_dir in fdroidserver.update.get_all_icon_dirs('repo'):
372 if not os.path.exists(icon_dir):
373 os.makedirs(icon_dir)
375 knownapks = fdroidserver.common.KnownApks()
376 apkList = ['../urzip.apk', '../org.dyndns.fules.ck_20.apk']
378 for apkName in apkList:
379 _, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo', knownapks,
381 # Don't care about the date added to the repo and relative apkName
384 # avoid AAPT application name bug
387 # ensure that icons have been extracted properly
388 if apkName == '../urzip.apk':
389 self.assertEqual(apk['icon'], 'info.guardianproject.urzip.100.png')
390 if apkName == '../org.dyndns.fules.ck_20.apk':
391 self.assertEqual(apk['icon'], 'org.dyndns.fules.ck.20.png')
392 for density in fdroidserver.update.screen_densities:
393 icon_path = os.path.join(fdroidserver.update.get_icon_dir('repo', density),
395 self.assertTrue(os.path.isfile(icon_path))
396 self.assertTrue(os.path.getsize(icon_path) > 1)
398 savepath = os.path.join('metadata', 'apk', apk['packageName'] + '.yaml')
399 # Uncomment to save APK metadata
400 # with open(savepath, 'w') as f:
401 # yaml.add_representer(fdroidserver.metadata.Build, _build_yaml_representer)
402 # yaml.dump(apk, f, default_flow_style=False)
404 with open(savepath, 'r') as f:
405 frompickle = yaml.load(f)
407 self.assertEqual(apk, frompickle)
409 def test_process_apk_signed_by_disabled_algorithms(self):
411 fdroidserver.common.fill_config_defaults(config)
412 fdroidserver.update.config = config
414 config['ndk_paths'] = dict()
415 config['accepted_formats'] = ['json', 'txt', 'yml']
416 fdroidserver.common.config = config
417 fdroidserver.update.config = config
419 fdroidserver.update.options = type('', (), {})()
420 fdroidserver.update.options.clean = True
421 fdroidserver.update.options.verbose = True
422 fdroidserver.update.options.rename_apks = False
423 fdroidserver.update.options.delete_unknown = True
424 fdroidserver.update.options.allow_disabled_algorithms = False
426 knownapks = fdroidserver.common.KnownApks()
428 tmptestsdir = tempfile.mkdtemp(prefix=inspect.currentframe().f_code.co_name,
430 print('tmptestsdir', tmptestsdir)
431 os.chdir(tmptestsdir)
434 # setup the repo, create icons dirs, etc.
435 fdroidserver.update.process_apks({}, 'repo', knownapks)
436 fdroidserver.update.process_apks({}, 'archive', knownapks)
438 disabledsigs = ['org.bitbucket.tickytacky.mirrormirror_2.apk', ]
439 for apkName in disabledsigs:
440 shutil.copy(os.path.join(self.basedir, apkName),
441 os.path.join(tmptestsdir, 'repo'))
443 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
445 allow_disabled_algorithms=True,
446 archive_bad_sig=False)
447 self.assertFalse(skip)
448 self.assertIsNotNone(apk)
449 self.assertTrue(cachechanged)
450 self.assertFalse(os.path.exists(os.path.join('archive', apkName)))
451 self.assertTrue(os.path.exists(os.path.join('repo', apkName)))
453 javac = config['jarsigner'].replace('jarsigner', 'javac')
454 v = subprocess.check_output([javac, '-version'], stderr=subprocess.STDOUT)[6:-1].decode('utf-8')
455 if LooseVersion(v) < LooseVersion('1.8.0_132'):
456 print('SKIPPING: running tests with old Java (' + v + ')')
459 # this test only works on systems with fully updated Java/jarsigner
460 # that has MD5 listed in jdk.jar.disabledAlgorithms in java.security
461 # https://blogs.oracle.com/java-platform-group/oracle-jre-will-no-longer-trust-md5-signed-code-by-default
462 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
464 allow_disabled_algorithms=False,
465 archive_bad_sig=True)
466 self.assertTrue(skip)
467 self.assertIsNone(apk)
468 self.assertFalse(cachechanged)
469 self.assertTrue(os.path.exists(os.path.join('archive', apkName)))
470 self.assertFalse(os.path.exists(os.path.join('repo', apkName)))
472 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'archive',
474 allow_disabled_algorithms=False,
475 archive_bad_sig=False)
476 self.assertFalse(skip)
477 self.assertIsNotNone(apk)
478 self.assertTrue(cachechanged)
479 self.assertTrue(os.path.exists(os.path.join('archive', apkName)))
480 self.assertFalse(os.path.exists(os.path.join('repo', apkName)))
482 # ensure that icons have been moved to the archive as well
483 for density in fdroidserver.update.screen_densities:
484 icon_path = os.path.join(fdroidserver.update.get_icon_dir('archive', density),
486 self.assertTrue(os.path.isfile(icon_path))
487 self.assertTrue(os.path.getsize(icon_path) > 1)
489 badsigs = ['urzip-badcert.apk', 'urzip-badsig.apk', 'urzip-release-unsigned.apk', ]
490 for apkName in badsigs:
491 shutil.copy(os.path.join(self.basedir, apkName),
492 os.path.join(tmptestsdir, 'repo'))
494 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
496 allow_disabled_algorithms=False,
497 archive_bad_sig=False)
498 self.assertTrue(skip)
499 self.assertIsNone(apk)
500 self.assertFalse(cachechanged)
502 def test_process_invalid_apk(self):
503 os.chdir(os.path.join(localmodule, 'tests'))
504 if os.path.basename(os.getcwd()) != 'tests':
505 raise Exception('This test must be run in the "tests/" subdir')
508 fdroidserver.common.fill_config_defaults(config)
509 fdroidserver.common.config = config
510 fdroidserver.update.config = config
511 fdroidserver.update.options.delete_unknown = False
513 knownapks = fdroidserver.common.KnownApks()
514 apk = 'fake.ota.update_1234.zip' # this is not an APK, scanning should fail
515 (skip, apk, cachechanged) = fdroidserver.update.process_apk({}, apk, 'repo', knownapks,
518 self.assertTrue(skip)
519 self.assertIsNone(apk)
520 self.assertFalse(cachechanged)
522 def test_translate_per_build_anti_features(self):
523 os.chdir(os.path.join(localmodule, 'tests'))
524 if os.path.basename(os.getcwd()) != 'tests':
525 raise Exception('This test must be run in the "tests/" subdir')
528 fdroidserver.common.fill_config_defaults(config)
529 config['ndk_paths'] = dict()
530 config['accepted_formats'] = ['json', 'txt', 'yml']
531 fdroidserver.common.config = config
532 fdroidserver.update.config = config
534 fdroidserver.update.options = type('', (), {})()
535 fdroidserver.update.options.clean = True
536 fdroidserver.update.options.delete_unknown = True
537 fdroidserver.update.options.rename_apks = False
538 fdroidserver.update.options.allow_disabled_algorithms = False
540 apps = fdroidserver.metadata.read_metadata(xref=True)
541 knownapks = fdroidserver.common.KnownApks()
542 apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
543 fdroidserver.update.translate_per_build_anti_features(apps, apks)
544 self.assertEqual(len(apks), 13)
547 if apk['packageName'] == 'com.politedroid' and apk['versionCode'] == 3:
548 antiFeatures = apk.get('antiFeatures')
549 self.assertTrue('KnownVuln' in antiFeatures)
550 self.assertEqual(3, len(antiFeatures))
552 self.assertTrue(foundtest)
554 def test_create_metadata_from_template(self):
555 tmptestsdir = tempfile.mkdtemp(prefix=inspect.currentframe().f_code.co_name,
557 print('tmptestsdir', tmptestsdir)
558 os.chdir(tmptestsdir)
561 shutil.copy(os.path.join(localmodule, 'tests', 'urzip.apk'), 'repo')
564 fdroidserver.common.fill_config_defaults(config)
565 config['ndk_paths'] = dict()
566 config['accepted_formats'] = ['json', 'txt', 'yml']
567 fdroidserver.common.config = config
568 fdroidserver.update.config = config
570 fdroidserver.update.options = type('', (), {})()
571 fdroidserver.update.options.clean = True
572 fdroidserver.update.options.delete_unknown = False
573 fdroidserver.update.options.rename_apks = False
574 fdroidserver.update.options.allow_disabled_algorithms = False
576 knownapks = fdroidserver.common.KnownApks()
577 apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
578 self.assertEqual(1, len(apks))
581 testfile = 'metadata/info.guardianproject.urzip.yml'
582 # create empty 0 byte .yml file, run read_metadata, it should work
583 open(testfile, 'a').close()
584 apps = fdroidserver.metadata.read_metadata(xref=True)
585 self.assertEqual(1, len(apps))
588 # test using internal template
589 apps = fdroidserver.metadata.read_metadata(xref=True)
590 self.assertEqual(0, len(apps))
591 fdroidserver.update.create_metadata_from_template(apk)
592 self.assertTrue(os.path.exists(testfile))
593 apps = fdroidserver.metadata.read_metadata(xref=True)
594 self.assertEqual(1, len(apps))
595 for app in apps.values():
596 self.assertEqual('urzip', app['Name'])
597 self.assertEqual(1, len(app['Categories']))
600 # test using external template.yml
602 self.assertFalse(os.path.exists(testfile))
603 shutil.copy(os.path.join(localmodule, 'examples', 'template.yml'), tmptestsdir)
604 fdroidserver.update.create_metadata_from_template(apk)
605 self.assertTrue(os.path.exists(testfile))
606 apps = fdroidserver.metadata.read_metadata(xref=True)
607 self.assertEqual(1, len(apps))
608 for app in apps.values():
609 self.assertEqual('urzip', app['Name'])
610 self.assertEqual(1, len(app['Categories']))
611 self.assertEqual('Internet', app['Categories'][0])
613 with open(testfile) as fp:
615 self.assertEqual('urzip', data['Name'])
616 self.assertEqual('urzip', data['Summary'])
618 def test_has_known_vulnerability(self):
620 'org.bitbucket.tickytacky.mirrormirror_1.apk',
621 'org.bitbucket.tickytacky.mirrormirror_2.apk',
622 'org.bitbucket.tickytacky.mirrormirror_3.apk',
623 'org.bitbucket.tickytacky.mirrormirror_4.apk',
624 'org.dyndns.fules.ck_20.apk',
629 'urzip-release-unsigned.apk',
630 'repo/com.politedroid_3.apk',
631 'repo/com.politedroid_4.apk',
632 'repo/com.politedroid_5.apk',
633 'repo/com.politedroid_6.apk',
634 'repo/obb.main.oldversion_1444412523.apk',
635 'repo/obb.mainpatch.current_1619_another-release-key.apk',
636 'repo/obb.mainpatch.current_1619.apk',
637 'repo/obb.main.twoversions_1101613.apk',
638 'repo/obb.main.twoversions_1101615.apk',
639 'repo/obb.main.twoversions_1101617.apk',
640 'repo/urzip-; Рахма́нинов, [rɐxˈmanʲɪnəf] سيرجي_رخمانينوف 谢尔盖·.apk',
643 self.assertFalse(fdroidserver.update.has_known_vulnerability(f))
644 with self.assertRaises(fdroidserver.exception.FDroidException):
645 fdroidserver.update.has_known_vulnerability('janus.apk')
648 if __name__ == "__main__":
649 parser = optparse.OptionParser()
650 parser.add_option("-v", "--verbose", action="store_true", default=False,
651 help="Spew out even more information than normal")
652 (fdroidserver.common.options, args) = parser.parse_args(['--verbose'])
654 newSuite = unittest.TestSuite()
655 newSuite.addTest(unittest.makeSuite(UpdateTest))
656 unittest.main(failfast=False)