From 23574dc33ce854faa34fe3d4b1098c21c87578e1 Mon Sep 17 00:00:00 2001 From: Peter Hamilton Date: Thu, 14 May 2015 13:08:02 -0400 Subject: [PATCH] Reorganizing test suite and updating tox configuration This change reorganizes the test suite, splitting it into two separate test suites, one for unit tests and one for integration tests. The tox configuration is also updated to reflect this change. Invoking tox now runs the unit tests by default. A separate tox environment is used to run the integration tests. --- .gitignore | 1 + README.rst | 10 +- .../attributes => integration}/__init__.py | 0 .../services}/__init__.py | 0 .../integration/services/test_kmip_client.py | 401 ++++++++++++++++++ .../tests/{ => integration}/utils/__init__.py | 0 kmip/tests/integration/utils/certs/server.crt | 19 + kmip/tests/integration/utils/certs/server.key | 27 ++ kmip/tests/{ => integration}/utils/server.py | 4 +- kmip/tests/{core/misc => unit}/__init__.py | 0 kmip/tests/{ => unit}/core/__init__.py | 0 .../core/attributes}/__init__.py | 0 .../test_application_specific_information.py | 0 .../core/attributes/test_attributes.py | 0 .../{ => unit}/core/attributes/test_digest.py | 0 .../{ => unit}/core/factories/__init__.py | 0 .../core/factories/payloads/__init__.py | 0 .../core/factories/payloads/test_payload.py | 0 .../core/factories/payloads/test_request.py | 0 .../core/factories/payloads/test_response.py | 0 .../core/factories/test_attribute_values.py | 0 .../{ => unit}/core/messages/__init__.py | 0 .../core/messages/contents}/__init__.py | 0 .../contents/test_protocol_version.py | 0 .../core/messages/payloads/__init__.py | 0 .../core/messages/payloads/test_create.py | 0 .../messages/payloads/test_create_key_pair.py | 0 .../core/messages/payloads/test_destroy.py | 0 .../payloads/test_discover_versions.py | 0 .../core/messages/payloads/test_get.py | 0 .../core/messages/payloads/test_locate.py | 0 .../core/messages/payloads/test_query.py | 0 .../core/messages/payloads/test_register.py | 0 .../messages/payloads/test_rekey_key_pair.py | 0 .../{ => unit}/core/messages/test_messages.py | 0 .../core/messages/test_operations.py | 0 kmip/tests/unit/core/misc/__init__.py | 14 + kmip/tests/{ => unit}/core/misc/test_misc.py | 0 .../core/misc/test_server_information.py | 0 kmip/tests/unit/core/objects/__init__.py | 14 + .../objects/test_extension_information.py | 0 .../{ => unit}/core/objects/test_objects.py | 0 kmip/tests/unit/core/secrets/__init__.py | 14 + .../core/secrets/test_certificate.py | 0 .../{ => unit}/core/test_config_helper.py | 0 kmip/tests/{ => unit}/core/test_primitives.py | 0 kmip/tests/{ => unit}/core/test_server.py | 0 kmip/tests/{ => unit}/core/test_utils.py | 0 kmip/tests/{ => unit}/services/__init__.py | 0 .../{ => unit}/services/test_kmip_client.py | 373 ---------------- setup.py | 2 +- tox.ini | 13 +- 52 files changed, 510 insertions(+), 382 deletions(-) rename kmip/tests/{core/attributes => integration}/__init__.py (100%) rename kmip/tests/{core/messages/contents => integration/services}/__init__.py (100%) create mode 100644 kmip/tests/integration/services/test_kmip_client.py rename kmip/tests/{ => integration}/utils/__init__.py (100%) create mode 100644 kmip/tests/integration/utils/certs/server.crt create mode 100644 kmip/tests/integration/utils/certs/server.key rename kmip/tests/{ => integration}/utils/server.py (96%) rename kmip/tests/{core/misc => unit}/__init__.py (100%) rename kmip/tests/{ => unit}/core/__init__.py (100%) rename kmip/tests/{core/objects => unit/core/attributes}/__init__.py (100%) rename kmip/tests/{ => unit}/core/attributes/test_application_specific_information.py (100%) rename kmip/tests/{ => unit}/core/attributes/test_attributes.py (100%) rename kmip/tests/{ => unit}/core/attributes/test_digest.py (100%) rename kmip/tests/{ => unit}/core/factories/__init__.py (100%) rename kmip/tests/{ => unit}/core/factories/payloads/__init__.py (100%) rename kmip/tests/{ => unit}/core/factories/payloads/test_payload.py (100%) rename kmip/tests/{ => unit}/core/factories/payloads/test_request.py (100%) rename kmip/tests/{ => unit}/core/factories/payloads/test_response.py (100%) rename kmip/tests/{ => unit}/core/factories/test_attribute_values.py (100%) rename kmip/tests/{ => unit}/core/messages/__init__.py (100%) rename kmip/tests/{core/secrets => unit/core/messages/contents}/__init__.py (100%) rename kmip/tests/{ => unit}/core/messages/contents/test_protocol_version.py (100%) rename kmip/tests/{ => unit}/core/messages/payloads/__init__.py (100%) rename kmip/tests/{ => unit}/core/messages/payloads/test_create.py (100%) rename kmip/tests/{ => unit}/core/messages/payloads/test_create_key_pair.py (100%) rename kmip/tests/{ => unit}/core/messages/payloads/test_destroy.py (100%) rename kmip/tests/{ => unit}/core/messages/payloads/test_discover_versions.py (100%) rename kmip/tests/{ => unit}/core/messages/payloads/test_get.py (100%) rename kmip/tests/{ => unit}/core/messages/payloads/test_locate.py (100%) rename kmip/tests/{ => unit}/core/messages/payloads/test_query.py (100%) rename kmip/tests/{ => unit}/core/messages/payloads/test_register.py (100%) rename kmip/tests/{ => unit}/core/messages/payloads/test_rekey_key_pair.py (100%) rename kmip/tests/{ => unit}/core/messages/test_messages.py (100%) rename kmip/tests/{ => unit}/core/messages/test_operations.py (100%) create mode 100644 kmip/tests/unit/core/misc/__init__.py rename kmip/tests/{ => unit}/core/misc/test_misc.py (100%) rename kmip/tests/{ => unit}/core/misc/test_server_information.py (100%) create mode 100644 kmip/tests/unit/core/objects/__init__.py rename kmip/tests/{ => unit}/core/objects/test_extension_information.py (100%) rename kmip/tests/{ => unit}/core/objects/test_objects.py (100%) create mode 100644 kmip/tests/unit/core/secrets/__init__.py rename kmip/tests/{ => unit}/core/secrets/test_certificate.py (100%) rename kmip/tests/{ => unit}/core/test_config_helper.py (100%) rename kmip/tests/{ => unit}/core/test_primitives.py (100%) rename kmip/tests/{ => unit}/core/test_server.py (100%) rename kmip/tests/{ => unit}/core/test_utils.py (100%) rename kmip/tests/{ => unit}/services/__init__.py (100%) rename kmip/tests/{ => unit}/services/test_kmip_client.py (58%) diff --git a/.gitignore b/.gitignore index d1df503..d0cfe21 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ ChangeLog PyKMIP.egg-info/ dist/ +htmlcov/ diff --git a/README.rst b/README.rst index ad72350..48c0576 100644 --- a/README.rst +++ b/README.rst @@ -122,7 +122,7 @@ Server profiles: Testing ------- The PyKMIP test suite is composed of two parts: a unit test suite composed of -over 500 unit tests, and an integration test suite that runs against +over 550 unit tests, and an integration test suite that runs against instantiations of the software KMIP server. The tests are managed by a combination of the ``tox``, ``pytest``, and ``flake8`` libraries and cover approximately 80% of the code. @@ -130,7 +130,7 @@ approximately 80% of the code. There are several ways to run different versions of the tests. To run, use one of the following commands in the PyKMIP root directory. -To run all of the tests:: +To run all of the unit tests:: $ tox @@ -138,10 +138,14 @@ To run the Python syntax and format compliance tests:: $ tox -e pep8 -To run the test suite against Python 2.7:: +To run the unit test suite against Python 2.7:: $ tox -e py27 +To run the integration test suite against the default Python installation: + + $ tox -e integration + For more information and a list of supported ``tox`` environments, see ``tox.ini`` in the PyKMIP root directory. diff --git a/kmip/tests/core/attributes/__init__.py b/kmip/tests/integration/__init__.py similarity index 100% rename from kmip/tests/core/attributes/__init__.py rename to kmip/tests/integration/__init__.py diff --git a/kmip/tests/core/messages/contents/__init__.py b/kmip/tests/integration/services/__init__.py similarity index 100% rename from kmip/tests/core/messages/contents/__init__.py rename to kmip/tests/integration/services/__init__.py diff --git a/kmip/tests/integration/services/test_kmip_client.py b/kmip/tests/integration/services/test_kmip_client.py new file mode 100644 index 0000000..5b41b7c --- /dev/null +++ b/kmip/tests/integration/services/test_kmip_client.py @@ -0,0 +1,401 @@ +# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory +# 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 testtools import TestCase + +from subprocess import Popen + +import os +import sys +import time + +from kmip.core.attributes import CryptographicAlgorithm +from kmip.core.attributes import CryptographicLength + +from kmip.core.enums import AttributeType +from kmip.core.enums import CredentialType +from kmip.core.enums import CryptographicAlgorithm as CryptoAlgorithmEnum +from kmip.core.enums import CryptographicUsageMask +from kmip.core.enums import ObjectType +from kmip.core.enums import KeyFormatType as KeyFormatTypeEnum +from kmip.core.enums import ResultStatus +from kmip.core.enums import ResultReason + +from kmip.core.errors import KMIPServerSuicideError +from kmip.core.errors import KMIPServerZombieError + +from kmip.core.factories.attributes import AttributeFactory +from kmip.core.factories.credentials import CredentialFactory +from kmip.core.factories.secrets import SecretFactory + +from kmip.core.misc import KeyFormatType + +from kmip.core.objects import Attribute +from kmip.core.objects import KeyBlock +from kmip.core.objects import KeyMaterial +from kmip.core.objects import KeyValue +from kmip.core.objects import TemplateAttribute + +from kmip.core.secrets import SymmetricKey + +from kmip.services.kmip_client import KMIPProxy + +import kmip.core.utils as utils + + +class TestKMIPClientIntegration(TestCase): + STARTUP_TIME = 1.0 + SHUTDOWN_TIME = 0.1 + KMIP_PORT = 9090 + CA_CERTS_PATH = os.path.normpath(os.path.join(os.path.dirname( + os.path.abspath(__file__)), '../utils/certs/server.crt')) + + def setUp(self): + super(TestKMIPClientIntegration, self).setUp() + + self.attr_factory = AttributeFactory() + self.cred_factory = CredentialFactory() + self.secret_factory = SecretFactory() + + # Set up the KMIP server process + path = os.path.join(os.path.dirname(__file__), os.path.pardir, + 'utils', 'server.py') + self.server = Popen(['python', '{0}'.format(path), '-p', + '{0}'.format(self.KMIP_PORT)], stderr=sys.stdout) + + time.sleep(self.STARTUP_TIME) + + if self.server.poll() is not None: + raise KMIPServerSuicideError(self.server.pid) + + # Set up and open the client proxy; shutdown the server if open fails + try: + self.client = KMIPProxy(port=self.KMIP_PORT, + ca_certs=self.CA_CERTS_PATH) + self.client.open() + except Exception as e: + self._shutdown_server() + raise e + + def tearDown(self): + super(TestKMIPClientIntegration, self).tearDown() + + # Close the client proxy and shutdown the server + self.client.close() + self._shutdown_server() + + def test_create(self): + result = self._create_symmetric_key() + + self._check_result_status(result.result_status.enum, ResultStatus, + ResultStatus.SUCCESS) + self._check_object_type(result.object_type.enum, ObjectType, + ObjectType.SYMMETRIC_KEY) + self._check_uuid(result.uuid.value, str) + + # Check the template attribute type + self._check_template_attribute(result.template_attribute, + TemplateAttribute, 2, + [[str, 'Cryptographic Length', int, + 256], + [str, 'Unique Identifier', str, + None]]) + + def test_get(self): + credential_type = CredentialType.USERNAME_AND_PASSWORD + credential_value = {'Username': 'Peter', 'Password': 'abc123'} + credential = self.cred_factory.create_credential(credential_type, + credential_value) + result = self._create_symmetric_key() + uuid = result.uuid.value + + result = self.client.get(uuid=uuid, credential=credential) + + self._check_result_status(result.result_status.enum, ResultStatus, + ResultStatus.SUCCESS) + self._check_object_type(result.object_type.enum, ObjectType, + ObjectType.SYMMETRIC_KEY) + self._check_uuid(result.uuid.value, str) + + # Check the secret type + secret = result.secret + + expected = SymmetricKey + message = utils.build_er_error(result.__class__, 'type', expected, + secret, 'secret') + self.assertIsInstance(secret, expected, message) + + def test_destroy(self): + credential_type = CredentialType.USERNAME_AND_PASSWORD + credential_value = {'Username': 'Peter', 'Password': 'abc123'} + credential = self.cred_factory.create_credential(credential_type, + credential_value) + result = self._create_symmetric_key() + uuid = result.uuid.value + + # Verify the secret was created + result = self.client.get(uuid=uuid, credential=credential) + + self._check_result_status(result.result_status.enum, ResultStatus, + ResultStatus.SUCCESS) + self._check_object_type(result.object_type.enum, ObjectType, + ObjectType.SYMMETRIC_KEY) + self._check_uuid(result.uuid.value, str) + + secret = result.secret + + expected = SymmetricKey + message = utils.build_er_error(result.__class__, 'type', expected, + secret, 'secret') + self.assertIsInstance(secret, expected, message) + + # Destroy the SYMMETRIC_KEY object + result = self.client.destroy(uuid, credential) + self._check_result_status(result.result_status.enum, ResultStatus, + ResultStatus.SUCCESS) + self._check_uuid(result.uuid.value, str) + + # Verify the secret was destroyed + result = self.client.get(uuid=uuid, credential=credential) + + self._check_result_status(result.result_status.enum, ResultStatus, + ResultStatus.OPERATION_FAILED) + + expected = ResultReason + observed = type(result.result_reason.enum) + message = utils.build_er_error(result.result_reason.__class__, 'type', + expected, observed) + self.assertEqual(expected, observed, message) + + expected = ResultReason.ITEM_NOT_FOUND + observed = result.result_reason.enum + message = utils.build_er_error(result.result_reason.__class__, + 'value', expected, observed) + self.assertEqual(expected, observed, message) + + def test_register(self): + credential_type = CredentialType.USERNAME_AND_PASSWORD + credential_value = {'Username': 'Peter', 'Password': 'abc123'} + credential = self.cred_factory.create_credential(credential_type, + credential_value) + + object_type = ObjectType.SYMMETRIC_KEY + algorithm_value = CryptoAlgorithmEnum.AES + mask_flags = [CryptographicUsageMask.ENCRYPT, + CryptographicUsageMask.DECRYPT] + attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK + usage_mask = self.attr_factory.create_attribute(attribute_type, + mask_flags) + attributes = [usage_mask] + template_attribute = TemplateAttribute(attributes=attributes) + + key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW) + + key_data = ( + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00') + + key_material = KeyMaterial(key_data) + key_value = KeyValue(key_material) + cryptographic_algorithm = CryptographicAlgorithm(algorithm_value) + cryptographic_length = CryptographicLength(128) + + key_block = KeyBlock( + key_format_type=key_format_type, + key_compression_type=None, + key_value=key_value, + cryptographic_algorithm=cryptographic_algorithm, + cryptographic_length=cryptographic_length, + key_wrapping_data=None) + + secret = SymmetricKey(key_block) + + result = self.client.register(object_type, template_attribute, secret, + credential) + + self._check_result_status(result.result_status.enum, ResultStatus, + ResultStatus.SUCCESS) + self._check_uuid(result.uuid.value, str) + + # Check the template attribute type + self._check_template_attribute(result.template_attribute, + TemplateAttribute, 1, + [[str, 'Unique Identifier', str, + None]]) + # Check that the returned key bytes match what was provided + uuid = result.uuid.value + result = self.client.get(uuid=uuid, credential=credential) + + self._check_result_status(result.result_status.enum, ResultStatus, + ResultStatus.SUCCESS) + self._check_object_type(result.object_type.enum, ObjectType, + ObjectType.SYMMETRIC_KEY) + self._check_uuid(result.uuid.value, str) + + # Check the secret type + secret = result.secret + + expected = SymmetricKey + message = utils.build_er_error(result.__class__, 'type', expected, + secret, 'secret') + self.assertIsInstance(secret, expected, message) + + key_block = result.secret.key_block + key_value = key_block.key_value + key_material = key_value.key_material + + expected = key_data + observed = key_material.value + message = utils.build_er_error(key_material.__class__, 'value', + expected, observed, 'value') + self.assertEqual(expected, observed, message) + + def _shutdown_server(self): + if self.server.poll() is not None: + return + else: + # Terminate the server process. If it resists, kill it. + pid = self.server.pid + self.server.terminate() + time.sleep(self.SHUTDOWN_TIME) + + if self.server.poll() is None: + raise KMIPServerZombieError(pid) + + def _create_symmetric_key(self): + credential_type = CredentialType.USERNAME_AND_PASSWORD + credential_value = {'Username': 'Peter', 'Password': 'abc123'} + credential = self.cred_factory.create_credential(credential_type, + credential_value) + + object_type = ObjectType.SYMMETRIC_KEY + attribute_type = AttributeType.CRYPTOGRAPHIC_ALGORITHM + algorithm = self.attr_factory.create_attribute( + attribute_type, + CryptoAlgorithmEnum.AES) + + mask_flags = [CryptographicUsageMask.ENCRYPT, + CryptographicUsageMask.DECRYPT] + attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK + usage_mask = self.attr_factory.create_attribute(attribute_type, + mask_flags) + attributes = [algorithm, usage_mask] + template_attribute = TemplateAttribute(attributes=attributes) + + return self.client.create(object_type, template_attribute, + credential) + + def _check_result_status(self, result_status, result_status_type, + result_status_value): + # Error check the result status type and value + expected = result_status_type + message = utils.build_er_error(result_status_type, 'type', expected, + result_status) + self.assertIsInstance(result_status, expected, message) + + expected = result_status_value + message = utils.build_er_error(result_status_type, 'value', expected, + result_status) + self.assertEqual(expected, result_status, message) + + def _check_uuid(self, uuid, uuid_type): + # Error check the UUID type and value + not_expected = None + message = utils.build_er_error(uuid_type, 'type', + 'not {0}'.format(not_expected), uuid) + self.assertNotEqual(not_expected, uuid, message) + + expected = uuid_type + message = utils.build_er_error(uuid_type, 'type', expected, uuid) + self.assertEqual(expected, type(uuid), message) + + def _check_object_type(self, object_type, object_type_type, + object_type_value): + # Error check the object type type and value + expected = object_type_type + message = utils.build_er_error(object_type_type, 'type', expected, + object_type) + self.assertIsInstance(object_type, expected, message) + + expected = object_type_value + message = utils.build_er_error(object_type_type, 'value', expected, + object_type) + self.assertEqual(expected, object_type, message) + + def _check_template_attribute(self, template_attribute, + template_attribute_type, num_attributes, + attribute_features): + # Error check the template attribute type + expected = template_attribute_type + message = utils.build_er_error(template_attribute.__class__, 'type', + expected, template_attribute) + self.assertIsInstance(template_attribute, expected, message) + + attributes = template_attribute.attributes + + expected = num_attributes + observed = len(attributes) + message = utils.build_er_error(TemplateAttribute.__class__, 'number', + expected, observed, 'attributes') + + for i in range(num_attributes): + features = attribute_features[i] + self._check_attribute(attributes[i], features[0], features[1], + features[2], features[3]) + + def _check_attribute(self, attribute, attribute_name_type, + attribute_name_value, attribute_value_type, + attribute_value_value): + # Error check the attribute name and value type and value + attribute_name = attribute.attribute_name + attribute_value = attribute.attribute_value + + self._check_attribute_name(attribute_name, attribute_name_type, + attribute_name_value) + + if attribute_name_value == 'Unique Identifier': + self._check_uuid(attribute_value.value, attribute_value_type) + else: + self._check_attribute_value(attribute_value, attribute_value_type, + attribute_value_value) + + def _check_attribute_name(self, attribute_name, attribute_name_type, + attribute_name_value): + # Error check the attribute name type and value + expected = attribute_name_type + observed = type(attribute_name.value) + message = utils.build_er_error(attribute_name_type, 'type', expected, + observed) + self.assertEqual(expected, observed, message) + + expected = attribute_name_value + observed = attribute_name.value + message = utils.build_er_error(attribute_name_type, 'value', expected, + observed) + self.assertEqual(expected, observed, message) + + def _check_attribute_value(self, attribute_value, attribute_value_type, + attribute_value_value): + expected = attribute_value_type + observed = type(attribute_value.value) + message = utils.build_er_error(Attribute, 'type', expected, observed, + 'attribute_value') + self.assertEqual(expected, observed, message) + + expected = attribute_value_value + observed = attribute_value.value + message = utils.build_er_error(Attribute, 'value', expected, observed, + 'attribute_value') + self.assertEqual(expected, observed, message) diff --git a/kmip/tests/utils/__init__.py b/kmip/tests/integration/utils/__init__.py similarity index 100% rename from kmip/tests/utils/__init__.py rename to kmip/tests/integration/utils/__init__.py diff --git a/kmip/tests/integration/utils/certs/server.crt b/kmip/tests/integration/utils/certs/server.crt new file mode 100644 index 0000000..5382c69 --- /dev/null +++ b/kmip/tests/integration/utils/certs/server.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBjCCAe4CCQDWchiOQEmcDDANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB +VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMB4XDTE0MDgxOTA0MjAzM1oXDTE1MDgxOTA0MjAzM1owRTELMAkG +A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 +IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AKcLbcQbhvzQ/5JB/omGt+VHXbnUinWKygYPNdJH5dvt0DVUNRvlvjTjkrNqTTVG +iAdSuhxylW6NB7/aJ5Cen3J22NT01O7g5JNsNrrDwvOUNLnaMYCtIaMaHPrLFqTb +SwlUoCbwY1W9/PWb63IorZOrs4iT0DhBqal6gshUFXYPYqTtseO+lMwTh9ETIcnV +8wwFCieX4czmQKcBZCBXShkyepSW/JczaYEelxhlfsAvNWKnvLE0SCOM2wp7XaB4 +Rjx0wbenQQvg0KqksIBXBa/Xm2YNyzonnPpG59HoAuap3ZP6ZqgdRy9CYNK92j17 +ZGzrxG5FWNeGKSCJUi7O7/sCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAnx2LB4Ma +BKHOszMJQi5vrLni6G1IMWNmbbXERHancFovgGB//YaTnKnJxEPXx+WIrX5S+zLI +3Du4bQ78HMv7TSp5YV/E988qaGHjrKNp4aZpDM/uDE1p3Ik2mPUCa4uf3/HT2VaI +LzSYZN7/C2CLg/65MuV10Tus0wE3H6UCWmBjNuZpCxIvuEYA2ZD7pHdvZgOe/dYX +PEDRyDzkMAArJ/v4A/yj9JUB2nGkJLf/KHImFfZ+3+6UIiOQPsRvMlw4y7vCV+5d +T5TN4NSj9+l6kGiB4fFszj60erPlRpshuRjcrrzJAxK7XZgZgsl/6UMoPBoUdsNx +/Wc6VFs6KyJvgw== +-----END CERTIFICATE----- diff --git a/kmip/tests/integration/utils/certs/server.key b/kmip/tests/integration/utils/certs/server.key new file mode 100644 index 0000000..5063f9e --- /dev/null +++ b/kmip/tests/integration/utils/certs/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEApwttxBuG/ND/kkH+iYa35UddudSKdYrKBg810kfl2+3QNVQ1 +G+W+NOOSs2pNNUaIB1K6HHKVbo0Hv9onkJ6fcnbY1PTU7uDkk2w2usPC85Q0udox +gK0hoxoc+ssWpNtLCVSgJvBjVb389Zvrciitk6uziJPQOEGpqXqCyFQVdg9ipO2x +476UzBOH0RMhydXzDAUKJ5fhzOZApwFkIFdKGTJ6lJb8lzNpgR6XGGV+wC81Yqe8 +sTRII4zbCntdoHhGPHTBt6dBC+DQqqSwgFcFr9ebZg3LOiec+kbn0egC5qndk/pm +qB1HL0Jg0r3aPXtkbOvEbkVY14YpIIlSLs7v+wIDAQABAoIBAQCiM6nJNAWWdgbE +aUqVFfh5LRwoduZfjn3u9lQHtQLQ1JJJRlQvm51fU98+UilYYv1xRvYq62SIrW7p +7xZeCni/OAICfx5IOp4ZPInEPpSN2sp78RACZ5ry+kdLi2qYd8vb6o18Yg3C0zHO ++DDeb/tkGeTB6O3VwoTRaYGWrncMZABgOjGI0Iyjn4tJZnl8V+rhoseCKezGwaZl +rAukc0lv4GX6jQoMWB72/qhIu8a9MinP0b3U17j+flnVlcrYS1Y6Atuj4sGCpeVc +fxLfbkUy2p7Ja4YBmYfhlnJb76VBKr2MeKHcHJl2+CzWMbDJsH+/skD0UPfvicjr +wC1m9NQxAoGBANR6a6x3afQG2iLMhmQa9WdH7ufWlL122ssal+u66r68PsqBu0Zs +264lYyJmjyQvWw6Kbh1Lre14/LpwJMZko2HSqcy0cz7qTKwIAcxI3Qi5ZEhngU/l +lyOLFm6fPdA57vTkb7kgi1EmwWdf8mTDCHrLQpCMIRXc1rQAYKwfGb35AoGBAMlC +o3Ol+Br8pltjKtmlfYLnznFeepqPWBO+lTFqZYA6LvDAsjfEVufsMXCeNKq0Uopi +ocRIkPy0V1DZSe3hfZAV55fH3nk9uo2MfSsEKS/0lrG6PG4VK69Mo9wvkj7N5Oyj +qFc8tjRO43IZaOA1zWh8eFGdHERs6AZHXWEPvCqTAoGAB7nX1nKVILFrFx7WuCce +yz2bW0S7LdR3ijESWxj11i+kHNrww1PL/R4Q57xQ8iDir7mq3VfWIC9pCSJww+H+ +6tytHetl0WDVnt+/qPzxRJLxKYzR7+TKRRmWnDkgF0U0AiWYRmP/jNja6XZcqvtI +gKaJahYeUdww1mS5HykWV4kCgYEAjz2yf7j8YJi4/goSkV1Le0Polp+buy2Sjlry +bH1BSIYgqpE7Rp2jDOX6OiEfcu9sX7nbUIwlRPZFvvEnwPrgFxDACDLkkH3yrJP0 +8gzAE7WNG2llYSQIN3fgl/HzsGdyK0o/ofc/5vLOxoJ3NjyUuWz9ZXjgiYLJkM5y +E4bTcakCgYBQZuce3iG9DpW/YZwRIasUYfjLgOecwLRP+Bh8iv6NAe3sOJFlY1XQ +37De7wtSG24SogJDv5vglI9MwY2N1MCqT74HgZhazjtIz3cXwREDf7/vmiWsBPlA +Xghc8kmX70eb471WAI9y1wlj/UtNEeXT/ntfWCLFKdBH+o32P/UsiQ== +-----END RSA PRIVATE KEY----- diff --git a/kmip/tests/utils/server.py b/kmip/tests/integration/utils/server.py similarity index 96% rename from kmip/tests/utils/server.py rename to kmip/tests/integration/utils/server.py index 2e1fa44..2c061e5 100644 --- a/kmip/tests/utils/server.py +++ b/kmip/tests/integration/utils/server.py @@ -60,11 +60,11 @@ def build_cli_parser(): dest="port", help="Port number for KMIP services") parser.add_option("-k", "--keyfile", action="store", default=os.path.normpath(os.path.join( - FILE_PATH, '../../demos/certs/server.key')), + FILE_PATH, '../utils/certs/server.key')), dest="keyfile") parser.add_option("-c", "--certfile", action="store", default=os.path.normpath(os.path.join( - FILE_PATH, '../../demos/certs/server.crt')), + FILE_PATH, '../utils/certs/server.crt')), dest="certfile") parser.add_option("-r", "--cert_reqs", action="store", default="CERT_NONE", dest="cert_reqs") diff --git a/kmip/tests/core/misc/__init__.py b/kmip/tests/unit/__init__.py similarity index 100% rename from kmip/tests/core/misc/__init__.py rename to kmip/tests/unit/__init__.py diff --git a/kmip/tests/core/__init__.py b/kmip/tests/unit/core/__init__.py similarity index 100% rename from kmip/tests/core/__init__.py rename to kmip/tests/unit/core/__init__.py diff --git a/kmip/tests/core/objects/__init__.py b/kmip/tests/unit/core/attributes/__init__.py similarity index 100% rename from kmip/tests/core/objects/__init__.py rename to kmip/tests/unit/core/attributes/__init__.py diff --git a/kmip/tests/core/attributes/test_application_specific_information.py b/kmip/tests/unit/core/attributes/test_application_specific_information.py similarity index 100% rename from kmip/tests/core/attributes/test_application_specific_information.py rename to kmip/tests/unit/core/attributes/test_application_specific_information.py diff --git a/kmip/tests/core/attributes/test_attributes.py b/kmip/tests/unit/core/attributes/test_attributes.py similarity index 100% rename from kmip/tests/core/attributes/test_attributes.py rename to kmip/tests/unit/core/attributes/test_attributes.py diff --git a/kmip/tests/core/attributes/test_digest.py b/kmip/tests/unit/core/attributes/test_digest.py similarity index 100% rename from kmip/tests/core/attributes/test_digest.py rename to kmip/tests/unit/core/attributes/test_digest.py diff --git a/kmip/tests/core/factories/__init__.py b/kmip/tests/unit/core/factories/__init__.py similarity index 100% rename from kmip/tests/core/factories/__init__.py rename to kmip/tests/unit/core/factories/__init__.py diff --git a/kmip/tests/core/factories/payloads/__init__.py b/kmip/tests/unit/core/factories/payloads/__init__.py similarity index 100% rename from kmip/tests/core/factories/payloads/__init__.py rename to kmip/tests/unit/core/factories/payloads/__init__.py diff --git a/kmip/tests/core/factories/payloads/test_payload.py b/kmip/tests/unit/core/factories/payloads/test_payload.py similarity index 100% rename from kmip/tests/core/factories/payloads/test_payload.py rename to kmip/tests/unit/core/factories/payloads/test_payload.py diff --git a/kmip/tests/core/factories/payloads/test_request.py b/kmip/tests/unit/core/factories/payloads/test_request.py similarity index 100% rename from kmip/tests/core/factories/payloads/test_request.py rename to kmip/tests/unit/core/factories/payloads/test_request.py diff --git a/kmip/tests/core/factories/payloads/test_response.py b/kmip/tests/unit/core/factories/payloads/test_response.py similarity index 100% rename from kmip/tests/core/factories/payloads/test_response.py rename to kmip/tests/unit/core/factories/payloads/test_response.py diff --git a/kmip/tests/core/factories/test_attribute_values.py b/kmip/tests/unit/core/factories/test_attribute_values.py similarity index 100% rename from kmip/tests/core/factories/test_attribute_values.py rename to kmip/tests/unit/core/factories/test_attribute_values.py diff --git a/kmip/tests/core/messages/__init__.py b/kmip/tests/unit/core/messages/__init__.py similarity index 100% rename from kmip/tests/core/messages/__init__.py rename to kmip/tests/unit/core/messages/__init__.py diff --git a/kmip/tests/core/secrets/__init__.py b/kmip/tests/unit/core/messages/contents/__init__.py similarity index 100% rename from kmip/tests/core/secrets/__init__.py rename to kmip/tests/unit/core/messages/contents/__init__.py diff --git a/kmip/tests/core/messages/contents/test_protocol_version.py b/kmip/tests/unit/core/messages/contents/test_protocol_version.py similarity index 100% rename from kmip/tests/core/messages/contents/test_protocol_version.py rename to kmip/tests/unit/core/messages/contents/test_protocol_version.py diff --git a/kmip/tests/core/messages/payloads/__init__.py b/kmip/tests/unit/core/messages/payloads/__init__.py similarity index 100% rename from kmip/tests/core/messages/payloads/__init__.py rename to kmip/tests/unit/core/messages/payloads/__init__.py diff --git a/kmip/tests/core/messages/payloads/test_create.py b/kmip/tests/unit/core/messages/payloads/test_create.py similarity index 100% rename from kmip/tests/core/messages/payloads/test_create.py rename to kmip/tests/unit/core/messages/payloads/test_create.py diff --git a/kmip/tests/core/messages/payloads/test_create_key_pair.py b/kmip/tests/unit/core/messages/payloads/test_create_key_pair.py similarity index 100% rename from kmip/tests/core/messages/payloads/test_create_key_pair.py rename to kmip/tests/unit/core/messages/payloads/test_create_key_pair.py diff --git a/kmip/tests/core/messages/payloads/test_destroy.py b/kmip/tests/unit/core/messages/payloads/test_destroy.py similarity index 100% rename from kmip/tests/core/messages/payloads/test_destroy.py rename to kmip/tests/unit/core/messages/payloads/test_destroy.py diff --git a/kmip/tests/core/messages/payloads/test_discover_versions.py b/kmip/tests/unit/core/messages/payloads/test_discover_versions.py similarity index 100% rename from kmip/tests/core/messages/payloads/test_discover_versions.py rename to kmip/tests/unit/core/messages/payloads/test_discover_versions.py diff --git a/kmip/tests/core/messages/payloads/test_get.py b/kmip/tests/unit/core/messages/payloads/test_get.py similarity index 100% rename from kmip/tests/core/messages/payloads/test_get.py rename to kmip/tests/unit/core/messages/payloads/test_get.py diff --git a/kmip/tests/core/messages/payloads/test_locate.py b/kmip/tests/unit/core/messages/payloads/test_locate.py similarity index 100% rename from kmip/tests/core/messages/payloads/test_locate.py rename to kmip/tests/unit/core/messages/payloads/test_locate.py diff --git a/kmip/tests/core/messages/payloads/test_query.py b/kmip/tests/unit/core/messages/payloads/test_query.py similarity index 100% rename from kmip/tests/core/messages/payloads/test_query.py rename to kmip/tests/unit/core/messages/payloads/test_query.py diff --git a/kmip/tests/core/messages/payloads/test_register.py b/kmip/tests/unit/core/messages/payloads/test_register.py similarity index 100% rename from kmip/tests/core/messages/payloads/test_register.py rename to kmip/tests/unit/core/messages/payloads/test_register.py diff --git a/kmip/tests/core/messages/payloads/test_rekey_key_pair.py b/kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py similarity index 100% rename from kmip/tests/core/messages/payloads/test_rekey_key_pair.py rename to kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py diff --git a/kmip/tests/core/messages/test_messages.py b/kmip/tests/unit/core/messages/test_messages.py similarity index 100% rename from kmip/tests/core/messages/test_messages.py rename to kmip/tests/unit/core/messages/test_messages.py diff --git a/kmip/tests/core/messages/test_operations.py b/kmip/tests/unit/core/messages/test_operations.py similarity index 100% rename from kmip/tests/core/messages/test_operations.py rename to kmip/tests/unit/core/messages/test_operations.py diff --git a/kmip/tests/unit/core/misc/__init__.py b/kmip/tests/unit/core/misc/__init__.py new file mode 100644 index 0000000..417e2f9 --- /dev/null +++ b/kmip/tests/unit/core/misc/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory +# 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. diff --git a/kmip/tests/core/misc/test_misc.py b/kmip/tests/unit/core/misc/test_misc.py similarity index 100% rename from kmip/tests/core/misc/test_misc.py rename to kmip/tests/unit/core/misc/test_misc.py diff --git a/kmip/tests/core/misc/test_server_information.py b/kmip/tests/unit/core/misc/test_server_information.py similarity index 100% rename from kmip/tests/core/misc/test_server_information.py rename to kmip/tests/unit/core/misc/test_server_information.py diff --git a/kmip/tests/unit/core/objects/__init__.py b/kmip/tests/unit/core/objects/__init__.py new file mode 100644 index 0000000..417e2f9 --- /dev/null +++ b/kmip/tests/unit/core/objects/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory +# 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. diff --git a/kmip/tests/core/objects/test_extension_information.py b/kmip/tests/unit/core/objects/test_extension_information.py similarity index 100% rename from kmip/tests/core/objects/test_extension_information.py rename to kmip/tests/unit/core/objects/test_extension_information.py diff --git a/kmip/tests/core/objects/test_objects.py b/kmip/tests/unit/core/objects/test_objects.py similarity index 100% rename from kmip/tests/core/objects/test_objects.py rename to kmip/tests/unit/core/objects/test_objects.py diff --git a/kmip/tests/unit/core/secrets/__init__.py b/kmip/tests/unit/core/secrets/__init__.py new file mode 100644 index 0000000..417e2f9 --- /dev/null +++ b/kmip/tests/unit/core/secrets/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory +# 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. diff --git a/kmip/tests/core/secrets/test_certificate.py b/kmip/tests/unit/core/secrets/test_certificate.py similarity index 100% rename from kmip/tests/core/secrets/test_certificate.py rename to kmip/tests/unit/core/secrets/test_certificate.py diff --git a/kmip/tests/core/test_config_helper.py b/kmip/tests/unit/core/test_config_helper.py similarity index 100% rename from kmip/tests/core/test_config_helper.py rename to kmip/tests/unit/core/test_config_helper.py diff --git a/kmip/tests/core/test_primitives.py b/kmip/tests/unit/core/test_primitives.py similarity index 100% rename from kmip/tests/core/test_primitives.py rename to kmip/tests/unit/core/test_primitives.py diff --git a/kmip/tests/core/test_server.py b/kmip/tests/unit/core/test_server.py similarity index 100% rename from kmip/tests/core/test_server.py rename to kmip/tests/unit/core/test_server.py diff --git a/kmip/tests/core/test_utils.py b/kmip/tests/unit/core/test_utils.py similarity index 100% rename from kmip/tests/core/test_utils.py rename to kmip/tests/unit/core/test_utils.py diff --git a/kmip/tests/services/__init__.py b/kmip/tests/unit/services/__init__.py similarity index 100% rename from kmip/tests/services/__init__.py rename to kmip/tests/unit/services/__init__.py diff --git a/kmip/tests/services/test_kmip_client.py b/kmip/tests/unit/services/test_kmip_client.py similarity index 58% rename from kmip/tests/services/test_kmip_client.py rename to kmip/tests/unit/services/test_kmip_client.py index 2d9f659..fceafa7 100644 --- a/kmip/tests/services/test_kmip_client.py +++ b/kmip/tests/unit/services/test_kmip_client.py @@ -15,31 +15,13 @@ from testtools import TestCase -from subprocess import Popen - -import os -import sys -import time - -from kmip.core.attributes import CryptographicAlgorithm -from kmip.core.attributes import CryptographicLength from kmip.core.attributes import PrivateKeyUniqueIdentifier -from kmip.core.enums import AttributeType from kmip.core.enums import AuthenticationSuite from kmip.core.enums import ConformanceClause from kmip.core.enums import CredentialType -from kmip.core.enums import CryptographicAlgorithm as CryptoAlgorithmEnum -from kmip.core.enums import CryptographicUsageMask -from kmip.core.enums import ObjectType from kmip.core.enums import Operation as OperationEnum -from kmip.core.enums import KeyFormatType as KeyFormatTypeEnum from kmip.core.enums import QueryFunction as QueryFunctionEnum -from kmip.core.enums import ResultStatus -from kmip.core.enums import ResultReason - -from kmip.core.errors import KMIPServerSuicideError -from kmip.core.errors import KMIPServerZombieError from kmip.core.factories.attributes import AttributeFactory from kmip.core.factories.credentials import CredentialFactory @@ -59,22 +41,14 @@ from kmip.core.messages.payloads.query import \ from kmip.core.messages.payloads.rekey_key_pair import \ RekeyKeyPairRequestPayload, RekeyKeyPairResponsePayload -from kmip.core.misc import KeyFormatType from kmip.core.misc import Offset from kmip.core.misc import QueryFunction from kmip.core.misc import ServerInformation from kmip.core.misc import VendorIdentification -from kmip.core.objects import Attribute from kmip.core.objects import CommonTemplateAttribute -from kmip.core.objects import KeyBlock -from kmip.core.objects import KeyMaterial -from kmip.core.objects import KeyValue from kmip.core.objects import PrivateKeyTemplateAttribute from kmip.core.objects import PublicKeyTemplateAttribute -from kmip.core.objects import TemplateAttribute - -from kmip.core.secrets import SymmetricKey from kmip.services.kmip_client import KMIPProxy @@ -86,353 +60,6 @@ from kmip.services.results import RekeyKeyPairResult import kmip.core.utils as utils -# TODO (peter-hamilton) Move integration tests into separate module -class TestKMIPClientIntegration(TestCase): - STARTUP_TIME = 1.0 - SHUTDOWN_TIME = 0.1 - KMIP_PORT = 9090 - CA_CERTS_PATH = os.path.normpath(os.path.join(os.path.dirname( - os.path.abspath(__file__)), '../../demos/certs/server.crt')) - - def setUp(self): - super(TestKMIPClientIntegration, self).setUp() - - self.attr_factory = AttributeFactory() - self.cred_factory = CredentialFactory() - self.secret_factory = SecretFactory() - - # Set up the KMIP server process - path = os.path.join(os.path.dirname(__file__), os.path.pardir, - 'utils', 'server.py') - self.server = Popen(['python', '{0}'.format(path), '-p', - '{0}'.format(self.KMIP_PORT)], stderr=sys.stdout) - - time.sleep(self.STARTUP_TIME) - - if self.server.poll() is not None: - raise KMIPServerSuicideError(self.server.pid) - - # Set up and open the client proxy; shutdown the server if open fails - try: - self.client = KMIPProxy(port=self.KMIP_PORT, - ca_certs=self.CA_CERTS_PATH) - self.client.open() - except Exception as e: - self._shutdown_server() - raise e - - def tearDown(self): - super(TestKMIPClientIntegration, self).tearDown() - - # Close the client proxy and shutdown the server - self.client.close() - self._shutdown_server() - - def test_create(self): - result = self._create_symmetric_key() - - self._check_result_status(result.result_status.enum, ResultStatus, - ResultStatus.SUCCESS) - self._check_object_type(result.object_type.enum, ObjectType, - ObjectType.SYMMETRIC_KEY) - self._check_uuid(result.uuid.value, str) - - # Check the template attribute type - self._check_template_attribute(result.template_attribute, - TemplateAttribute, 2, - [[str, 'Cryptographic Length', int, - 256], - [str, 'Unique Identifier', str, - None]]) - - def test_get(self): - credential_type = CredentialType.USERNAME_AND_PASSWORD - credential_value = {'Username': 'Peter', 'Password': 'abc123'} - credential = self.cred_factory.create_credential(credential_type, - credential_value) - result = self._create_symmetric_key() - uuid = result.uuid.value - - result = self.client.get(uuid=uuid, credential=credential) - - self._check_result_status(result.result_status.enum, ResultStatus, - ResultStatus.SUCCESS) - self._check_object_type(result.object_type.enum, ObjectType, - ObjectType.SYMMETRIC_KEY) - self._check_uuid(result.uuid.value, str) - - # Check the secret type - secret = result.secret - - expected = SymmetricKey - message = utils.build_er_error(result.__class__, 'type', expected, - secret, 'secret') - self.assertIsInstance(secret, expected, message) - - def test_destroy(self): - credential_type = CredentialType.USERNAME_AND_PASSWORD - credential_value = {'Username': 'Peter', 'Password': 'abc123'} - credential = self.cred_factory.create_credential(credential_type, - credential_value) - result = self._create_symmetric_key() - uuid = result.uuid.value - - # Verify the secret was created - result = self.client.get(uuid=uuid, credential=credential) - - self._check_result_status(result.result_status.enum, ResultStatus, - ResultStatus.SUCCESS) - self._check_object_type(result.object_type.enum, ObjectType, - ObjectType.SYMMETRIC_KEY) - self._check_uuid(result.uuid.value, str) - - secret = result.secret - - expected = SymmetricKey - message = utils.build_er_error(result.__class__, 'type', expected, - secret, 'secret') - self.assertIsInstance(secret, expected, message) - - # Destroy the SYMMETRIC_KEY object - result = self.client.destroy(uuid, credential) - self._check_result_status(result.result_status.enum, ResultStatus, - ResultStatus.SUCCESS) - self._check_uuid(result.uuid.value, str) - - # Verify the secret was destroyed - result = self.client.get(uuid=uuid, credential=credential) - - self._check_result_status(result.result_status.enum, ResultStatus, - ResultStatus.OPERATION_FAILED) - - expected = ResultReason - observed = type(result.result_reason.enum) - message = utils.build_er_error(result.result_reason.__class__, 'type', - expected, observed) - self.assertEqual(expected, observed, message) - - expected = ResultReason.ITEM_NOT_FOUND - observed = result.result_reason.enum - message = utils.build_er_error(result.result_reason.__class__, - 'value', expected, observed) - self.assertEqual(expected, observed, message) - - def test_register(self): - credential_type = CredentialType.USERNAME_AND_PASSWORD - credential_value = {'Username': 'Peter', 'Password': 'abc123'} - credential = self.cred_factory.create_credential(credential_type, - credential_value) - - object_type = ObjectType.SYMMETRIC_KEY - algorithm_value = CryptoAlgorithmEnum.AES - mask_flags = [CryptographicUsageMask.ENCRYPT, - CryptographicUsageMask.DECRYPT] - attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK - usage_mask = self.attr_factory.create_attribute(attribute_type, - mask_flags) - attributes = [usage_mask] - template_attribute = TemplateAttribute(attributes=attributes) - - key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW) - - key_data = ( - b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' - b'\x00') - - key_material = KeyMaterial(key_data) - key_value = KeyValue(key_material) - cryptographic_algorithm = CryptographicAlgorithm(algorithm_value) - cryptographic_length = CryptographicLength(128) - - key_block = KeyBlock( - key_format_type=key_format_type, - key_compression_type=None, - key_value=key_value, - cryptographic_algorithm=cryptographic_algorithm, - cryptographic_length=cryptographic_length, - key_wrapping_data=None) - - secret = SymmetricKey(key_block) - - result = self.client.register(object_type, template_attribute, secret, - credential) - - self._check_result_status(result.result_status.enum, ResultStatus, - ResultStatus.SUCCESS) - self._check_uuid(result.uuid.value, str) - - # Check the template attribute type - self._check_template_attribute(result.template_attribute, - TemplateAttribute, 1, - [[str, 'Unique Identifier', str, - None]]) - # Check that the returned key bytes match what was provided - uuid = result.uuid.value - result = self.client.get(uuid=uuid, credential=credential) - - self._check_result_status(result.result_status.enum, ResultStatus, - ResultStatus.SUCCESS) - self._check_object_type(result.object_type.enum, ObjectType, - ObjectType.SYMMETRIC_KEY) - self._check_uuid(result.uuid.value, str) - - # Check the secret type - secret = result.secret - - expected = SymmetricKey - message = utils.build_er_error(result.__class__, 'type', expected, - secret, 'secret') - self.assertIsInstance(secret, expected, message) - - key_block = result.secret.key_block - key_value = key_block.key_value - key_material = key_value.key_material - - expected = key_data - observed = key_material.value - message = utils.build_er_error(key_material.__class__, 'value', - expected, observed, 'value') - self.assertEqual(expected, observed, message) - - def _shutdown_server(self): - if self.server.poll() is not None: - return - else: - # Terminate the server process. If it resists, kill it. - pid = self.server.pid - self.server.terminate() - time.sleep(self.SHUTDOWN_TIME) - - if self.server.poll() is None: - raise KMIPServerZombieError(pid) - - def _create_symmetric_key(self): - credential_type = CredentialType.USERNAME_AND_PASSWORD - credential_value = {'Username': 'Peter', 'Password': 'abc123'} - credential = self.cred_factory.create_credential(credential_type, - credential_value) - - object_type = ObjectType.SYMMETRIC_KEY - attribute_type = AttributeType.CRYPTOGRAPHIC_ALGORITHM - algorithm = self.attr_factory.create_attribute( - attribute_type, - CryptoAlgorithmEnum.AES) - - mask_flags = [CryptographicUsageMask.ENCRYPT, - CryptographicUsageMask.DECRYPT] - attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK - usage_mask = self.attr_factory.create_attribute(attribute_type, - mask_flags) - attributes = [algorithm, usage_mask] - template_attribute = TemplateAttribute(attributes=attributes) - - return self.client.create(object_type, template_attribute, - credential) - - def _check_result_status(self, result_status, result_status_type, - result_status_value): - # Error check the result status type and value - expected = result_status_type - message = utils.build_er_error(result_status_type, 'type', expected, - result_status) - self.assertIsInstance(result_status, expected, message) - - expected = result_status_value - message = utils.build_er_error(result_status_type, 'value', expected, - result_status) - self.assertEqual(expected, result_status, message) - - def _check_uuid(self, uuid, uuid_type): - # Error check the UUID type and value - not_expected = None - message = utils.build_er_error(uuid_type, 'type', - 'not {0}'.format(not_expected), uuid) - self.assertNotEqual(not_expected, uuid, message) - - expected = uuid_type - message = utils.build_er_error(uuid_type, 'type', expected, uuid) - self.assertEqual(expected, type(uuid), message) - - def _check_object_type(self, object_type, object_type_type, - object_type_value): - # Error check the object type type and value - expected = object_type_type - message = utils.build_er_error(object_type_type, 'type', expected, - object_type) - self.assertIsInstance(object_type, expected, message) - - expected = object_type_value - message = utils.build_er_error(object_type_type, 'value', expected, - object_type) - self.assertEqual(expected, object_type, message) - - def _check_template_attribute(self, template_attribute, - template_attribute_type, num_attributes, - attribute_features): - # Error check the template attribute type - expected = template_attribute_type - message = utils.build_er_error(template_attribute.__class__, 'type', - expected, template_attribute) - self.assertIsInstance(template_attribute, expected, message) - - attributes = template_attribute.attributes - - expected = num_attributes - observed = len(attributes) - message = utils.build_er_error(TemplateAttribute.__class__, 'number', - expected, observed, 'attributes') - - for i in range(num_attributes): - features = attribute_features[i] - self._check_attribute(attributes[i], features[0], features[1], - features[2], features[3]) - - def _check_attribute(self, attribute, attribute_name_type, - attribute_name_value, attribute_value_type, - attribute_value_value): - # Error check the attribute name and value type and value - attribute_name = attribute.attribute_name - attribute_value = attribute.attribute_value - - self._check_attribute_name(attribute_name, attribute_name_type, - attribute_name_value) - - if attribute_name_value == 'Unique Identifier': - self._check_uuid(attribute_value.value, attribute_value_type) - else: - self._check_attribute_value(attribute_value, attribute_value_type, - attribute_value_value) - - def _check_attribute_name(self, attribute_name, attribute_name_type, - attribute_name_value): - # Error check the attribute name type and value - expected = attribute_name_type - observed = type(attribute_name.value) - message = utils.build_er_error(attribute_name_type, 'type', expected, - observed) - self.assertEqual(expected, observed, message) - - expected = attribute_name_value - observed = attribute_name.value - message = utils.build_er_error(attribute_name_type, 'value', expected, - observed) - self.assertEqual(expected, observed, message) - - def _check_attribute_value(self, attribute_value, attribute_value_type, - attribute_value_value): - expected = attribute_value_type - observed = type(attribute_value.value) - message = utils.build_er_error(Attribute, 'type', expected, observed, - 'attribute_value') - self.assertEqual(expected, observed, message) - - expected = attribute_value_value - observed = attribute_value.value - message = utils.build_er_error(Attribute, 'value', expected, observed, - 'attribute_value') - self.assertEqual(expected, observed, message) - - class TestKMIPClient(TestCase): def setUp(self): diff --git a/setup.py b/setup.py index 9c843e1..8fe3ea6 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,7 @@ setuptools.setup( url='https://github.com/OpenKMIP/PyKMIP', license='Apache License, Version 2.0', packages=setuptools.find_packages(exclude=["kmip.tests", "kmip.tests.*"]), - package_data={'kmip': ['logconfig.ini'], + package_data={'kmip': ['kmipconfig.ini', 'logconfig.ini'], 'kmip.demos': ['certs/server.crt', 'certs/server.key']}, install_requires=[ "enum34", diff --git a/tox.ini b/tox.ini index c33ab27..00dd890 100644 --- a/tox.ini +++ b/tox.ini @@ -6,11 +6,18 @@ deps = -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt commands = - coverage run --source=kmip/ -m pytest --strict {posargs} - coverage report + coverage run --source=kmip/ --omit=kmip/demos/*,kmip/tests/* -m pytest --strict kmip/tests/unit + coverage report -m + coverage html [testenv:pep8] -commands = flake8 {posargs} +commands = flake8 kmip/ + +[testenv:integration] +# Note: This requires local or remote access to a KMIP appliance or service +deps = {[testenv]deps} +commands = + py.test --strict kmip/tests/integration [flake8] exclude = .git,.tox,dist,rpmbuild,*.egg-info