Ejemplo n.º 1
0
    def setUp(self):
        self.rlock_mock = self.patch('splitio.splits.RLock')
        self.some_split_change_fetcher = mock.MagicMock()
        self.some_split_parser = mock.MagicMock()

        self.fetcher = SelfRefreshingSplitFetcher(
            self.some_split_change_fetcher, self.some_split_parser)
        self.refresh_splits_mock = self.patch_object(self.fetcher,
                                                     'refresh_splits')
        self.timer_refresh_mock = self.patch_object(self.fetcher,
                                                    '_timer_refresh')
Ejemplo n.º 2
0
    def setUp(self):
        self.rlock_mock = self.patch('splitio.splits.RLock')
        self.thread_mock = self.patch('splitio.splits.Thread')
        self.some_split_change_fetcher = mock.MagicMock()
        self.some_split_parser = mock.MagicMock()
        self.some_interval = mock.NonCallableMagicMock()

        self.fetcher = SelfRefreshingSplitFetcher(
            self.some_split_change_fetcher,
            self.some_split_parser,
            interval=self.some_interval)
        self.timer_start_mock = self.patch_object(self.fetcher, '_timer_start')
        self.fetcher.stopped = False
Ejemplo n.º 3
0
class SelfRefreshingSplitFetcherTimerRefreshTests(TestCase, MockUtilsMixin):
    def setUp(self):
        self.rlock_mock = self.patch('splitio.splits.RLock')
        self.thread_mock = self.patch('splitio.splits.Thread')
        self.some_split_change_fetcher = mock.MagicMock()
        self.some_split_parser = mock.MagicMock()
        self.some_interval = mock.NonCallableMagicMock()

        self.fetcher = SelfRefreshingSplitFetcher(
            self.some_split_change_fetcher,
            self.some_split_parser,
            interval=self.some_interval)
        self.timer_start_mock = self.patch_object(self.fetcher, '_timer_start')
        self.fetcher.stopped = False

    def test_thread_created_and_started_with_refresh_splits(self):
        """Tests that _timer_refresh creates and starts a Thread with _refresh_splits target"""
        self.fetcher._timer_refresh()
        self.thread_mock.assert_called_once_with(
            target=self.fetcher.refresh_splits)
        self.thread_mock.return_value.start.assert_called_once_with()

    def test_calls_timer_start(self):
        """Tests that _timer_refresh creates and starts a Timer with _timer_refresh target"""
        self.fetcher._timer_refresh()
        self.timer_start_mock.assert_called_once_with()

    def test_no_thread_created_if_stopped(self):
        """Tests that _timer_refresh doesn't create a Thread if it is stopped"""
        self.fetcher.stopped = True
        self.fetcher._timer_refresh()
        self.thread_mock.assert_not_called()

    def test_timer_start_not_called_if_stopped(self):
        """Tests that _timer_refresh doesn't call start_tiemer if it is stopped"""
        self.fetcher.stopped = True
        self.fetcher._timer_refresh()
        self.timer_start_mock.assert_called()

    def test_timer_start_called_if_thread_raises_exception(self):
        """
        Tests that _timer_refresh calls timer_start even if the _refresh_splits thread
        setup raises an exception
        """
        self.thread_mock.return_value = None
        self.thread_mock.side_effect = Exception()
        self.fetcher._timer_refresh()
        self.timer_start_mock.assert_called_once_with()
Ejemplo n.º 4
0
    def setUp(self):
        self.rlock_mock = self.patch('splitio.splits.RLock')

        self.some_feature = mock.MagicMock()
        self.some_splits = mock.MagicMock()
        self.some_split_change_fetcher = mock.MagicMock()
        self.some_split_parser = mock.MagicMock()

        self.fetcher = SelfRefreshingSplitFetcher(
            self.some_split_change_fetcher,
            self.some_split_parser,
            splits=self.some_splits)

        self.split_to_add = {'status': 'ACTIVE', 'name': 'split_to_add'}
        self.split_to_remove = {
            'status': 'ARCHIVED',
            'name': 'split_to_remove'
        }
        self.some_response = {
            'splits': [self.split_to_add, self.split_to_remove]
        }
Ejemplo n.º 5
0
class SelfRefreshingSplitFetcherTests(TestCase, MockUtilsMixin):
    def setUp(self):
        self.rlock_mock = self.patch('splitio.splits.RLock')
        self.some_split_change_fetcher = mock.MagicMock()
        self.some_split_parser = mock.MagicMock()

        self.fetcher = SelfRefreshingSplitFetcher(
            self.some_split_change_fetcher, self.some_split_parser)
        self.refresh_splits_mock = self.patch_object(self.fetcher,
                                                     'refresh_splits')
        self.timer_refresh_mock = self.patch_object(self.fetcher,
                                                    '_timer_refresh')

    def test_start_calls_timer_refresh_if_stopped(self):
        """Tests that if stopped is True, start calls _timer_refresh"""
        self.fetcher.stopped = True
        self.fetcher.start()

        self.timer_refresh_mock.assert_called_once_with()

    def test_start_sets_stopped_False_if_stopped(self):
        """Tests that if stopped is True, start sets it to True"""
        self.fetcher.stopped = True
        self.fetcher.start()

        self.assertFalse(self.fetcher.stopped)

    def test_start_doesnt_call_timer_refresh_if_not_stopped(self):
        """Tests that if stopped is false, start doesn't call _timer_refresh"""
        self.fetcher.stopped = False
        self.fetcher.start()

        self.timer_refresh_mock.assert_not_called()
