コード例 #1
0
ファイル: factories.py プロジェクト: engstrom/python-client
    def __init__(self, api_key, **kwargs):
        super(MainSplitFactory, self).__init__()

        config = dict()
        if 'config' in kwargs:
            config = kwargs['config']

        labels_enabled = config.get('labelsEnabled', True)

        impression_listener = ImpressionListenerWrapper(
            config.get('impressionListener')
        ) if 'impressionListener' in config else None  # noqa: E501,E261

        if 'redisHost' in config or 'redisSentinels' in config:
            broker = get_redis_broker(api_key, **kwargs)
            self._client = Client(broker, labels_enabled, impression_listener)
            self._manager = RedisSplitManager(broker)
        else:
            if 'uwsgiClient' in config and config['uwsgiClient']:
                broker = get_uwsgi_broker(api_key, **kwargs)
                self._client = Client(broker, labels_enabled,
                                      impression_listener)
                self._manager = UWSGISplitManager(broker)
            else:
                broker = get_self_refreshing_broker(api_key, **kwargs)
                self._client = Client(broker, labels_enabled,
                                      impression_listener)
                self._manager = SelfRefreshingSplitManager(broker)
コード例 #2
0
class RedisReadOnlyTest(TestCase, MockUtilsMixin):
    def setUp(self):
        self._some_config = mock.MagicMock()
        self._split_changes_file_name = join(dirname(__file__), 'splitChangesReadOnly.json')

        with open(self._split_changes_file_name) as f:
            self._json = load(f)
            split_definition = self._json['splits'][0]
            split_name = split_definition['name']

        self._redis = get_redis({'redisPrefix': 'test'})

        self._mocked_redis = ReadOnlyRedisMock(self._redis)
        self._redis_split_cache = RedisSplitCache(self._redis)
        self._redis_split_cache.add_split(split_name, split_definition)
        self._client = Client(RedisBroker(self._mocked_redis, self._some_config))

        self._impression = mock.MagicMock()
        self._start = mock.MagicMock()
        self._operation = mock.MagicMock()

    def test_redis_read_only_mode(self):
        self.assertEqual(self._client.get_treatment('valid', 'test_read_only_1'), 'on')
        self.assertEqual(self._client.get_treatment('invalid', 'test_read_only_1'), 'off')
        self.assertEqual(self._client.get_treatment('valid', 'test_read_only_1_invalid'), 'control')
コード例 #3
0
    def setUp(self):
        self.some_config = mock.MagicMock()
        self.some_api_key = mock.MagicMock()
        self.redis = get_redis({'redisPrefix': 'test'})
        self.client = Client(RedisBroker(self.redis, self.some_config))

        input_validator._LOGGER.error = mock.MagicMock()
        self.logger_error = input_validator._LOGGER.error
        input_validator._LOGGER.warning = mock.MagicMock()
        self.logger_warning = input_validator._LOGGER.warning
コード例 #4
0
    def setUp(self):
        self.some_config = mock.MagicMock()
        self.some_api_key = mock.MagicMock()
        self.redis = get_redis({'redisPrefix': 'test'})
        self.client = Client(RedisBroker(self.redis, self.some_config))
        self.client._broker.fetch_feature = mock.MagicMock(
            return_value=Split("some_feature", 0, False, "default_treatment",
                               "user", "ACTIVE", 123))

        self.client._build_impression = mock.MagicMock()

        input_validator._LOGGER.error = mock.MagicMock()
        self.logger_error = input_validator._LOGGER.error
        input_validator._LOGGER.warning = mock.MagicMock()
        self.logger_warning = input_validator._LOGGER.warning
コード例 #5
0
    def test_client_raise_attribute_error(self):
        client_1 = Client(RedisBroker(self._redis, self._some_config), True,
                          ImpressionListenerClientEmpty())

        with self.assertRaises(AttributeError):
            client_1._impression_listener.log_impression(
                self.some_impression_0)
