Updated documentation for mock a1 tool
[ric-app/admin.git] / test / unit_test_protector_plugin.cc
1 /*
2 ==================================================================================
3
4         Copyright (c) 2018-2019 AT&T Intellectual Property.
5
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
9
10        http://www.apache.org/licenses/LICENSE-2.0
11
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 ==================================================================================
18 */
19
20 /* Author : Ashwin Sridharan
21    Date   : Nov 2019
22 */
23
24 #define CATCH_CONFIG_MAIN
25 #include <catch2/catch.hpp>
26
27 #include <NetworkProtector.h>
28
29
30 TEST_CASE("Protector Plugin", "Test Input types"){
31
32
33   mdclog_attr_t *attr;
34   mdclog_attr_init(&attr);
35   mdclog_attr_set_ident(attr, "UNIT TEST PROTECTOR PLUGIN ");
36   mdclog_init(attr);
37   mdclog_level_set(MDCLOG_ERR);
38   mdclog_attr_destroy(attr);
39   FILE *pfile;
40  
41   unsigned char scratch_buf[512];
42   size_t scratch_buf_size = 512;
43
44   // Load buffers with different types of X2AP PDUs to test
45   // behaviour if valid/invalid
46   //========================================================
47   // valid x2 sgnb addition request  
48   unsigned char x2ap_buf[256];
49   size_t x2ap_buf_size ;
50   pfile = fopen("test-data/X2AP-PDU-SgNBAdditionRequest.per", "r");
51   REQUIRE(pfile != NULL);
52   x2ap_buf_size = fread((char *)x2ap_buf, sizeof(char), 256, pfile);
53   fclose(pfile);
54
55
56   // incorrect x2ap pdu 
57   srand(10902390);
58   unsigned char incorrect_x2ap_buf[8192];
59   size_t incorrect_x2ap_buf_size = 8192;
60   for(int i = 0; i < 8192; i++){
61     incorrect_x2ap_buf[i] = rand()%256;
62   }
63
64   // valid x2 but not an initiating message
65   unsigned char x2ap_sgnb_ack[512];
66   size_t x2ap_sgnb_ack_size;
67   pfile = fopen("test-data/X2AP-PDU-SgNBAdditionAck.per", "r");
68   REQUIRE(pfile != NULL);
69   x2ap_sgnb_ack_size = fread((char *)x2ap_sgnb_ack, sizeof(char), 512, pfile);
70   fclose(pfile);
71
72   //valid x2 initiating message, but not sgnb addition request
73   unsigned char x2ap_resource_req_buf[512];
74   size_t x2ap_resource_req_buf_size;
75   pfile = fopen("test-data/X2AP-PDU-ResourceStatusRequest.per", "r");
76   REQUIRE(pfile != NULL);
77   x2ap_resource_req_buf_size = fread((char *)x2ap_resource_req_buf, sizeof(char), 512, pfile);
78   fclose(pfile);
79
80
81   SECTION("Valid X2 SgnB Addition Request"){
82     protector n_plugin(false);
83     bool res = n_plugin(x2ap_buf, x2ap_buf_size, scratch_buf, &scratch_buf_size);
84     REQUIRE(res == true);
85     REQUIRE(n_plugin.get_requests(0) == 1);
86
87     // todo: need to validate response ...
88     // decode x2ap response
89     // verify it is a successful message and compare against input x2ap ..
90
91   }
92
93   SECTION("Invalid X2 message"){
94     protector n_plugin(1, 20, 5, 0, false);
95     bool res = n_plugin(incorrect_x2ap_buf, incorrect_x2ap_buf_size, scratch_buf, &scratch_buf_size);
96     REQUIRE(res == false);
97     REQUIRE(n_plugin.get_requests(0) == 0);
98   }
99
100   SECTION("Valid X2 but not Initating message"){
101
102     protector n_plugin(1, 20, 5, 0, false);
103     bool res = n_plugin(x2ap_sgnb_ack, x2ap_sgnb_ack_size, scratch_buf, &scratch_buf_size);
104     REQUIRE(res == false);
105     REQUIRE(n_plugin.get_requests(0) == 0);
106   }
107   
108
109   SECTION("Valid X2 Initiating but not SgNB Addition Request"){
110     
111     protector n_plugin(1, 20, 5, 0, false);
112     bool res = n_plugin(x2ap_resource_req_buf, x2ap_resource_req_buf_size, scratch_buf, &scratch_buf_size);
113     REQUIRE(res == false);
114     REQUIRE(n_plugin.get_requests(0) == 0);
115     
116   }
117
118   SECTION("Cycle through various messages"){
119     int num_cycles = 1000;
120     int num_valid = 0;
121     protector n_plugin(1, 20, 5, 0, false);
122     bool res;
123     
124     for(int i = 0; i < num_cycles;i++){
125       scratch_buf_size = 512;
126       res = n_plugin(x2ap_buf, x2ap_buf_size, scratch_buf, &scratch_buf_size);
127       REQUIRE(res == true);
128       num_valid ++;
129       
130       res = n_plugin(x2ap_sgnb_ack, x2ap_sgnb_ack_size, scratch_buf, &scratch_buf_size);
131       REQUIRE(res == false);
132       
133       res = n_plugin(x2ap_resource_req_buf, x2ap_resource_req_buf_size, scratch_buf, &scratch_buf_size);
134       REQUIRE(res == false);
135   
136       res = n_plugin(incorrect_x2ap_buf, incorrect_x2ap_buf_size, scratch_buf, &scratch_buf_size);
137       REQUIRE(res == false);
138       
139     }
140     
141     REQUIRE(num_valid == n_plugin.get_requests(0));
142     REQUIRE(num_valid == n_plugin.get_requests(-1));
143     REQUIRE(n_plugin.get_rejects(0) == 0);
144
145   }
146
147
148   
149
150   SECTION("No blocking"){
151     bool res;
152     int num_packets = 1000;
153     protector n_plugin(1, 20, 5, 0, false);
154     for(int i = 0; i < num_packets; i++){
155       res = n_plugin(x2ap_buf, x2ap_buf_size, scratch_buf, &scratch_buf_size);
156       REQUIRE(res == true);
157     }
158
159     REQUIRE(n_plugin.get_requests(0) == num_packets);
160     REQUIRE(n_plugin.get_rejects(0) == 0);
161     
162   }
163     
164   SECTION("All blocking"){
165     bool res;
166     int num_packets = 1000;
167     protector n_plugin(1, 20, 0, 100, false);
168     for(int i = 0; i < num_packets; i++){
169       scratch_buf_size = 512;
170       res = n_plugin(x2ap_buf, x2ap_buf_size, scratch_buf, &scratch_buf_size);
171       REQUIRE(res == true);
172     }
173
174     REQUIRE(n_plugin.get_requests(0) == num_packets);
175     REQUIRE(n_plugin.get_rejects(0) == num_packets);
176
177     REQUIRE(n_plugin.get_requests(-1) == num_packets);
178     REQUIRE(n_plugin.get_rejects(-1) == num_packets);
179   }
180
181   SECTION("Add/delete/configure/query policies"){
182     bool res;
183     int policy_id = 5;
184     std::vector<double> info;
185     std::vector<int> active_list;
186
187     protector n_plugin(1, 20, 0, 100, false);
188
189     // metrics query default policy always returns
190     REQUIRE(n_plugin.get_requests(0) == 0);
191     REQUIRE(n_plugin.get_rejects(0) == 0);
192     
193     //metrics invalid policy returns -1;
194     REQUIRE(n_plugin.get_requests(100) == -1);
195     REQUIRE(n_plugin.get_rejects(100) == -1);
196
197     // 1 active policy
198     n_plugin.get_active_policies(active_list);
199     REQUIRE(active_list.size() == 1);
200
201     // verify returned policy
202     REQUIRE(n_plugin.is_active(active_list[0]) == true);
203     
204     // add a policy
205     res = n_plugin.add_policy(1, 35, 10, 10, policy_id);
206     REQUIRE(res == true);
207
208     active_list.clear();
209     n_plugin.get_active_policies(active_list);
210     REQUIRE(active_list.size() == 2);
211     
212     // query default policy
213     res = n_plugin.query_policy(0, info);
214     REQUIRE(res == true);
215     REQUIRE(info.size() == 4);
216     REQUIRE(info[0] == 1);
217     REQUIRE(info[1] == 20);
218     REQUIRE(info[2] == 0);
219     REQUIRE(info[3] == 100);
220
221     // query new policy
222     info.clear();
223     res = n_plugin.query_policy(policy_id, info);
224     REQUIRE(res == true);
225     REQUIRE(info.size() == 4);
226     REQUIRE(info[0] == 1);
227     REQUIRE(info[1] == 35);
228     REQUIRE(info[2] == 10);
229     REQUIRE(info[3] == 10);
230     
231     // try adding same policy
232     res = n_plugin.add_policy(1, 200, 10, 10, policy_id);
233     REQUIRE(res == false);
234     REQUIRE_THAT(n_plugin.get_error(), Catch::Matchers::Contains("already exists"));
235     
236     // delete the policy
237     res = n_plugin.delete_policy(policy_id);
238     REQUIRE(res == true);
239
240     // delete non-existent policy
241     res = n_plugin.delete_policy(policy_id);
242     REQUIRE(res == false);
243     REQUIRE_THAT(n_plugin.get_error(), Catch::Matchers::Contains("No policy with id"));
244
245     // configure non-existent policy
246     res = n_plugin.configure(1, 20, 0, 100, policy_id);
247     REQUIRE(res == false);
248     
249     // invalid window size to configure policy
250     res = n_plugin.configure(0, -1, 0, 100, 0);
251     REQUIRE(res == false);
252     REQUIRE_THAT(n_plugin.get_error(), Catch::Matchers::Contains("Illegal value for window"));
253
254      // invalid trigger  in configure policy
255     res = n_plugin.configure(0, 12, -1, 100, 0);
256     REQUIRE(res == false);
257     REQUIRE_THAT(n_plugin.get_error(), Catch::Matchers::Contains("Illegal"));
258
259     // invalid class in configure  policy
260     res = n_plugin.configure(0, 20, 1, 100, -25);
261     REQUIRE(res == false);
262     REQUIRE_THAT(n_plugin.get_error(), Catch::Matchers::Contains("Illegal"));
263
264     // invalid blocking rate in configure policy
265     res = n_plugin.configure(0, 21, 0, 105, 0);
266     REQUIRE(res == false);
267     REQUIRE_THAT(n_plugin.get_error(), Catch::Matchers::Contains("Illegal"));
268
269
270     // invalid window size in add policy
271     res = n_plugin.add_policy(0, -1, 0, 100, 25);
272     REQUIRE(res == false);
273     REQUIRE_THAT(n_plugin.get_error(), Catch::Matchers::Contains("Illegal"));
274
275     // invalid trigger  in add policy
276     res = n_plugin.add_policy(0, 12, -1, 100, 25);
277     REQUIRE(res == false);
278     REQUIRE_THAT(n_plugin.get_error(), Catch::Matchers::Contains("Illegal"));
279
280     // invalid class in add policy
281     res = n_plugin.add_policy(0, 20, 1, 100, -25);
282     REQUIRE(res == false);
283     REQUIRE_THAT(n_plugin.get_error(), Catch::Matchers::Contains("Illegal"));
284
285     // invalid blocking rate in add policy
286     res = n_plugin.add_policy(0, 21, 0, 105, 25);
287     REQUIRE(res == false);
288     REQUIRE_THAT(n_plugin.get_error(), Catch::Matchers::Contains("Illegal"));
289
290     // query a non-existant policy
291     res = n_plugin.query_policy(200, info);
292     REQUIRE(res == false);
293
294     
295   }
296   
297   SECTION("Test turning enforcement on off "){
298     bool res;
299     protector n_plugin(1, 20, 0, 100, false);
300     int num_packets = 10;
301
302     for(int i = 0; i < num_packets; i++){
303       scratch_buf_size = 512;
304       res = n_plugin(x2ap_buf, x2ap_buf_size, scratch_buf, &scratch_buf_size);
305       REQUIRE(res == true);
306     }
307
308     // enforcement with 100% blocking. all should be rejected
309     REQUIRE(n_plugin.get_requests(0) == num_packets);
310     REQUIRE(n_plugin.get_rejects(0) == num_packets);
311     
312     n_plugin.clear();
313     REQUIRE(n_plugin.get_requests(0) == 0);
314     REQUIRE(n_plugin.get_rejects(0) == 0);
315
316     // no enforcement even if blocking set to 100%
317     // all should be accepted
318     n_plugin.configure(0, 20, 0, 100, 0);
319     for(int i = 0; i < num_packets; i++){
320       scratch_buf_size = 512;
321       res = n_plugin(x2ap_buf, x2ap_buf_size, scratch_buf, &scratch_buf_size);
322       REQUIRE(res == true);
323     }
324     
325     REQUIRE(n_plugin.get_requests(0) == num_packets);
326     REQUIRE(n_plugin.get_rejects(0) == 0);
327
328   }
329
330   SECTION("Test using various policies against pdus with  different subscriber profile ids"){
331
332     // use pre-generated X2AP PDUs with two different subscriber profile ids 
333     unsigned char x2ap1_buf[512];
334     size_t x2ap1_size;
335     unsigned char x2ap2_buf[512];
336     size_t x2ap2_size;
337     
338     pfile = fopen("test-data/X2AP-PDU-SgNBAdditionRequest_SubId_29.per", "r");
339     REQUIRE(pfile != NULL);
340     x2ap1_size = fread((char *)x2ap1_buf, sizeof(char), 512, pfile);
341     fclose(pfile);
342
343     pfile = fopen("test-data/X2AP-PDU-SgNBAdditionRequest_SubId_34.per", "r");
344     REQUIRE(pfile != NULL);
345     x2ap2_size = fread((char *)x2ap2_buf, sizeof(char), 512, pfile);
346     fclose(pfile);
347     
348     
349     bool res;
350     protector n_plugin(1, 20, 0, 100, false);
351     // test with just default policy
352     scratch_buf_size = 512;
353     res = n_plugin(x2ap1_buf, x2ap1_size, scratch_buf, &scratch_buf_size);
354     REQUIRE(res == true);
355     scratch_buf_size = 512;
356     res = n_plugin(x2ap2_buf, x2ap2_size, scratch_buf, &scratch_buf_size);
357     REQUIRE(res == true);
358     REQUIRE(n_plugin.get_requests(0) == 2);
359
360     n_plugin.clear();
361
362     // add a policy and test
363     n_plugin.add_policy(1, 20, 0, 100, 29);
364     scratch_buf_size = 512;
365     res = n_plugin(x2ap1_buf, x2ap1_size, scratch_buf, &scratch_buf_size);
366     REQUIRE(res == true);
367     scratch_buf_size = 512;
368     res = n_plugin(x2ap2_buf, x2ap2_size, scratch_buf, &scratch_buf_size);
369     REQUIRE(res == true);
370     REQUIRE(n_plugin.get_requests(0) == 1);
371     REQUIRE(n_plugin.get_requests(29) == 1);
372
373     // add another policy and test
374     n_plugin.add_policy(1, 20, 0, 100, 34);
375     scratch_buf_size = 512;
376     res = n_plugin(x2ap2_buf, x2ap2_size, scratch_buf, &scratch_buf_size);
377     REQUIRE(res == true);
378     scratch_buf_size = 512;
379     res = n_plugin(x2ap1_buf, x2ap1_size, scratch_buf, &scratch_buf_size);
380     REQUIRE(res == true);
381
382     REQUIRE(n_plugin.get_requests(34) == 1);
383     REQUIRE(n_plugin.get_requests(29) == 2);
384     REQUIRE(n_plugin.get_requests(-1) == 4); // 1 for 0, 2 for 29 and 1 for 34
385     
386   }
387 }