Ejemplo n.º 6
0
    def setUp(self):
        self.rlock_mock = self.patch('splitio.splits.RLock')

        self.some_feature = mock.MagicMock()
        self.some_splits = mock.MagicMock()
        self.some_split_change_fetcher = mock.MagicMock()
        self.some_split_parser = mock.MagicMock()

        self.response_0 = {'till': 1, 'splits': [mock.MagicMock()]}
        self.response_1 = {'till': 2, 'splits': [mock.MagicMock()]}
        self.response_2 = {'till': 2, 'splits': []}

        self.some_split_change_fetcher.fetch.side_effect = [
            self.response_0, self.response_1, self.response_2
        ]

        self.fetcher = SelfRefreshingSplitFetcher(
            self.some_split_change_fetcher,
            self.some_split_parser,
            change_number=-1,
            splits=self.some_splits)
        self.update_splits_from_change_fetcher_response_mock = self.patch_object(
            self.fetcher, '_update_splits_from_change_fetcher_response')
Ejemplo n.º 7
0
 def _build_split_fetcher(self):
     """
     Build the self refreshing split fetcher
     :return: The self refreshing split fetcher
     :rtype: SelfRefreshingSplitFetcher
     """
     segment_change_fetcher = ApiSegmentChangeFetcher(self._sdk_api)
     segment_fetcher = SelfRefreshingSegmentFetcher(
         segment_change_fetcher,
         interval=self._segment_fetcher_interval
     )
     split_change_fetcher = ApiSplitChangeFetcher(self._sdk_api)
     split_parser = SplitParser(segment_fetcher)
     split_fetcher = SelfRefreshingSplitFetcher(
         split_change_fetcher,
         split_parser,
         interval=self._split_fetcher_interval
     )
     return split_fetcher
Ejemplo n.º 8
0
class SelfRefreshingSplitFetcherRefreshSplitsTests(TestCase, MockUtilsMixin):
    def setUp(self):
        self.rlock_mock = self.patch('splitio.splits.RLock')

        self.some_feature = mock.MagicMock()
        self.some_splits = mock.MagicMock()
        self.some_split_change_fetcher = mock.MagicMock()
        self.some_split_parser = mock.MagicMock()

        self.response_0 = {'till': 1, 'splits': [mock.MagicMock()]}
        self.response_1 = {'till': 2, 'splits': [mock.MagicMock()]}
        self.response_2 = {'till': 2, 'splits': []}

        self.some_split_change_fetcher.fetch.side_effect = [
            self.response_0, self.response_1, self.response_2
        ]

        self.fetcher = SelfRefreshingSplitFetcher(
            self.some_split_change_fetcher,
            self.some_split_parser,
            change_number=-1,
            splits=self.some_splits)
        self.update_splits_from_change_fetcher_response_mock = self.patch_object(
            self.fetcher, '_update_splits_from_change_fetcher_response')

    def test_calls_split_change_fetcher_until_change_number_ge_till_if_greedy(
            self):
        """
        Tests that if greedy is True _refresh_splits calls fetch on split_change_fetcher until
        change_number >= till
        """
        self.fetcher.refresh_splits()

        self.assertListEqual(
            [mock.call(-1), mock.call(1),
             mock.call(2)],
            self.some_split_change_fetcher.fetch.call_args_list)

    def test_calls_split_change_fetcher_once_if_non_greedy(self):
        """
        Tests that if greedy is False _refresh_splits calls fetch on split_change_fetcher once
        """
        self.fetcher._greedy = False
        self.fetcher.refresh_splits()
        self.some_split_change_fetcher.fetch.assert_called_once_with(-1)

    def test_calls_update_splits_from_change_fetcher_response_on_each_response_if_greedy(
            self):
        """
        Tests that if greedy is True _refresh_splits calls
        _update_splits_from_change_fetcher_response on all responses from split change fetcher
        with the default value for block_until_ready
        """
        self.fetcher.refresh_splits()
        self.assertListEqual([
            mock.call(self.response_0, block_until_ready=False),
            mock.call(self.response_1, block_until_ready=False)
        ], self.update_splits_from_change_fetcher_response_mock.call_args_list)

    def test_calls_update_splits_from_change_fetcher_response_on_each_response_greedy_block(
            self):
        """
        Tests that if greedy is True _refresh_splits calls
        _update_splits_from_change_fetcher_response on all responses from split change fetcher
        with the supplied value for block_until_ready
        """
        some_block_until_ready = mock.MagicMock()
        self.fetcher.refresh_splits(block_until_ready=some_block_until_ready)
        self.assertListEqual([
            mock.call(self.response_0,
                      block_until_ready=some_block_until_ready),
            mock.call(self.response_1,
                      block_until_ready=some_block_until_ready)
        ], self.update_splits_from_change_fetcher_response_mock.call_args_list)

    def test_calls_update_splits_from_change_fetcher_response_once_if_non_greedy(
            self):
        """
        Tests that if greedy is False _refresh_splits calls
        _update_splits_from_change_fetcher_response once with the default value for
        block_until_ready
        """
        self.fetcher._greedy = False
        self.fetcher.refresh_splits()
        self.update_splits_from_change_fetcher_response_mock.assert_called_once_with(
            self.response_0, block_until_ready=False)

    def test_calls_update_splits_from_change_fetcher_response_once_if_non_greedy_blocking(
            self):
        """
        Tests that if greedy is False _refresh_splits calls
        _update_splits_from_change_fetcher_response once with the supplied value for
        block_until_ready
        """
        some_block_until_ready = mock.MagicMock()
        self.fetcher._greedy = False
        self.fetcher.refresh_splits(block_until_ready=some_block_until_ready)
        self.update_splits_from_change_fetcher_response_mock.assert_called_once_with(
            self.response_0, block_until_ready=some_block_until_ready)

    def test_sets_change_number_to_latest_value_of_till_response(self):
        """
        Tests that _refresh_splits sets change_number to the largest value of "till" in the
        response of the split_change_fetcher fetch response.
        """
        self.fetcher.refresh_splits()
        self.assertEqual(2, self.fetcher.change_number)

    def test_stop_set_true_on_exception(self):
        """
        Tests that stopped is set to True if an exception is raised
        """
        self.some_split_change_fetcher.fetch.side_effect = [
            self.response_0, Exception()
        ]
        self.fetcher.refresh_splits()
        self.assertTrue(self.fetcher.stopped)

    def test_change_number_set_value_till_latest_successful_iteration(self):
        """
        Tests that change_number is set to the value of "till" in the latest successful iteration
        before an exception is raised
        """
        self.some_split_change_fetcher.fetch.side_effect = [
            self.response_0, Exception()
        ]
        self.fetcher.refresh_splits()
        self.assertEqual(1, self.fetcher.change_number)
