Esempio n. 1
0
    def test_destroy_with_event_redis(self, mocker):
        def _make_factory_with_apikey(apikey, *_, **__):
            return SplitFactory(apikey, {}, True, mocker.Mock(spec=ImpressionsManager), None)

        factory_module_logger = mocker.Mock()
        build_redis = mocker.Mock()
        build_redis.side_effect = _make_factory_with_apikey
        mocker.patch('splitio.client.factory._LOGGER', new=factory_module_logger)
        mocker.patch('splitio.client.factory._build_redis_factory', new=build_redis)

        config = {
            'redisDb': 0,
            'redisHost': 'localhost',
            'redisPosrt': 6379,
        }

        factory = get_factory("none", config=config)
        event = threading.Event()
        factory.destroy(event)
        event.wait()
        assert factory.destroyed
        assert len(build_redis.mock_calls) == 1

        factory = get_factory("none", config=config)
        factory.destroy(None)
        time.sleep(0.1)
        assert factory.destroyed
        assert len(build_redis.mock_calls) == 2
Esempio n. 2
0
    def test_localhost_e2e(self):
        """Instantiate a client with a YAML file and issue get_treatment() calls."""
        filename = os.path.join(os.path.dirname(__file__), 'files', 'file2.yaml')
        factory = get_factory('localhost', config={'splitFile': filename})
        factory.block_until_ready()
        client = factory.client()
        assert client.get_treatment_with_config('key', 'my_feature') == ('on', '{"desc" : "this applies only to ON treatment"}')
        assert client.get_treatment_with_config('only_key', 'my_feature') == (
            'off', '{"desc" : "this applies only to OFF and only for only_key. The rest will receive ON"}'
        )
        assert client.get_treatment_with_config('another_key', 'my_feature') == ('control', None)
        assert client.get_treatment_with_config('key2', 'other_feature') == ('on', None)
        assert client.get_treatment_with_config('key3', 'other_feature') == ('on', None)
        assert client.get_treatment_with_config('some_key', 'other_feature_2') == ('on', None)
        assert client.get_treatment_with_config('key_whitelist', 'other_feature_3') == ('on', None)
        assert client.get_treatment_with_config('any_other_key', 'other_feature_3') == ('off', None)

        manager = factory.manager()
        assert manager.split('my_feature').configs == {
            'on': '{"desc" : "this applies only to ON treatment"}',
            'off': '{"desc" : "this applies only to OFF and only for only_key. The rest will receive ON"}'
        }
        assert manager.split('other_feature').configs == {}
        assert manager.split('other_feature_2').configs == {}
        assert manager.split('other_feature_3').configs == {}
        event = threading.Event()
        factory.destroy(event)
        event.wait()

        # hack to increase isolation and prevent conflicts with other tests
        thread = factory._sync_manager._synchronizer._split_tasks.split_task._task._thread
        if thread is not None and thread.is_alive():
            thread.join()
Esempio n. 3
0
    def test_uwsgi_preforked(self, mocker):
        """Test preforked initializations."""

        def clear_impressions():
            clear_impressions._called += 1

        def clear_events():
            clear_events._called += 1

        def clear_telemetry():
            clear_telemetry._called += 1

        clear_impressions._called = 0
        clear_events._called = 0
        clear_telemetry._called = 0
        split_storage = mocker.Mock(spec=inmemmory.SplitStorage)
        segment_storage = mocker.Mock(spec=inmemmory.SegmentStorage)
        impression_storage = mocker.Mock(spec=inmemmory.ImpressionStorage)
        impression_storage.clear.side_effect = clear_impressions
        event_storage = mocker.Mock(spec=inmemmory.EventStorage)
        event_storage.clear.side_effect = clear_events
        telemetry_storage = mocker.Mock(spec=inmemmory.TelemetryStorage)
        telemetry_storage.clear.side_effect = clear_telemetry

        def _get_storage_mock(self, name):
            return {
                'splits': split_storage,
                'segments': segment_storage,
                'impressions': impression_storage,
                'events': event_storage,
                'telemetry': telemetry_storage
            }[name]

        mocker.patch('splitio.client.factory.SplitFactory._get_storage', new=_get_storage_mock)

        sync_all_mock = mocker.Mock()
        mocker.patch('splitio.sync.synchronizer.Synchronizer.sync_all', new=sync_all_mock)

        start_mock = mocker.Mock()
        mocker.patch('splitio.sync.manager.Manager.start', new=start_mock)

        recreate_mock = mocker.Mock()
        mocker.patch('splitio.sync.manager.Manager.recreate', new=recreate_mock)

        config = {
            'preforkedInitialization': True,
        }
        factory = get_factory("none", config=config)
        factory.block_until_ready(10)
        assert factory._status == Status.WAITING_FORK
        assert len(sync_all_mock.mock_calls) == 1
        assert len(start_mock.mock_calls) == 0

        factory.resume()
        assert len(recreate_mock.mock_calls) == 1
        assert len(start_mock.mock_calls) == 1

        assert clear_impressions._called == 1
        assert clear_events._called == 1
        assert clear_telemetry._called == 1
