2015-08-17 21:13:13 +02:00
|
|
|
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
|
|
|
|
2016-01-04 07:12:39 +01:00
|
|
|
# Copyright 2015-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
|
2015-08-17 21:13:13 +02:00
|
|
|
#
|
|
|
|
# This file is part of qutebrowser.
|
|
|
|
#
|
|
|
|
# qutebrowser is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# qutebrowser is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
"""Tests for qutebrowser.commands.cmdutils."""
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
2016-05-10 18:58:23 +02:00
|
|
|
from qutebrowser.commands import cmdutils, cmdexc, argparser, command
|
2015-08-17 21:13:13 +02:00
|
|
|
|
|
|
|
|
|
|
|
class TestCheckOverflow:
|
|
|
|
|
|
|
|
def test_good(self):
|
|
|
|
cmdutils.check_overflow(1, 'int')
|
|
|
|
|
|
|
|
def test_bad(self):
|
|
|
|
int32_max = 2 ** 31 - 1
|
|
|
|
|
|
|
|
with pytest.raises(cmdexc.CommandError) as excinfo:
|
|
|
|
cmdutils.check_overflow(int32_max + 1, 'int')
|
|
|
|
|
|
|
|
expected_str = ("Numeric argument is too large for internal int "
|
|
|
|
"representation.")
|
|
|
|
|
|
|
|
assert str(excinfo.value) == expected_str
|
|
|
|
|
|
|
|
|
|
|
|
class TestArgOrCount:
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('arg, count', [(None, None), (1, 1)])
|
|
|
|
def test_exceptions(self, arg, count):
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
cmdutils.arg_or_count(arg, count)
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('arg, count', [(1, None), (None, 1)])
|
|
|
|
def test_normal(self, arg, count):
|
|
|
|
assert cmdutils.arg_or_count(arg, count) == 1
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('arg, count, countzero, expected', [
|
|
|
|
(0, None, 2, 0),
|
|
|
|
(None, 0, 2, 2),
|
|
|
|
])
|
|
|
|
def test_countzero(self, arg, count, countzero, expected):
|
|
|
|
ret = cmdutils.arg_or_count(arg, count, countzero=countzero)
|
|
|
|
assert ret == expected
|
|
|
|
|
|
|
|
def test_default(self):
|
|
|
|
assert cmdutils.arg_or_count(None, None, default=2) == 2
|
|
|
|
|
|
|
|
|
|
|
|
class TestCheckExclusive:
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('flags', [[], [False, True], [False, False]])
|
|
|
|
def test_good(self, flags):
|
|
|
|
cmdutils.check_exclusive(flags, [])
|
|
|
|
|
|
|
|
def test_bad(self):
|
|
|
|
with pytest.raises(cmdexc.CommandError) as excinfo:
|
|
|
|
cmdutils.check_exclusive([True, True], 'xyz')
|
|
|
|
|
|
|
|
assert str(excinfo.value) == "Only one of -x/-y/-z can be given!"
|
|
|
|
|
|
|
|
|
|
|
|
class TestRegister:
|
|
|
|
|
|
|
|
# pylint: disable=unused-variable
|
|
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
|
|
def clear_globals(self, monkeypatch):
|
|
|
|
"""Clear the cmdutils globals between each test."""
|
|
|
|
monkeypatch.setattr(cmdutils, 'cmd_dict', {})
|
|
|
|
monkeypatch.setattr(cmdutils, 'aliases', [])
|
|
|
|
|
|
|
|
def test_simple(self):
|
|
|
|
@cmdutils.register()
|
|
|
|
def fun():
|
|
|
|
"""Blah."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
cmd = cmdutils.cmd_dict['fun']
|
|
|
|
assert cmd.handler is fun
|
|
|
|
assert cmd.name == 'fun'
|
|
|
|
assert len(cmdutils.cmd_dict) == 1
|
|
|
|
assert not cmdutils.aliases
|
|
|
|
|
|
|
|
def test_underlines(self):
|
|
|
|
"""Make sure the function name is normalized correctly (_ -> -)."""
|
|
|
|
@cmdutils.register()
|
|
|
|
def eggs_bacon():
|
|
|
|
"""Blah."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
assert cmdutils.cmd_dict['eggs-bacon'].name == 'eggs-bacon'
|
|
|
|
assert 'eggs_bacon' not in cmdutils.cmd_dict
|
|
|
|
|
|
|
|
def test_lowercasing(self):
|
|
|
|
"""Make sure the function name is normalized correctly (uppercase)."""
|
|
|
|
@cmdutils.register()
|
|
|
|
def Test(): # pylint: disable=invalid-name
|
|
|
|
"""Blah."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
assert cmdutils.cmd_dict['test'].name == 'test'
|
|
|
|
assert 'Test' not in cmdutils.cmd_dict
|
|
|
|
|
|
|
|
def test_explicit_name(self):
|
|
|
|
"""Test register with explicit name."""
|
|
|
|
@cmdutils.register(name='foobar')
|
|
|
|
def fun():
|
|
|
|
"""Blah."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
assert cmdutils.cmd_dict['foobar'].name == 'foobar'
|
|
|
|
assert 'fun' not in cmdutils.cmd_dict
|
|
|
|
assert len(cmdutils.cmd_dict) == 1
|
|
|
|
assert not cmdutils.aliases
|
|
|
|
|
|
|
|
def test_multiple_names(self):
|
|
|
|
"""Test register with name being a list."""
|
|
|
|
@cmdutils.register(name=['foobar', 'blub'])
|
|
|
|
def fun():
|
|
|
|
"""Blah."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
assert cmdutils.cmd_dict['foobar'].name == 'foobar'
|
|
|
|
assert cmdutils.cmd_dict['blub'].name == 'foobar'
|
|
|
|
assert 'fun' not in cmdutils.cmd_dict
|
|
|
|
assert len(cmdutils.cmd_dict) == 2
|
|
|
|
assert cmdutils.aliases == ['blub']
|
|
|
|
|
|
|
|
def test_multiple_registrations(self):
|
|
|
|
"""Make sure registering the same name twice raises ValueError."""
|
|
|
|
@cmdutils.register(name=['foobar', 'blub'])
|
|
|
|
def fun():
|
|
|
|
"""Blah."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
@cmdutils.register(name=['blah', 'blub'])
|
|
|
|
def fun2():
|
|
|
|
"""Blah."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
def test_instance(self):
|
|
|
|
"""Make sure the instance gets passed to Command."""
|
|
|
|
@cmdutils.register(instance='foobar')
|
|
|
|
def fun(self):
|
|
|
|
"""Blah."""
|
|
|
|
pass
|
|
|
|
assert cmdutils.cmd_dict['fun']._instance == 'foobar'
|
|
|
|
|
|
|
|
def test_kwargs(self):
|
|
|
|
"""Make sure the other keyword arguments get passed to Command."""
|
|
|
|
@cmdutils.register(hide=True)
|
|
|
|
def fun():
|
|
|
|
"""Blah."""
|
|
|
|
pass
|
|
|
|
assert cmdutils.cmd_dict['fun'].hide
|
2016-05-10 06:41:42 +02:00
|
|
|
|
2016-05-10 07:12:50 +02:00
|
|
|
def test_wrong_completion_count(self):
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
@cmdutils.register(completion=['one', 'two'])
|
|
|
|
def fun(arg):
|
|
|
|
"""Blah."""
|
|
|
|
pass
|
|
|
|
|
2016-05-10 06:41:42 +02:00
|
|
|
def test_star_args(self):
|
2016-05-10 07:56:54 +02:00
|
|
|
"""Check handling of *args."""
|
2016-05-10 06:41:42 +02:00
|
|
|
@cmdutils.register()
|
|
|
|
def fun(*args):
|
|
|
|
"""Blah."""
|
|
|
|
pass
|
|
|
|
with pytest.raises(argparser.ArgumentParserError):
|
|
|
|
cmdutils.cmd_dict['fun'].parser.parse_args([])
|
|
|
|
|
|
|
|
def test_star_args_optional(self):
|
2016-05-10 07:56:54 +02:00
|
|
|
"""Check handling of *args withstar_args_optional."""
|
2016-05-10 06:41:42 +02:00
|
|
|
@cmdutils.register(star_args_optional=True)
|
|
|
|
def fun(*args):
|
|
|
|
"""Blah."""
|
|
|
|
pass
|
|
|
|
cmdutils.cmd_dict['fun'].parser.parse_args([])
|
2016-05-10 07:00:10 +02:00
|
|
|
|
|
|
|
def test_flag(self):
|
|
|
|
@cmdutils.register()
|
|
|
|
def fun(arg=False):
|
|
|
|
"""Blah."""
|
|
|
|
pass
|
|
|
|
parser = cmdutils.cmd_dict['fun'].parser
|
|
|
|
assert parser.parse_args(['--arg']).arg
|
|
|
|
assert parser.parse_args(['-a']).arg
|
|
|
|
assert not parser.parse_args([]).arg
|
|
|
|
|
2016-05-10 07:35:41 +02:00
|
|
|
def test_flag_argument(self):
|
2016-05-10 18:58:23 +02:00
|
|
|
@cmdutils.register()
|
|
|
|
@cmdutils.argument('arg', flag='b')
|
2016-05-10 07:35:41 +02:00
|
|
|
def fun(arg=False):
|
2016-05-10 07:00:10 +02:00
|
|
|
"""Blah."""
|
|
|
|
pass
|
|
|
|
parser = cmdutils.cmd_dict['fun'].parser
|
|
|
|
|
|
|
|
assert parser.parse_args(['-b']).arg
|
|
|
|
with pytest.raises(argparser.ArgumentParserError):
|
|
|
|
parser.parse_args(['-a'])
|
2016-05-10 07:35:41 +02:00
|
|
|
|
2016-05-10 18:58:23 +02:00
|
|
|
def test_partial_arg(self):
|
|
|
|
"""Test with only some arguments decorated with @cmdutils.argument."""
|
|
|
|
@cmdutils.register()
|
|
|
|
@cmdutils.argument('arg1', flag='b')
|
|
|
|
def fun(arg1=False, arg2=False):
|
|
|
|
"""Blah."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class TestArgument:
|
|
|
|
|
|
|
|
"""Test the @cmdutils.argument decorator."""
|
|
|
|
|
|
|
|
# pylint: disable=unused-variable
|
|
|
|
|
|
|
|
def test_invalid_argument(self):
|
|
|
|
with pytest.raises(ValueError) as excinfo:
|
|
|
|
@cmdutils.argument('foo')
|
|
|
|
def fun(bar):
|
2016-05-10 07:35:41 +02:00
|
|
|
"""Blah."""
|
|
|
|
pass
|
2016-05-10 18:58:23 +02:00
|
|
|
assert str(excinfo.value) == "fun has no argument foo!"
|
|
|
|
|
|
|
|
def test_storage(self):
|
|
|
|
@cmdutils.argument('foo', flag='x')
|
|
|
|
@cmdutils.argument('bar', flag='y')
|
|
|
|
def fun(foo, bar):
|
|
|
|
"""Blah."""
|
|
|
|
pass
|
|
|
|
expected = {
|
2016-05-10 19:46:45 +02:00
|
|
|
'foo': command.ArgInfo(flag='x'),
|
|
|
|
'bar': command.ArgInfo(flag='y')
|
2016-05-10 18:58:23 +02:00
|
|
|
}
|
|
|
|
assert fun.qute_args == expected
|
2016-05-10 19:09:07 +02:00
|
|
|
|
|
|
|
def test_wrong_order(self):
|
|
|
|
"""When @cmdutils.argument is used above (after) @register, fail."""
|
|
|
|
with pytest.raises(ValueError) as excinfo:
|
|
|
|
@cmdutils.argument('bar', flag='y')
|
|
|
|
@cmdutils.register()
|
|
|
|
def fun(bar):
|
|
|
|
"""Blah."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
text = ("@cmdutils.argument got called above (after) "
|
|
|
|
"@cmdutils.register for fun!")
|
|
|
|
|
|
|
|
assert str(excinfo.value) == text
|