Skip to content

Commit b9cd98f

Browse files
authored
Merge pull request #378 from splitio/iff-e2e-tests
Added e2e tests
2 parents 97e636b + 8569369 commit b9cd98f

File tree

7 files changed

+121
-32
lines changed

7 files changed

+121
-32
lines changed

splitio/push/parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ def default_treatment(self):
419419
def __str__(self):
420420
"""Return string representation."""
421421
return "SplitKill - changeNumber=%d, name=%s, defaultTreatment=%s" % \
422-
(self.change_number, self.feature_flag, self.default_treatment)
422+
(self.change_number, self.feature_flag_name, self.default_treatment)
423423

424424

425425
class SegmentChangeUpdate(BaseUpdate):

splitio/push/splitworker.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from enum import Enum
99

1010
from splitio.models.splits import from_raw
11+
from splitio.push.parser import UpdateType
1112

1213
_LOGGER = logging.getLogger(__name__)
1314

@@ -63,16 +64,17 @@ def _run(self):
6364
continue
6465
_LOGGER.debug('Processing feature flag update %d', event.change_number)
6566
try:
66-
if event.compression is not None and event.previous_change_number == self._feature_flag_storage.get_change_number():
67-
try:
68-
self._feature_flag_storage.put(from_raw(json.loads(self._get_feature_flag_definition(event))))
69-
self._feature_flag_storage.set_change_number(event.change_number)
70-
continue
71-
except Exception as e:
72-
_LOGGER.error('Exception raised in updating feature flag')
73-
_LOGGER.debug(str(e))
74-
_LOGGER.debug('Exception information: ', exc_info=True)
75-
pass
67+
if event.update_type == UpdateType.SPLIT_UPDATE:
68+
if event.compression is not None and event.previous_change_number == self._feature_flag_storage.get_change_number():
69+
try:
70+
self._feature_flag_storage.put(from_raw(json.loads(self._get_feature_flag_definition(event))))
71+
self._feature_flag_storage.set_change_number(event.change_number)
72+
continue
73+
except Exception as e:
74+
_LOGGER.error('Exception raised in updating feature flag')
75+
_LOGGER.debug(str(e))
76+
_LOGGER.debug('Exception information: ', exc_info=True)
77+
pass
7678
self._handler(event.change_number)
7779
except Exception as e: # pylint: disable=broad-except
7880
_LOGGER.error('Exception raised in feature flag synchronization')

tests/client/test_localhost.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def test_make_whitelist_condition(self):
7272
def test_parse_legacy_file(self):
7373
"""Test that aprsing a legacy file works."""
7474
filename = os.path.join(os.path.dirname(__file__), 'files', 'file1.split')
75-
splits = LocalSplitSynchronizer._read_splits_from_legacy_file(filename)
75+
splits = LocalSplitSynchronizer._read_feature_flags_from_legacy_file(filename)
7676
assert len(splits) == 2
7777
for split in splits.values():
7878
assert isinstance(split, Split)
@@ -84,7 +84,7 @@ def test_parse_legacy_file(self):
8484
def test_parse_yaml_file(self):
8585
"""Test that parsing a yaml file works."""
8686
filename = os.path.join(os.path.dirname(__file__), 'files', 'file2.yaml')
87-
splits = LocalSplitSynchronizer._read_splits_from_yaml_file(filename)
87+
splits = LocalSplitSynchronizer._read_feature_flags_from_yaml_file(filename)
8888
assert len(splits) == 4
8989
for split in splits.values():
9090
assert isinstance(split, Split)
@@ -116,44 +116,44 @@ def test_update_splits(self, mocker):
116116
parse_legacy.reset_mock()
117117
parse_yaml.reset_mock()
118118
sync = LocalSplitSynchronizer('something', storage_mock)
119-
sync._read_splits_from_legacy_file = parse_legacy
120-
sync._read_splits_from_yaml_file = parse_yaml
119+
sync._read_feature_flags_from_legacy_file = parse_legacy
120+
sync._read_feature_flags_from_yaml_file = parse_yaml
121121
sync.synchronize_splits()
122122
assert parse_legacy.mock_calls == [mocker.call('something')]
123123
assert parse_yaml.mock_calls == []
124124

125125
parse_legacy.reset_mock()
126126
parse_yaml.reset_mock()
127127
sync = LocalSplitSynchronizer('something.yaml', storage_mock)
128-
sync._read_splits_from_legacy_file = parse_legacy
129-
sync._read_splits_from_yaml_file = parse_yaml
128+
sync._read_feature_flags_from_legacy_file = parse_legacy
129+
sync._read_feature_flags_from_yaml_file = parse_yaml
130130
sync.synchronize_splits()
131131
assert parse_legacy.mock_calls == []
132132
assert parse_yaml.mock_calls == [mocker.call('something.yaml')]
133133