Esempio n. 4
0
    def test_inmemory_client_creation_streaming_false(self, mocker):
        """Test that a client with in-memory storage is created correctly."""

        # Setup synchronizer
        def _split_synchronizer(self, ready_flag, synchronizer, auth_api, streaming_enabled, sse_url=None):
            synchronizer = mocker.Mock(spec=Synchronizer)
            synchronizer.sync_all.return_values = None
            self._ready_flag = ready_flag
            self._synchronizer = synchronizer
            self._streaming_enabled = False
        mocker.patch('splitio.sync.manager.Manager.__init__', new=_split_synchronizer)

        # Start factory and make assertions
        factory = get_factory('some_api_key')
        assert isinstance(factory._storages['splits'], inmemmory.InMemorySplitStorage)
        assert isinstance(factory._storages['segments'], inmemmory.InMemorySegmentStorage)
        assert isinstance(factory._storages['impressions'], inmemmory.InMemoryImpressionStorage)
        assert factory._storages['impressions']._impressions.maxsize == 10000
        assert isinstance(factory._storages['events'], inmemmory.InMemoryEventStorage)
        assert factory._storages['events']._events.maxsize == 10000
        assert isinstance(factory._storages['telemetry'], inmemmory.InMemoryTelemetryStorage)

        assert isinstance(factory._sync_manager, Manager)

        assert isinstance(factory._recorder, StandardRecorder)
        assert isinstance(factory._recorder._impressions_manager, ImpressionsManager)
        assert isinstance(factory._recorder._telemetry_storage, inmemmory.TelemetryStorage)
        assert isinstance(factory._recorder._event_sotrage, inmemmory.EventStorage)
        assert isinstance(factory._recorder._impression_storage, inmemmory.ImpressionStorage)

        assert factory._labels_enabled is True
        factory.block_until_ready()
        assert factory.ready
        factory.destroy()
Esempio n. 5
0
    def test_uwsgi_forked_client_creation(self):
        """Test client with preforked initialization."""
        factory = get_factory('some_api_key',
                              config={'preforkedInitialization': True})
        assert isinstance(factory._storages['splits'],
                          inmemmory.InMemorySplitStorage)
        assert isinstance(factory._storages['segments'],
                          inmemmory.InMemorySegmentStorage)
        assert isinstance(factory._storages['impressions'],
                          inmemmory.InMemoryImpressionStorage)
        assert factory._storages['impressions']._impressions.maxsize == 10000
        assert isinstance(factory._storages['events'],
                          inmemmory.InMemoryEventStorage)
        assert factory._storages['events']._events.maxsize == 10000

        assert isinstance(factory._sync_manager, Manager)

        assert isinstance(factory._recorder, StandardRecorder)
        assert isinstance(factory._recorder._impressions_manager,
                          ImpressionsManager)
        assert isinstance(factory._recorder._event_sotrage,
                          inmemmory.EventStorage)
        assert isinstance(factory._recorder._impression_storage,
                          inmemmory.ImpressionStorage)

        assert factory._status == Status.WAITING_FORK
        factory.destroy()
Esempio n. 6
0
    def test_destroy(self, mocker):
        """Test that tasks are shutdown and data is flushed when destroy is called."""
        def _split_task_init_mock(self, api, storage, period, event):
            self._task = mocker.Mock()
            self._api = api
            self._storage = storage
            self._period = period
            self._event = event
            event.set()
        mocker.patch('splitio.client.factory.SplitSynchronizationTask.__init__', new=_split_task_init_mock)

        def _segment_task_init_mock(self, api, storage, split_storage, period, event):
            self._task = mocker.Mock()
            self._worker_pool = mocker.Mock()
            self._api = api
            self._segment_storage = storage
            self._split_storage = split_storage
            self._period = period
            self._event = event
            event.set()
        mocker.patch('splitio.client.factory.SegmentSynchronizationTask.__init__', new=_segment_task_init_mock)

        imp_async_task_mock = mocker.Mock(spec=asynctask.AsyncTask)
        def _imppression_task_init_mock(self, api, storage, refresh_rate, bulk_size):
            self._logger = mocker.Mock()
            self._impressions_api = api
            self._storage = storage
            self._period = refresh_rate
            self._task = imp_async_task_mock
            self._failed = mocker.Mock()
            self._bulk_size = bulk_size
        mocker.patch('splitio.client.factory.ImpressionsSyncTask.__init__', new=_imppression_task_init_mock)

        evt_async_task_mock = mocker.Mock(spec=asynctask.AsyncTask)
        def _event_task_init_mock(self, api, storage, refresh_rate, bulk_size):
            self._logger = mocker.Mock()
            self._impressions_api = api
            self._storage = storage
            self._period = refresh_rate
            self._task = evt_async_task_mock
            self._failed = mocker.Mock()
            self._bulk_size = bulk_size
        mocker.patch('splitio.client.factory.EventsSyncTask.__init__', new=_event_task_init_mock)

        # Start factory and make assertions
        factory = get_factory('some_api_key')
        factory.block_until_ready()
        time.sleep(1) # give a chance for the bg thread to set the ready status
        assert factory.ready
        assert factory.destroyed is False

        factory.destroy()
        assert imp_async_task_mock.stop.mock_calls == [mocker.call(None)]
        assert evt_async_task_mock.stop.mock_calls == [mocker.call(None)]
        assert factory.destroyed is True
