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