134134
parse_legacy.reset_mock()
135135
parse_yaml.reset_mock()
136136
sync = LocalSplitSynchronizer('something.yml', storage_mock)
137-
sync._read_splits_from_legacy_file = parse_legacy
138-
sync._read_splits_from_yaml_file = parse_yaml
137+
sync._read_feature_flags_from_legacy_file = parse_legacy
138+
sync._read_feature_flags_from_yaml_file = parse_yaml
139139
sync.synchronize_splits()
140140
assert parse_legacy.mock_calls == []
141141
assert parse_yaml.mock_calls == [mocker.call('something.yml')]
142142

143143
parse_legacy.reset_mock()
144144
parse_yaml.reset_mock()
145145
sync = LocalSplitSynchronizer('something.YAML', storage_mock)
146-
sync._read_splits_from_legacy_file = parse_legacy
147-
sync._read_splits_from_yaml_file = parse_yaml
146+
sync._read_feature_flags_from_legacy_file = parse_legacy
147+
sync._read_feature_flags_from_yaml_file = parse_yaml
148148
sync.synchronize_splits()
149149
assert parse_legacy.mock_calls == []
150150
assert parse_yaml.mock_calls == [mocker.call('something.YAML')]
151151

152152
parse_legacy.reset_mock()
153153
parse_yaml.reset_mock()
154154
sync = LocalSplitSynchronizer('yaml', storage_mock)
155-
sync._read_splits_from_legacy_file = parse_legacy
156-
sync._read_splits_from_yaml_file = parse_yaml
155+
sync._read_feature_flags_from_legacy_file = parse_legacy
156+
sync._read_feature_flags_from_yaml_file = parse_yaml
157157
sync.synchronize_splits()
158158
assert parse_legacy.mock_calls == [mocker.call('yaml')]
159159
assert parse_yaml.mock_calls == []

tests/integration/test_client_e2e.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -965,7 +965,7 @@ def test_localhost_json_e2e(self):
965965

966966
# Tests 1
967967
self.factory._storages['splits'].remove('SPLIT_1')
968-
self.factory._sync_manager._synchronizer._split_synchronizers._split_sync._split_storage.set_change_number(-1)
968+
self.factory._sync_manager._synchronizer._split_synchronizers._feature_flag_sync._feature_flag_storage.set_change_number(-1)
969969
self._update_temp_file(splits_json['splitChange1_1'])
970970
self._synchronize_now()
971971

@@ -989,7 +989,7 @@ def test_localhost_json_e2e(self):
989989

990990
# Tests 3
991991
self.factory._storages['splits'].remove('SPLIT_1')
992-
self.factory._sync_manager._synchronizer._split_synchronizers._split_sync._split_storage.set_change_number(-1)
992+
self.factory._sync_manager._synchronizer._split_synchronizers._feature_flag_sync._feature_flag_storage.set_change_number(-1)
993993
self._update_temp_file(splits_json['splitChange3_1'])
994994
self._synchronize_now()
995995

@@ -1004,7 +1004,7 @@ def test_localhost_json_e2e(self):
10041004

10051005
# Tests 4
10061006
self.factory._storages['splits'].remove('SPLIT_2')
1007-
self.factory._sync_manager._synchronizer._split_synchronizers._split_sync._split_storage.set_change_number(-1)
1007+
self.factory._sync_manager._synchronizer._split_synchronizers._feature_flag_sync._feature_flag_storage.set_change_number(-1)
10081008
self._update_temp_file(splits_json['splitChange4_1'])
10091009
self._synchronize_now()
10101010

@@ -1029,7 +1029,7 @@ def test_localhost_json_e2e(self):
10291029
# Tests 5
10301030
self.factory._storages['splits'].remove('SPLIT_1')
10311031
self.factory._storages['splits'].remove('SPLIT_2')
1032-
self.factory._sync_manager._synchronizer._split_synchronizers._split_sync._split_storage.set_change_number(-1)
1032+
self.factory._sync_manager._synchronizer._split_synchronizers._feature_flag_sync._feature_flag_storage.set_change_number(-1)
10331033
self._update_temp_file(splits_json['splitChange5_1'])
10341034
self._synchronize_now()
10351035

@@ -1044,7 +1044,7 @@ def test_localhost_json_e2e(self):
10441044