Esempio n. 7
0
    def test_error_prefork(self, mocker):
        """Test not handling fork."""
        expected_msg = [mocker.call('Cannot call resume')]

        filename = os.path.join(os.path.dirname(__file__),
                                '../integration/files', 'file2.yaml')
        factory = get_factory('localhost', config={'splitFile': filename})
        factory.block_until_ready(1)

        _logger = mocker.Mock()
        mocker.patch('splitio.client.factory._LOGGER', new=_logger)
        factory.resume()
        assert _logger.warning.mock_calls == expected_msg
Esempio n. 8
0
 def test_uwsgi_client_creation(self):
     """Test that a client with redis storage is created correctly."""
     factory = get_factory('some_api_key', config={'uwsgiClient': True})
     assert isinstance(factory._get_storage('splits'), uwsgi.UWSGISplitStorage)
     assert isinstance(factory._get_storage('segments'), uwsgi.UWSGISegmentStorage)
     assert isinstance(factory._get_storage('impressions'), uwsgi.UWSGIImpressionStorage)
     assert isinstance(factory._get_storage('events'), uwsgi.UWSGIEventStorage)
     assert isinstance(factory._get_storage('telemetry'), uwsgi.UWSGITelemetryStorage)
     assert factory._apis == {}
     assert factory._tasks == {}
     assert factory._labels_enabled is True
     assert factory._impression_listener is None
     factory.block_until_ready()
     time.sleep(1) # give a chance for the bg thread to set the ready status
     assert factory.ready
Esempio n. 9
0
    def test_localhost_e2e(self):
        """Instantiate a client with a YAML file and issue get_treatment() calls."""
        filename = os.path.join(os.path.dirname(__file__), 'files',
                                'file2.yaml')
        factory = get_factory('localhost', config={'splitFile': filename})
        factory.block_until_ready()
        time.sleep(1)
        client = factory.client()
        assert client.get_treatment_with_config(
            'key',
            'my_feature') == ('on',
                              '{"desc" : "this applies only to ON treatment"}')
        assert client.get_treatment_with_config('only_key', 'my_feature') == (
            'off',
            '{"desc" : "this applies only to OFF and only for only_key. The rest will receive ON"}'
        )
        assert client.get_treatment_with_config('another_key',
                                                'my_feature') == ('control',
                                                                  None)
        assert client.get_treatment_with_config('key2',
                                                'other_feature') == ('on',
                                                                     None)
        assert client.get_treatment_with_config('key3',
                                                'other_feature') == ('on',
                                                                     None)
        assert client.get_treatment_with_config('some_key',
                                                'other_feature_2') == ('on',
                                                                       None)
        assert client.get_treatment_with_config('key_whitelist',
                                                'other_feature_3') == ('on',
                                                                       None)
        assert client.get_treatment_with_config('any_other_key',
                                                'other_feature_3') == ('off',
                                                                       None)

        manager = factory.manager()
        assert manager.split('my_feature').configs == {
            'on':
            '{"desc" : "this applies only to ON treatment"}',
            'off':
            '{"desc" : "this applies only to OFF and only for only_key. The rest will receive ON"}'
        }
        assert manager.split('other_feature').configs == {}
        assert manager.split('other_feature_2').configs == {}
        assert manager.split('other_feature_3').configs == {}
