mirror of
				https://github.com/f-droid/fdroidserver.git
				synced 2025-11-04 14:30:30 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			229 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			229 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
#!/usr/bin/env python3
 | 
						|
 | 
						|
import inspect
 | 
						|
import optparse
 | 
						|
import os
 | 
						|
import sys
 | 
						|
import pkgutil
 | 
						|
import textwrap
 | 
						|
import unittest
 | 
						|
import tempfile
 | 
						|
from unittest import mock
 | 
						|
from testcommon import TmpCwd, TmpPyPath
 | 
						|
 | 
						|
localmodule = os.path.realpath(
 | 
						|
    os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..'))
 | 
						|
print('localmodule: ' + localmodule)
 | 
						|
if localmodule not in sys.path:
 | 
						|
    sys.path.insert(0, localmodule)
 | 
						|
 | 
						|
from fdroidserver import common
 | 
						|
import fdroidserver.__main__
 | 
						|
 | 
						|
 | 
						|
class MainTest(unittest.TestCase):
 | 
						|
    '''this tests fdroid.py'''
 | 
						|
 | 
						|
    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()],
 | 
						|
                             ['build',
 | 
						|
                              'init',
 | 
						|
                              'publish',
 | 
						|
                              'gpgsign',
 | 
						|
                              'update',
 | 
						|
                              'deploy',
 | 
						|
                              'verify',
 | 
						|
                              'checkupdates',
 | 
						|
                              'import',
 | 
						|
                              'install',
 | 
						|
                              'readmeta',
 | 
						|
                              'rewritemeta',
 | 
						|
                              'lint',
 | 
						|
                              'scanner',
 | 
						|
                              'stats',
 | 
						|
                              'signindex',
 | 
						|
                              'btlog',
 | 
						|
                              'signatures',
 | 
						|
                              'nightly',
 | 
						|
                              'mirror'])
 | 
						|
 | 
						|
    def test_call_init(self):
 | 
						|
        co = mock.Mock()
 | 
						|
        with mock.patch('sys.argv', ['', 'init', '-h']):
 | 
						|
            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()
 | 
						|
 | 
						|
    def test_call_deploy(self):
 | 
						|
        co = mock.Mock()
 | 
						|
        with mock.patch('sys.argv', ['', 'deploy', '-h']):
 | 
						|
            with mock.patch('fdroidserver.deploy.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_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('testy1', plugins.keys())
 | 
						|
                self.assertEqual(plugins['testy1']['summary'], 'ttt')
 | 
						|
                self.assertEqual(__import__(plugins['testy1']['name'],
 | 
						|
                                            None,
 | 
						|
                                            None,
 | 
						|
                                            ['testy1'])
 | 
						|
                                 .main(),
 | 
						|
                                 'all good')
 | 
						|
 | 
						|
    def test_main_plugin_lambda(self):
 | 
						|
        with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
 | 
						|
            with open('fdroid_testy2.py', 'w') as f:
 | 
						|
                f.write(textwrap.dedent("""\
 | 
						|
                        fdroid_summary = "ttt"
 | 
						|
                        main = lambda: print('all good')"""))
 | 
						|
            with TmpPyPath(tmpdir):
 | 
						|
                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_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'})
 | 
						|
 | 
						|
 | 
						|
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")
 | 
						|
    (common.options, args) = parser.parse_args(['--verbose'])
 | 
						|
 | 
						|
    newSuite = unittest.TestSuite()
 | 
						|
    newSuite.addTest(unittest.makeSuite(MainTest))
 | 
						|
    unittest.main(failfast=False)
 |