blob: 2b519835a12d0a8f1bdb174a72aec4287646bf2d [file] [log] [blame]
Alex Shatova39f4e82018-12-05 15:23:50 -05001# ============LICENSE_START=======================================================
Alex Shatov78ff88f2020-02-27 12:45:54 -05002# Copyright (c) 2018-2020 AT&T Intellectual Property. All rights reserved.
Alex Shatova39f4e82018-12-05 15:23:50 -05003# ================================================================================
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15# ============LICENSE_END=========================================================
16#
Alex Shatova39f4e82018-12-05 15:23:50 -050017"""record all the messages going outside policy-handler during testing"""
18
19import copy
20import json
21
Alex Shatov9a4d3c52019-04-01 11:32:06 -040022from policyhandler.config import Config
Alex Shatov78ff88f2020-02-27 12:45:54 -050023from policyhandler.onap.audit import (REQUEST_X_ECOMP_REQUESTID,
24 REQUEST_X_ONAP_REQUESTID)
Alex Shatov9a4d3c52019-04-01 11:32:06 -040025from policyhandler.utils import Utils
Alex Shatova39f4e82018-12-05 15:23:50 -050026
Alex Shatov78ff88f2020-02-27 12:45:54 -050027REQUEST = "request"
28STATUS_CODE = "status_code"
Alex Shatova39f4e82018-12-05 15:23:50 -050029RESPONSE = "res"
Alex Shatov9a4d3c52019-04-01 11:32:06 -040030PEP_INSTANCE = "ONAPInstance"
31_LOGGER = Utils.get_logger(__file__)
Alex Shatova39f4e82018-12-05 15:23:50 -050032
33class _MockHttpRequestInResponse(object):
34 """Mock http request in reponse object"""
35 def __init__(self, method, uri, **kwargs):
36 self.method = method
37 self.uri = uri
38 self.params = copy.deepcopy(kwargs.get("params"))
39 self.req_json = copy.deepcopy(kwargs.get("json"))
40 self.headers = copy.deepcopy(kwargs.get("headers"))
41
42 def to_json(self):
43 """create json of the request"""
44 return {
45 "method": self.method,
46 "uri": self.uri,
47 "params": self.params,
48 "json": self.req_json,
49 "headers": self.headers
50 }
51
52
53class MockHttpResponse(object):
54 """Mock http response based on request"""
Alex Shatov78ff88f2020-02-27 12:45:54 -050055 def __init__(self, method, uri, res_json=None, **kwargs):
Alex Shatova39f4e82018-12-05 15:23:50 -050056 """create response based on request"""
57 self.request = _MockHttpRequestInResponse(method, uri, **kwargs)
Alex Shatov78ff88f2020-02-27 12:45:54 -050058 self.headers = {}
Alex Shatova39f4e82018-12-05 15:23:50 -050059
Alex Shatov78ff88f2020-02-27 12:45:54 -050060 self.status_code, self.res = Tracker.get_response(self.request.to_json())
61 if self.status_code is None and res_json:
62 self.status_code = kwargs.get(STATUS_CODE, 200)
63 if res_json:
64 self.res = copy.deepcopy(res_json)
65 if self.status_code is None:
66 self.status_code = 500
Alex Shatova39f4e82018-12-05 15:23:50 -050067 self.text = json.dumps(self.res)
68
Alex Shatov78ff88f2020-02-27 12:45:54 -050069 _LOGGER.info("MockHttpResponse: %s", self)
Alex Shatova39f4e82018-12-05 15:23:50 -050070
71 def json(self):
72 """returns json of response"""
73 return self.res
74
75 def raise_for_status(self):
76 """ignoring"""
77 pass
78
79 def to_json(self):
80 """create json of the message"""
81 return {
Alex Shatov78ff88f2020-02-27 12:45:54 -050082 REQUEST: self.request.to_json(),
83 STATUS_CODE: self.status_code,
Alex Shatova39f4e82018-12-05 15:23:50 -050084 RESPONSE: self.res
85 }
86
Alex Shatova39f4e82018-12-05 15:23:50 -050087 def __str__(self):
88 """stringify for logging"""
89 return json.dumps(self.to_json(), sort_keys=True)
90
91
92class Tracker(object):
93 """record all the messages going outside policy-handler during testing"""
94 test_name = None
Alex Shatov9a4d3c52019-04-01 11:32:06 -040095 test_names = []
Alex Shatov78ff88f2020-02-27 12:45:54 -050096
97 requests = []
98 expected = []
99
Alex Shatov9a4d3c52019-04-01 11:32:06 -0400100 validated_tests = {}
101 valid_tests = {}
Alex Shatova39f4e82018-12-05 15:23:50 -0500102
Alex Shatov78ff88f2020-02-27 12:45:54 -0500103 main_history = {}
104 pdp_api_v0_history = {}
105
106 @staticmethod
107 def _init():
108 """load expected data from json files"""
109 try:
110 with open("tests/main/expectations.json", 'r') as expectations:
111 Tracker.main_history = json.load(expectations)
112 except Exception:
113 Tracker.main_history = {}
114
115 try:
116 with open("tests/pdp_api_v0/expectations.json", 'r') as expectations:
117 Tracker.pdp_api_v0_history = json.load(expectations)
118 except Exception:
119 Tracker.pdp_api_v0_history = {}
120
Alex Shatova39f4e82018-12-05 15:23:50 -0500121 @staticmethod
Alex Shatov9a4d3c52019-04-01 11:32:06 -0400122 def reset(test_name=None):
Alex Shatova39f4e82018-12-05 15:23:50 -0500123 """remove all the messages from history"""
Alex Shatov78ff88f2020-02-27 12:45:54 -0500124 if not Tracker.test_names:
125 Tracker._init()
126
Alex Shatova39f4e82018-12-05 15:23:50 -0500127 Tracker.test_name = test_name
Alex Shatov78ff88f2020-02-27 12:45:54 -0500128 Tracker.requests.clear()
Alex Shatov9a4d3c52019-04-01 11:32:06 -0400129 Tracker.test_names.append(test_name)
Alex Shatova39f4e82018-12-05 15:23:50 -0500130
Alex Shatov78ff88f2020-02-27 12:45:54 -0500131 if Config.is_pdp_api_default():
132 Tracker.expected = Tracker.main_history.get(Tracker.test_name, [])
133 else:
134 Tracker.expected = Tracker.pdp_api_v0_history.get(Tracker.test_name, [])
135
136
Alex Shatova39f4e82018-12-05 15:23:50 -0500137 @staticmethod
Alex Shatov78ff88f2020-02-27 12:45:54 -0500138 def get_response(request):
139 """
140 track the request to the history of requests
141 and return the response with the status_code from the expected history queue
142 """
143 request_idx = len(Tracker.requests)
144 request = copy.deepcopy(request)
145 Tracker.requests.append(request)
146
147 if request_idx < len(Tracker.expected):
148 expected = Tracker.expected[request_idx] or {}
149 masked_request = Tracker._hide_volatiles(copy.deepcopy(request))
150 expected_request = Tracker._hide_volatiles(copy.deepcopy(expected.get(REQUEST)))
151 if Utils.are_the_same(masked_request, expected_request):
152 _LOGGER.info("as expected[%s]: %s", request_idx,
153 json.dumps(expected, sort_keys=True))
154 return expected.get(STATUS_CODE), expected.get(RESPONSE)
155
156 unexpected_request = {"unit-test-tracker": {
157 "request_idx": request_idx,
158 "received_request": copy.deepcopy(request),
159 "expected": copy.deepcopy(expected.get(REQUEST))
160 }}
161 _LOGGER.error("unexpected_request[%s]: %s", request_idx,
162 json.dumps(unexpected_request, sort_keys=True))
163 return None, unexpected_request
164
165 unexpected_request = {"unit-test-tracker":{
166 "request_idx": request_idx, "out-of-range": len(Tracker.expected),
167 "received_request": copy.deepcopy(request)
168 }}
169 _LOGGER.error("unexpected_request[%s]: %s", request_idx,
170 json.dumps(unexpected_request, sort_keys=True))
171 return None, unexpected_request
Alex Shatova39f4e82018-12-05 15:23:50 -0500172
173 @staticmethod
174 def to_string():
175 """stringify message history for logging"""
Alex Shatov78ff88f2020-02-27 12:45:54 -0500176 return json.dumps(Tracker.requests, sort_keys=True)
Alex Shatova39f4e82018-12-05 15:23:50 -0500177
178 @staticmethod
Alex Shatov9a4d3c52019-04-01 11:32:06 -0400179 def get_status(test_name=None):
180 """get the status of validation"""
181 if Tracker.valid_tests.get(test_name):
182 return "success"
183 if Tracker.validated_tests.get(test_name):
184 return "failed"
185 if test_name in Tracker.test_names:
186 return "covered"
187 return "unknown"
188
189 @staticmethod
190 def log_all_tests():
191 """log the covered and not covered test names"""
192 _LOGGER.info("-"*75)
193 _LOGGER.info("tracked test_names[%s]", len(Tracker.test_names))
194 for idx, test_name in enumerate(Tracker.test_names):
195 _LOGGER.info("%s[%s]: %s", Tracker.get_status(test_name), (idx + 1), test_name)
196
Alex Shatov78ff88f2020-02-27 12:45:54 -0500197 _LOGGER.info("not tracked test_names listed in main.expectations")
198
199 for test_name in Tracker.main_history:
Alex Shatov9a4d3c52019-04-01 11:32:06 -0400200 if test_name not in Tracker.test_names:
201 _LOGGER.info("untracked: %s", test_name)
202
Alex Shatov78ff88f2020-02-27 12:45:54 -0500203 _LOGGER.info("not tracked test_names listed in pdp_api_v0.expectations")
204 for test_name in Tracker.pdp_api_v0_history:
Alex Shatov9a4d3c52019-04-01 11:32:06 -0400205 if test_name not in Tracker.test_names:
206 _LOGGER.info("untracked: %s", test_name)
207
208 @staticmethod
Alex Shatova39f4e82018-12-05 15:23:50 -0500209 def _hide_volatiles(obj):
210 """hides the volatile field values"""
211 if not isinstance(obj, dict):
212 return obj
213
214 for key, value in obj.items():
Alex Shatov78ff88f2020-02-27 12:45:54 -0500215 if key in [REQUEST_X_ONAP_REQUESTID, REQUEST_X_ECOMP_REQUESTID, RESPONSE, PEP_INSTANCE]:
Alex Shatova39f4e82018-12-05 15:23:50 -0500216 obj[key] = "*"
217 elif isinstance(value, dict):
218 obj[key] = Tracker._hide_volatiles(value)
219
220 return obj
221
222 @staticmethod
223 def validate():
224 """validate that the message history is as expected"""
Alex Shatov9a4d3c52019-04-01 11:32:06 -0400225 _LOGGER.info("Tracker.validate(%s)", Tracker.test_name)
Alex Shatov9a4d3c52019-04-01 11:32:06 -0400226 Tracker.validated_tests[Tracker.test_name] = True
Alex Shatov78ff88f2020-02-27 12:45:54 -0500227 requests = [Tracker._hide_volatiles(copy.deepcopy(request))
228 for request in Tracker.requests]
229 expected_reqs = [Tracker._hide_volatiles(copy.deepcopy(expected.get(REQUEST)))
230 for expected in Tracker.expected]
Alex Shatova39f4e82018-12-05 15:23:50 -0500231
Alex Shatov78ff88f2020-02-27 12:45:54 -0500232 _LOGGER.info("requests: %s", json.dumps(requests, sort_keys=True))
233 _LOGGER.info("expected: %s", json.dumps(expected_reqs, sort_keys=True))
234 assert Utils.are_the_same(requests, expected_reqs)
Alex Shatova39f4e82018-12-05 15:23:50 -0500235
Alex Shatov9a4d3c52019-04-01 11:32:06 -0400236 _LOGGER.info("history valid for Tracker.validate(%s)", Tracker.test_name)
237 Tracker.valid_tests[Tracker.test_name] = True