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.metadata
25 import fdroidserver.update
26 from fdroidserver.common import FDroidPopen
29 class UpdateTest(unittest.TestCase):
32 def testInsertStoreMetadata(self):
34 fdroidserver.common.fill_config_defaults(config)
35 config['accepted_formats'] = ('txt', 'yml')
36 fdroidserver.update.config = config
37 fdroidserver.update.options = fdroidserver.common.options
38 os.chdir(os.path.join(localmodule, 'tests'))
40 shutil.rmtree(os.path.join('repo', 'info.guardianproject.urzip'), ignore_errors=True)
43 for packageName in ('info.guardianproject.urzip', 'org.videolan.vlc', 'obb.mainpatch.current'):
44 apps[packageName] = dict()
45 apps[packageName]['id'] = packageName
46 apps[packageName]['CurrentVersionCode'] = 0xcafebeef
47 apps['info.guardianproject.urzip']['CurrentVersionCode'] = 100
48 fdroidserver.update.insert_localized_app_metadata(apps)
50 appdir = os.path.join('repo', 'info.guardianproject.urzip', 'en-US')
51 self.assertTrue(os.path.isfile(os.path.join(appdir, 'icon.png')))
52 self.assertTrue(os.path.isfile(os.path.join(appdir, 'featureGraphic.png')))
54 self.assertEqual(3, len(apps))
55 for packageName, app in apps.items():
56 self.assertTrue('localized' in app)
57 self.assertTrue('en-US' in app['localized'])
58 self.assertEqual(1, len(app['localized']))
59 if packageName == 'info.guardianproject.urzip':
60 self.assertEqual(7, len(app['localized']['en-US']))
61 self.assertEqual('full description\n', app['localized']['en-US']['description'])
62 self.assertEqual('title\n', app['localized']['en-US']['name'])
63 self.assertEqual('short description\n', app['localized']['en-US']['summary'])
64 self.assertEqual('video\n', app['localized']['en-US']['video'])
65 self.assertEqual('icon.png', app['localized']['en-US']['icon'])
66 self.assertEqual('featureGraphic.png', app['localized']['en-US']['featureGraphic'])
67 self.assertEqual('100\n', app['localized']['en-US']['whatsNew'])
68 elif packageName == 'org.videolan.vlc':
69 self.assertEqual('icon.png', app['localized']['en-US']['icon'])
70 self.assertEqual(9, len(app['localized']['en-US']['phoneScreenshots']))
71 self.assertEqual(15, len(app['localized']['en-US']['sevenInchScreenshots']))
72 elif packageName == 'obb.mainpatch.current':
73 self.assertEqual('icon.png', app['localized']['en-US']['icon'])
74 self.assertEqual('featureGraphic.png', app['localized']['en-US']['featureGraphic'])
75 self.assertEqual(1, len(app['localized']['en-US']['phoneScreenshots']))
76 self.assertEqual(1, len(app['localized']['en-US']['sevenInchScreenshots']))
78 def test_insert_triple_t_metadata(self):
79 importer = os.path.join(localmodule, 'tests', 'tmp', 'importer')
80 packageName = 'org.fdroid.ci.test.app'
81 if not os.path.isdir(importer):
82 logging.warning('skipping test_insert_triple_t_metadata, import.TestCase must run first!')
84 tmpdir = os.path.join(localmodule, '.testfiles')
85 if not os.path.exists(tmpdir):
87 tmptestsdir = tempfile.mkdtemp(prefix='test_insert_triple_t_metadata-', dir=tmpdir)
88 packageDir = os.path.join(tmptestsdir, 'build', packageName)
89 shutil.copytree(importer, packageDir)
91 # always use the same commit so these tests work when ci-test-app.git is updated
92 repo = git.Repo(packageDir)
93 for remote in repo.remotes:
95 repo.git.reset('--hard', 'b9e5d1a0d8d6fc31d4674b2f0514fef10762ed4f')
96 repo.git.clean('-fdx')
98 os.mkdir(os.path.join(tmptestsdir, 'metadata'))
100 metadata['Description'] = 'This is just a test app'
101 with open(os.path.join(tmptestsdir, 'metadata', packageName + '.yml'), 'w') as fp:
102 yaml.dump(metadata, fp)
105 fdroidserver.common.fill_config_defaults(config)
106 config['accepted_formats'] = ('yml')
107 fdroidserver.common.config = config
108 fdroidserver.update.config = config
109 fdroidserver.update.options = fdroidserver.common.options
110 os.chdir(tmptestsdir)
112 apps = fdroidserver.metadata.read_metadata(xref=True)
113 fdroidserver.update.copy_triple_t_store_metadata(apps)
115 # TODO ideally, this would compare the whole dict like in metadata.TestCase's test_read_metadata()
117 'ar', 'ast_ES', 'az', 'ca', 'ca_ES', 'cs-CZ', 'cs_CZ', 'da',
118 'da-DK', 'de', 'de-DE', 'el', 'en-US', 'es', 'es-ES', 'es_ES', 'et',
119 'fi', 'fr', 'fr-FR', 'he_IL', 'hi-IN', 'hi_IN', 'hu', 'id', 'it',
120 'it-IT', 'it_IT', 'iw-IL', 'ja', 'ja-JP', 'kn_IN', 'ko', 'ko-KR',
121 'ko_KR', 'lt', 'nb', 'nb_NO', 'nl', 'nl-NL', 'no', 'pl', 'pl-PL',
122 'pl_PL', 'pt', 'pt-BR', 'pt-PT', 'pt_BR', 'ro', 'ro_RO', 'ru-RU',
123 'ru_RU', 'sv-SE', 'sv_SE', 'te', 'tr', 'tr-TR', 'uk', 'uk_UA', 'vi',
124 'vi_VN', 'zh-CN', 'zh_CN', 'zh_TW',
126 locales = sorted(list(apps['org.fdroid.ci.test.app']['localized'].keys()))
127 self.assertEqual(correctlocales, locales)
129 def javagetsig(self, apkfile):
130 getsig_dir = os.path.join(os.path.dirname(__file__), 'getsig')
131 if not os.path.exists(getsig_dir + "/getsig.class"):
132 logging.critical("getsig.class not found. To fix: cd '%s' && ./make.sh" % getsig_dir)
134 # FDroidPopen needs some config to work
136 fdroidserver.common.fill_config_defaults(config)
137 fdroidserver.common.config = config
138 p = FDroidPopen(['java', '-cp', os.path.join(os.path.dirname(__file__), 'getsig'),
139 'getsig', os.path.join(os.getcwd(), apkfile)])
141 for line in p.output.splitlines():
142 if line.startswith('Result:'):
143 sig = line[7:].strip()
145 if p.returncode == 0:
150 def testGoodGetsig(self):
151 # config needed to use jarsigner and keytool
153 fdroidserver.common.fill_config_defaults(config)
154 fdroidserver.update.config = config
155 apkfile = os.path.join(os.path.dirname(__file__), 'urzip.apk')
156 sig = self.javagetsig(apkfile)
157 self.assertIsNotNone(sig, "sig is None")
158 pysig = fdroidserver.update.getsig(apkfile)
159 self.assertIsNotNone(pysig, "pysig is None")
160 self.assertEqual(sig, fdroidserver.update.getsig(apkfile),
161 "python sig not equal to java sig!")
162 self.assertEqual(len(sig), len(pysig),
163 "the length of the two sigs are different!")
165 self.assertEqual(unhexlify(sig), unhexlify(pysig),
166 "the length of the two sigs are different!")
167 except TypeError as e:
169 self.assertTrue(False, 'TypeError!')
171 def testBadGetsig(self):
172 """getsig() should still be able to fetch the fingerprint of bad signatures"""
173 # config needed to use jarsigner and keytool
175 fdroidserver.common.fill_config_defaults(config)
176 fdroidserver.update.config = config
178 apkfile = os.path.join(os.path.dirname(__file__), 'urzip-badsig.apk')
179 sig = fdroidserver.update.getsig(apkfile)
180 self.assertEqual(sig, 'e0ecb5fc2d63088e4a07ae410a127722',
181 "python sig should be: " + str(sig))
183 apkfile = os.path.join(os.path.dirname(__file__), 'urzip-badcert.apk')
184 sig = fdroidserver.update.getsig(apkfile)
185 self.assertEqual(sig, 'e0ecb5fc2d63088e4a07ae410a127722',
186 "python sig should be: " + str(sig))
188 def testScanApksAndObbs(self):
189 os.chdir(os.path.join(localmodule, 'tests'))
190 if os.path.basename(os.getcwd()) != 'tests':
191 raise Exception('This test must be run in the "tests/" subdir')
194 fdroidserver.common.fill_config_defaults(config)
195 config['ndk_paths'] = dict()
196 config['accepted_formats'] = ['json', 'txt', 'yml']
197 fdroidserver.common.config = config
198 fdroidserver.update.config = config
200 fdroidserver.update.options = type('', (), {})()
201 fdroidserver.update.options.clean = True
202 fdroidserver.update.options.delete_unknown = True
203 fdroidserver.update.options.rename_apks = False
205 apps = fdroidserver.metadata.read_metadata(xref=True)
206 knownapks = fdroidserver.common.KnownApks()
207 apks, cachechanged = fdroidserver.update.scan_apks({}, 'repo', knownapks, False)
208 self.assertEqual(len(apks), 7)
210 self.assertEqual(apk['minSdkVersion'], '4')
211 self.assertEqual(apk['targetSdkVersion'], '18')
212 self.assertFalse('maxSdkVersion' in apk)
214 fdroidserver.update.insert_obbs('repo', apps, apks)
216 if apk['packageName'] == 'obb.mainpatch.current':
217 self.assertEqual(apk.get('obbMainFile'), 'main.1619.obb.mainpatch.current.obb')
218 self.assertEqual(apk.get('obbPatchFile'), 'patch.1619.obb.mainpatch.current.obb')
219 elif apk['packageName'] == 'obb.main.oldversion':
220 self.assertEqual(apk.get('obbMainFile'), 'main.1434483388.obb.main.oldversion.obb')
221 self.assertIsNone(apk.get('obbPatchFile'))
222 elif apk['packageName'] == 'obb.main.twoversions':
223 self.assertIsNone(apk.get('obbPatchFile'))
224 if apk['versionCode'] == 1101613:
225 self.assertEqual(apk.get('obbMainFile'), 'main.1101613.obb.main.twoversions.obb')
226 elif apk['versionCode'] == 1101615:
227 self.assertEqual(apk.get('obbMainFile'), 'main.1101615.obb.main.twoversions.obb')
228 elif apk['versionCode'] == 1101617:
229 self.assertEqual(apk.get('obbMainFile'), 'main.1101615.obb.main.twoversions.obb')
231 self.assertTrue(False)
232 elif apk['packageName'] == 'info.guardianproject.urzip':
233 self.assertIsNone(apk.get('obbMainFile'))
234 self.assertIsNone(apk.get('obbPatchFile'))
236 def testScanApkMetadata(self):
238 def _build_yaml_representer(dumper, data):
239 '''Creates a YAML representation of a Build instance'''
240 return dumper.represent_dict(data)
243 fdroidserver.common.fill_config_defaults(config)
244 fdroidserver.update.config = config
245 os.chdir(os.path.dirname(__file__))
246 if os.path.basename(os.getcwd()) != 'tests':
247 raise Exception('This test must be run in the "tests/" subdir')
249 config['ndk_paths'] = dict()
250 config['accepted_formats'] = ['json', 'txt', 'yml']
251 fdroidserver.common.config = config
252 fdroidserver.update.config = config
254 fdroidserver.update.options = type('', (), {})()
255 fdroidserver.update.options.clean = True
256 fdroidserver.update.options.rename_apks = False
257 fdroidserver.update.options.delete_unknown = True
259 for icon_dir in fdroidserver.update.get_all_icon_dirs('repo'):
260 if not os.path.exists(icon_dir):
261 os.makedirs(icon_dir)
263 knownapks = fdroidserver.common.KnownApks()
264 apkList = ['../urzip.apk', '../org.dyndns.fules.ck_20.apk']
266 for apkName in apkList:
267 _, apk, cachechanged = fdroidserver.update.scan_apk({}, apkName, 'repo', knownapks, False)
268 # Don't care about the date added to the repo and relative apkName
271 # avoid AAPT application name bug
274 savepath = os.path.join('metadata', 'apk', apk['packageName'] + '.yaml')
275 # Uncomment to save APK metadata
276 # with open(savepath, 'w') as f:
277 # yaml.add_representer(fdroidserver.metadata.Build, _build_yaml_representer)
278 # yaml.dump(apk, f, default_flow_style=False)
280 with open(savepath, 'r') as f:
281 frompickle = yaml.load(f)
283 self.assertEqual(apk, frompickle)
285 def test_scan_invalid_apk(self):
286 os.chdir(os.path.join(localmodule, 'tests'))
287 if os.path.basename(os.getcwd()) != 'tests':
288 raise Exception('This test must be run in the "tests/" subdir')
291 fdroidserver.common.fill_config_defaults(config)
292 fdroidserver.common.config = config
293 fdroidserver.update.config = config
294 fdroidserver.update.options.delete_unknown = False
296 knownapks = fdroidserver.common.KnownApks()
297 apk = 'fake.ota.update_1234.zip' # this is not an APK, scanning should fail
298 (skip, apk, cachechanged) = fdroidserver.update.scan_apk({}, apk, 'repo', knownapks, False)
300 self.assertTrue(skip)
301 self.assertIsNone(apk)
302 self.assertFalse(cachechanged)
305 if __name__ == "__main__":
306 parser = optparse.OptionParser()
307 parser.add_option("-v", "--verbose", action="store_true", default=False,
308 help="Spew out even more information than normal")
309 (fdroidserver.common.options, args) = parser.parse_args(['--verbose'])
311 newSuite = unittest.TestSuite()
312 newSuite.addTest(unittest.makeSuite(UpdateTest))