コード例 #6
0
    def setUp(self):
        self._some_config = mock.MagicMock()
        self._split_changes_file_name = join(
            dirname(__file__), 'splitCustomImpressionListener.json')

        with open(self._split_changes_file_name) as f:
            self._json = load(f)
            split_definition = self._json['splits'][0]
            split_name = split_definition['name']

        self._redis = get_redis(
            {'redisPrefix': 'customImpressionListenerTest'})

        self._redis_split_cache = RedisSplitCache(self._redis)
        self._redis_split_cache.add_split(split_name, split_definition)
        self._client = Client(RedisBroker(self._redis, self._some_config))

        self.some_feature = 'feature_0'
        self.some_impression_0 = Impression(matching_key=mock.MagicMock(),
                                            feature_name=self.some_feature,
                                            treatment=mock.MagicMock(),
                                            label=mock.MagicMock(),
                                            change_number=mock.MagicMock(),
                                            bucketing_key=mock.MagicMock(),
                                            time=mock.MagicMock())
コード例 #7
0
    def setUp(self):
        self._some_config = mock.MagicMock()
        self._split_changes_file_name = join(dirname(__file__),
                                             'splitGetTreatments.json')

        with open(self._split_changes_file_name) as f:
            self._json = load(f)
            split_definition = self._json['splits'][0]
            split_name = split_definition['name']

        self._redis = get_redis({'redisPrefix': 'getTreatmentsTest'})

        self._redis_split_cache = RedisSplitCache(self._redis)
        self._redis_split_cache.add_split(split_name, split_definition)
        self._client = Client(RedisBroker(self._redis, self._some_config))

        self._config = {
            'ready': 180000,
            'redisDb': 0,
            'redisHost': 'localhost',
            'redisPosrt': 6379,
            'redisPrefix': 'getTreatmentsTest'
        }
        self._factory = get_factory('asdqwe123456', config=self._config)
        self._split = self._factory.client()
コード例 #8
0
    def setUp(self):
        self.some_api_key = mock.MagicMock()
        self.broker = SelfRefreshingBroker(self.some_api_key)
        self.client = Client(self.broker)
        self.manager = SelfRefreshingSplitManager(self.broker)

        input_validator._LOGGER.error = mock.MagicMock()
        self.logger_error = input_validator._LOGGER.error
コード例 #9
0
    def setUp(self):
        self.some_api_key = mock.MagicMock()
        self.uwsgi = UWSGICacheEmulator()
        self.broker = UWSGIBroker(self.uwsgi, {'eventsQueueSize': 30})
        self.client = Client(self.broker)
        self.manager = UWSGISplitManager(self.broker)

        input_validator._LOGGER.error = mock.MagicMock()
        self.logger_error = input_validator._LOGGER.error
コード例 #10
0
    def setUp(self):
        self._some_config = mock.MagicMock()
        self._split_changes_file_name = join(dirname(__file__), 'splitChangesReadOnly.json')

        with open(self._split_changes_file_name) as f:
            self._json = load(f)
            split_definition = self._json['splits'][0]
            split_name = split_definition['name']

        self._redis = get_redis({'redisPrefix': 'test'})

        self._mocked_redis = ReadOnlyRedisMock(self._redis)
        self._redis_split_cache = RedisSplitCache(self._redis)
        self._redis_split_cache.add_split(split_name, split_definition)
        self._client = Client(RedisBroker(self._mocked_redis, self._some_config))

        self._impression = mock.MagicMock()
        self._start = mock.MagicMock()
        self._operation = mock.MagicMock()
コード例 #11
0
    def __init__(self, api_key, **kwargs):
        super(MainSplitFactory, self).__init__()

        config = dict()
        if 'config' in kwargs:
            config = kwargs['config']

        labels_enabled = config.get('labelsEnabled', True)
        if 'redisHost' in config:
            broker = get_redis_broker(api_key, **kwargs)
            self._client = Client(broker, labels_enabled)
            self._manager = RedisSplitManager(broker)
        else:
            if 'uwsgiClient' in config and config['uwsgiClient']:
                broker = get_uwsgi_broker(api_key, **kwargs)
                self._client = Client(broker, labels_enabled)
                self._manager = UWSGISplitManager(broker)
            else:
                broker = get_self_refreshing_broker(api_key, **kwargs)
                self._client = Client(broker, labels_enabled)
                self._manager = SelfRefreshingSplitManager(broker)