Esempio n. 10
0
 def test_uwsgi_client_creation(self):
     """Test that a client with redis storage is created correctly."""
     factory = get_factory('some_api_key', config={'uwsgiClient': True})
     assert isinstance(factory._get_storage('splits'), uwsgi.UWSGISplitStorage)
     assert isinstance(factory._get_storage('segments'), uwsgi.UWSGISegmentStorage)
     assert isinstance(factory._get_storage('impressions'), uwsgi.UWSGIImpressionStorage)
     assert isinstance(factory._get_storage('events'), uwsgi.UWSGIEventStorage)
     assert isinstance(factory._get_storage('telemetry'), uwsgi.UWSGITelemetryStorage)
     assert factory._sync_manager is None
     assert factory._labels_enabled is True
     assert isinstance(factory._recorder, StandardRecorder)
     assert isinstance(factory._recorder._impressions_manager, ImpressionsManager)
     assert isinstance(factory._recorder._telemetry_storage, inmemmory.TelemetryStorage)
     assert isinstance(factory._recorder._event_sotrage, inmemmory.EventStorage)
     assert isinstance(factory._recorder._impression_storage, inmemmory.ImpressionStorage)
     factory.block_until_ready()
     assert factory.ready
     factory.destroy()
Esempio n. 11
0
    def test_multiple_factories(self, mocker):
        """Test multiple factories instantiation and tracking."""
        def _make_factory_with_apikey(apikey, *_, **__):
            return SplitFactory(apikey, {}, True)

        factory_module_logger = mocker.Mock()
        build_in_memory = mocker.Mock()
        build_in_memory.side_effect = _make_factory_with_apikey
        build_redis = mocker.Mock()
        build_redis.side_effect = _make_factory_with_apikey
        build_uwsgi = mocker.Mock()
        build_uwsgi.side_effect = _make_factory_with_apikey
        build_localhost = mocker.Mock()
        build_localhost.side_effect = _make_factory_with_apikey
        mocker.patch('splitio.client.factory._LOGGER',
                     new=factory_module_logger)
        mocker.patch('splitio.client.factory._build_in_memory_factory',
                     new=build_in_memory)
        mocker.patch('splitio.client.factory._build_redis_factory',
                     new=build_redis)
        mocker.patch('splitio.client.factory._build_uwsgi_factory',
                     new=build_uwsgi)
        mocker.patch('splitio.client.factory._build_localhost_factory',
                     new=build_localhost)

        _INSTANTIATED_FACTORIES.clear(
        )  # Clear all factory counters for testing purposes

        factory1 = get_factory('some_api_key')
        assert _INSTANTIATED_FACTORIES['some_api_key'] == 1
        assert factory_module_logger.warning.mock_calls == []

        factory2 = get_factory('some_api_key')
        assert _INSTANTIATED_FACTORIES['some_api_key'] == 2
        assert factory_module_logger.warning.mock_calls == [
            mocker.call(
                "factory instantiation: You already have %d %s with this API Key. "
                "We recommend keeping only one instance of the factory at all times "
                "(Singleton pattern) and reusing it throughout your application.",
                1, 'factory')
        ]

        factory_module_logger.reset_mock()
        factory3 = get_factory('some_api_key')
        assert _INSTANTIATED_FACTORIES['some_api_key'] == 3
        assert factory_module_logger.warning.mock_calls == [
            mocker.call(
                "factory instantiation: You already have %d %s with this API Key. "
                "We recommend keeping only one instance of the factory at all times "
                "(Singleton pattern) and reusing it throughout your application.",
                2, 'factories')
        ]

        factory_module_logger.reset_mock()
        factory4 = get_factory('some_other_api_key')
        assert _INSTANTIATED_FACTORIES['some_api_key'] == 3
        assert _INSTANTIATED_FACTORIES['some_other_api_key'] == 1
        assert factory_module_logger.warning.mock_calls == [
            mocker.call(
                "factory instantiation: You already have an instance of the Split factory. "
                "Make sure you definitely want this additional instance. "
                "We recommend keeping only one instance of the factory at all times "
                "(Singleton pattern) and reusing it throughout your application."
            )
        ]

        event = threading.Event()
        factory1.destroy(event)
        event.wait()
        assert _INSTANTIATED_FACTORIES['some_other_api_key'] == 1
        assert _INSTANTIATED_FACTORIES['some_api_key'] == 2
        factory2.destroy()
        factory3.destroy()
        factory4.destroy()
