--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-admin-commands.py Wed Jan 25 15:34:27 2023 +0100
@@ -0,0 +1,399 @@
+# Test admin commands
+
+import functools
+import unittest
+from mercurial.i18n import _
+from mercurial import error, ui as uimod
+from mercurial import registrar
+from mercurial.admin import verify
+
+
+class TestAdminVerifyFindChecks(unittest.TestCase):
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.ui = uimod.ui.load()
+ self.repo = b"fake-repo"
+
+ def cleanup_table(self):
+ self.table = {}
+ self.alias_table = {}
+ self.pyramid = {}
+
+ self.addCleanup(cleanup_table, self)
+
+ def setUp(self):
+ self.table = {}
+ self.alias_table = {}
+ self.pyramid = {}
+ check = registrar.verify_check(self.table, self.alias_table)
+
+ # mock some fake check method for tests purpose
+ @check(
+ b"test.dummy",
+ alias=b"dummy",
+ options=[],
+ )
+ def check_dummy(ui, repo, **options):
+ return options
+
+ @check(
+ b"test.fake",
+ alias=b"fake",
+ options=[
+ (b'a', False, _(b'a boolean value (default: False)')),
+ (b'b', True, _(b'a boolean value (default: True)')),
+ (b'c', [], _(b'a list')),
+ ],
+ )
+ def check_fake(ui, repo, **options):
+ return options
+
+ # alias in the middle of a hierarchy
+ check(
+ b"test.noop",
+ alias=b"noop",
+ options=[],
+ )(verify.noop_func)
+
+ @check(
+ b"test.noop.deeper",
+ alias=b"deeper",
+ options=[
+ (b'y', True, _(b'a boolean value (default: True)')),
+ (b'z', [], _(b'a list')),
+ ],
+ )
+ def check_noop_deeper(ui, repo, **options):
+ return options
+
+ # args wrapper utilities
+ def find_checks(self, name):
+ return verify.find_checks(
+ name=name,
+ table=self.table,
+ alias_table=self.alias_table,
+ full_pyramid=self.pyramid,
+ )
+
+ def pass_options(self, checks, options):
+ return verify.pass_options(
+ self.ui,
+ checks,
+ options,
+ table=self.table,
+ alias_table=self.alias_table,
+ full_pyramid=self.pyramid,
+ )
+
+ def get_checks(self, names, options):
+ return verify.get_checks(
+ self.repo,
+ self.ui,
+ names=names,
+ options=options,
+ table=self.table,
+ alias_table=self.alias_table,
+ full_pyramid=self.pyramid,
+ )
+
+ # tests find_checks
+ def test_find_checks_empty_name(self):
+ with self.assertRaises(error.InputError):
+ self.find_checks(name=b"")
+
+ def test_find_checks_wrong_name(self):
+ with self.assertRaises(error.InputError):
+ self.find_checks(name=b"unknown")
+
+ def test_find_checks_dummy(self):
+ name = b"test.dummy"
+ found = self.find_checks(name=name)
+ self.assertEqual(len(found), 1)
+ self.assertIn(name, found)
+ meth = found[name]
+ self.assertTrue(callable(meth))
+ self.assertEqual(len(meth.options), 0)
+
+ def test_find_checks_fake(self):
+ name = b"test.fake"
+ found = self.find_checks(name=name)
+ self.assertEqual(len(found), 1)
+ self.assertIn(name, found)
+ meth = found[name]
+ self.assertTrue(callable(meth))
+ self.assertEqual(len(meth.options), 3)
+
+ def test_find_checks_noop(self):
+ name = b"test.noop.deeper"
+ found = self.find_checks(name=name)
+ self.assertEqual(len(found), 1)
+ self.assertIn(name, found)
+ meth = found[name]
+ self.assertTrue(callable(meth))
+ self.assertEqual(len(meth.options), 2)
+
+ def test_find_checks_from_aliases(self):
+ found = self.find_checks(name=b"dummy")
+ self.assertEqual(len(found), 1)
+ self.assertIn(b"test.dummy", found)
+
+ found = self.find_checks(name=b"fake")
+ self.assertEqual(len(found), 1)
+ self.assertIn(b"test.fake", found)
+
+ found = self.find_checks(name=b"deeper")
+ self.assertEqual(len(found), 1)
+ self.assertIn(b"test.noop.deeper", found)
+
+ def test_find_checks_from_root(self):
+ found = self.find_checks(name=b"test")
+ self.assertEqual(len(found), 3)
+ self.assertIn(b"test.dummy", found)
+ self.assertIn(b"test.fake", found)
+ self.assertIn(b"test.noop.deeper", found)
+
+ def test_find_checks_from_intermediate(self):
+ found = self.find_checks(name=b"test.noop")
+ self.assertEqual(len(found), 1)
+ self.assertIn(b"test.noop.deeper", found)
+
+ def test_find_checks_from_parent_dot_name(self):
+ found = self.find_checks(name=b"noop.deeper")
+ self.assertEqual(len(found), 1)
+ self.assertIn(b"test.noop.deeper", found)
+
+ # tests pass_options
+ def test_pass_options_no_checks_no_options(self):
+ checks = {}
+ options = []
+
+ with self.assertRaises(error.Error):
+ self.pass_options(checks=checks, options=options)
+
+ def test_pass_options_fake_empty_options(self):
+ checks = self.find_checks(name=b"test.fake")
+ funcs = {
+ n: functools.partial(f, self.ui, self.repo)
+ for n, f in checks.items()
+ }
+ options = []
+ # should end with default options
+ expected_options = {"a": False, "b": True, "c": []}
+ func = self.pass_options(checks=funcs, options=options)
+
+ self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
+
+ def test_pass_options_fake_non_existing_options(self):
+ checks = self.find_checks(name=b"test.fake")
+ funcs = {
+ n: functools.partial(f, self.ui, self.repo)
+ for n, f in checks.items()
+ }
+
+ with self.assertRaises(error.InputError):
+ options = [b"test.fake:boom=yes"]
+ self.pass_options(checks=funcs, options=options)
+
+ def test_pass_options_fake_unrelated_options(self):
+ checks = self.find_checks(name=b"test.fake")
+ funcs = {
+ n: functools.partial(f, self.ui, self.repo)
+ for n, f in checks.items()
+ }
+ options = [b"test.noop.deeper:y=yes"]
+
+ with self.assertRaises(error.InputError):
+ self.pass_options(checks=funcs, options=options)
+
+ def test_pass_options_fake_set_option(self):
+ checks = self.find_checks(name=b"test.fake")
+ funcs = {
+ n: functools.partial(f, self.ui, self.repo)
+ for n, f in checks.items()
+ }
+ options = [b"test.fake:a=yes"]
+ expected_options = {"a": True, "b": True, "c": []}
+ func = self.pass_options(checks=funcs, options=options)
+
+ self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
+
+ def test_pass_options_fake_set_option_with_alias(self):
+ checks = self.find_checks(name=b"test.fake")
+ funcs = {
+ n: functools.partial(f, self.ui, self.repo)
+ for n, f in checks.items()
+ }
+ options = [b"fake:a=yes"]
+ expected_options = {"a": True, "b": True, "c": []}
+ func = self.pass_options(checks=funcs, options=options)
+
+ self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
+
+ def test_pass_options_fake_set_all_option(self):
+ checks = self.find_checks(name=b"test.fake")
+ funcs = {
+ n: functools.partial(f, self.ui, self.repo)
+ for n, f in checks.items()
+ }
+ options = [b"test.fake:a=yes", b"test.fake:b=no", b"test.fake:c=0,1,2"]
+ expected_options = {"a": True, "b": False, "c": [b"0", b"1", b"2"]}
+ func = self.pass_options(checks=funcs, options=options)
+
+ self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
+
+ def test_pass_options_fake_set_all_option_plus_unexisting(self):
+ checks = self.find_checks(name=b"test.fake")
+ funcs = {
+ n: functools.partial(f, self.ui, self.repo)
+ for n, f in checks.items()
+ }
+ options = [
+ b"test.fake:a=yes",
+ b"test.fake:b=no",
+ b"test.fake:c=0,1,2",
+ b"test.fake:d=0",
+ ]
+
+ with self.assertRaises(error.InputError):
+ self.pass_options(checks=funcs, options=options)
+
+ def test_pass_options_fake_duplicate_option(self):
+ checks = self.find_checks(name=b"test.fake")
+ funcs = {
+ n: functools.partial(f, self.ui, self.repo)
+ for n, f in checks.items()
+ }
+ options = [
+ b"test.fake:a=yes",
+ b"test.fake:a=no",
+ ]
+
+ with self.assertRaises(error.InputError):
+ self.pass_options(checks=funcs, options=options)
+
+ def test_pass_options_fake_set_malformed_option(self):
+ checks = self.find_checks(name=b"test.fake")
+ funcs = {
+ n: functools.partial(f, self.ui, self.repo)
+ for n, f in checks.items()
+ }
+ options = [
+ b"test.fake:ayes",
+ b"test.fake:b==no",
+ b"test.fake=",
+ b"test.fake:",
+ b"test.fa=ke:d=0",
+ b"test.fa=ke:d=0",
+ ]
+
+ for opt in options:
+ with self.assertRaises(error.InputError):
+ self.pass_options(checks=funcs, options=[opt])
+
+ def test_pass_options_types(self):
+ checks = self.find_checks(name=b"test.fake")
+ funcs = {
+ n: functools.partial(f, self.ui, self.repo)
+ for n, f in checks.items()
+ }
+ # boolean, yes/no
+ options = [b"test.fake:a=yes", b"test.fake:b=no"]
+ expected_options = {"a": True, "b": False, "c": []}
+ func = self.pass_options(checks=funcs, options=options)
+
+ self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
+
+ # boolean, 0/1
+ options = [b"test.fake:a=1", b"test.fake:b=0"]
+ expected_options = {"a": True, "b": False, "c": []}
+ func = self.pass_options(checks=funcs, options=options)
+
+ self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
+
+ # boolean, true/false
+ options = [b"test.fake:a=true", b"test.fake:b=false"]
+ expected_options = {"a": True, "b": False, "c": []}
+ func = self.pass_options(checks=funcs, options=options)
+
+ self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
+
+ # boolean, wrong type
+ options = [b"test.fake:a=si"]
+ with self.assertRaises(error.InputError):
+ self.pass_options(checks=funcs, options=options)
+
+ # lists
+ options = [b"test.fake:c=0,1,2"]
+ expected_options = {"a": False, "b": True, "c": [b"0", b"1", b"2"]}
+ func = self.pass_options(checks=funcs, options=options)
+
+ self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
+
+ options = [b"test.fake:c=x,y,z"]
+ expected_options = {"a": False, "b": True, "c": [b"x", b"y", b"z"]}
+ func = self.pass_options(checks=funcs, options=options)
+
+ self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
+
+ # tests get_checks
+ def test_get_checks_fake(self):
+ funcs = self.get_checks(
+ names=[b"test.fake"], options=[b"test.fake:a=yes"]
+ )
+ options = funcs.get(b"test.fake").keywords
+ expected_options = {"a": True, "b": True, "c": []}
+ self.assertDictEqual(options, expected_options)
+
+ def test_get_checks_multiple_mixed_with_defaults(self):
+ funcs = self.get_checks(
+ names=[b"test.fake", b"test.noop.deeper", b"test.dummy"],
+ options=[
+ b"test.noop.deeper:y=no",
+ b"test.noop.deeper:z=-1,0,1",
+ ],
+ )
+ options = funcs.get(b"test.fake").keywords
+ expected_options = {"a": False, "b": True, "c": []}
+ self.assertDictEqual(options, expected_options)
+
+ options = funcs.get(b"test.noop.deeper").keywords
+ expected_options = {"y": False, "z": [b"-1", b"0", b"1"]}
+ self.assertDictEqual(options, expected_options)
+
+ options = funcs.get(b"test.dummy").keywords
+ expected_options = {}
+ self.assertDictEqual(options, expected_options)
+
+ def test_broken_pyramid(self):
+ """Check that we detect pyramids that can't resolve"""
+ table = {}
+ alias_table = {}
+ pyramid = {}
+ check = registrar.verify_check(table, alias_table)
+
+ # Create two checks that clash
+ @check(b"test.wrong.intermediate")
+ def check_dummy(ui, repo, **options):
+ return options
+
+ @check(b"test.wrong.intermediate.thing")
+ def check_fake(ui, repo, **options):
+ return options
+
+ with self.assertRaises(error.ProgrammingError) as e:
+ verify.get_checks(
+ self.repo,
+ self.ui,
+ names=[b"test.wrong.intermediate"],
+ options=[],
+ table=table,
+ alias_table=alias_table,
+ full_pyramid=pyramid,
+ )
+ assert "`verify.noop_func`" in str(e.exception), str(e.exception)
+
+
+if __name__ == '__main__':
+ import silenttestrunner
+
+ silenttestrunner.main(__name__)