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