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