1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
import asyncio
import concurrent.futures as cf
import ldclient
import sentry_sdk
import pytest
from ldclient import LDClient
from ldclient.config import Config
from ldclient.context import Context
from ldclient.integrations.test_data import TestData
from sentry_sdk.integrations import DidNotEnable
from sentry_sdk.integrations.launchdarkly import LaunchDarklyIntegration
@pytest.mark.parametrize(
"use_global_client",
(False, True),
)
def test_launchdarkly_integration(sentry_init, use_global_client):
td = TestData.data_source()
config = Config("sdk-key", update_processor_class=td)
if use_global_client:
ldclient.set_config(config)
sentry_init(integrations=[LaunchDarklyIntegration()])
client = ldclient.get()
else:
client = LDClient(config=config)
sentry_init(integrations=[LaunchDarklyIntegration(ld_client=client)])
# Set test values
td.update(td.flag("hello").variation_for_all(True))
td.update(td.flag("world").variation_for_all(True))
# Evaluate
client.variation("hello", Context.create("my-org", "organization"), False)
client.variation("world", Context.create("user1", "user"), False)
client.variation("other", Context.create("user2", "user"), False)
assert sentry_sdk.get_current_scope().flags.get() == [
{"flag": "hello", "result": True},
{"flag": "world", "result": True},
{"flag": "other", "result": False},
]
def test_launchdarkly_integration_threaded(sentry_init):
td = TestData.data_source()
client = LDClient(config=Config("sdk-key", update_processor_class=td))
sentry_init(integrations=[LaunchDarklyIntegration(ld_client=client)])
context = Context.create("user1")
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.variation(flag_key, context, False)
return [f["flag"] for f in sentry_sdk.get_current_scope().flags.get()]
td.update(td.flag("hello").variation_for_all(True))
td.update(td.flag("world").variation_for_all(False))
# Capture an eval before we split isolation scopes.
client.variation("hello", context, False)
with cf.ThreadPoolExecutor(max_workers=2) as pool:
results = list(pool.map(task, ["world", "other"]))
assert results[0] == ["hello", "world"]
assert results[1] == ["hello", "other"]
def test_launchdarkly_integration_asyncio(sentry_init):
"""Assert concurrently evaluated flags do not pollute one another."""
td = TestData.data_source()
client = LDClient(config=Config("sdk-key", update_processor_class=td))
sentry_init(integrations=[LaunchDarklyIntegration(ld_client=client)])
context = Context.create("user1")
async def task(flag_key):
with sentry_sdk.isolation_scope():
client.variation(flag_key, context, False)
return [f["flag"] for f in sentry_sdk.get_current_scope().flags.get()]
async def runner():
return asyncio.gather(task("world"), task("other"))
td.update(td.flag("hello").variation_for_all(True))
td.update(td.flag("world").variation_for_all(False))
client.variation("hello", context, False)
results = asyncio.run(runner()).result()
assert results[0] == ["hello", "world"]
assert results[1] == ["hello", "other"]
def test_launchdarkly_integration_did_not_enable(monkeypatch):
# Client is not passed in and set_config wasn't called.
# TODO: Bad practice to access internals like this. We can skip this test, or remove this
# case entirely (force user to pass in a client instance).
ldclient._reset_client()
try:
ldclient.__lock.lock()
ldclient.__config = None
finally:
ldclient.__lock.unlock()
with pytest.raises(DidNotEnable):
LaunchDarklyIntegration()
# Client not initialized.
client = LDClient(config=Config("sdk-key"))
monkeypatch.setattr(client, "is_initialized", lambda: False)
with pytest.raises(DidNotEnable):
LaunchDarklyIntegration(ld_client=client)
|