diff options
author | Jenkins <jenkins@review.openstack.org> | 2015-09-12 00:54:47 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2015-09-12 00:54:47 +0000 |
commit | 0c813d068b0d69fd141697378d5854389d22e282 (patch) | |
tree | 48d4aaa3f585bba8e06bc2d29e758f448a16fcd0 | |
parent | ba69524e05578d1efae9aace3c4c7a8d25f77b2f (diff) | |
parent | 8c553fd4394a7f889627aca4f304e10168d3fd2c (diff) | |
download | trove-0c813d068b0d69fd141697378d5854389d22e282.tar.gz |
Merge "Add user and database actions int-tests"
-rw-r--r-- | trove/tests/int_tests.py | 32 | ||||
-rw-r--r-- | trove/tests/scenario/groups/database_actions_group.py | 63 | ||||
-rw-r--r-- | trove/tests/scenario/groups/user_actions_group.py | 94 | ||||
-rw-r--r-- | trove/tests/scenario/runners/database_actions_runners.py | 184 | ||||
-rw-r--r-- | trove/tests/scenario/runners/user_actions_runners.py | 307 |
5 files changed, 670 insertions, 10 deletions
diff --git a/trove/tests/int_tests.py b/trove/tests/int_tests.py index ff203bba..9ca0d967 100644 --- a/trove/tests/int_tests.py +++ b/trove/tests/int_tests.py @@ -36,10 +36,12 @@ from trove.tests.api import users from trove.tests.api import versions from trove.tests.scenario.groups import backup_group from trove.tests.scenario.groups import cluster_actions_group +from trove.tests.scenario.groups import database_actions_group from trove.tests.scenario.groups import instance_actions_group from trove.tests.scenario.groups import instance_delete_group from trove.tests.scenario.groups import negative_cluster_actions_group from trove.tests.scenario.groups import replication_group +from trove.tests.scenario.groups import user_actions_group GROUP_SERVICES_INITIALIZE = "services.initialize" @@ -127,6 +129,12 @@ initial_groups = [ backup_groups = list(initial_groups) backup_groups.extend([backup_group.GROUP]) +user_actions_groups = list(initial_groups) +user_actions_groups.extend([user_actions_group.GROUP]) + +database_actions_groups = list(initial_groups) +database_actions_groups.extend([database_actions_group.GROUP]) + cluster_actions_groups = list(initial_groups) cluster_actions_groups.extend([cluster_actions_group.GROUP, negative_cluster_actions_group.GROUP]) @@ -140,22 +148,26 @@ replication_groups.extend([replication_group.GROUP]) # Module based groups register(["backup"], backup_groups) register(["cluster"], cluster_actions_groups) +register(["database"], database_actions_group) register(["instance_actions"], instance_actions_groups) +register(["user"], user_actions_groups) register(["replication"], replication_groups) # Datastore based groups - these should contain all functionality # currently supported by the datastore -register(["cassandra_group"], backup_groups, instance_actions_groups) -register(["couchbase_group"], instance_actions_groups) -register(["postgresql_group"], backup_groups, instance_actions_groups) -register(["mongodb_group"], backup_groups, cluster_actions_groups, - instance_actions_groups) -register(["mysql_group"], backup_groups, instance_actions_groups, +register(["cassandra_supported"], backup_groups, instance_actions_groups) +register(["couchbase_supported"], instance_actions_groups) +register(["postgresql_supported"], backup_groups, database_actions_groups, + instance_actions_groups, user_actions_groups) +register(["mongodb_supported"], backup_groups, cluster_actions_groups, + database_actions_groups, instance_actions_groups, user_actions_groups) +register(["mysql_supported"], backup_groups, database_actions_groups, + instance_actions_groups, replication_groups, user_actions_groups) +register(["redis_supported"], backup_groups, instance_actions_groups, replication_groups) -register(["redis_group"], backup_groups, instance_actions_groups, - replication_groups) -register(["vertica_group"], cluster_actions_groups, instance_actions_groups) -register(["pxc_group"], instance_actions_groups, cluster_actions_groups) +register(["vertica_supported"], cluster_actions_groups, + instance_actions_groups) +register(["pxc_supported"], instance_actions_groups, cluster_actions_groups) # Redis int-tests redis_group = [ diff --git a/trove/tests/scenario/groups/database_actions_group.py b/trove/tests/scenario/groups/database_actions_group.py new file mode 100644 index 00000000..232ca357 --- /dev/null +++ b/trove/tests/scenario/groups/database_actions_group.py @@ -0,0 +1,63 @@ +# Copyright 2015 Tesora Inc. +# All Rights Reserved. +# +# 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 proboscis import test + +from trove.tests.api.instances import GROUP_START_SIMPLE +from trove.tests.api.instances import WaitForGuestInstallationToFinish +from trove.tests.scenario.groups.test_group import TestGroup +from trove.tests.scenario.groups import user_actions_group + +GROUP = "dbaas.api.database_actions_tests" + + +@test(depends_on_groups=[GROUP_START_SIMPLE], groups=[GROUP], + runs_after=[WaitForGuestInstallationToFinish], + runs_after_groups=[user_actions_group.GROUP]) +class DatabaseActionsGroup(TestGroup): + + def __init__(self): + super(DatabaseActionsGroup, self).__init__( + 'database_actions_runners', 'DatabaseActionsRunner') + + @test + def create_databases(self): + self.test_runner.run_databases_create() + + @test(depends_on=[create_databases]) + def list_databases(self): + self.test_runner.run_databases_list() + + @test(depends_on=[create_databases], + runs_after=[list_databases]) + def negative_create_database(self): + self.test_runner.run_negative_database_create() + + @test(depends_on=[create_databases], + runs_after=[negative_create_database]) + def delete_database(self): + self.test_runner.run_database_delete() + + @test + def nonexisting_database_delete(self): + self.test_runner.run_nonexisting_database_delete() + + @test + def system_database_create(self): + self.test_runner.run_system_database_create() + + @test + def system_database_delete(self): + self.test_runner.run_system_database_delete() diff --git a/trove/tests/scenario/groups/user_actions_group.py b/trove/tests/scenario/groups/user_actions_group.py new file mode 100644 index 00000000..92d3846e --- /dev/null +++ b/trove/tests/scenario/groups/user_actions_group.py @@ -0,0 +1,94 @@ +# Copyright 2015 Tesora Inc. +# All Rights Reserved. +# +# 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 proboscis import test + +from trove.tests.api.instances import GROUP_START_SIMPLE +from trove.tests.api.instances import WaitForGuestInstallationToFinish +from trove.tests.scenario.groups import instance_actions_group +from trove.tests.scenario.groups.test_group import TestGroup + +GROUP = "dbaas.api.user_actions_tests" + + +@test(depends_on_groups=[GROUP_START_SIMPLE], groups=[GROUP], + runs_after=[WaitForGuestInstallationToFinish], + runs_after_groups=[instance_actions_group.GROUP]) +class UserActionsGroup(TestGroup): + + def __init__(self): + super(UserActionsGroup, self).__init__( + 'user_actions_runners', 'UserActionsRunner') + + @test + def create_users(self): + self.test_runner.run_users_create() + + @test(depends_on=[create_users]) + def show_user(self): + self.test_runner.run_user_show() + + @test(depends_on=[create_users], + runs_after=[show_user]) + def list_users(self): + self.test_runner.run_users_list() + + @test(depends_on=[create_users], + runs_after=[list_users]) + def negative_create_user(self): + self.test_runner.run_negative_user_create() + + @test(depends_on=[create_users], + runs_after=[list_users]) + def negative_user_attribute_update(self): + self.test_runner.run_negative_user_attribute_update() + + @test(depends_on=[create_users], + runs_after=[negative_user_attribute_update]) + def user_attribute_update(self): + self.test_runner.run_user_attribute_update() + + @test(depends_on=[create_users], + runs_after=[user_attribute_update]) + def delete_user(self): + self.test_runner.run_user_delete() + + @test + def nonexisting_user_show(self): + self.test_runner.run_nonexisting_user_show() + + @test + def nonexisting_user_attribute_update(self): + self.test_runner.run_nonexisting_user_update() + + @test + def nonexisting_user_delete(self): + self.test_runner.run_nonexisting_user_delete() + + @test + def system_user_create(self): + self.test_runner.run_system_user_create() + + @test + def system_user_show(self): + self.test_runner.run_system_user_show() + + @test + def system_user_attribute_update(self): + self.test_runner.run_system_user_attribute_update() + + @test + def system_user_delete(self): + self.test_runner.run_system_user_delete() diff --git a/trove/tests/scenario/runners/database_actions_runners.py b/trove/tests/scenario/runners/database_actions_runners.py new file mode 100644 index 00000000..c2da8f62 --- /dev/null +++ b/trove/tests/scenario/runners/database_actions_runners.py @@ -0,0 +1,184 @@ +# Copyright 2015 Tesora Inc. +# All Rights Reserved. +# +# 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 proboscis import asserts + +from trove.tests.scenario.runners.test_runners import TestRunner +from troveclient.compat import exceptions + + +class DatabaseActionsRunner(TestRunner): + + # TODO(pmalik): I believe the 202 (Accepted) should be replaced by + # 200 (OK) as the actions are generally very fast and their results + # available immediately upon execution of the request. This would + # likely require replacing GA casts with calls which I believe are + # more appropriate anyways. + + def run_databases_create(self, expected_http_code=202): + databases = [{"name": 'database1'}, + {"name": 'database2'}, + {"name": 'database3'}] + self.db_defs = self.assert_databases_create( + self.instance_info.id, databases, expected_http_code) + + def assert_databases_create(self, instance_id, serial_databases_def, + expected_http_code): + self.rd_client.databases.create(instance_id, serial_databases_def) + self.assert_client_code(expected_http_code) + return serial_databases_def + + def run_databases_list(self, expected_http_code=200): + self.assert_databases_list( + self.instance_info.id, self.db_defs, expected_http_code) + + def assert_databases_list(self, instance_id, expected_database_defs, + expected_http_code, limit=2): + full_list = self.rd_client.databases.list(instance_id) + self.assert_client_code(expected_http_code) + listed_databases = {database.name: database for database in full_list} + asserts.assert_is_none(full_list.next, + "Unexpected pagination in the list.") + + for database_def in expected_database_defs: + database_name = database_def['name'] + asserts.assert_true( + database_name in listed_databases, + "Database not included in the 'database-list' output: %s" % + database_name) + + # Check that the system (ignored) databases are not included in the + # output. + system_databases = self.get_system_databases() + asserts.assert_false( + any(name in listed_databases for name in system_databases), + "System databases should not be included in the 'database-list' " + "output.") + + # Test list pagination. + list_page = self.rd_client.databases.list(instance_id, limit=limit) + self.assert_client_code(expected_http_code) + + asserts.assert_true(len(list_page) <= limit) + asserts.assert_is_not_none(list_page.next, "List page is missing.") + marker = list_page.next + + self.assert_pagination_match(list_page, full_list, 0, limit) + self.assert_pagination_match( + list_page[-1:], full_list, limit - 1, limit) + + list_page = self.rd_client.databases.list(instance_id, marker=marker) + self.assert_client_code(expected_http_code) + self.assert_pagination_match( + list_page, full_list, limit, len(full_list)) + + def run_negative_database_create( + self, expected_exception=exceptions.BadRequest, + expected_http_code=400): + # Test with no attribites. + self.assert_databases_create_failure( + self.instance_info.id, {}, expected_exception, expected_http_code) + + # Test with empty database name attribute. + self.assert_databases_create_failure( + self.instance_info.id, {'name': ''}, + expected_exception, expected_http_code) + + # Test creating an existing database. + self.assert_databases_create_failure( + self.instance_info.id, self.db_defs[0], + expected_exception, expected_http_code) + + def assert_databases_create_failure( + self, instance_id, serial_databases_def, + expected_exception, expected_http_code): + self.assert_raises( + expected_exception, expected_http_code, + self.rd_client.databases.create, instance_id, serial_databases_def) + + def run_system_database_create( + self, expected_exception=exceptions.BadRequest, + expected_http_code=400): + # TODO(pmalik): Actions on system users and databases should probably + # return Forbidden 403 instead. The current error messages are + # confusing (talking about a malformed request). + system_databases = self.get_system_databases() + if system_databases: + for name in system_databases: + database_def = {'name': name, 'password': 'password1', + 'databases': []} + self.assert_databases_create_failure( + self.instance_info.id, database_def, + expected_exception, expected_http_code) + + def run_database_delete(self, expected_http_code=202): + for database_def in self.db_defs: + self.assert_database_delete( + self.instance_info.id, database_def['name'], + expected_http_code) + + def assert_database_delete( + self, + instance_id, + database_name, + expected_http_code): + self.rd_client.databases.delete(instance_id, database_name) + self.assert_client_code(expected_http_code) + + for database in self.rd_client.databases.list(instance_id): + if database.name == database_name: + asserts.fail( + "Database still listed after delete: %s" % + database_name) + + def run_nonexisting_database_delete(self, expected_http_code=202): + # Deleting a non-existing database is expected to succeed as if the + # database was deleted. + self.assert_database_delete( + self.instance_info.id, 'justashadow', expected_http_code) + + def run_system_database_delete( + self, expected_exception=exceptions.BadRequest, + expected_http_code=400): + # TODO(pmalik): Actions on system users and databases should probably + # return Forbidden 403 instead. The current error messages are + # confusing (talking about a malformed request). + system_databases = self.get_system_databases() + if system_databases: + for name in system_databases: + self.assert_database_delete_failure( + self.instance_info.id, name, + expected_exception, expected_http_code) + + def assert_database_delete_failure( + self, instance_id, database_name, + expected_exception, expected_http_code): + self.assert_raises(expected_exception, expected_http_code, + self.rd_client.databases.delete, + instance_id, database_name) + + def get_system_databases(self): + return self.get_datastore_config_property('ignore_dbs') + + +class MysqlDatabaseActionsRunner(DatabaseActionsRunner): + + def get_system_databases(self): + # It seems the client does not like this name. + # Does this particular name actually still have to be ignored after + # all the datadir changes? + return [name for name + in self.get_datastore_config_property('ignore_dbs') + if name != '#mysql50#lost+found'] diff --git a/trove/tests/scenario/runners/user_actions_runners.py b/trove/tests/scenario/runners/user_actions_runners.py new file mode 100644 index 00000000..88e7d0fc --- /dev/null +++ b/trove/tests/scenario/runners/user_actions_runners.py @@ -0,0 +1,307 @@ +# Copyright 2015 Tesora Inc. +# All Rights Reserved. +# +# 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 proboscis import asserts + +from trove.tests.scenario.runners.test_runners import TestRunner +from troveclient.compat import exceptions + + +class UserActionsRunner(TestRunner): + + # TODO(pmalik): I believe the 202 (Accepted) should be replaced by + # 200 (OK) as the actions are generally very fast and their results + # available immediately upon execution of the request. This would + # likely require replacing GA casts with calls which I believe are + # more appropriate anyways. + + def run_users_create(self, expected_http_code=202): + users = [{'name': 'nodbguy', 'password': 'password1', + 'databases': []}, + {'name': 'singledbguy', 'password': 'password1', + 'databases': [{'name': 'db1'}]}, + {'name': 'multidbguy', 'password': 'password1', + 'databases': [{'name': 'db1', 'name': 'db2'}]}] + self.user_defs = self.assert_users_create( + self.instance_info.id, users, expected_http_code) + + def assert_users_create(self, instance_id, serial_users_def, + expected_http_code): + self.rd_client.users.create(instance_id, serial_users_def) + self.assert_client_code(expected_http_code) + return serial_users_def + + def run_user_show(self, expected_http_code=200): + for user_def in self.user_defs: + self.assert_user_show( + self.instance_info.id, user_def, expected_http_code) + + def assert_user_show(self, instance_id, expected_user_def, + expected_http_code): + user_name = expected_user_def['name'] + queried_user = self.rd_client.users.get(instance_id, user_name, '%') + self.assert_client_code(expected_http_code) + self._assert_user_matches(queried_user, expected_user_def) + + def _assert_user_matches(self, user, expected_user_def): + user_name = expected_user_def['name'] + asserts.assert_equal(user.name, expected_user_def['name'], + "Mismatch of names for user: %s" % user_name) + asserts.assert_equal(user.databases, expected_user_def['databases'], + "Mismatch of databases for user: %s" % user_name) + + def run_users_list(self, expected_http_code=200): + self.assert_users_list( + self.instance_info.id, self.user_defs, expected_http_code) + + def assert_users_list(self, instance_id, expected_user_defs, + expected_http_code, limit=2): + full_list = self.rd_client.users.list(instance_id) + self.assert_client_code(expected_http_code) + listed_users = {user.name: user for user in full_list} + asserts.assert_is_none(full_list.next, + "Unexpected pagination in the list.") + + for user_def in expected_user_defs: + user_name = user_def['name'] + asserts.assert_true( + user_name in listed_users, + "User not included in the 'user-list' output: %s" % + user_name) + self._assert_user_matches(listed_users[user_name], user_def) + + # Check that the system (ignored) users are not included in the output. + system_users = self.get_system_users() + asserts.assert_false( + any(name in listed_users for name in system_users), + "System users should not be included in the 'user-list' output.") + + # Test list pagination. + list_page = self.rd_client.users.list(instance_id, limit=limit) + self.assert_client_code(expected_http_code) + + asserts.assert_true(len(list_page) <= limit) + asserts.assert_is_not_none(list_page.next, "List page is missing.") + marker = list_page.next + + self.assert_pagination_match(list_page, full_list, 0, limit) + self.assert_pagination_match( + list_page[-1:], full_list, limit - 1, limit) + + list_page = self.rd_client.users.list(instance_id, marker=marker) + self.assert_client_code(expected_http_code) + self.assert_pagination_match( + list_page, full_list, limit, len(full_list)) + + def run_negative_user_create( + self, expected_exception=exceptions.BadRequest, + expected_http_code=400): + # Test with no attribites. + self.assert_users_create_failure( + self.instance_info.id, {}, expected_exception, expected_http_code) + + # Test with missing user name attribute. + self.assert_users_create_failure( + self.instance_info.id, + {'password': 'password1', 'databases': []}, + expected_exception, expected_http_code) + + # Test with empty user name attribute. + self.assert_users_create_failure( + self.instance_info.id, + {'name': '', 'password': 'password1', 'databases': []}, + expected_exception, expected_http_code) + + # Test with missing password attribute. + self.assert_users_create_failure( + self.instance_info.id, + {'name': 'nopassguy', 'databases': []}, + expected_exception, expected_http_code) + + # Test with missing databases attribute. + self.assert_users_create_failure( + self.instance_info.id, + {'name': 'nodbguy', 'password': 'password1'}, + expected_exception, expected_http_code) + + # Test creating an existing user. + self.assert_users_create_failure( + self.instance_info.id, self.user_defs[0], + expected_exception, expected_http_code) + + def run_system_user_create( + self, expected_exception=exceptions.BadRequest, + expected_http_code=400): + # TODO(pmalik): Actions on system users and databases should probably + # return Forbidden 403 instead. The current error messages are + # confusing (talking about a malformed request). + system_users = self.get_system_users() + if system_users: + for name in system_users: + user_def = {'name': name, 'password': 'password1', + 'databases': []} + self.assert_users_create_failure( + self.instance_info.id, user_def, + expected_exception, expected_http_code) + + def assert_users_create_failure( + self, instance_id, serial_users_def, + expected_exception, expected_http_code): + self.assert_raises( + expected_exception, expected_http_code, + self.rd_client.users.create, instance_id, serial_users_def) + + def run_negative_user_attribute_update( + self, expected_exception=exceptions.BadRequest, + expected_http_code=400): + # Test some basic invalid attributes on an existing user. + + # Test with no attribites. + # Note: this is caught on the client-side. + self.assert_user_attribute_update_failure( + self.instance_info.id, 'nodbguy', {}, Exception, None) + + # Test with empty user name. + self.assert_user_attribute_update_failure( + self.instance_info.id, 'nodbguy', {'name': ''}, + expected_exception, expected_http_code) + + # Test updating an existing user with a conflicting name. + self.assert_user_attribute_update_failure( + self.instance_info.id, self.user_defs[0]['name'], + {'name': self.user_defs[1]['name']}, + expected_exception, expected_http_code) + + def assert_user_attribute_update_failure( + self, instance_id, user_name, update_attribites, + expected_exception, expected_http_code): + self.assert_raises( + expected_exception, expected_http_code, + self.rd_client.users.update_attributes, instance_id, + user_name, update_attribites) + + def run_system_user_attribute_update( + self, expected_exception=exceptions.BadRequest, + expected_http_code=400): + # TODO(pmalik): Actions on system users and databases should probably + # return Forbidden 403 instead. The current error messages are + # confusing (talking about a malformed request). + system_users = self.get_system_users() + if system_users: + for name in system_users: + update_attribites = {'name': name, 'password': 'password2'} + self.assert_user_attribute_update_failure( + self.instance_info.id, name, update_attribites, + expected_exception, expected_http_code) + + def run_user_attribute_update(self, expected_http_code=202): + update_attribites = {'name': 'dblessguy', 'password': 'password2'} + self.assert_user_attribute_update( + self.instance_info.id, 'nodbguy', update_attribites, + expected_http_code) + + def assert_user_attribute_update(self, instance_id, user_name, + update_attribites, expected_http_code): + self.rd_client.users.update_attributes( + instance_id, user_name, update_attribites) + self.assert_client_code(expected_http_code) + + # Update the stored definitions with the new value. + expected_def = None + for user_def in self.user_defs: + if user_def['name'] == user_name: + user_def.update(update_attribites) + expected_def = user_def + + # Verify using 'user-show' and 'user-list'. + self.assert_user_show(instance_id, expected_def, 200) + self.assert_users_list(instance_id, self.user_defs, 200) + + def run_user_delete(self, expected_http_code=202): + for user_def in self.user_defs: + self.assert_user_delete( + self.instance_info.id, user_def['name'], expected_http_code) + + def assert_user_delete(self, instance_id, user_name, expected_http_code): + self.rd_client.users.delete(instance_id, user_name) + self.assert_client_code(expected_http_code) + + self.assert_raises(exceptions.NotFound, 404, + self.rd_client.users.get, + instance_id, user_name, '%') + + for user in self.rd_client.users.list(instance_id): + if user.name == user_name: + asserts.fail("User still listed after delete: %s" % user_name) + + def run_nonexisting_user_show( + self, expected_exception=exceptions.NotFound, + expected_http_code=404): + self.assert_user_show_failure(self.instance_info.id, 'nonexistingusr', + expected_exception, expected_http_code) + + def assert_user_show_failure(self, instance_id, user_name, + expected_exception, expected_http_code): + self.assert_raises( + expected_exception, expected_http_code, + self.rd_client.users.get, instance_id, user_name, '%') + + def run_system_user_show( + self, expected_exception=exceptions.BadRequest, + expected_http_code=400): + # TODO(pmalik): Actions on system users and databases should probably + # return Forbidden 403 instead. The current error messages are + # confusing (talking about a malformed request). + system_users = self.get_system_users() + if system_users: + for name in system_users: + self.assert_user_show_failure( + self.instance_info.id, name, + expected_exception, expected_http_code) + + def run_nonexisting_user_update(self, expected_http_code=404): + # Test valid update on a non-existing user. + self.assert_user_attribute_update_failure( + self.instance_info.id, 'nonexistingusr', {'name': 'justashadow'}, + exceptions.NotFound, expected_http_code) + + def run_nonexisting_user_delete( + self, expected_exception=exceptions.NotFound, + expected_http_code=404): + self.assert_user_delete_failure(self.instance_info.id, 'justashadow', + expected_exception, expected_http_code) + + def assert_user_delete_failure( + self, instance_id, user_name, + expected_exception, expected_http_code): + self.assert_raises(expected_exception, expected_http_code, + self.rd_client.users.delete, + instance_id, user_name) + + def run_system_user_delete( + self, expected_exception=exceptions.BadRequest, + expected_http_code=400): + # TODO(pmalik): Actions on system users and databases should probably + # return Forbidden 403 instead. The current error messages are + # confusing (talking about a malformed request). + system_users = self.get_system_users() + if system_users: + for name in system_users: + self.assert_user_delete_failure( + self.instance_info.id, name, + expected_exception, expected_http_code) + + def get_system_users(self): + return self.get_datastore_config_property('ignore_users') |