コード例 #12
0
    def __init__(self, **kwargs):
        super(LocalhostSplitFactory, self).__init__()

        if 'split_definition_file_name' in kwargs:
            broker = get_self_refreshing_broker(
                'localhost',
                split_definition_file_name=kwargs['split_definition_file_name']
            )
        else:
            broker = get_self_refreshing_broker('localhost')

        self._client = Client(broker)
        self._manager = LocalhostSplitManager(broker.get_split_fetcher())
コード例 #13
0
class TestInputSanitizationGetTreatmentS(TestCase):
    def setUp(self):
        self.some_config = mock.MagicMock()
        self.some_api_key = mock.MagicMock()
        self.redis = get_redis({'redisPrefix': 'test'})
        self.client = Client(RedisBroker(self.redis, self.some_config))

        input_validator._LOGGER.error = mock.MagicMock()
        self.logger_error = input_validator._LOGGER.error
        input_validator._LOGGER.warning = mock.MagicMock()
        self.logger_warning = input_validator._LOGGER.warning

    def test_get_treatments_with_null_features(self):
        self.assertEqual(None, self.client.get_treatments("some_key", None))
        self.logger_error \
            .assert_called_once_with("get_treatments: features cannot be None.")

    def test_get_treatments_with_bool_type_of_features(self):
        self.assertEqual(None, self.client.get_treatments("some_key", True))
        self.logger_error \
            .assert_called_once_with("get_treatments: features must be a list.")

    def test_get_treatments_with_string_type_of_features(self):
        self.assertEqual(None,
                         self.client.get_treatments("some_key", "some_string"))
        self.logger_error \
            .assert_called_once_with("get_treatments: features must be a list.")

    def test_get_treatments_with_empty_features(self):
        self.assertEqual({}, self.client.get_treatments("some_key", []))
        self.logger_warning \
            .assert_called_once_with("get_treatments: features is an empty "
                                     "list or has None values.")

    def test_get_treatments_with_none_features(self):
        self.assertEqual({},
                         self.client.get_treatments("some_key", [None, None]))
        self.logger_warning \
            .assert_called_once_with("get_treatments: features is an empty "
                                     "list or has None values.")

    def test_get_treatments_with_invalid_type_of_features(self):
        self.assertEqual({}, self.client.get_treatments("some_key", [True]))
        self.logger_error \
            .assert_called_once_with("get_treatments: feature_name has to be of type string.")
コード例 #14
0
    def setUp(self):
        '''
        '''
        redis = get_redis({})
        segment_cache = RedisSegmentCache(redis)
        split_parser = RedisSplitParser(segment_cache)
        self._client = Client(RedisBroker(redis))

        self._splitObjects = {}

        raw_split = {
            'name':
            'test1',
            'algo':
            1,
            'killed':
            False,
            'status':
            'ACTIVE',
            'defaultTreatment':
            'default',
            'seed':
            -1222652054,
            'orgId':
            None,
            'environment':
            None,
            'trafficTypeId':
            None,
            'trafficTypeName':
            None,
            'changeNumber':
            1,
            'conditions': [{
                'conditionType': 'WHITELIST',
                'matcherGroup': {
                    'combiner':
                    'AND',
                    'matchers': [{
                        'matcherType': 'ALL_KEYS',
                        'negate': False,
                        'userDefinedSegmentMatcherData': None,
                        'whitelistMatcherData': None
                    }]
                },
                'partitions': [{
                    'treatment': 'on',
                    'size': 100
                }],
                'label': 'in segment all'
            }]
        }
        self._splitObjects['whitelist'] = split_parser.parse(raw_split, True)

        raw_split['name'] = 'test2'
        raw_split['conditions'][0]['conditionType'] = 'ROLLOUT'
        self._splitObjects['rollout1'] = split_parser.parse(raw_split, True)

        raw_split['name'] = 'test3'
        raw_split['trafficAllocation'] = 1
        raw_split['trafficAllocationSeed'] = -1
        self._splitObjects['rollout2'] = split_parser.parse(raw_split, True)

        raw_split['name'] = 'test4'
        raw_split['trafficAllocation'] = None  #must be mapped as 100
        raw_split['trafficAllocationSeed'] = -1
        self._splitObjects['rollout3'] = split_parser.parse(raw_split, True)
