3 # http://www.drdobbs.com/testing/unit-testing-with-python/240165163
15 from binascii import unhexlify
17 localmodule = os.path.realpath(
18 os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..'))
19 print('localmodule: ' + localmodule)
20 if localmodule not in sys.path:
21 sys.path.insert(0, localmodule)
23 import fdroidserver.common
24 import fdroidserver.exception
25 import fdroidserver.metadata
26 import fdroidserver.update
27 from fdroidserver.common import FDroidPopen
30 class UpdateTest(unittest.TestCase):
33 def testInsertStoreMetadata(self):
35 fdroidserver.common.fill_config_defaults(config)
36 config['accepted_formats'] = ('txt', 'yml')
37 fdroidserver.update.config = config
38 fdroidserver.update.options = fdroidserver.common.options
39 os.chdir(os.path.join(localmodule, 'tests'))
41 shutil.rmtree(os.path.join('repo', 'info.guardianproject.urzip'), ignore_errors=True)
44 for packageName in ('info.guardianproject.urzip', 'org.videolan.vlc', 'obb.mainpatch.current'):
45 apps[packageName] = dict()
46 apps[packageName]['id'] = packageName
47 apps[packageName]['CurrentVersionCode'] = 0xcafebeef
48 apps['info.guardianproject.urzip']['CurrentVersionCode'] = 100
49 fdroidserver.update.insert_localized_app_metadata(apps)
51 appdir = os.path.join('repo', 'info.guardianproject.urzip', 'en-US')
52 self.assertTrue(os.path.isfile(os.path.join(appdir, 'icon.png')))
53 self.assertTrue(os.path.isfile(os.path.join(appdir, 'featureGraphic.png')))
55 self.assertEqual(3, len(apps))
56 for packageName, app in apps.items():
57 self.assertTrue('localized' in app)
58 self.assertTrue('en-US' in app['localized'])
59 self.assertEqual(1, len(app['localized']))
60 if packageName == 'info.guardianproject.urzip':
61 self.assertEqual(7, len(app['localized']['en-US']))
62 self.assertEqual('full description\n', app['localized']['en-US']['description'])
63 self.assertEqual('title\n', app['localized']['en-US']['name'])
64 self.assertEqual('short description\n', app['localized']['en-US']['summary'])
65 self.assertEqual('video\n', app['localized']['en-US']['video'])
66 self.assertEqual('icon.png', app['localized']['en-US']['icon'])
67 self.assertEqual('featureGraphic.png', app['localized']['en-US']['featureGraphic'])
68 self.assertEqual('100\n', app['localized']['en-US']['whatsNew'])
69 elif packageName == 'org.videolan.vlc':
70 self.assertEqual('icon.png', app['localized']['en-US']['icon'])
71 self.assertEqual(9, len(app['localized']['en-US']['phoneScreenshots']))
72 self.assertEqual(15, len(app['localized']['en-US']['sevenInchScreenshots']))
73 elif packageName == 'obb.mainpatch.current':
74 self.assertEqual('icon.png', app['localized']['en-US']['icon'])
75 self.assertEqual('featureGraphic.png', app['localized']['en-US']['featureGraphic'])
76 self.assertEqual(1, len(app['localized']['en-US']['phoneScreenshots']))
77 self.assertEqual(1, len(app['localized']['en-US']['sevenInchScreenshots']))
79 def test_insert_triple_t_metadata(self):
80 importer = os.path.join(localmodule, 'tests', 'tmp', 'importer')
81 packageName = 'org.fdroid.ci.test.app'
82 if not os.path.isdir(importer):
83 logging.warning('skipping test_insert_triple_t_metadata, import.TestCase must run first!')
85 tmpdir = os.path.join(localmodule, '.testfiles')
86 if not os.path.exists(tmpdir):
88 tmptestsdir = tempfile.mkdtemp(prefix='test_insert_triple_t_metadata-', dir=tmpdir)
89 packageDir = os.path.join(tmptestsdir, 'build', packageName)
90 shutil.copytree(importer, packageDir)
92 # always use the same commit so these tests work when ci-test-app.git is updated
93 repo = git.Repo(packageDir)
94 for remote in repo.remotes:
96 repo.git.reset('--hard', 'b9e5d1a0d8d6fc31d4674b2f0514fef10762ed4f')
97 repo.git.clean('-fdx')
99 os.mkdir(os.path.join(tmptestsdir, 'metadata'))
101 metadata['Description'] = 'This is just a test app'
102 with open(os.path.join(tmptestsdir, 'metadata', packageName + '.yml'), 'w') as fp:
103 yaml.dump(metadata, fp)
106 fdroidserver.common.fill_config_defaults(config)
107 config['accepted_formats'] = ('yml')
108 fdroidserver.common.config = config
109 fdroidserver.update.config = config
110 fdroidserver.update.options = fdroidserver.common.options
111 os.chdir(tmptestsdir)
113 apps = fdroidserver.metadata.read_metadata(xref=True)
114 fdroidserver.update.copy_triple_t_store_metadata(apps)
116 # TODO ideally, this would compare the whole dict like in metadata.TestCase's test_read_metadata()
118 'ar', 'ast_ES', 'az', 'ca', 'ca_ES', 'cs-CZ', 'cs_CZ', 'da',
119 'da-DK', 'de', 'de-DE', 'el', 'en-US', 'es', 'es-ES', 'es_ES', 'et',
120 'fi', 'fr', 'fr-FR', 'he_IL', 'hi-IN', 'hi_IN', 'hu', 'id', 'it',
121 'it-IT', 'it_IT', 'iw-IL', 'ja', 'ja-JP', 'kn_IN', 'ko', 'ko-KR',
122 'ko_KR', 'lt', 'nb', 'nb_NO', 'nl', 'nl-NL', 'no', 'pl', 'pl-PL',
123 'pl_PL', 'pt', 'pt-BR', 'pt-PT', 'pt_BR', 'ro', 'ro_RO', 'ru-RU',
124 'ru_RU', 'sv-SE', 'sv_SE', 'te', 'tr', 'tr-TR', 'uk', 'uk_UA', 'vi',
125 'vi_VN', 'zh-CN', 'zh_CN', 'zh_TW',
127 locales = sorted(list(apps['org.fdroid.ci.test.app']['localized'].keys()))
128 self.assertEqual(correctlocales, locales)
130 def javagetsig(self, apkfile):
131 getsig_dir = os.path.join(os.path.dirname(__file__), 'getsig')
132 if not os.path.exists(getsig_dir + "/getsig.class"):
133 logging.critical("getsig.class not found. To fix: cd '%s' && ./make.sh" % getsig_dir)
135 # FDroidPopen needs some config to work
137 fdroidserver.common.fill_config_defaults(config)
138 fdroidserver.common.config = config
139 p = FDroidPopen(['java', '-cp', os.path.join(os.path.dirname(__file__), 'getsig'),
140 'getsig', os.path.join(os.getcwd(), apkfile)])
142 for line in p.output.splitlines():
143 if line.startswith('Result:'):
144 sig = line[7:].strip()
146 if p.returncode == 0:
151 def testGoodGetsig(self):
152 # config needed to use jarsigner and keytool
154 fdroidserver.common.fill_config_defaults(config)
155 fdroidserver.update.config = config
156 apkfile = os.path.join(os.path.dirname(__file__), 'urzip.apk')
157 sig = self.javagetsig(apkfile)
158 self.assertIsNotNone(sig, "sig is None")
159 pysig = fdroidserver.update.getsig(apkfile)
160 self.assertIsNotNone(pysig, "pysig is None")
161 self.assertEqual(sig, fdroidserver.update.getsig(apkfile),
162 "python sig not equal to java sig!")
163 self.assertEqual(len(sig), len(pysig),
164 "the length of the two sigs are different!")
166 self.assertEqual(unhexlify(sig), unhexlify(pysig),
167 "the length of the two sigs are different!")
168 except TypeError as e:
170 self.assertTrue(False, 'TypeError!')
172 def testBadGetsig(self):
173 """getsig() should still be able to fetch the fingerprint of bad signatures"""
174 # config needed to use jarsigner and keytool
176 fdroidserver.common.fill_config_defaults(config)
177 fdroidserver.update.config = config
179 apkfile = os.path.join(os.path.dirname(__file__), 'urzip-badsig.apk')
180 sig = fdroidserver.update.getsig(apkfile)
181 self.assertEqual(sig, 'e0ecb5fc2d63088e4a07ae410a127722',
182 "python sig should be: " + str(sig))
184 apkfile = os.path.join(os.path.dirname(__file__), 'urzip-badcert.apk')
185 sig = fdroidserver.update.getsig(apkfile)
186 self.assertEqual(sig, 'e0ecb5fc2d63088e4a07ae410a127722',
187 "python sig should be: " + str(sig))
189 def testScanApksAndObbs(self):
190 os.chdir(os.path.join(localmodule, 'tests'))
191 if os.path.basename(os.getcwd()) != 'tests':
192 raise Exception('This test must be run in the "tests/" subdir')
195 fdroidserver.common.fill_config_defaults(config)
196 config['ndk_paths'] = dict()
197 config['accepted_formats'] = ['json', 'txt', 'yml']
198 fdroidserver.common.config = config
199 fdroidserver.update.config = config
201 fdroidserver.update.options = type('', (), {})()
202 fdroidserver.update.options.clean = True
203 fdroidserver.update.options.delete_unknown = True
204 fdroidserver.update.options.rename_apks = False
205 fdroidserver.update.options.allow_disabled_algorithms = False
207 apps = fdroidserver.metadata.read_metadata(xref=True)
208 knownapks = fdroidserver.common.KnownApks()
209 apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
210 self.assertEqual(len(apks), 11)
212 self.assertEqual(apk['packageName'], 'com.politedroid')
213 self.assertEqual(apk['versionCode'], 3)
214 self.assertEqual(apk['minSdkVersion'], '3')
215 self.assertEqual(apk['targetSdkVersion'], '3')
216 self.assertFalse('maxSdkVersion' in apk)
218 self.assertEqual(apk['packageName'], 'obb.main.oldversion')
219 self.assertEqual(apk['versionCode'], 1444412523)
220 self.assertEqual(apk['minSdkVersion'], '4')
221 self.assertEqual(apk['targetSdkVersion'], '18')
222 self.assertFalse('maxSdkVersion' in apk)
224 fdroidserver.update.insert_obbs('repo', apps, apks)
226 if apk['packageName'] == 'obb.mainpatch.current':
227 self.assertEqual(apk.get('obbMainFile'), 'main.1619.obb.mainpatch.current.obb')
228 self.assertEqual(apk.get('obbPatchFile'), 'patch.1619.obb.mainpatch.current.obb')
229 elif apk['packageName'] == 'obb.main.oldversion':
230 self.assertEqual(apk.get('obbMainFile'), 'main.1434483388.obb.main.oldversion.obb')
231 self.assertIsNone(apk.get('obbPatchFile'))
232 elif apk['packageName'] == 'obb.main.twoversions':
233 self.assertIsNone(apk.get('obbPatchFile'))
234 if apk['versionCode'] == 1101613:
235 self.assertEqual(apk.get('obbMainFile'), 'main.1101613.obb.main.twoversions.obb')
236 elif apk['versionCode'] == 1101615:
237 self.assertEqual(apk.get('obbMainFile'), 'main.1101615.obb.main.twoversions.obb')
238 elif apk['versionCode'] == 1101617:
239 self.assertEqual(apk.get('obbMainFile'), 'main.1101615.obb.main.twoversions.obb')
241 self.assertTrue(False)
242 elif apk['packageName'] == 'info.guardianproject.urzip':
243 self.assertIsNone(apk.get('obbMainFile'))
244 self.assertIsNone(apk.get('obbPatchFile'))
246 def test_scan_apk(self):
248 fdroidserver.common.fill_config_defaults(config)
249 fdroidserver.update.config = config
250 os.chdir(os.path.join(localmodule, 'tests'))
251 if os.path.basename(os.getcwd()) != 'tests':
252 raise Exception('This test must be run in the "tests/" subdir')
254 apk_info = fdroidserver.update.scan_apk('org.dyndns.fules.ck_20.apk')
256 self.assertEqual(apk_info['icons_src'], {'240': 'res/drawable-hdpi-v4/icon_launcher.png',
257 '120': 'res/drawable-ldpi-v4/icon_launcher.png',
258 '160': 'res/drawable-mdpi-v4/icon_launcher.png',
259 '-1': 'res/drawable-mdpi-v4/icon_launcher.png'})
260 self.assertEqual(apk_info['icons'], {})
261 self.assertEqual(apk_info['features'], [])
262 self.assertEqual(apk_info['antiFeatures'], set())
263 self.assertEqual(apk_info['versionName'], 'v1.6pre2')
264 self.assertEqual(apk_info['hash'],
265 '897486e1f857c6c0ee32ccbad0e1b8cd82f6d0e65a44a23f13f852d2b63a18c8')
266 self.assertEqual(apk_info['packageName'], 'org.dyndns.fules.ck')
267 self.assertEqual(apk_info['versionCode'], 20)
268 self.assertEqual(apk_info['size'], 132453)
269 self.assertEqual(apk_info['nativecode'],
270 ['arm64-v8a', 'armeabi', 'armeabi-v7a', 'mips', 'mips64', 'x86', 'x86_64'])
271 self.assertEqual(apk_info['minSdkVersion'], '7')
272 self.assertEqual(apk_info['sig'], '9bf7a6a67f95688daec75eab4b1436ac')
273 self.assertEqual(apk_info['hashType'], 'sha256')
274 self.assertEqual(apk_info['targetSdkVersion'], '8')
276 def test_scan_apk_no_sig(self):
278 fdroidserver.common.fill_config_defaults(config)
279 fdroidserver.update.config = config
280 os.chdir(os.path.join(localmodule, 'tests'))
281 if os.path.basename(os.getcwd()) != 'tests':
282 raise Exception('This test must be run in the "tests/" subdir')
284 with self.assertRaises(fdroidserver.exception.BuildException):
285 fdroidserver.update.scan_apk('urzip-release-unsigned.apk')
287 def test_process_apk(self):
289 def _build_yaml_representer(dumper, data):
290 '''Creates a YAML representation of a Build instance'''
291 return dumper.represent_dict(data)
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 config['ndk_paths'] = dict()
301 config['accepted_formats'] = ['json', 'txt', 'yml']
302 fdroidserver.common.config = config
303 fdroidserver.update.config = config
305 fdroidserver.update.options = type('', (), {})()
306 fdroidserver.update.options.clean = True
307 fdroidserver.update.options.rename_apks = False
308 fdroidserver.update.options.delete_unknown = True
309 fdroidserver.update.options.allow_disabled_algorithms = False
311 for icon_dir in fdroidserver.update.get_all_icon_dirs('repo'):
312 if not os.path.exists(icon_dir):
313 os.makedirs(icon_dir)
315 knownapks = fdroidserver.common.KnownApks()
316 apkList = ['../urzip.apk', '../org.dyndns.fules.ck_20.apk']
318 for apkName in apkList:
319 _, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo', knownapks,
321 # Don't care about the date added to the repo and relative apkName
324 # avoid AAPT application name bug
327 # ensure that icons have been extracted properly
328 if apkName == '../urzip.apk':
329 self.assertEqual(apk['icon'], 'info.guardianproject.urzip.100.png')
330 if apkName == '../org.dyndns.fules.ck_20.apk':
331 self.assertEqual(apk['icon'], 'org.dyndns.fules.ck.20.png')
332 for density in fdroidserver.update.screen_densities:
333 icon_path = os.path.join(fdroidserver.update.get_icon_dir('repo', density),
335 self.assertTrue(os.path.isfile(icon_path))
336 self.assertTrue(os.path.getsize(icon_path) > 1)
338 savepath = os.path.join('metadata', 'apk', apk['packageName'] + '.yaml')
339 # Uncomment to save APK metadata
340 # with open(savepath, 'w') as f:
341 # yaml.add_representer(fdroidserver.metadata.Build, _build_yaml_representer)
342 # yaml.dump(apk, f, default_flow_style=False)
344 with open(savepath, 'r') as f:
345 frompickle = yaml.load(f)
347 self.assertEqual(apk, frompickle)
349 def test_process_apk_signed_by_disabled_algorithms(self):
350 os.chdir(os.path.join(localmodule, 'tests'))
351 if os.path.basename(os.getcwd()) != 'tests':
352 raise Exception('This test must be run in the "tests/" subdir')
355 fdroidserver.common.fill_config_defaults(config)
356 fdroidserver.update.config = config
358 config['ndk_paths'] = dict()
359 config['accepted_formats'] = ['json', 'txt', 'yml']
360 fdroidserver.common.config = config
361 fdroidserver.update.config = config
363 fdroidserver.update.options = type('', (), {})()
364 fdroidserver.update.options.clean = True
365 fdroidserver.update.options.verbose = True
366 fdroidserver.update.options.rename_apks = False
367 fdroidserver.update.options.delete_unknown = True
368 fdroidserver.update.options.allow_disabled_algorithms = False
370 knownapks = fdroidserver.common.KnownApks()
371 apksourcedir = os.getcwd()
372 tmpdir = os.path.join(localmodule, '.testfiles')
373 if not os.path.exists(tmpdir):
375 tmptestsdir = tempfile.mkdtemp(prefix='test_process_apk_signed_by_disabled_algorithms-',
377 print('tmptestsdir', tmptestsdir)
378 os.chdir(tmptestsdir)
381 # setup the repo, create icons dirs, etc.
382 fdroidserver.update.process_apks({}, 'repo', knownapks)
383 fdroidserver.update.process_apks({}, 'archive', knownapks)
385 disabledsigs = ['org.bitbucket.tickytacky.mirrormirror_2.apk', ]
386 for apkName in disabledsigs:
387 shutil.copy(os.path.join(apksourcedir, apkName),
388 os.path.join(tmptestsdir, 'repo'))
390 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
392 allow_disabled_algorithms=True,
393 archive_bad_sig=False)
394 self.assertFalse(skip)
395 self.assertIsNotNone(apk)
396 self.assertTrue(cachechanged)
397 self.assertFalse(os.path.exists(os.path.join('archive', apkName)))
398 self.assertTrue(os.path.exists(os.path.join('repo', apkName)))
400 # this test only works on systems with fully updated Java/jarsigner
401 # that has MD5 listed in jdk.jar.disabledAlgorithms in java.security
402 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
404 allow_disabled_algorithms=False,
405 archive_bad_sig=True)
406 self.assertTrue(skip)
407 self.assertIsNone(apk)
408 self.assertFalse(cachechanged)
409 self.assertTrue(os.path.exists(os.path.join('archive', apkName)))
410 self.assertFalse(os.path.exists(os.path.join('repo', apkName)))
412 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'archive',
414 allow_disabled_algorithms=False,
415 archive_bad_sig=False)
416 self.assertFalse(skip)
417 self.assertIsNotNone(apk)
418 self.assertTrue(cachechanged)
419 self.assertTrue(os.path.exists(os.path.join('archive', apkName)))
420 self.assertFalse(os.path.exists(os.path.join('repo', apkName)))
422 # ensure that icons have been moved to the archive as well
423 for density in fdroidserver.update.screen_densities:
424 icon_path = os.path.join(fdroidserver.update.get_icon_dir('archive', density),
426 self.assertTrue(os.path.isfile(icon_path))
427 self.assertTrue(os.path.getsize(icon_path) > 1)
429 badsigs = ['urzip-badcert.apk', 'urzip-badsig.apk', 'urzip-release-unsigned.apk', ]
430 for apkName in badsigs:
431 shutil.copy(os.path.join(apksourcedir, apkName),
432 os.path.join(tmptestsdir, 'repo'))
434 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
436 allow_disabled_algorithms=False,
437 archive_bad_sig=False)
438 self.assertTrue(skip)
439 self.assertIsNone(apk)
440 self.assertFalse(cachechanged)
442 def test_process_invalid_apk(self):
443 os.chdir(os.path.join(localmodule, 'tests'))
444 if os.path.basename(os.getcwd()) != 'tests':
445 raise Exception('This test must be run in the "tests/" subdir')
448 fdroidserver.common.fill_config_defaults(config)
449 fdroidserver.common.config = config
450 fdroidserver.update.config = config
451 fdroidserver.update.options.delete_unknown = False
453 knownapks = fdroidserver.common.KnownApks()
454 apk = 'fake.ota.update_1234.zip' # this is not an APK, scanning should fail
455 (skip, apk, cachechanged) = fdroidserver.update.process_apk({}, apk, 'repo', knownapks,
458 self.assertTrue(skip)
459 self.assertIsNone(apk)
460 self.assertFalse(cachechanged)
462 def test_translate_per_build_anti_features(self):
463 os.chdir(os.path.join(localmodule, 'tests'))
464 if os.path.basename(os.getcwd()) != 'tests':
465 raise Exception('This test must be run in the "tests/" subdir')
468 fdroidserver.common.fill_config_defaults(config)
469 config['ndk_paths'] = dict()
470 config['accepted_formats'] = ['json', 'txt', 'yml']
471 fdroidserver.common.config = config
472 fdroidserver.update.config = config
474 fdroidserver.update.options = type('', (), {})()
475 fdroidserver.update.options.clean = True
476 fdroidserver.update.options.delete_unknown = True
477 fdroidserver.update.options.rename_apks = False
478 fdroidserver.update.options.allow_disabled_algorithms = False
480 apps = fdroidserver.metadata.read_metadata(xref=True)
481 knownapks = fdroidserver.common.KnownApks()
482 apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
483 fdroidserver.update.translate_per_build_anti_features(apps, apks)
484 self.assertEqual(len(apks), 11)
487 if apk['packageName'] == 'com.politedroid' and apk['versionCode'] == 3:
488 antiFeatures = apk.get('antiFeatures')
489 self.assertTrue('KnownVuln' in antiFeatures)
490 self.assertEqual(3, len(antiFeatures))
492 self.assertTrue(foundtest)
494 def test_create_metadata_from_template(self):
495 tmpdir = os.path.join(localmodule, '.testfiles')
496 if not os.path.exists(tmpdir):
498 tmptestsdir = tempfile.mkdtemp(prefix='test_create_metadata_from_template-',
500 print('tmptestsdir', tmptestsdir)
501 os.chdir(tmptestsdir)
504 shutil.copy(os.path.join(localmodule, 'tests', 'urzip.apk'), 'repo')
507 fdroidserver.common.fill_config_defaults(config)
508 config['ndk_paths'] = dict()
509 config['accepted_formats'] = ['json', 'txt', 'yml']
510 fdroidserver.common.config = config
511 fdroidserver.update.config = config
513 fdroidserver.update.options = type('', (), {})()
514 fdroidserver.update.options.clean = True
515 fdroidserver.update.options.delete_unknown = False
516 fdroidserver.update.options.rename_apks = False
517 fdroidserver.update.options.allow_disabled_algorithms = False
519 knownapks = fdroidserver.common.KnownApks()
520 apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
521 self.assertEqual(1, len(apks))
524 testfile = 'metadata/info.guardianproject.urzip.yml'
525 # create empty 0 byte .yml file, run read_metadata, it should work
526 open(testfile, 'a').close()
527 apps = fdroidserver.metadata.read_metadata(xref=True)
528 self.assertEqual(1, len(apps))
531 # test using internal template
532 apps = fdroidserver.metadata.read_metadata(xref=True)
533 self.assertEqual(0, len(apps))
534 fdroidserver.update.create_metadata_from_template(apk)
535 self.assertTrue(os.path.exists(testfile))
536 apps = fdroidserver.metadata.read_metadata(xref=True)
537 self.assertEqual(1, len(apps))
538 for app in apps.values():
539 self.assertEqual('urzip', app['Name'])
540 self.assertEqual(1, len(app['Categories']))
543 # test using external template.yml
545 self.assertFalse(os.path.exists(testfile))
546 shutil.copy(os.path.join(localmodule, 'examples', 'template.yml'), tmptestsdir)
547 fdroidserver.update.create_metadata_from_template(apk)
548 self.assertTrue(os.path.exists(testfile))
549 apps = fdroidserver.metadata.read_metadata(xref=True)
550 self.assertEqual(1, len(apps))
551 for app in apps.values():
552 self.assertEqual('urzip', app['Name'])
553 self.assertEqual(1, len(app['Categories']))
554 self.assertEqual('Internet', app['Categories'][0])
556 with open(testfile) as fp:
558 self.assertEqual('urzip', data['Name'])
559 self.assertEqual('urzip', data['Summary'])
562 if __name__ == "__main__":
563 parser = optparse.OptionParser()
564 parser.add_option("-v", "--verbose", action="store_true", default=False,
565 help="Spew out even more information than normal")
566 (fdroidserver.common.options, args) = parser.parse_args(['--verbose'])
568 newSuite = unittest.TestSuite()
569 newSuite.addTest(unittest.makeSuite(UpdateTest))