Esempio n. 12
0
    def test_destroy_with_event(self, mocker):
        """Test that tasks are shutdown and data is flushed when destroy is called."""
        spl_async_task_mock = mocker.Mock(spec=asynctask.AsyncTask)

        def _split_task_init_mock(self, api, storage, period, event):
            self._task = spl_async_task_mock
            self._api = api
            self._storage = storage
            self._period = period
            self._event = event
            event.set()

        mocker.patch(
            'splitio.client.factory.SplitSynchronizationTask.__init__',
            new=_split_task_init_mock)

        sgm_async_task_mock = mocker.Mock(spec=asynctask.AsyncTask)
        worker_pool_mock = mocker.Mock(spec=workerpool.WorkerPool)

        def _segment_task_init_mock(self, api, storage, split_storage, period,
                                    event):
            self._task = sgm_async_task_mock
            self._worker_pool = worker_pool_mock
            self._api = api
            self._segment_storage = storage
            self._split_storage = split_storage
            self._period = period
            self._event = event
            event.set()

        mocker.patch(
            'splitio.client.factory.SegmentSynchronizationTask.__init__',
            new=_segment_task_init_mock)

        imp_async_task_mock = mocker.Mock(spec=asynctask.AsyncTask)

        def _imppression_task_init_mock(self, api, storage, refresh_rate,
                                        bulk_size):
            self._logger = mocker.Mock()
            self._impressions_api = api
            self._storage = storage
            self._period = refresh_rate
            self._task = imp_async_task_mock
            self._failed = mocker.Mock()
            self._bulk_size = bulk_size

        mocker.patch('splitio.client.factory.ImpressionsSyncTask.__init__',
                     new=_imppression_task_init_mock)

        evt_async_task_mock = mocker.Mock(spec=asynctask.AsyncTask)

        def _event_task_init_mock(self, api, storage, refresh_rate, bulk_size):
            self._logger = mocker.Mock()
            self._impressions_api = api
            self._storage = storage
            self._period = refresh_rate
            self._task = evt_async_task_mock
            self._failed = mocker.Mock()
            self._bulk_size = bulk_size

        mocker.patch('splitio.client.factory.EventsSyncTask.__init__',
                     new=_event_task_init_mock)

        tmt_async_task_mock = mocker.Mock(spec=asynctask.AsyncTask)

        def _telemetry_task_init_mock(self, api, storage, refresh_rate):
            self._task = tmt_async_task_mock
            self._logger = mocker.Mock()
            self._api = api
            self._storage = storage
            self._period = refresh_rate

        mocker.patch(
            'splitio.client.factory.TelemetrySynchronizationTask.__init__',
            new=_telemetry_task_init_mock)

        # Start factory and make assertions
        factory = get_factory('some_api_key')
        assert factory.destroyed is False

        factory.block_until_ready()
        time.sleep(
            1)  # give a chance for the bg thread to set the ready status
        assert factory.ready

        event = threading.Event()
        factory.destroy(event)

        # When destroy is called an event is created and passed to each task when
        # stop() is called. We will extract those events assert their type, and assert that
        # by setting them, the main event gets set.
        splits_event = spl_async_task_mock.stop.mock_calls[0][1][0]
        segments_event = worker_pool_mock.stop.mock_calls[0][1][
            0]  # Segment task stops when wp finishes.
        impressions_event = imp_async_task_mock.stop.mock_calls[0][1][0]
        events_event = evt_async_task_mock.stop.mock_calls[0][1][0]
        telemetry_event = tmt_async_task_mock.stop.mock_calls[0][1][0]

        # python2 & 3 compatibility
        try:
            from threading import _Event as __EVENT_CLASS
        except ImportError:
            from threading import Event as __EVENT_CLASS

        assert isinstance(splits_event, __EVENT_CLASS)
        assert isinstance(segments_event, __EVENT_CLASS)
        assert isinstance(impressions_event, __EVENT_CLASS)
        assert isinstance(events_event, __EVENT_CLASS)
        assert isinstance(telemetry_event, __EVENT_CLASS)
        assert not event.is_set()

        splits_event.set()
        segments_event.set()
        impressions_event.set()
        events_event.set()
        telemetry_event.set()

        time.sleep(
            1
        )  # I/O wait to trigger context switch, to give the waiting thread
        # a chance to run and set the main event.

        assert event.is_set()
        assert factory.destroyed
