2020from splitio .storage .adapters .redis import build , RedisAdapter
2121from splitio .models import splits , segments
2222from splitio .engine .impressions .impressions import Manager as ImpressionsManager , ImpressionsMode
23- from splitio .engine .impressions .strategies import StrategyDebugMode , StrategyOptimizedMode
23+ from splitio .engine .impressions import set_classes
24+ from splitio .engine .impressions .strategies import StrategyDebugMode , StrategyOptimizedMode , StrategyNoneMode
2425from splitio .engine .impressions .manager import Counter
2526from splitio .engine .telemetry import TelemetryStorageConsumer , TelemetryStorageProducer
2627from splitio .engine .impressions .manager import Counter as ImpressionsCounter
2728from splitio .recorder .recorder import StandardRecorder , PipelinedRecorder
2829from splitio .client .config import DEFAULT_CONFIG
29- from splitio .sync .synchronizer import SplitTasks , SplitSynchronizers , Synchronizer
30+ from splitio .sync .synchronizer import SplitTasks , SplitSynchronizers , Synchronizer , RedisSynchronizer
3031from splitio .sync .manager import Manager , RedisManager
3132from splitio .sync .synchronizer import PluggableSynchronizer
3233
@@ -1721,3 +1722,157 @@ def test_track(self):
17211722 client ,
17221723 ('user1' , 'user' , 'conversion' , 1 , "{'prop1': 'value1'}" )
17231724 )
1725+
1726+ class PluggableNoneIntegrationTests (object ):
1727+ """Pluggable storage-based integration tests."""
1728+
1729+ def setup_method (self ):
1730+ """Prepare storages with test data."""
1731+ metadata = SdkMetadata ('python-1.2.3' , 'some_ip' , 'some_name' )
1732+ self .pluggable_storage_adapter = StorageMockAdapter ()
1733+ split_storage = PluggableSplitStorage (self .pluggable_storage_adapter , 'myprefix' )
1734+ segment_storage = PluggableSegmentStorage (self .pluggable_storage_adapter , 'myprefix' )
1735+
1736+ telemetry_pluggable_storage = PluggableTelemetryStorage (self .pluggable_storage_adapter , metadata , 'myprefix' )
1737+ telemetry_producer = TelemetryStorageProducer (telemetry_pluggable_storage )
1738+ telemetry_consumer = TelemetryStorageConsumer (telemetry_pluggable_storage )
1739+ telemetry_runtime_producer = telemetry_producer .get_telemetry_runtime_producer ()
1740+
1741+ storages = {
1742+ 'splits' : split_storage ,
1743+ 'segments' : segment_storage ,
1744+ 'impressions' : PluggableImpressionsStorage (self .pluggable_storage_adapter , metadata , 'myprefix' ),
1745+ 'events' : PluggableEventsStorage (self .pluggable_storage_adapter , metadata , 'myprefix' ),
1746+ 'telemetry' : telemetry_pluggable_storage
1747+ }
1748+
1749+ unique_keys_synchronizer , clear_filter_sync , unique_keys_task , \
1750+ clear_filter_task , impressions_count_sync , impressions_count_task , \
1751+ imp_strategy = set_classes ('PLUGGABLE' , ImpressionsMode .NONE , self .pluggable_storage_adapter , 'myprefix' )
1752+ impmanager = ImpressionsManager (imp_strategy , telemetry_runtime_producer ) # no listener
1753+
1754+ recorder = StandardRecorder (impmanager , storages ['events' ],
1755+ storages ['impressions' ], storages ['telemetry' ])
1756+
1757+ synchronizers = SplitSynchronizers (None , None , None , None ,
1758+ impressions_count_sync ,
1759+ None ,
1760+ unique_keys_synchronizer ,
1761+ clear_filter_sync
1762+ )
1763+
1764+ tasks = SplitTasks (None , None , None , None ,
1765+ impressions_count_task ,
1766+ None ,
1767+ unique_keys_task ,
1768+ clear_filter_task
1769+ )
1770+
1771+ synchronizer = RedisSynchronizer (synchronizers , tasks )
1772+
1773+ manager = RedisManager (synchronizer )
1774+ manager .start ()
1775+ self .factory = SplitFactory ('some_api_key' ,
1776+ storages ,
1777+ True ,
1778+ recorder ,
1779+ manager ,
1780+ sdk_ready_flag = None ,
1781+ telemetry_producer = telemetry_producer ,
1782+ telemetry_init_producer = telemetry_producer .get_telemetry_init_producer (),
1783+ ) # pylint:disable=attribute-defined-outside-init
1784+
1785+ # Adding data to storage
1786+ split_fn = os .path .join (os .path .dirname (__file__ ), 'files' , 'splitChanges.json' )
1787+ with open (split_fn , 'r' ) as flo :
1788+ data = json .loads (flo .read ())
1789+ for split in data ['splits' ]:
1790+ self .pluggable_storage_adapter .set (split_storage ._prefix .format (split_name = split ['name' ]), split )
1791+ self .pluggable_storage_adapter .set (split_storage ._split_till_prefix , data ['till' ])
1792+
1793+ segment_fn = os .path .join (os .path .dirname (__file__ ), 'files' , 'segmentEmployeesChanges.json' )
1794+ with open (segment_fn , 'r' ) as flo :
1795+ data = json .loads (flo .read ())
1796+ self .pluggable_storage_adapter .set (segment_storage ._prefix .format (segment_name = data ['name' ]), set (data ['added' ]))
1797+ self .pluggable_storage_adapter .set (segment_storage ._segment_till_prefix .format (segment_name = data ['name' ]), data ['till' ])
1798+
1799+ segment_fn = os .path .join (os .path .dirname (__file__ ), 'files' , 'segmentHumanBeignsChanges.json' )
1800+ with open (segment_fn , 'r' ) as flo :
1801+ data = json .loads (flo .read ())
1802+ self .pluggable_storage_adapter .set (segment_storage ._prefix .format (segment_name = data ['name' ]), set (data ['added' ]))
1803+ self .pluggable_storage_adapter .set (segment_storage ._segment_till_prefix .format (segment_name = data ['name' ]), data ['till' ])
1804+ self .client = self .factory .client ()
1805+
1806+
1807+ def _validate_last_events (self , client , * to_validate ):
1808+ """Validate the last N impressions are present disregarding the order."""
1809+ event_storage = client ._factory ._get_storage ('events' )
1810+ events_raw = []
1811+ stored_events = self .pluggable_storage_adapter .pop_items (event_storage ._events_queue_key )
1812+ if stored_events is not None :
1813+ events_raw = [json .loads (im ) for im in stored_events ]
1814+
1815+ as_tup_set = set (
1816+ (i ['e' ]['key' ], i ['e' ]['trafficTypeName' ], i ['e' ]['eventTypeId' ], i ['e' ]['value' ], str (i ['e' ]['properties' ]))
1817+ for i in events_raw
1818+ )
1819+ assert as_tup_set == set (to_validate )
1820+
1821+ def test_get_treatment (self ):
1822+ """Test client.get_treatment()."""
1823+ assert self .client .get_treatment ('user1' , 'sample_feature' ) == 'on'
1824+ assert self .client .get_treatment ('invalidKey' , 'sample_feature' ) == 'off'
1825+ assert self .pluggable_storage_adapter ._keys ['myprefix.SPLITIO.impressions' ] == []
1826+
1827+ def test_get_treatments (self ):
1828+ """Test client.get_treatments()."""
1829+ result = self .client .get_treatments ('user1' , ['sample_feature' ])
1830+ assert len (result ) == 1
1831+ assert result ['sample_feature' ] == 'on'
1832+
1833+ result = self .client .get_treatments ('invalidKey' , ['sample_feature' ])
1834+ assert len (result ) == 1
1835+ assert result ['sample_feature' ] == 'off'
1836+
1837+ result = self .client .get_treatments ('invalidKey' , ['invalid_feature' ])
1838+ assert len (result ) == 1
1839+ assert result ['invalid_feature' ] == 'control'
1840+ assert self .pluggable_storage_adapter ._keys ['myprefix.SPLITIO.impressions' ] == []
1841+
1842+ def test_get_treatments_with_config (self ):
1843+ """Test client.get_treatments_with_config()."""
1844+ result = self .client .get_treatments_with_config ('user1' , ['sample_feature' ])
1845+ assert len (result ) == 1
1846+ assert result ['sample_feature' ] == ('on' , '{"size":15,"test":20}' )
1847+
1848+ result = self .client .get_treatments_with_config ('invalidKey2' , ['sample_feature' ])
1849+ assert len (result ) == 1
1850+ assert result ['sample_feature' ] == ('off' , None )
1851+
1852+ result = self .client .get_treatments_with_config ('invalidKey' , ['invalid_feature' ])
1853+ assert len (result ) == 1
1854+ assert result ['invalid_feature' ] == ('control' , None )
1855+ assert self .pluggable_storage_adapter ._keys ['myprefix.SPLITIO.impressions' ] == []
1856+
1857+ def test_track (self ):
1858+ """Test client.track()."""
1859+ assert (self .client .track ('user1' , 'user' , 'conversion' , 1 , {"prop1" : "value1" }))
1860+ assert (not self .client .track (None , 'user' , 'conversion' ))
1861+ assert (not self .client .track ('user1' , None , 'conversion' ))
1862+ assert (not self .client .track ('user1' , 'user' , None ))
1863+ self ._validate_last_events (
1864+ self .client ,
1865+ ('user1' , 'user' , 'conversion' , 1 , "{'prop1': 'value1'}" )
1866+ )
1867+
1868+ def test_mtk (self ):
1869+ self .client .get_treatment ('user1' , 'sample_feature' )
1870+ self .client .get_treatment ('invalidKey' , 'sample_feature' )
1871+ self .client .get_treatment ('invalidKey2' , 'sample_feature' )
1872+ self .client .get_treatment ('user22' , 'invalidFeature' )
1873+ event = threading .Event ()
1874+ self .factory .destroy (event )
1875+ event .wait ()
1876+ assert (json .loads (self .pluggable_storage_adapter ._keys ['myprefix.SPLITIO.uniquekeys' ][0 ])["f" ] == "sample_feature" )
1877+ assert (json .loads (self .pluggable_storage_adapter ._keys ['myprefix.SPLITIO.uniquekeys' ][0 ])["ks" ].sort () ==
1878+ ["invalidKey2" , "invalidKey" , "user1" ].sort ())
0 commit comments