misc: binary api fuzz test fixes
[vpp.git] / test / ext / vapi_c_test.c
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2017 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *------------------------------------------------------------------
16  */
17
18 #include <stdio.h>
19 #include <endian.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <assert.h>
23 #include <setjmp.h>
24 #include <check.h>
25 #include <vppinfra/string.h>
26 #include <vapi/vapi.h>
27 #include <vapi/vpe.api.vapi.h>
28 #include <vapi/interface.api.vapi.h>
29 #include <vapi/l2.api.vapi.h>
30 #include <fake.api.vapi.h>
31
32 #include <vppinfra/vec.h>
33 #include <vppinfra/mem.h>
34
35 DEFINE_VAPI_MSG_IDS_VPE_API_JSON;
36 DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON;
37 DEFINE_VAPI_MSG_IDS_L2_API_JSON;
38 DEFINE_VAPI_MSG_IDS_FAKE_API_JSON;
39
40 static char *app_name = NULL;
41 static char *api_prefix = NULL;
42 static const int max_outstanding_requests = 64;
43 static const int response_queue_size = 32;
44
45 /* centos has ancient check so we hack our way around here
46  * to make it work somehow */
47 #ifndef ck_assert_ptr_eq
48 #define ck_assert_ptr_eq(X,Y) ck_assert_int_eq((long)X, (long)Y)
49 #endif
50
51 #ifndef ck_assert_ptr_ne
52 #define ck_assert_ptr_ne(X,Y) ck_assert_int_ne((long)X, (long)Y)
53 #endif
54
55 START_TEST (test_invalid_values)
56 {
57   vapi_ctx_t ctx;
58   vapi_error_e rv = vapi_ctx_alloc (&ctx);
59   ck_assert_int_eq (VAPI_OK, rv);
60   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
61   ck_assert_ptr_eq (NULL, sv);
62   rv = vapi_send (ctx, sv);
63   ck_assert_int_eq (VAPI_EINVAL, rv);
64   rv = vapi_connect (ctx, app_name, api_prefix, max_outstanding_requests,
65                      response_queue_size, VAPI_MODE_BLOCKING, true);
66   ck_assert_int_eq (VAPI_OK, rv);
67   rv = vapi_send (ctx, NULL);
68   ck_assert_int_eq (VAPI_EINVAL, rv);
69   rv = vapi_send (NULL, NULL);
70   ck_assert_int_eq (VAPI_EINVAL, rv);
71   rv = vapi_recv (NULL, NULL, NULL, 0, 0);
72   ck_assert_int_eq (VAPI_EINVAL, rv);
73   rv = vapi_recv (ctx, NULL, NULL, 0, 0);
74   ck_assert_int_eq (VAPI_EINVAL, rv);
75   vapi_msg_show_version_reply *reply;
76   rv = vapi_recv (ctx, (void **) &reply, NULL, 0, 0);
77   ck_assert_int_eq (VAPI_EINVAL, rv);
78   rv = vapi_disconnect (ctx);
79   ck_assert_int_eq (VAPI_OK, rv);
80   vapi_ctx_free (ctx);
81 }
82
83 END_TEST;
84
85 START_TEST (test_hton_1)
86 {
87   const u16 _vl_msg_id = 1;
88   vapi_type_msg_header1_t h;
89   h._vl_msg_id = _vl_msg_id;
90   vapi_type_msg_header1_t_hton (&h);
91   ck_assert_int_eq (be16toh (h._vl_msg_id), _vl_msg_id);
92 }
93
94 END_TEST;
95
96 START_TEST (test_hton_2)
97 {
98   const u16 _vl_msg_id = 1;
99   const u32 client_index = 3;
100   vapi_type_msg_header2_t h;
101   h._vl_msg_id = _vl_msg_id;
102   h.client_index = client_index;
103   vapi_type_msg_header2_t_hton (&h);
104   ck_assert_int_eq (be16toh (h._vl_msg_id), _vl_msg_id);
105   ck_assert_int_eq (h.client_index, client_index);
106 }
107
108 END_TEST;
109
110 #define verify_hton_swap(expr, value)           \
111   if (4 == sizeof (expr))                       \
112     {                                           \
113       ck_assert_int_eq (expr, htobe32 (value)); \
114     }                                           \
115   else if (2 == sizeof (expr))                  \
116     {                                           \
117       ck_assert_int_eq (expr, htobe16 (value)); \
118     }                                           \
119   else                                          \
120     {                                           \
121       ck_assert_int_eq (expr, value);           \
122     }
123
124 START_TEST (test_hton_4)
125 {
126   const int vla_count = 3;
127   char x[sizeof (vapi_msg_bridge_domain_details) +
128          vla_count * sizeof (vapi_type_bridge_domain_sw_if)];
129   vapi_msg_bridge_domain_details *d = (void *) x;
130   int cnt = 1;
131   d->header._vl_msg_id = cnt++;
132   d->header.context = cnt++;
133   d->payload.bd_id = cnt++;
134   d->payload.mac_age = cnt++;
135   d->payload.bvi_sw_if_index = cnt++;
136   d->payload.n_sw_ifs = vla_count;
137   int i;
138   for (i = 0; i < vla_count; ++i)
139     {
140       vapi_type_bridge_domain_sw_if *det = &d->payload.sw_if_details[i];
141       det->context = cnt++;
142       det->sw_if_index = cnt++;
143       det->shg = cnt++;
144     }
145   ck_assert_int_eq (sizeof (x), vapi_calc_bridge_domain_details_msg_size (d));
146   vapi_msg_bridge_domain_details_hton (d);
147   int tmp = 1;
148   verify_hton_swap (d->header._vl_msg_id, tmp);
149   ++tmp;
150   ck_assert_int_eq (d->header.context, tmp);
151   ++tmp;
152   verify_hton_swap (d->payload.bd_id, tmp);
153   ++tmp;
154   verify_hton_swap (d->payload.mac_age, tmp);
155   ++tmp;
156   verify_hton_swap (d->payload.bvi_sw_if_index, tmp);
157   ++tmp;
158   ck_assert_int_eq (d->payload.n_sw_ifs, htobe32 (vla_count));
159   for (i = 0; i < vla_count; ++i)
160     {
161       vapi_type_bridge_domain_sw_if *det = &d->payload.sw_if_details[i];
162       verify_hton_swap (det->context, tmp);
163       ++tmp;
164       verify_hton_swap (det->sw_if_index, tmp);
165       ++tmp;
166       verify_hton_swap (det->shg, tmp);
167       ++tmp;
168     }
169   vapi_msg_bridge_domain_details_ntoh (d);
170   tmp = 1;
171   ck_assert_int_eq (d->header._vl_msg_id, tmp);
172   ++tmp;
173   ck_assert_int_eq (d->header.context, tmp);
174   ++tmp;
175   ck_assert_int_eq (d->payload.bd_id, tmp);
176   ++tmp;
177   ck_assert_int_eq (d->payload.mac_age, tmp);
178   ++tmp;
179   ck_assert_int_eq (d->payload.bvi_sw_if_index, tmp);
180   ++tmp;
181   ck_assert_int_eq (d->payload.n_sw_ifs, vla_count);
182   for (i = 0; i < vla_count; ++i)
183     {
184       vapi_type_bridge_domain_sw_if *det = &d->payload.sw_if_details[i];
185       ck_assert_int_eq (det->context, tmp);
186       ++tmp;
187       ck_assert_int_eq (det->sw_if_index, tmp);
188       ++tmp;
189       ck_assert_int_eq (det->shg, tmp);
190       ++tmp;
191     }
192   ck_assert_int_eq (sizeof (x), vapi_calc_bridge_domain_details_msg_size (d));
193 }
194
195 END_TEST;
196
197 START_TEST (test_ntoh_1)
198 {
199   const u16 _vl_msg_id = 1;
200   vapi_type_msg_header1_t h;
201   h._vl_msg_id = _vl_msg_id;
202   vapi_type_msg_header1_t_ntoh (&h);
203   ck_assert_int_eq (htobe16 (h._vl_msg_id), _vl_msg_id);
204 }
205
206 END_TEST;
207
208 START_TEST (test_ntoh_2)
209 {
210   const u16 _vl_msg_id = 1;
211   const u32 client_index = 3;
212   vapi_type_msg_header2_t h;
213   h._vl_msg_id = _vl_msg_id;
214   h.client_index = client_index;
215   vapi_type_msg_header2_t_ntoh (&h);
216   ck_assert_int_eq (htobe16 (h._vl_msg_id), _vl_msg_id);
217   ck_assert_int_eq (h.client_index, client_index);
218 }
219
220 END_TEST;
221
222 #define verify_ntoh_swap(expr, value)           \
223   if (4 == sizeof (expr))                       \
224     {                                           \
225       ck_assert_int_eq (expr, be32toh (value)); \
226     }                                           \
227   else if (2 == sizeof (expr))                  \
228     {                                           \
229       ck_assert_int_eq (expr, be16toh (value)); \
230     }                                           \
231   else                                          \
232     {                                           \
233       ck_assert_int_eq (expr, value);           \
234     }
235
236 START_TEST (test_ntoh_4)
237 {
238   const int vla_count = 3;
239   char x[sizeof (vapi_msg_bridge_domain_details) +
240          vla_count * sizeof (vapi_type_bridge_domain_sw_if)];
241   vapi_msg_bridge_domain_details *d = (void *) x;
242   int cnt = 1;
243   d->header._vl_msg_id = cnt++;
244   d->header.context = cnt++;
245   d->payload.bd_id = cnt++;
246   d->payload.mac_age = cnt++;
247   d->payload.bvi_sw_if_index = cnt++;
248   d->payload.n_sw_ifs = htobe32 (vla_count);
249   int i;
250   for (i = 0; i < vla_count; ++i)
251     {
252       vapi_type_bridge_domain_sw_if *det = &d->payload.sw_if_details[i];
253       det->context = cnt++;
254       det->sw_if_index = cnt++;
255       det->shg = cnt++;
256     }
257   vapi_msg_bridge_domain_details_ntoh (d);
258   ck_assert_int_eq (sizeof (x), vapi_calc_bridge_domain_details_msg_size (d));
259   int tmp = 1;
260   verify_ntoh_swap (d->header._vl_msg_id, tmp);
261   ++tmp;
262   ck_assert_int_eq (d->header.context, tmp);
263   ++tmp;
264   verify_ntoh_swap (d->payload.bd_id, tmp);
265   ++tmp;
266   verify_ntoh_swap (d->payload.mac_age, tmp);
267   ++tmp;
268   verify_ntoh_swap (d->payload.bvi_sw_if_index, tmp);
269   ++tmp;
270   ck_assert_int_eq (d->payload.n_sw_ifs, vla_count);
271   for (i = 0; i < vla_count; ++i)
272     {
273       vapi_type_bridge_domain_sw_if *det = &d->payload.sw_if_details[i];
274       verify_ntoh_swap (det->context, tmp);
275       ++tmp;
276       verify_ntoh_swap (det->sw_if_index, tmp);
277       ++tmp;
278       verify_ntoh_swap (det->shg, tmp);
279       ++tmp;
280     }
281   vapi_msg_bridge_domain_details_hton (d);
282   tmp = 1;
283   ck_assert_int_eq (d->header._vl_msg_id, tmp);
284   ++tmp;
285   ck_assert_int_eq (d->header.context, tmp);
286   ++tmp;
287   ck_assert_int_eq (d->payload.bd_id, tmp);
288   ++tmp;
289   ck_assert_int_eq (d->payload.mac_age, tmp);
290   ++tmp;
291   ck_assert_int_eq (d->payload.bvi_sw_if_index, tmp);
292   ++tmp;
293   ck_assert_int_eq (d->payload.n_sw_ifs, htobe32 (vla_count));
294   for (i = 0; i < vla_count; ++i)
295     {
296       vapi_type_bridge_domain_sw_if *det = &d->payload.sw_if_details[i];
297       ck_assert_int_eq (det->context, tmp);
298       ++tmp;
299       ck_assert_int_eq (det->sw_if_index, tmp);
300       ++tmp;
301       ck_assert_int_eq (det->shg, tmp);
302       ++tmp;
303     }
304 }
305
306 END_TEST;
307
308 vapi_error_e
309 show_version_cb (vapi_ctx_t ctx, void *caller_ctx,
310                  vapi_error_e rv, bool is_last,
311                  vapi_payload_show_version_reply * p)
312 {
313   ck_assert_int_eq (VAPI_OK, rv);
314   ck_assert_int_eq (true, is_last);
315   ck_assert_str_eq ("vpe", (char *) p->program);
316   printf
317     ("show_version_reply: program: `%s', version: `%s', build directory: "
318      "`%s', build date: `%s'\n", p->program, p->version, p->build_directory,
319      p->build_date);
320   ++*(int *) caller_ctx;
321   return VAPI_OK;
322 }
323
324 typedef struct
325 {
326   int called;
327   int expected_retval;
328   u32 *sw_if_index_storage;
329 } test_create_loopback_ctx_t;
330
331 vapi_error_e
332 loopback_create_cb (vapi_ctx_t ctx, void *caller_ctx,
333                     vapi_error_e rv, bool is_last,
334                     vapi_payload_create_loopback_reply * p)
335 {
336   test_create_loopback_ctx_t *clc = caller_ctx;
337   ck_assert_int_eq (clc->expected_retval, p->retval);
338   *clc->sw_if_index_storage = p->sw_if_index;
339   ++clc->called;
340   return VAPI_OK;
341 }
342
343 typedef struct
344 {
345   int called;
346   int expected_retval;
347   u32 *sw_if_index_storage;
348 } test_delete_loopback_ctx_t;
349
350 vapi_error_e
351 loopback_delete_cb (vapi_ctx_t ctx, void *caller_ctx,
352                     vapi_error_e rv, bool is_last,
353                     vapi_payload_delete_loopback_reply * p)
354 {
355   test_delete_loopback_ctx_t *dlc = caller_ctx;
356   ck_assert_int_eq (dlc->expected_retval, p->retval);
357   ++dlc->called;
358   return VAPI_OK;
359 }
360
361 START_TEST (test_connect)
362 {
363   vapi_ctx_t ctx;
364   vapi_error_e rv = vapi_ctx_alloc (&ctx);
365   ck_assert_int_eq (VAPI_OK, rv);
366   rv = vapi_connect (ctx, app_name, api_prefix, max_outstanding_requests,
367                      response_queue_size, VAPI_MODE_BLOCKING, true);
368   ck_assert_int_eq (VAPI_OK, rv);
369   rv = vapi_disconnect (ctx);
370   ck_assert_int_eq (VAPI_OK, rv);
371   vapi_ctx_free (ctx);
372 }
373
374 END_TEST;
375
376 vapi_ctx_t ctx;
377
378 void
379 setup_blocking (void)
380 {
381   vapi_error_e rv = vapi_ctx_alloc (&ctx);
382   ck_assert_int_eq (VAPI_OK, rv);
383   rv = vapi_connect (ctx, app_name, api_prefix, max_outstanding_requests,
384                      response_queue_size, VAPI_MODE_BLOCKING, true);
385   ck_assert_int_eq (VAPI_OK, rv);
386 }
387
388 void
389 setup_nonblocking (void)
390 {
391   vapi_error_e rv = vapi_ctx_alloc (&ctx);
392   ck_assert_int_eq (VAPI_OK, rv);
393   rv = vapi_connect (ctx, app_name, api_prefix, max_outstanding_requests,
394                      response_queue_size, VAPI_MODE_NONBLOCKING, true);
395   ck_assert_int_eq (VAPI_OK, rv);
396 }
397
398 void
399 teardown (void)
400 {
401   vapi_disconnect (ctx);
402   vapi_ctx_free (ctx);
403 }
404
405 START_TEST (test_show_version_1)
406 {
407   printf ("--- Basic show version message - reply test ---\n");
408   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
409   ck_assert_ptr_ne (NULL, sv);
410   vapi_msg_show_version_hton (sv);
411   vapi_error_e rv = vapi_send (ctx, sv);
412   ck_assert_int_eq (VAPI_OK, rv);
413   vapi_msg_show_version_reply *resp;
414   size_t size;
415   rv = vapi_recv (ctx, (void *) &resp, &size, 0, 0);
416   ck_assert_int_eq (VAPI_OK, rv);
417   int dummy;
418   show_version_cb (NULL, &dummy, VAPI_OK, true, &resp->payload);
419   vapi_msg_free (ctx, resp);
420 }
421
422 END_TEST;
423
424 START_TEST (test_show_version_2)
425 {
426   int called = 0;
427   printf ("--- Show version via blocking callback API ---\n");
428   const int attempts = response_queue_size * 4;
429   int i = 0;
430   for (i = 0; i < attempts; ++i)
431     {
432       vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
433       ck_assert_ptr_ne (NULL, sv);
434       vapi_error_e rv = vapi_show_version (ctx, sv, show_version_cb, &called);
435       ck_assert_int_eq (VAPI_OK, rv);
436     }
437   ck_assert_int_eq (attempts, called);
438 }
439
440 END_TEST;
441
442 typedef struct
443 {
444   bool last_called;
445   size_t num_ifs;
446   u32 *sw_if_indexes;
447   bool *seen;
448   int called;
449 } sw_interface_dump_ctx;
450
451 vapi_error_e
452 sw_interface_dump_cb (struct vapi_ctx_s *ctx, void *callback_ctx,
453                       vapi_error_e rv, bool is_last,
454                       vapi_payload_sw_interface_details * reply)
455 {
456   sw_interface_dump_ctx *dctx = callback_ctx;
457   ck_assert_int_eq (false, dctx->last_called);
458   if (is_last)
459     {
460       ck_assert (NULL == reply);
461       dctx->last_called = true;
462     }
463   else
464     {
465       ck_assert (NULL != reply);
466       printf ("Interface dump entry: [%u]: %s\n", reply->sw_if_index,
467               reply->interface_name);
468       size_t i = 0;
469       for (i = 0; i < dctx->num_ifs; ++i)
470         {
471           if (dctx->sw_if_indexes[i] == reply->sw_if_index)
472             {
473               ck_assert_int_eq (false, dctx->seen[i]);
474               dctx->seen[i] = true;
475             }
476         }
477     }
478   ++dctx->called;
479   return VAPI_OK;
480 }
481
482 START_TEST (test_loopbacks_1)
483 {
484   printf ("--- Create/delete loopbacks using blocking API ---\n");
485   const size_t num_ifs = 5;
486   u8 mac_addresses[num_ifs][6];
487   clib_memset (&mac_addresses, 0, sizeof (mac_addresses));
488   u32 sw_if_indexes[num_ifs];
489   clib_memset (&sw_if_indexes, 0xff, sizeof (sw_if_indexes));
490   test_create_loopback_ctx_t clcs[num_ifs];
491   clib_memset (&clcs, 0, sizeof (clcs));
492   test_delete_loopback_ctx_t dlcs[num_ifs];
493   clib_memset (&dlcs, 0, sizeof (dlcs));
494   int i;
495   for (i = 0; i < num_ifs; ++i)
496     {
497       memcpy (&mac_addresses[i], "\1\2\3\4\5\6", 6);
498       mac_addresses[i][5] = i;
499       clcs[i].sw_if_index_storage = &sw_if_indexes[i];
500     }
501   for (i = 0; i < num_ifs; ++i)
502     {
503       vapi_msg_create_loopback *cl = vapi_alloc_create_loopback (ctx);
504       memcpy (cl->payload.mac_address, mac_addresses[i],
505               sizeof (cl->payload.mac_address));
506       vapi_error_e rv =
507         vapi_create_loopback (ctx, cl, loopback_create_cb, &clcs[i]);
508       ck_assert_int_eq (VAPI_OK, rv);
509     }
510   for (i = 0; i < num_ifs; ++i)
511     {
512       ck_assert_int_eq (1, clcs[i].called);
513       printf ("Created loopback with MAC %02x:%02x:%02x:%02x:%02x:%02x --> "
514               "sw_if_index %u\n",
515               mac_addresses[i][0], mac_addresses[i][1], mac_addresses[i][2],
516               mac_addresses[i][3], mac_addresses[i][4], mac_addresses[i][5],
517               sw_if_indexes[i]);
518     }
519   bool seen[num_ifs];
520   sw_interface_dump_ctx dctx = { false, num_ifs, sw_if_indexes, seen, 0 };
521   vapi_msg_sw_interface_dump *dump;
522   vapi_error_e rv;
523   const int attempts = response_queue_size * 4;
524   for (i = 0; i < attempts; ++i)
525     {
526       dctx.last_called = false;
527       clib_memset (&seen, 0, sizeof (seen));
528       dump = vapi_alloc_sw_interface_dump (ctx);
529       dump->payload.name_filter_valid = 0;
530       clib_memset (dump->payload.name_filter.buf, 0,
531                    dump->payload.name_filter.length);
532       while (VAPI_EAGAIN ==
533              (rv =
534               vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb,
535                                       &dctx)))
536         ;
537       ck_assert_int_eq (true, dctx.last_called);
538       int j = 0;
539       for (j = 0; j < num_ifs; ++j)
540         {
541           ck_assert_int_eq (true, seen[j]);
542         }
543     }
544   clib_memset (&seen, 0, sizeof (seen));
545   for (i = 0; i < num_ifs; ++i)
546     {
547       vapi_msg_delete_loopback *dl = vapi_alloc_delete_loopback (ctx);
548       dl->payload.sw_if_index = sw_if_indexes[i];
549       vapi_error_e rv =
550         vapi_delete_loopback (ctx, dl, loopback_delete_cb, &dlcs[i]);
551       ck_assert_int_eq (VAPI_OK, rv);
552     }
553   for (i = 0; i < num_ifs; ++i)
554     {
555       ck_assert_int_eq (1, dlcs[i].called);
556       printf ("Deleted loopback with sw_if_index %u\n", sw_if_indexes[i]);
557     }
558   dctx.last_called = false;
559   clib_memset (&seen, 0, sizeof (seen));
560   dump = vapi_alloc_sw_interface_dump (ctx);
561   dump->payload.name_filter_valid = 0;
562   clib_memset (dump->payload.name_filter.buf, 0,
563                dump->payload.name_filter.length);
564   while (VAPI_EAGAIN ==
565          (rv =
566           vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb, &dctx)))
567     ;
568   ck_assert_int_eq (true, dctx.last_called);
569   for (i = 0; i < num_ifs; ++i)
570     {
571       ck_assert_int_eq (false, seen[i]);
572     }
573 }
574
575 END_TEST;
576
577 START_TEST (test_show_version_3)
578 {
579   printf ("--- Show version via async callback ---\n");
580   int called = 0;
581   vapi_error_e rv;
582   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
583   ck_assert_ptr_ne (NULL, sv);
584   while (VAPI_EAGAIN ==
585          (rv = vapi_show_version (ctx, sv, show_version_cb, &called)))
586     ;
587   ck_assert_int_eq (VAPI_OK, rv);
588   ck_assert_int_eq (0, called);
589   rv = vapi_dispatch (ctx);
590   ck_assert_int_eq (VAPI_OK, rv);
591   ck_assert_int_eq (1, called);
592   called = 0;
593   rv = vapi_dispatch (ctx);
594   ck_assert_int_eq (VAPI_OK, rv);
595   ck_assert_int_eq (0, called);
596 }
597
598 END_TEST;
599
600 START_TEST (test_show_version_4)
601 {
602   printf ("--- Show version via async callback - multiple messages ---\n");
603   vapi_error_e rv;
604   const size_t num_req = 5;
605   int contexts[num_req];
606   clib_memset (contexts, 0, sizeof (contexts));
607   int i;
608   for (i = 0; i < num_req; ++i)
609     {
610       vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
611       ck_assert_ptr_ne (NULL, sv);
612       while (VAPI_EAGAIN ==
613              (rv =
614               vapi_show_version (ctx, sv, show_version_cb, &contexts[i])))
615         ;
616       ck_assert_int_eq (VAPI_OK, rv);
617       int j;
618       for (j = 0; j < num_req; ++j)
619         {
620           ck_assert_int_eq (0, contexts[j]);
621         }
622     }
623   rv = vapi_dispatch (ctx);
624   ck_assert_int_eq (VAPI_OK, rv);
625   for (i = 0; i < num_req; ++i)
626     {
627       ck_assert_int_eq (1, contexts[i]);
628     }
629   clib_memset (contexts, 0, sizeof (contexts));
630   rv = vapi_dispatch (ctx);
631   ck_assert_int_eq (VAPI_OK, rv);
632   for (i = 0; i < num_req; ++i)
633     {
634       ck_assert_int_eq (0, contexts[i]);
635     }
636 }
637
638 END_TEST;
639
640 START_TEST (test_loopbacks_2)
641 {
642   printf ("--- Create/delete loopbacks using non-blocking API ---\n");
643   vapi_error_e rv;
644   const size_t num_ifs = 5;
645   u8 mac_addresses[num_ifs][6];
646   clib_memset (&mac_addresses, 0, sizeof (mac_addresses));
647   u32 sw_if_indexes[num_ifs];
648   clib_memset (&sw_if_indexes, 0xff, sizeof (sw_if_indexes));
649   test_create_loopback_ctx_t clcs[num_ifs];
650   clib_memset (&clcs, 0, sizeof (clcs));
651   test_delete_loopback_ctx_t dlcs[num_ifs];
652   clib_memset (&dlcs, 0, sizeof (dlcs));
653   int i;
654   for (i = 0; i < num_ifs; ++i)
655     {
656       memcpy (&mac_addresses[i], "\1\2\3\4\5\6", 6);
657       mac_addresses[i][5] = i;
658       clcs[i].sw_if_index_storage = &sw_if_indexes[i];
659     }
660   for (i = 0; i < num_ifs; ++i)
661     {
662       vapi_msg_create_loopback *cl = vapi_alloc_create_loopback (ctx);
663       memcpy (cl->payload.mac_address, mac_addresses[i],
664               sizeof (cl->payload.mac_address));
665       while (VAPI_EAGAIN ==
666              (rv =
667               vapi_create_loopback (ctx, cl, loopback_create_cb, &clcs[i])))
668         ;
669       ck_assert_int_eq (VAPI_OK, rv);
670     }
671   rv = vapi_dispatch (ctx);
672   ck_assert_int_eq (VAPI_OK, rv);
673   for (i = 0; i < num_ifs; ++i)
674     {
675       ck_assert_int_eq (1, clcs[i].called);
676       printf ("Loopback with MAC %02x:%02x:%02x:%02x:%02x:%02x --> "
677               "sw_if_index %u\n",
678               mac_addresses[i][0], mac_addresses[i][1], mac_addresses[i][2],
679               mac_addresses[i][3], mac_addresses[i][4], mac_addresses[i][5],
680               sw_if_indexes[i]);
681     }
682   bool seen[num_ifs];
683   clib_memset (&seen, 0, sizeof (seen));
684   sw_interface_dump_ctx dctx = { false, num_ifs, sw_if_indexes, seen, 0 };
685   vapi_msg_sw_interface_dump *dump = vapi_alloc_sw_interface_dump (ctx);
686   dump->payload.name_filter_valid = 0;
687   clib_memset (dump->payload.name_filter.buf, 0,
688                dump->payload.name_filter.length);
689   while (VAPI_EAGAIN ==
690          (rv =
691           vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb, &dctx)))
692     ;
693   for (i = 0; i < num_ifs; ++i)
694     {
695       ck_assert_int_eq (false, seen[i]);
696     }
697   clib_memset (&seen, 0, sizeof (seen));
698   ck_assert_int_eq (false, dctx.last_called);
699   rv = vapi_dispatch (ctx);
700   ck_assert_int_eq (VAPI_OK, rv);
701   for (i = 0; i < num_ifs; ++i)
702     {
703       ck_assert_int_eq (true, seen[i]);
704     }
705   clib_memset (&seen, 0, sizeof (seen));
706   ck_assert_int_eq (true, dctx.last_called);
707   for (i = 0; i < num_ifs; ++i)
708     {
709       vapi_msg_delete_loopback *dl = vapi_alloc_delete_loopback (ctx);
710       dl->payload.sw_if_index = sw_if_indexes[i];
711       while (VAPI_EAGAIN ==
712              (rv =
713               vapi_delete_loopback (ctx, dl, loopback_delete_cb, &dlcs[i])))
714         ;
715       ck_assert_int_eq (VAPI_OK, rv);
716     }
717   rv = vapi_dispatch (ctx);
718   ck_assert_int_eq (VAPI_OK, rv);
719   for (i = 0; i < num_ifs; ++i)
720     {
721       ck_assert_int_eq (1, dlcs[i].called);
722       printf ("Deleted loopback with sw_if_index %u\n", sw_if_indexes[i]);
723     }
724   clib_memset (&seen, 0, sizeof (seen));
725   dctx.last_called = false;
726   dump = vapi_alloc_sw_interface_dump (ctx);
727   dump->payload.name_filter_valid = 0;
728   clib_memset (dump->payload.name_filter.buf, 0,
729                dump->payload.name_filter.length);
730   while (VAPI_EAGAIN ==
731          (rv =
732           vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb, &dctx)))
733     ;
734   rv = vapi_dispatch (ctx);
735   ck_assert_int_eq (VAPI_OK, rv);
736   for (i = 0; i < num_ifs; ++i)
737     {
738       ck_assert_int_eq (false, seen[i]);
739     }
740   clib_memset (&seen, 0, sizeof (seen));
741   ck_assert_int_eq (true, dctx.last_called);
742 }
743
744 END_TEST;
745
746 vapi_error_e
747 generic_cb (vapi_ctx_t ctx, void *callback_ctx, vapi_msg_id_t id, void *msg)
748 {
749   int *called = callback_ctx;
750   ck_assert_int_eq (0, *called);
751   ++*called;
752   ck_assert_int_eq (id, vapi_msg_id_show_version_reply);
753   ck_assert_ptr_ne (NULL, msg);
754   vapi_msg_show_version_reply *reply = msg;
755   ck_assert_str_eq ("vpe", (char *) reply->payload.program);
756   return VAPI_OK;
757 }
758
759 START_TEST (test_show_version_5)
760 {
761   printf ("--- Receive show version using generic callback - nonblocking "
762           "API ---\n");
763   vapi_error_e rv;
764   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
765   ck_assert_ptr_ne (NULL, sv);
766   vapi_msg_show_version_hton (sv);
767   while (VAPI_EAGAIN == (rv = vapi_send (ctx, sv)))
768     ;
769   ck_assert_int_eq (VAPI_OK, rv);
770   int called = 0;
771   vapi_set_generic_event_cb (ctx, generic_cb, &called);
772   ck_assert_int_eq (VAPI_OK, rv);
773   rv = vapi_dispatch_one (ctx);
774   ck_assert_int_eq (VAPI_OK, rv);
775   ck_assert_int_eq (1, called);
776   sv = vapi_alloc_show_version (ctx);
777   ck_assert_ptr_ne (NULL, sv);
778   vapi_msg_show_version_hton (sv);
779   while (VAPI_EAGAIN == (rv = vapi_send (ctx, sv)))
780     ;
781   ck_assert_int_eq (VAPI_OK, rv);
782   vapi_clear_generic_event_cb (ctx);
783   rv = vapi_dispatch_one (ctx);
784   ck_assert_int_eq (VAPI_OK, rv);
785   ck_assert_int_eq (1, called); /* needs to remain unchanged */
786 }
787
788 END_TEST;
789
790 vapi_error_e
791 show_version_no_cb (vapi_ctx_t ctx, void *caller_ctx,
792                     vapi_error_e rv, bool is_last,
793                     vapi_payload_show_version_reply * p)
794 {
795   ck_assert_int_eq (VAPI_ENORESP, rv);
796   ck_assert_int_eq (true, is_last);
797   ck_assert_ptr_eq (NULL, p);
798   ++*(int *) caller_ctx;
799   return VAPI_OK;
800 }
801
802 START_TEST (test_no_response_1)
803 {
804   printf ("--- Simulate no response to regular message ---\n");
805   vapi_error_e rv;
806   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
807   ck_assert_ptr_ne (NULL, sv);
808   sv->header._vl_msg_id = ~0;   /* malformed ID causes vpp to drop the msg */
809   int called = 0;
810   while (VAPI_EAGAIN ==
811          (rv = vapi_show_version (ctx, sv, show_version_no_cb, &called)))
812     ;
813   ck_assert_int_eq (VAPI_OK, rv);
814   sv = vapi_alloc_show_version (ctx);
815   ck_assert_ptr_ne (NULL, sv);
816   while (VAPI_EAGAIN ==
817          (rv = vapi_show_version (ctx, sv, show_version_cb, &called)))
818     ;
819   ck_assert_int_eq (VAPI_OK, rv);
820   rv = vapi_dispatch (ctx);
821   ck_assert_int_eq (VAPI_OK, rv);
822   ck_assert_int_eq (2, called);
823 }
824
825 END_TEST;
826
827 vapi_error_e
828 no_msg_cb (struct vapi_ctx_s *ctx, void *callback_ctx,
829            vapi_error_e rv, bool is_last,
830            vapi_payload_sw_interface_details * reply)
831 {
832   int *called = callback_ctx;
833   ++*called;
834   ck_assert_int_eq (VAPI_OK, rv);
835   ck_assert_int_eq (true, is_last);
836   ck_assert_ptr_eq (NULL, reply);
837   return VAPI_OK;
838 }
839
840 START_TEST (test_no_response_2)
841 {
842   printf ("--- Simulate no response to dump message ---\n");
843   vapi_error_e rv;
844   vapi_msg_sw_interface_dump *dump = vapi_alloc_sw_interface_dump (ctx);
845   dump->header._vl_msg_id = ~0; /* malformed ID causes vpp to drop the msg */
846   int no_called = 0;
847   while (VAPI_EAGAIN ==
848          (rv = vapi_sw_interface_dump (ctx, dump, no_msg_cb, &no_called)))
849     ;
850   ck_assert_int_eq (VAPI_OK, rv);
851   rv = vapi_dispatch (ctx);
852   ck_assert_int_eq (VAPI_OK, rv);
853   ck_assert_int_eq (1, no_called);
854 }
855
856 END_TEST;
857
858 START_TEST (test_unsupported)
859 {
860   printf ("--- Unsupported messages ---\n");
861   bool available = vapi_is_msg_available (ctx, vapi_msg_id_test_fake_msg);
862   ck_assert_int_eq (false, available);
863 }
864
865 END_TEST;
866
867 START_TEST (test_api_strings)
868 {
869   printf ("--- Invalid api strings ---\n");
870
871   /* test string 'TEST'
872    * size = 5
873    * length = 4
874    */
875   const char str[] = "TEST";
876   u8 *vec_str = 0, *vstr = 0;
877   char *cstr;
878
879   vapi_msg_sw_interface_dump *dump =
880     malloc (sizeof (vapi_msg_sw_interface_dump) + strlen (str));
881   clib_mem_init (0, 1 << 20);
882
883   vl_api_c_string_to_api_string (str, &dump->payload.name_filter);
884   /* Assert nul terminator NOT present */
885   ck_assert_int_eq (vl_api_string_len (&dump->payload.name_filter),
886                     strlen (str));
887
888   cstr = vl_api_from_api_to_new_c_string (&dump->payload.name_filter);
889   ck_assert_ptr_ne (cstr, NULL);
890   /* Assert nul terminator present */
891   ck_assert_int_eq (vec_len (cstr), sizeof (str));
892   ck_assert_int_eq (strlen (str), strlen (cstr));
893   vec_free (cstr);
894
895   vstr = vl_api_from_api_to_new_vec (0 /* not really an API message */ ,
896                                      &dump->payload.name_filter);
897   ck_assert_ptr_ne (vstr, NULL);
898   /* Assert nul terminator NOT present */
899   ck_assert_int_eq (vec_len (vstr), strlen (str));
900   vec_free (vstr);
901
902   /* vector conaining NON nul terminated string 'TEST' */
903   vec_add (vec_str, str, strlen (str));
904   clib_memset (dump->payload.name_filter.buf, 0, strlen (str));
905   dump->payload.name_filter.length = 0;
906
907   vl_api_vec_to_api_string (vec_str, &dump->payload.name_filter);
908   /* Assert nul terminator NOT present */
909   ck_assert_int_eq (vl_api_string_len (&dump->payload.name_filter),
910                     vec_len (vec_str));
911
912   cstr = vl_api_from_api_to_new_c_string (&dump->payload.name_filter);
913   ck_assert_ptr_ne (cstr, NULL);
914   /* Assert nul terminator present */
915   ck_assert_int_eq (vec_len (cstr), sizeof (str));
916   ck_assert_int_eq (strlen (str), strlen (cstr));
917   vec_free (cstr);
918
919   vstr = vl_api_from_api_to_new_vec (0 /* not a real api msg */ ,
920                                      &dump->payload.name_filter);
921   ck_assert_ptr_ne (vstr, NULL);
922   /* Assert nul terminator NOT present */
923   ck_assert_int_eq (vec_len (vstr), strlen (str));
924   vec_free (vstr);
925 }
926
927 END_TEST;
928
929 Suite *
930 test_suite (void)
931 {
932   Suite *s = suite_create ("VAPI test");
933
934   TCase *tc_negative = tcase_create ("Negative tests");
935   tcase_add_test (tc_negative, test_invalid_values);
936   suite_add_tcase (s, tc_negative);
937
938   TCase *tc_swap = tcase_create ("Byteswap tests");
939   tcase_add_test (tc_swap, test_hton_1);
940   tcase_add_test (tc_swap, test_hton_2);
941   tcase_add_test (tc_swap, test_hton_4);
942   tcase_add_test (tc_swap, test_ntoh_1);
943   tcase_add_test (tc_swap, test_ntoh_2);
944   tcase_add_test (tc_swap, test_ntoh_4);
945   suite_add_tcase (s, tc_swap);
946
947   TCase *tc_connect = tcase_create ("Connect");
948   tcase_add_test (tc_connect, test_connect);
949   suite_add_tcase (s, tc_connect);
950
951   TCase *tc_block = tcase_create ("Blocking API");
952   tcase_set_timeout (tc_block, 25);
953   tcase_add_checked_fixture (tc_block, setup_blocking, teardown);
954   tcase_add_test (tc_block, test_show_version_1);
955   tcase_add_test (tc_block, test_show_version_2);
956   tcase_add_test (tc_block, test_loopbacks_1);
957   suite_add_tcase (s, tc_block);
958
959   TCase *tc_nonblock = tcase_create ("Nonblocking API");
960   tcase_set_timeout (tc_nonblock, 25);
961   tcase_add_checked_fixture (tc_nonblock, setup_nonblocking, teardown);
962   tcase_add_test (tc_nonblock, test_show_version_3);
963   tcase_add_test (tc_nonblock, test_show_version_4);
964   tcase_add_test (tc_nonblock, test_show_version_5);
965   tcase_add_test (tc_nonblock, test_loopbacks_2);
966   tcase_add_test (tc_nonblock, test_no_response_1);
967   tcase_add_test (tc_nonblock, test_no_response_2);
968   suite_add_tcase (s, tc_nonblock);
969
970   TCase *tc_unsupported = tcase_create ("Unsupported message");
971   tcase_add_checked_fixture (tc_unsupported, setup_blocking, teardown);
972   tcase_add_test (tc_unsupported, test_unsupported);
973   suite_add_tcase (s, tc_unsupported);
974
975   TCase *tc_dynamic = tcase_create ("Dynamic message size");
976   tcase_add_test (tc_dynamic, test_api_strings);
977   suite_add_tcase (s, tc_dynamic);
978
979   return s;
980 }
981
982 int
983 main (int argc, char *argv[])
984 {
985   if (3 != argc)
986     {
987       printf ("Invalid argc==`%d'\n", argc);
988       return EXIT_FAILURE;
989     }
990   app_name = argv[1];
991   api_prefix = argv[2];
992   printf ("App name: `%s', API prefix: `%s'\n", app_name, api_prefix);
993
994   int number_failed;
995   Suite *s;
996   SRunner *sr;
997
998   s = test_suite ();
999   sr = srunner_create (s);
1000
1001   srunner_run_all (sr, CK_NORMAL);
1002   number_failed = srunner_ntests_failed (sr);
1003   srunner_free (sr);
1004   return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
1005 }
1006
1007 /*
1008  * fd.io coding-style-patch-verification: ON
1009  *
1010  * Local Variables:
1011  * eval: (c-set-style "gnu")
1012  * End:
1013  */