blob: 756a0d042abc3c7d9ad49ba6063a5d7eff62d393 [file] [log] [blame]
Tommy Carpenter5ad8f032019-05-30 14:33:21 -04001# ==================================================================================
2# Copyright (c) 2019 Nokia
3# Copyright (c) 2018-2019 AT&T Intellectual Property.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16# ==================================================================================
Tommy Carpenter40caa312019-09-12 16:24:10 -040017
Tommy Carpenter6b699102019-10-17 13:35:59 -040018import time
Tommy Carpenter5ad8f032019-05-30 14:33:21 -040019from rmr.rmr_mocks import rmr_mocks
Tommy Carpenter8bcc51a2019-10-21 16:07:31 -040020from a1 import a1rmr
Tommy Carpenter5ad8f032019-05-30 14:33:21 -040021
Tommy Carpenter40caa312019-09-12 16:24:10 -040022
23ADM_CTRL = "admission_control_policy"
Tommy Carpenter30a7bdc2019-09-23 09:48:23 -040024ADM_CTRL_POLICIES = "/a1-p/policytypes/20000/policies"
25ADM_CTRL_INSTANCE = ADM_CTRL_POLICIES + "/" + ADM_CTRL
Tommy Carpenter40caa312019-09-12 16:24:10 -040026ADM_CTRL_INSTANCE_STATUS = ADM_CTRL_INSTANCE + "/status"
Tommy Carpenter91ae8892019-09-18 10:45:50 -040027ADM_CTRL_TYPE = "/a1-p/policytypes/20000"
28TEST_TYPE = "/a1-p/policytypes/20001"
Tommy Carpenter40caa312019-09-12 16:24:10 -040029
30
Tommy Carpenter8bcc51a2019-10-21 16:07:31 -040031def _fake_dequeue():
Tommy Carpenter6b699102019-10-17 13:35:59 -040032 """for monkeypatching with a good status"""
Tommy Carpenter40caa312019-09-12 16:24:10 -040033 pay = b'{"policy_type_id": 20000, "policy_instance_id": "admission_control_policy", "handler_id": "test_receiver", "status": "OK"}'
Tommy Carpenter8bcc51a2019-10-21 16:07:31 -040034 fake_msg = {"payload": pay}
35 return [fake_msg]
Tommy Carpenter5ad8f032019-05-30 14:33:21 -040036
37
Tommy Carpenter8bcc51a2019-10-21 16:07:31 -040038def _fake_dequeue_none():
Tommy Carpenter6b699102019-10-17 13:35:59 -040039 """for monkeypatching with no waiting messages"""
Tommy Carpenterbfa46142019-09-26 11:14:16 -040040 return []
41
42
Tommy Carpenter8bcc51a2019-10-21 16:07:31 -040043def _fake_dequeue_deleted():
Tommy Carpenter6b699102019-10-17 13:35:59 -040044 """for monkeypatching with a DELETED status"""
Tommy Carpenter7cec82d2019-10-14 16:18:21 -040045 new_msgs = []
46
47 # insert some that don't exist to make sure nothing blows up
48 pay = b'{"policy_type_id": 20666, "policy_instance_id": "admission_control_policy", "handler_id": "test_receiver", "status": "DELETED"}'
49 fake_msg = {"payload": pay}
50 new_msgs.append(fake_msg)
51
52 pay = b'{"policy_type_id": 20000, "policy_instance_id": "darkness", "handler_id": "test_receiver", "status": "DELETED"}'
53 fake_msg = {"payload": pay}
54 new_msgs.append(fake_msg)
55
Tommy Carpenter8bcc51a2019-10-21 16:07:31 -040056 # insert a bad one with a malformed body to make sure we keep going
57 fake_msg = {"payload": "asdf"}
58 new_msgs.append(fake_msg)
59
Tommy Carpenterbfa46142019-09-26 11:14:16 -040060 pay = b'{"policy_type_id": 20000, "policy_instance_id": "admission_control_policy", "handler_id": "test_receiver", "status": "DELETED"}'
Tommy Carpenter7cec82d2019-10-14 16:18:21 -040061 fake_msg = {"payload": pay}
62 new_msgs.append(fake_msg)
63
64 return new_msgs
Tommy Carpenterbfa46142019-09-26 11:14:16 -040065
66
Tommy Carpenter5ad8f032019-05-30 14:33:21 -040067def _test_put_patch(monkeypatch):
Tommy Carpenter91ae8892019-09-18 10:45:50 -040068 rmr_mocks.patch_rmr(monkeypatch)
Tommy Carpenter6b699102019-10-17 13:35:59 -040069 # assert that rmr bad states don't cause problems
70 monkeypatch.setattr("rmr.rmr.rmr_send_msg", rmr_mocks.send_mock_generator(10))
Tommy Carpenter5ad8f032019-05-30 14:33:21 -040071
Tommy Carpentera0876ef2019-10-02 11:15:04 -040072 # we need this because free expects a real sbuf
73 # TODO: move this into rmr_mocks
74 def noop(_sbuf):
75 pass
76
77 monkeypatch.setattr("rmr.rmr.rmr_free_msg", noop)
78
Tommy Carpenter5ad8f032019-05-30 14:33:21 -040079 # we need to repatch alloc (already patched in patch_rmr) to fix the transactionid, alloc is called in send and recieve
Tommy Carpenter0b42dfc2019-10-24 10:13:54 -040080 def fake_alloc(_unused1, _unused2, _unused3, _unused4, _unused5):
Tommy Carpenter5ad8f032019-05-30 14:33:21 -040081 sbuf = rmr_mocks.Rmr_mbuf_t()
82 sbuf.contents.xaction = b"d49b53e478b711e9a1130242ac110002"
83 return sbuf
84
85 # we also need to repatch set, since in the send function, we alloc, then set a new transid
86 def fake_set_transactionid(sbuf):
87 sbuf.contents.xaction = b"d49b53e478b711e9a1130242ac110002"
88
89 # Note, we could have just patched summary, but this patches at a "lower level" so is a better test
90 monkeypatch.setattr("rmr.rmr.rmr_alloc_msg", fake_alloc)
91 monkeypatch.setattr("rmr.rmr.generate_and_set_transaction_id", fake_set_transactionid)
92
93
Tommy Carpenter6b699102019-10-17 13:35:59 -040094# Module level Hack
95
96
Tommy Carpenter6b699102019-10-17 13:35:59 -040097def setup_module():
98 """module level setup"""
Tommy Carpenter8bcc51a2019-10-21 16:07:31 -040099
100 def noop():
101 pass
102
103 # launch the thread with a fake init func and a patched rcv func; we will "repatch" later
Tommy Carpenter0b42dfc2019-10-24 10:13:54 -0400104 a1rmr.start_rmr_thread(init_func_override=noop, rcv_func_override=_fake_dequeue_none)
Tommy Carpenter6b699102019-10-17 13:35:59 -0400105
106
Tommy Carpenterfdf05042019-07-18 20:21:21 +0000107# Actual Tests
108
109
Tommy Carpenter8bcc51a2019-10-21 16:07:31 -0400110def test_workflow_nothing_there_yet(client):
Tommy Carpenter24514462019-07-16 11:25:52 -0400111 """ test policy put good"""
Tommy Carpenter91ae8892019-09-18 10:45:50 -0400112 # no type there yet
113 res = client.get(ADM_CTRL_TYPE)
114 assert res.status_code == 404
115
Tommy Carpenter30a7bdc2019-09-23 09:48:23 -0400116 # no types at all
117 res = client.get("/a1-p/policytypes")
118 assert res.status_code == 200
119 assert res.json == []
120
121 # instance 404 because type not there yet
122 res = client.get(ADM_CTRL_POLICIES)
123 assert res.status_code == 404
124
Tommy Carpenter7cec82d2019-10-14 16:18:21 -0400125
126def test_workflow(client, monkeypatch, adm_type_good, adm_instance_good):
Tommy Carpenter6b699102019-10-17 13:35:59 -0400127 """
128 test a full A1 workflow
129 """
Tommy Carpenter91ae8892019-09-18 10:45:50 -0400130 # put the type
131 res = client.put(ADM_CTRL_TYPE, json=adm_type_good)
132 assert res.status_code == 201
133
Tommy Carpenter7cec82d2019-10-14 16:18:21 -0400134 # cant replace types
135 res = client.put(ADM_CTRL_TYPE, json=adm_type_good)
136 assert res.status_code == 400
137
Tommy Carpenter30a7bdc2019-09-23 09:48:23 -0400138 # type there now
Tommy Carpenter91ae8892019-09-18 10:45:50 -0400139 res = client.get(ADM_CTRL_TYPE)
140 assert res.status_code == 200
141 assert res.json == adm_type_good
Tommy Carpenter30a7bdc2019-09-23 09:48:23 -0400142 res = client.get("/a1-p/policytypes")
143 assert res.status_code == 200
144 assert res.json == [20000]
145
146 # instance 200 but empty list
147 res = client.get(ADM_CTRL_POLICIES)
148 assert res.status_code == 200
149 assert res.json == []
Tommy Carpenter91ae8892019-09-18 10:45:50 -0400150
151 # no instance there yet
Tommy Carpenter40caa312019-09-12 16:24:10 -0400152 res = client.get(ADM_CTRL_INSTANCE)
153 assert res.status_code == 404
154 res = client.get(ADM_CTRL_INSTANCE_STATUS)
155 assert res.status_code == 404
156
157 # create a good instance
Tommy Carpenter24514462019-07-16 11:25:52 -0400158 _test_put_patch(monkeypatch)
Tommy Carpenter91ae8892019-09-18 10:45:50 -0400159 res = client.put(ADM_CTRL_INSTANCE, json=adm_instance_good)
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400160 assert res.status_code == 202
Tommy Carpenter40caa312019-09-12 16:24:10 -0400161
Tommy Carpenter7cec82d2019-10-14 16:18:21 -0400162 # replace is allowed on instances
163 res = client.put(ADM_CTRL_INSTANCE, json=adm_instance_good)
164 assert res.status_code == 202
165
Tommy Carpenter30a7bdc2019-09-23 09:48:23 -0400166 # instance 200 and in list
167 res = client.get(ADM_CTRL_POLICIES)
168 assert res.status_code == 200
169 assert res.json == [ADM_CTRL]
170
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400171 def get_instance_good(expected):
172 # get the instance
173 res = client.get(ADM_CTRL_INSTANCE)
174 assert res.status_code == 200
175 assert res.json == adm_instance_good
Tommy Carpenter40caa312019-09-12 16:24:10 -0400176
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400177 # get the instance status
178 res = client.get(ADM_CTRL_INSTANCE_STATUS)
179 assert res.status_code == 200
180 assert res.get_data(as_text=True) == expected
181
Tommy Carpenter6b699102019-10-17 13:35:59 -0400182 # try a status get but we didn't get any ACKs yet to test NOT IN EFFECT
183 time.sleep(1) # wait for the rmr thread
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400184 get_instance_good("NOT IN EFFECT")
185
186 # now pretend we did get a good ACK
Tommy Carpenter0b42dfc2019-10-24 10:13:54 -0400187 a1rmr.replace_rcv_func(_fake_dequeue)
Tommy Carpenter6b699102019-10-17 13:35:59 -0400188 time.sleep(1) # wait for the rmr thread
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400189 get_instance_good("IN EFFECT")
Tommy Carpenter40caa312019-09-12 16:24:10 -0400190
Tommy Carpenterf87c8572019-10-07 11:15:45 -0400191 # cant delete type until there are no instances
192 res = client.delete(ADM_CTRL_TYPE)
193 assert res.status_code == 400
194
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400195 # delete it
196 res = client.delete(ADM_CTRL_INSTANCE)
197 assert res.status_code == 202
198 res = client.delete(ADM_CTRL_INSTANCE) # should be able to do multiple deletes
199 assert res.status_code == 202
200
201 # status after a delete, but there are no messages yet, should still return
Tommy Carpenter6b699102019-10-17 13:35:59 -0400202 time.sleep(1) # wait for the rmr thread
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400203 get_instance_good("IN EFFECT")
204
205 # now pretend we deleted successfully
Tommy Carpenter0b42dfc2019-10-24 10:13:54 -0400206 a1rmr.replace_rcv_func(_fake_dequeue_deleted)
Tommy Carpenter6b699102019-10-17 13:35:59 -0400207 time.sleep(1) # wait for the rmr thread
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400208 # list still 200 but no instance
209 res = client.get(ADM_CTRL_POLICIES)
210 assert res.status_code == 200
211 assert res.json == []
Tommy Carpenter8bcc51a2019-10-21 16:07:31 -0400212 res = client.get(ADM_CTRL_INSTANCE_STATUS) # cant get status
213 assert res.status_code == 404
214 res = client.get(ADM_CTRL_INSTANCE) # cant get instance
215 assert res.status_code == 404
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400216
Tommy Carpenterf87c8572019-10-07 11:15:45 -0400217 # delete the type
218 res = client.delete(ADM_CTRL_TYPE)
219 assert res.status_code == 204
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400220
Tommy Carpenterf87c8572019-10-07 11:15:45 -0400221 # cant touch this
222 res = client.get(ADM_CTRL_TYPE)
223 assert res.status_code == 404
224 res = client.delete(ADM_CTRL_TYPE)
225 assert res.status_code == 404
Tommy Carpenter24514462019-07-16 11:25:52 -0400226
227
Tommy Carpenter91ae8892019-09-18 10:45:50 -0400228def test_bad_instances(client, monkeypatch, adm_type_good):
Tommy Carpenter5ad8f032019-05-30 14:33:21 -0400229 """
Tommy Carpenterf87c8572019-10-07 11:15:45 -0400230 test various failure modes
Tommy Carpenter5ad8f032019-05-30 14:33:21 -0400231 """
Tommy Carpenterf87c8572019-10-07 11:15:45 -0400232 # put the type (needed for some of the tests below)
Tommy Carpenter91ae8892019-09-18 10:45:50 -0400233 rmr_mocks.patch_rmr(monkeypatch)
Tommy Carpenterf87c8572019-10-07 11:15:45 -0400234 res = client.put(ADM_CTRL_TYPE, json=adm_type_good)
235 assert res.status_code == 201
Tommy Carpenter91ae8892019-09-18 10:45:50 -0400236
237 # bad body
Tommy Carpenter40caa312019-09-12 16:24:10 -0400238 res = client.put(ADM_CTRL_INSTANCE, json={"not": "expected"})
Tommy Carpenter24514462019-07-16 11:25:52 -0400239 assert res.status_code == 400
240
Tommy Carpenter5ad8f032019-05-30 14:33:21 -0400241 # bad media type
Tommy Carpenter40caa312019-09-12 16:24:10 -0400242 res = client.put(ADM_CTRL_INSTANCE, data="notajson")
Tommy Carpenter5ad8f032019-05-30 14:33:21 -0400243 assert res.status_code == 415
244
Tommy Carpenterf87c8572019-10-07 11:15:45 -0400245 # delete a non existent instance
246 res = client.delete(ADM_CTRL_INSTANCE + "DARKNESS")
247 assert res.status_code == 404
248
249 # get a non existent instance
Tommy Carpenter0b42dfc2019-10-24 10:13:54 -0400250 a1rmr.replace_rcv_func(_fake_dequeue)
Tommy Carpenter6b699102019-10-17 13:35:59 -0400251 time.sleep(1)
Tommy Carpenterf87c8572019-10-07 11:15:45 -0400252 res = client.get(ADM_CTRL_INSTANCE + "DARKNESS")
253 assert res.status_code == 404
254
255 # delete the type (as cleanup)
256 res = client.delete(ADM_CTRL_TYPE)
257 assert res.status_code == 204
258
259
Tommy Carpenter0b42dfc2019-10-24 10:13:54 -0400260def test_illegal_types(client, adm_type_good):
Tommy Carpenterf87c8572019-10-07 11:15:45 -0400261 """
262 Test illegal types
263 """
264 res = client.put("/a1-p/policytypes/19999", json=adm_type_good)
265 assert res.status_code == 400
266 res = client.put("/a1-p/policytypes/21024", json=adm_type_good)
267 assert res.status_code == 400
268
Tommy Carpenterfdf05042019-07-18 20:21:21 +0000269
270def test_healthcheck(client):
271 """
272 test healthcheck
273 """
274 res = client.get("/a1-p/healthcheck")
275 assert res.status_code == 200
Tommy Carpenter6b699102019-10-17 13:35:59 -0400276
277
278def teardown_module():
279 """module teardown"""
Tommy Carpenter0b42dfc2019-10-24 10:13:54 -0400280 a1rmr.stop_rmr_thread()