implement plugin system review suggestsions

This commit is contained in:
Michael Pöhn 2020-06-10 18:15:38 +02:00
parent 77167e098e
commit a97b3ca4dd
2 changed files with 91 additions and 38 deletions

View file

@ -24,9 +24,9 @@ import fdroidserver.__main__
class MainTest(unittest.TestCase):
'''this tests fdroid.py'''
def test_commands(self):
def test_COMMANDS_check(self):
"""make sure the built in sub-command defs didn't change unintentionally"""
self.assertListEqual([x for x in fdroidserver.__main__.commands.keys()],
self.assertListEqual([x for x in fdroidserver.__main__.COMMANDS.keys()],
['build',
'init',
'publish',
@ -55,6 +55,8 @@ class MainTest(unittest.TestCase):
with mock.patch('fdroidserver.init.main', co):
with mock.patch('sys.exit') as exit_mock:
fdroidserver.__main__.main()
# note: this is sloppy, if `init` changes
# this might need changing too
exit_mock.assert_called_once_with(0)
co.assert_called_once_with()
@ -64,51 +66,102 @@ class MainTest(unittest.TestCase):
with mock.patch('fdroidserver.server.main', co):
with mock.patch('sys.exit') as exit_mock:
fdroidserver.__main__.main()
# note: this is sloppy, if `deploy` changes
# this might need changing too
exit_mock.assert_called_once_with(0)
co.assert_called_once_with()
def test_find_plugins(self):
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
with open('fdroid_testy.py', 'w') as f:
with open('fdroid_testy1.py', 'w') as f:
f.write(textwrap.dedent("""\
fdroid_summary = "ttt"
main = lambda: 'all good'"""))
with TmpPyPath(tmpdir):
plugins = fdroidserver.__main__.find_plugins()
self.assertIn('testy', plugins.keys())
self.assertEqual(plugins['testy']['summary'], 'ttt')
self.assertEqual(__import__(plugins['testy']['name'],
self.assertIn('testy1', plugins.keys())
self.assertEqual(plugins['testy1']['summary'], 'ttt')
self.assertEqual(__import__(plugins['testy1']['name'],
None,
None,
['testy'])
['testy1'])
.main(),
'all good')
def test_main_plugin_lambda(self):
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
with open('fdroid_testy.py', 'w') as f:
with open('fdroid_testy2.py', 'w') as f:
f.write(textwrap.dedent("""\
fdroid_summary = "ttt"
main = lambda: pritn('all good')"""))
main = lambda: print('all good')"""))
with TmpPyPath(tmpdir):
with mock.patch('sys.argv', ['', 'testy']):
with mock.patch('sys.argv', ['', 'testy2']):
with mock.patch('sys.exit') as exit_mock:
fdroidserver.__main__.main()
exit_mock.assert_called_once_with(0)
def test_main_plugin_def(self):
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
with open('fdroid_testy.py', 'w') as f:
with open('fdroid_testy3.py', 'w') as f:
f.write(textwrap.dedent("""\
fdroid_summary = "ttt"
def main():
pritn('all good')"""))
print('all good')"""))
with TmpPyPath(tmpdir):
with mock.patch('sys.argv', ['', 'testy']):
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,
@ -121,7 +174,7 @@ class MainTest(unittest.TestCase):
def test_preparse_plugin_lookup_summary_missing(self):
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
with open('fdroid_testy.py', 'w') as f:
with open('fdroid_testy6.py', 'w') as f:
f.write(textwrap.dedent("""\
main = lambda: print('all good')"""))
with TmpPyPath(tmpdir):
@ -134,7 +187,7 @@ class MainTest(unittest.TestCase):
def test_preparse_plugin_lookup_module_file(self):
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
with open('fdroid_testy.py', 'w') as f:
with open('fdroid_testy7.py', 'w') as f:
f.write(textwrap.dedent("""\
fdroid_summary = "ttt"
main = lambda: pritn('all good')"""))
@ -143,24 +196,24 @@ class MainTest(unittest.TestCase):
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_testy',
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_testy'))
with open('fdroid_testy/__main__.py', 'w') as f:
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_testy/__init__.py', 'w') as f:
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_testy',
self.assertDictEqual(d, {'name': 'fdroid_testy8',
'summary': 'ttt'})