85fc8b3504c1a0edc9bc5a4ca9cd61c81a34f0e4
[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       memcpy (cl->payload.mac_address, mac_addresses[i],
507               sizeof (cl->payload.mac_address));
508       vapi_error_e rv =
509         vapi_create_loopback (ctx, cl, loopback_create_cb, &clcs[i]);
510       ck_assert_int_eq (VAPI_OK, rv);
511     }
512   for (i = 0; i < num_ifs; ++i)
513     {
514       ck_assert_int_eq (1, clcs[i].called);
515       printf ("Created loopback with MAC %02x:%02x:%02x:%02x:%02x:%02x --> "
516               "sw_if_index %u\n",
517               mac_addresses[i][0], mac_addresses[i][1], mac_addresses[i][2],
518               mac_addresses[i][3], mac_addresses[i][4], mac_addresses[i][5],
519               sw_if_indexes[i]);
520     }
521   bool seen[num_ifs];
522   sw_interface_dump_ctx dctx = { false, num_ifs, sw_if_indexes, seen, 0 };
523   vapi_msg_sw_interface_dump *dump;
524   vapi_error_e rv;
525   const int attempts = response_queue_size * 4;
526   for (i = 0; i < attempts; ++i)
527     {
528       dctx.last_called = false;
529       clib_memset (&seen, 0, sizeof (seen));
530       dump = vapi_alloc_sw_interface_dump (ctx);
531       while (VAPI_EAGAIN ==
532              (rv =
533               vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb,
534                                       &dctx)))
535         ;
536       ck_assert_int_eq (true, dctx.last_called);
537       int j = 0;
538       for (j = 0; j < num_ifs; ++j)
539         {
540           ck_assert_int_eq (true, seen[j]);
541         }
542     }
543   clib_memset (&seen, 0, sizeof (seen));
544   for (i = 0; i < num_ifs; ++i)
545     {
546       vapi_msg_delete_loopback *dl = vapi_alloc_delete_loopback (ctx);
547       dl->payload.sw_if_index = sw_if_indexes[i];
548       vapi_error_e rv =
549         vapi_delete_loopback (ctx, dl, loopback_delete_cb, &dlcs[i]);
550       ck_assert_int_eq (VAPI_OK, rv);
551     }
552   for (i = 0; i < num_ifs; ++i)
553     {
554       ck_assert_int_eq (1, dlcs[i].called);
555       printf ("Deleted loopback with sw_if_index %u\n", sw_if_indexes[i]);
556     }
557   dctx.last_called = false;
558   clib_memset (&seen, 0, sizeof (seen));
559   dump = vapi_alloc_sw_interface_dump (ctx);
560   while (VAPI_EAGAIN ==
561          (rv =
562           vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb, &dctx)))
563     ;
564   ck_assert_int_eq (true, dctx.last_called);
565   for (i = 0; i < num_ifs; ++i)
566     {
567       ck_assert_int_eq (false, seen[i]);
568     }
569 }
570
571 END_TEST;
572
573 START_TEST (test_show_version_3)
574 {
575   printf ("--- Show version via async callback ---\n");
576   int called = 0;
577   vapi_error_e rv;
578   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
579   ck_assert_ptr_ne (NULL, sv);
580   while (VAPI_EAGAIN ==
581          (rv = vapi_show_version (ctx, sv, show_version_cb, &called)))
582     ;
583   ck_assert_int_eq (VAPI_OK, rv);
584   ck_assert_int_eq (0, called);
585   rv = vapi_dispatch (ctx);
586   ck_assert_int_eq (VAPI_OK, rv);
587   ck_assert_int_eq (1, called);
588   called = 0;
589   rv = vapi_dispatch (ctx);
590   ck_assert_int_eq (VAPI_OK, rv);
591   ck_assert_int_eq (0, called);
592 }
593
594 END_TEST;
595
596 START_TEST (test_show_version_4)
597 {
598   printf ("--- Show version via async callback - multiple messages ---\n");
599   vapi_error_e rv;
600   const size_t num_req = 5;
601   int contexts[num_req];
602   clib_memset (contexts, 0, sizeof (contexts));
603   int i;
604   for (i = 0; i < num_req; ++i)
605     {
606       vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
607       ck_assert_ptr_ne (NULL, sv);
608       while (VAPI_EAGAIN ==
609              (rv =
610               vapi_show_version (ctx, sv, show_version_cb, &contexts[i])))
611         ;
612       ck_assert_int_eq (VAPI_OK, rv);
613       int j;
614       for (j = 0; j < num_req; ++j)
615         {
616           ck_assert_int_eq (0, contexts[j]);
617         }
618     }
619   rv = vapi_dispatch (ctx);
620   ck_assert_int_eq (VAPI_OK, rv);
621   for (i = 0; i < num_req; ++i)
622     {
623       ck_assert_int_eq (1, contexts[i]);
624     }
625   clib_memset (contexts, 0, sizeof (contexts));
626   rv = vapi_dispatch (ctx);
627   ck_assert_int_eq (VAPI_OK, rv);
628   for (i = 0; i < num_req; ++i)
629     {
630       ck_assert_int_eq (0, contexts[i]);
631     }
632 }
633
634 END_TEST;
635
636 START_TEST (test_loopbacks_2)
637 {
638   printf ("--- Create/delete loopbacks using non-blocking API ---\n");
639   vapi_error_e rv;
640   const size_t num_ifs = 5;
641   u8 mac_addresses[num_ifs][6];
642   clib_memset (&mac_addresses, 0, sizeof (mac_addresses));
643   u32 sw_if_indexes[num_ifs];
644   clib_memset (&sw_if_indexes, 0xff, sizeof (sw_if_indexes));
645   test_create_loopback_ctx_t clcs[num_ifs];
646   clib_memset (&clcs, 0, sizeof (clcs));
647   test_delete_loopback_ctx_t dlcs[num_ifs];
648   clib_memset (&dlcs, 0, sizeof (dlcs));
649   int i;
650   for (i = 0; i < num_ifs; ++i)
651     {
652       memcpy (&mac_addresses[i], "\1\2\3\4\5\6", 6);
653       mac_addresses[i][5] = i;
654       clcs[i].sw_if_index_storage = &sw_if_indexes[i];
655     }
656   for (i = 0; i < num_ifs; ++i)
657     {
658       vapi_msg_create_loopback *cl = vapi_alloc_create_loopback (ctx);
659       memcpy (cl->payload.mac_address, mac_addresses[i],
660               sizeof (cl->payload.mac_address));
661       while (VAPI_EAGAIN ==
662              (rv =
663               vapi_create_loopback (ctx, cl, loopback_create_cb, &clcs[i])))
664         ;
665       ck_assert_int_eq (VAPI_OK, rv);
666     }
667   rv = vapi_dispatch (ctx);
668   ck_assert_int_eq (VAPI_OK, rv);
669   for (i = 0; i < num_ifs; ++i)
670     {
671       ck_assert_int_eq (1, clcs[i].called);
672       printf ("Loopback with MAC %02x:%02x:%02x:%02x:%02x:%02x --> "
673               "sw_if_index %u\n",
674               mac_addresses[i][0], mac_addresses[i][1], mac_addresses[i][2],
675               mac_addresses[i][3], mac_addresses[i][4], mac_addresses[i][5],
676               sw_if_indexes[i]);
677     }
678   bool seen[num_ifs];
679   clib_memset (&seen, 0, sizeof (seen));
680   sw_interface_dump_ctx dctx = { false, num_ifs, sw_if_indexes, seen, 0 };
681   vapi_msg_sw_interface_dump *dump = vapi_alloc_sw_interface_dump (ctx);
682   while (VAPI_EAGAIN ==
683          (rv =
684           vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb, &dctx)))
685     ;
686   for (i = 0; i < num_ifs; ++i)
687     {
688       ck_assert_int_eq (false, seen[i]);
689     }
690   clib_memset (&seen, 0, sizeof (seen));
691   ck_assert_int_eq (false, dctx.last_called);
692   rv = vapi_dispatch (ctx);
693   ck_assert_int_eq (VAPI_OK, rv);
694   for (i = 0; i < num_ifs; ++i)
695     {
696       ck_assert_int_eq (true, seen[i]);
697     }
698   clib_memset (&seen, 0, sizeof (seen));
699   ck_assert_int_eq (true, dctx.last_called);
700   for (i = 0; i < num_ifs; ++i)
701     {
702       vapi_msg_delete_loopback *dl = vapi_alloc_delete_loopback (ctx);
703       dl->payload.sw_if_index = sw_if_indexes[i];
704       while (VAPI_EAGAIN ==
705              (rv =
706               vapi_delete_loopback (ctx, dl, loopback_delete_cb, &dlcs[i])))
707         ;
708       ck_assert_int_eq (VAPI_OK, rv);
709     }
710   rv = vapi_dispatch (ctx);
711   ck_assert_int_eq (VAPI_OK, rv);
712   for (i = 0; i < num_ifs; ++i)
713     {
714       ck_assert_int_eq (1, dlcs[i].called);
715       printf ("Deleted loopback with sw_if_index %u\n", sw_if_indexes[i]);
716     }
717   clib_memset (&seen, 0, sizeof (seen));
718   dctx.last_called = false;
719   dump = vapi_alloc_sw_interface_dump (ctx);
720   while (VAPI_EAGAIN ==
721          (rv =
722           vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb, &dctx)))
723     ;
724   rv = vapi_dispatch (ctx);
725   ck_assert_int_eq (VAPI_OK, rv);
726   for (i = 0; i < num_ifs; ++i)
727     {
728       ck_assert_int_eq (false, seen[i]);
729     }
730   clib_memset (&seen, 0, sizeof (seen));
731   ck_assert_int_eq (true, dctx.last_called);
732 }
733
734 END_TEST;
735
736 vapi_error_e
737 generic_cb (vapi_ctx_t ctx, void *callback_ctx, vapi_msg_id_t id, void *msg)
738 {
739   int *called = callback_ctx;
740   ck_assert_int_eq (0, *called);
741   ++*called;
742   ck_assert_int_eq (id, vapi_msg_id_show_version_reply);
743   ck_assert_ptr_ne (NULL, msg);
744   vapi_msg_show_version_reply *reply = msg;
745   ck_assert_str_eq ("vpe", (char *) reply->payload.program);
746   return VAPI_OK;
747 }
748
749 START_TEST (test_show_version_5)
750 {
751   printf ("--- Receive show version using generic callback - nonblocking "
752           "API ---\n");
753   vapi_error_e rv;
754   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
755   ck_assert_ptr_ne (NULL, sv);
756   vapi_msg_show_version_hton (sv);
757   while (VAPI_EAGAIN == (rv = vapi_send (ctx, sv)))
758     ;
759   ck_assert_int_eq (VAPI_OK, rv);
760   int called = 0;
761   vapi_set_generic_event_cb (ctx, generic_cb, &called);
762   ck_assert_int_eq (VAPI_OK, rv);
763   rv = vapi_dispatch_one (ctx);
764   ck_assert_int_eq (VAPI_OK, rv);
765   ck_assert_int_eq (1, called);
766   sv = vapi_alloc_show_version (ctx);
767   ck_assert_ptr_ne (NULL, sv);
768   vapi_msg_show_version_hton (sv);
769   while (VAPI_EAGAIN == (rv = vapi_send (ctx, sv)))
770     ;
771   ck_assert_int_eq (VAPI_OK, rv);
772   vapi_clear_generic_event_cb (ctx);
773   rv = vapi_dispatch_one (ctx);
774   ck_assert_int_eq (VAPI_OK, rv);
775   ck_assert_int_eq (1, called); /* needs to remain unchanged */
776 }
777
778 END_TEST;
779
780 vapi_error_e
781 show_version_no_cb (vapi_ctx_t ctx, void *caller_ctx,
782                     vapi_error_e rv, bool is_last,
783                     vapi_payload_show_version_reply * p)
784 {
785   ck_assert_int_eq (VAPI_ENORESP, rv);
786   ck_assert_int_eq (true, is_last);
787   ck_assert_ptr_eq (NULL, p);
788   ++*(int *) caller_ctx;
789   return VAPI_OK;
790 }
791
792 START_TEST (test_no_response_1)
793 {
794   printf ("--- Simulate no response to regular message ---\n");
795   vapi_error_e rv;
796   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
797   ck_assert_ptr_ne (NULL, sv);
798   sv->header._vl_msg_id = ~0;   /* malformed ID causes vpp to drop the msg */
799   int called = 0;
800   while (VAPI_EAGAIN ==
801          (rv = vapi_show_version (ctx, sv, show_version_no_cb, &called)))
802     ;
803   ck_assert_int_eq (VAPI_OK, rv);
804   sv = vapi_alloc_show_version (ctx);
805   ck_assert_ptr_ne (NULL, sv);
806   while (VAPI_EAGAIN ==
807          (rv = vapi_show_version (ctx, sv, show_version_cb, &called)))
808     ;
809   ck_assert_int_eq (VAPI_OK, rv);
810   rv = vapi_dispatch (ctx);
811   ck_assert_int_eq (VAPI_OK, rv);
812   ck_assert_int_eq (2, called);
813 }
814
815 END_TEST;
816
817 vapi_error_e
818 no_msg_cb (struct vapi_ctx_s *ctx, void *callback_ctx,
819            vapi_error_e rv, bool is_last,
820            vapi_payload_sw_interface_details * reply)
821 {
822   int *called = callback_ctx;
823   ++*called;
824   ck_assert_int_eq (VAPI_OK, rv);
825   ck_assert_int_eq (true, is_last);
826   ck_assert_ptr_eq (NULL, reply);
827   return VAPI_OK;
828 }
829
830 START_TEST (test_no_response_2)
831 {
832   printf ("--- Simulate no response to dump message ---\n");
833   vapi_error_e rv;
834   vapi_msg_sw_interface_dump *dump = vapi_alloc_sw_interface_dump (ctx);
835   dump->header._vl_msg_id = ~0; /* malformed ID causes vpp to drop the msg */
836   int no_called = 0;
837   while (VAPI_EAGAIN ==
838          (rv = vapi_sw_interface_dump (ctx, dump, no_msg_cb, &no_called)))
839     ;
840   ck_assert_int_eq (VAPI_OK, rv);
841   rv = vapi_dispatch (ctx);
842   ck_assert_int_eq (VAPI_OK, rv);
843   ck_assert_int_eq (1, no_called);
844 }
845
846 END_TEST;
847
848 START_TEST (test_unsupported)
849 {
850   printf ("--- Unsupported messages ---\n");
851   bool available = vapi_is_msg_available (ctx, vapi_msg_id_test_fake_msg);
852   ck_assert_int_eq (false, available);
853 }
854
855 END_TEST;
856
857 START_TEST (test_api_strings)
858 {
859   printf ("--- Invalid api strings ---\n");
860
861   /* test string 'TEST'
862    * size = 5
863    * length = 4
864    */
865   const char str[] = "TEST";
866   u8 *vec_str = 0, *vstr = 0;
867   char *cstr;
868
869   vapi_msg_sw_interface_dump *dump =
870     malloc (sizeof (vapi_msg_sw_interface_dump) + strlen (str));
871   clib_mem_init (0, 1 << 20);
872
873   vl_api_c_string_to_api_string (str, &dump->payload.name_filter);
874   /* Assert nul terminator NOT present */
875   ck_assert_int_eq (vl_api_string_len (&dump->payload.name_filter),
876                     strlen (str));
877
878   cstr = vl_api_from_api_to_new_c_string (&dump->payload.name_filter);
879   ck_assert_ptr_ne (cstr, NULL);
880   /* Assert nul terminator present */
881   ck_assert_int_eq (vec_len (cstr), sizeof (str));
882   ck_assert_int_eq (strlen (str), strlen (cstr));
883   vec_free (cstr);
884
885   vstr = vl_api_from_api_to_new_vec (0 /* not really an API message */ ,
886                                      &dump->payload.name_filter);
887   ck_assert_ptr_ne (vstr, NULL);
888   /* Assert nul terminator NOT present */
889   ck_assert_int_eq (vec_len (vstr), strlen (str));
890   vec_free (vstr);
891
892   /* vector conaining NON nul terminated string 'TEST' */
893   vec_add (vec_str, str, strlen (str));
894   clib_memset (dump->payload.name_filter.buf, 0, strlen (str));
895   dump->payload.name_filter.length = 0;
896
897   vl_api_vec_to_api_string (vec_str, &dump->payload.name_filter);
898   /* Assert nul terminator NOT present */
899   ck_assert_int_eq (vl_api_string_len (&dump->payload.name_filter),
900                     vec_len (vec_str));
901
902   cstr = vl_api_from_api_to_new_c_string (&dump->payload.name_filter);
903   ck_assert_ptr_ne (cstr, NULL);
904   /* Assert nul terminator present */
905   ck_assert_int_eq (vec_len (cstr), sizeof (str));
906   ck_assert_int_eq (strlen (str), strlen (cstr));
907   vec_free (cstr);
908
909   vstr = vl_api_from_api_to_new_vec (0 /* not a real api msg */ ,
910                                      &dump->payload.name_filter);
911   ck_assert_ptr_ne (vstr, NULL);
912   /* Assert nul terminator NOT present */
913   ck_assert_int_eq (vec_len (vstr), strlen (str));
914   vec_free (vstr);
915   free (dump);
916 }
917
918 END_TEST;
919
920 Suite *
921 test_suite (void)
922 {
923   Suite *s = suite_create ("VAPI test");
924
925   TCase *tc_negative = tcase_create ("Negative tests");
926   tcase_add_test (tc_negative, test_invalid_values);
927   suite_add_tcase (s, tc_negative);
928
929   TCase *tc_swap = tcase_create ("Byteswap tests");
930   tcase_add_test (tc_swap, test_hton_1);
931   tcase_add_test (tc_swap, test_hton_2);
932   tcase_add_test (tc_swap, test_hton_4);
933   tcase_add_test (tc_swap, test_ntoh_1);
934   tcase_add_test (tc_swap, test_ntoh_2);
935   tcase_add_test (tc_swap, test_ntoh_4);
936   suite_add_tcase (s, tc_swap);
937
938   TCase *tc_connect = tcase_create ("Connect");
939   tcase_add_test (tc_connect, test_connect);
940   suite_add_tcase (s, tc_connect);
941
942   TCase *tc_block = tcase_create ("Blocking API");
943   tcase_set_timeout (tc_block, 25);
944   tcase_add_checked_fixture (tc_block, setup_blocking, teardown);
945   tcase_add_test (tc_block, test_show_version_1);
946   tcase_add_test (tc_block, test_show_version_2);
947   tcase_add_test (tc_block, test_loopbacks_1);
948   suite_add_tcase (s, tc_block);
949
950   TCase *tc_nonblock = tcase_create ("Nonblocking API");
951   tcase_set_timeout (tc_nonblock, 25);
952   tcase_add_checked_fixture (tc_nonblock, setup_nonblocking, teardown);
953   tcase_add_test (tc_nonblock, test_show_version_3);
954   tcase_add_test (tc_nonblock, test_show_version_4);
955   tcase_add_test (tc_nonblock, test_show_version_5);
956   tcase_add_test (tc_nonblock, test_loopbacks_2);
957   tcase_add_test (tc_nonblock, test_no_response_1);
958   tcase_add_test (tc_nonblock, test_no_response_2);
959   suite_add_tcase (s, tc_nonblock);
960
961   TCase *tc_unsupported = tcase_create ("Unsupported message");
962   tcase_add_checked_fixture (tc_unsupported, setup_blocking, teardown);
963   tcase_add_test (tc_unsupported, test_unsupported);
964   suite_add_tcase (s, tc_unsupported);
965
966   TCase *tc_dynamic = tcase_create ("Dynamic message size");
967   tcase_add_test (tc_dynamic, test_api_strings);
968   suite_add_tcase (s, tc_dynamic);
969
970   return s;
971 }
972
973 int
974 main (int argc, char *argv[])
975 {
976   if (3 != argc)
977     {
978       printf ("Invalid argc==`%d'\n", argc);
979       return EXIT_FAILURE;
980     }
981   app_name = argv[1];
982   api_prefix = argv[2];
983   printf ("App name: `%s', API prefix: `%s'\n", app_name, api_prefix);
984
985   int number_failed;
986   Suite *s;
987   SRunner *sr;
988
989   s = test_suite ();
990   sr = srunner_create (s);
991
992   srunner_run_all (sr, CK_NORMAL);
993   number_failed = srunner_ntests_failed (sr);
994   srunner_free (sr);
995   return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
996 }
997
998 /*
999  * fd.io coding-style-patch-verification: ON
1000  *
1001  * Local Variables:
1002  * eval: (c-set-style "gnu")
1003  * End:
1004  */