Added unit tests for ringbuilder command-line utility

Added new unit tests:

test_add_device_old_missing_region
test_create_ring_number_of_arguments
test_add_duplicate_devices
test_rebalance_with_seed
test_set_overload_number_of_arguments
test_main_no_arguments
test_main_single_argument
test_main_with_safe

Modified existing unit tests to create sample ring at start of test.
This change was needed to have unit tests run correctly and demonstrate
code coverage.

test_unknown
test_search_device_number_of_arguments
test_list_parts_number_of_arguments
test_set_weight_number_of_arguments
test_set_info_number_of_arguments
test_remove_device_number_of_arguments
test_set_min_part_hours_number_of_arguments
test_set_replicas_number_of_arguments
test_set_replicas_invalid_value

Updates to handled nested mocks.
Updates to handle no exception case when SystemExit is expected.
PEP8 corrections.

Moved new tests from try blocks to use of assertRaises or call to
run_srb using exp_results with specified exit codes.

Updated run_srb to accept a dictionary of expected results. Specifically,
look for 'valid_exit_codes' to test, default to (0,1).

Change-Id: I4cf3f5f055a9babba140c68a9c7ff90b9c50ea62
This commit is contained in:
Paul Dardeau 2015-10-28 22:25:24 +00:00
parent e75dc8028b
commit 7f4139bc26

View File

