diff options
author | asteroide <thomas.duval@orange.com> | 2015-09-01 16:03:26 +0200 |
---|---|---|
committer | asteroide <thomas.duval@orange.com> | 2015-09-01 16:04:53 +0200 |
commit | 92fd2dbfb672d7b2b1cdfd5dd5cf89f7716b3e12 (patch) | |
tree | 7ba22297042019e7363fa1d4ad26d1c32c5908c6 /keystone-moon/keystone/tests/unit/token | |
parent | 26e753254f3e43399cc76e62892908b7742415e8 (diff) |
Update Keystone code from official Github repository with branch Master on 09/01/2015.
Change-Id: I0ff6099e6e2580f87f502002a998bbfe12673498
Diffstat (limited to 'keystone-moon/keystone/tests/unit/token')
6 files changed, 441 insertions, 20 deletions
diff --git a/keystone-moon/keystone/tests/unit/token/test_fernet_provider.py b/keystone-moon/keystone/tests/unit/token/test_fernet_provider.py index 23fc0214..4101369c 100644 --- a/keystone-moon/keystone/tests/unit/token/test_fernet_provider.py +++ b/keystone-moon/keystone/tests/unit/token/test_fernet_provider.py @@ -11,17 +11,21 @@ # under the License. import datetime +import hashlib +import os import uuid from oslo_utils import timeutils from keystone.common import config +from keystone.common import utils from keystone import exception from keystone.tests import unit as tests from keystone.tests.unit import ksfixtures from keystone.token import provider from keystone.token.providers import fernet from keystone.token.providers.fernet import token_formatters +from keystone.token.providers.fernet import utils as fernet_utils CONF = config.CONF @@ -33,21 +37,21 @@ class TestFernetTokenProvider(tests.TestCase): self.useFixture(ksfixtures.KeyRepository(self.config_fixture)) self.provider = fernet.Provider() - def test_get_token_id_raises_not_implemented(self): - """Test that an exception is raised when calling _get_token_id.""" - token_data = {} - self.assertRaises(exception.NotImplemented, - self.provider._get_token_id, token_data) + def test_supports_bind_authentication_returns_false(self): + self.assertFalse(self.provider._supports_bind_authentication) - def test_invalid_v3_token_raises_401(self): + def test_needs_persistence_returns_false(self): + self.assertFalse(self.provider.needs_persistence()) + + def test_invalid_v3_token_raises_404(self): self.assertRaises( - exception.Unauthorized, + exception.TokenNotFound, self.provider.validate_v3_token, uuid.uuid4().hex) - def test_invalid_v2_token_raises_401(self): + def test_invalid_v2_token_raises_404(self): self.assertRaises( - exception.Unauthorized, + exception.TokenNotFound, self.provider.validate_v2_token, uuid.uuid4().hex) @@ -69,7 +73,7 @@ class TestPayloads(tests.TestCase): def test_time_string_to_int_conversions(self): payload_cls = token_formatters.BasePayload - expected_time_str = timeutils.isotime() + expected_time_str = utils.isotime(subsecond=True) time_obj = timeutils.parse_isotime(expected_time_str) expected_time_int = ( (timeutils.normalize_time(time_obj) - @@ -86,7 +90,7 @@ class TestPayloads(tests.TestCase): def test_unscoped_payload(self): exp_user_id = uuid.uuid4().hex exp_methods = ['password'] - exp_expires_at = timeutils.isotime(timeutils.utcnow()) + exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) exp_audit_ids = [provider.random_urlsafe_str()] payload = token_formatters.UnscopedPayload.assemble( @@ -104,7 +108,7 @@ class TestPayloads(tests.TestCase): exp_user_id = uuid.uuid4().hex exp_methods = ['password'] exp_project_id = uuid.uuid4().hex - exp_expires_at = timeutils.isotime(timeutils.utcnow()) + exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) exp_audit_ids = [provider.random_urlsafe_str()] payload = token_formatters.ProjectScopedPayload.assemble( @@ -124,7 +128,7 @@ class TestPayloads(tests.TestCase): exp_user_id = uuid.uuid4().hex exp_methods = ['password'] exp_domain_id = uuid.uuid4().hex - exp_expires_at = timeutils.isotime(timeutils.utcnow()) + exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) exp_audit_ids = [provider.random_urlsafe_str()] payload = token_formatters.DomainScopedPayload.assemble( @@ -144,7 +148,7 @@ class TestPayloads(tests.TestCase): exp_user_id = uuid.uuid4().hex exp_methods = ['password'] exp_domain_id = CONF.identity.default_domain_id - exp_expires_at = timeutils.isotime(timeutils.utcnow()) + exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) exp_audit_ids = [provider.random_urlsafe_str()] payload = token_formatters.DomainScopedPayload.assemble( @@ -164,7 +168,128 @@ class TestPayloads(tests.TestCase): exp_user_id = uuid.uuid4().hex exp_methods = ['password'] exp_project_id = uuid.uuid4().hex - exp_expires_at = timeutils.isotime(timeutils.utcnow()) + exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) + exp_audit_ids = [provider.random_urlsafe_str()] + exp_trust_id = uuid.uuid4().hex + + payload = token_formatters.TrustScopedPayload.assemble( + exp_user_id, exp_methods, exp_project_id, exp_expires_at, + exp_audit_ids, exp_trust_id) + + (user_id, methods, project_id, expires_at, audit_ids, trust_id) = ( + token_formatters.TrustScopedPayload.disassemble(payload)) + + self.assertEqual(exp_user_id, user_id) + self.assertEqual(exp_methods, methods) + self.assertEqual(exp_project_id, project_id) + self.assertEqual(exp_expires_at, expires_at) + self.assertEqual(exp_audit_ids, audit_ids) + self.assertEqual(exp_trust_id, trust_id) + + def test_unscoped_payload_with_non_uuid_user_id(self): + exp_user_id = 'someNonUuidUserId' + exp_methods = ['password'] + exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) + exp_audit_ids = [provider.random_urlsafe_str()] + + payload = token_formatters.UnscopedPayload.assemble( + exp_user_id, exp_methods, exp_expires_at, exp_audit_ids) + + (user_id, methods, expires_at, audit_ids) = ( + token_formatters.UnscopedPayload.disassemble(payload)) + + self.assertEqual(exp_user_id, user_id) + self.assertEqual(exp_methods, methods) + self.assertEqual(exp_expires_at, expires_at) + self.assertEqual(exp_audit_ids, audit_ids) + + def test_project_scoped_payload_with_non_uuid_user_id(self): + exp_user_id = 'someNonUuidUserId' + exp_methods = ['password'] + exp_project_id = uuid.uuid4().hex + exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) + exp_audit_ids = [provider.random_urlsafe_str()] + + payload = token_formatters.ProjectScopedPayload.assemble( + exp_user_id, exp_methods, exp_project_id, exp_expires_at, + exp_audit_ids) + + (user_id, methods, project_id, expires_at, audit_ids) = ( + token_formatters.ProjectScopedPayload.disassemble(payload)) + + self.assertEqual(exp_user_id, user_id) + self.assertEqual(exp_methods, methods) + self.assertEqual(exp_project_id, project_id) + self.assertEqual(exp_expires_at, expires_at) + self.assertEqual(exp_audit_ids, audit_ids) + + def test_project_scoped_payload_with_non_uuid_project_id(self): + exp_user_id = uuid.uuid4().hex + exp_methods = ['password'] + exp_project_id = 'someNonUuidProjectId' + exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) + exp_audit_ids = [provider.random_urlsafe_str()] + + payload = token_formatters.ProjectScopedPayload.assemble( + exp_user_id, exp_methods, exp_project_id, exp_expires_at, + exp_audit_ids) + + (user_id, methods, project_id, expires_at, audit_ids) = ( + token_formatters.ProjectScopedPayload.disassemble(payload)) + + self.assertEqual(exp_user_id, user_id) + self.assertEqual(exp_methods, methods) + self.assertEqual(exp_project_id, project_id) + self.assertEqual(exp_expires_at, expires_at) + self.assertEqual(exp_audit_ids, audit_ids) + + def test_domain_scoped_payload_with_non_uuid_user_id(self): + exp_user_id = 'someNonUuidUserId' + exp_methods = ['password'] + exp_domain_id = uuid.uuid4().hex + exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) + exp_audit_ids = [provider.random_urlsafe_str()] + + payload = token_formatters.DomainScopedPayload.assemble( + exp_user_id, exp_methods, exp_domain_id, exp_expires_at, + exp_audit_ids) + + (user_id, methods, domain_id, expires_at, audit_ids) = ( + token_formatters.DomainScopedPayload.disassemble(payload)) + + self.assertEqual(exp_user_id, user_id) + self.assertEqual(exp_methods, methods) + self.assertEqual(exp_domain_id, domain_id) + self.assertEqual(exp_expires_at, expires_at) + self.assertEqual(exp_audit_ids, audit_ids) + + def test_trust_scoped_payload_with_non_uuid_user_id(self): + exp_user_id = 'someNonUuidUserId' + exp_methods = ['password'] + exp_project_id = uuid.uuid4().hex + exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) + exp_audit_ids = [provider.random_urlsafe_str()] + exp_trust_id = uuid.uuid4().hex + + payload = token_formatters.TrustScopedPayload.assemble( + exp_user_id, exp_methods, exp_project_id, exp_expires_at, + exp_audit_ids, exp_trust_id) + + (user_id, methods, project_id, expires_at, audit_ids, trust_id) = ( + token_formatters.TrustScopedPayload.disassemble(payload)) + + self.assertEqual(exp_user_id, user_id) + self.assertEqual(exp_methods, methods) + self.assertEqual(exp_project_id, project_id) + self.assertEqual(exp_expires_at, expires_at) + self.assertEqual(exp_audit_ids, audit_ids) + self.assertEqual(exp_trust_id, trust_id) + + def test_trust_scoped_payload_with_non_uuid_project_id(self): + exp_user_id = uuid.uuid4().hex + exp_methods = ['password'] + exp_project_id = 'someNonUuidProjectId' + exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) exp_audit_ids = [provider.random_urlsafe_str()] exp_trust_id = uuid.uuid4().hex @@ -181,3 +306,218 @@ class TestPayloads(tests.TestCase): self.assertEqual(exp_expires_at, expires_at) self.assertEqual(exp_audit_ids, audit_ids) self.assertEqual(exp_trust_id, trust_id) + + def test_federated_payload_with_non_uuid_ids(self): + exp_user_id = 'someNonUuidUserId' + exp_methods = ['password'] + exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) + exp_audit_ids = [provider.random_urlsafe_str()] + exp_federated_info = {'group_ids': [{'id': 'someNonUuidGroupId'}], + 'idp_id': uuid.uuid4().hex, + 'protocol_id': uuid.uuid4().hex} + + payload = token_formatters.FederatedUnscopedPayload.assemble( + exp_user_id, exp_methods, exp_expires_at, exp_audit_ids, + exp_federated_info) + + (user_id, methods, expires_at, audit_ids, federated_info) = ( + token_formatters.FederatedUnscopedPayload.disassemble(payload)) + + self.assertEqual(exp_user_id, user_id) + self.assertEqual(exp_methods, methods) + self.assertEqual(exp_expires_at, expires_at) + self.assertEqual(exp_audit_ids, audit_ids) + self.assertEqual(exp_federated_info['group_ids'][0]['id'], + federated_info['group_ids'][0]['id']) + self.assertEqual(exp_federated_info['idp_id'], + federated_info['idp_id']) + self.assertEqual(exp_federated_info['protocol_id'], + federated_info['protocol_id']) + + def test_federated_project_scoped_payload(self): + exp_user_id = 'someNonUuidUserId' + exp_methods = ['token'] + exp_project_id = uuid.uuid4().hex + exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) + exp_audit_ids = [provider.random_urlsafe_str()] + exp_federated_info = {'group_ids': [{'id': 'someNonUuidGroupId'}], + 'idp_id': uuid.uuid4().hex, + 'protocol_id': uuid.uuid4().hex} + + payload = token_formatters.FederatedProjectScopedPayload.assemble( + exp_user_id, exp_methods, exp_project_id, exp_expires_at, + exp_audit_ids, exp_federated_info) + + (user_id, methods, project_id, expires_at, audit_ids, + federated_info) = ( + token_formatters.FederatedProjectScopedPayload.disassemble( + payload)) + + self.assertEqual(exp_user_id, user_id) + self.assertEqual(exp_methods, methods) + self.assertEqual(exp_project_id, project_id) + self.assertEqual(exp_expires_at, expires_at) + self.assertEqual(exp_audit_ids, audit_ids) + self.assertDictEqual(exp_federated_info, federated_info) + + def test_federated_domain_scoped_payload(self): + exp_user_id = 'someNonUuidUserId' + exp_methods = ['token'] + exp_domain_id = uuid.uuid4().hex + exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) + exp_audit_ids = [provider.random_urlsafe_str()] + exp_federated_info = {'group_ids': [{'id': 'someNonUuidGroupId'}], + 'idp_id': uuid.uuid4().hex, + 'protocol_id': uuid.uuid4().hex} + + payload = token_formatters.FederatedDomainScopedPayload.assemble( + exp_user_id, exp_methods, exp_domain_id, exp_expires_at, + exp_audit_ids, exp_federated_info) + + (user_id, methods, domain_id, expires_at, audit_ids, + federated_info) = ( + token_formatters.FederatedDomainScopedPayload.disassemble( + payload)) + + self.assertEqual(exp_user_id, user_id) + self.assertEqual(exp_methods, methods) + self.assertEqual(exp_domain_id, domain_id) + self.assertEqual(exp_expires_at, expires_at) + self.assertEqual(exp_audit_ids, audit_ids) + self.assertDictEqual(exp_federated_info, federated_info) + + +class TestFernetKeyRotation(tests.TestCase): + def setUp(self): + super(TestFernetKeyRotation, self).setUp() + + # A collection of all previously-seen signatures of the key + # repository's contents. + self.key_repo_signatures = set() + + @property + def keys(self): + """Key files converted to numbers.""" + return sorted( + int(x) for x in os.listdir(CONF.fernet_tokens.key_repository)) + + @property + def key_repository_size(self): + """The number of keys in the key repository.""" + return len(self.keys) + + @property + def key_repository_signature(self): + """Create a "thumbprint" of the current key repository. + + Because key files are renamed, this produces a hash of the contents of + the key files, ignoring their filenames. + + The resulting signature can be used, for example, to ensure that you + have a unique set of keys after you perform a key rotation (taking a + static set of keys, and simply shuffling them, would fail such a test). + + """ + # Load the keys into a list. + keys = fernet_utils.load_keys() + + # Sort the list of keys by the keys themselves (they were previously + # sorted by filename). + keys.sort() + + # Create the thumbprint using all keys in the repository. + signature = hashlib.sha1() + for key in keys: + signature.update(key) + return signature.hexdigest() + + def assertRepositoryState(self, expected_size): + """Validate the state of the key repository.""" + self.assertEqual(expected_size, self.key_repository_size) + self.assertUniqueRepositoryState() + + def assertUniqueRepositoryState(self): + """Ensures that the current key repo state has not been seen before.""" + # This is assigned to a variable because it takes some work to + # calculate. + signature = self.key_repository_signature + + # Ensure the signature is not in the set of previously seen signatures. + self.assertNotIn(signature, self.key_repo_signatures) + + # Add the signature to the set of repository signatures to validate + # that we don't see it again later. + self.key_repo_signatures.add(signature) + + def test_rotation(self): + # Initializing a key repository results in this many keys. We don't + # support max_active_keys being set any lower. + min_active_keys = 2 + + # Simulate every rotation strategy up to "rotating once a week while + # maintaining a year's worth of keys." + for max_active_keys in range(min_active_keys, 52 + 1): + self.config_fixture.config(group='fernet_tokens', + max_active_keys=max_active_keys) + + # Ensure that resetting the key repository always results in 2 + # active keys. + self.useFixture(ksfixtures.KeyRepository(self.config_fixture)) + + # Validate the initial repository state. + self.assertRepositoryState(expected_size=min_active_keys) + + # The repository should be initialized with a staged key (0) and a + # primary key (1). The next key is just auto-incremented. + exp_keys = [0, 1] + next_key_number = exp_keys[-1] + 1 # keep track of next key + self.assertEqual(exp_keys, self.keys) + + # Rotate the keys just enough times to fully populate the key + # repository. + for rotation in range(max_active_keys - min_active_keys): + fernet_utils.rotate_keys() + self.assertRepositoryState(expected_size=rotation + 3) + + exp_keys.append(next_key_number) + next_key_number += 1 + self.assertEqual(exp_keys, self.keys) + + # We should have a fully populated key repository now. + self.assertEqual(max_active_keys, self.key_repository_size) + + # Rotate an additional number of times to ensure that we maintain + # the desired number of active keys. + for rotation in range(10): + fernet_utils.rotate_keys() + self.assertRepositoryState(expected_size=max_active_keys) + + exp_keys.pop(1) + exp_keys.append(next_key_number) + next_key_number += 1 + self.assertEqual(exp_keys, self.keys) + + def test_non_numeric_files(self): + self.useFixture(ksfixtures.KeyRepository(self.config_fixture)) + evil_file = os.path.join(CONF.fernet_tokens.key_repository, '99.bak') + with open(evil_file, 'w'): + pass + fernet_utils.rotate_keys() + self.assertTrue(os.path.isfile(evil_file)) + keys = 0 + for x in os.listdir(CONF.fernet_tokens.key_repository): + if x == '99.bak': + continue + keys += 1 + self.assertEqual(3, keys) + + +class TestLoadKeys(tests.TestCase): + def test_non_numeric_files(self): + self.useFixture(ksfixtures.KeyRepository(self.config_fixture)) + evil_file = os.path.join(CONF.fernet_tokens.key_repository, '~1') + with open(evil_file, 'w'): + pass + keys = fernet_utils.load_keys() + self.assertEqual(2, len(keys)) + self.assertTrue(len(keys[0])) diff --git a/keystone-moon/keystone/tests/unit/token/test_pki_provider.py b/keystone-moon/keystone/tests/unit/token/test_pki_provider.py new file mode 100644 index 00000000..dad31266 --- /dev/null +++ b/keystone-moon/keystone/tests/unit/token/test_pki_provider.py @@ -0,0 +1,26 @@ +# 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 keystone.tests import unit as tests +from keystone.token.providers import pki + + +class TestPkiTokenProvider(tests.TestCase): + def setUp(self): + super(TestPkiTokenProvider, self).setUp() + self.provider = pki.Provider() + + def test_supports_bind_authentication_returns_true(self): + self.assertTrue(self.provider._supports_bind_authentication) + + def test_need_persistence_return_true(self): + self.assertIs(True, self.provider.needs_persistence()) diff --git a/keystone-moon/keystone/tests/unit/token/test_pkiz_provider.py b/keystone-moon/keystone/tests/unit/token/test_pkiz_provider.py new file mode 100644 index 00000000..4a492bc1 --- /dev/null +++ b/keystone-moon/keystone/tests/unit/token/test_pkiz_provider.py @@ -0,0 +1,26 @@ +# 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 keystone.tests import unit as tests +from keystone.token.providers import pkiz + + +class TestPkizTokenProvider(tests.TestCase): + def setUp(self): + super(TestPkizTokenProvider, self).setUp() + self.provider = pkiz.Provider() + + def test_supports_bind_authentication_returns_true(self): + self.assertTrue(self.provider._supports_bind_authentication) + + def test_need_persistence_return_true(self): + self.assertIs(True, self.provider.needs_persistence()) diff --git a/keystone-moon/keystone/tests/unit/token/test_provider.py b/keystone-moon/keystone/tests/unit/token/test_provider.py index e5910690..be831484 100644 --- a/keystone-moon/keystone/tests/unit/token/test_provider.py +++ b/keystone-moon/keystone/tests/unit/token/test_provider.py @@ -10,7 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -import urllib +import six +from six.moves import urllib from keystone.tests import unit from keystone.token import provider @@ -19,11 +20,11 @@ from keystone.token import provider class TestRandomStrings(unit.BaseTestCase): def test_strings_are_url_safe(self): s = provider.random_urlsafe_str() - self.assertEqual(s, urllib.quote_plus(s)) + self.assertEqual(s, urllib.parse.quote_plus(s)) def test_strings_can_be_converted_to_bytes(self): s = provider.random_urlsafe_str() - self.assertTrue(isinstance(s, basestring)) + self.assertTrue(isinstance(s, six.string_types)) b = provider.random_urlsafe_str_to_bytes(s) self.assertTrue(isinstance(b, bytes)) diff --git a/keystone-moon/keystone/tests/unit/token/test_token_model.py b/keystone-moon/keystone/tests/unit/token/test_token_model.py index b2474289..3959d901 100644 --- a/keystone-moon/keystone/tests/unit/token/test_token_model.py +++ b/keystone-moon/keystone/tests/unit/token/test_token_model.py @@ -15,7 +15,9 @@ import uuid from oslo_config import cfg from oslo_utils import timeutils +from six.moves import range +from keystone.contrib.federation import constants as federation_constants from keystone import exception from keystone.models import token_model from keystone.tests.unit import core @@ -127,7 +129,7 @@ class TestKeystoneTokenModel(core.TestCase): self.assertIsNone(token_data.federation_protocol_id) self.assertIsNone(token_data.federation_idp_id) - token_data['user'][token_model.federation.FEDERATION] = federation_data + token_data['user'][federation_constants.FEDERATION] = federation_data self.assertTrue(token_data.is_federated_user) self.assertEqual([x['id'] for x in federation_data['groups']], @@ -149,7 +151,7 @@ class TestKeystoneTokenModel(core.TestCase): self.assertIsNone(token_data.federation_protocol_id) self.assertIsNone(token_data.federation_idp_id) - token_data['user'][token_model.federation.FEDERATION] = federation_data + token_data['user'][federation_constants.FEDERATION] = federation_data # Federated users should not exist in V2, the data should remain empty self.assertFalse(token_data.is_federated_user) diff --git a/keystone-moon/keystone/tests/unit/token/test_uuid_provider.py b/keystone-moon/keystone/tests/unit/token/test_uuid_provider.py new file mode 100644 index 00000000..b49427f0 --- /dev/null +++ b/keystone-moon/keystone/tests/unit/token/test_uuid_provider.py @@ -0,0 +1,26 @@ +# 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 keystone.tests import unit as tests +from keystone.token.providers import uuid + + +class TestUuidTokenProvider(tests.TestCase): + def setUp(self): + super(TestUuidTokenProvider, self).setUp() + self.provider = uuid.Provider() + + def test_supports_bind_authentication_returns_true(self): + self.assertTrue(self.provider._supports_bind_authentication) + + def test_need_persistence_return_true(self): + self.assertIs(True, self.provider.needs_persistence()) |