Esempio n. 13
0
    def test_inmemory_client_creation(self, mocker):
        """Test that a client with in-memory storage is created correctly."""

        # Setup task mocks
        def _split_task_init_mock(self, api, storage, period, event):
            self._task = mocker.Mock()
            self._api = api
            self._storage = storage
            self._period = period
            self._event = event
            event.set()

        mocker.patch(
            'splitio.client.factory.SplitSynchronizationTask.__init__',
            new=_split_task_init_mock)

        def _segment_task_init_mock(self, api, storage, split_storage, period,
                                    event):
            self._task = mocker.Mock()
            self._worker_pool = mocker.Mock()
            self._api = api
            self._segment_storage = storage
            self._split_storage = split_storage
            self._period = period
            self._event = event
            event.set()

        mocker.patch(
            'splitio.client.factory.SegmentSynchronizationTask.__init__',
            new=_segment_task_init_mock)

        # Start factory and make assertions
        factory = get_factory('some_api_key')
        assert isinstance(factory._storages['splits'],
                          inmemmory.InMemorySplitStorage)
        assert isinstance(factory._storages['segments'],
                          inmemmory.InMemorySegmentStorage)
        assert isinstance(factory._storages['impressions'],
                          inmemmory.InMemoryImpressionStorage)
        assert factory._storages['impressions']._impressions.maxsize == 10000
        assert isinstance(factory._storages['events'],
                          inmemmory.InMemoryEventStorage)
        assert factory._storages['events']._events.maxsize == 10000
        assert isinstance(factory._storages['telemetry'],
                          inmemmory.InMemoryTelemetryStorage)

        assert isinstance(factory._apis['splits'], SplitsAPI)
        assert factory._apis['splits']._client._timeout == 1.5
        assert isinstance(factory._apis['segments'], SegmentsAPI)
        assert factory._apis['segments']._client._timeout == 1.5
        assert isinstance(factory._apis['impressions'], ImpressionsAPI)
        assert factory._apis['impressions']._client._timeout == 1.5
        assert isinstance(factory._apis['events'], EventsAPI)
        assert factory._apis['events']._client._timeout == 1.5
        assert isinstance(factory._apis['telemetry'], TelemetryAPI)
        assert factory._apis['telemetry']._client._timeout == 1.5

        assert isinstance(factory._tasks['splits'],
                          split_sync.SplitSynchronizationTask)
        assert factory._tasks['splits']._period == DEFAULT_CONFIG[
            'featuresRefreshRate']
        assert factory._tasks['splits']._storage == factory._storages['splits']
        assert factory._tasks['splits']._api == factory._apis['splits']
        assert isinstance(factory._tasks['segments'],
                          segment_sync.SegmentSynchronizationTask)
        assert factory._tasks['segments']._period == DEFAULT_CONFIG[
            'segmentsRefreshRate']
        assert factory._tasks[
            'segments']._segment_storage == factory._storages['segments']
        assert factory._tasks['segments']._split_storage == factory._storages[
            'splits']
        assert factory._tasks['segments']._api == factory._apis['segments']
        assert isinstance(factory._tasks['impressions'],
                          impressions_sync.ImpressionsSyncTask)
        assert factory._tasks['impressions']._period == DEFAULT_CONFIG[
            'impressionsRefreshRate']
        assert factory._tasks['impressions']._storage == factory._storages[
            'impressions']
        assert factory._tasks['impressions']._impressions_api == factory._apis[
            'impressions']
        assert isinstance(factory._tasks['events'], events_sync.EventsSyncTask)
        assert factory._tasks['events']._period == DEFAULT_CONFIG[
            'eventsPushRate']
        assert factory._tasks['events']._storage == factory._storages['events']
        assert factory._tasks['events']._events_api == factory._apis['events']
        assert isinstance(factory._tasks['telemetry'],
                          telemetry_sync.TelemetrySynchronizationTask)
        assert factory._tasks['telemetry']._period == DEFAULT_CONFIG[
            'metricsRefreshRate']
        assert factory._tasks['telemetry']._storage == factory._storages[
            'telemetry']
        assert factory._tasks['telemetry']._api == factory._apis['telemetry']
        assert factory._labels_enabled is True
        factory.block_until_ready()
        time.sleep(
            1)  # give a chance for the bg thread to set the ready status
        assert factory.ready
        factory.destroy()
Esempio n. 14
0
    def test_redis_client_creation(self, mocker):
        """Test that a client with redis storage is created correctly."""
        strict_redis_mock = mocker.Mock()
        mocker.patch('splitio.storage.adapters.redis.StrictRedis',
                     new=strict_redis_mock)

        config = {
            'labelsEnabled': False,
            'impressionListener': 123,
            'redisHost': 'some_host',
            'redisPort': 1234,
            'redisDb': 1,
            'redisPassword': '******',
            'redisSocketTimeout': 123,
            'redisSocketConnectTimeout': 123,
            'redisSocketKeepalive': 123,
            'redisSocketKeepaliveOptions': False,
            'redisConnectionPool': False,
            'redisUnixSocketPath': '/some_path',
            'redisEncoding': 'ascii',
            'redisEncodingErrors': 'non-strict',
            'redisCharset': 'ascii',
            'redisErrors': True,
            'redisDecodeResponses': True,
            'redisRetryOnTimeout': True,
            'redisSsl': True,
            'redisSslKeyfile': 'some_file',
            'redisSslCertfile': 'some_cert_file',
            'redisSslCertReqs': 'some_cert_req',
            'redisSslCaCerts': 'some_ca_cert',
            'redisMaxConnections': 999,
        }
        factory = get_factory('some_api_key', config=config)
        assert isinstance(factory._get_storage('splits'),
                          redis.RedisSplitStorage)
        assert isinstance(factory._get_storage('segments'),
                          redis.RedisSegmentStorage)
        assert isinstance(factory._get_storage('impressions'),
                          redis.RedisImpressionsStorage)
        assert isinstance(factory._get_storage('events'),
                          redis.RedisEventsStorage)
        assert isinstance(factory._get_storage('telemetry'),
                          redis.RedisTelemetryStorage)

        assert factory._apis == {}
        assert factory._tasks == {}

        adapter = factory._get_storage('splits')._redis
        assert adapter == factory._get_storage('segments')._redis
        assert adapter == factory._get_storage('impressions')._redis
        assert adapter == factory._get_storage('events')._redis
        assert adapter == factory._get_storage('telemetry')._redis

        assert strict_redis_mock.mock_calls == [
            mocker.call(host='some_host',
                        port=1234,
                        db=1,
                        password='******',
                        socket_timeout=123,
                        socket_connect_timeout=123,
                        socket_keepalive=123,
                        socket_keepalive_options=False,
                        connection_pool=False,
                        unix_socket_path='/some_path',
                        encoding='ascii',
                        encoding_errors='non-strict',
                        charset='ascii',
                        errors=True,
                        decode_responses=True,
                        retry_on_timeout=True,
                        ssl=True,
                        ssl_keyfile='some_file',
                        ssl_certfile='some_cert_file',
                        ssl_cert_reqs='some_cert_req',
                        ssl_ca_certs='some_ca_cert',
                        max_connections=999)
        ]
        assert factory._labels_enabled is False
        assert isinstance(factory._impression_listener,
                          ImpressionListenerWrapper)
        factory.block_until_ready()
        time.sleep(
            1)  # give a chance for the bg thread to set the ready status
        assert factory.ready
        factory.destroy()
