Tommy Carpenter | 5ad8f03 | 2019-05-30 14:33:21 -0400 | [diff] [blame] | 1 | # ================================================================================== |
| 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 Carpenter | 40caa31 | 2019-09-12 16:24:10 -0400 | [diff] [blame] | 17 | |
Tommy Carpenter | 6b69910 | 2019-10-17 13:35:59 -0400 | [diff] [blame] | 18 | import time |
Tommy Carpenter | 5ad8f03 | 2019-05-30 14:33:21 -0400 | [diff] [blame] | 19 | from rmr.rmr_mocks import rmr_mocks |
Tommy Carpenter | 8bcc51a | 2019-10-21 16:07:31 -0400 | [diff] [blame] | 20 | from a1 import a1rmr |
Tommy Carpenter | 5ad8f03 | 2019-05-30 14:33:21 -0400 | [diff] [blame] | 21 | |
Tommy Carpenter | 40caa31 | 2019-09-12 16:24:10 -0400 | [diff] [blame] | 22 | |
| 23 | ADM_CTRL = "admission_control_policy" |
Tommy Carpenter | 30a7bdc | 2019-09-23 09:48:23 -0400 | [diff] [blame] | 24 | ADM_CTRL_POLICIES = "/a1-p/policytypes/20000/policies" |
| 25 | ADM_CTRL_INSTANCE = ADM_CTRL_POLICIES + "/" + ADM_CTRL |
Tommy Carpenter | 40caa31 | 2019-09-12 16:24:10 -0400 | [diff] [blame] | 26 | ADM_CTRL_INSTANCE_STATUS = ADM_CTRL_INSTANCE + "/status" |
Tommy Carpenter | 91ae889 | 2019-09-18 10:45:50 -0400 | [diff] [blame] | 27 | ADM_CTRL_TYPE = "/a1-p/policytypes/20000" |
| 28 | TEST_TYPE = "/a1-p/policytypes/20001" |
Tommy Carpenter | 40caa31 | 2019-09-12 16:24:10 -0400 | [diff] [blame] | 29 | |
| 30 | |
Tommy Carpenter | 8bcc51a | 2019-10-21 16:07:31 -0400 | [diff] [blame] | 31 | def _fake_dequeue(): |
Tommy Carpenter | 6b69910 | 2019-10-17 13:35:59 -0400 | [diff] [blame] | 32 | """for monkeypatching with a good status""" |
Tommy Carpenter | 40caa31 | 2019-09-12 16:24:10 -0400 | [diff] [blame] | 33 | pay = b'{"policy_type_id": 20000, "policy_instance_id": "admission_control_policy", "handler_id": "test_receiver", "status": "OK"}' |
Tommy Carpenter | 8bcc51a | 2019-10-21 16:07:31 -0400 | [diff] [blame] | 34 | fake_msg = {"payload": pay} |
| 35 | return [fake_msg] |
Tommy Carpenter | 5ad8f03 | 2019-05-30 14:33:21 -0400 | [diff] [blame] | 36 | |
| 37 | |
Tommy Carpenter | 8bcc51a | 2019-10-21 16:07:31 -0400 | [diff] [blame] | 38 | def _fake_dequeue_none(): |
Tommy Carpenter | 6b69910 | 2019-10-17 13:35:59 -0400 | [diff] [blame] | 39 | """for monkeypatching with no waiting messages""" |
Tommy Carpenter | bfa4614 | 2019-09-26 11:14:16 -0400 | [diff] [blame] | 40 | return [] |
| 41 | |
| 42 | |
Tommy Carpenter | 8bcc51a | 2019-10-21 16:07:31 -0400 | [diff] [blame] | 43 | def _fake_dequeue_deleted(): |
Tommy Carpenter | 6b69910 | 2019-10-17 13:35:59 -0400 | [diff] [blame] | 44 | """for monkeypatching with a DELETED status""" |
Tommy Carpenter | 7cec82d | 2019-10-14 16:18:21 -0400 | [diff] [blame] | 45 | 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 Carpenter | 8bcc51a | 2019-10-21 16:07:31 -0400 | [diff] [blame] | 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) |
| 59 | |
Tommy Carpenter | bfa4614 | 2019-09-26 11:14:16 -0400 | [diff] [blame] | 60 | pay = b'{"policy_type_id": 20000, "policy_instance_id": "admission_control_policy", "handler_id": "test_receiver", "status": "DELETED"}' |
Tommy Carpenter | 7cec82d | 2019-10-14 16:18:21 -0400 | [diff] [blame] | 61 | fake_msg = {"payload": pay} |
| 62 | new_msgs.append(fake_msg) |
| 63 | |
| 64 | return new_msgs |
Tommy Carpenter | bfa4614 | 2019-09-26 11:14:16 -0400 | [diff] [blame] | 65 | |
| 66 | |
Tommy Carpenter | 5ad8f03 | 2019-05-30 14:33:21 -0400 | [diff] [blame] | 67 | def _test_put_patch(monkeypatch): |
Tommy Carpenter | 91ae889 | 2019-09-18 10:45:50 -0400 | [diff] [blame] | 68 | rmr_mocks.patch_rmr(monkeypatch) |
Tommy Carpenter | 6b69910 | 2019-10-17 13:35:59 -0400 | [diff] [blame] | 69 | # assert that rmr bad states don't cause problems |
| 70 | monkeypatch.setattr("rmr.rmr.rmr_send_msg", rmr_mocks.send_mock_generator(10)) |
Tommy Carpenter | 5ad8f03 | 2019-05-30 14:33:21 -0400 | [diff] [blame] | 71 | |
Tommy Carpenter | a0876ef | 2019-10-02 11:15:04 -0400 | [diff] [blame] | 72 | # 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 Carpenter | 5ad8f03 | 2019-05-30 14:33:21 -0400 | [diff] [blame] | 79 | # we need to repatch alloc (already patched in patch_rmr) to fix the transactionid, alloc is called in send and recieve |
Tommy Carpenter | 0b42dfc | 2019-10-24 10:13:54 -0400 | [diff] [blame] | 80 | def fake_alloc(_unused1, _unused2, _unused3, _unused4, _unused5): |
Tommy Carpenter | 5ad8f03 | 2019-05-30 14:33:21 -0400 | [diff] [blame] | 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 Carpenter | 6b69910 | 2019-10-17 13:35:59 -0400 | [diff] [blame] | 94 | # Module level Hack |
| 95 | |
| 96 | |
Tommy Carpenter | 6b69910 | 2019-10-17 13:35:59 -0400 | [diff] [blame] | 97 | def setup_module(): |
| 98 | """module level setup""" |
Tommy Carpenter | 8bcc51a | 2019-10-21 16:07:31 -0400 | [diff] [blame] | 99 | |
| 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 Carpenter | 0b42dfc | 2019-10-24 10:13:54 -0400 | [diff] [blame] | 104 | a1rmr.start_rmr_thread(init_func_override=noop, rcv_func_override=_fake_dequeue_none) |
Tommy Carpenter | 6b69910 | 2019-10-17 13:35:59 -0400 | [diff] [blame] | 105 | |
| 106 | |
Tommy Carpenter | fdf0504 | 2019-07-18 20:21:21 +0000 | [diff] [blame] | 107 | # Actual Tests |
| 108 | |
| 109 | |
Tommy Carpenter | 8bcc51a | 2019-10-21 16:07:31 -0400 | [diff] [blame] | 110 | def test_workflow_nothing_there_yet(client): |
Tommy Carpenter | 2451446 | 2019-07-16 11:25:52 -0400 | [diff] [blame] | 111 | """ test policy put good""" |
Tommy Carpenter | 91ae889 | 2019-09-18 10:45:50 -0400 | [diff] [blame] | 112 | # no type there yet |
| 113 | res = client.get(ADM_CTRL_TYPE) |
| 114 | assert res.status_code == 404 |
| 115 | |
Tommy Carpenter | 30a7bdc | 2019-09-23 09:48:23 -0400 | [diff] [blame] | 116 | # 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 Carpenter | 7cec82d | 2019-10-14 16:18:21 -0400 | [diff] [blame] | 125 | |
| 126 | def test_workflow(client, monkeypatch, adm_type_good, adm_instance_good): |
Tommy Carpenter | 6b69910 | 2019-10-17 13:35:59 -0400 | [diff] [blame] | 127 | """ |
| 128 | test a full A1 workflow |
| 129 | """ |
Tommy Carpenter | 91ae889 | 2019-09-18 10:45:50 -0400 | [diff] [blame] | 130 | # put the type |
| 131 | res = client.put(ADM_CTRL_TYPE, json=adm_type_good) |
| 132 | assert res.status_code == 201 |
| 133 | |
Tommy Carpenter | 7cec82d | 2019-10-14 16:18:21 -0400 | [diff] [blame] | 134 | # cant replace types |
| 135 | res = client.put(ADM_CTRL_TYPE, json=adm_type_good) |
| 136 | assert res.status_code == 400 |
| 137 | |
Tommy Carpenter | 30a7bdc | 2019-09-23 09:48:23 -0400 | [diff] [blame] | 138 | # type there now |
Tommy Carpenter | 91ae889 | 2019-09-18 10:45:50 -0400 | [diff] [blame] | 139 | res = client.get(ADM_CTRL_TYPE) |
| 140 | assert res.status_code == 200 |
| 141 | assert res.json == adm_type_good |
Tommy Carpenter | 30a7bdc | 2019-09-23 09:48:23 -0400 | [diff] [blame] | 142 | 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 Carpenter | 91ae889 | 2019-09-18 10:45:50 -0400 | [diff] [blame] | 150 | |
| 151 | # no instance there yet |
Tommy Carpenter | 40caa31 | 2019-09-12 16:24:10 -0400 | [diff] [blame] | 152 | 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 Carpenter | 2451446 | 2019-07-16 11:25:52 -0400 | [diff] [blame] | 158 | _test_put_patch(monkeypatch) |
Tommy Carpenter | 91ae889 | 2019-09-18 10:45:50 -0400 | [diff] [blame] | 159 | res = client.put(ADM_CTRL_INSTANCE, json=adm_instance_good) |
Tommy Carpenter | bfa4614 | 2019-09-26 11:14:16 -0400 | [diff] [blame] | 160 | assert res.status_code == 202 |
Tommy Carpenter | 40caa31 | 2019-09-12 16:24:10 -0400 | [diff] [blame] | 161 | |
Tommy Carpenter | 7cec82d | 2019-10-14 16:18:21 -0400 | [diff] [blame] | 162 | # replace is allowed on instances |
| 163 | res = client.put(ADM_CTRL_INSTANCE, json=adm_instance_good) |
| 164 | assert res.status_code == 202 |
| 165 | |
Tommy Carpenter | 30a7bdc | 2019-09-23 09:48:23 -0400 | [diff] [blame] | 166 | # 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 Carpenter | bfa4614 | 2019-09-26 11:14:16 -0400 | [diff] [blame] | 171 | 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 Carpenter | 40caa31 | 2019-09-12 16:24:10 -0400 | [diff] [blame] | 176 | |
Tommy Carpenter | bfa4614 | 2019-09-26 11:14:16 -0400 | [diff] [blame] | 177 | # 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 Carpenter | 6b69910 | 2019-10-17 13:35:59 -0400 | [diff] [blame] | 182 | # 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 Carpenter | bfa4614 | 2019-09-26 11:14:16 -0400 | [diff] [blame] | 184 | get_instance_good("NOT IN EFFECT") |
| 185 | |
| 186 | # now pretend we did get a good ACK |
Tommy Carpenter | 0b42dfc | 2019-10-24 10:13:54 -0400 | [diff] [blame] | 187 | a1rmr.replace_rcv_func(_fake_dequeue) |
Tommy Carpenter | 6b69910 | 2019-10-17 13:35:59 -0400 | [diff] [blame] | 188 | time.sleep(1) # wait for the rmr thread |
Tommy Carpenter | bfa4614 | 2019-09-26 11:14:16 -0400 | [diff] [blame] | 189 | get_instance_good("IN EFFECT") |
Tommy Carpenter | 40caa31 | 2019-09-12 16:24:10 -0400 | [diff] [blame] | 190 | |
Tommy Carpenter | f87c857 | 2019-10-07 11:15:45 -0400 | [diff] [blame] | 191 | # cant delete type until there are no instances |
| 192 | res = client.delete(ADM_CTRL_TYPE) |
| 193 | assert res.status_code == 400 |
| 194 | |
Tommy Carpenter | bfa4614 | 2019-09-26 11:14:16 -0400 | [diff] [blame] | 195 | # 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 Carpenter | 6b69910 | 2019-10-17 13:35:59 -0400 | [diff] [blame] | 202 | time.sleep(1) # wait for the rmr thread |
Tommy Carpenter | bfa4614 | 2019-09-26 11:14:16 -0400 | [diff] [blame] | 203 | get_instance_good("IN EFFECT") |
| 204 | |
| 205 | # now pretend we deleted successfully |
Tommy Carpenter | 0b42dfc | 2019-10-24 10:13:54 -0400 | [diff] [blame] | 206 | a1rmr.replace_rcv_func(_fake_dequeue_deleted) |
Tommy Carpenter | 6b69910 | 2019-10-17 13:35:59 -0400 | [diff] [blame] | 207 | time.sleep(1) # wait for the rmr thread |
Tommy Carpenter | bfa4614 | 2019-09-26 11:14:16 -0400 | [diff] [blame] | 208 | # list still 200 but no instance |
| 209 | res = client.get(ADM_CTRL_POLICIES) |
| 210 | assert res.status_code == 200 |
| 211 | assert res.json == [] |
Tommy Carpenter | 8bcc51a | 2019-10-21 16:07:31 -0400 | [diff] [blame] | 212 | 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 Carpenter | bfa4614 | 2019-09-26 11:14:16 -0400 | [diff] [blame] | 216 | |
Tommy Carpenter | f87c857 | 2019-10-07 11:15:45 -0400 | [diff] [blame] | 217 | # delete the type |
| 218 | res = client.delete(ADM_CTRL_TYPE) |
| 219 | assert res.status_code == 204 |
Tommy Carpenter | bfa4614 | 2019-09-26 11:14:16 -0400 | [diff] [blame] | 220 | |
Tommy Carpenter | f87c857 | 2019-10-07 11:15:45 -0400 | [diff] [blame] | 221 | # 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 Carpenter | 2451446 | 2019-07-16 11:25:52 -0400 | [diff] [blame] | 226 | |
| 227 | |
Tommy Carpenter | 91ae889 | 2019-09-18 10:45:50 -0400 | [diff] [blame] | 228 | def test_bad_instances(client, monkeypatch, adm_type_good): |
Tommy Carpenter | 5ad8f03 | 2019-05-30 14:33:21 -0400 | [diff] [blame] | 229 | """ |
Tommy Carpenter | f87c857 | 2019-10-07 11:15:45 -0400 | [diff] [blame] | 230 | test various failure modes |
Tommy Carpenter | 5ad8f03 | 2019-05-30 14:33:21 -0400 | [diff] [blame] | 231 | """ |
Tommy Carpenter | f87c857 | 2019-10-07 11:15:45 -0400 | [diff] [blame] | 232 | # put the type (needed for some of the tests below) |
Tommy Carpenter | 91ae889 | 2019-09-18 10:45:50 -0400 | [diff] [blame] | 233 | rmr_mocks.patch_rmr(monkeypatch) |
Tommy Carpenter | f87c857 | 2019-10-07 11:15:45 -0400 | [diff] [blame] | 234 | res = client.put(ADM_CTRL_TYPE, json=adm_type_good) |
| 235 | assert res.status_code == 201 |
Tommy Carpenter | 91ae889 | 2019-09-18 10:45:50 -0400 | [diff] [blame] | 236 | |
| 237 | # bad body |
Tommy Carpenter | 40caa31 | 2019-09-12 16:24:10 -0400 | [diff] [blame] | 238 | res = client.put(ADM_CTRL_INSTANCE, json={"not": "expected"}) |
Tommy Carpenter | 2451446 | 2019-07-16 11:25:52 -0400 | [diff] [blame] | 239 | assert res.status_code == 400 |
| 240 | |
Tommy Carpenter | 5ad8f03 | 2019-05-30 14:33:21 -0400 | [diff] [blame] | 241 | # bad media type |
Tommy Carpenter | 40caa31 | 2019-09-12 16:24:10 -0400 | [diff] [blame] | 242 | res = client.put(ADM_CTRL_INSTANCE, data="notajson") |
Tommy Carpenter | 5ad8f03 | 2019-05-30 14:33:21 -0400 | [diff] [blame] | 243 | assert res.status_code == 415 |
| 244 | |
Tommy Carpenter | f87c857 | 2019-10-07 11:15:45 -0400 | [diff] [blame] | 245 | # 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 Carpenter | 0b42dfc | 2019-10-24 10:13:54 -0400 | [diff] [blame] | 250 | a1rmr.replace_rcv_func(_fake_dequeue) |
Tommy Carpenter | 6b69910 | 2019-10-17 13:35:59 -0400 | [diff] [blame] | 251 | time.sleep(1) |
Tommy Carpenter | f87c857 | 2019-10-07 11:15:45 -0400 | [diff] [blame] | 252 | 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 Carpenter | 0b42dfc | 2019-10-24 10:13:54 -0400 | [diff] [blame] | 260 | def test_illegal_types(client, adm_type_good): |
Tommy Carpenter | f87c857 | 2019-10-07 11:15:45 -0400 | [diff] [blame] | 261 | """ |
| 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 Carpenter | fdf0504 | 2019-07-18 20:21:21 +0000 | [diff] [blame] | 269 | |
| 270 | def test_healthcheck(client): |
| 271 | """ |
| 272 | test healthcheck |
| 273 | """ |
| 274 | res = client.get("/a1-p/healthcheck") |
| 275 | assert res.status_code == 200 |
Tommy Carpenter | 6b69910 | 2019-10-17 13:35:59 -0400 | [diff] [blame] | 276 | |
| 277 | |
| 278 | def teardown_module(): |
| 279 | """module teardown""" |
Tommy Carpenter | 0b42dfc | 2019-10-24 10:13:54 -0400 | [diff] [blame] | 280 | a1rmr.stop_rmr_thread() |