10451045
# Tests 6
10461046
self.factory._storages['splits'].remove('SPLIT_2')
1047-
self.factory._sync_manager._synchronizer._split_synchronizers._split_sync._split_storage.set_change_number(-1)
1047+
self.factory._sync_manager._synchronizer._split_synchronizers._feature_flag_sync._feature_flag_storage.set_change_number(-1)
10481048
self._update_temp_file(splits_json['splitChange6_1'])
10491049
self._synchronize_now()
10501050

@@ -1073,8 +1073,8 @@ def _update_temp_file(self, json_body):
10731073

10741074
def _synchronize_now(self):
10751075
filename = os.path.join(os.path.dirname(__file__), 'files', 'split_changes_temp.json')
1076-
self.factory._sync_manager._synchronizer._split_synchronizers._split_sync._filename = filename
1077-
self.factory._sync_manager._synchronizer._split_synchronizers._split_sync.synchronize_splits()
1076+
self.factory._sync_manager._synchronizer._split_synchronizers._feature_flag_sync._filename = filename
1077+
self.factory._sync_manager._synchronizer._split_synchronizers._feature_flag_sync.synchronize_splits()
10781078

10791079
def test_incorrect_file_e2e(self):
10801080
"""Test initialize factory with a incorrect file name."""

tests/integration/test_streaming_e2e.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import threading
55
import time
66
import json
7+
import base64
8+
import pytest
9+
710
from queue import Queue
811
from splitio.client.factory import get_factory
912
from tests.helpers.mockserver import SSEMockServer, SplitMockServer
@@ -106,6 +109,21 @@ def test_happiness(self):
106109
assert factory.client().get_treatment('pindon', 'split2') == 'off'
107110
assert factory.client().get_treatment('maldo', 'split2') == 'on'
108111

112+
# test if changeNumber is missing
113+
# split_changes = make_split_fast_change_event(4)
114+
# data = json.loads(split_changes['data'])
115+
# inner_data = json.loads(data['data'])
116+
# inner_data['changeNumber'] = None
117+
# data['data'] = json.dumps(inner_data)
118+
# split_changes['data'] = json.dumps(data)
119+
# sse_server.publish(split_changes)
120+
# time.sleep(1)
121+
# assert factory.client().get_treatment('maldo', 'split1') == 'off'
122+
123+
sse_server.publish(make_split_fast_change_event(4))
124+
time.sleep(1)
125+
assert factory.client().get_treatment('maldo', 'split1') == 'on'
126+
109127
# Validate the SSE request
110128
sse_request = sse_requests.get()
111129
assert sse_request.method == 'GET'
@@ -1233,6 +1251,32 @@ def make_split_change_event(change_number):
12331251
})
12341252
}
12351253