Esempio n. 15
0
    def test_multiple_factories(self, mocker):
        """Test multiple factories instantiation and tracking."""
        sdk_ready_flag = threading.Event()

        def _init(self, ready_flag, some, auth_api, streaming_enabled, sse_url=None):
            self._ready_flag = ready_flag
            self._synchronizer = mocker.Mock(spec=Synchronizer)
            self._streaming_enabled = False
        mocker.patch('splitio.sync.manager.Manager.__init__', new=_init)

        def _start(self, *args, **kwargs):
            sdk_ready_flag.set()
        mocker.patch('splitio.sync.manager.Manager.start', new=_start)

        def _stop(self, *args, **kwargs):
            pass
        mocker.patch('splitio.sync.manager.Manager.stop', new=_stop)

        mockManager = Manager(sdk_ready_flag, mocker.Mock(), mocker.Mock(), False)

        def _make_factory_with_apikey(apikey, *_, **__):
            return SplitFactory(apikey, {}, True, mocker.Mock(spec=ImpressionsManager), mockManager)

        factory_module_logger = mocker.Mock()
        build_in_memory = mocker.Mock()
        build_in_memory.side_effect = _make_factory_with_apikey
        build_redis = mocker.Mock()
        build_redis.side_effect = _make_factory_with_apikey
        build_uwsgi = mocker.Mock()
        build_uwsgi.side_effect = _make_factory_with_apikey
        build_localhost = mocker.Mock()
        build_localhost.side_effect = _make_factory_with_apikey
        mocker.patch('splitio.client.factory._LOGGER', new=factory_module_logger)
        mocker.patch('splitio.client.factory._build_in_memory_factory', new=build_in_memory)
        mocker.patch('splitio.client.factory._build_redis_factory', new=build_redis)
        mocker.patch('splitio.client.factory._build_uwsgi_factory', new=build_uwsgi)
        mocker.patch('splitio.client.factory._build_localhost_factory', new=build_localhost)

        _INSTANTIATED_FACTORIES.clear()  # Clear all factory counters for testing purposes

        factory1 = get_factory('some_api_key')
        assert _INSTANTIATED_FACTORIES['some_api_key'] == 1
        assert factory_module_logger.warning.mock_calls == []

        factory2 = get_factory('some_api_key')
        assert _INSTANTIATED_FACTORIES['some_api_key'] == 2
        assert factory_module_logger.warning.mock_calls == [mocker.call(
            "factory instantiation: You already have %d %s with this API Key. "
            "We recommend keeping only one instance of the factory at all times "
            "(Singleton pattern) and reusing it throughout your application.",
            1,
            'factory'
        )]

        factory_module_logger.reset_mock()
        factory3 = get_factory('some_api_key')
        assert _INSTANTIATED_FACTORIES['some_api_key'] == 3
        assert factory_module_logger.warning.mock_calls == [mocker.call(
            "factory instantiation: You already have %d %s with this API Key. "
            "We recommend keeping only one instance of the factory at all times "
            "(Singleton pattern) and reusing it throughout your application.",
            2,
            'factories'
        )]

        factory_module_logger.reset_mock()
        factory4 = get_factory('some_other_api_key')
        assert _INSTANTIATED_FACTORIES['some_api_key'] == 3
        assert _INSTANTIATED_FACTORIES['some_other_api_key'] == 1
        assert factory_module_logger.warning.mock_calls == [mocker.call(
            "factory instantiation: You already have an instance of the Split factory. "
            "Make sure you definitely want this additional instance. "
            "We recommend keeping only one instance of the factory at all times "
            "(Singleton pattern) and reusing it throughout your application."
        )]

        event = threading.Event()
        factory1.destroy(event)
        event.wait()
        assert _INSTANTIATED_FACTORIES['some_other_api_key'] == 1
        assert _INSTANTIATED_FACTORIES['some_api_key'] == 2
        factory2.destroy()
        factory3.destroy()
        factory4.destroy()
