Skip to content

fix(feature_flags): tests and type validation #36

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def _is_rule_matched(self, feature_name: str, rule: Dict[str, Any], context: Dic
return False
# if we got here, all conditions match
logger.debug(
f"rule matched, rule_name={rule_name}, rule_default_value={rule_default_value}, " f"name={feature_name}"
f"rule matched, rule_name={rule_name}, rule_default_value={rule_default_value}, name={feature_name}"
)
return True
return False
Expand Down Expand Up @@ -160,7 +160,7 @@ def evaluate(self, *, name: str, context: Optional[Dict[str, Any]] = None, defau
feature = features.get(name)
if feature is None:
logger.debug(
f"feature does not appear in configuration, using provided default, " f"name={name}, default={default}"
f"feature does not appear in configuration, using provided default, name={name}, default={default}"
)
return default

Expand Down
13 changes: 5 additions & 8 deletions aws_lambda_powertools/utilities/feature_flags/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,9 @@ def validate(self) -> None:


class FeaturesValidator(BaseValidator):
def __init__(self, schema):
def __init__(self, schema: Dict):
self.schema = schema
self.features: Optional[Dict[str, Dict]] = None

if isinstance(self.schema, dict):
self.features = self.schema.get(FEATURES_KEY)
self.features: Optional[Dict[str, Dict]] = self.schema.get(FEATURES_KEY)

def validate(self):
if not isinstance(self.features, dict):
Expand Down Expand Up @@ -71,13 +68,13 @@ def __init__(self, feature: Dict[str, Any], feature_name: str):
self.rules: Optional[List[Dict]] = self.feature.get(RULES_KEY)

def validate(self):
if not isinstance(self.rules, list):
raise ConfigurationError(f"Feature rules is not a list, feature_name={self.feature_name}")

if not self.rules:
logger.debug("Rules are empty, ignoring validation")
return

if not isinstance(self.rules, list):
raise ConfigurationError(f"Feature rules is not a list, feature_name={self.feature_name}")

for rule in self.rules:
self.validate_rule(rule, self.feature)
conditions = ConditionsValidator(rule=rule, rule_name=rule.get(RULE_NAME_KEY))
Expand Down
8 changes: 4 additions & 4 deletions tests/functional/feature_toggles/test_feature_toggles.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ def test_toggles_match_rule_with_contains_action(mocker, config):
"feature_default_value": False,
"rules": [
{
"rule_name": "tenant id is contained in [6,2] ",
"rule_name": "tenant id is contained in [6, 2]",
"value_when_applies": expected_value,
"conditions": [
{
Expand All @@ -306,7 +306,7 @@ def test_toggles_no_match_rule_with_contains_action(mocker, config):
"feature_default_value": expected_value,
"rules": [
{
"rule_name": "tenant id is contained in [6,2] ",
"rule_name": "tenant id is contained in [8, 2]",
"value_when_applies": True,
"conditions": [
{
Expand All @@ -333,7 +333,7 @@ def test_multiple_features_enabled(mocker, config):
"feature_default_value": False,
"rules": [
{
"rule_name": "tenant id is contained in [6,2] ",
"rule_name": "tenant id is contained in [6, 2]",
"value_when_applies": True,
"conditions": [
{
Expand Down Expand Up @@ -366,7 +366,7 @@ def test_multiple_features_only_some_enabled(mocker, config):
"feature_default_value": False,
"rules": [
{
"rule_name": "tenant id is contained in [6,2] ",
"rule_name": "tenant id is contained in [6, 2]",
"value_when_applies": True,
"conditions": [
{
Expand Down
21 changes: 17 additions & 4 deletions tests/functional/feature_toggles/test_schema_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ def test_invalid_features_dict():

schema = []
# invalid type
validator = SchemaValidator(schema)
with pytest.raises(ConfigurationError):
validator.validate()

# invalid features key
schema = {FEATURES_KEY: []}
validator = SchemaValidator(schema)
with pytest.raises(ConfigurationError):
validator.validate()

Expand All @@ -57,33 +59,38 @@ def test_invalid_feature_dict():

# empty feature dict
schema = {FEATURES_KEY: {"my_feature": {}}}
validator = SchemaValidator(schema)
with pytest.raises(ConfigurationError):
validator.validate()

# invalid FEATURE_DEFAULT_VAL_KEY type, not boolean
schema = {FEATURES_KEY: {"my_feature": {FEATURE_DEFAULT_VAL_KEY: "False"}}}
validator = SchemaValidator(schema)
with pytest.raises(ConfigurationError):
validator.validate()

# invalid FEATURE_DEFAULT_VAL_KEY type, not boolean #2
schema = {FEATURES_KEY: {"my_feature": {FEATURE_DEFAULT_VAL_KEY: 5}}}
validator = SchemaValidator(schema)
with pytest.raises(ConfigurationError):
validator.validate()

# invalid rules type, not list
schema = {FEATURES_KEY: {"my_feature": {FEATURE_DEFAULT_VAL_KEY: False, RULES_KEY: "4"}}}
validator = SchemaValidator(schema)
with pytest.raises(ConfigurationError):
validator.validate()


def test_valid_feature_dict():
# no rules list at all
schema = {FEATURES_KEY: {"my_feature": {FEATURE_DEFAULT_VAL_KEY: False}}}
# empty rules list
schema = {FEATURES_KEY: {"my_feature": {FEATURE_DEFAULT_VAL_KEY: False, RULES_KEY: []}}}
validator = SchemaValidator(schema)
validator.validate()

# empty rules list
schema = {FEATURES_KEY: {"my_feature": {FEATURE_DEFAULT_VAL_KEY: False, RULES_KEY: []}}}
# no rules list at all
schema = {FEATURES_KEY: {"my_feature": {FEATURE_DEFAULT_VAL_KEY: False}}}
validator = SchemaValidator(schema)
validator.validate()


Expand Down Expand Up @@ -118,6 +125,7 @@ def test_invalid_rule():
}
}
}
validator = SchemaValidator(schema)
with pytest.raises(ConfigurationError):
validator.validate()

Expand All @@ -135,6 +143,7 @@ def test_invalid_rule():
}
}
}
validator = SchemaValidator(schema)
with pytest.raises(ConfigurationError):
validator.validate()

Expand All @@ -149,6 +158,7 @@ def test_invalid_rule():
}
}
}
validator = SchemaValidator(schema)
with pytest.raises(ConfigurationError):
validator.validate()

Expand All @@ -163,6 +173,7 @@ def test_invalid_rule():
}
}
}
validator = SchemaValidator(schema)
with pytest.raises(ConfigurationError):
validator.validate()

Expand Down Expand Up @@ -202,6 +213,7 @@ def test_invalid_condition():
}
}
}
validator = SchemaValidator(schema)
with pytest.raises(ConfigurationError):
validator.validate()

Expand All @@ -224,6 +236,7 @@ def test_invalid_condition():
}
}
}
validator = SchemaValidator(schema)
with pytest.raises(ConfigurationError):
validator.validate()

Expand Down