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