# -*- coding: utf-8 -*- ############################################################################## # # Copyright (c) 2007, Agendaless Consulting and Contributors. # Copyright (c) 2008, Florent Aide . # Copyright (c) 2008-2009, Gustavo Narea . # All Rights Reserved. # # This software is subject to the provisions of the BSD-like license at # http://www.repoze.org/LICENSE.txt. A copy of the license should accompany # this distribution. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL # EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND # FITNESS FOR A PARTICULAR PURPOSE. # ############################################################################## """Utilities to test source adapters.""" from repoze.what.adapters import SourceError, ExistingSectionError, \ NonExistingSectionError, \ ItemPresentError, ItemNotPresentError __all__ = ['GroupsAdapterTester', 'PermissionsAdapterTester', 'ReadOnlyGroupsAdapterTester', 'ReadOnlyPermissionsAdapterTester'] class _ReadOnlyBaseAdapterTester(object): """Base test case for read-only adapters""" def _get_all_items(self): all_items = set() for items in self.all_sections.values(): all_items |= items return all_items def _get_item_sections(self, item): return set([n for (n, s) in self.all_sections.items() if item in s]) def test_retrieving_all_sections(self): self.assertEqual(self.adapter._get_all_sections(), self.all_sections) def test_getting_section_items(self): for section_name, items in self.all_sections.items(): self.assertEqual(self.adapter._get_section_items(section_name), items) def test_checking_existing_section(self): for section_name in self.all_sections.keys(): assert self.adapter._section_exists(section_name), \ 'Section "%s" does NOT exist' % section_name def test_checking_non_existing_section(self): section_name = u'i_dont_exist' assert not self.adapter._section_exists(section_name), \ 'Section "%s" DOES exist' % section_name def test_checking_item_inclusion(self): for section_name, items in self.all_sections.items(): for item in self.adapter._get_section_items(section_name): assert self.adapter._item_is_included(section_name, item), \ 'Item "%s" must be included in section "%s"' % \ (item, section_name) def test_checking_excluded_item_inclusion(self): excluded_item = self.new_items.pop() for section_name, items in self.all_sections.items(): assert not self.adapter._item_is_included(section_name, excluded_item), \ 'Item "%s" must not included in section "%s"' % \ (item, section_name) def test_checking_section_existence(self): for section_name in self.all_sections.keys(): assert self.adapter._section_exists(section_name), \ 'Section "%s" must exist' % section_name def test_checking_non_existing_section_existence(self): invalid_section = u'designers' assert not self.adapter._section_exists(invalid_section), \ 'Section "%s" must not exist' % invalid_section def test_sets_if_it_is_writable(self): assert hasattr(self.adapter, 'is_writable'), \ "The adapter doesn't have the 'is_writable' attribute; " \ "please call its parent's constructor too" class _BaseAdapterTester(_ReadOnlyBaseAdapterTester): """Base test case for read & write adapters""" def test_adding_many_items_to_section(self): for section_name, items in self.all_sections.items(): self.adapter._include_items(section_name, self.new_items) final_items = items | self.new_items assert self.adapter._get_section_items(section_name)==final_items, \ '"%s" does not include %s' % (section_name, self.new_items) def test_creating_section(self): section = u'cool-section' self.adapter._create_section(section) assert section in self.adapter._get_all_sections().keys(), \ 'Section "%s" could not be added' % section def test_editing_section(self): old_section = self.all_sections.keys()[0] new_section = u'cool-section' self.adapter._edit_section(old_section, new_section) assert new_section in self.adapter._get_all_sections().keys() and \ old_section not in self.adapter._get_all_sections().keys(), \ 'Section "%s" was not renamed to "%s"' % (old_section, new_section) def test_deleting_section(self): section = self.all_sections.keys()[0] self.adapter._delete_section(section) assert section not in self.adapter._get_all_sections().keys(), \ 'Section "%s" was not deleted' % section class ReadOnlyGroupsAdapterTester(_ReadOnlyBaseAdapterTester): """ Test case for read-only groups source adapters. The groups source used for the tests must only contain the following groups (aka "sections") and their relevant users (aka "items"; if any): * admins * rms * developers * rms * linus * trolls * sballmer * python * php .. attribute:: adapter An instance of the :term:`group adapter` to be tested. For example, a test case for the mock group adapter ``FakeReadOnlyGroupSourceAdapter`` may look like this:: from repoze.what.adapters.testutil import ReadOnlyGroupsAdapterTester class TestReadOnlyGroupsAdapterTester(ReadOnlyGroupsAdapterTester, unittest.TestCase): def setUp(self): super(TestReadOnlyGroupsAdapterTester, self).setUp() self.adapter = FakeReadOnlyGroupSourceAdapter() .. note:: :class:`GroupsAdapterTester` extends this test case to check write operations. """ new_items = set((u'guido', u'rasmus')) def setUp(self): self.all_sections = { u'admins': set((u'rms', )), u'developers': set((u'rms', u'linus')), u'trolls': set((u'sballmer', )), u'python': set(), u'php': set() } def _make_credentials(self, userid): """ Return a fake :mod:`repoze.what` ``credentials`` dictionary based on the ``userid``. Overwrite this method if its generated ``credentials`` dictionaries are not suitable for your adapter. """ return {'repoze.what.userid': userid} def test_finding_groups_of_authenticated_user(self): for userid in self._get_all_items(): credentials = self._make_credentials(userid) self.assertEqual(self.adapter._find_sections(credentials), self._get_item_sections(userid)) def test_finding_groups_of_non_existing_user(self): credentials = self._make_credentials(u'gustavo') self.assertEqual(self.adapter._find_sections(credentials), set()) class GroupsAdapterTester(ReadOnlyGroupsAdapterTester, _BaseAdapterTester): """ Test case for groups source adapters. This test case extends :class:`ReadOnlyGroupsAdapterTester` to test write operations in read & write adapters and it should be set up the same way as its parent. For example, a test case for the mock group adapter ``FakeGroupSourceAdapter`` may look like this:: from repoze.what.adapters.testutil import GroupsAdapterTester class TestGroupsAdapterTester(GroupsAdapterTester, unittest.TestCase): def setUp(self): super(TestGroupsAdapterTester, self).setUp() self.adapter = FakeGroupSourceAdapter() """ def test_removing_many_users_from_group(self): group = u'developers' users = (u'rms', u'linus') self.adapter._exclude_items(group, users) assert self.adapter._get_section_items(group)==set(), \ '"%s" still includes %s' % (group, users) class ReadOnlyPermissionsAdapterTester(_ReadOnlyBaseAdapterTester): """ Test case for read-only permissions source adapters. The permissions source used for the tests must only contain the following permissions (aka "sections") and their relevant groups (aka "items"; if any): * see-site * trolls * edit-site * admins * developers * commit * developers .. attribute:: adapter An instance of the :term:`permission adapter` to be tested. For example, a test case for the mock permission adapter defined above (``FakeReadOnlyPermissionSourceAdapter``) may look like this:: from repoze.what.adapters.testutil import ReadOnlyPermissionsAdapterTester class TestReadOnlyPermissionsAdapterTester(ReadOnlyPermissionsAdapterTester, unittest.TestCase): def setUp(self): super(TestReadOnlyPermissionsAdapterTester, self).setUp() self.adapter = FakeReadOnlyPermissionSourceAdapter() .. note:: :class:`PermissionsAdapterTester` extends this test case to check write operations. """ new_items = set((u'python', u'php')) def setUp(self): self.all_sections = { u'see-site': set((u'trolls', )), u'edit-site': set((u'admins', u'developers')), u'commit': set((u'developers', )) } def test_finding_permissions(self): for group in self._get_all_items(): self.assertEqual(self.adapter._find_sections(group), self._get_item_sections(group)) def test_finding_permissions_of_non_existing_group(self): self.assertEqual(self.adapter._find_sections(u'designers'), set()) class PermissionsAdapterTester(ReadOnlyPermissionsAdapterTester, _BaseAdapterTester): """ Test case for permissions source adapters. This test case extends :class:`ReadOnlyPermissionsAdapterTester` to test write operations in read & write adapters and it should be set up the same way as its parent. For example, a test case for the mock group adapter ``FakePermissionSourceAdapter`` may look like this: For example, a test case for the mock permission adapter defined above (``FakePermissionSourceAdapter``) may look like this:: from repoze.what.adapters.testutil import PermissionsAdapterTester class TestPermissionsAdapterTester(PermissionsAdapterTester, unittest.TestCase): def setUp(self): super(TestPermissionsAdapterTester, self).setUp() self.adapter = FakePermissionSourceAdapter() """ def test_deying_permisssion_to_many_groups(self): permission = u'edit-site' groups = (u'admins', u'developers') self.adapter._exclude_items(permission, groups) assert self.adapter._get_section_items(permission)==set(), \ '"%s" still includes %s' % (permission, groups)