Ejemplo n.º 9
0
class SelfRefreshingSplitFetcherUpdateSplitsFromChangeFetcherResponseTests(
        TestCase, MockUtilsMixin):
    def setUp(self):
        self.rlock_mock = self.patch('splitio.splits.RLock')

        self.some_feature = mock.MagicMock()
        self.some_splits = mock.MagicMock()
        self.some_split_change_fetcher = mock.MagicMock()
        self.some_split_parser = mock.MagicMock()

        self.fetcher = SelfRefreshingSplitFetcher(
            self.some_split_change_fetcher,
            self.some_split_parser,
            splits=self.some_splits)

        self.split_to_add = {'status': 'ACTIVE', 'name': 'split_to_add'}
        self.split_to_remove = {
            'status': 'ARCHIVED',
            'name': 'split_to_remove'
        }
        self.some_response = {
            'splits': [self.split_to_add, self.split_to_remove]
        }

    def test_pop_is_called_on_removed_split(self):
        """Tests that pop is called on splits for removed features"""
        self.fetcher._update_splits_from_change_fetcher_response(
            self.some_response)

        self.some_splits.pop.assert_called_once_with(
            self.split_to_remove['name'], None)

    def test_split_parser_parse_is_called_for_split_to_add(self):
        """Tests that parse is called on split_parser with the split to add with the default value
        for block_until_ready"""
        self.fetcher._update_splits_from_change_fetcher_response(
            self.some_response)

        self.some_split_parser.parse.assert_called_once_with(
            self.split_to_add, block_until_ready=False)

    def test_split_parser_parse_is_called_for_split_to_add_with_block_until_ready(
            self):
        """Tests that parse is called on split_parser with the split to add with the supplied value
        for block_until_ready"""
        some_block_until_ready = mock.MagicMock()
        self.fetcher._update_splits_from_change_fetcher_response(
            self.some_response, block_until_ready=some_block_until_ready)

        self.some_split_parser.parse.assert_called_once_with(
            self.split_to_add, block_until_ready=some_block_until_ready)

    def test_setitem_is_called_with_parsed_split_to_add(self):
        """Tests that pop is called on splits for removed features"""
        self.fetcher._update_splits_from_change_fetcher_response(
            self.some_response)

        self.some_splits.__setitem__.assert_called_once_with(
            self.split_to_add['name'],
            self.some_split_parser.parse.return_value)

    def test_pop_is_called_if_split_parse_fails(self):
        """Tests that pop is called on splits if parse returns None"""
        self.some_split_parser.parse.return_value = None

        self.fetcher._update_splits_from_change_fetcher_response(
            {'splits': [self.split_to_add]})

        self.some_splits.pop.assert_called_once_with(self.split_to_add['name'],
                                                     None)