blob: 63831b0d81ce606e84e2744f8814da4bceddee51 [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
80 def fake_alloc(_unused, _alsounused):
81 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
97RMR_THREAD = None
98
99
100def setup_module():
101 """module level setup"""
102 global RMR_THREAD
Tommy Carpenter8bcc51a2019-10-21 16:07:31 -0400103
104 def noop():
105 pass
106
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)
Tommy Carpenter6b699102019-10-17 13:35:59 -0400109
110
Tommy Carpenterfdf05042019-07-18 20:21:21 +0000111# Actual Tests
112
113
Tommy Carpenter8bcc51a2019-10-21 16:07:31 -0400114def test_workflow_nothing_there_yet(client):
Tommy Carpenter24514462019-07-16 11:25:52 -0400115 """ test policy put good"""
Tommy Carpenter91ae8892019-09-18 10:45:50 -0400116 # no type there yet
117 res = client.get(ADM_CTRL_TYPE)
118 assert res.status_code == 404
119
Tommy Carpenter30a7bdc2019-09-23 09:48:23 -0400120 # no types at all
121 res = client.get("/a1-p/policytypes")
122 assert res.status_code == 200
123 assert res.json == []
124
125 # instance 404 because type not there yet
126 res = client.get(ADM_CTRL_POLICIES)
127 assert res.status_code == 404
128
Tommy Carpenter7cec82d2019-10-14 16:18:21 -0400129
130def test_workflow(client, monkeypatch, adm_type_good, adm_instance_good):
Tommy Carpenter6b699102019-10-17 13:35:59 -0400131 """
132 test a full A1 workflow
133 """
Tommy Carpenter91ae8892019-09-18 10:45:50 -0400134 # put the type
135 res = client.put(ADM_CTRL_TYPE, json=adm_type_good)
136 assert res.status_code == 201
137
Tommy Carpenter7cec82d2019-10-14 16:18:21 -0400138 # cant replace types
139 res = client.put(ADM_CTRL_TYPE, json=adm_type_good)
140 assert res.status_code == 400
141
Tommy Carpenter30a7bdc2019-09-23 09:48:23 -0400142 # type there now
Tommy Carpenter91ae8892019-09-18 10:45:50 -0400143 res = client.get(ADM_CTRL_TYPE)
144 assert res.status_code == 200
145 assert res.json == adm_type_good
Tommy Carpenter30a7bdc2019-09-23 09:48:23 -0400146 res = client.get("/a1-p/policytypes")
147 assert res.status_code == 200
148 assert res.json == [20000]
149
150 # instance 200 but empty list
151 res = client.get(ADM_CTRL_POLICIES)
152 assert res.status_code == 200
153 assert res.json == []
Tommy Carpenter91ae8892019-09-18 10:45:50 -0400154
155 # no instance there yet
Tommy Carpenter40caa312019-09-12 16:24:10 -0400156 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
160
161 # create a good instance
Tommy Carpenter24514462019-07-16 11:25:52 -0400162 _test_put_patch(monkeypatch)
Tommy Carpenter91ae8892019-09-18 10:45:50 -0400163 res = client.put(ADM_CTRL_INSTANCE, json=adm_instance_good)
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400164 assert res.status_code == 202
Tommy Carpenter40caa312019-09-12 16:24:10 -0400165
Tommy Carpenter7cec82d2019-10-14 16:18:21 -0400166 # replace is allowed on instances
167 res = client.put(ADM_CTRL_INSTANCE, json=adm_instance_good)
168 assert res.status_code == 202
169
Tommy Carpenter30a7bdc2019-09-23 09:48:23 -0400170 # instance 200 and in list
171 res = client.get(ADM_CTRL_POLICIES)
172 assert res.status_code == 200
173 assert res.json == [ADM_CTRL]
174
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400175 def get_instance_good(expected):
176 # get the instance
177 res = client.get(ADM_CTRL_INSTANCE)
178 assert res.status_code == 200
179 assert res.json == adm_instance_good
Tommy Carpenter40caa312019-09-12 16:24:10 -0400180
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400181 # 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
185
Tommy Carpenter6b699102019-10-17 13:35:59 -0400186 # 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
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400188 get_instance_good("NOT IN EFFECT")
189
190 # now pretend we did get a good ACK
Tommy Carpenter8bcc51a2019-10-21 16:07:31 -0400191 RMR_THREAD._rcv_func = _fake_dequeue
Tommy Carpenter6b699102019-10-17 13:35:59 -0400192 time.sleep(1) # wait for the rmr thread
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400193 get_instance_good("IN EFFECT")
Tommy Carpenter40caa312019-09-12 16:24:10 -0400194
Tommy Carpenterf87c8572019-10-07 11:15:45 -0400195 # cant delete type until there are no instances
196 res = client.delete(ADM_CTRL_TYPE)
197 assert res.status_code == 400
198
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400199 # delete it
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
204
205 # status after a delete, but there are no messages yet, should still return
Tommy Carpenter6b699102019-10-17 13:35:59 -0400206 time.sleep(1) # wait for the rmr thread
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400207 get_instance_good("IN EFFECT")
208
209 # now pretend we deleted successfully
Tommy Carpenter8bcc51a2019-10-21 16:07:31 -0400210 RMR_THREAD._rcv_func = _fake_dequeue_deleted
Tommy Carpenter6b699102019-10-17 13:35:59 -0400211 time.sleep(1) # wait for the rmr thread
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400212 # list still 200 but no instance
213 res = client.get(ADM_CTRL_POLICIES)
214 assert res.status_code == 200
215 assert res.json == []
Tommy Carpenter8bcc51a2019-10-21 16:07:31 -0400216 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
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400220
Tommy Carpenterf87c8572019-10-07 11:15:45 -0400221 # delete the type
222 res = client.delete(ADM_CTRL_TYPE)
223 assert res.status_code == 204
Tommy Carpenterbfa46142019-09-26 11:14:16 -0400224
Tommy Carpenterf87c8572019-10-07 11:15:45 -0400225 # cant touch this
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
Tommy Carpenter24514462019-07-16 11:25:52 -0400230
231
Tommy Carpenter91ae8892019-09-18 10:45:50 -0400232def test_bad_instances(client, monkeypatch, adm_type_good):
Tommy Carpenter5ad8f032019-05-30 14:33:21 -0400233 """
Tommy Carpenterf87c8572019-10-07 11:15:45 -0400234 test various failure modes
Tommy Carpenter5ad8f032019-05-30 14:33:21 -0400235 """
Tommy Carpenterf87c8572019-10-07 11:15:45 -0400236 # put the type (needed for some of the tests below)
Tommy Carpenter91ae8892019-09-18 10:45:50 -0400237 rmr_mocks.patch_rmr(monkeypatch)
Tommy Carpenterf87c8572019-10-07 11:15:45 -0400238 res = client.put(ADM_CTRL_TYPE, json=adm_type_good)
239 assert res.status_code == 201
Tommy Carpenter91ae8892019-09-18 10:45:50 -0400240
241 # bad body
Tommy Carpenter40caa312019-09-12 16:24:10 -0400242 res = client.put(ADM_CTRL_INSTANCE, json={"not": "expected"})
Tommy Carpenter24514462019-07-16 11:25:52 -0400243 assert res.status_code == 400
244
Tommy Carpenter5ad8f032019-05-30 14:33:21 -0400245 # bad media type
Tommy Carpenter40caa312019-09-12 16:24:10 -0400246 res = client.put(ADM_CTRL_INSTANCE, data="notajson")
Tommy Carpenter5ad8f032019-05-30 14:33:21 -0400247 assert res.status_code == 415
248
Tommy Carpenterf87c8572019-10-07 11:15:45 -0400249 # delete a non existent instance
250 res = client.delete(ADM_CTRL_INSTANCE + "DARKNESS")
251 assert res.status_code == 404
252
253 # get a non existent instance
Tommy Carpenter8bcc51a2019-10-21 16:07:31 -0400254 RMR_THREAD._rcv_func = _fake_dequeue
Tommy Carpenter6b699102019-10-17 13:35:59 -0400255 time.sleep(1)
Tommy Carpenterf87c8572019-10-07 11:15:45 -0400256 res = client.get(ADM_CTRL_INSTANCE + "DARKNESS")
257 assert res.status_code == 404
258
259 # delete the type (as cleanup)
260 res = client.delete(ADM_CTRL_TYPE)
261 assert res.status_code == 204
262
263
264def test_illegal_types(client, monkeypatch, adm_type_good):
265 """
266 Test illegal types
267 """
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
272
Tommy Carpenterfdf05042019-07-18 20:21:21 +0000273
274def test_healthcheck(client):
275 """
276 test healthcheck
277 """
278 res = client.get("/a1-p/healthcheck")
279 assert res.status_code == 200
Tommy Carpenter6b699102019-10-17 13:35:59 -0400280
281
282def teardown_module():
283 """module teardown"""
284 RMR_THREAD.stop()