fdroid-server/tests/main.TestCase

281 lines
10 KiB
Plaintext
Raw Permalink Normal View History

2020-01-20 23:16:34 +01:00
#!/usr/bin/env python3
import inspect
import optparse
import os
import sys
import pkgutil
2020-01-23 04:13:14 +01:00
import textwrap
2020-01-20 23:16:34 +01:00
import unittest
2020-01-23 04:13:14 +01:00
import tempfile
2020-01-20 23:16:34 +01:00
from unittest import mock
2020-01-23 04:13:14 +01:00
from testcommon import TmpCwd, TmpPyPath
2020-01-20 23:16:34 +01:00
localmodule = os.path.realpath(
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
2020-01-20 23:16:34 +01:00
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
from fdroidserver import common
import fdroidserver.__main__
2020-01-23 04:13:14 +01:00
class MainTest(unittest.TestCase):
2020-01-20 23:16:34 +01:00
'''this tests fdroid.py'''
def test_COMMANDS_check(self):
2020-01-20 23:16:34 +01:00
"""make sure the built in sub-command defs didn't change unintentionally"""
self.assertListEqual(
[x for x in fdroidserver.__main__.COMMANDS.keys()],
[
'build',
'init',
'publish',
'gpgsign',
'update',
'deploy',
'verify',
'checkupdates',
'import',
'install',
'readmeta',
'rewritemeta',
'lint',
'scanner',
'signindex',
'btlog',
'signatures',
'nightly',
'mirror',
],
)
2020-01-20 23:16:34 +01:00
def test_call_init(self):
co = mock.Mock()
with mock.patch('sys.argv', ['', 'init', '-h']):
with mock.patch('fdroidserver.init.main', co):
2020-01-23 04:13:14 +01:00
with mock.patch('sys.exit') as exit_mock:
2020-01-20 23:16:34 +01:00
fdroidserver.__main__.main()
# note: this is sloppy, if `init` changes
# this might need changing too
2020-01-23 04:13:14 +01:00
exit_mock.assert_called_once_with(0)
2020-01-28 11:40:58 +01:00
co.assert_called_once_with()
2020-01-20 23:16:34 +01:00
def test_call_deploy(self):
co = mock.Mock()
with mock.patch('sys.argv', ['', 'deploy', '-h']):
with mock.patch('fdroidserver.deploy.main', co):
2020-01-23 04:13:14 +01:00
with mock.patch('sys.exit') as exit_mock:
2020-01-20 23:16:34 +01:00
fdroidserver.__main__.main()
# note: this is sloppy, if `deploy` changes
# this might need changing too
2020-01-23 04:13:14 +01:00
exit_mock.assert_called_once_with(0)
2020-01-28 11:40:58 +01:00
co.assert_called_once_with()
2020-01-20 23:16:34 +01:00
2020-01-23 04:13:14 +01:00
def test_find_plugins(self):
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
with open('fdroid_testy1.py', 'w') as f:
f.write(
textwrap.dedent(
"""\
2020-01-23 04:13:14 +01:00
fdroid_summary = "ttt"
main = lambda: 'all good'"""
)
)
2020-01-23 04:13:14 +01:00
with TmpPyPath(tmpdir):
plugins = fdroidserver.__main__.find_plugins()
self.assertIn('testy1', plugins.keys())
self.assertEqual(plugins['testy1']['summary'], 'ttt')
self.assertEqual(
__import__(
plugins['testy1']['name'], None, None, ['testy1']
).main(),
'all good',
)
2020-01-23 04:13:14 +01:00
def test_main_plugin_lambda(self):
2020-01-23 04:13:14 +01:00
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
with open('fdroid_testy2.py', 'w') as f:
f.write(
textwrap.dedent(
"""\
2020-01-23 04:13:14 +01:00
fdroid_summary = "ttt"
main = lambda: print('all good')"""
)
)
with TmpPyPath(tmpdir):
with mock.patch('sys.argv', ['', 'testy2']):
2020-01-29 13:08:43 +01:00
with mock.patch('sys.exit') as exit_mock:
fdroidserver.__main__.main()
exit_mock.assert_called_once_with(0)
2020-01-23 04:13:14 +01:00
def test_main_plugin_def(self):
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
with open('fdroid_testy3.py', 'w') as f:
f.write(
textwrap.dedent(
"""\
fdroid_summary = "ttt"
def main():
print('all good')"""
)
)
with TmpPyPath(tmpdir):
with mock.patch('sys.argv', ['', 'testy3']):
with mock.patch('sys.exit') as exit_mock:
fdroidserver.__main__.main()
exit_mock.assert_called_once_with(0)
def test_main_broken_plugin(self):
"""making sure broken plugins get their exceptions through"""
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
with open('fdroid_testy4.py', 'w') as f:
f.write(
textwrap.dedent(
"""\
fdroid_summary = "ttt"
def main():
raise Exception("this plugin is broken")"""
)
)
with TmpPyPath(tmpdir):
with mock.patch('sys.argv', ['', 'testy4']):
with self.assertRaisesRegex(Exception, "this plugin is broken"):
fdroidserver.__main__.main()
def test_main_malicious_plugin(self):
"""The purpose of this test is to make sure code in plugins
doesn't get executed unintentionally.
"""
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
with open('fdroid_testy5.py', 'w') as f:
f.write(
textwrap.dedent(
"""\
fdroid_summary = "ttt"
raise Exception("this plugin is malicious")
def main():
print("evil things")"""
)
)
with TmpPyPath(tmpdir):
with mock.patch('sys.argv', ['', 'lint']):
with mock.patch('sys.exit') as exit_mock:
fdroidserver.__main__.main()
# note: this is sloppy, if `lint` changes
# this might need changing too
exit_mock.assert_called_once_with(0)
def test_main_prevent_plugin_override(self):
"""making sure build-in subcommands cannot be overridden by plugins"""
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
with open('fdroid_signatures.py', 'w') as f:
f.write(
textwrap.dedent(
"""\
fdroid_summary = "ttt"
def main():
raise("plugin overrides don't get prevent!")"""
)
)
with TmpPyPath(tmpdir):
with mock.patch('sys.argv', ['', 'signatures']):
with mock.patch('sys.exit') as exit_mock:
fdroidserver.__main__.main()
# note: this is sloppy, if `signatures` changes
# this might need changing too
self.assertEqual(exit_mock.call_count, 2)
def test_preparse_plugin_lookup_bad_name(self):
self.assertRaises(
ValueError,
fdroidserver.__main__.preparse_plugin,
"some.package",
"/non/existent/module/path",
)
def test_preparse_plugin_lookup_bad_path(self):
self.assertRaises(
ValueError,
fdroidserver.__main__.preparse_plugin,
"fake_module_name",
"/non/existent/module/path",
)
def test_preparse_plugin_lookup_summary_missing(self):
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
with open('fdroid_testy6.py', 'w') as f:
f.write(
textwrap.dedent(
"""\
main = lambda: print('all good')"""
)
)
with TmpPyPath(tmpdir):
p = [x for x in pkgutil.iter_modules() if x[1].startswith('fdroid_')]
module_dir = p[0][0].path
module_name = p[0][1]
self.assertRaises(
NameError,
fdroidserver.__main__.preparse_plugin,
module_name,
module_dir,
)
def test_preparse_plugin_lookup_module_file(self):
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
with open('fdroid_testy7.py', 'w') as f:
f.write(
textwrap.dedent(
"""\
fdroid_summary = "ttt"
main = lambda: pritn('all good')"""
)
)
with TmpPyPath(tmpdir):
p = [x for x in pkgutil.iter_modules() if x[1].startswith('fdroid_')]
module_path = p[0][0].path
module_name = p[0][1]
d = fdroidserver.__main__.preparse_plugin(module_name, module_path)
self.assertDictEqual(d, {'name': 'fdroid_testy7', 'summary': 'ttt'})
def test_preparse_plugin_lookup_module_dir(self):
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
os.mkdir(os.path.join(tmpdir, 'fdroid_testy8'))
with open('fdroid_testy8/__main__.py', 'w') as f:
f.write(
textwrap.dedent(
"""\
fdroid_summary = "ttt"
main = lambda: print('all good')"""
)
)
with open('fdroid_testy8/__init__.py', 'w') as f:
pass
with TmpPyPath(tmpdir):
p = [x for x in pkgutil.iter_modules() if x[1].startswith('fdroid_')]
module_path = p[0][0].path
module_name = p[0][1]
d = fdroidserver.__main__.preparse_plugin(module_name, module_path)
self.assertDictEqual(d, {'name': 'fdroid_testy8', 'summary': 'ttt'})
2020-01-20 23:16:34 +01:00
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
parser = optparse.OptionParser()
parser.add_option(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
2020-01-20 23:16:34 +01:00
(common.options, args) = parser.parse_args(['--verbose'])
newSuite = unittest.TestSuite()
2020-01-23 04:13:14 +01:00
newSuite.addTest(unittest.makeSuite(MainTest))
2020-01-20 23:16:34 +01:00
unittest.main(failfast=False)