doc: whitespace changes in licenses
[dpdk.git] / app / test / test_pmac_pm.c
1 /*-
2  *   BSD LICENSE
3  * 
4  *   Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  * 
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  * 
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  * 
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <string.h>
35 #include <errno.h>
36
37 #include <cmdline_parse.h>
38
39 #include <rte_string_fns.h>
40 #include <rte_mbuf.h>
41
42 #include "test.h"
43
44 #ifdef RTE_LIBRTE_PMAC
45
46 #include <rte_pm.h>
47
48 #include "test_pmac_pm.h"
49
50 struct pm_store_buf {
51         void * buf;
52         size_t len;
53 };
54
55 struct rte_pm_param good_param = {
56         .name = "param",
57         .socket_id = SOCKET_ID_ANY,
58         .max_pattern_num = 0x20000,
59         .max_pattern_len = 0x20000,
60 };
61
62 /* pattern set.
63  * this switches between clean (ASCII-only), mixed (those needing conversion
64  * from ASCII to binary) and P1 (a list of only 1 pattern, for use with P1
65  * algorithm) pattern sets. each pattern set is attempted to be tested with all
66  * algorithms, thus maximizing coverage.
67  */
68 enum pattern_set {
69         PAT_CLEAN,
70         PAT_MIXED,
71         PAT_P1,
72         PAT_NUM
73 };
74
75
76 #define LEN 16
77 #define BUFSIZE 0x1000000
78
79 #define OPT_CASE_SENSE 0x1
80 #define OPT_OUT_OF_ORDER 0x2
81 #define NUM_OPTS 2
82
83 /* keep track of which algorithms were tested */
84 uint8_t tested_algorithms[RTE_PM_SEARCH_NUM];
85
86 /* pointer to an array with one of the test buffers from test_pmac_pm.h */
87 static struct pm_test_buffer * pm_test_buf;
88 /* length of the list (since we can't use sizeof on a pointer) */
89 int pm_test_buf_len = 0;
90
91
92 /* store pattern-match buffer */
93 static int
94 pm_store(void *arg, const void *buf,
95                 uint64_t offset, uint64_t size)
96 {
97         struct pm_store_buf * dst = (struct pm_store_buf *) arg;
98         if (size + offset > dst->len) {
99                 printf("Line %i: Not enough space in PM store buffer!\n", __LINE__);
100                 return -ENOMEM;
101         }
102         memcpy((char*) dst->buf + offset, buf, size);
103
104         return (0);
105 }
106
107 /* load pattern-match buffer */
108 static int
109 pm_load(void *arg, void *buf,
110                 uint64_t offset, uint64_t size)
111 {
112         struct pm_store_buf * src = (struct pm_store_buf *) arg;
113         if (size + offset > src->len) {
114                 printf("Line %i: Not enough space in PM load buffer!\n", __LINE__);
115                 return -ENOMEM;
116         }
117         memcpy(buf, (char*) src->buf + offset, size);
118
119         return (0);
120 }
121
122 /**
123  * perform bulk search
124  *
125  * Due to the way bulk works, we can only look for <=1 results per buffer
126  */
127 static int
128 bulk_search(struct rte_pm_ctx * pmx, struct rte_pm_build_opt * bopt)
129 {
130         struct rte_pm_match res[pm_test_buf_len];
131         struct rte_pm_inbuf in_buf[pm_test_buf_len];
132
133         int i, len, tmp;
134         int num_matches, total_matches;
135
136         if (pm_test_buf_len <= 0) {
137                 printf("Line %i: Error at %s invalid value for "
138                         "pm_test_buf_len: %d\n",
139                                 __LINE__, __func__, pm_test_buf_len);
140                 return (-1);
141         }
142
143         memset(res, 0, sizeof(res));
144         memset(in_buf, 0, sizeof(in_buf));
145
146         /* prepare buffers */
147         for (i = 0; i < pm_test_buf_len; i++) {
148
149                 /* prepare PM buffer */
150                 len = strnlen(pm_test_buf[i].string, sizeof(pm_test_buf[i].string));
151
152                 in_buf[i].buf = (const uint8_t*) pm_test_buf[i].string;
153                 in_buf[i].len = len;
154         }
155
156         num_matches = 0;
157
158         /* get number of total matches we're supposed to get */
159         /* we can only get up to 1 results because of bulk search */
160         if (bopt->case_sense) {
161                 for (i = 0; i < pm_test_buf_len; i++)
162                         num_matches += pm_test_buf[i].n_matches_with_case_sense > 0;
163         }
164         else {
165                 for (i = 0; i < pm_test_buf_len; i++)
166                         num_matches += pm_test_buf[i].n_matches > 0;
167         }
168
169         /* run bulk search */
170         total_matches = rte_pm_search_bulk(pmx, in_buf, res, pm_test_buf_len);
171
172         /* check if we have a different number of total matches */
173         if (total_matches != num_matches) {
174                 rte_pm_dump(pmx);
175                 printf("Line %i: Error bulk matching (ret=%i num_matches=%i)!\n",
176                                 __LINE__, total_matches, num_matches);
177                 return -1;
178         }
179         /* cycle through each result and check first match, if any */
180         else {
181                 for (i = 0; i < pm_test_buf_len; i++) {
182
183                         /* get supposed number of matches */
184                         if (bopt->case_sense)
185                                 tmp = pm_test_buf[i].n_matches_with_case_sense > 0;
186                         else
187                                 tmp = pm_test_buf[i].n_matches > 0;
188
189                         /* check if we have a match when we shouldn't (and vice versa) */
190                         if (((const char *)(uintptr_t)res[i].userdata !=
191                                         NULL) == (tmp == 0)) {
192                                 printf("Line %i: Should have %i matches!\n", __LINE__, tmp);
193                                 return -1;
194                         }
195
196                         /* skip null results */
197                         if (tmp == 0)
198                                 continue;
199
200                         /* compare result string */
201                         if ((const char*)(uintptr_t)res[i].userdata !=
202                                         pm_test_buf[i].matched_str[0]) {
203                                 rte_pm_dump(pmx);
204                                 printf("Line %i: Wrong match at bulk search %i!\n",
205                                                 __LINE__, i);
206                                 printf("Matched: %s\n",
207                                         (const char *)(uintptr_t)
208                                         res[i].userdata);
209                                 printf("Should have matched: %s\n",
210                                                 pm_test_buf[i].matched_str[0]);
211                                 return -1;
212                         }
213                 }
214         }
215         return 0;
216 }
217
218 /**
219  * perform multiple searches on a split single buffer
220  */
221 static int
222 split_buffer_search(struct rte_pm_ctx * pmx, struct rte_pm_build_opt * bopt)
223 {
224 /* works with any reasonable segment count */
225 #define NUM_SEG 2
226         struct rte_pm_match res_seg[NUM_SEG][MAX_MATCH_COUNT];
227         struct rte_pm_inbuf in_seg[NUM_SEG];
228         struct rte_pm_match * res;
229         struct rte_pm_state state;
230
231         int len, seg_len, total_len;
232         int i, j, n_seg;
233         int cur_match, num_matches, total_matches = 0;
234
235         /* chain matching */
236         for (i = 0; i < pm_test_buf_len; i++) {
237
238                 memset(res_seg, 0, sizeof(res_seg));
239                 memset(&state, 0, sizeof(struct rte_pm_state));
240
241                 /* prepare PM buffer */
242                 len = strnlen(pm_test_buf[i].string, sizeof(pm_test_buf[i].string));
243
244                 total_len = 0;
245
246                 /* create segments out of one string */
247                 for (n_seg = 0; n_seg < NUM_SEG; n_seg++) {
248                         /* if last segment */
249                         if (n_seg == NUM_SEG - 1)
250                                 seg_len = len - total_len;
251                         else
252                                 seg_len = len / NUM_SEG;
253                         in_seg[n_seg].len = seg_len;
254                         in_seg[n_seg].buf =
255                                         (const uint8_t*) (pm_test_buf[i].string + total_len);
256                         total_len += seg_len;
257                 }
258
259
260                 /* number of matches we are supposed to find */
261                 if (bopt->case_sense)
262                         num_matches = pm_test_buf[i].n_matches_with_case_sense;
263                 else
264                         num_matches = pm_test_buf[i].n_matches;
265
266                 /* search in segments */
267                 for (n_seg = 0; n_seg < NUM_SEG; n_seg++) {
268                         /* if first segment */
269                         if (n_seg == 0)
270                                 total_matches = rte_pm_search_chain_start(pmx, &in_seg[n_seg],
271                                                 res_seg[n_seg], MAX_MATCH_COUNT, &state);
272                         else
273                                 total_matches += rte_pm_search_chain_next(pmx, &in_seg[n_seg],
274                                                 res_seg[n_seg], MAX_MATCH_COUNT - total_matches,
275                                                 &state);
276                 }
277
278                 if (total_matches != num_matches) {
279                         rte_pm_dump(pmx);
280                         printf("Line %i: Error matching %s%s (ret=%i num_matches=%i)!\n",
281                                         __LINE__, in_seg[0].buf, in_seg[1].buf, total_matches,
282                                         num_matches);
283                         return -1;
284                 }
285                 /* check if match was correct */
286                 else {
287                         cur_match = 0;
288                         for (j = 0; j < MAX_MATCH_COUNT * NUM_SEG; j++) {
289
290                                 /* check if we have reached our maximum */
291                                 if (cur_match == num_matches || cur_match == MAX_MATCH_COUNT)
292                                         break;
293
294                                 n_seg = j / MAX_MATCH_COUNT;
295
296                                 /* get current result pointer */
297                                 res = &res_seg[n_seg][j % MAX_MATCH_COUNT];
298
299                                 /* skip uninitialized results */
300                                 if (res->fin == 0)
301                                         continue;
302
303                                 /* compare result string */
304                                 if ((const char*)(uintptr_t)res->userdata !=
305                                                 pm_test_buf[i].matched_str[cur_match]) {
306                                         rte_pm_dump(pmx);
307                                         printf("Line %i: Wrong match at split buffer search %i!\n",
308                                                         __LINE__, i);
309                                         printf("Matched: %s\n",
310                                                 (const char *)(uintptr_t)
311                                                 res->userdata);
312                                         printf("Should have matched: %s\n",
313                                                         pm_test_buf[i].matched_str[cur_match]);
314                                         return -1;
315                                 }
316                                 /* we got ourselves a match! */
317                                 else
318                                         cur_match++;
319                         }
320                 }
321         }
322         return 0;
323 }
324
325 /**
326  * perform multiple searches on a single buffer
327  */
328 static int
329 single_buffer_search(struct rte_pm_ctx * pmx, struct rte_pm_build_opt * bopt)
330 {
331         struct rte_pm_match res[MAX_MATCH_COUNT];
332         struct rte_pm_state state;
333         struct rte_pm_inbuf in_buf;
334
335         int i, j, len;
336         int match, num_matches, total_matches = 0;
337
338         /* look at same segment three times */
339         for (i = 0; i < pm_test_buf_len; i++) {
340
341                 memset(&res, 0, sizeof(res));
342                 memset(&state, 0, sizeof(struct rte_pm_state));
343
344                 /* prepare PM buffer */
345                 len = strnlen(pm_test_buf[i].string, sizeof(pm_test_buf[i].string));
346
347                 in_buf.buf = (const uint8_t*) pm_test_buf[i].string;
348                 in_buf.len = len;
349
350                 /* number of matches we are supposed to find */
351                 if (bopt->case_sense)
352                         num_matches = pm_test_buf[i].n_matches_with_case_sense;
353                 else
354                         num_matches = pm_test_buf[i].n_matches;
355
356                 /* run through a buffer multiple times, looking for 1 match */
357                 for (j = 0; j < MAX_MATCH_COUNT; j++) {
358                         /* start search chain */
359                         if (j == 0)
360                                 total_matches = rte_pm_search_chain_start(pmx, &in_buf,
361                                                 &res[j], 1, &state);
362                         /* continue search */
363                         else
364                                 total_matches += rte_pm_search_chain(pmx, &res[j], 1, &state);
365                 }
366
367                 if (total_matches != num_matches) {
368                         rte_pm_dump(pmx);
369                         printf("Line %i: Error matching %s (ret=%i num_matches=%i)!\n",
370                                         __LINE__, in_buf.buf, total_matches, num_matches);
371                         return -1;
372                 }
373                 /* check if match was correct */
374                 else {
375                         for (match = 0; match < num_matches; match++) {
376                                 if ((const char*)(uintptr_t)
377                                                 res[match].userdata !=
378                                                 pm_test_buf[i].matched_str[match]) {
379                                         rte_pm_dump(pmx);
380                                         printf("Line %i: Wrong match at single buffer search %i!\n",
381                                                         __LINE__, i);
382                                         printf("Matched: %s\n",
383                                                 (const char *)(uintptr_t)
384                                                 res[match].userdata);
385                                         printf("Should have matched: %s\n",
386                                                         pm_test_buf[i].matched_str[match]);
387                                         return -1;
388                                 }
389                         }
390                 }
391         }
392
393         return 0;
394 }
395
396 /*
397  * perform basic searches
398  */
399 static int
400 simple_search(struct rte_pm_ctx * pmx, struct rte_pm_build_opt * bopt)
401 {
402         struct rte_pm_match res[MAX_MATCH_COUNT];
403         struct rte_pm_state state;
404         struct rte_pm_inbuf in_buf;
405
406         int i, len, ret;
407         int match, num_matches;
408
409         /* simple matching */
410         for (i = 0; i < pm_test_buf_len; i++) {
411
412                 memset(&res, 0, sizeof(res));
413                 memset(&state, 0, sizeof(struct rte_pm_state));
414
415                 /* prepare PM buffer */
416                 len = strnlen(pm_test_buf[i].string, sizeof(pm_test_buf[i].string));
417
418                 in_buf.buf = (const uint8_t*) pm_test_buf[i].string;
419                 in_buf.len = len;
420
421                 /* number of matches we are supposed to find */
422                 if (bopt->case_sense)
423                         num_matches = pm_test_buf[i].n_matches_with_case_sense;
424                 else
425                         num_matches = pm_test_buf[i].n_matches;
426
427                 ret = rte_pm_search_chain_start(pmx, &in_buf, res,
428                                 MAX_MATCH_COUNT, &state);
429
430                 if (ret != num_matches) {
431                         rte_pm_dump(pmx);
432                         printf("Line %i: Error matching %s (ret=%i num_matches=%i)!\n",
433                                         __LINE__, in_buf.buf, ret, num_matches);
434                         return -1;
435                 }
436                 /* check if match was correct */
437                 else {
438                         for (match = 0; match < num_matches; match++) {
439                                 if ((const char *)(uintptr_t)
440                                                 res[match].userdata !=
441                                                 pm_test_buf[i].matched_str[match]) {
442                                         rte_pm_dump(pmx);
443                                         printf("Line %i: Wrong match at simple search %i!\n",
444                                                         __LINE__, i);
445                                         printf("Matched: %s\n",
446                                                 (const char *)(uintptr_t)
447                                                 res[match].userdata);
448                                         printf("Should have matched: %s\n",
449                                                         pm_test_buf[i].matched_str[match]);
450                                         return -1;
451                                 }
452                         }
453                 }
454         }
455
456         return 0;
457 }
458
459 /*
460  * build PM context and call search function
461  */
462 static int
463 build_and_search(struct rte_pm_ctx * pmx,
464                                  struct rte_pm_search_avail * avail,
465                                  struct rte_pm_build_opt * bopt, enum pattern_set p_set)
466 {
467         struct rte_pm_param param;
468         struct rte_pm_ctx * pmx2;
469         struct pm_store_buf buffer;
470         enum rte_pm_search search_type;
471         int ret;
472
473         /* allocate load/store buffer */
474         if ((buffer.buf = malloc(BUFSIZE)) == NULL) {
475                 printf("%s at line %i: failed to allocate load/store buffer!\n",
476                         __func__, __LINE__);
477                 return (-1);
478         }
479         buffer.len = BUFSIZE;
480
481         /* prepare data for second context */
482         memcpy(&param, &good_param, sizeof(param));
483         param.name = "pmx2";
484
485         /* cycle through all search algorithms */
486         for (search_type = RTE_PM_SEARCH_UNDEF; search_type < RTE_PM_SEARCH_NUM;
487                         search_type++) {
488
489                 /* skip unavailable search types, but include RTE_PM_SEARCH_UNDEF
490                  * as it should work */
491                 if (search_type == RTE_PM_SEARCH_UNDEF ||
492                                 RTE_PM_GET_BIT(avail->avail, search_type) > 0) {
493
494                         /* make a note that we tested this algorithm */
495                         tested_algorithms[search_type] = 1;
496
497                         /* build pm */
498                         bopt->search_type = search_type;
499
500                         ret = rte_pm_build(pmx, bopt);
501                         if (ret == -ENOTSUP) {
502                                 printf("Line %i: Algorightm %s not supported.\n",
503                                                 __LINE__, rte_pm_search_names[search_type]);
504                                 continue;
505                         }
506                         else if (ret != 0) {
507                                 printf("Line %i: PM build for algorithm %s failed! "
508                                                 "Return code: %i\n",
509                                                 __LINE__, rte_pm_search_names[search_type], ret);
510                                 goto err;
511                         }
512
513                         /* select which buffer list to process */
514                         switch (p_set)
515                         {
516                         case PAT_CLEAN:
517                                 pm_test_buf = clean_buffers;
518                                 pm_test_buf_len = DIM(clean_buffers);
519                                 break;
520                         case PAT_MIXED:
521                                 pm_test_buf = mixed_buffers;
522                                 pm_test_buf_len = DIM(mixed_buffers);
523                                 break;
524                         case PAT_P1:
525                                 pm_test_buf = P1_buffers;
526                                 pm_test_buf_len = DIM(P1_buffers);
527                                 break;
528                         default:
529                                 goto err;
530                         }
531
532                         /* do searches */
533                         if (simple_search(pmx, bopt) < 0)
534                                 goto err;
535                         if (single_buffer_search(pmx, bopt) < 0)
536                                 goto err;
537                         if (split_buffer_search(pmx, bopt) < 0)
538                                 goto err;
539                         if (bulk_search(pmx, bopt) < 0)
540                                 goto err;
541
542                         /* create second context and load it with data from pmx */
543                         pmx2 = rte_pm_create(&param);
544                         if (pmx2 == NULL) {
545                                 printf("Line %i: Creating second context failed!\n", __LINE__);
546                                 goto err;
547                         }
548
549                         /* clear load/store buffer, store pmx data and load into pmx2 */
550                         memset(buffer.buf, 0, BUFSIZE);
551
552                         ret = rte_pm_store(pmx, pm_store, &buffer);
553                         if (ret != 0) {
554                                 printf("Line %i: PM store failed!\n", __LINE__);
555                                 goto err_pmx2;
556                         }
557
558                         ret = rte_pm_load(pmx2, pm_load, &buffer);
559                         if (ret != 0) {
560                                 printf("Line %i: PM load failed!\n", __LINE__);
561                                 goto err_pmx2;
562                         }
563
564                         /* do searches for pmx2 */
565                         if (simple_search(pmx2, bopt) < 0)
566                                 goto err_pmx2;
567                         if (single_buffer_search(pmx2, bopt) < 0)
568                                 goto err_pmx2;
569                         if (split_buffer_search(pmx2, bopt) < 0)
570                                 goto err_pmx2;
571                         if (bulk_search(pmx2, bopt) < 0)
572                                 goto err_pmx2;
573
574                         /* free second context */
575                         rte_pm_free(pmx2);
576                 }
577         }
578
579         /* free load/store buffer */
580         free(buffer.buf);
581
582         return 0;
583 err_pmx2:
584         rte_pm_free(pmx2);
585 err:
586         free(buffer.buf);
587         return -1;
588 }
589
590 /* add patterns to PM context */
591 static int
592 add_patterns(struct rte_pm_ctx * pmx, enum pattern_set p_set)
593 {
594         int i, ret;
595         struct rte_pm_pattern * pat = NULL;
596
597         /* only needed when converting strings */
598         uint8_t tmp_str[DIM(mixed_patterns)][MAX_PATTERN_LEN];
599
600         switch (p_set)
601         {
602                 case PAT_CLEAN:
603                 {
604                         /* allocate space for patterns */
605                         pat = malloc(sizeof(struct rte_pm_pattern) * DIM(clean_patterns));
606
607                         if (!pat) {
608                                 printf("Line %i: Allocating space for patterns failed!\n",
609                                                 __LINE__);
610                                 return -1;
611                         }
612
613                         for (i = 0; i < (int) DIM(clean_patterns); i++) {
614                                 pat[i].pattern = (const uint8_t *) clean_patterns[i];
615                                 pat[i].userdata = (uintptr_t) clean_patterns[i];
616                                 pat[i].len = strnlen(clean_patterns[i],
617                                                 sizeof(clean_patterns[i]));
618                         }
619
620                         ret = rte_pm_add_patterns(pmx, pat, DIM(clean_patterns));
621
622                         if (ret != 0) {
623                                 printf("Line %i: PM pattern add failed! Return code: %i\n",
624                                                 __LINE__, ret);
625                                 free(pat);
626                                 return -1;
627                         }
628                         free(pat);
629                         break;
630                 }
631                 case PAT_MIXED:
632                 {
633                         pat = NULL;
634
635                         pat = malloc(sizeof(struct rte_pm_pattern) * DIM(mixed_patterns));
636                         memset(tmp_str, 0, sizeof(tmp_str));
637
638                         if (!pat) {
639                                 printf("Line %i: Allocating space for patterns failed!\n",
640                                                 __LINE__);
641                                 if (pat)
642                                         free(pat);
643                                 return -1;
644                         }
645
646                         for (i = 0; i < (int) DIM(mixed_patterns); i++) {
647
648                                 ret = rte_pm_convert_pattern(mixed_patterns[i],
649                                                 tmp_str[i], MAX_PATTERN_LEN);
650
651                                 if (!ret) {
652                                         printf("Line %i: Converting pattern failed!\n", __LINE__);
653                                         free(pat);
654                                         return -1;
655                                 }
656                                 pat[i].pattern = tmp_str[i];
657                                 /* we assign original string here so that later comparison
658                                  * doesn't fail.
659                                  */
660                                 pat[i].userdata = (uintptr_t) mixed_patterns[i];
661                                 pat[i].len = strnlen((const char*) tmp_str[i], MAX_PATTERN_LEN);
662                         }
663
664                         ret = rte_pm_add_patterns(pmx, pat, DIM(mixed_patterns));
665
666                         if (ret != 0) {
667                                 printf("Line %i: PM pattern add failed! Return code: %i\n",
668                                                 __LINE__, ret);
669                                 free(pat);
670                                 return -1;
671                         }
672                         free(pat);
673                         break;
674                 }
675                 case PAT_P1:
676                 {
677                         pat = malloc(sizeof(struct rte_pm_pattern) * DIM(P1_patterns));
678
679                         if (!pat) {
680                                 printf("Line %i: Allocating space for patterns failed!\n",
681                                                 __LINE__);
682                                 return -1;
683                         }
684
685                         for (i = 0; i < (int) DIM(P1_patterns); i++) {
686                                 pat[i].pattern = (const uint8_t *) P1_patterns[i];
687                                 pat[i].userdata = (uintptr_t) P1_patterns[i];
688                                 pat[i].len = strnlen(P1_patterns[i], sizeof(P1_patterns[i]));
689                         }
690
691                         ret = rte_pm_add_patterns(pmx, pat, 1);
692
693                         if (ret != 0) {
694                                 printf("Line %i: PM pattern add failed! Return code: %i\n",
695                                                 __LINE__, ret);
696                                 free(pat);
697                                 return -1;
698                         }
699                         free(pat);
700                         break;
701                 }
702         default:
703                 printf("Line %i: Unknown pattern type\n", __LINE__);
704                 return -1;
705         }
706         return 0;
707 }
708
709 /*
710  * this function is in no way a replacement for
711  * proper in-depth unit tests (those are available
712  * as a separate application). this is just a quick
713  * sanity test to check basic functionality.
714  */
715 static int
716 test_search_patterns(void)
717 {
718         struct rte_pm_ctx * pmx;
719         struct rte_pm_search_avail avail;
720         struct rte_pm_build_opt bopt;
721         int i, ret;
722
723         /* bitmask to configure build options */
724         uint8_t options_bm = 0;
725         /* pattern set to use for tests */
726         enum pattern_set p_set;
727
728         /* reset the tested algorithms array */
729         memset(tested_algorithms, 0, sizeof(tested_algorithms));
730
731         /* two possible options: case sense and OOO */
732         for (options_bm = 0; options_bm < (1 << NUM_OPTS); options_bm++) {
733
734                 bopt.search_type = RTE_PM_SEARCH_UNDEF;
735
736                 /* configure options according to bitmask */
737                 bopt.case_sense = !!(options_bm & OPT_CASE_SENSE);
738                 bopt.out_of_order = !!(options_bm & OPT_OUT_OF_ORDER);
739
740                 for (p_set = PAT_CLEAN; p_set < PAT_NUM; p_set++) {
741
742                         /* create new PM context */
743                         pmx = rte_pm_create(&good_param);
744                         if (pmx == NULL) {
745                                 printf("Line %i: Failed to create PM context!\n", __LINE__);
746                                 return -1;
747                         }
748
749                         /* add patterns to context */
750                         ret = add_patterns(pmx, p_set);
751                         if (ret < 0)
752                                 goto err;
753
754                         ret = rte_pm_analyze(pmx, &bopt, &avail);
755                         if (ret != 0) {
756                                 printf("Line %i: PM analyze failed! Return code: %i\n",
757                                                 __LINE__, ret);
758                                 goto err;
759                         }
760
761                         ret = build_and_search(pmx, &avail, &bopt, p_set);
762                         if (ret < 0)
763                                 goto err;
764
765                         rte_pm_free(pmx);
766                 }
767         }
768
769         ret = 0;
770
771         /*
772          * check if all algorithms were attempted
773          */
774
775         /* skip nil algorithm */
776         for (i = 1; i < RTE_PM_SEARCH_NUM; i++) {
777                 if (tested_algorithms[i] == 0) {
778                         printf("Line %i: Algorithm %s was not tested!\n",
779                                         __LINE__, rte_pm_search_names[i]);
780                         ret = -1;
781                 }
782         }
783
784         return ret;
785 err:
786         rte_pm_free(pmx);
787         return -1;
788 }
789
790
791 /*
792  * Test creating and finding PM contexts, and adding patterns
793  */
794 static int
795 test_create_find_add(void)
796 {
797         struct rte_pm_param param;
798         struct rte_pm_ctx * pmx, *pmx2, *tmp;
799         struct rte_pm_pattern pat[LEN];
800         const char * pmx_name = "pmx";
801         const char * pmx2_name = "pmx2";
802         int i, ret;
803
804         /* create two contexts */
805         memcpy(&param, &good_param, sizeof(param));
806         param.max_pattern_len = 8;
807         param.max_pattern_num = 2;
808
809         param.name = pmx_name;
810         pmx = rte_pm_create(&param);
811         if (pmx == NULL) {
812                 printf("Line %i: Error creating %s!\n", __LINE__, pmx_name);
813                 return -1;
814         }
815
816         param.name = pmx2_name;
817         pmx2 = rte_pm_create(&param);
818         if (pmx2 == NULL || pmx2 == pmx) {
819                 printf("Line %i: Error creating %s!\n", __LINE__, pmx2_name);
820                 rte_pm_free(pmx);
821                 return -1;
822         }
823
824         /* try to create third one, with an existing name */
825         param.name = pmx_name;
826         tmp = rte_pm_create(&param);
827         if (tmp != pmx) {
828                 printf("Line %i: Creating context with existing name test failed!\n",
829                                 __LINE__);
830                 if (tmp)
831                         rte_pm_free(tmp);
832                 goto err;
833         }
834
835         param.name = pmx2_name;
836         tmp = rte_pm_create(&param);
837         if (tmp != pmx2) {
838                 printf("Line %i: Creating context with existing name test 2 failed!\n",
839                                 __LINE__);
840                 if (tmp)
841                         rte_pm_free(tmp);
842                 goto err;
843         }
844
845         /* try to find existing PM contexts */
846         tmp = rte_pm_find_existing(pmx_name);
847         if (tmp != pmx) {
848                 printf("Line %i: Finding %s failed!\n", __LINE__, pmx_name);
849                 if (tmp)
850                         rte_pm_free(tmp);
851                 goto err;
852         }
853
854         tmp = rte_pm_find_existing(pmx2_name);
855         if (tmp != pmx2) {
856                 printf("Line %i: Finding %s failed!\n", __LINE__, pmx2_name);
857                 if (tmp)
858                         rte_pm_free(tmp);
859                 goto err;
860         }
861
862         /* try to find non-existing context */
863         tmp = rte_pm_find_existing("invalid");
864         if (tmp != NULL) {
865                 printf("Line %i: Non-existent PM context found!\n", __LINE__);
866                 goto err;
867         }
868
869         rte_pm_free(pmx);
870
871
872         /* create valid (but severely limited) pmx */
873         memcpy(&param, &good_param, sizeof(param));
874         param.max_pattern_num = LEN;
875
876         pmx = rte_pm_create(&param);
877         if (pmx == NULL) {
878                 printf("Line %i: Error creating %s!\n", __LINE__, param.name);
879                 goto err;
880         }
881
882         /* create dummy patterns */
883         for (i = 0; i < LEN; i++) {
884                 pat[i].len = 4;
885                 pat[i].userdata = 0;
886                 pat[i].pattern = (const uint8_t*)"1234";
887         }
888
889         /* try filling up the context */
890         ret = rte_pm_add_patterns(pmx, pat, LEN);
891         if (ret != 0) {
892                 printf("Line %i: Adding %i patterns to PM context failed!\n",
893                                 __LINE__, LEN);
894                 goto err;
895         }
896
897         /* try adding to a (supposedly) full context */
898         ret = rte_pm_add_patterns(pmx, pat, 1);
899         if (ret == 0) {
900                 printf("Line %i: Adding patterns to full PM context "
901                                 "should have failed!\n", __LINE__);
902                 goto err;
903         }
904
905         rte_pm_free(pmx);
906
907         /* create another valid (but severely limited) pmx */
908         memcpy(&param, &good_param, sizeof(param));
909         param.max_pattern_len = LEN * 4;
910
911         pmx = rte_pm_create(&param);
912         if (pmx == NULL) {
913                 printf("Line %i: Error creating %s!\n", __LINE__, param.name);
914                 goto err;
915         }
916
917         /* create dummy patterns */
918         for (i = 0; i < LEN; i++) {
919                 pat[i].len = 4;
920                 pat[i].userdata = 0;
921                 pat[i].pattern = (const uint8_t*)"1234";
922         }
923
924         /* try filling up the context */
925         ret = rte_pm_add_patterns(pmx, pat, LEN);
926         if (ret != 0) {
927                 printf("Line %i: Adding %i patterns to PM context failed!\n",
928                                 __LINE__, LEN);
929                 goto err;
930         }
931
932         /* try adding to a (supposedly) full context */
933         ret = rte_pm_add_patterns(pmx, pat, 1);
934         if (ret == 0) {
935                 printf("Line %i: Adding patterns to full PM context "
936                                 "should have failed!\n", __LINE__);
937                 goto err;
938         }
939
940         rte_pm_free(pmx);
941         rte_pm_free(pmx2);
942
943         return 0;
944 err:
945         rte_pm_free(pmx);
946         rte_pm_free(pmx2);
947         return -1;
948 }
949
950 /*
951  * test serialization functions.
952  * tests include:
953  * - passing invalid parameters to function
954  * - trying to load invalid pm store
955  * - save buffer, load buffer, save another, and compare them
956  * - try to load/save with a too small buffer (pm_store/pm_load should fail)
957  */
958 static int
959 test_serialize(void)
960 {
961         struct rte_pm_ctx * pmx, * pmx2;
962         struct rte_pm_build_opt build_opt;
963         struct rte_pm_pattern pat[LEN];
964         int i, res;
965         struct pm_store_buf buffer, buffer2;
966
967         memset(&buffer, 0, sizeof (buffer));
968         memset(&buffer2, 0, sizeof (buffer2));
969
970         /* allocate two load/store buffers */
971         if ((buffer.buf = malloc(BUFSIZE)) == NULL ||
972                 (buffer2.buf = malloc(BUFSIZE)) == NULL) {
973                 printf("Line %i: Creating load/store buffers failed!\n",
974                         __LINE__);
975                 free(buffer2.buf);
976                 free(buffer.buf);
977                 return (-1);
978         }
979
980         buffer.len = BUFSIZE;
981         memset(buffer.buf, 0, BUFSIZE);
982
983         buffer2.len = BUFSIZE;
984         memset(buffer2.buf, 0, BUFSIZE);
985
986         /* create a context */
987         pmx = rte_pm_create(&good_param);
988         if (!pmx) {
989                 printf("Line %i: Creating pmx failed!\n", __LINE__);
990                 goto err;
991         }
992
993         /* create dummy patterns */
994         for (i = 0; i < LEN; i++) {
995                         pat[i].len = 4;
996                         pat[i].userdata = 0;
997                         pat[i].pattern = (const uint8_t*)"1234";
998         }
999
1000         /* fill context with patterns */
1001         res = rte_pm_add_patterns(pmx, pat, LEN);
1002         if (res != 0) {
1003                 printf("Line %i: Adding patterns to PM context failed!\n", __LINE__);
1004                 goto err;
1005         }
1006
1007         build_opt.search_type = RTE_PM_SEARCH_UNDEF;
1008
1009         /* build the patterns */
1010         res = rte_pm_build(pmx, &build_opt);
1011         if (res != 0) {
1012                 printf("Line %i: Building PM context failed!\n", __LINE__);
1013                 goto err;
1014         }
1015
1016         /**
1017          * test serialize functions
1018          */
1019         res = rte_pm_store(NULL, pm_store, &buffer);
1020         if (res != -EINVAL) {
1021                 printf("Line %i: PM store should have failed!\n", __LINE__);
1022                 goto err;
1023         }
1024
1025         res = rte_pm_store(pmx, NULL, &buffer);
1026         if (res != -EINVAL) {
1027                 printf("Line %i: PM store should have failed!\n", __LINE__);
1028                 goto err;
1029         }
1030
1031         res = rte_pm_store(pmx, pm_store, NULL);
1032         if (res != -EINVAL) {
1033                 printf("Line %i: PM store should have failed!\n", __LINE__);
1034                 goto err;
1035         }
1036
1037
1038         res = rte_pm_load(NULL, pm_load, &buffer);
1039         if (res != -EINVAL) {
1040                 printf("Line %i: PM load should have failed!\n", __LINE__);
1041                 goto err;
1042         }
1043
1044         res = rte_pm_load(pmx, NULL, &buffer);
1045         if (res != -EINVAL) {
1046                 printf("Line %i: PM load should have failed!\n", __LINE__);
1047                 goto err;
1048         }
1049
1050         res = rte_pm_load(pmx, pm_load, NULL);
1051         if (res != -EINVAL) {
1052                 printf("Line %i: PM load should have failed!\n", __LINE__);
1053                 goto err;
1054         }
1055
1056         /* since buffer is currently zeroed out, load should complain about
1057          * unsupported format*/
1058         res = rte_pm_load(pmx, pm_load, &buffer);
1059         if (res != -EINVAL) {
1060                 printf("Line %i: PM load should have failed!\n", __LINE__);
1061                 goto err;
1062         }
1063
1064         /* rte_pm_load zeroed out the context, so re-add all patterns, rebuild,
1065          * save the context to buffer and free context
1066          */
1067         rte_pm_free(pmx);
1068
1069         /* create a context */
1070         pmx = rte_pm_create(&good_param);
1071         if (!pmx) {
1072                 printf("Line %i: Creating pmx failed!\n", __LINE__);
1073                 goto err;
1074         }
1075
1076         res = rte_pm_add_patterns(pmx, pat, LEN);
1077         if (res != 0) {
1078                 printf("Line %i: Adding patterns to PM context failed!\n", __LINE__);
1079                 goto err;
1080         }
1081
1082         res = rte_pm_build(pmx, &build_opt);
1083         if (res != 0) {
1084                 printf("Line %i: Building PM context failed!\n", __LINE__);
1085                 goto err;
1086         }
1087
1088         res = rte_pm_store(pmx, pm_store, &buffer);
1089         if (res != 0) {
1090                 printf("Line %i: PM store failed!\n", __LINE__);
1091                 goto err;
1092         }
1093
1094         rte_pm_free(pmx);
1095         pmx = NULL;
1096
1097
1098
1099         /* create pmx2 */
1100         pmx2 = rte_pm_create(&good_param);
1101         if (!pmx2) {
1102                 printf("Line %i: Creating pmx2 failed!\n", __LINE__);
1103                 goto err;
1104         }
1105
1106         /* load buffer into pmx2 */
1107         res = rte_pm_load(pmx2, pm_load, &buffer);
1108         if (res != 0) {
1109                 printf("Line %i: PM load failed!\n", __LINE__);
1110                 goto err_pmx2;
1111         }
1112
1113         /* save pmx2 into another buffer */
1114         res = rte_pm_store(pmx2, pm_store, &buffer2);
1115         if (res != 0) {
1116                 printf("Line %i: PM store failed!\n", __LINE__);
1117                 goto err_pmx2;
1118         }
1119
1120         /* compare two buffers */
1121         if (memcmp(buffer.buf, buffer2.buf, BUFSIZE) != 0) {
1122                 printf("Line %i: Buffers are different!\n", __LINE__);
1123                 goto err_pmx2;
1124         }
1125
1126         /* try and save pmx2 into a too small buffer */
1127         buffer2.len = 4;
1128         res = rte_pm_store(pmx2, pm_store, &buffer2);
1129         if (res != -ENOMEM) {
1130                 printf("Line %i: PM store should have failed!\n", __LINE__);
1131                 goto err_pmx2;
1132         }
1133
1134         /* try and load from a too small buffer */
1135         res = rte_pm_load(pmx2, pm_load, &buffer2);
1136         if (res != -ENOMEM) {
1137                 printf("Line %i: PM load should have failed!\n", __LINE__);
1138                 goto err_pmx2;
1139         }
1140
1141         /* free everything */
1142         rte_pm_free(pmx2);
1143
1144         free(buffer2.buf);
1145         free(buffer.buf);
1146
1147         return 0;
1148 err_pmx2:
1149         rte_pm_free(pmx2);
1150 err:
1151         rte_pm_free(pmx);
1152         free(buffer2.buf);
1153         free(buffer.buf);
1154         return -1;
1155 }
1156
1157 /*
1158  * test functions by passing invalid or
1159  * non-workable parameters.
1160  *
1161  * we do NOT test pattern search functions here
1162  * because those are performance-critical and
1163  * thus don't do any parameter checking.
1164  */
1165 static int
1166 test_invalid_parameters(void)
1167 {
1168         struct rte_pm_param param;
1169         struct rte_pm_ctx * pmx;
1170         enum rte_pm_search search_result;
1171         int res = 0;
1172         /* needed for rte_pm_convert_pattern */
1173         char in_buf[LEN];
1174         uint8_t out_buf[LEN];
1175         /* needed for rte_pm_add_patterns */
1176         struct rte_pm_pattern pat;
1177         /* needed for rte_pm_analyze */
1178         struct rte_pm_search_avail build_res[LEN];
1179         /* needed for rte_pm_build */
1180         struct rte_pm_build_opt build_opt;
1181
1182
1183         /**
1184          * rte_pm_create()
1185          */
1186
1187         /* NULL param */
1188         pmx = rte_pm_create(NULL);
1189         if (pmx != NULL) {
1190                 printf("Line %i: PM context creation with NULL param "
1191                                 "should have failed!\n", __LINE__);
1192                 rte_pm_free(pmx);
1193                 return -1;
1194         }
1195
1196         /* zero pattern len */
1197         memcpy(&param, &good_param, sizeof(param));
1198         param.max_pattern_len = 0;
1199
1200         pmx = rte_pm_create(&param);
1201         if (pmx == NULL) {
1202                 printf("Line %i: PM context creation with zero pattern len failed!\n",
1203                                 __LINE__);
1204                 return -1;
1205         }
1206         else
1207                 rte_pm_free(pmx);
1208
1209         /* zero pattern num */
1210         memcpy(&param, &good_param, sizeof(param));
1211         param.max_pattern_num = 0;
1212
1213         pmx = rte_pm_create(&param);
1214         if (pmx == NULL) {
1215                 printf("Line %i: PM context creation with zero pattern num failed!\n",
1216                                 __LINE__);
1217                 return -1;
1218         }
1219         else
1220                 rte_pm_free(pmx);
1221
1222         /* invalid NUMA node */
1223         memcpy(&param, &good_param, sizeof(param));
1224         param.socket_id = RTE_MAX_NUMA_NODES + 1;
1225
1226         pmx = rte_pm_create(&param);
1227         if (pmx != NULL) {
1228                 printf("Line %i: PM context creation with invalid NUMA "
1229                                 "should have failed!\n", __LINE__);
1230                 rte_pm_free(pmx);
1231                 return -1;
1232         }
1233
1234         /* NULL name */
1235         memcpy(&param, &good_param, sizeof(param));
1236         param.name = NULL;
1237
1238         pmx = rte_pm_create(&param);
1239         if (pmx != NULL) {
1240                 printf("Line %i: PM context creation with NULL name "
1241                                 "should have failed!\n", __LINE__);
1242                 rte_pm_free(pmx);
1243                 return -1;
1244         }
1245
1246         /**
1247          * rte_pm_search_type_by_name()
1248          */
1249
1250         /* invalid algorithm names */
1251         search_result = rte_pm_search_type_by_name("invalid");
1252         if (search_result != RTE_PM_SEARCH_UNDEF) {
1253                 printf("Line %i: Found invalid PM algorithm!\n", __LINE__);
1254         }
1255
1256         search_result = rte_pm_search_type_by_name(NULL);
1257         if (search_result != RTE_PM_SEARCH_UNDEF) {
1258                 printf("Line %i: Found NULL PM algorithm!\n", __LINE__);
1259         }
1260
1261         /**
1262          * rte_pm_convert_pattern()
1263          */
1264
1265         /* null in buffer */
1266         res = rte_pm_convert_pattern(NULL, out_buf, sizeof(out_buf));
1267         if (res != (-EINVAL)) {
1268                 printf("Line %i: Converting a NULL input pattern "
1269                                 "should have failed!\n", __LINE__);
1270                 return -1;
1271         }
1272
1273         /* null out buffer */
1274         res = rte_pm_convert_pattern(in_buf, NULL, sizeof(out_buf));
1275         if (res != (-EINVAL)) {
1276                 printf("Line %i: Converting to NULL output buffer "
1277                                 "should have failed!\n", __LINE__);
1278                 return -1;
1279         }
1280
1281         /* zero length (should throw -ENOMEM) */
1282         res = rte_pm_convert_pattern(in_buf, out_buf, 0);
1283         if (res != -(ENOMEM)) {
1284                 printf("Line %i: Converting to a 0-length output buffer "
1285                                 "should have failed!\n", __LINE__);
1286                 return -1;
1287         }
1288
1289         /* wrong binary value */
1290         res = rte_pm_convert_pattern("|1", out_buf, sizeof(out_buf));
1291         if (res != (-EINVAL)) {
1292                 printf("Line %i: Converting malformed binary "
1293                                 "should have failed!\n", __LINE__);
1294                 return -1;
1295         }
1296
1297         /* wrong binary value */
1298         res = rte_pm_convert_pattern("|P1|", out_buf, sizeof(out_buf));
1299         if (res != (-EINVAL)) {
1300                 printf("Line %i: Converting malformed binary "
1301                                 "should have failed!\n", __LINE__);
1302                 return -1;
1303         }
1304
1305         /* wrong binary value */
1306         res = rte_pm_convert_pattern("|FFF|", out_buf, sizeof(out_buf));
1307         if (res != (-EINVAL)) {
1308                 printf("Line %i: Converting malformed binary "
1309                                 "should have failed!\n", __LINE__);
1310                 return -1;
1311         }
1312
1313         /**
1314          * rte_pm_add_patterns()
1315          */
1316         /* create valid pmx since we'll need it for tests */
1317         memcpy(&param, &good_param, sizeof(param));
1318
1319         param.max_pattern_len = 2;
1320
1321         pmx = rte_pm_create(&param);
1322         if (!pmx) {
1323                 printf("Line %i: Creating pmx failed!\n", __LINE__);
1324                 return -1;
1325         }
1326
1327         /* NULL pmx */
1328         res = rte_pm_add_patterns(NULL, &pat, LEN);
1329         if (res != -EINVAL) {
1330                 printf("Line %i: Adding patterns to NULL PM context "
1331                                 "should have failed!\n", __LINE__);
1332                 return -1;
1333         }
1334
1335         /* NULL pat */
1336         res = rte_pm_add_patterns(pmx, NULL, LEN);
1337         if (res != -EINVAL) {
1338                 printf("Line %i: Adding patterns to NULL pattern "
1339                                 "should have failed!\n", __LINE__);
1340                 return -1;
1341         }
1342
1343         pat.len = 4;
1344
1345         /* zero len (should succeed) */
1346         res = rte_pm_add_patterns(pmx, &pat, 0);
1347         if (res != 0) {
1348                 printf("Line %i: Adding 0 patterns to PM context failed!\n", __LINE__);
1349                 rte_pm_free(pmx);
1350                 return -1;
1351         }
1352
1353         /**
1354          * rte_pm_analyze()
1355          */
1356
1357         /* NULL context */
1358         res = rte_pm_analyze(NULL, &build_opt, build_res);
1359         if (res != -EINVAL) {
1360                 printf("Line %i: PM analyze on NULL pmx "
1361                                 "should have failed!\n", __LINE__);
1362                 rte_pm_free(pmx);
1363                 return -1;
1364         }
1365
1366         /* NULL opt */
1367         res = rte_pm_analyze(pmx, NULL, build_res);
1368         if (res != -EINVAL) {
1369                 printf("Line %i: PM analyze on NULL opt "
1370                                 "should have failed!\n", __LINE__);
1371                 rte_pm_free(pmx);
1372                 return -1;
1373         }
1374
1375         /* NULL res */
1376         res = rte_pm_analyze(pmx, &build_opt, NULL);
1377         if (res != -EINVAL) {
1378                 printf("Line %i: PM analyze on NULL res should have failed!\n",
1379                                 __LINE__);
1380                 rte_pm_free(pmx);
1381                 return -1;
1382         }
1383
1384         /**
1385          * rte_pm_build()
1386          */
1387
1388         /* NULL context */
1389         res = rte_pm_build(NULL, &build_opt);
1390         if (res != -EINVAL) {
1391                 printf("Line %i: PM build on NULL pmx should have failed!\n",
1392                                 __LINE__);
1393                 rte_pm_free(pmx);
1394                 return -1;
1395         }
1396
1397         /* NULL opt */
1398         res = rte_pm_build(pmx, NULL);
1399         if (res != -EINVAL) {
1400                 printf("Line %i: PM build on NULL opt should have failed!\n", __LINE__);
1401                 rte_pm_free(pmx);
1402                 return -1;
1403         }
1404
1405         /* build with unsuitable algorithm */
1406         build_opt.case_sense = 0;
1407         build_opt.out_of_order = 0;
1408         /* MB expects out_of_order */
1409         build_opt.search_type = RTE_PM_SEARCH_AC2_L1x4_MB;
1410
1411         res = rte_pm_build(pmx, &build_opt);
1412         if (res != -EINVAL) {
1413                 printf("Line %i: PM build on NULL opt should have failed! %i\n",
1414                                 __LINE__, res);
1415                 rte_pm_free(pmx);
1416                 return -1;
1417         }
1418
1419         /* free context */
1420         rte_pm_free(pmx);
1421
1422         /**
1423          * make sure void functions don't crash with NULL parameters
1424          */
1425
1426         rte_pm_free(NULL);
1427
1428         rte_pm_dump(NULL);
1429
1430         return 0;
1431 }
1432
1433
1434 /**
1435  * Various tests that don't test much but improve coverage
1436  */
1437 static int
1438 test_misc(void)
1439 {
1440         struct rte_pm_build_opt build_opt;
1441         struct rte_pm_pattern pat;
1442         struct rte_pm_ctx * pmx;
1443         enum rte_pm_search search_result;
1444         char buf[MAX_PATTERN_LEN];
1445         int ret;
1446
1447         pmx = NULL;
1448
1449         /* search for existing PM algorithm */
1450         search_result = rte_pm_search_type_by_name("AC2_L1x4");
1451         if (search_result != RTE_PM_SEARCH_AC2_L1x4) {
1452                 printf("Line %i: Wrong PM algorithm found!\n", __LINE__);
1453         }
1454
1455         pmx = rte_pm_create(&good_param);
1456         if (!pmx) {
1457                 printf("Line %i: Failed to create PM context!\n", __LINE__);
1458                 return -1;
1459         }
1460
1461         /* convert a pattern and add it to context */
1462         ret = rte_pm_convert_pattern("|01 02 03 04| readable", (uint8_t*) buf,
1463                         sizeof(buf));
1464         if (ret <= 0) {
1465                 rte_pm_free(pmx);
1466                 printf("Line %i: Converting binary failed!\n", __LINE__);
1467                 return -1;
1468         }
1469
1470         /* add pattern to context */
1471         pat.len = (uint32_t) ret;
1472         pat.pattern = (const uint8_t *) buf;
1473         pat.userdata = 0;
1474
1475         ret = rte_pm_add_patterns(pmx, &pat, 1);
1476         if (ret != 0) {
1477                 rte_pm_free(pmx);
1478                 printf("Line %i: Adding pattern failed!\n", __LINE__);
1479                 return -1;
1480         }
1481
1482         /* convert another pattern and add it to context */
1483         ret = rte_pm_convert_pattern("pattern", (uint8_t*) buf, 4);
1484
1485         if (ret <= 0) {
1486                 rte_pm_free(pmx);
1487                 printf("Line %i: Converting pattern failed!\n", __LINE__);
1488                 return -1;
1489         }
1490
1491         /* add pattern to context */
1492         pat.len = (uint32_t) ret;
1493         pat.pattern = (const uint8_t *) buf;
1494         pat.userdata = 0;
1495
1496         ret = rte_pm_add_patterns(pmx, &pat, 1);
1497         if (ret != 0) {
1498                 rte_pm_free(pmx);
1499                 printf("Line %i: Adding pattern failed!\n", __LINE__);
1500                 return -1;
1501         }
1502
1503         build_opt.case_sense = 0;
1504         build_opt.out_of_order = 0;
1505         build_opt.search_type = RTE_PM_SEARCH_AC2_L1x4;
1506
1507         ret = rte_pm_build(pmx, &build_opt);
1508         if (ret != 0) {
1509                 rte_pm_free(pmx);
1510                 printf("Line %i: Building PM failed!\n", __LINE__);
1511                 return -1;
1512         }
1513
1514         /* dump context with patterns - useful for coverage */
1515         rte_pm_list_dump();
1516
1517         rte_pm_dump(pmx);
1518
1519         rte_pm_free(pmx);
1520
1521         return 0;
1522 }
1523
1524 int
1525 test_pmac_pm(void)
1526 {
1527         if (test_invalid_parameters() < 0)
1528                 return -1;
1529         if (test_serialize() < 0)
1530                 return -1;
1531         if (test_create_find_add() < 0)
1532                 return -1;
1533         if (test_search_patterns() < 0)
1534                 return -1;
1535         if (test_misc() < 0)
1536                 return -1;
1537         return 0;
1538 }
1539
1540 #else /* RTE_LIBRTE_PMAC=n */
1541
1542 int
1543 test_pmac_pm(void)
1544 {
1545         printf("This binary was not compiled with PMAC support!\n");
1546         return 0;
1547 }
1548
1549 #endif /* RTE_LIBRTE_PMAC */