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)
46 for packageName in ('info.guardianproject.urzip', 'org.videolan.vlc', 'obb.mainpatch.current'):
47 apps[packageName] = dict()
48 apps[packageName]['id'] = packageName
49 apps[packageName]['CurrentVersionCode'] = 0xcafebeef
50 apps['info.guardianproject.urzip']['CurrentVersionCode'] = 100
51 fdroidserver.update.insert_localized_app_metadata(apps)
53 appdir = os.path.join('repo', 'info.guardianproject.urzip', 'en-US')
54 self.assertTrue(os.path.isfile(os.path.join(appdir, 'icon.png')))
55 self.assertTrue(os.path.isfile(os.path.join(appdir, 'featureGraphic.png')))
57 self.assertEqual(3, len(apps))
58 for packageName, app in apps.items():
59 self.assertTrue('localized' in app)
60 self.assertTrue('en-US' in app['localized'])
61 self.assertEqual(1, len(app['localized']))
62 if packageName == 'info.guardianproject.urzip':
63 self.assertEqual(7, len(app['localized']['en-US']))
64 self.assertEqual('full description\n', app['localized']['en-US']['description'])
65 self.assertEqual('title\n', app['localized']['en-US']['name'])
66 self.assertEqual('short description\n', app['localized']['en-US']['summary'])
67 self.assertEqual('video\n', app['localized']['en-US']['video'])
68 self.assertEqual('icon.png', app['localized']['en-US']['icon'])
69 self.assertEqual('featureGraphic.png', app['localized']['en-US']['featureGraphic'])
70 self.assertEqual('100\n', app['localized']['en-US']['whatsNew'])
71 elif packageName == 'org.videolan.vlc':
72 self.assertEqual('icon.png', app['localized']['en-US']['icon'])
73 self.assertEqual(9, len(app['localized']['en-US']['phoneScreenshots']))
74 self.assertEqual(15, len(app['localized']['en-US']['sevenInchScreenshots']))
75 elif packageName == 'obb.mainpatch.current':
76 self.assertEqual('icon.png', app['localized']['en-US']['icon'])
77 self.assertEqual('featureGraphic.png', app['localized']['en-US']['featureGraphic'])
78 self.assertEqual(1, len(app['localized']['en-US']['phoneScreenshots']))
79 self.assertEqual(1, len(app['localized']['en-US']['sevenInchScreenshots']))
81 def test_insert_triple_t_metadata(self):
82 importer = os.path.join(localmodule, 'tests', 'tmp', 'importer')
83 packageName = 'org.fdroid.ci.test.app'
84 if not os.path.isdir(importer):
85 logging.warning('skipping test_insert_triple_t_metadata, import.TestCase must run first!')
87 tmpdir = os.path.join(localmodule, '.testfiles')
88 if not os.path.exists(tmpdir):
90 tmptestsdir = tempfile.mkdtemp(prefix='test_insert_triple_t_metadata-', dir=tmpdir)
91 packageDir = os.path.join(tmptestsdir, 'build', packageName)
92 shutil.copytree(importer, packageDir)
94 # always use the same commit so these tests work when ci-test-app.git is updated
95 repo = git.Repo(packageDir)
96 for remote in repo.remotes:
98 repo.git.reset('--hard', 'b9e5d1a0d8d6fc31d4674b2f0514fef10762ed4f')
99 repo.git.clean('-fdx')
101 os.mkdir(os.path.join(tmptestsdir, 'metadata'))
103 metadata['Description'] = 'This is just a test app'
104 with open(os.path.join(tmptestsdir, 'metadata', packageName + '.yml'), 'w') as fp:
105 yaml.dump(metadata, fp)
108 fdroidserver.common.fill_config_defaults(config)
109 config['accepted_formats'] = ('yml')
110 fdroidserver.common.config = config
111 fdroidserver.update.config = config
112 fdroidserver.update.options = fdroidserver.common.options
113 os.chdir(tmptestsdir)
115 apps = fdroidserver.metadata.read_metadata(xref=True)
116 fdroidserver.update.copy_triple_t_store_metadata(apps)
118 # TODO ideally, this would compare the whole dict like in metadata.TestCase's test_read_metadata()
120 'ar', 'ast_ES', 'az', 'ca', 'ca_ES', 'cs-CZ', 'cs_CZ', 'da',
121 'da-DK', 'de', 'de-DE', 'el', 'en-US', 'es', 'es-ES', 'es_ES', 'et',
122 'fi', 'fr', 'fr-FR', 'he_IL', 'hi-IN', 'hi_IN', 'hu', 'id', 'it',
123 'it-IT', 'it_IT', 'iw-IL', 'ja', 'ja-JP', 'kn_IN', 'ko', 'ko-KR',
124 'ko_KR', 'lt', 'nb', 'nb_NO', 'nl', 'nl-NL', 'no', 'pl', 'pl-PL',
125 'pl_PL', 'pt', 'pt-BR', 'pt-PT', 'pt_BR', 'ro', 'ro_RO', 'ru-RU',
126 'ru_RU', 'sv-SE', 'sv_SE', 'te', 'tr', 'tr-TR', 'uk', 'uk_UA', 'vi',
127 'vi_VN', 'zh-CN', 'zh_CN', 'zh_TW',
129 locales = sorted(list(apps['org.fdroid.ci.test.app']['localized'].keys()))
130 self.assertEqual(correctlocales, locales)
132 def javagetsig(self, apkfile):
133 getsig_dir = os.path.join(os.path.dirname(__file__), 'getsig')
134 if not os.path.exists(getsig_dir + "/getsig.class"):
135 logging.critical("getsig.class not found. To fix: cd '%s' && ./make.sh" % getsig_dir)
137 # FDroidPopen needs some config to work
139 fdroidserver.common.fill_config_defaults(config)
140 fdroidserver.common.config = config
141 p = FDroidPopen(['java', '-cp', os.path.join(os.path.dirname(__file__), 'getsig'),
142 'getsig', os.path.join(os.getcwd(), apkfile)])
144 for line in p.output.splitlines():
145 if line.startswith('Result:'):
146 sig = line[7:].strip()
148 if p.returncode == 0:
153 def testGoodGetsig(self):
154 # config needed to use jarsigner and keytool
156 fdroidserver.common.fill_config_defaults(config)
157 fdroidserver.update.config = config
158 apkfile = os.path.join(os.path.dirname(__file__), 'urzip.apk')
159 sig = self.javagetsig(apkfile)
160 self.assertIsNotNone(sig, "sig is None")
161 pysig = fdroidserver.update.getsig(apkfile)
162 self.assertIsNotNone(pysig, "pysig is None")
163 self.assertEqual(sig, fdroidserver.update.getsig(apkfile),
164 "python sig not equal to java sig!")
165 self.assertEqual(len(sig), len(pysig),
166 "the length of the two sigs are different!")
168 self.assertEqual(unhexlify(sig), unhexlify(pysig),
169 "the length of the two sigs are different!")
170 except TypeError as e:
172 self.assertTrue(False, 'TypeError!')
174 def testBadGetsig(self):
175 """getsig() should still be able to fetch the fingerprint of bad signatures"""
176 # config needed to use jarsigner and keytool
178 fdroidserver.common.fill_config_defaults(config)
179 fdroidserver.update.config = config
181 apkfile = os.path.join(os.path.dirname(__file__), 'urzip-badsig.apk')
182 sig = fdroidserver.update.getsig(apkfile)
183 self.assertEqual(sig, 'e0ecb5fc2d63088e4a07ae410a127722',
184 "python sig should be: " + str(sig))
186 apkfile = os.path.join(os.path.dirname(__file__), 'urzip-badcert.apk')
187 sig = fdroidserver.update.getsig(apkfile)
188 self.assertEqual(sig, 'e0ecb5fc2d63088e4a07ae410a127722',
189 "python sig should be: " + str(sig))
191 def testScanApksAndObbs(self):
192 os.chdir(os.path.join(localmodule, 'tests'))
193 if os.path.basename(os.getcwd()) != 'tests':
194 raise Exception('This test must be run in the "tests/" subdir')
197 fdroidserver.common.fill_config_defaults(config)
198 config['ndk_paths'] = dict()
199 config['accepted_formats'] = ['json', 'txt', 'yml']
200 fdroidserver.common.config = config
201 fdroidserver.update.config = config
203 fdroidserver.update.options = type('', (), {})()
204 fdroidserver.update.options.clean = True
205 fdroidserver.update.options.delete_unknown = True
206 fdroidserver.update.options.rename_apks = False
207 fdroidserver.update.options.allow_disabled_algorithms = False
209 apps = fdroidserver.metadata.read_metadata(xref=True)
210 knownapks = fdroidserver.common.KnownApks()
211 apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
212 self.assertEqual(len(apks), 11)
214 self.assertEqual(apk['packageName'], 'com.politedroid')
215 self.assertEqual(apk['versionCode'], 3)
216 self.assertEqual(apk['minSdkVersion'], '3')
217 self.assertEqual(apk['targetSdkVersion'], '3')
218 self.assertFalse('maxSdkVersion' in apk)
220 self.assertEqual(apk['packageName'], 'obb.main.oldversion')
221 self.assertEqual(apk['versionCode'], 1444412523)
222 self.assertEqual(apk['minSdkVersion'], '4')
223 self.assertEqual(apk['targetSdkVersion'], '18')
224 self.assertFalse('maxSdkVersion' in apk)
226 fdroidserver.update.insert_obbs('repo', apps, apks)
228 if apk['packageName'] == 'obb.mainpatch.current':
229 self.assertEqual(apk.get('obbMainFile'), 'main.1619.obb.mainpatch.current.obb')
230 self.assertEqual(apk.get('obbPatchFile'), 'patch.1619.obb.mainpatch.current.obb')
231 elif apk['packageName'] == 'obb.main.oldversion':
232 self.assertEqual(apk.get('obbMainFile'), 'main.1434483388.obb.main.oldversion.obb')
233 self.assertIsNone(apk.get('obbPatchFile'))
234 elif apk['packageName'] == 'obb.main.twoversions':
235 self.assertIsNone(apk.get('obbPatchFile'))
236 if apk['versionCode'] == 1101613:
237 self.assertEqual(apk.get('obbMainFile'), 'main.1101613.obb.main.twoversions.obb')
238 elif apk['versionCode'] == 1101615:
239 self.assertEqual(apk.get('obbMainFile'), 'main.1101615.obb.main.twoversions.obb')
240 elif apk['versionCode'] == 1101617:
241 self.assertEqual(apk.get('obbMainFile'), 'main.1101615.obb.main.twoversions.obb')
243 self.assertTrue(False)
244 elif apk['packageName'] == 'info.guardianproject.urzip':
245 self.assertIsNone(apk.get('obbMainFile'))
246 self.assertIsNone(apk.get('obbPatchFile'))
248 def test_scan_apk(self):
250 fdroidserver.common.fill_config_defaults(config)
251 fdroidserver.update.config = config
252 os.chdir(os.path.join(localmodule, 'tests'))
253 if os.path.basename(os.getcwd()) != 'tests':
254 raise Exception('This test must be run in the "tests/" subdir')
256 apk_info = fdroidserver.update.scan_apk('org.dyndns.fules.ck_20.apk')
258 self.assertEqual(apk_info['icons_src'], {'240': 'res/drawable-hdpi-v4/icon_launcher.png',
259 '120': 'res/drawable-ldpi-v4/icon_launcher.png',
260 '160': 'res/drawable-mdpi-v4/icon_launcher.png',
261 '-1': 'res/drawable-mdpi-v4/icon_launcher.png'})
262 self.assertEqual(apk_info['icons'], {})
263 self.assertEqual(apk_info['features'], [])
264 self.assertEqual(apk_info['antiFeatures'], set())
265 self.assertEqual(apk_info['versionName'], 'v1.6pre2')
266 self.assertEqual(apk_info['hash'],
267 '897486e1f857c6c0ee32ccbad0e1b8cd82f6d0e65a44a23f13f852d2b63a18c8')
268 self.assertEqual(apk_info['packageName'], 'org.dyndns.fules.ck')
269 self.assertEqual(apk_info['versionCode'], 20)
270 self.assertEqual(apk_info['size'], 132453)
271 self.assertEqual(apk_info['nativecode'],
272 ['arm64-v8a', 'armeabi', 'armeabi-v7a', 'mips', 'mips64', 'x86', 'x86_64'])
273 self.assertEqual(apk_info['minSdkVersion'], '7')
274 self.assertEqual(apk_info['sig'], '9bf7a6a67f95688daec75eab4b1436ac')
275 self.assertEqual(apk_info['hashType'], 'sha256')
276 self.assertEqual(apk_info['targetSdkVersion'], '8')
278 def test_scan_apk_no_sig(self):
280 fdroidserver.common.fill_config_defaults(config)
281 fdroidserver.update.config = config
282 os.chdir(os.path.join(localmodule, 'tests'))
283 if os.path.basename(os.getcwd()) != 'tests':
284 raise Exception('This test must be run in the "tests/" subdir')
286 with self.assertRaises(fdroidserver.exception.BuildException):
287 fdroidserver.update.scan_apk('urzip-release-unsigned.apk')
289 def test_process_apk(self):
291 def _build_yaml_representer(dumper, data):
292 '''Creates a YAML representation of a Build instance'''
293 return dumper.represent_dict(data)
296 fdroidserver.common.fill_config_defaults(config)
297 fdroidserver.update.config = config
298 os.chdir(os.path.join(localmodule, 'tests'))
299 if os.path.basename(os.getcwd()) != 'tests':
300 raise Exception('This test must be run in the "tests/" subdir')
302 config['ndk_paths'] = dict()
303 config['accepted_formats'] = ['json', 'txt', 'yml']
304 fdroidserver.common.config = config
305 fdroidserver.update.config = config
307 fdroidserver.update.options = type('', (), {})()
308 fdroidserver.update.options.clean = True
309 fdroidserver.update.options.rename_apks = False
310 fdroidserver.update.options.delete_unknown = True
311 fdroidserver.update.options.allow_disabled_algorithms = False
313 for icon_dir in fdroidserver.update.get_all_icon_dirs('repo'):
314 if not os.path.exists(icon_dir):
315 os.makedirs(icon_dir)
317 knownapks = fdroidserver.common.KnownApks()
318 apkList = ['../urzip.apk', '../org.dyndns.fules.ck_20.apk']
320 for apkName in apkList:
321 _, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo', knownapks,
323 # Don't care about the date added to the repo and relative apkName
326 # avoid AAPT application name bug
329 # ensure that icons have been extracted properly
330 if apkName == '../urzip.apk':
331 self.assertEqual(apk['icon'], 'info.guardianproject.urzip.100.png')
332 if apkName == '../org.dyndns.fules.ck_20.apk':
333 self.assertEqual(apk['icon'], 'org.dyndns.fules.ck.20.png')
334 for density in fdroidserver.update.screen_densities:
335 icon_path = os.path.join(fdroidserver.update.get_icon_dir('repo', density),
337 self.assertTrue(os.path.isfile(icon_path))
338 self.assertTrue(os.path.getsize(icon_path) > 1)
340 savepath = os.path.join('metadata', 'apk', apk['packageName'] + '.yaml')
341 # Uncomment to save APK metadata
342 # with open(savepath, 'w') as f:
343 # yaml.add_representer(fdroidserver.metadata.Build, _build_yaml_representer)
344 # yaml.dump(apk, f, default_flow_style=False)
346 with open(savepath, 'r') as f:
347 frompickle = yaml.load(f)
349 self.assertEqual(apk, frompickle)
351 def test_process_apk_signed_by_disabled_algorithms(self):
352 os.chdir(os.path.join(localmodule, 'tests'))
353 if os.path.basename(os.getcwd()) != 'tests':
354 raise Exception('This test must be run in the "tests/" subdir')
357 fdroidserver.common.fill_config_defaults(config)
358 fdroidserver.update.config = config
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.verbose = True
368 fdroidserver.update.options.rename_apks = False
369 fdroidserver.update.options.delete_unknown = True
370 fdroidserver.update.options.allow_disabled_algorithms = False
372 knownapks = fdroidserver.common.KnownApks()
373 apksourcedir = os.getcwd()
374 tmpdir = os.path.join(localmodule, '.testfiles')
375 if not os.path.exists(tmpdir):
377 tmptestsdir = tempfile.mkdtemp(prefix='test_process_apk_signed_by_disabled_algorithms-',
379 print('tmptestsdir', tmptestsdir)
380 os.chdir(tmptestsdir)
383 # setup the repo, create icons dirs, etc.
384 fdroidserver.update.process_apks({}, 'repo', knownapks)
385 fdroidserver.update.process_apks({}, 'archive', knownapks)
387 disabledsigs = ['org.bitbucket.tickytacky.mirrormirror_2.apk', ]
388 for apkName in disabledsigs:
389 shutil.copy(os.path.join(apksourcedir, apkName),
390 os.path.join(tmptestsdir, 'repo'))
392 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
394 allow_disabled_algorithms=True,
395 archive_bad_sig=False)
396 self.assertFalse(skip)
397 self.assertIsNotNone(apk)
398 self.assertTrue(cachechanged)
399 self.assertFalse(os.path.exists(os.path.join('archive', apkName)))
400 self.assertTrue(os.path.exists(os.path.join('repo', apkName)))
402 javac = config['jarsigner'].replace('jarsigner', 'javac')
403 v = subprocess.check_output([javac, '-version'], stderr=subprocess.STDOUT)[6:-1].decode('utf-8')
404 if LooseVersion(v) < LooseVersion('1.8.0_132'):
405 print('SKIPPING: running tests with old Java (' + v + ')')
408 # this test only works on systems with fully updated Java/jarsigner
409 # that has MD5 listed in jdk.jar.disabledAlgorithms in java.security
410 # https://blogs.oracle.com/java-platform-group/oracle-jre-will-no-longer-trust-md5-signed-code-by-default
411 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
413 allow_disabled_algorithms=False,
414 archive_bad_sig=True)
415 self.assertTrue(skip)
416 self.assertIsNone(apk)
417 self.assertFalse(cachechanged)
418 self.assertTrue(os.path.exists(os.path.join('archive', apkName)))
419 self.assertFalse(os.path.exists(os.path.join('repo', apkName)))
421 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'archive',
423 allow_disabled_algorithms=False,
424 archive_bad_sig=False)
425 self.assertFalse(skip)
426 self.assertIsNotNone(apk)
427 self.assertTrue(cachechanged)
428 self.assertTrue(os.path.exists(os.path.join('archive', apkName)))
429 self.assertFalse(os.path.exists(os.path.join('repo', apkName)))
431 # ensure that icons have been moved to the archive as well
432 for density in fdroidserver.update.screen_densities:
433 icon_path = os.path.join(fdroidserver.update.get_icon_dir('archive', density),
435 self.assertTrue(os.path.isfile(icon_path))
436 self.assertTrue(os.path.getsize(icon_path) > 1)
438 badsigs = ['urzip-badcert.apk', 'urzip-badsig.apk', 'urzip-release-unsigned.apk', ]
439 for apkName in badsigs:
440 shutil.copy(os.path.join(apksourcedir, apkName),
441 os.path.join(tmptestsdir, 'repo'))
443 skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
445 allow_disabled_algorithms=False,
446 archive_bad_sig=False)
447 self.assertTrue(skip)
448 self.assertIsNone(apk)
449 self.assertFalse(cachechanged)
451 def test_process_invalid_apk(self):
452 os.chdir(os.path.join(localmodule, 'tests'))
453 if os.path.basename(os.getcwd()) != 'tests':
454 raise Exception('This test must be run in the "tests/" subdir')
457 fdroidserver.common.fill_config_defaults(config)
458 fdroidserver.common.config = config
459 fdroidserver.update.config = config
460 fdroidserver.update.options.delete_unknown = False
462 knownapks = fdroidserver.common.KnownApks()
463 apk = 'fake.ota.update_1234.zip' # this is not an APK, scanning should fail
464 (skip, apk, cachechanged) = fdroidserver.update.process_apk({}, apk, 'repo', knownapks,
467 self.assertTrue(skip)
468 self.assertIsNone(apk)
469 self.assertFalse(cachechanged)
471 def test_translate_per_build_anti_features(self):
472 os.chdir(os.path.join(localmodule, 'tests'))
473 if os.path.basename(os.getcwd()) != 'tests':
474 raise Exception('This test must be run in the "tests/" subdir')
477 fdroidserver.common.fill_config_defaults(config)
478 config['ndk_paths'] = dict()
479 config['accepted_formats'] = ['json', 'txt', 'yml']
480 fdroidserver.common.config = config
481 fdroidserver.update.config = config
483 fdroidserver.update.options = type('', (), {})()
484 fdroidserver.update.options.clean = True
485 fdroidserver.update.options.delete_unknown = True
486 fdroidserver.update.options.rename_apks = False
487 fdroidserver.update.options.allow_disabled_algorithms = False
489 apps = fdroidserver.metadata.read_metadata(xref=True)
490 knownapks = fdroidserver.common.KnownApks()
491 apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
492 fdroidserver.update.translate_per_build_anti_features(apps, apks)
493 self.assertEqual(len(apks), 11)
496 if apk['packageName'] == 'com.politedroid' and apk['versionCode'] == 3:
497 antiFeatures = apk.get('antiFeatures')
498 self.assertTrue('KnownVuln' in antiFeatures)
499 self.assertEqual(3, len(antiFeatures))
501 self.assertTrue(foundtest)
503 def test_create_metadata_from_template(self):
504 tmpdir = os.path.join(localmodule, '.testfiles')
505 if not os.path.exists(tmpdir):
507 tmptestsdir = tempfile.mkdtemp(prefix='test_create_metadata_from_template-',
509 print('tmptestsdir', tmptestsdir)
510 os.chdir(tmptestsdir)
513 shutil.copy(os.path.join(localmodule, 'tests', 'urzip.apk'), 'repo')
516 fdroidserver.common.fill_config_defaults(config)
517 config['ndk_paths'] = dict()
518 config['accepted_formats'] = ['json', 'txt', 'yml']
519 fdroidserver.common.config = config
520 fdroidserver.update.config = config
522 fdroidserver.update.options = type('', (), {})()
523 fdroidserver.update.options.clean = True
524 fdroidserver.update.options.delete_unknown = False
525 fdroidserver.update.options.rename_apks = False
526 fdroidserver.update.options.allow_disabled_algorithms = False
528 knownapks = fdroidserver.common.KnownApks()
529 apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks, False)
530 self.assertEqual(1, len(apks))
533 testfile = 'metadata/info.guardianproject.urzip.yml'
534 # create empty 0 byte .yml file, run read_metadata, it should work
535 open(testfile, 'a').close()
536 apps = fdroidserver.metadata.read_metadata(xref=True)
537 self.assertEqual(1, len(apps))
540 # test using internal template
541 apps = fdroidserver.metadata.read_metadata(xref=True)
542 self.assertEqual(0, len(apps))
543 fdroidserver.update.create_metadata_from_template(apk)
544 self.assertTrue(os.path.exists(testfile))
545 apps = fdroidserver.metadata.read_metadata(xref=True)
546 self.assertEqual(1, len(apps))
547 for app in apps.values():
548 self.assertEqual('urzip', app['Name'])
549 self.assertEqual(1, len(app['Categories']))
552 # test using external template.yml
554 self.assertFalse(os.path.exists(testfile))
555 shutil.copy(os.path.join(localmodule, 'examples', 'template.yml'), tmptestsdir)
556 fdroidserver.update.create_metadata_from_template(apk)
557 self.assertTrue(os.path.exists(testfile))
558 apps = fdroidserver.metadata.read_metadata(xref=True)
559 self.assertEqual(1, len(apps))
560 for app in apps.values():
561 self.assertEqual('urzip', app['Name'])
562 self.assertEqual(1, len(app['Categories']))
563 self.assertEqual('Internet', app['Categories'][0])
565 with open(testfile) as fp:
567 self.assertEqual('urzip', data['Name'])
568 self.assertEqual('urzip', data['Summary'])
571 if __name__ == "__main__":
572 parser = optparse.OptionParser()
573 parser.add_option("-v", "--verbose", action="store_true", default=False,
574 help="Spew out even more information than normal")
575 (fdroidserver.common.options, args) = parser.parse_args(['--verbose'])
577 newSuite = unittest.TestSuite()
578 newSuite.addTest(unittest.makeSuite(UpdateTest))
579 unittest.main(failfast=False)