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.common.config = config
296 fdroidserver.update.config = config
297 os.chdir(os.path.join(localmodule, 'tests'))
298 if os.path.basename(os.getcwd()) != 'tests':
299 raise Exception('This test must be run in the "tests/" subdir')
301 apk_info = fdroidserver.update.scan_apk('repo/duplicate.permisssions_9999999.apk')
302 self.assertEqual(apk_info['icons_src'], {'160': 'res/drawable/ic_launcher.png',
303 '-1': 'res/drawable/ic_launcher.png'})
305 apk_info = fdroidserver.update.scan_apk('org.dyndns.fules.ck_20.apk')
306 self.assertEqual(apk_info['icons_src'], {'240': 'res/drawable-hdpi-v4/icon_launcher.png',
307 '120': 'res/drawable-ldpi-v4/icon_launcher.png',
308 '160': 'res/drawable-mdpi-v4/icon_launcher.png',
309 '-1': 'res/drawable-mdpi-v4/icon_launcher.png'})
310 self.assertEqual(apk_info['icons'], {})
311 self.assertEqual(apk_info['features'], [])
312 self.assertEqual(apk_info['antiFeatures'], set())
313 self.assertEqual(apk_info['versionName'], 'v1.6pre2')
314 self.assertEqual(apk_info['hash'],
315 '897486e1f857c6c0ee32ccbad0e1b8cd82f6d0e65a44a23f13f852d2b63a18c8')
316 self.assertEqual(apk_info['packageName'], 'org.dyndns.fules.ck')
317 self.assertEqual(apk_info['versionCode'], 20)
318 self.assertEqual(apk_info['size'], 132453)
319 self.assertEqual(apk_info['nativecode'],
320 ['arm64-v8a', 'armeabi', 'armeabi-v7a', 'mips', 'mips64', 'x86', 'x86_64'])
321 self.assertEqual(apk_info['minSdkVersion'], '7')
322 self.assertEqual(apk_info['sig'], '9bf7a6a67f95688daec75eab4b1436ac')
323 self.assertEqual(apk_info['hashType'], 'sha256')
324 self.assertEqual(apk_info['targetSdkVersion'], '8')
326 apk_info = fdroidserver.update.scan_apk('org.bitbucket.tickytacky.mirrormirror_4.apk')
327 self.assertEqual(apk_info['icons_src'], {'160': 'res/drawable-mdpi/mirror.png',
328 '-1': 'res/drawable-mdpi/mirror.png'})
330 apk_info = fdroidserver.update.scan_apk('repo/info.zwanenburg.caffeinetile_4.apk')
331 self.assertEqual(apk_info['icons_src'], {'160': 'res/drawable/ic_coffee_on.xml',
332 '-1': 'res/drawable/ic_coffee_on.xml'})
334 apk_info = fdroidserver.update.scan_apk('repo/com.politedroid_6.apk')
335 self.assertEqual(apk_info['icons_src'], {'120': 'res/drawable-ldpi-v4/icon.png',
336 '160': 'res/drawable-mdpi-v4/icon.png',
337 '240': 'res/drawable-hdpi-v4/icon.png',
338 '320': 'res/drawable-xhdpi-v4/icon.png',
339 '-1': 'res/drawable-mdpi-v4/icon.png'})
341 apk_info = fdroidserver.update.scan_apk('SpeedoMeterApp.main_1.apk')
342 self.assertEqual(apk_info['icons_src'], {})
344 def test_scan_apk_no_sig(self):
346 fdroidserver.common.fill_config_defaults(config)
347 fdroidserver.update.config = config
348 os.chdir(os.path.join(localmodule, 'tests'))
349 if os.path.basename(os.getcwd()) != 'tests':
350 raise Exception('This test must be run in the "tests/" subdir')
352 with self.assertRaises(fdroidserver.exception.BuildException):
353 fdroidserver.update.scan_apk('urzip-release-unsigned.apk')
355 def test_process_apk(self):
357 def _build_yaml_representer(dumper, data):
358 '''Creates a YAML representation of a Build instance'''
359 return dumper.represent_dict(data)
362 fdroidserver.common.fill_config_defaults(config)
363 fdroidserver.update.config = config
364 os.chdir(os.path.join(localmodule, 'tests'))
365 if os.path.basename(os.getcwd()) != 'tests':
366 raise Exception('This test must be run in the "tests/" subdir')
368 config['ndk_paths'] = dict()
369 config['accepted_formats'] = ['json', 'txt', 'yml']
370 fdroidserver.common.config = config
371 fdroidserver.update.config = config
373 fdroidserver.update.options = type('', (), {})()
374 fdroidserver.update.options.clean = True
375 fdroidserver.update.options.rename_apks = False
376 fdroidserver.update.options.delete_unknown = True
377 fdroidserver.update.options.allow_disabled_algorithms = False
379 for icon_dir in fdroidserver.update.get_all_icon_dirs('repo'):
380 if not os.path.exists(icon_dir):
381 os.makedirs(icon_dir)
383 knownapks = fdroidserver.common.KnownApks()
384 apkList = ['../urzip.apk', '../org.dyndns.fules.ck_20.apk']
386 for apkName in apkList:
387 _, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo', knownapks,
389 # Don't care about the date added to the repo and relative apkName
392 # avoid AAPT application name bug
395 # ensure that icons have been extracted properly
396 if apkName == '../urzip.apk':
397 self.assertEqual(apk['icon'], 'info.guardianproject.urzip.100.png')
398 if apkName == '../org.dyndns.fules.ck_20.apk':
399 self.assertEqual(apk['icon'], 'org.dyndns.fules.ck.20.png')
400 for density in fdroidserver.update.screen_densities:
401 icon_path = os.path.join(fdroidserver.update.get_icon_dir('repo', density),
403 self.assertTrue(os.path.isfile(icon_path))
404 self.assertTrue(os.path.getsize(icon_path) > 1)
406 savepath = os.path.join('metadata', 'apk', apk['packageName'] + '.yaml')
407 # Uncomment to save APK metadata
408 # with open(savepath, 'w') as f:
409 # yaml.add_representer(fdroidserver.metadata.Build, _build_yaml_representer)
410 # yaml.dump(apk, f, default_flow_style=False)
412 with open(savepath, 'r') as f:
413 frompickle = yaml.load(f)
415 self.assertEqual(apk, frompickle)
417 def test_process_apk_signed_by_disabled_algorithms(self):
419 fdroidserver.common.fill_config_defaults(config)
420 fdroidserver.update.config = config
422 config['ndk_paths'] = dict()
423 config['accepted_formats'] = ['json', 'txt', 'yml']
424 fdroidserver.common.config = config
425 fdroidserver.update.config = config
427 fdroidserver.update.options = type('', (), {})()
428 fdroidserver.update.options.clean = True
429 fdroidserver.update.options.verbose = True
430 fdroidserver.update.options.rename_apks = False
431 fdroidserver.update.options.delete_unknown = True
432 fdroidserver.update.options.allow_disabled_algorithms = False
434 knownapks = fdroidserver.common.KnownApks()
436 tmptestsdir = tempfile.mkdtemp(prefix=inspect.currentframe().f_code.co_name,
438 print('tmptestsdir', tmptestsdir)
439 os.chdir(tmptestsdir)
442 # setup the repo, create icons dirs, etc.
443 fdroidserver.update.process_apks({}, 'repo', knownapks)
444 fdroidserver.update.process_apks({}, 'archive', knownapks)
446 disabledsigs = ['org.bitbucket.tickytacky.mirrormirror_2.apk', ]
447 for apkName in disabledsigs:
448 shutil.copy(os.path.join(self.basedir, apkName),
449 os.path.join(tmptestsdir, 'repo'))
451 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
453 allow_disabled_algorithms=True,
454 archive_bad_sig=False)
455 self.assertFalse(skip)
456 self.assertIsNotNone(apk)
457 self.assertTrue(cachechanged)
458 self.assertFalse(os.path.exists(os.path.join('archive', apkName)))
459 self.assertTrue(os.path.exists(os.path.join('repo', apkName)))
461 javac = config['jarsigner'].replace('jarsigner', 'javac')
462 v = subprocess.check_output([javac, '-version'], stderr=subprocess.STDOUT)[6:-1].decode('utf-8')
463 if LooseVersion(v) < LooseVersion('1.8.0_132'):
464 print('SKIPPING: running tests with old Java (' + v + ')')
467 # this test only works on systems with fully updated Java/jarsigner
468 # that has MD5 listed in jdk.jar.disabledAlgorithms in java.security
469 # https://blogs.oracle.com/java-platform-group/oracle-jre-will-no-longer-trust-md5-signed-code-by-default
470 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
472 allow_disabled_algorithms=False,
473 archive_bad_sig=True)
474 self.assertTrue(skip)
475 self.assertIsNone(apk)
476 self.assertFalse(cachechanged)
477 self.assertTrue(os.path.exists(os.path.join('archive', apkName)))
478 self.assertFalse(os.path.exists(os.path.join('repo', apkName)))
480 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'archive',
482 allow_disabled_algorithms=False,
483 archive_bad_sig=False)
484 self.assertFalse(skip)
485 self.assertIsNotNone(apk)
486 self.assertTrue(cachechanged)
487 self.assertTrue(os.path.exists(os.path.join('archive', apkName)))
488 self.assertFalse(os.path.exists(os.path.join('repo', apkName)))
490 # ensure that icons have been moved to the archive as well
491 for density in fdroidserver.update.screen_densities:
492 icon_path = os.path.join(fdroidserver.update.get_icon_dir('archive', density),
494 self.assertTrue(os.path.isfile(icon_path))
495 self.assertTrue(os.path.getsize(icon_path) > 1)
497 badsigs = ['urzip-badcert.apk', 'urzip-badsig.apk', 'urzip-release-unsigned.apk', ]
498 for apkName in badsigs:
499 shutil.copy(os.path.join(self.basedir, apkName),
500 os.path.join(tmptestsdir, 'repo'))
502 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
504 allow_disabled_algorithms=False,
505 archive_bad_sig=False)
506 self.assertTrue(skip)
507 self.assertIsNone(apk)
508 self.assertFalse(cachechanged)
510 def test_process_invalid_apk(self):
511 os.chdir(os.path.join(localmodule, 'tests'))
512 if os.path.basename(os.getcwd()) != 'tests':
513 raise Exception('This test must be run in the "tests/" subdir')
516 fdroidserver.common.fill_config_defaults(config)
517 fdroidserver.common.config = config
518 fdroidserver.update.config = config
519 fdroidserver.update.options.delete_unknown = False
521 knownapks = fdroidserver.common.KnownApks()
522 apk = 'fake.ota.update_1234.zip' # this is not an APK, scanning should fail
523 (skip, apk, cachechanged) = fdroidserver.update.process_apk({}, apk, 'repo', knownapks,
526 self.assertTrue(skip)
527 self.assertIsNone(apk)
528 self.assertFalse(cachechanged)
530 def test_translate_per_build_anti_features(self):
531 os.chdir(os.path.join(localmodule, 'tests'))
532 if os.path.basename(os.getcwd()) != 'tests':
533 raise Exception('This test must be run in the "tests/" subdir')
536 fdroidserver.common.fill_config_defaults(config)
537 config['ndk_paths'] = dict()
538 config['accepted_formats'] = ['json', 'txt', 'yml']
539 fdroidserver.common.config = config
540 fdroidserver.update.config = config
542 fdroidserver.update.options = type('', (), {})()
543 fdroidserver.update.options.clean = True
544 fdroidserver.update.options.delete_unknown = True
545 fdroidserver.update.options.rename_apks = False
546 fdroidserver.update.options.allow_disabled_algorithms = False
548 apps = fdroidserver.metadata.read_metadata(xref=True)
549 knownapks = fdroidserver.common.KnownApks()
550 apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
551 fdroidserver.update.translate_per_build_anti_features(apps, apks)
552 self.assertEqual(len(apks), 13)
555 if apk['packageName'] == 'com.politedroid' and apk['versionCode'] == 3:
556 antiFeatures = apk.get('antiFeatures')
557 self.assertTrue('KnownVuln' in antiFeatures)
558 self.assertEqual(3, len(antiFeatures))
560 self.assertTrue(foundtest)
562 def test_create_metadata_from_template(self):
563 tmptestsdir = tempfile.mkdtemp(prefix=inspect.currentframe().f_code.co_name,
565 print('tmptestsdir', tmptestsdir)
566 os.chdir(tmptestsdir)
569 shutil.copy(os.path.join(localmodule, 'tests', 'urzip.apk'), 'repo')
572 fdroidserver.common.fill_config_defaults(config)
573 config['ndk_paths'] = dict()
574 config['accepted_formats'] = ['json', 'txt', 'yml']
575 fdroidserver.common.config = config
576 fdroidserver.update.config = config
578 fdroidserver.update.options = type('', (), {})()
579 fdroidserver.update.options.clean = True
580 fdroidserver.update.options.delete_unknown = False
581 fdroidserver.update.options.rename_apks = False
582 fdroidserver.update.options.allow_disabled_algorithms = False
584 knownapks = fdroidserver.common.KnownApks()
585 apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
586 self.assertEqual(1, len(apks))
589 testfile = 'metadata/info.guardianproject.urzip.yml'
590 # create empty 0 byte .yml file, run read_metadata, it should work
591 open(testfile, 'a').close()
592 apps = fdroidserver.metadata.read_metadata(xref=True)
593 self.assertEqual(1, len(apps))
596 # test using internal template
597 apps = fdroidserver.metadata.read_metadata(xref=True)
598 self.assertEqual(0, len(apps))
599 fdroidserver.update.create_metadata_from_template(apk)
600 self.assertTrue(os.path.exists(testfile))
601 apps = fdroidserver.metadata.read_metadata(xref=True)
602 self.assertEqual(1, len(apps))
603 for app in apps.values():
604 self.assertEqual('urzip', app['Name'])
605 self.assertEqual(1, len(app['Categories']))
608 # test using external template.yml
610 self.assertFalse(os.path.exists(testfile))
611 shutil.copy(os.path.join(localmodule, 'examples', 'template.yml'), tmptestsdir)
612 fdroidserver.update.create_metadata_from_template(apk)
613 self.assertTrue(os.path.exists(testfile))
614 apps = fdroidserver.metadata.read_metadata(xref=True)
615 self.assertEqual(1, len(apps))
616 for app in apps.values():
617 self.assertEqual('urzip', app['Name'])
618 self.assertEqual(1, len(app['Categories']))
619 self.assertEqual('Internet', app['Categories'][0])
621 with open(testfile) as fp:
623 self.assertEqual('urzip', data['Name'])
624 self.assertEqual('urzip', data['Summary'])
626 def test_has_known_vulnerability(self):
628 'org.bitbucket.tickytacky.mirrormirror_1.apk',
629 'org.bitbucket.tickytacky.mirrormirror_2.apk',
630 'org.bitbucket.tickytacky.mirrormirror_3.apk',
631 'org.bitbucket.tickytacky.mirrormirror_4.apk',
632 'org.dyndns.fules.ck_20.apk',
637 'urzip-release-unsigned.apk',
638 'repo/com.politedroid_3.apk',
639 'repo/com.politedroid_4.apk',
640 'repo/com.politedroid_5.apk',
641 'repo/com.politedroid_6.apk',
642 'repo/obb.main.oldversion_1444412523.apk',
643 'repo/obb.mainpatch.current_1619_another-release-key.apk',
644 'repo/obb.mainpatch.current_1619.apk',
645 'repo/obb.main.twoversions_1101613.apk',
646 'repo/obb.main.twoversions_1101615.apk',
647 'repo/obb.main.twoversions_1101617.apk',
648 'repo/urzip-; Рахма́нинов, [rɐxˈmanʲɪnəf] سيرجي_رخمانينوف 谢尔盖·.apk',
651 self.assertFalse(fdroidserver.update.has_known_vulnerability(f))
652 with self.assertRaises(fdroidserver.exception.FDroidException):
653 fdroidserver.update.has_known_vulnerability('janus.apk')
655 def test_get_apk_icon_when_src_is_none(self):
657 fdroidserver.common.fill_config_defaults(config)
658 fdroidserver.common.config = config
659 fdroidserver.update.config = config
661 # pylint: disable=protected-access
662 icons_src = fdroidserver.update._get_apk_icons_src('urzip-release.apk', None)
663 assert icons_src == {}
666 if __name__ == "__main__":
667 parser = optparse.OptionParser()
668 parser.add_option("-v", "--verbose", action="store_true", default=False,
669 help="Spew out even more information than normal")
670 (fdroidserver.common.options, args) = parser.parse_args(['--verbose'])
672 newSuite = unittest.TestSuite()
673 newSuite.addTest(unittest.makeSuite(UpdateTest))
674 unittest.main(failfast=False)