197 lines
6.1 KiB
Python
197 lines
6.1 KiB
Python
from numbers import Number
|
|
|
|
import pytest
|
|
|
|
from openfeature.exception import ErrorCode
|
|
from openfeature.flag_evaluation import FlagResolutionDetails, Reason
|
|
from openfeature.provider.in_memory_provider import InMemoryFlag, InMemoryProvider
|
|
|
|
|
|
def test_should_return_in_memory_provider_metadata():
|
|
# Given
|
|
provider = InMemoryProvider({})
|
|
# When
|
|
metadata = provider.get_metadata()
|
|
# Then
|
|
assert metadata is not None
|
|
assert metadata.name == "In-Memory Provider"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_should_handle_unknown_flags_correctly():
|
|
# Given
|
|
provider = InMemoryProvider({})
|
|
# When
|
|
flag_sync = provider.resolve_boolean_details(flag_key="Key", default_value=True)
|
|
flag_async = await provider.resolve_boolean_details_async(
|
|
flag_key="Key", default_value=True
|
|
)
|
|
# Then
|
|
assert flag_sync == flag_async
|
|
for flag in [flag_sync, flag_async]:
|
|
assert flag is not None
|
|
assert flag.value is True
|
|
assert flag.reason == Reason.ERROR
|
|
assert flag.error_code == ErrorCode.FLAG_NOT_FOUND
|
|
assert flag.error_message == "Flag 'Key' not found"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_calls_context_evaluator_if_present():
|
|
# Given
|
|
def context_evaluator(flag: InMemoryFlag, evaluation_context: dict):
|
|
return FlagResolutionDetails(
|
|
value=False,
|
|
reason=Reason.TARGETING_MATCH,
|
|
)
|
|
|
|
provider = InMemoryProvider(
|
|
{
|
|
"Key": InMemoryFlag(
|
|
"true",
|
|
{"true": True, "false": False},
|
|
context_evaluator=context_evaluator,
|
|
)
|
|
}
|
|
)
|
|
# When
|
|
flag_sync = provider.resolve_boolean_details(flag_key="Key", default_value=False)
|
|
flag_async = await provider.resolve_boolean_details_async(
|
|
flag_key="Key", default_value=False
|
|
)
|
|
# Then
|
|
assert flag_sync == flag_async
|
|
for flag in [flag_sync, flag_async]:
|
|
assert flag is not None
|
|
assert flag.value is False
|
|
assert isinstance(flag.value, bool)
|
|
assert flag.reason == Reason.TARGETING_MATCH
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_should_resolve_boolean_flag_from_in_memory():
|
|
# Given
|
|
provider = InMemoryProvider(
|
|
{"Key": InMemoryFlag("true", {"true": True, "false": False})}
|
|
)
|
|
# When
|
|
flag_sync = provider.resolve_boolean_details(flag_key="Key", default_value=False)
|
|
flag_async = await provider.resolve_boolean_details_async(
|
|
flag_key="Key", default_value=False
|
|
)
|
|
# Then
|
|
assert flag_sync == flag_async
|
|
for flag in [flag_sync, flag_async]:
|
|
assert flag is not None
|
|
assert flag.value is True
|
|
assert isinstance(flag.value, bool)
|
|
assert flag.variant == "true"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_should_resolve_integer_flag_from_in_memory():
|
|
# Given
|
|
provider = InMemoryProvider(
|
|
{"Key": InMemoryFlag("hundred", {"zero": 0, "hundred": 100})}
|
|
)
|
|
# When
|
|
flag_sync = provider.resolve_integer_details(flag_key="Key", default_value=0)
|
|
flag_async = await provider.resolve_integer_details_async(
|
|
flag_key="Key", default_value=0
|
|
)
|
|
# Then
|
|
assert flag_sync == flag_async
|
|
for flag in [flag_sync, flag_async]:
|
|
assert flag is not None
|
|
assert flag.value == 100
|
|
assert isinstance(flag.value, Number)
|
|
assert flag.variant == "hundred"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_should_resolve_float_flag_from_in_memory():
|
|
# Given
|
|
provider = InMemoryProvider(
|
|
{"Key": InMemoryFlag("ten", {"zero": 0.0, "ten": 10.23})}
|
|
)
|
|
# When
|
|
flag_sync = provider.resolve_float_details(flag_key="Key", default_value=0.0)
|
|
flag_async = await provider.resolve_float_details_async(
|
|
flag_key="Key", default_value=0.0
|
|
)
|
|
# Then
|
|
assert flag_sync == flag_async
|
|
for flag in [flag_sync, flag_async]:
|
|
assert flag is not None
|
|
assert flag.value == 10.23
|
|
assert isinstance(flag.value, Number)
|
|
assert flag.variant == "ten"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_should_resolve_string_flag_from_in_memory():
|
|
# Given
|
|
provider = InMemoryProvider(
|
|
{
|
|
"Key": InMemoryFlag(
|
|
"stringVariant",
|
|
{"defaultVariant": "Default", "stringVariant": "String"},
|
|
)
|
|
}
|
|
)
|
|
# When
|
|
flag_sync = provider.resolve_string_details(flag_key="Key", default_value="Default")
|
|
flag_async = await provider.resolve_string_details_async(
|
|
flag_key="Key", default_value="Default"
|
|
)
|
|
# Then
|
|
assert flag_sync == flag_async
|
|
for flag in [flag_sync, flag_async]:
|
|
assert flag is not None
|
|
assert flag.value == "String"
|
|
assert isinstance(flag.value, str)
|
|
assert flag.variant == "stringVariant"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_should_resolve_list_flag_from_in_memory():
|
|
# Given
|
|
provider = InMemoryProvider(
|
|
{"Key": InMemoryFlag("twoItems", {"empty": [], "twoItems": ["item1", "item2"]})}
|
|
)
|
|
# When
|
|
flag_sync = provider.resolve_object_details(flag_key="Key", default_value=[])
|
|
flag_async = await provider.resolve_object_details_async(
|
|
flag_key="Key", default_value=[]
|
|
)
|
|
# Then
|
|
assert flag_sync == flag_async
|
|
for flag in [flag_sync, flag_async]:
|
|
assert flag is not None
|
|
assert flag.value == ["item1", "item2"]
|
|
assert isinstance(flag.value, list)
|
|
assert flag.variant == "twoItems"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_should_resolve_object_flag_from_in_memory():
|
|
# Given
|
|
return_value = {
|
|
"String": "string",
|
|
"Number": 2,
|
|
"Boolean": True,
|
|
}
|
|
provider = InMemoryProvider(
|
|
{"Key": InMemoryFlag("obj", {"obj": return_value, "empty": {}})}
|
|
)
|
|
# When
|
|
flag_sync = provider.resolve_object_details(flag_key="Key", default_value={})
|
|
flag_async = provider.resolve_object_details(flag_key="Key", default_value={})
|
|
# Then
|
|
assert flag_sync == flag_async
|
|
for flag in [flag_sync, flag_async]:
|
|
assert flag is not None
|
|
assert flag.value == return_value
|
|
assert isinstance(flag.value, dict)
|
|
assert flag.variant == "obj"
|