From 7f4139bc2669de07f55e8689956d87d9c78cc834 Mon Sep 17 00:00:00 2001 From: Paul Dardeau Date: Wed, 28 Oct 2015 22:25:24 +0000 Subject: [PATCH] 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 --- test/unit/cli/test_ringbuilder.py | 86 ++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 8 deletions(-) diff --git a/test/unit/cli/test_ringbuilder.py b/test/unit/cli/test_ringbuilder.py index f8911ad21a..25200b35a9 100644 --- a/test/unit/cli/test_ringbuilder.py +++ b/test/unit/cli/test_ringbuilder.py @@ -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):