Esempio n. 16
0
    def test_destroy_with_event(self, mocker):
        """Test that tasks are shutdown and data is flushed when destroy is called."""

        def stop_mock(event):
            time.sleep(0.1)
            event.set()
            return

        def stop_mock_2():
            return

        split_async_task_mock = mocker.Mock(spec=asynctask.AsyncTask)
        split_async_task_mock.stop.side_effect = stop_mock_2

        def _split_task_init_mock(self, synchronize_splits, period):
            self._task = split_async_task_mock
            self._period = period
        mocker.patch('splitio.client.factory.SplitSynchronizationTask.__init__',
                     new=_split_task_init_mock)

        segment_async_task_mock = mocker.Mock(spec=asynctask.AsyncTask)
        segment_async_task_mock.stop.side_effect = stop_mock_2

        def _segment_task_init_mock(self, synchronize_segments, period):
            self._task = segment_async_task_mock
            self._period = period
        mocker.patch('splitio.client.factory.SegmentSynchronizationTask.__init__',
                     new=_segment_task_init_mock)

        imp_async_task_mock = mocker.Mock(spec=asynctask.AsyncTask)
        imp_async_task_mock.stop.side_effect = stop_mock

        def _imppression_task_init_mock(self, synchronize_impressions, period):
            self._period = period
            self._task = imp_async_task_mock
        mocker.patch('splitio.client.factory.ImpressionsSyncTask.__init__',
                     new=_imppression_task_init_mock)

        evt_async_task_mock = mocker.Mock(spec=asynctask.AsyncTask)
        evt_async_task_mock.stop.side_effect = stop_mock

        def _event_task_init_mock(self, synchronize_events, period):
            self._period = period
            self._task = evt_async_task_mock
        mocker.patch('splitio.client.factory.EventsSyncTask.__init__', new=_event_task_init_mock)

        telemetry_async_task_mock = mocker.Mock(spec=asynctask.AsyncTask)
        telemetry_async_task_mock.stop.side_effect = stop_mock_2

        def _telemetry_task_init_mock(self, synchronize_counters, period):
            self._period = period
            self._task = telemetry_async_task_mock
        mocker.patch('splitio.client.factory.ImpressionsCountSyncTask.__init__',
                     new=_telemetry_task_init_mock)

        imp_count_async_task_mock = mocker.Mock(spec=asynctask.AsyncTask)
        imp_count_async_task_mock.stop.side_effect = stop_mock

        def _imppression_count_task_init_mock(self, synchronize_counters):
            self._task = imp_count_async_task_mock
        mocker.patch('splitio.client.factory.ImpressionsCountSyncTask.__init__',
                     new=_imppression_count_task_init_mock)

        split_sync = mocker.Mock(spec=SplitSynchronizer)
        split_sync.synchronize_splits.return_values = None
        segment_sync = mocker.Mock(spec=SegmentSynchronizer)
        segment_sync.synchronize_segments.return_values = None
        syncs = SplitSynchronizers(split_sync, segment_sync, mocker.Mock(),
                                   mocker.Mock(), mocker.Mock(), mocker.Mock())
        tasks = SplitTasks(split_async_task_mock, segment_async_task_mock, imp_async_task_mock,
                           evt_async_task_mock, telemetry_async_task_mock,
                           imp_count_async_task_mock)

        # Setup synchronizer
        def _split_synchronizer(self, ready_flag, some, auth_api, streaming_enabled, sse_url=None):
            synchronizer = Synchronizer(syncs, tasks)
            self._ready_flag = ready_flag
            self._synchronizer = synchronizer
            self._streaming_enabled = False
        mocker.patch('splitio.sync.manager.Manager.__init__', new=_split_synchronizer)

        # Start factory and make assertions
        factory = get_factory('some_api_key')
        factory.block_until_ready()
        assert factory.ready
        assert factory.destroyed is False

        event = threading.Event()
        factory.destroy(event)
        assert not event.is_set()
        time.sleep(1)
        assert event.is_set()
        assert len(imp_async_task_mock.stop.mock_calls) == 1
        assert len(evt_async_task_mock.stop.mock_calls) == 1
        assert len(telemetry_async_task_mock.stop.mock_calls) == 1
        assert len(imp_count_async_task_mock.stop.mock_calls) == 1
        assert factory.destroyed is True