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 # ==================================================================================
20 from rmr.rmr_mocks import rmr_mocks
25 ADM_CTRL = "admission_control_policy"
26 ADM_CTRL_POLICIES = "/a1-p/policytypes/20000/policies"
27 ADM_CTRL_INSTANCE = ADM_CTRL_POLICIES + "/" + ADM_CTRL
28 ADM_CTRL_INSTANCE_STATUS = ADM_CTRL_INSTANCE + "/status"
29 ADM_CTRL_TYPE = "/a1-p/policytypes/20000"
30 TEST_TYPE = "/a1-p/policytypes/20001"
33 # http://flask.pocoo.org/docs/1.0/testing/
36 db_fd, app.app.config["DATABASE"] = tempfile.mkstemp()
37 app.app.config["TESTING"] = True
38 cl = app.app.test_client()
43 os.unlink(app.app.config["DATABASE"])
46 def _fake_dequeue(_filter_type):
48 for monkeypatching a1rmnr.dequeue_all_messages with a good status
51 pay = b'{"policy_type_id": 20000, "policy_instance_id": "admission_control_policy", "handler_id": "test_receiver", "status": "OK"}'
52 fake_msg["payload"] = pay
53 new_messages = [fake_msg]
57 def _fake_dequeue_none(_filter_type):
59 for monkeypatching a1rmnr.dequeue_all_messages with no waiting messages
64 def _fake_dequeue_deleted(_filter_type):
66 for monkeypatching a1rmnr.dequeue_all_messages with a DELETED status
70 # insert some that don't exist to make sure nothing blows up
71 pay = b'{"policy_type_id": 20666, "policy_instance_id": "admission_control_policy", "handler_id": "test_receiver", "status": "DELETED"}'
72 fake_msg = {"payload": pay}
73 new_msgs.append(fake_msg)
75 pay = b'{"policy_type_id": 20000, "policy_instance_id": "darkness", "handler_id": "test_receiver", "status": "DELETED"}'
76 fake_msg = {"payload": pay}
77 new_msgs.append(fake_msg)
79 pay = b'{"policy_type_id": 20000, "policy_instance_id": "admission_control_policy", "handler_id": "test_receiver", "status": "DELETED"}'
80 fake_msg = {"payload": pay}
81 new_msgs.append(fake_msg)
86 def _test_put_patch(monkeypatch):
87 rmr_mocks.patch_rmr(monkeypatch)
88 monkeypatch.setattr("rmr.rmr.rmr_send_msg", rmr_mocks.send_mock_generator(0)) # good sends for this whole batch
90 # we need this because free expects a real sbuf
91 # TODO: move this into rmr_mocks
95 monkeypatch.setattr("rmr.rmr.rmr_free_msg", noop)
97 # we need to repatch alloc (already patched in patch_rmr) to fix the transactionid, alloc is called in send and recieve
98 def fake_alloc(_unused, _alsounused):
99 sbuf = rmr_mocks.Rmr_mbuf_t()
100 sbuf.contents.xaction = b"d49b53e478b711e9a1130242ac110002"
103 # we also need to repatch set, since in the send function, we alloc, then set a new transid
104 def fake_set_transactionid(sbuf):
105 sbuf.contents.xaction = b"d49b53e478b711e9a1130242ac110002"
107 # Note, we could have just patched summary, but this patches at a "lower level" so is a better test
108 monkeypatch.setattr("rmr.rmr.rmr_alloc_msg", fake_alloc)
109 monkeypatch.setattr("rmr.rmr.generate_and_set_transaction_id", fake_set_transactionid)
115 def test_workflow_nothing_there_yet(client, monkeypatch, adm_type_good, adm_instance_good):
116 """ test policy put good"""
119 res = client.get(ADM_CTRL_TYPE)
120 assert res.status_code == 404
123 res = client.get("/a1-p/policytypes")
124 assert res.status_code == 200
125 assert res.json == []
127 # instance 404 because type not there yet
128 monkeypatch.setattr("a1.a1rmr.dequeue_all_waiting_messages", _fake_dequeue_none)
129 res = client.get(ADM_CTRL_POLICIES)
130 assert res.status_code == 404
133 def test_workflow(client, monkeypatch, adm_type_good, adm_instance_good):
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 monkeypatch.setattr("a1.a1rmr.dequeue_all_waiting_messages", _fake_dequeue_none)
152 res = client.get(ADM_CTRL_POLICIES)
153 assert res.status_code == 200
154 assert res.json == []
156 # no instance there yet
157 res = client.get(ADM_CTRL_INSTANCE)
158 assert res.status_code == 404
159 res = client.get(ADM_CTRL_INSTANCE_STATUS)
160 assert res.status_code == 404
162 # create a good instance
163 _test_put_patch(monkeypatch)
164 # assert that rmr bad states don't cause problems
165 monkeypatch.setattr("rmr.rmr.rmr_send_msg", rmr_mocks.send_mock_generator(10))
166 res = client.put(ADM_CTRL_INSTANCE, json=adm_instance_good)
167 assert res.status_code == 202
169 # replace is allowed on instances
170 res = client.put(ADM_CTRL_INSTANCE, json=adm_instance_good)
171 assert res.status_code == 202
173 # instance 200 and in list
174 res = client.get(ADM_CTRL_POLICIES)
175 assert res.status_code == 200
176 assert res.json == [ADM_CTRL]
178 def get_instance_good(expected):
180 res = client.get(ADM_CTRL_INSTANCE)
181 assert res.status_code == 200
182 assert res.json == adm_instance_good
184 # get the instance status
185 res = client.get(ADM_CTRL_INSTANCE_STATUS)
186 assert res.status_code == 200
187 assert res.get_data(as_text=True) == expected
189 # try a status get but pretend we didn't get any ACKs yet to test NOT IN EFFECT
190 monkeypatch.setattr("a1.a1rmr.dequeue_all_waiting_messages", _fake_dequeue_none)
191 get_instance_good("NOT IN EFFECT")
193 # now pretend we did get a good ACK
194 monkeypatch.setattr("a1.a1rmr.dequeue_all_waiting_messages", _fake_dequeue)
195 get_instance_good("IN EFFECT")
197 # cant delete type until there are no instances
198 res = client.delete(ADM_CTRL_TYPE)
199 assert res.status_code == 400
202 res = client.delete(ADM_CTRL_INSTANCE)
203 assert res.status_code == 202
204 res = client.delete(ADM_CTRL_INSTANCE) # should be able to do multiple deletes
205 assert res.status_code == 202
207 # status after a delete, but there are no messages yet, should still return
208 monkeypatch.setattr("a1.a1rmr.dequeue_all_waiting_messages", _fake_dequeue)
209 get_instance_good("IN EFFECT")
211 # now pretend we deleted successfully
212 monkeypatch.setattr("a1.a1rmr.dequeue_all_waiting_messages", _fake_dequeue_deleted)
213 res = client.get(ADM_CTRL_INSTANCE_STATUS) # cant get status
214 assert res.status_code == 404
215 res = client.get(ADM_CTRL_INSTANCE) # cant get instance
216 assert res.status_code == 404
218 # list still 200 but no instance
219 res = client.get(ADM_CTRL_POLICIES)
220 assert res.status_code == 200
221 assert res.json == []
224 res = client.delete(ADM_CTRL_TYPE)
225 assert res.status_code == 204
228 res = client.get(ADM_CTRL_TYPE)
229 assert res.status_code == 404
230 res = client.delete(ADM_CTRL_TYPE)
231 assert res.status_code == 404
234 def test_bad_instances(client, monkeypatch, adm_type_good):
236 test various failure modes
238 # put the type (needed for some of the tests below)
239 rmr_mocks.patch_rmr(monkeypatch)
240 res = client.put(ADM_CTRL_TYPE, json=adm_type_good)
241 assert res.status_code == 201
244 res = client.put(ADM_CTRL_INSTANCE, json={"not": "expected"})
245 assert res.status_code == 400
248 res = client.put(ADM_CTRL_INSTANCE, data="notajson")
249 assert res.status_code == 415
251 # delete a non existent instance
252 res = client.delete(ADM_CTRL_INSTANCE + "DARKNESS")
253 assert res.status_code == 404
255 # get a non existent instance
256 monkeypatch.setattr("a1.a1rmr.dequeue_all_waiting_messages", _fake_dequeue)
257 res = client.get(ADM_CTRL_INSTANCE + "DARKNESS")
258 assert res.status_code == 404
260 # delete the type (as cleanup)
261 res = client.delete(ADM_CTRL_TYPE)
262 assert res.status_code == 204
265 def test_illegal_types(client, monkeypatch, adm_type_good):
269 res = client.put("/a1-p/policytypes/19999", json=adm_type_good)
270 assert res.status_code == 400
271 res = client.put("/a1-p/policytypes/21024", json=adm_type_good)
272 assert res.status_code == 400
275 def test_healthcheck(client):
279 res = client.get("/a1-p/healthcheck")
280 assert res.status_code == 200