コード例 #15
0
class TestInputSanitizationGetTreatment(TestCase):
    def setUp(self):
        self.some_config = mock.MagicMock()
        self.some_api_key = mock.MagicMock()
        self.redis = get_redis({'redisPrefix': 'test'})
        self.client = Client(RedisBroker(self.redis, self.some_config))
        self.client._broker.fetch_feature = mock.MagicMock(
            return_value=Split("some_feature", 0, False, "default_treatment",
                               "user", "ACTIVE", 123))

        self.client._build_impression = mock.MagicMock()

        input_validator._LOGGER.error = mock.MagicMock()
        self.logger_error = input_validator._LOGGER.error
        input_validator._LOGGER.warning = mock.MagicMock()
        self.logger_warning = input_validator._LOGGER.warning

    def test_get_treatment_with_null_key(self):
        self.assertEqual(CONTROL,
                         self.client.get_treatment(None, "some_feature"))
        self.logger_error \
            .assert_called_once_with("get_treatment: key cannot be None.")
        self.client._build_impression.assert_called_once_with(
            None, "some_feature", CONTROL, Label.EXCEPTION, 0, None, mock.ANY)

    def test_get_treatment_with_number_key(self):
        self.assertEqual("default_treatment",
                         self.client.get_treatment(12345, "some_feature"))
        self.logger_warning \
            .assert_called_once_with("get_treatment: key 12345 is not of type string, converting.")

    def test_get_treatment_with_bool_key(self):
        self.assertEqual(CONTROL,
                         self.client.get_treatment(True, "some_feature"))
        self.logger_error \
            .assert_called_once_with("get_treatment: key has to be of type string "
                                     "or object Key.")
        self.client._build_impression.assert_called_once_with(
            None, "some_feature", CONTROL, Label.EXCEPTION, 0, None, mock.ANY)

    def test_get_treatment_with_array_key(self):
        self.assertEqual(CONTROL, self.client.get_treatment([],
                                                            "some_feature"))
        self.logger_error \
            .assert_called_once_with("get_treatment: key has to be of type string "
                                     "or object Key.")
        self.client._build_impression.assert_called_once_with(
            None, "some_feature", CONTROL, Label.EXCEPTION, 0, None, mock.ANY)

    def test_get_treatment_with_null_feature_name(self):
        self.assertEqual(CONTROL, self.client.get_treatment("some_key", None))
        self.logger_error \
            .assert_called_once_with("get_treatment: feature_name cannot be None.")
        self.client._build_impression.assert_called_once_with(
            "some_key", None, CONTROL, Label.EXCEPTION, 0, None, mock.ANY)

    def test_get_treatment_with_numeric_feature_name(self):
        self.assertEqual(CONTROL, self.client.get_treatment("some_key", 12345))
        self.logger_error \
            .assert_called_once_with("get_treatment: feature_name has to be of type string.")
        self.client._build_impression.assert_called_once_with(
            "some_key", None, CONTROL, Label.EXCEPTION, 0, None, mock.ANY)

    def test_get_treatment_with_bool_feature_name(self):
        self.assertEqual(CONTROL, self.client.get_treatment("some_key", True))
        self.logger_error \
            .assert_called_once_with("get_treatment: feature_name has to be of type string.")
        self.client._build_impression.assert_called_once_with(
            "some_key", None, CONTROL, Label.EXCEPTION, 0, None, mock.ANY)

    def test_get_treatment_with_array_feature_name(self):
        self.assertEqual(CONTROL, self.client.get_treatment("some_key", []))
        self.logger_error \
            .assert_called_once_with("get_treatment: feature_name has to be of type string.")
        self.client._build_impression.assert_called_once_with(
            "some_key", None, CONTROL, Label.EXCEPTION, 0, None, mock.ANY)

    def test_get_treatment_with_valid_inputs(self):
        self.assertEqual("default_treatment",
                         self.client.get_treatment("some_key", "some_feature"))
        self.logger_error.assert_not_called()
        self.logger_warning.assert_not_called()

    def test_get_tratment_with_null_matching_key(self):
        self.assertEqual(
            CONTROL,
            self.client.get_treatment(Key(None, "bucketing_key"),
                                      "some_feature"))
        self.logger_error \
            .assert_called_once_with("get_treatment: Key should be an object with "
                                     "bucketingKey and matchingKey with valid string properties.")
        self.client._build_impression.assert_called_once_with(
            None, "some_feature", CONTROL, Label.EXCEPTION, 0, None, mock.ANY)

    def test_get_tratment_with_empty_matching_key(self):
        self.assertEqual(
            CONTROL,
            self.client.get_treatment(Key("", "bucketing_key"),
                                      "some_feature"))
        self.logger_error \
            .assert_called_once_with("get_treatment: matching_key must not be empty.")
        self.client._build_impression.assert_called_once_with(
            None, "some_feature", CONTROL, Label.EXCEPTION, 0, None, mock.ANY)

    def test_get_tratment_with_bool_matching_key(self):
        self.assertEqual(
            CONTROL,
            self.client.get_treatment(Key(True, "bucketing_key"),
                                      "some_feature"))
        self.logger_error \
            .assert_called_once_with("get_treatment: matching_key has to be of type string.")
        self.client._build_impression.assert_called_once_with(
            None, "some_feature", CONTROL, Label.EXCEPTION, 0, None, mock.ANY)

    def test_get_tratment_with_array_matching_key(self):
        self.assertEqual(
            CONTROL,
            self.client.get_treatment(Key([], "bucketing_key"),
                                      "some_feature"))
        self.logger_error \
            .assert_called_once_with("get_treatment: matching_key has to be of type string.")
        self.client._build_impression.assert_called_once_with(
            None, "some_feature", CONTROL, Label.EXCEPTION, 0, None, mock.ANY)

    def test_get_tratment_with_numeric_matching_key(self):
        self.assertEqual(
            "default_treatment",
            self.client.get_treatment(Key(12345, "bucketing_key"),
                                      "some_feature"))
        self.logger_warning \
            .assert_called_once_with("get_treatment: matching_key 12345 is not of type string, "
                                     "converting.")

    def test_get_tratment_with_null_bucketing_key(self):
        self.assertEqual(
            "default_treatment",
            self.client.get_treatment(Key("matching_key", None),
                                      "some_feature"))
        self.logger_warning \
            .assert_called_once_with("get_treatment: Key object should have bucketingKey set.")

    def test_get_tratment_with_bool_bucketing_key(self):
        self.assertEqual(
            CONTROL,
            self.client.get_treatment(Key("matching_key", True),
                                      "some_feature"))
        self.logger_error \
            .assert_called_once_with("get_treatment: bucketing_key has to be of type string.")
        self.client._build_impression.assert_called_once_with(
            None, "some_feature", CONTROL, Label.EXCEPTION, 0, None, mock.ANY)

    def test_get_tratment_with_array_bucketing_key(self):
        self.assertEqual(
            CONTROL,
            self.client.get_treatment(Key("matching_key", []), "some_feature"))
        self.logger_error \
            .assert_called_once_with("get_treatment: bucketing_key has to be of type string.")
        self.client._build_impression.assert_called_once_with(
            None, "some_feature", CONTROL, Label.EXCEPTION, 0, None, mock.ANY)

    def test_get_tratment_with_numeric_bucketing_key(self):
        self.assertEqual(
            "default_treatment",
            self.client.get_treatment(Key("matching_key", 12345),
                                      "some_feature"))
        self.logger_warning \
            .assert_called_once_with("get_treatment: bucketing_key 12345 is not of type string, "
                                     "converting.")
