|
8 | 8 |
|
9 | 9 | from splitio.client.util import get_metadata, SdkMetadata |
10 | 10 | from splitio.optional.loaders import asyncio |
11 | | -from splitio.storage.redis import RedisEventsStorage, RedisImpressionsStorage, \ |
| 11 | +from splitio.storage.redis import RedisEventsStorage, RedisImpressionsStorage, RedisImpressionsStorageAsync\ |
12 | 12 | RedisSegmentStorage, RedisSplitStorage, RedisSplitStorageAsync, RedisTelemetryStorage |
13 | 13 | from splitio.storage.adapters.redis import RedisAdapter, RedisAdapterException, build |
14 | 14 | from redis.asyncio.client import Redis as aioredis |
@@ -590,6 +590,167 @@ def test_add_impressions_to_pipe(self, mocker): |
590 | 590 | storage.add_impressions_to_pipe(impressions, adapter) |
591 | 591 | assert adapter.rpush.mock_calls == [mocker.call('SPLITIO.impressions', *to_validate)] |
592 | 592 |
|
| 593 | + def test_expire_key(self, mocker): |
| 594 | + adapter = mocker.Mock(spec=RedisAdapter) |
| 595 | + metadata = get_metadata({}) |
| 596 | + storage = RedisImpressionsStorage(adapter, metadata) |
| 597 | + |
| 598 | + self.key = None |
| 599 | + self.ttl = None |
| 600 | + def expire(key, ttl): |
| 601 | + self.key = key |
| 602 | + self.ttl = ttl |
| 603 | + adapter.expire = expire |
| 604 | + |
| 605 | + storage.expire_key(2, 2) |
| 606 | + assert self.key == 'SPLITIO.impressions' |
| 607 | + assert self.ttl == 3600 |
| 608 | + |
| 609 | + self.key = None |
| 610 | + storage.expire_key(2, 1) |
| 611 | + assert self.key == None |
| 612 | + |
| 613 | + |
| 614 | +class RedisImpressionsStorageAsyncTests(object): # pylint: disable=too-few-public-methods |
| 615 | + """Redis Impressions async storage test cases.""" |
| 616 | + |
| 617 | + def test_wrap_impressions(self, mocker): |
| 618 | + """Test wrap impressions.""" |
| 619 | + adapter = mocker.Mock(spec=RedisAdapterAsync) |
| 620 | + metadata = get_metadata({}) |
| 621 | + storage = RedisImpressionsStorageAsync(adapter, metadata) |
| 622 | + |
| 623 | + impressions = [ |
| 624 | + Impression('key1', 'feature1', 'on', 'some_label', 123456, 'buck1', 321654), |
| 625 | + Impression('key2', 'feature2', 'on', 'some_label', 123456, 'buck1', 321654), |
| 626 | + Impression('key3', 'feature2', 'on', 'some_label', 123456, 'buck1', 321654), |
| 627 | + Impression('key4', 'feature1', 'on', 'some_label', 123456, 'buck1', 321654) |
| 628 | + ] |
| 629 | + |
| 630 | + to_validate = [json.dumps({ |
| 631 | + 'm': { # METADATA PORTION |
| 632 | + 's': metadata.sdk_version, |
| 633 | + 'n': metadata.instance_name, |
| 634 | + 'i': metadata.instance_ip, |
| 635 | + }, |
| 636 | + 'i': { # IMPRESSION PORTION |
| 637 | + 'k': impression.matching_key, |
| 638 | + 'b': impression.bucketing_key, |
| 639 | + 'f': impression.feature_name, |
| 640 | + 't': impression.treatment, |
| 641 | + 'r': impression.label, |
| 642 | + 'c': impression.change_number, |
| 643 | + 'm': impression.time, |
| 644 | + } |
| 645 | + }) for impression in impressions] |
| 646 | + |
| 647 | + assert storage._wrap_impressions(impressions) == to_validate |
| 648 | + |
| 649 | + @pytest.mark.asyncio |
| 650 | + async def test_add_impressions(self, mocker): |
| 651 | + """Test that adding impressions to storage works.""" |
| 652 | + adapter = mocker.Mock(spec=RedisAdapterAsync) |
| 653 | + metadata = get_metadata({}) |
| 654 | + storage = RedisImpressionsStorageAsync(adapter, metadata) |
| 655 | + |
| 656 | + impressions = [ |
| 657 | + Impression('key1', 'feature1', 'on', 'some_label', 123456, 'buck1', 321654), |
| 658 | + Impression('key2', 'feature2', 'on', 'some_label', 123456, 'buck1', 321654), |
| 659 | + Impression('key3', 'feature2', 'on', 'some_label', 123456, 'buck1', 321654), |
| 660 | + Impression('key4', 'feature1', 'on', 'some_label', 123456, 'buck1', 321654) |
| 661 | + ] |
| 662 | + self.key = None |
| 663 | + self.imps = None |
| 664 | + async def rpush(key, *imps): |
| 665 | + self.key = key |
| 666 | + self.imps = imps |
| 667 | + |
| 668 | + adapter.rpush = rpush |
| 669 | + assert await storage.put(impressions) is True |
| 670 | + |
| 671 | + to_validate = [json.dumps({ |
| 672 | + 'm': { # METADATA PORTION |
| 673 | + 's': metadata.sdk_version, |
| 674 | + 'n': metadata.instance_name, |
| 675 | + 'i': metadata.instance_ip, |
| 676 | + }, |
| 677 | + 'i': { # IMPRESSION PORTION |
| 678 | + 'k': impression.matching_key, |
| 679 | + 'b': impression.bucketing_key, |
| 680 | + 'f': impression.feature_name, |
| 681 | + 't': impression.treatment, |
| 682 | + 'r': impression.label, |
| 683 | + 'c': impression.change_number, |
| 684 | + 'm': impression.time, |
| 685 | + } |
| 686 | + }) for impression in impressions] |
| 687 | + |
| 688 | + assert self.key == 'SPLITIO.impressions' |
| 689 | + assert self.imps == tuple(to_validate) |
| 690 | + |
| 691 | + # Assert that if an exception is thrown it's caught and False is returned |
| 692 | + adapter.reset_mock() |
| 693 | + |
| 694 | + async def rpush2(key, *imps): |
| 695 | + raise RedisAdapterException('something') |
| 696 | + adapter.rpush = rpush2 |
| 697 | + assert await storage.put(impressions) is False |
| 698 | + |
| 699 | + def test_add_impressions_to_pipe(self, mocker): |
| 700 | + """Test that adding impressions to storage works.""" |
| 701 | + adapter = mocker.Mock(spec=RedisAdapterAsync) |
| 702 | + metadata = get_metadata({}) |
| 703 | + storage = RedisImpressionsStorageAsync(adapter, metadata) |
| 704 | + |
| 705 | + impressions = [ |
| 706 | + Impression('key1', 'feature1', 'on', 'some_label', 123456, 'buck1', 321654), |
| 707 | + Impression('key2', 'feature2', 'on', 'some_label', 123456, 'buck1', 321654), |
| 708 | + Impression('key3', 'feature2', 'on', 'some_label', 123456, 'buck1', 321654), |
| 709 | + Impression('key4', 'feature1', 'on', 'some_label', 123456, 'buck1', 321654) |
| 710 | + ] |
| 711 | + |
| 712 | + to_validate = [json.dumps({ |
| 713 | + 'm': { # METADATA PORTION |
| 714 | + 's': metadata.sdk_version, |
| 715 | + 'n': metadata.instance_name, |
| 716 | + 'i': metadata.instance_ip, |
| 717 | + }, |
| 718 | + 'i': { # IMPRESSION PORTION |
| 719 | + 'k': impression.matching_key, |
| 720 | + 'b': impression.bucketing_key, |
| 721 | + 'f': impression.feature_name, |
| 722 | + 't': impression.treatment, |
| 723 | + 'r': impression.label, |
| 724 | + 'c': impression.change_number, |
| 725 | + 'm': impression.time, |
| 726 | + } |
| 727 | + }) for impression in impressions] |
| 728 | + |
| 729 | + storage.add_impressions_to_pipe(impressions, adapter) |
| 730 | + assert adapter.rpush.mock_calls == [mocker.call('SPLITIO.impressions', *to_validate)] |
| 731 | + |
| 732 | + @pytest.mark.asyncio |
| 733 | + async def test_expire_key(self, mocker): |
| 734 | + adapter = mocker.Mock(spec=RedisAdapterAsync) |
| 735 | + metadata = get_metadata({}) |
| 736 | + storage = RedisImpressionsStorageAsync(adapter, metadata) |
| 737 | + |
| 738 | + self.key = None |
| 739 | + self.ttl = None |
| 740 | + async def expire(key, ttl): |
| 741 | + self.key = key |
| 742 | + self.ttl = ttl |
| 743 | + adapter.expire = expire |
| 744 | + |
| 745 | + await storage.expire_key(2, 2) |
| 746 | + assert self.key == 'SPLITIO.impressions' |
| 747 | + assert self.ttl == 3600 |
| 748 | + |
| 749 | + self.key = None |
| 750 | + await storage.expire_key(2, 1) |
| 751 | + assert self.key == None |
| 752 | + |
| 753 | + |
593 | 754 |
|
594 | 755 | class RedisEventsStorageTests(object): # pylint: disable=too-few-public-methods |
595 | 756 | """Redis Impression storage test cases.""" |
|
0 commit comments