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 test_scan_invalid_apk(self):
228 os.chdir(os.path.join(localmodule, 'tests'))
229 if os.path.basename(os.getcwd()) != 'tests':
230 raise Exception('This test must be run in the "tests/" subdir')
233 fdroidserver.common.fill_config_defaults(config)
234 fdroidserver.common.config = config
235 fdroidserver.update.config = config
236 fdroidserver.update.options.delete_unknown = False
238 knownapks = fdroidserver.common.KnownApks()
239 apk = 'fake.ota.update_1234.zip' # this is not an APK, scanning should fail
240 (skip, apk, cachechanged) = fdroidserver.update.scan_apk({}, apk, 'repo', knownapks, False)
242 self.assertTrue(skip)
243 self.assertIsNone(apk)
244 self.assertFalse(cachechanged)
247 if __name__ == "__main__":
248 parser = optparse.OptionParser()
249 parser.add_option("-v", "--verbose", action="store_true", default=False,
250 help="Spew out even more information than normal")
251 (fdroidserver.common.options, args) = parser.parse_args(['--verbose'])
253 newSuite = unittest.TestSuite()
254 newSuite.addTest(unittest.makeSuite(UpdateTest))