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 # config needed to use jarsigner and keytool
174 fdroidserver.common.fill_config_defaults(config)
175 fdroidserver.update.config = config
176 apkfile = os.path.join(os.path.dirname(__file__), 'urzip-badsig.apk')
177 sig = self.javagetsig(apkfile)
178 self.assertIsNone(sig, "sig should be None: " + str(sig))
179 pysig = fdroidserver.update.getsig(apkfile)
180 self.assertIsNone(pysig, "python sig should be None: " + str(sig))
182 apkfile = os.path.join(os.path.dirname(__file__), 'urzip-badcert.apk')
183 sig = self.javagetsig(apkfile)
184 self.assertIsNone(sig, "sig should be None: " + str(sig))
185 pysig = fdroidserver.update.getsig(apkfile)
186 self.assertIsNone(pysig, "python sig should be None: " + 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
204 apps = fdroidserver.metadata.read_metadata(xref=True)
205 knownapks = fdroidserver.common.KnownApks()
206 apks, cachechanged = fdroidserver.update.scan_apks({}, 'repo', knownapks, False)
207 self.assertEqual(len(apks), 6)
209 self.assertEqual(apk['minSdkVersion'], '4')
210 self.assertEqual(apk['targetSdkVersion'], '18')
211 self.assertFalse('maxSdkVersion' in apk)
213 fdroidserver.update.insert_obbs('repo', apps, apks)
215 if apk['packageName'] == 'obb.mainpatch.current':
216 self.assertEqual(apk.get('obbMainFile'), 'main.1619.obb.mainpatch.current.obb')
217 self.assertEqual(apk.get('obbPatchFile'), 'patch.1619.obb.mainpatch.current.obb')
218 elif apk['packageName'] == 'obb.main.oldversion':
219 self.assertEqual(apk.get('obbMainFile'), 'main.1434483388.obb.main.oldversion.obb')
220 self.assertIsNone(apk.get('obbPatchFile'))
221 elif apk['packageName'] == 'obb.main.twoversions':
222 self.assertIsNone(apk.get('obbPatchFile'))
223 if apk['versionCode'] == 1101613:
224 self.assertEqual(apk.get('obbMainFile'), 'main.1101613.obb.main.twoversions.obb')
225 elif apk['versionCode'] == 1101615:
226 self.assertEqual(apk.get('obbMainFile'), 'main.1101615.obb.main.twoversions.obb')
227 elif apk['versionCode'] == 1101617:
228 self.assertEqual(apk.get('obbMainFile'), 'main.1101615.obb.main.twoversions.obb')
230 self.assertTrue(False)
231 elif apk['packageName'] == 'info.guardianproject.urzip':
232 self.assertIsNone(apk.get('obbMainFile'))
233 self.assertIsNone(apk.get('obbPatchFile'))
235 def testScanApkMetadata(self):
237 def _build_yaml_representer(dumper, data):
238 '''Creates a YAML representation of a Build instance'''
239 return dumper.represent_dict(data)
242 fdroidserver.common.fill_config_defaults(config)
243 fdroidserver.update.config = config
244 os.chdir(os.path.dirname(__file__))
245 if os.path.basename(os.getcwd()) != 'tests':
246 raise Exception('This test must be run in the "tests/" subdir')
248 config['ndk_paths'] = dict()
249 config['accepted_formats'] = ['json', 'txt', 'yml']
250 fdroidserver.common.config = config
251 fdroidserver.update.config = config
253 fdroidserver.update.options = type('', (), {})()
254 fdroidserver.update.options.clean = True
255 fdroidserver.update.options.rename_apks = False
256 fdroidserver.update.options.delete_unknown = True
258 for icon_dir in fdroidserver.update.get_all_icon_dirs('repo'):
259 if not os.path.exists(icon_dir):
260 os.makedirs(icon_dir)
262 knownapks = fdroidserver.common.KnownApks()
263 apkList = ['../urzip.apk', '../org.dyndns.fules.ck_20.apk']
265 for apkName in apkList:
266 _, apk, cachechanged = fdroidserver.update.scan_apk({}, apkName, 'repo', knownapks, False)
267 # Don't care about the date added to the repo and relative apkName
270 # avoid AAPT application name bug
273 savepath = os.path.join('metadata', 'apk', apk['packageName'] + '.yaml')
274 # Uncomment to save APK metadata
275 # with open(savepath, 'w') as f:
276 # yaml.add_representer(fdroidserver.metadata.Build, _build_yaml_representer)
277 # yaml.dump(apk, f, default_flow_style=False)
279 with open(savepath, 'r') as f:
280 frompickle = yaml.load(f)
282 self.assertEqual(apk, frompickle)
284 def test_scan_invalid_apk(self):
285 os.chdir(os.path.join(localmodule, 'tests'))
286 if os.path.basename(os.getcwd()) != 'tests':
287 raise Exception('This test must be run in the "tests/" subdir')
290 fdroidserver.common.fill_config_defaults(config)
291 fdroidserver.common.config = config
292 fdroidserver.update.config = config
293 fdroidserver.update.options.delete_unknown = False
295 knownapks = fdroidserver.common.KnownApks()
296 apk = 'fake.ota.update_1234.zip' # this is not an APK, scanning should fail
297 (skip, apk, cachechanged) = fdroidserver.update.scan_apk({}, apk, 'repo', knownapks, False)
299 self.assertTrue(skip)
300 self.assertIsNone(apk)
301 self.assertFalse(cachechanged)
304 if __name__ == "__main__":
305 parser = optparse.OptionParser()
306 parser.add_option("-v", "--verbose", action="store_true", default=False,
307 help="Spew out even more information than normal")
308 (fdroidserver.common.options, args) = parser.parse_args(['--verbose'])
310 newSuite = unittest.TestSuite()
311 newSuite.addTest(unittest.makeSuite(UpdateTest))