コード例 #16
0
class TrafficAllocationTests(TestCase):
    '''
    '''
    def setUp(self):
        '''
        '''
        redis = get_redis({})
        segment_cache = RedisSegmentCache(redis)
        split_parser = RedisSplitParser(segment_cache)
        self._client = Client(RedisBroker(redis))

        self._splitObjects = {}

        raw_split = {
            'name':
            'test1',
            'algo':
            1,
            'killed':
            False,
            'status':
            'ACTIVE',
            'defaultTreatment':
            'default',
            'seed':
            -1222652054,
            'orgId':
            None,
            'environment':
            None,
            'trafficTypeId':
            None,
            'trafficTypeName':
            None,
            'changeNumber':
            1,
            'conditions': [{
                'conditionType': 'WHITELIST',
                'matcherGroup': {
                    'combiner':
                    'AND',
                    'matchers': [{
                        'matcherType': 'ALL_KEYS',
                        'negate': False,
                        'userDefinedSegmentMatcherData': None,
                        'whitelistMatcherData': None
                    }]
                },
                'partitions': [{
                    'treatment': 'on',
                    'size': 100
                }],
                'label': 'in segment all'
            }]
        }
        self._splitObjects['whitelist'] = split_parser.parse(raw_split, True)

        raw_split['name'] = 'test2'
        raw_split['conditions'][0]['conditionType'] = 'ROLLOUT'
        self._splitObjects['rollout1'] = split_parser.parse(raw_split, True)

        raw_split['name'] = 'test3'
        raw_split['trafficAllocation'] = 1
        raw_split['trafficAllocationSeed'] = -1
        self._splitObjects['rollout2'] = split_parser.parse(raw_split, True)

        raw_split['name'] = 'test4'
        raw_split['trafficAllocation'] = None  #must be mapped as 100
        raw_split['trafficAllocationSeed'] = -1
        self._splitObjects['rollout3'] = split_parser.parse(raw_split, True)

    def testTrafficAllocation(self):
        '''
        '''
        treatment1, label1 = self._client._get_treatment_for_split(
            self._splitObjects['whitelist'], 'testKey', None)
        self.assertEqual(treatment1, 'on')

        # Make sure traffic allocation is set to 100 at construction time if a
        # value is not provided.
        self.assertEqual(self._splitObjects['whitelist'].traffic_allocation,
                         100)

        treatment2, label1 = self._client._get_treatment_for_split(
            self._splitObjects['rollout1'], 'testKey', None)
        self.assertEqual(treatment2, 'on')

        treatment3, label1 = self._client._get_treatment_for_split(
            self._splitObjects['rollout2'], 'testKey', None)
        self.assertEqual(treatment3, 'default')

        treatment4, label1 = self._client._get_treatment_for_split(
            self._splitObjects['rollout3'], 'testKey', None)
        self.assertEqual(treatment4, 'on')