1254+
def make_split_fast_change_event(change_number):
1255+
"""Make a split change event."""
1256+
json1 = make_simple_split('split1', 1, True, False, 'off', 'user', True)
1257+
str1 = json.dumps(json1)
1258+
byt1 = bytes(str1, encoding='utf-8')
1259+
compressed = base64.b64encode(byt1)
1260+
final = compressed.decode('utf-8')
1261+
1262+
return {
1263+
'event': 'message',
1264+
'data': json.dumps({
1265+
'id':'TVUsxaabHs:0:0',
1266+
'clientId':'pri:MzM0ODI1MTkxMw==',
1267+
'timestamp': change_number-1,
1268+
'encoding':'json',
1269+
'channel':'MTYyMTcxOTQ4Mw==_MjA4MzczNDU1Mg==_splits',
1270+
'data': json.dumps({
1271+
'type': 'SPLIT_UPDATE',
1272+
'changeNumber': change_number,
1273+
'pcn': 3,
1274+
'c': 0,
1275+
'd': final
1276+
})
1277+
})
1278+
}
1279+
12361280
def make_split_kill_event(name, default_treatment, change_number):
12371281
"""Make a split change event."""
12381282
return {

tests/push/test_manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ def test_auth_apiexception(self, mocker):
137137
def test_split_change(self, mocker):
138138
"""Test update-type messages are properly forwarded to the processor."""
139139
sse_event = SSEEvent('1', EventType.MESSAGE, '', '{}')
140-
update_message = SplitChangeUpdate('chan', 123, 456)
140+
update_message = SplitChangeUpdate('chan', 123, 456, None, None, None)
141141
parse_event_mock = mocker.Mock(spec=parse_incoming_event)
142142
parse_event_mock.return_value = update_message
143143
mocker.patch('splitio.push.manager.parse_incoming_event', new=parse_event_mock)

tests/push/test_split_worker.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,47 @@ def put(feature_flag):
118118
self._feature_flag = None
119119
q.put(SplitChangeUpdate('some', 'SPLIT_UPDATE', 123456790, 2345, 'H4sIAAkVZWQC/8WST0+DQBDFv0qzZ0ig/BF6a2xjGismUk2MaZopzOKmy9Isy0EbvrtDwbY2Xo233Tdv5se85cCMBs5FtvrYYwIlsglratTMYiKns+chcAgc24UwsF0Xczt2cm5z8Jw8DmPH9wPyqr5zKyTITb2XwpA4TJ5KWWVgRKXYxHWcX/QUkVi264W+68bjaGyxupdCJ4i9KPI9UgyYpibI9Ha1eJnT/J2QsnNxkDVaLEcOjTQrjWBKVIasFefky95BFZg05Zb2mrhh5I9vgsiL44BAIIuKTeiQVYqLotHHLyLOoT1quRjub4fztQuLxj89LpePzytClGCyd9R3umr21ErOcitUh2PTZHY29HN2+JGixMxUujNfvMB3+u2pY1AXySad3z3Mk46msACDp8W7jhly4uUpFt3qD33vDAx0gLpXkx+P1GusbdcE24M2F4uaywwVEWvxSa1Oa13Vjvn2RXradm0xCVuUVBJqNCBGV0DrX4OcLpeb+/lreh3jH8Uw/JQj3UhkxPgCCurdEnADAAA=', 1))
120120
time.sleep(0.1)
121-
assert self._feature_flag.name == 'bilal_split'
121+
assert self._feature_flag.name == 'bilal_split'
122+
123+
def test_edge_cases(self, mocker):
124+
q = queue.Queue()
125+
split_worker = SplitWorker(handler_sync, q, mocker.Mock())
126+
global change_number_received
127+
split_worker.start()
128+
129+
def get_change_number():
130+
return 2345
131+
132+
def put(feature_flag):
133+
self._feature_flag = feature_flag
134+
135+
split_worker._feature_flag_storage.get_change_number = get_change_number
136+
split_worker._feature_flag_storage.put = put
137+
138+
# should Not call the handler
139+
self._feature_flag = None
140+
change_number_received = 0
141+
q.put(SplitChangeUpdate('some', 'SPLIT_UPDATE', 123456, 2345, "/2X9I7+N8R/FcPmUd76zjH7X/w4AAP//90glTw==", 2))
142+
time.sleep(0.1)
143+
assert self._feature_flag == None
144+
145+
# should Not call the handler
146+
self._feature_flag = None
147+
change_number_received = 0
148+
q.put(SplitChangeUpdate('some', 'SPLIT_UPDATE', 123456, 2345, "/2X9I7+N8R/FcPmUd76zjH7X/w4AAP//90glTw==", 4))
149+
time.sleep(0.1)
150+
assert self._feature_flag == None
151+
152+
# should Not call the handler
153+
self._feature_flag = None
154+
change_number_received = 0
155+
q.put(SplitChangeUpdate('some', 'SPLIT_UPDATE', 123456, None, 'eJzEUtFq20AQ/JUwz2c4WZZr3ZupTQh1FKjcQinGrKU95cjpZE6nh9To34ssJ3FNX0sfd3Zm53b2TgietDbF9vXIGdUMha5lDwFTQiGOmTQlchLRPJlEEZeTVJZ6oimWZTpP5WyWQMCNyoOxZPft0ZoA8TZ5aW1TUDCNg4qk/AueM5dQkyiez6IonS6mAu0IzWWSxovFLBZoA4WuhcLy8/bh+xoCL8bagaXJtixQsqbOhq1nCjW7AIVGawgUz+Qqzrr6wB4qmi9m00/JIk7TZCpAtmqgpgJF47SpOn9+UQt16s9YaS71z9NHOYQFha9Pm83Tty0EagrFM/t733RHqIFZH4wb7LDMVh+Ecc4Lv+ZsuQiNH8hXF3hLv39XXNCHbJ+v7x/X2eDmuKLA74sPihVr47jMuRpWfxy1Kwo0GLQjmv1xpBFD3+96gSP5cLVouM7QQaA1vxhK9uKmd853bEZS9jsBSwe2UDDu7mJxd2Mo/muQy81m/2X9I7+N8R/FcPmUd76zjH7X/w4AAP//90glTw==', 2))
156+
time.sleep(0.1)
157+
assert self._feature_flag == None
158+
159+
# should Not call the handler
160+
self._feature_flag = None
161+
change_number_received = 0
162+
q.put(SplitChangeUpdate('some', 'SPLIT_UPDATE', 123456, 2345, None, 1))
163+
time.sleep(0.1)
164+
assert self._feature_flag == None

0 commit comments

Comments
 (0)