Towards A1 v1.0.0
[ric-plt/a1.git] / tests / test_controller.py
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 # ==================================================================================
17 import tempfile
18 import os
19
20 from rmr.rmr_mocks import rmr_mocks
21 from a1 import app
22 import pytest
23
24
25 ADM_CTRL = "admission_control_policy"
26 ADM_CTRL_INSTANCE = "/a1-p/policytypes/20000/policies/" + ADM_CTRL
27 ADM_CTRL_INSTANCE_STATUS = ADM_CTRL_INSTANCE + "/status"
28 ADM_CTRL_TYPE = "/a1-p/policytypes/20000"
29 TEST_TYPE = "/a1-p/policytypes/20001"
30
31
32 # http://flask.pocoo.org/docs/1.0/testing/
33 @pytest.fixture
34 def client():
35     db_fd, app.app.config["DATABASE"] = tempfile.mkstemp()
36     app.app.config["TESTING"] = True
37     cl = app.app.test_client()
38
39     yield cl
40
41     os.close(db_fd)
42     os.unlink(app.app.config["DATABASE"])
43
44
45 def _fake_dequeue(_filter_type):
46     """
47     for monkeypatching a1rmnr.dequeue_all_messages
48     """
49     fake_msg = {}
50     pay = b'{"policy_type_id": 20000, "policy_instance_id": "admission_control_policy", "handler_id": "test_receiver", "status": "OK"}'
51     fake_msg["payload"] = pay
52     new_messages = [fake_msg]
53     return new_messages
54
55
56 def _test_put_patch(monkeypatch):
57     rmr_mocks.patch_rmr(monkeypatch)
58     monkeypatch.setattr("rmr.rmr.rmr_send_msg", rmr_mocks.send_mock_generator(0))  # good sends for this whole batch
59
60     # we need to repatch alloc (already patched in patch_rmr) to fix the transactionid, alloc is called in send and recieve
61     def fake_alloc(_unused, _alsounused):
62         sbuf = rmr_mocks.Rmr_mbuf_t()
63         sbuf.contents.xaction = b"d49b53e478b711e9a1130242ac110002"
64         return sbuf
65
66     # we also need to repatch set, since in the send function, we alloc, then set a new transid
67     def fake_set_transactionid(sbuf):
68         sbuf.contents.xaction = b"d49b53e478b711e9a1130242ac110002"
69
70     # Note, we could have just patched summary, but this patches at a "lower level" so is a better test
71     monkeypatch.setattr("rmr.rmr.rmr_alloc_msg", fake_alloc)
72     monkeypatch.setattr("rmr.rmr.generate_and_set_transaction_id", fake_set_transactionid)
73
74
75 # Actual Tests
76
77
78 def test_xapp_put_good(client, monkeypatch, adm_type_good, adm_instance_good):
79     """ test policy put good"""
80
81     # no type there yet
82     res = client.get(ADM_CTRL_TYPE)
83     assert res.status_code == 404
84
85     # put the type
86     res = client.put(ADM_CTRL_TYPE, json=adm_type_good)
87     assert res.status_code == 201
88
89     # there now
90     res = client.get(ADM_CTRL_TYPE)
91     assert res.status_code == 200
92     assert res.json == adm_type_good
93
94     # no instance there yet
95     res = client.get(ADM_CTRL_INSTANCE)
96     assert res.status_code == 404
97     res = client.get(ADM_CTRL_INSTANCE_STATUS)
98     assert res.status_code == 404
99
100     # create a good instance
101     _test_put_patch(monkeypatch)
102     res = client.put(ADM_CTRL_INSTANCE, json=adm_instance_good)
103     assert res.status_code == 201
104
105     # get the instance
106     res = client.get(ADM_CTRL_INSTANCE)
107     assert res.status_code == 200
108     assert res.json == adm_instance_good
109
110     # get the instance status
111     monkeypatch.setattr("a1.a1rmr.dequeue_all_waiting_messages", _fake_dequeue)
112     res = client.get(ADM_CTRL_INSTANCE_STATUS)
113     assert res.status_code == 200
114     assert res.json == [{"handler_id": "test_receiver", "status": "OK"}]
115
116     # assert that rmr bad states don't cause problems
117     monkeypatch.setattr("rmr.rmr.rmr_send_msg", rmr_mocks.send_mock_generator(10))
118     res = client.put(ADM_CTRL_INSTANCE, json=adm_instance_good)
119     assert res.status_code == 201
120
121     monkeypatch.setattr("rmr.rmr.rmr_send_msg", rmr_mocks.send_mock_generator(5))
122     res = client.put(ADM_CTRL_INSTANCE, json=adm_instance_good)
123     assert res.status_code == 201
124
125
126 # def test_xapp_put_bad(client, monkeypatch):
127 #     """Test policy put fails"""
128 #     _test_put_patch(monkeypatch)
129 #     # return from policy handler has a status indicating FAIL
130 #     monkeypatch.setattr(
131 #         "a1.a1rmr.dequeue_all_waiting_messages", _fake_dequeue(monkeypatch, msg_payload={"status": "FAIL", "foo": "bar"})
132 #     )
133 #     res = client.put("/a1-p/policies/admission_control_policy", json=testing_helpers.good_payload())
134 #     assert res.status_code == 502
135 #     assert res.json["reason"] == "BAD STATUS"
136 #     assert res.json["return_payload"] == {"status": "FAIL", "foo": "bar"}
137 #
138 #     # return from policy handler has no status field
139 #     monkeypatch.setattr("a1.a1rmr.dequeue_all_waiting_messages", _fake_dequeue(monkeypatch, msg_payload={"foo": "bar"}))
140 #     res = client.put("/a1-p/policies/admission_control_policy", json=testing_helpers.good_payload())
141 #     assert res.status_code == 502
142 #     assert res.json["reason"] == "NO STATUS"
143 #     assert res.json["return_payload"] == {"foo": "bar"}
144 #
145 #     # return from policy handler not a json
146 #     monkeypatch.setattr(
147 #         "a1.a1rmr.dequeue_all_waiting_messages", _fake_dequeue(monkeypatch, msg_payload="booger", jsonb=False)
148 #     )
149 #     res = client.put("/a1-p/policies/admission_control_policy", json=testing_helpers.good_payload())
150 #     assert res.status_code == 502
151 #     assert res.json["reason"] == "NOT JSON"
152 #     assert res.json["return_payload"] == "booger"
153 #
154 #     # bad type
155 #     monkeypatch.setattr("a1.a1rmr.dequeue_all_waiting_messages", _fake_dequeue(monkeypatch, msg_type=666))
156 #     res = client.put("/a1-p/policies/admission_control_policy", json=testing_helpers.good_payload())
157 #     assert res.status_code == 504
158 #     assert res.data == b"\"A1 was expecting an ACK back but it didn't receive one or didn't recieve the expected ACK\"\n"
159 #
160 #     # bad state
161 #     monkeypatch.setattr("a1.a1rmr.dequeue_all_waiting_messages", _fake_dequeue(monkeypatch, msg_state=666))
162 #     res = client.put("/a1-p/policies/admission_control_policy", json=testing_helpers.good_payload())
163 #     assert res.status_code == 504
164 #     assert res.data == b"\"A1 was expecting an ACK back but it didn't receive one or didn't recieve the expected ACK\"\n"
165
166
167 def test_bad_instances(client, monkeypatch, adm_type_good):
168     """
169     Test bad send failures
170     """
171     rmr_mocks.patch_rmr(monkeypatch)
172
173     # TODO: reenable this after delete!
174     # put the type
175     # res = client.put(ADM_CTRL_TYPE, json=adm_type_good)
176     # assert res.status_code == 201
177
178     # illegal type range
179     res = client.put("/a1-p/policytypes/19999", json=adm_type_good)
180     assert res.status_code == 400
181     res = client.put("/a1-p/policytypes/21024", json=adm_type_good)
182     assert res.status_code == 400
183
184     # bad body
185     res = client.put(ADM_CTRL_INSTANCE, json={"not": "expected"})
186     assert res.status_code == 400
187
188     # bad media type
189     res = client.put(ADM_CTRL_INSTANCE, data="notajson")
190     assert res.status_code == 415
191
192
193 def test_healthcheck(client):
194     """
195     test healthcheck
196     """
197     res = client.get("/a1-p/healthcheck")
198     assert res.status_code == 200