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