Skip to content
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
7 changes: 6 additions & 1 deletion prefab_cloud_python/config_resolver.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations
import functools
import time
from collections.abc import Sequence

from .read_write_lock import ReadWriteLock
Expand Down Expand Up @@ -129,7 +130,11 @@ def all_criteria_match(self, conditional_value, props):
return True

def evaluate_criterion(self, criterion, properties):
value_from_properties = properties.get(criterion.property_name)
if criterion.property_name == "prefab.current-time":
value_from_properties = int(time.time() * 1000)
else:
value_from_properties = properties.get(criterion.property_name)

deepest_value = ConfigValueUnwrapper.deepest_value(
criterion.value_to_match, self.config, properties
)
Expand Down
96 changes: 96 additions & 0 deletions tests/test_criteria_evaluator.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from prefab_cloud_python.config_resolver import CriteriaEvaluator
from prefab_cloud_python.context import Context
import prefab_pb2 as Prefab
from datetime import datetime, timezone, timedelta
from unittest.mock import patch

project_env_id = 1
test_env_id = 2
Expand Down Expand Up @@ -1019,6 +1021,100 @@ def test_stringifying_property_values_and_names(self):
== desired_value
)

def test_prefab_current_time(self):
# Set up a fixed time for testing
test_time = datetime(2024, 1, 1, 12, 0, 0, tzinfo=timezone.utc)
int(test_time.timestamp() * 1000)

# Create a config that checks if current time is before a future time
future_time = test_time + timedelta(hours=1)
future_time_millis = int(future_time.timestamp() * 1000)

config = Prefab.Config(
key=key,
rows=[
default_row,
Prefab.ConfigRow(
project_env_id=project_env_id,
values=[
Prefab.ConditionalValue(
criteria=[
Prefab.Criterion(
operator=Prefab.Criterion.CriterionOperator.PROP_BEFORE,
property_name="prefab.current-time",
value_to_match=Prefab.ConfigValue(
int=future_time_millis
),
)
],
value=Prefab.ConfigValue(string=desired_value),
)
],
),
],
)

# Create a config that checks if current time is after a past time
past_time = test_time - timedelta(hours=1)
past_time_millis = int(past_time.timestamp() * 1000)

config_past = Prefab.Config(
key=key,
rows=[
default_row,
Prefab.ConfigRow(
project_env_id=project_env_id,
values=[
Prefab.ConditionalValue(
criteria=[
Prefab.Criterion(
operator=Prefab.Criterion.CriterionOperator.PROP_AFTER,
property_name="prefab.current-time",
value_to_match=Prefab.ConfigValue(
int=past_time_millis
),
)
],
value=Prefab.ConfigValue(string=desired_value),
)
],
),
],
)

with patch("time.time") as mock_time:
# Set the mock to return our test time
mock_time.return_value = test_time.timestamp()

evaluator = CriteriaEvaluator(
config, project_env_id, resolver=None, base_client=None
)
evaluator_past = CriteriaEvaluator(
config_past, project_env_id, resolver=None, base_client=None
)

# Test current time is before future time
evaluation = evaluator.evaluate(context({}))
assert evaluation.raw_config_value().string == desired_value

# Test current time is after past time
evaluation = evaluator_past.evaluate(context({}))
assert evaluation.raw_config_value().string == desired_value

# Test with a different time that's after the future time
mock_time.return_value = (
future_time.timestamp() + 3600
) # 1 hour after future_time
evaluation = evaluator.evaluate(context({}))
assert evaluation.raw_config_value().string == default_value

# Test with a different time that's before the past time
mock_time.return_value = (
past_time.timestamp() - 3600
) # 1 hour before past_time
evaluation = evaluator_past.evaluate(context({}))
assert evaluation.raw_config_value().string == default_value

@staticmethod
def mock_resolver(config):
return MockResolver(config)
Expand Down
Loading