コード例 #17
0
class TestInputSanitizationTrack(TestCase):
    def setUp(self):
        self.some_config = mock.MagicMock()
        self.some_api_key = mock.MagicMock()
        self.redis = get_redis({'redisPrefix': 'test'})
        self.client = Client(RedisBroker(self.redis, self.some_config))

        input_validator._LOGGER.error = mock.MagicMock()
        self.logger_error = input_validator._LOGGER.error
        input_validator._LOGGER.warning = mock.MagicMock()
        self.logger_warning = input_validator._LOGGER.warning

    def test_track_with_null_key(self):
        self.assertEqual(
            False, self.client.track(None, "traffic_type", "event_type", 1))
        self.logger_error \
            .assert_called_once_with("track: key cannot be None.")

    def test_track_with_numeric_key(self):
        self.assertEqual(
            True, self.client.track(12345, "traffic_type", "event_type", 1))
        self.logger_warning \
            .assert_called_once_with("track: key 12345 is not of type string,"
                                     " converting.")

    def test_track_with_bool_key(self):
        self.assertEqual(
            False, self.client.track(True, "traffic_type", "event_type", 1))
        self.logger_error \
            .assert_called_once_with("track: key has to be of type string.")

    def test_track_with_array_key(self):
        self.assertEqual(
            False, self.client.track([], "traffic_type", "event_type", 1))
        self.logger_error \
            .assert_called_once_with("track: key has to be of type string.")

    def test_track_with_null_traffic_type(self):
        self.assertEqual(False,
                         self.client.track("some_key", None, "event_type", 1))
        self.logger_error \
            .assert_called_once_with("track: traffic_type cannot be None.")

    def test_track_with_bool_traffic_type(self):
        self.assertEqual(False,
                         self.client.track("some_key", True, "event_type", 1))
        self.logger_error \
            .assert_called_once_with("track: traffic_type has to be of type string.")

    def test_track_with_array_traffic_type(self):
        self.assertEqual(False,
                         self.client.track("some_key", [], "event_type", 1))
        self.logger_error \
            .assert_called_once_with("track: traffic_type has to be of type string.")

    def test_track_with_numeric_traffic_type(self):
        self.assertEqual(False,
                         self.client.track("some_key", 12345, "event_type", 1))
        self.logger_error \
            .assert_called_once_with("track: traffic_type has to be of type string.")

    def test_track_with_empty_traffic_type(self):
        self.assertEqual(False,
                         self.client.track("some_key", "", "event_type", 1))
        self.logger_error \
            .assert_called_once_with("track: traffic_type must not be empty.")

    def test_track_with_null_event_type(self):
        self.assertEqual(
            False, self.client.track("some_key", "traffic_type", None, 1))
        self.logger_error \
            .assert_called_once_with("track: event_type cannot be None.")

    def test_track_with_bool_event_type(self):
        self.assertEqual(
            False, self.client.track("some_key", "traffic_type", True, 1))
        self.logger_error \
            .assert_called_once_with("track: event_type has to be of type string.")

    def test_track_with_array_event_type(self):
        self.assertEqual(False,
                         self.client.track("some_key", "traffic_type", [], 1))
        self.logger_error \
            .assert_called_once_with("track: event_type has to be of type string.")

    def test_track_with_numeric_event_type(self):
        self.assertEqual(
            False, self.client.track("some_key", "traffic_type", 12345, 1))
        self.logger_error \
            .assert_called_once_with("track: event_type has to be of type string.")

    def test_track_with_event_type_does_not_conform_reg_exp(self):
        self.assertEqual(
            False, self.client.track("some_key", "traffic_type", "@@", 1))
        self.logger_error \
            .assert_called_once_with("track: event_type must adhere to the regular "
                                     "expression [a-zA-Z0-9][-_\\.a-zA-Z0-9]{0,62}.")

    def test_track_with_null_value(self):
        self.assertEqual(
            True,
            self.client.track("some_key", "traffic_type", "event_type", None))
        self.logger_error.assert_not_called()
        self.logger_warning.assert_not_called()

    def test_track_with_string_value(self):
        self.assertEqual(
            False,
            self.client.track("some_key", "traffic_type", "event_type",
                              "test"))
        self.logger_error \
            .assert_called_once_with("track: value must be a number.")

    def test_track_with_bool_value(self):
        self.assertEqual(
            False,
            self.client.track("some_key", "traffic_type", "event_type", True))
        self.logger_error \
            .assert_called_once_with("track: value must be a number.")

    def test_track_with_array_value(self):
        self.assertEqual(
            False,
            self.client.track("some_key", "traffic_type", "event_type", []))
        self.logger_error \
            .assert_called_once_with("track: value must be a number.")

    def test_track_with_int_value(self):
        self.assertEqual(
            True, self.client.track("some_key", "traffic_type", "event_type",
                                    1))
        self.logger_error.assert_not_called()
        self.logger_warning.assert_not_called()

    def test_track_with_float_value(self):
        self.assertEqual(
            True,
            self.client.track("some_key", "traffic_type", "event_type", 1.3))
        self.logger_error.assert_not_called()
        self.logger_warning.assert_not_called()