1 # ==================================================================================
2 # Copyright (c) 2019 Nokia
3 # Copyright (c) 2018-2019 AT&T Intellectual Property.
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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 # ==================================================================================
19 from rmr.rmr_mocks import rmr_mocks
23 ADM_CTRL = "admission_control_policy"
24 ADM_CTRL_POLICIES = "/a1-p/policytypes/20000/policies"
25 ADM_CTRL_INSTANCE = ADM_CTRL_POLICIES + "/" + ADM_CTRL
26 ADM_CTRL_INSTANCE_STATUS = ADM_CTRL_INSTANCE + "/status"
27 ADM_CTRL_TYPE = "/a1-p/policytypes/20000"
28 TEST_TYPE = "/a1-p/policytypes/20001"
32 """for monkeypatching with a good status"""
33 pay = b'{"policy_type_id": 20000, "policy_instance_id": "admission_control_policy", "handler_id": "test_receiver", "status": "OK"}'
34 fake_msg = {"payload": pay}
38 def _fake_dequeue_none():
39 """for monkeypatching with no waiting messages"""
43 def _fake_dequeue_deleted():
44 """for monkeypatching with a DELETED status"""
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)
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)
56 # 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)
60 pay = b'{"policy_type_id": 20000, "policy_instance_id": "admission_control_policy", "handler_id": "test_receiver", "status": "DELETED"}'
61 fake_msg = {"payload": pay}
62 new_msgs.append(fake_msg)
67 def _test_put_patch(monkeypatch):
68 rmr_mocks.patch_rmr(monkeypatch)
69 # assert that rmr bad states don't cause problems
70 monkeypatch.setattr("rmr.rmr.rmr_send_msg", rmr_mocks.send_mock_generator(10))
72 # we need this because free expects a real sbuf
73 # TODO: move this into rmr_mocks
77 monkeypatch.setattr("rmr.rmr.rmr_free_msg", noop)
79 # we need to repatch alloc (already patched in patch_rmr) to fix the transactionid, alloc is called in send and recieve
80 def fake_alloc(_unused, _alsounused):
81 sbuf = rmr_mocks.Rmr_mbuf_t()
82 sbuf.contents.xaction = b"d49b53e478b711e9a1130242ac110002"
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"
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)
101 """module level setup"""
107 # launch the thread with a fake init func and a patched rcv func; we will "repatch" later
108 RMR_THREAD = a1rmr.start_rmr_thread(init_func_override=noop, rcv_func_override=_fake_dequeue_none)
114 def test_workflow_nothing_there_yet(client):
115 """ test policy put good"""
117 res = client.get(ADM_CTRL_TYPE)
118 assert res.status_code == 404
121 res = client.get("/a1-p/policytypes")
122 assert res.status_code == 200
123 assert res.json == []
125 # instance 404 because type not there yet
126 res = client.get(ADM_CTRL_POLICIES)
127 assert res.status_code == 404
130 def test_workflow(client, monkeypatch, adm_type_good, adm_instance_good):
132 test a full A1 workflow
135 res = client.put(ADM_CTRL_TYPE, json=adm_type_good)
136 assert res.status_code == 201
139 res = client.put(ADM_CTRL_TYPE, json=adm_type_good)
140 assert res.status_code == 400
143 res = client.get(ADM_CTRL_TYPE)
144 assert res.status_code == 200
145 assert res.json == adm_type_good
146 res = client.get("/a1-p/policytypes")
147 assert res.status_code == 200
148 assert res.json == [20000]
150 # instance 200 but empty list
151 res = client.get(ADM_CTRL_POLICIES)
152 assert res.status_code == 200
153 assert res.json == []
155 # no instance there yet
156 res = client.get(ADM_CTRL_INSTANCE)
157 assert res.status_code == 404
158 res = client.get(ADM_CTRL_INSTANCE_STATUS)
159 assert res.status_code == 404
161 # create a good instance
162 _test_put_patch(monkeypatch)
163 res = client.put(ADM_CTRL_INSTANCE, json=adm_instance_good)
164 assert res.status_code == 202
166 # replace is allowed on instances
167 res = client.put(ADM_CTRL_INSTANCE, json=adm_instance_good)
168 assert res.status_code == 202
170 # instance 200 and in list
171 res = client.get(ADM_CTRL_POLICIES)
172 assert res.status_code == 200
173 assert res.json == [ADM_CTRL]
175 def get_instance_good(expected):
177 res = client.get(ADM_CTRL_INSTANCE)
178 assert res.status_code == 200
179 assert res.json == adm_instance_good
181 # get the instance status
182 res = client.get(ADM_CTRL_INSTANCE_STATUS)
183 assert res.status_code == 200
184 assert res.get_data(as_text=True) == expected
186 # try a status get but we didn't get any ACKs yet to test NOT IN EFFECT
187 time.sleep(1) # wait for the rmr thread
188 get_instance_good("NOT IN EFFECT")
190 # now pretend we did get a good ACK
191 RMR_THREAD._rcv_func = _fake_dequeue
192 time.sleep(1) # wait for the rmr thread
193 get_instance_good("IN EFFECT")
195 # cant delete type until there are no instances
196 res = client.delete(ADM_CTRL_TYPE)
197 assert res.status_code == 400
200 res = client.delete(ADM_CTRL_INSTANCE)
201 assert res.status_code == 202
202 res = client.delete(ADM_CTRL_INSTANCE) # should be able to do multiple deletes
203 assert res.status_code == 202
205 # status after a delete, but there are no messages yet, should still return
206 time.sleep(1) # wait for the rmr thread
207 get_instance_good("IN EFFECT")
209 # now pretend we deleted successfully
210 RMR_THREAD._rcv_func = _fake_dequeue_deleted
211 time.sleep(1) # wait for the rmr thread
212 # list still 200 but no instance
213 res = client.get(ADM_CTRL_POLICIES)
214 assert res.status_code == 200
215 assert res.json == []
216 res = client.get(ADM_CTRL_INSTANCE_STATUS) # cant get status
217 assert res.status_code == 404
218 res = client.get(ADM_CTRL_INSTANCE) # cant get instance
219 assert res.status_code == 404
222 res = client.delete(ADM_CTRL_TYPE)
223 assert res.status_code == 204
226 res = client.get(ADM_CTRL_TYPE)
227 assert res.status_code == 404
228 res = client.delete(ADM_CTRL_TYPE)
229 assert res.status_code == 404
232 def test_bad_instances(client, monkeypatch, adm_type_good):
234 test various failure modes
236 # put the type (needed for some of the tests below)
237 rmr_mocks.patch_rmr(monkeypatch)
238 res = client.put(ADM_CTRL_TYPE, json=adm_type_good)
239 assert res.status_code == 201
242 res = client.put(ADM_CTRL_INSTANCE, json={"not": "expected"})
243 assert res.status_code == 400
246 res = client.put(ADM_CTRL_INSTANCE, data="notajson")
247 assert res.status_code == 415
249 # delete a non existent instance
250 res = client.delete(ADM_CTRL_INSTANCE + "DARKNESS")
251 assert res.status_code == 404
253 # get a non existent instance
254 RMR_THREAD._rcv_func = _fake_dequeue
256 res = client.get(ADM_CTRL_INSTANCE + "DARKNESS")
257 assert res.status_code == 404
259 # delete the type (as cleanup)
260 res = client.delete(ADM_CTRL_TYPE)
261 assert res.status_code == 204
264 def test_illegal_types(client, monkeypatch, adm_type_good):
268 res = client.put("/a1-p/policytypes/19999", json=adm_type_good)
269 assert res.status_code == 400
270 res = client.put("/a1-p/policytypes/21024", json=adm_type_good)
271 assert res.status_code == 400
274 def test_healthcheck(client):
278 res = client.get("/a1-p/healthcheck")
279 assert res.status_code == 200
282 def teardown_module():
283 """module teardown"""