devtools: pass custom options to checkpatch
[dpdk.git] / lib / librte_telemetry / rte_telemetry_parser_test.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Intel Corporation
3  */
4
5 #include <stdio.h>
6 #include <stdint.h>
7 #include <string.h>
8 #include <errno.h>
9 #include <jansson.h>
10 #include <sys/socket.h>
11 #include <sys/un.h>
12 #include <unistd.h>
13
14 #include <rte_common.h>
15 #include <rte_tailq.h>
16 #include <rte_string_fns.h>
17
18 #include "rte_telemetry_parser.h"
19 #include "rte_telemetry_internal.h"
20
21 enum choices {
22         INV_ACTION_VAL,
23         INV_COMMAND_VAL,
24         INV_DATA_VAL,
25         INV_ACTION_FIELD,
26         INV_COMMAND_FIELD,
27         INV_DATA_FIELD,
28         INV_JSON_FORMAT,
29         VALID_REQ
30 };
31
32
33 #define TEST_CLIENT "/var/run/dpdk/test_client"
34
35 static int32_t
36 rte_telemetry_create_test_socket(struct telemetry_impl *telemetry,
37         const char *test_client_path)
38 {
39         int ret, sockfd;
40         struct sockaddr_un addr = {0};
41         struct telemetry_client *client;
42
43         if (telemetry == NULL) {
44                 TELEMETRY_LOG_ERR("Telemetry argument has not been initialised");
45                 return -EINVAL;
46         }
47
48         sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
49         if (sockfd < 0) {
50                 TELEMETRY_LOG_ERR("Test socket creation failure");
51                 return -1;
52         }
53
54         addr.sun_family = AF_UNIX;
55         strlcpy(addr.sun_path, test_client_path, sizeof(addr.sun_path));
56         unlink(test_client_path);
57
58         if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
59                 TELEMETRY_LOG_ERR("Test socket binding failure");
60                 return -1;
61         }
62
63         if (listen(sockfd, 1) < 0) {
64                 TELEMETRY_LOG_ERR("Listen failure");
65                 return -1;
66         }
67
68         ret = rte_telemetry_register_client(telemetry, test_client_path);
69         if (ret < 0) {
70                 TELEMETRY_LOG_ERR("Register dummy client failed: %i", ret);
71                 return -1;
72         }
73
74         ret = accept(sockfd, NULL, NULL);
75         if (ret < 0) {
76                 TELEMETRY_LOG_ERR("Socket accept failed");
77                 return -1;
78         }
79
80         TAILQ_FOREACH(client, &telemetry->client_list_head, client_list)
81                 telemetry->request_client = client;
82
83         return 0;
84 }
85
86 static int32_t
87 rte_telemetry_format_port_stat_ids(int *port_ids, int num_port_ids,
88         const char * const *stat_names, int num_stat_names, json_t **data)
89 {
90
91         int ret;
92         json_t *stat_names_json_array = NULL;
93         json_t *port_ids_json_array = NULL;
94         uint32_t i;
95
96         if (num_port_ids < 0) {
97                 TELEMETRY_LOG_ERR("Port Ids Count invalid");
98                 goto fail;
99         }
100
101         *data = json_object();
102         if (*data == NULL) {
103                 TELEMETRY_LOG_ERR("Data json object creation failed");
104                 goto fail;
105         }
106
107         port_ids_json_array = json_array();
108         if (port_ids_json_array == NULL) {
109                 TELEMETRY_LOG_ERR("port_ids_json_array creation failed");
110                 goto fail;
111         }
112
113         for (i = 0; i < (uint32_t)num_port_ids; i++) {
114                 ret = json_array_append(port_ids_json_array,
115                                 json_integer(port_ids[i]));
116                 if (ret < 0) {
117                         TELEMETRY_LOG_ERR("JSON array creation failed");
118                         goto fail;
119                 }
120         }
121
122         ret = json_object_set_new(*data, "ports", port_ids_json_array);
123         if (ret < 0) {
124                 TELEMETRY_LOG_ERR("Setting 'ports' value in data object failed");
125                 goto fail;
126         }
127
128         if (stat_names) {
129                 if (num_stat_names < 0) {
130                         TELEMETRY_LOG_ERR("Stat Names Count invalid");
131                         goto fail;
132                 }
133
134                 stat_names_json_array = json_array();
135                 if (stat_names_json_array == NULL) {
136                         TELEMETRY_LOG_ERR("stat_names_json_array creation failed");
137                         goto fail;
138                 }
139
140                 uint32_t i;
141                 for (i = 0; i < (uint32_t)num_stat_names; i++) {
142                         ret = json_array_append(stat_names_json_array,
143                                  json_string(stat_names[i]));
144                         if (ret < 0) {
145                                 TELEMETRY_LOG_ERR("JSON array creation failed");
146                                 goto fail;
147                         }
148                 }
149
150                 ret = json_object_set_new(*data, "stats", stat_names_json_array);
151                 if (ret < 0) {
152                         TELEMETRY_LOG_ERR("Setting 'stats' value in data object failed");
153                         goto fail;
154                 }
155         }
156
157         return 0;
158
159 fail:
160         if (*data)
161                 json_decref(*data);
162         if (stat_names_json_array)
163                 json_decref(stat_names_json_array);
164         if (port_ids_json_array)
165                 json_decref(port_ids_json_array);
166         return -1;
167 }
168
169 static int32_t
170 rte_telemetry_create_json_request(int action, const char *command,
171         const char *client_path, int *port_ids, int num_port_ids,
172         const char * const *stat_names, int num_stat_names, char **request,
173         int inv_choice)
174 {
175         int ret;
176         json_t *root = json_object();
177         json_t *data;
178
179         if (root == NULL) {
180                 TELEMETRY_LOG_ERR("Could not create root json object");
181                 goto fail;
182         }
183
184         if (inv_choice == INV_ACTION_FIELD) {
185                 ret = json_object_set_new(root, "ac--on", json_integer(action));
186                 if (ret < 0) {
187                         TELEMETRY_LOG_ERR("Setting invalid action field in root object failed");
188                         goto fail;
189                 }
190         } else {
191                 ret = json_object_set_new(root, "action", json_integer(action));
192                 if (ret < 0) {
193                         TELEMETRY_LOG_ERR("Setting valid action field in root object failed");
194                         goto fail;
195                 }
196         }
197
198         if (inv_choice == INV_COMMAND_FIELD) {
199                 ret = json_object_set_new(root, "co---nd", json_string(command));
200                 if (ret < 0) {
201                         TELEMETRY_LOG_ERR("Setting invalid command field in root object failed");
202                         goto fail;
203                 }
204         } else {
205                 ret = json_object_set_new(root, "command", json_string(command));
206                 if (ret < 0) {
207                         TELEMETRY_LOG_ERR("Setting valid command field in root object failed");
208                         goto fail;
209                 }
210         }
211
212         data = json_null();
213         if (client_path) {
214                 data = json_object();
215                 if (data == NULL) {
216                         TELEMETRY_LOG_ERR("Data json object creation failed");
217                         goto fail;
218                 }
219
220                 ret = json_object_set_new(data, "client_path",
221                                 json_string(client_path));
222                 if (ret < 0) {
223                         TELEMETRY_LOG_ERR("Setting valid client_path field in data object failed");
224                         goto fail;
225                 }
226
227         } else if (port_ids) {
228                 ret = rte_telemetry_format_port_stat_ids(port_ids, num_port_ids,
229                                 stat_names, num_stat_names, &data);
230                 if (ret < 0) {
231                         TELEMETRY_LOG_ERR("Formatting Port/Stat arrays failed");
232                         goto fail;
233                 }
234
235         }
236
237         if (inv_choice == INV_DATA_FIELD) {
238                 ret = json_object_set_new(root, "d--a", data);
239                 if (ret < 0) {
240                         TELEMETRY_LOG_ERR("Setting invalid data field in data object failed");
241                         goto fail;
242                 }
243         } else {
244                 ret = json_object_set_new(root, "data", data);
245                 if (ret < 0) {
246                         TELEMETRY_LOG_ERR("Setting valid data field in data object failed");
247                         goto fail;
248                 }
249         }
250
251         *request = json_dumps(root, 0);
252         if (*request == NULL) {
253                 TELEMETRY_LOG_ERR("Converting JSON root object to char* failed");
254                 goto fail;
255         }
256
257         json_decref(root);
258         return 0;
259
260 fail:
261         if (root)
262                 json_decref(root);
263         return -1;
264 }
265
266 static int32_t
267 rte_telemetry_send_get_ports_and_stats_request(struct telemetry_impl *telemetry,
268         int action_choice, const char *command_choice, int inv_choice)
269 {
270         int ret;
271         char *request;
272         const char *client_path_data = NULL;
273
274         if (telemetry == NULL) {
275                 TELEMETRY_LOG_ERR("Telemetry argument has not been initialised");
276                 return -EINVAL;
277         }
278
279
280         if (inv_choice == INV_ACTION_VAL)
281                 action_choice = -1;
282         else if (inv_choice == INV_COMMAND_VAL)
283                 command_choice = "INVALID_COMMAND";
284         else if (inv_choice == INV_DATA_VAL)
285                 client_path_data = "INVALID_DATA";
286
287         ret = rte_telemetry_create_json_request(action_choice, command_choice,
288                 client_path_data, NULL, -1, NULL, -1, &request, inv_choice);
289         if (ret < 0) {
290                 TELEMETRY_LOG_ERR("Could not create JSON Request");
291                 return -1;
292         }
293
294         if (inv_choice == INV_JSON_FORMAT)
295                 request++;
296
297         ret = rte_telemetry_parse(telemetry, request);
298         if (ret < 0) {
299                 TELEMETRY_LOG_WARN("Could not parse JSON Request");
300                 return -1;
301         }
302
303         return 0;
304 }
305
306 static int32_t
307 rte_telemetry_send_get_ports_details_request(struct telemetry_impl *telemetry,
308         int action_choice, int *port_ids, int num_port_ids, int inv_choice)
309 {
310         int ret;
311         char *request;
312         if (telemetry == NULL) {
313                 TELEMETRY_LOG_ERR("Telemetry argument has not been initialised");
314                 return -EINVAL;
315         }
316
317         const char *command = "ports_details";
318
319         if (inv_choice == INV_ACTION_VAL)
320                 action_choice = -1;
321         else if (inv_choice == INV_COMMAND_VAL)
322                 command = "INVALID_COMMAND";
323         else if (inv_choice == INV_DATA_VAL)
324                 port_ids = NULL;
325
326
327         ret = rte_telemetry_create_json_request(action_choice, command, NULL,
328                 port_ids, num_port_ids, NULL, -1, &request, inv_choice);
329         if (ret < 0) {
330                 TELEMETRY_LOG_ERR("Could not create JSON Request");
331                 return -1;
332         }
333
334         if (inv_choice == INV_JSON_FORMAT)
335                 request++;
336
337         ret = rte_telemetry_parse(telemetry, request);
338         if (ret < 0) {
339                 TELEMETRY_LOG_WARN("Could not parse JSON Request");
340                 return -1;
341         }
342
343         return 0;
344 }
345
346 static int32_t
347 rte_telemetry_send_stats_values_by_name_request(struct telemetry_impl
348         *telemetry, int action_choice, int *port_ids, int num_port_ids,
349         const char * const *stat_names, int num_stat_names,
350         int inv_choice)
351 {
352         int ret;
353         char *request;
354         const char *command = "ports_stats_values_by_name";
355
356         if (telemetry == NULL) {
357                 TELEMETRY_LOG_ERR("Telemetry argument has not been initialised");
358                 return -EINVAL;
359         }
360
361         if (inv_choice == INV_ACTION_VAL)
362                 action_choice = -1;
363         else if (inv_choice == INV_COMMAND_VAL)
364                 command = "INVALID_COMMAND";
365         else if (inv_choice == INV_DATA_VAL) {
366                 port_ids = NULL;
367                 stat_names = NULL;
368         }
369
370         ret = rte_telemetry_create_json_request(action_choice, command, NULL,
371                 port_ids, num_port_ids, stat_names, num_stat_names, &request,
372                 inv_choice);
373         if (ret < 0) {
374                 TELEMETRY_LOG_ERR("Could not create JSON Request");
375                 return -1;
376         }
377
378         if (inv_choice == INV_JSON_FORMAT)
379                 request++;
380
381         ret = rte_telemetry_parse(telemetry, request);
382         if (ret < 0) {
383                 TELEMETRY_LOG_WARN("Could not parse JSON Request");
384                 return -1;
385         }
386
387         return 0;
388 }
389
390 static int32_t
391 rte_telemetry_send_unreg_request(struct telemetry_impl *telemetry,
392         int action_choice, const char *client_path, int inv_choice)
393 {
394         int ret;
395         char *request;
396
397         if (telemetry == NULL) {
398                 TELEMETRY_LOG_ERR("Telemetry argument has not been initialised");
399                 return -EINVAL;
400         }
401
402         const char *command = "clients";
403
404         if (inv_choice == INV_ACTION_VAL)
405                 action_choice = -1;
406         else if (inv_choice == INV_COMMAND_VAL)
407                 command = "INVALID_COMMAND";
408         else if (inv_choice == INV_DATA_VAL)
409                 client_path = NULL;
410
411         ret = rte_telemetry_create_json_request(action_choice, command,
412                 client_path, NULL, -1, NULL, -1, &request, inv_choice);
413         if (ret < 0) {
414                 TELEMETRY_LOG_ERR("Could not create JSON Request");
415                 return -1;
416         }
417
418         if (inv_choice == INV_JSON_FORMAT)
419                 request++;
420
421         ret = rte_telemetry_parse(telemetry, request);
422         if (ret < 0) {
423                 TELEMETRY_LOG_WARN("Could not parse JSON Request");
424                 return -1;
425         }
426
427         return 0;
428 }
429
430 int32_t
431 rte_telemetry_parser_test(struct telemetry_impl *telemetry)
432 {
433         int ret;
434         const char *client_path = TEST_CLIENT;
435
436         if (telemetry == NULL) {
437                 TELEMETRY_LOG_ERR("Telemetry argument has not been initialised");
438                 return -EINVAL;
439         }
440
441         ret = rte_telemetry_create_test_socket(telemetry, client_path);
442         if (ret < 0) {
443                 TELEMETRY_LOG_ERR("Could not create test request client socket");
444                 return -1;
445         }
446
447         int port_ids[] = {0, 1};
448         int num_port_ids = RTE_DIM(port_ids);
449
450         static const char * const stat_names[] = {"tx_good_packets",
451                 "rx_good_packets"};
452         int num_stat_names = RTE_DIM(stat_names);
453
454         static const char * const test_types[] = {
455                 "INVALID ACTION VALUE TESTS",
456                 "INVALID COMMAND VALUE TESTS",
457                 "INVALID DATA VALUE TESTS",
458                 "INVALID ACTION FIELD TESTS",
459                 "INVALID COMMAND FIELD TESTS",
460                 "INVALID DATA FIELD TESTS",
461                 "INVALID JSON FORMAT TESTS",
462                 "VALID TESTS"
463         };
464
465
466 #define NUM_TEST_TYPES (sizeof(test_types)/sizeof(const char * const))
467
468         uint32_t i;
469         for (i = 0; i < NUM_TEST_TYPES; i++) {
470                 TELEMETRY_LOG_INFO("%s", test_types[i]);
471
472                 ret = rte_telemetry_send_get_ports_and_stats_request(telemetry,
473                         ACTION_GET, "ports", i);
474                 if (ret != 0 && i == VALID_REQ) {
475                         TELEMETRY_LOG_ERR("Get ports valid test failed");
476                         return -EPERM;
477                 } else if (ret != -1 && i != VALID_REQ) {
478                         TELEMETRY_LOG_ERR("Get ports invalid test failed");
479                         return -EPERM;
480                 }
481
482                 TELEMETRY_LOG_INFO("Success - Get ports test passed");
483
484                 ret = rte_telemetry_send_get_ports_details_request(telemetry,
485                         ACTION_GET, port_ids, num_port_ids, i);
486                 if (ret != 0 && i == VALID_REQ) {
487                         TELEMETRY_LOG_ERR("Get ports details valid");
488                         return -EPERM;
489                 } else if (ret != -1 && i != VALID_REQ) {
490                         TELEMETRY_LOG_ERR("Get ports details invalid");
491                         return -EPERM;
492                 }
493
494                 TELEMETRY_LOG_INFO("Success - Get ports details test passed");
495
496                 ret = rte_telemetry_send_get_ports_and_stats_request(telemetry,
497                         ACTION_GET, "port_stats", i);
498                 if (ret != 0  && i == VALID_REQ) {
499                         TELEMETRY_LOG_ERR("Get port stats valid test");
500                         return -EPERM;
501                 } else if (ret != -1 && i != VALID_REQ) {
502                         TELEMETRY_LOG_ERR("Get ports stats invalid test failed");
503                         return -EPERM;
504                 }
505
506                 TELEMETRY_LOG_INFO("Success - Get ports stats test passed");
507
508                 ret = rte_telemetry_send_stats_values_by_name_request(telemetry,
509                         ACTION_GET, port_ids, num_port_ids, stat_names,
510                         num_stat_names, i);
511                 if (ret != 0 && i == VALID_REQ) {
512                         TELEMETRY_LOG_ERR("Get ports stats values by name valid test failed");
513                         return -EPERM;
514                 } else if (ret != -1 && i != VALID_REQ) {
515                         TELEMETRY_LOG_ERR("Get ports stats values by name invalid test failed");
516                         return -EPERM;
517                 }
518
519                 TELEMETRY_LOG_INFO("Success - Get ports stats values by name test passed");
520
521                 ret = rte_telemetry_send_unreg_request(telemetry, ACTION_DELETE,
522                         client_path, i);
523                 if (ret != 0 && i == VALID_REQ) {
524                         TELEMETRY_LOG_ERR("Deregister valid test failed");
525                         return -EPERM;
526                 } else if (ret != -1 && i != VALID_REQ) {
527                         TELEMETRY_LOG_ERR("Deregister invalid test failed");
528                         return -EPERM;
529                 }
530
531                 TELEMETRY_LOG_INFO("Success - Deregister test passed");
532         }
533
534         return 0;
535 }