221 lines
7.7 KiB
Python
221 lines
7.7 KiB
Python
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import argparse
|
|
import functools
|
|
|
|
from cliff import command
|
|
from cliff.tests import base
|
|
|
|
|
|
class TestCommand(command.Command):
|
|
"""Description of command.
|
|
"""
|
|
|
|
def get_parser(self, prog_name):
|
|
parser = super(TestCommand, self).get_parser(prog_name)
|
|
parser.add_argument(
|
|
'long_help_argument',
|
|
help="Create a NIC on the server.\n"
|
|
"Specify option multiple times to create multiple NICs. "
|
|
"Either net-id or port-id must be provided, but not both.\n"
|
|
"net-id: attach NIC to network with this UUID\n"
|
|
"port-id: attach NIC to port with this UUID\n"
|
|
"v4-fixed-ip: IPv4 fixed address for NIC (optional)\n"
|
|
"v6-fixed-ip: IPv6 fixed address for NIC (optional)\n"
|
|
"none: (v2.37+) no network is attached\n"
|
|
"auto: (v2.37+) the compute service will automatically "
|
|
"allocate a network.\n"
|
|
"Specifying a --nic of auto or none "
|
|
"cannot be used with any other --nic value.",
|
|
)
|
|
parser.add_argument(
|
|
'regular_help_argument',
|
|
help="The quick brown fox jumps "
|
|
"over the lazy dog.",
|
|
)
|
|
parser.add_argument(
|
|
'-z',
|
|
dest='zippy',
|
|
default='zippy-default',
|
|
help='defined in TestCommand and used in TestArgumentParser',
|
|
)
|
|
return parser
|
|
|
|
def take_action(self, parsed_args):
|
|
return 42
|
|
|
|
|
|
class TestCommandNoDocstring(command.Command):
|
|
|
|
def take_action(self, parsed_args):
|
|
return 42
|
|
|
|
|
|
class TestDescription(base.TestBase):
|
|
|
|
def test_get_description_docstring(self):
|
|
cmd = TestCommand(None, None)
|
|
desc = cmd.get_description()
|
|
assert desc == "Description of command.\n "
|
|
|
|
def test_get_description_attribute(self):
|
|
cmd = TestCommand(None, None)
|
|
# Artificially inject a value for _description to verify that it
|
|
# overrides the docstring.
|
|
cmd._description = 'this is not the default'
|
|
desc = cmd.get_description()
|
|
assert desc == 'this is not the default'
|
|
|
|
def test_get_description_default(self):
|
|
cmd = TestCommandNoDocstring(None, None)
|
|
desc = cmd.get_description()
|
|
assert desc == ''
|
|
|
|
|
|
class TestBasicValues(base.TestBase):
|
|
|
|
def test_get_parser(self):
|
|
cmd = TestCommand(None, None)
|
|
parser = cmd.get_parser('NAME')
|
|
assert parser.prog == 'NAME'
|
|
|
|
def test_get_name(self):
|
|
cmd = TestCommand(None, None, cmd_name='object action')
|
|
assert cmd.cmd_name == 'object action'
|
|
|
|
def test_run_return(self):
|
|
cmd = TestCommand(None, None, cmd_name='object action')
|
|
assert cmd.run(None) == 42
|
|
|
|
|
|
expected_help_message = """
|
|
long_help_argument Create a NIC on the server.
|
|
Specify option multiple times to create multiple NICs.
|
|
Either net-id or port-id must be provided, but not
|
|
both.
|
|
net-id: attach NIC to network with this UUID
|
|
port-id: attach NIC to port with this UUID
|
|
v4-fixed-ip: IPv4 fixed address for NIC (optional)
|
|
v6-fixed-ip: IPv6 fixed address for NIC (optional)
|
|
none: (v2.37+) no network is attached
|
|
auto: (v2.37+) the compute service will automatically
|
|
allocate a network.
|
|
Specifying a --nic of auto or none cannot be used with
|
|
any other --nic value.
|
|
regular_help_argument
|
|
The quick brown fox jumps over the lazy dog.
|
|
"""
|
|
|
|
|
|
class TestHelp(base.TestBase):
|
|
|
|
def test_smart_help_formatter(self):
|
|
cmd = TestCommand(None, None)
|
|
parser = cmd.get_parser('NAME')
|
|
# Set up the formatter to always use a width=80 so that the
|
|
# terminal width of the developer's system does not cause the
|
|
# test to fail. Trying to mock os.environ failed, but there is
|
|
# an arg to HelpFormatter to set the width
|
|
# explicitly. Unfortunately, there is no way to do that
|
|
# through the parser, so we have to replace the parser's
|
|
# formatter_class attribute with a partial() that passes width
|
|
# to the original class.
|
|
parser.formatter_class = functools.partial(
|
|
parser.formatter_class,
|
|
width=78,
|
|
)
|
|
self.assertIn(expected_help_message, parser.format_help())
|
|
|
|
|
|
class TestArgumentParser(base.TestBase):
|
|
|
|
def test_option_name_collision(self):
|
|
cmd = TestCommand(None, None)
|
|
parser = cmd.get_parser('NAME')
|
|
# We should have an exception registering an option with a
|
|
# name that already exists because we configure the argument
|
|
# parser to ignore conflicts but this option has no other name
|
|
# to be used.
|
|
self.assertRaises(
|
|
argparse.ArgumentError,
|
|
parser.add_argument,
|
|
'-z',
|
|
)
|
|
|
|
def test_option_name_collision_with_alias(self):
|
|
cmd = TestCommand(None, None)
|
|
parser = cmd.get_parser('NAME')
|
|
# We not should have an exception registering an option with a
|
|
# name that already exists because we configure the argument
|
|
# parser to ignore conflicts and this option can be added as
|
|
# --zero even if the -z is ignored.
|
|
parser.add_argument('-z', '--zero')
|
|
|
|
def test_resolve_option_with_name_collision(self):
|
|
cmd = TestCommand(None, None)
|
|
parser = cmd.get_parser('NAME')
|
|
parser.add_argument(
|
|
'-z', '--zero',
|
|
dest='zero',
|
|
default='zero-default',
|
|
)
|
|
args = parser.parse_args(['-z', 'foo', 'a', 'b'])
|
|
self.assertEqual(args.zippy, 'foo')
|
|
self.assertEqual(args.zero, 'zero-default')
|
|
|
|
def test_with_conflict_handler(self):
|
|
cmd = TestCommand(None, None)
|
|
cmd.conflict_handler = 'resolve'
|
|
parser = cmd.get_parser('NAME')
|
|
self.assertEqual(parser.conflict_handler, 'resolve')
|
|
|
|
def test_raise_conflict_argument_error(self):
|
|
cmd = TestCommand(None, None)
|
|
parser = cmd.get_parser('NAME')
|
|
parser.add_argument(
|
|
'-f', '--foo',
|
|
dest='foo',
|
|
default='foo',
|
|
)
|
|
self.assertRaises(
|
|
argparse.ArgumentError,
|
|
parser.add_argument,
|
|
'-f',
|
|
)
|
|
|
|
def test_resolve_conflict_argument(self):
|
|
cmd = TestCommand(None, None)
|
|
cmd.conflict_handler = 'resolve'
|
|
parser = cmd.get_parser('NAME')
|
|
parser.add_argument(
|
|
'-f', '--foo',
|
|
dest='foo',
|
|
default='foo',
|
|
)
|
|
parser.add_argument(
|
|
'-f', '--foo',
|
|
dest='foo',
|
|
default='bar',
|
|
)
|
|
args = parser.parse_args(['a', 'b'])
|
|
self.assertEqual(args.foo, 'bar')
|
|
|
|
def test_wrong_conflict_handler(self):
|
|
cmd = TestCommand(None, None)
|
|
cmd.conflict_handler = 'wrong'
|
|
self.assertRaises(
|
|
ValueError,
|
|
cmd.get_parser,
|
|
'NAME',
|
|
)
|