From a85254409093b44cc97bf255a6bf428a54cfbc7c Mon Sep 17 00:00:00 2001 From: Ivan Kolodyazhny Date: Fri, 14 Feb 2020 14:38:42 +0200 Subject: [PATCH] Convert project-list related tests to mock Change-Id: I62020a1c2069fb6281b10cdd79c1da33e86ab8b3 --- openstack_auth/tests/unit/test_auth.py | 299 +++++++++++++++---------- openstack_auth/utils.py | 4 +- 2 files changed, 177 insertions(+), 126 deletions(-) diff --git a/openstack_auth/tests/unit/test_auth.py b/openstack_auth/tests/unit/test_auth.py index fd2d7b070b..8d18de92dc 100644 --- a/openstack_auth/tests/unit/test_auth.py +++ b/openstack_auth/tests/unit/test_auth.py @@ -23,10 +23,12 @@ from keystoneauth1.identity import v3 as v3_auth from keystoneauth1 import session from keystoneauth1 import token_endpoint from keystoneclient.v3 import client as client_v3 +from keystoneclient.v3 import projects import mock from mox3 import mox -from testscenarios import load_tests_apply_scenarios + +from openstack_auth.plugin import password from openstack_auth.tests import data_v3 from openstack_auth import utils @@ -34,6 +36,17 @@ from openstack_auth import utils DEFAULT_DOMAIN = settings.OPENSTACK_KEYSTONE_DEFAULT_DOMAIN +# NOTE(e0ne): it's copy-pasted from horizon.test.helpers module until we +# figure out how to avoid this. +class IsA(object): + """Class to compare param is a specified class.""" + def __init__(self, cls): + self.cls = cls + + def __eq__(self, other): + return isinstance(other, self.cls) + + class OpenStackAuthTestsMixin(object): '''Common functions for version specific tests.''' @@ -239,83 +252,6 @@ class OpenStackAuthTestsV3(OpenStackAuthTestsMixin, self.mox.StubOutClassWithMocks(client_v3, 'Client') self.mox.StubOutClassWithMocks(v3_auth, 'Keystone2Keystone') - def test_login_with_disabled_project(self): - # Test to validate that authentication will not try to get - # scoped token for disabled project. - projects = [self.data.project_two, self.data.project_one] - user = self.data.user - unscoped = self.data.unscoped_access_info - - form_data = self.get_form_data(user) - self._mock_unscoped_and_domain_list_projects(user, projects) - self._mock_scoped_client_for_tenant(unscoped, self.data.project_one.id) - self.mox.ReplayAll() - - url = reverse('login') - - # GET the page to set the test cookie. - response = self.client.get(url, form_data) - self.assertEqual(response.status_code, 200) - - # POST to the page to log in. - response = self.client.post(url, form_data) - self.assertRedirects(response, settings.LOGIN_REDIRECT_URL) - - def test_no_enabled_projects(self): - projects = [self.data.project_two] - user = self.data.user - - form_data = self.get_form_data(user) - - self._mock_unscoped_and_domain_list_projects(user, projects) - self.mox.ReplayAll() - - url = reverse('login') - - # GET the page to set the test cookie. - response = self.client.get(url, form_data) - self.assertEqual(response.status_code, 200) - - # POST to the page to log in. - response = self.client.post(url, form_data) - self.assertRedirects(response, settings.LOGIN_REDIRECT_URL) - - def test_no_projects(self): - user = self.data.user - form_data = self.get_form_data(user) - - self._mock_unscoped_and_domain_list_projects(user, []) - self.mox.ReplayAll() - - url = reverse('login') - - # GET the page to set the test cookie. - response = self.client.get(url, form_data) - self.assertEqual(response.status_code, 200) - - # POST to the page to log in. - response = self.client.post(url, form_data) - self.assertRedirects(response, settings.LOGIN_REDIRECT_URL) - - def test_fail_projects(self): - user = self.data.user - - form_data = self.get_form_data(user) - self._mock_unscoped_client_list_projects_fail(user) - self.mox.ReplayAll() - - url = reverse('login') - - # GET the page to set the test cookie. - response = self.client.get(url, form_data) - self.assertEqual(response.status_code, 200) - - # POST to the page to log in. - response = self.client.post(url, form_data) - self.assertTemplateUsed(response, 'auth/login.html') - self.assertContains(response, - 'Unable to retrieve authorized projects.') - def test_switch(self, next=None): project = self.data.project_two projects = [self.data.project_one, self.data.project_two] @@ -650,50 +586,6 @@ class OpenStackAuthTestsV3(OpenStackAuthTestsMixin, unscoped.auth_token) self.assertEqual(self.client.session['k2k_auth_url'], auth_url) - def test_tenant_sorting(self): - projects = [self.data.project_two, self.data.project_one] - expected_projects = [self.data.project_one, self.data.project_two] - user = self.data.user - unscoped = self.data.unscoped_access_info - - client = self._mock_unscoped_client_with_token(user, unscoped) - self._mock_unscoped_list_projects(client, user, projects) - self.mox.ReplayAll() - - project_list = utils.get_project_list( - user_id=user.id, - auth_url=settings.OPENSTACK_KEYSTONE_URL, - token=unscoped.auth_token) - self.assertEqual(project_list, expected_projects) - - def test_login_form_multidomain(self): - override = self.settings(OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT=True) - override.enable() - self.addCleanup(override.disable) - - url = reverse('login') - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - self.assertContains(response, 'id="id_domain"') - self.assertContains(response, 'name="domain"') - - def test_login_form_multidomain_dropdown(self): - override = self.settings(OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT=True, - OPENSTACK_KEYSTONE_DOMAIN_DROPDOWN=True, - OPENSTACK_KEYSTONE_DOMAIN_CHOICES=( - ('Default', 'Default'),) - ) - override.enable() - self.addCleanup(override.disable) - - url = reverse('login') - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - self.assertContains(response, 'id="id_domain"') - self.assertContains(response, 'name="domain"') - self.assertContains(response, 'option value="Default"') - settings.OPENSTACK_KEYSTONE_DOMAIN_DROPDOWN = False - class OpenStackAuthTestsWebSSO(OpenStackAuthTestsMixin, OpenStackAuthFederatedTestsMixin, @@ -997,5 +889,166 @@ class OpenStackAuthTestsV3WithMock(test.TestCase): self.assertIsInstance(mock_get_access.call_args_list[0][0][0], session.Session) + def test_login_form_multidomain(self): + override = self.settings(OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT=True) + override.enable() + self.addCleanup(override.disable) -load_tests = load_tests_apply_scenarios + url = reverse('login') + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'id="id_domain"') + self.assertContains(response, 'name="domain"') + + def test_login_form_multidomain_dropdown(self): + override = self.settings(OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT=True, + OPENSTACK_KEYSTONE_DOMAIN_DROPDOWN=True, + OPENSTACK_KEYSTONE_DOMAIN_CHOICES=( + ('Default', 'Default'),) + ) + override.enable() + self.addCleanup(override.disable) + + url = reverse('login') + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'id="id_domain"') + self.assertContains(response, 'name="domain"') + self.assertContains(response, 'option value="Default"') + settings.OPENSTACK_KEYSTONE_DOMAIN_DROPDOWN = False + + @mock.patch.object(projects.ProjectManager, 'list') + def test_tenant_sorting(self, mock_project_list): + projects = [self.data.project_two, self.data.project_one] + expected_projects = [self.data.project_one, self.data.project_two] + user = self.data.user + unscoped = self.data.unscoped_access_info + + mock_project_list.return_value = projects + + project_list = utils.get_project_list( + user_id=user.id, + auth_url=settings.OPENSTACK_KEYSTONE_URL, + token=unscoped.auth_token) + self.assertEqual(project_list, expected_projects) + + mock_project_list.assert_called_once() + + @mock.patch.object(v3_auth.Token, 'get_access') + @mock.patch.object(password.PasswordPlugin, 'list_projects') + @mock.patch.object(v3_auth.Password, 'get_access') + def test_login_with_disabled_project(self, mock_access, mock_project_list, + mock_token): + # Test to validate that authentication will not try to get + # scoped token for disabled project. + projects = [self.data.project_two, self.data.project_one] + user = self.data.user + + mock_access.return_value = self.data.unscoped_access_info + mock_project_list.return_value = projects + mock_token.return_value = self.data.unscoped_access_info + + form_data = self.get_form_data(user) + + url = reverse('login') + + # GET the page to set the test cookie. + response = self.client.get(url, form_data) + self.assertEqual(response.status_code, 200) + + # POST to the page to log in. + response = self.client.post(url, form_data) + self.assertRedirects(response, settings.LOGIN_REDIRECT_URL) + mock_access.assert_called_once_with(IsA(session.Session)) + mock_token.assert_called_with(IsA(session.Session)) + mock_project_list.assert_called_once_with( + IsA(session.Session), + IsA(v3_auth.Password), + self.data.unscoped_access_info) + + @mock.patch.object(v3_auth.Token, 'get_access') + @mock.patch.object(password.PasswordPlugin, 'list_projects') + @mock.patch.object(v3_auth.Password, 'get_access') + def test_no_enabled_projects(self, mock_access, mock_project_list, + mock_token): + projects = [self.data.project_two] + user = self.data.user + + mock_access.return_value = self.data.unscoped_access_info + mock_project_list.return_value = projects + mock_token.return_value = self.data.unscoped_access_info + + form_data = self.get_form_data(user) + + url = reverse('login') + + # GET the page to set the test cookie. + response = self.client.get(url, form_data) + self.assertEqual(response.status_code, 200) + + # POST to the page to log in. + response = self.client.post(url, form_data) + self.assertRedirects(response, settings.LOGIN_REDIRECT_URL) + + mock_access.assert_called_once_with(IsA(session.Session)) + mock_token.assert_called_with(IsA(session.Session)) + mock_project_list.assert_called_once_with( + IsA(session.Session), + IsA(v3_auth.Password), + self.data.unscoped_access_info) + + @mock.patch.object(v3_auth.Token, 'get_access') + @mock.patch.object(password.PasswordPlugin, 'list_projects') + @mock.patch.object(v3_auth.Password, 'get_access') + def test_no_projects(self, mock_access, mock_project_list, mock_token): + user = self.data.user + form_data = self.get_form_data(user) + + mock_access.return_value = self.data.unscoped_access_info + mock_token.return_value = self.data.unscoped_access_info + mock_project_list.return_value = [] + + url = reverse('login') + + # GET the page to set the test cookie. + response = self.client.get(url, form_data) + self.assertEqual(response.status_code, 200) + + # POST to the page to log in. + response = self.client.post(url, form_data) + self.assertRedirects(response, settings.LOGIN_REDIRECT_URL) + + mock_access.assert_called_once_with(IsA(session.Session)) + mock_token.assert_called_with(IsA(session.Session)) + mock_project_list.assert_called_once_with( + IsA(session.Session), + IsA(v3_auth.Password), + self.data.unscoped_access_info) + + @mock.patch.object(v3_auth.Token, 'get_access') + @mock.patch.object(projects.ProjectManager, 'list') + @mock.patch.object(v3_auth.Password, 'get_access') + def test_fail_projects(self, mock_access, mock_project_list, mock_token): + user = self.data.user + + form_data = self.get_form_data(user) + + mock_access.return_value = self.data.unscoped_access_info + mock_token.return_value = self.data.unscoped_access_info + mock_project_list.side_effect = keystone_exceptions.AuthorizationFailure + + url = reverse('login') + + # GET the page to set the test cookie. + response = self.client.get(url, form_data) + self.assertEqual(response.status_code, 200) + + # POST to the page to log in. + response = self.client.post(url, form_data) + self.assertTemplateUsed(response, 'auth/login.html') + self.assertContains(response, + 'Unable to retrieve authorized projects.') + + mock_access.assert_called_once_with(IsA(session.Session)) + mock_token.assert_called_with(IsA(session.Session)) + mock_project_list.assert_called_once_with(user=user.id) diff --git a/openstack_auth/utils.py b/openstack_auth/utils.py index 331ef98172..8f5ad177eb 100644 --- a/openstack_auth/utils.py +++ b/openstack_auth/utils.py @@ -341,9 +341,7 @@ def get_project_list(*args, **kwargs): auth = token_endpoint.Token(auth_url, kwargs['token']) client = get_keystone_client().Client(session=sess, auth=auth) - if get_keystone_version() < 3: - projects = client.tenants.list() - elif is_federated: + if is_federated: projects = client.federation.projects.list() else: projects = client.projects.list(user=kwargs.get('user_id'))