Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

revamping attrs-controlled class tests #33

Merged
merged 9 commits into from
Dec 5, 2017
9 changes: 5 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,17 @@ matrix:
env: TOXENV=bandit
- python: 3.6
env: TOXENV=doc8
- python: 3.6
env: TOXENV=docs
- python: 3.6
env: TOXENV=readme
# pending reorg of deserialize_header
# - python: 3.6
# env: TOXENV=flake8
# - python: 3.6
# env: TOXENV=pylint
# pending test-vectors refactor
# - python: 3.6
# env: TOXENV=flake8-tests
- python: 3.6
env: TOXENV=flake8-tests
- python: 3.6
env: TOXENV=pylint-tests
- python: 3.6
Expand All @@ -33,4 +34,4 @@ matrix:
- python: 3.6
env: TOXENV=pylint-examples
install: pip install tox
script: tox
script: tox
14 changes: 14 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@
Changelog
*********

1.3.3
=====

Bugfixes
--------
* Remove use of attrs functionality deprecated in 17.3.0
`#29 <https://github.com/awslabs/aws-encryption-sdk-python/issues/29>`_

Maintenance
-----------
* Blacklisted pytest 3.3.0
`#32 <https://github.com/awslabs/aws-encryption-sdk-python/issues/32>`_
`pytest-dev/pytest#2957 <https://github.com/pytest-dev/pytest/issues/2957>`_

1.3.2
=====
* Addressed `issue #13 <https://github.com/awslabs/aws-encryption-sdk-python/issues/13>`_
Expand Down
2 changes: 1 addition & 1 deletion src/aws_encryption_sdk/identifiers.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

from aws_encryption_sdk.exceptions import InvalidAlgorithmError

__version__ = '1.3.2'
__version__ = '1.3.3'
USER_AGENT_SUFFIX = 'AwsEncryptionSdkPython-KMSMasterKey/{}'.format(__version__)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# language governing permissions and limitations under the License.
"""Components for handling AWS Encryption SDK message deserialization."""
from __future__ import division

