2017-06-23 21:58:46 +02:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
2018-02-27 12:09:54 +01:00
|
|
|
import logging
|
2017-06-23 21:58:46 +02:00
|
|
|
import os
|
|
|
|
import shutil
|
|
|
|
import tempfile
|
|
|
|
import unittest
|
2021-06-09 15:46:52 +08:00
|
|
|
from pathlib import Path
|
2017-06-23 21:58:46 +02:00
|
|
|
|
2024-12-18 11:17:52 +01:00
|
|
|
from .shared_test_code import mkdtemp
|
2024-09-05 02:10:08 +08:00
|
|
|
|
2017-06-23 21:58:46 +02:00
|
|
|
import fdroidserver.common
|
|
|
|
import fdroidserver.lint
|
2018-03-02 12:50:48 +01:00
|
|
|
import fdroidserver.metadata
|
2025-03-07 17:30:46 +01:00
|
|
|
from fdroidserver._yaml import config_dump
|
2024-11-19 20:36:41 +01:00
|
|
|
|
|
|
|
basedir = Path(__file__).parent
|
2017-06-23 21:58:46 +02:00
|
|
|
|
|
|
|
|
|
|
|
class LintTest(unittest.TestCase):
|
|
|
|
'''fdroidserver/lint.py'''
|
|
|
|
|
2018-02-27 12:09:54 +01:00
|
|
|
def setUp(self):
|
2024-11-19 20:36:41 +01:00
|
|
|
os.chdir(basedir)
|
2023-05-30 19:19:27 +02:00
|
|
|
fdroidserver.common.config = None
|
|
|
|
fdroidserver.lint.config = None
|
|
|
|
fdroidserver.lint.CATEGORIES_KEYS = None
|
|
|
|
self._td = mkdtemp()
|
|
|
|
self.testdir = self._td.name
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
self._td.cleanup()
|
2018-02-27 12:09:54 +01:00
|
|
|
|
2017-06-23 21:58:46 +02:00
|
|
|
def test_check_for_unsupported_metadata_files(self):
|
|
|
|
self.assertTrue(fdroidserver.lint.check_for_unsupported_metadata_files())
|
|
|
|
|
2024-11-19 20:36:41 +01:00
|
|
|
with tempfile.TemporaryDirectory() as testdir:
|
2021-06-09 15:46:52 +08:00
|
|
|
testdir = Path(testdir)
|
|
|
|
self.assertFalse(
|
|
|
|
fdroidserver.lint.check_for_unsupported_metadata_files(testdir)
|
|
|
|
)
|
|
|
|
shutil.copytree(
|
2024-11-19 20:36:41 +01:00
|
|
|
basedir / 'metadata',
|
2023-02-15 19:25:48 +00:00
|
|
|
testdir / 'metadata',
|
2021-06-09 15:46:52 +08:00
|
|
|
ignore=shutil.ignore_patterns('apk', 'dump', '*.json'),
|
|
|
|
)
|
|
|
|
self.assertFalse(
|
|
|
|
fdroidserver.lint.check_for_unsupported_metadata_files(testdir)
|
|
|
|
)
|
|
|
|
(testdir / 'metadata/org.adaway.json').write_text('placeholder')
|
|
|
|
self.assertTrue(
|
|
|
|
fdroidserver.lint.check_for_unsupported_metadata_files(testdir)
|
|
|
|
)
|
2017-06-23 21:58:46 +02:00
|
|
|
|
2018-02-27 12:09:54 +01:00
|
|
|
def test_forbidden_html_tags(self):
|
|
|
|
config = dict()
|
|
|
|
fdroidserver.common.fill_config_defaults(config)
|
|
|
|
fdroidserver.common.config = config
|
|
|
|
fdroidserver.lint.config = config
|
|
|
|
|
|
|
|
app = {
|
|
|
|
'Name': 'Bad App',
|
|
|
|
'Summary': 'We pwn you',
|
|
|
|
'Description': 'This way: <style><img src="</style><img src=x onerror=alert(1)//">',
|
|
|
|
}
|
|
|
|
|
|
|
|
anywarns = False
|
|
|
|
for warn in fdroidserver.lint.check_regexes(app):
|
|
|
|
anywarns = True
|
|
|
|
logging.debug(warn)
|
|
|
|
self.assertTrue(anywarns)
|
|
|
|
|
2019-09-30 13:07:49 +02:00
|
|
|
def test_source_urls(self):
|
|
|
|
config = dict()
|
|
|
|
fdroidserver.common.fill_config_defaults(config)
|
|
|
|
fdroidserver.common.config = config
|
|
|
|
fdroidserver.lint.config = config
|
|
|
|
|
|
|
|
app = {
|
|
|
|
'Name': 'My App',
|
|
|
|
'Summary': 'just a placeholder',
|
|
|
|
'Description': 'This app does all sorts of useful stuff',
|
|
|
|
}
|
|
|
|
good_urls = [
|
|
|
|
'https://github.com/Matteljay/mastermindy-android',
|
|
|
|
'https://gitlab.com/origin/master',
|
|
|
|
'https://gitlab.com/group/subgroup/masterthing',
|
|
|
|
'https://raw.githubusercontent.com/Seva-coder/Finder/HEAD/ChangeLog.txt',
|
|
|
|
'https://github.com/scoutant/blokish/blob/HEAD/README.md#changelog',
|
|
|
|
'https://git.ieval.ro/?p=fonbot.git;a=blob;f=Changes;hb=HEAD',
|
|
|
|
'https://htmlpreview.github.io/?https://github.com/YasuakiHonda/Maxima-on-Android-AS/blob/HEAD/app/src/main/assets/About_MoA/index.html',
|
|
|
|
'',
|
|
|
|
]
|
|
|
|
|
|
|
|
anywarns = False
|
|
|
|
for url in good_urls:
|
|
|
|
app['SourceCode'] = url
|
|
|
|
for warn in fdroidserver.lint.check_regexes(app):
|
|
|
|
anywarns = True
|
|
|
|
logging.debug(warn)
|
|
|
|
self.assertFalse(anywarns)
|
|
|
|
|
|
|
|
bad_urls = [
|
2019-09-30 13:08:58 +02:00
|
|
|
'github.com/my/proj',
|
2019-10-03 23:46:34 +02:00
|
|
|
'http://github.com/not/secure',
|
2019-09-30 13:08:58 +02:00
|
|
|
'https://github.com/foo/bar.git',
|
|
|
|
'https://gitlab.com/group/subgroup/project.git',
|
2019-09-30 13:07:49 +02:00
|
|
|
'https://raw.githubusercontent.com/Seva-coder/Finder/master/ChangeLog.txt',
|
|
|
|
'https://github.com/scoutant/blokish/blob/master/README.md#changelog',
|
2019-09-30 13:08:58 +02:00
|
|
|
'http://htmlpreview.github.io/?https://github.com/my/project/blob/HEAD/index.html',
|
2019-10-03 23:46:34 +02:00
|
|
|
'http://fdroid.gitlab.io/fdroid-website',
|
2019-09-30 13:07:49 +02:00
|
|
|
]
|
|
|
|
logging.debug('bad urls:')
|
|
|
|
for url in bad_urls:
|
2019-10-03 23:46:34 +02:00
|
|
|
anywarns = False
|
2019-09-30 13:07:49 +02:00
|
|
|
app['SourceCode'] = url
|
|
|
|
for warn in fdroidserver.lint.check_regexes(app):
|
|
|
|
anywarns = True
|
|
|
|
logging.debug(warn)
|
2019-10-03 23:46:34 +02:00
|
|
|
self.assertTrue(anywarns, url + " does not fail lint!")
|
2019-09-30 13:07:49 +02:00
|
|
|
|
2018-10-09 23:31:24 +02:00
|
|
|
def test_check_app_field_types(self):
|
|
|
|
config = dict()
|
|
|
|
fdroidserver.common.fill_config_defaults(config)
|
|
|
|
fdroidserver.common.config = config
|
|
|
|
fdroidserver.lint.config = config
|
|
|
|
|
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
app.id = 'fake.app'
|
|
|
|
app.Name = 'Bad App'
|
|
|
|
app.Summary = 'We pwn you'
|
|
|
|
app.Description = 'These are some back'
|
|
|
|
|
|
|
|
fields = {
|
|
|
|
'Categories': {
|
|
|
|
'good': [
|
2023-04-24 20:10:17 +02:00
|
|
|
['Sports & Health'],
|
2018-10-09 23:31:24 +02:00
|
|
|
['Multimedia', 'Graphics'],
|
|
|
|
],
|
|
|
|
'bad': [
|
|
|
|
'Science & Education',
|
|
|
|
'Multimedia,Graphics',
|
|
|
|
],
|
|
|
|
},
|
2018-10-10 12:19:09 +02:00
|
|
|
'WebSite': {
|
|
|
|
'good': [
|
|
|
|
'https://homepage.com',
|
|
|
|
],
|
|
|
|
'bad': [
|
|
|
|
[],
|
2021-06-09 15:46:52 +08:00
|
|
|
[
|
|
|
|
'nope',
|
|
|
|
],
|
2018-10-10 12:19:09 +02:00
|
|
|
29,
|
|
|
|
],
|
|
|
|
},
|
2018-10-09 23:31:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for field, values in fields.items():
|
|
|
|
for bad in values['bad']:
|
|
|
|
anywarns = False
|
|
|
|
app[field] = bad
|
|
|
|
for warn in fdroidserver.lint.check_app_field_types(app):
|
|
|
|
anywarns = True
|
|
|
|
logging.debug(warn)
|
|
|
|
self.assertTrue(anywarns)
|
|
|
|
|
|
|
|
for good in values['good']:
|
|
|
|
anywarns = False
|
|
|
|
app[field] = good
|
|
|
|
for warn in fdroidserver.lint.check_app_field_types(app):
|
|
|
|
anywarns = True
|
|
|
|
logging.debug(warn)
|
|
|
|
self.assertFalse(anywarns)
|
|
|
|
|
2018-03-02 12:50:48 +01:00
|
|
|
def test_check_vercode_operation(self):
|
|
|
|
config = dict()
|
|
|
|
fdroidserver.common.fill_config_defaults(config)
|
|
|
|
fdroidserver.common.config = config
|
|
|
|
fdroidserver.lint.config = config
|
|
|
|
|
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
app.Name = 'Bad App'
|
|
|
|
app.Summary = 'We pwn you'
|
|
|
|
app.Description = 'These are some back'
|
|
|
|
|
|
|
|
good_fields = [
|
|
|
|
'6%c',
|
|
|
|
'%c - 1',
|
|
|
|
'%c + 10',
|
|
|
|
'%c*10',
|
|
|
|
'%c*10 + 3',
|
|
|
|
'%c*10 + 8',
|
|
|
|
'%c + 2 ',
|
|
|
|
'%c + 3',
|
|
|
|
'%c + 7',
|
|
|
|
]
|
|
|
|
bad_fields = [
|
|
|
|
'open("/etc/passwd")',
|
|
|
|
'%C + 1',
|
|
|
|
'%%c * 123',
|
|
|
|
'123 + %%',
|
|
|
|
'%c % 7',
|
|
|
|
]
|
|
|
|
|
|
|
|
anywarns = False
|
|
|
|
for good in good_fields:
|
2022-10-27 19:11:37 +08:00
|
|
|
app.VercodeOperation = [good]
|
2018-03-02 12:50:48 +01:00
|
|
|
for warn in fdroidserver.lint.check_vercode_operation(app):
|
|
|
|
anywarns = True
|
|
|
|
logging.debug(warn)
|
|
|
|
self.assertFalse(anywarns)
|
|
|
|
|
|
|
|
for bad in bad_fields:
|
|
|
|
anywarns = False
|
2022-10-27 19:11:37 +08:00
|
|
|
app.VercodeOperation = [bad]
|
2018-03-02 12:50:48 +01:00
|
|
|
for warn in fdroidserver.lint.check_vercode_operation(app):
|
|
|
|
anywarns = True
|
|
|
|
logging.debug(warn)
|
|
|
|
self.assertTrue(anywarns)
|
|
|
|
|
2019-10-02 22:14:09 +02:00
|
|
|
def test_check_license_tag_no_custom_pass(self):
|
|
|
|
config = dict()
|
|
|
|
fdroidserver.common.fill_config_defaults(config)
|
|
|
|
fdroidserver.common.config = config
|
|
|
|
fdroidserver.lint.config = config
|
|
|
|
|
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
app.License = "GPL-3.0-or-later"
|
|
|
|
|
|
|
|
anywarns = False
|
|
|
|
for warn in fdroidserver.lint.check_license_tag(app):
|
|
|
|
anywarns = True
|
|
|
|
logging.debug(warn)
|
|
|
|
self.assertFalse(anywarns)
|
|
|
|
|
|
|
|
def test_check_license_tag_no_custom_fail(self):
|
|
|
|
config = dict()
|
|
|
|
fdroidserver.common.fill_config_defaults(config)
|
|
|
|
fdroidserver.common.config = config
|
|
|
|
fdroidserver.lint.config = config
|
|
|
|
|
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
app.License = "Adobe-2006"
|
|
|
|
|
|
|
|
anywarns = False
|
|
|
|
for warn in fdroidserver.lint.check_license_tag(app):
|
|
|
|
anywarns = True
|
|
|
|
logging.debug(warn)
|
|
|
|
self.assertTrue(anywarns)
|
|
|
|
|
|
|
|
def test_check_license_tag_with_custom_pass(self):
|
|
|
|
config = dict()
|
|
|
|
fdroidserver.common.fill_config_defaults(config)
|
|
|
|
fdroidserver.common.config = config
|
|
|
|
fdroidserver.lint.config = config
|
|
|
|
config['lint_licenses'] = ['fancy-license', 'GPL-3.0-or-later']
|
|
|
|
|
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
app.License = "fancy-license"
|
|
|
|
|
|
|
|
anywarns = False
|
|
|
|
for warn in fdroidserver.lint.check_license_tag(app):
|
|
|
|
anywarns = True
|
|
|
|
logging.debug(warn)
|
|
|
|
self.assertFalse(anywarns)
|
|
|
|
|
|
|
|
def test_check_license_tag_with_custom_fail(self):
|
|
|
|
config = dict()
|
|
|
|
fdroidserver.common.fill_config_defaults(config)
|
|
|
|
fdroidserver.common.config = config
|
|
|
|
fdroidserver.lint.config = config
|
|
|
|
config['lint_licenses'] = ['fancy-license', 'GPL-3.0-or-later']
|
|
|
|
|
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
app.License = "Apache-2.0"
|
|
|
|
|
|
|
|
anywarns = False
|
|
|
|
for warn in fdroidserver.lint.check_license_tag(app):
|
|
|
|
anywarns = True
|
|
|
|
logging.debug(warn)
|
|
|
|
self.assertTrue(anywarns)
|
|
|
|
|
|
|
|
def test_check_license_tag_with_custom_empty(self):
|
|
|
|
config = dict()
|
|
|
|
fdroidserver.common.fill_config_defaults(config)
|
|
|
|
fdroidserver.common.config = config
|
|
|
|
fdroidserver.lint.config = config
|
|
|
|
config['lint_licenses'] = []
|
|
|
|
|
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
app.License = "Apache-2.0"
|
|
|
|
|
|
|
|
anywarns = False
|
|
|
|
for warn in fdroidserver.lint.check_license_tag(app):
|
|
|
|
anywarns = True
|
|
|
|
logging.debug(warn)
|
|
|
|
self.assertTrue(anywarns)
|
|
|
|
|
|
|
|
def test_check_license_tag_disabled(self):
|
|
|
|
config = dict()
|
|
|
|
fdroidserver.common.fill_config_defaults(config)
|
|
|
|
fdroidserver.common.config = config
|
|
|
|
fdroidserver.lint.config = config
|
|
|
|
config['lint_licenses'] = None
|
|
|
|
|
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
app.License = "Apache-2.0"
|
|
|
|
|
|
|
|
anywarns = False
|
|
|
|
for warn in fdroidserver.lint.check_license_tag(app):
|
|
|
|
anywarns = True
|
|
|
|
logging.debug(warn)
|
|
|
|
self.assertFalse(anywarns)
|
|
|
|
|
2023-05-30 19:19:27 +02:00
|
|
|
def test_check_categories_in_config(self):
|
2024-11-19 20:36:41 +01:00
|
|
|
fdroidserver.lint.config = {
|
|
|
|
fdroidserver.common.CATEGORIES_CONFIG_NAME: ['InConfig']
|
|
|
|
}
|
2023-05-30 19:19:27 +02:00
|
|
|
fdroidserver.lint.load_categories_config()
|
|
|
|
app = fdroidserver.metadata.App({'Categories': ['InConfig']})
|
|
|
|
self.assertEqual(0, len(list(fdroidserver.lint.check_categories(app))))
|
|
|
|
|
|
|
|
def test_check_categories_not_in_config(self):
|
|
|
|
fdroidserver.lint.config = dict()
|
|
|
|
fdroidserver.lint.load_categories_config()
|
|
|
|
app = fdroidserver.metadata.App({'Categories': ['NotInConfig']})
|
|
|
|
self.assertEqual(1, len(list(fdroidserver.lint.check_categories(app))))
|
|
|
|
|
|
|
|
def test_check_categories_empty_is_error(self):
|
2024-11-19 20:36:41 +01:00
|
|
|
fdroidserver.lint.config = {fdroidserver.common.CATEGORIES_CONFIG_NAME: []}
|
2023-05-30 19:19:27 +02:00
|
|
|
fdroidserver.lint.load_categories_config()
|
|
|
|
app = fdroidserver.metadata.App({'Categories': ['something']})
|
|
|
|
self.assertEqual(1, len(list(fdroidserver.lint.check_categories(app))))
|
|
|
|
|
|
|
|
def test_check_categories_old_hardcoded_not_defined(self):
|
2024-11-19 20:36:41 +01:00
|
|
|
fdroidserver.lint.config = {
|
|
|
|
fdroidserver.common.CATEGORIES_CONFIG_NAME: ['foo', 'bar']
|
|
|
|
}
|
2023-05-30 19:19:27 +02:00
|
|
|
fdroidserver.lint.load_categories_config()
|
|
|
|
app = fdroidserver.metadata.App({'Categories': ['Writing']})
|
|
|
|
self.assertEqual(1, len(list(fdroidserver.lint.check_categories(app))))
|
|
|
|
|
|
|
|
def test_check_categories_from_config_yml(self):
|
|
|
|
"""In config.yml, categories is a list."""
|
|
|
|
os.chdir(self.testdir)
|
2025-02-26 18:16:06 +01:00
|
|
|
fdroidserver.common.write_config_file('categories: [foo, bar]\n')
|
2023-05-30 19:19:27 +02:00
|
|
|
fdroidserver.lint.config = fdroidserver.common.read_config()
|
|
|
|
fdroidserver.lint.load_categories_config()
|
|
|
|
self.assertEqual(fdroidserver.lint.CATEGORIES_KEYS, ['foo', 'bar'])
|
|
|
|
app = fdroidserver.metadata.App({'Categories': ['bar']})
|
|
|
|
self.assertEqual(0, len(list(fdroidserver.lint.check_categories(app))))
|
|
|
|
|
|
|
|
def test_check_categories_from_config_categories_yml(self):
|
|
|
|
"""In config/categories.yml, categories is a localized STRINGMAP dict."""
|
|
|
|
os.chdir(self.testdir)
|
|
|
|
os.mkdir('config')
|
|
|
|
Path('config/categories.yml').write_text('{foo: {name: foo}, bar: {name: bar}}')
|
|
|
|
fdroidserver.lint.config = fdroidserver.common.read_config()
|
|
|
|
fdroidserver.lint.load_categories_config()
|
|
|
|
self.assertEqual(fdroidserver.lint.CATEGORIES_KEYS, ['foo', 'bar'])
|
|
|
|
app = fdroidserver.metadata.App({'Categories': ['bar']})
|
|
|
|
self.assertEqual(0, len(list(fdroidserver.lint.check_categories(app))))
|
|
|
|
|
2023-12-07 17:38:34 +01:00
|
|
|
def test_lint_config_basic_mirrors_yml(self):
|
|
|
|
os.chdir(self.testdir)
|
|
|
|
with Path('mirrors.yml').open('w') as fp:
|
2025-03-07 17:30:46 +01:00
|
|
|
config_dump([{'url': 'https://example.com/fdroid/repo'}], fp)
|
2023-12-07 17:38:34 +01:00
|
|
|
self.assertTrue(fdroidserver.lint.lint_config('mirrors.yml'))
|
|
|
|
|
|
|
|
def test_lint_config_mirrors_yml_kenya_countryCode(self):
|
|
|
|
os.chdir(self.testdir)
|
|
|
|
with Path('mirrors.yml').open('w') as fp:
|
2025-03-07 17:30:46 +01:00
|
|
|
config_dump(
|
2025-03-07 14:13:21 +01:00
|
|
|
[{'url': 'https://foo.com/fdroid/repo', 'countryCode': 'KE'}], fp
|
|
|
|
)
|
2023-12-07 17:38:34 +01:00
|
|
|
self.assertTrue(fdroidserver.lint.lint_config('mirrors.yml'))
|
|
|
|
|
|
|
|
def test_lint_config_mirrors_yml_invalid_countryCode(self):
|
|
|
|
"""WV is "indeterminately reserved" so it should never be used."""
|
|
|
|
os.chdir(self.testdir)
|
|
|
|
with Path('mirrors.yml').open('w') as fp:
|
2025-03-07 17:30:46 +01:00
|
|
|
config_dump(
|
2025-03-07 14:13:21 +01:00
|
|
|
[{'url': 'https://foo.com/fdroid/repo', 'countryCode': 'WV'}], fp
|
|
|
|
)
|
2023-12-07 17:38:34 +01:00
|
|
|
self.assertFalse(fdroidserver.lint.lint_config('mirrors.yml'))
|
|
|
|
|
|
|
|
def test_lint_config_mirrors_yml_alpha3_countryCode(self):
|
|
|
|
"""Only ISO 3166-1 alpha 2 are supported"""
|
|
|
|
os.chdir(self.testdir)
|
|
|
|
with Path('mirrors.yml').open('w') as fp:
|
2025-03-07 17:30:46 +01:00
|
|
|
config_dump(
|
2025-03-07 14:13:21 +01:00
|
|
|
[{'url': 'https://de.com/fdroid/repo', 'countryCode': 'DEU'}], fp
|
|
|
|
)
|
2023-12-07 17:38:34 +01:00
|
|
|
self.assertFalse(fdroidserver.lint.lint_config('mirrors.yml'))
|
|
|
|
|
|
|
|
def test_lint_config_mirrors_yml_one_invalid_countryCode(self):
|
|
|
|
"""WV is "indeterminately reserved" so it should never be used."""
|
|
|
|
os.chdir(self.testdir)
|
|
|
|
with Path('mirrors.yml').open('w') as fp:
|
2025-03-07 17:30:46 +01:00
|
|
|
config_dump(
|
2023-12-07 17:38:34 +01:00
|
|
|
[
|
|
|
|
{'url': 'https://bar.com/fdroid/repo', 'countryCode': 'BA'},
|
|
|
|
{'url': 'https://foo.com/fdroid/repo', 'countryCode': 'FO'},
|
|
|
|
{'url': 'https://wv.com/fdroid/repo', 'countryCode': 'WV'},
|
|
|
|
],
|
|
|
|
fp,
|
|
|
|
)
|
|
|
|
self.assertFalse(fdroidserver.lint.lint_config('mirrors.yml'))
|
|
|
|
|
|
|
|
def test_lint_config_bad_mirrors_yml_dict(self):
|
|
|
|
os.chdir(self.testdir)
|
|
|
|
Path('mirrors.yml').write_text('baz: [foo, bar]\n')
|
|
|
|
with self.assertRaises(TypeError):
|
|
|
|
fdroidserver.lint.lint_config('mirrors.yml')
|
|
|
|
|
|
|
|
def test_lint_config_bad_mirrors_yml_float(self):
|
|
|
|
os.chdir(self.testdir)
|
|
|
|
Path('mirrors.yml').write_text('1.0\n')
|
|
|
|
with self.assertRaises(TypeError):
|
|
|
|
fdroidserver.lint.lint_config('mirrors.yml')
|
|
|
|
|
|
|
|
def test_lint_config_bad_mirrors_yml_int(self):
|
|
|
|
os.chdir(self.testdir)
|
|
|
|
Path('mirrors.yml').write_text('1\n')
|
|
|
|
with self.assertRaises(TypeError):
|
|
|
|
fdroidserver.lint.lint_config('mirrors.yml')
|
|
|
|
|
|
|
|
def test_lint_config_bad_mirrors_yml_str(self):
|
|
|
|
os.chdir(self.testdir)
|
|
|
|
Path('mirrors.yml').write_text('foo\n')
|
|
|
|
with self.assertRaises(TypeError):
|
|
|
|
fdroidserver.lint.lint_config('mirrors.yml')
|
|
|
|
|
2024-09-05 02:10:08 +08:00
|
|
|
def test_lint_invalid_config_keys(self):
|
|
|
|
os.chdir(self.testdir)
|
2025-02-26 18:16:06 +01:00
|
|
|
os.mkdir('config')
|
|
|
|
config_yml = fdroidserver.common.CONFIG_FILE
|
|
|
|
with open(f'config/{config_yml}', 'w', encoding='utf-8') as fp:
|
|
|
|
fp.write('repo:\n invalid_key: test\n')
|
|
|
|
self.assertFalse(fdroidserver.lint.lint_config(f'config/{config_yml}'))
|
2024-09-05 02:10:08 +08:00
|
|
|
|
|
|
|
def test_lint_invalid_localized_config_keys(self):
|
|
|
|
os.chdir(self.testdir)
|
|
|
|
Path('config/en').mkdir(parents=True)
|
2025-02-24 16:53:41 +01:00
|
|
|
Path('config/en/antiFeatures.yml').write_text('NonFreeNet:\n icon: test.png\n')
|
2024-09-05 02:10:08 +08:00
|
|
|
self.assertFalse(fdroidserver.lint.lint_config('config/en/antiFeatures.yml'))
|
|
|
|
|
2024-05-07 10:57:55 +02:00
|
|
|
def test_check_certificate_pinned_binaries_empty(self):
|
|
|
|
fdroidserver.common.config = {}
|
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
app.AllowedAPKSigningKeys = [
|
|
|
|
'a40da80a59d170caa950cf15c18c454d47a39b26989d8b640ecd745ba71bf5dc'
|
|
|
|
]
|
|
|
|
self.assertEqual(
|
|
|
|
[],
|
|
|
|
list(fdroidserver.lint.check_certificate_pinned_binaries(app)),
|
|
|
|
"when the config is empty, any signing key should be allowed",
|
|
|
|
)
|
|
|
|
|
|
|
|
def test_lint_known_debug_keys_no_match(self):
|
|
|
|
fdroidserver.common.config = {
|
|
|
|
"apk_signing_key_block_list": "a40da80a59d170caa950cf15c18c454d47a39b26989d8b640ecd745ba71bf5dc"
|
|
|
|
}
|
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
app.AllowedAPKSigningKeys = [
|
|
|
|
'2fd4fd5f54babba4bcb21237809bb653361d0d2583c80964ec89b28a26e9539e'
|
|
|
|
]
|
|
|
|
self.assertEqual(
|
|
|
|
[],
|
|
|
|
list(fdroidserver.lint.check_certificate_pinned_binaries(app)),
|
|
|
|
"A signing key that does not match one in the config should be allowed",
|
|
|
|
)
|
|
|
|
|
2024-05-03 20:00:14 +08:00
|
|
|
def test_lint_known_debug_keys(self):
|
2024-05-07 13:19:57 +02:00
|
|
|
fdroidserver.common.config = {
|
|
|
|
'apk_signing_key_block_list': 'a40da80a59d170caa950cf15c18c454d47a39b26989d8b640ecd745ba71bf5dc'
|
|
|
|
}
|
2024-05-03 20:00:14 +08:00
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
app.AllowedAPKSigningKeys = [
|
|
|
|
'a40da80a59d170caa950cf15c18c454d47a39b26989d8b640ecd745ba71bf5dc'
|
|
|
|
]
|
|
|
|
for warn in fdroidserver.lint.check_certificate_pinned_binaries(app):
|
|
|
|
anywarns = True
|
|
|
|
logging.debug(warn)
|
|
|
|
self.assertTrue(anywarns)
|
|
|
|
|
2017-06-23 21:58:46 +02:00
|
|
|
|
2023-04-24 20:10:17 +02:00
|
|
|
class LintAntiFeaturesTest(unittest.TestCase):
|
|
|
|
def setUp(self):
|
2024-11-19 20:36:41 +01:00
|
|
|
os.chdir(basedir)
|
2023-04-24 20:10:17 +02:00
|
|
|
fdroidserver.common.config = dict()
|
2023-05-30 19:19:27 +02:00
|
|
|
fdroidserver.lint.ANTIFEATURES_KEYS = None
|
2023-04-24 20:10:17 +02:00
|
|
|
fdroidserver.lint.load_antiFeatures_config()
|
|
|
|
|
|
|
|
def test_check_antiFeatures_empty(self):
|
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
self.assertEqual([], list(fdroidserver.lint.check_antiFeatures(app)))
|
|
|
|
|
|
|
|
def test_check_antiFeatures_empty_AntiFeatures(self):
|
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
app['AntiFeatures'] = []
|
|
|
|
self.assertEqual([], list(fdroidserver.lint.check_antiFeatures(app)))
|
|
|
|
|
|
|
|
def test_check_antiFeatures(self):
|
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
app['AntiFeatures'] = ['Ads', 'UpstreamNonFree']
|
|
|
|
self.assertEqual([], list(fdroidserver.lint.check_antiFeatures(app)))
|
|
|
|
|
|
|
|
def test_check_antiFeatures_fails_one(self):
|
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
app['AntiFeatures'] = ['Ad']
|
|
|
|
self.assertEqual(1, len(list(fdroidserver.lint.check_antiFeatures(app))))
|
|
|
|
|
|
|
|
def test_check_antiFeatures_fails_many(self):
|
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
app['AntiFeatures'] = ['Adss', 'Tracker', 'NoSourceSince', 'FAKE', 'NonFree']
|
|
|
|
self.assertEqual(4, len(list(fdroidserver.lint.check_antiFeatures(app))))
|
|
|
|
|
|
|
|
def test_check_antiFeatures_build_empty(self):
|
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
app['Builds'] = [{'antifeatures': []}]
|
|
|
|
self.assertEqual([], list(fdroidserver.lint.check_antiFeatures(app)))
|
|
|
|
|
|
|
|
def test_check_antiFeatures_build(self):
|
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
app['Builds'] = [{'antifeatures': ['Tracking']}]
|
|
|
|
self.assertEqual(0, len(list(fdroidserver.lint.check_antiFeatures(app))))
|
|
|
|
|
|
|
|
def test_check_antiFeatures_build_fail(self):
|
|
|
|
app = fdroidserver.metadata.App()
|
|
|
|
app['Builds'] = [{'antifeatures': ['Ads', 'Tracker']}]
|
|
|
|
self.assertEqual(1, len(list(fdroidserver.lint.check_antiFeatures(app))))
|
2025-02-22 23:27:24 +01:00
|
|
|
|
|
|
|
|
|
|
|
class ConfigYmlTest(LintTest):
|
|
|
|
def setUp(self):
|
|
|
|
super().setUp()
|
2025-02-26 18:16:06 +01:00
|
|
|
self.config_yml = Path(self.testdir) / fdroidserver.common.CONFIG_FILE
|
2025-02-22 23:27:24 +01:00
|
|
|
|
|
|
|
def test_config_yml_int(self):
|
|
|
|
self.config_yml.write_text('repo_maxage: 1\n')
|
|
|
|
self.assertTrue(fdroidserver.lint.lint_config(self.config_yml))
|
|
|
|
|
|
|
|
def test_config_yml_int_bad(self):
|
|
|
|
self.config_yml.write_text('repo_maxage: "1"\n')
|
|
|
|
self.assertFalse(fdroidserver.lint.lint_config(self.config_yml))
|
|
|
|
|
|
|
|
def test_config_yml_str(self):
|
|
|
|
self.config_yml.write_text('sdk_path: /opt/android-sdk\n')
|
|
|
|
self.assertTrue(fdroidserver.lint.lint_config(self.config_yml))
|
|
|
|
|
|
|
|
def test_config_yml_str_dict(self):
|
|
|
|
self.config_yml.write_text('sdk_path: {env: ANDROID_HOME}\n')
|
|
|
|
self.assertTrue(fdroidserver.lint.lint_config(self.config_yml))
|
|
|
|
|
|
|
|
def test_config_yml_str_bad(self):
|
|
|
|
self.config_yml.write_text('sdk_path: 1.0\n')
|
|
|
|
self.assertFalse(fdroidserver.lint.lint_config(self.config_yml))
|
|
|
|
|
|
|
|
def test_config_yml_bool(self):
|
|
|
|
self.config_yml.write_text("deploy_process_logs: true\n")
|
|
|
|
self.assertTrue(fdroidserver.lint.lint_config(self.config_yml))
|
|
|
|
|
|
|
|
def test_config_yml_bool_bad(self):
|
|
|
|
self.config_yml.write_text('deploy_process_logs: 2342fe23\n')
|
|
|
|
self.assertFalse(fdroidserver.lint.lint_config(self.config_yml))
|
|
|
|
|
|
|
|
def test_config_yml_dict(self):
|
|
|
|
self.config_yml.write_text("keyaliases: {com.example: '@com.foo'}\n")
|
|
|
|
self.assertTrue(fdroidserver.lint.lint_config(self.config_yml))
|
|
|
|
|
|
|
|
def test_config_yml_dict_bad(self):
|
|
|
|
self.config_yml.write_text('keyaliases: 2342fe23\n')
|
|
|
|
self.assertFalse(fdroidserver.lint.lint_config(self.config_yml))
|
|
|
|
|
|
|
|
def test_config_yml_bad_key_name(self):
|
|
|
|
self.config_yml.write_text('keyalias: 2342fe23\n')
|
|
|
|
self.assertFalse(fdroidserver.lint.lint_config(self.config_yml))
|
|
|
|
|
|
|
|
def test_config_yml_bad_value_for_all_keys(self):
|
|
|
|
"""Check all config keys with a bad value."""
|
|
|
|
for key in fdroidserver.lint.check_config_keys:
|
|
|
|
if key in fdroidserver.lint.bool_keys:
|
|
|
|
value = 'foobar'
|
|
|
|
else:
|
|
|
|
value = 'false'
|
|
|
|
self.config_yml.write_text(f'{key}: {value}\n')
|
|
|
|
self.assertFalse(
|
|
|
|
fdroidserver.lint.lint_config(self.config_yml),
|
|
|
|
f'{key} should fail on value of "{value}"',
|
|
|
|
)
|