add validation for topology and post event for cli
* check that limit is a positive number in 'vitrage topology show' * check that time is an iso8601 timestamp in 'vitrage event post' * add tests to check this Change-Id: If5c4b26578f865c68709027b6e815376e4ee9e1e
This commit is contained in:
parent
17ea93b290
commit
471cc55dcd
@ -8,3 +8,4 @@ cliff>=2.6.0 # Apache-2.0
|
||||
osc-lib>=1.5.1 # Apache-2.0
|
||||
oslo.utils>=3.20.0 # Apache-2.0
|
||||
keystoneauth1>=2.21.0 # Apache-2.0
|
||||
iso8601>=0.1.11 # MIT
|
@ -13,3 +13,4 @@ testrepository>=0.0.18 # Apache-2.0/BSD
|
||||
testscenarios>=0.4 # Apache-2.0/BSD
|
||||
testtools>=1.4.0 # MIT
|
||||
reno!=2.3.1,>=1.8.0 # Apache-2.0
|
||||
mock>=2.0 # BSD
|
||||
|
2
tox.ini
2
tox.ini
@ -10,7 +10,7 @@ install_command =
|
||||
setenv = VIRTUAL_ENV={envdir}
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
commands = rm -f .testrepository/times.dbm
|
||||
commands = /bin/rm -f .testrepository/times.dbm
|
||||
python setup.py test --slowest --testr-args='{posargs}'
|
||||
|
||||
[testenv:pep8]
|
||||
|
@ -10,7 +10,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import exc
|
||||
from vitrageclient import exc
|
||||
|
||||
from keystoneauth1 import adapter as keystoneauth
|
||||
from oslo_utils import importutils
|
||||
|
@ -28,15 +28,15 @@ from cliff import app
|
||||
from cliff import commandmanager
|
||||
from keystoneauth1 import loading
|
||||
|
||||
import client
|
||||
|
||||
from v1.cli import alarm
|
||||
from v1.cli import event
|
||||
from v1.cli import rca
|
||||
from v1.cli import resource
|
||||
from v1.cli import template
|
||||
from v1.cli import topology
|
||||
from vitrageclient import __version__
|
||||
from vitrageclient import client
|
||||
|
||||
from vitrageclient.v1.cli import alarm
|
||||
from vitrageclient.v1.cli import event
|
||||
from vitrageclient.v1.cli import rca
|
||||
from vitrageclient.v1.cli import resource
|
||||
from vitrageclient.v1.cli import template
|
||||
from vitrageclient.v1.cli import topology
|
||||
|
||||
|
||||
class VitrageCommandManager(commandmanager.CommandManager):
|
||||
|
0
vitrageclient/tests/cli/__init__.py
Normal file
0
vitrageclient/tests/cli/__init__.py
Normal file
@ -11,10 +11,18 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# noinspection PyPackageRequirements
|
||||
import argparse
|
||||
|
||||
from oslotest import base
|
||||
|
||||
|
||||
class TestCase(base.BaseTestCase):
|
||||
class CliTestCase(base.BaseTestCase):
|
||||
|
||||
"""Test case base class for all unit tests."""
|
||||
|
||||
# original error method of argparse uses exit
|
||||
# I just want to raise an exception and get the error message
|
||||
# that exit outputs
|
||||
@staticmethod
|
||||
def _my_parser_error_func(message):
|
||||
raise argparse.ArgumentTypeError(message)
|
53
vitrageclient/tests/cli/test_event_post.py
Normal file
53
vitrageclient/tests/cli/test_event_post.py
Normal file
@ -0,0 +1,53 @@
|
||||
# Copyright 2017 Nokia
|
||||
#
|
||||
# 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.
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from argparse import ArgumentTypeError
|
||||
|
||||
# noinspection PyPackageRequirements
|
||||
import mock
|
||||
from testtools import ExpectedException
|
||||
|
||||
from vitrageclient.tests.cli.base import CliTestCase
|
||||
from vitrageclient.v1.cli.event import EventPost
|
||||
|
||||
|
||||
# noinspection PyAttributeOutsideInit
|
||||
class EventPostTest(CliTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(EventPostTest, self).setUp()
|
||||
self.event_post = EventPost(mock.Mock(), mock.Mock())
|
||||
|
||||
def test_parsing_iso8601_with_not_a_date_string(self):
|
||||
self.assertRaises(ArgumentTypeError, self.event_post.iso8601, 'bla')
|
||||
|
||||
def test_parsing_iso8601_in_a_good_format(self):
|
||||
self.event_post.iso8601('2014-12-13T12:44:21.123456')
|
||||
|
||||
def test_iso8601_parsing_with_wrong_date_format(self):
|
||||
self.assertRaises(ArgumentTypeError, self.event_post.iso8601,
|
||||
'2014/12/13 12:44:21')
|
||||
|
||||
@mock.patch.object(ArgumentParser, "error")
|
||||
def test_parser_event_post_with_not_a_date_string(self, mock_parser):
|
||||
mock_parser.side_effect = self._my_parser_error_func
|
||||
parser = self.event_post.get_parser('vitrage event post')
|
||||
|
||||
# noinspection PyCallByClass
|
||||
with ExpectedException(ArgumentTypeError,
|
||||
'argument --time: -5 must be an iso8601 date'):
|
||||
parser.parse_args(args=['--type', 'bla',
|
||||
'--time', '-5',
|
||||
'--details', 'blabla'])
|
71
vitrageclient/tests/cli/test_topology_show.py
Normal file
71
vitrageclient/tests/cli/test_topology_show.py
Normal file
@ -0,0 +1,71 @@
|
||||
# Copyright 2017 Nokia
|
||||
#
|
||||
# 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.
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from argparse import ArgumentTypeError
|
||||
|
||||
# noinspection PyPackageRequirements
|
||||
import mock
|
||||
# noinspection PyPackageRequirements
|
||||
from testtools import ExpectedException
|
||||
|
||||
from vitrageclient.tests.cli.base import CliTestCase
|
||||
from vitrageclient.v1.cli.topology import TopologyShow
|
||||
|
||||
|
||||
# noinspection PyAttributeOutsideInit
|
||||
class TopologyShowTest(CliTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TopologyShowTest, self).setUp()
|
||||
self.topology_show = TopologyShow(mock.Mock(), mock.Mock())
|
||||
|
||||
def test_positive_integer_validation_with_negative(self):
|
||||
self.assertRaises(ArgumentTypeError,
|
||||
self.topology_show.positive_non_zero_int, -1)
|
||||
|
||||
def test_positive_integer_validation_with_zero(self):
|
||||
self.assertRaises(ArgumentTypeError,
|
||||
self.topology_show.positive_non_zero_int, 0)
|
||||
|
||||
def test_positive_integer_validation_with_string(self):
|
||||
self.assertRaises(ArgumentTypeError,
|
||||
self.topology_show.positive_non_zero_int, 'bla')
|
||||
|
||||
def test_positive_integer_validation_with_positive(self):
|
||||
self.topology_show.positive_non_zero_int(1)
|
||||
|
||||
@mock.patch.object(ArgumentParser, "error")
|
||||
def test_parser_topology_limit_with_a_negative_number(self, mock_parser):
|
||||
mock_parser.side_effect = self._my_parser_error_func
|
||||
parser = self.topology_show.get_parser('vitrage topology show')
|
||||
|
||||
with ExpectedException(ArgumentTypeError,
|
||||
'argument --limit: -5 must be greater than 0'):
|
||||
parser.parse_args(args=['--filter', 'bla',
|
||||
'--limit', '-5',
|
||||
'--root', 'blabla',
|
||||
'--graph-type', 'tree'])
|
||||
|
||||
@mock.patch.object(ArgumentParser, "error")
|
||||
def test_parser_topology_limit_with_a_string(self, mock_parser):
|
||||
mock_parser.side_effect = self._my_parser_error_func
|
||||
parser = self.topology_show.get_parser('vitrage topology show')
|
||||
|
||||
with ExpectedException(ArgumentTypeError,
|
||||
'argument --limit: spam must be an integer'):
|
||||
parser.parse_args(args=['--filter', 'bla',
|
||||
'--limit', 'spam',
|
||||
'--root', 'blabla',
|
||||
'--graph-type', 'tree'])
|
@ -1,26 +0,0 @@
|
||||
# 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.
|
||||
|
||||
"""
|
||||
test_vitrageclient
|
||||
----------------------------------
|
||||
|
||||
Tests for `vitrageclient` module.
|
||||
"""
|
||||
|
||||
from vitrageclient.tests import base
|
||||
|
||||
|
||||
class TestVitrageclient(base.TestCase):
|
||||
|
||||
def test_something(self):
|
||||
pass
|
@ -14,8 +14,11 @@
|
||||
|
||||
import json
|
||||
|
||||
from cliff import argparse
|
||||
from cliff import command
|
||||
from datetime import datetime
|
||||
from iso8601 import iso8601
|
||||
from iso8601 import ParseError
|
||||
|
||||
from vitrageclient.common import exc
|
||||
|
||||
@ -24,6 +27,14 @@ from vitrageclient.common import exc
|
||||
class EventPost(command.Command):
|
||||
"""Show the event of the system"""
|
||||
|
||||
@staticmethod
|
||||
def iso8601(argument_value):
|
||||
try:
|
||||
iso8601.parse_date(argument_value)
|
||||
except ParseError:
|
||||
msg = "%s must be an iso8601 date" % argument_value
|
||||
raise argparse.ArgumentTypeError(msg)
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(EventPost, self).get_parser(prog_name)
|
||||
|
||||
@ -32,6 +43,7 @@ class EventPost(command.Command):
|
||||
|
||||
parser.add_argument('--time',
|
||||
default='',
|
||||
type=self.iso8601,
|
||||
help='The timestamp of the event in ISO 8601 '
|
||||
'format: YYYY-MM-DDTHH:MM:SS.mmmmmm. '
|
||||
'If not specified, the current time is used')
|
||||
|
@ -10,6 +10,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from cliff import argparse
|
||||
from cliff import show
|
||||
from vitrageclient.common import exc
|
||||
from vitrageclient.common import utils
|
||||
@ -19,6 +20,20 @@ from vitrageclient.common import utils
|
||||
class TopologyShow(show.ShowOne):
|
||||
"""Show the topology of the system"""
|
||||
|
||||
@staticmethod
|
||||
def positive_non_zero_int(argument_value):
|
||||
if argument_value is None:
|
||||
return None
|
||||
try:
|
||||
value = int(argument_value)
|
||||
except ValueError:
|
||||
msg = "%s must be an integer" % argument_value
|
||||
raise argparse.ArgumentTypeError(msg)
|
||||
if value <= 0:
|
||||
msg = "%s must be greater than 0" % argument_value
|
||||
raise argparse.ArgumentTypeError(msg)
|
||||
return value
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(TopologyShow, self).get_parser(prog_name)
|
||||
parser.add_argument('--filter',
|
||||
@ -26,7 +41,7 @@ class TopologyShow(show.ShowOne):
|
||||
help='query for the graph)')
|
||||
|
||||
parser.add_argument('--limit',
|
||||
type=int,
|
||||
type=self.positive_non_zero_int,
|
||||
metavar='<depth>',
|
||||
help='the depth of the topology graph')
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user