@ -29,13 +29,19 @@ from swift.common.ring import RingBuilder
class RunSwiftRingBuilderMixin(object):
def run_srb(self, *argv):
def run_srb(self, *argv, **kwargs):
if len(argv) == 1 and isinstance(argv[0], six.string_types):
# convert a single string to a list
argv = shlex.split(argv[0])
mock_stdout = six.StringIO()
mock_stderr = six.StringIO()
if 'exp_results' in kwargs:
exp_results = kwargs['exp_results']
argv = argv[:-1]
else:
exp_results = None
srb_args = ["", self.tempfile] + [str(s) for s in argv]
try:
@ -43,7 +49,13 @@ class RunSwiftRingBuilderMixin(object):
with mock.patch("sys.stderr", mock_stderr):
ringbuilder.main(srb_args)
except SystemExit as err:
if err.code not in (0, 1): # (success, warning)
valid_exit_codes = None
if exp_results is not None and 'valid_exit_codes' in exp_results:
valid_exit_codes = exp_results['valid_exit_codes']
else:
valid_exit_codes = (0, 1) # (success, warning)
if err.code not in valid_exit_codes:
msg = 'Unexpected exit status %s\n' % err.code
msg += 'STDOUT:\n%s\nSTDERR:\n%s\n' % (
mock_stdout.getvalue(), mock_stderr.getvalue())
@ -282,6 +294,11 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
self.assertEqual(ring.replicas, 3.14159265359)
self.assertEqual(ring.min_part_hours, 1)
def test_create_ring_number_of_arguments(self):
# Test missing arguments
argv = ["", self.tmpfile, "create"]
self.assertRaises(SystemExit, ringbuilder.main, argv)
def test_add_device_ipv4_old_format(self):
self.create_sample_ring()
# Test ipv4(old format)
@ -302,6 +319,14 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
self.assertEqual(dev['replication_port'], 6000)
self.assertEqual(dev['meta'], 'some meta data')
def test_add_duplicate_devices(self):
self.create_sample_ring()
# Test adding duplicate devices
argv = ["", self.tmpfile, "add",
"r1z1-127.0.0.1:6000/sda9", "3.14159265359",
"r1z1-127.0.0.1:6000/sda9", "2"]
self.assertRaises(SystemExit, ringbuilder.main, argv)
def test_add_device_ipv6_old_format(self):
self.create_sample_ring()
# Test ipv6(old format)
@ -439,6 +464,18 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
err = e
self.assertEqual(err.code, 2)
def test_add_device_old_missing_region(self):
self.create_sample_ring()
# Test add device without specifying a region
argv = ["", self.tmpfile, "add",
"z3-127.0.0.1:6000/sde3_some meta data", "3.14159265359"]
exp_results = {'valid_exit_codes': [2]}
self.run_srb(*argv, exp_results=exp_results)
# Check that ring was created with sane value for region
ring = RingBuilder.load(self.tmpfile)
dev = ring.devs[-1]
self.assertTrue(dev['region'] > 0)
def test_remove_device(self):
for search_value in self.search_values:
self.create_sample_ring()
@ -700,6 +737,7 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
self.assertTrue(ring.validate())
def test_remove_device_number_of_arguments(self):
self.create_sample_ring()
# Test Number of arguments abnormal
argv = ["", self.tmpfile, "remove"]
err = None
@ -911,6 +949,7 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
self.assertTrue(ring.validate())
def test_set_weight_number_of_arguments(self):
self.create_sample_ring()
# Test Number of arguments abnormal
argv = ["", self.tmpfile, "set_weight"]
err = None
@ -1201,6 +1240,7 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
self.assertTrue(ring.validate())
def test_set_info_number_of_arguments(self):
self.create_sample_ring()
# Test Number of arguments abnormal
argv = ["", self.tmpfile, "set_info"]
err = None
@ -1253,6 +1293,7 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
self.assertEqual(ring.min_part_hours, 24)
def test_set_min_part_hours_number_of_arguments(self):
self.create_sample_ring()
# Test Number of arguments abnormal
argv = ["", self.tmpfile, "set_min_part_hours"]
err = None
@ -1326,7 +1367,14 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
self.assertTrue('1000.00%' in out)
self.assertTrue('10.000000' in out)
def test_set_overload_number_of_arguments(self):
self.create_sample_ring()
# Test missing arguments
argv = ["", self.tmpfile, "set_overload"]
self.assertRaises(SystemExit, ringbuilder.main, argv)
def test_set_replicas_number_of_arguments(self):
self.create_sample_ring()
# Test Number of arguments abnormal
argv = ["", self.tmpfile, "set_replicas"]
err = None
@ -1337,6 +1385,7 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
self.assertEqual(err.code, 2)
def test_set_replicas_invalid_value(self):
self.create_sample_ring()
# Test not a valid number
argv = ["", self.tmpfile, "set_replicas", "test"]
err = None
@ -1516,6 +1565,7 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
self.assertRaises(SystemExit, ringbuilder.main, argv)
def test_search_device_number_of_arguments(self):
self.create_sample_ring()
# Test Number of arguments abnormal
argv = ["", self.tmpfile, "search"]
err = None
@ -1628,6 +1678,7 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
self.assertRaises(SystemExit, ringbuilder.main, argv)
def test_list_parts_number_of_arguments(self):
self.create_sample_ring()
# Test Number of arguments abnormal
argv = ["", self.tmpfile, "list_parts"]
err = None
@ -1650,6 +1701,7 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
self.assertEqual(err.code, 2)
def test_unknown(self):
self.create_sample_ring()
argv = ["", self.tmpfile, "unknown"]
err = None
try:
@ -1754,6 +1806,12 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
self.assertTrue(ring.validate())
self.assertEqual(ring.devs[3], None)
def test_rebalance_with_seed(self):
self.create_sample_ring()
# Test rebalance using explicit seed parameter
argv = ["", self.tmpfile, "rebalance", "--seed", "2"]
self.assertRaises(SystemExit, ringbuilder.main, argv)
def test_write_ring(self):
self.create_sample_ring()
argv = ["", self.tmpfile, "rebalance"]
@ -1768,12 +1826,8 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
argv = ["", self.tmpfile, "rebalance"]
self.assertRaises(SystemExit, ringbuilder.main, argv)
argv = ["", self.tmpfile, "write_builder"]
err = None
try:
ringbuilder.main(argv)
except SystemExit as e:
err = e
self.assertEqual(err.code, 2)
exp_results = {'valid_exit_codes': [2]}
self.run_srb(*argv, exp_results=exp_results)
def test_write_builder_after_device_removal(self):
# Test regenerating builder file after having removed a device
@ -1896,6 +1950,22 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
"Ring Builder file does not exist: object.builder\n"
self.assertEqual(expected, mock_stdout.getvalue())
def test_main_no_arguments(self):
# Test calling main with no arguments
argv = []
self.assertRaises(SystemExit, ringbuilder.main, argv)
def test_main_single_argument(self):
# Test calling main with single argument
argv = [""]
self.assertRaises(SystemExit, ringbuilder.main, argv)
def test_main_with_safe(self):
# Test calling main with '-safe' argument
self.create_sample_ring()
argv = ["-safe", self.tmpfile]
self.assertRaises(SystemExit, ringbuilder.main, argv)
class TestRebalanceCommand(unittest.TestCase, RunSwiftRingBuilderMixin):