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):
35 def testInsertStoreMetadata(self):
37 fdroidserver.common.fill_config_defaults(config)
38 config['accepted_formats'] = ('txt', 'yml')
39 fdroidserver.update.config = config
40 fdroidserver.update.options = fdroidserver.common.options
41 os.chdir(os.path.join(localmodule, 'tests'))
43 shutil.rmtree(os.path.join('repo', 'info.guardianproject.urzip'), ignore_errors=True)
45 shutil.rmtree(os.path.join('build', 'com.nextcloud.client'), ignore_errors=True)
46 shutil.copytree(os.path.join('source-files', 'com.nextcloud.client'),
47 os.path.join('build', 'com.nextcloud.client'))
49 shutil.rmtree(os.path.join('build', 'com.nextcloud.client.dev'), ignore_errors=True)
50 shutil.copytree(os.path.join('source-files', 'com.nextcloud.client.dev'),
51 os.path.join('build', 'com.nextcloud.client.dev'))
53 shutil.rmtree(os.path.join('build', 'eu.siacs.conversations'), ignore_errors=True)
54 shutil.copytree(os.path.join('source-files', 'eu.siacs.conversations'),
55 os.path.join('build', 'eu.siacs.conversations'))
58 for packageName in ('info.guardianproject.urzip', 'org.videolan.vlc', 'obb.mainpatch.current',
59 'com.nextcloud.client', 'com.nextcloud.client.dev',
60 'eu.siacs.conversations'):
61 apps[packageName] = fdroidserver.metadata.App()
62 apps[packageName]['id'] = packageName
63 apps[packageName]['CurrentVersionCode'] = 0xcafebeef
65 apps['info.guardianproject.urzip']['CurrentVersionCode'] = 100
67 buildnextcloudclient = fdroidserver.metadata.Build()
68 buildnextcloudclient.gradle = ['generic']
69 apps['com.nextcloud.client']['builds'] = [buildnextcloudclient]
71 buildnextclouddevclient = fdroidserver.metadata.Build()
72 buildnextclouddevclient.gradle = ['versionDev']
73 apps['com.nextcloud.client.dev']['builds'] = [buildnextclouddevclient]
75 build_conversations = fdroidserver.metadata.Build()
76 build_conversations.gradle = ['free']
77 apps['eu.siacs.conversations']['builds'] = [build_conversations]
79 fdroidserver.update.insert_localized_app_metadata(apps)
81 appdir = os.path.join('repo', 'info.guardianproject.urzip', 'en-US')
82 self.assertTrue(os.path.isfile(os.path.join(appdir, 'icon.png')))
83 self.assertTrue(os.path.isfile(os.path.join(appdir, 'featureGraphic.png')))
85 self.assertEqual(6, len(apps))
86 for packageName, app in apps.items():
87 self.assertTrue('localized' in app)
88 self.assertTrue('en-US' in app['localized'])
89 self.assertEqual(1, len(app['localized']))
90 if packageName == 'info.guardianproject.urzip':
91 self.assertEqual(7, len(app['localized']['en-US']))
92 self.assertEqual('full description\n', app['localized']['en-US']['description'])
93 self.assertEqual('title\n', app['localized']['en-US']['name'])
94 self.assertEqual('short description\n', app['localized']['en-US']['summary'])
95 self.assertEqual('video\n', app['localized']['en-US']['video'])
96 self.assertEqual('icon.png', app['localized']['en-US']['icon'])
97 self.assertEqual('featureGraphic.png', app['localized']['en-US']['featureGraphic'])
98 self.assertEqual('100\n', app['localized']['en-US']['whatsNew'])
99 elif packageName == 'org.videolan.vlc':
100 self.assertEqual('icon.png', app['localized']['en-US']['icon'])
101 self.assertEqual(9, len(app['localized']['en-US']['phoneScreenshots']))
102 self.assertEqual(15, len(app['localized']['en-US']['sevenInchScreenshots']))
103 elif packageName == 'obb.mainpatch.current':
104 self.assertEqual('icon.png', app['localized']['en-US']['icon'])
105 self.assertEqual('featureGraphic.png', app['localized']['en-US']['featureGraphic'])
106 self.assertEqual(1, len(app['localized']['en-US']['phoneScreenshots']))
107 self.assertEqual(1, len(app['localized']['en-US']['sevenInchScreenshots']))
108 elif packageName == 'com.nextcloud.client':
109 self.assertEqual('Nextcloud', app['localized']['en-US']['name'])
110 self.assertEqual(1073, len(app['localized']['en-US']['description']))
111 self.assertEqual(78, len(app['localized']['en-US']['summary']))
112 elif packageName == 'com.nextcloud.client.dev':
113 self.assertEqual('Nextcloud Dev', app['localized']['en-US']['name'])
114 self.assertEqual(586, len(app['localized']['en-US']['description']))
115 self.assertEqual(79, len(app['localized']['en-US']['summary']))
116 elif packageName == 'eu.siacs.conversations':
117 self.assertEqual('Conversations', app['localized']['en-US']['name'])
119 def test_insert_triple_t_metadata(self):
120 importer = os.path.join(localmodule, 'tests', 'tmp', 'importer')
121 packageName = 'org.fdroid.ci.test.app'
122 if not os.path.isdir(importer):
123 logging.warning('skipping test_insert_triple_t_metadata, import.TestCase must run first!')
125 tmpdir = os.path.join(localmodule, '.testfiles')
126 if not os.path.exists(tmpdir):
128 tmptestsdir = tempfile.mkdtemp(prefix=inspect.currentframe().f_code.co_name, dir=tmpdir)
129 packageDir = os.path.join(tmptestsdir, 'build', packageName)
130 shutil.copytree(importer, packageDir)
132 # always use the same commit so these tests work when ci-test-app.git is updated
133 repo = git.Repo(packageDir)
134 for remote in repo.remotes:
136 repo.git.reset('--hard', 'b9e5d1a0d8d6fc31d4674b2f0514fef10762ed4f')
137 repo.git.clean('-fdx')
139 os.mkdir(os.path.join(tmptestsdir, 'metadata'))
141 metadata['Description'] = 'This is just a test app'
142 with open(os.path.join(tmptestsdir, 'metadata', packageName + '.yml'), 'w') as fp:
143 yaml.dump(metadata, fp)
146 fdroidserver.common.fill_config_defaults(config)
147 config['accepted_formats'] = ('yml')
148 fdroidserver.common.config = config
149 fdroidserver.update.config = config
150 fdroidserver.update.options = fdroidserver.common.options
151 os.chdir(tmptestsdir)
153 apps = fdroidserver.metadata.read_metadata(xref=True)
154 fdroidserver.update.copy_triple_t_store_metadata(apps)
156 # TODO ideally, this would compare the whole dict like in metadata.TestCase's test_read_metadata()
158 'ar', 'ast_ES', 'az', 'ca', 'ca_ES', 'cs-CZ', 'cs_CZ', 'da',
159 'da-DK', 'de', 'de-DE', 'el', 'en-US', 'es', 'es-ES', 'es_ES', 'et',
160 'fi', 'fr', 'fr-FR', 'he_IL', 'hi-IN', 'hi_IN', 'hu', 'id', 'it',
161 'it-IT', 'it_IT', 'iw-IL', 'ja', 'ja-JP', 'kn_IN', 'ko', 'ko-KR',
162 'ko_KR', 'lt', 'nb', 'nb_NO', 'nl', 'nl-NL', 'no', 'pl', 'pl-PL',
163 'pl_PL', 'pt', 'pt-BR', 'pt-PT', 'pt_BR', 'ro', 'ro_RO', 'ru-RU',
164 'ru_RU', 'sv-SE', 'sv_SE', 'te', 'tr', 'tr-TR', 'uk', 'uk_UA', 'vi',
165 'vi_VN', 'zh-CN', 'zh_CN', 'zh_TW',
167 locales = sorted(list(apps['org.fdroid.ci.test.app']['localized'].keys()))
168 self.assertEqual(correctlocales, locales)
170 def javagetsig(self, apkfile):
171 getsig_dir = os.path.join(os.path.dirname(__file__), 'getsig')
172 if not os.path.exists(getsig_dir + "/getsig.class"):
173 logging.critical("getsig.class not found. To fix: cd '%s' && ./make.sh" % getsig_dir)
175 # FDroidPopen needs some config to work
177 fdroidserver.common.fill_config_defaults(config)
178 fdroidserver.common.config = config
179 p = FDroidPopen(['java', '-cp', os.path.join(os.path.dirname(__file__), 'getsig'),
180 'getsig', os.path.join(os.getcwd(), apkfile)])
182 for line in p.output.splitlines():
183 if line.startswith('Result:'):
184 sig = line[7:].strip()
186 if p.returncode == 0:
191 def testGoodGetsig(self):
192 # config needed to use jarsigner and keytool
194 fdroidserver.common.fill_config_defaults(config)
195 fdroidserver.update.config = config
196 apkfile = os.path.join(os.path.dirname(__file__), 'urzip.apk')
197 sig = self.javagetsig(apkfile)
198 self.assertIsNotNone(sig, "sig is None")
199 pysig = fdroidserver.update.getsig(apkfile)
200 self.assertIsNotNone(pysig, "pysig is None")
201 self.assertEqual(sig, fdroidserver.update.getsig(apkfile),
202 "python sig not equal to java sig!")
203 self.assertEqual(len(sig), len(pysig),
204 "the length of the two sigs are different!")
206 self.assertEqual(unhexlify(sig), unhexlify(pysig),
207 "the length of the two sigs are different!")
208 except TypeError as e:
210 self.assertTrue(False, 'TypeError!')
212 def testBadGetsig(self):
213 """getsig() should still be able to fetch the fingerprint of bad signatures"""
214 # config needed to use jarsigner and keytool
216 fdroidserver.common.fill_config_defaults(config)
217 fdroidserver.update.config = config
219 apkfile = os.path.join(os.path.dirname(__file__), 'urzip-badsig.apk')
220 sig = fdroidserver.update.getsig(apkfile)
221 self.assertEqual(sig, 'e0ecb5fc2d63088e4a07ae410a127722',
222 "python sig should be: " + str(sig))
224 apkfile = os.path.join(os.path.dirname(__file__), 'urzip-badcert.apk')
225 sig = fdroidserver.update.getsig(apkfile)
226 self.assertEqual(sig, 'e0ecb5fc2d63088e4a07ae410a127722',
227 "python sig should be: " + str(sig))
229 def testScanApksAndObbs(self):
230 os.chdir(os.path.join(localmodule, 'tests'))
231 if os.path.basename(os.getcwd()) != 'tests':
232 raise Exception('This test must be run in the "tests/" subdir')
235 fdroidserver.common.fill_config_defaults(config)
236 config['ndk_paths'] = dict()
237 config['accepted_formats'] = ['json', 'txt', 'yml']
238 fdroidserver.common.config = config
239 fdroidserver.update.config = config
241 fdroidserver.update.options = type('', (), {})()
242 fdroidserver.update.options.clean = True
243 fdroidserver.update.options.delete_unknown = True
244 fdroidserver.update.options.rename_apks = False
245 fdroidserver.update.options.allow_disabled_algorithms = False
247 apps = fdroidserver.metadata.read_metadata(xref=True)
248 knownapks = fdroidserver.common.KnownApks()
249 apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
250 self.assertEqual(len(apks), 11)
252 self.assertEqual(apk['packageName'], 'com.politedroid')
253 self.assertEqual(apk['versionCode'], 3)
254 self.assertEqual(apk['minSdkVersion'], '3')
255 self.assertEqual(apk['targetSdkVersion'], '3')
256 self.assertFalse('maxSdkVersion' in apk)
258 self.assertEqual(apk['packageName'], 'obb.main.oldversion')
259 self.assertEqual(apk['versionCode'], 1444412523)
260 self.assertEqual(apk['minSdkVersion'], '4')
261 self.assertEqual(apk['targetSdkVersion'], '18')
262 self.assertFalse('maxSdkVersion' in apk)
264 fdroidserver.update.insert_obbs('repo', apps, apks)
266 if apk['packageName'] == 'obb.mainpatch.current':
267 self.assertEqual(apk.get('obbMainFile'), 'main.1619.obb.mainpatch.current.obb')
268 self.assertEqual(apk.get('obbPatchFile'), 'patch.1619.obb.mainpatch.current.obb')
269 elif apk['packageName'] == 'obb.main.oldversion':
270 self.assertEqual(apk.get('obbMainFile'), 'main.1434483388.obb.main.oldversion.obb')
271 self.assertIsNone(apk.get('obbPatchFile'))
272 elif apk['packageName'] == 'obb.main.twoversions':
273 self.assertIsNone(apk.get('obbPatchFile'))
274 if apk['versionCode'] == 1101613:
275 self.assertEqual(apk.get('obbMainFile'), 'main.1101613.obb.main.twoversions.obb')
276 elif apk['versionCode'] == 1101615:
277 self.assertEqual(apk.get('obbMainFile'), 'main.1101615.obb.main.twoversions.obb')
278 elif apk['versionCode'] == 1101617:
279 self.assertEqual(apk.get('obbMainFile'), 'main.1101615.obb.main.twoversions.obb')
281 self.assertTrue(False)
282 elif apk['packageName'] == 'info.guardianproject.urzip':
283 self.assertIsNone(apk.get('obbMainFile'))
284 self.assertIsNone(apk.get('obbPatchFile'))
286 def test_scan_apk(self):
288 fdroidserver.common.fill_config_defaults(config)
289 fdroidserver.update.config = config
290 os.chdir(os.path.join(localmodule, 'tests'))
291 if os.path.basename(os.getcwd()) != 'tests':
292 raise Exception('This test must be run in the "tests/" subdir')
294 apk_info = fdroidserver.update.scan_apk('org.dyndns.fules.ck_20.apk')
296 self.assertEqual(apk_info['icons_src'], {'240': 'res/drawable-hdpi-v4/icon_launcher.png',
297 '120': 'res/drawable-ldpi-v4/icon_launcher.png',
298 '160': 'res/drawable-mdpi-v4/icon_launcher.png',
299 '-1': 'res/drawable-mdpi-v4/icon_launcher.png'})
300 self.assertEqual(apk_info['icons'], {})
301 self.assertEqual(apk_info['features'], [])
302 self.assertEqual(apk_info['antiFeatures'], set())
303 self.assertEqual(apk_info['versionName'], 'v1.6pre2')
304 self.assertEqual(apk_info['hash'],
305 '897486e1f857c6c0ee32ccbad0e1b8cd82f6d0e65a44a23f13f852d2b63a18c8')
306 self.assertEqual(apk_info['packageName'], 'org.dyndns.fules.ck')
307 self.assertEqual(apk_info['versionCode'], 20)
308 self.assertEqual(apk_info['size'], 132453)
309 self.assertEqual(apk_info['nativecode'],
310 ['arm64-v8a', 'armeabi', 'armeabi-v7a', 'mips', 'mips64', 'x86', 'x86_64'])
311 self.assertEqual(apk_info['minSdkVersion'], '7')
312 self.assertEqual(apk_info['sig'], '9bf7a6a67f95688daec75eab4b1436ac')
313 self.assertEqual(apk_info['hashType'], 'sha256')
314 self.assertEqual(apk_info['targetSdkVersion'], '8')
316 def test_scan_apk_no_sig(self):
318 fdroidserver.common.fill_config_defaults(config)
319 fdroidserver.update.config = config
320 os.chdir(os.path.join(localmodule, 'tests'))
321 if os.path.basename(os.getcwd()) != 'tests':
322 raise Exception('This test must be run in the "tests/" subdir')
324 with self.assertRaises(fdroidserver.exception.BuildException):
325 fdroidserver.update.scan_apk('urzip-release-unsigned.apk')
327 def test_process_apk(self):
329 def _build_yaml_representer(dumper, data):
330 '''Creates a YAML representation of a Build instance'''
331 return dumper.represent_dict(data)
334 fdroidserver.common.fill_config_defaults(config)
335 fdroidserver.update.config = config
336 os.chdir(os.path.join(localmodule, 'tests'))
337 if os.path.basename(os.getcwd()) != 'tests':
338 raise Exception('This test must be run in the "tests/" subdir')
340 config['ndk_paths'] = dict()
341 config['accepted_formats'] = ['json', 'txt', 'yml']
342 fdroidserver.common.config = config
343 fdroidserver.update.config = config
345 fdroidserver.update.options = type('', (), {})()
346 fdroidserver.update.options.clean = True
347 fdroidserver.update.options.rename_apks = False
348 fdroidserver.update.options.delete_unknown = True
349 fdroidserver.update.options.allow_disabled_algorithms = False
351 for icon_dir in fdroidserver.update.get_all_icon_dirs('repo'):
352 if not os.path.exists(icon_dir):
353 os.makedirs(icon_dir)
355 knownapks = fdroidserver.common.KnownApks()
356 apkList = ['../urzip.apk', '../org.dyndns.fules.ck_20.apk']
358 for apkName in apkList:
359 _, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo', knownapks,
361 # Don't care about the date added to the repo and relative apkName
364 # avoid AAPT application name bug
367 # ensure that icons have been extracted properly
368 if apkName == '../urzip.apk':
369 self.assertEqual(apk['icon'], 'info.guardianproject.urzip.100.png')
370 if apkName == '../org.dyndns.fules.ck_20.apk':
371 self.assertEqual(apk['icon'], 'org.dyndns.fules.ck.20.png')
372 for density in fdroidserver.update.screen_densities:
373 icon_path = os.path.join(fdroidserver.update.get_icon_dir('repo', density),
375 self.assertTrue(os.path.isfile(icon_path))
376 self.assertTrue(os.path.getsize(icon_path) > 1)
378 savepath = os.path.join('metadata', 'apk', apk['packageName'] + '.yaml')
379 # Uncomment to save APK metadata
380 # with open(savepath, 'w') as f:
381 # yaml.add_representer(fdroidserver.metadata.Build, _build_yaml_representer)
382 # yaml.dump(apk, f, default_flow_style=False)
384 with open(savepath, 'r') as f:
385 frompickle = yaml.load(f)
387 self.assertEqual(apk, frompickle)
389 def test_process_apk_signed_by_disabled_algorithms(self):
390 os.chdir(os.path.join(localmodule, 'tests'))
391 if os.path.basename(os.getcwd()) != 'tests':
392 raise Exception('This test must be run in the "tests/" subdir')
395 fdroidserver.common.fill_config_defaults(config)
396 fdroidserver.update.config = config
398 config['ndk_paths'] = dict()
399 config['accepted_formats'] = ['json', 'txt', 'yml']
400 fdroidserver.common.config = config
401 fdroidserver.update.config = config
403 fdroidserver.update.options = type('', (), {})()
404 fdroidserver.update.options.clean = True
405 fdroidserver.update.options.verbose = True
406 fdroidserver.update.options.rename_apks = False
407 fdroidserver.update.options.delete_unknown = True
408 fdroidserver.update.options.allow_disabled_algorithms = False
410 knownapks = fdroidserver.common.KnownApks()
411 apksourcedir = os.getcwd()
412 tmpdir = os.path.join(localmodule, '.testfiles')
413 if not os.path.exists(tmpdir):
415 tmptestsdir = tempfile.mkdtemp(prefix=inspect.currentframe().f_code.co_name,
417 print('tmptestsdir', tmptestsdir)
418 os.chdir(tmptestsdir)
421 # setup the repo, create icons dirs, etc.
422 fdroidserver.update.process_apks({}, 'repo', knownapks)
423 fdroidserver.update.process_apks({}, 'archive', knownapks)
425 disabledsigs = ['org.bitbucket.tickytacky.mirrormirror_2.apk', ]
426 for apkName in disabledsigs:
427 shutil.copy(os.path.join(apksourcedir, apkName),
428 os.path.join(tmptestsdir, 'repo'))
430 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
432 allow_disabled_algorithms=True,
433 archive_bad_sig=False)
434 self.assertFalse(skip)
435 self.assertIsNotNone(apk)
436 self.assertTrue(cachechanged)
437 self.assertFalse(os.path.exists(os.path.join('archive', apkName)))
438 self.assertTrue(os.path.exists(os.path.join('repo', apkName)))
440 javac = config['jarsigner'].replace('jarsigner', 'javac')
441 v = subprocess.check_output([javac, '-version'], stderr=subprocess.STDOUT)[6:-1].decode('utf-8')
442 if LooseVersion(v) < LooseVersion('1.8.0_132'):
443 print('SKIPPING: running tests with old Java (' + v + ')')
446 # this test only works on systems with fully updated Java/jarsigner
447 # that has MD5 listed in jdk.jar.disabledAlgorithms in java.security
448 # https://blogs.oracle.com/java-platform-group/oracle-jre-will-no-longer-trust-md5-signed-code-by-default
449 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
451 allow_disabled_algorithms=False,
452 archive_bad_sig=True)
453 self.assertTrue(skip)
454 self.assertIsNone(apk)
455 self.assertFalse(cachechanged)
456 self.assertTrue(os.path.exists(os.path.join('archive', apkName)))
457 self.assertFalse(os.path.exists(os.path.join('repo', apkName)))
459 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'archive',
461 allow_disabled_algorithms=False,
462 archive_bad_sig=False)
463 self.assertFalse(skip)
464 self.assertIsNotNone(apk)
465 self.assertTrue(cachechanged)
466 self.assertTrue(os.path.exists(os.path.join('archive', apkName)))
467 self.assertFalse(os.path.exists(os.path.join('repo', apkName)))
469 # ensure that icons have been moved to the archive as well
470 for density in fdroidserver.update.screen_densities:
471 icon_path = os.path.join(fdroidserver.update.get_icon_dir('archive', density),
473 self.assertTrue(os.path.isfile(icon_path))
474 self.assertTrue(os.path.getsize(icon_path) > 1)
476 badsigs = ['urzip-badcert.apk', 'urzip-badsig.apk', 'urzip-release-unsigned.apk', ]
477 for apkName in badsigs:
478 shutil.copy(os.path.join(apksourcedir, apkName),
479 os.path.join(tmptestsdir, 'repo'))
481 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
483 allow_disabled_algorithms=False,
484 archive_bad_sig=False)
485 self.assertTrue(skip)
486 self.assertIsNone(apk)
487 self.assertFalse(cachechanged)
489 def test_process_invalid_apk(self):
490 os.chdir(os.path.join(localmodule, 'tests'))
491 if os.path.basename(os.getcwd()) != 'tests':
492 raise Exception('This test must be run in the "tests/" subdir')
495 fdroidserver.common.fill_config_defaults(config)
496 fdroidserver.common.config = config
497 fdroidserver.update.config = config
498 fdroidserver.update.options.delete_unknown = False
500 knownapks = fdroidserver.common.KnownApks()
501 apk = 'fake.ota.update_1234.zip' # this is not an APK, scanning should fail
502 (skip, apk, cachechanged) = fdroidserver.update.process_apk({}, apk, 'repo', knownapks,
505 self.assertTrue(skip)
506 self.assertIsNone(apk)
507 self.assertFalse(cachechanged)
509 def test_translate_per_build_anti_features(self):
510 os.chdir(os.path.join(localmodule, 'tests'))
511 if os.path.basename(os.getcwd()) != 'tests':
512 raise Exception('This test must be run in the "tests/" subdir')
515 fdroidserver.common.fill_config_defaults(config)
516 config['ndk_paths'] = dict()
517 config['accepted_formats'] = ['json', 'txt', 'yml']
518 fdroidserver.common.config = config
519 fdroidserver.update.config = config
521 fdroidserver.update.options = type('', (), {})()
522 fdroidserver.update.options.clean = True
523 fdroidserver.update.options.delete_unknown = True
524 fdroidserver.update.options.rename_apks = False
525 fdroidserver.update.options.allow_disabled_algorithms = False
527 apps = fdroidserver.metadata.read_metadata(xref=True)
528 knownapks = fdroidserver.common.KnownApks()
529 apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
530 fdroidserver.update.translate_per_build_anti_features(apps, apks)
531 self.assertEqual(len(apks), 11)
534 if apk['packageName'] == 'com.politedroid' and apk['versionCode'] == 3:
535 antiFeatures = apk.get('antiFeatures')
536 self.assertTrue('KnownVuln' in antiFeatures)
537 self.assertEqual(3, len(antiFeatures))
539 self.assertTrue(foundtest)
541 def test_create_metadata_from_template(self):
542 tmpdir = os.path.join(localmodule, '.testfiles')
543 if not os.path.exists(tmpdir):
545 tmptestsdir = tempfile.mkdtemp(prefix=inspect.currentframe().f_code.co_name,
547 print('tmptestsdir', tmptestsdir)
548 os.chdir(tmptestsdir)
551 shutil.copy(os.path.join(localmodule, 'tests', 'urzip.apk'), 'repo')
554 fdroidserver.common.fill_config_defaults(config)
555 config['ndk_paths'] = dict()
556 config['accepted_formats'] = ['json', 'txt', 'yml']
557 fdroidserver.common.config = config
558 fdroidserver.update.config = config
560 fdroidserver.update.options = type('', (), {})()
561 fdroidserver.update.options.clean = True
562 fdroidserver.update.options.delete_unknown = False
563 fdroidserver.update.options.rename_apks = False
564 fdroidserver.update.options.allow_disabled_algorithms = False
566 knownapks = fdroidserver.common.KnownApks()
567 apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
568 self.assertEqual(1, len(apks))
571 testfile = 'metadata/info.guardianproject.urzip.yml'
572 # create empty 0 byte .yml file, run read_metadata, it should work
573 open(testfile, 'a').close()
574 apps = fdroidserver.metadata.read_metadata(xref=True)
575 self.assertEqual(1, len(apps))
578 # test using internal template
579 apps = fdroidserver.metadata.read_metadata(xref=True)
580 self.assertEqual(0, len(apps))
581 fdroidserver.update.create_metadata_from_template(apk)
582 self.assertTrue(os.path.exists(testfile))
583 apps = fdroidserver.metadata.read_metadata(xref=True)
584 self.assertEqual(1, len(apps))
585 for app in apps.values():
586 self.assertEqual('urzip', app['Name'])
587 self.assertEqual(1, len(app['Categories']))
590 # test using external template.yml
592 self.assertFalse(os.path.exists(testfile))
593 shutil.copy(os.path.join(localmodule, 'examples', 'template.yml'), tmptestsdir)
594 fdroidserver.update.create_metadata_from_template(apk)
595 self.assertTrue(os.path.exists(testfile))
596 apps = fdroidserver.metadata.read_metadata(xref=True)
597 self.assertEqual(1, len(apps))
598 for app in apps.values():
599 self.assertEqual('urzip', app['Name'])
600 self.assertEqual(1, len(app['Categories']))
601 self.assertEqual('Internet', app['Categories'][0])
603 with open(testfile) as fp:
605 self.assertEqual('urzip', data['Name'])
606 self.assertEqual('urzip', data['Summary'])
609 if __name__ == "__main__":
610 parser = optparse.OptionParser()
611 parser.add_option("-v", "--verbose", action="store_true", default=False,
612 help="Spew out even more information than normal")
613 (fdroidserver.common.options, args) = parser.parse_args(['--verbose'])
615 newSuite = unittest.TestSuite()
616 newSuite.addTest(unittest.makeSuite(UpdateTest))
617 unittest.main(failfast=False)