|
3 | 3 |
|
4 | 4 | import json |
5 | 5 | import time |
| 6 | +import unittest.mock as mock |
| 7 | +import pytest |
6 | 8 |
|
7 | | -from splitio.client.util import get_metadata |
| 9 | +from splitio.client.util import get_metadata, SdkMetadata, get_method_constant |
8 | 10 | from splitio.storage.redis import RedisEventsStorage, RedisImpressionsStorage, \ |
9 | | - RedisSegmentStorage, RedisSplitStorage |
| 11 | + RedisSegmentStorage, RedisSplitStorage, RedisTelemetryStorage |
| 12 | +from splitio.storage.adapters.redis import RedisAdapter, RedisAdapterException, build |
10 | 13 | from splitio.models.segments import Segment |
11 | 14 | from splitio.models.impressions import Impression |
12 | 15 | from splitio.models.events import Event, EventWrapper |
13 | | -from splitio.storage.adapters.redis import RedisAdapter, RedisAdapterException |
| 16 | +from splitio.models.telemetry import MethodExceptions, MethodLatencies, TelemetryConfig |
14 | 17 |
|
15 | 18 |
|
16 | 19 | class RedisSplitStorageTests(object): |
@@ -380,3 +383,97 @@ def _raise_exc(*_): |
380 | 383 | raise RedisAdapterException('something') |
381 | 384 | adapter.rpush.side_effect = _raise_exc |
382 | 385 | assert storage.put(events) is False |
| 386 | + |
| 387 | +class RedisTelemetryStorageTests(object): |
| 388 | + """Redis Telemetry storage test cases.""" |
| 389 | + |
| 390 | + def test_init(self, mocker): |
| 391 | + redis_telemetry = RedisTelemetryStorage(mocker.Mock(), mocker.Mock()) |
| 392 | + assert(redis_telemetry._redis_client is not None) |
| 393 | + assert(redis_telemetry._sdk_metadata is not None) |
| 394 | + assert(isinstance(redis_telemetry._method_latencies, MethodLatencies)) |
| 395 | + assert(isinstance(redis_telemetry._method_exceptions, MethodExceptions)) |
| 396 | + assert(isinstance(redis_telemetry._tel_config, TelemetryConfig)) |
| 397 | + assert(redis_telemetry.host_ip is not None) |
| 398 | + assert(redis_telemetry.host_name is not None) |
| 399 | + assert(redis_telemetry._make_pipe is not None) |
| 400 | + |
| 401 | + @mock.patch('splitio.models.telemetry.TelemetryConfig.record_config') |
| 402 | + def test_record_config(self, mocker): |
| 403 | + redis_telemetry = RedisTelemetryStorage(mocker.Mock(), mocker.Mock()) |
| 404 | + redis_telemetry.record_config(mocker.Mock(), mocker.Mock()) |
| 405 | + assert(mocker.called) |
| 406 | + |
| 407 | + @mock.patch('splitio.storage.adapters.redis.RedisAdapter.hset') |
| 408 | + def test_push_config_stats(self, mocker): |
| 409 | + adapter = build({}) |
| 410 | + redis_telemetry = RedisTelemetryStorage(adapter, mocker.Mock()) |
| 411 | + redis_telemetry.push_config_stats() |
| 412 | + assert(mocker.called) |
| 413 | + |
| 414 | + def test_format_config_stats(self, mocker): |
| 415 | + redis_telemetry = RedisTelemetryStorage(mocker.Mock(), mocker.Mock()) |
| 416 | + json_value = redis_telemetry._format_config_stats() |
| 417 | + stats = redis_telemetry._tel_config.get_stats() |
| 418 | + assert(json_value == json.dumps({ |
| 419 | + 'aF': stats['aF'], |
| 420 | + 'rF': stats['rF'], |
| 421 | + 'sT': stats['sT'], |
| 422 | + 'oM': stats['oM'] |
| 423 | + })) |
| 424 | + |
| 425 | + def test_record_active_and_redundant_factories(self, mocker): |
| 426 | + redis_telemetry = RedisTelemetryStorage(mocker.Mock(), mocker.Mock()) |
| 427 | + active_factory_count = 1 |
| 428 | + redundant_factory_count = 2 |
| 429 | + redis_telemetry.record_active_and_redundant_factories(1, 2) |
| 430 | + assert (redis_telemetry._tel_config._active_factory_count == active_factory_count) |
| 431 | + assert (redis_telemetry._tel_config._redundant_factory_count == redundant_factory_count) |
| 432 | + |
| 433 | + def test_add_latency_to_pipe(self, mocker): |
| 434 | + def _mocked_hincrby(*args, **kwargs): |
| 435 | + assert(args[1] == RedisTelemetryStorage._TELEMETRY_LATENCIES_KEY) |
| 436 | + assert(args[2][-11:] == 'treatment/0') |
| 437 | + assert(args[3] == 1) |
| 438 | + |
| 439 | + adapter = build({}) |
| 440 | + metadata = SdkMetadata('python-1.1.1', 'hostname', 'ip') |
| 441 | + redis_telemetry = RedisTelemetryStorage(adapter, metadata) |
| 442 | + pipe = adapter._decorated.pipeline() |
| 443 | + with mock.patch('redis.client.Pipeline.hincrby', _mocked_hincrby): |
| 444 | + redis_telemetry.add_latency_to_pipe('treatment', 20, pipe) |
| 445 | + |
| 446 | + def test_record_exception(self, mocker): |
| 447 | + def _mocked_hincrby(*args, **kwargs): |
| 448 | + assert(args[1] == RedisTelemetryStorage._TELEMETRY_EXCEPTIONS_KEY) |
| 449 | + assert(args[2][-9:] == 'treatment') |
| 450 | + assert(args[3] == 1) |
| 451 | + |
| 452 | + adapter = build({}) |
| 453 | + metadata = SdkMetadata('python-1.1.1', 'hostname', 'ip') |
| 454 | + redis_telemetry = RedisTelemetryStorage(adapter, metadata) |
| 455 | + with mock.patch('redis.client.Pipeline.hincrby', _mocked_hincrby): |
| 456 | + with mock.patch('redis.client.Pipeline.execute') as mock_method: |
| 457 | + mock_method.return_value = [1] |
| 458 | + redis_telemetry.record_exception(get_method_constant('treatment')) |
| 459 | + |
| 460 | + def test_expire_latency_keys(self, mocker): |
| 461 | + redis_telemetry = RedisTelemetryStorage(mocker.Mock(), mocker.Mock()) |
| 462 | + def _mocked_method(*args, **kwargs): |
| 463 | + assert(args[1] == RedisTelemetryStorage._TELEMETRY_LATENCIES_KEY) |
| 464 | + assert(args[2] == RedisTelemetryStorage._TELEMETRY_KEY_DEFAULT_TTL) |
| 465 | + assert(args[3] == 1) |
| 466 | + assert(args[4] == 2) |
| 467 | + |
| 468 | + with mock.patch('splitio.storage.redis.RedisTelemetryStorage.expire_keys', _mocked_method): |
| 469 | + redis_telemetry.expire_latency_keys(1, 2) |
| 470 | + |
| 471 | + @mock.patch('redis.client.Redis.expire') |
| 472 | + def test_expire_keys(self, mocker): |
| 473 | + adapter = build({}) |
| 474 | + metadata = SdkMetadata('python-1.1.1', 'hostname', 'ip') |
| 475 | + redis_telemetry = RedisTelemetryStorage(adapter, metadata) |
| 476 | + redis_telemetry.expire_keys('key', 12, 1, 2) |
| 477 | + assert(not mocker.called) |
| 478 | + redis_telemetry.expire_keys('key', 12, 2, 2) |
| 479 | + assert(mocker.called) |
0 commit comments