diff --git a/tuning_box/library/__init__.py b/tuning_box/library/__init__.py index ba2c7b9..dbf51dd 100644 --- a/tuning_box/library/__init__.py +++ b/tuning_box/library/__init__.py @@ -86,17 +86,15 @@ def get_resource_values(environment, levels, res_def): if not res_values: raise errors.TuningboxNotFound( "Resource values not found by environment {0}, " - "resource definition {1}, level {2} with value {3}".format( - environment.id, res_def.id, level_value.level.name, - level_value.value + "resource definition {1} for levels {2}".format( + environment.id, res_def.id, levels ) ) elif len(res_values) > 1: raise errors.TuningboxIntegrityError( "Found more than one resource values for environment {0}, " - "resource definition {1}, level {2} with value {3}".format( - environment.id, res_def.id, level_value.level.name, - level_value.value + "resource definition {1} for levels {2}".format( + environment.id, res_def.id, levels ) ) return res_values[0] diff --git a/tuning_box/library/hierarchy_levels.py b/tuning_box/library/hierarchy_levels.py index 18841c6..dc85e3d 100644 --- a/tuning_box/library/hierarchy_levels.py +++ b/tuning_box/library/hierarchy_levels.py @@ -11,22 +11,33 @@ # under the License. import flask -import werkzeug import flask_restful from flask_restful import fields from tuning_box import db +from tuning_box import errors def iter_environment_level_values(environment, levels): env_levels = db.EnvironmentHierarchyLevel.get_for_environment(environment) + if len(env_levels) < len(levels): + raise errors.TuningboxNotFound( + "Levels {0} can't be matched with " + "environment {1} levels: {2}".format( + [l[0] for l in levels], + environment.id, + [l.name for l in env_levels] + ) + ) level_pairs = zip(env_levels, levels) for env_level, (level_name, level_value) in level_pairs: if env_level.name != level_name: - raise werkzeug.exceptions.BadRequest( + raise errors.TuningboxNotFound( "Unexpected level name '{0}'. Expected '{1}'.".format( - level_name, env_level.name)) + level_name, env_level.name) + ) + level_value_db = db.get_or_create( db.EnvironmentHierarchyLevelValue, level=env_level, diff --git a/tuning_box/tests/library/test_hierarchy_levels.py b/tuning_box/tests/library/test_hierarchy_levels.py index 3fcb68e..de3ef63 100644 --- a/tuning_box/tests/library/test_hierarchy_levels.py +++ b/tuning_box/tests/library/test_hierarchy_levels.py @@ -10,9 +10,10 @@ # License for the specific language governing permissions and limitations # under the License. -import werkzeug +import six from tuning_box import db +from tuning_box import errors from tuning_box.library import hierarchy_levels from tuning_box.tests.test_app import BaseTest @@ -50,13 +51,13 @@ class TestLevelsHierarchy(BaseTest): self._fixture() with self.app.app_context(), db.db.session.begin(): exc = self.assertRaises( - werkzeug.exceptions.BadRequest, + errors.TuningboxNotFound, hierarchy_levels.get_environment_level_value, db.Environment(id=9), [('lvlx', 'val1')], ) self.assertEqual( - exc.description, + six.text_type(exc), "Unexpected level name 'lvlx'. Expected 'lvl1'.", ) diff --git a/tuning_box/tests/library/test_library.py b/tuning_box/tests/library/test_library.py index 1a39af2..64dbf6a 100644 --- a/tuning_box/tests/library/test_library.py +++ b/tuning_box/tests/library/test_library.py @@ -105,3 +105,7 @@ class TestLibrary(BaseTest): self.assertRaises(errors.TuningboxNotFound, library.get_resource_values, environment, levels, res_def) + # Test for empty levels + self.assertRaises(errors.TuningboxNotFound, + library.get_resource_values, environment, + (), res_def) diff --git a/tuning_box/tests/library/test_resource_values.py b/tuning_box/tests/library/test_resource_values.py index 880ead6..0534252 100644 --- a/tuning_box/tests/library/test_resource_values.py +++ b/tuning_box/tests/library/test_resource_values.py @@ -56,13 +56,14 @@ class TestResourceValues(BaseTest): self.assertIsNone(level.parent) def test_put_resource_values_bad_level(self): + self.app.config["PROPAGATE_EXCEPTIONS"] = True self._fixture() res = self.client.put('/environments/9/lvlx/1/resources/5/values', data={'k': 'v'}) - self.assertEqual(res.status_code, 400) + self.assertEqual(res.status_code, 404) self.assertEqual( - res.json, - {"message": "Unexpected level name 'lvlx'. Expected 'lvl1'."}, + {"msg": "Unexpected level name 'lvlx'. Expected 'lvl1'."}, + res.json ) with self.app.app_context(): resource_values = db.ResourceValues.query.filter_by( @@ -191,6 +192,46 @@ class TestResourceValues(BaseTest): self.assertEqual({'key': 'key_value', 'key_x': 'key_x_value'}, actual) + def test_put_resource_values_levels_mismatch(self): + self.app.config["PROPAGATE_EXCEPTIONS"] = True + self._fixture() + env_id = 9 + res_def_id = 5 + levels = (('lvl1', 'val1'), ('lvl2', 'val2'), ('lvl3', 'val3')) + values = {'key': 'val'} + + res = self._add_resource_values( + env_id, res_def_id, levels, values, expect_code=404) + self.assertEqual( + {'msg': "Levels [u'lvl1', u'lvl2', u'lvl3'] can't be matched with " + "environment 9 levels: [u'lvl1', u'lvl2']"}, + res.json + ) + + def test_put_resource_values_levels_mismatch_for_empty_levels(self): + self.app.config["PROPAGATE_EXCEPTIONS"] = True + self._fixture() + env_id = 9 + res_def_id = 5 + levels = (('lvl1', 'val1'), ('lvl2', 'val2'), ('lvl3', 'val3')) + values = {'key': 'val'} + + env_url = '/environments/{0}'.format(env_id) + res = self.client.put(env_url, data={'hierarchy_levels': []}) + self.assertEqual(204, res.status_code) + + res = self.client.get(env_url) + self.assertEqual(200, res.status_code) + self.assertEqual([], res.json['hierarchy_levels']) + + res = self._add_resource_values( + env_id, res_def_id, levels, values, expect_code=404) + self.assertEqual( + {'msg': "Levels [u'lvl1', u'lvl2', u'lvl3'] can't be matched with " + "environment 9 levels: []"}, + res.json + ) + def test_put_resource_values_set_no_levels(self): self._fixture() environment_id = 9 diff --git a/tuning_box/tests/test_app.py b/tuning_box/tests/test_app.py index 32e0bbc..6dc82f2 100644 --- a/tuning_box/tests/test_app.py +++ b/tuning_box/tests/test_app.py @@ -80,7 +80,7 @@ class BaseTest(base.TestCase): return levels_url def _add_resource_values(self, environment_id, res_def_id, - levels, values): + levels, values, expect_code=204): res = self.client.put( '/environments/{0}/{1}resources/{2}/values'.format( environment_id, @@ -89,7 +89,8 @@ class BaseTest(base.TestCase): ), data=values ) - self.assertEqual(res.status_code, 204) + self.assertEqual(expect_code, res.status_code) + return res def _add_resource_overrides(self, environment_id, res_def_id, levels, overrides):