Skip to content
Merged
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
45 changes: 28 additions & 17 deletions tests/test_provider.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import threading
import time
from typing import List, Union
from unittest.mock import patch

Expand Down Expand Up @@ -150,39 +151,42 @@ def test_logger_changes_should_cascade_to_evaluation_converter(provider: LaunchD


def test_provider_emits_ready_event_when_immediately_ready():
ld_provider_ready_count = 0
emission_count = 0
lock = threading.Lock()
thread_event = threading.Event()

def handle_status(details: EventDetails):
if details.provider_name == 'launchdarkly-openfeature-server':
nonlocal lock
nonlocal ld_provider_ready_count
nonlocal emission_count
with lock:
ld_provider_ready_count = ld_provider_ready_count + 1
emission_count += 1
thread_event.set()

# At the time of implementation this handler runs synchronously on the same
# thread as initialization. The lock is in case this behavior changes.
api.add_handler(ProviderEvent.PROVIDER_READY, handle_status)

openfeature_provider = LaunchDarklyProvider(Config("", offline=True))
api.set_provider(openfeature_provider)

assert thread_event.wait(timeout=5)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there some way we could make this more robust against duplicate emissions?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call. Updated all three tests to track an emission_count alongside the threading.Event. After the event fires, a short time.sleep(0.1) allows any spurious duplicate emissions to arrive, then we assert the count is exactly 1.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aside: Typically we would avoid sleeps, but I think in this arrangement they are fine. We aren't using the sleep to try to catch the event we care about, but just as some extra time to check we aren't getting extra events. Which there isn't an amazing way to test for, but I have seen it be a problem with open feature, and hence the original test shape.

time.sleep(0.1)

with lock:
assert ld_provider_ready_count == 1
assert emission_count == 1

api.shutdown()


def test_provider_emits_error_event_immediately_failed():
ld_provider_error_count = 0
emission_count = 0
lock = threading.Lock()
thread_event = threading.Event()

def handle_status(details: EventDetails):
if details.provider_name == 'launchdarkly-openfeature-server':
nonlocal lock
nonlocal ld_provider_error_count
nonlocal emission_count
with lock:
ld_provider_error_count = ld_provider_error_count + 1
emission_count += 1
thread_event.set()

api.add_handler(ProviderEvent.PROVIDER_ERROR, handle_status)

Expand All @@ -191,22 +195,26 @@ def handle_status(details: EventDetails):

api.set_provider(openfeature_provider)

assert thread_event.wait(timeout=5)
time.sleep(0.1)

with lock:
assert ld_provider_error_count == 1
assert emission_count == 1

api.shutdown()


def test_provider_emits_error_event_delayed_failure():
ld_provider_error_count = 0
emission_count = 0
lock = threading.Lock()
thread_event = threading.Event()

def handle_status(details: EventDetails):
if details.provider_name == 'launchdarkly-openfeature-server':
nonlocal lock
nonlocal ld_provider_error_count
nonlocal emission_count
with lock:
ld_provider_error_count = ld_provider_error_count + 1
emission_count += 1
thread_event.set()

api.add_handler(ProviderEvent.PROVIDER_ERROR, handle_status)

Expand All @@ -215,8 +223,11 @@ def handle_status(details: EventDetails):

api.set_provider(openfeature_provider)

assert thread_event.wait(timeout=5)
time.sleep(0.1)

with lock:
assert ld_provider_error_count == 1
assert emission_count == 1

api.shutdown()

Expand Down
Loading