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