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