import io
import logging
import struct
Expand Down
26 changes: 8 additions & 18 deletions src/aws_encryption_sdk/key_providers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,6 @@ def decrypt_data_key_from_list(self, encrypted_data_keys, algorithm, encryption_


@attr.s(hash=True)
@six.add_metaclass(abc.ABCMeta)
class MasterKeyConfig(object):
"""Configuration object for MasterKey objects.

Expand All @@ -307,23 +306,10 @@ class MasterKeyConfig(object):
convert=to_bytes
)

@abc.abstractproperty
def provider_id(self):
"""Utilizing ABCMeta to enable children to either set this as a class property or require it as input.

.. note::
Must be implemented by child classes.

If requiring provider_id as input:

.. code-block:: python

provider_id = attr.ib(
hash=True,
validator=attr.validators.instance_of((six.string_types, bytes)),
convert=aws_encryption_sdk.internal.str_ops.to_str
)
"""
def __attrs_post_init__(self):
"""Verify that children of this class define a "provider_id" attribute."""
if not hasattr(self, 'provider_id'):
raise TypeError('Instances of MasterKeyConfig must have a "provider_id" attribute defined.')


@six.add_metaclass(abc.ABCMeta)
Expand All @@ -338,6 +324,10 @@ class MasterKey(MasterKeyProvider):
def __new__(cls, **kwargs):
"""Performs universal prep work for all MasterKeys."""
instance = super(MasterKey, cls).__new__(cls, **kwargs)

if not hasattr(instance.config, 'provider_id'):
raise TypeError('MasterKey config classes must have a "provider_id" attribute defined.')

if instance.config.provider_id is not None:
# Only allow override if provider_id is NOT set to non-None for the class
if instance.provider_id is None:
Expand Down
1 change: 1 addition & 0 deletions src/aws_encryption_sdk/streaming_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# language governing permissions and limitations under the License.
"""High level AWS Encryption SDK client for streaming objects."""
from __future__ import division

import abc
import io
import logging
Expand Down
4 changes: 1 addition & 3 deletions test/functional/test_f_xcompat.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
"""Functional test suite testing decryption of known good test files encrypted using static RawMasterKeyProvider."""
from __future__ import print_function
import base64
from collections import defaultdict
import json
Expand Down Expand Up @@ -78,7 +77,6 @@ def _get_raw_key(self, key_id):
key_bits = int(key_bits)
key_type = _KEY_TYPES_MAP[algorithm]
wrapping_algorithm = _WRAPPING_ALGORITHM_MAP[algorithm][key_bits][padding_algorithm][padding_hash]
print('looking up {} {}'.format(algorithm, key_bits))
static_key = _STATIC_KEYS[algorithm][key_bits]
return WrappingKey(
wrapping_algorithm=wrapping_algorithm,
Expand Down Expand Up @@ -113,7 +111,7 @@ class Scenario(object):
key_ids = attr.ib(validator=attr.validators.instance_of(list))


def _generate_test_cases():
def _generate_test_cases(): # noqa=C901
try:
root_dir = os.path.abspath(file_root())
except Exception: # pylint: disable=broad-except
Expand Down
1 change: 0 additions & 1 deletion test/integration/test_i_aws_encrytion_sdk_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

import aws_encryption_sdk
from aws_encryption_sdk.identifiers import Algorithm

from .integration_test_utils import setup_kms_master_key_provider, SKIP_MESSAGE, skip_tests


Expand Down
1 change: 0 additions & 1 deletion test/integration/test_i_xcompat_kms.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import pytest

import aws_encryption_sdk

from .integration_test_utils import setup_kms_master_key_provider, SKIP_MESSAGE, skip_tests


Expand Down
1 change: 0 additions & 1 deletion test/unit/test_crypto_authentication_signer.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import aws_encryption_sdk.internal.crypto.authentication
from aws_encryption_sdk.internal.crypto.authentication import Signer
from aws_encryption_sdk.internal.defaults import ALGORITHM

from .test_crypto import VALUES


Expand Down
1 change: 0 additions & 1 deletion test/unit/test_crypto_authentication_verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import aws_encryption_sdk.internal.crypto.authentication
from aws_encryption_sdk.internal.crypto.authentication import Verifier
from aws_encryption_sdk.internal.defaults import ALGORITHM

from .test_crypto import VALUES


Expand Down
1 change: 0 additions & 1 deletion test/unit/test_crypto_elliptic_curve.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
_ecc_public_numbers_from_compressed_point, _ecc_static_length_signature,
_ECCCurveParameters, generate_ecc_signing_key
)

from .test_crypto import VALUES


Expand Down
1 change: 0 additions & 1 deletion test/unit/test_crypto_wrapping_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import aws_encryption_sdk.internal.crypto.wrapping_keys
from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey
from aws_encryption_sdk.internal.structures import EncryptedData

from .test_crypto import VALUES


Expand Down
151 changes: 47 additions & 104 deletions test/unit/test_internal_structures.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,60 @@
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
"""Unit test suite for aws_encryption_sdk.internal.structures"""
import attr
import pytest
import six

from aws_encryption_sdk.internal.structures import (
EncryptedData, MessageFooter, MessageFrameBody, MessageHeaderAuthentication, MessageNoFrameBody
)
from .unit_test_utils import all_invalid_kwargs, all_valid_kwargs


VALID_KWARGS = {
EncryptedData: [
dict(ciphertext=b'asjfoiwaj', iv=None, tag=None),
dict(ciphertext=b'asjfoiwaj', iv=b'ajsdhfiuaweh', tag=None),
dict(ciphertext=b'asjfoiwaj', iv=None, tag=b'aosijfoiewj'),
dict(ciphertext=b'asjfoiwaj', iv=b'ajsdhfiuaweh', tag=b'aosijfoiewj')
],
MessageHeaderAuthentication: [
dict(iv=b'oasijfoaiwej', tag=b'aisudhfoaweij')
],
MessageFrameBody: [
dict(
iv=b'oaijefoiajew',
ciphertext=b'oasidjfaowiejf',
tag=b'ecoaiwjeconadf',
sequence_number=42523,
final_frame=False
)
],
MessageNoFrameBody: [
dict(
iv=b'afioaewj',
ciphertext=b'oasjfoeiwjfio',
tag=b'asfowaeijf'
)
],
MessageFooter: [
dict(signature=b'oajwefiowjaeofi')
]
}
INVALID_KWARGS = {
EncryptedData: [
dict(ciphertext=None, iv=None, tag=None)
]
}


@pytest.mark.parametrize('attribute, validator_type, is_optional', (
(EncryptedData.iv, bytes, True),
(EncryptedData.ciphertext, bytes, False),
(EncryptedData.tag, bytes, True),
(MessageHeaderAuthentication.iv, bytes, False),
(MessageHeaderAuthentication.tag, bytes, False),
(MessageFrameBody.iv, bytes, False),
(MessageFrameBody.ciphertext, bytes, False),
(MessageFrameBody.tag, bytes, False),
(MessageFrameBody.sequence_number, six.integer_types, False),
(MessageFrameBody.final_frame, bool, False),
(MessageNoFrameBody.iv, bytes, False),
(MessageNoFrameBody.ciphertext, bytes, False),
(MessageNoFrameBody.tag, bytes, False),
(MessageFooter.signature, bytes, False)
))
def test_attributes(attribute, validator_type, is_optional):
assert isinstance(attribute, attr.Attribute)
assert attribute.hash
if is_optional:
assert attribute.validator.validator.type == validator_type
else:
assert attribute.validator.type == validator_type
@pytest.mark.parametrize('cls, kwargs', all_valid_kwargs(VALID_KWARGS))
def test_attributes_valid_kwargs(cls, kwargs):
cls(**kwargs)


@pytest.mark.parametrize('cls, kwargs', all_invalid_kwargs(VALID_KWARGS, INVALID_KWARGS))
def test_attributes_invalid_kwargs(cls, kwargs):
with pytest.raises(TypeError):
cls(**kwargs)


@pytest.mark.parametrize('attribute, value', (
Expand All @@ -51,82 +73,3 @@ def test_attributes(attribute, validator_type, is_optional):
))
def test_static_attributes(attribute, value):
assert attribute == value


def test_encrypted_data_fails():
with pytest.raises(TypeError):
EncryptedData(ciphertext=None)


@pytest.mark.parametrize('iv, ciphertext, tag', (
(b'iv', b'ciphertext', b'tag'),
(None, b'ciphertext', None)
))
def test_encrypted_data_succeeds(iv, ciphertext, tag):
EncryptedData(iv=iv, ciphertext=ciphertext, tag=tag)


@pytest.mark.parametrize('iv, tag', (
(None, b''),
(b'', None)
))
def test_message_header_auth_fails(iv, tag):
with pytest.raises(TypeError):
MessageHeaderAuthentication(iv=iv, tag=tag)


def test_message_header_auth_succeeds():
MessageHeaderAuthentication(iv=b'', tag=b'')


@pytest.mark.parametrize('iv, ciphertext, tag, sequence_number, final_frame', (
(None, b'', b'', 1, True),
(b'', None, b'', 1, True),
(b'', b'', None, 1, True),
(b'', b'', b'', None, True),
(b'', b'', b'', 1, None)
))
def test_message_frame_body_fails(iv, ciphertext, tag, sequence_number, final_frame):
with pytest.raises(TypeError):
MessageFrameBody(
iv=iv,
ciphertext=ciphertext,
tag=tag,
sequence_number=sequence_number,
final_frame=final_frame
)


def test_message_frame_body_succeeds():
MessageFrameBody(
iv=b'iv',
ciphertext=b'ciphertext',
tag=b'tag',
sequence_number=1,
final_frame=False
)


@pytest.mark.parametrize('iv, ciphertext, tag', (
(None, b'', b''),
(b'', None, b''),
(b'', b'', None)
))
def test_message_no_frame_body_fails(iv, ciphertext, tag):
with pytest.raises(TypeError):
MessageNoFrameBody(iv=iv, ciphertext=ciphertext, tag=tag)


def test_message_no_frame_body_succeeds():
test = MessageNoFrameBody(iv=b'', ciphertext=b'', tag=b'')
assert test.sequence_number == 1
assert test.final_frame


def test_message_footer_fails():
with pytest.raises(TypeError):
MessageFooter(signature=None)


def test_message_footer_succeeds():
MessageFooter(signature=b'')
Loading