|
|
# 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__)
|
|
|
|