Skip to content

Commit

Permalink
chore: add tests and fix usage of behaves_like decorator throughout
Browse files Browse the repository at this point in the history
  • Loading branch information
pgautier404 committed Jul 12, 2023
1 parent 22069f7 commit 71df9be
Show file tree
Hide file tree
Showing 11 changed files with 441 additions and 143 deletions.
1 change: 1 addition & 0 deletions src/momento/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import Iterable, List, Mapping, Set, Union

TCacheName = str
TTopicName = str

TMomentoValue = Union[str, bytes]

Expand Down
38 changes: 36 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,19 @@
import pytest
import pytest_asyncio

from momento import CacheClient, CacheClientAsync, Configurations, CredentialProvider
from momento.config import Configuration
from momento import (
CacheClient,
CacheClientAsync,
Configurations,
CredentialProvider,
TopicClient,
TopicClientAsync,
TopicConfigurations,
)
from momento.config import Configuration, TopicConfiguration
from momento.typing import (
TCacheName,
TTopicName,
TDictionaryField,
TDictionaryFields,
TDictionaryItems,
Expand All @@ -36,13 +45,16 @@
#######################

TEST_CONFIGURATION = Configurations.Laptop.latest()
TEST_TOPIC_CONFIGURATION = TopicConfigurations.Default.latest()

TEST_AUTH_PROVIDER = CredentialProvider.from_environment_variable("TEST_AUTH_TOKEN")

TEST_CACHE_NAME: Optional[str] = os.getenv("TEST_CACHE_NAME")
if not TEST_CACHE_NAME:
raise RuntimeError("Integration tests require TEST_CACHE_NAME env var; see README for more details.")

TEST_TOPIC_NAME: Optional[str] = "my-topic"

DEFAULT_TTL_SECONDS: timedelta = timedelta(seconds=60)
BAD_AUTH_TOKEN: str = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJpbnRlZ3JhdGlvbiIsImNwIjoiY29udHJvbC5jZWxsLWFscGhhLWRldi5wcmVwcm9kLmEubW9tZW50b2hxLmNvbSIsImMiOiJjYWNoZS5jZWxsLWFscGhhLWRldi5wcmVwcm9kLmEubW9tZW50b2hxLmNvbSJ9.gdghdjjfjyehhdkkkskskmmls76573jnajhjjjhjdhnndy" # noqa: E501

Expand All @@ -68,11 +80,21 @@ def configuration() -> Configuration:
return TEST_CONFIGURATION


@pytest.fixture(scope="session")
def topic_configuration() -> TopicConfiguration:
return TEST_TOPIC_CONFIGURATION


@pytest.fixture(scope="session")
def cache_name() -> TCacheName:
return cast(str, TEST_CACHE_NAME)


@pytest.fixture(scope="session")
def topic_name() -> TTopicName:
return cast(str, TEST_TOPIC_NAME)


@pytest.fixture
def list_name() -> TListName:
return uuid_str()
Expand Down Expand Up @@ -258,6 +280,18 @@ async def client_async() -> AsyncIterator[CacheClientAsync]:
await _client.delete_cache(cast(str, TEST_CACHE_NAME))


@pytest.fixture(scope="session")
def topic_client() -> Iterator[TopicClient]:
with TopicClient(TEST_TOPIC_CONFIGURATION, TEST_AUTH_PROVIDER) as _client:
yield _client


@pytest.fixture(scope="session")
async def topic_client_async() -> AsyncIterator[TopicClientAsync]:
async with TopicClientAsync(TEST_TOPIC_CONFIGURATION, TEST_AUTH_PROVIDER) as _topic_client:
yield _topic_client


TUniqueCacheName = Callable[[CacheClient], str]


Expand Down
20 changes: 16 additions & 4 deletions tests/momento/cache_client/shared_behaviors_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@

from typing_extensions import Protocol

from momento import CacheClientAsync
from momento import CacheClientAsync, TopicClientAsync
from momento.auth import CredentialProvider
from momento.config import Configuration
from momento.errors import MomentoErrorCode
from momento.responses import CacheResponse
from momento.typing import TCacheName, TScalarKey
from momento.responses import CacheResponse, PubsubResponse
from momento.typing import TCacheName, TScalarKey, TTopicName
from tests.asserts import assert_response_is_error
from tests.utils import uuid_str

Expand Down Expand Up @@ -70,8 +70,20 @@ async def with_bad_key_throws_exception(cache_name: str, key_validator: TKeyVali
)


class TTopicValidator(Protocol):
def __call__(self, topic_name: TTopicName) -> Awaitable[PubsubResponse]:
...


def a_topic_validator() -> None:

async def with_null_topic_throws_exception(cache_name: str, topic_validator: TTopicValidator) -> None:
response = await topic_validator(topic_name=None) # type: ignore
assert_response_is_error(response, error_code=MomentoErrorCode.INVALID_ARGUMENT_ERROR)


class TConnectionValidator(Protocol):
def __call__(self, client_async: CacheClientAsync) -> Awaitable[CacheResponse]:
def __call__(self, client_async: CacheClientAsync) -> Awaitable[PubsubResponse]:
...


Expand Down
81 changes: 43 additions & 38 deletions tests/momento/cache_client/test_dictionary_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,11 +377,13 @@ async def with_wrong_container_throws_exception(dictionary_value_validator: TDic
assert response.error_code == MomentoErrorCode.INVALID_ARGUMENT_ERROR


@behaves_like(a_cache_name_validator)
@behaves_like(a_connection_validator)
@behaves_like(a_dictionary_getter)
@behaves_like(a_dictionary_name_validator)
@behaves_like(a_dictionary_field_validator)
@behaves_like(
a_cache_name_validator,
a_connection_validator,
a_dictionary_getter,
a_dictionary_name_validator,
a_dictionary_field_validator,
)
def describe_dictionary_get_field() -> None:
@fixture
def cache_name_validator(
Expand Down Expand Up @@ -430,11 +432,13 @@ async def misses_when_the_dictionary_does_not_exist(
assert isinstance(get_response, CacheDictionaryGetField.Miss)


@behaves_like(a_cache_name_validator)
@behaves_like(a_connection_validator)
@behaves_like(a_dictionary_getter)
@behaves_like(a_dictionary_name_validator)
@behaves_like(a_dictionary_fields_validator)
@behaves_like(
a_cache_name_validator,
a_connection_validator,
a_dictionary_getter,
a_dictionary_name_validator,
a_dictionary_fields_validator,
)
def describe_dictionary_get_fields() -> None:
@fixture
def cache_name_validator(
Expand Down Expand Up @@ -535,9 +539,7 @@ async def it_excludes_misses_from_dictionary(
assert missing_key not in get_response.value_dictionary_string_string


@behaves_like(a_cache_name_validator)
@behaves_like(a_connection_validator)
@behaves_like(a_dictionary_name_validator)
@behaves_like(a_cache_name_validator, a_connection_validator, a_dictionary_name_validator)
def describe_dictionary_fetch() -> None:
@fixture
def cache_name_validator(client_async: CacheClientAsync, dictionary_name: TDictionaryName) -> TCacheNameValidator:
Expand All @@ -561,10 +563,12 @@ async def misses_when_the_dictionary_does_not_exist(
assert isinstance(fetch_response, CacheDictionaryFetch.Miss)


@behaves_like(a_cache_name_validator)
@behaves_like(a_connection_validator)
@behaves_like(a_dictionary_name_validator)
@behaves_like(a_dictionary_field_validator)
@behaves_like(
a_cache_name_validator,
a_connection_validator,
a_dictionary_name_validator,
a_dictionary_field_validator,
)
def describe_dictionary_increment() -> None:
@fixture
def cache_name_validator(
Expand Down Expand Up @@ -684,11 +688,13 @@ async def it_errors_on_bad_initial_values(
assert increment_response.error_code == MomentoErrorCode.FAILED_PRECONDITION_ERROR


@behaves_like(a_cache_name_validator)
@behaves_like(a_connection_validator)
@behaves_like(a_dictionary_remover)
@behaves_like(a_dictionary_name_validator)
@behaves_like(a_dictionary_field_validator)
@behaves_like(
a_cache_name_validator,
a_connection_validator,
a_dictionary_remover,
a_dictionary_name_validator,
a_dictionary_field_validator,
)
def describe_dictionary_remove_field() -> None:
@fixture
def cache_name_validator(
Expand Down Expand Up @@ -756,12 +762,7 @@ async def it_removes_a_field(
assert fetch_response.value_dictionary_string_string == {extra_field: extra_value}


# TODO these don't work for this case?
# @behaves_like(a_cache_name_validator)
# @behaves_like(a_connection_validator)
@behaves_like(a_dictionary_remover)
@behaves_like(a_dictionary_name_validator)
@behaves_like(a_dictionary_fields_validator)
@behaves_like(a_dictionary_remover, a_dictionary_name_validator, a_dictionary_fields_validator, a_cache_name_validator, a_connection_validator)
def describe_dictionary_remove_fields() -> None:
@fixture
def cache_name_validator(
Expand Down Expand Up @@ -833,11 +834,13 @@ async def it_removes_multiple_items(
assert fetch_response.value_dictionary_string_string == {extra_field: extra_value}


@behaves_like(a_cache_name_validator)
@behaves_like(a_connection_validator)
@behaves_like(a_dictionary_setter)
@behaves_like(a_dictionary_name_validator)
@behaves_like(a_dictionary_value_validator)
@behaves_like(
a_cache_name_validator,
a_connection_validator,
a_dictionary_setter,
a_dictionary_name_validator,
a_dictionary_value_validator
)
def describe_dictionary_set_field() -> None:
@fixture
def cache_name_validator(
Expand Down Expand Up @@ -917,11 +920,13 @@ def dictionary_value_validator(
)


@behaves_like(a_cache_name_validator)
@behaves_like(a_connection_validator)
@behaves_like(a_dictionary_setter)
@behaves_like(a_dictionary_name_validator)
@behaves_like(a_dictionary_items_validator)
@behaves_like(
a_cache_name_validator,
a_connection_validator,
a_dictionary_setter,
a_dictionary_name_validator,
a_dictionary_items_validator
)
def describe_dictionary_set_fields() -> None:
@fixture
def cache_name_validator(
Expand Down
Loading

0 comments on commit 71df9be

Please sign in to comment.