tests/test-admin-commands.py
changeset 50986 752c5a5b73c6
equal deleted inserted replaced
50985:cf47b83d8ad0 50986:752c5a5b73c6
       
     1 # Test admin commands
       
     2 
       
     3 import functools
       
     4 import unittest
       
     5 from mercurial.i18n import _
       
     6 from mercurial import error, ui as uimod
       
     7 from mercurial import registrar
       
     8 from mercurial.admin import verify
       
     9 
       
    10 
       
    11 class TestAdminVerifyFindChecks(unittest.TestCase):
       
    12     def __init__(self, *args, **kwargs):
       
    13         super().__init__(*args, **kwargs)
       
    14         self.ui = uimod.ui.load()
       
    15         self.repo = b"fake-repo"
       
    16 
       
    17         def cleanup_table(self):
       
    18             self.table = {}
       
    19             self.alias_table = {}
       
    20             self.pyramid = {}
       
    21 
       
    22         self.addCleanup(cleanup_table, self)
       
    23 
       
    24     def setUp(self):
       
    25         self.table = {}
       
    26         self.alias_table = {}
       
    27         self.pyramid = {}
       
    28         check = registrar.verify_check(self.table, self.alias_table)
       
    29 
       
    30         # mock some fake check method for tests purpose
       
    31         @check(
       
    32             b"test.dummy",
       
    33             alias=b"dummy",
       
    34             options=[],
       
    35         )
       
    36         def check_dummy(ui, repo, **options):
       
    37             return options
       
    38 
       
    39         @check(
       
    40             b"test.fake",
       
    41             alias=b"fake",
       
    42             options=[
       
    43                 (b'a', False, _(b'a boolean value (default: False)')),
       
    44                 (b'b', True, _(b'a boolean value (default: True)')),
       
    45                 (b'c', [], _(b'a list')),
       
    46             ],
       
    47         )
       
    48         def check_fake(ui, repo, **options):
       
    49             return options
       
    50 
       
    51         # alias in the middle of a hierarchy
       
    52         check(
       
    53             b"test.noop",
       
    54             alias=b"noop",
       
    55             options=[],
       
    56         )(verify.noop_func)
       
    57 
       
    58         @check(
       
    59             b"test.noop.deeper",
       
    60             alias=b"deeper",
       
    61             options=[
       
    62                 (b'y', True, _(b'a boolean value (default: True)')),
       
    63                 (b'z', [], _(b'a list')),
       
    64             ],
       
    65         )
       
    66         def check_noop_deeper(ui, repo, **options):
       
    67             return options
       
    68 
       
    69     # args wrapper utilities
       
    70     def find_checks(self, name):
       
    71         return verify.find_checks(
       
    72             name=name,
       
    73             table=self.table,
       
    74             alias_table=self.alias_table,
       
    75             full_pyramid=self.pyramid,
       
    76         )
       
    77 
       
    78     def pass_options(self, checks, options):
       
    79         return verify.pass_options(
       
    80             self.ui,
       
    81             checks,
       
    82             options,
       
    83             table=self.table,
       
    84             alias_table=self.alias_table,
       
    85             full_pyramid=self.pyramid,
       
    86         )
       
    87 
       
    88     def get_checks(self, names, options):
       
    89         return verify.get_checks(
       
    90             self.repo,
       
    91             self.ui,
       
    92             names=names,
       
    93             options=options,
       
    94             table=self.table,
       
    95             alias_table=self.alias_table,
       
    96             full_pyramid=self.pyramid,
       
    97         )
       
    98 
       
    99     # tests find_checks
       
   100     def test_find_checks_empty_name(self):
       
   101         with self.assertRaises(error.InputError):
       
   102             self.find_checks(name=b"")
       
   103 
       
   104     def test_find_checks_wrong_name(self):
       
   105         with self.assertRaises(error.InputError):
       
   106             self.find_checks(name=b"unknown")
       
   107 
       
   108     def test_find_checks_dummy(self):
       
   109         name = b"test.dummy"
       
   110         found = self.find_checks(name=name)
       
   111         self.assertEqual(len(found), 1)
       
   112         self.assertIn(name, found)
       
   113         meth = found[name]
       
   114         self.assertTrue(callable(meth))
       
   115         self.assertEqual(len(meth.options), 0)
       
   116 
       
   117     def test_find_checks_fake(self):
       
   118         name = b"test.fake"
       
   119         found = self.find_checks(name=name)
       
   120         self.assertEqual(len(found), 1)
       
   121         self.assertIn(name, found)
       
   122         meth = found[name]
       
   123         self.assertTrue(callable(meth))
       
   124         self.assertEqual(len(meth.options), 3)
       
   125 
       
   126     def test_find_checks_noop(self):
       
   127         name = b"test.noop.deeper"
       
   128         found = self.find_checks(name=name)
       
   129         self.assertEqual(len(found), 1)
       
   130         self.assertIn(name, found)
       
   131         meth = found[name]
       
   132         self.assertTrue(callable(meth))
       
   133         self.assertEqual(len(meth.options), 2)
       
   134 
       
   135     def test_find_checks_from_aliases(self):
       
   136         found = self.find_checks(name=b"dummy")
       
   137         self.assertEqual(len(found), 1)
       
   138         self.assertIn(b"test.dummy", found)
       
   139 
       
   140         found = self.find_checks(name=b"fake")
       
   141         self.assertEqual(len(found), 1)
       
   142         self.assertIn(b"test.fake", found)
       
   143 
       
   144         found = self.find_checks(name=b"deeper")
       
   145         self.assertEqual(len(found), 1)
       
   146         self.assertIn(b"test.noop.deeper", found)
       
   147 
       
   148     def test_find_checks_from_root(self):
       
   149         found = self.find_checks(name=b"test")
       
   150         self.assertEqual(len(found), 3)
       
   151         self.assertIn(b"test.dummy", found)
       
   152         self.assertIn(b"test.fake", found)
       
   153         self.assertIn(b"test.noop.deeper", found)
       
   154 
       
   155     def test_find_checks_from_intermediate(self):
       
   156         found = self.find_checks(name=b"test.noop")
       
   157         self.assertEqual(len(found), 1)
       
   158         self.assertIn(b"test.noop.deeper", found)
       
   159 
       
   160     def test_find_checks_from_parent_dot_name(self):
       
   161         found = self.find_checks(name=b"noop.deeper")
       
   162         self.assertEqual(len(found), 1)
       
   163         self.assertIn(b"test.noop.deeper", found)
       
   164 
       
   165     # tests pass_options
       
   166     def test_pass_options_no_checks_no_options(self):
       
   167         checks = {}
       
   168         options = []
       
   169 
       
   170         with self.assertRaises(error.Error):
       
   171             self.pass_options(checks=checks, options=options)
       
   172 
       
   173     def test_pass_options_fake_empty_options(self):
       
   174         checks = self.find_checks(name=b"test.fake")
       
   175         funcs = {
       
   176             n: functools.partial(f, self.ui, self.repo)
       
   177             for n, f in checks.items()
       
   178         }
       
   179         options = []
       
   180         # should end with default options
       
   181         expected_options = {"a": False, "b": True, "c": []}
       
   182         func = self.pass_options(checks=funcs, options=options)
       
   183 
       
   184         self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
       
   185 
       
   186     def test_pass_options_fake_non_existing_options(self):
       
   187         checks = self.find_checks(name=b"test.fake")
       
   188         funcs = {
       
   189             n: functools.partial(f, self.ui, self.repo)
       
   190             for n, f in checks.items()
       
   191         }
       
   192 
       
   193         with self.assertRaises(error.InputError):
       
   194             options = [b"test.fake:boom=yes"]
       
   195             self.pass_options(checks=funcs, options=options)
       
   196 
       
   197     def test_pass_options_fake_unrelated_options(self):
       
   198         checks = self.find_checks(name=b"test.fake")
       
   199         funcs = {
       
   200             n: functools.partial(f, self.ui, self.repo)
       
   201             for n, f in checks.items()
       
   202         }
       
   203         options = [b"test.noop.deeper:y=yes"]
       
   204 
       
   205         with self.assertRaises(error.InputError):
       
   206             self.pass_options(checks=funcs, options=options)
       
   207 
       
   208     def test_pass_options_fake_set_option(self):
       
   209         checks = self.find_checks(name=b"test.fake")
       
   210         funcs = {
       
   211             n: functools.partial(f, self.ui, self.repo)
       
   212             for n, f in checks.items()
       
   213         }
       
   214         options = [b"test.fake:a=yes"]
       
   215         expected_options = {"a": True, "b": True, "c": []}
       
   216         func = self.pass_options(checks=funcs, options=options)
       
   217 
       
   218         self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
       
   219 
       
   220     def test_pass_options_fake_set_option_with_alias(self):
       
   221         checks = self.find_checks(name=b"test.fake")
       
   222         funcs = {
       
   223             n: functools.partial(f, self.ui, self.repo)
       
   224             for n, f in checks.items()
       
   225         }
       
   226         options = [b"fake:a=yes"]
       
   227         expected_options = {"a": True, "b": True, "c": []}
       
   228         func = self.pass_options(checks=funcs, options=options)
       
   229 
       
   230         self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
       
   231 
       
   232     def test_pass_options_fake_set_all_option(self):
       
   233         checks = self.find_checks(name=b"test.fake")
       
   234         funcs = {
       
   235             n: functools.partial(f, self.ui, self.repo)
       
   236             for n, f in checks.items()
       
   237         }
       
   238         options = [b"test.fake:a=yes", b"test.fake:b=no", b"test.fake:c=0,1,2"]
       
   239         expected_options = {"a": True, "b": False, "c": [b"0", b"1", b"2"]}
       
   240         func = self.pass_options(checks=funcs, options=options)
       
   241 
       
   242         self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
       
   243 
       
   244     def test_pass_options_fake_set_all_option_plus_unexisting(self):
       
   245         checks = self.find_checks(name=b"test.fake")
       
   246         funcs = {
       
   247             n: functools.partial(f, self.ui, self.repo)
       
   248             for n, f in checks.items()
       
   249         }
       
   250         options = [
       
   251             b"test.fake:a=yes",
       
   252             b"test.fake:b=no",
       
   253             b"test.fake:c=0,1,2",
       
   254             b"test.fake:d=0",
       
   255         ]
       
   256 
       
   257         with self.assertRaises(error.InputError):
       
   258             self.pass_options(checks=funcs, options=options)
       
   259 
       
   260     def test_pass_options_fake_duplicate_option(self):
       
   261         checks = self.find_checks(name=b"test.fake")
       
   262         funcs = {
       
   263             n: functools.partial(f, self.ui, self.repo)
       
   264             for n, f in checks.items()
       
   265         }
       
   266         options = [
       
   267             b"test.fake:a=yes",
       
   268             b"test.fake:a=no",
       
   269         ]
       
   270 
       
   271         with self.assertRaises(error.InputError):
       
   272             self.pass_options(checks=funcs, options=options)
       
   273 
       
   274     def test_pass_options_fake_set_malformed_option(self):
       
   275         checks = self.find_checks(name=b"test.fake")
       
   276         funcs = {
       
   277             n: functools.partial(f, self.ui, self.repo)
       
   278             for n, f in checks.items()
       
   279         }
       
   280         options = [
       
   281             b"test.fake:ayes",
       
   282             b"test.fake:b==no",
       
   283             b"test.fake=",
       
   284             b"test.fake:",
       
   285             b"test.fa=ke:d=0",
       
   286             b"test.fa=ke:d=0",
       
   287         ]
       
   288 
       
   289         for opt in options:
       
   290             with self.assertRaises(error.InputError):
       
   291                 self.pass_options(checks=funcs, options=[opt])
       
   292 
       
   293     def test_pass_options_types(self):
       
   294         checks = self.find_checks(name=b"test.fake")
       
   295         funcs = {
       
   296             n: functools.partial(f, self.ui, self.repo)
       
   297             for n, f in checks.items()
       
   298         }
       
   299         # boolean, yes/no
       
   300         options = [b"test.fake:a=yes", b"test.fake:b=no"]
       
   301         expected_options = {"a": True, "b": False, "c": []}
       
   302         func = self.pass_options(checks=funcs, options=options)
       
   303 
       
   304         self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
       
   305 
       
   306         # boolean, 0/1
       
   307         options = [b"test.fake:a=1", b"test.fake:b=0"]
       
   308         expected_options = {"a": True, "b": False, "c": []}
       
   309         func = self.pass_options(checks=funcs, options=options)
       
   310 
       
   311         self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
       
   312 
       
   313         # boolean, true/false
       
   314         options = [b"test.fake:a=true", b"test.fake:b=false"]
       
   315         expected_options = {"a": True, "b": False, "c": []}
       
   316         func = self.pass_options(checks=funcs, options=options)
       
   317 
       
   318         self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
       
   319 
       
   320         # boolean, wrong type
       
   321         options = [b"test.fake:a=si"]
       
   322         with self.assertRaises(error.InputError):
       
   323             self.pass_options(checks=funcs, options=options)
       
   324 
       
   325         # lists
       
   326         options = [b"test.fake:c=0,1,2"]
       
   327         expected_options = {"a": False, "b": True, "c": [b"0", b"1", b"2"]}
       
   328         func = self.pass_options(checks=funcs, options=options)
       
   329 
       
   330         self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
       
   331 
       
   332         options = [b"test.fake:c=x,y,z"]
       
   333         expected_options = {"a": False, "b": True, "c": [b"x", b"y", b"z"]}
       
   334         func = self.pass_options(checks=funcs, options=options)
       
   335 
       
   336         self.assertDictEqual(func[b"test.fake"].keywords, expected_options)
       
   337 
       
   338     # tests get_checks
       
   339     def test_get_checks_fake(self):
       
   340         funcs = self.get_checks(
       
   341             names=[b"test.fake"], options=[b"test.fake:a=yes"]
       
   342         )
       
   343         options = funcs.get(b"test.fake").keywords
       
   344         expected_options = {"a": True, "b": True, "c": []}
       
   345         self.assertDictEqual(options, expected_options)
       
   346 
       
   347     def test_get_checks_multiple_mixed_with_defaults(self):
       
   348         funcs = self.get_checks(
       
   349             names=[b"test.fake", b"test.noop.deeper", b"test.dummy"],
       
   350             options=[
       
   351                 b"test.noop.deeper:y=no",
       
   352                 b"test.noop.deeper:z=-1,0,1",
       
   353             ],
       
   354         )
       
   355         options = funcs.get(b"test.fake").keywords
       
   356         expected_options = {"a": False, "b": True, "c": []}
       
   357         self.assertDictEqual(options, expected_options)
       
   358 
       
   359         options = funcs.get(b"test.noop.deeper").keywords
       
   360         expected_options = {"y": False, "z": [b"-1", b"0", b"1"]}
       
   361         self.assertDictEqual(options, expected_options)
       
   362 
       
   363         options = funcs.get(b"test.dummy").keywords
       
   364         expected_options = {}
       
   365         self.assertDictEqual(options, expected_options)
       
   366 
       
   367     def test_broken_pyramid(self):
       
   368         """Check that we detect pyramids that can't resolve"""
       
   369         table = {}
       
   370         alias_table = {}
       
   371         pyramid = {}
       
   372         check = registrar.verify_check(table, alias_table)
       
   373 
       
   374         # Create two checks that clash
       
   375         @check(b"test.wrong.intermediate")
       
   376         def check_dummy(ui, repo, **options):
       
   377             return options
       
   378 
       
   379         @check(b"test.wrong.intermediate.thing")
       
   380         def check_fake(ui, repo, **options):
       
   381             return options
       
   382 
       
   383         with self.assertRaises(error.ProgrammingError) as e:
       
   384             verify.get_checks(
       
   385                 self.repo,
       
   386                 self.ui,
       
   387                 names=[b"test.wrong.intermediate"],
       
   388                 options=[],
       
   389                 table=table,
       
   390                 alias_table=alias_table,
       
   391                 full_pyramid=pyramid,
       
   392             )
       
   393         assert "`verify.noop_func`" in str(e.exception), str(e.exception)
       
   394 
       
   395 
       
   396 if __name__ == '__main__':
       
   397     import silenttestrunner
       
   398 
       
   399     silenttestrunner.main(__name__)