test/graph: add functional tests
[dpdk.git] / app / test / test_graph.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2020 Marvell International Ltd.
3  */
4 #include <assert.h>
5 #include <inttypes.h>
6 #include <signal.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <unistd.h>
10
11 #include <rte_errno.h>
12 #include <rte_graph.h>
13 #include <rte_graph_worker.h>
14 #include <rte_mbuf.h>
15
16 #include "test.h"
17
18 static uint16_t test_node_worker_source(struct rte_graph *graph,
19                                         struct rte_node *node, void **objs,
20                                         uint16_t nb_objs);
21
22 static uint16_t test_node0_worker(struct rte_graph *graph,
23                                   struct rte_node *node, void **objs,
24                                   uint16_t nb_objs);
25
26 static uint16_t test_node1_worker(struct rte_graph *graph,
27                                   struct rte_node *node, void **objs,
28                                   uint16_t nb_objs);
29
30 static uint16_t test_node2_worker(struct rte_graph *graph,
31                                   struct rte_node *node, void **objs,
32                                   uint16_t nb_objs);
33
34 static uint16_t test_node3_worker(struct rte_graph *graph,
35                                   struct rte_node *node, void **objs,
36                                   uint16_t nb_objs);
37
38 #define MBUFF_SIZE 512
39 #define MAX_NODES  4
40
41 static struct rte_mbuf mbuf[MAX_NODES + 1][MBUFF_SIZE];
42 static void *mbuf_p[MAX_NODES + 1][MBUFF_SIZE];
43 static rte_graph_t graph_id;
44 static uint64_t obj_stats[MAX_NODES + 1];
45 static uint64_t fn_calls[MAX_NODES + 1];
46
47 const char *node_patterns[] = {
48         "test_node_source1",       "test_node00",
49         "test_node00-test_node11", "test_node00-test_node22",
50         "test_node00-test_node33",
51 };
52
53 const char *node_names[] = {
54         "test_node00",
55         "test_node00-test_node11",
56         "test_node00-test_node22",
57         "test_node00-test_node33",
58 };
59
60 struct test_node_register {
61         char name[RTE_NODE_NAMESIZE];
62         rte_node_process_t process;
63         uint16_t nb_edges;
64         const char *next_nodes[MAX_NODES];
65 };
66
67 typedef struct {
68         uint32_t idx;
69         struct test_node_register node;
70 } test_node_t;
71
72 typedef struct {
73         test_node_t test_node[MAX_NODES];
74 } test_main_t;
75
76 static test_main_t test_main = {
77         .test_node = {
78                 {
79                         .node = {
80                                         .name = "test_node00",
81                                         .process = test_node0_worker,
82                                         .nb_edges = 2,
83                                         .next_nodes = {"test_node00-"
84                                                        "test_node11",
85                                                        "test_node00-"
86                                                        "test_node22"},
87                                 },
88                 },
89                 {
90                         .node = {
91                                         .name = "test_node11",
92                                         .process = test_node1_worker,
93                                         .nb_edges = 1,
94                                         .next_nodes = {"test_node00-"
95                                                        "test_node22"},
96                                 },
97                 },
98                 {
99                         .node = {
100                                         .name = "test_node22",
101                                         .process = test_node2_worker,
102                                         .nb_edges = 1,
103                                         .next_nodes = {"test_node00-"
104                                                        "test_node33"},
105                                 },
106                 },
107                 {
108                         .node = {
109                                         .name = "test_node33",
110                                         .process = test_node3_worker,
111                                         .nb_edges = 1,
112                                         .next_nodes = {"test_node00"},
113                                 },
114                 },
115         },
116 };
117
118 static int
119 node_init(const struct rte_graph *graph, struct rte_node *node)
120 {
121         RTE_SET_USED(graph);
122         *(uint32_t *)node->ctx = node->id;
123
124         return 0;
125 }
126
127 static struct rte_node_register test_node_source = {
128         .name = "test_node_source1",
129         .process = test_node_worker_source,
130         .flags = RTE_NODE_SOURCE_F,
131         .nb_edges = 2,
132         .init = node_init,
133         .next_nodes = {"test_node00", "test_node00-test_node11"},
134 };
135 RTE_NODE_REGISTER(test_node_source);
136
137 static struct rte_node_register test_node0 = {
138         .name = "test_node00",
139         .process = test_node0_worker,
140         .init = node_init,
141 };
142 RTE_NODE_REGISTER(test_node0);
143
144 uint16_t
145 test_node_worker_source(struct rte_graph *graph, struct rte_node *node,
146                         void **objs, uint16_t nb_objs)
147 {
148         uint32_t obj_node0 = rand() % 100, obj_node1;
149         test_main_t *tm = &test_main;
150         struct rte_mbuf *data;
151         void **next_stream;
152         rte_node_t next;
153         uint32_t i;
154
155         RTE_SET_USED(objs);
156         nb_objs = RTE_GRAPH_BURST_SIZE;
157
158         /* Prepare stream for next node 0 */
159         obj_node0 = nb_objs * obj_node0 * 0.01;
160         next = 0;
161         next_stream = rte_node_next_stream_get(graph, node, next, obj_node0);
162         for (i = 0; i < obj_node0; i++) {
163                 data = &mbuf[0][i];
164                 data->udata64 = ((uint64_t)tm->test_node[0].idx << 32) | i;
165                 if ((i + 1) == obj_node0)
166                         data->udata64 |= (1 << 16);
167                 next_stream[i] = &mbuf[0][i];
168         }
169         rte_node_next_stream_put(graph, node, next, obj_node0);
170
171         /* Prepare stream for next node 1 */
172         obj_node1 = nb_objs - obj_node0;
173         next = 1;
174         next_stream = rte_node_next_stream_get(graph, node, next, obj_node1);
175         for (i = 0; i < obj_node1; i++) {
176                 data = &mbuf[0][obj_node0 + i];
177                 data->udata64 = ((uint64_t)tm->test_node[1].idx << 32) | i;
178                 if ((i + 1) == obj_node1)
179                         data->udata64 |= (1 << 16);
180                 next_stream[i] = &mbuf[0][obj_node0 + i];
181         }
182
183         rte_node_next_stream_put(graph, node, next, obj_node1);
184         obj_stats[0] += nb_objs;
185         fn_calls[0] += 1;
186         return nb_objs;
187 }
188
189 uint16_t
190 test_node0_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
191                   uint16_t nb_objs)
192 {
193         test_main_t *tm = &test_main;
194
195         if (*(uint32_t *)node->ctx == test_node0.id) {
196                 uint32_t obj_node0 = rand() % 100, obj_node1;
197                 struct rte_mbuf *data;
198                 uint8_t second_pass = 0;
199                 uint32_t count = 0;
200                 uint32_t i;
201
202                 obj_stats[1] += nb_objs;
203                 fn_calls[1] += 1;
204
205                 for (i = 0; i < nb_objs; i++) {
206                         data = (struct rte_mbuf *)objs[i];
207                         if ((data->udata64 >> 32) != tm->test_node[0].idx) {
208                                 printf("Data idx miss match at node 0, expected"
209                                        " = %u got = %u\n",
210                                        tm->test_node[0].idx,
211                                        (uint32_t)(data->udata64 >> 32));
212                                 goto end;
213                         }
214
215                         if ((data->udata64 & 0xffff) != (i - count)) {
216                                 printf("Expected buff count miss match at "
217                                        "node 0\n");
218                                 goto end;
219                         }
220
221                         if (data->udata64 & (0x1 << 16))
222                                 count = i + 1;
223                         if (data->udata64 & (0x1 << 17))
224                                 second_pass = 1;
225                 }
226
227                 if (count != i) {
228                         printf("Count mismatch at node 0\n");
229                         goto end;
230                 }
231
232                 obj_node0 = nb_objs * obj_node0 * 0.01;
233                 for (i = 0; i < obj_node0; i++) {
234                         data = &mbuf[1][i];
235                         data->udata64 =
236                                 ((uint64_t)tm->test_node[1].idx << 32) | i;
237                         if ((i + 1) == obj_node0)
238                                 data->udata64 |= (1 << 16);
239                         if (second_pass)
240                                 data->udata64 |= (1 << 17);
241                 }
242                 rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[1][0],
243                                  obj_node0);
244
245                 obj_node1 = nb_objs - obj_node0;
246                 for (i = 0; i < obj_node1; i++) {
247                         data = &mbuf[1][obj_node0 + i];
248                         data->udata64 =
249                                 ((uint64_t)tm->test_node[2].idx << 32) | i;
250                         if ((i + 1) == obj_node1)
251                                 data->udata64 |= (1 << 16);
252                         if (second_pass)
253                                 data->udata64 |= (1 << 17);
254                 }
255                 rte_node_enqueue(graph, node, 1, (void **)&mbuf_p[1][obj_node0],
256                                  obj_node1);
257
258         } else if (*(uint32_t *)node->ctx == tm->test_node[1].idx) {
259                 test_node1_worker(graph, node, objs, nb_objs);
260         } else if (*(uint32_t *)node->ctx == tm->test_node[2].idx) {
261                 test_node2_worker(graph, node, objs, nb_objs);
262         } else if (*(uint32_t *)node->ctx == tm->test_node[3].idx) {
263                 test_node3_worker(graph, node, objs, nb_objs);
264         } else {
265                 printf("Unexpected node context\n");
266         }
267
268 end:
269         return nb_objs;
270 }
271
272 uint16_t
273 test_node1_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
274                   uint16_t nb_objs)
275 {
276         test_main_t *tm = &test_main;
277         uint8_t second_pass = 0;
278         uint32_t obj_node0 = 0;
279         struct rte_mbuf *data;
280         uint32_t count = 0;
281         uint32_t i;
282
283         obj_stats[2] += nb_objs;
284         fn_calls[2] += 1;
285         for (i = 0; i < nb_objs; i++) {
286                 data = (struct rte_mbuf *)objs[i];
287                 if ((data->udata64 >> 32) != tm->test_node[1].idx) {
288                         printf("Data idx miss match at node 1, expected = %u"
289                                " got = %u\n",
290                                tm->test_node[1].idx,
291                                (uint32_t)(data->udata64 >> 32));
292                         goto end;
293                 }
294
295                 if ((data->udata64 & 0xffff) != (i - count)) {
296                         printf("Expected buff count miss match at node 1\n");
297                         goto end;
298                 }
299
300                 if (data->udata64 & (0x1 << 16))
301                         count = i + 1;
302                 if (data->udata64 & (0x1 << 17))
303                         second_pass = 1;
304         }
305
306         if (count != i) {
307                 printf("Count mismatch at node 1\n");
308                 goto end;
309         }
310
311         obj_node0 = nb_objs;
312         for (i = 0; i < obj_node0; i++) {
313                 data = &mbuf[2][i];
314                 data->udata64 = ((uint64_t)tm->test_node[2].idx << 32) | i;
315                 if ((i + 1) == obj_node0)
316                         data->udata64 |= (1 << 16);
317                 if (second_pass)
318                         data->udata64 |= (1 << 17);
319         }
320         rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[2][0], obj_node0);
321
322 end:
323         return nb_objs;
324 }
325
326 uint16_t
327 test_node2_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
328                   uint16_t nb_objs)
329 {
330         test_main_t *tm = &test_main;
331         uint8_t second_pass = 0;
332         struct rte_mbuf *data;
333         uint32_t count = 0;
334         uint32_t obj_node0;
335         uint32_t i;
336
337         obj_stats[3] += nb_objs;
338         fn_calls[3] += 1;
339         for (i = 0; i < nb_objs; i++) {
340                 data = (struct rte_mbuf *)objs[i];
341                 if ((data->udata64 >> 32) != tm->test_node[2].idx) {
342                         printf("Data idx miss match at node 2, expected = %u"
343                                " got = %u\n",
344                                tm->test_node[2].idx,
345                                (uint32_t)(data->udata64 >> 32));
346                         goto end;
347                 }
348
349                 if ((data->udata64 & 0xffff) != (i - count)) {
350                         printf("Expected buff count miss match at node 2\n");
351                         goto end;
352                 }
353
354                 if (data->udata64 & (0x1 << 16))
355                         count = i + 1;
356                 if (data->udata64 & (0x1 << 17))
357                         second_pass = 1;
358         }
359
360         if (count != i) {
361                 printf("Count mismatch at node 2\n");
362                 goto end;
363         }
364
365         if (!second_pass) {
366                 obj_node0 = nb_objs;
367                 for (i = 0; i < obj_node0; i++) {
368                         data = &mbuf[3][i];
369                         data->udata64 =
370                                 ((uint64_t)tm->test_node[3].idx << 32) | i;
371                         if ((i + 1) == obj_node0)
372                                 data->udata64 |= (1 << 16);
373                 }
374                 rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[3][0],
375                                  obj_node0);
376         }
377
378 end:
379         return nb_objs;
380 }
381
382 uint16_t
383 test_node3_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
384                   uint16_t nb_objs)
385 {
386         test_main_t *tm = &test_main;
387         uint8_t second_pass = 0;
388         struct rte_mbuf *data;
389         uint32_t count = 0;
390         uint32_t obj_node0;
391         uint32_t i;
392
393         obj_stats[4] += nb_objs;
394         fn_calls[4] += 1;
395         for (i = 0; i < nb_objs; i++) {
396                 data = (struct rte_mbuf *)objs[i];
397                 if ((data->udata64 >> 32) != tm->test_node[3].idx) {
398                         printf("Data idx miss match at node 3, expected = %u"
399                                " got = %u\n",
400                                tm->test_node[3].idx,
401                                (uint32_t)(data->udata64 >> 32));
402                         goto end;
403                 }
404
405                 if ((data->udata64 & 0xffff) != (i - count)) {
406                         printf("Expected buff count miss match at node 3\n");
407                         goto end;
408                 }
409
410                 if (data->udata64 & (0x1 << 16))
411                         count = i + 1;
412                 if (data->udata64 & (0x1 << 17))
413                         second_pass = 1;
414         }
415
416         if (count != i) {
417                 printf("Count mismatch at node 3\n");
418                 goto end;
419         }
420
421         if (second_pass) {
422                 printf("Unexpected buffers are at node 3\n");
423                 goto end;
424         } else {
425                 obj_node0 = nb_objs * 2;
426                 for (i = 0; i < obj_node0; i++) {
427                         data = &mbuf[4][i];
428                         data->udata64 =
429                                 ((uint64_t)tm->test_node[0].idx << 32) | i;
430                         data->udata64 |= (1 << 17);
431                         if ((i + 1) == obj_node0)
432                                 data->udata64 |= (1 << 16);
433                 }
434                 rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[4][0],
435                                  obj_node0);
436         }
437
438 end:
439         return nb_objs;
440 }
441
442 static int
443 test_lookup_functions(void)
444 {
445         test_main_t *tm = &test_main;
446         int i;
447
448         /* Verify the name with ID */
449         for (i = 1; i < MAX_NODES; i++) {
450                 char *name = rte_node_id_to_name(tm->test_node[i].idx);
451                 if (strcmp(name, node_names[i]) != 0) {
452                         printf("Test node name verify by ID = %d failed "
453                                "Expected = %s, got %s\n",
454                                i, node_names[i], name);
455                         return -1;
456                 }
457         }
458
459         /* Verify by name */
460         for (i = 1; i < MAX_NODES; i++) {
461                 uint32_t idx = rte_node_from_name(node_names[i]);
462                 if (idx != tm->test_node[i].idx) {
463                         printf("Test node ID verify by name = %s failed "
464                                "Expected = %d, got %d\n",
465                                node_names[i], tm->test_node[i].idx, idx);
466                         return -1;
467                 }
468         }
469
470         /* Verify edge count */
471         for (i = 1; i < MAX_NODES; i++) {
472                 uint32_t count = rte_node_edge_count(tm->test_node[i].idx);
473                 if (count != tm->test_node[i].node.nb_edges) {
474                         printf("Test number of edges for node = %s failed Expected = %d, got = %d\n",
475                                tm->test_node[i].node.name,
476                                tm->test_node[i].node.nb_edges, count);
477                         return -1;
478                 }
479         }
480
481         /* Verify edge names */
482         for (i = 1; i < MAX_NODES; i++) {
483                 uint32_t j, count;
484                 char **next_edges;
485
486                 count = rte_node_edge_get(tm->test_node[i].idx, NULL);
487                 if (count != tm->test_node[i].node.nb_edges * sizeof(char *)) {
488                         printf("Test number of edge count for node = %s failed Expected = %d, got = %d\n",
489                                tm->test_node[i].node.name,
490                                tm->test_node[i].node.nb_edges, count);
491                         return -1;
492                 }
493                 next_edges = malloc(count);
494                 count = rte_node_edge_get(tm->test_node[i].idx, next_edges);
495                 if (count != tm->test_node[i].node.nb_edges) {
496                         printf("Test number of edges for node = %s failed Expected = %d, got %d\n",
497                                tm->test_node[i].node.name,
498                                tm->test_node[i].node.nb_edges, count);
499                         return -1;
500                 }
501
502                 for (j = 0; j < count; j++) {
503                         if (strcmp(next_edges[j],
504                                    tm->test_node[i].node.next_nodes[j]) != 0) {
505                                 printf("Edge name miss match, expected = %s got = %s\n",
506                                        tm->test_node[i].node.next_nodes[j],
507                                        next_edges[j]);
508                                 return -1;
509                         }
510                 }
511                 free(next_edges);
512         }
513
514         return 0;
515 }
516
517 static int
518 test_node_clone(void)
519 {
520         test_main_t *tm = &test_main;
521         uint32_t node_id, dummy_id;
522         int i;
523
524         node_id = rte_node_from_name("test_node00");
525         tm->test_node[0].idx = node_id;
526
527         /* Clone with same name, should fail */
528         dummy_id = rte_node_clone(node_id, "test_node00");
529         if (!rte_node_is_invalid(dummy_id)) {
530                 printf("Got valid id when clone with same name, Expecting fail\n");
531                 return -1;
532         }
533
534         for (i = 1; i < MAX_NODES; i++) {
535                 tm->test_node[i].idx =
536                         rte_node_clone(node_id, tm->test_node[i].node.name);
537                 if (rte_node_is_invalid(tm->test_node[i].idx)) {
538                         printf("Got invalid node id\n");
539                         return -1;
540                 }
541         }
542
543         /* Clone from cloned node should fail */
544         dummy_id = rte_node_clone(tm->test_node[1].idx, "dummy_node");
545         if (!rte_node_is_invalid(dummy_id)) {
546                 printf("Got valid node id when cloning from cloned node, expected fail\n");
547                 return -1;
548         }
549
550         return 0;
551 }
552
553 static int
554 test_update_edges(void)
555 {
556         test_main_t *tm = &test_main;
557         uint32_t node_id;
558         uint16_t count;
559         int i;
560
561         node_id = rte_node_from_name("test_node00");
562         count = rte_node_edge_update(node_id, 0,
563                                      tm->test_node[0].node.next_nodes,
564                                      tm->test_node[0].node.nb_edges);
565         if (count != tm->test_node[0].node.nb_edges) {
566                 printf("Update edges failed expected: %d got = %d\n",
567                        tm->test_node[0].node.nb_edges, count);
568                 return -1;
569         }
570
571         for (i = 1; i < MAX_NODES; i++) {
572                 count = rte_node_edge_update(tm->test_node[i].idx, 0,
573                                              tm->test_node[i].node.next_nodes,
574                                              tm->test_node[i].node.nb_edges);
575                 if (count != tm->test_node[i].node.nb_edges) {
576                         printf("Update edges failed expected: %d got = %d\n",
577                                tm->test_node[i].node.nb_edges, count);
578                         return -1;
579                 }
580
581                 count = rte_node_edge_shrink(tm->test_node[i].idx,
582                                              tm->test_node[i].node.nb_edges);
583                 if (count != tm->test_node[i].node.nb_edges) {
584                         printf("Shrink edges failed\n");
585                         return -1;
586                 }
587         }
588
589         return 0;
590 }
591
592 static int
593 test_create_graph(void)
594 {
595         static const char *node_patterns_dummy[] = {
596                 "test_node_source1",       "test_node00",
597                 "test_node00-test_node11", "test_node00-test_node22",
598                 "test_node00-test_node33", "test_node00-dummy_node",
599         };
600         struct rte_graph_param gconf = {
601                 .socket_id = SOCKET_ID_ANY,
602                 .nb_node_patterns = 6,
603                 .node_patterns = node_patterns_dummy,
604         };
605         uint32_t dummy_node_id;
606         uint32_t node_id;
607
608         node_id = rte_node_from_name("test_node00");
609         dummy_node_id = rte_node_clone(node_id, "dummy_node");
610         if (rte_node_is_invalid(dummy_node_id)) {
611                 printf("Got invalid node id\n");
612                 return -1;
613         }
614
615         graph_id = rte_graph_create("worker0", &gconf);
616         if (graph_id != RTE_GRAPH_ID_INVALID) {
617                 printf("Graph creation success with isolated node, expected graph creation fail\n");
618                 return -1;
619         }
620
621         gconf.nb_node_patterns = 5;
622         gconf.node_patterns = node_patterns;
623         graph_id = rte_graph_create("worker0", &gconf);
624         if (graph_id == RTE_GRAPH_ID_INVALID) {
625                 printf("Graph creation failed with error = %d\n", rte_errno);
626                 return -1;
627         }
628         return 0;
629 }
630
631 static int
632 test_graph_walk(void)
633 {
634         struct rte_graph *graph = rte_graph_lookup("worker0");
635         int i;
636
637         if (!graph) {
638                 printf("Graph lookup failed\n");
639                 return -1;
640         }
641
642         for (i = 0; i < 5; i++)
643                 rte_graph_walk(graph);
644         return 0;
645 }
646
647 static int
648 test_graph_lookup_functions(void)
649 {
650         test_main_t *tm = &test_main;
651         struct rte_node *node;
652         int i;
653
654         for (i = 0; i < MAX_NODES; i++) {
655                 node = rte_graph_node_get(graph_id, tm->test_node[i].idx);
656                 if (!node) {
657                         printf("rte_graph_node_get, failed for node = %d\n",
658                                tm->test_node[i].idx);
659                         return -1;
660                 }
661
662                 if (tm->test_node[i].idx != node->id) {
663                         printf("Node id didn't match, expected = %d got = %d\n",
664                                tm->test_node[i].idx, node->id);
665                         return 0;
666                 }
667
668                 if (strncmp(node->name, node_names[i], RTE_NODE_NAMESIZE)) {
669                         printf("Node name didn't match, expected = %s got %s\n",
670                                node_names[i], node->name);
671                         return -1;
672                 }
673         }
674
675         for (i = 0; i < MAX_NODES; i++) {
676                 node = rte_graph_node_get_by_name("worker0", node_names[i]);
677                 if (!node) {
678                         printf("rte_graph_node_get, failed for node = %d\n",
679                                tm->test_node[i].idx);
680                         return -1;
681                 }
682
683                 if (tm->test_node[i].idx != node->id) {
684                         printf("Node id didn't match, expected = %d got = %d\n",
685                                tm->test_node[i].idx, node->id);
686                         return 0;
687                 }
688
689                 if (strncmp(node->name, node_names[i], RTE_NODE_NAMESIZE)) {
690                         printf("Node name didn't match, expected = %s got %s\n",
691                                node_names[i], node->name);
692                         return -1;
693                 }
694         }
695
696         return 0;
697 }
698
699 static int
700 graph_cluster_stats_cb_t(bool is_first, bool is_last, void *cookie,
701                          const struct rte_graph_cluster_node_stats *st)
702 {
703         int i;
704
705         RTE_SET_USED(is_first);
706         RTE_SET_USED(is_last);
707         RTE_SET_USED(cookie);
708
709         for (i = 0; i < MAX_NODES + 1; i++) {
710                 rte_node_t id = rte_node_from_name(node_patterns[i]);
711                 if (id == st->id) {
712                         if (obj_stats[i] != st->objs) {
713                                 printf("Obj count miss match for node = %s expected = %"PRId64", got=%"PRId64"\n",
714                                        node_patterns[i], obj_stats[i],
715                                        st->objs);
716                                 return -1;
717                         }
718
719                         if (fn_calls[i] != st->calls) {
720                                 printf("Func call miss match for node = %s expected = %"PRId64", got = %"PRId64"\n",
721                                        node_patterns[i], fn_calls[i],
722                                        st->calls);
723                                 return -1;
724                         }
725                 }
726         }
727         return 0;
728 }
729
730 static int
731 test_print_stats(void)
732 {
733         struct rte_graph_cluster_stats_param s_param;
734         struct rte_graph_cluster_stats *stats;
735         const char *pattern = "worker0";
736
737         if (!rte_graph_has_stats_feature())
738                 return 0;
739
740         /* Prepare stats object */
741         memset(&s_param, 0, sizeof(s_param));
742         s_param.f = stdout;
743         s_param.socket_id = SOCKET_ID_ANY;
744         s_param.graph_patterns = &pattern;
745         s_param.nb_graph_patterns = 1;
746         s_param.fn = graph_cluster_stats_cb_t;
747
748         stats = rte_graph_cluster_stats_create(&s_param);
749         if (stats == NULL) {
750                 printf("Unable to get stats\n");
751                 return -1;
752         }
753         /* Clear screen and move to top left */
754         rte_graph_cluster_stats_get(stats, 0);
755         rte_graph_cluster_stats_destroy(stats);
756
757         return 0;
758 }
759
760 static int
761 graph_setup(void)
762 {
763         int i, j;
764
765         for (i = 0; i <= MAX_NODES; i++) {
766                 for (j = 0; j < MBUFF_SIZE; j++)
767                         mbuf_p[i][j] = &mbuf[i][j];
768         }
769         if (test_node_clone()) {
770                 printf("test_node_clone: fail\n");
771                 return -1;
772         }
773         printf("test_node_clone: pass\n");
774
775         return 0;
776 }
777
778 static void
779 graph_teardown(void)
780 {
781         int id;
782
783         id = rte_graph_destroy(rte_graph_from_name("worker0"));
784         if (id)
785                 printf("Graph Destroy failed\n");
786 }
787
788 static struct unit_test_suite graph_testsuite = {
789         .suite_name = "Graph library test suite",
790         .setup = graph_setup,
791         .teardown = graph_teardown,
792         .unit_test_cases = {
793                 TEST_CASE(test_update_edges),
794                 TEST_CASE(test_lookup_functions),
795                 TEST_CASE(test_create_graph),
796                 TEST_CASE(test_graph_lookup_functions),
797                 TEST_CASE(test_graph_walk),
798                 TEST_CASE(test_print_stats),
799                 TEST_CASES_END(), /**< NULL terminate unit test array */
800         },
801 };
802
803 static int
804 graph_autotest_fn(void)
805 {
806         return unit_test_suite_runner(&graph_testsuite);
807 }
808
809 REGISTER_TEST_COMMAND(graph_autotest, graph_autotest_fn);
810
811 static int
812 test_node_list_dump(void)
813 {
814         rte_node_list_dump(stdout);
815
816         return TEST_SUCCESS;
817 }
818 REGISTER_TEST_COMMAND(node_list_dump, test_node_list_dump);