Skip to content

Commit

Permalink
Threaded and asyncio tests
Browse files Browse the repository at this point in the history
  • Loading branch information
aliu39 committed Dec 23, 2024
1 parent 0538bce commit 47d29c3
Showing 1 changed file with 202 additions and 0 deletions.
202 changes: 202 additions & 0 deletions tests/integrations/unleash/test_unleash.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import concurrent.futures as cf
import sys
from random import random
from unittest.mock import patch

import pytest

import sentry_sdk
from sentry_sdk.integrations.unleash import UnleashIntegration
from tests.integrations.unleash.testutils import MockUnleashClient
Expand Down Expand Up @@ -57,6 +61,204 @@ def test_get_variant(sentry_init, capture_events, uninstall_integration):
}


@patch("sentry_sdk.integrations.unleash.UnleashClient", MockUnleashClient)
def test_is_enabled_threaded(sentry_init, capture_events, uninstall_integration):
client = MockUnleashClient()
uninstall_integration(UnleashIntegration)
sentry_init(integrations=[UnleashIntegration()])
events = capture_events()

def task(flag_key):
# Creates a new isolation scope for the thread.
# This means the evaluations in each task are captured separately.
with sentry_sdk.isolation_scope():
client.is_enabled(flag_key)
# use a tag to identify to identify events later on
sentry_sdk.set_tag("task_id", flag_key)
sentry_sdk.capture_exception(Exception("something wrong!"))

# Capture an eval before we split isolation scopes.
client.is_enabled("hello")

with cf.ThreadPoolExecutor(max_workers=2) as pool:
pool.map(task, ["world", "other"])

# Capture error in original scope
sentry_sdk.set_tag("task_id", "0")
sentry_sdk.capture_exception(Exception("something wrong!"))

assert len(events) == 3
events.sort(key=lambda e: e["tags"]["task_id"])

assert events[0]["contexts"]["flags"] == {
"values": [
{"flag": "hello", "result": True},
]
}
assert events[1]["contexts"]["flags"] == {
"values": [
{"flag": "hello", "result": True},
{"flag": "other", "result": False},
]
}
assert events[2]["contexts"]["flags"] == {
"values": [
{"flag": "hello", "result": True},
{"flag": "world", "result": False},
]
}


@patch("sentry_sdk.integrations.unleash.UnleashClient", MockUnleashClient)
def test_get_variant_threaded(sentry_init, capture_events, uninstall_integration):
client = MockUnleashClient()
uninstall_integration(UnleashIntegration)
sentry_init(integrations=[UnleashIntegration()])
events = capture_events()

def task(flag_key):
# Creates a new isolation scope for the thread.
# This means the evaluations in each task are captured separately.
with sentry_sdk.isolation_scope():
client.get_variant(flag_key)
# use a tag to identify to identify events later on
sentry_sdk.set_tag("task_id", flag_key)
sentry_sdk.capture_exception(Exception("something wrong!"))

# Capture an eval before we split isolation scopes.
client.get_variant("hello")

with cf.ThreadPoolExecutor(max_workers=2) as pool:
pool.map(task, ["other", "toggle_feature"])

# Capture error in original scope
sentry_sdk.set_tag("task_id", "0")
sentry_sdk.capture_exception(Exception("something wrong!"))

assert len(events) == 3
events.sort(key=lambda e: e["tags"]["task_id"])

assert events[0]["contexts"]["flags"] == {
"values": [
{"flag": "hello", "result": False},
]
}
assert events[1]["contexts"]["flags"] == {
"values": [
{"flag": "hello", "result": False},
{"flag": "other", "result": False},
]
}
assert events[2]["contexts"]["flags"] == {
"values": [
{"flag": "hello", "result": False},
{"flag": "toggle_feature", "result": True},
]
}


@pytest.mark.skipif(sys.version_info < (3, 7), reason="requires python3.7 or higher")
@patch("sentry_sdk.integrations.unleash.UnleashClient", MockUnleashClient)
def test_is_enabled_asyncio(sentry_init, capture_events, uninstall_integration):
asyncio = pytest.importorskip("asyncio")

client = MockUnleashClient()
uninstall_integration(UnleashIntegration)
sentry_init(integrations=[UnleashIntegration()])
events = capture_events()

async def task(flag_key):
with sentry_sdk.isolation_scope():
client.is_enabled(flag_key)
# use a tag to identify to identify events later on
sentry_sdk.set_tag("task_id", flag_key)
sentry_sdk.capture_exception(Exception("something wrong!"))

async def runner():
return asyncio.gather(task("world"), task("other"))

# Capture an eval before we split isolation scopes.
client.is_enabled("hello")

asyncio.run(runner())

# Capture error in original scope
sentry_sdk.set_tag("task_id", "0")
sentry_sdk.capture_exception(Exception("something wrong!"))

assert len(events) == 3
events.sort(key=lambda e: e["tags"]["task_id"])

assert events[0]["contexts"]["flags"] == {
"values": [
{"flag": "hello", "result": True},
]
}
assert events[1]["contexts"]["flags"] == {
"values": [
{"flag": "hello", "result": True},
{"flag": "other", "result": False},
]
}
assert events[2]["contexts"]["flags"] == {
"values": [
{"flag": "hello", "result": True},
{"flag": "world", "result": False},
]
}


@pytest.mark.skipif(sys.version_info < (3, 7), reason="requires python3.7 or higher")
@patch("sentry_sdk.integrations.unleash.UnleashClient", MockUnleashClient)
def test_get_variant_asyncio(sentry_init, capture_events, uninstall_integration):
asyncio = pytest.importorskip("asyncio")

client = MockUnleashClient()
uninstall_integration(UnleashIntegration)
sentry_init(integrations=[UnleashIntegration()])
events = capture_events()

async def task(flag_key):
with sentry_sdk.isolation_scope():
client.get_variant(flag_key)
# use a tag to identify to identify events later on
sentry_sdk.set_tag("task_id", flag_key)
sentry_sdk.capture_exception(Exception("something wrong!"))

async def runner():
return asyncio.gather(task("other"), task("toggle_feature"))

# Capture an eval before we split isolation scopes.
client.get_variant("hello")

asyncio.run(runner())

# Capture error in original scope
sentry_sdk.set_tag("task_id", "0")
sentry_sdk.capture_exception(Exception("something wrong!"))

assert len(events) == 3
events.sort(key=lambda e: e["tags"]["task_id"])

assert events[0]["contexts"]["flags"] == {
"values": [
{"flag": "hello", "result": False},
]
}
assert events[1]["contexts"]["flags"] == {
"values": [
{"flag": "hello", "result": False},
{"flag": "other", "result": False},
]
}
assert events[2]["contexts"]["flags"] == {
"values": [
{"flag": "hello", "result": False},
{"flag": "toggle_feature", "result": True},
]
}


@patch("sentry_sdk.integrations.unleash.UnleashClient", MockUnleashClient)
def test_wraps_original(sentry_init, uninstall_integration):
uninstall_integration(UnleashIntegration)
Expand Down

0 comments on commit 47d29c3

Please sign in to comment.