2 ==================================================================================
4 Copyright (c) 2018-2019 AT&T Intellectual Property.
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 ==================================================================================
20 /* Author : Ashwin Sridharan
24 #define CATCH_CONFIG_MAIN
25 #include <catch2/catch.hpp>
28 #include <admission_policy.hpp>
30 #define SCHEMA_FILE "../schemas/rate-control-policy.json"
31 #define SAMPLE_FILE "../schemas/samples.json"
32 #define VES_FILE "../schemas/ves_schema.json"
33 #define INVALID_JSON "./test-data/invalid.json"
34 #define VALID_JSON "./test-data/valid.json"
36 bool report_mode_only = false;
38 TEST_CASE("Admission Policy Wrapper", "[acxapp]"){
41 mdclog_attr_init(&attr);
42 mdclog_attr_set_ident(attr, "UNIT TEST MESSAGE PROCESSOR ");
44 mdclog_level_set(MDCLOG_DEBUG);
45 mdclog_attr_destroy(attr);
47 std::string xapp_id = "ac-xapp-test123";
49 SECTION("Invalid number of instances requested"){
50 REQUIRE_THROWS( admission(SCHEMA_FILE, SAMPLE_FILE, VES_FILE, 0, xapp_id));
51 REQUIRE_THROWS( admission(SCHEMA_FILE, SAMPLE_FILE, VES_FILE, -1, xapp_id));
52 REQUIRE_THROWS( admission(SCHEMA_FILE, SAMPLE_FILE, VES_FILE, 1000, xapp_id));
55 SECTION("Invalid AC xAPP Schema file "){
56 REQUIRE_THROWS( admission("hello there", SAMPLE_FILE, VES_FILE, 1, xapp_id));
59 SECTION("Invalid sample file"){
60 REQUIRE_THROWS(admission(SCHEMA_FILE, "hello there", VES_FILE, 1, xapp_id));
63 SECTION("Invalid VES schema file "){
64 REQUIRE_THROWS(admission(SCHEMA_FILE, SAMPLE_FILE, "hello there", 1, xapp_id));
67 SECTION("Invalid JSON in a schema"){
68 REQUIRE_THROWS(admission(INVALID_JSON, SAMPLE_FILE, VES_FILE, 1, xapp_id));
71 SECTION("Valid JSON, but no valid schema key"){
72 REQUIRE_THROWS(admission(VALID_JSON, SAMPLE_FILE, VES_FILE, 1, xapp_id));
73 REQUIRE_THROWS(admission(SCHEMA_FILE, VALID_JSON, VES_FILE, 1, xapp_id));
77 SECTION("Test policy schema validation"){
81 std::string valid_policy = "{\"policy_type_id\":21000, \"policy_instance_id\":\"hello-there\", \"operation\":\"CREATE\", \"payload\":{\"blocking_rate\":20, \"enforce\":true, \"window_length\":50, \"trigger_threshold\":10, \"class\":14}}";
83 std::string invalid_policy1 = "{\"policy_type_id\":21000, \"policy_instance_id\":\"hello-there\", \"operation\":\"CREATE\", \"payload\":{\"blocking_rate\":20, \"enforce\":true, \"window_length\":50, \"trigger_threshold\":10, \"class\":5000}}";
85 std::string invalid_policy2 = "{\"policy_instance_id\":\"hello-there\", \"operation\":\"CREATE\", \"payload\":{\"blocking_rate\":20, \"enforce\":true, \"window_length\":50, \"trigger_threshold\":10, \"class\":14}}";
87 std::string invalid_policy3 = "{\"policy_type_id\":21000, \"policy_instance_id\":\"hello-there\", \"operation\":\"CREATED\", \"payload\":{\"blocking_rate\":20, \"enforce\":true, \"window_length\":50, \"trigger_threshold\":10, \"class\":14}}";
89 std::string invalid_policy4 = "{\"policy_type_id\":21000, \"policy_instance_id\":\"hello-there\", \"operation\":\"CREATE\", \"payload\":{\"blocking_rate\":20, \"enforce\":true, \"window_length\":50, \"trigger_threshold\":10}}";
91 std::string invalid_policy5 = "hello-there";
93 admission adm_plugin(SCHEMA_FILE, SAMPLE_FILE, VES_FILE, 1, xapp_id);
95 REQUIRE_THAT(adm_plugin.getName(), Catch::Matchers::Equals("admission control policy"));
97 res = adm_plugin.setPolicy(invalid_policy1.c_str(), invalid_policy1.length(), response);
98 REQUIRE(res == false);
100 res = adm_plugin.setPolicy(invalid_policy2.c_str(), invalid_policy2.length(), response);
101 REQUIRE(res == false);
103 res = adm_plugin.setPolicy(invalid_policy3.c_str(), invalid_policy3.length(), response);
104 REQUIRE(res == false);
106 res = adm_plugin.setPolicy(invalid_policy4.c_str(), invalid_policy4.length(), response);
107 REQUIRE(res == false);
109 res = adm_plugin.setPolicy(invalid_policy5.c_str(), invalid_policy5.length(), response);
110 REQUIRE(res == false);
112 res = adm_plugin.setPolicy(valid_policy.c_str(), valid_policy.length(), response);
113 REQUIRE(res == true);
118 SECTION("Test Set/configure/delete policy"){
119 std::string policy = "{\"policy_type_id\":21000, \"policy_instance_id\":\"hello-there\", \"operation\":\"CREATE\", \"payload\":{\"blocking_rate\":20, \"enforce\":true, \"window_length\":50, \"trigger_threshold\":10, \"class\":14}}";
120 std::string delete_policy = "{\"policy_type_id\":21000, \"policy_instance_id\":\"hello-there\", \"operation\":\"DELETE\"}";
124 std::string response, test_policy, policy_instance_id;
125 rapidjson::Document doc;
126 rapidjson::StringBuffer s_buffer;
127 rapidjson::Writer<rapidjson::StringBuffer> writer(s_buffer);
129 int num_policies = 10;
130 admission adm_plugin(SCHEMA_FILE, SAMPLE_FILE, VES_FILE, 1, xapp_id);
131 doc.Parse(policy.c_str());
132 for(int i = 1; i <= num_policies; i++){
133 policy_instance_id = "rate_control_policy_" + std::to_string(i);
134 rapidjson::SetValueByPointer(doc, "/policy_instance_id", policy_instance_id.c_str());
135 rapidjson::SetValueByPointer(doc, "/payload/class", i);
137 writer.Reset(s_buffer);
139 test_policy.assign(s_buffer.GetString(), s_buffer.GetLength());
141 // valid policy should succeed
142 res = adm_plugin.setPolicy(test_policy.c_str(), test_policy.length(), response);
143 std::cout <<"Response1 = " << response << std::endl;
144 REQUIRE(res == true);
146 // trying to add policy with same class as before should also return true
147 res = adm_plugin.setPolicy(test_policy.c_str(), test_policy.length(), response);
148 REQUIRE(res == true);
152 REQUIRE(adm_plugin.get_num_policies() == num_policies);
154 // configure existing policy should work
155 rapidjson::SetValueByPointer(doc, "/operation", "UPDATE");
156 for(int i = 1; i <= num_policies; i++){
157 policy_instance_id = "rate_control_policy_" + std::to_string(i);
158 rapidjson::SetValueByPointer(doc, "/policy_instance_id", policy_instance_id.c_str());
159 rapidjson::SetValueByPointer(doc, "/payload/class", i);
160 rapidjson::SetValueByPointer(doc, "/payload/blocking_rate", 55.0);
162 writer.Reset(s_buffer);
164 test_policy.assign(s_buffer.GetString(), s_buffer.GetLength());
166 // valid policy should succeed
167 res = adm_plugin.setPolicy(test_policy.c_str(), test_policy.length(), response);
168 REQUIRE(res == true);
172 // configure non-existing policy should fail
173 policy_instance_id = "rate_control_policy_" + std::to_string(1000);
174 rapidjson::SetValueByPointer(doc, "/policy_instance_id", policy_instance_id.c_str());
176 writer.Reset(s_buffer);
178 test_policy.assign(s_buffer.GetString(), s_buffer.GetLength());
179 res = adm_plugin.setPolicy(test_policy.c_str(), test_policy.length(), response);
180 REQUIRE(res == false);
182 // configure exsting policy but with non-existing class should fail
183 policy_instance_id = "rate_control_policy_" + std::to_string(1);
184 rapidjson::SetValueByPointer(doc, "/policy_instance_id", policy_instance_id.c_str());
185 rapidjson::SetValueByPointer(doc, "/payload/class", 200);
187 writer.Reset(s_buffer);
189 test_policy.assign(s_buffer.GetString(), s_buffer.GetLength());
190 res = adm_plugin.setPolicy(test_policy.c_str(), test_policy.length(), response);
191 REQUIRE(res == false);
193 // delete existing policy should work
194 doc.Parse(delete_policy.c_str());
195 for(int i = 1; i <= num_policies; i++){
196 std::string policy_instance_id = "rate_control_policy_" + std::to_string(i);
197 rapidjson::SetValueByPointer(doc, "/policy_instance_id", policy_instance_id.c_str());
199 writer.Reset(s_buffer);
201 test_policy.assign(s_buffer.GetString(), s_buffer.GetLength());
203 // delete policy should succeed since these policies were created
204 res = adm_plugin.setPolicy(test_policy.c_str(), test_policy.length(), response);
205 REQUIRE(res == true);
208 REQUIRE(adm_plugin.get_num_policies() == 0);
210 //delete non-existing policy should fail
211 res = adm_plugin.setPolicy(test_policy.c_str(), test_policy.length(), response);
212 REQUIRE(res == false);
218 // SECTION("Get policy"){
220 // std::string valid_policy = "{\"blocking_rate\":20, \"enforce\":true, \"window_length\":50, \"trigger_threshold\":10}";
222 // std::string response;
224 // // first apply policy
225 // admission adm_plugin(SCHEMA_FILE, SAMPLE_FILE, VES_FILE, 1, xapp_id);
226 // res = adm_plugin.setPolicy(valid_policy.c_str(), valid_policy.length(), response);
227 // std::cout <<"Response = " << response << std::endl;
228 // REQUIRE(res == true);
229 // REQUIRE_THAT(response, Catch::Matchers::Contains("SUCCESS"));
232 // // now retreive policy and check
233 // res = adm_plugin.getPolicy(valid_policy.c_str(), valid_policy.length(), response);
234 // REQUIRE(res == true);
236 // REQUIRE_THAT(response, Catch::Matchers::Contains("\"trigger_threshold\":10"));
242 std::string policy = "{\"policy_type_id\":21000, \"policy_instance_id\":\"hello-there\", \"operation\":\"CREATE\", \"payload\":{\"blocking_rate\":20, \"enforce\":true, \"window_length\":50, \"trigger_threshold\":10, \"class\":14}}";
245 std::string response, test_policy, policy_instance_id;
246 rapidjson::Document doc;
247 rapidjson::StringBuffer s_buffer;
248 rapidjson::Writer<rapidjson::StringBuffer> writer(s_buffer);
250 int num_policies = 10;
251 admission adm_plugin(SCHEMA_FILE, SAMPLE_FILE, VES_FILE, 1, xapp_id);
252 doc.Parse(policy.c_str());
253 // Add some policies first
254 for(int i = 1; i <= num_policies; i++){
255 policy_instance_id = "rate_control_policy_" + std::to_string(i);
256 rapidjson::SetValueByPointer(doc, "/policy_instance_id", policy_instance_id.c_str());
257 rapidjson::SetValueByPointer(doc, "/payload/class", i);
259 writer.Reset(s_buffer);
261 test_policy.assign(s_buffer.GetString(), s_buffer.GetLength());
263 // valid policy should succeed
264 res = adm_plugin.setPolicy(test_policy.c_str(), test_policy.length(), response);
265 REQUIRE(res == true);
266 //REQUIRE_THAT(response, Catch::Matchers::Contains("SUCCESS"));
271 // First time, measurementInterval should be zero
272 std::vector<std::string> metrics;
273 adm_plugin.getMetrics(metrics);
274 REQUIRE(metrics.size() == num_policies + 1);
275 for(auto const e : metrics){
276 std::cout << e<< std::endl;
277 REQUIRE_THAT(e, Catch::Matchers::Contains("\"Class Id\""));
278 REQUIRE_THAT(e, Catch::Matchers::Contains("\"measurementInterval\":\"0\""));
282 // wait for 'x' seconds and try again
283 std::this_thread::sleep_for(std::chrono::seconds(interval));
284 rapidjson::Pointer int_ref("/event/measurementFields/measurementInterval");
287 adm_plugin.getMetrics(metrics);
288 REQUIRE(metrics.size() == num_policies + 1);
289 for(auto const e : metrics){
290 REQUIRE(doc.Parse(e.c_str()).HasParseError() == 0);
291 std::cout << e<< std::endl;
292 REQUIRE_THAT(e, Catch::Matchers::Contains("\"Class Id\""));
293 // extract measurement interval
294 rapidjson::Value *interval_val = int_ref.Get(doc);
295 REQUIRE(interval_val != NULL);
296 double read_interval_approx = atof(interval_val->GetString());
297 REQUIRE(read_interval_approx == Approx(interval).margin(1));
303 SECTION("Get plugin"){
304 admission adm_plugin(SCHEMA_FILE, SAMPLE_FILE, VES_FILE, 1, xapp_id);
305 protector * p = NULL;
306 p = adm_plugin.get_protector_instance(100);
309 p = adm_plugin.get_protector_instance(0);
311 REQUIRE(p->get_requests(0) == 0);